[PATCH] rpcrt4: Perform the INITOUT phase in NdrAsyncServerCall instead of RpcAsyncCompleteCall.

Dmitry Timoshkov dmitry at baikal.ru
Wed Sep 18 20:43:27 CDT 2019


This is required to correctly support out reference parameters,
otherwise server method receives not initialized pointers during
the CALLSERVER phase and crashes.

This patch is the last bit for a fully functional asynchronous RPC.

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 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 10de5a4f44..bceecdc827 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 699a6bcfcf..63bc656990 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];
 };
-- 
2.20.1




More information about the wine-devel mailing list