[PATCH 23/54] dplayx: IDirectPlay4 / IDirectPlay4A have independent refcounts.

Michael Stefaniuc mstefani at redhat.de
Fri Mar 29 10:49:30 CDT 2013


---
 dlls/dplayx/dplay.c        | 77 +++++++++++++++++++++++++---------------------
 dlls/dplayx/dplay_global.h |  3 +-
 dlls/dplayx/tests/dplayx.c |  2 +-
 3 files changed, 45 insertions(+), 37 deletions(-)

diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c
index 93862a3..b3bb7c6 100644
--- a/dlls/dplayx/dplay.c
+++ b/dlls/dplayx/dplay.c
@@ -355,6 +355,13 @@ static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
   return TRUE;
 }
 
+static void dplay_destroy(IDirectPlayImpl *obj)
+{
+     DP_DestroyDirectPlay2( obj );
+     obj->lock.DebugInfo->Spare[0] = 0;
+     DeleteCriticalSection( &obj->lock );
+     HeapFree( GetProcessHeap(), 0, obj );
+}
 
 /* Direct Play methods */
 
@@ -381,36 +388,6 @@ static HRESULT WINAPI DP_QueryInterface( IDirectPlayImpl *This, REFIID riid, voi
   return S_OK;
 }
 
-/* Shared between all dplay types */
-static ULONG WINAPI DP_AddRef( IDirectPlayImpl *This )
-{
-  ULONG ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
-
-  TRACE( "ref count incremented to %u for %p\n", ulInterfaceRefCount, This );
-
-  return ulInterfaceRefCount;
-}
-
-static ULONG WINAPI DP_Release( IDirectPlayImpl *This )
-{
-  ULONG ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
-
-  TRACE( "ref count decremented to %u for %p\n", ulInterfaceRefCount, This );
-
-  /* Deallocate if this is the last reference to the object */
-  if( ulInterfaceRefCount == 0 )
-  {
-     /* If we're destroying the object, this must be the last ref
-        of the last interface */
-     DP_DestroyDirectPlay2( This );
-     This->lock.DebugInfo->Spare[0] = 0;
-     DeleteCriticalSection( &This->lock );
-     HeapFree( GetProcessHeap(), 0, This );
-  }
-
-  return ulInterfaceRefCount;
-}
-
 static inline DPID DP_NextObjectId(void)
 {
   return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
@@ -610,25 +587,53 @@ static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFI
 static ULONG WINAPI IDirectPlay4AImpl_AddRef(IDirectPlay4A *iface)
 {
     IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
-    return DP_AddRef( This );
+    ULONG ref = InterlockedIncrement( &This->ref4A );
+
+    TRACE( "(%p) ref4A=%d\n", This, ref );
+
+    if ( ref == 1 )
+        InterlockedIncrement( &This->numIfaces );
+
+    return ref;
 }
 
 static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface)
 {
     IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
-    return DP_AddRef( This );
+    ULONG ref = InterlockedIncrement( &This->ref4 );
+
+    TRACE( "(%p) ref4=%d\n", This, ref );
+
+    if ( ref == 1 )
+        InterlockedIncrement( &This->numIfaces );
+
+    return ref;
 }
 
 static ULONG WINAPI IDirectPlay4AImpl_Release(IDirectPlay4A *iface)
 {
     IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
-    return DP_Release( This );
+    ULONG ref = InterlockedDecrement( &This->ref4A );
+
+    TRACE( "(%p) ref4A=%d\n", This, ref );
+
+    if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
+        dplay_destroy( This );
+
+    return ref;
 }
 
 static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface)
 {
     IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
-    return DP_Release( This );
+    ULONG ref = InterlockedDecrement( &This->ref4 );
+
+    TRACE( "(%p) ref4=%d\n", This, ref );
+
+    if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
+        dplay_destroy( This );
+
+    return ref;
 }
 
 static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface, DPID idGroup,
@@ -4700,7 +4705,9 @@ HRESULT dplay_create( REFIID riid, void **ppv )
 
     obj->IDirectPlay4A_iface.lpVtbl = &dp4A_vt;
     obj->IDirectPlay4_iface.lpVtbl = &dp4_vt;
-    obj->ulInterfaceRef = 1;
+    obj->numIfaces = 1;
+    obj->ref4A = 1;
+    obj->ref4 = 0;
 
     InitializeCriticalSection( &obj->lock );
     obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayImpl.lock");
diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h
index 4684f53..18eb8077 100644
--- a/dlls/dplayx/dplay_global.h
+++ b/dlls/dplayx/dplay_global.h
@@ -184,7 +184,8 @@ typedef struct IDirectPlayImpl
 {
   IDirectPlay4A IDirectPlay4A_iface;
   IDirectPlay4  IDirectPlay4_iface;
-  LONG ulInterfaceRef;
+  LONG numIfaces; /* "in use interfaces" refcount */
+  LONG ref4A, ref4;
   CRITICAL_SECTION lock;
   DirectPlay2Data *dp2;
 } IDirectPlayImpl;
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c
index b7bbac3..840015d 100644
--- a/dlls/dplayx/tests/dplayx.c
+++ b/dlls/dplayx/tests/dplayx.c
@@ -6399,7 +6399,7 @@ static void test_COM(void)
     hr = IDirectPlayX_QueryInterface(dp4, &IID_IDirectPlay2A, (void**)&dp2A);
     ok(hr == S_OK, "QueryInterface for IID_IDirectPlay2A failed: %08x\n", hr);
     refcount = IDirectPlay2_AddRef(dp2A);
-    todo_wine ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
+    ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
     IDirectPlay2_Release(dp2A);
 
     hr = IDirectPlayX_QueryInterface(dp4, &IID_IDirectPlay2, (void**)&dp2);
-- 
1.7.11.7



More information about the wine-patches mailing list