From 02e9c9997613f81c4f956bf1867e96068bd4f41d Mon Sep 17 00:00:00 2001 From: Michael Stefaniuc Date: Sat, 13 Apr 2013 21:41:32 +0200 Subject: [PATCH] dplayx: IDirectPlayLobby3 / IDirectPlayLobby3A have independent refcounts. --- dlls/dplayx/dplobby.c | 81 ++++++++++++++++++++------------------ dlls/dplayx/tests/dplayx.c | 2 +- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/dlls/dplayx/dplobby.c b/dlls/dplayx/dplobby.c index 12444cc4de3..a0c11dd7f1a 100644 --- a/dlls/dplayx/dplobby.c +++ b/dlls/dplayx/dplobby.c @@ -83,7 +83,8 @@ typedef struct IDirectPlayLobbyImpl { IDirectPlayLobby3 IDirectPlayLobby3_iface; IDirectPlayLobby3A IDirectPlayLobby3A_iface; - LONG ulInterfaceRef; + LONG numIfaces; /* "in use interfaces" refcount */ + LONG ref3, ref3A; CRITICAL_SECTION lock; DirectPlayLobbyData* dpl; } IDirectPlayLobbyImpl; @@ -152,40 +153,12 @@ static HRESULT WINAPI DPL_QueryInterface( IDirectPlayLobbyImpl *This, REFIID rii return S_OK; } -/* - * Simple procedure. Just increment the reference count to this - * structure and return the new reference count. - */ -static ULONG WINAPI DPL_AddRef( IDirectPlayLobbyImpl *This ) +static void dplobby_destroy(IDirectPlayLobbyImpl *obj) { - ULONG ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef ); - - TRACE( "ref count incremented to %u for %p\n", ulInterfaceRefCount, This ); - - return ulInterfaceRefCount; -} - -/* - * Simple COM procedure. Decrease the reference count to this object. - * If the object no longer has any reference counts, free up the associated - * memory. - */ -static ULONG WINAPI DPL_Release( IDirectPlayLobbyImpl *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 ) - { - DPL_DestroyLobby1( This ); - This->lock.DebugInfo->Spare[0] = 0; - DeleteCriticalSection( &This->lock ); - HeapFree( GetProcessHeap(), 0, This ); - } - - return ulInterfaceRefCount; + DPL_DestroyLobby1( obj ); + obj->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &obj->lock ); + HeapFree( GetProcessHeap(), 0, obj ); } static HRESULT WINAPI IDirectPlayLobby3AImpl_QueryInterface( IDirectPlayLobby3A *iface, REFIID riid, @@ -205,25 +178,53 @@ static HRESULT WINAPI IDirectPlayLobby3Impl_QueryInterface( IDirectPlayLobby3 *i static ULONG WINAPI IDirectPlayLobby3AImpl_AddRef(IDirectPlayLobby3A *iface) { IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); - return DPL_AddRef( This ); + ULONG ref = InterlockedIncrement( &This->ref3A ); + + TRACE( "(%p) ref3A=%d\n", This, ref ); + + if ( ref == 1 ) + InterlockedIncrement( &This->numIfaces ); + + return ref; } static ULONG WINAPI IDirectPlayLobby3Impl_AddRef(IDirectPlayLobby3 *iface) { IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); - return DPL_AddRef( This ); + ULONG ref = InterlockedIncrement( &This->ref3 ); + + TRACE( "(%p) ref3=%d\n", This, ref ); + + if ( ref == 1 ) + InterlockedIncrement( &This->numIfaces ); + + return ref; } static ULONG WINAPI IDirectPlayLobby3AImpl_Release(IDirectPlayLobby3A *iface) { IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); - return DPL_Release( This ); + ULONG ref = InterlockedDecrement( &This->ref3A ); + + TRACE( "(%p) ref3A=%d\n", This, ref ); + + if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) + dplobby_destroy( This ); + + return ref; } static ULONG WINAPI IDirectPlayLobby3Impl_Release(IDirectPlayLobby3 *iface) { IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); - return DPL_Release( This ); + ULONG ref = InterlockedDecrement( &This->ref3 ); + + TRACE( "(%p) ref3=%d\n", This, ref ); + + if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) + dplobby_destroy( This ); + + return ref; } @@ -1520,7 +1521,9 @@ HRESULT dplobby_create( REFIID riid, void **ppv ) obj->IDirectPlayLobby3_iface.lpVtbl = &dpl3_vt; obj->IDirectPlayLobby3A_iface.lpVtbl = &dpl3A_vt; - obj->ulInterfaceRef = 1; + obj->numIfaces = 1; + obj->ref3 = 1; + obj->ref3A = 0; InitializeCriticalSection( &obj->lock ); obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayLobbyImpl.lock"); diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 6ed864c6b68..991b3c6235e 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -6487,7 +6487,7 @@ static void test_COM_dplobby(void) hr = IDirectPlayLobby_QueryInterface(dpl, &IID_IDirectPlayLobbyA, (void**)&dplA); ok(hr == S_OK, "QueryInterface for IID_IDirectPlayLobbyA failed: %08x\n", hr); refcount = IDirectPlayLobby_AddRef(dplA); - todo_wine ok(refcount == 2, "refcount == %u, expected 2\n", refcount); + ok(refcount == 2, "refcount == %u, expected 2\n", refcount); IDirectPlayLobby_Release(dplA); hr = IDirectPlayLobby_QueryInterface(dpl, &IID_IDirectPlayLobby2, (void**)&dpl2);