rpcrt4: Add delegating stub support.
This commit is contained in:
parent
b058e6e729
commit
bd9891ffed
|
@ -110,6 +110,12 @@ static HRESULT WINAPI CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface,
|
|||
pUnkServer,ppStub);
|
||||
if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))
|
||||
return E_NOINTERFACE;
|
||||
|
||||
if(ProxyInfo->pDelegatedIIDs && ProxyInfo->pDelegatedIIDs[Index])
|
||||
return CStdStubBuffer_Delegating_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index],
|
||||
ProxyInfo->pStubVtblList[Index], ProxyInfo->pDelegatedIIDs[Index],
|
||||
iface, ppStub);
|
||||
|
||||
return CStdStubBuffer_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index],
|
||||
ProxyInfo->pStubVtblList[Index], iface, ppStub);
|
||||
}
|
||||
|
@ -152,6 +158,7 @@ HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv,
|
|||
int j;
|
||||
|
||||
if ((*pProxyFileList2)->pDelegatedIIDs && (*pProxyFileList2)->pDelegatedIIDs[i]) {
|
||||
pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Delegating_Vtbl;
|
||||
if ((*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount > max_delegating_vtbl_size)
|
||||
max_delegating_vtbl_size = (*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount;
|
||||
}
|
||||
|
|
|
@ -36,9 +36,18 @@ HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid,
|
|||
LPPSFACTORYBUFFER pPSFactory,
|
||||
LPRPCSTUBBUFFER *ppStub);
|
||||
|
||||
HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid,
|
||||
LPUNKNOWN pUnkServer,
|
||||
PCInterfaceName name,
|
||||
CInterfaceStubVtbl *vtbl,
|
||||
REFIID delegating_iid,
|
||||
LPPSFACTORYBUFFER pPSFactory,
|
||||
LPRPCSTUBBUFFER *ppStub);
|
||||
|
||||
const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface);
|
||||
|
||||
const IRpcStubBufferVtbl CStdStubBuffer_Vtbl;
|
||||
const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl;
|
||||
|
||||
void create_delegating_vtbl(DWORD num_methods);
|
||||
|
||||
|
|
|
@ -252,6 +252,58 @@ static void release_delegating_vtbl(IUnknownVtbl *vtbl)
|
|||
LeaveCriticalSection(&delegating_vtbl_section);
|
||||
}
|
||||
|
||||
HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid,
|
||||
LPUNKNOWN pUnkServer,
|
||||
PCInterfaceName name,
|
||||
CInterfaceStubVtbl *vtbl,
|
||||
REFIID delegating_iid,
|
||||
LPPSFACTORYBUFFER pPSFactory,
|
||||
LPRPCSTUBBUFFER *ppStub)
|
||||
{
|
||||
cstdstubbuffer_delegating_t *This;
|
||||
IUnknown *pvServer;
|
||||
HRESULT r;
|
||||
|
||||
TRACE("(%p,%p,%p,%p) %s\n", pUnkServer, vtbl, pPSFactory, ppStub, name);
|
||||
TRACE("iid=%s delegating to %s\n", debugstr_guid(vtbl->header.piid), debugstr_guid(delegating_iid));
|
||||
TRACE("vtbl=%p\n", &vtbl->Vtbl);
|
||||
|
||||
if (!IsEqualGUID(vtbl->header.piid, riid))
|
||||
{
|
||||
ERR("IID mismatch during stub creation\n");
|
||||
return RPC_E_UNEXPECTED;
|
||||
}
|
||||
|
||||
r = IUnknown_QueryInterface(pUnkServer, riid, (void**)&pvServer);
|
||||
if(FAILED(r)) return r;
|
||||
|
||||
This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
|
||||
if (!This)
|
||||
{
|
||||
IUnknown_Release(pvServer);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
This->base_obj = get_delegating_vtbl();
|
||||
r = create_stub(delegating_iid, (IUnknown*)&This->base_obj, &This->base_stub);
|
||||
if(FAILED(r))
|
||||
{
|
||||
release_delegating_vtbl(This->base_obj);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
IUnknown_Release(pvServer);
|
||||
return r;
|
||||
}
|
||||
|
||||
This->stub_buffer.lpVtbl = &vtbl->Vtbl;
|
||||
This->stub_buffer.RefCount = 1;
|
||||
This->stub_buffer.pvServerObject = pvServer;
|
||||
This->stub_buffer.pPSFactory = pPSFactory;
|
||||
*ppStub = (LPRPCSTUBBUFFER)&This->stub_buffer;
|
||||
|
||||
IPSFactoryBuffer_AddRef(pPSFactory);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CStdStubBuffer_QueryInterface(LPRPCSTUBBUFFER iface,
|
||||
REFIID riid,
|
||||
LPVOID *obj)
|
||||
|
@ -301,8 +353,26 @@ ULONG WINAPI NdrCStdStubBuffer_Release(LPRPCSTUBBUFFER iface,
|
|||
ULONG WINAPI NdrCStdStubBuffer2_Release(LPRPCSTUBBUFFER iface,
|
||||
LPPSFACTORYBUFFER pPSF)
|
||||
{
|
||||
FIXME("Not implemented\n");
|
||||
return 0;
|
||||
cstdstubbuffer_delegating_t *This = impl_from_delegating( iface );
|
||||
ULONG refs;
|
||||
|
||||
TRACE("(%p)->Release()\n", This);
|
||||
|
||||
refs = InterlockedDecrement(&This->stub_buffer.RefCount);
|
||||
if (!refs)
|
||||
{
|
||||
/* Just like NdrCStdStubBuffer_Release, we shouldn't call
|
||||
Disconnect here */
|
||||
IRpcStubBuffer_Disconnect((IRpcStubBuffer *)&This->stub_buffer);
|
||||
|
||||
IRpcStubBuffer_Release(This->base_stub);
|
||||
release_delegating_vtbl(This->base_obj);
|
||||
|
||||
IPSFactoryBuffer_Release(pPSF);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CStdStubBuffer_Connect(LPRPCSTUBBUFFER iface,
|
||||
|
@ -408,6 +478,55 @@ const IRpcStubBufferVtbl CStdStubBuffer_Vtbl =
|
|||
CStdStubBuffer_DebugServerRelease
|
||||
};
|
||||
|
||||
static HRESULT WINAPI CStdStubBuffer_Delegating_Connect(LPRPCSTUBBUFFER iface,
|
||||
LPUNKNOWN lpUnkServer)
|
||||
{
|
||||
cstdstubbuffer_delegating_t *This = impl_from_delegating(iface);
|
||||
HRESULT r;
|
||||
TRACE("(%p)->Connect(%p)\n", This, lpUnkServer);
|
||||
|
||||
r = CStdStubBuffer_Connect(iface, lpUnkServer);
|
||||
if(SUCCEEDED(r))
|
||||
r = IRpcStubBuffer_Connect(This->base_stub, (IUnknown*)&This->base_obj);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void WINAPI CStdStubBuffer_Delegating_Disconnect(LPRPCSTUBBUFFER iface)
|
||||
{
|
||||
cstdstubbuffer_delegating_t *This = impl_from_delegating(iface);
|
||||
TRACE("(%p)->Disconnect()\n", This);
|
||||
|
||||
IRpcStubBuffer_Disconnect(This->base_stub);
|
||||
CStdStubBuffer_Disconnect(iface);
|
||||
}
|
||||
|
||||
static ULONG WINAPI CStdStubBuffer_Delegating_CountRefs(LPRPCSTUBBUFFER iface)
|
||||
{
|
||||
cstdstubbuffer_delegating_t *This = impl_from_delegating(iface);
|
||||
ULONG ret;
|
||||
TRACE("(%p)->CountRefs()\n", This);
|
||||
|
||||
ret = CStdStubBuffer_CountRefs(iface);
|
||||
ret += IRpcStubBuffer_CountRefs(This->base_stub);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl =
|
||||
{
|
||||
CStdStubBuffer_QueryInterface,
|
||||
CStdStubBuffer_AddRef,
|
||||
NULL,
|
||||
CStdStubBuffer_Delegating_Connect,
|
||||
CStdStubBuffer_Delegating_Disconnect,
|
||||
CStdStubBuffer_Invoke,
|
||||
CStdStubBuffer_IsIIDSupported,
|
||||
CStdStubBuffer_Delegating_CountRefs,
|
||||
CStdStubBuffer_DebugServerQueryInterface,
|
||||
CStdStubBuffer_DebugServerRelease
|
||||
};
|
||||
|
||||
const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface)
|
||||
{
|
||||
CStdStubBuffer *This = (CStdStubBuffer *)iface;
|
||||
|
@ -420,22 +539,12 @@ const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface)
|
|||
void __RPC_STUB NdrStubForwardingFunction( IRpcStubBuffer *iface, IRpcChannelBuffer *pChannel,
|
||||
PRPC_MESSAGE pMsg, DWORD *pdwStubPhase )
|
||||
{
|
||||
/* Once stub delegation is implemented, this should call
|
||||
IRpcStubBuffer_Invoke on the stub's base interface. The
|
||||
IRpcStubBuffer for this interface is stored at (void**)iface-1.
|
||||
The pChannel and pMsg parameters are passed intact
|
||||
(RPCOLEMESSAGE is basically a RPC_MESSAGE). If Invoke returns
|
||||
with a failure then an exception is raised (to see this, change
|
||||
the return value in the test).
|
||||
/* Note pMsg is passed intact since RPCOLEMESSAGE is basically a RPC_MESSAGE. */
|
||||
|
||||
cstdstubbuffer_delegating_t *This = impl_from_delegating(iface);
|
||||
HRESULT r = IRpcStubBuffer_Invoke(This->base_stub, (RPCOLEMESSAGE*)pMsg, pChannel);
|
||||
if(FAILED(r)) RpcRaiseException(r);
|
||||
return;
|
||||
*/
|
||||
|
||||
FIXME("Not implemented\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -480,15 +480,11 @@ static IPSFactoryBuffer *test_NdrDllGetClassObject(void)
|
|||
VTBL_TEST_CHANGE_TO(QueryInterface, 1);
|
||||
VTBL_TEST_CHANGE_TO(AddRef, 1);
|
||||
VTBL_TEST_NOT_CHANGE_TO(Release, 1);
|
||||
todo_wine {
|
||||
VTBL_TEST_NOT_CHANGE_TO(Connect, 1);
|
||||
VTBL_TEST_NOT_CHANGE_TO(Disconnect, 1);
|
||||
}
|
||||
VTBL_TEST_CHANGE_TO(Invoke, 1);
|
||||
VTBL_TEST_CHANGE_TO(IsIIDSupported, 1);
|
||||
todo_wine {
|
||||
VTBL_TEST_NOT_CHANGE_TO(CountRefs, 1);
|
||||
}
|
||||
VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 1);
|
||||
VTBL_TEST_CHANGE_TO(DebugServerRelease, 1);
|
||||
|
||||
|
@ -506,15 +502,11 @@ todo_wine {
|
|||
VTBL_TEST_CHANGE_TO(QueryInterface, 3);
|
||||
VTBL_TEST_CHANGE_TO(AddRef, 3);
|
||||
VTBL_TEST_ZERO(Release, 3);
|
||||
todo_wine {
|
||||
VTBL_TEST_NOT_CHANGE_TO(Connect, 3);
|
||||
VTBL_TEST_NOT_CHANGE_TO(Disconnect, 3);
|
||||
}
|
||||
VTBL_TEST_CHANGE_TO(Invoke, 3);
|
||||
VTBL_TEST_CHANGE_TO(IsIIDSupported, 3);
|
||||
todo_wine {
|
||||
VTBL_TEST_NOT_CHANGE_TO(CountRefs, 3);
|
||||
}
|
||||
VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 3);
|
||||
VTBL_TEST_CHANGE_TO(DebugServerRelease, 3);
|
||||
|
||||
|
@ -565,10 +557,7 @@ static void test_NdrStubForwardingFunction(void)
|
|||
real_this = &This[1];
|
||||
|
||||
NdrStubForwardingFunction( real_this, channel, msg, phase );
|
||||
|
||||
todo_wine {
|
||||
ok(base_buffer_invoke_called == 1, "base_buffer_invoke called %d times\n", base_buffer_invoke_called);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -743,10 +732,8 @@ static void test_Connect(IPSFactoryBuffer *ppsf)
|
|||
|
||||
obj = (IUnknown*)&new_vtbl;
|
||||
r = IRpcStubBuffer_Connect(pstub, obj);
|
||||
todo_wine {
|
||||
ok(connect_test_base_Connect_called == 1, "connect_test_bsae_Connect called %d times\n",
|
||||
connect_test_base_Connect_called);
|
||||
}
|
||||
ok(connect_test_orig_release_called == 3, "release called %d\n", connect_test_orig_release_called);
|
||||
cstd_stub = (CStdStubBuffer*)pstub;
|
||||
ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject);
|
||||
|
@ -810,6 +797,92 @@ todo_wine {
|
|||
ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %ld orig %ld\n", PSFactoryBuffer.RefCount, facbuf_refs);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI delegating_invoke_test_QI(ITypeLib *pUnk, REFIID iid, void** ppv)
|
||||
{
|
||||
|
||||
*ppv = pUnk;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ULONG WINAPI delegating_invoke_test_addref(ITypeLib *pUnk)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ULONG WINAPI delegating_invoke_test_release(ITypeLib *pUnk)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static UINT WINAPI delegating_invoke_test_get_type_info_count(ITypeLib *pUnk)
|
||||
{
|
||||
return 0xabcdef;
|
||||
}
|
||||
|
||||
static ITypeLibVtbl delegating_invoke_test_obj_vtbl =
|
||||
{
|
||||
delegating_invoke_test_QI,
|
||||
delegating_invoke_test_addref,
|
||||
delegating_invoke_test_release,
|
||||
delegating_invoke_test_get_type_info_count,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static HRESULT WINAPI delegating_invoke_test_get_buffer(IRpcChannelBuffer *pchan,
|
||||
RPCOLEMESSAGE *msg,
|
||||
REFIID iid)
|
||||
{
|
||||
msg->Buffer = HeapAlloc(GetProcessHeap(), 0, msg->cbBuffer);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static IRpcChannelBufferVtbl delegating_invoke_test_rpc_chan_vtbl =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
delegating_invoke_test_get_buffer,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void test_delegating_Invoke(IPSFactoryBuffer *ppsf)
|
||||
{
|
||||
ITypeLibVtbl *obj_vtbl = &delegating_invoke_test_obj_vtbl;
|
||||
IUnknown *obj = (IUnknown*)&obj_vtbl;
|
||||
IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if2, obj, S_OK);
|
||||
IRpcChannelBufferVtbl *pchan_vtbl = &delegating_invoke_test_rpc_chan_vtbl;
|
||||
IRpcChannelBuffer *pchan = (IRpcChannelBuffer *)&pchan_vtbl;
|
||||
HRESULT r = E_FAIL;
|
||||
RPCOLEMESSAGE msg;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;
|
||||
msg.iMethod = 3;
|
||||
#if 0 /* FIXME: Figure out why this fails in Windows */
|
||||
r = IRpcStubBuffer_Invoke(pstub, &msg, pchan);
|
||||
ok(r == S_OK, "ret %08lx\n", r);
|
||||
#else
|
||||
pchan = NULL; /* stop compiler waring */
|
||||
#endif
|
||||
if(r == S_OK)
|
||||
{
|
||||
ok(*(DWORD*)msg.Buffer == 0xabcdef, "buf[0] %08lx\n", *(DWORD*)msg.Buffer);
|
||||
ok(*((DWORD*)msg.Buffer + 1) == S_OK, "buf[1] %08lx\n", *((DWORD*)msg.Buffer + 1));
|
||||
}
|
||||
IRpcStubBuffer_Release(pstub);
|
||||
}
|
||||
|
||||
START_TEST( cstub )
|
||||
{
|
||||
IPSFactoryBuffer *ppsf;
|
||||
|
@ -822,6 +895,7 @@ START_TEST( cstub )
|
|||
test_Connect(ppsf);
|
||||
test_Disconnect(ppsf);
|
||||
test_Release(ppsf);
|
||||
test_delegating_Invoke(ppsf);
|
||||
|
||||
OleUninitialize();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue