diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c index a677ca0c665..f5fb6f383ec 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; iVtbl[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 69d5ea70e2e..4ef70c28890 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);