/* * 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 #include #include #include #include #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; uMemory; 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; uOffset; 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; uMemory; 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; uOffset; 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; uMemory; 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: 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]); 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->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->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->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; }