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;
memset (&si, 0, sizeof (si));
si.cb = sizeof (STARTUPINFO);
+
si.lpReserved2 = (LPBYTE) &ch;
si.cbReserved2 = sizeof (ch);
+ /* See comment in dcrt0.cc, function get_cygwin_startup_info. */
+ if (wincap.needs_count_in_si_lpres2 ())
+ ch.zero[0] = sizeof (ch) / 5;
+
syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %p, 0, 0, %p, %p)",
myself->progname, myself->progname, c_flags, &si, &pi);
bool locked = __malloc_lock ();
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_95 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_95osr2 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_98 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_98se = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_me = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_nt3 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_nt4 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_nt4sp4 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_2000 = {
has_buggy_restart_scan:true,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_xp = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_2003 = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
+ needs_count_in_si_lpres2:false,
};
static NO_COPY wincaps wincap_vista = {
has_buggy_restart_scan:false,
has_mandatory_integrity_control:true,
needs_logon_sid_in_sid_list:false,
+ needs_count_in_si_lpres2:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));