~ [ 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 %ld, len %ld\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     {
865       *pPointer = NULL;    
866       pointer_needs_unmarshaling = 0;
867     }
868     break;
869   case RPC_FC_FP:
870     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
871     TRACE("pointer_id is 0x%08x\n", pointer_id);
872     pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
873       pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
874     break;
875   default:
876     FIXME("unhandled ptr type=%02x\n", type);
877     RpcRaiseException(RPC_X_BAD_STUB_DATA);
878     return;
879   }
880 
881   if (pointer_needs_unmarshaling) {
882     unsigned char *base_ptr_val = *pPointer;
883     unsigned char **current_ptr = pPointer;
884     if (pStubMsg->IsClient) {
885       TRACE("client\n");
886       /* if we aren't forcing allocation of memory then try to use the existing
887        * (source) pointer to unmarshall the data into so that [in,out]
888        * parameters behave correctly. it doesn't matter if the parameter is
889        * [out] only since in that case the pointer will be NULL. we force
890        * allocation when the source pointer is NULL here instead of in the type
891        * unmarshalling routine for the benefit of the deref code below */
892       if (!fMustAlloc) {
893         if (pSrcPointer) {
894           TRACE("setting *pPointer to %p\n", pSrcPointer);
895           *pPointer = base_ptr_val = pSrcPointer;
896         } else
897           fMustAlloc = TRUE;
898       }
899     } else {
900       TRACE("server\n");
901       /* the memory in a stub is never initialised, so we have to work out here
902        * whether we have to initialise it so we can use the optimisation of
903        * setting the pointer to the buffer, if possible, or set fMustAlloc to
904        * TRUE. */
905       if (attr & RPC_FC_P_DEREF) {
906         fMustAlloc = TRUE;
907       } else {
908         base_ptr_val = NULL;
909         *current_ptr = NULL;
910       }
911     }
912 
913     if (attr & RPC_FC_P_ALLOCALLNODES)
914         FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
915 
916     if (attr & RPC_FC_P_DEREF) {
917       if (fMustAlloc) {
918         base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
919         *pPointer = base_ptr_val;
920         current_ptr = (unsigned char **)base_ptr_val;
921       } else
922         current_ptr = *(unsigned char***)current_ptr;
923       TRACE("deref => %p\n", current_ptr);
924       if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
925     }
926     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
927     if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
928     else FIXME("no unmarshaller for data type=%02x\n", *desc);
929 
930     if (type == RPC_FC_FP)
931       NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
932                                 base_ptr_val);
933   }
934 
935   TRACE("pointer=%p\n", *pPointer);
936 }
937 
938 /***********************************************************************
939  *           PointerBufferSize [internal]
940  */
941 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
942                               unsigned char *Pointer,
943                               PFORMAT_STRING pFormat)
944 {
945   unsigned type = pFormat[0], attr = pFormat[1];
946   PFORMAT_STRING desc;
947   NDR_BUFFERSIZE m;
948   int pointer_needs_sizing;
949   ULONG pointer_id;
950 
951   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
952   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
953   pFormat += 2;
954   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
955   else desc = pFormat + *(const SHORT*)pFormat;
956 
957   switch (type) {
958   case RPC_FC_RP: /* ref pointer (always non-null) */
959     if (!Pointer)
960     {
961       ERR("NULL ref pointer is not allowed\n");
962       RpcRaiseException(RPC_X_NULL_REF_POINTER);
963     }
964     break;
965   case RPC_FC_OP:
966   case RPC_FC_UP:
967     /* NULL pointer has no further representation */
968     if (!Pointer)
969         return;
970     break;
971   case RPC_FC_FP:
972     pointer_needs_sizing = !NdrFullPointerQueryPointer(
973       pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
974     if (!pointer_needs_sizing)
975       return;
976     break;
977   default:
978     FIXME("unhandled ptr type=%02x\n", type);
979     RpcRaiseException(RPC_X_BAD_STUB_DATA);
980     return;
981   }
982 
983   if (attr & RPC_FC_P_DEREF) {
984     Pointer = *(unsigned char**)Pointer;
985     TRACE("deref => %p\n", Pointer);
986   }
987 
988   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
989   if (m) m(pStubMsg, Pointer, desc);
990   else FIXME("no buffersizer for data type=%02x\n", *desc);
991 }
992 
993 /***********************************************************************
994  *           PointerMemorySize [internal]
995  */
996 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
997                                        unsigned char *Buffer,
998                                        PFORMAT_STRING pFormat)
999 {
1000   unsigned type = pFormat[0], attr = pFormat[1];
1001   PFORMAT_STRING desc;
1002   NDR_MEMORYSIZE m;
1003   DWORD pointer_id = 0;
1004   int pointer_needs_sizing;
1005 
1006   TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1007   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1008   pFormat += 2;
1009   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1010   else desc = pFormat + *(const SHORT*)pFormat;
1011 
1012   switch (type) {
1013   case RPC_FC_RP: /* ref pointer (always non-null) */
1014     pointer_needs_sizing = 1;
1015     break;
1016   case RPC_FC_UP: /* unique pointer */
1017   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1018     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1019     TRACE("pointer_id is 0x%08x\n", pointer_id);
1020     if (pointer_id)
1021       pointer_needs_sizing = 1;
1022     else
1023       pointer_needs_sizing = 0;
1024     break;
1025   case RPC_FC_FP:
1026   {
1027     void *pointer;
1028     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1029     TRACE("pointer_id is 0x%08x\n", pointer_id);
1030     pointer_needs_sizing = !NdrFullPointerQueryRefId(
1031       pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1032     break;
1033   }
1034   default:
1035     FIXME("unhandled ptr type=%02x\n", type);
1036     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1037     return 0;
1038   }
1039 
1040   if (attr & RPC_FC_P_DEREF) {
1041     TRACE("deref\n");
1042   }
1043 
1044   if (pointer_needs_sizing) {
1045     m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1046     if (m) m(pStubMsg, desc);
1047     else FIXME("no memorysizer for data type=%02x\n", *desc);
1048   }
1049 
1050   return pStubMsg->MemorySize;
1051 }
1052 
1053 /***********************************************************************
1054  *           PointerFree [internal]
1055  */
1056 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1057                         unsigned char *Pointer,
1058                         PFORMAT_STRING pFormat)
1059 {
1060   unsigned type = pFormat[0], attr = pFormat[1];
1061   PFORMAT_STRING desc;
1062   NDR_FREE m;
1063   unsigned char *current_pointer = Pointer;
1064 
1065   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1066   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1067   if (attr & RPC_FC_P_DONTFREE) return;
1068   pFormat += 2;
1069   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1070   else desc = pFormat + *(const SHORT*)pFormat;
1071 
1072   if (!Pointer) return;
1073 
1074   if (type == RPC_FC_FP) {
1075     int pointer_needs_freeing = NdrFullPointerFree(
1076       pStubMsg->FullPtrXlatTables, Pointer);
1077     if (!pointer_needs_freeing)
1078       return;
1079   }
1080 
1081   if (attr & RPC_FC_P_DEREF) {
1082     current_pointer = *(unsigned char**)Pointer;
1083     TRACE("deref => %p\n", current_pointer);
1084   }
1085 
1086   m = NdrFreer[*desc & NDR_TABLE_MASK];
1087   if (m) m(pStubMsg, current_pointer, desc);
1088 
1089   /* this check stops us from trying to free buffer memory. we don't have to
1090    * worry about clients, since they won't call this function.
1091    * we don't have to check for the buffer being reallocated because
1092    * BufferStart and BufferEnd won't be reset when allocating memory for
1093    * sending the response. we don't have to check for the new buffer here as
1094    * it won't be used a type memory, only for buffer memory */
1095   if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd)
1096       goto notfree;
1097 
1098   if (attr & RPC_FC_P_ONSTACK) {
1099     TRACE("not freeing stack ptr %p\n", Pointer);
1100     return;
1101   }
1102   TRACE("freeing %p\n", Pointer);
1103   NdrFree(pStubMsg, Pointer);
1104   return;
1105 notfree:
1106   TRACE("not freeing %p\n", Pointer);
1107 }
1108 
1109 /***********************************************************************
1110  *           EmbeddedPointerMarshall
1111  */
1112 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1113                                                unsigned char *pMemory,
1114                                                PFORMAT_STRING pFormat)
1115 {
1116   unsigned char *Mark = pStubMsg->BufferMark;
1117   unsigned rep, count, stride;
1118   unsigned i;
1119   unsigned char *saved_buffer = NULL;
1120 
1121   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1122 
1123   if (*pFormat != RPC_FC_PP) return NULL;
1124   pFormat += 2;
1125 
1126   if (pStubMsg->PointerBufferMark)
1127   {
1128     saved_buffer = pStubMsg->Buffer;
1129     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1130     pStubMsg->PointerBufferMark = NULL;
1131   }
1132 
1133   while (pFormat[0] != RPC_FC_END) {
1134     switch (pFormat[0]) {
1135     default:
1136       FIXME("unknown repeat type %d\n", pFormat[0]);
1137     case RPC_FC_NO_REPEAT:
1138       rep = 1;
1139       stride = 0;
1140       count = 1;
1141       pFormat += 2;
1142       break;
1143     case RPC_FC_FIXED_REPEAT:
1144       rep = *(const WORD*)&pFormat[2];
1145       stride = *(const WORD*)&pFormat[4];
1146       count = *(const WORD*)&pFormat[8];
1147       pFormat += 10;
1148       break;
1149     case RPC_FC_VARIABLE_REPEAT:
1150       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1151       stride = *(const WORD*)&pFormat[2];
1152       count = *(const WORD*)&pFormat[6];
1153       pFormat += 8;
1154       break;
1155     }
1156     for (i = 0; i < rep; i++) {
1157       PFORMAT_STRING info = pFormat;
1158       unsigned char *membase = pMemory + (i * stride);
1159       unsigned char *bufbase = Mark + (i * stride);
1160       unsigned u;
1161 
1162       for (u=0; u<count; u++,info+=8) {
1163         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1164         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1165         unsigned char *saved_memory = pStubMsg->Memory;
1166 
1167         pStubMsg->Memory = pMemory;
1168         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1169         pStubMsg->Memory = saved_memory;
1170       }
1171     }
1172     pFormat += 8 * count;
1173   }
1174 
1175   if (saved_buffer)
1176   {
1177     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1178     pStubMsg->Buffer = saved_buffer;
1179   }
1180 
1181   STD_OVERFLOW_CHECK(pStubMsg);
1182 
1183   return NULL;
1184 }
1185 
1186 /***********************************************************************
1187  *           EmbeddedPointerUnmarshall
1188  */
1189 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1190                                                  unsigned char *pDstBuffer,
1191                                                  unsigned char *pSrcMemoryPtrs,
1192                                                  PFORMAT_STRING pFormat,
1193                                                  unsigned char fMustAlloc)
1194 {
1195   unsigned char *Mark = pStubMsg->BufferMark;
1196   unsigned rep, count, stride;
1197   unsigned i;
1198   unsigned char *saved_buffer = NULL;
1199 
1200   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1201 
1202   if (*pFormat != RPC_FC_PP) return NULL;
1203   pFormat += 2;
1204 
1205   if (pStubMsg->PointerBufferMark)
1206   {
1207     saved_buffer = pStubMsg->Buffer;
1208     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1209     pStubMsg->PointerBufferMark = NULL;
1210   }
1211 
1212   while (pFormat[0] != RPC_FC_END) {
1213     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1214     switch (pFormat[0]) {
1215     default:
1216       FIXME("unknown repeat type %d\n", pFormat[0]);
1217     case RPC_FC_NO_REPEAT:
1218       rep = 1;
1219       stride = 0;
1220       count = 1;
1221       pFormat += 2;
1222       break;
1223     case RPC_FC_FIXED_REPEAT:
1224       rep = *(const WORD*)&pFormat[2];
1225       stride = *(const WORD*)&pFormat[4];
1226       count = *(const WORD*)&pFormat[8];
1227       pFormat += 10;
1228       break;
1229     case RPC_FC_VARIABLE_REPEAT:
1230       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1231       stride = *(const WORD*)&pFormat[2];
1232       count = *(const WORD*)&pFormat[6];
1233       pFormat += 8;
1234       break;
1235     }
1236     for (i = 0; i < rep; i++) {
1237       PFORMAT_STRING info = pFormat;
1238       unsigned char *bufdstbase = pDstBuffer + (i * stride);
1239       unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1240       unsigned char *bufbase = Mark + (i * stride);
1241       unsigned u;
1242 
1243       for (u=0; u<count; u++,info+=8) {
1244         unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1245         unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1246         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1247         PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1248       }
1249     }
1250     pFormat += 8 * count;
1251   }
1252 
1253   if (saved_buffer)
1254   {
1255     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1256     pStubMsg->Buffer = saved_buffer;
1257   }
1258 
1259   return NULL;
1260 }
1261 
1262 /***********************************************************************
1263  *           EmbeddedPointerBufferSize
1264  */
1265 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1266                                       unsigned char *pMemory,
1267                                       PFORMAT_STRING pFormat)
1268 {
1269   unsigned rep, count, stride;
1270   unsigned i;
1271   ULONG saved_buffer_length = 0;
1272 
1273   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1274 
1275   if (pStubMsg->IgnoreEmbeddedPointers) return;
1276 
1277   if (*pFormat != RPC_FC_PP) return;
1278   pFormat += 2;
1279 
1280   if (pStubMsg->PointerLength)
1281   {
1282     saved_buffer_length = pStubMsg->BufferLength;
1283     pStubMsg->BufferLength = pStubMsg->PointerLength;
1284     pStubMsg->PointerLength = 0;
1285   }
1286 
1287   while (pFormat[0] != RPC_FC_END) {
1288     switch (pFormat[0]) {
1289     default:
1290       FIXME("unknown repeat type %d\n", pFormat[0]);
1291     case RPC_FC_NO_REPEAT:
1292       rep = 1;
1293       stride = 0;
1294       count = 1;
1295       pFormat += 2;
1296       break;
1297     case RPC_FC_FIXED_REPEAT:
1298       rep = *(const WORD*)&pFormat[2];
1299       stride = *(const WORD*)&pFormat[4];
1300       count = *(const WORD*)&pFormat[8];
1301       pFormat += 10;
1302       break;
1303     case RPC_FC_VARIABLE_REPEAT:
1304       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1305       stride = *(const WORD*)&pFormat[2];
1306       count = *(const WORD*)&pFormat[6];
1307       pFormat += 8;
1308       break;
1309     }
1310     for (i = 0; i < rep; i++) {
1311       PFORMAT_STRING info = pFormat;
1312       unsigned char *membase = pMemory + (i * stride);
1313       unsigned u;
1314 
1315       for (u=0; u<count; u++,info+=8) {
1316         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1317         unsigned char *saved_memory = pStubMsg->Memory;
1318 
1319         pStubMsg->Memory = pMemory;
1320         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1321         pStubMsg->Memory = saved_memory;
1322       }
1323     }
1324     pFormat += 8 * count;
1325   }
1326 
1327   if (saved_buffer_length)
1328   {
1329     pStubMsg->PointerLength = pStubMsg->BufferLength;
1330     pStubMsg->BufferLength = saved_buffer_length;
1331   }
1332 }
1333 
1334 /***********************************************************************
1335  *           EmbeddedPointerMemorySize [internal]
1336  */
1337 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1338                                                PFORMAT_STRING pFormat)
1339 {
1340   unsigned char *Mark = pStubMsg->BufferMark;
1341   unsigned rep, count, stride;
1342   unsigned i;
1343   unsigned char *saved_buffer = NULL;
1344 
1345   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1346 
1347   if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1348 
1349   if (pStubMsg->PointerBufferMark)
1350   {
1351     saved_buffer = pStubMsg->Buffer;
1352     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1353     pStubMsg->PointerBufferMark = NULL;
1354   }
1355 
1356   if (*pFormat != RPC_FC_PP) return 0;
1357   pFormat += 2;
1358 
1359   while (pFormat[0] != RPC_FC_END) {
1360     switch (pFormat[0]) {
1361     default:
1362       FIXME("unknown repeat type %d\n", pFormat[0]);
1363     case RPC_FC_NO_REPEAT:
1364       rep = 1;
1365       stride = 0;
1366       count = 1;
1367       pFormat += 2;
1368       break;
1369     case RPC_FC_FIXED_REPEAT:
1370       rep = *(const WORD*)&pFormat[2];
1371       stride = *(const WORD*)&pFormat[4];
1372       count = *(const WORD*)&pFormat[8];
1373       pFormat += 10;
1374       break;
1375     case RPC_FC_VARIABLE_REPEAT:
1376       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1377       stride = *(const WORD*)&pFormat[2];
1378       count = *(const WORD*)&pFormat[6];
1379       pFormat += 8;
1380       break;
1381     }
1382     for (i = 0; i < rep; i++) {
1383       PFORMAT_STRING info = pFormat;
1384       unsigned char *bufbase = Mark + (i * stride);
1385       unsigned u;
1386       for (u=0; u<count; u++,info+=8) {
1387         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1388         PointerMemorySize(pStubMsg, bufptr, info+4);
1389       }
1390     }
1391     pFormat += 8 * count;
1392   }
1393 
1394   if (saved_buffer)
1395   {
1396     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1397     pStubMsg->Buffer = saved_buffer;
1398   }
1399 
1400   return 0;
1401 }
1402 
1403 /***********************************************************************
1404  *           EmbeddedPointerFree [internal]
1405  */
1406 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1407                                 unsigned char *pMemory,
1408                                 PFORMAT_STRING pFormat)
1409 {
1410   unsigned rep, count, stride;
1411   unsigned i;
1412 
1413   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1414   if (*pFormat != RPC_FC_PP) return;
1415   pFormat += 2;
1416 
1417   while (pFormat[0] != RPC_FC_END) {
1418     switch (pFormat[0]) {
1419     default:
1420       FIXME("unknown repeat type %d\n", pFormat[0]);
1421     case RPC_FC_NO_REPEAT:
1422       rep = 1;
1423       stride = 0;
1424       count = 1;
1425       pFormat += 2;
1426       break;
1427     case RPC_FC_FIXED_REPEAT:
1428       rep = *(const WORD*)&pFormat[2];
1429       stride = *(const WORD*)&pFormat[4];
1430       count = *(const WORD*)&pFormat[8];
1431       pFormat += 10;
1432       break;
1433     case RPC_FC_VARIABLE_REPEAT:
1434       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1435       stride = *(const WORD*)&pFormat[2];
1436       count = *(const WORD*)&pFormat[6];
1437       pFormat += 8;
1438       break;
1439     }
1440     for (i = 0; i < rep; i++) {
1441       PFORMAT_STRING info = pFormat;
1442       unsigned char *membase = pMemory + (i * stride);
1443       unsigned u;
1444 
1445       for (u=0; u<count; u++,info+=8) {
1446         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1447         unsigned char *saved_memory = pStubMsg->Memory;
1448 
1449         pStubMsg->Memory = pMemory;
1450         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1451         pStubMsg->Memory = saved_memory;
1452       }
1453     }
1454     pFormat += 8 * count;
1455   }
1456 }
1457 
1458 /***********************************************************************
1459  *           NdrPointerMarshall [RPCRT4.@]
1460  */
1461 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1462                                           unsigned char *pMemory,
1463                                           PFORMAT_STRING pFormat)
1464 {
1465   unsigned char *Buffer;
1466 
1467   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1468 
1469   /* Increment the buffer here instead of in PointerMarshall,
1470    * as that is used by embedded pointers which already handle the incrementing
1471    * the buffer, and shouldn't write any additional pointer data to the wire */
1472   if (*pFormat != RPC_FC_RP)
1473   {
1474     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1475     Buffer = pStubMsg->Buffer;
1476     safe_buffer_increment(pStubMsg, 4);
1477   }
1478   else
1479     Buffer = pStubMsg->Buffer;
1480 
1481   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1482 
1483   return NULL;
1484 }
1485 
1486 /***********************************************************************
1487  *           NdrPointerUnmarshall [RPCRT4.@]
1488  */
1489 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1490                                             unsigned char **ppMemory,
1491                                             PFORMAT_STRING pFormat,
1492                                             unsigned char fMustAlloc)
1493 {
1494   unsigned char *Buffer;
1495 
1496   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1497 
1498   /* Increment the buffer here instead of in PointerUnmarshall,
1499    * as that is used by embedded pointers which already handle the incrementing
1500    * the buffer, and shouldn't read any additional pointer data from the
1501    * buffer */
1502   if (*pFormat != RPC_FC_RP)
1503   {
1504     ALIGN_POINTER(pStubMsg->Buffer, 4);
1505     Buffer = pStubMsg->Buffer;
1506     safe_buffer_increment(pStubMsg, 4);
1507   }
1508   else
1509     Buffer = pStubMsg->Buffer;
1510 
1511   PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1512 
1513   return NULL;
1514 }
1515 
1516 /***********************************************************************
1517  *           NdrPointerBufferSize [RPCRT4.@]
1518  */
1519 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1520                                       unsigned char *pMemory,
1521                                       PFORMAT_STRING pFormat)
1522 {
1523   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1524 
1525   /* Increment the buffer length here instead of in PointerBufferSize,
1526    * as that is used by embedded pointers which already handle the buffer
1527    * length, and shouldn't write anything more to the wire */
1528   if (*pFormat != RPC_FC_RP)
1529   {
1530     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1531     safe_buffer_length_increment(pStubMsg, 4);
1532   }
1533 
1534   PointerBufferSize(pStubMsg, pMemory, pFormat);
1535 }
1536 
1537 /***********************************************************************
1538  *           NdrPointerMemorySize [RPCRT4.@]
1539  */
1540 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1541                                   PFORMAT_STRING pFormat)
1542 {
1543   /* unsigned size = *(LPWORD)(pFormat+2); */
1544   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1545   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1546   return 0;
1547 }
1548 
1549 /***********************************************************************
1550  *           NdrPointerFree [RPCRT4.@]
1551  */
1552 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1553                            unsigned char *pMemory,
1554                            PFORMAT_STRING pFormat)
1555 {
1556   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1557   PointerFree(pStubMsg, pMemory, pFormat);
1558 }
1559 
1560 /***********************************************************************
1561  *           NdrSimpleTypeMarshall [RPCRT4.@]
1562  */
1563 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1564                                    unsigned char FormatChar )
1565 {
1566     NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1567 }
1568 
1569 /***********************************************************************
1570  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
1571  *
1572  * Unmarshall a base type.
1573  *
1574  * NOTES
1575  *  Doesn't check that the buffer is long enough before copying, so the caller
1576  * should do this.
1577  */
1578 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1579                                      unsigned char FormatChar )
1580 {
1581 #define BASE_TYPE_UNMARSHALL(type) \
1582         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
1583         TRACE("pMemory: %p\n", pMemory); \
1584         *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1585         pStubMsg->Buffer += sizeof(type);
1586 
1587     switch(FormatChar)
1588     {
1589     case RPC_FC_BYTE:
1590     case RPC_FC_CHAR:
1591     case RPC_FC_SMALL:
1592     case RPC_FC_USMALL:
1593         BASE_TYPE_UNMARSHALL(UCHAR);
1594         TRACE("value: 0x%02x\n", *pMemory);
1595         break;
1596     case RPC_FC_WCHAR:
1597     case RPC_FC_SHORT:
1598     case RPC_FC_USHORT:
1599         BASE_TYPE_UNMARSHALL(USHORT);
1600         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1601         break;
1602     case RPC_FC_LONG:
1603     case RPC_FC_ULONG:
1604     case RPC_FC_ERROR_STATUS_T:
1605     case RPC_FC_ENUM32:
1606         BASE_TYPE_UNMARSHALL(ULONG);
1607         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1608         break;
1609    case RPC_FC_FLOAT:
1610         BASE_TYPE_UNMARSHALL(float);
1611         TRACE("value: %f\n", *(float *)pMemory);
1612         break;
1613     case RPC_FC_DOUBLE:
1614         BASE_TYPE_UNMARSHALL(double);
1615         TRACE("value: %f\n", *(double *)pMemory);
1616         break;
1617     case RPC_FC_HYPER:
1618         BASE_TYPE_UNMARSHALL(ULONGLONG);
1619         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1620         break;
1621     case RPC_FC_ENUM16:
1622         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
1623         TRACE("pMemory: %p\n", pMemory);
1624         /* 16-bits on the wire, but int in memory */
1625         *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1626         pStubMsg->Buffer += sizeof(USHORT);
1627         TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1628         break;
1629     case RPC_FC_IGNORE:
1630         break;
1631     default:
1632         FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1633     }
1634 #undef BASE_TYPE_UNMARSHALL
1635 }
1636 
1637 /***********************************************************************
1638  *           NdrSimpleStructMarshall [RPCRT4.@]
1639  */
1640 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1641                                                unsigned char *pMemory,
1642                                                PFORMAT_STRING pFormat)
1643 {
1644   unsigned size = *(const WORD*)(pFormat+2);
1645   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1646 
1647   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
1648 
1649   pStubMsg->BufferMark = pStubMsg->Buffer;
1650   safe_copy_to_buffer(pStubMsg, pMemory, size);
1651 
1652   if (pFormat[0] != RPC_FC_STRUCT)
1653     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1654 
1655   return NULL;
1656 }
1657 
1658 /***********************************************************************
1659  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1660  */
1661 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1662                                                  unsigned char **ppMemory,
1663                                                  PFORMAT_STRING pFormat,
1664                                                  unsigned char fMustAlloc)
1665 {
1666   unsigned size = *(const WORD*)(pFormat+2);
1667   unsigned char *saved_buffer;
1668   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1669 
1670   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1671 
1672   if (fMustAlloc)
1673     *ppMemory = NdrAllocate(pStubMsg, size);
1674   else
1675   {
1676     if (!pStubMsg->IsClient && !*ppMemory)
1677       /* for servers, we just point straight into the RPC buffer */
1678       *ppMemory = pStubMsg->Buffer;
1679   }
1680 
1681   saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1682   safe_buffer_increment(pStubMsg, size);
1683   if (pFormat[0] == RPC_FC_PSTRUCT)
1684       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1685 
1686   TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1687   if (*ppMemory != saved_buffer)
1688       memcpy(*ppMemory, saved_buffer, size);
1689 
1690   return NULL;
1691 }
1692 
1693 /***********************************************************************
1694  *           NdrSimpleStructBufferSize [RPCRT4.@]
1695  */
1696 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1697                                       unsigned char *pMemory,
1698                                       PFORMAT_STRING pFormat)
1699 {
1700   unsigned size = *(const WORD*)(pFormat+2);
1701   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1702 
1703   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1704 
1705   safe_buffer_length_increment(pStubMsg, size);
1706   if (pFormat[0] != RPC_FC_STRUCT)
1707     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1708 }
1709 
1710 /***********************************************************************
1711  *           NdrSimpleStructMemorySize [RPCRT4.@]
1712  */
1713 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1714                                        PFORMAT_STRING pFormat)
1715 {
1716   unsigned short size = *(const WORD *)(pFormat+2);
1717 
1718   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1719 
1720   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1721   pStubMsg->MemorySize += size;
1722   safe_buffer_increment(pStubMsg, size);
1723 
1724   if (pFormat[0] != RPC_FC_STRUCT)
1725     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1726   return pStubMsg->MemorySize;
1727 }
1728 
1729 /***********************************************************************
1730  *           NdrSimpleStructFree [RPCRT4.@]
1731  */
1732 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1733                                 unsigned char *pMemory,
1734                                 PFORMAT_STRING pFormat)
1735 {
1736   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1737   if (pFormat[0] != RPC_FC_STRUCT)
1738     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1739 }
1740 
1741 /* Array helpers */
1742 
1743 static inline void array_compute_and_size_conformance(
1744     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1745     PFORMAT_STRING pFormat)
1746 {
1747   switch (fc)
1748   {
1749   case RPC_FC_CARRAY:
1750     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1751     SizeConformance(pStubMsg);
1752     break;
1753   case RPC_FC_CVARRAY:
1754     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1755     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1756     SizeConformance(pStubMsg);
1757     break;
1758   case RPC_FC_C_CSTRING:
1759   case RPC_FC_C_WSTRING:
1760     if (pFormat[0] == RPC_FC_C_CSTRING)
1761     {
1762       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1763       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1764     }
1765     else
1766     {
1767       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1768       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1769     }
1770 
1771     if (fc == RPC_FC_STRING_SIZED)
1772       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1773     else
1774       pStubMsg->MaxCount = pStubMsg->ActualCount;
1775 
1776     SizeConformance(pStubMsg);
1777     break;
1778   default:
1779     ERR("unknown array format 0x%x\n", fc);
1780     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1781   }
1782 }
1783 
1784 static inline void array_buffer_size(
1785     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1786     PFORMAT_STRING pFormat, unsigned char fHasPointers)
1787 {
1788   DWORD size;
1789   DWORD esize;
1790   unsigned char alignment;
1791 
1792   switch (fc)
1793   {
1794   case RPC_FC_CARRAY:
1795     esize = *(const WORD*)(pFormat+2);
1796     alignment = pFormat[1] + 1;
1797 
1798     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1799 
1800     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1801 
1802     size = safe_multiply(esize, pStubMsg->MaxCount);
1803     /* conformance value plus array */
1804     safe_buffer_length_increment(pStubMsg, size);
1805 
1806     if (fHasPointers)
1807       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1808     break;
1809   case RPC_FC_CVARRAY:
1810     esize = *(const WORD*)(pFormat+2);
1811     alignment = pFormat[1] + 1;
1812 
1813     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1814     pFormat = SkipConformance(pStubMsg, pFormat);
1815 
1816     SizeVariance(pStubMsg);
1817 
1818     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1819 
1820     size = safe_multiply(esize, pStubMsg->ActualCount);
1821     safe_buffer_length_increment(pStubMsg, size);
1822 
1823     if (fHasPointers)
1824       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1825     break;
1826   case RPC_FC_C_CSTRING:
1827   case RPC_FC_C_WSTRING:
1828     if (fc == RPC_FC_C_CSTRING)
1829       esize = 1;
1830     else
1831       esize = 2;
1832 
1833     SizeVariance(pStubMsg);
1834 
1835     size = safe_multiply(esize, pStubMsg->ActualCount);
1836     safe_buffer_length_increment(pStubMsg, size);
1837     break;
1838   default:
1839     ERR("unknown array format 0x%x\n", fc);
1840     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1841   }
1842 }
1843 
1844 static inline void array_compute_and_write_conformance(
1845     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1846     PFORMAT_STRING pFormat)
1847 {
1848   switch (fc)
1849   {
1850   case RPC_FC_CARRAY:
1851     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1852     WriteConformance(pStubMsg);
1853     break;
1854   case RPC_FC_CVARRAY:
1855     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1856     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1857     WriteConformance(pStubMsg);
1858     break;
1859   case RPC_FC_C_CSTRING:
1860   case RPC_FC_C_WSTRING:
1861     if (fc == RPC_FC_C_CSTRING)
1862     {
1863       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1864       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1865     }
1866     else
1867     {
1868       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1869       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1870     }
1871     if (pFormat[1] == RPC_FC_STRING_SIZED)
1872       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1873     else
1874       pStubMsg->MaxCount = pStubMsg->ActualCount;
1875     pStubMsg->Offset = 0;
1876     WriteConformance(pStubMsg);
1877     break;
1878   default:
1879     ERR("unknown array format 0x%x\n", fc);
1880     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1881   }
1882 }
1883 
1884 static inline void array_write_variance_and_marshall(
1885     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1886     PFORMAT_STRING pFormat, unsigned char fHasPointers)
1887 {
1888   DWORD size;
1889   DWORD esize;
1890   unsigned char alignment;
1891 
1892   switch (fc)
1893   {
1894   case RPC_FC_CARRAY:
1895     esize = *(const WORD*)(pFormat+2);
1896     alignment = pFormat[1] + 1;
1897 
1898     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1899 
1900     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1901 
1902     size = safe_multiply(esize, pStubMsg->MaxCount);
1903     if (fHasPointers)
1904       pStubMsg->BufferMark = pStubMsg->Buffer;
1905     safe_copy_to_buffer(pStubMsg, pMemory, size);
1906 
1907     if (fHasPointers)
1908       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1909     break;
1910   case RPC_FC_CVARRAY:
1911     esize = *(const WORD*)(pFormat+2);
1912     alignment = pFormat[1] + 1;
1913 
1914     /* conformance */
1915     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1916     /* variance */
1917     pFormat = SkipConformance(pStubMsg, pFormat);
1918 
1919     WriteVariance(pStubMsg);
1920 
1921     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1922 
1923     size = safe_multiply(esize, pStubMsg->ActualCount);
1924 
1925     if (fHasPointers)
1926       pStubMsg->BufferMark = pStubMsg->Buffer;
1927     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
1928 
1929     if (fHasPointers)
1930       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1931     break;
1932   case RPC_FC_C_CSTRING:
1933   case RPC_FC_C_WSTRING:
1934     if (fc == RPC_FC_C_CSTRING)
1935       esize = 1;
1936     else
1937       esize = 2;
1938 
1939     WriteVariance(pStubMsg);
1940 
1941     size = safe_multiply(esize, pStubMsg->ActualCount);
1942     safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
1943     break;
1944   default:
1945     ERR("unknown array format 0x%x\n", fc);
1946     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1947   }
1948 }
1949 
1950 static inline ULONG array_read_conformance(
1951     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
1952 {
1953   DWORD esize;
1954 
1955   switch (fc)
1956   {
1957   case RPC_FC_CARRAY:
1958     esize = *(const WORD*)(pFormat+2);
1959     pFormat = ReadConformance(pStubMsg, pFormat+4);
1960     return safe_multiply(esize, pStubMsg->MaxCount);
1961   case RPC_FC_CVARRAY:
1962     esize = *(const WORD*)(pFormat+2);
1963     pFormat = ReadConformance(pStubMsg, pFormat+4);
1964     return safe_multiply(esize, pStubMsg->MaxCount);
1965   case RPC_FC_C_CSTRING:
1966   case RPC_FC_C_WSTRING:
1967     if (fc == RPC_FC_C_CSTRING)
1968       esize = 1;
1969     else
1970       esize = 2;
1971 
1972     if (pFormat[1] == RPC_FC_STRING_SIZED)
1973       ReadConformance(pStubMsg, pFormat + 2);
1974     else
1975       ReadConformance(pStubMsg, NULL);
1976     return safe_multiply(esize, pStubMsg->MaxCount);
1977   default:
1978     ERR("unknown array format 0x%x\n", fc);
1979     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1980   }
1981 }
1982 
1983 static inline ULONG array_read_variance_and_unmarshall(
1984     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
1985     PFORMAT_STRING pFormat, unsigned char fMustAlloc,
1986     unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
1987 {
1988   ULONG bufsize, memsize;
1989   WORD esize;
1990   unsigned char alignment;
1991   unsigned char *saved_buffer;
1992   ULONG offset;
1993 
1994   switch (fc)
1995   {
1996   case RPC_FC_CARRAY:
1997     esize = *(const WORD*)(pFormat+2);
1998     alignment = pFormat[1] + 1;
1999 
2000     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2001 
2002     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2003 
2004     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2005 
2006     if (fUnmarshall)
2007     {
2008       if (fMustAlloc)
2009         *ppMemory = NdrAllocate(pStubMsg, memsize);
2010       else
2011       {
2012         if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2013           /* for servers, we just point straight into the RPC buffer */
2014           *ppMemory = pStubMsg->Buffer;
2015       }
2016 
2017       saved_buffer = pStubMsg->Buffer;
2018       safe_buffer_increment(pStubMsg, bufsize);
2019 
2020       pStubMsg->BufferMark = saved_buffer;
2021       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2022 
2023       TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2024       if (*ppMemory != saved_buffer)
2025         memcpy(*ppMemory, saved_buffer, bufsize);
2026     }
2027     return bufsize;
2028   case RPC_FC_CVARRAY:
2029     esize = *(const WORD*)(pFormat+2);
2030     alignment = pFormat[1] + 1;
2031 
2032     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2033 
2034     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2035 
2036     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2037 
2038     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2039     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2040 
2041     if (fUnmarshall)
2042     {
2043       offset = pStubMsg->Offset;
2044 
2045       if (!fMustAlloc && !*ppMemory)
2046         fMustAlloc = TRUE;
2047       if (fMustAlloc)
2048         *ppMemory = NdrAllocate(pStubMsg, memsize);
2049       saved_buffer = pStubMsg->Buffer;
2050       safe_buffer_increment(pStubMsg, bufsize);
2051 
2052       pStubMsg->BufferMark = saved_buffer;
2053       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2054                                 fMustAlloc);
2055 
2056       memcpy(*ppMemory + offset, saved_buffer, bufsize);
2057     }
2058     return bufsize;
2059   case RPC_FC_C_CSTRING:
2060   case RPC_FC_C_WSTRING:
2061     if (fc == RPC_FC_C_CSTRING)
2062       esize = 1;
2063     else
2064       esize = 2;
2065 
2066     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2067 
2068     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2069     {
2070       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2071           pStubMsg->ActualCount, pStubMsg->MaxCount);
2072       RpcRaiseException(RPC_S_INVALID_BOUND);
2073     }
2074     if (pStubMsg->Offset)
2075     {
2076       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2077       RpcRaiseException(RPC_S_INVALID_BOUND);
2078     }
2079 
2080     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2081     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2082 
2083     validate_string_data(pStubMsg, bufsize, esize);
2084 
2085     if (fUnmarshall)
2086     {
2087       if (fMustAlloc)
2088         *ppMemory = NdrAllocate(pStubMsg, memsize);
2089       else
2090       {
2091         if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2092             !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2093           /* if the data in the RPC buffer is big enough, we just point
2094            * straight into it */
2095           *ppMemory = pStubMsg->Buffer;
2096         else if (!*ppMemory)
2097           *ppMemory = NdrAllocate(pStubMsg, memsize);
2098       }
2099 
2100       if (*ppMemory == pStubMsg->Buffer)
2101         safe_buffer_increment(pStubMsg, bufsize);
2102       else
2103         safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2104 
2105       if (*pFormat == RPC_FC_C_CSTRING)
2106         TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2107       else
2108         TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2109     }
2110     return bufsize;
2111   default:
2112     ERR("unknown array format 0x%x\n", fc);
2113     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2114   }
2115 }
2116 
2117 static inline void array_memory_size(
2118     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2119     unsigned char fHasPointers)
2120 {
2121   ULONG bufsize, memsize;
2122   DWORD esize;
2123   unsigned char alignment;
2124 
2125   switch (fc)
2126   {
2127   case RPC_FC_CARRAY:
2128     esize = *(const WORD*)(pFormat+2);
2129     alignment = pFormat[1] + 1;
2130 
2131     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2132 
2133     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2134     pStubMsg->MemorySize += memsize;
2135 
2136     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2137     if (fHasPointers)
2138       pStubMsg->BufferMark = pStubMsg->Buffer;
2139     safe_buffer_increment(pStubMsg, bufsize);
2140 
2141     if (fHasPointers)
2142       EmbeddedPointerMemorySize(pStubMsg, pFormat);
2143     break;
2144   case RPC_FC_CVARRAY:
2145     esize = *(const WORD*)(pFormat+2);
2146     alignment = pFormat[1] + 1;
2147 
2148     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2149 
2150     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2151 
2152     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2153     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2154     pStubMsg->MemorySize += memsize;
2155 
2156     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2157     if (fHasPointers)
2158       pStubMsg->BufferMark = pStubMsg->Buffer;
2159     safe_buffer_increment(pStubMsg, bufsize);
2160 
2161     if (fHasPointers)
2162       EmbeddedPointerMemorySize(pStubMsg, pFormat);
2163     break;
2164   case RPC_FC_C_CSTRING:
2165   case RPC_FC_C_WSTRING:
2166     if (fc == RPC_FC_C_CSTRING)
2167       esize = 1;
2168     else
2169       esize = 2;
2170 
2171     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2172 
2173     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2174     {
2175       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2176           pStubMsg->ActualCount, pStubMsg->MaxCount);
2177       RpcRaiseException(RPC_S_INVALID_BOUND);
2178     }
2179     if (pStubMsg->Offset)
2180     {
2181       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2182       RpcRaiseException(RPC_S_INVALID_BOUND);
2183     }
2184 
2185     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2186     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2187 
2188     validate_string_data(pStubMsg, bufsize, esize);
2189 
2190     safe_buffer_increment(pStubMsg, bufsize);
2191     pStubMsg->MemorySize += memsize;
2192     break;
2193   default:
2194     ERR("unknown array format 0x%x\n", fc);
2195     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2196   }
2197 }
2198 
2199 static inline void array_free(
2200     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2201     unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2202 {
2203   switch (fc)
2204   {
2205   case RPC_FC_CARRAY:
2206     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2207     if (fHasPointers)
2208       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2209     break;
2210   case RPC_FC_CVARRAY:
2211     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2212     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2213     if (fHasPointers)
2214       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2215     break;
2216   case RPC_FC_C_CSTRING:
2217   case RPC_FC_C_WSTRING:
2218     /* No embedded pointers so nothing to do */
2219     break;
2220   default:
2221     ERR("unknown array format 0x%x\n", fc);
2222     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2223   }
2224 }
2225 
2226 /*
2227  * NdrConformantString:
2228  *
2229  * What MS calls a ConformantString is, in DCE terminology,
2230  * a Varying-Conformant String.
2231  * [
2232  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2233  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
2234  *           into unmarshalled string)
2235  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2236  *   [
2237  *     data: CHARTYPE[maxlen]
2238  *   ]
2239  * ], where CHARTYPE is the appropriate character type (specified externally)
2240  *
2241  */
2242 
2243 /***********************************************************************
2244  *            NdrConformantStringMarshall [RPCRT4.@]
2245  */
2246 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
2247   unsigned char *pszMessage, PFORMAT_STRING pFormat)
2248 {
2249   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2250 
2251   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2252     ERR("Unhandled string type: %#x\n", pFormat[0]);
2253     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2254   }
2255 
2256   /* allow compiler to optimise inline function by passing constant into
2257    * these functions */
2258   if (pFormat[0] == RPC_FC_C_CSTRING) {
2259     array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2260                                         pFormat);
2261     array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2262                                       pFormat, TRUE /* fHasPointers */);
2263   } else {
2264     array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2265                                         pFormat);
2266     array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2267                                       pFormat, TRUE /* fHasPointers */);
2268   }
2269 
2270   return NULL;
2271 }
2272 
2273 /***********************************************************************
2274  *           NdrConformantStringBufferSize [RPCRT4.@]
2275  */
2276 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2277   unsigned char* pMemory, PFORMAT_STRING pFormat)
2278 {
2279   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2280 
2281   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2282     ERR("Unhandled string type: %#x\n", pFormat[0]);
2283     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2284   }
2285 
2286   /* allow compiler to optimise inline function by passing constant into
2287    * these functions */
2288   if (pFormat[0] == RPC_FC_C_CSTRING) {
2289     array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory,
2290                                        pFormat);
2291     array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2292                       TRUE /* fHasPointers */);
2293   } else {
2294     array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory,
2295                                        pFormat);
2296     array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2297                       TRUE /* fHasPointers */);
2298   }
2299 }
2300 
2301 /************************************************************************
2302  *            NdrConformantStringMemorySize [RPCRT4.@]
2303  */
2304 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2305   PFORMAT_STRING pFormat )
2306 {
2307   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2308 
2309   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2310     ERR("Unhandled string type: %#x\n", pFormat[0]);
2311     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2312   }
2313 
2314   /* allow compiler to optimise inline function by passing constant into
2315    * these functions */
2316   if (pFormat[0] == RPC_FC_C_CSTRING) {
2317     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2318     array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat,
2319                       TRUE /* fHasPointers */);
2320   } else {
2321     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2322     array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat,
2323                       TRUE /* fHasPointers */);
2324   }
2325 
2326   return pStubMsg->MemorySize;
2327 }
2328 
2329 /************************************************************************
2330  *           NdrConformantStringUnmarshall [RPCRT4.@]
2331  */
2332 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2333   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2334 {
2335   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2336     pStubMsg, *ppMemory, pFormat, fMustAlloc);
2337 
2338   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2339     ERR("Unhandled string type: %#x\n", *pFormat);
2340     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2341   }
2342 
2343   /* allow compiler to optimise inline function by passing constant into
2344    * these functions */
2345   if (pFormat[0] == RPC_FC_C_CSTRING) {
2346     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2347     array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory,
2348                                        pFormat, fMustAlloc,
2349                                        TRUE /* fUseBufferMemoryServer */,
2350                                        TRUE /* fUnmarshall */);
2351   } else {
2352     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2353     array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory,
2354                                        pFormat, fMustAlloc,
2355                                        TRUE /* fUseBufferMemoryServer */,
2356                                        TRUE /* fUnmarshall */);
2357   }
2358 
2359   return NULL;
2360 }
2361 
2362 /***********************************************************************
2363  *           NdrNonConformantStringMarshall [RPCRT4.@]
2364  */
2365 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2366                                 unsigned char *pMemory,
2367                                 PFORMAT_STRING pFormat)
2368 {
2369   ULONG esize, size, maxsize;
2370 
2371   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2372 
2373   maxsize = *(USHORT *)&pFormat[2];
2374 
2375   if (*pFormat == RPC_FC_CSTRING)
2376   {
2377     ULONG i;
2378     const char *str = (const char *)pMemory;
2379     for (i = 0; i < maxsize && *str; i++, str++)
2380         ;
2381     TRACE("string=%s\n", debugstr_an(str, i));
2382     pStubMsg->ActualCount = i + 1;
2383     esize = 1;
2384   }
2385   else if (*pFormat == RPC_FC_WSTRING)
2386   {
2387     ULONG i;
2388     const WCHAR *str = (const WCHAR *)pMemory;
2389     for (i = 0; i < maxsize && *str; i++, str++)
2390         ;
2391     TRACE("string=%s\n", debugstr_wn(str, i));
2392     pStubMsg->ActualCount = i + 1;
2393     esize = 2;
2394   }
2395   else
2396   {
2397     ERR("Unhandled string type: %#x\n", *pFormat);
2398     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2399   }
2400 
2401   pStubMsg->Offset = 0;
2402   WriteVariance(pStubMsg);
2403 
2404   size = safe_multiply(esize, pStubMsg->ActualCount);
2405   safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2406 
2407   return NULL;
2408 }
2409 
2410 /***********************************************************************
2411  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
2412  */
2413 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2414                                 unsigned char **ppMemory,
2415                                 PFORMAT_STRING pFormat,
2416                                 unsigned char fMustAlloc)
2417 {
2418   ULONG bufsize, memsize, esize, maxsize;
2419 
2420   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2421     pStubMsg, *ppMemory, pFormat, fMustAlloc);
2422 
2423   maxsize = *(USHORT *)&pFormat[2];
2424 
2425   ReadVariance(pStubMsg, NULL, maxsize);
2426   if (pStubMsg->Offset)
2427   {
2428     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2429     RpcRaiseException(RPC_S_INVALID_BOUND);
2430   }
2431 
2432   if (*pFormat == RPC_FC_CSTRING) esize = 1;
2433   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2434   else
2435   {
2436     ERR("Unhandled string type: %#x\n", *pFormat);
2437     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2438   }
2439 
2440   memsize = esize * maxsize;
2441   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2442 
2443   validate_string_data(pStubMsg, bufsize, esize);
2444 
2445   if (fMustAlloc || !*ppMemory)
2446     *ppMemory = NdrAllocate(pStubMsg, memsize);
2447 
2448   safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2449 
2450   if (*pFormat == RPC_FC_CSTRING) {
2451     TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2452   }
2453   else if (*pFormat == RPC_FC_WSTRING) {
2454     TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2455   }
2456 
2457   return NULL;
2458 }
2459 
2460 /***********************************************************************
2461  *           NdrNonConformantStringBufferSize [RPCRT4.@]
2462  */
2463 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2464                                 unsigned char *pMemory,
2465                                 PFORMAT_STRING pFormat)
2466 {
2467   ULONG esize, maxsize;
2468 
2469   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2470 
2471   maxsize = *(USHORT *)&pFormat[2];
2472 
2473   SizeVariance(pStubMsg);
2474 
2475   if (*pFormat == RPC_FC_CSTRING)
2476   {
2477     ULONG i;
2478     const char *str = (const char *)pMemory;
2479     for (i = 0; i < maxsize && *str; i++, str++)
2480         ;
2481     TRACE("string=%s\n", debugstr_an(str, i));
2482     pStubMsg->ActualCount = i + 1;
2483     esize = 1;
2484   }
2485   else if (*pFormat == RPC_FC_WSTRING)
2486   {
2487     ULONG i;
2488     const WCHAR *str = (const WCHAR *)pMemory;
2489     for (i = 0; i < maxsize && *str; i++, str++)
2490         ;
2491     TRACE("string=%s\n", debugstr_wn(str, i));
2492     pStubMsg->ActualCount = i + 1;
2493     esize = 2;
2494   }
2495   else
2496   {
2497     ERR("Unhandled string type: %#x\n", *pFormat);
2498     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2499   }
2500 
2501   safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2502 }
2503 
2504 /***********************************************************************
2505  *           NdrNonConformantStringMemorySize [RPCRT4.@]
2506  */
2507 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2508                                 PFORMAT_STRING pFormat)
2509 {
2510   ULONG bufsize, memsize, esize, maxsize;
2511 
2512   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2513 
2514   maxsize = *(USHORT *)&pFormat[2];
2515 
2516   ReadVariance(pStubMsg, NULL, maxsize);
2517 
2518   if (pStubMsg->Offset)
2519   {
2520     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2521     RpcRaiseException(RPC_S_INVALID_BOUND);
2522   }
2523 
2524   if (*pFormat == RPC_FC_CSTRING) esize = 1;
2525   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2526   else
2527   {
2528     ERR("Unhandled string type: %#x\n", *pFormat);
2529     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2530   }
2531 
2532   memsize = esize * maxsize;
2533   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2534 
2535   validate_string_data(pStubMsg, bufsize, esize);
2536 
2537   safe_buffer_increment(pStubMsg, bufsize);
2538   pStubMsg->MemorySize += memsize;
2539 
2540   return pStubMsg->MemorySize;
2541 }
2542 
2543 /* Complex types */
2544 
2545 #include "pshpack1.h"
2546 typedef struct
2547 {
2548     unsigned char type;
2549     unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2550     ULONG low_value;
2551     ULONG high_value;
2552 } NDR_RANGE;
2553 #include "poppack.h"
2554 
2555 static unsigned long EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2556                                          PFORMAT_STRING pFormat)
2557 {
2558   switch (*pFormat) {
2559   case RPC_FC_STRUCT:
2560   case RPC_FC_PSTRUCT:
2561   case RPC_FC_CSTRUCT:
2562   case RPC_FC_BOGUS_STRUCT:
2563   case RPC_FC_SMFARRAY:
2564   case RPC_FC_SMVARRAY:
2565   case RPC_FC_CSTRING:
2566     return *(const WORD*)&pFormat[2];
2567   case RPC_FC_USER_MARSHAL:
2568     return *(const WORD*)&pFormat[4];
2569   case RPC_FC_RANGE: {
2570     switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2571     case RPC_FC_BYTE:
2572     case RPC_FC_CHAR:
2573     case RPC_FC_SMALL:
2574     case RPC_FC_USMALL:
2575         return sizeof(UCHAR);
2576     case RPC_FC_WCHAR:
2577     case RPC_FC_SHORT:
2578     case RPC_FC_USHORT:
2579         return sizeof(USHORT);
2580     case RPC_FC_LONG:
2581     case RPC_FC_ULONG:
2582     case RPC_FC_ENUM32:
2583         return sizeof(ULONG);
2584     case RPC_FC_FLOAT:
2585         return sizeof(float);
2586     case RPC_FC_DOUBLE:
2587         return sizeof(double);
2588     case RPC_FC_HYPER:
2589         return sizeof(ULONGLONG);
2590     case RPC_FC_ENUM16:
2591         return sizeof(UINT);
2592     default:
2593         ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2594         RpcRaiseException(RPC_X_BAD_STUB_DATA);
2595     }
2596   }
2597   case RPC_FC_NON_ENCAPSULATED_UNION:
2598     pFormat += 2;
2599     if (pStubMsg->fHasNewCorrDesc)
2600         pFormat += 6;
2601     else
2602         pFormat += 4;
2603 
2604     pFormat += *(const SHORT*)pFormat;
2605     return *(const SHORT*)pFormat;
2606   case RPC_FC_IP:
2607     return sizeof(void *);
2608   case RPC_FC_WSTRING:
2609     return *(const WORD*)&pFormat[2] * 2;
2610   default:
2611     FIXME("unhandled embedded type %02x\n", *pFormat);
2612   }
2613   return 0;
2614 }
2615 
2616 
2617 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2618                                                PFORMAT_STRING pFormat)
2619 {
2620   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2621 
2622   if (!m)
2623   {
2624     FIXME("no memorysizer for data type=%02x\n", *pFormat);
2625     return 0;
2626   }
2627 
2628   return m(pStubMsg, pFormat);
2629 }
2630 
2631 
2632 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2633                                        unsigned char *pMemory,
2634                                        PFORMAT_STRING pFormat,
2635                                        PFORMAT_STRING pPointer)
2636 {
2637   PFORMAT_STRING desc;
2638   NDR_MARSHALL m;
2639   unsigned long size;
2640 
2641   while (*pFormat != RPC_FC_END) {
2642     switch (*pFormat) {
2643     case RPC_FC_BYTE:
2644     case RPC_FC_CHAR:
2645     case RPC_FC_SMALL:
2646     case RPC_FC_USMALL:
2647       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2648       safe_copy_to_buffer(pStubMsg, pMemory, 1);
2649       pMemory += 1;
2650       break;
2651     case RPC_FC_WCHAR:
2652     case RPC_FC_SHORT:
2653     case RPC_FC_USHORT:
2654       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2655       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2656       pMemory += 2;
2657       break;
2658     case RPC_FC_ENUM16:
2659       TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2660       if (32767 < *(DWORD*)pMemory)
2661         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2662       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2663       pMemory += 4;
2664       break;
2665     case RPC_FC_LONG:
2666     case RPC_FC_ULONG:
2667     case RPC_FC_ENUM32:
2668       TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2669       safe_copy_to_buffer(pStubMsg, pMemory, 4);
2670       pMemory += 4;
2671       break;
2672     case RPC_FC_HYPER:
2673       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2674       safe_copy_to_buffer(pStubMsg, pMemory, 8);
2675       pMemory += 8;
2676       break;
2677     case RPC_FC_POINTER:
2678     {
2679       unsigned char *saved_buffer;
2680       int pointer_buffer_mark_set = 0;
2681       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2682       TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2683       if (*pPointer != RPC_FC_RP)
2684         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2685       saved_buffer = pStubMsg->Buffer;
2686       if (pStubMsg->PointerBufferMark)
2687       {
2688         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2689         pStubMsg->PointerBufferMark = NULL;
2690         pointer_buffer_mark_set = 1;
2691       }
2692       else if (*pPointer != RPC_FC_RP)
2693         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2694       PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2695       if (pointer_buffer_mark_set)
2696       {
2697         STD_OVERFLOW_CHECK(pStubMsg);
2698         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2699         pStubMsg->Buffer = saved_buffer;
2700         if (*pPointer != RPC_FC_RP)
2701           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2702       }
2703       TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2704       pPointer += 4;
2705       pMemory += 4;
2706       break;
2707     }
2708     case RPC_FC_ALIGNM4:
2709       ALIGN_POINTER(pMemory, 4);
2710       break;
2711     case RPC_FC_ALIGNM8:
2712       ALIGN_POINTER(pMemory, 8);
2713       break;
2714     case RPC_FC_STRUCTPAD1:
2715     case RPC_FC_STRUCTPAD2:
2716     case RPC_FC_STRUCTPAD3:
2717     case RPC_FC_STRUCTPAD4:
2718     case RPC_FC_STRUCTPAD5:
2719     case RPC_FC_STRUCTPAD6:
2720     case RPC_FC_STRUCTPAD7:
2721       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2722       break;
2723     case RPC_FC_EMBEDDED_COMPLEX:
2724       pMemory += pFormat[1];
2725       pFormat += 2;
2726       desc = pFormat + *(const SHORT*)pFormat;
2727       size = EmbeddedComplexSize(pStubMsg, desc);
2728       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
2729       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2730       if (m)
2731       {
2732         /* for some reason interface pointers aren't generated as
2733          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2734          * they still need the derefencing treatment that pointers are
2735          * given */
2736         if (*desc == RPC_FC_IP)
2737           m(pStubMsg, *(unsigned char **)pMemory, desc);
2738         else
2739           m(pStubMsg, pMemory, desc);
2740       }
2741       else FIXME("no marshaller for embedded type %02x\n", *desc);
2742       pMemory += size;
2743       pFormat += 2;
2744       continue;
2745     case RPC_FC_PAD:
2746       break;
2747     default:
2748       FIXME("unhandled format 0x%02x\n", *pFormat);
2749     }
2750     pFormat++;
2751   }
2752 
2753   return pMemory;
2754 }
2755 
2756 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2757                                          unsigned char *pMemory,
2758                                          PFORMAT_STRING pFormat,
2759                                          PFORMAT_STRING pPointer,
2760                                          unsigned char fMustAlloc)
2761 {
2762   PFORMAT_STRING desc;
2763   NDR_UNMARSHALL m;
2764   unsigned long size;
2765 
2766   while (*pFormat != RPC_FC_END) {
2767     switch (*pFormat) {
2768     case RPC_FC_BYTE:
2769     case RPC_FC_CHAR:
2770     case RPC_FC_SMALL:
2771     case RPC_FC_USMALL:
2772       safe_copy_from_buffer(pStubMsg, pMemory, 1);
2773       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2774       pMemory += 1;
2775       break;
2776     case RPC_FC_WCHAR:
2777     case RPC_FC_SHORT:
2778     case RPC_FC_USHORT:
2779       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2780       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2781       pMemory += 2;
2782       break;
2783     case RPC_FC_ENUM16:
2784       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2785       *(DWORD*)pMemory &= 0xffff;
2786       TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2787       if (32767 < *(DWORD*)pMemory)
2788         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2789       pMemory += 4;
2790       break;
2791     case RPC_FC_LONG:
2792     case RPC_FC_ULONG:
2793     case RPC_FC_ENUM32:
2794       safe_copy_from_buffer(pStubMsg, pMemory, 4);
2795       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2796       pMemory += 4;
2797       break;
2798     case RPC_FC_HYPER:
2799       safe_copy_from_buffer(pStubMsg, pMemory, 8);
2800       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2801       pMemory += 8;
2802       break;
2803     case RPC_FC_POINTER:
2804     {
2805       unsigned char *saved_buffer;
2806       int pointer_buffer_mark_set = 0;
2807       TRACE("pointer => %p\n", pMemory);
2808       if (*pPointer != RPC_FC_RP)
2809         ALIGN_POINTER(pStubMsg->Buffer, 4);
2810       saved_buffer = pStubMsg->Buffer;
2811       if (pStubMsg->PointerBufferMark)
2812       {
2813         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2814         pStubMsg->PointerBufferMark = NULL;
2815         pointer_buffer_mark_set = 1;
2816       }
2817       else if (*pPointer != RPC_FC_RP)
2818         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2819 
2820       PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
2821       if (pointer_buffer_mark_set)
2822       {
2823         STD_OVERFLOW_CHECK(pStubMsg);
2824         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2825         pStubMsg->Buffer = saved_buffer;
2826         if (*pPointer != RPC_FC_RP)
2827           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2828       }
2829       pPointer += 4;
2830       pMemory += 4;
2831       break;
2832     }
2833     case RPC_FC_ALIGNM4:
2834       ALIGN_POINTER_CLEAR(pMemory, 4);
2835       break;
2836     case RPC_FC_ALIGNM8:
2837       ALIGN_POINTER_CLEAR(pMemory, 8);
2838       break;
2839     case RPC_FC_STRUCTPAD1:
2840     case RPC_FC_STRUCTPAD2:
2841     case RPC_FC_STRUCTPAD3:
2842     case RPC_FC_STRUCTPAD4:
2843     case RPC_FC_STRUCTPAD5:
2844     case RPC_FC_STRUCTPAD6:
2845     case RPC_FC_STRUCTPAD7:
2846       memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2847       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2848       break;
2849     case RPC_FC_EMBEDDED_COMPLEX:
2850       pMemory += pFormat[1];
2851       pFormat += 2;
2852       desc = pFormat + *(const SHORT*)pFormat;
2853       size = EmbeddedComplexSize(pStubMsg, desc);
2854       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
2855       if (fMustAlloc)
2856         /* we can't pass fMustAlloc=TRUE into the marshaller for this type
2857          * since the type is part of the memory block that is encompassed by
2858          * the whole complex type. Memory is forced to allocate when pointers
2859          * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
2860          * clearing the memory we pass in to the unmarshaller */
2861         memset(pMemory, 0, size);
2862       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2863       if (m)
2864       {
2865         /* for some reason interface pointers aren't generated as
2866          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2867          * they still need the derefencing treatment that pointers are
2868          * given */
2869         if (*desc == RPC_FC_IP)
2870           m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2871         else
2872           m(pStubMsg, &pMemory, desc, FALSE);
2873       }
2874       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2875       pMemory += size;
2876       pFormat += 2;
2877       continue;
2878     case RPC_FC_PAD:
2879       break;
2880     default:
2881       FIXME("unhandled format %d\n", *pFormat);
2882     }
2883     pFormat++;
2884   }
2885 
2886   return pMemory;
2887 }
2888 
2889 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2890                                          unsigned char *pMemory,
2891                                          PFORMAT_STRING pFormat,
2892                                          PFORMAT_STRING pPointer)
2893 {
2894   PFORMAT_STRING desc;
2895   NDR_BUFFERSIZE m;
2896   unsigned long size;
2897 
2898   while (*pFormat != RPC_FC_END) {
2899     switch (*pFormat) {
2900     case RPC_FC_BYTE:
2901     case RPC_FC_CHAR:
2902     case RPC_FC_SMALL:
2903     case RPC_FC_USMALL:
2904       safe_buffer_length_increment(pStubMsg, 1);
2905       pMemory += 1;
2906       break;
2907     case RPC_FC_WCHAR:
2908     case RPC_FC_SHORT:
2909     case RPC_FC_USHORT:
2910       safe_buffer_length_increment(pStubMsg, 2);
2911       pMemory += 2;
2912       break;
2913     case RPC_FC_ENUM16:
2914       safe_buffer_length_increment(pStubMsg, 2);
2915       pMemory += 4;
2916       break;
2917     case RPC_FC_LONG:
2918     case RPC_FC_ULONG:
2919     case RPC_FC_ENUM32:
2920       safe_buffer_length_increment(pStubMsg, 4);
2921       pMemory += 4;
2922       break;
2923     case RPC_FC_HYPER:
2924       safe_buffer_length_increment(pStubMsg, 8);
2925       pMemory += 8;
2926       break;
2927     case RPC_FC_POINTER:
2928       if (!pStubMsg->IgnoreEmbeddedPointers)
2929       {
2930         int saved_buffer_length = pStubMsg->BufferLength;
2931         pStubMsg->BufferLength = pStubMsg->PointerLength;
2932         pStubMsg->PointerLength = 0;
2933         if(!pStubMsg->BufferLength)
2934           ERR("BufferLength == 0??\n");
2935         PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2936         pStubMsg->PointerLength = pStubMsg->BufferLength;
2937         pStubMsg->BufferLength = saved_buffer_length;
2938       }
2939       if (*pPointer != RPC_FC_RP)
2940       {
2941         ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2942         safe_buffer_length_increment(pStubMsg, 4);
2943       }
2944       pPointer += 4;
2945       pMemory += 4;
2946       break;
2947     case RPC_FC_ALIGNM4:
2948       ALIGN_POINTER(pMemory, 4);
2949       break;
2950     case RPC_FC_ALIGNM8:
2951       ALIGN_POINTER(pMemory, 8);
2952       break;
2953     case RPC_FC_STRUCTPAD1:
2954     case RPC_FC_STRUCTPAD2:
2955     case RPC_FC_STRUCTPAD3:
2956     case RPC_FC_STRUCTPAD4:
2957     case RPC_FC_STRUCTPAD5:
2958     case RPC_FC_STRUCTPAD6:
2959     case RPC_FC_STRUCTPAD7:
2960       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2961       break;
2962     case RPC_FC_EMBEDDED_COMPLEX:
2963       pMemory += pFormat[1];
2964       pFormat += 2;
2965       desc = pFormat + *(const SHORT*)pFormat;
2966       size = EmbeddedComplexSize(pStubMsg, desc);
2967       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2968       if (m)
2969       {
2970         /* for some reason interface pointers aren't generated as
2971          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2972          * they still need the derefencing treatment that pointers are
2973          * given */
2974         if (*desc == RPC_FC_IP)
2975           m(pStubMsg, *(unsigned char **)pMemory, desc);
2976         else
2977           m(pStubMsg, pMemory, desc);
2978       }
2979       else FIXME("no buffersizer for embedded type %02x\n", *desc);
2980       pMemory += size;
2981       pFormat += 2;
2982       continue;
2983     case RPC_FC_PAD:
2984       break;
2985     default:
2986       FIXME("unhandled format 0x%02x\n", *pFormat);
2987     }
2988     pFormat++;
2989   }
2990 
2991   return pMemory;
2992 }
2993 
2994 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2995                                    unsigned char *pMemory,
2996                                    PFORMAT_STRING pFormat,
2997                                    PFORMAT_STRING pPointer)
2998 {
2999   PFORMAT_STRING desc;
3000   NDR_FREE m;
3001   unsigned long size;
3002 
3003   while (*pFormat != RPC_FC_END) {
3004     switch (*pFormat) {
3005     case RPC_FC_BYTE:
3006     case RPC_FC_CHAR:
3007     case RPC_FC_SMALL:
3008     case RPC_FC_USMALL:
3009       pMemory += 1;
3010       break;
3011     case RPC_FC_WCHAR:
3012     case RPC_FC_SHORT:
3013     case RPC_FC_USHORT:
3014       pMemory += 2;
3015       break;
3016     case RPC_FC_LONG:
3017     case RPC_FC_ULONG:
3018     case RPC_FC_ENUM16:
3019     case RPC_FC_ENUM32:
3020       pMemory += 4;
3021       break;
3022     case RPC_FC_HYPER:
3023       pMemory += 8;
3024       break;
3025     case RPC_FC_POINTER:
3026       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3027       pPointer += 4;
3028       pMemory += 4;
3029       break;
3030     case RPC_FC_ALIGNM4:
3031       ALIGN_POINTER(pMemory, 4);
3032       break;
3033     case RPC_FC_ALIGNM8:
3034       ALIGN_POINTER(pMemory, 8);
3035       break;
3036     case RPC_FC_STRUCTPAD1:
3037     case RPC_FC_STRUCTPAD2:
3038     case RPC_FC_STRUCTPAD3:
3039     case RPC_FC_STRUCTPAD4:
3040     case RPC_FC_STRUCTPAD5:
3041     case RPC_FC_STRUCTPAD6:
3042     case RPC_FC_STRUCTPAD7:
3043       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3044       break;
3045     case RPC_FC_EMBEDDED_COMPLEX:
3046       pMemory += pFormat[1];
3047       pFormat += 2;
3048       desc = pFormat + *(const SHORT*)pFormat;
3049       size = EmbeddedComplexSize(pStubMsg, desc);
3050       m = NdrFreer[*desc & NDR_TABLE_MASK];
3051       if (m)
3052       {
3053         /* for some reason interface pointers aren't generated as
3054          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3055          * they still need the derefencing treatment that pointers are
3056          * given */
3057         if (*desc == RPC_FC_IP)
3058           m(pStubMsg, *(unsigned char **)pMemory, desc);
3059         else
3060           m(pStubMsg, pMemory, desc);
3061       }
3062       pMemory += size;
3063       pFormat += 2;
3064       continue;
3065     case RPC_FC_PAD:
3066       break;
3067     default:
3068       FIXME("unhandled format 0x%02x\n", *pFormat);
3069     }
3070     pFormat++;
3071   }
3072 
3073   return pMemory;
3074 }
3075 
3076 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3077                                              PFORMAT_STRING pFormat,
3078                                              PFORMAT_STRING pPointer)
3079 {
3080   PFORMAT_STRING desc;
3081   unsigned long size = 0;
3082 
3083   while (*pFormat != RPC_FC_END) {
3084     switch (*pFormat) {
3085     case RPC_FC_BYTE:
3086     case RPC_FC_CHAR:
3087     case RPC_FC_SMALL:
3088     case RPC_FC_USMALL:
3089       size += 1;
3090       safe_buffer_increment(pStubMsg, 1);
3091       break;
3092     case RPC_FC_WCHAR:
3093     case RPC_FC_SHORT:
3094     case RPC_FC_USHORT:
3095       size += 2;
3096       safe_buffer_increment(pStubMsg, 2);
3097       break;
3098     case RPC_FC_ENUM16:
3099       size += 4;
3100       safe_buffer_increment(pStubMsg, 2);
3101       break;
3102     case RPC_FC_LONG:
3103     case RPC_FC_ULONG:
3104     case RPC_FC_ENUM32:
3105       size += 4;
3106       safe_buffer_increment(pStubMsg, 4);
3107       break;
3108     case RPC_FC_HYPER:
3109       size += 8;
3110       safe_buffer_increment(pStubMsg, 8);
3111       break;
3112     case RPC_FC_POINTER:
3113     {
3114       unsigned char *saved_buffer;
3115       int pointer_buffer_mark_set = 0;
3116       if (*pPointer != RPC_FC_RP)
3117         ALIGN_POINTER(pStubMsg->Buffer, 4);
3118       saved_buffer = pStubMsg->Buffer;
3119       if (pStubMsg->PointerBufferMark)
3120       {
3121         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3122         pStubMsg->PointerBufferMark = NULL;
3123         pointer_buffer_mark_set = 1;
3124       }
3125       else if (*pPointer != RPC_FC_RP)
3126         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3127 
3128       if (!pStubMsg->IgnoreEmbeddedPointers)
3129         PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3130       if (pointer_buffer_mark_set)
3131       {
3132         STD_OVERFLOW_CHECK(pStubMsg);
3133         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3134         pStubMsg->Buffer = saved_buffer;
3135         if (*pPointer != RPC_FC_RP)
3136           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3137       }
3138       pPointer += 4;
3139       size += 4;
3140       break;
3141     }
3142     case RPC_FC_ALIGNM4:
3143       ALIGN_LENGTH(size, 4);
3144       ALIGN_POINTER(pStubMsg->Buffer, 4);
3145       break;
3146     case RPC_FC_ALIGNM8:
3147       ALIGN_LENGTH(size, 8);
3148       ALIGN_POINTER(pStubMsg->Buffer, 8);
3149       break;
3150     case RPC_FC_STRUCTPAD1:
3151     case RPC_FC_STRUCTPAD2:
3152     case RPC_FC_STRUCTPAD3:
3153     case RPC_FC_STRUCTPAD4:
3154     case RPC_FC_STRUCTPAD5:
3155     case RPC_FC_STRUCTPAD6:
3156     case RPC_FC_STRUCTPAD7:
3157       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3158       break;
3159     case RPC_FC_EMBEDDED_COMPLEX:
3160       size += pFormat[1];
3161       pFormat += 2;
3162       desc = pFormat + *(const SHORT*)pFormat;
3163       size += EmbeddedComplexMemorySize(pStubMsg, desc);
3164       pFormat += 2;
3165       continue;
3166     case RPC_FC_PAD:
3167       break;
3168     default:
3169       FIXME("unhandled format 0x%02x\n", *pFormat);
3170     }
3171     pFormat++;
3172   }
3173 
3174   return size;
3175 }
3176 
3177 unsigned long ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,
3178                                 PFORMAT_STRING pFormat)
3179 {
3180   PFORMAT_STRING desc;
3181   unsigned long size = 0;
3182 
3183   while (*pFormat != RPC_FC_END) {
3184     switch (*pFormat) {
3185     case RPC_FC_BYTE:
3186     case RPC_FC_CHAR:
3187     case RPC_FC_SMALL:
3188     case RPC_FC_USMALL:
3189       size += 1;
3190       break;
3191     case RPC_FC_WCHAR:
3192     case RPC_FC_SHORT:
3193     case RPC_FC_USHORT:
3194       size += 2;
3195       break;
3196     case RPC_FC_LONG:
3197     case RPC_FC_ULONG:
3198     case RPC_FC_ENUM16:
3199     case RPC_FC_ENUM32:
3200       size += 4;
3201       break;
3202     case RPC_FC_HYPER:
3203       size += 8;
3204       break;
3205     case RPC_FC_POINTER:
3206       size += sizeof(void *);
3207       break;
3208     case RPC_FC_ALIGNM4:
3209       ALIGN_LENGTH(size, 4);
3210       break;
3211     case RPC_FC_ALIGNM8:
3212       ALIGN_LENGTH(size, 8);
3213       break;
3214     case RPC_FC_STRUCTPAD1:
3215     case RPC_FC_STRUCTPAD2:
3216     case RPC_FC_STRUCTPAD3:
3217     case RPC_FC_STRUCTPAD4:
3218     case RPC_FC_STRUCTPAD5:
3219     case RPC_FC_STRUCTPAD6:
3220     case RPC_FC_STRUCTPAD7:
3221       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3222       break;
3223     case RPC_FC_EMBEDDED_COMPLEX:
3224       size += pFormat[1];
3225       pFormat += 2;
3226       desc = pFormat + *(const SHORT*)pFormat;
3227       size += EmbeddedComplexSize(pStubMsg, desc);
3228       pFormat += 2;
3229       continue;
3230     case RPC_FC_PAD:
3231       break;
3232     default:
3233       FIXME("unhandled format 0x%02x\n", *pFormat);
3234     }
3235     pFormat++;
3236   }
3237 
3238   return size;
3239 }
3240 
3241 /***********************************************************************
3242  *           NdrComplexStructMarshall [RPCRT4.@]
3243  */
3244 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3245                                                 unsigned char *pMemory,
3246                                                 PFORMAT_STRING pFormat)
3247 {
3248   PFORMAT_STRING conf_array = NULL;
3249   PFORMAT_STRING pointer_desc = NULL;
3250   unsigned char *OldMemory = pStubMsg->Memory;
3251   int pointer_buffer_mark_set = 0;
3252   ULONG count = 0;
3253   ULONG max_count = 0;
3254   ULONG offset = 0;
3255 
3256   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3257 
3258   if (!pStubMsg->PointerBufferMark)
3259   {
3260     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3261     /* save buffer length */
3262     unsigned long saved_buffer_length = pStubMsg->BufferLength;
3263 
3264     /* get the buffer pointer after complex array data, but before
3265      * pointer data */
3266     pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
3267     pStubMsg->IgnoreEmbeddedPointers = 1;
3268     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3269     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3270 
3271     /* save it for use by embedded pointer code later */
3272     pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
3273     TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
3274     pointer_buffer_mark_set = 1;
3275 
3276     /* restore the original buffer length */
3277     pStubMsg->BufferLength = saved_buffer_length;
3278   }
3279 
3280   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
3281 
3282   pFormat += 4;
3283   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3284   pFormat += 2;
3285   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3286   pFormat += 2;
3287 
3288   pStubMsg->Memory = pMemory;
3289 
3290   if (conf_array)
3291   {
3292     unsigned long struct_size = ComplexStructSize(pStubMsg, pFormat);
3293     array_compute_and_write_conformance(conf_array[0], pStubMsg,
3294                                         pMemory + struct_size, conf_array);
3295     /* these could be changed in ComplexMarshall so save them for later */
3296     max_count = pStubMsg->MaxCount;
3297     count = pStubMsg->ActualCount;
3298     offset = pStubMsg->Offset;
3299   }
3300 
3301   pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3302 
3303   if (conf_array)
3304   {
3305     pStubMsg->MaxCount = max_count;
3306     pStubMsg->ActualCount = count;
3307     pStubMsg->Offset = offset;
3308     array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3309                                       conf_array, TRUE /* fHasPointers */);
3310   }
3311 
3312   pStubMsg->Memory = OldMemory;
3313 
3314   if (pointer_buffer_mark_set)
3315   {
3316     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3317     pStubMsg->PointerBufferMark = NULL;
3318   }
3319 
3320   STD_OVERFLOW_CHECK(pStubMsg);
3321 
3322   return NULL;
3323 }
3324 
3325 /***********************************************************************
3326  *           NdrComplexStructUnmarshall [RPCRT4.@]
3327  */
3328 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3329                                                   unsigned char **ppMemory,
3330                                                   PFORMAT_STRING pFormat,
3331                                                   unsigned char fMustAlloc)
3332 {
3333   unsigned size = *(const WORD*)(pFormat+2);
3334   PFORMAT_STRING conf_array = NULL;
3335   PFORMAT_STRING pointer_desc = NULL;
3336   unsigned char *pMemory;
3337   int pointer_buffer_mark_set = 0;
3338   ULONG count = 0;
3339   ULONG max_count = 0;
3340   ULONG offset = 0;
3341   ULONG array_size = 0;
3342 
3343   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3344 
3345   if (!pStubMsg->PointerBufferMark)
3346   {
3347     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3348     /* save buffer pointer */
3349     unsigned char *saved_buffer = pStubMsg->Buffer;
3350 
3351     /* get the buffer pointer after complex array data, but before
3352      * pointer data */
3353     pStubMsg->IgnoreEmbeddedPointers = 1;
3354     NdrComplexStructMemorySize(pStubMsg, pFormat);
3355     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3356 
3357     /* save it for use by embedded pointer code later */
3358     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3359     TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
3360     pointer_buffer_mark_set = 1;
3361 
3362     /* restore the original buffer */
3363     pStubMsg->Buffer = saved_buffer;
3364   }
3365 
3366   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3367 
3368   pFormat += 4;
3369   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3370   pFormat += 2;
3371   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3372   pFormat += 2;
3373 
3374   if (conf_array)
3375   {
3376     array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3377     size += array_size;
3378 
3379     /* these could be changed in ComplexMarshall so save them for later */
3380     max_count = pStubMsg->MaxCount;
3381     count = pStubMsg->ActualCount;
3382     offset = pStubMsg->Offset;
3383   }
3384 
3385   if (fMustAlloc || !*ppMemory)
3386     *ppMemory = NdrAllocate(pStubMsg, size);
3387 
3388   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3389 
3390   if (conf_array)
3391   {
3392     pStubMsg->MaxCount = max_count;
3393     pStubMsg->ActualCount = count;
3394     pStubMsg->Offset = offset;
3395     if (fMustAlloc)
3396       memset(pMemory, 0, array_size);
3397     array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3398                                        conf_array, FALSE,
3399                                        FALSE /* fUseBufferMemoryServer */,
3400                                        TRUE /* fUnmarshall */);
3401   }
3402 
3403   if (pointer_buffer_mark_set)
3404   {
3405     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3406     pStubMsg->PointerBufferMark = NULL;
3407   }
3408 
3409   return NULL;
3410 }
3411 
3412 /***********************************************************************
3413  *           NdrComplexStructBufferSize [RPCRT4.@]
3414  */
3415 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3416                                        unsigned char *pMemory,
3417                                        PFORMAT_STRING pFormat)
3418 {
3419   PFORMAT_STRING conf_array = NULL;
3420   PFORMAT_STRING pointer_desc = NULL;
3421   unsigned char *OldMemory = pStubMsg->Memory;
3422   int pointer_length_set = 0;
3423   ULONG count = 0;
3424   ULONG max_count = 0;
3425   ULONG offset = 0;
3426 
3427   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3428 
3429   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
3430 
3431   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3432   {
3433     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3434     unsigned long saved_buffer_length = pStubMsg->BufferLength;
3435 
3436     /* get the buffer length after complex struct data, but before
3437      * pointer data */
3438     pStubMsg->IgnoreEmbeddedPointers = 1;
3439     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3440     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3441 
3442     /* save it for use by embedded pointer code later */
3443     pStubMsg->PointerLength = pStubMsg->BufferLength;
3444     pointer_length_set = 1;
3445     TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
3446 
3447     /* restore the original buffer length */
3448     pStubMsg->BufferLength = saved_buffer_length;
3449   }
3450 
3451   pFormat += 4;
3452   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3453   pFormat += 2;
3454   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3455   pFormat += 2;
3456 
3457   pStubMsg->Memory = pMemory;
3458 
3459   if (conf_array)
3460   {
3461     unsigned long struct_size = ComplexStructSize(pStubMsg, pFormat);
3462     array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3463                                        conf_array);
3464 
3465     /* these could be changed in ComplexMarshall so save them for later */
3466     max_count = pStubMsg->MaxCount;
3467     count = pStubMsg->ActualCount;
3468     offset = pStubMsg->Offset;
3469   }
3470 
3471   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3472 
3473   if (conf_array)
3474   {
3475     pStubMsg->MaxCount = max_count;
3476     pStubMsg->ActualCount = count;
3477     pStubMsg->Offset = offset;
3478     array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3479                       TRUE /* fHasPointers */);
3480   }
3481 
3482   pStubMsg->Memory = OldMemory;
3483 
3484   if(pointer_length_set)
3485   {
3486     pStubMsg->BufferLength = pStubMsg->PointerLength;
3487     pStubMsg->PointerLength = 0;
3488   }
3489 
3490 }
3491 
3492 /***********************************************************************
3493  *           NdrComplexStructMemorySize [RPCRT4.@]
3494  */
3495 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3496                                         PFORMAT_STRING pFormat)
3497 {
3498   unsigned size = *(const WORD*)(pFormat+2);
3499   PFORMAT_STRING conf_array = NULL;
3500   PFORMAT_STRING pointer_desc = NULL;
3501   ULONG count = 0;
3502   ULONG max_count = 0;
3503   ULONG offset = 0;
3504 
3505   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3506 
3507   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3508 
3509   pFormat += 4;
3510   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3511   pFormat += 2;
3512   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3513   pFormat += 2;
3514 
3515   if (conf_array)
3516   {
3517     array_read_conformance(conf_array[0], pStubMsg, conf_array);
3518 
3519     /* these could be changed in ComplexStructMemorySize so save them for
3520      * later */
3521     max_count = pStubMsg->MaxCount;
3522     count = pStubMsg->ActualCount;
3523     offset = pStubMsg->Offset;
3524   }
3525 
3526   ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3527 
3528   if (conf_array)
3529   {
3530     pStubMsg->MaxCount = max_count;
3531     pStubMsg->ActualCount = count;
3532     pStubMsg->Offset = offset;
3533     array_memory_size(conf_array[0], pStubMsg, conf_array,
3534                       TRUE /* fHasPointers */);
3535   }
3536 
3537   return size;
3538 }
3539 
3540 /***********************************************************************
3541  *           NdrComplexStructFree [RPCRT4.@]
3542  */
3543 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3544                                  unsigned char *pMemory,
3545                                  PFORMAT_STRING pFormat)
3546 {
3547   PFORMAT_STRING conf_array = NULL;
3548   PFORMAT_STRING pointer_desc = NULL;
3549   unsigned char *OldMemory = pStubMsg->Memory;
3550 
3551   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3552 
3553   pFormat += 4;
3554   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3555   pFormat += 2;
3556   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3557   pFormat += 2;
3558 
3559   pStubMsg->Memory = pMemory;
3560 
3561   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3562 
3563   if (conf_array)
3564     array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3565                TRUE /* fHasPointers */);
3566 
3567   pStubMsg->Memory = OldMemory;
3568 }
3569 
3570 /***********************************************************************
3571  *           NdrConformantArrayMarshall [RPCRT4.@]
3572  */
3573 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3574                                                   unsigned char *pMemory,
3575                                                   PFORMAT_STRING pFormat)
3576 {
3577   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3578   if (pFormat[0] != RPC_FC_CARRAY)
3579   {
3580     ERR("invalid format = 0x%x\n", pFormat[0]);
3581     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3582   }
3583 
3584   array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
3585                                       pFormat);
3586   array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3587                                     TRUE /* fHasPointers */);
3588 
3589   return NULL;
3590 }
3591 
3592 /***********************************************************************
3593  *           NdrConformantArrayUnmarshall [RPCRT4.@]
3594  */
3595 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3596                                                     unsigned char **ppMemory,
3597                                                     PFORMAT_STRING pFormat,
3598                                                     unsigned char fMustAlloc)
3599 {
3600   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3601   if (pFormat[0] != RPC_FC_CARRAY)
3602   {
3603     ERR("invalid format = 0x%x\n", pFormat[0]);
3604     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3605   }
3606 
3607   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3608   array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
3609                                      fMustAlloc,
3610                                      TRUE /* fUseBufferMemoryServer */,
3611                                      TRUE /* fUnmarshall */);
3612 
3613   return NULL;
3614 }
3615 
3616 /***********************************************************************
3617  *           NdrConformantArrayBufferSize [RPCRT4.@]
3618  */
3619 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3620                                          unsigned char *pMemory,
3621                                          PFORMAT_STRING pFormat)
3622 {
3623   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3624   if (pFormat[0] != RPC_FC_CARRAY)