📄 ndr_marshall.c
字号:
/* * NDR data marshalling * * Copyright 2002 Greg Turner * Copyright 2003-2006 CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * TODO: * - Non-conformant strings * - String structs * - Encapsulated unions * - Byte count pointers * - transmit_as/represent as * - Multi-dimensional arrays * - Conversion functions (NdrConvert) * - Checks for integer addition overflow * - Checks for out-of-memory conditions */#include <stdarg.h>#include <stdio.h>#include <string.h>#include <assert.h>#include <limits.h>#include "windef.h"#include "winbase.h"#include "winerror.h"#include "ndr_misc.h"#include "rpcndr.h"#include "wine/unicode.h"#include "wine/rpcfc.h"#include "wine/debug.h"#include "wine/list.h"WINE_DEFAULT_DEBUG_CHANNEL(ole);#if defined(__i386__)# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ (*((UINT32 *)(pchar)) = (uint32))# define LITTLE_ENDIAN_UINT32_READ(pchar) \ (*((UINT32 *)(pchar)))#else /* these would work for i386 too, but less efficient */# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ (*(pchar) = LOBYTE(LOWORD(uint32)), \ *((pchar)+1) = HIBYTE(LOWORD(uint32)), \ *((pchar)+2) = LOBYTE(HIWORD(uint32)), \ *((pchar)+3) = HIBYTE(HIWORD(uint32)), \ (uint32)) /* allow as r-value */# define LITTLE_ENDIAN_UINT32_READ(pchar) \ (MAKELONG( \ MAKEWORD(*(pchar), *((pchar)+1)), \ MAKEWORD(*((pchar)+2), *((pchar)+3))))#endif#define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \ (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \ *((pchar)+2) = HIBYTE(LOWORD(uint32)), \ *((pchar)+1) = LOBYTE(HIWORD(uint32)), \ *(pchar) = HIBYTE(HIWORD(uint32)), \ (uint32)) /* allow as r-value */#define BIG_ENDIAN_UINT32_READ(pchar) \ (MAKELONG( \ MAKEWORD(*((pchar)+3), *((pchar)+2)), \ MAKEWORD(*((pchar)+1), *(pchar))))#ifdef NDR_LOCAL_IS_BIG_ENDIAN# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ BIG_ENDIAN_UINT32_WRITE(pchar, uint32)# define NDR_LOCAL_UINT32_READ(pchar) \ BIG_ENDIAN_UINT32_READ(pchar)#else# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)# define NDR_LOCAL_UINT32_READ(pchar) \ LITTLE_ENDIAN_UINT32_READ(pchar)#endif/* _Align must be the desired alignment, * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)#define STD_OVERFLOW_CHECK(_Msg) do { \ TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \ if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \ ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \ } while (0)#define NDR_TABLE_SIZE 128#define NDR_TABLE_MASK 127static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = { 0, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, /* 0x10 */ NdrBaseTypeMarshall, /* 0x11 */ NdrPointerMarshall, NdrPointerMarshall, NdrPointerMarshall, NdrPointerMarshall, /* 0x15 */ NdrSimpleStructMarshall, NdrSimpleStructMarshall, NdrConformantStructMarshall, NdrConformantStructMarshall, NdrConformantVaryingStructMarshall, NdrComplexStructMarshall, /* 0x1b */ NdrConformantArrayMarshall, NdrConformantVaryingArrayMarshall, NdrFixedArrayMarshall, NdrFixedArrayMarshall, NdrVaryingArrayMarshall, NdrVaryingArrayMarshall, NdrComplexArrayMarshall, /* 0x22 */ NdrConformantStringMarshall, 0, 0, NdrConformantStringMarshall, NdrNonConformantStringMarshall, 0, 0, 0, /* 0x2a */ NdrEncapsulatedUnionMarshall, NdrNonEncapsulatedUnionMarshall, NdrByteCountPointerMarshall, NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall, /* 0x2f */ NdrInterfacePointerMarshall, /* 0x30 */ NdrContextHandleMarshall, /* 0xb1 */ 0, 0, 0, NdrUserMarshalMarshall, 0, 0, /* 0xb7 */ NdrRangeMarshall};const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = { 0, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, /* 0x10 */ NdrBaseTypeUnmarshall, /* 0x11 */ NdrPointerUnmarshall, NdrPointerUnmarshall, NdrPointerUnmarshall, NdrPointerUnmarshall, /* 0x15 */ NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall, NdrConformantStructUnmarshall, NdrConformantStructUnmarshall, NdrConformantVaryingStructUnmarshall, NdrComplexStructUnmarshall, /* 0x1b */ NdrConformantArrayUnmarshall, NdrConformantVaryingArrayUnmarshall, NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall, NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall, NdrComplexArrayUnmarshall, /* 0x22 */ NdrConformantStringUnmarshall, 0, 0, NdrConformantStringUnmarshall, NdrNonConformantStringUnmarshall, 0, 0, 0, /* 0x2a */ NdrEncapsulatedUnionUnmarshall, NdrNonEncapsulatedUnionUnmarshall, NdrByteCountPointerUnmarshall, NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall, /* 0x2f */ NdrInterfacePointerUnmarshall, /* 0x30 */ NdrContextHandleUnmarshall, /* 0xb1 */ 0, 0, 0, NdrUserMarshalUnmarshall, 0, 0, /* 0xb7 */ NdrRangeUnmarshall};const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = { 0, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, /* 0x10 */ NdrBaseTypeBufferSize, /* 0x11 */ NdrPointerBufferSize, NdrPointerBufferSize, NdrPointerBufferSize, NdrPointerBufferSize, /* 0x15 */ NdrSimpleStructBufferSize, NdrSimpleStructBufferSize, NdrConformantStructBufferSize, NdrConformantStructBufferSize, NdrConformantVaryingStructBufferSize, NdrComplexStructBufferSize, /* 0x1b */ NdrConformantArrayBufferSize, NdrConformantVaryingArrayBufferSize, NdrFixedArrayBufferSize, NdrFixedArrayBufferSize, NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize, NdrComplexArrayBufferSize, /* 0x22 */ NdrConformantStringBufferSize, 0, 0, NdrConformantStringBufferSize, NdrNonConformantStringBufferSize, 0, 0, 0, /* 0x2a */ NdrEncapsulatedUnionBufferSize, NdrNonEncapsulatedUnionBufferSize, NdrByteCountPointerBufferSize, NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize, /* 0x2f */ NdrInterfacePointerBufferSize, /* 0x30 */ NdrContextHandleBufferSize, /* 0xb1 */ 0, 0, 0, NdrUserMarshalBufferSize, 0, 0, /* 0xb7 */ NdrRangeBufferSize};const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = { 0, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, /* 0x10 */ NdrBaseTypeMemorySize, /* 0x11 */ NdrPointerMemorySize, NdrPointerMemorySize, NdrPointerMemorySize, NdrPointerMemorySize, /* 0x15 */ NdrSimpleStructMemorySize, NdrSimpleStructMemorySize, NdrConformantStructMemorySize, NdrConformantStructMemorySize, NdrConformantVaryingStructMemorySize, NdrComplexStructMemorySize, /* 0x1b */ NdrConformantArrayMemorySize, NdrConformantVaryingArrayMemorySize, NdrFixedArrayMemorySize, NdrFixedArrayMemorySize, NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize, NdrComplexArrayMemorySize, /* 0x22 */ NdrConformantStringMemorySize, 0, 0, NdrConformantStringMemorySize, NdrNonConformantStringMemorySize, 0, 0, 0, /* 0x2a */ NdrEncapsulatedUnionMemorySize, NdrNonEncapsulatedUnionMemorySize, NdrByteCountPointerMemorySize, NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize, /* 0x2f */ NdrInterfacePointerMemorySize, /* 0x30 */ 0, /* 0xb1 */ 0, 0, 0, NdrUserMarshalMemorySize, 0, 0, /* 0xb7 */ NdrRangeMemorySize};const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = { 0, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, /* 0x10 */ NdrBaseTypeFree, /* 0x11 */ NdrPointerFree, NdrPointerFree, NdrPointerFree, NdrPointerFree, /* 0x15 */ NdrSimpleStructFree, NdrSimpleStructFree, NdrConformantStructFree, NdrConformantStructFree, NdrConformantVaryingStructFree, NdrComplexStructFree, /* 0x1b */ NdrConformantArrayFree, NdrConformantVaryingArrayFree, NdrFixedArrayFree, NdrFixedArrayFree, NdrVaryingArrayFree, NdrVaryingArrayFree, NdrComplexArrayFree, /* 0x22 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x2a */ NdrEncapsulatedUnionFree, NdrNonEncapsulatedUnionFree, 0, NdrXmitOrRepAsFree, NdrXmitOrRepAsFree, /* 0x2f */ NdrInterfacePointerFree, /* 0x30 */ 0, /* 0xb1 */ 0, 0, 0, NdrUserMarshalFree, 0, 0, /* 0xb7 */ NdrRangeFree};void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len){ /* hmm, this is probably supposed to do more? */ return pStubMsg->pfnAllocate(len);}static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer){ pStubMsg->pfnFree(Pointer);}static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat){ return (*(const ULONG *)pFormat != -1);}static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat){ ALIGN_POINTER(pStubMsg->Buffer, 4); pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); pStubMsg->Buffer += 4; TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount); if (pStubMsg->fHasNewCorrDesc) return pFormat+6; else return pFormat+4;}static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue){ if (pFormat && !IsConformanceOrVariancePresent(pFormat)) { pStubMsg->Offset = 0; pStubMsg->ActualCount = pStubMsg->MaxCount; goto done; } ALIGN_POINTER(pStubMsg->Buffer, 4); pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); pStubMsg->Buffer += 4; TRACE("offset is %d\n", pStubMsg->Offset); pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); pStubMsg->Buffer += 4; TRACE("variance is %d\n", pStubMsg->ActualCount); if ((pStubMsg->ActualCount > MaxValue) || (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue)) { ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n", pStubMsg->ActualCount, pStubMsg->Offset, MaxValue); RpcRaiseException(RPC_S_INVALID_BOUND); return NULL; }done: if (pStubMsg->fHasNewCorrDesc) return pFormat+6; else return pFormat+4;}/* writes the conformance value to the buffer */static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg){ ALIGN_POINTER(pStubMsg->Buffer, 4); NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount); pStubMsg->Buffer += 4;}/* writes the variance values to the buffer */static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg){ ALIGN_POINTER(pStubMsg->Buffer, 4); NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset); pStubMsg->Buffer += 4; NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount); pStubMsg->Buffer += 4;}/* requests buffer space for the conformance value */static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg){ ALIGN_LENGTH(pStubMsg->BufferLength, 4); pStubMsg->BufferLength += 4;}/* requests buffer space for the variance values */static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg){ ALIGN_LENGTH(pStubMsg->BufferLength, 4); pStubMsg->BufferLength += 8;}PFORMAT_STRING ComputeConformanceOrVariance( MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -