From: "Rémi Bernon" Subject: [PATCH 6/8] dinput: Allow internal thread to be restarted. Message-Id: <20220105135842.718365-6-rbernon@codeweavers.com> Date: Wed, 5 Jan 2022 14:58:40 +0100 In-Reply-To: <20220105135842.718365-1-rbernon@codeweavers.com> References: <20220105135842.718365-1-rbernon@codeweavers.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52263 Signed-off-by: Rémi Bernon --- 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