From 306e14b956551570f3a13f2f9c38945c02ac9f1f Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Thu, 19 Sep 2019 09:43:27 +0800 Subject: [PATCH] rpcrt4: Perform the INITOUT phase in NdrAsyncServerCall instead of RpcAsyncCompleteCall. This is required to correctly support out reference parameters, otherwise server method receives not initialized pointers during the CALLSERVER phase and crashes. Signed-off-by: Dmitry Timoshkov Signed-off-by: Alexandre Julliard --- dlls/rpcrt4/ndr_stubless.c | 17 +++++++++-------- dlls/rpcrt4/ndr_stubless.h | 2 ++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/dlls/rpcrt4/ndr_stubless.c b/dlls/rpcrt4/ndr_stubless.c index 10de5a4f44d..bceecdc8277 100644 --- a/dlls/rpcrt4/ndr_stubless.c +++ b/dlls/rpcrt4/ndr_stubless.c @@ -1632,6 +1632,8 @@ static void do_ndr_async_client_call( const MIDL_STUB_DESC *pStubDesc, PFORMAT_S pAsync->StubInfo = async_call_data; async_call_data->pHandleFormat = pFormat; + TRACE("pAsync %p, pAsync->StubInfo %p, NotificationType %d\n", pAsync, pAsync->StubInfo, pAsync->NotificationType); + pFormat += get_handle_desc_size(pProcHeader, pFormat); async_call_data->hBinding = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat); if (!async_call_data->hBinding) return; @@ -2075,7 +2077,11 @@ void RPC_ENTRY NdrAsyncServerCall(PRPC_MESSAGE pRpcMsg) TRACE("UNMARSHAL\n"); stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_UNMARSHAL, async_call_data->number_of_params); - /* 2. CALLSERVER */ + /* 2. INITOUT */ + TRACE("INITOUT\n"); + async_call_data->retval_ptr = stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_INITOUT, async_call_data->number_of_params); + + /* 3. CALLSERVER */ TRACE("CALLSERVER\n"); if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) pServerInfo->ThunkTable[pRpcMsg->ProcNum](async_call_data->pStubMsg); @@ -2090,8 +2096,6 @@ RPC_STATUS NdrpCompleteAsyncServerCall(RPC_ASYNC_STATE *pAsync, void *Reply) struct async_call_data *async_call_data; /* the type of pass we are currently doing */ enum stubless_phase phase; - /* location to put retval into */ - LONG_PTR *retval_ptr; RPC_STATUS status = RPC_S_OK; if (!pAsync->StubInfo) @@ -2102,13 +2106,10 @@ RPC_STATUS NdrpCompleteAsyncServerCall(RPC_ASYNC_STATE *pAsync, void *Reply) TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat); - /* 3. INITOUT */ - TRACE("INITOUT\n"); - retval_ptr = stub_do_args(async_call_data->pStubMsg, async_call_data->pHandleFormat, STUBLESS_INITOUT, async_call_data->number_of_params); - if (retval_ptr) + if (async_call_data->retval_ptr) { TRACE("stub implementation returned 0x%lx\n", *(LONG_PTR *)Reply); - *retval_ptr = *(LONG_PTR *)Reply; + *async_call_data->retval_ptr = *(LONG_PTR *)Reply; } else TRACE("void stub implementation\n"); diff --git a/dlls/rpcrt4/ndr_stubless.h b/dlls/rpcrt4/ndr_stubless.h index 699a6bcfcf0..63bc656990b 100644 --- a/dlls/rpcrt4/ndr_stubless.h +++ b/dlls/rpcrt4/ndr_stubless.h @@ -235,6 +235,8 @@ struct async_call_data unsigned short stack_size; /* number of parameters. optional for client to give it to us */ unsigned int number_of_params; + /* location to put retval into */ + LONG_PTR *retval_ptr; /* correlation cache */ ULONG_PTR NdrCorrCache[256]; };