Robert Shearman : ole: Pass a channel into IRpcStubBuffer::Invoke.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Jan 10 14:14:15 CST 2006


Module: wine
Branch: refs/heads/master
Commit: a02cb3ebd655745743ca681ea8e82393177ed5aa
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=a02cb3ebd655745743ca681ea8e82393177ed5aa

Author: Robert Shearman <rob at codeweavers.com>
Date:   Tue Jan 10 20:08:02 2006 +0100

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 c7a1069..6dd7d4e 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(struc
 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 6e4ff1f..f2647c1 100644
--- a/dlls/ole32/rpc.c
+++ b/dlls/ole32/rpc.c
@@ -227,7 +227,6 @@ static HRESULT WINAPI RpcChannelBuffer_S
     DWORD index;
     struct dispatch_params *params;
     DWORD tid;
-    IRpcStubBuffer *stub;
     APARTMENT *apt;
     IPID ipid;
 
@@ -248,11 +247,9 @@ static HRESULT WINAPI RpcChannelBuffer_S
      * 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_S
     }
     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_S
             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_par
     }
     __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
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 @@ HRESULT ipid_to_stub_manager(const IPID 
     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;
-
-    if (ret) IRpcStubBuffer_AddRef(ret);
-
-    stub_manager_int_release(stubmgr);
+    {
+        *stub = ifstub->stubbuffer;
+        IRpcStubBuffer_AddRef(*stub);
+        *chan = ifstub->chan;
+        IRpcChannelBuffer_AddRef(*chan);
+        *stub_apt = apt;
 
-    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(stru
 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(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(s
     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);
 }




More information about the wine-cvs mailing list