diff options
author | Christopher Faylor <me@cgf.cx> | 2011-12-10 18:10:22 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2011-12-10 18:10:22 +0000 |
commit | bc1d321c570c5f7f17fcd559cd8e04a3fbd05aeb (patch) | |
tree | e8c6cfa1c9cb835bc688f2fa9137167b5a695c09 /winsup/cygwin/init.cc | |
parent | dfbab81589fe598f8088f068ae32e2ff74de3a77 (diff) | |
download | cygnal-bc1d321c570c5f7f17fcd559cd8e04a3fbd05aeb.tar.gz cygnal-bc1d321c570c5f7f17fcd559cd8e04a3fbd05aeb.tar.bz2 cygnal-bc1d321c570c5f7f17fcd559cd8e04a3fbd05aeb.zip |
Add ChangeLog entry for previous change and revert erroneously checked in
changes to dcrt0.cc and init.cc
Diffstat (limited to 'winsup/cygwin/init.cc')
-rw-r--r-- | winsup/cygwin/init.cc | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc index b02b3cdfc..107d037f9 100644 --- a/winsup/cygwin/init.cc +++ b/winsup/cygwin/init.cc @@ -64,12 +64,58 @@ munge_threadfunc () } } +inline static void +respawn_wow64_process () +{ + NTSTATUS ret; + PROCESS_BASIC_INFORMATION pbi; + HANDLE parent; + + ULONG wow64 = TRUE; /* Opt on the safe side. */ + + /* Unfortunately there's no simpler way to retrieve the + parent process in NT, as far as I know. Hints welcome. */ + ret = NtQueryInformationProcess (NtCurrentProcess (), + ProcessBasicInformation, + &pbi, sizeof pbi, NULL); + if (NT_SUCCESS (ret) + && (parent = OpenProcess (PROCESS_QUERY_INFORMATION, + FALSE, + pbi.InheritedFromUniqueProcessId))) + { + NtQueryInformationProcess (parent, ProcessWow64Information, + &wow64, sizeof wow64, NULL); + CloseHandle (parent); + } + + /* The parent is a real 64 bit process? Respawn! */ + if (!wow64) + { + PROCESS_INFORMATION pi; + STARTUPINFOW si; + DWORD ret = 0; + + GetStartupInfoW (&si); + if (!CreateProcessW (NULL, GetCommandLineW (), NULL, NULL, TRUE, + CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()), + NULL, NULL, &si, &pi)) + api_fatal ("Failed to create process <%s>, %E", GetCommandLineA ()); + CloseHandle (pi.hThread); + if (WaitForSingleObject (pi.hProcess, INFINITE) == WAIT_FAILED) + api_fatal ("Waiting for process %d failed, %E", pi.dwProcessId); + GetExitCodeProcess (pi.hProcess, &ret); + CloseHandle (pi.hProcess); + ExitProcess (ret); + } +} + void dll_crt0_0 (); extern "C" BOOL WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load) { - extern bool wow64_respawn; + BOOL wow64_test_stack_marker; switch (reason) { @@ -80,6 +126,16 @@ dll_entry (HANDLE h, DWORD reason, void *static_load) cygwin_hmodule = (HMODULE) h; dynamically_loaded = (static_load == NULL); + /* Is the stack at an unusual address? That is, an address which + is in the usual space occupied by the process image, but below + the auto load address of DLLs? + Check if we're running in WOW64 on a 64 bit machine *and* are + spawned by a genuine 64 bit process. If so, respawn. */ + if (wincap.is_wow64 () + && &wow64_test_stack_marker >= (PBOOL) 0x400000 + && &wow64_test_stack_marker <= (PBOOL) 0x10000000) + respawn_wow64_process (); + dll_crt0_0 (); _my_oldfunc = TlsAlloc (); dll_finished_loading = true; @@ -94,7 +150,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load) break; case DLL_THREAD_DETACH: if (dll_finished_loading - && !wow64_respawn + && (PVOID) &_my_tls > (PVOID) &wow64_test_stack_marker && _my_tls.isinitialized ()) _my_tls.remove (0); /* Windows 2000 has a bug in NtTerminateThread. Instead of releasing |