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

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

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

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