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:
parent
13f9c71960
commit
d84f0abb70
125
dlls/ole32/rpc.c
125
dlls/ole32/rpc.c
|
@ -129,6 +129,8 @@ struct message_state
|
||||||
SChannelHookCallInfo channel_hook_info;
|
SChannelHookCallInfo channel_hook_info;
|
||||||
|
|
||||||
/* client only */
|
/* client only */
|
||||||
|
HWND target_hwnd;
|
||||||
|
DWORD target_tid;
|
||||||
struct dispatch_params params;
|
struct dispatch_params params;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -562,6 +564,24 @@ static HRESULT WINAPI ServerRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface,
|
||||||
return HRESULT_FROM_WIN32(status);
|
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)
|
static HRESULT WINAPI ClientRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid)
|
||||||
{
|
{
|
||||||
ClientRpcChannelBuffer *This = (ClientRpcChannelBuffer *)iface;
|
ClientRpcChannelBuffer *This = (ClientRpcChannelBuffer *)iface;
|
||||||
|
@ -574,6 +594,9 @@ static HRESULT WINAPI ClientRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface,
|
||||||
struct channel_hook_buffer_data *channel_hook_data;
|
struct channel_hook_buffer_data *channel_hook_data;
|
||||||
unsigned int channel_hook_count;
|
unsigned int channel_hook_count;
|
||||||
ULONG extension_count;
|
ULONG extension_count;
|
||||||
|
IPID ipid;
|
||||||
|
HRESULT hr;
|
||||||
|
APARTMENT *apt = NULL;
|
||||||
|
|
||||||
TRACE("(%p)->(%p,%s)\n", This, olemsg, debugstr_guid(riid));
|
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->Handle = This->bind;
|
||||||
msg->RpcInterfaceInformation = cif;
|
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.iid = *riid;
|
||||||
message_state->channel_hook_info.cbSize = sizeof(message_state->channel_hook_info);
|
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.uCausality = COM_CurrentCausalityId();
|
||||||
message_state->channel_hook_info.dwServerPid = This->server_pid;
|
message_state->channel_hook_info.dwServerPid = This->server_pid;
|
||||||
message_state->channel_hook_info.iMethod = msg->ProcNum;
|
message_state->channel_hook_info.iMethod = msg->ProcNum;
|
||||||
message_state->channel_hook_info.pObject = NULL; /* only present on server-side */
|
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));
|
memset(&message_state->params, 0, sizeof(message_state->params));
|
||||||
|
|
||||||
extensions_size = ChannelHooks_ClientGetSize(&message_state->channel_hook_info,
|
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]);
|
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);
|
status = I_RpcGetBuffer(msg);
|
||||||
|
|
||||||
message_state->prefix_data_len = 0;
|
|
||||||
message_state->binding_handle = This->bind;
|
|
||||||
msg->Handle = message_state;
|
msg->Handle = message_state;
|
||||||
|
|
||||||
if (status == RPC_S_OK)
|
if (status == RPC_S_OK)
|
||||||
|
@ -682,24 +740,6 @@ static HRESULT WINAPI ServerRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
|
||||||
return E_NOTIMPL;
|
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 */
|
/* this thread runs an outgoing RPC */
|
||||||
static DWORD WINAPI rpc_sendreceive_thread(LPVOID param)
|
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_MESSAGE *msg = (RPC_MESSAGE *)olemsg;
|
||||||
RPC_STATUS status;
|
RPC_STATUS status;
|
||||||
DWORD index;
|
DWORD index;
|
||||||
APARTMENT *apt = NULL;
|
|
||||||
IPID ipid;
|
|
||||||
struct message_state *message_state;
|
struct message_state *message_state;
|
||||||
ORPCTHAT orpcthat;
|
ORPCTHAT orpcthat;
|
||||||
ORPC_EXTENT_ARRAY orpc_ext_array;
|
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->Buffer = (char *)msg->Buffer - message_state->prefix_data_len;
|
||||||
msg->BufferLength += 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
|
/* 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
|
* to copy, as shown by the test_no_couninitialize_client test. without
|
||||||
* short-circuiting the RPC runtime in the case below, the test will
|
* 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
|
* a thread to process the RPC when this function is called indirectly
|
||||||
* from DllMain */
|
* from DllMain */
|
||||||
|
|
||||||
RpcBindingInqObject(message_state->binding_handle, &ipid);
|
message_state->params.msg = olemsg;
|
||||||
hr = ipid_get_dispatch_params(&ipid, &apt, &message_state->params.stub,
|
if (message_state->target_hwnd)
|
||||||
&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)
|
|
||||||
{
|
{
|
||||||
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))
|
(LPARAM)&message_state->params))
|
||||||
{
|
{
|
||||||
ERR("PostMessage failed with error %u\n", GetLastError());
|
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
|
/* Note: message_state->params.iface doesn't have a reference and
|
||||||
* so doesn't need to be released */
|
* so doesn't need to be released */
|
||||||
|
|
||||||
|
@ -809,16 +834,6 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
|
||||||
}
|
}
|
||||||
else
|
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
|
/* 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,
|
* pump the message loop in the application thread: if we do not,
|
||||||
* any windows created by this thread will hang and RPCs that try
|
* any windows created by this thread will hang and RPCs that try
|
||||||
|
@ -833,7 +848,6 @@ static HRESULT WINAPI ClientRpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER ifac
|
||||||
else
|
else
|
||||||
hr = S_OK;
|
hr = S_OK;
|
||||||
}
|
}
|
||||||
if (apt) apartment_release(apt);
|
|
||||||
|
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
{
|
{
|
||||||
|
@ -950,6 +964,11 @@ static HRESULT WINAPI ClientRpcChannelBuffer_FreeBuffer(LPRPCCHANNELBUFFER iface
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, msg->RpcInterfaceInformation);
|
HeapFree(GetProcessHeap(), 0, msg->RpcInterfaceInformation);
|
||||||
msg->RpcInterfaceInformation = NULL;
|
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);
|
HeapFree(GetProcessHeap(), 0, message_state);
|
||||||
|
|
||||||
TRACE("-- %ld\n", status);
|
TRACE("-- %ld\n", status);
|
||||||
|
@ -1344,8 +1363,6 @@ exit_reset_state:
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
HeapFree(GetProcessHeap(), 0, message_state);
|
HeapFree(GetProcessHeap(), 0, message_state);
|
||||||
IRpcStubBuffer_Release(params->stub);
|
|
||||||
IRpcChannelBuffer_Release(params->chan);
|
|
||||||
if (params->handle) SetEvent(params->handle);
|
if (params->handle) SetEvent(params->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1418,6 +1435,10 @@ static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = params->hr;
|
hr = params->hr;
|
||||||
|
if (params->chan)
|
||||||
|
IRpcChannelBuffer_Release(params->chan);
|
||||||
|
if (params->stub)
|
||||||
|
IRpcStubBuffer_Release(params->stub);
|
||||||
HeapFree(GetProcessHeap(), 0, params);
|
HeapFree(GetProcessHeap(), 0, params);
|
||||||
|
|
||||||
apartment_release(apt);
|
apartment_release(apt);
|
||||||
|
|
Loading…
Reference in New Issue