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) {
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue