rpcrt4: Implement NdrMesProcEncodeDecode.

This commit is contained in:
Rob Shearman 2007-11-05 11:16:43 +00:00 committed by Alexandre Julliard
parent 0879041cd2
commit 734094ed2c
4 changed files with 259 additions and 23 deletions

View file

@ -26,10 +26,13 @@
#include "winerror.h"
#include "rpc.h"
#include "midles.h"
#include "ndrtypes.h"
#include "ndr_misc.h"
#include "ndr_stubless.h"
#include "wine/debug.h"
#include "wine/rpcfc.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
@ -128,3 +131,230 @@ RPC_STATUS WINAPI MesHandleFree(handle_t Handle)
HeapFree(GetProcessHeap(), 0, Handle);
return RPC_S_OK;
}
static void es_data_alloc(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
{
if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
{
unsigned int tmpsize = size;
TRACE("%d with incremental handle\n", size);
pEsMsg->Alloc(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
if (tmpsize < size)
{
ERR("not enough bytes allocated - requested %d, got %d\n", size, tmpsize);
RpcRaiseException(ERROR_OUTOFMEMORY);
}
}
pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
}
static void es_data_read(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
{
if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
{
unsigned int tmpsize = size;
TRACE("%d from incremental handle\n", size);
pEsMsg->Read(pEsMsg->UserState, (char **)&pEsMsg->StubMsg.Buffer, &tmpsize);
if (tmpsize < size)
{
ERR("not enough bytes read - requested %d, got %d\n", size, tmpsize);
RpcRaiseException(ERROR_OUTOFMEMORY);
}
}
pEsMsg->StubMsg.BufferLength = size;
pEsMsg->StubMsg.RpcMsg->Buffer = pEsMsg->StubMsg.BufferStart = pEsMsg->StubMsg.Buffer;
pEsMsg->StubMsg.BufferEnd = pEsMsg->StubMsg.Buffer + size;
}
static void es_data_write(MIDL_ES_MESSAGE *pEsMsg, ULONG size)
{
if (pEsMsg->HandleStyle == MES_INCREMENTAL_HANDLE)
{
TRACE("%d to incremental handle\n", size);
pEsMsg->Write(pEsMsg->UserState, (char *)pEsMsg->StubMsg.BufferStart, size);
}
}
static inline ULONG mes_proc_header_buffer_size(void)
{
return 4 + 2*sizeof(RPC_SYNTAX_IDENTIFIER) + 12;
}
static void mes_proc_header_marshal(MIDL_ES_MESSAGE *pEsMsg)
{
const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
*(WORD *)pEsMsg->StubMsg.Buffer = 0x0101;
pEsMsg->StubMsg.Buffer += 2;
*(WORD *)pEsMsg->StubMsg.Buffer = 0xcccc;
pEsMsg->StubMsg.Buffer += 2;
memcpy(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER));
pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
memcpy(pEsMsg->StubMsg.Buffer, &pEsMsg->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER));
pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
*(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ProcNumber;
pEsMsg->StubMsg.Buffer += 4;
*(DWORD *)pEsMsg->StubMsg.Buffer = 0x00000001;
pEsMsg->StubMsg.Buffer += 4;
*(DWORD *)pEsMsg->StubMsg.Buffer = pEsMsg->ByteCount;
pEsMsg->StubMsg.Buffer += 4;
}
static void mes_proc_header_unmarshal(MIDL_ES_MESSAGE *pEsMsg)
{
const RPC_CLIENT_INTERFACE *client_interface = pEsMsg->StubMsg.StubDesc->RpcInterfaceInformation;
es_data_read(pEsMsg, mes_proc_header_buffer_size());
if (*(WORD *)pEsMsg->StubMsg.Buffer != 0x0101)
{
FIXME("unknown value at Buffer[0] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
RpcRaiseException(RPC_X_WRONG_ES_VERSION);
}
pEsMsg->StubMsg.Buffer += 2;
if (*(WORD *)pEsMsg->StubMsg.Buffer != 0xcccc)
FIXME("unknown value at Buffer[2] 0x%04x\n", *(WORD *)pEsMsg->StubMsg.Buffer);
pEsMsg->StubMsg.Buffer += 2;
if (memcmp(pEsMsg->StubMsg.Buffer, &client_interface->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER)))
{
const RPC_SYNTAX_IDENTIFIER *AlienTransferSyntax = (const RPC_SYNTAX_IDENTIFIER *)pEsMsg->StubMsg.Buffer;
ERR("bad transfer syntax %s {%d.%d}\n", debugstr_guid(&AlienTransferSyntax->SyntaxGUID),
AlienTransferSyntax->SyntaxVersion.MajorVersion,
AlienTransferSyntax->SyntaxVersion.MinorVersion);
RpcRaiseException(RPC_S_UNSUPPORTED_TRANS_SYN);
}
pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
memcpy(&pEsMsg->InterfaceId, pEsMsg->StubMsg.Buffer, sizeof(RPC_SYNTAX_IDENTIFIER));
pEsMsg->StubMsg.Buffer += sizeof(RPC_SYNTAX_IDENTIFIER);
pEsMsg->ProcNumber = *(DWORD *)pEsMsg->StubMsg.Buffer;
pEsMsg->StubMsg.Buffer += 4;
if (*(DWORD *)pEsMsg->StubMsg.Buffer != 0x00000001)
FIXME("unknown value 0x%08x, expected 0x00000001\n", *(DWORD *)pEsMsg->StubMsg.Buffer);
pEsMsg->StubMsg.Buffer += 4;
pEsMsg->ByteCount = *(DWORD *)pEsMsg->StubMsg.Buffer;
pEsMsg->StubMsg.Buffer += 4;
if (pEsMsg->ByteCount + mes_proc_header_buffer_size() < pEsMsg->ByteCount)
RpcRaiseException(RPC_S_INVALID_BOUND);
}
/***********************************************************************
* NdrMesProcEncodeDecode [RPCRT4.@]
*/
void WINAPIV NdrMesProcEncodeDecode(handle_t Handle, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, ...)
{
/* pointer to start of stack where arguments start */
RPC_MESSAGE rpcMsg;
MIDL_ES_MESSAGE *pEsMsg = (MIDL_ES_MESSAGE *)Handle;
/* size of stack */
unsigned short stack_size;
/* header for procedure string */
const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
/* the value to return to the client from the remote procedure */
LONG_PTR RetVal = 0;
const RPC_CLIENT_INTERFACE *client_interface;
TRACE("Handle %p, pStubDesc %p, pFormat %p, ...\n", Handle, 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);
}
client_interface = pStubDesc->RpcInterfaceInformation;
pEsMsg->InterfaceId = client_interface->InterfaceId;
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
{
const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
stack_size = pProcHeader->stack_size;
pEsMsg->ProcNumber = pProcHeader->proc_num;
pFormat += sizeof(NDR_PROC_HEADER_RPC);
}
else
{
stack_size = pProcHeader->stack_size;
pEsMsg->ProcNumber = pProcHeader->proc_num;
pFormat += sizeof(NDR_PROC_HEADER);
}
if (pProcHeader->handle_type == RPC_FC_BIND_EXPLICIT)
{
switch (*pFormat) /* handle_type */
{
case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
pFormat += sizeof(NDR_EHD_PRIMITIVE);
break;
case RPC_FC_BIND_GENERIC: /* explicit generic */
pFormat += sizeof(NDR_EHD_GENERIC);
break;
case RPC_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);
}
}
TRACE("stack size: 0x%x\n", stack_size);
TRACE("proc num: %d\n", pEsMsg->ProcNumber);
memset(&rpcMsg, 0, sizeof(rpcMsg));
pEsMsg->StubMsg.RpcMsg = &rpcMsg;
pEsMsg->StubMsg.StubDesc = pStubDesc;
pEsMsg->StubMsg.pfnAllocate = pStubDesc->pfnAllocate;
pEsMsg->StubMsg.pfnFree = pStubDesc->pfnFree;
/* create the full pointer translation tables, if requested */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
pEsMsg->StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
TRACE("stubdesc version = 0x%x\n", pStubDesc->Version);
TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
/* needed for conformance of top-level objects */
#ifdef __i386__
pEsMsg->StubMsg.StackTop = *(unsigned char **)(&pFormat+1);
#else
# warning Stack not retrieved for your CPU architecture
#endif
switch (pEsMsg->Operation)
{
case MES_ENCODE:
pEsMsg->StubMsg.BufferLength = mes_proc_header_buffer_size();
client_do_args_old_format(&pEsMsg->StubMsg, pFormat, PROXY_CALCSIZE,
pEsMsg->StubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
FALSE /* object_proc */);
pEsMsg->ByteCount = pEsMsg->StubMsg.BufferLength - mes_proc_header_buffer_size();
es_data_alloc(pEsMsg, pEsMsg->StubMsg.BufferLength);
mes_proc_header_marshal(pEsMsg);
client_do_args_old_format(&pEsMsg->StubMsg, pFormat, PROXY_MARSHAL,
pEsMsg->StubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
FALSE /* object_proc */);
es_data_write(pEsMsg, pEsMsg->ByteCount);
break;
case MES_DECODE:
mes_proc_header_unmarshal(pEsMsg);
es_data_read(pEsMsg, pEsMsg->ByteCount);
client_do_args_old_format(&pEsMsg->StubMsg, pFormat, PROXY_UNMARSHAL,
pEsMsg->StubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
FALSE /* object_proc */);
break;
default:
RpcRaiseException(RPC_S_INTERNAL_ERROR);
return;
}
/* free the full pointer translation tables */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
NdrFullPointerXlatFree(pEsMsg->StubMsg.FullPtrXlatTables);
}

View file

@ -136,7 +136,7 @@ static void WINAPI dump_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags)
TRACE("\n");
}
#define ARG_FROM_OFFSET(stubMsg, offset) ((stubMsg).StackTop + (offset))
#define ARG_FROM_OFFSET(args, offset) ((args) + (offset))
static PFORMAT_STRING client_get_handle(
PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
@ -156,9 +156,9 @@ static PFORMAT_STRING client_get_handle(
TRACE("Explicit primitive handle @ %d\n", pDesc->offset);
if (pDesc->flag) /* pointer to binding */
*phBinding = **(handle_t **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
*phBinding = **(handle_t **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
else
*phBinding = *(handle_t *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
*phBinding = *(handle_t *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
return pFormat + sizeof(NDR_EHD_PRIMITIVE);
}
case RPC_FC_BIND_GENERIC: /* explicit generic */
@ -171,9 +171,9 @@ static PFORMAT_STRING client_get_handle(
TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
else
pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
*phBinding = pGenPair->pfnBind(pObject);
@ -187,10 +187,10 @@ static PFORMAT_STRING client_get_handle(
if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR)
{
TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n");
context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
}
else
context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
if ((pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) &&
!context_handle)
{
@ -254,9 +254,9 @@ static void client_free_handle(
TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
else
pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
pGenPair->pfnUnbind(pObject, hBinding);
@ -285,7 +285,8 @@ static void client_free_handle(
}
static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
int phase, unsigned short number_of_params, unsigned char *pRetVal)
int phase, unsigned char *args, unsigned short number_of_params,
unsigned char *pRetVal)
{
/* current format string offset */
int current_offset = 0;
@ -301,7 +302,7 @@ static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
unsigned char * pArg;
current_stack_offset = pParam->stack_offset;
pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset);
pArg = ARG_FROM_OFFSET(args, current_stack_offset);
TRACE("param[%d]: new format\n", i);
TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
@ -437,8 +438,9 @@ static unsigned int type_stack_size(unsigned char fc)
}
}
static void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat, int phase, unsigned short stack_size,
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)
{
/* current format string offset */
@ -460,7 +462,7 @@ static void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
* if present, so adjust this */
unsigned short current_stack_offset_adjusted = current_stack_offset +
(object_proc ? sizeof(void *) : 0);
unsigned char * pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset_adjusted);
unsigned char * pArg = ARG_FROM_OFFSET(args, current_stack_offset_adjusted);
/* no more parameters; exit loop */
if (current_stack_offset_adjusted >= stack_size)
@ -716,11 +718,11 @@ LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma
case PROXY_MARSHAL:
case PROXY_UNMARSHAL:
if (bV2Format)
client_do_args(&stubMsg, pFormat, phase, number_of_params,
(unsigned char *)&RetVal);
client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop,
number_of_params, (unsigned char *)&RetVal);
else
client_do_args_old_format(&stubMsg, pFormat, phase, stack_size,
(unsigned char *)&RetVal,
client_do_args_old_format(&stubMsg, pFormat, phase,
stubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT));
break;
default:
@ -794,11 +796,11 @@ LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma
case PROXY_MARSHAL:
case PROXY_UNMARSHAL:
if (bV2Format)
client_do_args(&stubMsg, pFormat, phase, number_of_params,
(unsigned char *)&RetVal);
client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop,
number_of_params, (unsigned char *)&RetVal);
else
client_do_args_old_format(&stubMsg, pFormat, phase, stack_size,
(unsigned char *)&RetVal,
client_do_args_old_format(&stubMsg, pFormat, phase,
stubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT));
break;
default:

View file

@ -235,3 +235,7 @@ typedef struct _NDR_EHD_CONTEXT
} NDR_EHD_CONTEXT;
#include "poppack.h"
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);

View file

@ -218,7 +218,7 @@
@ stdcall NdrMapCommAndFaultStatus(ptr ptr ptr long)
@ stub NdrMarkNextActivePipe
@ stub NdrMesProcEncodeDecode2
@ stub NdrMesProcEncodeDecode
@ varargs NdrMesProcEncodeDecode(ptr ptr ptr)
@ stub NdrMesSimpleTypeAlignSize
@ stub NdrMesSimpleTypeDecode
@ stub NdrMesSimpleTypeEncode