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.
This commit is contained in:
Rob Shearman 2008-01-04 16:25:39 +00:00 committed by Alexandre Julliard
parent 13f9c71960
commit d84f0abb70
1 changed files with 73 additions and 52 deletions

View File

@ -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);