From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 38 +++++++++++++++++++++++------------- dlls/dinput/device_private.h | 8 ++++++-- dlls/dinput/joystick_hid.c | 38 ++++++++++++------------------------ 3 files changed, 42 insertions(+), 42 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index e53940a2e3b..afb3a1512bb 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -693,25 +693,35 @@ static HRESULT WINAPI dinput_device_SetEventNotification( IDirectInputDevice8W * return DI_OK; }
-void dinput_device_destroy( IDirectInputDevice8W *iface ) +void dinput_device_internal_addref( struct dinput_device *impl ) { - struct dinput_device *This = impl_from_IDirectInputDevice8W( iface ); + ULONG ref = InterlockedIncrement( &impl->internal_ref ); + TRACE( "impl %p, internal ref %lu.\n", impl, ref ); +}
- TRACE( "iface %p.\n", iface ); +void dinput_device_internal_release( struct dinput_device *impl ) +{ + ULONG ref = InterlockedDecrement( &impl->internal_ref ); + TRACE( "impl %p, internal ref %lu.\n", impl, ref );
- free( This->object_properties ); - free( This->data_queue ); + if (!ref) + { + if (impl->vtbl->destroy) impl->vtbl->destroy( &impl->IDirectInputDevice8W_iface );
- free( This->device_format.rgodf ); - dinput_device_release_user_format( This ); + free( impl->object_properties ); + free( impl->data_queue );
- free( This->action_map ); + free( impl->device_format.rgodf ); + dinput_device_release_user_format( impl );
- IDirectInput_Release(&This->dinput->IDirectInput7A_iface); - This->crit.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->crit); + free( impl->action_map );
- free( This ); + IDirectInput_Release( &impl->dinput->IDirectInput7A_iface ); + impl->crit.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &impl->crit ); + + free( impl ); + } }
static ULONG WINAPI dinput_device_Release( IDirectInputDevice8W *iface ) @@ -724,8 +734,7 @@ static ULONG WINAPI dinput_device_Release( IDirectInputDevice8W *iface ) if (!ref) { IDirectInputDevice_Unacquire( iface ); - if (impl->vtbl->release) impl->vtbl->release( iface ); - else dinput_device_destroy( iface ); + dinput_device_internal_release( impl ); }
return ref; @@ -2107,6 +2116,7 @@ void dinput_device_init( struct dinput_device *device, const struct dinput_devic { device->IDirectInputDevice8A_iface.lpVtbl = &dinput_device_a_vtbl; device->IDirectInputDevice8W_iface.lpVtbl = &dinput_device_w_vtbl; + device->internal_ref = 1; device->ref = 1; device->guid = *guid; device->instance.dwSize = sizeof(DIDEVICEINSTANCEW); diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 45250ed082b..fd48a602b97 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -36,7 +36,7 @@ typedef struct
struct dinput_device_vtbl { - void (*release)( IDirectInputDevice8W *iface ); + void (*destroy)( IDirectInputDevice8W *iface ); HRESULT (*poll)( IDirectInputDevice8W *iface ); HRESULT (*read)( IDirectInputDevice8W *iface ); HRESULT (*acquire)( IDirectInputDevice8W *iface ); @@ -81,7 +81,9 @@ struct dinput_device { IDirectInputDevice8W IDirectInputDevice8W_iface; IDirectInputDevice8A IDirectInputDevice8A_iface; + LONG internal_ref; LONG ref; + GUID guid; CRITICAL_SECTION crit; struct dinput *dinput; @@ -125,8 +127,10 @@ struct dinput_device
extern void dinput_device_init( struct dinput_device *device, const struct dinput_device_vtbl *vtbl, const GUID *guid, struct dinput *dinput ); +extern void dinput_device_internal_addref( struct dinput_device *device ); +extern void dinput_device_internal_release( struct dinput_device *device ); + extern HRESULT dinput_device_init_device_format( IDirectInputDevice8W *iface ); -extern void dinput_device_destroy( IDirectInputDevice8W *iface );
extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN; extern DWORD get_config_key( HKEY, HKEY, const WCHAR *, WCHAR *, DWORD ) DECLSPEC_HIDDEN; diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 2ec218ffc09..6846410e02c 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -172,7 +172,6 @@ struct pid_effect_state struct hid_joystick { struct dinput_device base; - LONG internal_ref;
HANDLE device; OVERLAPPED read_ovl; @@ -775,30 +774,18 @@ static void set_report_value( struct hid_joystick *impl, char *report_buf, caps->usage_page, caps->usage_min, status ); }
-static void hid_joystick_addref( IDirectInputDevice8W *iface ) +static void hid_joystick_destroy( IDirectInputDevice8W *iface ) { struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); - ULONG ref = InterlockedIncrement( &impl->internal_ref ); - TRACE( "iface %p, internal ref %lu.\n", iface, ref ); -} - -static void hid_joystick_release( IDirectInputDevice8W *iface ) -{ - struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); - ULONG ref = InterlockedDecrement( &impl->internal_ref ); - TRACE( "iface %p, internal ref %lu.\n", iface, ref ); + TRACE( "iface %p.\n", iface );
- if (!ref) - { - free( impl->usages_buf ); - free( impl->feature_report_buf ); - free( impl->output_report_buf ); - free( impl->input_report_buf ); - HidD_FreePreparsedData( impl->preparsed ); - CloseHandle( impl->base.read_event ); - CloseHandle( impl->device ); - dinput_device_destroy( iface ); - } + free( impl->usages_buf ); + free( impl->feature_report_buf ); + free( impl->output_report_buf ); + free( impl->input_report_buf ); + HidD_FreePreparsedData( impl->preparsed ); + CloseHandle( impl->base.read_event ); + CloseHandle( impl->device ); }
static HRESULT hid_joystick_get_property( IDirectInputDevice8W *iface, DWORD property, @@ -1367,7 +1354,7 @@ static HRESULT hid_joystick_enum_objects( IDirectInputDevice8W *iface, const DIP
static const struct dinput_device_vtbl hid_joystick_vtbl = { - hid_joystick_release, + hid_joystick_destroy, NULL, hid_joystick_read, hid_joystick_acquire, @@ -2036,7 +2023,6 @@ HRESULT hid_joystick_create_device( struct dinput *dinput, const GUID *guid, IDi impl->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": hid_joystick.base.crit"); impl->base.dwCoopLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND; impl->base.read_event = CreateEventW( NULL, TRUE, FALSE, NULL ); - impl->internal_ref = 1;
if (memcmp( device_path_guid.Data4, guid->Data4, sizeof(device_path_guid.Data4) )) hr = hid_joystick_device_open( -1, guid, &impl->base.instance, impl->device_path, &impl->device, &impl->preparsed, @@ -2163,7 +2149,7 @@ static ULONG WINAPI hid_joystick_effect_Release( IDirectInputEffect *iface ) EnterCriticalSection( &impl->joystick->base.crit ); list_remove( &impl->entry ); LeaveCriticalSection( &impl->joystick->base.crit ); - hid_joystick_release( &impl->joystick->base.IDirectInputDevice8W_iface ); + dinput_device_internal_release( &impl->joystick->base ); free( impl->set_envelope_buf ); free( impl->type_specific_buf ); free( impl->effect_update_buf ); @@ -3155,7 +3141,7 @@ static HRESULT hid_joystick_create_effect( IDirectInputDevice8W *iface, IDirectI impl->IDirectInputEffect_iface.lpVtbl = &hid_joystick_effect_vtbl; impl->ref = 1; impl->joystick = joystick; - hid_joystick_addref( &joystick->base.IDirectInputDevice8W_iface ); + dinput_device_internal_addref( &joystick->base );
EnterCriticalSection( &joystick->base.crit ); list_add_tail( &joystick->effect_list, &impl->entry );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/dinput_main.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 19bdf07975d..896126635bd 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -46,6 +46,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+struct input_thread_state +{ + UINT events_count; + HANDLE events[128]; +}; + static inline struct dinput_device *impl_from_IDirectInputDevice8W( IDirectInputDevice8W *iface ) { return CONTAINING_RECORD( iface, struct dinput_device, IDirectInputDevice8W_iface ); @@ -233,11 +239,10 @@ 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; + HANDLE finished_event, start_event = params; + struct input_thread_state state = {0}; static HHOOK kbd_hook, mouse_hook; struct dinput_device *impl, *next; - SIZE_T events_count = 0; - HANDLE finished_event; DWORD ret; MSG msg;
@@ -247,16 +252,16 @@ static DWORD WINAPI dinput_thread_proc( void *params ) PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE ); SetEvent( start_event );
- while ((ret = MsgWaitForMultipleObjectsEx( events_count, events, INFINITE, QS_ALLINPUT, 0 )) <= events_count) + while ((ret = MsgWaitForMultipleObjectsEx( state.events_count, state.events, INFINITE, QS_ALLINPUT, 0 )) <= state.events_count) { UINT kbd_cnt = 0, mice_cnt = 0;
- if (ret < events_count) + if (ret < state.events_count) { EnterCriticalSection( &dinput_hook_crit ); LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_device_list, struct dinput_device, entry ) { - if (impl->read_event == events[ret]) + if (impl->read_event == state.events[ret]) { if (FAILED( impl->vtbl->read( &impl->IDirectInputDevice8W_iface ) )) { @@ -314,18 +319,18 @@ static DWORD WINAPI dinput_thread_proc( void *params ) SetEvent(finished_event); }
- events_count = 0; + state.events_count = 0; EnterCriticalSection( &dinput_hook_crit ); LIST_FOR_EACH_ENTRY( impl, &acquired_device_list, struct dinput_device, entry ) { if (!impl->read_event || !impl->vtbl->read) continue; - if (events_count >= ARRAY_SIZE(events)) break; - events[events_count++] = impl->read_event; + if (state.events_count >= ARRAY_SIZE(state.events)) break; + state.events[state.events_count++] = impl->read_event; } LeaveCriticalSection( &dinput_hook_crit ); }
- if (ret != events_count) ERR("Unexpected termination, ret %#lx\n", ret); + if (ret != state.events_count) ERR("Unexpected termination, ret %#lx\n", ret);
done: DestroyWindow( di_em_win );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/dinput_main.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 896126635bd..9daff6f3750 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -237,6 +237,22 @@ static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam return CallNextHookEx( 0, code, wparam, lparam ); }
+static void input_thread_update_device_list( struct input_thread_state *state ) +{ + struct dinput_device *device; + UINT count = 0; + + EnterCriticalSection( &dinput_hook_crit ); + LIST_FOR_EACH_ENTRY( device, &acquired_device_list, struct dinput_device, entry ) + { + if (!device->read_event || !device->vtbl->read) continue; + state->events[count] = device->read_event; + if (++count >= ARRAY_SIZE(state->events)) break; + } + state->events_count = count; + LeaveCriticalSection( &dinput_hook_crit ); +} + static DWORD WINAPI dinput_thread_proc( void *params ) { HANDLE finished_event, start_event = params; @@ -319,15 +335,7 @@ static DWORD WINAPI dinput_thread_proc( void *params ) SetEvent(finished_event); }
- state.events_count = 0; - EnterCriticalSection( &dinput_hook_crit ); - LIST_FOR_EACH_ENTRY( impl, &acquired_device_list, struct dinput_device, entry ) - { - if (!impl->read_event || !impl->vtbl->read) continue; - if (state.events_count >= ARRAY_SIZE(state.events)) break; - state.events[state.events_count++] = impl->read_event; - } - LeaveCriticalSection( &dinput_hook_crit ); + input_thread_update_device_list( &state ); }
if (ret != state.events_count) ERR("Unexpected termination, ret %#lx\n", ret);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 5 ++--- dlls/dinput/dinput.c | 30 ++++++++++++++++++++++++------ dlls/dinput/dinput_private.h | 4 ++++ dlls/dinput/tests/device8.c | 1 - dlls/dinput/tests/hid.c | 2 -- 5 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index afb3a1512bb..7f97067bd81 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -716,7 +716,7 @@ void dinput_device_internal_release( struct dinput_device *impl )
free( impl->action_map );
- IDirectInput_Release( &impl->dinput->IDirectInput7A_iface ); + dinput_internal_release( impl->dinput ); impl->crit.DebugInfo->Spare[0] = 0; DeleteCriticalSection( &impl->crit );
@@ -2125,8 +2125,7 @@ void dinput_device_init( struct dinput_device *device, const struct dinput_devic device->device_gain = 10000; device->force_feedback_state = DIGFFS_STOPPED | DIGFFS_EMPTY; InitializeCriticalSection( &device->crit ); - device->dinput = dinput; - IDirectInput_AddRef( &dinput->IDirectInput7A_iface ); + dinput_internal_addref( (device->dinput = dinput) ); device->vtbl = vtbl; }
diff --git a/dlls/dinput/dinput.c b/dlls/dinput/dinput.c index 08d36246071..7cf06364dc3 100644 --- a/dlls/dinput/dinput.c +++ b/dlls/dinput/dinput.c @@ -107,6 +107,28 @@ static HRESULT WINAPI dinput7_EnumDevices( IDirectInput7W *iface, DWORD type, LP return IDirectInput8_EnumDevices( &impl->IDirectInput8W_iface, type, callback, context, flags ); }
+void dinput_internal_addref( struct dinput *impl ) +{ + ULONG ref = InterlockedIncrement( &impl->internal_ref ); + TRACE( "impl %p, internal ref %lu.\n", impl, ref ); +} + +void dinput_internal_release( struct dinput *impl ) +{ + ULONG ref = InterlockedDecrement( &impl->internal_ref ); + TRACE( "impl %p, internal ref %lu.\n", impl, ref ); + + if (!ref) + { + struct DevicePlayer *device_player, *device_player2; + + LIST_FOR_EACH_ENTRY_SAFE( device_player, device_player2, &impl->device_players, struct DevicePlayer, entry ) + free( device_player ); + + free( impl ); + } +} + static ULONG WINAPI dinput7_AddRef( IDirectInput7W *iface ) { struct dinput *impl = impl_from_IDirectInput7W( iface ); @@ -124,12 +146,7 @@ static ULONG WINAPI dinput7_Release( IDirectInput7W *iface )
if (!ref) { - struct DevicePlayer *device_player, *device_player2; - - LIST_FOR_EACH_ENTRY_SAFE( device_player, device_player2, &impl->device_players, struct DevicePlayer, entry ) - free( device_player ); - - free( impl ); + dinput_internal_release( impl ); }
return ref; @@ -792,6 +809,7 @@ static HRESULT dinput_create( IUnknown **out ) impl->IDirectInput8A_iface.lpVtbl = &dinput8_a_vtbl; impl->IDirectInput8W_iface.lpVtbl = &dinput8_vtbl; impl->IDirectInputJoyConfig8_iface.lpVtbl = &joy_config_vtbl; + impl->internal_ref = 1; impl->ref = 1;
list_init( &impl->device_players ); diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h index 79a5baabb6e..fb9558716a3 100644 --- a/dlls/dinput/dinput_private.h +++ b/dlls/dinput/dinput_private.h @@ -36,6 +36,7 @@ struct dinput IDirectInput8A IDirectInput8A_iface; IDirectInput8W IDirectInput8W_iface; IDirectInputJoyConfig8 IDirectInputJoyConfig8_iface; + LONG internal_ref; LONG ref;
DWORD dwVersion; /* direct input version number */ @@ -46,6 +47,9 @@ struct dinput extern const IDirectInput7AVtbl dinput7_a_vtbl DECLSPEC_HIDDEN; extern const IDirectInput8AVtbl dinput8_a_vtbl DECLSPEC_HIDDEN;
+extern void dinput_internal_addref( struct dinput *dinput ); +extern void dinput_internal_release( struct dinput *dinput ); + extern HRESULT mouse_enum_device( DWORD type, DWORD flags, DIDEVICEINSTANCEW *instance, DWORD version ); extern HRESULT mouse_create_device( struct dinput *dinput, const GUID *guid, IDirectInputDevice8W **out ); extern HRESULT keyboard_enum_device( DWORD type, DWORD flags, DIDEVICEINSTANCEW *instance, DWORD version ); diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index 86f0360c0f1..449402621a7 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -116,7 +116,6 @@ static HRESULT create_dinput_device( DWORD version, const GUID *guid, IDirectInp ok( hr == DI_OK, "CreateDevice returned %#lx\n", hr );
ref = IDirectInput_Release( dinput ); - todo_wine ok( ref == 0, "Release returned %ld\n", ref );
return DI_OK; diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index a5ede6ee29b..facbf69fcec 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -3689,7 +3689,6 @@ HRESULT dinput_test_create_device( DWORD version, DIDEVICEINSTANCEW *devinst, ID ok( hr == DI_OK, "CreateDevice returned %#lx\n", hr );
ref = IDirectInput8_Release( di8 ); - todo_wine ok( ref == 0, "Release returned %ld\n", ref ); } else @@ -3716,7 +3715,6 @@ HRESULT dinput_test_create_device( DWORD version, DIDEVICEINSTANCEW *devinst, ID ok( hr == DI_OK, "CreateDevice returned %#lx\n", hr );
ref = IDirectInput_Release( di ); - todo_wine ok( ref == 0, "Release returned %ld\n", ref ); }
From: Rémi Bernon rbernon@codeweavers.com
--- 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;