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