diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2006-12-05 13:59:21 +0300 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2006-12-05 13:59:21 +0300 |
commit | c6674b53d3b910b8d3dd4095d626e554b5c32fa1 (patch) | |
tree | f5230c3705aecf055c5210f469208ae72c9c36a2 /winsup/cygwin/dcrt0.cc | |
parent | 489bb390ceff00454f0f904c8c96cd39405918c6 (diff) |
* dcrt0.cc (get_cygwin_startup_info): Change zeros to DWORD array.
Expect first DWORD in child_info struct being set to non-zero if
wincap.needs_count_in_si_lpres2 is set. Add comment to explain why.
* fork.cc (frok::parent): Set ch.zero[0] to a sensible count value
if wincap.needs_count_in_si_lpres2 is set.
* spawn.cc (spawn_guts): Ditto. Add filler bytes after ch on stack
to accomodate needs_count_in_si_lpres2.
* wincap.h: Define needs_count_in_si_lpres2 throughout.
* wincap.cc: Ditto.
Diffstat (limited to 'winsup/cygwin/dcrt0.cc')
-rw-r--r-- | winsup/cygwin/dcrt0.cc | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 2a7b67211..023f7682c 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -590,10 +590,36 @@ child_info * get_cygwin_startup_info () { STARTUPINFO si; - char zeros[sizeof (child_proc_info->zero)] = {0}; + DWORD zeros[sizeof (child_proc_info->zero) + / sizeof (child_proc_info->zero[0])] = {0}; GetStartupInfo (&si); child_info *res = (child_info *) si.lpReserved2; + + /* It appears that when running under WOW64 on Vista 64, the first DWORD + value in the datastructure lpReserved2 is pointing to (zero[0] in + Cygwin), has to reflect the size of that datastructure as used in the + Microsoft C runtime (a count value, counting the number of elements in + two subsequent arrays, BYTE[count and HANDLE[count]), even though the C + runtime isn't used. Otherwise, if zero[0] is 0 or too small, the + datastructure gets overwritten. + + This seems to be a bug in Vista's WOW64, which apparently copies the + lpReserved2 datastructure not using the cbReserved2 size information, + but using the information given in the first DWORD within lpReserved2 + instead. Funny enough, 32 bit Vista doesn't care if zero[0] is 0 or a + non-0 count value, while older versions of Windows might crash if + zero[0] is set to a non-zero value, as observed at least on XP 64. + + exec/spawn as well as fork write an appropriate value into zero[0] now, + depending on the wincap.needs_count_in_si_lpres2 flag. The value is + sizeof (child_info_*) / 5 which results in a count which covers the + full datastructure, plus not more than 4 extra bytes. This is ok as + long as the child_info structure is cosily stored within a bigger + datastructure. */ + if (wincap.needs_count_in_si_lpres2 ()) + zeros[0] = si.cbReserved2 / 5; + if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res || memcmp (res->zero, zeros, sizeof (res->zero)) != 0) res = NULL; |