[PATCH 6/8] dinput: Allow internal thread to be restarted.

Rémi Bernon rbernon at codeweavers.com
Wed Jan 5 07:58:40 CST 2022


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52263
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/dinput/dinput_main.c | 62 +++++++++++++++++++++------------------
 1 file changed, 34 insertions(+), 28 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 5ba959e8414..9903a02c42f 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -1262,15 +1262,19 @@ static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam
 static DWORD WINAPI dinput_thread_proc( void *params )
 {
     HANDLE events[128], start_event = params;
-    static HHOOK kbd_hook, mouse_hook;
+    HHOOK kbd_hook = NULL, mouse_hook = NULL;
     struct dinput_device *impl, *next;
     SIZE_T events_count = 0;
     HANDLE finished_event;
     HRESULT hr;
     DWORD ret;
+    HWND hwnd;
     MSG msg;
 
-    di_em_win = CreateWindowW( L"DIEmWin", L"DIEmWin", 0, 0, 0, 0, 0, HWND_MESSAGE, 0, DINPUT_instance, NULL );
+    TRACE( "starting internal thread\n" );
+
+    hwnd = CreateWindowW( L"DIEmWin", L"DIEmWin", 0, 0, 0, 0, 0, HWND_MESSAGE, 0, DINPUT_instance, NULL );
+    di_em_win = hwnd;
 
     /* Force creation of the message queue */
     PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE );
@@ -1312,7 +1316,7 @@ static DWORD WINAPI dinput_thread_proc( void *params )
             {
                 if (kbd_hook) UnhookWindowsHookEx( kbd_hook );
                 if (mouse_hook) UnhookWindowsHookEx( mouse_hook );
-                kbd_hook = mouse_hook = NULL;
+                di_em_win = 0;
                 LeaveCriticalSection( &dinput_hook_crit );
                 goto done;
             }
@@ -1356,42 +1360,44 @@ static DWORD WINAPI dinput_thread_proc( void *params )
     dinput_unacquire_window_devices( 0, TRUE );
     if (kbd_hook) UnhookWindowsHookEx( kbd_hook );
     if (mouse_hook) UnhookWindowsHookEx( mouse_hook );
-    kbd_hook = mouse_hook = NULL;
+    di_em_win = 0;
     LeaveCriticalSection( &dinput_hook_crit );
 
 done:
-    DestroyWindow( di_em_win );
-    di_em_win = NULL;
+    DestroyWindow( hwnd );
+
+    TRACE( "exiting internal thread\n" );
     return 0;
 }
 
-static BOOL WINAPI dinput_thread_start_once( INIT_ONCE *once, void *param, void **context )
-{
-    HANDLE start_event;
-
-    start_event = CreateEventW( NULL, FALSE, FALSE, NULL );
-    if (!start_event) ERR( "failed to create start event, error %u\n", GetLastError() );
-
-    dinput_thread = CreateThread( NULL, 0, dinput_thread_proc, start_event, 0, NULL );
-    if (!dinput_thread) ERR( "failed to create internal thread, error %u\n", GetLastError() );
-
-    WaitForSingleObject( start_event, INFINITE );
-    CloseHandle( start_event );
-
-    return TRUE;
-}
-
 static void dinput_thread_start(void)
 {
-    static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
-    InitOnceExecuteOnce( &init_once, dinput_thread_start_once, NULL, NULL );
+    HANDLE start_event, thread;
+
+    start_event = CreateEventW( NULL, FALSE, FALSE, NULL );
+    if (!start_event) ERR( "failed to create start event, error %u\n", GetLastError() );
+
+    thread = CreateThread( NULL, 0, dinput_thread_proc, start_event, 0, NULL );
+    if (!thread) ERR( "failed to create internal thread, error %u\n", GetLastError() );
+    else WaitForSingleObject( start_event, INFINITE );
+    CloseHandle( start_event );
+
+    CloseHandle( dinput_thread );
+    dinput_thread = thread;
 }
 
 static void dinput_thread_stop(void)
 {
+    HANDLE thread = NULL;
+
+    EnterCriticalSection( &dinput_hook_crit );
     PostMessageW( di_em_win, WM_USER + 0x10, 0, 0 );
-    WaitForSingleObject( dinput_thread, INFINITE );
-    CloseHandle( dinput_thread );
+    thread = dinput_thread;
+    dinput_thread = NULL;
+    LeaveCriticalSection( &dinput_hook_crit );
+
+    WaitForSingleObject( thread, INFINITE );
+    CloseHandle( thread );
 }
 
 void check_dinput_hooks( IDirectInputDevice8W *iface, BOOL acquired )
@@ -1401,10 +1407,10 @@ void check_dinput_hooks( IDirectInputDevice8W *iface, BOOL acquired )
     struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface );
     HANDLE hook_change_finished_event = NULL;
 
-    dinput_thread_start();
-
     EnterCriticalSection(&dinput_hook_crit);
 
+    if (!di_em_win) dinput_thread_start();
+
     if (impl->dwCoopLevel & DISCL_FOREGROUND)
     {
         if (acquired)
-- 
2.34.1




More information about the wine-devel mailing list