/* * 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: * - String structs * - Byte count pointers * - transmit_as/represent as * - Multi-dimensional arrays * - Conversion functions (NdrConvert) * - Checks for integer addition overflow in user marshall functions */ #include #include #include #include #include "windef.h" #include "winbase.h" #include "winerror.h" #include "ndr_misc.h" #include "rpcndr.h" #include "wine/unicode.h" #include "wine/rpcfc.h" #include "wine/debug.h" 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))) # 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))) #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 ALIGN_POINTER_CLEAR(_Ptr, _Align) \ do { \ memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \ ALIGN_POINTER(_Ptr, _Align); \ } while(0) #define STD_OVERFLOW_CHECK(_Msg) do { \ TRACE("buffer=%d/%d\n", (ULONG)(_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", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \ } while (0) #define NDR_POINTER_ID_BASE 0x20000 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4) #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 ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING); static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING); static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING); static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); static ULONG WINAPI NdrByteCountPointerMemorySize(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, /* 0x30 */ NdrContextHandleMarshall, /* 0xb1 */ 0, 0, 0, NdrUserMarshalMarshall, 0, 0, /* 0xb7 */ NdrRangeMarshall }; const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = { 0, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, /* 0x10 */ NdrBaseTypeUnmarshall, /* 0x11 */ NdrPointerUnmarshall, NdrPointerUnmarshall, NdrPointerUnmarshall, NdrPointerUnmarshall, /* 0x15 */ NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall, NdrConformantStructUnmarshall, NdrConformantStructUnmarshall, NdrConformantVaryingStructUnmarshall, NdrComplexStructUnmarshall, /* 0x1b */ NdrConformantArrayUnmarshall, NdrConformantVaryingArrayUnmarshall, NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall, NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall, NdrComplexArrayUnmarshall, /* 0x22 */ NdrConformantStringUnmarshall, 0, 0, NdrConformantStringUnmarshall, NdrNonConformantStringUnmarshall, 0, 0, 0, /* 0x2a */ NdrEncapsulatedUnionUnmarshall, NdrNonEncapsulatedUnionUnmarshall, NdrByteCountPointerUnmarshall, NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall, /* 0x2f */ NdrInterfacePointerUnmarshall, /* 0x30 */ NdrContextHandleUnmarshall, /* 0xb1 */ 0, 0, 0, NdrUserMarshalUnmarshall, 0, 0, /* 0xb7 */ NdrRangeUnmarshall }; const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = { 0, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, /* 0x10 */ NdrBaseTypeBufferSize, /* 0x11 */ NdrPointerBufferSize, NdrPointerBufferSize, NdrPointerBufferSize, NdrPointerBufferSize, /* 0x15 */ NdrSimpleStructBufferSize, NdrSimpleStructBufferSize, NdrConformantStructBufferSize, NdrConformantStructBufferSize, NdrConformantVaryingStructBufferSize, NdrComplexStructBufferSize, /* 0x1b */ NdrConformantArrayBufferSize, NdrConformantVaryingArrayBufferSize, NdrFixedArrayBufferSize, NdrFixedArrayBufferSize, NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize, NdrComplexArrayBufferSize, /* 0x22 */ NdrConformantStringBufferSize, 0, 0, NdrConformantStringBufferSize, NdrNonConformantStringBufferSize, 0, 0, 0, /* 0x2a */ NdrEncapsulatedUnionBufferSize, NdrNonEncapsulatedUnionBufferSize, NdrByteCountPointerBufferSize, NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize, /* 0x2f */ NdrInterfacePointerBufferSize, /* 0x30 */ NdrContextHandleBufferSize, /* 0xb1 */ 0, 0, 0, NdrUserMarshalBufferSize, 0, 0, /* 0xb7 */ NdrRangeBufferSize }; const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = { 0, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, /* 0x10 */ NdrBaseTypeMemorySize, /* 0x11 */ NdrPointerMemorySize, NdrPointerMemorySize, NdrPointerMemorySize, NdrPointerMemorySize, /* 0x15 */ NdrSimpleStructMemorySize, NdrSimpleStructMemorySize, NdrConformantStructMemorySize, NdrConformantStructMemorySize, NdrConformantVaryingStructMemorySize, NdrComplexStructMemorySize, /* 0x1b */ NdrConformantArrayMemorySize, NdrConformantVaryingArrayMemorySize, NdrFixedArrayMemorySize, NdrFixedArrayMemorySize, NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize, NdrComplexArrayMemorySize, /* 0x22 */ NdrConformantStringMemorySize, 0, 0, NdrConformantStringMemorySize, NdrNonConformantStringMemorySize, 0, 0, 0, /* 0x2a */ NdrEncapsulatedUnionMemorySize, NdrNonEncapsulatedUnionMemorySize, NdrByteCountPointerMemorySize, NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize, /* 0x2f */ NdrInterfacePointerMemorySize, /* 0x30 */ 0, /* 0xb1 */ 0, 0, 0, NdrUserMarshalMemorySize, 0, 0, /* 0xb7 */ NdrRangeMemorySize }; const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = { 0, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, /* 0x10 */ NdrBaseTypeFree, /* 0x11 */ NdrPointerFree, NdrPointerFree, NdrPointerFree, NdrPointerFree, /* 0x15 */ NdrSimpleStructFree, NdrSimpleStructFree, NdrConformantStructFree, NdrConformantStructFree, NdrConformantVaryingStructFree, NdrComplexStructFree, /* 0x1b */ NdrConformantArrayFree, NdrConformantVaryingArrayFree, NdrFixedArrayFree, NdrFixedArrayFree, NdrVaryingArrayFree, NdrVaryingArrayFree, NdrComplexArrayFree, /* 0x22 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x2a */ NdrEncapsulatedUnionFree, NdrNonEncapsulatedUnionFree, 0, NdrXmitOrRepAsFree, NdrXmitOrRepAsFree, /* 0x2f */ NdrInterfacePointerFree, /* 0x30 */ 0, /* 0xb1 */ 0, 0, 0, NdrUserMarshalFree, 0, 0, /* 0xb7 */ NdrRangeFree }; typedef struct _NDR_MEMORY_LIST { ULONG magic; ULONG size; ULONG reserved; struct _NDR_MEMORY_LIST *next; } NDR_MEMORY_LIST; #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L') /*********************************************************************** * NdrAllocate [RPCRT4.@] * * Allocates a block of memory using pStubMsg->pfnAllocate. * * PARAMS * pStubMsg [I/O] MIDL_STUB_MESSAGE structure. * len [I] Size of memory block to allocate. * * RETURNS * The memory block of size len that was allocated. * * NOTES * The memory block is always 8-byte aligned. * If the function is unable to allocate memory an ERROR_OUTOFMEMORY * exception is raised. */ void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len) { SIZE_T aligned_len; SIZE_T adjusted_len; void *p; NDR_MEMORY_LIST *mem_list; aligned_len = ALIGNED_LENGTH(len, 8); adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST); /* check for overflow */ if (adjusted_len < len) { ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len); RpcRaiseException(RPC_X_BAD_STUB_DATA); } p = pStubMsg->pfnAllocate(adjusted_len); if (!p) RpcRaiseException(ERROR_OUTOFMEMORY); mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len); mem_list->magic = MEML_MAGIC; mem_list->size = aligned_len; mem_list->reserved = 0; mem_list->next = pStubMsg->pMemoryList; pStubMsg->pMemoryList = mem_list; TRACE("-- %p\n", p); return p; } static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer) { TRACE("(%p, %p)\n", pStubMsg, 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); if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); 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); if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); pStubMsg->Buffer += 4; TRACE("offset is %d\n", pStubMsg->Offset); pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); pStubMsg->Buffer += 4; TRACE("variance is %d\n", pStubMsg->ActualCount); if ((pStubMsg->ActualCount > MaxValue) || (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue)) { ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n", pStubMsg->ActualCount, pStubMsg->Offset, MaxValue); RpcRaiseException(RPC_S_INVALID_BOUND); return NULL; } done: if (pStubMsg->fHasNewCorrDesc) return pFormat+6; else return pFormat+4; } /* writes the conformance value to the buffer */ static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg) { ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); 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_CLEAR(pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); 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); if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->BufferLength += 4; } /* requests buffer space for the variance values */ static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg) { ALIGN_LENGTH(pStubMsg->BufferLength, 4); if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->BufferLength += 8; } PFORMAT_STRING ComputeConformanceOrVariance( MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount) { BYTE dtype = pFormat[0] & 0xf; short ofs = *(const 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=%d\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 %d\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; } static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { if (IsConformanceOrVariancePresent(pFormat)) { if (pStubMsg->fHasNewCorrDesc) pFormat += 6; else pFormat += 4; } return pFormat; } /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if * the result overflows 32-bits */ static inline ULONG safe_multiply(ULONG a, ULONG b) { ULONGLONG ret = (ULONGLONG)a * b; if (ret > 0xffffffff) { RpcRaiseException(RPC_S_INVALID_BOUND); return 0; } return ret; } static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size) { if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->Buffer += size; } static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size) { if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */ { ERR("buffer length overflow - BufferLength = %u, size = %u\n", pStubMsg->BufferLength, size); RpcRaiseException(RPC_X_BAD_STUB_DATA); } pStubMsg->BufferLength += size; } /* copies data from the buffer, checking that there is enough data in the buffer * to do so */ static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size) { if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ (pStubMsg->Buffer + size > pStubMsg->BufferEnd)) { ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n", pStubMsg->Buffer, pStubMsg->BufferEnd, size); RpcRaiseException(RPC_X_BAD_STUB_DATA); } if (p == pStubMsg->Buffer) ERR("pointer is the same as the buffer\n"); memcpy(p, pStubMsg->Buffer, size); pStubMsg->Buffer += size; } /* copies data to the buffer, checking that there is enough space to do so */ static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size) { if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)) { ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n", pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength, size); RpcRaiseException(RPC_X_BAD_STUB_DATA); } memcpy(pStubMsg->Buffer, p, size); pStubMsg->Buffer += size; } /* verify that string data sitting in the buffer is valid and safe to * unmarshall */ static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize) { ULONG i; /* verify the buffer is safe to access */ if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) { ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, pStubMsg->BufferEnd, pStubMsg->Buffer); RpcRaiseException(RPC_X_BAD_STUB_DATA); } /* strings must always have null terminating bytes */ if (bufsize < esize) { ERR("invalid string length of %d\n", bufsize / esize); RpcRaiseException(RPC_S_INVALID_BOUND); } for (i = bufsize - esize; i < bufsize; i++) if (pStubMsg->Buffer[i] != 0) { ERR("string not null-terminated at byte position %d, data is 0x%x\n", i, pStubMsg->Buffer[i]); RpcRaiseException(RPC_S_INVALID_BOUND); } } 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 [internal] */ 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; ULONG 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 (!Pointer) { ERR("NULL ref pointer is not allowed\n"); RpcRaiseException(RPC_X_NULL_REF_POINTER); } 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 = Pointer ? NDR_POINTER_ID(pStubMsg) : 0; TRACE("writing 0x%08x 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%08x 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 [internal] */ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *Buffer, unsigned char **pPointer, unsigned char *pSrcPointer, 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,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, 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%08x\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%08x\n", pointer_id); if (!fMustAlloc && pSrcPointer) { FIXME("free object pointer %p\n", pSrcPointer); fMustAlloc = TRUE; } if (pointer_id) pointer_needs_unmarshaling = 1; else { *pPointer = NULL; pointer_needs_unmarshaling = 0; } break; case RPC_FC_FP: pointer_id = NDR_LOCAL_UINT32_READ(Buffer); TRACE("pointer_id is 0x%08x\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) { unsigned char *base_ptr_val = *pPointer; unsigned char **current_ptr = pPointer; if (pStubMsg->IsClient) { TRACE("client\n"); /* if we aren't forcing allocation of memory then try to use the existing * (source) pointer to unmarshall the data into so that [in,out] * parameters behave correctly. it doesn't matter if the parameter is * [out] only since in that case the pointer will be NULL. we force * allocation when the source pointer is NULL here instead of in the type * unmarshalling routine for the benefit of the deref code below */ if (!fMustAlloc) { if (pSrcPointer) { TRACE("setting *pPointer to %p\n", pSrcPointer); *pPointer = base_ptr_val = pSrcPointer; } else fMustAlloc = TRUE; } } else { TRACE("server\n"); /* the memory in a stub is never initialised, so we have to work out here * whether we have to initialise it so we can use the optimisation of * setting the pointer to the buffer, if possible, or set fMustAlloc to * TRUE. */ if (attr & RPC_FC_P_DEREF) { fMustAlloc = TRUE; } else { base_ptr_val = NULL; *current_ptr = NULL; } } if (attr & RPC_FC_P_ALLOCALLNODES) FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n"); if (attr & RPC_FC_P_DEREF) { if (fMustAlloc) { base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *)); *pPointer = base_ptr_val; current_ptr = (unsigned char **)base_ptr_val; } else current_ptr = *(unsigned char***)current_ptr; TRACE("deref => %p\n", current_ptr); if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE; } m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; if (m) m(pStubMsg, current_ptr, desc, fMustAlloc); else FIXME("no unmarshaller for data type=%02x\n", *desc); if (type == RPC_FC_FP) NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id, base_ptr_val); } TRACE("pointer=%p\n", *pPointer); } /*********************************************************************** * PointerBufferSize [internal] */ 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; ULONG 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) */ if (!Pointer) { ERR("NULL ref pointer is not allowed\n"); RpcRaiseException(RPC_X_NULL_REF_POINTER); } 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 [internal] */ static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *Buffer, PFORMAT_STRING pFormat) { unsigned type = pFormat[0], attr = pFormat[1]; PFORMAT_STRING desc; NDR_MEMORYSIZE m; DWORD pointer_id = 0; int pointer_needs_sizing; TRACE("(%p,%p,%p)\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) */ pointer_needs_sizing = 1; break; case RPC_FC_UP: /* unique pointer */ 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%08x\n", pointer_id); if (pointer_id) pointer_needs_sizing = 1; else pointer_needs_sizing = 0; break; case RPC_FC_FP: { void *pointer; pointer_id = NDR_LOCAL_UINT32_READ(Buffer); TRACE("pointer_id is 0x%08x\n", pointer_id); pointer_needs_sizing = !NdrFullPointerQueryRefId( pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer); break; } default: FIXME("unhandled ptr type=%02x\n", type); RpcRaiseException(RPC_X_BAD_STUB_DATA); return 0; } if (attr & RPC_FC_P_DEREF) { ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void*)); pStubMsg->MemorySize += sizeof(void*); TRACE("deref\n"); } if (pointer_needs_sizing) { m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; if (m) m(pStubMsg, desc); else FIXME("no memorysizer for data type=%02x\n", *desc); } return pStubMsg->MemorySize; } /*********************************************************************** * PointerFree [internal] */ 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; unsigned char *current_pointer = Pointer; 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) { current_pointer = *(unsigned char**)Pointer; TRACE("deref => %p\n", current_pointer); } m = NdrFreer[*desc & NDR_TABLE_MASK]; if (m) m(pStubMsg, current_pointer, desc); /* this check stops us from trying to free buffer memory. we don't have to * worry about clients, since they won't call this function. * we don't have to check for the buffer being reallocated because * BufferStart and BufferEnd won't be reset when allocating memory for * sending the response. we don't have to check for the new buffer here as * it won't be used a type memory, only for buffer memory */ if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd) 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 rep, count, stride; unsigned i; unsigned char *saved_buffer = NULL; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); if (*pFormat != RPC_FC_PP) return NULL; pFormat += 2; if (pStubMsg->PointerBufferMark) { saved_buffer = pStubMsg->Buffer; pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } 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; count = 1; pFormat += 2; break; case RPC_FC_FIXED_REPEAT: rep = *(const WORD*)&pFormat[2]; stride = *(const WORD*)&pFormat[4]; count = *(const WORD*)&pFormat[8]; pFormat += 10; break; case RPC_FC_VARIABLE_REPEAT: rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; stride = *(const WORD*)&pFormat[2]; count = *(const WORD*)&pFormat[6]; 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; for (u=0; uMemory; pStubMsg->Memory = pMemory; PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4); pStubMsg->Memory = saved_memory; } } pFormat += 8 * count; } if (saved_buffer) { pStubMsg->PointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = saved_buffer; } STD_OVERFLOW_CHECK(pStubMsg); return NULL; } /*********************************************************************** * EmbeddedPointerUnmarshall */ static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pDstBuffer, unsigned char *pSrcMemoryPtrs, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { unsigned char *Mark = pStubMsg->BufferMark; unsigned rep, count, stride; unsigned i; unsigned char *saved_buffer = NULL; TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc); if (*pFormat != RPC_FC_PP) return NULL; pFormat += 2; if (pStubMsg->PointerBufferMark) { saved_buffer = pStubMsg->Buffer; pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } 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; count = 1; pFormat += 2; break; case RPC_FC_FIXED_REPEAT: rep = *(const WORD*)&pFormat[2]; stride = *(const WORD*)&pFormat[4]; count = *(const WORD*)&pFormat[8]; pFormat += 10; break; case RPC_FC_VARIABLE_REPEAT: rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; stride = *(const WORD*)&pFormat[2]; count = *(const WORD*)&pFormat[6]; pFormat += 8; break; } for (i = 0; i < rep; i++) { PFORMAT_STRING info = pFormat; unsigned char *bufdstbase = pDstBuffer + (i * stride); unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride); unsigned char *bufbase = Mark + (i * stride); unsigned u; for (u=0; uPointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = saved_buffer; } return NULL; } /*********************************************************************** * EmbeddedPointerBufferSize */ static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { unsigned rep, count, stride; unsigned i; ULONG saved_buffer_length = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); if (pStubMsg->IgnoreEmbeddedPointers) return; if (*pFormat != RPC_FC_PP) return; pFormat += 2; if (pStubMsg->PointerLength) { saved_buffer_length = pStubMsg->BufferLength; pStubMsg->BufferLength = pStubMsg->PointerLength; pStubMsg->PointerLength = 0; } 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; count = 1; pFormat += 2; break; case RPC_FC_FIXED_REPEAT: rep = *(const WORD*)&pFormat[2]; stride = *(const WORD*)&pFormat[4]; count = *(const WORD*)&pFormat[8]; pFormat += 10; break; case RPC_FC_VARIABLE_REPEAT: rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; stride = *(const WORD*)&pFormat[2]; count = *(const WORD*)&pFormat[6]; pFormat += 8; break; } 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; } if (saved_buffer_length) { pStubMsg->PointerLength = pStubMsg->BufferLength; pStubMsg->BufferLength = saved_buffer_length; } } /*********************************************************************** * EmbeddedPointerMemorySize [internal] */ static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { unsigned char *Mark = pStubMsg->BufferMark; unsigned rep, count, stride; unsigned i; unsigned char *saved_buffer = NULL; TRACE("(%p,%p)\n", pStubMsg, pFormat); if (pStubMsg->IgnoreEmbeddedPointers) return 0; if (pStubMsg->PointerBufferMark) { saved_buffer = pStubMsg->Buffer; pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } 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; count = 1; pFormat += 2; break; case RPC_FC_FIXED_REPEAT: rep = *(const WORD*)&pFormat[2]; stride = *(const WORD*)&pFormat[4]; count = *(const WORD*)&pFormat[8]; pFormat += 10; break; case RPC_FC_VARIABLE_REPEAT: rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; stride = *(const WORD*)&pFormat[2]; count = *(const WORD*)&pFormat[6]; pFormat += 8; break; } for (i = 0; i < rep; i++) { PFORMAT_STRING info = pFormat; unsigned char *bufbase = Mark + (i * stride); unsigned u; for (u=0; uPointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = saved_buffer; } return 0; } /*********************************************************************** * EmbeddedPointerFree [internal] */ static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { unsigned rep, count, stride; 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; count = 1; pFormat += 2; break; case RPC_FC_FIXED_REPEAT: rep = *(const WORD*)&pFormat[2]; stride = *(const WORD*)&pFormat[4]; count = *(const WORD*)&pFormat[8]; pFormat += 10; break; case RPC_FC_VARIABLE_REPEAT: rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; stride = *(const WORD*)&pFormat[2]; count = *(const WORD*)&pFormat[6]; pFormat += 8; break; } 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); /* Increment 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_CLEAR(pStubMsg->Buffer, 4); Buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 4); } else Buffer = pStubMsg->Buffer; PointerMarshall(pStubMsg, Buffer, pMemory, pFormat); 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); if (*pFormat == RPC_FC_RP) { Buffer = pStubMsg->Buffer; /* Do the NULL ref pointer check here because embedded pointers can be * NULL if the type the pointer is embedded in was allocated rather than * being passed in by the client */ if (pStubMsg->IsClient && !*ppMemory) { ERR("NULL ref pointer is not allowed\n"); RpcRaiseException(RPC_X_NULL_REF_POINTER); } } else { /* Increment 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 */ ALIGN_POINTER(pStubMsg->Buffer, 4); Buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 4); } PointerUnmarshall(pStubMsg, Buffer, ppMemory, *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); /* Increment 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); safe_buffer_length_increment(pStubMsg, 4); } PointerBufferSize(pStubMsg, pMemory, pFormat); } /*********************************************************************** * NdrPointerMemorySize [RPCRT4.@] */ ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { unsigned char *Buffer = pStubMsg->Buffer; if (*pFormat != RPC_FC_RP) { ALIGN_POINTER(pStubMsg->Buffer, 4); safe_buffer_increment(pStubMsg, 4); } ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); return PointerMemorySize(pStubMsg, Buffer, pFormat); } /*********************************************************************** * 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 ) { NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar); } /*********************************************************************** * NdrSimpleTypeUnmarshall [RPCRT4.@] * * Unmarshall a base type. * * NOTES * Doesn't check that the buffer is long enough before copying, so the caller * should do this. */ void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, unsigned char FormatChar ) { #define BASE_TYPE_UNMARSHALL(type) \ ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ TRACE("pMemory: %p\n", pMemory); \ *(type *)pMemory = *(type *)pStubMsg->Buffer; \ pStubMsg->Buffer += sizeof(type); switch(FormatChar) { 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", *pMemory); break; case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: BASE_TYPE_UNMARSHALL(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: BASE_TYPE_UNMARSHALL(ULONG); TRACE("value: 0x%08x\n", *(ULONG *)pMemory); break; case RPC_FC_FLOAT: BASE_TYPE_UNMARSHALL(float); TRACE("value: %f\n", *(float *)pMemory); break; case RPC_FC_DOUBLE: BASE_TYPE_UNMARSHALL(double); TRACE("value: %f\n", *(double *)pMemory); break; case RPC_FC_HYPER: BASE_TYPE_UNMARSHALL(ULONGLONG); TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory)); break; case RPC_FC_ENUM16: ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); TRACE("pMemory: %p\n", pMemory); /* 16-bits on the wire, but int in memory */ *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer; pStubMsg->Buffer += sizeof(USHORT); TRACE("value: 0x%08x\n", *(UINT *)pMemory); break; case RPC_FC_IGNORE: break; default: FIXME("Unhandled base type: 0x%02x\n", FormatChar); } #undef BASE_TYPE_UNMARSHALL } /*********************************************************************** * 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_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory, size); if (pFormat[0] != RPC_FC_STRUCT) EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4); 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); unsigned char *saved_buffer; TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, size); else { if (!pStubMsg->IsClient && !*ppMemory) /* for servers, we just point straight into the RPC buffer */ *ppMemory = pStubMsg->Buffer; } saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, size); if (pFormat[0] == RPC_FC_PSTRUCT) EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc); TRACE("copying %p to %p\n", saved_buffer, *ppMemory); if (*ppMemory != saved_buffer) memcpy(*ppMemory, saved_buffer, size); 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); safe_buffer_length_increment(pStubMsg, size); if (pFormat[0] != RPC_FC_STRUCT) EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4); } /*********************************************************************** * NdrSimpleStructMemorySize [RPCRT4.@] */ ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { unsigned short size = *(const WORD *)(pFormat+2); TRACE("(%p,%p)\n", pStubMsg, pFormat); ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); pStubMsg->MemorySize += size; safe_buffer_increment(pStubMsg, size); if (pFormat[0] != RPC_FC_STRUCT) EmbeddedPointerMemorySize(pStubMsg, pFormat+4); return pStubMsg->MemorySize; } /*********************************************************************** * 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); } /* Array helpers */ static inline void array_compute_and_size_conformance( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { switch (fc) { case RPC_FC_CARRAY: ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); SizeConformance(pStubMsg); break; case RPC_FC_CVARRAY: pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0); pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); SizeConformance(pStubMsg); break; case RPC_FC_C_CSTRING: case RPC_FC_C_WSTRING: if (pFormat[0] == RPC_FC_C_CSTRING) { TRACE("string=%s\n", debugstr_a((const char *)pMemory)); pStubMsg->ActualCount = strlen((const char *)pMemory)+1; } else { TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory)); pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1; } if (fc == RPC_FC_STRING_SIZED) pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); else pStubMsg->MaxCount = pStubMsg->ActualCount; SizeConformance(pStubMsg); break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); } } static inline void array_buffer_size( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { DWORD size; DWORD esize; unsigned char alignment; switch (fc) { case RPC_FC_CARRAY: esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; pFormat = SkipConformance(pStubMsg, pFormat + 4); ALIGN_LENGTH(pStubMsg->BufferLength, alignment); size = safe_multiply(esize, pStubMsg->MaxCount); /* conformance value plus array */ safe_buffer_length_increment(pStubMsg, size); if (fHasPointers) EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); break; case RPC_FC_CVARRAY: esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; pFormat = SkipConformance(pStubMsg, pFormat + 4); pFormat = SkipConformance(pStubMsg, pFormat); SizeVariance(pStubMsg); ALIGN_LENGTH(pStubMsg->BufferLength, alignment); size = safe_multiply(esize, pStubMsg->ActualCount); safe_buffer_length_increment(pStubMsg, size); if (fHasPointers) EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); break; case RPC_FC_C_CSTRING: case RPC_FC_C_WSTRING: if (fc == RPC_FC_C_CSTRING) esize = 1; else esize = 2; SizeVariance(pStubMsg); size = safe_multiply(esize, pStubMsg->ActualCount); safe_buffer_length_increment(pStubMsg, size); break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); } } static inline void array_compute_and_write_conformance( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { switch (fc) { case RPC_FC_CARRAY: ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); WriteConformance(pStubMsg); break; case RPC_FC_CVARRAY: pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0); pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); WriteConformance(pStubMsg); break; case RPC_FC_C_CSTRING: case RPC_FC_C_WSTRING: if (fc == RPC_FC_C_CSTRING) { TRACE("string=%s\n", debugstr_a((const char *)pMemory)); pStubMsg->ActualCount = strlen((const char *)pMemory)+1; } else { TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory)); pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1; } if (pFormat[1] == RPC_FC_STRING_SIZED) pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); else pStubMsg->MaxCount = pStubMsg->ActualCount; pStubMsg->Offset = 0; WriteConformance(pStubMsg); break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); } } static inline void array_write_variance_and_marshall( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { DWORD size; DWORD esize; unsigned char alignment; switch (fc) { case RPC_FC_CARRAY: esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; pFormat = SkipConformance(pStubMsg, pFormat + 4); ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); size = safe_multiply(esize, pStubMsg->MaxCount); if (fHasPointers) pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory, size); if (fHasPointers) EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); break; case RPC_FC_CVARRAY: esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; /* conformance */ pFormat = SkipConformance(pStubMsg, pFormat + 4); /* variance */ pFormat = SkipConformance(pStubMsg, pFormat); WriteVariance(pStubMsg); ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); size = safe_multiply(esize, pStubMsg->ActualCount); if (fHasPointers) pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size); if (fHasPointers) EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); break; case RPC_FC_C_CSTRING: case RPC_FC_C_WSTRING: if (fc == RPC_FC_C_CSTRING) esize = 1; else esize = 2; WriteVariance(pStubMsg); size = safe_multiply(esize, pStubMsg->ActualCount); safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); } } static inline ULONG array_read_conformance( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { DWORD esize; switch (fc) { case RPC_FC_CARRAY: esize = *(const WORD*)(pFormat+2); pFormat = ReadConformance(pStubMsg, pFormat+4); return safe_multiply(esize, pStubMsg->MaxCount); case RPC_FC_CVARRAY: esize = *(const WORD*)(pFormat+2); pFormat = ReadConformance(pStubMsg, pFormat+4); return safe_multiply(esize, pStubMsg->MaxCount); case RPC_FC_C_CSTRING: case RPC_FC_C_WSTRING: if (fc == RPC_FC_C_CSTRING) esize = 1; else esize = 2; if (pFormat[1] == RPC_FC_STRING_SIZED) ReadConformance(pStubMsg, pFormat + 2); else ReadConformance(pStubMsg, NULL); return safe_multiply(esize, pStubMsg->MaxCount); default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); } } static inline ULONG array_read_variance_and_unmarshall( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc, unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall) { ULONG bufsize, memsize; WORD esize; unsigned char alignment; unsigned char *saved_buffer; ULONG offset; switch (fc) { case RPC_FC_CARRAY: esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); pFormat = SkipConformance(pStubMsg, pFormat + 4); ALIGN_POINTER(pStubMsg->Buffer, alignment); if (fUnmarshall) { if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, memsize); else { if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory) /* for servers, we just point straight into the RPC buffer */ *ppMemory = pStubMsg->Buffer; } saved_buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); pStubMsg->BufferMark = saved_buffer; EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); TRACE("copying %p to %p\n", saved_buffer, *ppMemory); if (*ppMemory != saved_buffer) memcpy(*ppMemory, saved_buffer, bufsize); } return bufsize; case RPC_FC_CVARRAY: esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; pFormat = SkipConformance(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 (fUnmarshall) { offset = pStubMsg->Offset; if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, memsize); saved_buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); pStubMsg->BufferMark = saved_buffer; EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); memcpy(*ppMemory + offset, saved_buffer, bufsize); } return bufsize; case RPC_FC_C_CSTRING: case RPC_FC_C_WSTRING: if (fc == RPC_FC_C_CSTRING) esize = 1; else esize = 2; ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) { ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", pStubMsg->ActualCount, pStubMsg->MaxCount); RpcRaiseException(RPC_S_INVALID_BOUND); } if (pStubMsg->Offset) { ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); RpcRaiseException(RPC_S_INVALID_BOUND); } memsize = safe_multiply(esize, pStubMsg->MaxCount); bufsize = safe_multiply(esize, pStubMsg->ActualCount); validate_string_data(pStubMsg, bufsize, esize); if (fUnmarshall) { if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, memsize); else { if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount)) /* if the data in the RPC buffer is big enough, we just point * straight into it */ *ppMemory = pStubMsg->Buffer; else if (!*ppMemory) *ppMemory = NdrAllocate(pStubMsg, memsize); } if (*ppMemory == pStubMsg->Buffer) safe_buffer_increment(pStubMsg, bufsize); else safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); if (*pFormat == RPC_FC_C_CSTRING) TRACE("string=%s\n", debugstr_a((char*)*ppMemory)); else TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); } return bufsize; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); } } static inline void array_memory_size( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, unsigned char fHasPointers) { ULONG bufsize, memsize; DWORD esize; unsigned char alignment; switch (fc) { case RPC_FC_CARRAY: esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; pFormat = SkipConformance(pStubMsg, pFormat + 4); bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); pStubMsg->MemorySize += memsize; ALIGN_POINTER(pStubMsg->Buffer, alignment); if (fHasPointers) pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); if (fHasPointers) EmbeddedPointerMemorySize(pStubMsg, pFormat); break; case RPC_FC_CVARRAY: esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; pFormat = SkipConformance(pStubMsg, pFormat + 4); pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); bufsize = safe_multiply(esize, pStubMsg->ActualCount); memsize = safe_multiply(esize, pStubMsg->MaxCount); pStubMsg->MemorySize += memsize; ALIGN_POINTER(pStubMsg->Buffer, alignment); if (fHasPointers) pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); if (fHasPointers) EmbeddedPointerMemorySize(pStubMsg, pFormat); break; case RPC_FC_C_CSTRING: case RPC_FC_C_WSTRING: if (fc == RPC_FC_C_CSTRING) esize = 1; else esize = 2; ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) { ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", pStubMsg->ActualCount, pStubMsg->MaxCount); RpcRaiseException(RPC_S_INVALID_BOUND); } if (pStubMsg->Offset) { ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); RpcRaiseException(RPC_S_INVALID_BOUND); } memsize = safe_multiply(esize, pStubMsg->MaxCount); bufsize = safe_multiply(esize, pStubMsg->ActualCount); validate_string_data(pStubMsg, bufsize, esize); safe_buffer_increment(pStubMsg, bufsize); pStubMsg->MemorySize += memsize; break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); } } static inline void array_free( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { switch (fc) { case RPC_FC_CARRAY: pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); if (fHasPointers) EmbeddedPointerFree(pStubMsg, pMemory, pFormat); break; case RPC_FC_CVARRAY: pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); if (fHasPointers) EmbeddedPointerFree(pStubMsg, pMemory, pFormat); break; case RPC_FC_C_CSTRING: case RPC_FC_C_WSTRING: /* No embedded pointers so nothing to do */ break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); } } /* * 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) { TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) { ERR("Unhandled string type: %#x\n", pFormat[0]); RpcRaiseException(RPC_X_BAD_STUB_DATA); } /* allow compiler to optimise inline function by passing constant into * these functions */ if (pFormat[0] == RPC_FC_C_CSTRING) { array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage, pFormat); array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage, pFormat, TRUE /* fHasPointers */); } else { array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage, pFormat); array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage, pFormat, TRUE /* fHasPointers */); } return NULL; } /*********************************************************************** * NdrConformantStringBufferSize [RPCRT4.@] */ void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) { TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) { ERR("Unhandled string type: %#x\n", pFormat[0]); RpcRaiseException(RPC_X_BAD_STUB_DATA); } /* allow compiler to optimise inline function by passing constant into * these functions */ if (pFormat[0] == RPC_FC_C_CSTRING) { array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat); array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); } else { array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat); array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); } } /************************************************************************ * NdrConformantStringMemorySize [RPCRT4.@] */ ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ) { TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) { ERR("Unhandled string type: %#x\n", pFormat[0]); RpcRaiseException(RPC_X_BAD_STUB_DATA); } /* allow compiler to optimise inline function by passing constant into * these functions */ if (pFormat[0] == RPC_FC_C_CSTRING) { array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat); array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat, TRUE /* fHasPointers */); } else { array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat); array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat, TRUE /* fHasPointers */); } return pStubMsg->MemorySize; } /************************************************************************ * NdrConformantStringUnmarshall [RPCRT4.@] */ unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) { TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", pStubMsg, *ppMemory, pFormat, fMustAlloc); if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) { ERR("Unhandled string type: %#x\n", *pFormat); RpcRaiseException(RPC_X_BAD_STUB_DATA); } /* allow compiler to optimise inline function by passing constant into * these functions */ if (pFormat[0] == RPC_FC_C_CSTRING) { array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat); array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory, pFormat, fMustAlloc, TRUE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */); } else { array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat); array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory, pFormat, fMustAlloc, TRUE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */); } return NULL; } /*********************************************************************** * NdrNonConformantStringMarshall [RPCRT4.@] */ unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { ULONG esize, size, maxsize; TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); maxsize = *(USHORT *)&pFormat[2]; if (*pFormat == RPC_FC_CSTRING) { ULONG i; const char *str = (const char *)pMemory; for (i = 0; i < maxsize && *str; i++, str++) ; TRACE("string=%s\n", debugstr_an(str, i)); pStubMsg->ActualCount = i + 1; esize = 1; } else if (*pFormat == RPC_FC_WSTRING) { ULONG i; const WCHAR *str = (const WCHAR *)pMemory; for (i = 0; i < maxsize && *str; i++, str++) ; TRACE("string=%s\n", debugstr_wn(str, i)); pStubMsg->ActualCount = i + 1; esize = 2; } else { ERR("Unhandled string type: %#x\n", *pFormat); RpcRaiseException(RPC_X_BAD_STUB_DATA); } pStubMsg->Offset = 0; WriteVariance(pStubMsg); size = safe_multiply(esize, pStubMsg->ActualCount); safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ return NULL; } /*********************************************************************** * NdrNonConformantStringUnmarshall [RPCRT4.@] */ unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { ULONG bufsize, memsize, esize, maxsize; TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", pStubMsg, *ppMemory, pFormat, fMustAlloc); maxsize = *(USHORT *)&pFormat[2]; ReadVariance(pStubMsg, NULL, maxsize); if (pStubMsg->Offset) { ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); RpcRaiseException(RPC_S_INVALID_BOUND); } if (*pFormat == RPC_FC_CSTRING) esize = 1; else if (*pFormat == RPC_FC_WSTRING) esize = 2; else { ERR("Unhandled string type: %#x\n", *pFormat); RpcRaiseException(RPC_X_BAD_STUB_DATA); } memsize = esize * maxsize; bufsize = safe_multiply(esize, pStubMsg->ActualCount); validate_string_data(pStubMsg, bufsize, esize); if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, memsize); safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); if (*pFormat == RPC_FC_CSTRING) { TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount)); } else if (*pFormat == RPC_FC_WSTRING) { TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount)); } return NULL; } /*********************************************************************** * NdrNonConformantStringBufferSize [RPCRT4.@] */ void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { ULONG esize, maxsize; TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); maxsize = *(USHORT *)&pFormat[2]; SizeVariance(pStubMsg); if (*pFormat == RPC_FC_CSTRING) { ULONG i; const char *str = (const char *)pMemory; for (i = 0; i < maxsize && *str; i++, str++) ; TRACE("string=%s\n", debugstr_an(str, i)); pStubMsg->ActualCount = i + 1; esize = 1; } else if (*pFormat == RPC_FC_WSTRING) { ULONG i; const WCHAR *str = (const WCHAR *)pMemory; for (i = 0; i < maxsize && *str; i++, str++) ; TRACE("string=%s\n", debugstr_wn(str, i)); pStubMsg->ActualCount = i + 1; esize = 2; } else { ERR("Unhandled string type: %#x\n", *pFormat); RpcRaiseException(RPC_X_BAD_STUB_DATA); } safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); } /*********************************************************************** * NdrNonConformantStringMemorySize [RPCRT4.@] */ ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { ULONG bufsize, memsize, esize, maxsize; TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); maxsize = *(USHORT *)&pFormat[2]; ReadVariance(pStubMsg, NULL, maxsize); if (pStubMsg->Offset) { ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); RpcRaiseException(RPC_S_INVALID_BOUND); } if (*pFormat == RPC_FC_CSTRING) esize = 1; else if (*pFormat == RPC_FC_WSTRING) esize = 2; else { ERR("Unhandled string type: %#x\n", *pFormat); RpcRaiseException(RPC_X_BAD_STUB_DATA); } memsize = esize * maxsize; bufsize = safe_multiply(esize, pStubMsg->ActualCount); validate_string_data(pStubMsg, bufsize, esize); safe_buffer_increment(pStubMsg, bufsize); pStubMsg->MemorySize += memsize; return pStubMsg->MemorySize; } /* Complex types */ #include "pshpack1.h" typedef struct { unsigned char type; unsigned char flags_type; /* flags in upper nibble, type in lower nibble */ ULONG low_value; ULONG high_value; } NDR_RANGE; #include "poppack.h" static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) { switch (*pFormat) { case RPC_FC_STRUCT: case RPC_FC_PSTRUCT: case RPC_FC_CSTRUCT: case RPC_FC_BOGUS_STRUCT: case RPC_FC_SMFARRAY: case RPC_FC_SMVARRAY: case RPC_FC_CSTRING: return *(const WORD*)&pFormat[2]; case RPC_FC_USER_MARSHAL: return *(const WORD*)&pFormat[4]; case RPC_FC_RANGE: { switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) { case RPC_FC_BYTE: case RPC_FC_CHAR: case RPC_FC_SMALL: case RPC_FC_USMALL: return sizeof(UCHAR); case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: return sizeof(USHORT); case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: return sizeof(ULONG); case RPC_FC_FLOAT: return sizeof(float); case RPC_FC_DOUBLE: return sizeof(double); case RPC_FC_HYPER: return sizeof(ULONGLONG); case RPC_FC_ENUM16: return sizeof(UINT); default: ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf); RpcRaiseException(RPC_X_BAD_STUB_DATA); } } 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 *); case RPC_FC_WSTRING: return *(const WORD*)&pFormat[2] * 2; default: FIXME("unhandled embedded type %02x\n", *pFormat); } return 0; } static ULONG 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; ULONG 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); safe_copy_to_buffer(pStubMsg, pMemory, 1); pMemory += 1; break; case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory); safe_copy_to_buffer(pStubMsg, pMemory, 2); pMemory += 2; break; case RPC_FC_ENUM16: TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory); if (32767 < *(DWORD*)pMemory) RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); safe_copy_to_buffer(pStubMsg, pMemory, 2); pMemory += 4; break; case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory); safe_copy_to_buffer(pStubMsg, pMemory, 4); pMemory += 4; break; case RPC_FC_HYPER: TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); safe_copy_to_buffer(pStubMsg, pMemory, 8); pMemory += 8; break; case RPC_FC_POINTER: { unsigned char *saved_buffer; int pointer_buffer_mark_set = 0; TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory); TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer); if (*pPointer != RPC_FC_RP) ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; pointer_buffer_mark_set = 1; } else if (*pPointer != RPC_FC_RP) safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer); if (pointer_buffer_mark_set) { STD_OVERFLOW_CHECK(pStubMsg); pStubMsg->PointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = saved_buffer; if (*pPointer != RPC_FC_RP) safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ } TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer); pPointer += 4; pMemory += sizeof(void *); break; } case RPC_FC_ALIGNM2: ALIGN_POINTER(pMemory, 2); 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=%d) <= %p\n", size, pMemory); m = NdrMarshaller[*desc & NDR_TABLE_MASK]; if (m) { /* for some reason interface pointers aren't generated as * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet * they still need the derefencing treatment that pointers are * given */ if (*desc == RPC_FC_IP) m(pStubMsg, *(unsigned char **)pMemory, desc); else 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, unsigned char fMustAlloc) { PFORMAT_STRING desc; NDR_UNMARSHALL m; ULONG size; while (*pFormat != RPC_FC_END) { switch (*pFormat) { case RPC_FC_BYTE: case RPC_FC_CHAR: case RPC_FC_SMALL: case RPC_FC_USMALL: safe_copy_from_buffer(pStubMsg, pMemory, 1); TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory); pMemory += 1; break; case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: safe_copy_from_buffer(pStubMsg, pMemory, 2); TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory); pMemory += 2; break; case RPC_FC_ENUM16: safe_copy_from_buffer(pStubMsg, pMemory, 2); *(DWORD*)pMemory &= 0xffff; TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory); if (32767 < *(DWORD*)pMemory) RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); pMemory += 4; break; case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: safe_copy_from_buffer(pStubMsg, pMemory, 4); TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory); pMemory += 4; break; case RPC_FC_HYPER: safe_copy_from_buffer(pStubMsg, pMemory, 8); TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); pMemory += 8; break; case RPC_FC_POINTER: { unsigned char *saved_buffer; int pointer_buffer_mark_set = 0; TRACE("pointer => %p\n", pMemory); if (*pPointer != RPC_FC_RP) ALIGN_POINTER(pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; pointer_buffer_mark_set = 1; } else if (*pPointer != RPC_FC_RP) safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc); if (pointer_buffer_mark_set) { STD_OVERFLOW_CHECK(pStubMsg); pStubMsg->PointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = saved_buffer; if (*pPointer != RPC_FC_RP) safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ } pPointer += 4; pMemory += sizeof(void *); break; } case RPC_FC_ALIGNM2: ALIGN_POINTER_CLEAR(pMemory, 2); break; case RPC_FC_ALIGNM4: ALIGN_POINTER_CLEAR(pMemory, 4); break; case RPC_FC_ALIGNM8: ALIGN_POINTER_CLEAR(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: memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1); 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=%d) => %p\n", size, pMemory); if (fMustAlloc) /* we can't pass fMustAlloc=TRUE into the marshaller for this type * since the type is part of the memory block that is encompassed by * the whole complex type. Memory is forced to allocate when pointers * are set to NULL, so we emulate that part of fMustAlloc=TRUE by * clearing the memory we pass in to the unmarshaller */ memset(pMemory, 0, size); m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; if (m) { /* for some reason interface pointers aren't generated as * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet * they still need the derefencing treatment that pointers are * given */ if (*desc == RPC_FC_IP) m(pStubMsg, (unsigned char **)pMemory, desc, FALSE); else 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; ULONG size; while (*pFormat != RPC_FC_END) { switch (*pFormat) { case RPC_FC_BYTE: case RPC_FC_CHAR: case RPC_FC_SMALL: case RPC_FC_USMALL: safe_buffer_length_increment(pStubMsg, 1); pMemory += 1; break; case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: safe_buffer_length_increment(pStubMsg, 2); pMemory += 2; break; case RPC_FC_ENUM16: safe_buffer_length_increment(pStubMsg, 2); pMemory += 4; break; case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: safe_buffer_length_increment(pStubMsg, 4); pMemory += 4; break; case RPC_FC_HYPER: safe_buffer_length_increment(pStubMsg, 8); pMemory += 8; break; case RPC_FC_POINTER: if (!pStubMsg->IgnoreEmbeddedPointers) { int saved_buffer_length = pStubMsg->BufferLength; pStubMsg->BufferLength = pStubMsg->PointerLength; pStubMsg->PointerLength = 0; if(!pStubMsg->BufferLength) ERR("BufferLength == 0??\n"); PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer); pStubMsg->PointerLength = pStubMsg->BufferLength; pStubMsg->BufferLength = saved_buffer_length; } if (*pPointer != RPC_FC_RP) { ALIGN_LENGTH(pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, 4); } pPointer += 4; pMemory += sizeof(void*); break; case RPC_FC_ALIGNM2: ALIGN_POINTER(pMemory, 2); 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) { /* for some reason interface pointers aren't generated as * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet * they still need the derefencing treatment that pointers are * given */ if (*desc == RPC_FC_IP) m(pStubMsg, *(unsigned char **)pMemory, desc); else 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; ULONG 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_ENUM16: 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 += sizeof(void *); break; case RPC_FC_ALIGNM2: ALIGN_POINTER(pMemory, 2); 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) { /* for some reason interface pointers aren't generated as * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet * they still need the derefencing treatment that pointers are * given */ if (*desc == RPC_FC_IP) m(pStubMsg, *(unsigned char **)pMemory, desc); else m(pStubMsg, pMemory, desc); } pMemory += size; pFormat += 2; continue; case RPC_FC_PAD: break; default: FIXME("unhandled format 0x%02x\n", *pFormat); } pFormat++; } return pMemory; } static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, PFORMAT_STRING pPointer) { PFORMAT_STRING desc; ULONG 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; safe_buffer_increment(pStubMsg, 1); break; case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: size += 2; safe_buffer_increment(pStubMsg, 2); break; case RPC_FC_ENUM16: size += 4; safe_buffer_increment(pStubMsg, 2); break; case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: size += 4; safe_buffer_increment(pStubMsg, 4); break; case RPC_FC_HYPER: size += 8; safe_buffer_increment(pStubMsg, 8); break; case RPC_FC_POINTER: { unsigned char *saved_buffer; int pointer_buffer_mark_set = 0; if (*pPointer != RPC_FC_RP) ALIGN_POINTER(pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; pointer_buffer_mark_set = 1; } else if (*pPointer != RPC_FC_RP) safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ if (!pStubMsg->IgnoreEmbeddedPointers) PointerMemorySize(pStubMsg, saved_buffer, pPointer); if (pointer_buffer_mark_set) { STD_OVERFLOW_CHECK(pStubMsg); pStubMsg->PointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = saved_buffer; if (*pPointer != RPC_FC_RP) safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ } pPointer += 4; size += sizeof(void *); break; } case RPC_FC_ALIGNM2: ALIGN_LENGTH(size, 2); break; case RPC_FC_ALIGNM4: ALIGN_LENGTH(size, 4); break; case RPC_FC_ALIGNM8: ALIGN_LENGTH(size, 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; } ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { PFORMAT_STRING desc; ULONG 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; break; case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: size += 2; break; case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM16: case RPC_FC_ENUM32: size += 4; break; case RPC_FC_HYPER: size += 8; break; case RPC_FC_POINTER: size += sizeof(void *); break; case RPC_FC_ALIGNM2: ALIGN_LENGTH(size, 2); break; case RPC_FC_ALIGNM4: ALIGN_LENGTH(size, 4); break; case RPC_FC_ALIGNM8: ALIGN_LENGTH(size, 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 += EmbeddedComplexSize(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; int pointer_buffer_mark_set = 0; ULONG count = 0; ULONG max_count = 0; ULONG offset = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); if (!pStubMsg->PointerBufferMark) { int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; /* save buffer length */ ULONG saved_buffer_length = pStubMsg->BufferLength; /* get the buffer pointer after complex array data, but before * pointer data */ pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer; pStubMsg->IgnoreEmbeddedPointers = 1; NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; /* save it for use by embedded pointer code later */ pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength; TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer)); pointer_buffer_mark_set = 1; /* restore the original buffer length */ pStubMsg->BufferLength = saved_buffer_length; } ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; pFormat += 2; if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; pFormat += 2; pStubMsg->Memory = pMemory; if (conf_array) { ULONG struct_size = ComplexStructSize(pStubMsg, pFormat); array_compute_and_write_conformance(conf_array[0], pStubMsg, pMemory + struct_size, conf_array); /* these could be changed in ComplexMarshall so save them for later */ max_count = pStubMsg->MaxCount; count = pStubMsg->ActualCount; offset = pStubMsg->Offset; } pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc); if (conf_array) { pStubMsg->MaxCount = max_count; pStubMsg->ActualCount = count; pStubMsg->Offset = offset; array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory, conf_array, TRUE /* fHasPointers */); } pStubMsg->Memory = OldMemory; if (pointer_buffer_mark_set) { pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } 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; int pointer_buffer_mark_set = 0; ULONG count = 0; ULONG max_count = 0; ULONG offset = 0; ULONG array_size = 0; TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); if (!pStubMsg->PointerBufferMark) { int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; /* save buffer pointer */ unsigned char *saved_buffer = pStubMsg->Buffer; /* get the buffer pointer after complex array data, but before * pointer data */ pStubMsg->IgnoreEmbeddedPointers = 1; NdrComplexStructMemorySize(pStubMsg, pFormat); pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; /* save it for use by embedded pointer code later */ pStubMsg->PointerBufferMark = pStubMsg->Buffer; TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer)); pointer_buffer_mark_set = 1; /* restore the original buffer */ pStubMsg->Buffer = saved_buffer; } ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; pFormat += 2; if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; pFormat += 2; if (conf_array) { array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array); size += array_size; /* these could be changed in ComplexMarshall so save them for later */ max_count = pStubMsg->MaxCount; count = pStubMsg->ActualCount; offset = pStubMsg->Offset; } if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, size); pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc); if (conf_array) { pStubMsg->MaxCount = max_count; pStubMsg->ActualCount = count; pStubMsg->Offset = offset; if (fMustAlloc) memset(pMemory, 0, array_size); array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory, conf_array, FALSE, FALSE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */); } if (pointer_buffer_mark_set) { pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } 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; int pointer_length_set = 0; ULONG count = 0; ULONG max_count = 0; ULONG offset = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) { int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; ULONG saved_buffer_length = pStubMsg->BufferLength; /* get the buffer length after complex struct data, but before * pointer data */ pStubMsg->IgnoreEmbeddedPointers = 1; NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; /* save it for use by embedded pointer code later */ pStubMsg->PointerLength = pStubMsg->BufferLength; pointer_length_set = 1; TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length); /* restore the original buffer length */ pStubMsg->BufferLength = saved_buffer_length; } pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; pFormat += 2; if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; pFormat += 2; pStubMsg->Memory = pMemory; if (conf_array) { ULONG struct_size = ComplexStructSize(pStubMsg, pFormat); array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size, conf_array); /* these could be changed in ComplexMarshall so save them for later */ max_count = pStubMsg->MaxCount; count = pStubMsg->ActualCount; offset = pStubMsg->Offset; } pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc); if (conf_array) { pStubMsg->MaxCount = max_count; pStubMsg->ActualCount = count; pStubMsg->Offset = offset; array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array, TRUE /* fHasPointers */); } pStubMsg->Memory = OldMemory; if(pointer_length_set) { pStubMsg->BufferLength = pStubMsg->PointerLength; pStubMsg->PointerLength = 0; } } /*********************************************************************** * NdrComplexStructMemorySize [RPCRT4.@] */ ULONG 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; ULONG count = 0; ULONG max_count = 0; ULONG offset = 0; TRACE("(%p,%p)\n", pStubMsg, pFormat); ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; pFormat += 2; if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; pFormat += 2; if (conf_array) { array_read_conformance(conf_array[0], pStubMsg, conf_array); /* these could be changed in ComplexStructMemorySize so save them for * later */ max_count = pStubMsg->MaxCount; count = pStubMsg->ActualCount; offset = pStubMsg->Offset; } ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc); if (conf_array) { pStubMsg->MaxCount = max_count; pStubMsg->ActualCount = count; pStubMsg->Offset = offset; array_memory_size(conf_array[0], pStubMsg, conf_array, TRUE /* fHasPointers */); } 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 SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)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) array_free(conf_array[0], pStubMsg, pMemory, conf_array, TRUE /* fHasPointers */); pStubMsg->Memory = OldMemory; } /*********************************************************************** * NdrConformantArrayMarshall [RPCRT4.@] */ unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); if (pFormat[0] != RPC_FC_CARRAY) { ERR("invalid format = 0x%x\n", pFormat[0]); RpcRaiseException(RPC_X_BAD_STUB_DATA); } array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat); array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); return NULL; } /*********************************************************************** * NdrConformantArrayUnmarshall [RPCRT4.@] */ unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); if (pFormat[0] != RPC_FC_CARRAY) { ERR("invalid format = 0x%x\n", pFormat[0]); RpcRaiseException(RPC_X_BAD_STUB_DATA); } array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat); array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat, fMustAlloc, TRUE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */); return NULL; } /*********************************************************************** * NdrConformantArrayBufferSize [RPCRT4.@] */ void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); if (pFormat[0] != RPC_FC_CARRAY) { ERR("invalid format = 0x%x\n", pFormat[0]); RpcRaiseException(RPC_X_BAD_STUB_DATA); } array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat); array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); } /*********************************************************************** * NdrConformantArrayMemorySize [RPCRT4.@] */ ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { TRACE("(%p,%p)\n", pStubMsg, pFormat); if (pFormat[0] != RPC_FC_CARRAY) { ERR("invalid format = 0x%x\n", pFormat[0]); RpcRaiseException(RPC_X_BAD_STUB_DATA); } array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat); array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */); 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) { ERR("invalid format = 0x%x\n", pFormat[0]); RpcRaiseException(RPC_X_BAD_STUB_DATA); } array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); } /*********************************************************************** * NdrConformantVaryingArrayMarshall [RPCRT4.@] */ unsigned char* WINAPI NdrConformantVaryingArrayMarshall( 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 NULL; } array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat); array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); return NULL; } /*********************************************************************** * NdrConformantVaryingArrayUnmarshall [RPCRT4.@] */ unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) { 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; } array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat); array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory, pFormat, fMustAlloc, TRUE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */); 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; } array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); } /*********************************************************************** * NdrConformantVaryingArrayBufferSize [RPCRT4.@] */ void WINAPI NdrConformantVaryingArrayBufferSize( 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; } array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat); array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); } /*********************************************************************** * NdrConformantVaryingArrayMemorySize [RPCRT4.@] */ ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ) { TRACE("(%p, %p)\n", pStubMsg, pFormat); if (pFormat[0] != RPC_FC_CVARRAY) { ERR("invalid format type %x\n", pFormat[0]); RpcRaiseException(RPC_S_INTERNAL_ERROR); return pStubMsg->MemorySize; } array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat); array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */); return pStubMsg->MemorySize; } /*********************************************************************** * 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; int pointer_buffer_mark_set = 0; 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; if (!pStubMsg->PointerBufferMark) { /* save buffer fields that may be changed by buffer sizer functions * and that may be needed later on */ int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; ULONG saved_buffer_length = pStubMsg->BufferLength; ULONG_PTR saved_max_count = pStubMsg->MaxCount; ULONG saved_offset = pStubMsg->Offset; ULONG saved_actual_count = pStubMsg->ActualCount; /* get the buffer pointer after complex array data, but before * pointer data */ pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer; pStubMsg->IgnoreEmbeddedPointers = 1; NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; /* save it for use by embedded pointer code later */ pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength; TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer)); pointer_buffer_mark_set = 1; /* restore fields */ pStubMsg->ActualCount = saved_actual_count; pStubMsg->Offset = saved_offset; pStubMsg->MaxCount = saved_max_count; pStubMsg->BufferLength = saved_buffer_length; } 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 = %d\n", pStubMsg->ActualCount); WriteConformance(pStubMsg); if (variance_present) WriteVariance(pStubMsg); ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); count = pStubMsg->ActualCount; for (i = 0; i < count; i++) pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL); STD_OVERFLOW_CHECK(pStubMsg); if (pointer_buffer_mark_set) { pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } return NULL; } /*********************************************************************** * NdrComplexArrayUnmarshall [RPCRT4.@] */ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { ULONG i, count, size; unsigned char alignment; unsigned char *pMemory; unsigned char *saved_buffer; int pointer_buffer_mark_set = 0; int saved_ignore_embedded; 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; saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; /* save buffer pointer */ saved_buffer = pStubMsg->Buffer; /* get the buffer pointer after complex array data, but before * pointer data */ pStubMsg->IgnoreEmbeddedPointers = 1; pStubMsg->MemorySize = 0; NdrComplexArrayMemorySize(pStubMsg, pFormat); size = pStubMsg->MemorySize; pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer)); if (!pStubMsg->PointerBufferMark) { /* save it for use by embedded pointer code later */ pStubMsg->PointerBufferMark = pStubMsg->Buffer; pointer_buffer_mark_set = 1; } /* restore the original buffer */ pStubMsg->Buffer = saved_buffer; pFormat += 4; pFormat = ReadConformance(pStubMsg, pFormat); pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, size); ALIGN_POINTER(pStubMsg->Buffer, alignment); pMemory = *ppMemory; count = pStubMsg->ActualCount; for (i = 0; i < count; i++) pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc); if (pointer_buffer_mark_set) { pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = 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; int pointer_length_set = 0; 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; if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) { /* save buffer fields that may be changed by buffer sizer functions * and that may be needed later on */ int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; ULONG saved_buffer_length = pStubMsg->BufferLength; ULONG_PTR saved_max_count = pStubMsg->MaxCount; ULONG saved_offset = pStubMsg->Offset; ULONG saved_actual_count = pStubMsg->ActualCount; /* get the buffer pointer after complex array data, but before * pointer data */ pStubMsg->IgnoreEmbeddedPointers = 1; NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; /* save it for use by embedded pointer code later */ pStubMsg->PointerLength = pStubMsg->BufferLength; pointer_length_set = 1; /* restore fields */ pStubMsg->ActualCount = saved_actual_count; pStubMsg->Offset = saved_offset; pStubMsg->MaxCount = saved_max_count; pStubMsg->BufferLength = saved_buffer_length; } 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 = %d\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); if(pointer_length_set) { pStubMsg->BufferLength = pStubMsg->PointerLength; pStubMsg->PointerLength = 0; } } /*********************************************************************** * NdrComplexArrayMemorySize [RPCRT4.@] */ ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { ULONG i, count, esize, SavedMemorySize, MemorySize; unsigned char alignment; 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; esize = ComplexStructSize(pStubMsg, pFormat); MemorySize = safe_multiply(pStubMsg->MaxCount, esize); count = pStubMsg->ActualCount; for (i = 0; i < count; i++) ComplexStructMemorySize(pStubMsg, pFormat, NULL); 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 = %d\n", pStubMsg->ActualCount); count = pStubMsg->ActualCount; for (i = 0; i < count; i++) pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL); } static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg, USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat, USER_MARSHAL_CB *umcb) { umcb->Flags = MAKELONG(pStubMsg->dwDestContext, pStubMsg->RpcMsg->DataRepresentation); umcb->pStubMsg = pStubMsg; umcb->pReserve = NULL; umcb->Signature = USER_MARSHAL_CB_SIGNATURE; umcb->CBType = cbtype; umcb->pFormat = pFormat; umcb->pTypeFormat = NULL /* FIXME */; } #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 char *saved_buffer = NULL; USER_MARSHAL_CB umcb; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); TRACE("index=%d\n", index); UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb); if (flags & USER_MARSHAL_POINTER) { ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX); pStubMsg->Buffer += 4; if (pStubMsg->PointerBufferMark) { saved_buffer = pStubMsg->Buffer; pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8); } else ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1); pStubMsg->Buffer = pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall( &umcb.Flags, pStubMsg->Buffer, pMemory); if (saved_buffer) { STD_OVERFLOW_CHECK(pStubMsg); pStubMsg->PointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = saved_buffer; } 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 char *saved_buffer = NULL; USER_MARSHAL_CB umcb; TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); TRACE("index=%d\n", index); UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb); if (flags & USER_MARSHAL_POINTER) { ALIGN_POINTER(pStubMsg->Buffer, 4); /* skip pointer prefix */ pStubMsg->Buffer += 4; if (pStubMsg->PointerBufferMark) { saved_buffer = pStubMsg->Buffer; pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } ALIGN_POINTER(pStubMsg->Buffer, 8); } else ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) { *ppMemory = NdrAllocate(pStubMsg, memsize); memset(*ppMemory, 0, memsize); } pStubMsg->Buffer = pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall( &umcb.Flags, pStubMsg->Buffer, *ppMemory); if (saved_buffer) { STD_OVERFLOW_CHECK(pStubMsg); pStubMsg->PointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = saved_buffer; } 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]; USER_MARSHAL_CB umcb; ULONG saved_buffer_length = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); TRACE("index=%d\n", index); UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb); if (flags & USER_MARSHAL_POINTER) { ALIGN_LENGTH(pStubMsg->BufferLength, 4); /* skip pointer prefix */ safe_buffer_length_increment(pStubMsg, 4); if (pStubMsg->IgnoreEmbeddedPointers) return; if (pStubMsg->PointerLength) { saved_buffer_length = pStubMsg->BufferLength; pStubMsg->BufferLength = pStubMsg->PointerLength; pStubMsg->PointerLength = 0; } ALIGN_LENGTH(pStubMsg->BufferLength, 8); } else ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1); if (bufsize) { TRACE("size=%d\n", bufsize); safe_buffer_length_increment(pStubMsg, bufsize); } else pStubMsg->BufferLength = pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize( &umcb.Flags, pStubMsg->BufferLength, pMemory); if (saved_buffer_length) { pStubMsg->PointerLength = pStubMsg->BufferLength; pStubMsg->BufferLength = saved_buffer_length; } } /*********************************************************************** * NdrUserMarshalMemorySize [RPCRT4.@] */ ULONG 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; if (pStubMsg->IgnoreEmbeddedPointers) return pStubMsg->MemorySize; ALIGN_POINTER(pStubMsg->Buffer, 8); } else ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); if (!bufsize) FIXME("not implemented for varying buffer size\n"); 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]; USER_MARSHAL_CB umcb; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); TRACE("index=%d\n", index); UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb); pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree( &umcb.Flags, pMemory); } /*********************************************************************** * NdrGetUserMarshalInfo [RPCRT4.@] */ RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi) { USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags); TRACE("(%p,%u,%p)\n", flags, level, umi); if (level != 1) return RPC_S_INVALID_ARG; memset(&umi->Level1, 0, sizeof(umi->Level1)); umi->InformationLevel = level; if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE) return RPC_S_INVALID_ARG; umi->Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate; umi->Level1.pfnFree = umcb->pStubMsg->pfnFree; umi->Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer; switch (umcb->CBType) { case USER_MARSHAL_CB_MARSHALL: case USER_MARSHAL_CB_UNMARSHALL: { RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg; unsigned char *buffer_start = msg->Buffer; unsigned char *buffer_end = (unsigned char *)msg->Buffer + msg->BufferLength; if (umcb->pStubMsg->Buffer < buffer_start || umcb->pStubMsg->Buffer > buffer_end) return ERROR_INVALID_USER_BUFFER; umi->Level1.Buffer = umcb->pStubMsg->Buffer; umi->Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer; break; } case USER_MARSHAL_CB_BUFFER_SIZE: case USER_MARSHAL_CB_FREE: break; default: WARN("unrecognised CBType %d\n", umcb->CBType); } return RPC_S_OK; } /*********************************************************************** * 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 == %d): stub.\n", pStubMsg, pFormat, NumberParams); /* FIXME: since this stub doesn't do any converting, the proper behavior is to raise an exception */ } #include "pshpack1.h" 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; #include "poppack.h" /*********************************************************************** * NdrConformantStructMarshall [RPCRT4.@] */ unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { const NDR_CSTRUCT_FORMAT *pCStructFormat = (const 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 = (const 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_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCStructFormat->memory_size); bufsize = safe_multiply(esize, pStubMsg->MaxCount); if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */ { ERR("integer overflow of memory_size %u with bufsize %u\n", pCStructFormat->memory_size, bufsize); RpcRaiseException(RPC_X_BAD_STUB_DATA); } /* copy constant sized part of struct */ pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize); if (pCStructFormat->type == RPC_FC_CPSTRUCT) EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); 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 = (const NDR_CSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCArrayFormat; ULONG esize, bufsize; unsigned char *saved_buffer; 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 = (const 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); if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */ { ERR("integer overflow of memory_size %u with bufsize %u\n", pCStructFormat->memory_size, bufsize); RpcRaiseException(RPC_X_BAD_STUB_DATA); } if (fMustAlloc) { SIZE_T size = pCStructFormat->memory_size + bufsize; *ppMemory = NdrAllocate(pStubMsg, size); } else { if (!pStubMsg->IsClient && !*ppMemory) /* for servers, we just point straight into the RPC buffer */ *ppMemory = pStubMsg->Buffer; } saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize); if (pCStructFormat->type == RPC_FC_CPSTRUCT) EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); TRACE("copying %p to %p\n", saved_buffer, *ppMemory); if (*ppMemory != saved_buffer) memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize); return NULL; } /*********************************************************************** * NdrConformantStructBufferSize [RPCRT4.@] */ void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { const NDR_CSTRUCT_FORMAT * pCStructFormat = (const 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 = (const 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); safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size); safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize)); if (pCStructFormat->type == RPC_FC_CPSTRUCT) EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); } /*********************************************************************** * NdrConformantStructMemorySize [RPCRT4.@] */ ULONG 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) { const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCArrayFormat; 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 = (const 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; } ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat + 4, 0); TRACE("memory_size = %d\n", pCStructFormat->memory_size); /* copy constant sized part of struct */ pStubMsg->BufferMark = pStubMsg->Buffer; if (pCStructFormat->type == RPC_FC_CPSTRUCT) EmbeddedPointerFree(pStubMsg, pMemory, pFormat); } /*********************************************************************** * NdrConformantVaryingStructMarshall [RPCRT4.@] */ unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCVArrayFormat; 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 = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg, pMemory + pCVStructFormat->memory_size, pCVArrayFormat); ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); /* write constant sized part */ pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size); array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg, pMemory + pCVStructFormat->memory_size, pCVArrayFormat, FALSE /* fHasPointers */); EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); 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 = (const NDR_CVSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCVArrayFormat; ULONG memsize, bufsize; unsigned char *saved_buffer, *saved_array_buffer; ULONG offset; unsigned char *array_memory; 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 = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; memsize = array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat); 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 (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) { SIZE_T size = pCVStructFormat->memory_size + memsize; *ppMemory = NdrAllocate(pStubMsg, size); } /* mark the start of the constant data */ saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size); array_memory = *ppMemory + pCVStructFormat->memory_size; bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg, &array_memory, pCVArrayFormat, FALSE /* fMustAlloc */, FALSE /* fUseServerBufferMemory */, FALSE /* fUnmarshall */); /* save offset in case unmarshalling pointers changes it */ offset = pStubMsg->Offset; /* mark the start of the array data */ saved_array_buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); /* copy the constant data */ memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size); /* copy the array data */ TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size); memcpy(*ppMemory + pCVStructFormat->memory_size + offset, saved_array_buffer, bufsize); if (*pCVArrayFormat == RPC_FC_C_CSTRING) TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size))); else if (*pCVArrayFormat == RPC_FC_C_WSTRING) TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size))); return NULL; } /*********************************************************************** * NdrConformantVaryingStructBufferSize [RPCRT4.@] */ void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCVArrayFormat; 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 = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg, pMemory + pCVStructFormat->memory_size, pCVArrayFormat); ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size); array_buffer_size(*pCVArrayFormat, pStubMsg, pMemory + pCVStructFormat->memory_size, pCVArrayFormat, FALSE /* fHasPointers */); EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); } /*********************************************************************** * NdrConformantVaryingStructMemorySize [RPCRT4.@] */ ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCVArrayFormat; 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 = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat); ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size); array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat, FALSE /* fHasPointers */); pStubMsg->MemorySize += pCVStructFormat->memory_size; EmbeddedPointerMemorySize(pStubMsg, pFormat); return pStubMsg->MemorySize; } /*********************************************************************** * NdrConformantVaryingStructFree [RPCRT4.@] */ void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCVArrayFormat; 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 = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; array_free(*pCVArrayFormat, pStubMsg, pMemory + pCVStructFormat->memory_size, pCVArrayFormat, FALSE /* fHasPointers */); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); EmbeddedPointerFree(pStubMsg, pMemory, pFormat); } #include "pshpack1.h" typedef struct { unsigned char type; unsigned char alignment; unsigned short total_size; } NDR_SMFARRAY_FORMAT; typedef struct { unsigned char type; unsigned char alignment; ULONG total_size; } NDR_LGFARRAY_FORMAT; #include "poppack.h" /*********************************************************************** * 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; ULONG 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_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) { total_size = pSmFArrayFormat->total_size; pFormat = (const unsigned char *)(pSmFArrayFormat + 1); } else { const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; total_size = pLgFArrayFormat->total_size; pFormat = (const unsigned char *)(pLgFArrayFormat + 1); } pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory, 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; ULONG total_size; unsigned char *saved_buffer; 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 = (const unsigned char *)(pSmFArrayFormat + 1); } else { const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; total_size = pLgFArrayFormat->total_size; pFormat = (const unsigned char *)(pLgFArrayFormat + 1); } if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, total_size); else { if (!pStubMsg->IsClient && !*ppMemory) /* for servers, we just point straight into the RPC buffer */ *ppMemory = pStubMsg->Buffer; } saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, total_size); pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); TRACE("copying %p to %p\n", saved_buffer, *ppMemory); if (*ppMemory != saved_buffer) memcpy(*ppMemory, saved_buffer, total_size); 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; ULONG 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 = (const unsigned char *)(pSmFArrayFormat + 1); } else { const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; total_size = pLgFArrayFormat->total_size; pFormat = (const unsigned char *)(pLgFArrayFormat + 1); } safe_buffer_length_increment(pStubMsg, total_size); EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); } /*********************************************************************** * NdrFixedArrayMemorySize [RPCRT4.@] */ ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; ULONG 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 = (const unsigned char *)(pSmFArrayFormat + 1); } else { const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; total_size = pLgFArrayFormat->total_size; pFormat = (const unsigned char *)(pLgFArrayFormat + 1); } pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 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 = (const unsigned char *)(pSmFArrayFormat + 1); else { const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; pFormat = (const 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_CLEAR(pStubMsg->Buffer, alignment); bufsize = safe_multiply(esize, pStubMsg->ActualCount); pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize); EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); 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; unsigned char *saved_buffer; ULONG offset; 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); offset = pStubMsg->Offset; if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, size); saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); memcpy(*ppMemory + offset, saved_buffer, bufsize); 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); safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); } /*********************************************************************** * NdrVaryingArrayMemorySize [RPCRT4.@] */ ULONG 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); safe_buffer_increment(pStubMsg, 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) { 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; } 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); } static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory) { switch (fc) { case RPC_FC_BYTE: case RPC_FC_CHAR: case RPC_FC_SMALL: case RPC_FC_USMALL: return *pMemory; case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: case RPC_FC_ENUM16: return *(const USHORT *)pMemory; case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: return *(const ULONG *)pMemory; default: FIXME("Unhandled base type: 0x%02x\n", fc); return 0; } } static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg, ULONG 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%x 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%x\n", discriminant); return NULL; } } return pFormat; } static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat) { unsigned short type; pFormat += 2; pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, 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; int pointer_buffer_mark_set = 0; switch(*desc) { case RPC_FC_RP: case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; pointer_buffer_mark_set = 1; } else safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc); if (pointer_buffer_mark_set) { STD_OVERFLOW_CHECK(pStubMsg); pStubMsg->PointerBufferMark = pStubMsg->Buffer; if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); RpcRaiseException(RPC_X_BAD_STUB_DATA); } pStubMsg->Buffer = saved_buffer + 4; } break; default: m(pStubMsg, pMemory, desc); } } else FIXME("no marshaller for embedded type %02x\n", *desc); } return NULL; } static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, ULONG discriminant, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { unsigned short type; pFormat += 2; pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); if(!pFormat) return NULL; type = *(const unsigned short*)pFormat; if((type & 0xff00) == 0x8000) { unsigned char basetype = LOBYTE(type); return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE); } else { PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; if (m) { unsigned char *saved_buffer = NULL; int pointer_buffer_mark_set = 0; 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; if (pStubMsg->PointerBufferMark) { pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; pointer_buffer_mark_set = 1; } else pStubMsg->Buffer += 4; /* for pointer ID */ if (saved_buffer + 4 > pStubMsg->BufferEnd) { ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", saved_buffer, pStubMsg->BufferEnd); RpcRaiseException(RPC_X_BAD_STUB_DATA); } PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc); if (pointer_buffer_mark_set) { STD_OVERFLOW_CHECK(pStubMsg); pStubMsg->PointerBufferMark = pStubMsg->Buffer; pStubMsg->Buffer = saved_buffer + 4; } break; default: m(pStubMsg, ppMemory, desc, fMustAlloc); } } else FIXME("no marshaller for embedded type %02x\n", *desc); } return NULL; } static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat) { unsigned short type; pFormat += 2; pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, 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); safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */ if (!pStubMsg->IgnoreEmbeddedPointers) { int saved_buffer_length = pStubMsg->BufferLength; pStubMsg->BufferLength = pStubMsg->PointerLength; pStubMsg->PointerLength = 0; if(!pStubMsg->BufferLength) ERR("BufferLength == 0??\n"); PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc); pStubMsg->PointerLength = pStubMsg->BufferLength; pStubMsg->BufferLength = saved_buffer_length; } break; default: m(pStubMsg, pMemory, desc); } } else FIXME("no buffersizer for embedded type %02x\n", *desc); } } static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg, ULONG discriminant, PFORMAT_STRING pFormat) { unsigned short type, size; size = *(const unsigned short*)pFormat; pStubMsg->Memory += size; pFormat += 2; pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); if(!pFormat) return 0; 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; safe_buffer_increment(pStubMsg, 4); ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); pStubMsg->MemorySize += sizeof(void *); if (!pStubMsg->IgnoreEmbeddedPointers) 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; } static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat) { unsigned short type; pFormat += 2; pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); if(!pFormat) return; type = *(const unsigned short*)pFormat; if((type & 0xff00) != 0x8000) { PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK]; if (m) { switch(*desc) { case RPC_FC_RP: case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: PointerFree(pStubMsg, *(unsigned char **)pMemory, desc); break; default: m(pStubMsg, pMemory, desc); } } } } /*********************************************************************** * NdrEncapsulatedUnionMarshall [RPCRT4.@] */ unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { unsigned char switch_type; unsigned char increment; ULONG switch_value; TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); pFormat++; switch_type = *pFormat & 0xf; increment = (*pFormat & 0xf0) >> 4; pFormat++; ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment); switch_value = get_discriminant(switch_type, pMemory); TRACE("got switch value 0x%x\n", switch_value); NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type); pMemory += increment; return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat); } /*********************************************************************** * NdrEncapsulatedUnionUnmarshall [RPCRT4.@] */ unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { unsigned char switch_type; unsigned char increment; ULONG switch_value; unsigned short size; unsigned char *pMemoryArm; TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); pFormat++; switch_type = *pFormat & 0xf; increment = (*pFormat & 0xf0) >> 4; pFormat++; ALIGN_POINTER(pStubMsg->Buffer, increment); switch_value = get_discriminant(switch_type, pStubMsg->Buffer); TRACE("got switch value 0x%x\n", switch_value); size = *(const unsigned short*)pFormat + increment; if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, size); /* we can't pass fMustAlloc=TRUE into the marshaller for the arm * since the arm is part of the memory block that is encompassed by * the whole union. Memory is forced to allocate when pointers * are set to NULL, so we emulate that part of fMustAlloc=TRUE by * clearing the memory we pass in to the unmarshaller */ if (fMustAlloc) memset(*ppMemory, 0, size); NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE); pMemoryArm = *ppMemory + increment; return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE); } /*********************************************************************** * NdrEncapsulatedUnionBufferSize [RPCRT4.@] */ void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { unsigned char switch_type; unsigned char increment; ULONG switch_value; TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); pFormat++; switch_type = *pFormat & 0xf; increment = (*pFormat & 0xf0) >> 4; pFormat++; ALIGN_LENGTH(pStubMsg->BufferLength, increment); switch_value = get_discriminant(switch_type, pMemory); TRACE("got switch value 0x%x\n", switch_value); /* Add discriminant size */ NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type); pMemory += increment; union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat); } /*********************************************************************** * NdrEncapsulatedUnionMemorySize [RPCRT4.@] */ ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { unsigned char switch_type; unsigned char increment; ULONG switch_value; switch_type = *pFormat & 0xf; increment = (*pFormat & 0xf0) >> 4; pFormat++; ALIGN_POINTER(pStubMsg->Buffer, increment); switch_value = get_discriminant(switch_type, pStubMsg->Buffer); TRACE("got switch value 0x%x\n", switch_value); pStubMsg->Memory += increment; return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat); } /*********************************************************************** * NdrEncapsulatedUnionFree [RPCRT4.@] */ void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { unsigned char switch_type; unsigned char increment; ULONG switch_value; TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); pFormat++; switch_type = *pFormat & 0xf; increment = (*pFormat & 0xf0) >> 4; pFormat++; switch_value = get_discriminant(switch_type, pMemory); TRACE("got switch value 0x%x\n", switch_value); pMemory += increment; union_arm_free(pStubMsg, pMemory, switch_value, pFormat); } /*********************************************************************** * NdrNonEncapsulatedUnionMarshall [RPCRT4.@] */ unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { 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); return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); } 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: { UCHAR d; safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); discriminant = d; break; } case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: { USHORT d; ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); discriminant = d; break; } case RPC_FC_LONG: case RPC_FC_ULONG: { ULONG d; ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); discriminant = d; 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 size; TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); pFormat++; /* Unmarshall discriminant */ discriminant = unmarshall_discriminant(pStubMsg, &pFormat); TRACE("unmarshalled discriminant %x\n", discriminant); pFormat += *(const SHORT*)pFormat; size = *(const unsigned short*)pFormat; if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, size); /* we can't pass fMustAlloc=TRUE into the marshaller for the arm * since the arm is part of the memory block that is encompassed by * the whole union. Memory is forced to allocate when pointers * are set to NULL, so we emulate that part of fMustAlloc=TRUE by * clearing the memory we pass in to the unmarshaller */ if (fMustAlloc) memset(*ppMemory, 0, size); return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE); } /*********************************************************************** * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@] */ void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { 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); union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); } /*********************************************************************** * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@] */ ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { ULONG discriminant; pFormat++; /* Unmarshall discriminant */ discriminant = unmarshall_discriminant(pStubMsg, &pFormat); TRACE("unmarshalled discriminant 0x%x\n", discriminant); return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat); } /*********************************************************************** * NdrNonEncapsulatedUnionFree [RPCRT4.@] */ void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); pFormat++; pFormat++; pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); } /*********************************************************************** * 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 [internal] */ static ULONG 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.@] */ ULONG 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"); } /*********************************************************************** * NdrRangeMarshall [internal] */ static unsigned char *WINAPI NdrRangeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { NDR_RANGE *pRange = (NDR_RANGE *)pFormat; unsigned char base_type; TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); if (pRange->type != RPC_FC_RANGE) { ERR("invalid format type %x\n", pRange->type); RpcRaiseException(RPC_S_INTERNAL_ERROR); return NULL; } base_type = pRange->flags_type & 0xf; return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type); } /*********************************************************************** * NdrRangeUnmarshall [RPCRT4.@] */ unsigned char *WINAPI NdrRangeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { NDR_RANGE *pRange = (NDR_RANGE *)pFormat; unsigned char base_type; TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); if (pRange->type != RPC_FC_RANGE) { ERR("invalid format type %x\n", pRange->type); RpcRaiseException(RPC_S_INTERNAL_ERROR); return NULL; } base_type = pRange->flags_type & 0xf; TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n", base_type, pRange->low_value, pRange->high_value); #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \ do \ { \ ALIGN_POINTER(pStubMsg->Buffer, sizeof(wire_type)); \ if (!fMustAlloc && !*ppMemory) \ fMustAlloc = TRUE; \ if (fMustAlloc) \ *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \ if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \ { \ ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \ pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \ RpcRaiseException(RPC_X_BAD_STUB_DATA); \ } \ if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \ (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \ { \ ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \ *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \ (mem_type)pRange->high_value); \ RpcRaiseException(RPC_S_INVALID_BOUND); \ return NULL; \ } \ TRACE("*ppMemory: %p\n", *ppMemory); \ **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \ pStubMsg->Buffer += sizeof(wire_type); \ } while (0) switch(base_type) { case RPC_FC_CHAR: case RPC_FC_SMALL: RANGE_UNMARSHALL(UCHAR, UCHAR, "%d"); TRACE("value: 0x%02x\n", **ppMemory); break; case RPC_FC_BYTE: case RPC_FC_USMALL: RANGE_UNMARSHALL(CHAR, CHAR, "%u"); TRACE("value: 0x%02x\n", **ppMemory); break; case RPC_FC_WCHAR: /* FIXME: valid? */ case RPC_FC_USHORT: RANGE_UNMARSHALL(USHORT, USHORT, "%u"); TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); break; case RPC_FC_SHORT: RANGE_UNMARSHALL(SHORT, SHORT, "%d"); TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); break; case RPC_FC_LONG: case RPC_FC_ENUM32: RANGE_UNMARSHALL(LONG, LONG, "%d"); TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); break; case RPC_FC_ULONG: RANGE_UNMARSHALL(ULONG, ULONG, "%u"); TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); break; case RPC_FC_ENUM16: RANGE_UNMARSHALL(UINT, USHORT, "%u"); TRACE("value: 0x%08x\n", **(UINT **)ppMemory); break; case RPC_FC_FLOAT: case RPC_FC_DOUBLE: case RPC_FC_HYPER: default: ERR("invalid range base type: 0x%02x\n", base_type); RpcRaiseException(RPC_S_INTERNAL_ERROR); } return NULL; } /*********************************************************************** * NdrRangeBufferSize [internal] */ static void WINAPI NdrRangeBufferSize( PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { NDR_RANGE *pRange = (NDR_RANGE *)pFormat; unsigned char base_type; TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); if (pRange->type != RPC_FC_RANGE) { ERR("invalid format type %x\n", pRange->type); RpcRaiseException(RPC_S_INTERNAL_ERROR); } base_type = pRange->flags_type & 0xf; NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type); } /*********************************************************************** * NdrRangeMemorySize [internal] */ static ULONG WINAPI NdrRangeMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { NDR_RANGE *pRange = (NDR_RANGE *)pFormat; unsigned char base_type; if (pRange->type != RPC_FC_RANGE) { ERR("invalid format type %x\n", pRange->type); RpcRaiseException(RPC_S_INTERNAL_ERROR); return 0; } base_type = pRange->flags_type & 0xf; return NdrBaseTypeMemorySize(pStubMsg, &base_type); } /*********************************************************************** * NdrRangeFree [internal] */ static void WINAPI NdrRangeFree(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 */ } /*********************************************************************** * 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: safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR)); TRACE("value: 0x%02x\n", *pMemory); break; case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); safe_copy_to_buffer(pStubMsg, pMemory, 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_CLEAR(pStubMsg->Buffer, sizeof(ULONG)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG)); TRACE("value: 0x%08x\n", *(ULONG *)pMemory); break; case RPC_FC_FLOAT: ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float)); break; case RPC_FC_DOUBLE: ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double)); break; case RPC_FC_HYPER: ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG)); safe_copy_to_buffer(pStubMsg, pMemory, 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 > SHRT_MAX) RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory; pStubMsg->Buffer += sizeof(USHORT); TRACE("value: 0x%04x\n", *(UINT *)pMemory); break; case RPC_FC_IGNORE: break; default: FIXME("Unhandled base type: 0x%02x\n", *pFormat); } /* 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 && !pStubMsg->IsClient && !*ppMemory) \ { \ *ppMemory = pStubMsg->Buffer; \ TRACE("*ppMemory: %p\n", *ppMemory); \ safe_buffer_increment(pStubMsg, sizeof(type)); \ } \ else \ { \ if (fMustAlloc) \ *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ TRACE("*ppMemory: %p\n", *ppMemory); \ safe_copy_from_buffer(pStubMsg, *ppMemory, 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", **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%08x\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) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT)); if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); 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; case RPC_FC_IGNORE: 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: safe_buffer_length_increment(pStubMsg, 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)); safe_buffer_length_increment(pStubMsg, sizeof(USHORT)); break; case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG)); safe_buffer_length_increment(pStubMsg, sizeof(ULONG)); break; case RPC_FC_FLOAT: ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float)); safe_buffer_length_increment(pStubMsg, sizeof(float)); break; case RPC_FC_DOUBLE: ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double)); safe_buffer_length_increment(pStubMsg, sizeof(double)); break; case RPC_FC_HYPER: ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG)); safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG)); break; case RPC_FC_ERROR_STATUS_T: ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t)); safe_buffer_length_increment(pStubMsg, sizeof(error_status_t)); break; case RPC_FC_IGNORE: break; default: FIXME("Unhandled base type: 0x%02x\n", *pFormat); } } /*********************************************************************** * NdrBaseTypeMemorySize [internal] */ static ULONG WINAPI NdrBaseTypeMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat); switch(*pFormat) { case RPC_FC_BYTE: case RPC_FC_CHAR: case RPC_FC_SMALL: case RPC_FC_USMALL: safe_buffer_increment(pStubMsg, sizeof(UCHAR)); pStubMsg->MemorySize += sizeof(UCHAR); return sizeof(UCHAR); case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); safe_buffer_increment(pStubMsg, sizeof(USHORT)); ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(USHORT)); pStubMsg->MemorySize += sizeof(USHORT); return sizeof(USHORT); case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); safe_buffer_increment(pStubMsg, sizeof(ULONG)); ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONG)); pStubMsg->MemorySize += sizeof(ULONG); return sizeof(ULONG); case RPC_FC_FLOAT: ALIGN_POINTER(pStubMsg->Buffer, sizeof(float)); safe_buffer_increment(pStubMsg, sizeof(float)); ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(float)); pStubMsg->MemorySize += sizeof(float); return sizeof(float); case RPC_FC_DOUBLE: ALIGN_POINTER(pStubMsg->Buffer, sizeof(double)); safe_buffer_increment(pStubMsg, sizeof(double)); ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(double)); pStubMsg->MemorySize += sizeof(double); return sizeof(double); case RPC_FC_HYPER: ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG)); safe_buffer_increment(pStubMsg, sizeof(ULONGLONG)); ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONGLONG)); pStubMsg->MemorySize += sizeof(ULONGLONG); return sizeof(ULONGLONG); case RPC_FC_ERROR_STATUS_T: ALIGN_POINTER(pStubMsg->Buffer, sizeof(error_status_t)); safe_buffer_increment(pStubMsg, sizeof(error_status_t)); ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(error_status_t)); pStubMsg->MemorySize += sizeof(error_status_t); return sizeof(error_status_t); case RPC_FC_ENUM16: ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); safe_buffer_increment(pStubMsg, sizeof(USHORT)); ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(UINT)); pStubMsg->MemorySize += sizeof(UINT); return sizeof(UINT); case RPC_FC_IGNORE: ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); pStubMsg->MemorySize += sizeof(void *); return sizeof(void *); 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 */ } /*********************************************************************** * NdrContextHandleBufferSize [internal] */ static void WINAPI NdrContextHandleBufferSize( PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); if (*pFormat != RPC_FC_BIND_CONTEXT) { ERR("invalid format type %x\n", *pFormat); RpcRaiseException(RPC_S_INTERNAL_ERROR); } ALIGN_LENGTH(pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, cbNDRContext); } /*********************************************************************** * NdrContextHandleMarshall [internal] */ static unsigned char *WINAPI NdrContextHandleMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); if (*pFormat != RPC_FC_BIND_CONTEXT) { ERR("invalid format type %x\n", *pFormat); RpcRaiseException(RPC_S_INTERNAL_ERROR); } TRACE("flags: 0x%02x\n", pFormat[1]); if (pFormat[1] & 0x80) NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE); else NdrClientContextMarshall(pStubMsg, pMemory, FALSE); return NULL; } /*********************************************************************** * NdrContextHandleUnmarshall [internal] */ static unsigned char *WINAPI NdrContextHandleUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg, ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE"); if (*pFormat != RPC_FC_BIND_CONTEXT) { ERR("invalid format type %x\n", *pFormat); RpcRaiseException(RPC_S_INTERNAL_ERROR); } TRACE("flags: 0x%02x\n", pFormat[1]); /* [out]-only or [ret] param */ if ((pFormat[1] & 0x60) == 0x20) **(NDR_CCONTEXT **)ppMemory = NULL; NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle); return NULL; } /*********************************************************************** * NdrClientContextMarshall [RPCRT4.@] */ void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, NDR_CCONTEXT ContextHandle, int fCheck) { TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck); ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); RpcRaiseException(RPC_X_BAD_STUB_DATA); } /* FIXME: what does fCheck do? */ NDRCContextMarshall(ContextHandle, pStubMsg->Buffer); pStubMsg->Buffer += cbNDRContext; } /*********************************************************************** * NdrClientContextUnmarshall [RPCRT4.@] */ 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); if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); NDRCContextUnmarshall(pContextHandle, BindHandle, pStubMsg->Buffer, pStubMsg->RpcMsg->DataRepresentation); pStubMsg->Buffer += cbNDRContext; } void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, NDR_SCONTEXT ContextHandle, NDR_RUNDOWN RundownRoutine ) { TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine); ALIGN_POINTER(pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); RpcRaiseException(RPC_X_BAD_STUB_DATA); } NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle, pStubMsg->Buffer, RundownRoutine, NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS); pStubMsg->Buffer += cbNDRContext; } NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg) { NDR_SCONTEXT ContextHandle; TRACE("(%p)\n", pStubMsg); ALIGN_POINTER(pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); RpcRaiseException(RPC_X_BAD_STUB_DATA); } ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, pStubMsg->Buffer, pStubMsg->RpcMsg->DataRepresentation, NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS); pStubMsg->Buffer += cbNDRContext; return ContextHandle; } 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) { RPC_SYNTAX_IDENTIFIER *if_id = NULL; ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS; TRACE("(%p, %p)\n", pStubMsg, pFormat); if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE) flags |= RPC_CONTEXT_HANDLE_SERIALIZE; if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE) flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE; if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE) { RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation; if_id = &sif->InterfaceId; } return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL, pStubMsg->RpcMsg->DataRepresentation, if_id, flags); } void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg, NDR_SCONTEXT ContextHandle, NDR_RUNDOWN RundownRoutine, PFORMAT_STRING pFormat) { RPC_SYNTAX_IDENTIFIER *if_id = NULL; ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS; TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat); ALIGN_POINTER(pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); RpcRaiseException(RPC_X_BAD_STUB_DATA); } if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE) flags |= RPC_CONTEXT_HANDLE_SERIALIZE; if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE) flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE; if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE) { RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation; if_id = &sif->InterfaceId; } NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle, pStubMsg->Buffer, RundownRoutine, if_id, flags); pStubMsg->Buffer += cbNDRContext; } NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { NDR_SCONTEXT ContextHandle; RPC_SYNTAX_IDENTIFIER *if_id = NULL; ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS; TRACE("(%p, %p)\n", pStubMsg, pFormat); ALIGN_POINTER(pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); RpcRaiseException(RPC_X_BAD_STUB_DATA); } if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE) flags |= RPC_CONTEXT_HANDLE_SERIALIZE; if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE) flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE; if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE) { RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation; if_id = &sif->InterfaceId; } ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, pStubMsg->Buffer, pStubMsg->RpcMsg->DataRepresentation, if_id, flags); pStubMsg->Buffer += cbNDRContext; return ContextHandle; } /*********************************************************************** * NdrCorrelationInitialize [RPCRT4.@] * * Initializes correlation validity checking. * * PARAMS * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling. * pMemory [I] Pointer to memory to use as a cache. * CacheSize [I] Size of the memory pointed to by pMemory. * Flags [I] Reserved. Set to zero. * * RETURNS * Nothing. */ void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags) { FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags); pStubMsg->fHasNewCorrDesc = TRUE; } /*********************************************************************** * NdrCorrelationPass [RPCRT4.@] * * Performs correlation validity checking. * * PARAMS * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling. * * RETURNS * Nothing. */ void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg) { FIXME("(%p): stub\n", pStubMsg); } /*********************************************************************** * NdrCorrelationFree [RPCRT4.@] * * Frees any resources used while unmarshalling parameters that need * correlation validity checking. * * PARAMS * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling. * * RETURNS * Nothing. */ void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg) { FIXME("(%p): stub\n", pStubMsg); }