From b2305adc3c8505a0a033cabc94d417cedb8cda5c Mon Sep 17 00:00:00 2001 From: Rob Shearman Date: Sun, 10 Aug 2008 11:14:25 +0100 Subject: [PATCH] rpcrt4: Factorise conformant string functions into array_* functions. This allows conformant string array types to be marshalled/unmarshalled when embedded in a complex type. --- dlls/rpcrt4/ndr_marshall.c | 1187 +++++++++++++++++++++++--------------------- 1 file changed, 627 insertions(+), 560 deletions(-) diff --git a/dlls/rpcrt4/ndr_marshall.c b/dlls/rpcrt4/ndr_marshall.c index d09ae895b51..8696afa37df 100644 --- a/dlls/rpcrt4/ndr_marshall.c +++ b/dlls/rpcrt4/ndr_marshall.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "windef.h" @@ -734,396 +733,6 @@ static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULO } } -/* - * NdrConformantString: - * - * What MS calls a ConformantString is, in DCE terminology, - * a Varying-Conformant String. - * [ - * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0') - * offset: DWORD (actual string data begins at (offset) CHARTYPE's - * into unmarshalled string) - * length: DWORD (# of CHARTYPE characters, inclusive of '\0') - * [ - * data: CHARTYPE[maxlen] - * ] - * ], where CHARTYPE is the appropriate character type (specified externally) - * - */ - -/*********************************************************************** - * NdrConformantStringMarshall [RPCRT4.@] - */ -unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, - unsigned char *pszMessage, PFORMAT_STRING pFormat) -{ - ULONG esize, size; - - TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)pszMessage)); - pStubMsg->ActualCount = strlen((char*)pszMessage)+1; - esize = 1; - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage)); - pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1; - esize = 2; - } - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception. */ - return NULL; - } - - if (pFormat[1] == RPC_FC_STRING_SIZED) - pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - pStubMsg->Offset = 0; - WriteConformance(pStubMsg); - WriteVariance(pStubMsg); - - size = safe_multiply(esize, pStubMsg->ActualCount); - safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */ - - /* success */ - return NULL; /* is this always right? */ -} - -/*********************************************************************** - * NdrConformantStringBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, PFORMAT_STRING pFormat) -{ - ULONG esize; - - TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - - SizeConformance(pStubMsg); - SizeVariance(pStubMsg); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)pMemory)); - pStubMsg->ActualCount = strlen((char*)pMemory)+1; - esize = 1; - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1; - esize = 2; - } - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - return; - } - - if (pFormat[1] == RPC_FC_STRING_SIZED) - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - - safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); -} - -/************************************************************************ - * NdrConformantStringMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat ) -{ - ULONG bufsize, memsize, esize; - - TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); - - ReadConformance(pStubMsg, NULL); - 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); - } - - if (*pFormat == RPC_FC_C_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - esize = 0; - } - - memsize = safe_multiply(esize, pStubMsg->MaxCount); - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - validate_string_data(pStubMsg, bufsize, esize); - - safe_buffer_increment(pStubMsg, bufsize); - pStubMsg->MemorySize += memsize; - - return pStubMsg->MemorySize; -} - -/************************************************************************ - * NdrConformantStringUnmarshall [RPCRT4.@] - */ -unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) -{ - ULONG bufsize, memsize, esize; - - TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", - pStubMsg, *ppMemory, pFormat, fMustAlloc); - - assert(pFormat && ppMemory && pStubMsg); - - ReadConformance(pStubMsg, NULL); - ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); - - if (pFormat[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); - return NULL; - } - if (pStubMsg->Offset) - { - ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - if (*pFormat == RPC_FC_C_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - esize = 0; - } - - memsize = safe_multiply(esize, pStubMsg->MaxCount); - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - validate_string_data(pStubMsg, bufsize, esize); - - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, memsize); - else - { - if (!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 if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); - } - - return NULL; /* FIXME: is this always right? */ -} - -/*********************************************************************** - * NdrNonConformantStringMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - 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) - *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; -} - static inline void dump_pointer_attr(unsigned char attr) { if (attr & RPC_FC_P_ALLOCALLNODES) @@ -2143,19 +1752,235 @@ static inline void array_compute_and_size_conformance( 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) +{ + 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); + + 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); + + 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) +{ + 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); + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, size); + + 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); + + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size); + + 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 void array_buffer_size( - unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, - PFORMAT_STRING pFormat) +static inline void array_read_variance_and_unmarshall( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, + PFORMAT_STRING pFormat, unsigned char fMustAlloc, + unsigned char fUseBufferMemoryServer) { - DWORD size; - DWORD esize; + ULONG bufsize, memsize; + WORD esize; unsigned char alignment; + unsigned char *saved_buffer; + ULONG offset; switch (fc) { @@ -2163,52 +1988,102 @@ static inline void array_buffer_size( esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; + bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); + pFormat = SkipConformance(pStubMsg, pFormat + 4); - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + ALIGN_POINTER(pStubMsg->Buffer, alignment); - size = safe_multiply(esize, pStubMsg->MaxCount); - /* conformance value plus array */ - safe_buffer_length_increment(pStubMsg, size); + 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; + } - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); + 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); 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); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + ALIGN_POINTER(pStubMsg->Buffer, alignment); - size = safe_multiply(esize, pStubMsg->ActualCount); - safe_buffer_length_increment(pStubMsg, size); + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + memsize = safe_multiply(esize, pStubMsg->MaxCount); + offset = pStubMsg->Offset; - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); - break; - default: - ERR("unknown array format 0x%x\n", fc); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } -} + if (!fMustAlloc && !*ppMemory) + fMustAlloc = TRUE; + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, memsize); + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); -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); + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + memcpy(*ppMemory + offset, saved_buffer, bufsize); break; - case RPC_FC_CVARRAY: - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - WriteConformance(pStubMsg); + 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 (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)); break; default: ERR("unknown array format 0x%x\n", fc); @@ -2216,11 +2091,10 @@ static inline void array_compute_and_write_conformance( } } -static inline void array_write_variance_and_marshall( - unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, - PFORMAT_STRING pFormat) +static inline void array_memory_size( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - DWORD size; + ULONG bufsize, memsize; DWORD esize; unsigned char alignment; @@ -2232,33 +2106,61 @@ static inline void array_write_variance_and_marshall( pFormat = SkipConformance(pStubMsg, pFormat + 4); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->MemorySize += memsize; - size = safe_multiply(esize, pStubMsg->MaxCount); + ALIGN_POINTER(pStubMsg->Buffer, alignment); pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory, size); + safe_buffer_increment(pStubMsg, bufsize); - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + EmbeddedPointerMemorySize(pStubMsg, 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); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - size = safe_multiply(esize, pStubMsg->ActualCount); + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + memsize = safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->MemorySize += memsize; + ALIGN_POINTER(pStubMsg->Buffer, alignment); pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size); + safe_buffer_increment(pStubMsg, bufsize); - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + 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); @@ -2266,169 +2168,334 @@ static inline void array_write_variance_and_marshall( } } -static inline ULONG array_read_conformance( - unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) +static inline void array_free( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, 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); + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); + break; case RPC_FC_CVARRAY: - esize = *(const WORD*)(pFormat+2); - pFormat = ReadConformance(pStubMsg, pFormat+4); - return safe_multiply(esize, pStubMsg->MaxCount); + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + 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); } } -static inline void array_read_variance_and_unmarshall( - unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, - PFORMAT_STRING pFormat, unsigned char fMustAlloc, - unsigned char fUseBufferMemoryServer) +/* + * 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); + } else { + array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage, pFormat); + array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage, pFormat); + } + + 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); + } else { + array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat); + array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat); + } +} + +/************************************************************************ + * 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); + } else { + array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat); + array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat); + } + + 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 */); + } 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 */); + } + + return NULL; +} + +/*********************************************************************** + * NdrNonConformantStringMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) { - ULONG bufsize, memsize; - WORD esize; - unsigned char alignment; - unsigned char *saved_buffer; - ULONG offset; + ULONG esize, size, maxsize; - switch (fc) + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + + maxsize = *(USHORT *)&pFormat[2]; + + if (*pFormat == RPC_FC_CSTRING) { - case RPC_FC_CARRAY: - esize = *(const WORD*)(pFormat+2); - alignment = pFormat[1] + 1; + 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); + } - bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->Offset = 0; + WriteVariance(pStubMsg); - pFormat = SkipConformance(pStubMsg, pFormat + 4); + size = safe_multiply(esize, pStubMsg->ActualCount); + safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ - ALIGN_POINTER(pStubMsg->Buffer, alignment); + return NULL; +} - 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; - } +/*********************************************************************** + * NdrNonConformantStringUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + ULONG bufsize, memsize, esize, maxsize; - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, bufsize); - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", + pStubMsg, *ppMemory, pFormat, fMustAlloc); - TRACE("copying %p to %p\n", saved_buffer, *ppMemory); - if (*ppMemory != saved_buffer) - memcpy(*ppMemory, saved_buffer, bufsize); - break; - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pFormat+2); - alignment = pFormat[1] + 1; + maxsize = *(USHORT *)&pFormat[2]; - pFormat = SkipConformance(pStubMsg, pFormat + 4); + ReadVariance(pStubMsg, NULL, maxsize); + if (pStubMsg->Offset) + { + ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + 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); + } - ALIGN_POINTER(pStubMsg->Buffer, alignment); + memsize = esize * maxsize; + bufsize = safe_multiply(esize, pStubMsg->ActualCount); - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - memsize = safe_multiply(esize, pStubMsg->MaxCount); - offset = pStubMsg->Offset; + validate_string_data(pStubMsg, bufsize, esize); - if (!fMustAlloc && !*ppMemory) - fMustAlloc = TRUE; - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, memsize); - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, bufsize); + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); - memcpy(*ppMemory + offset, saved_buffer, bufsize); - break; - default: - ERR("unknown array format 0x%x\n", fc); - RpcRaiseException(RPC_X_BAD_STUB_DATA); + 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; } -static inline void array_memory_size( - unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) +/*********************************************************************** + * NdrNonConformantStringBufferSize [RPCRT4.@] + */ +void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) { - ULONG bufsize, memsize; - DWORD esize; - unsigned char alignment; + ULONG esize, maxsize; - switch (fc) - { - case RPC_FC_CARRAY: - esize = *(const WORD*)(pFormat+2); - alignment = pFormat[1] + 1; + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - pFormat = SkipConformance(pStubMsg, pFormat + 4); + maxsize = *(USHORT *)&pFormat[2]; - bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); - pStubMsg->MemorySize += memsize; + SizeVariance(pStubMsg); - ALIGN_POINTER(pStubMsg->Buffer, alignment); - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, bufsize); + 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); + } - EmbeddedPointerMemorySize(pStubMsg, pFormat); - break; - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pFormat+2); - alignment = pFormat[1] + 1; + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); +} - pFormat = SkipConformance(pStubMsg, pFormat + 4); +/*********************************************************************** + * NdrNonConformantStringMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + ULONG bufsize, memsize, esize, maxsize; - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - memsize = safe_multiply(esize, pStubMsg->MaxCount); - pStubMsg->MemorySize += memsize; + maxsize = *(USHORT *)&pFormat[2]; - ALIGN_POINTER(pStubMsg->Buffer, alignment); - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, bufsize); + ReadVariance(pStubMsg, NULL, maxsize); - EmbeddedPointerMemorySize(pStubMsg, pFormat); - break; - default: - ERR("unknown array format 0x%x\n", fc); - RpcRaiseException(RPC_X_BAD_STUB_DATA); + if (pStubMsg->Offset) + { + ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); } -} -static inline void array_free( - unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, PFORMAT_STRING pFormat) -{ - switch (fc) + if (*pFormat == RPC_FC_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_WSTRING) esize = 2; + else { - case RPC_FC_CARRAY: - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); - break; - case RPC_FC_CVARRAY: - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - 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); + 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 */ -- 2.11.4.GIT