ole: Pass a channel into IRpcStubBuffer::Invoke.

Create a server channel and store this in the ifstub.
Rename ipid_to_apt_and_stubbuffer to ipid_get_dispatch_params and make
the function return an HRESULT.
Return the channel for the ifstub in ipid_get_dispatch_params.
This commit is contained in:
Robert Shearman 2006-01-10 20:08:02 +01:00 committed by Alexandre Julliard
parent 8e5b36147d
commit a02cb3ebd6
3 changed files with 59 additions and 32 deletions

View File

@ -72,6 +72,7 @@ struct ifstub
IPID ipid; /* RO */
IUnknown *iface; /* RO */
MSHLFLAGS flags; /* so we can enforce process-local marshalling rules (RO) */
IRpcChannelBuffer*chan; /* channel passed to IRpcStubBuffer::Invoke (RO) */
};
@ -188,7 +189,7 @@ BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid);
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid);
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid);
HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret);
IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt);
HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt, IRpcStubBuffer **stub, IRpcChannelBuffer **chan);
HRESULT start_apartment_remote_unknown(void);
HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags);
@ -199,6 +200,7 @@ struct dispatch_params;
void RPC_StartRemoting(struct apartment *apt);
HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **pipebuf);
HRESULT RPC_CreateServerChannel(IRpcChannelBuffer **chan);
void RPC_ExecuteCall(struct dispatch_params *params);
HRESULT RPC_RegisterInterface(REFIID riid);
void RPC_UnregisterInterface(REFIID riid);

View File

@ -227,7 +227,6 @@ static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPC
DWORD index;
struct dispatch_params *params;
DWORD tid;
IRpcStubBuffer *stub;
APARTMENT *apt;
IPID ipid;
@ -248,11 +247,9 @@ static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPC
* from DllMain */
RpcBindingInqObject(msg->Handle, &ipid);
stub = ipid_to_apt_and_stubbuffer(&ipid, &apt);
if (apt && (apt->model & COINIT_APARTMENTTHREADED))
hr = ipid_get_dispatch_params(&ipid, &apt, &params->stub, &params->chan);
if ((hr == S_OK) && (apt->model & COINIT_APARTMENTTHREADED))
{
params->stub = stub;
params->chan = NULL; /* FIXME: pass server channel */
params->handle = CreateEventW(NULL, FALSE, FALSE, NULL);
TRACE("Calling apartment thread 0x%08lx...\n", apt->tid);
@ -261,7 +258,15 @@ static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPC
}
else
{
if (stub) IRpcStubBuffer_Release(stub);
if (hr == S_OK)
{
/* otherwise, we go via RPC runtime so the stub and channel aren't
* needed here */
IRpcStubBuffer_Release(params->stub);
params->stub = NULL;
IRpcChannelBuffer_Release(params->chan);
params->chan = NULL;
}
/* we use a separate thread here because we need to be able to
* pump the message loop in the application thread: if we do not,
@ -275,6 +280,8 @@ static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPC
ERR("Could not create RpcSendReceive thread, error %lx\n", GetLastError());
hr = E_UNEXPECTED;
}
else
hr = S_OK;
}
if (apt) apartment_release(apt);
@ -459,35 +466,35 @@ void RPC_ExecuteCall(struct dispatch_params *params)
}
__ENDTRY
IRpcStubBuffer_Release(params->stub);
IRpcChannelBuffer_Release(params->chan);
if (params->handle) SetEvent(params->handle);
}
static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
{
struct dispatch_params *params;
IRpcStubBuffer *stub;
APARTMENT *apt;
IPID ipid;
APARTMENT *apt;
IPID ipid;
HRESULT hr;
RpcBindingInqObject(msg->Handle, &ipid);
TRACE("ipid = %s, iMethod = %d\n", debugstr_guid(&ipid), msg->ProcNum);
params = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*params));
params = HeapAlloc(GetProcessHeap(), 0, sizeof(*params));
if (!params) return RpcRaiseException(E_OUTOFMEMORY);
stub = ipid_to_apt_and_stubbuffer(&ipid, &apt);
if (!apt || !stub)
hr = ipid_get_dispatch_params(&ipid, &apt, &params->stub, &params->chan);
if (hr != S_OK)
{
if (apt) apartment_release(apt);
ERR("no apartment found for ipid %s\n", debugstr_guid(&ipid));
return RpcRaiseException(RPC_E_DISCONNECTED);
return RpcRaiseException(hr);
}
params->msg = (RPCOLEMESSAGE *)msg;
params->stub = stub;
params->chan = NULL; /* FIXME: pass server channel */
params->status = RPC_S_OK;
params->hr = S_OK;
params->handle = NULL;
/* Note: this is the important difference between STAs and MTAs - we
* always execute RPCs to STAs in the thread that originally created the

View File

@ -365,29 +365,38 @@ HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub
return S_OK;
}
/* gets the apartment and IRpcStubBuffer from an object. the caller must
* release the references to both objects */
IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt)
/* gets the apartment, stub and channel of an object. the caller must
* release the references to all objects if the function returned success,
* otherwise no references are returned. */
HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt,
IRpcStubBuffer **stub, IRpcChannelBuffer **chan)
{
IRpcStubBuffer *ret = NULL;
struct stub_manager *stubmgr;
struct ifstub *ifstub;
APARTMENT *apt;
HRESULT hr;
*stub_apt = NULL;
hr = ipid_to_stub_manager(ipid, stub_apt, &stubmgr);
if (hr != S_OK) return NULL;
hr = ipid_to_stub_manager(ipid, &apt, &stubmgr);
if (hr != S_OK) return RPC_E_DISCONNECTED;
ifstub = stub_manager_ipid_to_ifstub(stubmgr, ipid);
if (ifstub)
ret = ifstub->stubbuffer;
{
*stub = ifstub->stubbuffer;
IRpcStubBuffer_AddRef(*stub);
*chan = ifstub->chan;
IRpcChannelBuffer_AddRef(*chan);
*stub_apt = apt;
if (ret) IRpcStubBuffer_AddRef(ret);
stub_manager_int_release(stubmgr);
return ret;
stub_manager_int_release(stubmgr);
return S_OK;
}
else
{
stub_manager_int_release(stubmgr);
apartment_release(apt);
return RPC_E_DISCONNECTED;
}
}
/* generates an ipid in the following format (similar to native version):
@ -417,6 +426,7 @@ static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, MSHLFLAGS flags)
{
struct ifstub *stub;
HRESULT hr;
TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n",
wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid));
@ -424,6 +434,13 @@ struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *s
stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub));
if (!stub) return NULL;
hr = RPC_CreateServerChannel(&stub->chan);
if (hr != S_OK)
{
HeapFree(GetProcessHeap(), 0, stub);
return NULL;
}
stub->stubbuffer = sb;
if (sb) IRpcStubBuffer_AddRef(sb);
@ -471,6 +488,7 @@ static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *if
if (ifstub->stubbuffer) IUnknown_Release(ifstub->stubbuffer);
IUnknown_Release(ifstub->iface);
IRpcChannelBuffer_Release(ifstub->chan);
HeapFree(GetProcessHeap(), 0, ifstub);
}