rpcrt4: Fix the PSFactoryBuffer proxy refcounting, with tests.
This commit is contained in:
parent
36965f5726
commit
7571c1fd53
|
@ -147,11 +147,11 @@ HRESULT StdProxy_Construct(REFIID riid,
|
||||||
|
|
||||||
if (stubless) {
|
if (stubless) {
|
||||||
CInterfaceStubVtbl *svtbl = ProxyInfo->pStubVtblList[Index];
|
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
|
/* Maybe the original vtbl is just modified directly to point at
|
||||||
* ObjectStublessClientXXX thunks in real Windows, but I don't like it
|
* 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->thunks = HeapAlloc(GetProcessHeap(),0,sizeof(struct StublessThunk)*count);
|
||||||
This->PVtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID)*count);
|
This->PVtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID)*count);
|
||||||
for (i=0; i<count; i++) {
|
for (i=0; i<count; i++) {
|
||||||
|
@ -159,7 +159,7 @@ HRESULT StdProxy_Construct(REFIID riid,
|
||||||
if (vtbl->Vtbl[i] == (LPVOID)-1) {
|
if (vtbl->Vtbl[i] == (LPVOID)-1) {
|
||||||
PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i];
|
PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i];
|
||||||
unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST;
|
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)
|
FILL_STUBLESS(thunk, i, bytes)
|
||||||
This->PVtbl[i] = thunk;
|
This->PVtbl[i] = thunk;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,7 @@ HRESULT StdProxy_Construct(REFIID riid,
|
||||||
else
|
else
|
||||||
This->PVtbl = vtbl->Vtbl;
|
This->PVtbl = vtbl->Vtbl;
|
||||||
|
|
||||||
|
if (!pUnkOuter) pUnkOuter = (IUnknown *)This;
|
||||||
This->lpVtbl = &StdProxy_Vtbl;
|
This->lpVtbl = &StdProxy_Vtbl;
|
||||||
/* one reference for the proxy */
|
/* one reference for the proxy */
|
||||||
This->RefCount = 1;
|
This->RefCount = 1;
|
||||||
|
@ -183,11 +184,7 @@ HRESULT StdProxy_Construct(REFIID riid,
|
||||||
This->pChannel = NULL;
|
This->pChannel = NULL;
|
||||||
*ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl;
|
*ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl;
|
||||||
*ppvObj = &This->PVtbl;
|
*ppvObj = &This->PVtbl;
|
||||||
/* if there is no outer unknown then the caller will control the lifetime
|
IUnknown_AddRef((IUnknown *)*ppvObj);
|
||||||
* 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);
|
|
||||||
IPSFactoryBuffer_AddRef(pPSFactory);
|
IPSFactoryBuffer_AddRef(pPSFactory);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -613,6 +613,74 @@ static IUnknownVtbl create_stub_test_fail_vtbl =
|
||||||
NULL
|
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)
|
static void test_CreateStub(IPSFactoryBuffer *ppsf)
|
||||||
{
|
{
|
||||||
IUnknownVtbl *vtbl = &create_stub_test_vtbl;
|
IUnknownVtbl *vtbl = &create_stub_test_vtbl;
|
||||||
|
@ -951,6 +1019,7 @@ START_TEST( cstub )
|
||||||
|
|
||||||
ppsf = test_NdrDllGetClassObject();
|
ppsf = test_NdrDllGetClassObject();
|
||||||
test_NdrStubForwardingFunction();
|
test_NdrStubForwardingFunction();
|
||||||
|
test_CreateProxy(ppsf);
|
||||||
test_CreateStub(ppsf);
|
test_CreateStub(ppsf);
|
||||||
test_Connect(ppsf);
|
test_Connect(ppsf);
|
||||||
test_Disconnect(ppsf);
|
test_Disconnect(ppsf);
|
||||||
|
|
Loading…
Reference in New Issue