Commit bd9891ff authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

rpcrt4: Add delegating stub support.

parent b058e6e7
......@@ -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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment