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