~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/rpcrt4/ndr_marshall.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * NDR data marshalling
  3  *
  4  * Copyright 2002 Greg Turner
  5  * Copyright 2003-2006 CodeWeavers
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  *
 21  * TODO:
 22  *  - String structs
 23  *  - Byte count pointers
 24  *  - transmit_as/represent as
 25  *  - Multi-dimensional arrays
 26  *  - Conversion functions (NdrConvert)
 27  *  - Checks for integer addition overflow in user marshall functions
 28  */
 29 
 30 #include <stdarg.h>
 31 #include <stdio.h>
 32 #include <string.h>
 33 #include <limits.h>
 34 
 35 #include "windef.h"
 36 #include "winbase.h"
 37 #include "winerror.h"
 38 
 39 #include "ndr_misc.h"
 40 #include "rpcndr.h"
 41 
 42 #include "wine/unicode.h"
 43 #include "wine/rpcfc.h"
 44 
 45 #include "wine/debug.h"
 46 
 47 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 48 
 49 #if defined(__i386__)
 50 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
 51     (*((UINT32 *)(pchar)) = (uint32))
 52 
 53 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
 54     (*((UINT32 *)(pchar)))
 55 #else
 56   /* these would work for i386 too, but less efficient */
 57 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
 58     (*(pchar)     = LOBYTE(LOWORD(uint32)), \
 59      *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
 60      *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
 61      *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
 62      (uint32)) /* allow as r-value */
 63 
 64 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
 65     (MAKELONG( \
 66       MAKEWORD(*(pchar), *((pchar)+1)), \
 67       MAKEWORD(*((pchar)+2), *((pchar)+3))))
 68 #endif
 69 
 70 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
 71   (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
 72    *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
 73    *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
 74    *(pchar)     = HIBYTE(HIWORD(uint32)), \
 75    (uint32)) /* allow as r-value */
 76 
 77 #define BIG_ENDIAN_UINT32_READ(pchar) \
 78   (MAKELONG( \
 79     MAKEWORD(*((pchar)+3), *((pchar)+2)), \
 80     MAKEWORD(*((pchar)+1), *(pchar))))
 81 
 82 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
 83 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
 84     BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
 85 # define NDR_LOCAL_UINT32_READ(pchar) \
 86     BIG_ENDIAN_UINT32_READ(pchar)
 87 #else
 88 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
 89     LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
 90 # define NDR_LOCAL_UINT32_READ(pchar) \
 91     LITTLE_ENDIAN_UINT32_READ(pchar)
 92 #endif
 93 
 94 /* _Align must be the desired alignment,
 95  * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
 96 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
 97 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
 98 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
 99 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
100 #define ALIGN_POINTER_CLEAR(_Ptr, _Align) \
101     do { \
102         memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \
103         ALIGN_POINTER(_Ptr, _Align); \
104     } while(0)
105 
106 #define STD_OVERFLOW_CHECK(_Msg) do { \
107     TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
108     if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
109         ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
110   } while (0)
111 
112 #define NDR_POINTER_ID_BASE 0x20000
113 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
114 #define NDR_TABLE_SIZE 128
115 #define NDR_TABLE_MASK 127
116 
117 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
118 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
119 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
120 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
121 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
122 
123 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
124 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
125 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
126 
127 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
128   0,
129   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
130   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
131   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
132   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
133   /* 0x10 */
134   NdrBaseTypeMarshall,
135   /* 0x11 */
136   NdrPointerMarshall, NdrPointerMarshall,
137   NdrPointerMarshall, NdrPointerMarshall,
138   /* 0x15 */
139   NdrSimpleStructMarshall, NdrSimpleStructMarshall,
140   NdrConformantStructMarshall, NdrConformantStructMarshall,
141   NdrConformantVaryingStructMarshall,
142   NdrComplexStructMarshall,
143   /* 0x1b */
144   NdrConformantArrayMarshall, 
145   NdrConformantVaryingArrayMarshall,
146   NdrFixedArrayMarshall, NdrFixedArrayMarshall,
147   NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
148   NdrComplexArrayMarshall,
149   /* 0x22 */
150   NdrConformantStringMarshall, 0, 0,
151   NdrConformantStringMarshall,
152   NdrNonConformantStringMarshall, 0, 0, 0,
153   /* 0x2a */
154   NdrEncapsulatedUnionMarshall,
155   NdrNonEncapsulatedUnionMarshall,
156   NdrByteCountPointerMarshall,
157   NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
158   /* 0x2f */
159   NdrInterfacePointerMarshall,
160   /* 0x30 */
161   NdrContextHandleMarshall,
162   /* 0xb1 */
163   0, 0, 0,
164   NdrUserMarshalMarshall,
165   0, 0,
166   /* 0xb7 */
167   NdrRangeMarshall
168 };
169 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
170   0,
171   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
172   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
173   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
174   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
175   /* 0x10 */
176   NdrBaseTypeUnmarshall,
177   /* 0x11 */
178   NdrPointerUnmarshall, NdrPointerUnmarshall,
179   NdrPointerUnmarshall, NdrPointerUnmarshall,
180   /* 0x15 */
181   NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
182   NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
183   NdrConformantVaryingStructUnmarshall,
184   NdrComplexStructUnmarshall,
185   /* 0x1b */
186   NdrConformantArrayUnmarshall, 
187   NdrConformantVaryingArrayUnmarshall,
188   NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
189   NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
190   NdrComplexArrayUnmarshall,
191   /* 0x22 */
192   NdrConformantStringUnmarshall, 0, 0,
193   NdrConformantStringUnmarshall,
194   NdrNonConformantStringUnmarshall, 0, 0, 0,
195   /* 0x2a */
196   NdrEncapsulatedUnionUnmarshall,
197   NdrNonEncapsulatedUnionUnmarshall,
198   NdrByteCountPointerUnmarshall,
199   NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
200   /* 0x2f */
201   NdrInterfacePointerUnmarshall,
202   /* 0x30 */
203   NdrContextHandleUnmarshall,
204   /* 0xb1 */
205   0, 0, 0,
206   NdrUserMarshalUnmarshall,
207   0, 0,
208   /* 0xb7 */
209   NdrRangeUnmarshall
210 };
211 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
212   0,
213   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
214   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
215   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
216   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
217   /* 0x10 */
218   NdrBaseTypeBufferSize,
219   /* 0x11 */
220   NdrPointerBufferSize, NdrPointerBufferSize,
221   NdrPointerBufferSize, NdrPointerBufferSize,
222   /* 0x15 */
223   NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
224   NdrConformantStructBufferSize, NdrConformantStructBufferSize,
225   NdrConformantVaryingStructBufferSize,
226   NdrComplexStructBufferSize,
227   /* 0x1b */
228   NdrConformantArrayBufferSize, 
229   NdrConformantVaryingArrayBufferSize,
230   NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
231   NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
232   NdrComplexArrayBufferSize,
233   /* 0x22 */
234   NdrConformantStringBufferSize, 0, 0,
235   NdrConformantStringBufferSize,
236   NdrNonConformantStringBufferSize, 0, 0, 0,
237   /* 0x2a */
238   NdrEncapsulatedUnionBufferSize,
239   NdrNonEncapsulatedUnionBufferSize,
240   NdrByteCountPointerBufferSize,
241   NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
242   /* 0x2f */
243   NdrInterfacePointerBufferSize,
244   /* 0x30 */
245   NdrContextHandleBufferSize,
246   /* 0xb1 */
247   0, 0, 0,
248   NdrUserMarshalBufferSize,
249   0, 0,
250   /* 0xb7 */
251   NdrRangeBufferSize
252 };
253 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
254   0,
255   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
256   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
257   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
258   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
259   /* 0x10 */
260   NdrBaseTypeMemorySize,
261   /* 0x11 */
262   NdrPointerMemorySize, NdrPointerMemorySize,
263   NdrPointerMemorySize, NdrPointerMemorySize,
264   /* 0x15 */
265   NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
266   NdrConformantStructMemorySize, NdrConformantStructMemorySize,
267   NdrConformantVaryingStructMemorySize,
268   NdrComplexStructMemorySize,
269   /* 0x1b */
270   NdrConformantArrayMemorySize,
271   NdrConformantVaryingArrayMemorySize,
272   NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
273   NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
274   NdrComplexArrayMemorySize,
275   /* 0x22 */
276   NdrConformantStringMemorySize, 0, 0,
277   NdrConformantStringMemorySize,
278   NdrNonConformantStringMemorySize, 0, 0, 0,
279   /* 0x2a */
280   NdrEncapsulatedUnionMemorySize,
281   NdrNonEncapsulatedUnionMemorySize,
282   NdrByteCountPointerMemorySize,
283   NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
284   /* 0x2f */
285   NdrInterfacePointerMemorySize,
286   /* 0x30 */
287   0,
288   /* 0xb1 */
289   0, 0, 0,
290   NdrUserMarshalMemorySize,
291   0, 0,
292   /* 0xb7 */
293   NdrRangeMemorySize
294 };
295 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
296   0,
297   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
298   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
299   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
300   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
301   /* 0x10 */
302   NdrBaseTypeFree,
303   /* 0x11 */
304   NdrPointerFree, NdrPointerFree,
305   NdrPointerFree, NdrPointerFree,
306   /* 0x15 */
307   NdrSimpleStructFree, NdrSimpleStructFree,
308   NdrConformantStructFree, NdrConformantStructFree,
309   NdrConformantVaryingStructFree,
310   NdrComplexStructFree,
311   /* 0x1b */
312   NdrConformantArrayFree, 
313   NdrConformantVaryingArrayFree,
314   NdrFixedArrayFree, NdrFixedArrayFree,
315   NdrVaryingArrayFree, NdrVaryingArrayFree,
316   NdrComplexArrayFree,
317   /* 0x22 */
318   0, 0, 0,
319   0, 0, 0, 0, 0,
320   /* 0x2a */
321   NdrEncapsulatedUnionFree,
322   NdrNonEncapsulatedUnionFree,
323   0,
324   NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
325   /* 0x2f */
326   NdrInterfacePointerFree,
327   /* 0x30 */
328   0,
329   /* 0xb1 */
330   0, 0, 0,
331   NdrUserMarshalFree,
332   0, 0,
333   /* 0xb7 */
334   NdrRangeFree
335 };
336 
337 typedef struct _NDR_MEMORY_LIST
338 {
339     ULONG magic;
340     ULONG size;
341     ULONG reserved;
342     struct _NDR_MEMORY_LIST *next;
343 } NDR_MEMORY_LIST;
344 
345 #define MEML_MAGIC  ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
346 
347 /***********************************************************************
348  *            NdrAllocate [RPCRT4.@]
349  *
350  * Allocates a block of memory using pStubMsg->pfnAllocate.
351  *
352  * PARAMS
353  *  pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
354  *  len      [I]   Size of memory block to allocate.
355  *
356  * RETURNS
357  *  The memory block of size len that was allocated.
358  *
359  * NOTES
360  *  The memory block is always 8-byte aligned.
361  *  If the function is unable to allocate memory an ERROR_OUTOFMEMORY
362  *  exception is raised.
363  */
364 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
365 {
366     size_t aligned_len;
367     size_t adjusted_len;
368     void *p;
369     NDR_MEMORY_LIST *mem_list;
370 
371     aligned_len = ALIGNED_LENGTH(len, 8);
372     adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
373     /* check for overflow */
374     if (adjusted_len < len)
375     {
376         ERR("overflow of adjusted_len %d, len %d\n", adjusted_len, len);
377         RpcRaiseException(RPC_X_BAD_STUB_DATA);
378     }
379 
380     p = pStubMsg->pfnAllocate(adjusted_len);
381     if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
382 
383     mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
384     mem_list->magic = MEML_MAGIC;
385     mem_list->size = aligned_len;
386     mem_list->reserved = 0;
387     mem_list->next = pStubMsg->pMemoryList;
388     pStubMsg->pMemoryList = mem_list;
389 
390     TRACE("-- %p\n", p);
391     return p;
392 }
393 
394 static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
395 {
396     TRACE("(%p, %p)\n", pStubMsg, Pointer);
397 
398     pStubMsg->pfnFree(Pointer);
399 }
400 
401 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
402 {
403     return (*(const ULONG *)pFormat != -1);
404 }
405 
406 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
407 {
408   ALIGN_POINTER(pStubMsg->Buffer, 4);
409   if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
410       RpcRaiseException(RPC_X_BAD_STUB_DATA);
411   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
412   pStubMsg->Buffer += 4;
413   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
414   if (pStubMsg->fHasNewCorrDesc)
415     return pFormat+6;
416   else
417     return pFormat+4;
418 }
419 
420 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
421 {
422   if (pFormat && !IsConformanceOrVariancePresent(pFormat))
423   {
424     pStubMsg->Offset = 0;
425     pStubMsg->ActualCount = pStubMsg->MaxCount;
426     goto done;
427   }
428 
429   ALIGN_POINTER(pStubMsg->Buffer, 4);
430   if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
431     RpcRaiseException(RPC_X_BAD_STUB_DATA);
432   pStubMsg->Offset      = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
433   pStubMsg->Buffer += 4;
434   TRACE("offset is %d\n", pStubMsg->Offset);
435   pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
436   pStubMsg->Buffer += 4;
437   TRACE("variance is %d\n", pStubMsg->ActualCount);
438 
439   if ((pStubMsg->ActualCount > MaxValue) ||
440       (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
441   {
442     ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
443         pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
444     RpcRaiseException(RPC_S_INVALID_BOUND);
445     return NULL;
446   }
447 
448 done:
449   if (pStubMsg->fHasNewCorrDesc)
450     return pFormat+6;
451   else
452     return pFormat+4;
453 }
454 
455 /* writes the conformance value to the buffer */
456 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
457 {
458     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
459     if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
460         RpcRaiseException(RPC_X_BAD_STUB_DATA);
461     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
462     pStubMsg->Buffer += 4;
463 }
464 
465 /* writes the variance values to the buffer */
466 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
467 {
468     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
469     if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
470         RpcRaiseException(RPC_X_BAD_STUB_DATA);
471     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
472     pStubMsg->Buffer += 4;
473     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
474     pStubMsg->Buffer += 4;
475 }
476 
477 /* requests buffer space for the conformance value */
478 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
479 {
480     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
481     if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
482         RpcRaiseException(RPC_X_BAD_STUB_DATA);
483     pStubMsg->BufferLength += 4;
484 }
485 
486 /* requests buffer space for the variance values */
487 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
488 {
489     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
490     if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
491         RpcRaiseException(RPC_X_BAD_STUB_DATA);
492     pStubMsg->BufferLength += 8;
493 }
494 
495 PFORMAT_STRING ComputeConformanceOrVariance(
496     MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
497     PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
498 {
499   BYTE dtype = pFormat[0] & 0xf;
500   short ofs = *(const short *)&pFormat[2];
501   LPVOID ptr = NULL;
502   DWORD data = 0;
503 
504   if (!IsConformanceOrVariancePresent(pFormat)) {
505     /* null descriptor */
506     *pCount = def;
507     goto finish_conf;
508   }
509 
510   switch (pFormat[0] & 0xf0) {
511   case RPC_FC_NORMAL_CONFORMANCE:
512     TRACE("normal conformance, ofs=%d\n", ofs);
513     ptr = pMemory;
514     break;
515   case RPC_FC_POINTER_CONFORMANCE:
516     TRACE("pointer conformance, ofs=%d\n", ofs);
517     ptr = pStubMsg->Memory;
518     break;
519   case RPC_FC_TOP_LEVEL_CONFORMANCE:
520     TRACE("toplevel conformance, ofs=%d\n", ofs);
521     if (pStubMsg->StackTop) {
522       ptr = pStubMsg->StackTop;
523     }
524     else {
525       /* -Os mode, *pCount is already set */
526       goto finish_conf;
527     }
528     break;
529   case RPC_FC_CONSTANT_CONFORMANCE:
530     data = ofs | ((DWORD)pFormat[1] << 16);
531     TRACE("constant conformance, val=%d\n", data);
532     *pCount = data;
533     goto finish_conf;
534   case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
535     FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
536     if (pStubMsg->StackTop) {
537       ptr = pStubMsg->StackTop;
538     }
539     else {
540       /* ? */
541       goto done_conf_grab;
542     }
543     break;
544   default:
545     FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
546   }
547 
548   switch (pFormat[1]) {
549   case RPC_FC_DEREFERENCE:
550     ptr = *(LPVOID*)((char *)ptr + ofs);
551     break;
552   case RPC_FC_CALLBACK:
553   {
554     unsigned char *old_stack_top = pStubMsg->StackTop;
555     pStubMsg->StackTop = ptr;
556 
557     /* ofs is index into StubDesc->apfnExprEval */
558     TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
559     pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
560 
561     pStubMsg->StackTop = old_stack_top;
562 
563     /* the callback function always stores the computed value in MaxCount */
564     *pCount = pStubMsg->MaxCount;
565     goto finish_conf;
566   }
567   default:
568     ptr = (char *)ptr + ofs;
569     break;
570   }
571 
572   switch (dtype) {
573   case RPC_FC_LONG:
574   case RPC_FC_ULONG:
575     data = *(DWORD*)ptr;
576     break;
577   case RPC_FC_SHORT:
578     data = *(SHORT*)ptr;
579     break;
580   case RPC_FC_USHORT:
581     data = *(USHORT*)ptr;
582     break;
583   case RPC_FC_CHAR:
584   case RPC_FC_SMALL:
585     data = *(CHAR*)ptr;
586     break;
587   case RPC_FC_BYTE:
588   case RPC_FC_USMALL:
589     data = *(UCHAR*)ptr;
590     break;
591   default:
592     FIXME("unknown conformance data type %x\n", dtype);
593     goto done_conf_grab;
594   }
595   TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
596 
597 done_conf_grab:
598   switch (pFormat[1]) {
599   case RPC_FC_DEREFERENCE: /* already handled */
600   case 0: /* no op */
601     *pCount = data;
602     break;
603   case RPC_FC_ADD_1:
604     *pCount = data + 1;
605     break;
606   case RPC_FC_SUB_1:
607     *pCount = data - 1;
608     break;
609   case RPC_FC_MULT_2:
610     *pCount = data * 2;
611     break;
612   case RPC_FC_DIV_2:
613     *pCount = data / 2;
614     break;
615   default:
616     FIXME("unknown conformance op %d\n", pFormat[1]);
617     goto finish_conf;
618   }
619 
620 finish_conf:
621   TRACE("resulting conformance is %ld\n", *pCount);
622   if (pStubMsg->fHasNewCorrDesc)
623     return pFormat+6;
624   else
625     return pFormat+4;
626 }
627 
628 static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg,
629                                              PFORMAT_STRING pFormat)
630 {
631   if (IsConformanceOrVariancePresent(pFormat))
632   {
633     if (pStubMsg->fHasNewCorrDesc)
634       pFormat += 6;
635     else
636       pFormat += 4;
637   }
638   return pFormat;
639 }
640 
641 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
642  * the result overflows 32-bits */
643 static inline ULONG safe_multiply(ULONG a, ULONG b)
644 {
645     ULONGLONG ret = (ULONGLONG)a * b;
646     if (ret > 0xffffffff)
647     {
648         RpcRaiseException(RPC_S_INVALID_BOUND);
649         return 0;
650     }
651     return ret;
652 }
653 
654 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
655 {
656     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
657         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
658         RpcRaiseException(RPC_X_BAD_STUB_DATA);
659     pStubMsg->Buffer += size;
660 }
661 
662 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
663 {
664     if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
665     {
666         ERR("buffer length overflow - BufferLength = %u, size = %u\n",
667             pStubMsg->BufferLength, size);
668         RpcRaiseException(RPC_X_BAD_STUB_DATA);
669     }
670     pStubMsg->BufferLength += size;
671 }
672 
673 /* copies data from the buffer, checking that there is enough data in the buffer
674  * to do so */
675 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
676 {
677     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
678         (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
679     {
680         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
681             pStubMsg->Buffer, pStubMsg->BufferEnd, size);
682         RpcRaiseException(RPC_X_BAD_STUB_DATA);
683     }
684     if (p == pStubMsg->Buffer)
685         ERR("pointer is the same as the buffer\n");
686     memcpy(p, pStubMsg->Buffer, size);
687     pStubMsg->Buffer += size;
688 }
689 
690 /* copies data to the buffer, checking that there is enough space to do so */
691 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
692 {
693     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
694         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
695     {
696         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
697             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
698             size);
699         RpcRaiseException(RPC_X_BAD_STUB_DATA);
700     }
701     memcpy(pStubMsg->Buffer, p, size);
702     pStubMsg->Buffer += size;
703 }
704 
705 /* verify that string data sitting in the buffer is valid and safe to
706  * unmarshall */
707 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
708 {
709     ULONG i;
710 
711     /* verify the buffer is safe to access */
712     if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
713         (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
714     {
715         ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
716             pStubMsg->BufferEnd, pStubMsg->Buffer);
717         RpcRaiseException(RPC_X_BAD_STUB_DATA);
718     }
719 
720     /* strings must always have null terminating bytes */
721     if (bufsize < esize)
722     {
723         ERR("invalid string length of %d\n", bufsize / esize);
724         RpcRaiseException(RPC_S_INVALID_BOUND);
725     }
726 
727     for (i = bufsize - esize; i < bufsize; i++)
728         if (pStubMsg->Buffer[i] != 0)
729         {
730             ERR("string not null-terminated at byte position %d, data is 0x%x\n",
731                 i, pStubMsg->Buffer[i]);
732             RpcRaiseException(RPC_S_INVALID_BOUND);
733         }
734 }
735 
736 static inline void dump_pointer_attr(unsigned char attr)
737 {
738     if (attr & RPC_FC_P_ALLOCALLNODES)
739         TRACE(" RPC_FC_P_ALLOCALLNODES");
740     if (attr & RPC_FC_P_DONTFREE)
741         TRACE(" RPC_FC_P_DONTFREE");
742     if (attr & RPC_FC_P_ONSTACK)
743         TRACE(" RPC_FC_P_ONSTACK");
744     if (attr & RPC_FC_P_SIMPLEPOINTER)
745         TRACE(" RPC_FC_P_SIMPLEPOINTER");
746     if (attr & RPC_FC_P_DEREF)
747         TRACE(" RPC_FC_P_DEREF");
748     TRACE("\n");
749 }
750 
751 /***********************************************************************
752  *           PointerMarshall [internal]
753  */
754 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
755                             unsigned char *Buffer,
756                             unsigned char *Pointer,
757                             PFORMAT_STRING pFormat)
758 {
759   unsigned type = pFormat[0], attr = pFormat[1];
760   PFORMAT_STRING desc;
761   NDR_MARSHALL m;
762   ULONG pointer_id;
763   int pointer_needs_marshaling;
764 
765   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
766   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
767   pFormat += 2;
768   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
769   else desc = pFormat + *(const SHORT*)pFormat;
770 
771   switch (type) {
772   case RPC_FC_RP: /* ref pointer (always non-null) */
773     if (!Pointer)
774     {
775       ERR("NULL ref pointer is not allowed\n");
776       RpcRaiseException(RPC_X_NULL_REF_POINTER);
777     }
778     pointer_needs_marshaling = 1;
779     break;
780   case RPC_FC_UP: /* unique pointer */
781   case RPC_FC_OP: /* object pointer - same as unique here */
782     if (Pointer)
783       pointer_needs_marshaling = 1;
784     else
785       pointer_needs_marshaling = 0;
786     pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
787     TRACE("writing 0x%08x to buffer\n", pointer_id);
788     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
789     break;
790   case RPC_FC_FP:
791     pointer_needs_marshaling = !NdrFullPointerQueryPointer(
792       pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
793     TRACE("writing 0x%08x to buffer\n", pointer_id);
794     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
795     break;
796   default:
797     FIXME("unhandled ptr type=%02x\n", type);
798     RpcRaiseException(RPC_X_BAD_STUB_DATA);
799     return;
800   }
801 
802   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
803 
804   if (pointer_needs_marshaling) {
805     if (attr & RPC_FC_P_DEREF) {
806       Pointer = *(unsigned char**)Pointer;
807       TRACE("deref => %p\n", Pointer);
808     }
809     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
810     if (m) m(pStubMsg, Pointer, desc);
811     else FIXME("no marshaller for data type=%02x\n", *desc);
812   }
813 
814   STD_OVERFLOW_CHECK(pStubMsg);
815 }
816 
817 /***********************************************************************
818  *           PointerUnmarshall [internal]
819  */
820 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
821                               unsigned char *Buffer,
822                               unsigned char **pPointer,
823                               unsigned char *pSrcPointer,
824                               PFORMAT_STRING pFormat,
825                               unsigned char fMustAlloc)
826 {
827   unsigned type = pFormat[0], attr = pFormat[1];
828   PFORMAT_STRING desc;
829   NDR_UNMARSHALL m;
830   DWORD pointer_id = 0;
831   int pointer_needs_unmarshaling;
832 
833   TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
834   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
835   pFormat += 2;
836   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
837   else desc = pFormat + *(const SHORT*)pFormat;
838 
839   switch (type) {
840   case RPC_FC_RP: /* ref pointer (always non-null) */
841     pointer_needs_unmarshaling = 1;
842     break;
843   case RPC_FC_UP: /* unique pointer */
844     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
845     TRACE("pointer_id is 0x%08x\n", pointer_id);
846     if (pointer_id)
847       pointer_needs_unmarshaling = 1;
848     else {
849       *pPointer = NULL;
850       pointer_needs_unmarshaling = 0;
851     }
852     break;
853   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
854     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
855     TRACE("pointer_id is 0x%08x\n", pointer_id);
856     if (!fMustAlloc && pSrcPointer)
857     {
858         FIXME("free object pointer %p\n", pSrcPointer);
859         fMustAlloc = TRUE;
860     }
861     if (pointer_id)
862       pointer_needs_unmarshaling = 1;
863     else
864       pointer_needs_unmarshaling = 0;
865     break;
866   case RPC_FC_FP:
867     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
868     TRACE("pointer_id is 0x%08x\n", pointer_id);
869     pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
870       pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
871     break;
872   default:
873     FIXME("unhandled ptr type=%02x\n", type);
874     RpcRaiseException(RPC_X_BAD_STUB_DATA);
875     return;
876   }
877 
878   if (pointer_needs_unmarshaling) {
879     unsigned char *base_ptr_val = *pPointer;
880     unsigned char **current_ptr = pPointer;
881     if (pStubMsg->IsClient) {
882       TRACE("client\n");
883       /* if we aren't forcing allocation of memory then try to use the existing
884        * (source) pointer to unmarshall the data into so that [in,out]
885        * parameters behave correctly. it doesn't matter if the parameter is
886        * [out] only since in that case the pointer will be NULL. we force
887        * allocation when the source pointer is NULL here instead of in the type
888        * unmarshalling routine for the benefit of the deref code below */
889       if (!fMustAlloc) {
890         if (pSrcPointer) {
891           TRACE("setting *pPointer to %p\n", pSrcPointer);
892           *pPointer = base_ptr_val = pSrcPointer;
893         } else
894           fMustAlloc = TRUE;
895       }
896     } else {
897       TRACE("server\n");
898       /* the memory in a stub is never initialised, so we have to work out here
899        * whether we have to initialise it so we can use the optimisation of
900        * setting the pointer to the buffer, if possible, or set fMustAlloc to
901        * TRUE. */
902       if (attr & RPC_FC_P_DEREF) {
903         fMustAlloc = TRUE;
904       } else {
905         base_ptr_val = NULL;
906         *current_ptr = NULL;
907       }
908     }
909 
910     if (attr & RPC_FC_P_ALLOCALLNODES)
911         FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
912 
913     if (attr & RPC_FC_P_DEREF) {
914       if (fMustAlloc) {
915         base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
916         *pPointer = base_ptr_val;
917         current_ptr = (unsigned char **)base_ptr_val;
918       } else
919         current_ptr = *(unsigned char***)current_ptr;
920       TRACE("deref => %p\n", current_ptr);
921       if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
922     }
923     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
924     if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
925     else FIXME("no unmarshaller for data type=%02x\n", *desc);
926 
927     if (type == RPC_FC_FP)
928       NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
929                                 base_ptr_val);
930   }
931 
932   TRACE("pointer=%p\n", *pPointer);
933 }
934 
935 /***********************************************************************
936  *           PointerBufferSize [internal]
937  */
938 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
939                               unsigned char *Pointer,
940                               PFORMAT_STRING pFormat)
941 {
942   unsigned type = pFormat[0], attr = pFormat[1];
943   PFORMAT_STRING desc;
944   NDR_BUFFERSIZE m;
945   int pointer_needs_sizing;
946   ULONG pointer_id;
947 
948   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
949   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
950   pFormat += 2;
951   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
952   else desc = pFormat + *(const SHORT*)pFormat;
953 
954   switch (type) {
955   case RPC_FC_RP: /* ref pointer (always non-null) */
956     if (!Pointer)
957     {
958       ERR("NULL ref pointer is not allowed\n");
959       RpcRaiseException(RPC_X_NULL_REF_POINTER);
960     }
961     break;
962   case RPC_FC_OP:
963   case RPC_FC_UP:
964     /* NULL pointer has no further representation */
965     if (!Pointer)
966         return;
967     break;
968   case RPC_FC_FP:
969     pointer_needs_sizing = !NdrFullPointerQueryPointer(
970       pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
971     if (!pointer_needs_sizing)
972       return;
973     break;
974   default:
975     FIXME("unhandled ptr type=%02x\n", type);
976     RpcRaiseException(RPC_X_BAD_STUB_DATA);
977     return;
978   }
979 
980   if (attr & RPC_FC_P_DEREF) {
981     Pointer = *(unsigned char**)Pointer;
982     TRACE("deref => %p\n", Pointer);
983   }
984 
985   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
986   if (m) m(pStubMsg, Pointer, desc);
987   else FIXME("no buffersizer for data type=%02x\n", *desc);
988 }
989 
990 /***********************************************************************
991  *           PointerMemorySize [internal]
992  */
993 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
994                                        unsigned char *Buffer,
995                                        PFORMAT_STRING pFormat)
996 {
997   unsigned type = pFormat[0], attr = pFormat[1];
998   PFORMAT_STRING desc;
999   NDR_MEMORYSIZE m;
1000   DWORD pointer_id = 0;
1001   int pointer_needs_sizing;
1002 
1003   TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1004   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1005   pFormat += 2;
1006   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1007   else desc = pFormat + *(const SHORT*)pFormat;
1008 
1009   switch (type) {
1010   case RPC_FC_RP: /* ref pointer (always non-null) */
1011     pointer_needs_sizing = 1;
1012     break;
1013   case RPC_FC_UP: /* unique pointer */
1014   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1015     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1016     TRACE("pointer_id is 0x%08x\n", pointer_id);
1017     if (pointer_id)
1018       pointer_needs_sizing = 1;
1019     else
1020       pointer_needs_sizing = 0;
1021     break;
1022   case RPC_FC_FP:
1023   {
1024     void *pointer;
1025     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1026     TRACE("pointer_id is 0x%08x\n", pointer_id);
1027     pointer_needs_sizing = !NdrFullPointerQueryRefId(
1028       pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1029     break;
1030   }
1031   default:
1032     FIXME("unhandled ptr type=%02x\n", type);
1033     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1034     return 0;
1035   }
1036 
1037   if (attr & RPC_FC_P_DEREF) {
1038     TRACE("deref\n");
1039   }
1040 
1041   if (pointer_needs_sizing) {
1042     m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1043     if (m) m(pStubMsg, desc);
1044     else FIXME("no memorysizer for data type=%02x\n", *desc);
1045   }
1046 
1047   return pStubMsg->MemorySize;
1048 }
1049 
1050 /***********************************************************************
1051  *           PointerFree [internal]
1052  */
1053 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1054                         unsigned char *Pointer,
1055                         PFORMAT_STRING pFormat)
1056 {
1057   unsigned type = pFormat[0], attr = pFormat[1];
1058   PFORMAT_STRING desc;
1059   NDR_FREE m;
1060   unsigned char *current_pointer = Pointer;
1061 
1062   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1063   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1064   if (attr & RPC_FC_P_DONTFREE) return;
1065   pFormat += 2;
1066   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1067   else desc = pFormat + *(const SHORT*)pFormat;
1068 
1069   if (!Pointer) return;
1070 
1071   if (type == RPC_FC_FP) {
1072     int pointer_needs_freeing = NdrFullPointerFree(
1073       pStubMsg->FullPtrXlatTables, Pointer);
1074     if (!pointer_needs_freeing)
1075       return;
1076   }
1077 
1078   if (attr & RPC_FC_P_DEREF) {
1079     current_pointer = *(unsigned char**)Pointer;
1080     TRACE("deref => %p\n", current_pointer);
1081   }
1082 
1083   m = NdrFreer[*desc & NDR_TABLE_MASK];
1084   if (m) m(pStubMsg, current_pointer, desc);
1085 
1086   /* this check stops us from trying to free buffer memory. we don't have to
1087    * worry about clients, since they won't call this function.
1088    * we don't have to check for the buffer being reallocated because
1089    * BufferStart and BufferEnd won't be reset when allocating memory for
1090    * sending the response. we don't have to check for the new buffer here as
1091    * it won't be used a type memory, only for buffer memory */
1092   if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd)
1093       goto notfree;
1094 
1095   if (attr & RPC_FC_P_ONSTACK) {
1096     TRACE("not freeing stack ptr %p\n", Pointer);
1097     return;
1098   }
1099   TRACE("freeing %p\n", Pointer);
1100   NdrFree(pStubMsg, Pointer);
1101   return;
1102 notfree:
1103   TRACE("not freeing %p\n", Pointer);
1104 }
1105 
1106 /***********************************************************************
1107  *           EmbeddedPointerMarshall
1108  */
1109 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1110                                                unsigned char *pMemory,
1111                                                PFORMAT_STRING pFormat)
1112 {
1113   unsigned char *Mark = pStubMsg->BufferMark;
1114   unsigned rep, count, stride;
1115   unsigned i;
1116   unsigned char *saved_buffer = NULL;
1117 
1118   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1119 
1120   if (*pFormat != RPC_FC_PP) return NULL;
1121   pFormat += 2;
1122 
1123   if (pStubMsg->PointerBufferMark)
1124   {
1125     saved_buffer = pStubMsg->Buffer;
1126     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1127     pStubMsg->PointerBufferMark = NULL;
1128   }
1129 
1130   while (pFormat[0] != RPC_FC_END) {
1131     switch (pFormat[0]) {
1132     default:
1133       FIXME("unknown repeat type %d\n", pFormat[0]);
1134     case RPC_FC_NO_REPEAT:
1135       rep = 1;
1136       stride = 0;
1137       count = 1;
1138       pFormat += 2;
1139       break;
1140     case RPC_FC_FIXED_REPEAT:
1141       rep = *(const WORD*)&pFormat[2];
1142       stride = *(const WORD*)&pFormat[4];
1143       count = *(const WORD*)&pFormat[8];
1144       pFormat += 10;
1145       break;
1146     case RPC_FC_VARIABLE_REPEAT:
1147       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1148       stride = *(const WORD*)&pFormat[2];
1149       count = *(const WORD*)&pFormat[6];
1150       pFormat += 8;
1151       break;
1152     }
1153     for (i = 0; i < rep; i++) {
1154       PFORMAT_STRING info = pFormat;
1155       unsigned char *membase = pMemory + (i * stride);
1156       unsigned char *bufbase = Mark + (i * stride);
1157       unsigned u;
1158 
1159       for (u=0; u<count; u++,info+=8) {
1160         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1161         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1162         unsigned char *saved_memory = pStubMsg->Memory;
1163 
1164         pStubMsg->Memory = pMemory;
1165         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1166         pStubMsg->Memory = saved_memory;
1167       }
1168     }
1169     pFormat += 8 * count;
1170   }
1171 
1172   if (saved_buffer)
1173   {
1174     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1175     pStubMsg->Buffer = saved_buffer;
1176   }
1177 
1178   STD_OVERFLOW_CHECK(pStubMsg);
1179 
1180   return NULL;
1181 }
1182 
1183 /***********************************************************************
1184  *           EmbeddedPointerUnmarshall
1185  */
1186 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1187                                                  unsigned char *pDstBuffer,
1188                                                  unsigned char *pSrcMemoryPtrs,
1189                                                  PFORMAT_STRING pFormat,
1190                                                  unsigned char fMustAlloc)
1191 {
1192   unsigned char *Mark = pStubMsg->BufferMark;
1193   unsigned rep, count, stride;
1194   unsigned i;
1195   unsigned char *saved_buffer = NULL;
1196 
1197   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1198 
1199   if (*pFormat != RPC_FC_PP) return NULL;
1200   pFormat += 2;
1201 
1202   if (pStubMsg->PointerBufferMark)
1203   {
1204     saved_buffer = pStubMsg->Buffer;
1205     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1206     pStubMsg->PointerBufferMark = NULL;
1207   }
1208 
1209   while (pFormat[0] != RPC_FC_END) {
1210     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1211     switch (pFormat[0]) {
1212     default:
1213       FIXME("unknown repeat type %d\n", pFormat[0]);
1214     case RPC_FC_NO_REPEAT:
1215       rep = 1;
1216       stride = 0;
1217       count = 1;
1218       pFormat += 2;
1219       break;
1220     case RPC_FC_FIXED_REPEAT:
1221       rep = *(const WORD*)&pFormat[2];
1222       stride = *(const WORD*)&pFormat[4];
1223       count = *(const WORD*)&pFormat[8];
1224       pFormat += 10;
1225       break;
1226     case RPC_FC_VARIABLE_REPEAT:
1227       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1228       stride = *(const WORD*)&pFormat[2];
1229       count = *(const WORD*)&pFormat[6];
1230       pFormat += 8;
1231       break;
1232     }
1233     for (i = 0; i < rep; i++) {
1234       PFORMAT_STRING info = pFormat;
1235       unsigned char *bufdstbase = pDstBuffer + (i * stride);
1236       unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1237       unsigned char *bufbase = Mark + (i * stride);
1238       unsigned u;
1239 
1240       for (u=0; u<count; u++,info+=8) {
1241         unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1242         unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1243         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1244         PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1245       }
1246     }
1247     pFormat += 8 * count;
1248   }
1249 
1250   if (saved_buffer)
1251   {
1252     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1253     pStubMsg->Buffer = saved_buffer;
1254   }
1255 
1256   return NULL;
1257 }
1258 
1259 /***********************************************************************
1260  *           EmbeddedPointerBufferSize
1261  */
1262 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1263                                       unsigned char *pMemory,
1264                                       PFORMAT_STRING pFormat)
1265 {
1266   unsigned rep, count, stride;
1267   unsigned i;
1268   ULONG saved_buffer_length = 0;
1269 
1270   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1271 
1272   if (pStubMsg->IgnoreEmbeddedPointers) return;
1273 
1274   if (*pFormat != RPC_FC_PP) return;
1275   pFormat += 2;
1276 
1277   if (pStubMsg->PointerLength)
1278   {
1279     saved_buffer_length = pStubMsg->BufferLength;
1280     pStubMsg->BufferLength = pStubMsg->PointerLength;
1281     pStubMsg->PointerLength = 0;
1282   }
1283 
1284   while (pFormat[0] != RPC_FC_END) {
1285     switch (pFormat[0]) {
1286     default:
1287       FIXME("unknown repeat type %d\n", pFormat[0]);
1288     case RPC_FC_NO_REPEAT:
1289       rep = 1;
1290       stride = 0;
1291       count = 1;
1292       pFormat += 2;
1293       break;
1294     case RPC_FC_FIXED_REPEAT:
1295       rep = *(const WORD*)&pFormat[2];
1296       stride = *(const WORD*)&pFormat[4];
1297       count = *(const WORD*)&pFormat[8];
1298       pFormat += 10;
1299       break;
1300     case RPC_FC_VARIABLE_REPEAT:
1301       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1302       stride = *(const WORD*)&pFormat[2];
1303       count = *(const WORD*)&pFormat[6];
1304       pFormat += 8;
1305       break;
1306     }
1307     for (i = 0; i < rep; i++) {
1308       PFORMAT_STRING info = pFormat;
1309       unsigned char *membase = pMemory + (i * stride);
1310       unsigned u;
1311 
1312       for (u=0; u<count; u++,info+=8) {
1313         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1314         unsigned char *saved_memory = pStubMsg->Memory;
1315 
1316         pStubMsg->Memory = pMemory;
1317         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1318         pStubMsg->Memory = saved_memory;
1319       }
1320     }
1321     pFormat += 8 * count;
1322   }
1323 
1324   if (saved_buffer_length)
1325   {
1326     pStubMsg->PointerLength = pStubMsg->BufferLength;
1327     pStubMsg->BufferLength = saved_buffer_length;
1328   }
1329 }
1330 
1331 /***********************************************************************
1332  *           EmbeddedPointerMemorySize [internal]
1333  */
1334 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1335                                                PFORMAT_STRING pFormat)
1336 {
1337   unsigned char *Mark = pStubMsg->BufferMark;
1338   unsigned rep, count, stride;
1339   unsigned i;
1340   unsigned char *saved_buffer = NULL;
1341 
1342   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1343 
1344   if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1345 
1346   if (pStubMsg->PointerBufferMark)
1347   {
1348     saved_buffer = pStubMsg->Buffer;
1349     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1350     pStubMsg->PointerBufferMark = NULL;
1351   }
1352 
1353   if (*pFormat != RPC_FC_PP) return 0;
1354   pFormat += 2;
1355 
1356   while (pFormat[0] != RPC_FC_END) {
1357     switch (pFormat[0]) {
1358     default:
1359       FIXME("unknown repeat type %d\n", pFormat[0]);
1360     case RPC_FC_NO_REPEAT:
1361       rep = 1;
1362       stride = 0;
1363       count = 1;
1364       pFormat += 2;
1365       break;
1366     case RPC_FC_FIXED_REPEAT:
1367       rep = *(const WORD*)&pFormat[2];
1368       stride = *(const WORD*)&pFormat[4];
1369       count = *(const WORD*)&pFormat[8];
1370       pFormat += 10;
1371       break;
1372     case RPC_FC_VARIABLE_REPEAT:
1373       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1374       stride = *(const WORD*)&pFormat[2];
1375       count = *(const WORD*)&pFormat[6];
1376       pFormat += 8;
1377       break;
1378     }
1379     for (i = 0; i < rep; i++) {
1380       PFORMAT_STRING info = pFormat;
1381       unsigned char *bufbase = Mark + (i * stride);
1382       unsigned u;
1383       for (u=0; u<count; u++,info+=8) {
1384         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1385         PointerMemorySize(pStubMsg, bufptr, info+4);
1386       }
1387     }
1388     pFormat += 8 * count;
1389   }
1390 
1391   if (saved_buffer)
1392   {
1393     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1394     pStubMsg->Buffer = saved_buffer;
1395   }
1396 
1397   return 0;
1398 }
1399 
1400 /***********************************************************************
1401  *           EmbeddedPointerFree [internal]
1402  */
1403 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1404                                 unsigned char *pMemory,
1405                                 PFORMAT_STRING pFormat)
1406 {
1407   unsigned rep, count, stride;
1408   unsigned i;
1409 
1410   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1411   if (*pFormat != RPC_FC_PP) return;
1412   pFormat += 2;
1413 
1414   while (pFormat[0] != RPC_FC_END) {
1415     switch (pFormat[0]) {
1416     default:
1417       FIXME("unknown repeat type %d\n", pFormat[0]);
1418     case RPC_FC_NO_REPEAT:
1419       rep = 1;
1420       stride = 0;
1421       count = 1;
1422       pFormat += 2;
1423       break;
1424     case RPC_FC_FIXED_REPEAT:
1425       rep = *(const WORD*)&pFormat[2];
1426       stride = *(const WORD*)&pFormat[4];
1427       count = *(const WORD*)&pFormat[8];
1428       pFormat += 10;
1429       break;
1430     case RPC_FC_VARIABLE_REPEAT:
1431       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1432       stride = *(const WORD*)&pFormat[2];
1433       count = *(const WORD*)&pFormat[6];
1434       pFormat += 8;
1435       break;
1436     }
1437     for (i = 0; i < rep; i++) {
1438       PFORMAT_STRING info = pFormat;
1439       unsigned char *membase = pMemory + (i * stride);
1440       unsigned u;
1441 
1442       for (u=0; u<count; u++,info+=8) {
1443         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1444         unsigned char *saved_memory = pStubMsg->Memory;
1445 
1446         pStubMsg->Memory = pMemory;
1447         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1448         pStubMsg->Memory = saved_memory;
1449       }
1450     }
1451     pFormat += 8 * count;
1452   }
1453 }
1454 
1455 /***********************************************************************
1456  *           NdrPointerMarshall [RPCRT4.@]
1457  */
1458 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1459                                           unsigned char *pMemory,
1460                                           PFORMAT_STRING pFormat)
1461 {
1462   unsigned char *Buffer;
1463 
1464   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1465 
1466   /* Increment the buffer here instead of in PointerMarshall,
1467    * as that is used by embedded pointers which already handle the incrementing
1468    * the buffer, and shouldn't write any additional pointer data to the wire */
1469   if (*pFormat != RPC_FC_RP)
1470   {
1471     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1472     Buffer = pStubMsg->Buffer;
1473     safe_buffer_increment(pStubMsg, 4);
1474   }
1475   else
1476     Buffer = pStubMsg->Buffer;
1477 
1478   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1479 
1480   return NULL;
1481 }
1482 
1483 /***********************************************************************
1484  *           NdrPointerUnmarshall [RPCRT4.@]
1485  */
1486 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1487                                             unsigned char **ppMemory,
1488                                             PFORMAT_STRING pFormat,
1489                                             unsigned char fMustAlloc)
1490 {
1491   unsigned char *Buffer;
1492 
1493   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1494 
1495   /* Increment the buffer here instead of in PointerUnmarshall,
1496    * as that is used by embedded pointers which already handle the incrementing
1497    * the buffer, and shouldn't read any additional pointer data from the
1498    * buffer */
1499   if (*pFormat != RPC_FC_RP)
1500   {
1501     ALIGN_POINTER(pStubMsg->Buffer, 4);
1502     Buffer = pStubMsg->Buffer;
1503     safe_buffer_increment(pStubMsg, 4);
1504   }
1505   else
1506     Buffer = pStubMsg->Buffer;
1507 
1508   PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1509 
1510   return NULL;
1511 }
1512 
1513 /***********************************************************************
1514  *           NdrPointerBufferSize [RPCRT4.@]
1515  */
1516 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1517                                       unsigned char *pMemory,
1518                                       PFORMAT_STRING pFormat)
1519 {
1520   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1521 
1522   /* Increment the buffer length here instead of in PointerBufferSize,
1523    * as that is used by embedded pointers which already handle the buffer
1524    * length, and shouldn't write anything more to the wire */
1525   if (*pFormat != RPC_FC_RP)
1526   {
1527     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1528     safe_buffer_length_increment(pStubMsg, 4);
1529   }
1530 
1531   PointerBufferSize(pStubMsg, pMemory, pFormat);
1532 }
1533 
1534 /***********************************************************************
1535  *           NdrPointerMemorySize [RPCRT4.@]
1536  */
1537 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1538                                   PFORMAT_STRING pFormat)
1539 {
1540   /* unsigned size = *(LPWORD)(pFormat+2); */
1541   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1542   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1543   return 0;
1544 }
1545 
1546 /***********************************************************************
1547  *           NdrPointerFree [RPCRT4.@]
1548  */
1549 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1550                            unsigned char *pMemory,
1551                            PFORMAT_STRING pFormat)
1552 {
1553   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1554   PointerFree(pStubMsg, pMemory, pFormat);
1555 }
1556 
1557 /***********************************************************************
1558  *           NdrSimpleTypeMarshall [RPCRT4.@]
1559  */
1560 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1561                                    unsigned char FormatChar )
1562 {
1563     NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1564 }
1565 
1566 /***********************************************************************
1567  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
1568  *
1569  * Unmarshall a base type.
1570  *
1571  * NOTES
1572  *  Doesn't check that the buffer is long enough before copying, so the caller
1573  * should do this.
1574  */
1575 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1576                                      unsigned char FormatChar )
1577 {
1578 #define BASE_TYPE_UNMARSHALL(type) \
1579         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
1580         TRACE("pMemory: %p\n", pMemory); \
1581         *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1582         pStubMsg->Buffer += sizeof(type);
1583 
1584     switch(FormatChar)
1585     {
1586     case RPC_FC_BYTE:
1587     case RPC_FC_CHAR:
1588     case RPC_FC_SMALL:
1589     case RPC_FC_USMALL:
1590         BASE_TYPE_UNMARSHALL(UCHAR);
1591         TRACE("value: 0x%02x\n", *pMemory);
1592         break;
1593     case RPC_FC_WCHAR:
1594     case RPC_FC_SHORT:
1595     case RPC_FC_USHORT:
1596         BASE_TYPE_UNMARSHALL(USHORT);
1597         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1598         break;
1599     case RPC_FC_LONG:
1600     case RPC_FC_ULONG:
1601     case RPC_FC_ERROR_STATUS_T:
1602     case RPC_FC_ENUM32:
1603         BASE_TYPE_UNMARSHALL(ULONG);
1604         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1605         break;
1606    case RPC_FC_FLOAT:
1607         BASE_TYPE_UNMARSHALL(float);
1608         TRACE("value: %f\n", *(float *)pMemory);
1609         break;
1610     case RPC_FC_DOUBLE:
1611         BASE_TYPE_UNMARSHALL(double);
1612         TRACE("value: %f\n", *(double *)pMemory);
1613         break;
1614     case RPC_FC_HYPER:
1615         BASE_TYPE_UNMARSHALL(ULONGLONG);
1616         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1617         break;
1618     case RPC_FC_ENUM16:
1619         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
1620         TRACE("pMemory: %p\n", pMemory);
1621         /* 16-bits on the wire, but int in memory */
1622         *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1623         pStubMsg->Buffer += sizeof(USHORT);
1624         TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1625         break;
1626     case RPC_FC_IGNORE:
1627         break;
1628     default:
1629         FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1630     }
1631 #undef BASE_TYPE_UNMARSHALL
1632 }
1633 
1634 /***********************************************************************
1635  *           NdrSimpleStructMarshall [RPCRT4.@]
1636  */
1637 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1638                                                unsigned char *pMemory,
1639                                                PFORMAT_STRING pFormat)
1640 {
1641   unsigned size = *(const WORD*)(pFormat+2);
1642   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1643 
1644   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
1645 
1646   pStubMsg->BufferMark = pStubMsg->Buffer;
1647   safe_copy_to_buffer(pStubMsg, pMemory, size);
1648 
1649   if (pFormat[0] != RPC_FC_STRUCT)
1650     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1651 
1652   return NULL;
1653 }
1654 
1655 /***********************************************************************
1656  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1657  */
1658 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1659                                                  unsigned char **ppMemory,
1660                                                  PFORMAT_STRING pFormat,
1661                                                  unsigned char fMustAlloc)
1662 {
1663   unsigned size = *(const WORD*)(pFormat+2);
1664   unsigned char *saved_buffer;
1665   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1666 
1667   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1668 
1669   if (fMustAlloc)
1670     *ppMemory = NdrAllocate(pStubMsg, size);
1671   else
1672   {
1673     if (!pStubMsg->IsClient && !*ppMemory)
1674       /* for servers, we just point straight into the RPC buffer */
1675       *ppMemory = pStubMsg->Buffer;
1676   }
1677 
1678   saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1679   safe_buffer_increment(pStubMsg, size);
1680   if (pFormat[0] == RPC_FC_PSTRUCT)
1681       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1682 
1683   TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1684   if (*ppMemory != saved_buffer)
1685       memcpy(*ppMemory, saved_buffer, size);
1686 
1687   return NULL;
1688 }
1689 
1690 /***********************************************************************
1691  *           NdrSimpleStructBufferSize [RPCRT4.@]
1692  */
1693 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1694                                       unsigned char *pMemory,
1695                                       PFORMAT_STRING pFormat)
1696 {
1697   unsigned size = *(const WORD*)(pFormat+2);
1698   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1699 
1700   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1701 
1702   safe_buffer_length_increment(pStubMsg, size);
1703   if (pFormat[0] != RPC_FC_STRUCT)
1704     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1705 }
1706 
1707 /***********************************************************************
1708  *           NdrSimpleStructMemorySize [RPCRT4.@]
1709  */
1710 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1711                                        PFORMAT_STRING pFormat)
1712 {
1713   unsigned short size = *(const WORD *)(pFormat+2);
1714 
1715   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1716 
1717   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1718   pStubMsg->MemorySize += size;
1719   safe_buffer_increment(pStubMsg, size);
1720 
1721   if (pFormat[0] != RPC_FC_STRUCT)
1722     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1723   return pStubMsg->MemorySize;
1724 }
1725 
1726 /***********************************************************************
1727  *           NdrSimpleStructFree [RPCRT4.@]
1728  */
1729 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1730                                 unsigned char *pMemory,
1731                                 PFORMAT_STRING pFormat)
1732 {
1733   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1734   if (pFormat[0] != RPC_FC_STRUCT)
1735     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1736 }
1737 
1738 /* Array helpers */
1739 
1740 static inline void array_compute_and_size_conformance(
1741     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1742     PFORMAT_STRING pFormat)
1743 {
1744   switch (fc)
1745   {
1746   case RPC_FC_CARRAY:
1747     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1748     SizeConformance(pStubMsg);
1749     break;
1750   case RPC_FC_CVARRAY:
1751     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1752     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1753     SizeConformance(pStubMsg);
1754     break;
1755   case RPC_FC_C_CSTRING:
1756   case RPC_FC_C_WSTRING:
1757     if (pFormat[0] == RPC_FC_C_CSTRING)
1758     {
1759       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1760       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1761     }
1762     else
1763     {
1764       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1765       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1766     }
1767 
1768     if (fc == RPC_FC_STRING_SIZED)
1769       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1770     else
1771       pStubMsg->MaxCount = pStubMsg->ActualCount;
1772 
1773     SizeConformance(pStubMsg);
1774     break;
1775   default:
1776     ERR("unknown array format 0x%x\n", fc);
1777     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1778   }
1779 }
1780 
1781 static inline void array_buffer_size(
1782     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1783     PFORMAT_STRING pFormat, unsigned char fHasPointers)
1784 {
1785   DWORD size;
1786   DWORD esize;
1787   unsigned char alignment;
1788 
1789   switch (fc)
1790   {
1791   case RPC_FC_CARRAY:
1792     esize = *(const WORD*)(pFormat+2);
1793     alignment = pFormat[1] + 1;
1794 
1795     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1796 
1797     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1798 
1799     size = safe_multiply(esize, pStubMsg->MaxCount);
1800     /* conformance value plus array */
1801     safe_buffer_length_increment(pStubMsg, size);
1802 
1803     if (fHasPointers)
1804       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1805     break;
1806   case RPC_FC_CVARRAY:
1807     esize = *(const WORD*)(pFormat+2);
1808     alignment = pFormat[1] + 1;
1809 
1810     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1811     pFormat = SkipConformance(pStubMsg, pFormat);
1812 
1813     SizeVariance(pStubMsg);
1814 
1815     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1816 
1817     size = safe_multiply(esize, pStubMsg->ActualCount);
1818     safe_buffer_length_increment(pStubMsg, size);
1819 
1820     if (fHasPointers)
1821       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1822     break;
1823   case RPC_FC_C_CSTRING:
1824   case RPC_FC_C_WSTRING:
1825     if (fc == RPC_FC_C_CSTRING)
1826       esize = 1;
1827     else
1828       esize = 2;
1829 
1830     SizeVariance(pStubMsg);
1831 
1832     size = safe_multiply(esize, pStubMsg->ActualCount);
1833     safe_buffer_length_increment(pStubMsg, size);
1834     break;
1835   default:
1836     ERR("unknown array format 0x%x\n", fc);
1837     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1838   }
1839 }
1840 
1841 static inline void array_compute_and_write_conformance(
1842     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1843     PFORMAT_STRING pFormat)
1844 {
1845   switch (fc)
1846   {
1847   case RPC_FC_CARRAY:
1848     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1849     WriteConformance(pStubMsg);
1850     break;
1851   case RPC_FC_CVARRAY:
1852     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1853     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1854     WriteConformance(pStubMsg);
1855     break;
1856   case RPC_FC_C_CSTRING:
1857   case RPC_FC_C_WSTRING:
1858     if (fc == RPC_FC_C_CSTRING)
1859     {
1860       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1861       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1862     }
1863     else
1864     {
1865       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1866       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1867     }
1868     if (pFormat[1] == RPC_FC_STRING_SIZED)
1869       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1870     else
1871       pStubMsg->MaxCount = pStubMsg->ActualCount;
1872     pStubMsg->Offset = 0;
1873     WriteConformance(pStubMsg);
1874     break;
1875   default:
1876     ERR("unknown array format 0x%x\n", fc);
1877     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1878   }
1879 }
1880 
1881 static inline void array_write_variance_and_marshall(
1882     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1883     PFORMAT_STRING pFormat, unsigned char fHasPointers)
1884 {
1885   DWORD size;
1886   DWORD esize;
1887   unsigned char alignment;
1888 
1889   switch (fc)
1890   {
1891   case RPC_FC_CARRAY:
1892     esize = *(const WORD*)(pFormat+2);
1893     alignment = pFormat[1] + 1;
1894 
1895     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1896 
1897     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1898 
1899     size = safe_multiply(esize, pStubMsg->MaxCount);
1900     if (fHasPointers)
1901       pStubMsg->BufferMark = pStubMsg->Buffer;
1902     safe_copy_to_buffer(pStubMsg, pMemory, size);
1903 
1904     if (fHasPointers)
1905       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1906     break;
1907   case RPC_FC_CVARRAY:
1908     esize = *(const WORD*)(pFormat+2);
1909     alignment = pFormat[1] + 1;
1910 
1911     /* conformance */
1912     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1913     /* variance */
1914     pFormat = SkipConformance(pStubMsg, pFormat);
1915 
1916     WriteVariance(pStubMsg);
1917 
1918     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1919 
1920     size = safe_multiply(esize, pStubMsg->ActualCount);
1921 
1922     if (fHasPointers)
1923       pStubMsg->BufferMark = pStubMsg->Buffer;
1924     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
1925 
1926     if (fHasPointers)
1927       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1928     break;
1929   case RPC_FC_C_CSTRING:
1930   case RPC_FC_C_WSTRING:
1931     if (fc == RPC_FC_C_CSTRING)
1932       esize = 1;
1933     else
1934       esize = 2;
1935 
1936     WriteVariance(pStubMsg);
1937 
1938     size = safe_multiply(esize, pStubMsg->ActualCount);
1939     safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
1940     break;
1941   default:
1942     ERR("unknown array format 0x%x\n", fc);
1943     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1944   }
1945 }
1946 
1947 static inline ULONG array_read_conformance(
1948     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
1949 {
1950   DWORD esize;
1951 
1952   switch (fc)
1953   {
1954   case RPC_FC_CARRAY:
1955     esize = *(const WORD*)(pFormat+2);
1956     pFormat = ReadConformance(pStubMsg, pFormat+4);
1957     return safe_multiply(esize, pStubMsg->MaxCount);
1958   case RPC_FC_CVARRAY:
1959     esize = *(const WORD*)(pFormat+2);
1960     pFormat = ReadConformance(pStubMsg, pFormat+4);
1961     return safe_multiply(esize, pStubMsg->MaxCount);
1962   case RPC_FC_C_CSTRING:
1963   case RPC_FC_C_WSTRING:
1964     if (fc == RPC_FC_C_CSTRING)
1965       esize = 1;
1966     else
1967       esize = 2;
1968 
1969     if (pFormat[1] == RPC_FC_STRING_SIZED)
1970       ReadConformance(pStubMsg, pFormat + 2);
1971     else
1972       ReadConformance(pStubMsg, NULL);
1973     return safe_multiply(esize, pStubMsg->MaxCount);
1974   default:
1975     ERR("unknown array format 0x%x\n", fc);
1976     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1977   }
1978 }
1979 
1980 static inline ULONG array_read_variance_and_unmarshall(
1981     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
1982     PFORMAT_STRING pFormat, unsigned char fMustAlloc,
1983     unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
1984 {
1985   ULONG bufsize, memsize;
1986   WORD esize;
1987   unsigned char alignment;
1988   unsigned char *saved_buffer;
1989   ULONG offset;
1990 
1991   switch (fc)
1992   {
1993   case RPC_FC_CARRAY:
1994     esize = *(const WORD*)(pFormat+2);
1995     alignment = pFormat[1] + 1;
1996 
1997     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
1998 
1999     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2000 
2001     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2002 
2003     if (fUnmarshall)
2004     {
2005       if (fMustAlloc)
2006         *ppMemory = NdrAllocate(pStubMsg, memsize);
2007       else
2008       {
2009         if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2010           /* for servers, we just point straight into the RPC buffer */
2011           *ppMemory = pStubMsg->Buffer;
2012       }
2013 
2014       saved_buffer = pStubMsg->Buffer;
2015       safe_buffer_increment(pStubMsg, bufsize);
2016 
2017       pStubMsg->BufferMark = saved_buffer;
2018       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2019 
2020       TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2021       if (*ppMemory != saved_buffer)
2022         memcpy(*ppMemory, saved_buffer, bufsize);
2023     }
2024     return bufsize;
2025   case RPC_FC_CVARRAY:
2026     esize = *(const WORD*)(pFormat+2);
2027     alignment = pFormat[1] + 1;
2028 
2029     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2030 
2031     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2032 
2033     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2034 
2035     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2036     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2037 
2038     if (fUnmarshall)
2039     {
2040       offset = pStubMsg->Offset;
2041 
2042       if (!fMustAlloc && !*ppMemory)
2043         fMustAlloc = TRUE;
2044       if (fMustAlloc)
2045         *ppMemory = NdrAllocate(pStubMsg, memsize);
2046       saved_buffer = pStubMsg->Buffer;
2047       safe_buffer_increment(pStubMsg, bufsize);
2048 
2049       pStubMsg->BufferMark = saved_buffer;
2050       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2051                                 fMustAlloc);
2052 
2053       memcpy(*ppMemory + offset, saved_buffer, bufsize);
2054     }
2055     return bufsize;
2056   case RPC_FC_C_CSTRING:
2057   case RPC_FC_C_WSTRING:
2058     if (fc == RPC_FC_C_CSTRING)
2059       esize = 1;
2060     else
2061       esize = 2;
2062 
2063     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2064 
2065     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2066     {
2067       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2068           pStubMsg->ActualCount, pStubMsg->MaxCount);
2069       RpcRaiseException(RPC_S_INVALID_BOUND);
2070     }
2071     if (pStubMsg->Offset)
2072     {
2073       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2074       RpcRaiseException(RPC_S_INVALID_BOUND);
2075     }
2076 
2077     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2078     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2079 
2080     validate_string_data(pStubMsg, bufsize, esize);
2081 
2082     if (fUnmarshall)
2083     {
2084       if (fMustAlloc)
2085         *ppMemory = NdrAllocate(pStubMsg, memsize);
2086       else
2087       {
2088         if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2089             !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2090           /* if the data in the RPC buffer is big enough, we just point
2091            * straight into it */
2092           *ppMemory = pStubMsg->Buffer;
2093         else if (!*ppMemory)
2094           *ppMemory = NdrAllocate(pStubMsg, memsize);
2095       }
2096 
2097       if (*ppMemory == pStubMsg->Buffer)
2098         safe_buffer_increment(pStubMsg, bufsize);
2099       else
2100         safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2101 
2102       if (*pFormat == RPC_FC_C_CSTRING)
2103         TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2104       else
2105         TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2106     }
2107     return bufsize;
2108   default:
2109     ERR("unknown array format 0x%x\n", fc);
2110     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2111   }
2112 }
2113 
2114 static inline void array_memory_size(
2115     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2116     unsigned char fHasPointers)
2117 {
2118   ULONG bufsize, memsize;
2119   DWORD esize;
2120   unsigned char alignment;
2121 
2122   switch (fc)
2123   {
2124   case RPC_FC_CARRAY:
2125     esize = *(const WORD*)(pFormat+2);
2126     alignment = pFormat[1] + 1;
2127 
2128     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2129 
2130     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2131     pStubMsg->MemorySize += memsize;
2132 
2133     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2134     if (fHasPointers)
2135       pStubMsg->BufferMark = pStubMsg->Buffer;
2136     safe_buffer_increment(pStubMsg, bufsize);
2137 
2138     if (fHasPointers)
2139       EmbeddedPointerMemorySize(pStubMsg, pFormat);
2140     break;
2141   case RPC_FC_CVARRAY:
2142     esize = *(const WORD*)(pFormat+2);
2143     alignment = pFormat[1] + 1;
2144 
2145     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2146 
2147     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2148 
2149     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2150     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2151     pStubMsg->MemorySize += memsize;
2152 
2153     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2154     if (fHasPointers)
2155       pStubMsg->BufferMark = pStubMsg->Buffer;
2156     safe_buffer_increment(pStubMsg, bufsize);
2157 
2158     if (fHasPointers)
2159       EmbeddedPointerMemorySize(pStubMsg, pFormat);
2160     break;
2161   case RPC_FC_C_CSTRING:
2162   case RPC_FC_C_WSTRING:
2163     if (fc == RPC_FC_C_CSTRING)
2164       esize = 1;
2165     else
2166       esize = 2;
2167 
2168     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2169 
2170     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2171     {
2172       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2173           pStubMsg->ActualCount, pStubMsg->MaxCount);
2174       RpcRaiseException(RPC_S_INVALID_BOUND);
2175     }
2176     if (pStubMsg->Offset)
2177     {
2178       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2179       RpcRaiseException(RPC_S_INVALID_BOUND);
2180     }
2181 
2182     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2183     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2184 
2185     validate_string_data(pStubMsg, bufsize, esize);
2186 
2187     safe_buffer_increment(pStubMsg, bufsize);
2188     pStubMsg->MemorySize += memsize;
2189     break;
2190   default:
2191     ERR("unknown array format 0x%x\n", fc);
2192     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2193   }
2194 }
2195 
2196 static inline void array_free(
2197     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2198     unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2199 {
2200   switch (fc)
2201   {
2202   case RPC_FC_CARRAY:
2203     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2204     if (fHasPointers)
2205       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2206     break;
2207   case RPC_FC_CVARRAY:
2208     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2209     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2210     if (fHasPointers)
2211       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2212     break;
2213   case RPC_FC_C_CSTRING:
2214   case RPC_FC_C_WSTRING:
2215     /* No embedded pointers so nothing to do */
2216     break;
2217   default:
2218     ERR("unknown array format 0x%x\n", fc);
2219     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2220   }
2221 }
2222 
2223 /*
2224  * NdrConformantString:
2225  *
2226  * What MS calls a ConformantString is, in DCE terminology,
2227  * a Varying-Conformant String.
2228  * [
2229  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2230  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
2231  *           into unmarshalled string)
2232  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2233  *   [
2234  *     data: CHARTYPE[maxlen]
2235  *   ]
2236  * ], where CHARTYPE is the appropriate character type (specified externally)
2237  *
2238  */
2239 
2240 /***********************************************************************
2241  *            NdrConformantStringMarshall [RPCRT4.@]
2242  */
2243 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
2244   unsigned char *pszMessage, PFORMAT_STRING pFormat)
2245 {
2246   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2247 
2248   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2249     ERR("Unhandled string type: %#x\n", pFormat[0]);
2250     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2251   }
2252 
2253   /* allow compiler to optimise inline function by passing constant into
2254    * these functions */
2255   if (pFormat[0] == RPC_FC_C_CSTRING) {
2256     array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2257                                         pFormat);
2258     array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2259                                       pFormat, TRUE /* fHasPointers */);
2260   } else {
2261     array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2262                                         pFormat);
2263     array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2264                                       pFormat, TRUE /* fHasPointers */);
2265   }
2266 
2267   return NULL;
2268 }
2269 
2270 /***********************************************************************
2271  *           NdrConformantStringBufferSize [RPCRT4.@]
2272  */
2273 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2274   unsigned char* pMemory, PFORMAT_STRING pFormat)
2275 {
2276   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2277 
2278   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2279     ERR("Unhandled string type: %#x\n", pFormat[0]);
2280     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2281   }
2282 
2283   /* allow compiler to optimise inline function by passing constant into
2284    * these functions */
2285   if (pFormat[0] == RPC_FC_C_CSTRING) {
2286     array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory,
2287                                        pFormat);
2288     array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2289                       TRUE /* fHasPointers */);
2290   } else {
2291     array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory,
2292                                        pFormat);
2293     array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2294                       TRUE /* fHasPointers */);
2295   }
2296 }
2297 
2298 /************************************************************************
2299  *            NdrConformantStringMemorySize [RPCRT4.@]
2300  */
2301 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2302   PFORMAT_STRING pFormat )
2303 {
2304   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2305 
2306   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2307     ERR("Unhandled string type: %#x\n", pFormat[0]);
2308     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2309   }
2310 
2311   /* allow compiler to optimise inline function by passing constant into
2312    * these functions */
2313   if (pFormat[0] == RPC_FC_C_CSTRING) {
2314     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2315     array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat,
2316                       TRUE /* fHasPointers */);
2317   } else {
2318     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2319     array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat,
2320                       TRUE /* fHasPointers */);
2321   }
2322 
2323   return pStubMsg->MemorySize;
2324 }
2325 
2326 /************************************************************************
2327  *           NdrConformantStringUnmarshall [RPCRT4.@]
2328  */
2329 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2330   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2331 {
2332   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2333     pStubMsg, *ppMemory, pFormat, fMustAlloc);
2334 
2335   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2336     ERR("Unhandled string type: %#x\n", *pFormat);
2337     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2338   }
2339 
2340   /* allow compiler to optimise inline function by passing constant into
2341    * these functions */
2342   if (pFormat[0] == RPC_FC_C_CSTRING) {
2343     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2344     array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory,
2345                                        pFormat, fMustAlloc,
2346                                        TRUE /* fUseBufferMemoryServer */,
2347                                        TRUE /* fUnmarshall */);
2348   } else {
2349     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2350     array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory,
2351                                        pFormat, fMustAlloc,
2352                                        TRUE /* fUseBufferMemoryServer */,
2353                                        TRUE /* fUnmarshall */);
2354   }
2355 
2356   return NULL;
2357 }
2358 
2359 /***********************************************************************
2360  *           NdrNonConformantStringMarshall [RPCRT4.@]
2361  */
2362 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2363                                 unsigned char *pMemory,
2364                                 PFORMAT_STRING pFormat)
2365 {
2366   ULONG esize, size, maxsize;
2367 
2368   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2369 
2370   maxsize = *(USHORT *)&pFormat[2];
2371 
2372   if (*pFormat == RPC_FC_CSTRING)
2373   {
2374     ULONG i;
2375     const char *str = (const char *)pMemory;
2376     for (i = 0; i < maxsize && *str; i++, str++)
2377         ;
2378     TRACE("string=%s\n", debugstr_an(str, i));
2379     pStubMsg->ActualCount = i + 1;
2380     esize = 1;
2381   }
2382   else if (*pFormat == RPC_FC_WSTRING)
2383   {
2384     ULONG i;
2385     const WCHAR *str = (const WCHAR *)pMemory;
2386     for (i = 0; i < maxsize && *str; i++, str++)
2387         ;
2388     TRACE("string=%s\n", debugstr_wn(str, i));
2389     pStubMsg->ActualCount = i + 1;
2390     esize = 2;
2391   }
2392   else
2393   {
2394     ERR("Unhandled string type: %#x\n", *pFormat);
2395     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2396   }
2397 
2398   pStubMsg->Offset = 0;
2399   WriteVariance(pStubMsg);
2400 
2401   size = safe_multiply(esize, pStubMsg->ActualCount);
2402   safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2403 
2404   return NULL;
2405 }
2406 
2407 /***********************************************************************
2408  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
2409  */
2410 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2411                                 unsigned char **ppMemory,
2412                                 PFORMAT_STRING pFormat,
2413                                 unsigned char fMustAlloc)
2414 {
2415   ULONG bufsize, memsize, esize, maxsize;
2416 
2417   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2418     pStubMsg, *ppMemory, pFormat, fMustAlloc);
2419 
2420   maxsize = *(USHORT *)&pFormat[2];
2421 
2422   ReadVariance(pStubMsg, NULL, maxsize);
2423   if (pStubMsg->Offset)
2424   {
2425     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2426     RpcRaiseException(RPC_S_INVALID_BOUND);
2427   }
2428 
2429   if (*pFormat == RPC_FC_CSTRING) esize = 1;
2430   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2431   else
2432   {
2433     ERR("Unhandled string type: %#x\n", *pFormat);
2434     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2435   }
2436 
2437   memsize = esize * maxsize;
2438   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2439 
2440   validate_string_data(pStubMsg, bufsize, esize);
2441 
2442   if (fMustAlloc || !*ppMemory)
2443     *ppMemory = NdrAllocate(pStubMsg, memsize);
2444 
2445   safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2446 
2447   if (*pFormat == RPC_FC_CSTRING) {
2448     TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2449   }
2450   else if (*pFormat == RPC_FC_WSTRING) {
2451     TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2452   }
2453 
2454   return NULL;
2455 }
2456 
2457 /***********************************************************************
2458  *           NdrNonConformantStringBufferSize [RPCRT4.@]
2459  */
2460 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2461                                 unsigned char *pMemory,
2462                                 PFORMAT_STRING pFormat)
2463 {
2464   ULONG esize, maxsize;
2465 
2466   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2467 
2468   maxsize = *(USHORT *)&pFormat[2];
2469 
2470   SizeVariance(pStubMsg);
2471 
2472   if (*pFormat == RPC_FC_CSTRING)
2473   {
2474     ULONG i;
2475     const char *str = (const char *)pMemory;
2476     for (i = 0; i < maxsize && *str; i++, str++)
2477         ;
2478     TRACE("string=%s\n", debugstr_an(str, i));
2479     pStubMsg->ActualCount = i + 1;
2480     esize = 1;
2481   }
2482   else if (*pFormat == RPC_FC_WSTRING)
2483   {
2484     ULONG i;
2485     const WCHAR *str = (const WCHAR *)pMemory;
2486     for (i = 0; i < maxsize && *str; i++, str++)
2487         ;
2488     TRACE("string=%s\n", debugstr_wn(str, i));
2489     pStubMsg->ActualCount = i + 1;
2490     esize = 2;
2491   }
2492   else
2493   {
2494     ERR("Unhandled string type: %#x\n", *pFormat);
2495     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2496   }
2497 
2498   safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2499 }
2500 
2501 /***********************************************************************
2502  *           NdrNonConformantStringMemorySize [RPCRT4.@]
2503  */
2504 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2505                                 PFORMAT_STRING pFormat)
2506 {
2507   ULONG bufsize, memsize, esize, maxsize;
2508 
2509   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2510 
2511   maxsize = *(USHORT *)&pFormat[2];
2512 
2513   ReadVariance(pStubMsg, NULL, maxsize);
2514 
2515   if (pStubMsg->Offset)
2516   {
2517     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2518     RpcRaiseException(RPC_S_INVALID_BOUND);
2519   }
2520 
2521   if (*pFormat == RPC_FC_CSTRING) esize = 1;
2522   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2523   else
2524   {
2525     ERR("Unhandled string type: %#x\n", *pFormat);
2526     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2527   }
2528 
2529   memsize = esize * maxsize;
2530   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2531 
2532   validate_string_data(pStubMsg, bufsize, esize);
2533 
2534   safe_buffer_increment(pStubMsg, bufsize);
2535   pStubMsg->MemorySize += memsize;
2536 
2537   return pStubMsg->MemorySize;
2538 }
2539 
2540 /* Complex types */
2541 
2542 #include "pshpack1.h"
2543 typedef struct
2544 {
2545     unsigned char type;
2546     unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2547     ULONG low_value;
2548     ULONG high_value;
2549 } NDR_RANGE;
2550 #include "poppack.h"
2551 
2552 static unsigned long EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2553                                          PFORMAT_STRING pFormat)
2554 {
2555   switch (*pFormat) {
2556   case RPC_FC_STRUCT:
2557   case RPC_FC_PSTRUCT:
2558   case RPC_FC_CSTRUCT:
2559   case RPC_FC_BOGUS_STRUCT:
2560   case RPC_FC_SMFARRAY:
2561   case RPC_FC_SMVARRAY:
2562   case RPC_FC_CSTRING:
2563     return *(const WORD*)&pFormat[2];
2564   case RPC_FC_USER_MARSHAL:
2565     return *(const WORD*)&pFormat[4];
2566   case RPC_FC_RANGE: {
2567     switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2568     case RPC_FC_BYTE:
2569     case RPC_FC_CHAR:
2570     case RPC_FC_SMALL:
2571     case RPC_FC_USMALL:
2572         return sizeof(UCHAR);
2573     case RPC_FC_WCHAR:
2574     case RPC_FC_SHORT:
2575     case RPC_FC_USHORT:
2576         return sizeof(USHORT);
2577     case RPC_FC_LONG:
2578     case RPC_FC_ULONG:
2579     case RPC_FC_ENUM32:
2580         return sizeof(ULONG);
2581     case RPC_FC_FLOAT:
2582         return sizeof(float);
2583     case RPC_FC_DOUBLE:
2584         return sizeof(double);
2585     case RPC_FC_HYPER:
2586         return sizeof(ULONGLONG);
2587     case RPC_FC_ENUM16:
2588         return sizeof(UINT);
2589     default:
2590         ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2591         RpcRaiseException(RPC_X_BAD_STUB_DATA);
2592     }
2593   }
2594   case RPC_FC_NON_ENCAPSULATED_UNION:
2595     pFormat += 2;
2596     if (pStubMsg->fHasNewCorrDesc)
2597         pFormat += 6;
2598     else
2599         pFormat += 4;
2600 
2601     pFormat += *(const SHORT*)pFormat;
2602     return *(const SHORT*)pFormat;
2603   case RPC_FC_IP:
2604     return sizeof(void *);
2605   case RPC_FC_WSTRING:
2606     return *(const WORD*)&pFormat[2] * 2;
2607   default:
2608     FIXME("unhandled embedded type %02x\n", *pFormat);
2609   }
2610   return 0;
2611 }
2612 
2613 
2614 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2615                                                PFORMAT_STRING pFormat)
2616 {
2617   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2618 
2619   if (!m)
2620   {
2621     FIXME("no memorysizer for data type=%02x\n", *pFormat);
2622     return 0;
2623   }
2624 
2625   return m(pStubMsg, pFormat);
2626 }
2627 
2628 
2629 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2630                                        unsigned char *pMemory,
2631                                        PFORMAT_STRING pFormat,
2632                                        PFORMAT_STRING pPointer)
2633 {
2634   PFORMAT_STRING desc;
2635   NDR_MARSHALL m;
2636   unsigned long size;
2637 
2638   while (*pFormat != RPC_FC_END) {
2639     switch (*pFormat) {
2640     case RPC_FC_BYTE:
2641     case RPC_FC_CHAR:
2642     case RPC_FC_SMALL:
2643     case RPC_FC_USMALL:
2644       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2645       safe_copy_to_buffer(pStubMsg, pMemory, 1);
2646       pMemory += 1;
2647       break;
2648     case RPC_FC_WCHAR:
2649     case RPC_FC_SHORT:
2650     case RPC_FC_USHORT:
2651       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2652       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2653       pMemory += 2;
2654       break;
2655     case RPC_FC_ENUM16:
2656       TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2657       if (32767 < *(DWORD*)pMemory)
2658         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2659       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2660       pMemory += 4;
2661       break;
2662     case RPC_FC_LONG:
2663     case RPC_FC_ULONG:
2664     case RPC_FC_ENUM32:
2665       TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2666       safe_copy_to_buffer(pStubMsg, pMemory, 4);
2667       pMemory += 4;
2668       break;
2669     case RPC_FC_HYPER:
2670       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2671       safe_copy_to_buffer(pStubMsg, pMemory, 8);
2672       pMemory += 8;
2673       break;
2674     case RPC_FC_POINTER:
2675     {
2676       unsigned char *saved_buffer;
2677       int pointer_buffer_mark_set = 0;
2678       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2679       TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2680       if (*pPointer != RPC_FC_RP)
2681         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2682       saved_buffer = pStubMsg->Buffer;
2683       if (pStubMsg->PointerBufferMark)
2684       {
2685         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2686         pStubMsg->PointerBufferMark = NULL;
2687         pointer_buffer_mark_set = 1;
2688       }
2689       else if (*pPointer != RPC_FC_RP)
2690         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2691       PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2692       if (pointer_buffer_mark_set)
2693       {
2694         STD_OVERFLOW_CHECK(pStubMsg);
2695         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2696         pStubMsg->Buffer = saved_buffer;
2697         if (*pPointer != RPC_FC_RP)
2698           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2699       }
2700       TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2701       pPointer += 4;
2702       pMemory += 4;
2703       break;
2704     }
2705     case RPC_FC_ALIGNM4:
2706       ALIGN_POINTER(pMemory, 4);
2707       break;
2708     case RPC_FC_ALIGNM8:
2709       ALIGN_POINTER(pMemory, 8);
2710       break;
2711     case RPC_FC_STRUCTPAD1:
2712     case RPC_FC_STRUCTPAD2:
2713     case RPC_FC_STRUCTPAD3:
2714     case RPC_FC_STRUCTPAD4:
2715     case RPC_FC_STRUCTPAD5:
2716     case RPC_FC_STRUCTPAD6:
2717     case RPC_FC_STRUCTPAD7:
2718       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2719       break;
2720     case RPC_FC_EMBEDDED_COMPLEX:
2721       pMemory += pFormat[1];
2722       pFormat += 2;
2723       desc = pFormat + *(const SHORT*)pFormat;
2724       size = EmbeddedComplexSize(pStubMsg, desc);
2725       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
2726       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2727       if (m)
2728       {
2729         /* for some reason interface pointers aren't generated as
2730          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2731          * they still need the derefencing treatment that pointers are
2732          * given */
2733         if (*desc == RPC_FC_IP)
2734           m(pStubMsg, *(unsigned char **)pMemory, desc);
2735         else
2736           m(pStubMsg, pMemory, desc);
2737       }
2738       else FIXME("no marshaller for embedded type %02x\n", *desc);
2739       pMemory += size;
2740       pFormat += 2;
2741       continue;
2742     case RPC_FC_PAD:
2743       break;
2744     default:
2745       FIXME("unhandled format 0x%02x\n", *pFormat);
2746     }
2747     pFormat++;
2748   }
2749 
2750   return pMemory;
2751 }
2752 
2753 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2754                                          unsigned char *pMemory,
2755                                          PFORMAT_STRING pFormat,
2756                                          PFORMAT_STRING pPointer,
2757                                          unsigned char fMustAlloc)
2758 {
2759   PFORMAT_STRING desc;
2760   NDR_UNMARSHALL m;
2761   unsigned long size;
2762 
2763   while (*pFormat != RPC_FC_END) {
2764     switch (*pFormat) {
2765     case RPC_FC_BYTE:
2766     case RPC_FC_CHAR:
2767     case RPC_FC_SMALL:
2768     case RPC_FC_USMALL:
2769       safe_copy_from_buffer(pStubMsg, pMemory, 1);
2770       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2771       pMemory += 1;
2772       break;
2773     case RPC_FC_WCHAR:
2774     case RPC_FC_SHORT:
2775     case RPC_FC_USHORT:
2776       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2777       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2778       pMemory += 2;
2779       break;
2780     case RPC_FC_ENUM16:
2781       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2782       *(DWORD*)pMemory &= 0xffff;
2783       TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2784       if (32767 < *(DWORD*)pMemory)
2785         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2786       pMemory += 4;
2787       break;
2788     case RPC_FC_LONG:
2789     case RPC_FC_ULONG:
2790     case RPC_FC_ENUM32:
2791       safe_copy_from_buffer(pStubMsg, pMemory, 4);
2792       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2793       pMemory += 4;
2794       break;
2795     case RPC_FC_HYPER:
2796       safe_copy_from_buffer(pStubMsg, pMemory, 8);
2797       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2798       pMemory += 8;
2799       break;
2800     case RPC_FC_POINTER:
2801     {
2802       unsigned char *saved_buffer;
2803       int pointer_buffer_mark_set = 0;
2804       TRACE("pointer => %p\n", pMemory);
2805       if (*pPointer != RPC_FC_RP)
2806         ALIGN_POINTER(pStubMsg->Buffer, 4);
2807       saved_buffer = pStubMsg->Buffer;
2808       if (pStubMsg->PointerBufferMark)
2809       {
2810         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2811         pStubMsg->PointerBufferMark = NULL;
2812         pointer_buffer_mark_set = 1;
2813       }
2814       else if (*pPointer != RPC_FC_RP)
2815         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2816 
2817       PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
2818       if (pointer_buffer_mark_set)
2819       {
2820         STD_OVERFLOW_CHECK(pStubMsg);
2821         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2822         pStubMsg->Buffer = saved_buffer;
2823         if (*pPointer != RPC_FC_RP)
2824           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2825       }
2826       pPointer += 4;
2827       pMemory += 4;
2828       break;
2829     }
2830     case RPC_FC_ALIGNM4:
2831       ALIGN_POINTER_CLEAR(pMemory, 4);
2832       break;
2833     case RPC_FC_ALIGNM8:
2834       ALIGN_POINTER_CLEAR(pMemory, 8);
2835       break;
2836     case RPC_FC_STRUCTPAD1:
2837     case RPC_FC_STRUCTPAD2:
2838     case RPC_FC_STRUCTPAD3:
2839     case RPC_FC_STRUCTPAD4:
2840     case RPC_FC_STRUCTPAD5:
2841     case RPC_FC_STRUCTPAD6:
2842     case RPC_FC_STRUCTPAD7:
2843       memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2844       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2845       break;
2846     case RPC_FC_EMBEDDED_COMPLEX:
2847       pMemory += pFormat[1];
2848       pFormat += 2;
2849       desc = pFormat + *(const SHORT*)pFormat;
2850       size = EmbeddedComplexSize(pStubMsg, desc);
2851       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
2852       if (fMustAlloc)
2853         /* we can't pass fMustAlloc=TRUE into the marshaller for this type
2854          * since the type is part of the memory block that is encompassed by
2855          * the whole complex type. Memory is forced to allocate when pointers
2856          * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
2857          * clearing the memory we pass in to the unmarshaller */
2858         memset(pMemory, 0, size);
2859       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2860       if (m)
2861       {
2862         /* for some reason interface pointers aren't generated as
2863          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2864          * they still need the derefencing treatment that pointers are
2865          * given */
2866         if (*desc == RPC_FC_IP)
2867           m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2868         else
2869           m(pStubMsg, &pMemory, desc, FALSE);
2870       }
2871       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2872       pMemory += size;
2873       pFormat += 2;
2874       continue;
2875     case RPC_FC_PAD:
2876       break;
2877     default:
2878       FIXME("unhandled format %d\n", *pFormat);
2879     }
2880     pFormat++;
2881   }
2882 
2883   return pMemory;
2884 }
2885 
2886 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2887                                          unsigned char *pMemory,
2888                                          PFORMAT_STRING pFormat,
2889                                          PFORMAT_STRING pPointer)
2890 {
2891   PFORMAT_STRING desc;
2892   NDR_BUFFERSIZE m;
2893   unsigned long size;
2894 
2895   while (*pFormat != RPC_FC_END) {
2896     switch (*pFormat) {
2897     case RPC_FC_BYTE:
2898     case RPC_FC_CHAR:
2899     case RPC_FC_SMALL:
2900     case RPC_FC_USMALL:
2901       safe_buffer_length_increment(pStubMsg, 1);
2902       pMemory += 1;
2903       break;
2904     case RPC_FC_WCHAR:
2905     case RPC_FC_SHORT:
2906     case RPC_FC_USHORT:
2907       safe_buffer_length_increment(pStubMsg, 2);
2908       pMemory += 2;
2909       break;
2910     case RPC_FC_ENUM16:
2911       safe_buffer_length_increment(pStubMsg, 2);
2912       pMemory += 4;
2913       break;
2914     case RPC_FC_LONG:
2915     case RPC_FC_ULONG:
2916     case RPC_FC_ENUM32:
2917       safe_buffer_length_increment(pStubMsg, 4);
2918       pMemory += 4;
2919       break;
2920     case RPC_FC_HYPER:
2921       safe_buffer_length_increment(pStubMsg, 8);
2922       pMemory += 8;
2923       break;
2924     case RPC_FC_POINTER:
2925       if (!pStubMsg->IgnoreEmbeddedPointers)
2926       {
2927         int saved_buffer_length = pStubMsg->BufferLength;
2928         pStubMsg->BufferLength = pStubMsg->PointerLength;
2929         pStubMsg->PointerLength = 0;
2930         if(!pStubMsg->BufferLength)
2931           ERR("BufferLength == 0??\n");
2932         PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2933         pStubMsg->PointerLength = pStubMsg->BufferLength;
2934         pStubMsg->BufferLength = saved_buffer_length;
2935       }
2936       if (*pPointer != RPC_FC_RP)
2937       {
2938         ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2939         safe_buffer_length_increment(pStubMsg, 4);
2940       }
2941       pPointer += 4;
2942       pMemory += 4;
2943       break;
2944     case RPC_FC_ALIGNM4:
2945       ALIGN_POINTER(pMemory, 4);
2946       break;
2947     case RPC_FC_ALIGNM8:
2948       ALIGN_POINTER(pMemory, 8);
2949       break;
2950     case RPC_FC_STRUCTPAD1:
2951     case RPC_FC_STRUCTPAD2:
2952     case RPC_FC_STRUCTPAD3:
2953     case RPC_FC_STRUCTPAD4:
2954     case RPC_FC_STRUCTPAD5:
2955     case RPC_FC_STRUCTPAD6:
2956     case RPC_FC_STRUCTPAD7:
2957       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2958       break;
2959     case RPC_FC_EMBEDDED_COMPLEX:
2960       pMemory += pFormat[1];
2961       pFormat += 2;
2962       desc = pFormat + *(const SHORT*)pFormat;
2963       size = EmbeddedComplexSize(pStubMsg, desc);
2964       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2965       if (m)
2966       {
2967         /* for some reason interface pointers aren't generated as
2968          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2969          * they still need the derefencing treatment that pointers are
2970          * given */
2971         if (*desc == RPC_FC_IP)
2972           m(pStubMsg, *(unsigned char **)pMemory, desc);
2973         else
2974           m(pStubMsg, pMemory, desc);
2975       }
2976       else FIXME("no buffersizer for embedded type %02x\n", *desc);
2977       pMemory += size;
2978       pFormat += 2;
2979       continue;
2980     case RPC_FC_PAD:
2981       break;
2982     default:
2983       FIXME("unhandled format 0x%02x\n", *pFormat);
2984     }
2985     pFormat++;
2986   }
2987 
2988   return pMemory;
2989 }
2990 
2991 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2992                                    unsigned char *pMemory,
2993                                    PFORMAT_STRING pFormat,
2994                                    PFORMAT_STRING pPointer)
2995 {
2996   PFORMAT_STRING desc;
2997   NDR_FREE m;
2998   unsigned long size;
2999 
3000   while (*pFormat != RPC_FC_END) {
3001     switch (*pFormat) {
3002     case RPC_FC_BYTE:
3003     case RPC_FC_CHAR:
3004     case RPC_FC_SMALL:
3005     case RPC_FC_USMALL:
3006       pMemory += 1;
3007       break;
3008     case RPC_FC_WCHAR:
3009     case RPC_FC_SHORT:
3010     case RPC_FC_USHORT:
3011       pMemory += 2;
3012       break;
3013     case RPC_FC_LONG:
3014     case RPC_FC_ULONG:
3015     case RPC_FC_ENUM16:
3016     case RPC_FC_ENUM32:
3017       pMemory += 4;
3018       break;
3019     case RPC_FC_HYPER:
3020       pMemory += 8;
3021       break;
3022     case RPC_FC_POINTER:
3023       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3024       pPointer += 4;
3025       pMemory += 4;
3026       break;
3027     case RPC_FC_ALIGNM4:
3028       ALIGN_POINTER(pMemory, 4);
3029       break;
3030     case RPC_FC_ALIGNM8:
3031       ALIGN_POINTER(pMemory, 8);
3032       break;
3033     case RPC_FC_STRUCTPAD1:
3034     case RPC_FC_STRUCTPAD2:
3035     case RPC_FC_STRUCTPAD3:
3036     case RPC_FC_STRUCTPAD4:
3037     case RPC_FC_STRUCTPAD5:
3038     case RPC_FC_STRUCTPAD6:
3039     case RPC_FC_STRUCTPAD7:
3040       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3041       break;
3042     case RPC_FC_EMBEDDED_COMPLEX:
3043       pMemory += pFormat[1];
3044       pFormat += 2;
3045       desc = pFormat + *(const SHORT*)pFormat;
3046       size = EmbeddedComplexSize(pStubMsg, desc);
3047       m = NdrFreer[*desc & NDR_TABLE_MASK];
3048       if (m)
3049       {
3050         /* for some reason interface pointers aren't generated as
3051          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3052          * they still need the derefencing treatment that pointers are
3053          * given */
3054         if (*desc == RPC_FC_IP)
3055           m(pStubMsg, *(unsigned char **)pMemory, desc);
3056         else
3057           m(pStubMsg, pMemory, desc);
3058       }
3059       pMemory += size;
3060       pFormat += 2;
3061       continue;
3062     case RPC_FC_PAD:
3063       break;
3064     default:
3065       FIXME("unhandled format 0x%02x\n", *pFormat);
3066     }
3067     pFormat++;
3068   }
3069 
3070   return pMemory;
3071 }
3072 
3073 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3074                                              PFORMAT_STRING pFormat,
3075                                              PFORMAT_STRING pPointer)
3076 {
3077   PFORMAT_STRING desc;
3078   unsigned long size = 0;
3079 
3080   while (*pFormat != RPC_FC_END) {
3081     switch (*pFormat) {
3082     case RPC_FC_BYTE:
3083     case RPC_FC_CHAR:
3084     case RPC_FC_SMALL:
3085     case RPC_FC_USMALL:
3086       size += 1;
3087       safe_buffer_increment(pStubMsg, 1);
3088       break;
3089     case RPC_FC_WCHAR:
3090     case RPC_FC_SHORT:
3091     case RPC_FC_USHORT:
3092       size += 2;
3093       safe_buffer_increment(pStubMsg, 2);
3094       break;
3095     case RPC_FC_ENUM16:
3096       size += 4;
3097       safe_buffer_increment(pStubMsg, 2);
3098       break;
3099     case RPC_FC_LONG:
3100     case RPC_FC_ULONG:
3101     case RPC_FC_ENUM32:
3102       size += 4;
3103       safe_buffer_increment(pStubMsg, 4);
3104       break;
3105     case RPC_FC_HYPER:
3106       size += 8;
3107       safe_buffer_increment(pStubMsg, 8);
3108       break;
3109     case RPC_FC_POINTER:
3110     {
3111       unsigned char *saved_buffer;
3112       int pointer_buffer_mark_set = 0;
3113       if (*pPointer != RPC_FC_RP)
3114         ALIGN_POINTER(pStubMsg->Buffer, 4);
3115       saved_buffer = pStubMsg->Buffer;
3116       if (pStubMsg->PointerBufferMark)
3117       {
3118         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3119         pStubMsg->PointerBufferMark = NULL;
3120         pointer_buffer_mark_set = 1;
3121       }
3122       else if (*pPointer != RPC_FC_RP)
3123         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3124 
3125       if (!pStubMsg->IgnoreEmbeddedPointers)
3126         PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3127       if (pointer_buffer_mark_set)
3128       {
3129         STD_OVERFLOW_CHECK(pStubMsg);
3130         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3131         pStubMsg->Buffer = saved_buffer;
3132         if (*pPointer != RPC_FC_RP)
3133           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3134       }
3135       pPointer += 4;
3136       size += 4;
3137       break;
3138     }
3139     case RPC_FC_ALIGNM4:
3140       ALIGN_LENGTH(size, 4);
3141       ALIGN_POINTER(pStubMsg->Buffer, 4);
3142       break;
3143     case RPC_FC_ALIGNM8:
3144       ALIGN_LENGTH(size, 8);
3145       ALIGN_POINTER(pStubMsg->Buffer, 8);
3146       break;
3147     case RPC_FC_STRUCTPAD1:
3148     case RPC_FC_STRUCTPAD2:
3149     case RPC_FC_STRUCTPAD3:
3150     case RPC_FC_STRUCTPAD4:
3151     case RPC_FC_STRUCTPAD5:
3152     case RPC_FC_STRUCTPAD6:
3153     case RPC_FC_STRUCTPAD7:
3154       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3155       break;
3156     case RPC_FC_EMBEDDED_COMPLEX:
3157       size += pFormat[1];
3158       pFormat += 2;
3159       desc = pFormat + *(const SHORT*)pFormat;
3160       size += EmbeddedComplexMemorySize(pStubMsg, desc);
3161       pFormat += 2;
3162       continue;
3163     case RPC_FC_PAD:
3164       break;
3165     default:
3166       FIXME("unhandled format 0x%02x\n", *pFormat);
3167     }
3168     pFormat++;
3169   }
3170 
3171   return size;
3172 }
3173 
3174 unsigned long ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,
3175                                 PFORMAT_STRING pFormat)
3176 {
3177   PFORMAT_STRING desc;
3178   unsigned long size = 0;
3179 
3180   while (*pFormat != RPC_FC_END) {
3181     switch (*pFormat) {
3182     case RPC_FC_BYTE:
3183     case RPC_FC_CHAR:
3184     case RPC_FC_SMALL:
3185     case RPC_FC_USMALL:
3186       size += 1;
3187       break;
3188     case RPC_FC_WCHAR:
3189     case RPC_FC_SHORT:
3190     case RPC_FC_USHORT:
3191       size += 2;
3192       break;
3193     case RPC_FC_LONG:
3194     case RPC_FC_ULONG:
3195     case RPC_FC_ENUM16:
3196     case RPC_FC_ENUM32:
3197       size += 4;
3198       break;
3199     case RPC_FC_HYPER:
3200       size += 8;
3201       break;
3202     case RPC_FC_POINTER:
3203       size += sizeof(void *);
3204       break;
3205     case RPC_FC_ALIGNM4:
3206       ALIGN_LENGTH(size, 4);
3207       break;
3208     case RPC_FC_ALIGNM8:
3209       ALIGN_LENGTH(size, 8);
3210       break;
3211     case RPC_FC_STRUCTPAD1:
3212     case RPC_FC_STRUCTPAD2:
3213     case RPC_FC_STRUCTPAD3:
3214     case RPC_FC_STRUCTPAD4:
3215     case RPC_FC_STRUCTPAD5:
3216     case RPC_FC_STRUCTPAD6:
3217     case RPC_FC_STRUCTPAD7:
3218       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3219       break;
3220     case RPC_FC_EMBEDDED_COMPLEX:
3221       size += pFormat[1];
3222       pFormat += 2;
3223       desc = pFormat + *(const SHORT*)pFormat;
3224       size += EmbeddedComplexSize(pStubMsg, desc);
3225       pFormat += 2;
3226       continue;
3227     case RPC_FC_PAD:
3228       break;
3229     default:
3230       FIXME("unhandled format 0x%02x\n", *pFormat);
3231     }
3232     pFormat++;
3233   }
3234 
3235   return size;
3236 }
3237 
3238 /***********************************************************************
3239  *           NdrComplexStructMarshall [RPCRT4.@]
3240  */
3241 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3242                                                 unsigned char *pMemory,
3243                                                 PFORMAT_STRING pFormat)
3244 {
3245   PFORMAT_STRING conf_array = NULL;
3246   PFORMAT_STRING pointer_desc = NULL;
3247   unsigned char *OldMemory = pStubMsg->Memory;
3248   int pointer_buffer_mark_set = 0;
3249   ULONG count = 0;
3250   ULONG max_count = 0;
3251   ULONG offset = 0;
3252 
3253   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3254 
3255   if (!pStubMsg->PointerBufferMark)
3256   {
3257     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3258     /* save buffer length */
3259     unsigned long saved_buffer_length = pStubMsg->BufferLength;
3260 
3261     /* get the buffer pointer after complex array data, but before
3262      * pointer data */
3263     pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
3264     pStubMsg->IgnoreEmbeddedPointers = 1;
3265     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3266     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3267 
3268     /* save it for use by embedded pointer code later */
3269     pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
3270     TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
3271     pointer_buffer_mark_set = 1;
3272 
3273     /* restore the original buffer length */
3274     pStubMsg->BufferLength = saved_buffer_length;
3275   }
3276 
3277   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
3278 
3279   pFormat += 4;
3280   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3281   pFormat += 2;
3282   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3283   pFormat += 2;
3284 
3285   pStubMsg->Memory = pMemory;
3286 
3287   if (conf_array)
3288   {
3289     unsigned long struct_size = ComplexStructSize(pStubMsg, pFormat);
3290     array_compute_and_write_conformance(conf_array[0], pStubMsg,
3291                                         pMemory + struct_size, conf_array);
3292     /* these could be changed in ComplexMarshall so save them for later */
3293     max_count = pStubMsg->MaxCount;
3294     count = pStubMsg->ActualCount;
3295     offset = pStubMsg->Offset;
3296   }
3297 
3298   pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3299 
3300   if (conf_array)
3301   {
3302     pStubMsg->MaxCount = max_count;
3303     pStubMsg->ActualCount = count;
3304     pStubMsg->Offset = offset;
3305     array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3306                                       conf_array, TRUE /* fHasPointers */);
3307   }
3308 
3309   pStubMsg->Memory = OldMemory;
3310 
3311   if (pointer_buffer_mark_set)
3312   {
3313     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3314     pStubMsg->PointerBufferMark = NULL;
3315   }
3316 
3317   STD_OVERFLOW_CHECK(pStubMsg);
3318 
3319   return NULL;
3320 }
3321 
3322 /***********************************************************************
3323  *           NdrComplexStructUnmarshall [RPCRT4.@]
3324  */
3325 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3326                                                   unsigned char **ppMemory,
3327                                                   PFORMAT_STRING pFormat,
3328                                                   unsigned char fMustAlloc)
3329 {
3330   unsigned size = *(const WORD*)(pFormat+2);
3331   PFORMAT_STRING conf_array = NULL;
3332   PFORMAT_STRING pointer_desc = NULL;
3333   unsigned char *pMemory;
3334   int pointer_buffer_mark_set = 0;
3335   ULONG count = 0;
3336   ULONG max_count = 0;
3337   ULONG offset = 0;
3338   ULONG array_size = 0;
3339 
3340   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3341 
3342   if (!pStubMsg->PointerBufferMark)
3343   {
3344     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3345     /* save buffer pointer */
3346     unsigned char *saved_buffer = pStubMsg->Buffer;
3347 
3348     /* get the buffer pointer after complex array data, but before
3349      * pointer data */
3350     pStubMsg->IgnoreEmbeddedPointers = 1;
3351     NdrComplexStructMemorySize(pStubMsg, pFormat);
3352     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3353 
3354     /* save it for use by embedded pointer code later */
3355     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3356     TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
3357     pointer_buffer_mark_set = 1;
3358 
3359     /* restore the original buffer */
3360     pStubMsg->Buffer = saved_buffer;
3361   }
3362 
3363   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3364 
3365   pFormat += 4;
3366   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3367   pFormat += 2;
3368   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3369   pFormat += 2;
3370 
3371   if (conf_array)
3372   {
3373     array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3374     size += array_size;
3375 
3376     /* these could be changed in ComplexMarshall so save them for later */
3377     max_count = pStubMsg->MaxCount;
3378     count = pStubMsg->ActualCount;
3379     offset = pStubMsg->Offset;
3380   }
3381 
3382   if (fMustAlloc || !*ppMemory)
3383     *ppMemory = NdrAllocate(pStubMsg, size);
3384 
3385   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3386 
3387   if (conf_array)
3388   {
3389     pStubMsg->MaxCount = max_count;
3390     pStubMsg->ActualCount = count;
3391     pStubMsg->Offset = offset;
3392     if (fMustAlloc)
3393       memset(pMemory, 0, array_size);
3394     array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3395                                        conf_array, FALSE,
3396                                        FALSE /* fUseBufferMemoryServer */,
3397                                        TRUE /* fUnmarshall */);
3398   }
3399 
3400   if (pointer_buffer_mark_set)
3401   {
3402     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3403     pStubMsg->PointerBufferMark = NULL;
3404   }
3405 
3406   return NULL;
3407 }
3408 
3409 /***********************************************************************
3410  *           NdrComplexStructBufferSize [RPCRT4.@]
3411  */
3412 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3413                                        unsigned char *pMemory,
3414                                        PFORMAT_STRING pFormat)
3415 {
3416   PFORMAT_STRING conf_array = NULL;
3417   PFORMAT_STRING pointer_desc = NULL;
3418   unsigned char *OldMemory = pStubMsg->Memory;
3419   int pointer_length_set = 0;
3420   ULONG count = 0;
3421   ULONG max_count = 0;
3422   ULONG offset = 0;
3423 
3424   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3425 
3426   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
3427 
3428   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3429   {
3430     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3431     unsigned long saved_buffer_length = pStubMsg->BufferLength;
3432 
3433     /* get the buffer length after complex struct data, but before
3434      * pointer data */
3435     pStubMsg->IgnoreEmbeddedPointers = 1;
3436     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3437     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3438 
3439     /* save it for use by embedded pointer code later */
3440     pStubMsg->PointerLength = pStubMsg->BufferLength;
3441     pointer_length_set = 1;
3442     TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
3443 
3444     /* restore the original buffer length */
3445     pStubMsg->BufferLength = saved_buffer_length;
3446   }
3447 
3448   pFormat += 4;
3449   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3450   pFormat += 2;
3451   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3452   pFormat += 2;
3453 
3454   pStubMsg->Memory = pMemory;
3455 
3456   if (conf_array)
3457   {
3458     unsigned long struct_size = ComplexStructSize(pStubMsg, pFormat);
3459     array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3460                                        conf_array);
3461 
3462     /* these could be changed in ComplexMarshall so save them for later */
3463     max_count = pStubMsg->MaxCount;
3464     count = pStubMsg->ActualCount;
3465     offset = pStubMsg->Offset;
3466   }
3467 
3468   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3469 
3470   if (conf_array)
3471   {
3472     pStubMsg->MaxCount = max_count;
3473     pStubMsg->ActualCount = count;
3474     pStubMsg->Offset = offset;
3475     array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3476                       TRUE /* fHasPointers */);
3477   }
3478 
3479   pStubMsg->Memory = OldMemory;
3480 
3481   if(pointer_length_set)
3482   {
3483     pStubMsg->BufferLength = pStubMsg->PointerLength;
3484     pStubMsg->PointerLength = 0;
3485   }
3486 
3487 }
3488 
3489 /***********************************************************************
3490  *           NdrComplexStructMemorySize [RPCRT4.@]
3491  */
3492 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3493                                         PFORMAT_STRING pFormat)
3494 {
3495   unsigned size = *(const WORD*)(pFormat+2);
3496   PFORMAT_STRING conf_array = NULL;
3497   PFORMAT_STRING pointer_desc = NULL;
3498   ULONG count = 0;
3499   ULONG max_count = 0;
3500   ULONG offset = 0;
3501 
3502   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3503 
3504   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3505 
3506   pFormat += 4;
3507   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3508   pFormat += 2;
3509   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3510   pFormat += 2;
3511 
3512   if (conf_array)
3513   {
3514     array_read_conformance(conf_array[0], pStubMsg, conf_array);
3515 
3516     /* these could be changed in ComplexStructMemorySize so save them for
3517      * later */
3518     max_count = pStubMsg->MaxCount;
3519     count = pStubMsg->ActualCount;
3520     offset = pStubMsg->Offset;
3521   }
3522 
3523   ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3524 
3525   if (conf_array)
3526   {
3527     pStubMsg->MaxCount = max_count;
3528     pStubMsg->ActualCount = count;
3529     pStubMsg->Offset = offset;
3530     array_memory_size(conf_array[0], pStubMsg, conf_array,
3531                       TRUE /* fHasPointers */);
3532   }
3533 
3534   return size;
3535 }
3536 
3537 /***********************************************************************
3538  *           NdrComplexStructFree [RPCRT4.@]
3539  */
3540 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3541                                  unsigned char *pMemory,
3542                                  PFORMAT_STRING pFormat)
3543 {
3544   PFORMAT_STRING conf_array = NULL;
3545   PFORMAT_STRING pointer_desc = NULL;
3546   unsigned char *OldMemory = pStubMsg->Memory;
3547 
3548   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3549 
3550   pFormat += 4;
3551   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3552   pFormat += 2;
3553   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3554   pFormat += 2;
3555 
3556   pStubMsg->Memory = pMemory;
3557 
3558   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3559 
3560   if (conf_array)
3561     array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3562                TRUE /* fHasPointers */);
3563 
3564   pStubMsg->Memory = OldMemory;
3565 }
3566 
3567 /***********************************************************************
3568  *           NdrConformantArrayMarshall [RPCRT4.@]
3569  */
3570 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3571                                                   unsigned char *pMemory,
3572                                                   PFORMAT_STRING pFormat)
3573 {
3574   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3575   if (pFormat[0] != RPC_FC_CARRAY)
3576   {
3577     ERR("invalid format = 0x%x\n", pFormat[0]);
3578     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3579   }
3580 
3581   array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
3582                                       pFormat);
3583   array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3584                                     TRUE /* fHasPointers */);
3585 
3586   return NULL;
3587 }
3588 
3589 /***********************************************************************
3590  *           NdrConformantArrayUnmarshall [RPCRT4.@]
3591  */
3592 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3593                                                     unsigned char **ppMemory,
3594                                                     PFORMAT_STRING pFormat,
3595                                                     unsigned char fMustAlloc)
3596 {
3597   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3598   if (pFormat[0] != RPC_FC_CARRAY)
3599   {
3600     ERR("invalid format = 0x%x\n", pFormat[0]);
3601     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3602   }
3603 
3604   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3605   array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
3606                                      fMustAlloc,
3607                                      TRUE /* fUseBufferMemoryServer */,
3608                                      TRUE /* fUnmarshall */);
3609 
3610   return NULL;
3611 }
3612 
3613 /***********************************************************************
3614  *           NdrConformantArrayBufferSize [RPCRT4.@]
3615  */
3616 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3617                                          unsigned char *pMemory,
3618                                          PFORMAT_STRING pFormat)
3619 {
3620   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3621   if (pFormat[0] != RPC_FC_CARRAY)