dinput: Prevent race between destroying the hook window and unloading the dll.

This commit is contained in:
Vitaliy Margolen 2007-05-14 19:56:48 -06:00 committed by Alexandre Julliard
parent 1af94dbf3b
commit 4659f98314

View File

@ -753,6 +753,7 @@ static LRESULT CALLBACK dinput_hook_WndProc(HWND hWnd, UINT message, WPARAM wPar
static HWND hook_thread_hwnd; static HWND hook_thread_hwnd;
static LONG hook_thread_refcount; static LONG hook_thread_refcount;
static HANDLE hook_thread;
static const WCHAR classW[]={'H','o','o','k','_','L','L','_','C','L',0}; static const WCHAR classW[]={'H','o','o','k','_','L','L','_','C','L',0};
@ -776,6 +777,7 @@ static DWORD WINAPI hook_thread_proc(void *param)
} }
else ERR("Error creating message window\n"); else ERR("Error creating message window\n");
UnregisterClassW(classW, DINPUT_instance);
return 0; return 0;
} }
@ -791,39 +793,36 @@ static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0
static BOOL create_hook_thread(void) static BOOL create_hook_thread(void)
{ {
LONG ref; LONG ref;
static ATOM class_atom;
EnterCriticalSection(&dinput_hook_crit); EnterCriticalSection(&dinput_hook_crit);
if (!class_atom)
{
WNDCLASSEXW wcex;
memset(&wcex, 0, sizeof(wcex));
wcex.cbSize = sizeof(wcex);
wcex.lpfnWndProc = dinput_hook_WndProc;
wcex.lpszClassName = classW;
wcex.hInstance = GetModuleHandleW(0);
if (!(class_atom = RegisterClassExW(&wcex))) ERR("Error registering window class\n");
}
ref = ++hook_thread_refcount; ref = ++hook_thread_refcount;
TRACE("Refcount %d\n", ref); TRACE("Refcount %d\n", ref);
if (ref == 1) if (ref == 1)
{ {
DWORD tid; DWORD tid;
HANDLE thread, event; HANDLE event;
/* Create window class */
WNDCLASSEXW wcex;
memset(&wcex, 0, sizeof(wcex));
wcex.cbSize = sizeof(wcex);
wcex.lpfnWndProc = dinput_hook_WndProc;
wcex.lpszClassName = classW;
wcex.hInstance = DINPUT_instance;
if (!RegisterClassExW(&wcex))
ERR("Error registering window class\n");
event = CreateEventW(NULL, FALSE, FALSE, NULL); event = CreateEventW(NULL, FALSE, FALSE, NULL);
thread = CreateThread(NULL, 0, hook_thread_proc, &event, 0, &tid); hook_thread = CreateThread(NULL, 0, hook_thread_proc, &event, 0, &tid);
if (event && thread) if (event && hook_thread)
{ {
HANDLE handles[2]; HANDLE handles[2];
handles[0] = event; handles[0] = event;
handles[1] = thread; handles[1] = hook_thread;
WaitForMultipleObjects(2, handles, FALSE, INFINITE); WaitForMultipleObjects(2, handles, FALSE, INFINITE);
} }
CloseHandle(event); CloseHandle(event);
CloseHandle(thread);
} }
LeaveCriticalSection(&dinput_hook_crit); LeaveCriticalSection(&dinput_hook_crit);
@ -842,6 +841,9 @@ static void release_hook_thread(void)
HWND hwnd = hook_thread_hwnd; HWND hwnd = hook_thread_hwnd;
hook_thread_hwnd = 0; hook_thread_hwnd = 0;
SendMessageW(hwnd, WM_USER+0x10, 0, 0); SendMessageW(hwnd, WM_USER+0x10, 0, 0);
/* wait for hook thread to exit */
WaitForSingleObject(hook_thread, INFINITE);
CloseHandle(hook_thread);
} }
LeaveCriticalSection(&dinput_hook_crit); LeaveCriticalSection(&dinput_hook_crit);
} }