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.
diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index c7a1069..6dd7d4e 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -72,6 +72,7 @@
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_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 @@
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 6e4ff1f..f2647c10 100644
--- a/dlls/ole32/rpc.c
+++ b/dlls/ole32/rpc.c
@@ -227,7 +227,6 @@
DWORD index;
struct dispatch_params *params;
DWORD tid;
- IRpcStubBuffer *stub;
APARTMENT *apt;
IPID ipid;
@@ -248,11 +247,9 @@
* 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 @@
}
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 @@
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 @@
}
__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 413f4f3..2f2e297 100644
--- a/dlls/ole32/stubmanager.c
+++ b/dlls/ole32/stubmanager.c
@@ -365,29 +365,38 @@
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 @@
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 @@
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 @@
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);
}