| /* |
| * 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 "winreg.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/%ld\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 127 |
| |
| static 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 unsigned long WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING); |
| |
| 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, |
| /* 0xb0 */ |
| 0, 0, 0, 0, |
| NdrUserMarshalMarshall |
| }; |
| 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, |
| /* 0xb0 */ |
| 0, 0, 0, 0, |
| NdrUserMarshalUnmarshall |
| }; |
| 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, |
| /* 0xb0 */ |
| 0, 0, 0, 0, |
| NdrUserMarshalBufferSize |
| }; |
| 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, |
| /* 0xb0 */ |
| 0, 0, 0, 0, |
| NdrUserMarshalMemorySize |
| }; |
| 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, |
| /* 0xb0 */ |
| 0, 0, 0, 0, |
| NdrUserMarshalFree |
| }; |
| |
| 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 %ld\n", pStubMsg->Offset); |
| pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); |
| pStubMsg->Buffer += 4; |
| TRACE("variance is %ld\n", pStubMsg->ActualCount); |
| |
| if ((pStubMsg->ActualCount > MaxValue) || |
| (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue)) |
| { |
| ERR("invalid array bound(s): ActualCount = %ld, Offset = %ld, MaxValue = %ld\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 *pCount) |
| { |
| BYTE dtype = pFormat[0] & 0xf; |
| short ofs = *(short *)&pFormat[2]; |
| LPVOID ptr = NULL; |
| DWORD data = 0; |
| |
| if (!IsConformanceOrVariancePresent(pFormat)) { |
| /* null descriptor */ |
| *pCount = def; |
| goto finish_conf; |
| } |
| |
| switch (pFormat[0] & 0xf0) { |
| case RPC_FC_NORMAL_CONFORMANCE: |
| TRACE("normal conformance, ofs=%d\n", ofs); |
| ptr = pMemory; |
| break; |
| case RPC_FC_POINTER_CONFORMANCE: |
| TRACE("pointer conformance, ofs=%d\n", ofs); |
| ptr = pStubMsg->Memory; |
| break; |
| case RPC_FC_TOP_LEVEL_CONFORMANCE: |
| TRACE("toplevel conformance, ofs=%d\n", ofs); |
| if (pStubMsg->StackTop) { |
| ptr = pStubMsg->StackTop; |
| } |
| else { |
| /* -Os mode, *pCount is already set */ |
| goto finish_conf; |
| } |
| break; |
| case RPC_FC_CONSTANT_CONFORMANCE: |
| data = ofs | ((DWORD)pFormat[1] << 16); |
| TRACE("constant conformance, val=%ld\n", data); |
| *pCount = data; |
| goto finish_conf; |
| case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE: |
| FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs); |
| if (pStubMsg->StackTop) { |
| ptr = pStubMsg->StackTop; |
| } |
| else { |
| /* ? */ |
| goto done_conf_grab; |
| } |
| break; |
| default: |
| FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0); |
| } |
| |
| switch (pFormat[1]) { |
| case RPC_FC_DEREFERENCE: |
| ptr = *(LPVOID*)((char *)ptr + ofs); |
| break; |
| case RPC_FC_CALLBACK: |
| { |
| unsigned char *old_stack_top = pStubMsg->StackTop; |
| pStubMsg->StackTop = ptr; |
| |
| /* ofs is index into StubDesc->apfnExprEval */ |
| TRACE("callback conformance into apfnExprEval[%d]\n", ofs); |
| pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg); |
| |
| pStubMsg->StackTop = old_stack_top; |
| |
| /* the callback function always stores the computed value in MaxCount */ |
| *pCount = pStubMsg->MaxCount; |
| goto finish_conf; |
| } |
| default: |
| ptr = (char *)ptr + ofs; |
| break; |
| } |
| |
| switch (dtype) { |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| data = *(DWORD*)ptr; |
| break; |
| case RPC_FC_SHORT: |
| data = *(SHORT*)ptr; |
| break; |
| case RPC_FC_USHORT: |
| data = *(USHORT*)ptr; |
| break; |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| data = *(CHAR*)ptr; |
| break; |
| case RPC_FC_BYTE: |
| case RPC_FC_USMALL: |
| data = *(UCHAR*)ptr; |
| break; |
| default: |
| FIXME("unknown conformance data type %x\n", dtype); |
| goto done_conf_grab; |
| } |
| TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data); |
| |
| done_conf_grab: |
| switch (pFormat[1]) { |
| case RPC_FC_DEREFERENCE: /* already handled */ |
| case 0: /* no op */ |
| *pCount = data; |
| break; |
| case RPC_FC_ADD_1: |
| *pCount = data + 1; |
| break; |
| case RPC_FC_SUB_1: |
| *pCount = data - 1; |
| break; |
| case RPC_FC_MULT_2: |
| *pCount = data * 2; |
| break; |
| case RPC_FC_DIV_2: |
| *pCount = data / 2; |
| break; |
| default: |
| FIXME("unknown conformance op %d\n", pFormat[1]); |
| goto finish_conf; |
| } |
| |
| finish_conf: |
| TRACE("resulting conformance is %ld\n", *pCount); |
| if (pStubMsg->fHasNewCorrDesc) |
| return pFormat+6; |
| else |
| return pFormat+4; |
| } |
| |
| /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if |
| * the result overflows 32-bits */ |
| inline static ULONG safe_multiply(ULONG a, ULONG b) |
| { |
| ULONGLONG ret = (ULONGLONG)a * b; |
| if (ret > 0xffffffff) |
| { |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| return 0; |
| } |
| return ret; |
| } |
| |
| |
| /* |
| * NdrConformantString: |
| * |
| * What MS calls a ConformantString is, in DCE terminology, |
| * a Varying-Conformant String. |
| * [ |
| * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0') |
| * offset: DWORD (actual string data begins at (offset) CHARTYPE's |
| * into unmarshalled string) |
| * length: DWORD (# of CHARTYPE characters, inclusive of '\0') |
| * [ |
| * data: CHARTYPE[maxlen] |
| * ] |
| * ], where CHARTYPE is the appropriate character type (specified externally) |
| * |
| */ |
| |
| /*********************************************************************** |
| * NdrConformantStringMarshall [RPCRT4.@] |
| */ |
| unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, |
| unsigned char *pszMessage, PFORMAT_STRING pFormat) |
| { |
| ULONG esize, size; |
| |
| TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); |
| |
| if (*pFormat == RPC_FC_C_CSTRING) { |
| TRACE("string=%s\n", debugstr_a((char*)pszMessage)); |
| pStubMsg->ActualCount = strlen((char*)pszMessage)+1; |
| esize = 1; |
| } |
| else if (*pFormat == RPC_FC_C_WSTRING) { |
| TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage)); |
| pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1; |
| esize = 2; |
| } |
| else { |
| ERR("Unhandled string type: %#x\n", *pFormat); |
| /* FIXME: raise an exception. */ |
| return NULL; |
| } |
| |
| if (pFormat[1] == RPC_FC_STRING_SIZED) |
| pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0); |
| else |
| pStubMsg->MaxCount = pStubMsg->ActualCount; |
| pStubMsg->Offset = 0; |
| WriteConformance(pStubMsg); |
| WriteVariance(pStubMsg); |
| |
| size = safe_multiply(esize, pStubMsg->ActualCount); |
| memcpy(pStubMsg->Buffer, pszMessage, size); /* the string itself */ |
| pStubMsg->Buffer += size; |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| /* success */ |
| return NULL; /* is this always right? */ |
| } |
| |
| /*********************************************************************** |
| * NdrConformantStringBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char* pMemory, PFORMAT_STRING pFormat) |
| { |
| ULONG esize; |
| |
| TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); |
| |
| SizeConformance(pStubMsg); |
| SizeVariance(pStubMsg); |
| |
| if (*pFormat == RPC_FC_C_CSTRING) { |
| TRACE("string=%s\n", debugstr_a((char*)pMemory)); |
| pStubMsg->ActualCount = strlen((char*)pMemory)+1; |
| esize = 1; |
| } |
| else if (*pFormat == RPC_FC_C_WSTRING) { |
| TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory)); |
| pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1; |
| esize = 2; |
| } |
| else { |
| ERR("Unhandled string type: %#x\n", *pFormat); |
| /* FIXME: raise an exception */ |
| return; |
| } |
| |
| if (pFormat[1] == RPC_FC_STRING_SIZED) |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); |
| else |
| pStubMsg->MaxCount = pStubMsg->ActualCount; |
| |
| pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount); |
| } |
| |
| /************************************************************************ |
| * NdrConformantStringMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat ) |
| { |
| unsigned long rslt = 0; |
| |
| FIXME("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); |
| |
| assert(pStubMsg && pFormat); |
| |
| if (*pFormat == RPC_FC_C_CSTRING) { |
| rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */ |
| } |
| else if (*pFormat == RPC_FC_C_WSTRING) { |
| rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */ |
| } |
| else { |
| ERR("Unhandled string type: %#x\n", *pFormat); |
| /* FIXME: raise an exception */ |
| } |
| |
| if (pFormat[1] != RPC_FC_PAD) { |
| FIXME("sized string format=%d\n", pFormat[1]); |
| } |
| |
| TRACE(" --> %lu\n", rslt); |
| return rslt; |
| } |
| |
| /************************************************************************ |
| * NdrConformantStringUnmarshall [RPCRT4.@] |
| */ |
| unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) |
| { |
| ULONG bufsize, memsize, esize, i; |
| |
| TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", |
| pStubMsg, *ppMemory, pFormat, fMustAlloc); |
| |
| assert(pFormat && ppMemory && pStubMsg); |
| |
| ReadConformance(pStubMsg, NULL); |
| ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); |
| |
| if (*pFormat == RPC_FC_C_CSTRING) esize = 1; |
| else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; |
| else { |
| ERR("Unhandled string type: %#x\n", *pFormat); |
| /* FIXME: raise an exception */ |
| esize = 0; |
| } |
| |
| memsize = safe_multiply(esize, pStubMsg->MaxCount); |
| bufsize = safe_multiply(esize, pStubMsg->ActualCount); |
| |
| /* strings must always have null terminating bytes */ |
| if (bufsize < esize) |
| { |
| ERR("invalid string length of %ld\n", pStubMsg->ActualCount); |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| return NULL; |
| } |
| for (i = bufsize - esize; i < bufsize; i++) |
| if (pStubMsg->Buffer[i] != 0) |
| { |
| ERR("string not null-terminated at byte position %ld, data is 0x%x\n", |
| i, pStubMsg->Buffer[i]); |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| return NULL; |
| } |
| |
| if (fMustAlloc || !*ppMemory) |
| *ppMemory = NdrAllocate(pStubMsg, memsize); |
| |
| memcpy(*ppMemory, pStubMsg->Buffer, bufsize); |
| |
| pStubMsg->Buffer += bufsize; |
| |
| if (*pFormat == RPC_FC_C_CSTRING) { |
| TRACE("string=%s\n", debugstr_a((char*)*ppMemory)); |
| } |
| else if (*pFormat == RPC_FC_C_WSTRING) { |
| TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); |
| } |
| |
| return NULL; /* FIXME: is this always right? */ |
| } |
| |
| /*********************************************************************** |
| * NdrNonConformantStringMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrNonConformantStringUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| FIXME("stub\n"); |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrNonConformantStringBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrNonConformantStringMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| return 0; |
| } |
| |
| static inline void dump_pointer_attr(unsigned char attr) |
| { |
| if (attr & RPC_FC_P_ALLOCALLNODES) |
| TRACE(" RPC_FC_P_ALLOCALLNODES"); |
| if (attr & RPC_FC_P_DONTFREE) |
| TRACE(" RPC_FC_P_DONTFREE"); |
| if (attr & RPC_FC_P_ONSTACK) |
| TRACE(" RPC_FC_P_ONSTACK"); |
| if (attr & RPC_FC_P_SIMPLEPOINTER) |
| TRACE(" RPC_FC_P_SIMPLEPOINTER"); |
| if (attr & RPC_FC_P_DEREF) |
| TRACE(" RPC_FC_P_DEREF"); |
| TRACE("\n"); |
| } |
| |
| /*********************************************************************** |
| * PointerMarshall |
| */ |
| static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *Buffer, |
| unsigned char *Pointer, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned type = pFormat[0], attr = pFormat[1]; |
| PFORMAT_STRING desc; |
| NDR_MARSHALL m; |
| unsigned long pointer_id; |
| int pointer_needs_marshaling; |
| |
| TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat); |
| TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); |
| pFormat += 2; |
| if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; |
| else desc = pFormat + *(const SHORT*)pFormat; |
| |
| switch (type) { |
| case RPC_FC_RP: /* ref pointer (always non-null) */ |
| #if 0 /* this causes problems for InstallShield so is disabled - we need more tests */ |
| if (!Pointer) |
| RpcRaiseException(RPC_X_NULL_REF_POINTER); |
| #endif |
| pointer_needs_marshaling = 1; |
| break; |
| case RPC_FC_UP: /* unique pointer */ |
| case RPC_FC_OP: /* object pointer - same as unique here */ |
| if (Pointer) |
| pointer_needs_marshaling = 1; |
| else |
| pointer_needs_marshaling = 0; |
| pointer_id = (unsigned long)Pointer; |
| TRACE("writing 0x%08lx to buffer\n", pointer_id); |
| NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); |
| break; |
| case RPC_FC_FP: |
| pointer_needs_marshaling = !NdrFullPointerQueryPointer( |
| pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id); |
| TRACE("writing 0x%08lx to buffer\n", pointer_id); |
| NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); |
| break; |
| default: |
| FIXME("unhandled ptr type=%02x\n", type); |
| RpcRaiseException(RPC_X_BAD_STUB_DATA); |
| return; |
| } |
| |
| TRACE("calling marshaller for type 0x%x\n", (int)*desc); |
| |
| if (pointer_needs_marshaling) { |
| if (attr & RPC_FC_P_DEREF) { |
| Pointer = *(unsigned char**)Pointer; |
| TRACE("deref => %p\n", Pointer); |
| } |
| m = NdrMarshaller[*desc & NDR_TABLE_MASK]; |
| if (m) m(pStubMsg, Pointer, desc); |
| else FIXME("no marshaller for data type=%02x\n", *desc); |
| } |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| } |
| |
| /*********************************************************************** |
| * PointerUnmarshall |
| */ |
| static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *Buffer, |
| unsigned char **pPointer, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| unsigned type = pFormat[0], attr = pFormat[1]; |
| PFORMAT_STRING desc; |
| NDR_UNMARSHALL m; |
| DWORD pointer_id = 0; |
| int pointer_needs_unmarshaling; |
| |
| TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc); |
| TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); |
| pFormat += 2; |
| if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; |
| else desc = pFormat + *(const SHORT*)pFormat; |
| |
| switch (type) { |
| case RPC_FC_RP: /* ref pointer (always non-null) */ |
| pointer_needs_unmarshaling = 1; |
| break; |
| case RPC_FC_UP: /* unique pointer */ |
| pointer_id = NDR_LOCAL_UINT32_READ(Buffer); |
| TRACE("pointer_id is 0x%08lx\n", pointer_id); |
| if (pointer_id) |
| pointer_needs_unmarshaling = 1; |
| else { |
| *pPointer = NULL; |
| pointer_needs_unmarshaling = 0; |
| } |
| break; |
| case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ |
| pointer_id = NDR_LOCAL_UINT32_READ(Buffer); |
| TRACE("pointer_id is 0x%08lx\n", pointer_id); |
| if (!fMustAlloc && *pPointer) |
| { |
| FIXME("free object pointer %p\n", *pPointer); |
| *pPointer = NULL; |
| } |
| if (pointer_id) |
| pointer_needs_unmarshaling = 1; |
| else |
| pointer_needs_unmarshaling = 0; |
| break; |
| case RPC_FC_FP: |
| pointer_id = NDR_LOCAL_UINT32_READ(Buffer); |
| TRACE("pointer_id is 0x%08lx\n", pointer_id); |
| pointer_needs_unmarshaling = !NdrFullPointerQueryRefId( |
| pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer); |
| break; |
| default: |
| FIXME("unhandled ptr type=%02x\n", type); |
| RpcRaiseException(RPC_X_BAD_STUB_DATA); |
| return; |
| } |
| |
| if (pointer_needs_unmarshaling) { |
| if (attr & RPC_FC_P_DEREF) { |
| if (!*pPointer || fMustAlloc) |
| *pPointer = NdrAllocate(pStubMsg, sizeof(void *)); |
| pPointer = *(unsigned char***)pPointer; |
| TRACE("deref => %p\n", pPointer); |
| } |
| m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; |
| if (m) m(pStubMsg, pPointer, desc, fMustAlloc); |
| else FIXME("no unmarshaller for data type=%02x\n", *desc); |
| |
| if (type == RPC_FC_FP) |
| NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id, |
| *pPointer); |
| } |
| |
| TRACE("pointer=%p\n", *pPointer); |
| } |
| |
| /*********************************************************************** |
| * PointerBufferSize |
| */ |
| static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *Pointer, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned type = pFormat[0], attr = pFormat[1]; |
| PFORMAT_STRING desc; |
| NDR_BUFFERSIZE m; |
| int pointer_needs_sizing; |
| unsigned long pointer_id; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); |
| TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); |
| pFormat += 2; |
| if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; |
| else desc = pFormat + *(const SHORT*)pFormat; |
| |
| switch (type) { |
| case RPC_FC_RP: /* ref pointer (always non-null) */ |
| break; |
| case RPC_FC_OP: |
| case RPC_FC_UP: |
| /* NULL pointer has no further representation */ |
| if (!Pointer) |
| return; |
| break; |
| case RPC_FC_FP: |
| pointer_needs_sizing = !NdrFullPointerQueryPointer( |
| pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id); |
| if (!pointer_needs_sizing) |
| return; |
| break; |
| default: |
| FIXME("unhandled ptr type=%02x\n", type); |
| RpcRaiseException(RPC_X_BAD_STUB_DATA); |
| return; |
| } |
| |
| if (attr & RPC_FC_P_DEREF) { |
| Pointer = *(unsigned char**)Pointer; |
| TRACE("deref => %p\n", Pointer); |
| } |
| |
| m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; |
| if (m) m(pStubMsg, Pointer, desc); |
| else FIXME("no buffersizer for data type=%02x\n", *desc); |
| } |
| |
| /*********************************************************************** |
| * PointerMemorySize [RPCRT4.@] |
| */ |
| static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *Buffer, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned type = pFormat[0], attr = pFormat[1]; |
| PFORMAT_STRING desc; |
| NDR_MEMORYSIZE m; |
| |
| FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat); |
| TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); |
| pFormat += 2; |
| if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; |
| else desc = pFormat + *(const SHORT*)pFormat; |
| |
| switch (type) { |
| case RPC_FC_RP: /* ref pointer (always non-null) */ |
| break; |
| default: |
| FIXME("unhandled ptr type=%02x\n", type); |
| RpcRaiseException(RPC_X_BAD_STUB_DATA); |
| } |
| |
| if (attr & RPC_FC_P_DEREF) { |
| TRACE("deref\n"); |
| } |
| |
| m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; |
| if (m) m(pStubMsg, desc); |
| else FIXME("no memorysizer for data type=%02x\n", *desc); |
| |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * PointerFree [RPCRT4.@] |
| */ |
| static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *Pointer, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned type = pFormat[0], attr = pFormat[1]; |
| PFORMAT_STRING desc; |
| NDR_FREE m; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); |
| TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); |
| if (attr & RPC_FC_P_DONTFREE) return; |
| pFormat += 2; |
| if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; |
| else desc = pFormat + *(const SHORT*)pFormat; |
| |
| if (!Pointer) return; |
| |
| if (type == RPC_FC_FP) { |
| int pointer_needs_freeing = NdrFullPointerFree( |
| pStubMsg->FullPtrXlatTables, Pointer); |
| if (!pointer_needs_freeing) |
| return; |
| } |
| |
| if (attr & RPC_FC_P_DEREF) { |
| Pointer = *(unsigned char**)Pointer; |
| TRACE("deref => %p\n", Pointer); |
| } |
| |
| m = NdrFreer[*desc & NDR_TABLE_MASK]; |
| if (m) m(pStubMsg, Pointer, desc); |
| |
| /* hmm... is this sensible? |
| * perhaps we should check if the memory comes from NdrAllocate, |
| * and deallocate only if so - checking if the pointer is between |
| * BufferStart and BufferEnd is probably no good since the buffer |
| * may be reallocated when the server wants to marshal the reply */ |
| switch (*desc) { |
| case RPC_FC_BOGUS_STRUCT: |
| case RPC_FC_BOGUS_ARRAY: |
| case RPC_FC_USER_MARSHAL: |
| case RPC_FC_CARRAY: |
| case RPC_FC_CVARRAY: |
| break; |
| default: |
| FIXME("unhandled data type=%02x\n", *desc); |
| break; |
| case RPC_FC_C_CSTRING: |
| case RPC_FC_C_WSTRING: |
| if (pStubMsg->ReuseBuffer) goto notfree; |
| break; |
| case RPC_FC_IP: |
| goto notfree; |
| } |
| |
| if (attr & RPC_FC_P_ONSTACK) { |
| TRACE("not freeing stack ptr %p\n", Pointer); |
| return; |
| } |
| TRACE("freeing %p\n", Pointer); |
| NdrFree(pStubMsg, Pointer); |
| return; |
| notfree: |
| TRACE("not freeing %p\n", Pointer); |
| } |
| |
| /*********************************************************************** |
| * EmbeddedPointerMarshall |
| */ |
| static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned char *Mark = pStubMsg->BufferMark; |
| unsigned long Offset = pStubMsg->Offset; |
| unsigned ofs, rep, count, stride, xofs; |
| unsigned i; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| if (*pFormat != RPC_FC_PP) return NULL; |
| pFormat += 2; |
| |
| while (pFormat[0] != RPC_FC_END) { |
| switch (pFormat[0]) { |
| default: |
| FIXME("unknown repeat type %d\n", pFormat[0]); |
| case RPC_FC_NO_REPEAT: |
| rep = 1; |
| stride = 0; |
| ofs = 0; |
| count = 1; |
| xofs = 0; |
| pFormat += 2; |
| break; |
| case RPC_FC_FIXED_REPEAT: |
| rep = *(const WORD*)&pFormat[2]; |
| stride = *(const WORD*)&pFormat[4]; |
| ofs = *(const WORD*)&pFormat[6]; |
| count = *(const WORD*)&pFormat[8]; |
| xofs = 0; |
| pFormat += 10; |
| break; |
| case RPC_FC_VARIABLE_REPEAT: |
| rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; |
| stride = *(const WORD*)&pFormat[2]; |
| ofs = *(const WORD*)&pFormat[4]; |
| count = *(const WORD*)&pFormat[6]; |
| xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; |
| pFormat += 8; |
| break; |
| } |
| for (i = 0; i < rep; i++) { |
| PFORMAT_STRING info = pFormat; |
| unsigned char *membase = pMemory + (i * stride); |
| unsigned char *bufbase = Mark + (i * stride); |
| unsigned u; |
| /* ofs doesn't seem to matter in this context */ |
| for (u=0; u<count; u++,info+=8) { |
| unsigned char *memptr = membase + *(const SHORT*)&info[0]; |
| unsigned char *bufptr = bufbase + *(const SHORT*)&info[2]; |
| unsigned char *saved_memory = pStubMsg->Memory; |
| |
| pStubMsg->Memory = pMemory; |
| PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4); |
| pStubMsg->Memory = saved_memory; |
| } |
| } |
| pFormat += 8 * count; |
| } |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * EmbeddedPointerUnmarshall |
| */ |
| static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| unsigned char *Mark = pStubMsg->BufferMark; |
| unsigned long Offset = pStubMsg->Offset; |
| unsigned ofs, rep, count, stride, xofs; |
| unsigned i; |
| |
| TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| if (*pFormat != RPC_FC_PP) return NULL; |
| pFormat += 2; |
| |
| while (pFormat[0] != RPC_FC_END) { |
| TRACE("pFormat[0] = 0x%x\n", pFormat[0]); |
| switch (pFormat[0]) { |
| default: |
| FIXME("unknown repeat type %d\n", pFormat[0]); |
| case RPC_FC_NO_REPEAT: |
| rep = 1; |
| stride = 0; |
| ofs = 0; |
| count = 1; |
| xofs = 0; |
| pFormat += 2; |
| break; |
| case RPC_FC_FIXED_REPEAT: |
| rep = *(const WORD*)&pFormat[2]; |
| stride = *(const WORD*)&pFormat[4]; |
| ofs = *(const WORD*)&pFormat[6]; |
| count = *(const WORD*)&pFormat[8]; |
| xofs = 0; |
| pFormat += 10; |
| break; |
| case RPC_FC_VARIABLE_REPEAT: |
| rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; |
| stride = *(const WORD*)&pFormat[2]; |
| ofs = *(const WORD*)&pFormat[4]; |
| count = *(const WORD*)&pFormat[6]; |
| xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; |
| pFormat += 8; |
| break; |
| } |
| /* ofs doesn't seem to matter in this context */ |
| for (i = 0; i < rep; i++) { |
| PFORMAT_STRING info = pFormat; |
| unsigned char *membase = *ppMemory + (i * stride); |
| unsigned char *bufbase = Mark + (i * stride); |
| unsigned u; |
| for (u=0; u<count; u++,info+=8) { |
| unsigned char *memptr = membase + *(const SHORT*)&info[0]; |
| unsigned char *bufptr = bufbase + *(const SHORT*)&info[2]; |
| PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, TRUE); |
| } |
| } |
| pFormat += 8 * count; |
| } |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * EmbeddedPointerBufferSize |
| */ |
| static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned long Offset = pStubMsg->Offset; |
| unsigned ofs, rep, count, stride, xofs; |
| unsigned i; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| if (pStubMsg->IgnoreEmbeddedPointers) return; |
| |
| if (*pFormat != RPC_FC_PP) return; |
| pFormat += 2; |
| |
| while (pFormat[0] != RPC_FC_END) { |
| switch (pFormat[0]) { |
| default: |
| FIXME("unknown repeat type %d\n", pFormat[0]); |
| case RPC_FC_NO_REPEAT: |
| rep = 1; |
| stride = 0; |
| ofs = 0; |
| count = 1; |
| xofs = 0; |
| pFormat += 2; |
| break; |
| case RPC_FC_FIXED_REPEAT: |
| rep = *(const WORD*)&pFormat[2]; |
| stride = *(const WORD*)&pFormat[4]; |
| ofs = *(const WORD*)&pFormat[6]; |
| count = *(const WORD*)&pFormat[8]; |
| xofs = 0; |
| pFormat += 10; |
| break; |
| case RPC_FC_VARIABLE_REPEAT: |
| rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; |
| stride = *(const WORD*)&pFormat[2]; |
| ofs = *(const WORD*)&pFormat[4]; |
| count = *(const WORD*)&pFormat[6]; |
| xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; |
| pFormat += 8; |
| break; |
| } |
| /* ofs doesn't seem to matter in this context */ |
| for (i = 0; i < rep; i++) { |
| PFORMAT_STRING info = pFormat; |
| unsigned char *membase = pMemory + (i * stride); |
| unsigned u; |
| for (u=0; u<count; u++,info+=8) { |
| unsigned char *memptr = membase + *(const SHORT*)&info[0]; |
| unsigned char *saved_memory = pStubMsg->Memory; |
| |
| pStubMsg->Memory = pMemory; |
| PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4); |
| pStubMsg->Memory = saved_memory; |
| } |
| } |
| pFormat += 8 * count; |
| } |
| } |
| |
| /*********************************************************************** |
| * EmbeddedPointerMemorySize |
| */ |
| static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned long Offset = pStubMsg->Offset; |
| unsigned char *Mark = pStubMsg->BufferMark; |
| unsigned ofs, rep, count, stride, xofs; |
| unsigned i; |
| |
| FIXME("(%p,%p): stub\n", pStubMsg, pFormat); |
| |
| if (*pFormat != RPC_FC_PP) return 0; |
| pFormat += 2; |
| |
| while (pFormat[0] != RPC_FC_END) { |
| switch (pFormat[0]) { |
| default: |
| FIXME("unknown repeat type %d\n", pFormat[0]); |
| case RPC_FC_NO_REPEAT: |
| rep = 1; |
| stride = 0; |
| ofs = 0; |
| count = 1; |
| xofs = 0; |
| pFormat += 2; |
| break; |
| case RPC_FC_FIXED_REPEAT: |
| rep = *(const WORD*)&pFormat[2]; |
| stride = *(const WORD*)&pFormat[4]; |
| ofs = *(const WORD*)&pFormat[6]; |
| count = *(const WORD*)&pFormat[8]; |
| xofs = 0; |
| pFormat += 10; |
| break; |
| case RPC_FC_VARIABLE_REPEAT: |
| rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; |
| stride = *(const WORD*)&pFormat[2]; |
| ofs = *(const WORD*)&pFormat[4]; |
| count = *(const WORD*)&pFormat[6]; |
| xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; |
| pFormat += 8; |
| break; |
| } |
| /* ofs doesn't seem to matter in this context */ |
| for (i = 0; i < rep; i++) { |
| PFORMAT_STRING info = pFormat; |
| unsigned char *bufbase = Mark + (i * stride); |
| unsigned u; |
| for (u=0; u<count; u++,info+=8) { |
| unsigned char *bufptr = bufbase + *(const SHORT*)&info[2]; |
| PointerMemorySize(pStubMsg, bufptr, info+4); |
| } |
| } |
| pFormat += 8 * count; |
| } |
| |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * EmbeddedPointerFree |
| */ |
| static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned long Offset = pStubMsg->Offset; |
| unsigned ofs, rep, count, stride, xofs; |
| unsigned i; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| if (*pFormat != RPC_FC_PP) return; |
| pFormat += 2; |
| |
| while (pFormat[0] != RPC_FC_END) { |
| switch (pFormat[0]) { |
| default: |
| FIXME("unknown repeat type %d\n", pFormat[0]); |
| case RPC_FC_NO_REPEAT: |
| rep = 1; |
| stride = 0; |
| ofs = 0; |
| count = 1; |
| xofs = 0; |
| pFormat += 2; |
| break; |
| case RPC_FC_FIXED_REPEAT: |
| rep = *(const WORD*)&pFormat[2]; |
| stride = *(const WORD*)&pFormat[4]; |
| ofs = *(const WORD*)&pFormat[6]; |
| count = *(const WORD*)&pFormat[8]; |
| xofs = 0; |
| pFormat += 10; |
| break; |
| case RPC_FC_VARIABLE_REPEAT: |
| rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; |
| stride = *(const WORD*)&pFormat[2]; |
| ofs = *(const WORD*)&pFormat[4]; |
| count = *(const WORD*)&pFormat[6]; |
| xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; |
| pFormat += 8; |
| break; |
| } |
| /* ofs doesn't seem to matter in this context */ |
| for (i = 0; i < rep; i++) { |
| PFORMAT_STRING info = pFormat; |
| unsigned char *membase = pMemory + (i * stride); |
| unsigned u; |
| for (u=0; u<count; u++,info+=8) { |
| unsigned char *memptr = membase + *(const SHORT*)&info[0]; |
| unsigned char *saved_memory = pStubMsg->Memory; |
| |
| pStubMsg->Memory = pMemory; |
| PointerFree(pStubMsg, *(unsigned char**)memptr, info+4); |
| pStubMsg->Memory = saved_memory; |
| } |
| } |
| pFormat += 8 * count; |
| } |
| } |
| |
| /*********************************************************************** |
| * NdrPointerMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned char *Buffer; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| /* incremement the buffer here instead of in PointerMarshall, |
| * as that is used by embedded pointers which already handle the incrementing |
| * the buffer, and shouldn't write any additional pointer data to the wire */ |
| if (*pFormat != RPC_FC_RP) |
| { |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| Buffer = pStubMsg->Buffer; |
| pStubMsg->Buffer += 4; |
| } |
| else |
| Buffer = pStubMsg->Buffer; |
| |
| PointerMarshall(pStubMsg, Buffer, pMemory, pFormat); |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrPointerUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| unsigned char *Buffer; |
| |
| TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| /* incremement the buffer here instead of in PointerUnmarshall, |
| * as that is used by embedded pointers which already handle the incrementing |
| * the buffer, and shouldn't read any additional pointer data from the |
| * buffer */ |
| if (*pFormat != RPC_FC_RP) |
| { |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| Buffer = pStubMsg->Buffer; |
| pStubMsg->Buffer += 4; |
| } |
| else |
| Buffer = pStubMsg->Buffer; |
| |
| PointerUnmarshall(pStubMsg, Buffer, ppMemory, pFormat, fMustAlloc); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrPointerBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| /* incremement the buffer length here instead of in PointerBufferSize, |
| * as that is used by embedded pointers which already handle the buffer |
| * length, and shouldn't write anything more to the wire */ |
| if (*pFormat != RPC_FC_RP) |
| { |
| ALIGN_LENGTH(pStubMsg->BufferLength, 4); |
| pStubMsg->BufferLength += 4; |
| } |
| |
| PointerBufferSize(pStubMsg, pMemory, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrPointerMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| /* unsigned size = *(LPWORD)(pFormat+2); */ |
| FIXME("(%p,%p): stub\n", pStubMsg, pFormat); |
| PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * NdrPointerFree [RPCRT4.@] |
| */ |
| void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| PointerFree(pStubMsg, pMemory, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrSimpleTypeMarshall [RPCRT4.@] |
| */ |
| void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, |
| unsigned char FormatChar ) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrSimpleTypeUnmarshall [RPCRT4.@] |
| */ |
| void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, |
| unsigned char FormatChar ) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrSimpleStructMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned size = *(const WORD*)(pFormat+2); |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); |
| |
| memcpy(pStubMsg->Buffer, pMemory, size); |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += size; |
| |
| if (pFormat[0] != RPC_FC_STRUCT) |
| EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4); |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrSimpleStructUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| unsigned size = *(const WORD*)(pFormat+2); |
| TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); |
| |
| if (fMustAlloc) { |
| *ppMemory = NdrAllocate(pStubMsg, size); |
| memcpy(*ppMemory, pStubMsg->Buffer, size); |
| } else { |
| if (!pStubMsg->IsClient && !*ppMemory) |
| /* for servers, we just point straight into the RPC buffer */ |
| *ppMemory = pStubMsg->Buffer; |
| else |
| /* for clients, memory should be provided by caller */ |
| memcpy(*ppMemory, pStubMsg->Buffer, size); |
| } |
| |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += size; |
| |
| if (pFormat[0] != RPC_FC_STRUCT) |
| EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrSimpleStructBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned size = *(const WORD*)(pFormat+2); |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); |
| |
| pStubMsg->BufferLength += size; |
| if (pFormat[0] != RPC_FC_STRUCT) |
| EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4); |
| } |
| |
| /*********************************************************************** |
| * NdrSimpleStructMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned short size = *(LPWORD)(pFormat+2); |
| |
| TRACE("(%p,%p)\n", pStubMsg, pFormat); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); |
| pStubMsg->MemorySize += size; |
| pStubMsg->Buffer += size; |
| |
| if (pFormat[0] != RPC_FC_STRUCT) |
| EmbeddedPointerMemorySize(pStubMsg, pFormat+4); |
| return size; |
| } |
| |
| /*********************************************************************** |
| * NdrSimpleStructFree [RPCRT4.@] |
| */ |
| void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| if (pFormat[0] != RPC_FC_STRUCT) |
| EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4); |
| } |
| |
| |
| static unsigned long EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| switch (*pFormat) { |
| case RPC_FC_STRUCT: |
| case RPC_FC_PSTRUCT: |
| case RPC_FC_CSTRUCT: |
| case RPC_FC_BOGUS_STRUCT: |
| case RPC_FC_SMFARRAY: |
| case RPC_FC_SMVARRAY: |
| return *(const WORD*)&pFormat[2]; |
| case RPC_FC_USER_MARSHAL: |
| return *(const WORD*)&pFormat[4]; |
| case RPC_FC_NON_ENCAPSULATED_UNION: |
| pFormat += 2; |
| if (pStubMsg->fHasNewCorrDesc) |
| pFormat += 6; |
| else |
| pFormat += 4; |
| |
| pFormat += *(const SHORT*)pFormat; |
| return *(const SHORT*)pFormat; |
| case RPC_FC_IP: |
| return sizeof(void *); |
| default: |
| FIXME("unhandled embedded type %02x\n", *pFormat); |
| } |
| return 0; |
| } |
| |
| |
| static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK]; |
| |
| if (!m) |
| { |
| FIXME("no memorysizer for data type=%02x\n", *pFormat); |
| return 0; |
| } |
| |
| return m(pStubMsg, pFormat); |
| } |
| |
| |
| static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat, |
| PFORMAT_STRING pPointer) |
| { |
| PFORMAT_STRING desc; |
| NDR_MARSHALL m; |
| unsigned long size; |
| |
| while (*pFormat != RPC_FC_END) { |
| switch (*pFormat) { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory); |
| memcpy(pStubMsg->Buffer, pMemory, 1); |
| pStubMsg->Buffer += 1; |
| pMemory += 1; |
| break; |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory); |
| memcpy(pStubMsg->Buffer, pMemory, 2); |
| pStubMsg->Buffer += 2; |
| pMemory += 2; |
| break; |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| case RPC_FC_ENUM32: |
| TRACE("long=%ld <= %p\n", *(DWORD*)pMemory, pMemory); |
| memcpy(pStubMsg->Buffer, pMemory, 4); |
| pStubMsg->Buffer += 4; |
| pMemory += 4; |
| break; |
| case RPC_FC_HYPER: |
| TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); |
| memcpy(pStubMsg->Buffer, pMemory, 8); |
| pStubMsg->Buffer += 8; |
| pMemory += 8; |
| break; |
| case RPC_FC_POINTER: |
| TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory); |
| NdrPointerMarshall(pStubMsg, *(unsigned char**)pMemory, pPointer); |
| pPointer += 4; |
| pMemory += 4; |
| break; |
| case RPC_FC_ALIGNM4: |
| ALIGN_POINTER(pMemory, 4); |
| break; |
| case RPC_FC_ALIGNM8: |
| ALIGN_POINTER(pMemory, 8); |
| break; |
| case RPC_FC_STRUCTPAD1: |
| case RPC_FC_STRUCTPAD2: |
| case RPC_FC_STRUCTPAD3: |
| case RPC_FC_STRUCTPAD4: |
| case RPC_FC_STRUCTPAD5: |
| case RPC_FC_STRUCTPAD6: |
| case RPC_FC_STRUCTPAD7: |
| pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; |
| break; |
| case RPC_FC_EMBEDDED_COMPLEX: |
| pMemory += pFormat[1]; |
| pFormat += 2; |
| desc = pFormat + *(const SHORT*)pFormat; |
| size = EmbeddedComplexSize(pStubMsg, desc); |
| TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory); |
| m = NdrMarshaller[*desc & NDR_TABLE_MASK]; |
| if (m) m(pStubMsg, pMemory, desc); |
| else FIXME("no marshaller for embedded type %02x\n", *desc); |
| pMemory += size; |
| pFormat += 2; |
| continue; |
| case RPC_FC_PAD: |
| break; |
| default: |
| FIXME("unhandled format 0x%02x\n", *pFormat); |
| } |
| pFormat++; |
| } |
| |
| return pMemory; |
| } |
| |
| static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat, |
| PFORMAT_STRING pPointer) |
| { |
| PFORMAT_STRING desc; |
| NDR_UNMARSHALL m; |
| unsigned long size; |
| |
| while (*pFormat != RPC_FC_END) { |
| switch (*pFormat) { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| memcpy(pMemory, pStubMsg->Buffer, 1); |
| TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory); |
| pStubMsg->Buffer += 1; |
| pMemory += 1; |
| break; |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| memcpy(pMemory, pStubMsg->Buffer, 2); |
| TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory); |
| pStubMsg->Buffer += 2; |
| pMemory += 2; |
| break; |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| case RPC_FC_ENUM32: |
| memcpy(pMemory, pStubMsg->Buffer, 4); |
| TRACE("long=%ld => %p\n", *(DWORD*)pMemory, pMemory); |
| pStubMsg->Buffer += 4; |
| pMemory += 4; |
| break; |
| case RPC_FC_HYPER: |
| memcpy(pMemory, pStubMsg->Buffer, 8); |
| TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); |
| pStubMsg->Buffer += 8; |
| pMemory += 8; |
| break; |
| case RPC_FC_POINTER: |
| TRACE("pointer => %p\n", pMemory); |
| NdrPointerUnmarshall(pStubMsg, (unsigned char**)pMemory, pPointer, TRUE); |
| pPointer += 4; |
| pMemory += 4; |
| break; |
| case RPC_FC_ALIGNM4: |
| ALIGN_POINTER(pMemory, 4); |
| break; |
| case RPC_FC_ALIGNM8: |
| ALIGN_POINTER(pMemory, 8); |
| break; |
| case RPC_FC_STRUCTPAD1: |
| case RPC_FC_STRUCTPAD2: |
| case RPC_FC_STRUCTPAD3: |
| case RPC_FC_STRUCTPAD4: |
| case RPC_FC_STRUCTPAD5: |
| case RPC_FC_STRUCTPAD6: |
| case RPC_FC_STRUCTPAD7: |
| pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; |
| break; |
| case RPC_FC_EMBEDDED_COMPLEX: |
| pMemory += pFormat[1]; |
| pFormat += 2; |
| desc = pFormat + *(const SHORT*)pFormat; |
| size = EmbeddedComplexSize(pStubMsg, desc); |
| TRACE("embedded complex (size=%ld) => %p\n", size, pMemory); |
| m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; |
| memset(pMemory, 0, size); /* just in case */ |
| if (m) m(pStubMsg, &pMemory, desc, FALSE); |
| else FIXME("no unmarshaller for embedded type %02x\n", *desc); |
| pMemory += size; |
| pFormat += 2; |
| continue; |
| case RPC_FC_PAD: |
| break; |
| default: |
| FIXME("unhandled format %d\n", *pFormat); |
| } |
| pFormat++; |
| } |
| |
| return pMemory; |
| } |
| |
| static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat, |
| PFORMAT_STRING pPointer) |
| { |
| PFORMAT_STRING desc; |
| NDR_BUFFERSIZE m; |
| unsigned long size; |
| |
| while (*pFormat != RPC_FC_END) { |
| switch (*pFormat) { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| pStubMsg->BufferLength += 1; |
| pMemory += 1; |
| break; |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| pStubMsg->BufferLength += 2; |
| pMemory += 2; |
| break; |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| case RPC_FC_ENUM32: |
| pStubMsg->BufferLength += 4; |
| pMemory += 4; |
| break; |
| case RPC_FC_HYPER: |
| pStubMsg->BufferLength += 8; |
| pMemory += 8; |
| break; |
| case RPC_FC_POINTER: |
| NdrPointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer); |
| pPointer += 4; |
| pMemory += 4; |
| break; |
| case RPC_FC_ALIGNM4: |
| ALIGN_POINTER(pMemory, 4); |
| break; |
| case RPC_FC_ALIGNM8: |
| ALIGN_POINTER(pMemory, 8); |
| break; |
| case RPC_FC_STRUCTPAD1: |
| case RPC_FC_STRUCTPAD2: |
| case RPC_FC_STRUCTPAD3: |
| case RPC_FC_STRUCTPAD4: |
| case RPC_FC_STRUCTPAD5: |
| case RPC_FC_STRUCTPAD6: |
| case RPC_FC_STRUCTPAD7: |
| pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; |
| break; |
| case RPC_FC_EMBEDDED_COMPLEX: |
| pMemory += pFormat[1]; |
| pFormat += 2; |
| desc = pFormat + *(const SHORT*)pFormat; |
| size = EmbeddedComplexSize(pStubMsg, desc); |
| m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; |
| if (m) m(pStubMsg, pMemory, desc); |
| else FIXME("no buffersizer for embedded type %02x\n", *desc); |
| pMemory += size; |
| pFormat += 2; |
| continue; |
| case RPC_FC_PAD: |
| break; |
| default: |
| FIXME("unhandled format 0x%02x\n", *pFormat); |
| } |
| pFormat++; |
| } |
| |
| return pMemory; |
| } |
| |
| static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat, |
| PFORMAT_STRING pPointer) |
| { |
| PFORMAT_STRING desc; |
| NDR_FREE m; |
| unsigned long size; |
| |
| while (*pFormat != RPC_FC_END) { |
| switch (*pFormat) { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| pMemory += 1; |
| break; |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| pMemory += 2; |
| break; |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| case RPC_FC_ENUM32: |
| pMemory += 4; |
| break; |
| case RPC_FC_HYPER: |
| pMemory += 8; |
| break; |
| case RPC_FC_POINTER: |
| NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer); |
| pPointer += 4; |
| pMemory += 4; |
| break; |
| case RPC_FC_ALIGNM4: |
| ALIGN_POINTER(pMemory, 4); |
| break; |
| case RPC_FC_ALIGNM8: |
| ALIGN_POINTER(pMemory, 8); |
| break; |
| case RPC_FC_STRUCTPAD1: |
| case RPC_FC_STRUCTPAD2: |
| case RPC_FC_STRUCTPAD3: |
| case RPC_FC_STRUCTPAD4: |
| case RPC_FC_STRUCTPAD5: |
| case RPC_FC_STRUCTPAD6: |
| case RPC_FC_STRUCTPAD7: |
| pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; |
| break; |
| case RPC_FC_EMBEDDED_COMPLEX: |
| pMemory += pFormat[1]; |
| pFormat += 2; |
| desc = pFormat + *(const SHORT*)pFormat; |
| size = EmbeddedComplexSize(pStubMsg, desc); |
| m = NdrFreer[*desc & NDR_TABLE_MASK]; |
| if (m) m(pStubMsg, pMemory, desc); |
| else FIXME("no freer for embedded type %02x\n", *desc); |
| pMemory += size; |
| pFormat += 2; |
| continue; |
| case RPC_FC_PAD: |
| break; |
| default: |
| FIXME("unhandled format 0x%02x\n", *pFormat); |
| } |
| pFormat++; |
| } |
| |
| return pMemory; |
| } |
| |
| static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| PFORMAT_STRING desc; |
| unsigned long size = 0; |
| |
| while (*pFormat != RPC_FC_END) { |
| switch (*pFormat) { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| size += 1; |
| pStubMsg->Buffer += 1; |
| break; |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| size += 2; |
| pStubMsg->Buffer += 2; |
| break; |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| case RPC_FC_ENUM32: |
| size += 4; |
| pStubMsg->Buffer += 4; |
| break; |
| case RPC_FC_HYPER: |
| size += 8; |
| pStubMsg->Buffer += 8; |
| break; |
| case RPC_FC_POINTER: |
| size += 4; |
| pStubMsg->Buffer += 4; |
| break; |
| case RPC_FC_ALIGNM4: |
| ALIGN_LENGTH(size, 4); |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| break; |
| case RPC_FC_ALIGNM8: |
| ALIGN_LENGTH(size, 8); |
| ALIGN_POINTER(pStubMsg->Buffer, 8); |
| break; |
| case RPC_FC_STRUCTPAD1: |
| case RPC_FC_STRUCTPAD2: |
| case RPC_FC_STRUCTPAD3: |
| case RPC_FC_STRUCTPAD4: |
| case RPC_FC_STRUCTPAD5: |
| case RPC_FC_STRUCTPAD6: |
| case RPC_FC_STRUCTPAD7: |
| size += *pFormat - RPC_FC_STRUCTPAD1 + 1; |
| break; |
| case RPC_FC_EMBEDDED_COMPLEX: |
| size += pFormat[1]; |
| pFormat += 2; |
| desc = pFormat + *(const SHORT*)pFormat; |
| size += EmbeddedComplexMemorySize(pStubMsg, desc); |
| pFormat += 2; |
| continue; |
| case RPC_FC_PAD: |
| break; |
| default: |
| FIXME("unhandled format 0x%02x\n", *pFormat); |
| } |
| pFormat++; |
| } |
| |
| return size; |
| } |
| |
| /*********************************************************************** |
| * NdrComplexStructMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| PFORMAT_STRING conf_array = NULL; |
| PFORMAT_STRING pointer_desc = NULL; |
| unsigned char *OldMemory = pStubMsg->Memory; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); |
| |
| pFormat += 4; |
| if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| |
| pStubMsg->Memory = pMemory; |
| |
| ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc); |
| |
| if (conf_array) |
| NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array); |
| |
| pStubMsg->Memory = OldMemory; |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrComplexStructUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| unsigned size = *(const WORD*)(pFormat+2); |
| PFORMAT_STRING conf_array = NULL; |
| PFORMAT_STRING pointer_desc = NULL; |
| unsigned char *pMemory; |
| |
| TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); |
| |
| if (fMustAlloc || !*ppMemory) |
| { |
| *ppMemory = NdrAllocate(pStubMsg, size); |
| memset(*ppMemory, 0, size); |
| } |
| |
| pFormat += 4; |
| if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| |
| pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc); |
| |
| if (conf_array) |
| NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrComplexStructBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| PFORMAT_STRING conf_array = NULL; |
| PFORMAT_STRING pointer_desc = NULL; |
| unsigned char *OldMemory = pStubMsg->Memory; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); |
| |
| pFormat += 4; |
| if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| |
| pStubMsg->Memory = pMemory; |
| |
| pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc); |
| |
| if (conf_array) |
| NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array); |
| |
| pStubMsg->Memory = OldMemory; |
| } |
| |
| /*********************************************************************** |
| * NdrComplexStructMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned size = *(const WORD*)(pFormat+2); |
| PFORMAT_STRING conf_array = NULL; |
| PFORMAT_STRING pointer_desc = NULL; |
| |
| TRACE("(%p,%p)\n", pStubMsg, pFormat); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); |
| |
| pFormat += 4; |
| if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| |
| ComplexStructMemorySize(pStubMsg, pFormat); |
| |
| if (conf_array) |
| NdrConformantArrayMemorySize(pStubMsg, conf_array); |
| |
| return size; |
| } |
| |
| /*********************************************************************** |
| * NdrComplexStructFree [RPCRT4.@] |
| */ |
| void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| PFORMAT_STRING conf_array = NULL; |
| PFORMAT_STRING pointer_desc = NULL; |
| unsigned char *OldMemory = pStubMsg->Memory; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| pFormat += 4; |
| if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; |
| pFormat += 2; |
| |
| pStubMsg->Memory = pMemory; |
| |
| pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc); |
| |
| if (conf_array) |
| NdrConformantArrayFree(pStubMsg, pMemory, conf_array); |
| |
| pStubMsg->Memory = OldMemory; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantArrayMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| DWORD size = 0, esize = *(const WORD*)(pFormat+2); |
| unsigned char alignment = pFormat[1] + 1; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); |
| |
| WriteConformance(pStubMsg); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| size = safe_multiply(esize, pStubMsg->MaxCount); |
| memcpy(pStubMsg->Buffer, pMemory, size); |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += size; |
| |
| EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantArrayUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| DWORD size, esize = *(const WORD*)(pFormat+2); |
| unsigned char alignment = pFormat[1] + 1; |
| |
| TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); |
| |
| pFormat = ReadConformance(pStubMsg, pFormat+4); |
| |
| size = safe_multiply(esize, pStubMsg->MaxCount); |
| |
| if (fMustAlloc || !*ppMemory) |
| *ppMemory = NdrAllocate(pStubMsg, size); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| memcpy(*ppMemory, pStubMsg->Buffer, size); |
| |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += size; |
| |
| EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantArrayBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| DWORD size, esize = *(const WORD*)(pFormat+2); |
| unsigned char alignment = pFormat[1] + 1; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); |
| |
| SizeConformance(pStubMsg); |
| |
| ALIGN_LENGTH(pStubMsg->BufferLength, alignment); |
| |
| size = safe_multiply(esize, pStubMsg->MaxCount); |
| /* conformance value plus array */ |
| pStubMsg->BufferLength += size; |
| |
| EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrConformantArrayMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| DWORD size = 0, esize = *(const WORD*)(pFormat+2); |
| unsigned char alignment = pFormat[1] + 1; |
| |
| TRACE("(%p,%p)\n", pStubMsg, pFormat); |
| if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); |
| |
| pFormat = ReadConformance(pStubMsg, pFormat+4); |
| size = safe_multiply(esize, pStubMsg->MaxCount); |
| pStubMsg->MemorySize += size; |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += size; |
| |
| EmbeddedPointerMemorySize(pStubMsg, pFormat); |
| |
| return pStubMsg->MemorySize; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantArrayFree [RPCRT4.@] |
| */ |
| void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); |
| |
| EmbeddedPointerFree(pStubMsg, pMemory, pFormat); |
| } |
| |
| |
| /*********************************************************************** |
| * NdrConformantVaryingArrayMarshall [RPCRT4.@] |
| */ |
| unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char* pMemory, |
| PFORMAT_STRING pFormat ) |
| { |
| ULONG bufsize; |
| unsigned char alignment = pFormat[1] + 1; |
| DWORD esize = *(const WORD*)(pFormat+2); |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| if (pFormat[0] != RPC_FC_CVARRAY) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); |
| pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); |
| |
| WriteConformance(pStubMsg); |
| WriteVariance(pStubMsg); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| bufsize = safe_multiply(esize, pStubMsg->ActualCount); |
| |
| memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize); |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += bufsize; |
| |
| EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| |
| /*********************************************************************** |
| * NdrConformantVaryingArrayUnmarshall [RPCRT4.@] |
| */ |
| unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char** ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc ) |
| { |
| ULONG bufsize, memsize; |
| unsigned char alignment = pFormat[1] + 1; |
| DWORD esize = *(const WORD*)(pFormat+2); |
| |
| TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| if (pFormat[0] != RPC_FC_CVARRAY) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| pFormat = ReadConformance(pStubMsg, pFormat+4); |
| pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| bufsize = safe_multiply(esize, pStubMsg->ActualCount); |
| memsize = safe_multiply(esize, pStubMsg->MaxCount); |
| |
| if (!*ppMemory || fMustAlloc) |
| *ppMemory = NdrAllocate(pStubMsg, memsize); |
| memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, bufsize); |
| pStubMsg->Buffer += bufsize; |
| |
| EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| return NULL; |
| } |
| |
| |
| /*********************************************************************** |
| * NdrConformantVaryingArrayFree [RPCRT4.@] |
| */ |
| void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char* pMemory, |
| PFORMAT_STRING pFormat ) |
| { |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| if (pFormat[0] != RPC_FC_CVARRAY) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); |
| pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); |
| |
| EmbeddedPointerFree(pStubMsg, pMemory, pFormat); |
| } |
| |
| |
| /*********************************************************************** |
| * NdrConformantVaryingArrayBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char* pMemory, PFORMAT_STRING pFormat ) |
| { |
| unsigned char alignment = pFormat[1] + 1; |
| DWORD esize = *(const WORD*)(pFormat+2); |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| if (pFormat[0] != RPC_FC_CVARRAY) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| /* compute size */ |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); |
| /* compute length */ |
| pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); |
| |
| SizeConformance(pStubMsg); |
| SizeVariance(pStubMsg); |
| |
| ALIGN_LENGTH(pStubMsg->BufferLength, alignment); |
| |
| pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount); |
| |
| EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); |
| } |
| |
| |
| /*********************************************************************** |
| * NdrConformantVaryingArrayMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat ) |
| { |
| FIXME( "stub\n" ); |
| return 0; |
| } |
| |
| |
| /*********************************************************************** |
| * NdrComplexArrayMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| ULONG i, count, def; |
| BOOL variance_present; |
| unsigned char alignment; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| if (pFormat[0] != RPC_FC_BOGUS_ARRAY) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| alignment = pFormat[1] + 1; |
| |
| def = *(const WORD*)&pFormat[2]; |
| pFormat += 4; |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); |
| TRACE("conformance = %ld\n", pStubMsg->MaxCount); |
| |
| variance_present = IsConformanceOrVariancePresent(pFormat); |
| pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); |
| TRACE("variance = %ld\n", pStubMsg->ActualCount); |
| |
| WriteConformance(pStubMsg); |
| if (variance_present) |
| WriteVariance(pStubMsg); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| count = pStubMsg->ActualCount; |
| for (i = 0; i < count; i++) |
| pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL); |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrComplexArrayUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| ULONG i, count, esize, memsize; |
| unsigned char alignment; |
| unsigned char *pMemory; |
| unsigned char *Buffer; |
| |
| TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| if (pFormat[0] != RPC_FC_BOGUS_ARRAY) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| alignment = pFormat[1] + 1; |
| |
| pFormat += 4; |
| |
| pFormat = ReadConformance(pStubMsg, pFormat); |
| pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); |
| |
| Buffer = pStubMsg->Buffer; |
| pStubMsg->MemorySize = 0; |
| esize = ComplexStructMemorySize(pStubMsg, pFormat); |
| pStubMsg->Buffer = Buffer; |
| |
| /* do multiply here instead of inside if block to verify MaxCount */ |
| memsize = safe_multiply(esize, pStubMsg->MaxCount); |
| if (fMustAlloc || !*ppMemory) |
| { |
| *ppMemory = NdrAllocate(pStubMsg, memsize); |
| memset(*ppMemory, 0, memsize); |
| } |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| pMemory = *ppMemory; |
| count = pStubMsg->ActualCount; |
| for (i = 0; i < count; i++) |
| pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrComplexArrayBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| ULONG i, count, def; |
| unsigned char alignment; |
| BOOL variance_present; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| if (pFormat[0] != RPC_FC_BOGUS_ARRAY) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| alignment = pFormat[1] + 1; |
| |
| def = *(const WORD*)&pFormat[2]; |
| pFormat += 4; |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); |
| TRACE("conformance = %ld\n", pStubMsg->MaxCount); |
| SizeConformance(pStubMsg); |
| |
| variance_present = IsConformanceOrVariancePresent(pFormat); |
| pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); |
| TRACE("variance = %ld\n", pStubMsg->ActualCount); |
| |
| if (variance_present) |
| SizeVariance(pStubMsg); |
| |
| ALIGN_LENGTH(pStubMsg->BufferLength, alignment); |
| |
| count = pStubMsg->ActualCount; |
| for (i = 0; i < count; i++) |
| pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL); |
| } |
| |
| /*********************************************************************** |
| * NdrComplexArrayMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| ULONG i, count, esize; |
| unsigned char alignment; |
| unsigned char *Buffer; |
| unsigned long SavedMemorySize; |
| unsigned long MemorySize; |
| |
| TRACE("(%p,%p)\n", pStubMsg, pFormat); |
| |
| if (pFormat[0] != RPC_FC_BOGUS_ARRAY) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return 0; |
| } |
| |
| alignment = pFormat[1] + 1; |
| |
| pFormat += 4; |
| |
| pFormat = ReadConformance(pStubMsg, pFormat); |
| pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| SavedMemorySize = pStubMsg->MemorySize; |
| |
| Buffer = pStubMsg->Buffer; |
| pStubMsg->MemorySize = 0; |
| esize = ComplexStructMemorySize(pStubMsg, pFormat); |
| pStubMsg->Buffer = Buffer; |
| |
| MemorySize = safe_multiply(pStubMsg->MaxCount, esize); |
| |
| count = pStubMsg->ActualCount; |
| for (i = 0; i < count; i++) |
| ComplexStructMemorySize(pStubMsg, pFormat); |
| |
| pStubMsg->MemorySize = SavedMemorySize; |
| |
| pStubMsg->MemorySize += MemorySize; |
| return MemorySize; |
| } |
| |
| /*********************************************************************** |
| * NdrComplexArrayFree [RPCRT4.@] |
| */ |
| void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| ULONG i, count, def; |
| |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| |
| if (pFormat[0] != RPC_FC_BOGUS_ARRAY) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| def = *(const WORD*)&pFormat[2]; |
| pFormat += 4; |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); |
| TRACE("conformance = %ld\n", pStubMsg->MaxCount); |
| |
| pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); |
| TRACE("variance = %ld\n", pStubMsg->ActualCount); |
| |
| count = pStubMsg->ActualCount; |
| for (i = 0; i < count; i++) |
| pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL); |
| } |
| |
| static unsigned long UserMarshalFlags(PMIDL_STUB_MESSAGE pStubMsg) |
| { |
| return MAKELONG(pStubMsg->dwDestContext, |
| pStubMsg->RpcMsg->DataRepresentation); |
| } |
| |
| #define USER_MARSHAL_PTR_PREFIX \ |
| ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \ |
| ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) ) |
| |
| /*********************************************************************** |
| * NdrUserMarshalMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned flags = pFormat[1]; |
| unsigned index = *(const WORD*)&pFormat[2]; |
| unsigned long uflag = UserMarshalFlags(pStubMsg); |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| TRACE("index=%d\n", index); |
| |
| if (flags & USER_MARSHAL_POINTER) |
| { |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX); |
| pStubMsg->Buffer += 4; |
| ALIGN_POINTER(pStubMsg->Buffer, 8); |
| } |
| else |
| ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); |
| |
| pStubMsg->Buffer = |
| pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall( |
| &uflag, pStubMsg->Buffer, pMemory); |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrUserMarshalUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| unsigned flags = pFormat[1]; |
| unsigned index = *(const WORD*)&pFormat[2]; |
| DWORD memsize = *(const WORD*)&pFormat[4]; |
| unsigned long uflag = UserMarshalFlags(pStubMsg); |
| TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| TRACE("index=%d\n", index); |
| |
| if (flags & USER_MARSHAL_POINTER) |
| { |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| /* skip pointer prefix */ |
| pStubMsg->Buffer += 4; |
| ALIGN_POINTER(pStubMsg->Buffer, 8); |
| } |
| else |
| ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); |
| |
| if (fMustAlloc || !*ppMemory) |
| *ppMemory = NdrAllocate(pStubMsg, memsize); |
| |
| pStubMsg->Buffer = |
| pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall( |
| &uflag, pStubMsg->Buffer, *ppMemory); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrUserMarshalBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned flags = pFormat[1]; |
| unsigned index = *(const WORD*)&pFormat[2]; |
| DWORD bufsize = *(const WORD*)&pFormat[6]; |
| unsigned long uflag = UserMarshalFlags(pStubMsg); |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| TRACE("index=%d\n", index); |
| |
| if (flags & USER_MARSHAL_POINTER) |
| { |
| ALIGN_LENGTH(pStubMsg->BufferLength, 4); |
| /* skip pointer prefix */ |
| pStubMsg->BufferLength += 4; |
| ALIGN_LENGTH(pStubMsg->BufferLength, 8); |
| } |
| else |
| ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1); |
| |
| if (bufsize) { |
| TRACE("size=%ld\n", bufsize); |
| pStubMsg->BufferLength += bufsize; |
| return; |
| } |
| |
| pStubMsg->BufferLength = |
| pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize( |
| &uflag, pStubMsg->BufferLength, pMemory); |
| } |
| |
| /*********************************************************************** |
| * NdrUserMarshalMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned flags = pFormat[1]; |
| unsigned index = *(const WORD*)&pFormat[2]; |
| DWORD memsize = *(const WORD*)&pFormat[4]; |
| DWORD bufsize = *(const WORD*)&pFormat[6]; |
| |
| TRACE("(%p,%p)\n", pStubMsg, pFormat); |
| TRACE("index=%d\n", index); |
| |
| pStubMsg->MemorySize += memsize; |
| |
| if (flags & USER_MARSHAL_POINTER) |
| { |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| /* skip pointer prefix */ |
| pStubMsg->Buffer += 4; |
| ALIGN_POINTER(pStubMsg->Buffer, 8); |
| } |
| else |
| ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); |
| |
| pStubMsg->Buffer += bufsize; |
| |
| return pStubMsg->MemorySize; |
| } |
| |
| /*********************************************************************** |
| * NdrUserMarshalFree [RPCRT4.@] |
| */ |
| void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| /* unsigned flags = pFormat[1]; */ |
| unsigned index = *(const WORD*)&pFormat[2]; |
| unsigned long uflag = UserMarshalFlags(pStubMsg); |
| TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); |
| TRACE("index=%d\n", index); |
| |
| pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree( |
| &uflag, pMemory); |
| } |
| |
| /*********************************************************************** |
| * NdrClearOutParameters [RPCRT4.@] |
| */ |
| void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat, |
| void *ArgAddr) |
| { |
| FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr); |
| } |
| |
| /*********************************************************************** |
| * NdrConvert [RPCRT4.@] |
| */ |
| void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ) |
| { |
| FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat); |
| /* FIXME: since this stub doesn't do any converting, the proper behavior |
| is to raise an exception */ |
| } |
| |
| /*********************************************************************** |
| * NdrConvert2 [RPCRT4.@] |
| */ |
| void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams ) |
| { |
| FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n", |
| pStubMsg, pFormat, NumberParams); |
| /* FIXME: since this stub doesn't do any converting, the proper behavior |
| is to raise an exception */ |
| } |
| |
| typedef struct _NDR_CSTRUCT_FORMAT |
| { |
| unsigned char type; |
| unsigned char alignment; |
| unsigned short memory_size; |
| short offset_to_array_description; |
| } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT; |
| |
| /*********************************************************************** |
| * NdrConformantStructMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat; |
| PFORMAT_STRING pCArrayFormat; |
| ULONG esize, bufsize; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| pFormat += sizeof(NDR_CSTRUCT_FORMAT); |
| if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) |
| { |
| ERR("invalid format type %x\n", pCStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description + |
| pCStructFormat->offset_to_array_description; |
| if (*pCArrayFormat != RPC_FC_CARRAY) |
| { |
| ERR("invalid array format type %x\n", pCStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| esize = *(const WORD*)(pCArrayFormat+2); |
| |
| ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, |
| pCArrayFormat + 4, 0); |
| |
| WriteConformance(pStubMsg); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1); |
| |
| TRACE("memory_size = %d\n", pCStructFormat->memory_size); |
| |
| bufsize = safe_multiply(esize, pStubMsg->MaxCount); |
| /* copy constant sized part of struct */ |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size + bufsize); |
| pStubMsg->Buffer += pCStructFormat->memory_size + bufsize; |
| |
| if (pCStructFormat->type == RPC_FC_CPSTRUCT) |
| EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantStructUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat; |
| PFORMAT_STRING pCArrayFormat; |
| ULONG esize, bufsize; |
| |
| TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| pFormat += sizeof(NDR_CSTRUCT_FORMAT); |
| if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) |
| { |
| ERR("invalid format type %x\n", pCStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description + |
| pCStructFormat->offset_to_array_description; |
| if (*pCArrayFormat != RPC_FC_CARRAY) |
| { |
| ERR("invalid array format type %x\n", pCStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| esize = *(const WORD*)(pCArrayFormat+2); |
| |
| pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1); |
| |
| TRACE("memory_size = %d\n", pCStructFormat->memory_size); |
| |
| bufsize = safe_multiply(esize, pStubMsg->MaxCount); |
| /* work out how much memory to allocate if we need to do so */ |
| if (!*ppMemory || fMustAlloc) |
| { |
| SIZE_T size = pCStructFormat->memory_size + bufsize; |
| *ppMemory = NdrAllocate(pStubMsg, size); |
| } |
| |
| /* now copy the data */ |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| memcpy(*ppMemory, pStubMsg->Buffer, pCStructFormat->memory_size + bufsize); |
| pStubMsg->Buffer += pCStructFormat->memory_size + bufsize; |
| |
| if (pCStructFormat->type == RPC_FC_CPSTRUCT) |
| EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantStructBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat; |
| PFORMAT_STRING pCArrayFormat; |
| ULONG esize; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| pFormat += sizeof(NDR_CSTRUCT_FORMAT); |
| if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) |
| { |
| ERR("invalid format type %x\n", pCStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description + |
| pCStructFormat->offset_to_array_description; |
| if (*pCArrayFormat != RPC_FC_CARRAY) |
| { |
| ERR("invalid array format type %x\n", pCStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| esize = *(const WORD*)(pCArrayFormat+2); |
| |
| pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0); |
| SizeConformance(pStubMsg); |
| |
| ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1); |
| |
| TRACE("memory_size = %d\n", pCStructFormat->memory_size); |
| |
| pStubMsg->BufferLength += pCStructFormat->memory_size + |
| safe_multiply(pStubMsg->MaxCount, esize); |
| |
| if (pCStructFormat->type == RPC_FC_CPSTRUCT) |
| EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrConformantStructMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantStructFree [RPCRT4.@] |
| */ |
| void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrConformantVaryingStructMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat; |
| PFORMAT_STRING pCVArrayFormat; |
| ULONG esize, bufsize; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| pFormat += sizeof(NDR_CVSTRUCT_FORMAT); |
| if (pCVStructFormat->type != RPC_FC_CVSTRUCT) |
| { |
| ERR("invalid format type %x\n", pCVStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description + |
| pCVStructFormat->offset_to_array_description; |
| switch (*pCVArrayFormat) |
| { |
| case RPC_FC_CVARRAY: |
| esize = *(const WORD*)(pCVArrayFormat+2); |
| |
| pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat + 4, 0); |
| pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat, 0); |
| break; |
| case RPC_FC_C_CSTRING: |
| TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); |
| pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; |
| esize = sizeof(char); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat + 2, 0); |
| else |
| pStubMsg->MaxCount = pStubMsg->ActualCount; |
| break; |
| case RPC_FC_C_WSTRING: |
| TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); |
| pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; |
| esize = sizeof(WCHAR); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat + 2, 0); |
| else |
| pStubMsg->MaxCount = pStubMsg->ActualCount; |
| break; |
| default: |
| ERR("invalid array format type %x\n", *pCVArrayFormat); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| WriteConformance(pStubMsg); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); |
| |
| TRACE("memory_size = %d\n", pCVStructFormat->memory_size); |
| |
| /* write constant sized part */ |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| memcpy(pStubMsg->Buffer, pMemory, pCVStructFormat->memory_size); |
| pStubMsg->Buffer += pCVStructFormat->memory_size; |
| |
| WriteVariance(pStubMsg); |
| |
| bufsize = safe_multiply(esize, pStubMsg->ActualCount); |
| |
| /* write array part */ |
| memcpy(pStubMsg->Buffer, pMemory + pCVStructFormat->memory_size, bufsize); |
| pStubMsg->Buffer += bufsize; |
| |
| EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantVaryingStructUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat; |
| PFORMAT_STRING pCVArrayFormat; |
| ULONG esize, bufsize; |
| unsigned char cvarray_type; |
| |
| TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| pFormat += sizeof(NDR_CVSTRUCT_FORMAT); |
| if (pCVStructFormat->type != RPC_FC_CVSTRUCT) |
| { |
| ERR("invalid format type %x\n", pCVStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description + |
| pCVStructFormat->offset_to_array_description; |
| cvarray_type = *pCVArrayFormat; |
| switch (cvarray_type) |
| { |
| case RPC_FC_CVARRAY: |
| esize = *(const WORD*)(pCVArrayFormat+2); |
| pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); |
| break; |
| case RPC_FC_C_CSTRING: |
| esize = sizeof(char); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); |
| else |
| pCVArrayFormat = ReadConformance(pStubMsg, NULL); |
| break; |
| case RPC_FC_C_WSTRING: |
| esize = sizeof(WCHAR); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); |
| else |
| pCVArrayFormat = ReadConformance(pStubMsg, NULL); |
| break; |
| default: |
| ERR("invalid array format type %x\n", *pCVArrayFormat); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); |
| |
| TRACE("memory_size = %d\n", pCVStructFormat->memory_size); |
| |
| /* work out how much memory to allocate if we need to do so */ |
| if (!*ppMemory || fMustAlloc) |
| { |
| SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); |
| *ppMemory = NdrAllocate(pStubMsg, size); |
| } |
| |
| /* copy the constant data */ |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| memcpy(*ppMemory, pStubMsg->Buffer, pCVStructFormat->memory_size); |
| pStubMsg->Buffer += pCVStructFormat->memory_size; |
| |
| pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); |
| |
| bufsize = safe_multiply(esize, pStubMsg->ActualCount); |
| |
| if ((cvarray_type == RPC_FC_C_CSTRING) || |
| (cvarray_type == RPC_FC_C_WSTRING)) |
| { |
| ULONG i; |
| /* strings must always have null terminating bytes */ |
| if (bufsize < esize) |
| { |
| ERR("invalid string length of %ld\n", pStubMsg->ActualCount); |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| return NULL; |
| } |
| for (i = bufsize - esize; i < bufsize; i++) |
| if (pStubMsg->Buffer[i] != 0) |
| { |
| ERR("string not null-terminated at byte position %ld, data is 0x%x\n", |
| i, pStubMsg->Buffer[i]); |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| return NULL; |
| } |
| } |
| |
| /* copy the array data */ |
| memcpy(*ppMemory + pCVStructFormat->memory_size, pStubMsg->Buffer, |
| bufsize); |
| pStubMsg->Buffer += bufsize; |
| |
| if (cvarray_type == RPC_FC_C_CSTRING) |
| TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size))); |
| else if (cvarray_type == RPC_FC_C_WSTRING) |
| TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size))); |
| |
| EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantVaryingStructBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat; |
| PFORMAT_STRING pCVArrayFormat; |
| ULONG esize; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| pFormat += sizeof(NDR_CVSTRUCT_FORMAT); |
| if (pCVStructFormat->type != RPC_FC_CVSTRUCT) |
| { |
| ERR("invalid format type %x\n", pCVStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description + |
| pCVStructFormat->offset_to_array_description; |
| switch (*pCVArrayFormat) |
| { |
| case RPC_FC_CVARRAY: |
| esize = *(const WORD*)(pCVArrayFormat+2); |
| |
| pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat + 4, 0); |
| pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat, 0); |
| break; |
| case RPC_FC_C_CSTRING: |
| TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); |
| pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; |
| esize = sizeof(char); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat + 2, 0); |
| else |
| pStubMsg->MaxCount = pStubMsg->ActualCount; |
| break; |
| case RPC_FC_C_WSTRING: |
| TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); |
| pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; |
| esize = sizeof(WCHAR); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat + 2, 0); |
| else |
| pStubMsg->MaxCount = pStubMsg->ActualCount; |
| break; |
| default: |
| ERR("invalid array format type %x\n", *pCVArrayFormat); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| SizeConformance(pStubMsg); |
| |
| ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1); |
| |
| TRACE("memory_size = %d\n", pCVStructFormat->memory_size); |
| |
| pStubMsg->BufferLength += pCVStructFormat->memory_size; |
| SizeVariance(pStubMsg); |
| pStubMsg->BufferLength += safe_multiply(pStubMsg->MaxCount, esize); |
| |
| EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrConformantVaryingStructMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat; |
| PFORMAT_STRING pCVArrayFormat; |
| ULONG esize; |
| unsigned char cvarray_type; |
| |
| TRACE("(%p, %p)\n", pStubMsg, pFormat); |
| |
| pFormat += sizeof(NDR_CVSTRUCT_FORMAT); |
| if (pCVStructFormat->type != RPC_FC_CVSTRUCT) |
| { |
| ERR("invalid format type %x\n", pCVStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return 0; |
| } |
| |
| pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description + |
| pCVStructFormat->offset_to_array_description; |
| cvarray_type = *pCVArrayFormat; |
| switch (cvarray_type) |
| { |
| case RPC_FC_CVARRAY: |
| esize = *(const WORD*)(pCVArrayFormat+2); |
| pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); |
| break; |
| case RPC_FC_C_CSTRING: |
| esize = sizeof(char); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); |
| else |
| pCVArrayFormat = ReadConformance(pStubMsg, NULL); |
| break; |
| case RPC_FC_C_WSTRING: |
| esize = sizeof(WCHAR); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); |
| else |
| pCVArrayFormat = ReadConformance(pStubMsg, NULL); |
| break; |
| default: |
| ERR("invalid array format type %x\n", *pCVArrayFormat); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return 0; |
| } |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); |
| |
| TRACE("memory_size = %d\n", pCVStructFormat->memory_size); |
| |
| pStubMsg->Buffer += pCVStructFormat->memory_size; |
| pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); |
| pStubMsg->Buffer += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->ActualCount); |
| |
| pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); |
| |
| EmbeddedPointerMemorySize(pStubMsg, pFormat); |
| |
| return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize; |
| } |
| |
| /*********************************************************************** |
| * NdrConformantVaryingStructFree [RPCRT4.@] |
| */ |
| void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat; |
| PFORMAT_STRING pCVArrayFormat; |
| ULONG esize; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| pFormat += sizeof(NDR_CVSTRUCT_FORMAT); |
| if (pCVStructFormat->type != RPC_FC_CVSTRUCT) |
| { |
| ERR("invalid format type %x\n", pCVStructFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description + |
| pCVStructFormat->offset_to_array_description; |
| switch (*pCVArrayFormat) |
| { |
| case RPC_FC_CVARRAY: |
| esize = *(const WORD*)(pCVArrayFormat+2); |
| |
| pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat + 4, 0); |
| pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat, 0); |
| break; |
| case RPC_FC_C_CSTRING: |
| TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); |
| pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; |
| esize = sizeof(char); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat + 2, 0); |
| else |
| pStubMsg->MaxCount = pStubMsg->ActualCount; |
| break; |
| case RPC_FC_C_WSTRING: |
| TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); |
| pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; |
| esize = sizeof(WCHAR); |
| if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) |
| pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, |
| pCVArrayFormat + 2, 0); |
| else |
| pStubMsg->MaxCount = pStubMsg->ActualCount; |
| break; |
| default: |
| ERR("invalid array format type %x\n", *pCVArrayFormat); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| TRACE("memory_size = %d\n", pCVStructFormat->memory_size); |
| |
| EmbeddedPointerFree(pStubMsg, pMemory, pFormat); |
| } |
| |
| typedef struct |
| { |
| unsigned char type; |
| unsigned char alignment; |
| unsigned short total_size; |
| } NDR_SMFARRAY_FORMAT; |
| |
| typedef struct |
| { |
| unsigned char type; |
| unsigned char alignment; |
| unsigned long total_size; |
| } NDR_LGFARRAY_FORMAT; |
| |
| /*********************************************************************** |
| * NdrFixedArrayMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; |
| unsigned long total_size; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && |
| (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) |
| { |
| ERR("invalid format type %x\n", pSmFArrayFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); |
| |
| if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) |
| { |
| total_size = pSmFArrayFormat->total_size; |
| pFormat = (unsigned char *)(pSmFArrayFormat + 1); |
| } |
| else |
| { |
| const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; |
| total_size = pLgFArrayFormat->total_size; |
| pFormat = (unsigned char *)(pLgFArrayFormat + 1); |
| } |
| |
| memcpy(pStubMsg->Buffer, pMemory, total_size); |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += total_size; |
| |
| pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrFixedArrayUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; |
| unsigned long total_size; |
| |
| TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && |
| (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) |
| { |
| ERR("invalid format type %x\n", pSmFArrayFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); |
| |
| if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) |
| { |
| total_size = pSmFArrayFormat->total_size; |
| pFormat = (unsigned char *)(pSmFArrayFormat + 1); |
| } |
| else |
| { |
| const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; |
| total_size = pLgFArrayFormat->total_size; |
| pFormat = (unsigned char *)(pLgFArrayFormat + 1); |
| } |
| |
| if (fMustAlloc || !*ppMemory) |
| *ppMemory = NdrAllocate(pStubMsg, total_size); |
| memcpy(*ppMemory, pStubMsg->Buffer, total_size); |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += total_size; |
| |
| pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrFixedArrayBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; |
| unsigned long total_size; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && |
| (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) |
| { |
| ERR("invalid format type %x\n", pSmFArrayFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1); |
| |
| if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) |
| { |
| total_size = pSmFArrayFormat->total_size; |
| pFormat = (unsigned char *)(pSmFArrayFormat + 1); |
| } |
| else |
| { |
| const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; |
| total_size = pLgFArrayFormat->total_size; |
| pFormat = (unsigned char *)(pLgFArrayFormat + 1); |
| } |
| pStubMsg->BufferLength += total_size; |
| |
| EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrFixedArrayMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; |
| unsigned long total_size; |
| |
| TRACE("(%p, %p)\n", pStubMsg, pFormat); |
| |
| if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && |
| (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) |
| { |
| ERR("invalid format type %x\n", pSmFArrayFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return 0; |
| } |
| |
| ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); |
| |
| if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) |
| { |
| total_size = pSmFArrayFormat->total_size; |
| pFormat = (unsigned char *)(pSmFArrayFormat + 1); |
| } |
| else |
| { |
| const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; |
| total_size = pLgFArrayFormat->total_size; |
| pFormat = (unsigned char *)(pLgFArrayFormat + 1); |
| } |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += total_size; |
| pStubMsg->MemorySize += total_size; |
| |
| EmbeddedPointerMemorySize(pStubMsg, pFormat); |
| |
| return total_size; |
| } |
| |
| /*********************************************************************** |
| * NdrFixedArrayFree [RPCRT4.@] |
| */ |
| void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && |
| (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) |
| { |
| ERR("invalid format type %x\n", pSmFArrayFormat->type); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) |
| pFormat = (unsigned char *)(pSmFArrayFormat + 1); |
| else |
| { |
| const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; |
| pFormat = (unsigned char *)(pLgFArrayFormat + 1); |
| } |
| |
| EmbeddedPointerFree(pStubMsg, pMemory, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrVaryingArrayMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned char alignment; |
| DWORD elements, esize; |
| ULONG bufsize; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| if ((pFormat[0] != RPC_FC_SMVARRAY) && |
| (pFormat[0] != RPC_FC_LGVARRAY)) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| alignment = pFormat[1] + 1; |
| |
| if (pFormat[0] == RPC_FC_SMVARRAY) |
| { |
| pFormat += 2; |
| pFormat += sizeof(WORD); |
| elements = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| } |
| else |
| { |
| pFormat += 2; |
| pFormat += sizeof(DWORD); |
| elements = *(const DWORD*)pFormat; |
| pFormat += sizeof(DWORD); |
| } |
| |
| esize = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| |
| pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); |
| if ((pStubMsg->ActualCount > elements) || |
| (pStubMsg->ActualCount + pStubMsg->Offset > elements)) |
| { |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| return NULL; |
| } |
| |
| WriteVariance(pStubMsg); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| bufsize = safe_multiply(esize, pStubMsg->ActualCount); |
| memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize); |
| pStubMsg->BufferMark = pStubMsg->Buffer; |
| pStubMsg->Buffer += bufsize; |
| |
| EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrVaryingArrayUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| unsigned char alignment; |
| DWORD size, elements, esize; |
| ULONG bufsize; |
| |
| TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| if ((pFormat[0] != RPC_FC_SMVARRAY) && |
| (pFormat[0] != RPC_FC_LGVARRAY)) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return NULL; |
| } |
| |
| alignment = pFormat[1] + 1; |
| |
| if (pFormat[0] == RPC_FC_SMVARRAY) |
| { |
| pFormat += 2; |
| size = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| elements = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| } |
| else |
| { |
| pFormat += 2; |
| size = *(const DWORD*)pFormat; |
| pFormat += sizeof(DWORD); |
| elements = *(const DWORD*)pFormat; |
| pFormat += sizeof(DWORD); |
| } |
| |
| esize = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| |
| pFormat = ReadVariance(pStubMsg, pFormat, elements); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| bufsize = safe_multiply(esize, pStubMsg->ActualCount); |
| |
| if (!*ppMemory || fMustAlloc) |
| *ppMemory = NdrAllocate(pStubMsg, size); |
| memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, bufsize); |
| pStubMsg->Buffer += bufsize; |
| |
| EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrVaryingArrayBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned char alignment; |
| DWORD elements, esize; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| if ((pFormat[0] != RPC_FC_SMVARRAY) && |
| (pFormat[0] != RPC_FC_LGVARRAY)) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| alignment = pFormat[1] + 1; |
| |
| if (pFormat[0] == RPC_FC_SMVARRAY) |
| { |
| pFormat += 2; |
| pFormat += sizeof(WORD); |
| elements = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| } |
| else |
| { |
| pFormat += 2; |
| pFormat += sizeof(DWORD); |
| elements = *(const DWORD*)pFormat; |
| pFormat += sizeof(DWORD); |
| } |
| |
| esize = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| |
| pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); |
| if ((pStubMsg->ActualCount > elements) || |
| (pStubMsg->ActualCount + pStubMsg->Offset > elements)) |
| { |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| return; |
| } |
| |
| SizeVariance(pStubMsg); |
| |
| ALIGN_LENGTH(pStubMsg->BufferLength, alignment); |
| |
| pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount); |
| |
| EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrVaryingArrayMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned char alignment; |
| DWORD size, elements, esize; |
| |
| TRACE("(%p, %p)\n", pStubMsg, pFormat); |
| |
| if ((pFormat[0] != RPC_FC_SMVARRAY) && |
| (pFormat[0] != RPC_FC_LGVARRAY)) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return 0; |
| } |
| |
| alignment = pFormat[1] + 1; |
| |
| if (pFormat[0] == RPC_FC_SMVARRAY) |
| { |
| pFormat += 2; |
| size = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| elements = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| } |
| else |
| { |
| pFormat += 2; |
| size = *(const DWORD*)pFormat; |
| pFormat += sizeof(DWORD); |
| elements = *(const DWORD*)pFormat; |
| pFormat += sizeof(DWORD); |
| } |
| |
| esize = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| |
| pFormat = ReadVariance(pStubMsg, pFormat, elements); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, alignment); |
| |
| pStubMsg->Buffer += safe_multiply(esize, pStubMsg->ActualCount); |
| pStubMsg->MemorySize += size; |
| |
| EmbeddedPointerMemorySize(pStubMsg, pFormat); |
| |
| return pStubMsg->MemorySize; |
| } |
| |
| /*********************************************************************** |
| * NdrVaryingArrayFree [RPCRT4.@] |
| */ |
| void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned char alignment; |
| DWORD elements; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| |
| if ((pFormat[0] != RPC_FC_SMVARRAY) && |
| (pFormat[0] != RPC_FC_LGVARRAY)) |
| { |
| ERR("invalid format type %x\n", pFormat[0]); |
| RpcRaiseException(RPC_S_INTERNAL_ERROR); |
| return; |
| } |
| |
| alignment = pFormat[1] + 1; |
| |
| if (pFormat[0] == RPC_FC_SMVARRAY) |
| { |
| pFormat += 2; |
| pFormat += sizeof(WORD); |
| elements = *(const WORD*)pFormat; |
| pFormat += sizeof(WORD); |
| } |
| else |
| { |
| pFormat += 2; |
| pFormat += sizeof(DWORD); |
| elements = *(const DWORD*)pFormat; |
| pFormat += sizeof(DWORD); |
| } |
| |
| pFormat += sizeof(WORD); |
| |
| pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); |
| if ((pStubMsg->ActualCount > elements) || |
| (pStubMsg->ActualCount + pStubMsg->Offset > elements)) |
| { |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| return; |
| } |
| |
| EmbeddedPointerFree(pStubMsg, pMemory, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrEncapsulatedUnionMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrEncapsulatedUnionUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| FIXME("stub\n"); |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrEncapsulatedUnionBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrEncapsulatedUnionMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * NdrEncapsulatedUnionFree [RPCRT4.@] |
| */ |
| void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| } |
| |
| static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned long discriminant, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned short num_arms, arm, type; |
| |
| num_arms = *(const SHORT*)pFormat & 0x0fff; |
| pFormat += 2; |
| for(arm = 0; arm < num_arms; arm++) |
| { |
| if(discriminant == *(const ULONG*)pFormat) |
| { |
| pFormat += 4; |
| break; |
| } |
| pFormat += 6; |
| } |
| |
| type = *(const unsigned short*)pFormat; |
| TRACE("type %04x\n", type); |
| if(arm == num_arms) /* default arm extras */ |
| { |
| if(type == 0xffff) |
| { |
| ERR("no arm for 0x%lx and no default case\n", discriminant); |
| RpcRaiseException(RPC_S_INVALID_TAG); |
| return NULL; |
| } |
| if(type == 0) |
| { |
| TRACE("falling back to empty default case for 0x%lx\n", discriminant); |
| return NULL; |
| } |
| } |
| return pFormat; |
| } |
| |
| static PFORMAT_STRING get_non_encapsulated_union_arm(PMIDL_STUB_MESSAGE pStubMsg, |
| ULONG value, |
| PFORMAT_STRING pFormat) |
| { |
| pFormat += *(const SHORT*)pFormat; |
| pFormat += 2; |
| |
| return get_arm_offset_from_union_arm_selector(pStubMsg, value, pFormat); |
| } |
| |
| /*********************************************************************** |
| * NdrNonEncapsulatedUnionMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned short type; |
| unsigned char switch_type; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| pFormat++; |
| |
| switch_type = *pFormat; |
| pFormat++; |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); |
| TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); |
| /* Marshall discriminant */ |
| NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); |
| |
| pFormat = get_non_encapsulated_union_arm(pStubMsg, pStubMsg->MaxCount, pFormat); |
| if(!pFormat) |
| return NULL; |
| |
| type = *(const unsigned short*)pFormat; |
| if((type & 0xff00) == 0x8000) |
| { |
| unsigned char basetype = LOBYTE(type); |
| return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype); |
| } |
| else |
| { |
| PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; |
| NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK]; |
| if (m) |
| { |
| unsigned char *saved_buffer = NULL; |
| switch(*desc) |
| { |
| case RPC_FC_RP: |
| case RPC_FC_UP: |
| case RPC_FC_OP: |
| case RPC_FC_FP: |
| saved_buffer = pStubMsg->Buffer; |
| pStubMsg->Buffer += 4; /* for pointer ID */ |
| PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc); |
| break; |
| default: |
| m(pStubMsg, pMemory, desc); |
| } |
| } |
| else FIXME("no marshaller for embedded type %02x\n", *desc); |
| } |
| return NULL; |
| } |
| |
| static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING *ppFormat) |
| { |
| long discriminant = 0; |
| |
| switch(**ppFormat) |
| { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| discriminant = *(UCHAR *)pStubMsg->Buffer; |
| pStubMsg->Buffer += sizeof(UCHAR); |
| break; |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); |
| discriminant = *(USHORT *)pStubMsg->Buffer; |
| pStubMsg->Buffer += sizeof(USHORT); |
| break; |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); |
| discriminant = *(ULONG *)pStubMsg->Buffer; |
| pStubMsg->Buffer += sizeof(ULONG); |
| break; |
| default: |
| FIXME("Unhandled base type: 0x%02x\n", **ppFormat); |
| } |
| (*ppFormat)++; |
| |
| if (pStubMsg->fHasNewCorrDesc) |
| *ppFormat += 6; |
| else |
| *ppFormat += 4; |
| return discriminant; |
| } |
| |
| /********************************************************************** |
| * NdrNonEncapsulatedUnionUnmarshall[RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| long discriminant; |
| unsigned short type, size; |
| |
| TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); |
| pFormat++; |
| |
| /* Unmarshall discriminant */ |
| discriminant = unmarshall_discriminant(pStubMsg, &pFormat); |
| TRACE("unmarshalled discriminant %lx\n", discriminant); |
| |
| pFormat += *(const SHORT*)pFormat; |
| |
| size = *(const unsigned short*)pFormat; |
| pFormat += 2; |
| |
| pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); |
| if(!pFormat) |
| return NULL; |
| |
| if(!*ppMemory || fMustAlloc) |
| *ppMemory = NdrAllocate(pStubMsg, size); |
| |
| type = *(const unsigned short*)pFormat; |
| if((type & 0xff00) == 0x8000) |
| { |
| unsigned char basetype = LOBYTE(type); |
| return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, fMustAlloc); |
| } |
| else |
| { |
| PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; |
| NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; |
| if (m) |
| { |
| unsigned char *saved_buffer = NULL; |
| switch(*desc) |
| { |
| case RPC_FC_RP: |
| case RPC_FC_UP: |
| case RPC_FC_OP: |
| case RPC_FC_FP: |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| saved_buffer = pStubMsg->Buffer; |
| pStubMsg->Buffer += 4; /* for pointer ID */ |
| PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, TRUE); |
| break; |
| default: |
| m(pStubMsg, ppMemory, desc, fMustAlloc); |
| } |
| } |
| else FIXME("no marshaller for embedded type %02x\n", *desc); |
| } |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned short type; |
| unsigned char switch_type; |
| |
| TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); |
| pFormat++; |
| |
| switch_type = *pFormat; |
| pFormat++; |
| |
| pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); |
| TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); |
| /* Add discriminant size */ |
| NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); |
| |
| pFormat = get_non_encapsulated_union_arm(pStubMsg, pStubMsg->MaxCount, pFormat); |
| if(!pFormat) |
| return; |
| |
| type = *(const unsigned short*)pFormat; |
| if((type & 0xff00) == 0x8000) |
| { |
| unsigned char basetype = LOBYTE(type); |
| NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype); |
| } |
| else |
| { |
| PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; |
| NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; |
| if (m) |
| { |
| switch(*desc) |
| { |
| case RPC_FC_RP: |
| case RPC_FC_UP: |
| case RPC_FC_OP: |
| case RPC_FC_FP: |
| ALIGN_LENGTH(pStubMsg->BufferLength, 4); |
| pStubMsg->BufferLength += 4; /* for pointer ID */ |
| PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc); |
| break; |
| default: |
| m(pStubMsg, pMemory, desc); |
| } |
| } |
| else FIXME("no buffersizer for embedded type %02x\n", *desc); |
| } |
| return; |
| } |
| |
| /*********************************************************************** |
| * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| unsigned long discriminant; |
| unsigned short type, size; |
| |
| pFormat++; |
| /* Unmarshall discriminant */ |
| discriminant = unmarshall_discriminant(pStubMsg, &pFormat); |
| TRACE("unmarshalled discriminant 0x%lx\n", discriminant); |
| |
| pFormat += *(const SHORT*)pFormat; |
| |
| size = *(const unsigned short*)pFormat; |
| pFormat += 2; |
| |
| pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); |
| if(!pFormat) |
| return 0; |
| |
| pStubMsg->Memory += size; |
| |
| type = *(const unsigned short*)pFormat; |
| if((type & 0xff00) == 0x8000) |
| { |
| return NdrBaseTypeMemorySize(pStubMsg, pFormat); |
| } |
| else |
| { |
| PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; |
| NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; |
| unsigned char *saved_buffer; |
| if (m) |
| { |
| switch(*desc) |
| { |
| case RPC_FC_RP: |
| case RPC_FC_UP: |
| case RPC_FC_OP: |
| case RPC_FC_FP: |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| saved_buffer = pStubMsg->Buffer; |
| pStubMsg->Buffer += 4; |
| ALIGN_LENGTH(pStubMsg->MemorySize, 4); |
| pStubMsg->MemorySize += 4; |
| PointerMemorySize(pStubMsg, saved_buffer, pFormat); |
| break; |
| default: |
| return m(pStubMsg, desc); |
| } |
| } |
| else FIXME("no marshaller for embedded type %02x\n", *desc); |
| } |
| |
| TRACE("size %d\n", size); |
| return size; |
| } |
| |
| /*********************************************************************** |
| * NdrNonEncapsulatedUnionFree [RPCRT4.@] |
| */ |
| void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrByteCountPointerMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrByteCountPointerUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| FIXME("stub\n"); |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrByteCountPointerBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrByteCountPointerMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * NdrByteCountPointerFree [RPCRT4.@] |
| */ |
| void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrXmitOrRepAsMarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrXmitOrRepAsUnmarshall [RPCRT4.@] |
| */ |
| unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| FIXME("stub\n"); |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrXmitOrRepAsBufferSize [RPCRT4.@] |
| */ |
| void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrXmitOrRepAsMemorySize [RPCRT4.@] |
| */ |
| unsigned long WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * NdrXmitOrRepAsFree [RPCRT4.@] |
| */ |
| void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("stub\n"); |
| } |
| |
| /*********************************************************************** |
| * NdrBaseTypeMarshall [internal] |
| */ |
| static unsigned char *WINAPI NdrBaseTypeMarshall( |
| PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); |
| |
| switch(*pFormat) |
| { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory; |
| pStubMsg->Buffer += sizeof(UCHAR); |
| TRACE("value: 0x%02x\n", *(UCHAR *)pMemory); |
| break; |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); |
| *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory; |
| pStubMsg->Buffer += sizeof(USHORT); |
| TRACE("value: 0x%04x\n", *(USHORT *)pMemory); |
| break; |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| case RPC_FC_ERROR_STATUS_T: |
| case RPC_FC_ENUM32: |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); |
| *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory; |
| pStubMsg->Buffer += sizeof(ULONG); |
| TRACE("value: 0x%08lx\n", *(ULONG *)pMemory); |
| break; |
| case RPC_FC_FLOAT: |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(float)); |
| *(float *)pStubMsg->Buffer = *(float *)pMemory; |
| pStubMsg->Buffer += sizeof(float); |
| break; |
| case RPC_FC_DOUBLE: |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(double)); |
| *(double *)pStubMsg->Buffer = *(double *)pMemory; |
| pStubMsg->Buffer += sizeof(double); |
| break; |
| case RPC_FC_HYPER: |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG)); |
| *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory; |
| pStubMsg->Buffer += sizeof(ULONGLONG); |
| TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory)); |
| break; |
| case RPC_FC_ENUM16: |
| /* only 16-bits on the wire, so do a sanity check */ |
| if (*(UINT *)pMemory > USHRT_MAX) |
| RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); |
| *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory; |
| pStubMsg->Buffer += sizeof(USHORT); |
| TRACE("value: 0x%04x\n", *(UINT *)pMemory); |
| break; |
| default: |
| FIXME("Unhandled base type: 0x%02x\n", *pFormat); |
| } |
| |
| STD_OVERFLOW_CHECK(pStubMsg); |
| |
| /* FIXME: what is the correct return value? */ |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrBaseTypeUnmarshall [internal] |
| */ |
| static unsigned char *WINAPI NdrBaseTypeUnmarshall( |
| PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char **ppMemory, |
| PFORMAT_STRING pFormat, |
| unsigned char fMustAlloc) |
| { |
| TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); |
| |
| #define BASE_TYPE_UNMARSHALL(type) \ |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ |
| if (fMustAlloc || !*ppMemory) \ |
| *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ |
| TRACE("*ppMemory: %p\n", *ppMemory); \ |
| **(type **)ppMemory = *(type *)pStubMsg->Buffer; \ |
| pStubMsg->Buffer += sizeof(type); |
| |
| switch(*pFormat) |
| { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| BASE_TYPE_UNMARSHALL(UCHAR); |
| TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); |
| break; |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| BASE_TYPE_UNMARSHALL(USHORT); |
| TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); |
| break; |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| case RPC_FC_ERROR_STATUS_T: |
| case RPC_FC_ENUM32: |
| BASE_TYPE_UNMARSHALL(ULONG); |
| TRACE("value: 0x%08lx\n", **(ULONG **)ppMemory); |
| break; |
| case RPC_FC_FLOAT: |
| BASE_TYPE_UNMARSHALL(float); |
| TRACE("value: %f\n", **(float **)ppMemory); |
| break; |
| case RPC_FC_DOUBLE: |
| BASE_TYPE_UNMARSHALL(double); |
| TRACE("value: %f\n", **(double **)ppMemory); |
| break; |
| case RPC_FC_HYPER: |
| BASE_TYPE_UNMARSHALL(ULONGLONG); |
| TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory)); |
| break; |
| case RPC_FC_ENUM16: |
| ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); |
| if (fMustAlloc || !*ppMemory) |
| *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT)); |
| TRACE("*ppMemory: %p\n", *ppMemory); |
| /* 16-bits on the wire, but int in memory */ |
| **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer; |
| pStubMsg->Buffer += sizeof(USHORT); |
| TRACE("value: 0x%08x\n", **(UINT **)ppMemory); |
| break; |
| default: |
| FIXME("Unhandled base type: 0x%02x\n", *pFormat); |
| } |
| #undef BASE_TYPE_UNMARSHALL |
| |
| /* FIXME: what is the correct return value? */ |
| |
| return NULL; |
| } |
| |
| /*********************************************************************** |
| * NdrBaseTypeBufferSize [internal] |
| */ |
| static void WINAPI NdrBaseTypeBufferSize( |
| PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); |
| |
| switch(*pFormat) |
| { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| pStubMsg->BufferLength += sizeof(UCHAR); |
| break; |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| case RPC_FC_ENUM16: |
| ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT)); |
| pStubMsg->BufferLength += sizeof(USHORT); |
| break; |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| case RPC_FC_ENUM32: |
| ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG)); |
| pStubMsg->BufferLength += sizeof(ULONG); |
| break; |
| case RPC_FC_FLOAT: |
| ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float)); |
| pStubMsg->BufferLength += sizeof(float); |
| break; |
| case RPC_FC_DOUBLE: |
| ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double)); |
| pStubMsg->BufferLength += sizeof(double); |
| break; |
| case RPC_FC_HYPER: |
| ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG)); |
| pStubMsg->BufferLength += sizeof(ULONGLONG); |
| break; |
| case RPC_FC_ERROR_STATUS_T: |
| ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t)); |
| pStubMsg->BufferLength += sizeof(error_status_t); |
| break; |
| default: |
| FIXME("Unhandled base type: 0x%02x\n", *pFormat); |
| } |
| } |
| |
| /*********************************************************************** |
| * NdrBaseTypeMemorySize [internal] |
| */ |
| static unsigned long WINAPI NdrBaseTypeMemorySize( |
| PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| switch(*pFormat) |
| { |
| case RPC_FC_BYTE: |
| case RPC_FC_CHAR: |
| case RPC_FC_SMALL: |
| case RPC_FC_USMALL: |
| pStubMsg->Buffer += sizeof(UCHAR); |
| pStubMsg->MemorySize += sizeof(UCHAR); |
| return sizeof(UCHAR); |
| case RPC_FC_WCHAR: |
| case RPC_FC_SHORT: |
| case RPC_FC_USHORT: |
| pStubMsg->Buffer += sizeof(USHORT); |
| pStubMsg->MemorySize += sizeof(USHORT); |
| return sizeof(USHORT); |
| case RPC_FC_LONG: |
| case RPC_FC_ULONG: |
| pStubMsg->Buffer += sizeof(ULONG); |
| pStubMsg->MemorySize += sizeof(ULONG); |
| return sizeof(ULONG); |
| case RPC_FC_FLOAT: |
| pStubMsg->Buffer += sizeof(float); |
| pStubMsg->MemorySize += sizeof(float); |
| return sizeof(float); |
| case RPC_FC_DOUBLE: |
| pStubMsg->Buffer += sizeof(double); |
| pStubMsg->MemorySize += sizeof(double); |
| return sizeof(double); |
| case RPC_FC_HYPER: |
| pStubMsg->Buffer += sizeof(ULONGLONG); |
| pStubMsg->MemorySize += sizeof(ULONGLONG); |
| return sizeof(ULONGLONG); |
| case RPC_FC_ERROR_STATUS_T: |
| pStubMsg->Buffer += sizeof(error_status_t); |
| pStubMsg->MemorySize += sizeof(error_status_t); |
| return sizeof(error_status_t); |
| case RPC_FC_ENUM16: |
| case RPC_FC_ENUM32: |
| pStubMsg->Buffer += sizeof(INT); |
| pStubMsg->MemorySize += sizeof(INT); |
| return sizeof(INT); |
| default: |
| FIXME("Unhandled base type: 0x%02x\n", *pFormat); |
| return 0; |
| } |
| } |
| |
| /*********************************************************************** |
| * NdrBaseTypeFree [internal] |
| */ |
| static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char *pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat); |
| |
| /* nothing to do */ |
| } |
| |
| /*********************************************************************** |
| * NdrClientContextMarshall |
| */ |
| void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| NDR_CCONTEXT ContextHandle, |
| int fCheck) |
| { |
| TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| |
| /* FIXME: what does fCheck do? */ |
| NDRCContextMarshall(ContextHandle, |
| pStubMsg->Buffer); |
| |
| pStubMsg->Buffer += cbNDRContext; |
| } |
| |
| /*********************************************************************** |
| * NdrClientContextUnmarshall |
| */ |
| void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| NDR_CCONTEXT * pContextHandle, |
| RPC_BINDING_HANDLE BindHandle) |
| { |
| TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle); |
| |
| ALIGN_POINTER(pStubMsg->Buffer, 4); |
| |
| NDRCContextUnmarshall(pContextHandle, |
| BindHandle, |
| pStubMsg->Buffer, |
| pStubMsg->RpcMsg->DataRepresentation); |
| |
| pStubMsg->Buffer += cbNDRContext; |
| } |
| |
| void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| NDR_SCONTEXT ContextHandle, |
| NDR_RUNDOWN RundownRoutine ) |
| { |
| FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine); |
| } |
| |
| NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg) |
| { |
| FIXME("(%p): stub\n", pStubMsg); |
| return NULL; |
| } |
| |
| void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg, |
| unsigned char* pMemory, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat); |
| } |
| |
| NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("(%p, %p): stub\n", pStubMsg, pFormat); |
| return NULL; |
| } |
| |
| void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| NDR_SCONTEXT ContextHandle, |
| NDR_RUNDOWN RundownRoutine, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat); |
| } |
| |
| NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, |
| PFORMAT_STRING pFormat) |
| { |
| FIXME("(%p, %p): stub\n", pStubMsg, pFormat); |
| return NULL; |
| } |
| |
| #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e |
| |
| typedef struct ndr_context_handle |
| { |
| DWORD attributes; |
| GUID uuid; |
| } ndr_context_handle; |
| |
| struct context_handle_entry |
| { |
| struct list entry; |
| DWORD magic; |
| RPC_BINDING_HANDLE handle; |
| ndr_context_handle wire_data; |
| }; |
| |
| static struct list context_handle_list = LIST_INIT(context_handle_list); |
| |
| static CRITICAL_SECTION ndr_context_cs; |
| static CRITICAL_SECTION_DEBUG ndr_context_debug = |
| { |
| 0, 0, &ndr_context_cs, |
| { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList }, |
| 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") } |
| }; |
| static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 }; |
| |
| static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext) |
| { |
| struct context_handle_entry *che = (struct context_handle_entry*) CContext; |
| |
| if (che->magic != NDR_CONTEXT_HANDLE_MAGIC) |
| return NULL; |
| return che; |
| } |
| |
| static struct context_handle_entry *context_entry_from_guid(LPGUID uuid) |
| { |
| struct context_handle_entry *che; |
| LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry) |
| if (IsEqualGUID(&che->wire_data.uuid, uuid)) |
| return che; |
| return NULL; |
| } |
| |
| RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext) |
| { |
| struct context_handle_entry *che; |
| RPC_BINDING_HANDLE handle = NULL; |
| |
| TRACE("%p\n", CContext); |
| |
| EnterCriticalSection(&ndr_context_cs); |
| che = get_context_entry(CContext); |
| if (che) |
| handle = che->handle; |
| LeaveCriticalSection(&ndr_context_cs); |
| |
| if (!handle) |
| RpcRaiseException(ERROR_INVALID_HANDLE); |
| return handle; |
| } |
| |
| void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff) |
| { |
| struct context_handle_entry *che; |
| |
| TRACE("%p %p\n", CContext, pBuff); |
| |
| if (CContext) |
| { |
| EnterCriticalSection(&ndr_context_cs); |
| che = get_context_entry(CContext); |
| memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle)); |
| LeaveCriticalSection(&ndr_context_cs); |
| } |
| else |
| { |
| ndr_context_handle *wire_data = (ndr_context_handle *)pBuff; |
| wire_data->attributes = 0; |
| wire_data->uuid = GUID_NULL; |
| } |
| } |
| |
| static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext, |
| RPC_BINDING_HANDLE hBinding, |
| ndr_context_handle *chi) |
| { |
| struct context_handle_entry *che = NULL; |
| |
| /* a null UUID means we should free the context handle */ |
| if (IsEqualGUID(&chi->uuid, &GUID_NULL)) |
| { |
| if (*CContext) |
| { |
| che = get_context_entry(*CContext); |
| if (!che) |
| return ERROR_INVALID_HANDLE; |
| list_remove(&che->entry); |
| RpcBindingFree(&che->handle); |
| HeapFree(GetProcessHeap(), 0, che); |
| che = NULL; |
| } |
| } |
| /* if there's no existing entry matching the GUID, allocate one */ |
| else if (!(che = context_entry_from_guid(&chi->uuid))) |
| { |
| che = HeapAlloc(GetProcessHeap(), 0, sizeof *che); |
| if (!che) |
| return ERROR_NOT_ENOUGH_MEMORY; |
| che->magic = NDR_CONTEXT_HANDLE_MAGIC; |
| RpcBindingCopy(hBinding, &che->handle); |
| list_add_tail(&context_handle_list, &che->entry); |
| memcpy(&che->wire_data, chi, sizeof *chi); |
| } |
| |
| *CContext = che; |
| |
| return ERROR_SUCCESS; |
| } |
| |
| void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext, |
| RPC_BINDING_HANDLE hBinding, |
| void *pBuff, |
| unsigned long DataRepresentation) |
| { |
| UINT r; |
| |
| TRACE("*%p=(%p) %p %p %08lx\n", |
| CContext, *CContext, hBinding, pBuff, DataRepresentation); |
| |
| EnterCriticalSection(&ndr_context_cs); |
| r = ndr_update_context_handle(CContext, hBinding, pBuff); |
| LeaveCriticalSection(&ndr_context_cs); |
| if (r) |
| RpcRaiseException(r); |
| } |
| |
| void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext, |
| void *pBuff, |
| NDR_RUNDOWN userRunDownIn) |
| { |
| FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn); |
| } |
| |
| void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding, |
| NDR_SCONTEXT CContext, |
| void *pBuff, |
| NDR_RUNDOWN userRunDownIn) |
| { |
| FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn); |
| } |
| |
| void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding, |
| NDR_SCONTEXT CContext, |
| void *pBuff, |
| NDR_RUNDOWN userRunDownIn, |
| void *CtxGuard, |
| unsigned long Flags) |
| { |
| FIXME("(%p %p %p %p %p %lu): stub\n", |
| hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags); |
| } |
| |
| NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff, |
| unsigned long DataRepresentation) |
| { |
| FIXME("(%p %08lx): stub\n", pBuff, DataRepresentation); |
| return NULL; |
| } |
| |
| NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding, |
| void *pBuff, |
| unsigned long DataRepresentation) |
| { |
| FIXME("(%p %p %08lx): stub\n", hBinding, pBuff, DataRepresentation); |
| return NULL; |
| } |
| |
| NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding, |
| void *pBuff, |
| unsigned long DataRepresentation, |
| void *CtxGuard, |
| unsigned long Flags) |
| { |
| FIXME("(%p %p %08lx %p %lu): stub\n", |
| hBinding, pBuff, DataRepresentation, CtxGuard, Flags); |
| return NULL; |
| } |