From a02cb3ebd655745743ca681ea8e82393177ed5aa Mon Sep 17 00:00:00 2001 From: Robert Shearman Date: Tue, 10 Jan 2006 20:08:02 +0100 Subject: [PATCH] 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. --- dlls/ole32/compobj_private.h | 4 ++- dlls/ole32/rpc.c | 39 +++++++++++++++++------------ dlls/ole32/stubmanager.c | 48 +++++++++++++++++++++++++----------- 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index c7a10694fbb..6dd7d4edd12 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -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); diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c index 6e4ff1f3159..f2647c100f6 100644 --- a/dlls/ole32/rpc.c +++ b/dlls/ole32/rpc.c @@ -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, ¶ms->stub, ¶ms->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, ¶ms->stub, ¶ms->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 diff --git a/dlls/ole32/stubmanager.c b/dlls/ole32/stubmanager.c index 413f4f3e426..2f2e297f280 100644 --- a/dlls/ole32/stubmanager.c +++ b/dlls/ole32/stubmanager.c @@ -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); @@ -468,9 +485,10 @@ static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *if list_remove(&ifstub->entry); RPC_UnregisterInterface(&ifstub->iid); - + if (ifstub->stubbuffer) IUnknown_Release(ifstub->stubbuffer); IUnknown_Release(ifstub->iface); + IRpcChannelBuffer_Release(ifstub->chan); HeapFree(GetProcessHeap(), 0, ifstub); }