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