From 67ec0cd9faede475da12984cf385218325e6138a Mon Sep 17 00:00:00 2001 From: Michael Curran Date: Sat, 21 Apr 2012 03:06:08 +1000 Subject: [PATCH] Hopefully stop crashes in apps when they exit on XP (#2254). Specific changes to nvdaHelperRemote: * Declare isProcessExiting extern in dllmain.h and use it in apiHooks_terminate to return early to stop freeing libraries if the process is exiting -- its dangerous to call LoadLibrary or FreeLibrary when dllmain is being run. * dllmain: If the process is exiting, also unregister any in-context winEvent hooks. Seems that winEvents kept being fired on process shutdown trying to install IA2 support over and over again -- until the whole thing fell over due to it trying to log an error via a freed rpc binding handle. * dllmain: only free nvdaController and nvdaControllerInternal binding handles if the process isn't exiting. If it is the OS will clean it up anyway and we want logging to work for as long as possible. --- nvdaHelper/remote/apiHook.cpp | 2 ++ nvdaHelper/remote/dllmain.h | 1 + nvdaHelper/remote/injection.cpp | 16 ++++++++-------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/nvdaHelper/remote/apiHook.cpp b/nvdaHelper/remote/apiHook.cpp index 4f946cfa5..ee76afc06 100644 --- a/nvdaHelper/remote/apiHook.cpp +++ b/nvdaHelper/remote/apiHook.cpp @@ -90,6 +90,8 @@ bool apiHook_terminate() { Sleep(250); res=MH_Uninitialize(); nhAssert(res==MH_OK); + //If the process is exiting do not free any dlls as the OS should do this itself correctly + if(isProcessExiting) return true; for(moduleSet_t::iterator i=g_hookedModules.begin();i!=g_hookedModules.end();++i) { FreeLibrary(*i); } diff --git a/nvdaHelper/remote/dllmain.h b/nvdaHelper/remote/dllmain.h index 0aa1de2ea..98c204e42 100644 --- a/nvdaHelper/remote/dllmain.h +++ b/nvdaHelper/remote/dllmain.h @@ -20,5 +20,6 @@ http://www.gnu.org/licenses/old-licenses/gpl-2.0.html extern HINSTANCE dllHandle; extern wchar_t dllDirectory[MAX_PATH]; +extern bool isProcessExiting; #endif diff --git a/nvdaHelper/remote/injection.cpp b/nvdaHelper/remote/injection.cpp index c4418bd75..158132392 100644 --- a/nvdaHelper/remote/injection.cpp +++ b/nvdaHelper/remote/injection.cpp @@ -153,11 +153,6 @@ if(isSecureModeNVDAProcess) real_OpenClipboard=apiHook_hookFunction_safe("USER32 apiHook_terminate(); //Terminate all in-process subsystems. inProcess_terminate(); - //Unregister winEvents for this process - if(inprocWinEventHookID) { - UnhookWinEvent(inprocWinEventHookID); - inprocWinEventHookID=0; - } //Unregister any windows hooks registered so far killRunningWindowsHooks(); //Release and close the thread mutex @@ -316,9 +311,6 @@ BOOL WINAPI DllMain(HINSTANCE hModule,DWORD reason,LPVOID lpReserved) { #ifndef NDEBUG Beep(1760,75); #endif - //cleanup some RPC binding handles - RpcBindingFree(&nvdaControllerBindingHandle); - RpcBindingFree(&nvdaControllerInternalBindingHandle); if(lpReserved) { // process is terminating isProcessExiting=true; //If the inproc manager thread was killed off due to process termination then at least unregister hooks @@ -330,9 +322,17 @@ BOOL WINAPI DllMain(HINSTANCE hModule,DWORD reason,LPVOID lpReserved) { apiHook_terminate(); //Unregister any current windows hooks killRunningWindowsHooks(); + //Unregister winEvents for this process + if(inprocWinEventHookID) { + UnhookWinEvent(inprocWinEventHookID); + inprocWinEventHookID=0; + } } } else { //The dll is being unloaded from this process TlsFree(tlsIndex_inThreadInjectionID); + //cleanup some RPC binding handles + RpcBindingFree(&nvdaControllerBindingHandle); + RpcBindingFree(&nvdaControllerInternalBindingHandle); } } return TRUE; -- 2.11.0