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