From 734094ed2c2db2187f6c6785203f5a76cc22ccaa Mon Sep 17 00:00:00 2001 From: Rob Shearman Date: Mon, 5 Nov 2007 11:16:43 +0000 Subject: [PATCH] rpcrt4: Implement NdrMesProcEncodeDecode. --- dlls/rpcrt4/ndr_es.c | 230 +++++++++++++++++++++++++++++++++++++ dlls/rpcrt4/ndr_stubless.c | 46 ++++---- dlls/rpcrt4/ndr_stubless.h | 4 + dlls/rpcrt4/rpcrt4.spec | 2 +- 4 files changed, 259 insertions(+), 23 deletions(-) diff --git a/dlls/rpcrt4/ndr_es.c b/dlls/rpcrt4/ndr_es.c index 4b3260257d9..097d8a950fe 100644 --- a/dlls/rpcrt4/ndr_es.c +++ b/dlls/rpcrt4/ndr_es.c @@ -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); +} diff --git a/dlls/rpcrt4/ndr_stubless.c b/dlls/rpcrt4/ndr_stubless.c index 06a7afab6c4..9d28b362c45 100644 --- a/dlls/rpcrt4/ndr_stubless.c +++ b/dlls/rpcrt4/ndr_stubless.c @@ -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: diff --git a/dlls/rpcrt4/ndr_stubless.h b/dlls/rpcrt4/ndr_stubless.h index 35a228d2094..06b552c3388 100644 --- a/dlls/rpcrt4/ndr_stubless.h +++ b/dlls/rpcrt4/ndr_stubless.h @@ -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); diff --git a/dlls/rpcrt4/rpcrt4.spec b/dlls/rpcrt4/rpcrt4.spec index 3300512c904..f2fa80a1211 100644 --- a/dlls/rpcrt4/rpcrt4.spec +++ b/dlls/rpcrt4/rpcrt4.spec @@ -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