Vitaliy Margolen : dinput: Freed effect should remove itself from the parent's list of effects. Add tests.

Alexandre Julliard julliard at winehq.org
Mon Jul 7 09:19:12 CDT 2008


Module: wine
Branch: master
Commit: a478c4fe251daba7080f9e6dc934be5168eec1c8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a478c4fe251daba7080f9e6dc934be5168eec1c8

Author: Vitaliy Margolen <wine-patches at kievinfo.com>
Date:   Sat Jul  5 22:24:57 2008 -0600

dinput: Freed effect should remove itself from the parent's list of effects. Add tests.

---

 dlls/dinput/effect_linuxinput.c   |   13 ++++++----
 dlls/dinput/joystick_linuxinput.c |    4 +-
 dlls/dinput/tests/joystick.c      |   46 +++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/dlls/dinput/effect_linuxinput.c b/dlls/dinput/effect_linuxinput.c
index ab72d2c..1fef4cd 100644
--- a/dlls/dinput/effect_linuxinput.c
+++ b/dlls/dinput/effect_linuxinput.c
@@ -53,11 +53,9 @@ struct LinuxInputEffectImpl
     LONG	ref;
     GUID	guid;
 
-    /* Effect data */
-    struct ff_effect effect;
-
-    /* Parent device */
-    int* 	fd;
+    struct ff_effect    effect; /* Effect data */
+    int*                fd;     /* Parent device */
+    struct list        *entry;  /* Entry into the parent's list of effects */
 };
 
 
@@ -766,6 +764,8 @@ static ULONG WINAPI LinuxInputEffectImpl_Release(LPDIRECTINPUTEFFECT iface)
     {
         LinuxInputEffectImpl_Stop(iface);
         LinuxInputEffectImpl_Unload(iface);
+        list_remove(This->entry);
+        HeapFree(GetProcessHeap(), 0, LIST_ENTRY(This->entry, effect_list_item, entry));
         HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
@@ -778,6 +778,7 @@ static ULONG WINAPI LinuxInputEffectImpl_Release(LPDIRECTINPUTEFFECT iface)
 HRESULT linuxinput_create_effect(
 	int* fd,
 	REFGUID rguid,
+        struct list *parent_list_entry,
 	LPDIRECTINPUTEFFECT* peff)
 {
     LinuxInputEffectImpl* newEffect = HeapAlloc(GetProcessHeap(), 
@@ -835,6 +836,8 @@ HRESULT linuxinput_create_effect(
     /* mark as non-uploaded */
     newEffect->effect.id = -1;
 
+    newEffect->entry = parent_list_entry;
+
     *peff = (LPDIRECTINPUTEFFECT)newEffect; 
 
     TRACE("Creating linux input system effect (%p) with guid %s\n", 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index d3185d3..0ef90a1 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -141,7 +141,7 @@ struct wine_input_absinfo {
 };
 
 /* implemented in effect_linuxinput.c */
-HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, LPDIRECTINPUTEFFECT* peff);
+HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_list_entry, LPDIRECTINPUTEFFECT* peff);
 HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info);
 HRESULT linuxinput_get_info_W(int fd, REFGUID rguid, LPDIEFFECTINFOW info);
 
@@ -1053,7 +1053,7 @@ static HRESULT WINAPI JoystickAImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface,
     if (!(new_effect = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_effect))))
         return DIERR_OUTOFMEMORY;
 
-    retval = linuxinput_create_effect(&This->joyfd, rguid, &new_effect->ref);
+    retval = linuxinput_create_effect(&This->joyfd, rguid, &new_effect->entry, &new_effect->ref);
     if (retval != DI_OK)
     {
         HeapFree(GetProcessHeap(), 0, new_effect);
diff --git a/dlls/dinput/tests/joystick.c b/dlls/dinput/tests/joystick.c
index 4727a5a..567dad0 100644
--- a/dlls/dinput/tests/joystick.c
+++ b/dlls/dinput/tests/joystick.c
@@ -18,6 +18,7 @@
 
 #define DIRECTINPUT_VERSION 0x0700
 
+#define COBJMACROS
 #include <windows.h>
 
 #include <math.h>
@@ -85,6 +86,12 @@ typedef struct tagJoystickInfo
     DWORD dZone;
 } JoystickInfo;
 
+static int get_refcount(IUnknown *object)
+{
+    IUnknown_AddRef( object );
+    return IUnknown_Release( object );
+}
+
 static BOOL CALLBACK EnumAxes(
     const DIDEVICEOBJECTINSTANCE* pdidoi,
     VOID* pContext)
@@ -331,6 +338,45 @@ static BOOL CALLBACK EnumJoysticks(
         ok(js.rgdwPOV[3] == -1, "Default for unassigned POV should be -1 not: %d\n", js.rgdwPOV[3]);
     }
 
+    if (caps.dwFlags & DIDC_FORCEFEEDBACK)
+    {
+        DWORD axes[2] = {DIJOFS_X, DIJOFS_Y};
+        LONG  direction[2] = {0, 0};
+        DICONSTANTFORCE force = {0};
+        DIEFFECT eff;
+        LPDIRECTINPUTEFFECT effect = NULL;
+        LONG cnt1, cnt2;
+
+        trace("Testing force-feedback\n");
+        memset(&eff, 0, sizeof(eff));
+        eff.dwSize                = sizeof(eff);
+        eff.dwFlags               = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
+        eff.dwDuration            = INFINITE;
+        eff.dwGain                = DI_FFNOMINALMAX;
+        eff.dwTriggerButton       = DIEB_NOTRIGGER;
+        eff.cAxes                 = sizeof(axes) / sizeof(axes[0]);
+        eff.rgdwAxes              = axes;
+        eff.rglDirection          = direction;
+        eff.cbTypeSpecificParams  = sizeof(force);
+        eff.lpvTypeSpecificParams = &force;
+
+        cnt1 = get_refcount((IUnknown*)pJoystick);
+
+        hr = IDirectInputDevice2_CreateEffect((LPDIRECTINPUTDEVICE2)pJoystick, &GUID_ConstantForce,
+                                              &eff, &effect, NULL);
+        ok(hr == DI_OK, "IDirectInputDevice_CreateEffect() failed: %s\n", DXGetErrorString8(hr));
+        cnt2 = get_refcount((IUnknown*)pJoystick);
+        ok(cnt1 == cnt2, "Ref count is wrong %d != %d\n", cnt1, cnt2);
+
+        if (effect)
+        {
+            ref = IUnknown_Release(effect);
+            ok(ref == 0, "IDirectInputDevice_Release() reference count = %d\n", ref);
+        }
+        cnt1 = get_refcount((IUnknown*)pJoystick);
+        ok(cnt1 == cnt2, "Ref count is wrong %d != %d\n", cnt1, cnt2);
+    }
+
     if (winetest_interactive) {
         trace("You have 30 seconds to test all axes, sliders, POVs and buttons\n");
         count = 300;




More information about the wine-cvs mailing list