rpcrt4: Implement NdrAsyncServerCall.
Based on NdrStubCall2 and NdrAsyncClientCall implementations. In order to test asynchronous RPC I used dlls/rpcrt4/tests/server.c as a base, converted int_return() and sum() to use asynchronous RPC on both client and server sides (server.idl doesn't need any changes), and added server.acf: interface IServer { [async] int_return(); [async] sum(); } With this implementation these tests pass under Wine. Since widl doesn't support asynchronous RPC it's impossible to add appropriate Wine tests. Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
bb7c119190
commit
29fa835687
|
@ -1559,21 +1559,6 @@ void WINAPI NdrServerCallAll( PRPC_MESSAGE msg )
|
|||
FIXME("%p stub\n", msg);
|
||||
}
|
||||
|
||||
struct async_call_data
|
||||
{
|
||||
MIDL_STUB_MESSAGE *pStubMsg;
|
||||
const NDR_PROC_HEADER *pProcHeader;
|
||||
PFORMAT_STRING pHandleFormat;
|
||||
PFORMAT_STRING pParamFormat;
|
||||
RPC_BINDING_HANDLE hBinding;
|
||||
/* size of stack */
|
||||
unsigned short stack_size;
|
||||
/* number of parameters. optional for client to give it to us */
|
||||
unsigned int number_of_params;
|
||||
/* correlation cache */
|
||||
ULONG_PTR NdrCorrCache[256];
|
||||
};
|
||||
|
||||
/* Helper for ndr_async_client_call, to factor out the part that may or may not be
|
||||
* guarded by a try/except block. */
|
||||
static void do_ndr_async_client_call( const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormat, void **stack_top )
|
||||
|
@ -1922,5 +1907,178 @@ RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis,
|
|||
|
||||
void RPC_ENTRY NdrAsyncServerCall(PRPC_MESSAGE pRpcMsg)
|
||||
{
|
||||
FIXME("unimplemented, %p\n", pRpcMsg);
|
||||
const MIDL_SERVER_INFO *pServerInfo;
|
||||
const MIDL_STUB_DESC *pStubDesc;
|
||||
PFORMAT_STRING pFormat;
|
||||
/* pointer to start of stack to pass into stub implementation */
|
||||
unsigned char *args;
|
||||
/* header for procedure string */
|
||||
const NDR_PROC_HEADER *pProcHeader;
|
||||
struct async_call_data *async_call_data;
|
||||
PRPC_ASYNC_STATE pAsync;
|
||||
RPC_STATUS status;
|
||||
|
||||
TRACE("%p\n", pRpcMsg);
|
||||
|
||||
pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
|
||||
|
||||
pStubDesc = pServerInfo->pStubDesc;
|
||||
pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
|
||||
pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
|
||||
|
||||
TRACE("NDR Version: 0x%x\n", pStubDesc->Version);
|
||||
|
||||
async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
|
||||
if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY);
|
||||
async_call_data->pProcHeader = pProcHeader;
|
||||
|
||||
async_call_data->pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
|
||||
*(PRPC_MESSAGE)(async_call_data->pStubMsg + 1) = *pRpcMsg;
|
||||
|
||||
if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
|
||||
{
|
||||
const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
|
||||
async_call_data->stack_size = header_rpc->stack_size;
|
||||
pFormat += sizeof(NDR_PROC_HEADER_RPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
async_call_data->stack_size = pProcHeader->stack_size;
|
||||
pFormat += sizeof(NDR_PROC_HEADER);
|
||||
}
|
||||
|
||||
TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
|
||||
|
||||
/* binding */
|
||||
switch (pProcHeader->handle_type)
|
||||
{
|
||||
/* explicit binding: parse additional section */
|
||||
case 0:
|
||||
switch (*pFormat) /* handle_type */
|
||||
{
|
||||
case FC_BIND_PRIMITIVE: /* explicit primitive */
|
||||
pFormat += sizeof(NDR_EHD_PRIMITIVE);
|
||||
break;
|
||||
case FC_BIND_GENERIC: /* explicit generic */
|
||||
pFormat += sizeof(NDR_EHD_GENERIC);
|
||||
break;
|
||||
case FC_BIND_CONTEXT: /* explicit context */
|
||||
pFormat += sizeof(NDR_EHD_CONTEXT);
|
||||
break;
|
||||
default:
|
||||
ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
|
||||
RpcRaiseException(RPC_X_BAD_STUB_DATA);
|
||||
}
|
||||
break;
|
||||
case FC_BIND_GENERIC: /* implicit generic */
|
||||
case FC_BIND_PRIMITIVE: /* implicit primitive */
|
||||
case FC_CALLBACK_HANDLE: /* implicit callback */
|
||||
case FC_AUTO_HANDLE: /* implicit auto handle */
|
||||
break;
|
||||
default:
|
||||
ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
|
||||
RpcRaiseException(RPC_X_BAD_STUB_DATA);
|
||||
}
|
||||
|
||||
if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
|
||||
{
|
||||
ERR("objects not supported\n");
|
||||
I_RpcFree(async_call_data);
|
||||
RpcRaiseException(RPC_X_BAD_STUB_DATA);
|
||||
}
|
||||
|
||||
NdrServerInitializeNew(pRpcMsg, async_call_data->pStubMsg, pStubDesc);
|
||||
|
||||
/* create the full pointer translation tables, if requested */
|
||||
if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
|
||||
async_call_data->pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0, XLAT_SERVER);
|
||||
|
||||
/* use alternate memory allocation routines */
|
||||
if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
|
||||
#if 0
|
||||
NdrRpcSsEnableAllocate(&stubMsg);
|
||||
#else
|
||||
FIXME("Set RPCSS memory allocation routines\n");
|
||||
#endif
|
||||
|
||||
TRACE("allocating memory for stack of size %x\n", async_call_data->stack_size);
|
||||
|
||||
args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, async_call_data->stack_size);
|
||||
async_call_data->pStubMsg->StackTop = args; /* used by conformance of top-level objects */
|
||||
|
||||
pAsync = I_RpcAllocate(sizeof(*pAsync));
|
||||
if (!pAsync) RpcRaiseException(RPC_X_NO_MEMORY);
|
||||
|
||||
status = RpcAsyncInitializeHandle(pAsync, sizeof(*pAsync));
|
||||
if (status != RPC_S_OK)
|
||||
RpcRaiseException(status);
|
||||
|
||||
pAsync->StubInfo = async_call_data;
|
||||
TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat);
|
||||
|
||||
/* add the implicit pAsync pointer as the first arg to the function */
|
||||
*(void **)args = pAsync;
|
||||
|
||||
if (is_oicf_stubdesc(pStubDesc))
|
||||
{
|
||||
const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
|
||||
/* cache of Oif_flags from v2 procedure header */
|
||||
INTERPRETER_OPT_FLAGS Oif_flags;
|
||||
/* cache of extension flags from NDR_PROC_HEADER_EXTS */
|
||||
INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
|
||||
|
||||
Oif_flags = pOIFHeader->Oi2Flags;
|
||||
async_call_data->number_of_params = pOIFHeader->number_of_params;
|
||||
|
||||
pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
|
||||
|
||||
TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
|
||||
|
||||
if (Oif_flags.HasExtensions)
|
||||
{
|
||||
const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
|
||||
ext_flags = pExtensions->Flags2;
|
||||
pFormat += pExtensions->Size;
|
||||
}
|
||||
|
||||
if (Oif_flags.HasPipes)
|
||||
{
|
||||
FIXME("pipes not supported yet\n");
|
||||
RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
|
||||
/* init pipes package */
|
||||
/* NdrPipesInitialize(...) */
|
||||
}
|
||||
if (ext_flags.HasNewCorrDesc)
|
||||
{
|
||||
/* initialize extra correlation package */
|
||||
NdrCorrelationInitialize(async_call_data->pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
|
||||
if (ext_flags.Unused & 0x2) /* has range on conformance */
|
||||
async_call_data->pStubMsg->CorrDespIncrement = 12;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pFormat = convert_old_args( async_call_data->pStubMsg, pFormat, async_call_data->stack_size,
|
||||
pProcHeader->Oi_flags & Oi_OBJECT_PROC,
|
||||
/* reuse the correlation cache, it's not needed for v1 format */
|
||||
async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), &async_call_data->number_of_params );
|
||||
}
|
||||
|
||||
/* convert strings, floating point values and endianness into our
|
||||
* preferred format */
|
||||
if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
|
||||
NdrConvert(async_call_data->pStubMsg, pFormat);
|
||||
|
||||
async_call_data->pHandleFormat = pFormat;
|
||||
|
||||
/* 1. UNMARSHAL */
|
||||
TRACE("UNMARSHAL\n");
|
||||
stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_UNMARSHAL, async_call_data->number_of_params);
|
||||
|
||||
/* 2. CALLSERVER */
|
||||
TRACE("CALLSERVER\n");
|
||||
if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
|
||||
pServerInfo->ThunkTable[pRpcMsg->ProcNum](async_call_data->pStubMsg);
|
||||
else
|
||||
call_server_func(pServerInfo->DispatchTable[pRpcMsg->ProcNum], args, async_call_data->stack_size);
|
||||
}
|
||||
|
|
|
@ -224,6 +224,21 @@ typedef struct _NDR_EHD_CONTEXT
|
|||
|
||||
#include "poppack.h"
|
||||
|
||||
struct async_call_data
|
||||
{
|
||||
MIDL_STUB_MESSAGE *pStubMsg;
|
||||
const NDR_PROC_HEADER *pProcHeader;
|
||||
PFORMAT_STRING pHandleFormat;
|
||||
PFORMAT_STRING pParamFormat;
|
||||
RPC_BINDING_HANDLE hBinding;
|
||||
/* size of stack */
|
||||
unsigned short stack_size;
|
||||
/* number of parameters. optional for client to give it to us */
|
||||
unsigned int number_of_params;
|
||||
/* correlation cache */
|
||||
ULONG_PTR NdrCorrCache[256];
|
||||
};
|
||||
|
||||
enum stubless_phase
|
||||
{
|
||||
STUBLESS_UNMARSHAL,
|
||||
|
|
|
@ -110,6 +110,8 @@ RPC_STATUS WINAPI RpcAsyncGetCallStatus(PRPC_ASYNC_STATE pAsync)
|
|||
*/
|
||||
RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply)
|
||||
{
|
||||
struct async_call_data *data;
|
||||
|
||||
TRACE("(%p, %p)\n", pAsync, Reply);
|
||||
|
||||
if (!valid_async_handle(pAsync))
|
||||
|
@ -117,7 +119,14 @@ RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply)
|
|||
|
||||
/* FIXME: check completed */
|
||||
|
||||
TRACE("pAsync %p, pAsync->StubInfo %p\n", pAsync, pAsync->StubInfo);
|
||||
|
||||
data = pAsync->StubInfo;
|
||||
if (data->pStubMsg->IsClient)
|
||||
return NdrpCompleteAsyncClientCall(pAsync, Reply);
|
||||
|
||||
FIXME("not implemented for server side\n");
|
||||
return RPC_S_CALL_FAILED;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in New Issue