rpcrt4: Implement stubless asynchronous NDR interpreter.
CodeWeavers did this work for supporting Outlook 2007.
This commit is contained in:
parent
9c6e6efa32
commit
834c5b4275
|
@ -1522,3 +1522,339 @@ void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
|
|||
DWORD dwPhase;
|
||||
NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
|
||||
}
|
||||
|
||||
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 char number_of_params;
|
||||
/* correlation cache */
|
||||
unsigned long NdrCorrCache[256];
|
||||
};
|
||||
|
||||
LONG_PTR WINAPIV NdrAsyncClientCall(PMIDL_STUB_DESC pStubDesc,
|
||||
PFORMAT_STRING pFormat, ...)
|
||||
{
|
||||
/* pointer to start of stack where arguments start */
|
||||
PRPC_MESSAGE pRpcMsg;
|
||||
PMIDL_STUB_MESSAGE pStubMsg;
|
||||
RPC_ASYNC_STATE *pAsync;
|
||||
struct async_call_data *async_call_data;
|
||||
/* procedure number */
|
||||
unsigned short procedure_number;
|
||||
/* cache of Oif_flags from v2 procedure header */
|
||||
INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
|
||||
/* cache of extension flags from NDR_PROC_HEADER_EXTS */
|
||||
INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
|
||||
/* the type of pass we are currently doing */
|
||||
int phase;
|
||||
/* header for procedure string */
|
||||
const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
|
||||
/* -Oif or -Oicf generated format */
|
||||
BOOL bV2Format = FALSE;
|
||||
|
||||
TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
|
||||
|
||||
/* Later NDR language versions probably won't be backwards compatible */
|
||||
if (pStubDesc->Version > 0x50002)
|
||||
{
|
||||
FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
|
||||
RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
|
||||
}
|
||||
|
||||
async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
|
||||
if (!async_call_data) RpcRaiseException(ERROR_OUTOFMEMORY);
|
||||
async_call_data->number_of_params = ~0;
|
||||
async_call_data->pProcHeader = pProcHeader;
|
||||
|
||||
async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
|
||||
pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1);
|
||||
|
||||
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
|
||||
{
|
||||
const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
|
||||
async_call_data->stack_size = pProcHeader->stack_size;
|
||||
procedure_number = pProcHeader->proc_num;
|
||||
pFormat += sizeof(NDR_PROC_HEADER_RPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
async_call_data->stack_size = pProcHeader->stack_size;
|
||||
procedure_number = pProcHeader->proc_num;
|
||||
pFormat += sizeof(NDR_PROC_HEADER);
|
||||
}
|
||||
TRACE("stack size: 0x%x\n", async_call_data->stack_size);
|
||||
TRACE("proc num: %d\n", procedure_number);
|
||||
|
||||
/* create the full pointer translation tables, if requested */
|
||||
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
|
||||
pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
|
||||
|
||||
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
|
||||
{
|
||||
ERR("objects not supported\n");
|
||||
I_RpcFree(async_call_data);
|
||||
RpcRaiseException(RPC_X_BAD_STUB_DATA);
|
||||
}
|
||||
|
||||
NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number);
|
||||
|
||||
TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
|
||||
TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
|
||||
|
||||
/* needed for conformance of top-level objects */
|
||||
#ifdef __i386__
|
||||
pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size);
|
||||
/* FIXME: this may read one more DWORD than is necessary, but it shouldn't hurt */
|
||||
memcpy(pStubMsg->StackTop, *(unsigned char **)(&pFormat+1), async_call_data->stack_size);
|
||||
#else
|
||||
# warning Stack not retrieved for your CPU architecture
|
||||
#endif
|
||||
|
||||
pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop;
|
||||
pAsync->StubInfo = async_call_data;
|
||||
async_call_data->pHandleFormat = pFormat;
|
||||
|
||||
pFormat = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, &async_call_data->hBinding);
|
||||
if (!pFormat) return 0;
|
||||
|
||||
bV2Format = (pStubDesc->Version >= 0x20000);
|
||||
|
||||
if (bV2Format)
|
||||
{
|
||||
const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
|
||||
(const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
|
||||
|
||||
Oif_flags = pOIFHeader->Oi2Flags;
|
||||
async_call_data->number_of_params = pOIFHeader->number_of_params;
|
||||
|
||||
pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
|
||||
}
|
||||
|
||||
TRACE("Oif_flags = "); dump_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;
|
||||
}
|
||||
|
||||
async_call_data->pParamFormat = pFormat;
|
||||
|
||||
pStubMsg->BufferLength = 0;
|
||||
|
||||
/* store the RPC flags away */
|
||||
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
|
||||
pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
|
||||
|
||||
/* use alternate memory allocation routines */
|
||||
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
|
||||
NdrRpcSmSetClientToOsf(pStubMsg);
|
||||
|
||||
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(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
|
||||
}
|
||||
|
||||
/* order of phases:
|
||||
* 1. PROXY_CALCSIZE - calculate the buffer size
|
||||
* 2. PROXY_GETBUFFER - allocate the buffer
|
||||
* 3. PROXY_MARHSAL - marshal [in] params into the buffer
|
||||
* 4. PROXY_SENDRECEIVE - send buffer
|
||||
* Then in NdrpCompleteAsyncClientCall:
|
||||
* 1. PROXY_SENDRECEIVE - receive buffer
|
||||
* 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
|
||||
*/
|
||||
for (phase = PROXY_CALCSIZE; phase <= PROXY_SENDRECEIVE; phase++)
|
||||
{
|
||||
RPC_STATUS status;
|
||||
TRACE("phase = %d\n", phase);
|
||||
switch (phase)
|
||||
{
|
||||
case PROXY_GETBUFFER:
|
||||
/* allocate the buffer */
|
||||
if (Oif_flags.HasPipes)
|
||||
/* NdrGetPipeBuffer(...) */
|
||||
FIXME("pipes not supported yet\n");
|
||||
else
|
||||
{
|
||||
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
|
||||
#if 0
|
||||
NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
|
||||
#else
|
||||
FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
|
||||
#endif
|
||||
else
|
||||
NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
|
||||
}
|
||||
pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
|
||||
status = I_RpcAsyncSetHandle(pRpcMsg, pAsync);
|
||||
if (status != RPC_S_OK)
|
||||
RpcRaiseException(status);
|
||||
break;
|
||||
case PROXY_SENDRECEIVE:
|
||||
pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
|
||||
/* send the [in] params only */
|
||||
if (Oif_flags.HasPipes)
|
||||
/* NdrPipesSend(...) */
|
||||
FIXME("pipes not supported yet\n");
|
||||
else
|
||||
{
|
||||
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
|
||||
#if 0
|
||||
NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
|
||||
#else
|
||||
FIXME("using auto handle - call NdrNsSend when it gets implemented\n");
|
||||
#endif
|
||||
else
|
||||
{
|
||||
pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
|
||||
status = I_RpcSend(pStubMsg->RpcMsg);
|
||||
if (status != RPC_S_OK)
|
||||
RpcRaiseException(status);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case PROXY_CALCSIZE:
|
||||
case PROXY_MARSHAL:
|
||||
if (bV2Format)
|
||||
client_do_args(pStubMsg, pFormat, phase, pStubMsg->StackTop,
|
||||
async_call_data->number_of_params, NULL);
|
||||
else
|
||||
client_do_args_old_format(pStubMsg, pFormat, phase,
|
||||
pStubMsg->StackTop, async_call_data->stack_size, NULL,
|
||||
(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT), FALSE);
|
||||
break;
|
||||
default:
|
||||
ERR("shouldn't reach here. phase %d\n", phase);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("returning 0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
|
||||
{
|
||||
/* pointer to start of stack where arguments start */
|
||||
PMIDL_STUB_MESSAGE pStubMsg;
|
||||
struct async_call_data *async_call_data;
|
||||
/* the type of pass we are currently doing */
|
||||
int phase;
|
||||
/* header for procedure string */
|
||||
const NDR_PROC_HEADER * pProcHeader;
|
||||
/* -Oif or -Oicf generated format */
|
||||
BOOL bV2Format;
|
||||
RPC_STATUS status = RPC_S_OK;
|
||||
|
||||
if (!pAsync->StubInfo)
|
||||
return RPC_S_INVALID_ASYNC_HANDLE;
|
||||
|
||||
async_call_data = pAsync->StubInfo;
|
||||
pStubMsg = async_call_data->pStubMsg;
|
||||
pProcHeader = async_call_data->pProcHeader;
|
||||
|
||||
bV2Format = (pStubMsg->StubDesc->Version >= 0x20000);
|
||||
|
||||
/* order of phases:
|
||||
* 1. PROXY_CALCSIZE - calculate the buffer size
|
||||
* 2. PROXY_GETBUFFER - allocate the buffer
|
||||
* 3. PROXY_MARHSAL - marshal [in] params into the buffer
|
||||
* 4. PROXY_SENDRECEIVE - send buffer
|
||||
* Then in NdrpCompleteAsyncClientCall:
|
||||
* 1. PROXY_SENDRECEIVE - receive buffer
|
||||
* 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
|
||||
*/
|
||||
for (phase = PROXY_SENDRECEIVE; phase <= PROXY_UNMARSHAL; phase++)
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
case PROXY_SENDRECEIVE:
|
||||
pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
|
||||
/* receive the [out] params */
|
||||
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
|
||||
#if 0
|
||||
NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
|
||||
#else
|
||||
FIXME("using auto handle - call NdrNsReceive when it gets implemented\n");
|
||||
#endif
|
||||
else
|
||||
{
|
||||
status = I_RpcReceive(pStubMsg->RpcMsg);
|
||||
if (status != RPC_S_OK)
|
||||
goto cleanup;
|
||||
pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;
|
||||
pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
|
||||
pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
|
||||
pStubMsg->Buffer = pStubMsg->BufferStart;
|
||||
}
|
||||
|
||||
/* convert strings, floating point values and endianess into our
|
||||
* preferred format */
|
||||
#if 0
|
||||
if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
|
||||
NdrConvert(pStubMsg, pFormat);
|
||||
#endif
|
||||
|
||||
break;
|
||||
case PROXY_UNMARSHAL:
|
||||
if (bV2Format)
|
||||
client_do_args(pStubMsg, async_call_data->pParamFormat, phase, pStubMsg->StackTop,
|
||||
async_call_data->number_of_params, Reply);
|
||||
else
|
||||
client_do_args_old_format(pStubMsg, async_call_data->pParamFormat, phase,
|
||||
pStubMsg->StackTop, async_call_data->stack_size, Reply, FALSE, FALSE);
|
||||
break;
|
||||
default:
|
||||
ERR("shouldn't reach here. phase %d\n", phase);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (pStubMsg->fHasNewCorrDesc)
|
||||
{
|
||||
/* free extra correlation package */
|
||||
NdrCorrelationFree(pStubMsg);
|
||||
}
|
||||
|
||||
/* free the full pointer translation tables */
|
||||
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
|
||||
NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
|
||||
|
||||
/* free marshalling buffer */
|
||||
NdrFreeBuffer(pStubMsg);
|
||||
client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding);
|
||||
|
||||
I_RpcFree(pStubMsg->StackTop);
|
||||
I_RpcFree(async_call_data);
|
||||
|
||||
TRACE("-- 0x%x\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis,
|
||||
struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg,
|
||||
DWORD * pdwStubPhase)
|
||||
{
|
||||
FIXME("unimplemented, expect crash!\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -240,3 +240,4 @@ void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
PFORMAT_STRING pFormat, int phase, unsigned char *args,
|
||||
unsigned short stack_size, unsigned char *pRetVal, BOOL object_proc,
|
||||
BOOL ignore_retval);
|
||||
RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply);
|
||||
|
|
|
@ -416,6 +416,7 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc,
|
|||
void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection)
|
||||
{
|
||||
assert(!Connection->server);
|
||||
Connection->async_state = NULL;
|
||||
EnterCriticalSection(&assoc->cs);
|
||||
if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id;
|
||||
list_add_head(&assoc->free_connection_pool, &Connection->conn_pool_entry);
|
||||
|
|
|
@ -29,11 +29,17 @@
|
|||
|
||||
#include "rpc_binding.h"
|
||||
#include "rpc_message.h"
|
||||
#include "ndr_stubless.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
|
||||
|
||||
#define RPC_ASYNC_SIGNATURE 0x43595341
|
||||
|
||||
static inline BOOL valid_async_handle(PRPC_ASYNC_STATE pAsync)
|
||||
{
|
||||
return pAsync->Signature == RPC_ASYNC_SIGNATURE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RpcAsyncInitializeHandle [RPCRT4.@]
|
||||
*
|
||||
|
@ -104,8 +110,14 @@ RPC_STATUS WINAPI RpcAsyncGetCallStatus(PRPC_ASYNC_STATE pAsync)
|
|||
*/
|
||||
RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply)
|
||||
{
|
||||
FIXME("(%p, %p): stub\n", pAsync, Reply);
|
||||
TRACE("(%p, %p)\n", pAsync, Reply);
|
||||
|
||||
if (!valid_async_handle(pAsync))
|
||||
return RPC_S_INVALID_ASYNC_HANDLE;
|
||||
|
||||
/* FIXME: check completed */
|
||||
|
||||
return NdrpCompleteAsyncClientCall(pAsync, Reply);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -116,8 +116,9 @@
|
|||
@ stdcall NDRSContextUnmarshallEx(ptr ptr ptr)
|
||||
@ stub NDRcopy
|
||||
@ stdcall NdrAllocate(ptr long)
|
||||
@ stub NdrAsyncClientCall
|
||||
@ varargs NdrAsyncClientCall(ptr ptr)
|
||||
@ stub NdrAsyncServerCall
|
||||
@ stdcall NdrAsyncStubCall(ptr ptr ptr ptr)
|
||||
@ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr)
|
||||
@ stdcall NdrByteCountPointerFree(ptr ptr ptr)
|
||||
@ stdcall NdrByteCountPointerMarshall(ptr ptr ptr)
|
||||
|
|
Loading…
Reference in New Issue