Module: wine Branch: master Commit: d58055dd7d79cdb7466d4183ec4326f95a23cdd1 URL: https://gitlab.winehq.org/wine/wine/-/commit/d58055dd7d79cdb7466d4183ec4326f...
Author: Rémi Bernon rbernon@codeweavers.com Date: Sun Jan 22 14:45:43 2023 +0100
dinput: Keep a reference on acquired devices while waiting.
---
dlls/dinput/dinput_main.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 9daff6f3750..48aa53c63cb 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -46,10 +46,14 @@
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+#define INPUT_THREAD_MAX_DEVICES 128 + struct input_thread_state { UINT events_count; - HANDLE events[128]; + UINT devices_count; + struct dinput_device *devices[INPUT_THREAD_MAX_DEVICES]; + HANDLE events[INPUT_THREAD_MAX_DEVICES]; };
static inline struct dinput_device *impl_from_IDirectInputDevice8W( IDirectInputDevice8W *iface ) @@ -247,9 +251,11 @@ static void input_thread_update_device_list( struct input_thread_state *state ) { if (!device->read_event || !device->vtbl->read) continue; state->events[count] = device->read_event; - if (++count >= ARRAY_SIZE(state->events)) break; + dinput_device_internal_addref( (state->devices[count] = device) ); + if (++count >= INPUT_THREAD_MAX_DEVICES) break; } state->events_count = count; + state->devices_count = count; LeaveCriticalSection( &dinput_hook_crit ); }
@@ -258,7 +264,7 @@ static DWORD WINAPI dinput_thread_proc( void *params ) HANDLE finished_event, start_event = params; struct input_thread_state state = {0}; static HHOOK kbd_hook, mouse_hook; - struct dinput_device *impl, *next; + struct dinput_device *device; DWORD ret; MSG msg;
@@ -274,20 +280,13 @@ static DWORD WINAPI dinput_thread_proc( void *params )
if (ret < state.events_count) { - EnterCriticalSection( &dinput_hook_crit ); - LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_device_list, struct dinput_device, entry ) + if ((device = state.devices[ret]) && FAILED( device->vtbl->read( &device->IDirectInputDevice8W_iface ) )) { - if (impl->read_event == state.events[ret]) - { - if (FAILED( impl->vtbl->read( &impl->IDirectInputDevice8W_iface ) )) - { - dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface ); - impl->status = STATUS_UNPLUGGED; - } - break; - } + EnterCriticalSection( &dinput_hook_crit ); + dinput_device_internal_unacquire( &device->IDirectInputDevice8W_iface ); + LeaveCriticalSection( &dinput_hook_crit ); + device->status = STATUS_UNPLUGGED; } - LeaveCriticalSection( &dinput_hook_crit ); }
while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) @@ -335,12 +334,14 @@ static DWORD WINAPI dinput_thread_proc( void *params ) SetEvent(finished_event); }
+ while (state.devices_count--) dinput_device_internal_release( state.devices[state.devices_count] ); input_thread_update_device_list( &state ); }
if (ret != state.events_count) ERR("Unexpected termination, ret %#lx\n", ret);
done: + while (state.devices_count--) dinput_device_internal_release( state.devices[state.devices_count] ); DestroyWindow( di_em_win ); di_em_win = NULL; return 0;