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