Vitaliy Margolen : dinput: Create/destroy hook thread from DirectInput.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Sep 13 06:07:08 CDT 2006


Module: wine
Branch: master
Commit: ad045d6e8142d8fd197a8d445670a3fc95dfcda2
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=ad045d6e8142d8fd197a8d445670a3fc95dfcda2

Author: Vitaliy Margolen <wine-patch at kievinfo.com>
Date:   Wed Sep 13 00:06:15 2006 -0600

dinput: Create/destroy hook thread from DirectInput.

---

 dlls/dinput/dinput_main.c |   78 +++++++++++++++++++++++++++++++--------------
 1 files changed, 53 insertions(+), 25 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 2a05347..b60cd89 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -76,6 +76,8 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWO
     return TRUE;
 }
 
+static BOOL create_hook_thread(void);
+static void release_hook_thread(void);
 
 /******************************************************************************
  *	DirectInputCreateEx (DINPUT.@)
@@ -118,6 +120,7 @@ HRESULT WINAPI DirectInputCreateEx(
         res = DI_OK;
     }
 
+    if (res == DI_OK && !create_hook_thread()) res = DIERR_GENERIC;
     if (res == DI_OK)
     {
         This = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectInputImpl));
@@ -255,7 +258,10 @@ static ULONG WINAPI IDirectInputAImpl_Re
 	ULONG ref;
 	ref = InterlockedDecrement(&(This->ref));
 	if (ref == 0)
-		HeapFree(GetProcessHeap(),0,This);
+        {
+            HeapFree(GetProcessHeap(), 0, This);
+            release_hook_thread();
+        }
 	return ref;
 }
 
@@ -732,15 +738,21 @@ static LRESULT CALLBACK dinput_hook_WndP
                 return res;
             }
         }
+        else if (!wParam && !lParam)
+            DestroyWindow(hWnd);
+
         return 0;
 
     case WM_DESTROY:
+        if (kbd_hook) UnhookWindowsHookEx(kbd_hook);
+        if (mouse_hook) UnhookWindowsHookEx(mouse_hook);
         PostQuitMessage(0);
     }
     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)
 {
@@ -757,9 +769,9 @@ static DWORD WINAPI hook_thread_proc(voi
 
     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;
+    hook_thread_hwnd = hwnd;
 
-    SetEvent(signal_event);
+    SetEvent(*(LPHANDLE)param);
     if (hwnd)
     {
         while (GetMessageW(&msg, 0, 0, 0))
@@ -767,10 +779,10 @@ static DWORD WINAPI hook_thread_proc(voi
             TranslateMessage(&msg);
             DispatchMessageW(&msg);
         }
+        DestroyWindow(hwnd);
     }
     else ERR("Error creating message window\n");
 
-    DestroyWindow(hwnd);
     UnregisterClassW(wcex.lpszClassName, wcex.hInstance);
     return 0;
 }
@@ -784,41 +796,57 @@ static CRITICAL_SECTION_DEBUG dinput_cri
 };
 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;
-    static HWND   hook_thread_hwnd;
+    LONG ref;
 
     EnterCriticalSection(&dinput_hook_crit);
-    if (!hook_thread)
+    ref = ++hook_thread_refcount;
+    TRACE("Refcount %ld\n", ref);
+    if (ref == 1)
     {
         DWORD tid;
-        HWND hwnd;
+        HANDLE thread, event;
 
-        signal_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-        hook_thread = CreateThread(NULL, 0, hook_thread_proc, &hwnd, 0, &tid);
-        if (signal_event && hook_thread)
+        event = CreateEventW(NULL, FALSE, FALSE, NULL);
+        thread = CreateThread(NULL, 0, hook_thread_proc, &event, 0, &tid);
+        if (event && thread)
         {
             HANDLE handles[2];
-            handles[0] = signal_event;
-            handles[1] = hook_thread;
+            handles[0] = event;
+            handles[1] = 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;
-        }
+        CloseHandle(event);
+        CloseHandle(thread);
     }
     LeaveCriticalSection(&dinput_hook_crit);
 
-    return hook_thread_hwnd;
+    return hook_thread_hwnd != 0;
+}
+
+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) 
+    {
+        HWND hwnd = hook_thread_hwnd;
+        hook_thread_hwnd = 0;
+        SendMessageW(hwnd, WM_USER+0x10, 0, 0);
+    }
+    LeaveCriticalSection(&dinput_hook_crit);
 }
 
 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);
 }




More information about the wine-cvs mailing list