Rob Shearman : ole32: Determine the destination for the COM call and initialise the necessary parameters in ClientRpcChannelBuffer_GetBuffer instead of ClientRpcChannelBuffer_SendReceive .

Alexandre Julliard julliard at winehq.org
Mon Jan 7 08:39:03 CST 2008


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

Author: Rob Shearman <rob at codeweavers.com>
Date:   Fri Jan  4 16:25:39 2008 +0000

ole32: Determine the destination for the COM call and initialise the necessary parameters in ClientRpcChannelBuffer_GetBuffer instead of ClientRpcChannelBuffer_SendReceive.

The parameters are then freed in the matching 
ClientRpcChannelBuffer_FreeBuffer function.

---

 dlls/ole32/rpc.c |  125 +++++++++++++++++++++++++++++++----------------------
 1 files changed, 73 insertions(+), 52 deletions(-)

diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c
index 9fbff88..fdb49cb 100644
--- a/dlls/ole32/rpc.c
+++ b/dlls/ole32/rpc.c
@@ -129,6 +129,8 @@ struct message_state
     SChannelHookCallInfo channel_hook_info;
 
     /* client only */
+    HWND target_hwnd;
+    DWORD target_tid;
     struct dispatch_params params;
 };
 
@@ -562,6 +564,24 @@ static HRESULT WINAPI ServerRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface,
     return HRESULT_FROM_WIN32(status);
 }
 
+static HANDLE ClientRpcChannelBuffer_GetEventHandle(ClientRpcChannelBuffer *This)
+{
+    HANDLE event = InterlockedExchangePointer(&This->event, NULL);
+
+    /* Note: must be auto-reset event so we can reuse it without a call
+    * to ResetEvent */
+    if (!event) event = CreateEventW(NULL, FALSE, FALSE, NULL);
+
+    return event;
+}
+
+static void ClientRpcChannelBuffer_ReleaseEventHandle(ClientRpcChannelBuffer *This, HANDLE event)
+{
+    if (InterlockedCompareExchangePointer(&This->event, event, NULL))
+        /* already a handle cached in This */
+        CloseHandle(event);
+}
+
 static HRESULT WINAPI ClientRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid)
 {
     ClientRpcChannelBuffer *This = (ClientRpcChannelBuffer *)iface;
@@ -574,6 +594,9 @@ static HRESULT WINAPI ClientRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface,
     struct channel_hook_buffer_data *channel_hook_data;
     unsigned int channel_hook_count;
     ULONG extension_count;
+    IPID ipid;
+    HRESULT hr;
+    APARTMENT *apt = NULL;
 
     TRACE("(%p)->(%p,%s)\n", This, olemsg, debugstr_guid(riid));
 
@@ -597,12 +620,17 @@ static HRESULT WINAPI ClientRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface,
     msg->Handle = This->bind;
     msg->RpcInterfaceInformation = cif;
 
+    message_state->prefix_data_len = 0;
+    message_state->binding_handle = This->bind;
+
     message_state->channel_hook_info.iid = *riid;
     message_state->channel_hook_info.cbSize = sizeof(message_state->channel_hook_info);
     message_state->channel_hook_info.uCausality = COM_CurrentCausalityId();
     message_state->channel_hook_info.dwServerPid = This->server_pid;
     message_state->channel_hook_info.iMethod = msg->ProcNum;
     message_state->channel_hook_info.pObject = NULL; /* only present on server-side */
+    message_state->target_hwnd = NULL;
+    message_state->target_tid = 0;
     memset(&message_state->params, 0, sizeof(message_state->params));
 
     extensions_size = ChannelHooks_ClientGetSize(&message_state->channel_hook_info,
@@ -616,10 +644,40 @@ static HRESULT WINAPI ClientRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface,
             msg->BufferLength += FIELD_OFFSET(WIRE_ORPC_EXTENT, data[0]);
     }
 
+    RpcBindingInqObject(message_state->binding_handle, &ipid);
+    hr = ipid_get_dispatch_params(&ipid, &apt, &message_state->params.stub,
+                                  &message_state->params.chan,
+                                  &message_state->params.iid,
+                                  &message_state->params.iface);
+    if (hr == S_OK)
+    {
+        /* stub, chan, iface and iid are unneeded in multi-threaded case as we go
+         * via the RPC runtime */
+        if (apt->multi_threaded)
+        {
+            IRpcStubBuffer_Release(message_state->params.stub);
+            message_state->params.stub = NULL;
+            IRpcChannelBuffer_Release(message_state->params.chan);
+            message_state->params.chan = NULL;
+            message_state->params.iface = NULL;
+        }
+        else
+        {
+            message_state->target_hwnd = apartment_getwindow(apt);
+            message_state->target_tid = apt->tid;
+            /* we assume later on that this being non-NULL is the indicator that
+             * means call directly instead of going through RPC runtime */
+            if (!message_state->target_hwnd)
+                ERR("window for apartment %s is NULL\n", wine_dbgstr_longlong(apt->oxid));
+        }
+    }
+    if (apt) apartment_release(apt);
+    message_state->params.handle = ClientRpcChannelBuffer_GetEventHandle(This);
+    /* Note: message_state->params.msg is initialised in
+     * ClientRpcChannelBuffer_SendReceive */
+
     status = I_RpcGetBuffer(msg);
 
-    message_state->prefix_data_len = 0;
-    message_state->binding_handle = This->bind;
     msg->Handle = message_state;
 
     if (status == RPC_S_OK)
@@ -682,24 +740,6 @@ static HRESULT WINAPI ServerRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
     return E_NOTIMPL;
 }
 
-static HANDLE ClientRpcChannelBuffer_GetEventHandle(ClientRpcChannelBuffer *This)
-{
-    HANDLE event = InterlockedExchangePointer(&This->event, NULL);
-
-    /* Note: must be auto-reset event so we can reuse it without a call
-     * to ResetEvent */
-    if (!event) event = CreateEventW(NULL, FALSE, FALSE, NULL);
-
-    return event;
-}
-
-static void ClientRpcChannelBuffer_ReleaseEventHandle(ClientRpcChannelBuffer *This, HANDLE event)
-{
-    if (InterlockedCompareExchangePointer(&This->event, event, NULL))
-        /* already a handle cached in This */
-        CloseHandle(event);
-}
-
 /* this thread runs an outgoing RPC */
 static DWORD WINAPI rpc_sendreceive_thread(LPVOID param)
 {
@@ -735,8 +775,6 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
     RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg;
     RPC_STATUS status;
     DWORD index;
-    APARTMENT *apt = NULL;
-    IPID ipid;
     struct message_state *message_state;
     ORPCTHAT orpcthat;
     ORPC_EXTENT_ARRAY orpc_ext_array;
@@ -771,10 +809,6 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
     msg->Buffer = (char *)msg->Buffer - message_state->prefix_data_len;
     msg->BufferLength += message_state->prefix_data_len;
 
-    message_state->params.msg = olemsg;
-    message_state->params.status = RPC_S_OK;
-    message_state->params.hr = S_OK;
-
     /* Note: this is an optimization in the Microsoft OLE runtime that we need
      * to copy, as shown by the test_no_couninitialize_client test. without
      * short-circuiting the RPC runtime in the case below, the test will
@@ -782,25 +816,16 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
      * a thread to process the RPC when this function is called indirectly
      * from DllMain */
 
-    RpcBindingInqObject(message_state->binding_handle, &ipid);
-    hr = ipid_get_dispatch_params(&ipid, &apt, &message_state->params.stub,
-                                  &message_state->params.chan,
-                                  &message_state->params.iid,
-                                  &message_state->params.iface);
-    message_state->params.handle = ClientRpcChannelBuffer_GetEventHandle(This);
-    if ((hr == S_OK) && !apt->multi_threaded)
+    message_state->params.msg = olemsg;
+    if (message_state->target_hwnd)
     {
-        TRACE("Calling apartment thread 0x%08x...\n", apt->tid);
+        TRACE("Calling apartment thread 0x%08x...\n", message_state->target_tid);
 
-        if (!PostMessageW(apartment_getwindow(apt), DM_EXECUTERPC, 0,
+        if (!PostMessageW(message_state->target_hwnd, DM_EXECUTERPC, 0,
                           (LPARAM)&message_state->params))
         {
             ERR("PostMessage failed with error %u\n", GetLastError());
 
-            IRpcStubBuffer_Release(message_state->params.stub);
-            message_state->params.stub = NULL;
-            IRpcChannelBuffer_Release(message_state->params.chan);
-            message_state->params.chan = NULL;
             /* Note: message_state->params.iface doesn't have a reference and
              * so doesn't need to be released */
 
@@ -809,16 +834,6 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
     }
     else
     {
-        if (hr == S_OK)
-        {
-            /* otherwise, we go via RPC runtime so the stub and channel aren't
-             * needed here */
-            IRpcStubBuffer_Release(message_state->params.stub);
-            message_state->params.stub = NULL;
-            IRpcChannelBuffer_Release(message_state->params.chan);
-            message_state->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,
          * any windows created by this thread will hang and RPCs that try
@@ -833,7 +848,6 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
         else
             hr = S_OK;
     }
-    if (apt) apartment_release(apt);
 
     if (hr == S_OK)
     {
@@ -950,6 +964,11 @@ static HRESULT WINAPI ClientRpcChannelBuffer_FreeBuffer(LPRPCCHANNELBUFFER iface
 
     HeapFree(GetProcessHeap(), 0, msg->RpcInterfaceInformation);
     msg->RpcInterfaceInformation = NULL;
+
+    if (message_state->params.stub)
+        IRpcStubBuffer_Release(message_state->params.stub);
+    if (message_state->params.chan)
+        IRpcChannelBuffer_Release(message_state->params.chan);
     HeapFree(GetProcessHeap(), 0, message_state);
 
     TRACE("-- %ld\n", status);
@@ -1344,8 +1363,6 @@ exit_reset_state:
 
 exit:
     HeapFree(GetProcessHeap(), 0, message_state);
-    IRpcStubBuffer_Release(params->stub);
-    IRpcChannelBuffer_Release(params->chan);
     if (params->handle) SetEvent(params->handle);
 }
 
@@ -1418,6 +1435,10 @@ static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
     }
 
     hr = params->hr;
+    if (params->chan)
+        IRpcChannelBuffer_Release(params->chan);
+    if (params->stub)
+        IRpcStubBuffer_Release(params->stub);
     HeapFree(GetProcessHeap(), 0, params);
 
     apartment_release(apt);




More information about the wine-cvs mailing list