Commit ad045d6e authored by Vitaliy Margolen's avatar Vitaliy Margolen Committed by Alexandre Julliard

dinput: Create/destroy hook thread from DirectInput.

parent 61c1dd2b
...@@ -76,6 +76,8 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv) ...@@ -76,6 +76,8 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv)
return TRUE; return TRUE;
} }
static BOOL create_hook_thread(void);
static void release_hook_thread(void);
/****************************************************************************** /******************************************************************************
* DirectInputCreateEx (DINPUT.@) * DirectInputCreateEx (DINPUT.@)
...@@ -118,6 +120,7 @@ HRESULT WINAPI DirectInputCreateEx( ...@@ -118,6 +120,7 @@ HRESULT WINAPI DirectInputCreateEx(
res = DI_OK; res = DI_OK;
} }
if (res == DI_OK && !create_hook_thread()) res = DIERR_GENERIC;
if (res == DI_OK) if (res == DI_OK)
{ {
This = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectInputImpl)); This = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectInputImpl));
...@@ -255,7 +258,10 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface) ...@@ -255,7 +258,10 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
ULONG ref; ULONG ref;
ref = InterlockedDecrement(&(This->ref)); ref = InterlockedDecrement(&(This->ref));
if (ref == 0) if (ref == 0)
HeapFree(GetProcessHeap(),0,This); {
HeapFree(GetProcessHeap(), 0, This);
release_hook_thread();
}
return ref; return ref;
} }
...@@ -732,15 +738,21 @@ static LRESULT CALLBACK dinput_hook_WndProc(HWND hWnd, UINT message, WPARAM wPar ...@@ -732,15 +738,21 @@ static LRESULT CALLBACK dinput_hook_WndProc(HWND hWnd, UINT message, WPARAM wPar
return res; return res;
} }
} }
else if (!wParam && !lParam)
DestroyWindow(hWnd);
return 0; return 0;
case WM_DESTROY: case WM_DESTROY:
if (kbd_hook) UnhookWindowsHookEx(kbd_hook);
if (mouse_hook) UnhookWindowsHookEx(mouse_hook);
PostQuitMessage(0); PostQuitMessage(0);
} }
return DefWindowProcW(hWnd, message, wParam, lParam); return DefWindowProcW(hWnd, message, wParam, lParam);
} }
static HANDLE signal_event; static HWND hook_thread_hwnd;
static LONG hook_thread_refcount;
static DWORD WINAPI hook_thread_proc(void *param) static DWORD WINAPI hook_thread_proc(void *param)
{ {
...@@ -757,9 +769,9 @@ static DWORD WINAPI hook_thread_proc(void *param) ...@@ -757,9 +769,9 @@ static DWORD WINAPI hook_thread_proc(void *param)
if (!RegisterClassExW(&wcex)) ERR("Error registering window class\n"); if (!RegisterClassExW(&wcex)) ERR("Error registering window class\n");
hwnd = CreateWindowExW(0, classW, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, 0); hwnd = CreateWindowExW(0, classW, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, 0);
*(HWND*)param = hwnd; hook_thread_hwnd = hwnd;
SetEvent(signal_event); SetEvent(*(LPHANDLE)param);
if (hwnd) if (hwnd)
{ {
while (GetMessageW(&msg, 0, 0, 0)) while (GetMessageW(&msg, 0, 0, 0))
...@@ -767,10 +779,10 @@ static DWORD WINAPI hook_thread_proc(void *param) ...@@ -767,10 +779,10 @@ static DWORD WINAPI hook_thread_proc(void *param)
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessageW(&msg); DispatchMessageW(&msg);
} }
DestroyWindow(hwnd);
} }
else ERR("Error creating message window\n"); else ERR("Error creating message window\n");
DestroyWindow(hwnd);
UnregisterClassW(wcex.lpszClassName, wcex.hInstance); UnregisterClassW(wcex.lpszClassName, wcex.hInstance);
return 0; return 0;
} }
...@@ -784,41 +796,57 @@ static CRITICAL_SECTION_DEBUG dinput_critsect_debug = ...@@ -784,41 +796,57 @@ static CRITICAL_SECTION_DEBUG dinput_critsect_debug =
}; };
static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0, 0 }; static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0, 0 };
static HWND get_thread_hwnd(void) static BOOL create_hook_thread(void)
{ {
static HANDLE hook_thread; LONG ref;
static HWND hook_thread_hwnd;
EnterCriticalSection(&dinput_hook_crit); EnterCriticalSection(&dinput_hook_crit);
if (!hook_thread) ref = ++hook_thread_refcount;
TRACE("Refcount %ld\n", ref);
if (ref == 1)
{ {
DWORD tid; DWORD tid;
HWND hwnd; HANDLE thread, event;
signal_event = CreateEventW(NULL, FALSE, FALSE, NULL); event = CreateEventW(NULL, FALSE, FALSE, NULL);
hook_thread = CreateThread(NULL, 0, hook_thread_proc, &hwnd, 0, &tid); thread = CreateThread(NULL, 0, hook_thread_proc, &event, 0, &tid);
if (signal_event && hook_thread) if (event && thread)
{ {
HANDLE handles[2]; HANDLE handles[2];
handles[0] = signal_event; handles[0] = event;
handles[1] = hook_thread; handles[1] = thread;
WaitForMultipleObjects(2, handles, FALSE, INFINITE); WaitForMultipleObjects(2, handles, FALSE, INFINITE);
} }
CloseHandle(signal_event); CloseHandle(event);
CloseHandle(thread);
}
LeaveCriticalSection(&dinput_hook_crit);
return hook_thread_hwnd != 0;
}
if (!(hook_thread_hwnd = hwnd)) static void release_hook_thread(void)
{
LONG ref;
EnterCriticalSection(&dinput_hook_crit);
ref = --hook_thread_refcount;
TRACE("Releasing to %ld\n", ref);
if (ref == 0)
{ {
/* Thread failed to create window - reset things so we could try again later */ HWND hwnd = hook_thread_hwnd;
CloseHandle(hook_thread); hook_thread_hwnd = 0;
hook_thread = 0; SendMessageW(hwnd, WM_USER+0x10, 0, 0);
}
} }
LeaveCriticalSection(&dinput_hook_crit); LeaveCriticalSection(&dinput_hook_crit);
return hook_thread_hwnd;
} }
HHOOK set_dinput_hook(int hook_id, LPVOID proc) HHOOK set_dinput_hook(int hook_id, LPVOID proc)
{ {
return (HHOOK)SendMessageW(get_thread_hwnd(), WM_USER+0x10, (WPARAM)hook_id, (LPARAM)proc); HWND hwnd;
EnterCriticalSection(&dinput_hook_crit);
hwnd = hook_thread_hwnd;
LeaveCriticalSection(&dinput_hook_crit);
return (HHOOK)SendMessageW(hwnd, WM_USER+0x10, (WPARAM)hook_id, (LPARAM)proc);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment