Alexandre Julliard : rpcrt4: Fix the PSFactoryBuffer proxy refcounting, with tests.
Alexandre Julliard
julliard at winehq.org
Thu May 28 09:39:39 CDT 2009
Module: wine
Branch: master
Commit: 7571c1fd5397bd59de3f88f2d5ab89bdd07a496e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=7571c1fd5397bd59de3f88f2d5ab89bdd07a496e
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed May 27 21:25:10 2009 +0200
rpcrt4: Fix the PSFactoryBuffer proxy refcounting, with tests.
---
dlls/rpcrt4/cproxy.c | 13 +++-----
dlls/rpcrt4/tests/cstub.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 74 insertions(+), 8 deletions(-)
diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c
index a677ca0..f5fb6f3 100644
--- a/dlls/rpcrt4/cproxy.c
+++ b/dlls/rpcrt4/cproxy.c
@@ -147,11 +147,11 @@ HRESULT StdProxy_Construct(REFIID riid,
if (stubless) {
CInterfaceStubVtbl *svtbl = ProxyInfo->pStubVtblList[Index];
- unsigned long i, count = svtbl->header.DispatchTableCount;
+ ULONG i, count = svtbl->header.DispatchTableCount;
/* Maybe the original vtbl is just modified directly to point at
* ObjectStublessClientXXX thunks in real Windows, but I don't like it
*/
- TRACE("stubless thunks: count=%ld\n", count);
+ TRACE("stubless thunks: count=%d\n", count);
This->thunks = HeapAlloc(GetProcessHeap(),0,sizeof(struct StublessThunk)*count);
This->PVtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID)*count);
for (i=0; i<count; i++) {
@@ -159,7 +159,7 @@ HRESULT StdProxy_Construct(REFIID riid,
if (vtbl->Vtbl[i] == (LPVOID)-1) {
PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i];
unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST;
- TRACE("method %ld: stacksize=%d\n", i, bytes);
+ TRACE("method %d: stacksize=%d\n", i, bytes);
FILL_STUBLESS(thunk, i, bytes)
This->PVtbl[i] = thunk;
}
@@ -172,6 +172,7 @@ HRESULT StdProxy_Construct(REFIID riid,
else
This->PVtbl = vtbl->Vtbl;
+ if (!pUnkOuter) pUnkOuter = (IUnknown *)This;
This->lpVtbl = &StdProxy_Vtbl;
/* one reference for the proxy */
This->RefCount = 1;
@@ -183,11 +184,7 @@ HRESULT StdProxy_Construct(REFIID riid,
This->pChannel = NULL;
*ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl;
*ppvObj = &This->PVtbl;
- /* if there is no outer unknown then the caller will control the lifetime
- * of the proxy object through the proxy buffer, so no need to increment the
- * ref count of the proxy object */
- if (pUnkOuter)
- IUnknown_AddRef((IUnknown *)*ppvObj);
+ IUnknown_AddRef((IUnknown *)*ppvObj);
IPSFactoryBuffer_AddRef(pPSFactory);
return S_OK;
diff --git a/dlls/rpcrt4/tests/cstub.c b/dlls/rpcrt4/tests/cstub.c
index 69d5ea7..4ef70c2 100644
--- a/dlls/rpcrt4/tests/cstub.c
+++ b/dlls/rpcrt4/tests/cstub.c
@@ -613,6 +613,74 @@ static IUnknownVtbl create_stub_test_fail_vtbl =
NULL
};
+struct dummy_unknown
+{
+ const IUnknownVtbl *vtbl;
+ LONG ref;
+};
+
+static HRESULT WINAPI dummy_QueryInterface(IUnknown *This, REFIID iid, void **ppv)
+{
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI dummy_AddRef(LPUNKNOWN iface)
+{
+ struct dummy_unknown *this = (struct dummy_unknown *)iface;
+ return InterlockedIncrement( &this->ref );
+}
+
+ULONG WINAPI dummy_Release(LPUNKNOWN iface)
+{
+ struct dummy_unknown *this = (struct dummy_unknown *)iface;
+ return InterlockedDecrement( &this->ref );
+}
+
+static IUnknownVtbl dummy_unknown_vtbl =
+{
+ dummy_QueryInterface,
+ dummy_AddRef,
+ dummy_Release
+};
+static struct dummy_unknown dummy_unknown = { &dummy_unknown_vtbl, 0 };
+
+static void create_proxy_test( IPSFactoryBuffer *ppsf, REFIID iid, const void *expected_vtbl )
+{
+ IRpcProxyBuffer *proxy = NULL;
+ IUnknown *iface = NULL;
+ HRESULT r;
+ ULONG count;
+
+ r = IPSFactoryBuffer_CreateProxy(ppsf, NULL, iid, &proxy, (void **)&iface);
+ ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r );
+ ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl );
+ count = IUnknown_Release( iface );
+ ok( count == 1, "wrong refcount %u\n", count );
+ count = IRpcProxyBuffer_Release( proxy );
+ ok( count == 0, "wrong refcount %u\n", count );
+
+ dummy_unknown.ref = 4;
+ r = IPSFactoryBuffer_CreateProxy(ppsf, (IUnknown *)&dummy_unknown, iid, &proxy, (void **)&iface);
+ ok( r == S_OK, "IPSFactoryBuffer_CreateProxy failed %x\n", r );
+ ok( dummy_unknown.ref == 5, "wrong refcount %u\n", dummy_unknown.ref );
+ ok( *(void **)iface == expected_vtbl, "wrong iface pointer %p/%p\n", *(void **)iface, expected_vtbl );
+ count = IUnknown_Release( iface );
+ ok( count == 4, "wrong refcount %u\n", count );
+ ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref );
+ count = IRpcProxyBuffer_Release( proxy );
+ ok( count == 0, "wrong refcount %u\n", count );
+ ok( dummy_unknown.ref == 4, "wrong refcount %u\n", dummy_unknown.ref );
+}
+
+static void test_CreateProxy( IPSFactoryBuffer *ppsf )
+{
+ create_proxy_test( ppsf, &IID_if1, if1_proxy_vtbl.Vtbl );
+ create_proxy_test( ppsf, &IID_if2, if2_proxy_vtbl.Vtbl );
+ create_proxy_test( ppsf, &IID_if3, if3_proxy_vtbl.Vtbl );
+ create_proxy_test( ppsf, &IID_if4, if4_proxy_vtbl.Vtbl );
+}
+
static void test_CreateStub(IPSFactoryBuffer *ppsf)
{
IUnknownVtbl *vtbl = &create_stub_test_vtbl;
@@ -951,6 +1019,7 @@ START_TEST( cstub )
ppsf = test_NdrDllGetClassObject();
test_NdrStubForwardingFunction();
+ test_CreateProxy(ppsf);
test_CreateStub(ppsf);
test_Connect(ppsf);
test_Disconnect(ppsf);
More information about the wine-cvs
mailing list