[PATCH 2/7] dinput: Keep a private ref to the device on created effects.

Rémi Bernon rbernon at codeweavers.com
Mon Oct 4 02:51:29 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/dinput/joystick_hid.c | 47 +++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 8 deletions(-)

diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index 8f5dbee9dc3..b71f9f5f56b 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -90,6 +90,7 @@ struct pid_control_report
 struct hid_joystick
 {
     IDirectInputDeviceImpl base;
+    LONG ref;
 
     HANDLE device;
     OVERLAPPED read_ovl;
@@ -124,6 +125,8 @@ struct hid_joystick_effect
 {
     IDirectInputEffect IDirectInputEffect_iface;
     LONG ref;
+
+    struct hid_joystick *joystick;
 };
 
 static inline struct hid_joystick_effect *impl_from_IDirectInputEffect( IDirectInputEffect *iface )
@@ -372,13 +375,17 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header,
     return DIENUM_CONTINUE;
 }
 
-static ULONG WINAPI hid_joystick_Release( IDirectInputDevice8W *iface )
+static ULONG hid_joystick_private_incref( struct hid_joystick *impl )
+{
+    return IDirectInputDevice2WImpl_AddRef( &impl->base.IDirectInputDevice8W_iface );
+}
+
+static ULONG hid_joystick_private_decref( struct hid_joystick *impl )
 {
-    struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
     struct hid_joystick tmp = *impl;
     ULONG ref;
 
-    if (!(ref = IDirectInputDevice2WImpl_Release( iface )))
+    if (!(ref = IDirectInputDevice2WImpl_Release( &impl->base.IDirectInputDevice8W_iface )))
     {
         HeapFree( GetProcessHeap(), 0, tmp.usages_buf );
         HeapFree( GetProcessHeap(), 0, tmp.output_report_buf );
@@ -393,6 +400,23 @@ static ULONG WINAPI hid_joystick_Release( IDirectInputDevice8W *iface )
     return ref;
 }
 
+static ULONG WINAPI hid_joystick_AddRef( IDirectInputDevice8W *iface )
+{
+    struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
+    ULONG ref = InterlockedIncrement( &impl->ref );
+    TRACE( "iface %p, ref %u.\n", iface, ref );
+    return ref;
+}
+
+static ULONG WINAPI hid_joystick_Release( IDirectInputDevice8W *iface )
+{
+    struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
+    ULONG ref = InterlockedDecrement( &impl->ref );
+    TRACE( "iface %p, ref %u.\n", iface, ref );
+    if (!ref) hid_joystick_private_decref( impl );
+    return ref;
+}
+
 static HRESULT WINAPI hid_joystick_GetCapabilities( IDirectInputDevice8W *iface, DIDEVCAPS *caps )
 {
     struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
@@ -814,7 +838,7 @@ static HRESULT WINAPI hid_joystick_GetDeviceInfo( IDirectInputDevice8W *iface, D
     return S_OK;
 }
 
-static HRESULT hid_joystick_effect_create( IDirectInputEffect **out );
+static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirectInputEffect **out );
 
 static HRESULT WINAPI hid_joystick_CreateEffect( IDirectInputDevice8W *iface, const GUID *guid,
                                                  const DIEFFECT *params, IDirectInputEffect **out,
@@ -831,7 +855,7 @@ static HRESULT WINAPI hid_joystick_CreateEffect( IDirectInputDevice8W *iface, co
     *out = NULL;
 
     if (!(impl->dev_caps.dwFlags & DIDC_FORCEFEEDBACK)) return DIERR_UNSUPPORTED;
-    if (FAILED(hr = hid_joystick_effect_create( out ))) return hr;
+    if (FAILED(hr = hid_joystick_effect_create( impl, out ))) return hr;
 
     hr = IDirectInputEffect_Initialize( *out, DINPUT_instance, impl->base.dinput->dwVersion, guid );
     if (FAILED(hr)) goto failed;
@@ -1035,7 +1059,7 @@ static const IDirectInputDevice8WVtbl hid_joystick_vtbl =
 {
     /*** IUnknown methods ***/
     IDirectInputDevice2WImpl_QueryInterface,
-    IDirectInputDevice2WImpl_AddRef,
+    hid_joystick_AddRef,
     hid_joystick_Release,
     /*** IDirectInputDevice methods ***/
     hid_joystick_GetCapabilities,
@@ -1677,6 +1701,7 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID
                                    &attrs, &impl->caps, dinput->dwVersion );
     if (hr != DI_OK) goto failed;
 
+    impl->ref = 1;
     impl->instance = instance;
     impl->attrs = attrs;
     impl->dev_caps.dwSize = sizeof(impl->dev_caps);
@@ -1786,7 +1811,11 @@ static ULONG WINAPI hid_joystick_effect_Release( IDirectInputEffect *iface )
     struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
     ULONG ref = InterlockedDecrement( &impl->ref );
     TRACE( "iface %p, ref %u.\n", iface, ref );
-    if (!ref) HeapFree( GetProcessHeap(), 0, impl );
+    if (!ref)
+    {
+        hid_joystick_private_decref( impl->joystick );
+        HeapFree( GetProcessHeap(), 0, impl );
+    }
     return ref;
 }
 
@@ -1874,7 +1903,7 @@ static IDirectInputEffectVtbl hid_joystick_effect_vtbl =
     hid_joystick_effect_Escape,
 };
 
-static HRESULT hid_joystick_effect_create( IDirectInputEffect **out )
+static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirectInputEffect **out )
 {
     struct hid_joystick_effect *impl;
 
@@ -1882,6 +1911,8 @@ static HRESULT hid_joystick_effect_create( IDirectInputEffect **out )
         return DIERR_OUTOFMEMORY;
     impl->IDirectInputEffect_iface.lpVtbl = &hid_joystick_effect_vtbl;
     impl->ref = 1;
+    impl->joystick = joystick;
+    hid_joystick_private_incref( joystick );
 
     *out = &impl->IDirectInputEffect_iface;
     return DI_OK;
-- 
2.33.0




More information about the wine-devel mailing list