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 */ IPID ipid; /* RO */
IUnknown *iface; /* RO */ IUnknown *iface; /* RO */
MSHLFLAGS flags; /* so we can enforce process-local marshalling rules (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); 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); 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); 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 start_apartment_remote_unknown(void);
HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags); 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); void RPC_StartRemoting(struct apartment *apt);
HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **pipebuf); HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **pipebuf);
HRESULT RPC_CreateServerChannel(IRpcChannelBuffer **chan);
void RPC_ExecuteCall(struct dispatch_params *params); void RPC_ExecuteCall(struct dispatch_params *params);
HRESULT RPC_RegisterInterface(REFIID riid); HRESULT RPC_RegisterInterface(REFIID riid);
void RPC_UnregisterInterface(REFIID riid); void RPC_UnregisterInterface(REFIID riid);

View File

@ -227,7 +227,6 @@ static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPC
DWORD index; DWORD index;
struct dispatch_params *params; struct dispatch_params *params;
DWORD tid; DWORD tid;
IRpcStubBuffer *stub;
APARTMENT *apt; APARTMENT *apt;
IPID ipid; IPID ipid;
@ -248,11 +247,9 @@ static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPC
* from DllMain */ * from DllMain */
RpcBindingInqObject(msg->Handle, &ipid); RpcBindingInqObject(msg->Handle, &ipid);
stub = ipid_to_apt_and_stubbuffer(&ipid, &apt); hr = ipid_get_dispatch_params(&ipid, &apt, &params->stub, &params->chan);
if (apt && (apt->model & COINIT_APARTMENTTHREADED)) 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); params->handle = CreateEventW(NULL, FALSE, FALSE, NULL);
TRACE("Calling apartment thread 0x%08lx...\n", apt->tid); TRACE("Calling apartment thread 0x%08lx...\n", apt->tid);
@ -261,7 +258,15 @@ static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPC
} }
else 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 /* 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, * 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()); ERR("Could not create RpcSendReceive thread, error %lx\n", GetLastError());
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
else
hr = S_OK;
} }
if (apt) apartment_release(apt); if (apt) apartment_release(apt);
@ -459,35 +466,35 @@ void RPC_ExecuteCall(struct dispatch_params *params)
} }
__ENDTRY __ENDTRY
IRpcStubBuffer_Release(params->stub); IRpcStubBuffer_Release(params->stub);
IRpcChannelBuffer_Release(params->chan);
if (params->handle) SetEvent(params->handle); if (params->handle) SetEvent(params->handle);
} }
static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg) static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
{ {
struct dispatch_params *params; struct dispatch_params *params;
IRpcStubBuffer *stub;
APARTMENT *apt; APARTMENT *apt;
IPID ipid; IPID ipid;
HRESULT hr;
RpcBindingInqObject(msg->Handle, &ipid); RpcBindingInqObject(msg->Handle, &ipid);
TRACE("ipid = %s, iMethod = %d\n", debugstr_guid(&ipid), msg->ProcNum); 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); if (!params) return RpcRaiseException(E_OUTOFMEMORY);
stub = ipid_to_apt_and_stubbuffer(&ipid, &apt); hr = ipid_get_dispatch_params(&ipid, &apt, &params->stub, &params->chan);
if (!apt || !stub) if (hr != S_OK)
{ {
if (apt) apartment_release(apt);
ERR("no apartment found for ipid %s\n", debugstr_guid(&ipid)); ERR("no apartment found for ipid %s\n", debugstr_guid(&ipid));
return RpcRaiseException(RPC_E_DISCONNECTED); return RpcRaiseException(hr);
} }
params->msg = (RPCOLEMESSAGE *)msg; params->msg = (RPCOLEMESSAGE *)msg;
params->stub = stub;
params->chan = NULL; /* FIXME: pass server channel */
params->status = RPC_S_OK; params->status = RPC_S_OK;
params->hr = S_OK;
params->handle = NULL;
/* Note: this is the important difference between STAs and MTAs - we /* Note: this is the important difference between STAs and MTAs - we
* always execute RPCs to STAs in the thread that originally created the * 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; return S_OK;
} }
/* gets the apartment and IRpcStubBuffer from an object. the caller must /* gets the apartment, stub and channel of an object. the caller must
* release the references to both objects */ * release the references to all objects if the function returned success,
IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt) * 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 stub_manager *stubmgr;
struct ifstub *ifstub; struct ifstub *ifstub;
APARTMENT *apt;
HRESULT hr; HRESULT hr;
*stub_apt = NULL; hr = ipid_to_stub_manager(ipid, &apt, &stubmgr);
if (hr != S_OK) return RPC_E_DISCONNECTED;
hr = ipid_to_stub_manager(ipid, stub_apt, &stubmgr);
if (hr != S_OK) return NULL;
ifstub = stub_manager_ipid_to_ifstub(stubmgr, ipid); ifstub = stub_manager_ipid_to_ifstub(stubmgr, ipid);
if (ifstub) if (ifstub)
ret = ifstub->stubbuffer; {
*stub = ifstub->stubbuffer;
if (ret) IRpcStubBuffer_AddRef(ret); IRpcStubBuffer_AddRef(*stub);
*chan = ifstub->chan;
IRpcChannelBuffer_AddRef(*chan);
*stub_apt = apt;
stub_manager_int_release(stubmgr); stub_manager_int_release(stubmgr);
return S_OK;
return ret; }
else
{
stub_manager_int_release(stubmgr);
apartment_release(apt);
return RPC_E_DISCONNECTED;
}
} }
/* generates an ipid in the following format (similar to native version): /* 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_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, MSHLFLAGS flags)
{ {
struct ifstub *stub; struct ifstub *stub;
HRESULT hr;
TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n", TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n",
wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid)); 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)); stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub));
if (!stub) return NULL; if (!stub) return NULL;
hr = RPC_CreateServerChannel(&stub->chan);
if (hr != S_OK)
{
HeapFree(GetProcessHeap(), 0, stub);
return NULL;
}
stub->stubbuffer = sb; stub->stubbuffer = sb;
if (sb) IRpcStubBuffer_AddRef(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); if (ifstub->stubbuffer) IUnknown_Release(ifstub->stubbuffer);
IUnknown_Release(ifstub->iface); IUnknown_Release(ifstub->iface);
IRpcChannelBuffer_Release(ifstub->chan);
HeapFree(GetProcessHeap(), 0, ifstub); HeapFree(GetProcessHeap(), 0, ifstub);
} }