dinput [1/3]: Move hook thread management into DirectInput object.

Vitaliy Margolen wine-patch at kievinfo.com
Sat Jul 22 14:11:03 CDT 2006


ChangeLog:
dinput: Move hook thread management into DirectInput object.
This will guarantee that we create and destroy thread at the right
time.

Fixes bug 4973.

 dlls/dinput/device.c         |  135 ------------------------------------------
 dlls/dinput/device_private.h |    2 -
 dlls/dinput/dinput_main.c    |  109 +++++++++++++++++++++++++---------
 dlls/dinput/dinput_private.h |    5 ++
 dlls/dinput/keyboard.c       |    6 +-
 dlls/dinput/mouse.c          |    6 +-
 6 files changed, 91 insertions(+), 172 deletions(-)
-------------- next part --------------
e9f910450d5ccb72ad17a290ef9b0ea43184a20b
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 7e2e9d4..d71677b 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -901,138 +901,3 @@ HRESULT WINAPI IDirectInputDevice8WImpl_
     return DI_OK;
 }
 
-/******************************************************************************
- *	DInput hook thread
- */
-
-static LRESULT CALLBACK dinput_hook_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
-    static HHOOK kbd_hook, mouse_hook;
-    BOOL res;
-
-    TRACE("got message %x %p %p\n", message, (LPVOID)wParam, (LPVOID)lParam);
-    switch (message)
-    {
-    case WM_USER+0x10:
-        if (wParam == WH_KEYBOARD_LL)
-        {
-            if (lParam)
-            {
-                if (kbd_hook) return 0;
-                kbd_hook = SetWindowsHookExW(WH_KEYBOARD_LL, (LPVOID)lParam, DINPUT_instance, 0);
-                return (LRESULT)kbd_hook;
-            }
-            else
-            {
-                if (!kbd_hook) return 0;
-                res = UnhookWindowsHookEx(kbd_hook);
-                kbd_hook = NULL;
-                return res;
-            }
-        }
-        else if (wParam == WH_MOUSE_LL)
-        {
-            if (lParam)
-            {
-                if (mouse_hook) return 0;
-                mouse_hook = SetWindowsHookExW(WH_MOUSE_LL, (LPVOID)lParam, DINPUT_instance, 0);
-                return (LRESULT)mouse_hook;
-            }
-            else
-            {
-                if (!mouse_hook) return 0;
-                res = UnhookWindowsHookEx(mouse_hook);
-                mouse_hook = NULL;
-                return res;
-            }
-        }
-        return 0;
-
-    case WM_DESTROY:
-        PostQuitMessage(0);
-    }
-    return DefWindowProcW(hWnd, message, wParam, lParam);
-}
-
-static HANDLE signal_event;
-
-static DWORD WINAPI hook_thread_proc(void *param)
-{
-    static const WCHAR classW[]={'H','o','o','k','_','L','L','_','C','L',0};
-    MSG msg;
-    WNDCLASSEXW wcex;
-    HWND hwnd;
-
-    memset(&wcex, 0, sizeof(wcex));
-    wcex.cbSize = sizeof(wcex);
-    wcex.lpfnWndProc = dinput_hook_WndProc;
-    wcex.lpszClassName = classW;
-    wcex.hInstance = GetModuleHandleW(0);
-
-    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*)param = hwnd;
-
-    SetEvent(signal_event);
-    if (hwnd)
-    {
-        while (GetMessageW(&msg, 0, 0, 0))
-        {
-            TranslateMessage(&msg);
-            DispatchMessageW(&msg);
-        }
-    }
-    else ERR("Error creating message window\n");
-
-    DestroyWindow(hwnd);
-    UnregisterClassW(wcex.lpszClassName, wcex.hInstance);
-    return 0;
-}
-
-static CRITICAL_SECTION dinput_hook_crit;
-static CRITICAL_SECTION_DEBUG dinput_critsect_debug =
-{
-    0, 0, &dinput_hook_crit,
-    { &dinput_critsect_debug.ProcessLocksList, &dinput_critsect_debug.ProcessLocksList },
-      0, 0, { (DWORD_PTR)(__FILE__ ": dinput_hook_crit") }
-};
-static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0, 0 };
-
-static HWND get_thread_hwnd(void)
-{
-    static HANDLE hook_thread;
-    static HWND   hook_thread_hwnd;
-
-    EnterCriticalSection(&dinput_hook_crit);
-    if (!hook_thread)
-    {
-        DWORD tid;
-        HWND hwnd;
-
-        signal_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-        hook_thread = CreateThread(NULL, 0, hook_thread_proc, &hwnd, 0, &tid);
-        if (signal_event && hook_thread)
-        {
-            HANDLE handles[2];
-            handles[0] = signal_event;
-            handles[1] = hook_thread;
-            WaitForMultipleObjects(2, handles, FALSE, INFINITE);
-        }
-        CloseHandle(signal_event);
-
-        if (!(hook_thread_hwnd = hwnd))
-        {
-            /* Thread failed to create window - reset things so we could try again later */
-            CloseHandle(hook_thread);
-            hook_thread = 0;
-        }
-    }
-    LeaveCriticalSection(&dinput_hook_crit);
-
-    return hook_thread_hwnd;
-}
-
-HHOOK set_dinput_hook(int hook_id, LPVOID proc)
-{
-    return (HHOOK)SendMessageW(get_thread_hwnd(), WM_USER+0x10, (WPARAM)hook_id, (LPARAM)proc);
-}
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 9cde397..7aad7f4 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -52,8 +52,6 @@ extern void fill_DataFormat(void *out, c
 extern DataFormat *create_DataFormat(const DIDATAFORMAT *wine_format, LPCDIDATAFORMAT asked_format, int *offset) ;
 extern void release_DataFormat(DataFormat *df) ;
 
-extern HHOOK set_dinput_hook(int hook_id, LPVOID proc);
-
 /* Used to fill events in the queue */
 #define GEN_EVENT(offset,data,xtime,seq)					\
 {										\
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 9f93a52..4ae086e 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -76,6 +76,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWO
     return TRUE;
 }
 
+static DWORD WINAPI hook_thread_proc(void *param);
 
 /******************************************************************************
  *	DirectInputCreateEx (DINPUT.@)
@@ -84,7 +85,8 @@ HRESULT WINAPI DirectInputCreateEx(
 	HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI,
 	LPUNKNOWN punkOuter) 
 {
-	IDirectInputImpl* This;
+	IDirectInputImpl* This = NULL;
+        HRESULT res = DIERR_OLDDIRECTINPUTVERSION;
 
 	TRACE("(%p,%04lx,%s,%p,%p)\n", hinst,dwVersion,debugstr_guid(riid),ppDI,punkOuter);
 
@@ -97,7 +99,7 @@ HRESULT WINAPI DirectInputCreateEx(
 	  This->dwVersion = dwVersion; 
 	  *ppDI = This;
 
-	  return DI_OK;
+	  res = DI_OK;
 	}
 
 	if (IsEqualGUID(&IID_IDirectInputW,riid) ||
@@ -109,7 +111,7 @@ HRESULT WINAPI DirectInputCreateEx(
 	  This->dwVersion = dwVersion; 
 	  *ppDI = This;
 
-	  return DI_OK;
+	  res = DI_OK;
 	}
 
 	if (IsEqualGUID(&IID_IDirectInput8A,riid)) {
@@ -119,7 +121,7 @@ HRESULT WINAPI DirectInputCreateEx(
 	  This->dwVersion = dwVersion; 
 	  *ppDI = This;
 
-	  return DI_OK;
+	  res = DI_OK;
 	}
 
 	if (IsEqualGUID(&IID_IDirectInput8W,riid)) {
@@ -129,10 +131,14 @@ HRESULT WINAPI DirectInputCreateEx(
 	  This->dwVersion = dwVersion; 
 	  *ppDI = This;
 
-	  return DI_OK;
+	  res = DI_OK;
 	}
 
-	return DIERR_OLDDIRECTINPUTVERSION;
+        if (SUCCEEDED(res))
+            This->hook_thread = CreateThread(NULL, 0, hook_thread_proc, NULL, 0,
+                                             &This->hook_thread_id);
+
+        return res;
 }
 
 /******************************************************************************
@@ -140,15 +146,7 @@ HRESULT WINAPI DirectInputCreateEx(
  */
 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
 {
-	IDirectInputImpl* This;
-	TRACE("(%p,%04lx,%p,%p)\n", hinst,dwVersion,ppDI,punkOuter);
-	This = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
-	This->lpVtbl = &ddi7avt;
-	This->ref = 1;
-	This->dwVersion = dwVersion; 
-	*ppDI = (IDirectInputA*)This;
-	return 0;
-
+    return DirectInputCreateEx(hinst, dwVersion, &IID_IDirectInput7A, (LPVOID *)ppDI, punkOuter);
 }
 
 /******************************************************************************
@@ -156,14 +154,7 @@ HRESULT WINAPI DirectInputCreateA(HINSTA
  */
 HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter)
 {
-	IDirectInputImpl* This;
-	TRACE("(%p,%04lx,%p,%p)\n", hinst,dwVersion,ppDI,punkOuter);
-	This = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
-	This->lpVtbl = &ddi7wvt;
-	This->ref = 1;
-	This->dwVersion = dwVersion; 
-	*ppDI = (IDirectInputW*)This;
-	return 0;
+    return DirectInputCreateEx(hinst, dwVersion, &IID_IDirectInput7W, (LPVOID *)ppDI, punkOuter);
 }
 
 static const char *_dump_DIDEVTYPE_value(DWORD dwDevType) {
@@ -271,12 +262,16 @@ static ULONG WINAPI IDirectInputAImpl_Ad
 
 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
 {
-	IDirectInputImpl *This = (IDirectInputImpl *)iface;
-	ULONG ref;
-	ref = InterlockedDecrement(&(This->ref));
-	if (ref == 0)
-		HeapFree(GetProcessHeap(),0,This);
-	return ref;
+    IDirectInputImpl *This = (IDirectInputImpl *)iface;
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    if (ref == 0)
+    {
+        while (!PostThreadMessageW(This->hook_thread_id, WM_QUIT, 0, 0)) Sleep(200);
+        WaitForSingleObject(This->hook_thread, INFINITE);
+        HeapFree(GetProcessHeap(), 0, This);
+    }
+    return ref;
 }
 
 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, REFIID riid, LPVOID *ppobj) {
@@ -706,3 +701,59 @@ HRESULT WINAPI DllGetClassObject(REFCLSI
     FIXME("(%s,%s,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
     return CLASS_E_CLASSNOTAVAILABLE;
 }
+
+/***********************************************************************
+ *	DInput hook thread
+ */
+
+static void dinput_hook_proc(WPARAM wParam, LPARAM lParam)
+{
+    static HHOOK kbd_hook, mouse_hook;
+
+    switch (wParam)
+    {
+    case WH_KEYBOARD_LL:
+        if (lParam)
+        {
+            if (kbd_hook) return;
+            kbd_hook = SetWindowsHookExW(WH_KEYBOARD_LL, (LPVOID)lParam, DINPUT_instance, 0);
+        }
+        else
+        {
+            if (!kbd_hook) return;
+            UnhookWindowsHookEx(kbd_hook);
+            kbd_hook = NULL;
+        }
+        break;
+
+    case WH_MOUSE_LL:
+        if (lParam)
+        {
+            if (mouse_hook) return;
+            mouse_hook = SetWindowsHookExW(WH_MOUSE_LL, (LPVOID)lParam, DINPUT_instance, 0);
+        }
+        else
+        {
+            if (!mouse_hook) return;
+            UnhookWindowsHookEx(mouse_hook);
+            mouse_hook = NULL;
+        }
+    }
+}
+
+static DWORD WINAPI hook_thread_proc(void *param)
+{
+    MSG msg;
+
+    while (GetMessageW(&msg, 0, 0, 0))
+        if (msg.message == WM_USER+0x10) dinput_hook_proc(msg.wParam, msg.lParam);
+
+    return 0;
+}
+
+void set_dinput_hook(IDirectInputImpl *dinput, int hook_id, LPVOID proc)
+{
+    while (!PostThreadMessageW(dinput->hook_thread_id, WM_USER+0x10, (WPARAM)hook_id, (LPARAM)proc))
+        Sleep(200);
+}
+
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index c23b048..575eddb 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -36,6 +36,9 @@ struct IDirectInputImpl
    DWORD evsequence;
 
    DWORD dwVersion;
+
+   HANDLE hook_thread;
+   DWORD hook_thread_id;
 };
 
 /* Function called by all devices that Wine supports */
@@ -54,4 +57,6 @@ extern const struct dinput_device joysti
 
 extern HINSTANCE DINPUT_instance;
 
+extern void set_dinput_hook(IDirectInputImpl *iface, int hook_id, LPVOID proc);
+
 #endif /* __WINE_DLLS_DINPUT_DINPUT_PRIVATE_H */
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index f6195b1..8c6544b 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -290,7 +290,7 @@ static ULONG WINAPI SysKeyboardAImpl_Rel
     ref = InterlockedDecrement(&(This->ref));
     if (ref) return ref;
 
-    set_dinput_hook(WH_KEYBOARD_LL, NULL);
+    set_dinput_hook(This->dinput, WH_KEYBOARD_LL, NULL);
 
     /* Free the data queue */
     HeapFree(GetProcessHeap(),0,This->buffer);
@@ -533,7 +533,7 @@ static HRESULT WINAPI SysKeyboardAImpl_A
           This->buffer = NULL;
 	}
 
-        set_dinput_hook(WH_KEYBOARD_LL, KeyboardCallback);
+        set_dinput_hook(This->dinput, WH_KEYBOARD_LL, KeyboardCallback);
 
 	return DI_OK;
 }
@@ -546,7 +546,7 @@ static HRESULT WINAPI SysKeyboardAImpl_U
         if (This->acquired == 0)
           return DI_NOEFFECT;
 
-        set_dinput_hook(WH_KEYBOARD_LL, NULL);
+        set_dinput_hook(This->dinput, WH_KEYBOARD_LL, NULL);
 
 	/* No more locks */
         if (current_lock == This)
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index e626bf6..16bda15 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -330,7 +330,7 @@ static ULONG WINAPI SysMouseAImpl_Releas
     if (ref)
 	return ref;
 
-    set_dinput_hook(WH_MOUSE_LL, NULL);
+    set_dinput_hook(This->dinput, WH_MOUSE_LL, NULL);
 
     /* Free the data queue */
     HeapFree(GetProcessHeap(),0,This->data_queue);
@@ -599,7 +599,7 @@ static HRESULT WINAPI SysMouseAImpl_Acqu
     /* Install our mouse hook */
     if (This->dwCoopLevel & DISCL_EXCLUSIVE)
       ShowCursor(FALSE); /* hide cursor */
-    set_dinput_hook(WH_MOUSE_LL, dinput_mouse_hook);
+    set_dinput_hook(This->dinput, WH_MOUSE_LL, dinput_mouse_hook);
     
     /* Get the window dimension and find the center */
     GetWindowRect(This->win, &rect);
@@ -638,7 +638,7 @@ static HRESULT WINAPI SysMouseAImpl_Unac
 	return DI_NOEFFECT;
     }
 
-    set_dinput_hook(WH_MOUSE_LL, NULL);
+    set_dinput_hook(This->dinput, WH_MOUSE_LL, NULL);
     if (This->dwCoopLevel & DISCL_EXCLUSIVE)
         ShowCursor(TRUE); /* show cursor */
 


More information about the wine-patches mailing list