mciwave: Fix wave format first, then compute position.
[wine] / dlls / rpcrt4 / ndr_marshall.c
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 #define NONAMELESSUNION
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winerror.h"
39
40 #include "ndr_misc.h"
41 #include "rpcndr.h"
42
43 #include "wine/unicode.h"
44 #include "wine/rpcfc.h"
45
46 #include "wine/debug.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(ole);
49
50 #if defined(__i386__)
51 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
52     (*((UINT32 *)(pchar)) = (uint32))
53
54 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
55     (*((UINT32 *)(pchar)))
56 #else
57   /* these would work for i386 too, but less efficient */
58 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
59     (*(pchar)     = LOBYTE(LOWORD(uint32)), \
60      *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
61      *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
62      *((pchar)+3) = HIBYTE(HIWORD(uint32)))
63
64 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
65     (MAKELONG( \
66       MAKEWORD(*(pchar), *((pchar)+1)), \
67       MAKEWORD(*((pchar)+2), *((pchar)+3))))
68 #endif
69
70 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
71   (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
72    *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
73    *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
74    *(pchar)     = HIBYTE(HIWORD(uint32)))
75
76 #define BIG_ENDIAN_UINT32_READ(pchar) \
77   (MAKELONG( \
78     MAKEWORD(*((pchar)+3), *((pchar)+2)), \
79     MAKEWORD(*((pchar)+1), *(pchar))))
80
81 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
82 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
83     BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
84 # define NDR_LOCAL_UINT32_READ(pchar) \
85     BIG_ENDIAN_UINT32_READ(pchar)
86 #else
87 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
88     LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
89 # define NDR_LOCAL_UINT32_READ(pchar) \
90     LITTLE_ENDIAN_UINT32_READ(pchar)
91 #endif
92
93 /* _Align must be the desired alignment,
94  * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
95 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
96 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
97 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
98 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
99 #define ALIGN_POINTER_CLEAR(_Ptr, _Align) \
100     do { \
101         memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \
102         ALIGN_POINTER(_Ptr, _Align); \
103     } while(0)
104
105 #define STD_OVERFLOW_CHECK(_Msg) do { \
106     TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
107     if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
108         ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
109   } while (0)
110
111 #define NDR_POINTER_ID_BASE 0x20000
112 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
113 #define NDR_TABLE_SIZE 128
114 #define NDR_TABLE_MASK 127
115
116 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
117 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
118 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
119 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
120 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
121
122 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
123 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
124 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
125
126 static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
127 static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
128 static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
129 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
130
131 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
132
133 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
134   0,
135   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
136   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
137   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
138   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
139   /* 0x10 */
140   NdrBaseTypeMarshall,
141   /* 0x11 */
142   NdrPointerMarshall, NdrPointerMarshall,
143   NdrPointerMarshall, NdrPointerMarshall,
144   /* 0x15 */
145   NdrSimpleStructMarshall, NdrSimpleStructMarshall,
146   NdrConformantStructMarshall, NdrConformantStructMarshall,
147   NdrConformantVaryingStructMarshall,
148   NdrComplexStructMarshall,
149   /* 0x1b */
150   NdrConformantArrayMarshall, 
151   NdrConformantVaryingArrayMarshall,
152   NdrFixedArrayMarshall, NdrFixedArrayMarshall,
153   NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
154   NdrComplexArrayMarshall,
155   /* 0x22 */
156   NdrConformantStringMarshall, 0, 0,
157   NdrConformantStringMarshall,
158   NdrNonConformantStringMarshall, 0, 0, 0,
159   /* 0x2a */
160   NdrEncapsulatedUnionMarshall,
161   NdrNonEncapsulatedUnionMarshall,
162   NdrByteCountPointerMarshall,
163   NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
164   /* 0x2f */
165   NdrInterfacePointerMarshall,
166   /* 0x30 */
167   NdrContextHandleMarshall,
168   /* 0xb1 */
169   0, 0, 0,
170   NdrUserMarshalMarshall,
171   0, 0,
172   /* 0xb7 */
173   NdrRangeMarshall
174 };
175 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
176   0,
177   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
178   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
179   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
180   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
181   /* 0x10 */
182   NdrBaseTypeUnmarshall,
183   /* 0x11 */
184   NdrPointerUnmarshall, NdrPointerUnmarshall,
185   NdrPointerUnmarshall, NdrPointerUnmarshall,
186   /* 0x15 */
187   NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
188   NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
189   NdrConformantVaryingStructUnmarshall,
190   NdrComplexStructUnmarshall,
191   /* 0x1b */
192   NdrConformantArrayUnmarshall, 
193   NdrConformantVaryingArrayUnmarshall,
194   NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
195   NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
196   NdrComplexArrayUnmarshall,
197   /* 0x22 */
198   NdrConformantStringUnmarshall, 0, 0,
199   NdrConformantStringUnmarshall,
200   NdrNonConformantStringUnmarshall, 0, 0, 0,
201   /* 0x2a */
202   NdrEncapsulatedUnionUnmarshall,
203   NdrNonEncapsulatedUnionUnmarshall,
204   NdrByteCountPointerUnmarshall,
205   NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
206   /* 0x2f */
207   NdrInterfacePointerUnmarshall,
208   /* 0x30 */
209   NdrContextHandleUnmarshall,
210   /* 0xb1 */
211   0, 0, 0,
212   NdrUserMarshalUnmarshall,
213   0, 0,
214   /* 0xb7 */
215   NdrRangeUnmarshall
216 };
217 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
218   0,
219   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
220   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
221   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
222   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
223   /* 0x10 */
224   NdrBaseTypeBufferSize,
225   /* 0x11 */
226   NdrPointerBufferSize, NdrPointerBufferSize,
227   NdrPointerBufferSize, NdrPointerBufferSize,
228   /* 0x15 */
229   NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
230   NdrConformantStructBufferSize, NdrConformantStructBufferSize,
231   NdrConformantVaryingStructBufferSize,
232   NdrComplexStructBufferSize,
233   /* 0x1b */
234   NdrConformantArrayBufferSize, 
235   NdrConformantVaryingArrayBufferSize,
236   NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
237   NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
238   NdrComplexArrayBufferSize,
239   /* 0x22 */
240   NdrConformantStringBufferSize, 0, 0,
241   NdrConformantStringBufferSize,
242   NdrNonConformantStringBufferSize, 0, 0, 0,
243   /* 0x2a */
244   NdrEncapsulatedUnionBufferSize,
245   NdrNonEncapsulatedUnionBufferSize,
246   NdrByteCountPointerBufferSize,
247   NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
248   /* 0x2f */
249   NdrInterfacePointerBufferSize,
250   /* 0x30 */
251   NdrContextHandleBufferSize,
252   /* 0xb1 */
253   0, 0, 0,
254   NdrUserMarshalBufferSize,
255   0, 0,
256   /* 0xb7 */
257   NdrRangeBufferSize
258 };
259 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
260   0,
261   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
262   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
263   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
264   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
265   /* 0x10 */
266   NdrBaseTypeMemorySize,
267   /* 0x11 */
268   NdrPointerMemorySize, NdrPointerMemorySize,
269   NdrPointerMemorySize, NdrPointerMemorySize,
270   /* 0x15 */
271   NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
272   NdrConformantStructMemorySize, NdrConformantStructMemorySize,
273   NdrConformantVaryingStructMemorySize,
274   NdrComplexStructMemorySize,
275   /* 0x1b */
276   NdrConformantArrayMemorySize,
277   NdrConformantVaryingArrayMemorySize,
278   NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
279   NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
280   NdrComplexArrayMemorySize,
281   /* 0x22 */
282   NdrConformantStringMemorySize, 0, 0,
283   NdrConformantStringMemorySize,
284   NdrNonConformantStringMemorySize, 0, 0, 0,
285   /* 0x2a */
286   NdrEncapsulatedUnionMemorySize,
287   NdrNonEncapsulatedUnionMemorySize,
288   NdrByteCountPointerMemorySize,
289   NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
290   /* 0x2f */
291   NdrInterfacePointerMemorySize,
292   /* 0x30 */
293   0,
294   /* 0xb1 */
295   0, 0, 0,
296   NdrUserMarshalMemorySize,
297   0, 0,
298   /* 0xb7 */
299   NdrRangeMemorySize
300 };
301 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
302   0,
303   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
304   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
305   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
306   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
307   /* 0x10 */
308   NdrBaseTypeFree,
309   /* 0x11 */
310   NdrPointerFree, NdrPointerFree,
311   NdrPointerFree, NdrPointerFree,
312   /* 0x15 */
313   NdrSimpleStructFree, NdrSimpleStructFree,
314   NdrConformantStructFree, NdrConformantStructFree,
315   NdrConformantVaryingStructFree,
316   NdrComplexStructFree,
317   /* 0x1b */
318   NdrConformantArrayFree, 
319   NdrConformantVaryingArrayFree,
320   NdrFixedArrayFree, NdrFixedArrayFree,
321   NdrVaryingArrayFree, NdrVaryingArrayFree,
322   NdrComplexArrayFree,
323   /* 0x22 */
324   0, 0, 0,
325   0, 0, 0, 0, 0,
326   /* 0x2a */
327   NdrEncapsulatedUnionFree,
328   NdrNonEncapsulatedUnionFree,
329   0,
330   NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
331   /* 0x2f */
332   NdrInterfacePointerFree,
333   /* 0x30 */
334   0,
335   /* 0xb1 */
336   0, 0, 0,
337   NdrUserMarshalFree,
338   0, 0,
339   /* 0xb7 */
340   NdrRangeFree
341 };
342
343 typedef struct _NDR_MEMORY_LIST
344 {
345     ULONG magic;
346     ULONG size;
347     ULONG reserved;
348     struct _NDR_MEMORY_LIST *next;
349 } NDR_MEMORY_LIST;
350
351 #define MEML_MAGIC  ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
352
353 /***********************************************************************
354  *            NdrAllocate [RPCRT4.@]
355  *
356  * Allocates a block of memory using pStubMsg->pfnAllocate.
357  *
358  * PARAMS
359  *  pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
360  *  len      [I]   Size of memory block to allocate.
361  *
362  * RETURNS
363  *  The memory block of size len that was allocated.
364  *
365  * NOTES
366  *  The memory block is always 8-byte aligned.
367  *  If the function is unable to allocate memory an ERROR_OUTOFMEMORY
368  *  exception is raised.
369  */
370 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len)
371 {
372     SIZE_T aligned_len;
373     SIZE_T adjusted_len;
374     void *p;
375     NDR_MEMORY_LIST *mem_list;
376
377     aligned_len = ALIGNED_LENGTH(len, 8);
378     adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
379     /* check for overflow */
380     if (adjusted_len < len)
381     {
382         ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len);
383         RpcRaiseException(RPC_X_BAD_STUB_DATA);
384     }
385
386     p = pStubMsg->pfnAllocate(adjusted_len);
387     if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
388
389     mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
390     mem_list->magic = MEML_MAGIC;
391     mem_list->size = aligned_len;
392     mem_list->reserved = 0;
393     mem_list->next = pStubMsg->pMemoryList;
394     pStubMsg->pMemoryList = mem_list;
395
396     TRACE("-- %p\n", p);
397     return p;
398 }
399
400 static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
401 {
402     TRACE("(%p, %p)\n", pStubMsg, Pointer);
403
404     pStubMsg->pfnFree(Pointer);
405 }
406
407 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
408 {
409     return (*(const ULONG *)pFormat != -1);
410 }
411
412 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
413 {
414   ALIGN_POINTER(pStubMsg->Buffer, 4);
415   if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
416       RpcRaiseException(RPC_X_BAD_STUB_DATA);
417   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
418   pStubMsg->Buffer += 4;
419   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
420   if (pStubMsg->fHasNewCorrDesc)
421     return pFormat+6;
422   else
423     return pFormat+4;
424 }
425
426 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
427 {
428   if (pFormat && !IsConformanceOrVariancePresent(pFormat))
429   {
430     pStubMsg->Offset = 0;
431     pStubMsg->ActualCount = pStubMsg->MaxCount;
432     goto done;
433   }
434
435   ALIGN_POINTER(pStubMsg->Buffer, 4);
436   if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
437     RpcRaiseException(RPC_X_BAD_STUB_DATA);
438   pStubMsg->Offset      = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
439   pStubMsg->Buffer += 4;
440   TRACE("offset is %d\n", pStubMsg->Offset);
441   pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
442   pStubMsg->Buffer += 4;
443   TRACE("variance is %d\n", pStubMsg->ActualCount);
444
445   if ((pStubMsg->ActualCount > MaxValue) ||
446       (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
447   {
448     ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
449         pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
450     RpcRaiseException(RPC_S_INVALID_BOUND);
451     return NULL;
452   }
453
454 done:
455   if (pStubMsg->fHasNewCorrDesc)
456     return pFormat+6;
457   else
458     return pFormat+4;
459 }
460
461 /* writes the conformance value to the buffer */
462 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
463 {
464     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
465     if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
466         RpcRaiseException(RPC_X_BAD_STUB_DATA);
467     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
468     pStubMsg->Buffer += 4;
469 }
470
471 /* writes the variance values to the buffer */
472 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
473 {
474     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
475     if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
476         RpcRaiseException(RPC_X_BAD_STUB_DATA);
477     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
478     pStubMsg->Buffer += 4;
479     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
480     pStubMsg->Buffer += 4;
481 }
482
483 /* requests buffer space for the conformance value */
484 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
485 {
486     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
487     if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
488         RpcRaiseException(RPC_X_BAD_STUB_DATA);
489     pStubMsg->BufferLength += 4;
490 }
491
492 /* requests buffer space for the variance values */
493 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
494 {
495     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
496     if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
497         RpcRaiseException(RPC_X_BAD_STUB_DATA);
498     pStubMsg->BufferLength += 8;
499 }
500
501 PFORMAT_STRING ComputeConformanceOrVariance(
502     MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
503     PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
504 {
505   BYTE dtype = pFormat[0] & 0xf;
506   short ofs = *(const short *)&pFormat[2];
507   LPVOID ptr = NULL;
508   DWORD data = 0;
509
510   if (!IsConformanceOrVariancePresent(pFormat)) {
511     /* null descriptor */
512     *pCount = def;
513     goto finish_conf;
514   }
515
516   switch (pFormat[0] & 0xf0) {
517   case RPC_FC_NORMAL_CONFORMANCE:
518     TRACE("normal conformance, ofs=%d\n", ofs);
519     ptr = pMemory;
520     break;
521   case RPC_FC_POINTER_CONFORMANCE:
522     TRACE("pointer conformance, ofs=%d\n", ofs);
523     ptr = pStubMsg->Memory;
524     break;
525   case RPC_FC_TOP_LEVEL_CONFORMANCE:
526     TRACE("toplevel conformance, ofs=%d\n", ofs);
527     if (pStubMsg->StackTop) {
528       ptr = pStubMsg->StackTop;
529     }
530     else {
531       /* -Os mode, *pCount is already set */
532       goto finish_conf;
533     }
534     break;
535   case RPC_FC_CONSTANT_CONFORMANCE:
536     data = ofs | ((DWORD)pFormat[1] << 16);
537     TRACE("constant conformance, val=%d\n", data);
538     *pCount = data;
539     goto finish_conf;
540   case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
541     FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
542     if (pStubMsg->StackTop) {
543       ptr = pStubMsg->StackTop;
544     }
545     else {
546       /* ? */
547       goto done_conf_grab;
548     }
549     break;
550   default:
551     FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
552   }
553
554   switch (pFormat[1]) {
555   case RPC_FC_DEREFERENCE:
556     ptr = *(LPVOID*)((char *)ptr + ofs);
557     break;
558   case RPC_FC_CALLBACK:
559   {
560     unsigned char *old_stack_top = pStubMsg->StackTop;
561     pStubMsg->StackTop = ptr;
562
563     /* ofs is index into StubDesc->apfnExprEval */
564     TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
565     pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
566
567     pStubMsg->StackTop = old_stack_top;
568
569     /* the callback function always stores the computed value in MaxCount */
570     *pCount = pStubMsg->MaxCount;
571     goto finish_conf;
572   }
573   default:
574     ptr = (char *)ptr + ofs;
575     break;
576   }
577
578   switch (dtype) {
579   case RPC_FC_LONG:
580   case RPC_FC_ULONG:
581     data = *(DWORD*)ptr;
582     break;
583   case RPC_FC_SHORT:
584     data = *(SHORT*)ptr;
585     break;
586   case RPC_FC_USHORT:
587     data = *(USHORT*)ptr;
588     break;
589   case RPC_FC_CHAR:
590   case RPC_FC_SMALL:
591     data = *(CHAR*)ptr;
592     break;
593   case RPC_FC_BYTE:
594   case RPC_FC_USMALL:
595     data = *(UCHAR*)ptr;
596     break;
597   default:
598     FIXME("unknown conformance data type %x\n", dtype);
599     goto done_conf_grab;
600   }
601   TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
602
603 done_conf_grab:
604   switch (pFormat[1]) {
605   case RPC_FC_DEREFERENCE: /* already handled */
606   case 0: /* no op */
607     *pCount = data;
608     break;
609   case RPC_FC_ADD_1:
610     *pCount = data + 1;
611     break;
612   case RPC_FC_SUB_1:
613     *pCount = data - 1;
614     break;
615   case RPC_FC_MULT_2:
616     *pCount = data * 2;
617     break;
618   case RPC_FC_DIV_2:
619     *pCount = data / 2;
620     break;
621   default:
622     FIXME("unknown conformance op %d\n", pFormat[1]);
623     goto finish_conf;
624   }
625
626 finish_conf:
627   TRACE("resulting conformance is %ld\n", *pCount);
628   if (pStubMsg->fHasNewCorrDesc)
629     return pFormat+6;
630   else
631     return pFormat+4;
632 }
633
634 static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg,
635                                              PFORMAT_STRING pFormat)
636 {
637   if (IsConformanceOrVariancePresent(pFormat))
638   {
639     if (pStubMsg->fHasNewCorrDesc)
640       pFormat += 6;
641     else
642       pFormat += 4;
643   }
644   return pFormat;
645 }
646
647 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
648  * the result overflows 32-bits */
649 static inline ULONG safe_multiply(ULONG a, ULONG b)
650 {
651     ULONGLONG ret = (ULONGLONG)a * b;
652     if (ret > 0xffffffff)
653     {
654         RpcRaiseException(RPC_S_INVALID_BOUND);
655         return 0;
656     }
657     return ret;
658 }
659
660 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
661 {
662     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
663         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
664         RpcRaiseException(RPC_X_BAD_STUB_DATA);
665     pStubMsg->Buffer += size;
666 }
667
668 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
669 {
670     if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
671     {
672         ERR("buffer length overflow - BufferLength = %u, size = %u\n",
673             pStubMsg->BufferLength, size);
674         RpcRaiseException(RPC_X_BAD_STUB_DATA);
675     }
676     pStubMsg->BufferLength += size;
677 }
678
679 /* copies data from the buffer, checking that there is enough data in the buffer
680  * to do so */
681 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
682 {
683     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
684         (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
685     {
686         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
687             pStubMsg->Buffer, pStubMsg->BufferEnd, size);
688         RpcRaiseException(RPC_X_BAD_STUB_DATA);
689     }
690     if (p == pStubMsg->Buffer)
691         ERR("pointer is the same as the buffer\n");
692     memcpy(p, pStubMsg->Buffer, size);
693     pStubMsg->Buffer += size;
694 }
695
696 /* copies data to the buffer, checking that there is enough space to do so */
697 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
698 {
699     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
700         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
701     {
702         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
703             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
704             size);
705         RpcRaiseException(RPC_X_BAD_STUB_DATA);
706     }
707     memcpy(pStubMsg->Buffer, p, size);
708     pStubMsg->Buffer += size;
709 }
710
711 /* verify that string data sitting in the buffer is valid and safe to
712  * unmarshall */
713 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
714 {
715     ULONG i;
716
717     /* verify the buffer is safe to access */
718     if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
719         (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
720     {
721         ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
722             pStubMsg->BufferEnd, pStubMsg->Buffer);
723         RpcRaiseException(RPC_X_BAD_STUB_DATA);
724     }
725
726     /* strings must always have null terminating bytes */
727     if (bufsize < esize)
728     {
729         ERR("invalid string length of %d\n", bufsize / esize);
730         RpcRaiseException(RPC_S_INVALID_BOUND);
731     }
732
733     for (i = bufsize - esize; i < bufsize; i++)
734         if (pStubMsg->Buffer[i] != 0)
735         {
736             ERR("string not null-terminated at byte position %d, data is 0x%x\n",
737                 i, pStubMsg->Buffer[i]);
738             RpcRaiseException(RPC_S_INVALID_BOUND);
739         }
740 }
741
742 static inline void dump_pointer_attr(unsigned char attr)
743 {
744     if (attr & RPC_FC_P_ALLOCALLNODES)
745         TRACE(" RPC_FC_P_ALLOCALLNODES");
746     if (attr & RPC_FC_P_DONTFREE)
747         TRACE(" RPC_FC_P_DONTFREE");
748     if (attr & RPC_FC_P_ONSTACK)
749         TRACE(" RPC_FC_P_ONSTACK");
750     if (attr & RPC_FC_P_SIMPLEPOINTER)
751         TRACE(" RPC_FC_P_SIMPLEPOINTER");
752     if (attr & RPC_FC_P_DEREF)
753         TRACE(" RPC_FC_P_DEREF");
754     TRACE("\n");
755 }
756
757 /***********************************************************************
758  *           PointerMarshall [internal]
759  */
760 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
761                             unsigned char *Buffer,
762                             unsigned char *Pointer,
763                             PFORMAT_STRING pFormat)
764 {
765   unsigned type = pFormat[0], attr = pFormat[1];
766   PFORMAT_STRING desc;
767   NDR_MARSHALL m;
768   ULONG pointer_id;
769   int pointer_needs_marshaling;
770
771   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
772   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
773   pFormat += 2;
774   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
775   else desc = pFormat + *(const SHORT*)pFormat;
776
777   switch (type) {
778   case RPC_FC_RP: /* ref pointer (always non-null) */
779     if (!Pointer)
780     {
781       ERR("NULL ref pointer is not allowed\n");
782       RpcRaiseException(RPC_X_NULL_REF_POINTER);
783     }
784     pointer_needs_marshaling = 1;
785     break;
786   case RPC_FC_UP: /* unique pointer */
787   case RPC_FC_OP: /* object pointer - same as unique here */
788     if (Pointer)
789       pointer_needs_marshaling = 1;
790     else
791       pointer_needs_marshaling = 0;
792     pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
793     TRACE("writing 0x%08x to buffer\n", pointer_id);
794     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
795     break;
796   case RPC_FC_FP:
797     pointer_needs_marshaling = !NdrFullPointerQueryPointer(
798       pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
799     TRACE("writing 0x%08x to buffer\n", pointer_id);
800     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
801     break;
802   default:
803     FIXME("unhandled ptr type=%02x\n", type);
804     RpcRaiseException(RPC_X_BAD_STUB_DATA);
805     return;
806   }
807
808   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
809
810   if (pointer_needs_marshaling) {
811     if (attr & RPC_FC_P_DEREF) {
812       Pointer = *(unsigned char**)Pointer;
813       TRACE("deref => %p\n", Pointer);
814     }
815     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
816     if (m) m(pStubMsg, Pointer, desc);
817     else FIXME("no marshaller for data type=%02x\n", *desc);
818   }
819
820   STD_OVERFLOW_CHECK(pStubMsg);
821 }
822
823 /***********************************************************************
824  *           PointerUnmarshall [internal]
825  */
826 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
827                               unsigned char *Buffer,
828                               unsigned char **pPointer,
829                               unsigned char *pSrcPointer,
830                               PFORMAT_STRING pFormat,
831                               unsigned char fMustAlloc)
832 {
833   unsigned type = pFormat[0], attr = pFormat[1];
834   PFORMAT_STRING desc;
835   NDR_UNMARSHALL m;
836   DWORD pointer_id = 0;
837   int pointer_needs_unmarshaling;
838
839   TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
840   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
841   pFormat += 2;
842   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
843   else desc = pFormat + *(const SHORT*)pFormat;
844
845   switch (type) {
846   case RPC_FC_RP: /* ref pointer (always non-null) */
847     pointer_needs_unmarshaling = 1;
848     break;
849   case RPC_FC_UP: /* unique pointer */
850     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
851     TRACE("pointer_id is 0x%08x\n", pointer_id);
852     if (pointer_id)
853       pointer_needs_unmarshaling = 1;
854     else {
855       *pPointer = NULL;
856       pointer_needs_unmarshaling = 0;
857     }
858     break;
859   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
860     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
861     TRACE("pointer_id is 0x%08x\n", pointer_id);
862     if (!fMustAlloc && pSrcPointer)
863     {
864         FIXME("free object pointer %p\n", pSrcPointer);
865         fMustAlloc = TRUE;
866     }
867     if (pointer_id)
868       pointer_needs_unmarshaling = 1;
869     else
870     {
871       *pPointer = NULL;    
872       pointer_needs_unmarshaling = 0;
873     }
874     break;
875   case RPC_FC_FP:
876     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
877     TRACE("pointer_id is 0x%08x\n", pointer_id);
878     pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
879       pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
880     break;
881   default:
882     FIXME("unhandled ptr type=%02x\n", type);
883     RpcRaiseException(RPC_X_BAD_STUB_DATA);
884     return;
885   }
886
887   if (pointer_needs_unmarshaling) {
888     unsigned char *base_ptr_val = *pPointer;
889     unsigned char **current_ptr = pPointer;
890     if (pStubMsg->IsClient) {
891       TRACE("client\n");
892       /* if we aren't forcing allocation of memory then try to use the existing
893        * (source) pointer to unmarshall the data into so that [in,out]
894        * parameters behave correctly. it doesn't matter if the parameter is
895        * [out] only since in that case the pointer will be NULL. we force
896        * allocation when the source pointer is NULL here instead of in the type
897        * unmarshalling routine for the benefit of the deref code below */
898       if (!fMustAlloc) {
899         if (pSrcPointer) {
900           TRACE("setting *pPointer to %p\n", pSrcPointer);
901           *pPointer = base_ptr_val = pSrcPointer;
902         } else
903           fMustAlloc = TRUE;
904       }
905     } else {
906       TRACE("server\n");
907       /* the memory in a stub is never initialised, so we have to work out here
908        * whether we have to initialise it so we can use the optimisation of
909        * setting the pointer to the buffer, if possible, or set fMustAlloc to
910        * TRUE. */
911       if (attr & RPC_FC_P_DEREF) {
912         fMustAlloc = TRUE;
913       } else {
914         base_ptr_val = NULL;
915         *current_ptr = NULL;
916       }
917     }
918
919     if (attr & RPC_FC_P_ALLOCALLNODES)
920         FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
921
922     if (attr & RPC_FC_P_DEREF) {
923       if (fMustAlloc) {
924         base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
925         *pPointer = base_ptr_val;
926         current_ptr = (unsigned char **)base_ptr_val;
927       } else
928         current_ptr = *(unsigned char***)current_ptr;
929       TRACE("deref => %p\n", current_ptr);
930       if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
931     }
932     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
933     if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
934     else FIXME("no unmarshaller for data type=%02x\n", *desc);
935
936     if (type == RPC_FC_FP)
937       NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
938                                 base_ptr_val);
939   }
940
941   TRACE("pointer=%p\n", *pPointer);
942 }
943
944 /***********************************************************************
945  *           PointerBufferSize [internal]
946  */
947 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
948                               unsigned char *Pointer,
949                               PFORMAT_STRING pFormat)
950 {
951   unsigned type = pFormat[0], attr = pFormat[1];
952   PFORMAT_STRING desc;
953   NDR_BUFFERSIZE m;
954   int pointer_needs_sizing;
955   ULONG pointer_id;
956
957   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
958   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
959   pFormat += 2;
960   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
961   else desc = pFormat + *(const SHORT*)pFormat;
962
963   switch (type) {
964   case RPC_FC_RP: /* ref pointer (always non-null) */
965     if (!Pointer)
966     {
967       ERR("NULL ref pointer is not allowed\n");
968       RpcRaiseException(RPC_X_NULL_REF_POINTER);
969     }
970     break;
971   case RPC_FC_OP:
972   case RPC_FC_UP:
973     /* NULL pointer has no further representation */
974     if (!Pointer)
975         return;
976     break;
977   case RPC_FC_FP:
978     pointer_needs_sizing = !NdrFullPointerQueryPointer(
979       pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
980     if (!pointer_needs_sizing)
981       return;
982     break;
983   default:
984     FIXME("unhandled ptr type=%02x\n", type);
985     RpcRaiseException(RPC_X_BAD_STUB_DATA);
986     return;
987   }
988
989   if (attr & RPC_FC_P_DEREF) {
990     Pointer = *(unsigned char**)Pointer;
991     TRACE("deref => %p\n", Pointer);
992   }
993
994   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
995   if (m) m(pStubMsg, Pointer, desc);
996   else FIXME("no buffersizer for data type=%02x\n", *desc);
997 }
998
999 /***********************************************************************
1000  *           PointerMemorySize [internal]
1001  */
1002 static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1003                                unsigned char *Buffer, PFORMAT_STRING pFormat)
1004 {
1005   unsigned type = pFormat[0], attr = pFormat[1];
1006   PFORMAT_STRING desc;
1007   NDR_MEMORYSIZE m;
1008   DWORD pointer_id = 0;
1009   int pointer_needs_sizing;
1010
1011   TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1012   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1013   pFormat += 2;
1014   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1015   else desc = pFormat + *(const SHORT*)pFormat;
1016
1017   switch (type) {
1018   case RPC_FC_RP: /* ref pointer (always non-null) */
1019     pointer_needs_sizing = 1;
1020     break;
1021   case RPC_FC_UP: /* unique pointer */
1022   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1023     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1024     TRACE("pointer_id is 0x%08x\n", pointer_id);
1025     if (pointer_id)
1026       pointer_needs_sizing = 1;
1027     else
1028       pointer_needs_sizing = 0;
1029     break;
1030   case RPC_FC_FP:
1031   {
1032     void *pointer;
1033     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1034     TRACE("pointer_id is 0x%08x\n", pointer_id);
1035     pointer_needs_sizing = !NdrFullPointerQueryRefId(
1036       pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1037     break;
1038   }
1039   default:
1040     FIXME("unhandled ptr type=%02x\n", type);
1041     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1042     return 0;
1043   }
1044
1045   if (attr & RPC_FC_P_DEREF) {
1046     ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void*));
1047     pStubMsg->MemorySize += sizeof(void*);
1048     TRACE("deref\n");
1049   }
1050
1051   if (pointer_needs_sizing) {
1052     m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1053     if (m) m(pStubMsg, desc);
1054     else FIXME("no memorysizer for data type=%02x\n", *desc);
1055   }
1056
1057   return pStubMsg->MemorySize;
1058 }
1059
1060 /***********************************************************************
1061  *           PointerFree [internal]
1062  */
1063 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1064                         unsigned char *Pointer,
1065                         PFORMAT_STRING pFormat)
1066 {
1067   unsigned type = pFormat[0], attr = pFormat[1];
1068   PFORMAT_STRING desc;
1069   NDR_FREE m;
1070   unsigned char *current_pointer = Pointer;
1071
1072   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1073   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1074   if (attr & RPC_FC_P_DONTFREE) return;
1075   pFormat += 2;
1076   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1077   else desc = pFormat + *(const SHORT*)pFormat;
1078
1079   if (!Pointer) return;
1080
1081   if (type == RPC_FC_FP) {
1082     int pointer_needs_freeing = NdrFullPointerFree(
1083       pStubMsg->FullPtrXlatTables, Pointer);
1084     if (!pointer_needs_freeing)
1085       return;
1086   }
1087
1088   if (attr & RPC_FC_P_DEREF) {
1089     current_pointer = *(unsigned char**)Pointer;
1090     TRACE("deref => %p\n", current_pointer);
1091   }
1092
1093   m = NdrFreer[*desc & NDR_TABLE_MASK];
1094   if (m) m(pStubMsg, current_pointer, desc);
1095
1096   /* this check stops us from trying to free buffer memory. we don't have to
1097    * worry about clients, since they won't call this function.
1098    * we don't have to check for the buffer being reallocated because
1099    * BufferStart and BufferEnd won't be reset when allocating memory for
1100    * sending the response. we don't have to check for the new buffer here as
1101    * it won't be used a type memory, only for buffer memory */
1102   if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd)
1103       goto notfree;
1104
1105   if (attr & RPC_FC_P_ONSTACK) {
1106     TRACE("not freeing stack ptr %p\n", Pointer);
1107     return;
1108   }
1109   TRACE("freeing %p\n", Pointer);
1110   NdrFree(pStubMsg, Pointer);
1111   return;
1112 notfree:
1113   TRACE("not freeing %p\n", Pointer);
1114 }
1115
1116 /***********************************************************************
1117  *           EmbeddedPointerMarshall
1118  */
1119 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1120                                                unsigned char *pMemory,
1121                                                PFORMAT_STRING pFormat)
1122 {
1123   unsigned char *Mark = pStubMsg->BufferMark;
1124   unsigned rep, count, stride;
1125   unsigned i;
1126   unsigned char *saved_buffer = NULL;
1127
1128   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1129
1130   if (*pFormat != RPC_FC_PP) return NULL;
1131   pFormat += 2;
1132
1133   if (pStubMsg->PointerBufferMark)
1134   {
1135     saved_buffer = pStubMsg->Buffer;
1136     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1137     pStubMsg->PointerBufferMark = NULL;
1138   }
1139
1140   while (pFormat[0] != RPC_FC_END) {
1141     switch (pFormat[0]) {
1142     default:
1143       FIXME("unknown repeat type %d\n", pFormat[0]);
1144     case RPC_FC_NO_REPEAT:
1145       rep = 1;
1146       stride = 0;
1147       count = 1;
1148       pFormat += 2;
1149       break;
1150     case RPC_FC_FIXED_REPEAT:
1151       rep = *(const WORD*)&pFormat[2];
1152       stride = *(const WORD*)&pFormat[4];
1153       count = *(const WORD*)&pFormat[8];
1154       pFormat += 10;
1155       break;
1156     case RPC_FC_VARIABLE_REPEAT:
1157       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1158       stride = *(const WORD*)&pFormat[2];
1159       count = *(const WORD*)&pFormat[6];
1160       pFormat += 8;
1161       break;
1162     }
1163     for (i = 0; i < rep; i++) {
1164       PFORMAT_STRING info = pFormat;
1165       unsigned char *membase = pMemory + (i * stride);
1166       unsigned char *bufbase = Mark + (i * stride);
1167       unsigned u;
1168
1169       for (u=0; u<count; u++,info+=8) {
1170         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1171         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1172         unsigned char *saved_memory = pStubMsg->Memory;
1173
1174         pStubMsg->Memory = pMemory;
1175         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1176         pStubMsg->Memory = saved_memory;
1177       }
1178     }
1179     pFormat += 8 * count;
1180   }
1181
1182   if (saved_buffer)
1183   {
1184     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1185     pStubMsg->Buffer = saved_buffer;
1186   }
1187
1188   STD_OVERFLOW_CHECK(pStubMsg);
1189
1190   return NULL;
1191 }
1192
1193 /***********************************************************************
1194  *           EmbeddedPointerUnmarshall
1195  */
1196 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1197                                                  unsigned char *pDstBuffer,
1198                                                  unsigned char *pSrcMemoryPtrs,
1199                                                  PFORMAT_STRING pFormat,
1200                                                  unsigned char fMustAlloc)
1201 {
1202   unsigned char *Mark = pStubMsg->BufferMark;
1203   unsigned rep, count, stride;
1204   unsigned i;
1205   unsigned char *saved_buffer = NULL;
1206
1207   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1208
1209   if (*pFormat != RPC_FC_PP) return NULL;
1210   pFormat += 2;
1211
1212   if (pStubMsg->PointerBufferMark)
1213   {
1214     saved_buffer = pStubMsg->Buffer;
1215     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1216     pStubMsg->PointerBufferMark = NULL;
1217   }
1218
1219   while (pFormat[0] != RPC_FC_END) {
1220     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1221     switch (pFormat[0]) {
1222     default:
1223       FIXME("unknown repeat type %d\n", pFormat[0]);
1224     case RPC_FC_NO_REPEAT:
1225       rep = 1;
1226       stride = 0;
1227       count = 1;
1228       pFormat += 2;
1229       break;
1230     case RPC_FC_FIXED_REPEAT:
1231       rep = *(const WORD*)&pFormat[2];
1232       stride = *(const WORD*)&pFormat[4];
1233       count = *(const WORD*)&pFormat[8];
1234       pFormat += 10;
1235       break;
1236     case RPC_FC_VARIABLE_REPEAT:
1237       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1238       stride = *(const WORD*)&pFormat[2];
1239       count = *(const WORD*)&pFormat[6];
1240       pFormat += 8;
1241       break;
1242     }
1243     for (i = 0; i < rep; i++) {
1244       PFORMAT_STRING info = pFormat;
1245       unsigned char *bufdstbase = pDstBuffer + (i * stride);
1246       unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1247       unsigned char *bufbase = Mark + (i * stride);
1248       unsigned u;
1249
1250       for (u=0; u<count; u++,info+=8) {
1251         unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1252         unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1253         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1254         PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1255       }
1256     }
1257     pFormat += 8 * count;
1258   }
1259
1260   if (saved_buffer)
1261   {
1262     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1263     pStubMsg->Buffer = saved_buffer;
1264   }
1265
1266   return NULL;
1267 }
1268
1269 /***********************************************************************
1270  *           EmbeddedPointerBufferSize
1271  */
1272 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1273                                       unsigned char *pMemory,
1274                                       PFORMAT_STRING pFormat)
1275 {
1276   unsigned rep, count, stride;
1277   unsigned i;
1278   ULONG saved_buffer_length = 0;
1279
1280   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1281
1282   if (pStubMsg->IgnoreEmbeddedPointers) return;
1283
1284   if (*pFormat != RPC_FC_PP) return;
1285   pFormat += 2;
1286
1287   if (pStubMsg->PointerLength)
1288   {
1289     saved_buffer_length = pStubMsg->BufferLength;
1290     pStubMsg->BufferLength = pStubMsg->PointerLength;
1291     pStubMsg->PointerLength = 0;
1292   }
1293
1294   while (pFormat[0] != RPC_FC_END) {
1295     switch (pFormat[0]) {
1296     default:
1297       FIXME("unknown repeat type %d\n", pFormat[0]);
1298     case RPC_FC_NO_REPEAT:
1299       rep = 1;
1300       stride = 0;
1301       count = 1;
1302       pFormat += 2;
1303       break;
1304     case RPC_FC_FIXED_REPEAT:
1305       rep = *(const WORD*)&pFormat[2];
1306       stride = *(const WORD*)&pFormat[4];
1307       count = *(const WORD*)&pFormat[8];
1308       pFormat += 10;
1309       break;
1310     case RPC_FC_VARIABLE_REPEAT:
1311       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1312       stride = *(const WORD*)&pFormat[2];
1313       count = *(const WORD*)&pFormat[6];
1314       pFormat += 8;
1315       break;
1316     }
1317     for (i = 0; i < rep; i++) {
1318       PFORMAT_STRING info = pFormat;
1319       unsigned char *membase = pMemory + (i * stride);
1320       unsigned u;
1321
1322       for (u=0; u<count; u++,info+=8) {
1323         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1324         unsigned char *saved_memory = pStubMsg->Memory;
1325
1326         pStubMsg->Memory = pMemory;
1327         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1328         pStubMsg->Memory = saved_memory;
1329       }
1330     }
1331     pFormat += 8 * count;
1332   }
1333
1334   if (saved_buffer_length)
1335   {
1336     pStubMsg->PointerLength = pStubMsg->BufferLength;
1337     pStubMsg->BufferLength = saved_buffer_length;
1338   }
1339 }
1340
1341 /***********************************************************************
1342  *           EmbeddedPointerMemorySize [internal]
1343  */
1344 static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1345                                        PFORMAT_STRING pFormat)
1346 {
1347   unsigned char *Mark = pStubMsg->BufferMark;
1348   unsigned rep, count, stride;
1349   unsigned i;
1350   unsigned char *saved_buffer = NULL;
1351
1352   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1353
1354   if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1355
1356   if (pStubMsg->PointerBufferMark)
1357   {
1358     saved_buffer = pStubMsg->Buffer;
1359     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1360     pStubMsg->PointerBufferMark = NULL;
1361   }
1362
1363   if (*pFormat != RPC_FC_PP) return 0;
1364   pFormat += 2;
1365
1366   while (pFormat[0] != RPC_FC_END) {
1367     switch (pFormat[0]) {
1368     default:
1369       FIXME("unknown repeat type %d\n", pFormat[0]);
1370     case RPC_FC_NO_REPEAT:
1371       rep = 1;
1372       stride = 0;
1373       count = 1;
1374       pFormat += 2;
1375       break;
1376     case RPC_FC_FIXED_REPEAT:
1377       rep = *(const WORD*)&pFormat[2];
1378       stride = *(const WORD*)&pFormat[4];
1379       count = *(const WORD*)&pFormat[8];
1380       pFormat += 10;
1381       break;
1382     case RPC_FC_VARIABLE_REPEAT:
1383       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1384       stride = *(const WORD*)&pFormat[2];
1385       count = *(const WORD*)&pFormat[6];
1386       pFormat += 8;
1387       break;
1388     }
1389     for (i = 0; i < rep; i++) {
1390       PFORMAT_STRING info = pFormat;
1391       unsigned char *bufbase = Mark + (i * stride);
1392       unsigned u;
1393       for (u=0; u<count; u++,info+=8) {
1394         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1395         PointerMemorySize(pStubMsg, bufptr, info+4);
1396       }
1397     }
1398     pFormat += 8 * count;
1399   }
1400
1401   if (saved_buffer)
1402   {
1403     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1404     pStubMsg->Buffer = saved_buffer;
1405   }
1406
1407   return 0;
1408 }
1409
1410 /***********************************************************************
1411  *           EmbeddedPointerFree [internal]
1412  */
1413 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1414                                 unsigned char *pMemory,
1415                                 PFORMAT_STRING pFormat)
1416 {
1417   unsigned rep, count, stride;
1418   unsigned i;
1419
1420   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1421   if (*pFormat != RPC_FC_PP) return;
1422   pFormat += 2;
1423
1424   while (pFormat[0] != RPC_FC_END) {
1425     switch (pFormat[0]) {
1426     default:
1427       FIXME("unknown repeat type %d\n", pFormat[0]);
1428     case RPC_FC_NO_REPEAT:
1429       rep = 1;
1430       stride = 0;
1431       count = 1;
1432       pFormat += 2;
1433       break;
1434     case RPC_FC_FIXED_REPEAT:
1435       rep = *(const WORD*)&pFormat[2];
1436       stride = *(const WORD*)&pFormat[4];
1437       count = *(const WORD*)&pFormat[8];
1438       pFormat += 10;
1439       break;
1440     case RPC_FC_VARIABLE_REPEAT:
1441       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1442       stride = *(const WORD*)&pFormat[2];
1443       count = *(const WORD*)&pFormat[6];
1444       pFormat += 8;
1445       break;
1446     }
1447     for (i = 0; i < rep; i++) {
1448       PFORMAT_STRING info = pFormat;
1449       unsigned char *membase = pMemory + (i * stride);
1450       unsigned u;
1451
1452       for (u=0; u<count; u++,info+=8) {
1453         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1454         unsigned char *saved_memory = pStubMsg->Memory;
1455
1456         pStubMsg->Memory = pMemory;
1457         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1458         pStubMsg->Memory = saved_memory;
1459       }
1460     }
1461     pFormat += 8 * count;
1462   }
1463 }
1464
1465 /***********************************************************************
1466  *           NdrPointerMarshall [RPCRT4.@]
1467  */
1468 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1469                                           unsigned char *pMemory,
1470                                           PFORMAT_STRING pFormat)
1471 {
1472   unsigned char *Buffer;
1473
1474   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1475
1476   /* Increment the buffer here instead of in PointerMarshall,
1477    * as that is used by embedded pointers which already handle the incrementing
1478    * the buffer, and shouldn't write any additional pointer data to the wire */
1479   if (*pFormat != RPC_FC_RP)
1480   {
1481     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1482     Buffer = pStubMsg->Buffer;
1483     safe_buffer_increment(pStubMsg, 4);
1484   }
1485   else
1486     Buffer = pStubMsg->Buffer;
1487
1488   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1489
1490   return NULL;
1491 }
1492
1493 /***********************************************************************
1494  *           NdrPointerUnmarshall [RPCRT4.@]
1495  */
1496 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1497                                             unsigned char **ppMemory,
1498                                             PFORMAT_STRING pFormat,
1499                                             unsigned char fMustAlloc)
1500 {
1501   unsigned char *Buffer;
1502
1503   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1504
1505   if (*pFormat == RPC_FC_RP)
1506   {
1507     Buffer = pStubMsg->Buffer;
1508     /* Do the NULL ref pointer check here because embedded pointers can be
1509      * NULL if the type the pointer is embedded in was allocated rather than
1510      * being passed in by the client */
1511     if (pStubMsg->IsClient && !*ppMemory)
1512     {
1513       ERR("NULL ref pointer is not allowed\n");
1514       RpcRaiseException(RPC_X_NULL_REF_POINTER);
1515     }
1516   }
1517   else
1518   {
1519     /* Increment the buffer here instead of in PointerUnmarshall,
1520      * as that is used by embedded pointers which already handle the incrementing
1521      * the buffer, and shouldn't read any additional pointer data from the
1522      * buffer */
1523     ALIGN_POINTER(pStubMsg->Buffer, 4);
1524     Buffer = pStubMsg->Buffer;
1525     safe_buffer_increment(pStubMsg, 4);
1526   }
1527
1528   PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1529
1530   return NULL;
1531 }
1532
1533 /***********************************************************************
1534  *           NdrPointerBufferSize [RPCRT4.@]
1535  */
1536 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1537                                       unsigned char *pMemory,
1538                                       PFORMAT_STRING pFormat)
1539 {
1540   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1541
1542   /* Increment the buffer length here instead of in PointerBufferSize,
1543    * as that is used by embedded pointers which already handle the buffer
1544    * length, and shouldn't write anything more to the wire */
1545   if (*pFormat != RPC_FC_RP)
1546   {
1547     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1548     safe_buffer_length_increment(pStubMsg, 4);
1549   }
1550
1551   PointerBufferSize(pStubMsg, pMemory, pFormat);
1552 }
1553
1554 /***********************************************************************
1555  *           NdrPointerMemorySize [RPCRT4.@]
1556  */
1557 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1558                                   PFORMAT_STRING pFormat)
1559 {
1560     unsigned char *Buffer = pStubMsg->Buffer;
1561     if (*pFormat != RPC_FC_RP)
1562     {
1563         ALIGN_POINTER(pStubMsg->Buffer, 4);
1564         safe_buffer_increment(pStubMsg, 4);
1565     }
1566     ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
1567     return PointerMemorySize(pStubMsg, Buffer, pFormat);
1568 }
1569
1570 /***********************************************************************
1571  *           NdrPointerFree [RPCRT4.@]
1572  */
1573 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1574                            unsigned char *pMemory,
1575                            PFORMAT_STRING pFormat)
1576 {
1577   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1578   PointerFree(pStubMsg, pMemory, pFormat);
1579 }
1580
1581 /***********************************************************************
1582  *           NdrSimpleTypeMarshall [RPCRT4.@]
1583  */
1584 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1585                                    unsigned char FormatChar )
1586 {
1587     NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1588 }
1589
1590 /***********************************************************************
1591  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
1592  *
1593  * Unmarshall a base type.
1594  *
1595  * NOTES
1596  *  Doesn't check that the buffer is long enough before copying, so the caller
1597  * should do this.
1598  */
1599 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1600                                      unsigned char FormatChar )
1601 {
1602 #define BASE_TYPE_UNMARSHALL(type) \
1603         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
1604         TRACE("pMemory: %p\n", pMemory); \
1605         *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1606         pStubMsg->Buffer += sizeof(type);
1607
1608     switch(FormatChar)
1609     {
1610     case RPC_FC_BYTE:
1611     case RPC_FC_CHAR:
1612     case RPC_FC_SMALL:
1613     case RPC_FC_USMALL:
1614         BASE_TYPE_UNMARSHALL(UCHAR);
1615         TRACE("value: 0x%02x\n", *pMemory);
1616         break;
1617     case RPC_FC_WCHAR:
1618     case RPC_FC_SHORT:
1619     case RPC_FC_USHORT:
1620         BASE_TYPE_UNMARSHALL(USHORT);
1621         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1622         break;
1623     case RPC_FC_LONG:
1624     case RPC_FC_ULONG:
1625     case RPC_FC_ERROR_STATUS_T:
1626     case RPC_FC_ENUM32:
1627         BASE_TYPE_UNMARSHALL(ULONG);
1628         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1629         break;
1630    case RPC_FC_FLOAT:
1631         BASE_TYPE_UNMARSHALL(float);
1632         TRACE("value: %f\n", *(float *)pMemory);
1633         break;
1634     case RPC_FC_DOUBLE:
1635         BASE_TYPE_UNMARSHALL(double);
1636         TRACE("value: %f\n", *(double *)pMemory);
1637         break;
1638     case RPC_FC_HYPER:
1639         BASE_TYPE_UNMARSHALL(ULONGLONG);
1640         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1641         break;
1642     case RPC_FC_ENUM16:
1643         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
1644         TRACE("pMemory: %p\n", pMemory);
1645         /* 16-bits on the wire, but int in memory */
1646         *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1647         pStubMsg->Buffer += sizeof(USHORT);
1648         TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1649         break;
1650     case RPC_FC_IGNORE:
1651         break;
1652     default:
1653         FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1654     }
1655 #undef BASE_TYPE_UNMARSHALL
1656 }
1657
1658 /***********************************************************************
1659  *           NdrSimpleStructMarshall [RPCRT4.@]
1660  */
1661 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1662                                                unsigned char *pMemory,
1663                                                PFORMAT_STRING pFormat)
1664 {
1665   unsigned size = *(const WORD*)(pFormat+2);
1666   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1667
1668   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
1669
1670   pStubMsg->BufferMark = pStubMsg->Buffer;
1671   safe_copy_to_buffer(pStubMsg, pMemory, size);
1672
1673   if (pFormat[0] != RPC_FC_STRUCT)
1674     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1675
1676   return NULL;
1677 }
1678
1679 /***********************************************************************
1680  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1681  */
1682 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1683                                                  unsigned char **ppMemory,
1684                                                  PFORMAT_STRING pFormat,
1685                                                  unsigned char fMustAlloc)
1686 {
1687   unsigned size = *(const WORD*)(pFormat+2);
1688   unsigned char *saved_buffer;
1689   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1690
1691   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1692
1693   if (fMustAlloc)
1694     *ppMemory = NdrAllocate(pStubMsg, size);
1695   else
1696   {
1697     if (!pStubMsg->IsClient && !*ppMemory)
1698       /* for servers, we just point straight into the RPC buffer */
1699       *ppMemory = pStubMsg->Buffer;
1700   }
1701
1702   saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1703   safe_buffer_increment(pStubMsg, size);
1704   if (pFormat[0] == RPC_FC_PSTRUCT)
1705       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1706
1707   TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1708   if (*ppMemory != saved_buffer)
1709       memcpy(*ppMemory, saved_buffer, size);
1710
1711   return NULL;
1712 }
1713
1714 /***********************************************************************
1715  *           NdrSimpleStructBufferSize [RPCRT4.@]
1716  */
1717 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1718                                       unsigned char *pMemory,
1719                                       PFORMAT_STRING pFormat)
1720 {
1721   unsigned size = *(const WORD*)(pFormat+2);
1722   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1723
1724   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1725
1726   safe_buffer_length_increment(pStubMsg, size);
1727   if (pFormat[0] != RPC_FC_STRUCT)
1728     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1729 }
1730
1731 /***********************************************************************
1732  *           NdrSimpleStructMemorySize [RPCRT4.@]
1733  */
1734 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1735                                        PFORMAT_STRING pFormat)
1736 {
1737   unsigned short size = *(const WORD *)(pFormat+2);
1738
1739   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1740
1741   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1742   pStubMsg->MemorySize += size;
1743   safe_buffer_increment(pStubMsg, size);
1744
1745   if (pFormat[0] != RPC_FC_STRUCT)
1746     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1747   return pStubMsg->MemorySize;
1748 }
1749
1750 /***********************************************************************
1751  *           NdrSimpleStructFree [RPCRT4.@]
1752  */
1753 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1754                                 unsigned char *pMemory,
1755                                 PFORMAT_STRING pFormat)
1756 {
1757   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1758   if (pFormat[0] != RPC_FC_STRUCT)
1759     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1760 }
1761
1762 /* Array helpers */
1763
1764 static inline void array_compute_and_size_conformance(
1765     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1766     PFORMAT_STRING pFormat)
1767 {
1768   switch (fc)
1769   {
1770   case RPC_FC_CARRAY:
1771     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1772     SizeConformance(pStubMsg);
1773     break;
1774   case RPC_FC_CVARRAY:
1775     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1776     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1777     SizeConformance(pStubMsg);
1778     break;
1779   case RPC_FC_C_CSTRING:
1780   case RPC_FC_C_WSTRING:
1781     if (pFormat[0] == RPC_FC_C_CSTRING)
1782     {
1783       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1784       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1785     }
1786     else
1787     {
1788       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1789       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1790     }
1791
1792     if (fc == RPC_FC_STRING_SIZED)
1793       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1794     else
1795       pStubMsg->MaxCount = pStubMsg->ActualCount;
1796
1797     SizeConformance(pStubMsg);
1798     break;
1799   default:
1800     ERR("unknown array format 0x%x\n", fc);
1801     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1802   }
1803 }
1804
1805 static inline void array_buffer_size(
1806     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1807     PFORMAT_STRING pFormat, unsigned char fHasPointers)
1808 {
1809   DWORD size;
1810   DWORD esize;
1811   unsigned char alignment;
1812
1813   switch (fc)
1814   {
1815   case RPC_FC_CARRAY:
1816     esize = *(const WORD*)(pFormat+2);
1817     alignment = pFormat[1] + 1;
1818
1819     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1820
1821     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1822
1823     size = safe_multiply(esize, pStubMsg->MaxCount);
1824     /* conformance value plus array */
1825     safe_buffer_length_increment(pStubMsg, size);
1826
1827     if (fHasPointers)
1828       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1829     break;
1830   case RPC_FC_CVARRAY:
1831     esize = *(const WORD*)(pFormat+2);
1832     alignment = pFormat[1] + 1;
1833
1834     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1835     pFormat = SkipConformance(pStubMsg, pFormat);
1836
1837     SizeVariance(pStubMsg);
1838
1839     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1840
1841     size = safe_multiply(esize, pStubMsg->ActualCount);
1842     safe_buffer_length_increment(pStubMsg, size);
1843
1844     if (fHasPointers)
1845       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1846     break;
1847   case RPC_FC_C_CSTRING:
1848   case RPC_FC_C_WSTRING:
1849     if (fc == RPC_FC_C_CSTRING)
1850       esize = 1;
1851     else
1852       esize = 2;
1853
1854     SizeVariance(pStubMsg);
1855
1856     size = safe_multiply(esize, pStubMsg->ActualCount);
1857     safe_buffer_length_increment(pStubMsg, size);
1858     break;
1859   default:
1860     ERR("unknown array format 0x%x\n", fc);
1861     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1862   }
1863 }
1864
1865 static inline void array_compute_and_write_conformance(
1866     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1867     PFORMAT_STRING pFormat)
1868 {
1869   switch (fc)
1870   {
1871   case RPC_FC_CARRAY:
1872     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1873     WriteConformance(pStubMsg);
1874     break;
1875   case RPC_FC_CVARRAY:
1876     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1877     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1878     WriteConformance(pStubMsg);
1879     break;
1880   case RPC_FC_C_CSTRING:
1881   case RPC_FC_C_WSTRING:
1882     if (fc == RPC_FC_C_CSTRING)
1883     {
1884       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1885       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1886     }
1887     else
1888     {
1889       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1890       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1891     }
1892     if (pFormat[1] == RPC_FC_STRING_SIZED)
1893       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1894     else
1895       pStubMsg->MaxCount = pStubMsg->ActualCount;
1896     pStubMsg->Offset = 0;
1897     WriteConformance(pStubMsg);
1898     break;
1899   default:
1900     ERR("unknown array format 0x%x\n", fc);
1901     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1902   }
1903 }
1904
1905 static inline void array_write_variance_and_marshall(
1906     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1907     PFORMAT_STRING pFormat, unsigned char fHasPointers)
1908 {
1909   DWORD size;
1910   DWORD esize;
1911   unsigned char alignment;
1912
1913   switch (fc)
1914   {
1915   case RPC_FC_CARRAY:
1916     esize = *(const WORD*)(pFormat+2);
1917     alignment = pFormat[1] + 1;
1918
1919     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1920
1921     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1922
1923     size = safe_multiply(esize, pStubMsg->MaxCount);
1924     if (fHasPointers)
1925       pStubMsg->BufferMark = pStubMsg->Buffer;
1926     safe_copy_to_buffer(pStubMsg, pMemory, size);
1927
1928     if (fHasPointers)
1929       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1930     break;
1931   case RPC_FC_CVARRAY:
1932     esize = *(const WORD*)(pFormat+2);
1933     alignment = pFormat[1] + 1;
1934
1935     /* conformance */
1936     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1937     /* variance */
1938     pFormat = SkipConformance(pStubMsg, pFormat);
1939
1940     WriteVariance(pStubMsg);
1941
1942     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1943
1944     size = safe_multiply(esize, pStubMsg->ActualCount);
1945
1946     if (fHasPointers)
1947       pStubMsg->BufferMark = pStubMsg->Buffer;
1948     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
1949
1950     if (fHasPointers)
1951       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1952     break;
1953   case RPC_FC_C_CSTRING:
1954   case RPC_FC_C_WSTRING:
1955     if (fc == RPC_FC_C_CSTRING)
1956       esize = 1;
1957     else
1958       esize = 2;
1959
1960     WriteVariance(pStubMsg);
1961
1962     size = safe_multiply(esize, pStubMsg->ActualCount);
1963     safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
1964     break;
1965   default:
1966     ERR("unknown array format 0x%x\n", fc);
1967     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1968   }
1969 }
1970
1971 static inline ULONG array_read_conformance(
1972     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
1973 {
1974   DWORD esize;
1975
1976   switch (fc)
1977   {
1978   case RPC_FC_CARRAY:
1979     esize = *(const WORD*)(pFormat+2);
1980     pFormat = ReadConformance(pStubMsg, pFormat+4);
1981     return safe_multiply(esize, pStubMsg->MaxCount);
1982   case RPC_FC_CVARRAY:
1983     esize = *(const WORD*)(pFormat+2);
1984     pFormat = ReadConformance(pStubMsg, pFormat+4);
1985     return safe_multiply(esize, pStubMsg->MaxCount);
1986   case RPC_FC_C_CSTRING:
1987   case RPC_FC_C_WSTRING:
1988     if (fc == RPC_FC_C_CSTRING)
1989       esize = 1;
1990     else
1991       esize = 2;
1992
1993     if (pFormat[1] == RPC_FC_STRING_SIZED)
1994       ReadConformance(pStubMsg, pFormat + 2);
1995     else
1996       ReadConformance(pStubMsg, NULL);
1997     return safe_multiply(esize, pStubMsg->MaxCount);
1998   default:
1999     ERR("unknown array format 0x%x\n", fc);
2000     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2001   }
2002 }
2003
2004 static inline ULONG array_read_variance_and_unmarshall(
2005     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
2006     PFORMAT_STRING pFormat, unsigned char fMustAlloc,
2007     unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
2008 {
2009   ULONG bufsize, memsize;
2010   WORD esize;
2011   unsigned char alignment;
2012   unsigned char *saved_buffer;
2013   ULONG offset;
2014
2015   switch (fc)
2016   {
2017   case RPC_FC_CARRAY:
2018     esize = *(const WORD*)(pFormat+2);
2019     alignment = pFormat[1] + 1;
2020
2021     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2022
2023     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2024
2025     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2026
2027     if (fUnmarshall)
2028     {
2029       if (fMustAlloc)
2030         *ppMemory = NdrAllocate(pStubMsg, memsize);
2031       else
2032       {
2033         if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2034           /* for servers, we just point straight into the RPC buffer */
2035           *ppMemory = pStubMsg->Buffer;
2036       }
2037
2038       saved_buffer = pStubMsg->Buffer;
2039       safe_buffer_increment(pStubMsg, bufsize);
2040
2041       pStubMsg->BufferMark = saved_buffer;
2042       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2043
2044       TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2045       if (*ppMemory != saved_buffer)
2046         memcpy(*ppMemory, saved_buffer, bufsize);
2047     }
2048     return bufsize;
2049   case RPC_FC_CVARRAY:
2050     esize = *(const WORD*)(pFormat+2);
2051     alignment = pFormat[1] + 1;
2052
2053     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2054
2055     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2056
2057     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2058
2059     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2060     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2061
2062     if (fUnmarshall)
2063     {
2064       offset = pStubMsg->Offset;
2065
2066       if (!fMustAlloc && !*ppMemory)
2067         fMustAlloc = TRUE;
2068       if (fMustAlloc)
2069         *ppMemory = NdrAllocate(pStubMsg, memsize);
2070       saved_buffer = pStubMsg->Buffer;
2071       safe_buffer_increment(pStubMsg, bufsize);
2072
2073       pStubMsg->BufferMark = saved_buffer;
2074       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2075                                 fMustAlloc);
2076
2077       memcpy(*ppMemory + offset, saved_buffer, bufsize);
2078     }
2079     return bufsize;
2080   case RPC_FC_C_CSTRING:
2081   case RPC_FC_C_WSTRING:
2082     if (fc == RPC_FC_C_CSTRING)
2083       esize = 1;
2084     else
2085       esize = 2;
2086
2087     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2088
2089     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2090     {
2091       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2092           pStubMsg->ActualCount, pStubMsg->MaxCount);
2093       RpcRaiseException(RPC_S_INVALID_BOUND);
2094     }
2095     if (pStubMsg->Offset)
2096     {
2097       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2098       RpcRaiseException(RPC_S_INVALID_BOUND);
2099     }
2100
2101     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2102     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2103
2104     validate_string_data(pStubMsg, bufsize, esize);
2105
2106     if (fUnmarshall)
2107     {
2108       if (fMustAlloc)
2109         *ppMemory = NdrAllocate(pStubMsg, memsize);
2110       else
2111       {
2112         if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2113             !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2114           /* if the data in the RPC buffer is big enough, we just point
2115            * straight into it */
2116           *ppMemory = pStubMsg->Buffer;
2117         else if (!*ppMemory)
2118           *ppMemory = NdrAllocate(pStubMsg, memsize);
2119       }
2120
2121       if (*ppMemory == pStubMsg->Buffer)
2122         safe_buffer_increment(pStubMsg, bufsize);
2123       else
2124         safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2125
2126       if (*pFormat == RPC_FC_C_CSTRING)
2127         TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2128       else
2129         TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2130     }
2131     return bufsize;
2132   default:
2133     ERR("unknown array format 0x%x\n", fc);
2134     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2135   }
2136 }
2137
2138 static inline void array_memory_size(
2139     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2140     unsigned char fHasPointers)
2141 {
2142   ULONG bufsize, memsize;
2143   DWORD esize;
2144   unsigned char alignment;
2145
2146   switch (fc)
2147   {
2148   case RPC_FC_CARRAY:
2149     esize = *(const WORD*)(pFormat+2);
2150     alignment = pFormat[1] + 1;
2151
2152     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2153
2154     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2155     pStubMsg->MemorySize += memsize;
2156
2157     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2158     if (fHasPointers)
2159       pStubMsg->BufferMark = pStubMsg->Buffer;
2160     safe_buffer_increment(pStubMsg, bufsize);
2161
2162     if (fHasPointers)
2163       EmbeddedPointerMemorySize(pStubMsg, pFormat);
2164     break;
2165   case RPC_FC_CVARRAY:
2166     esize = *(const WORD*)(pFormat+2);
2167     alignment = pFormat[1] + 1;
2168
2169     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2170
2171     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2172
2173     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2174     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2175     pStubMsg->MemorySize += memsize;
2176
2177     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2178     if (fHasPointers)
2179       pStubMsg->BufferMark = pStubMsg->Buffer;
2180     safe_buffer_increment(pStubMsg, bufsize);
2181
2182     if (fHasPointers)
2183       EmbeddedPointerMemorySize(pStubMsg, pFormat);
2184     break;
2185   case RPC_FC_C_CSTRING:
2186   case RPC_FC_C_WSTRING:
2187     if (fc == RPC_FC_C_CSTRING)
2188       esize = 1;
2189     else
2190       esize = 2;
2191
2192     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2193
2194     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2195     {
2196       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2197           pStubMsg->ActualCount, pStubMsg->MaxCount);
2198       RpcRaiseException(RPC_S_INVALID_BOUND);
2199     }
2200     if (pStubMsg->Offset)
2201     {
2202       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2203       RpcRaiseException(RPC_S_INVALID_BOUND);
2204     }
2205
2206     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2207     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2208
2209     validate_string_data(pStubMsg, bufsize, esize);
2210
2211     safe_buffer_increment(pStubMsg, bufsize);
2212     pStubMsg->MemorySize += memsize;
2213     break;
2214   default:
2215     ERR("unknown array format 0x%x\n", fc);
2216     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2217   }
2218 }
2219
2220 static inline void array_free(
2221     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2222     unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2223 {
2224   switch (fc)
2225   {
2226   case RPC_FC_CARRAY:
2227     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2228     if (fHasPointers)
2229       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2230     break;
2231   case RPC_FC_CVARRAY:
2232     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2233     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2234     if (fHasPointers)
2235       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2236     break;
2237   case RPC_FC_C_CSTRING:
2238   case RPC_FC_C_WSTRING:
2239     /* No embedded pointers so nothing to do */
2240     break;
2241   default:
2242     ERR("unknown array format 0x%x\n", fc);
2243     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2244   }
2245 }
2246
2247 /*
2248  * NdrConformantString:
2249  *
2250  * What MS calls a ConformantString is, in DCE terminology,
2251  * a Varying-Conformant String.
2252  * [
2253  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2254  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
2255  *           into unmarshalled string)
2256  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2257  *   [
2258  *     data: CHARTYPE[maxlen]
2259  *   ]
2260  * ], where CHARTYPE is the appropriate character type (specified externally)
2261  *
2262  */
2263
2264 /***********************************************************************
2265  *            NdrConformantStringMarshall [RPCRT4.@]
2266  */
2267 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
2268   unsigned char *pszMessage, PFORMAT_STRING pFormat)
2269 {
2270   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2271
2272   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2273     ERR("Unhandled string type: %#x\n", pFormat[0]);
2274     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2275   }
2276
2277   /* allow compiler to optimise inline function by passing constant into
2278    * these functions */
2279   if (pFormat[0] == RPC_FC_C_CSTRING) {
2280     array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2281                                         pFormat);
2282     array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2283                                       pFormat, TRUE /* fHasPointers */);
2284   } else {
2285     array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2286                                         pFormat);
2287     array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2288                                       pFormat, TRUE /* fHasPointers */);
2289   }
2290
2291   return NULL;
2292 }
2293
2294 /***********************************************************************
2295  *           NdrConformantStringBufferSize [RPCRT4.@]
2296  */
2297 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2298   unsigned char* pMemory, PFORMAT_STRING pFormat)
2299 {
2300   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2301
2302   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2303     ERR("Unhandled string type: %#x\n", pFormat[0]);
2304     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2305   }
2306
2307   /* allow compiler to optimise inline function by passing constant into
2308    * these functions */
2309   if (pFormat[0] == RPC_FC_C_CSTRING) {
2310     array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory,
2311                                        pFormat);
2312     array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2313                       TRUE /* fHasPointers */);
2314   } else {
2315     array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory,
2316                                        pFormat);
2317     array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2318                       TRUE /* fHasPointers */);
2319   }
2320 }
2321
2322 /************************************************************************
2323  *            NdrConformantStringMemorySize [RPCRT4.@]
2324  */
2325 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2326   PFORMAT_STRING pFormat )
2327 {
2328   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2329
2330   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2331     ERR("Unhandled string type: %#x\n", pFormat[0]);
2332     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2333   }
2334
2335   /* allow compiler to optimise inline function by passing constant into
2336    * these functions */
2337   if (pFormat[0] == RPC_FC_C_CSTRING) {
2338     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2339     array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat,
2340                       TRUE /* fHasPointers */);
2341   } else {
2342     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2343     array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat,
2344                       TRUE /* fHasPointers */);
2345   }
2346
2347   return pStubMsg->MemorySize;
2348 }
2349
2350 /************************************************************************
2351  *           NdrConformantStringUnmarshall [RPCRT4.@]
2352  */
2353 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2354   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2355 {
2356   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2357     pStubMsg, *ppMemory, pFormat, fMustAlloc);
2358
2359   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2360     ERR("Unhandled string type: %#x\n", *pFormat);
2361     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2362   }
2363
2364   /* allow compiler to optimise inline function by passing constant into
2365    * these functions */
2366   if (pFormat[0] == RPC_FC_C_CSTRING) {
2367     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2368     array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory,
2369                                        pFormat, fMustAlloc,
2370                                        TRUE /* fUseBufferMemoryServer */,
2371                                        TRUE /* fUnmarshall */);
2372   } else {
2373     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2374     array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory,
2375                                        pFormat, fMustAlloc,
2376                                        TRUE /* fUseBufferMemoryServer */,
2377                                        TRUE /* fUnmarshall */);
2378   }
2379
2380   return NULL;
2381 }
2382
2383 /***********************************************************************
2384  *           NdrNonConformantStringMarshall [RPCRT4.@]
2385  */
2386 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2387                                 unsigned char *pMemory,
2388                                 PFORMAT_STRING pFormat)
2389 {
2390   ULONG esize, size, maxsize;
2391
2392   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2393
2394   maxsize = *(USHORT *)&pFormat[2];
2395
2396   if (*pFormat == RPC_FC_CSTRING)
2397   {
2398     ULONG i;
2399     const char *str = (const char *)pMemory;
2400     for (i = 0; i < maxsize && *str; i++, str++)
2401         ;
2402     TRACE("string=%s\n", debugstr_an(str, i));
2403     pStubMsg->ActualCount = i + 1;
2404     esize = 1;
2405   }
2406   else if (*pFormat == RPC_FC_WSTRING)
2407   {
2408     ULONG i;
2409     const WCHAR *str = (const WCHAR *)pMemory;
2410     for (i = 0; i < maxsize && *str; i++, str++)
2411         ;
2412     TRACE("string=%s\n", debugstr_wn(str, i));
2413     pStubMsg->ActualCount = i + 1;
2414     esize = 2;
2415   }
2416   else
2417   {
2418     ERR("Unhandled string type: %#x\n", *pFormat);
2419     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2420   }
2421
2422   pStubMsg->Offset = 0;
2423   WriteVariance(pStubMsg);
2424
2425   size = safe_multiply(esize, pStubMsg->ActualCount);
2426   safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2427
2428   return NULL;
2429 }
2430
2431 /***********************************************************************
2432  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
2433  */
2434 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2435                                 unsigned char **ppMemory,
2436                                 PFORMAT_STRING pFormat,
2437                                 unsigned char fMustAlloc)
2438 {
2439   ULONG bufsize, memsize, esize, maxsize;
2440
2441   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2442     pStubMsg, *ppMemory, pFormat, fMustAlloc);
2443
2444   maxsize = *(USHORT *)&pFormat[2];
2445
2446   ReadVariance(pStubMsg, NULL, maxsize);
2447   if (pStubMsg->Offset)
2448   {
2449     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2450     RpcRaiseException(RPC_S_INVALID_BOUND);
2451   }
2452
2453   if (*pFormat == RPC_FC_CSTRING) esize = 1;
2454   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2455   else
2456   {
2457     ERR("Unhandled string type: %#x\n", *pFormat);
2458     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2459   }
2460
2461   memsize = esize * maxsize;
2462   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2463
2464   validate_string_data(pStubMsg, bufsize, esize);
2465
2466   if (!fMustAlloc && !*ppMemory)
2467     fMustAlloc = TRUE;
2468   if (fMustAlloc)
2469     *ppMemory = NdrAllocate(pStubMsg, memsize);
2470
2471   safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2472
2473   if (*pFormat == RPC_FC_CSTRING) {
2474     TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2475   }
2476   else if (*pFormat == RPC_FC_WSTRING) {
2477     TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2478   }
2479
2480   return NULL;
2481 }
2482
2483 /***********************************************************************
2484  *           NdrNonConformantStringBufferSize [RPCRT4.@]
2485  */
2486 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2487                                 unsigned char *pMemory,
2488                                 PFORMAT_STRING pFormat)
2489 {
2490   ULONG esize, maxsize;
2491
2492   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2493
2494   maxsize = *(USHORT *)&pFormat[2];
2495
2496   SizeVariance(pStubMsg);
2497
2498   if (*pFormat == RPC_FC_CSTRING)
2499   {
2500     ULONG i;
2501     const char *str = (const char *)pMemory;
2502     for (i = 0; i < maxsize && *str; i++, str++)
2503         ;
2504     TRACE("string=%s\n", debugstr_an(str, i));
2505     pStubMsg->ActualCount = i + 1;
2506     esize = 1;
2507   }
2508   else if (*pFormat == RPC_FC_WSTRING)
2509   {
2510     ULONG i;
2511     const WCHAR *str = (const WCHAR *)pMemory;
2512     for (i = 0; i < maxsize && *str; i++, str++)
2513         ;
2514     TRACE("string=%s\n", debugstr_wn(str, i));
2515     pStubMsg->ActualCount = i + 1;
2516     esize = 2;
2517   }
2518   else
2519   {
2520     ERR("Unhandled string type: %#x\n", *pFormat);
2521     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2522   }
2523
2524   safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2525 }
2526
2527 /***********************************************************************
2528  *           NdrNonConformantStringMemorySize [RPCRT4.@]
2529  */
2530 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2531                                 PFORMAT_STRING pFormat)
2532 {
2533   ULONG bufsize, memsize, esize, maxsize;
2534
2535   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2536
2537   maxsize = *(USHORT *)&pFormat[2];
2538
2539   ReadVariance(pStubMsg, NULL, maxsize);
2540
2541   if (pStubMsg->Offset)
2542   {
2543     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2544     RpcRaiseException(RPC_S_INVALID_BOUND);
2545   }
2546
2547   if (*pFormat == RPC_FC_CSTRING) esize = 1;
2548   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2549   else
2550   {
2551     ERR("Unhandled string type: %#x\n", *pFormat);
2552     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2553   }
2554
2555   memsize = esize * maxsize;
2556   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2557
2558   validate_string_data(pStubMsg, bufsize, esize);
2559
2560   safe_buffer_increment(pStubMsg, bufsize);
2561   pStubMsg->MemorySize += memsize;
2562
2563   return pStubMsg->MemorySize;
2564 }
2565
2566 /* Complex types */
2567
2568 #include "pshpack1.h"
2569 typedef struct
2570 {
2571     unsigned char type;
2572     unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2573     ULONG low_value;
2574     ULONG high_value;
2575 } NDR_RANGE;
2576 #include "poppack.h"
2577
2578 static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2579                                  PFORMAT_STRING pFormat)
2580 {
2581   switch (*pFormat) {
2582   case RPC_FC_STRUCT:
2583   case RPC_FC_PSTRUCT:
2584   case RPC_FC_CSTRUCT:
2585   case RPC_FC_BOGUS_STRUCT:
2586   case RPC_FC_SMFARRAY:
2587   case RPC_FC_SMVARRAY:
2588   case RPC_FC_CSTRING:
2589     return *(const WORD*)&pFormat[2];
2590   case RPC_FC_USER_MARSHAL:
2591     return *(const WORD*)&pFormat[4];
2592   case RPC_FC_RANGE: {
2593     switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2594     case RPC_FC_BYTE:
2595     case RPC_FC_CHAR:
2596     case RPC_FC_SMALL:
2597     case RPC_FC_USMALL:
2598         return sizeof(UCHAR);
2599     case RPC_FC_WCHAR:
2600     case RPC_FC_SHORT:
2601     case RPC_FC_USHORT:
2602         return sizeof(USHORT);
2603     case RPC_FC_LONG:
2604     case RPC_FC_ULONG:
2605     case RPC_FC_ENUM32:
2606         return sizeof(ULONG);
2607     case RPC_FC_FLOAT:
2608         return sizeof(float);
2609     case RPC_FC_DOUBLE:
2610         return sizeof(double);
2611     case RPC_FC_HYPER:
2612         return sizeof(ULONGLONG);
2613     case RPC_FC_ENUM16:
2614         return sizeof(UINT);
2615     default:
2616         ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2617         RpcRaiseException(RPC_X_BAD_STUB_DATA);
2618     }
2619   }
2620   case RPC_FC_NON_ENCAPSULATED_UNION:
2621     pFormat += 2;
2622     if (pStubMsg->fHasNewCorrDesc)
2623         pFormat += 6;
2624     else
2625         pFormat += 4;
2626
2627     pFormat += *(const SHORT*)pFormat;
2628     return *(const SHORT*)pFormat;
2629   case RPC_FC_IP:
2630     return sizeof(void *);
2631   case RPC_FC_WSTRING:
2632     return *(const WORD*)&pFormat[2] * 2;
2633   default:
2634     FIXME("unhandled embedded type %02x\n", *pFormat);
2635   }
2636   return 0;
2637 }
2638
2639
2640 static ULONG EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2641                                        PFORMAT_STRING pFormat)
2642 {
2643   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2644
2645   if (!m)
2646   {
2647     FIXME("no memorysizer for data type=%02x\n", *pFormat);
2648     return 0;
2649   }
2650
2651   return m(pStubMsg, pFormat);
2652 }
2653
2654
2655 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2656                                        unsigned char *pMemory,
2657                                        PFORMAT_STRING pFormat,
2658                                        PFORMAT_STRING pPointer)
2659 {
2660   PFORMAT_STRING desc;
2661   NDR_MARSHALL m;
2662   ULONG size;
2663
2664   while (*pFormat != RPC_FC_END) {
2665     switch (*pFormat) {
2666     case RPC_FC_BYTE:
2667     case RPC_FC_CHAR:
2668     case RPC_FC_SMALL:
2669     case RPC_FC_USMALL:
2670       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2671       safe_copy_to_buffer(pStubMsg, pMemory, 1);
2672       pMemory += 1;
2673       break;
2674     case RPC_FC_WCHAR:
2675     case RPC_FC_SHORT:
2676     case RPC_FC_USHORT:
2677       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2678       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2679       pMemory += 2;
2680       break;
2681     case RPC_FC_ENUM16:
2682       TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2683       if (32767 < *(DWORD*)pMemory)
2684         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2685       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2686       pMemory += 4;
2687       break;
2688     case RPC_FC_LONG:
2689     case RPC_FC_ULONG:
2690     case RPC_FC_ENUM32:
2691       TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2692       safe_copy_to_buffer(pStubMsg, pMemory, 4);
2693       pMemory += 4;
2694       break;
2695     case RPC_FC_HYPER:
2696       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2697       safe_copy_to_buffer(pStubMsg, pMemory, 8);
2698       pMemory += 8;
2699       break;
2700     case RPC_FC_POINTER:
2701     {
2702       unsigned char *saved_buffer;
2703       int pointer_buffer_mark_set = 0;
2704       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2705       TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2706       if (*pPointer != RPC_FC_RP)
2707         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2708       saved_buffer = pStubMsg->Buffer;
2709       if (pStubMsg->PointerBufferMark)
2710       {
2711         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2712         pStubMsg->PointerBufferMark = NULL;
2713         pointer_buffer_mark_set = 1;
2714       }
2715       else if (*pPointer != RPC_FC_RP)
2716         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2717       PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2718       if (pointer_buffer_mark_set)
2719       {
2720         STD_OVERFLOW_CHECK(pStubMsg);
2721         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2722         pStubMsg->Buffer = saved_buffer;
2723         if (*pPointer != RPC_FC_RP)
2724           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2725       }
2726       TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2727       pPointer += 4;
2728       pMemory += sizeof(void *);
2729       break;
2730     }
2731     case RPC_FC_ALIGNM2:
2732       ALIGN_POINTER(pMemory, 2);
2733       break;
2734     case RPC_FC_ALIGNM4:
2735       ALIGN_POINTER(pMemory, 4);
2736       break;
2737     case RPC_FC_ALIGNM8:
2738       ALIGN_POINTER(pMemory, 8);
2739       break;
2740     case RPC_FC_STRUCTPAD1:
2741     case RPC_FC_STRUCTPAD2:
2742     case RPC_FC_STRUCTPAD3:
2743     case RPC_FC_STRUCTPAD4:
2744     case RPC_FC_STRUCTPAD5:
2745     case RPC_FC_STRUCTPAD6:
2746     case RPC_FC_STRUCTPAD7:
2747       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2748       break;
2749     case RPC_FC_EMBEDDED_COMPLEX:
2750       pMemory += pFormat[1];
2751       pFormat += 2;
2752       desc = pFormat + *(const SHORT*)pFormat;
2753       size = EmbeddedComplexSize(pStubMsg, desc);
2754       TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2755       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2756       if (m)
2757       {
2758         /* for some reason interface pointers aren't generated as
2759          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2760          * they still need the derefencing treatment that pointers are
2761          * given */
2762         if (*desc == RPC_FC_IP)
2763           m(pStubMsg, *(unsigned char **)pMemory, desc);
2764         else
2765           m(pStubMsg, pMemory, desc);
2766       }
2767       else FIXME("no marshaller for embedded type %02x\n", *desc);
2768       pMemory += size;
2769       pFormat += 2;
2770       continue;
2771     case RPC_FC_PAD:
2772       break;
2773     default:
2774       FIXME("unhandled format 0x%02x\n", *pFormat);
2775     }
2776     pFormat++;
2777   }
2778
2779   return pMemory;
2780 }
2781
2782 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2783                                          unsigned char *pMemory,
2784                                          PFORMAT_STRING pFormat,
2785                                          PFORMAT_STRING pPointer,
2786                                          unsigned char fMustAlloc)
2787 {
2788   PFORMAT_STRING desc;
2789   NDR_UNMARSHALL m;
2790   ULONG size;
2791
2792   while (*pFormat != RPC_FC_END) {
2793     switch (*pFormat) {
2794     case RPC_FC_BYTE:
2795     case RPC_FC_CHAR:
2796     case RPC_FC_SMALL:
2797     case RPC_FC_USMALL:
2798       safe_copy_from_buffer(pStubMsg, pMemory, 1);
2799       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2800       pMemory += 1;
2801       break;
2802     case RPC_FC_WCHAR:
2803     case RPC_FC_SHORT:
2804     case RPC_FC_USHORT:
2805       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2806       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2807       pMemory += 2;
2808       break;
2809     case RPC_FC_ENUM16:
2810       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2811       *(DWORD*)pMemory &= 0xffff;
2812       TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2813       if (32767 < *(DWORD*)pMemory)
2814         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2815       pMemory += 4;
2816       break;
2817     case RPC_FC_LONG:
2818     case RPC_FC_ULONG:
2819     case RPC_FC_ENUM32:
2820       safe_copy_from_buffer(pStubMsg, pMemory, 4);
2821       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2822       pMemory += 4;
2823       break;
2824     case RPC_FC_HYPER:
2825       safe_copy_from_buffer(pStubMsg, pMemory, 8);
2826       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2827       pMemory += 8;
2828       break;
2829     case RPC_FC_POINTER:
2830     {
2831       unsigned char *saved_buffer;
2832       int pointer_buffer_mark_set = 0;
2833       TRACE("pointer => %p\n", pMemory);
2834       if (*pPointer != RPC_FC_RP)
2835         ALIGN_POINTER(pStubMsg->Buffer, 4);
2836       saved_buffer = pStubMsg->Buffer;
2837       if (pStubMsg->PointerBufferMark)
2838       {
2839         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2840         pStubMsg->PointerBufferMark = NULL;
2841         pointer_buffer_mark_set = 1;
2842       }
2843       else if (*pPointer != RPC_FC_RP)
2844         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2845
2846       PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
2847       if (pointer_buffer_mark_set)
2848       {
2849         STD_OVERFLOW_CHECK(pStubMsg);
2850         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2851         pStubMsg->Buffer = saved_buffer;
2852         if (*pPointer != RPC_FC_RP)
2853           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2854       }
2855       pPointer += 4;
2856       pMemory += sizeof(void *);
2857       break;
2858     }
2859     case RPC_FC_ALIGNM2:
2860       ALIGN_POINTER_CLEAR(pMemory, 2);
2861       break;
2862     case RPC_FC_ALIGNM4:
2863       ALIGN_POINTER_CLEAR(pMemory, 4);
2864       break;
2865     case RPC_FC_ALIGNM8:
2866       ALIGN_POINTER_CLEAR(pMemory, 8);
2867       break;
2868     case RPC_FC_STRUCTPAD1:
2869     case RPC_FC_STRUCTPAD2:
2870     case RPC_FC_STRUCTPAD3:
2871     case RPC_FC_STRUCTPAD4:
2872     case RPC_FC_STRUCTPAD5:
2873     case RPC_FC_STRUCTPAD6:
2874     case RPC_FC_STRUCTPAD7:
2875       memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2876       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2877       break;
2878     case RPC_FC_EMBEDDED_COMPLEX:
2879       pMemory += pFormat[1];
2880       pFormat += 2;
2881       desc = pFormat + *(const SHORT*)pFormat;
2882       size = EmbeddedComplexSize(pStubMsg, desc);
2883       TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
2884       if (fMustAlloc)
2885         /* we can't pass fMustAlloc=TRUE into the marshaller for this type
2886          * since the type is part of the memory block that is encompassed by
2887          * the whole complex type. Memory is forced to allocate when pointers
2888          * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
2889          * clearing the memory we pass in to the unmarshaller */
2890         memset(pMemory, 0, size);
2891       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2892       if (m)
2893       {
2894         /* for some reason interface pointers aren't generated as
2895          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2896          * they still need the derefencing treatment that pointers are
2897          * given */
2898         if (*desc == RPC_FC_IP)
2899           m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2900         else
2901           m(pStubMsg, &pMemory, desc, FALSE);
2902       }
2903       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2904       pMemory += size;
2905       pFormat += 2;
2906       continue;
2907     case RPC_FC_PAD:
2908       break;
2909     default:
2910       FIXME("unhandled format %d\n", *pFormat);
2911     }
2912     pFormat++;
2913   }
2914
2915   return pMemory;
2916 }
2917
2918 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2919                                          unsigned char *pMemory,
2920                                          PFORMAT_STRING pFormat,
2921                                          PFORMAT_STRING pPointer)
2922 {
2923   PFORMAT_STRING desc;
2924   NDR_BUFFERSIZE m;
2925   ULONG size;
2926
2927   while (*pFormat != RPC_FC_END) {
2928     switch (*pFormat) {
2929     case RPC_FC_BYTE:
2930     case RPC_FC_CHAR:
2931     case RPC_FC_SMALL:
2932     case RPC_FC_USMALL:
2933       safe_buffer_length_increment(pStubMsg, 1);
2934       pMemory += 1;
2935       break;
2936     case RPC_FC_WCHAR:
2937     case RPC_FC_SHORT:
2938     case RPC_FC_USHORT:
2939       safe_buffer_length_increment(pStubMsg, 2);
2940       pMemory += 2;
2941       break;
2942     case RPC_FC_ENUM16:
2943       safe_buffer_length_increment(pStubMsg, 2);
2944       pMemory += 4;
2945       break;
2946     case RPC_FC_LONG:
2947     case RPC_FC_ULONG:
2948     case RPC_FC_ENUM32:
2949       safe_buffer_length_increment(pStubMsg, 4);
2950       pMemory += 4;
2951       break;
2952     case RPC_FC_HYPER:
2953       safe_buffer_length_increment(pStubMsg, 8);
2954       pMemory += 8;
2955       break;
2956     case RPC_FC_POINTER:
2957       if (!pStubMsg->IgnoreEmbeddedPointers)
2958       {
2959         int saved_buffer_length = pStubMsg->BufferLength;
2960         pStubMsg->BufferLength = pStubMsg->PointerLength;
2961         pStubMsg->PointerLength = 0;
2962         if(!pStubMsg->BufferLength)
2963           ERR("BufferLength == 0??\n");
2964         PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2965         pStubMsg->PointerLength = pStubMsg->BufferLength;
2966         pStubMsg->BufferLength = saved_buffer_length;
2967       }
2968       if (*pPointer != RPC_FC_RP)
2969       {
2970         ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2971         safe_buffer_length_increment(pStubMsg, 4);
2972       }
2973       pPointer += 4;
2974       pMemory += sizeof(void*);
2975       break;
2976     case RPC_FC_ALIGNM2:
2977       ALIGN_POINTER(pMemory, 2);
2978       break;
2979     case RPC_FC_ALIGNM4:
2980       ALIGN_POINTER(pMemory, 4);
2981       break;
2982     case RPC_FC_ALIGNM8:
2983       ALIGN_POINTER(pMemory, 8);
2984       break;
2985     case RPC_FC_STRUCTPAD1:
2986     case RPC_FC_STRUCTPAD2:
2987     case RPC_FC_STRUCTPAD3:
2988     case RPC_FC_STRUCTPAD4:
2989     case RPC_FC_STRUCTPAD5:
2990     case RPC_FC_STRUCTPAD6:
2991     case RPC_FC_STRUCTPAD7:
2992       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2993       break;
2994     case RPC_FC_EMBEDDED_COMPLEX:
2995       pMemory += pFormat[1];
2996       pFormat += 2;
2997       desc = pFormat + *(const SHORT*)pFormat;
2998       size = EmbeddedComplexSize(pStubMsg, desc);
2999       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3000       if (m)
3001       {
3002         /* for some reason interface pointers aren't generated as
3003          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3004          * they still need the derefencing treatment that pointers are
3005          * given */
3006         if (*desc == RPC_FC_IP)
3007           m(pStubMsg, *(unsigned char **)pMemory, desc);
3008         else
3009           m(pStubMsg, pMemory, desc);
3010       }
3011       else FIXME("no buffersizer for embedded type %02x\n", *desc);
3012       pMemory += size;
3013       pFormat += 2;
3014       continue;
3015     case RPC_FC_PAD:
3016       break;
3017     default:
3018       FIXME("unhandled format 0x%02x\n", *pFormat);
3019     }
3020     pFormat++;
3021   }
3022
3023   return pMemory;
3024 }
3025
3026 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
3027                                    unsigned char *pMemory,
3028                                    PFORMAT_STRING pFormat,
3029                                    PFORMAT_STRING pPointer)
3030 {
3031   PFORMAT_STRING desc;
3032   NDR_FREE m;
3033   ULONG size;
3034
3035   while (*pFormat != RPC_FC_END) {
3036     switch (*pFormat) {
3037     case RPC_FC_BYTE:
3038     case RPC_FC_CHAR:
3039     case RPC_FC_SMALL:
3040     case RPC_FC_USMALL:
3041       pMemory += 1;
3042       break;
3043     case RPC_FC_WCHAR:
3044     case RPC_FC_SHORT:
3045     case RPC_FC_USHORT:
3046       pMemory += 2;
3047       break;
3048     case RPC_FC_LONG:
3049     case RPC_FC_ULONG:
3050     case RPC_FC_ENUM16:
3051     case RPC_FC_ENUM32:
3052       pMemory += 4;
3053       break;
3054     case RPC_FC_HYPER:
3055       pMemory += 8;
3056       break;
3057     case RPC_FC_POINTER:
3058       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3059       pPointer += 4;
3060       pMemory += sizeof(void *);
3061       break;
3062     case RPC_FC_ALIGNM2:
3063       ALIGN_POINTER(pMemory, 2);
3064       break;
3065     case RPC_FC_ALIGNM4:
3066       ALIGN_POINTER(pMemory, 4);
3067       break;
3068     case RPC_FC_ALIGNM8:
3069       ALIGN_POINTER(pMemory, 8);
3070       break;
3071     case RPC_FC_STRUCTPAD1:
3072     case RPC_FC_STRUCTPAD2:
3073     case RPC_FC_STRUCTPAD3:
3074     case RPC_FC_STRUCTPAD4:
3075     case RPC_FC_STRUCTPAD5:
3076     case RPC_FC_STRUCTPAD6:
3077     case RPC_FC_STRUCTPAD7:
3078       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3079       break;
3080     case RPC_FC_EMBEDDED_COMPLEX:
3081       pMemory += pFormat[1];
3082       pFormat += 2;
3083       desc = pFormat + *(const SHORT*)pFormat;
3084       size = EmbeddedComplexSize(pStubMsg, desc);
3085       m = NdrFreer[*desc & NDR_TABLE_MASK];
3086       if (m)
3087       {
3088         /* for some reason interface pointers aren't generated as
3089          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3090          * they still need the derefencing treatment that pointers are
3091          * given */
3092         if (*desc == RPC_FC_IP)
3093           m(pStubMsg, *(unsigned char **)pMemory, desc);
3094         else
3095           m(pStubMsg, pMemory, desc);
3096       }
3097       pMemory += size;
3098       pFormat += 2;
3099       continue;
3100     case RPC_FC_PAD:
3101       break;
3102     default:
3103       FIXME("unhandled format 0x%02x\n", *pFormat);
3104     }
3105     pFormat++;
3106   }
3107
3108   return pMemory;
3109 }
3110
3111 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3112                                      PFORMAT_STRING pFormat,
3113                                      PFORMAT_STRING pPointer)
3114 {
3115   PFORMAT_STRING desc;
3116   ULONG size = 0;
3117
3118   while (*pFormat != RPC_FC_END) {
3119     switch (*pFormat) {
3120     case RPC_FC_BYTE:
3121     case RPC_FC_CHAR:
3122     case RPC_FC_SMALL:
3123     case RPC_FC_USMALL:
3124       size += 1;
3125       safe_buffer_increment(pStubMsg, 1);
3126       break;
3127     case RPC_FC_WCHAR:
3128     case RPC_FC_SHORT:
3129     case RPC_FC_USHORT:
3130       size += 2;
3131       safe_buffer_increment(pStubMsg, 2);
3132       break;
3133     case RPC_FC_ENUM16:
3134       size += 4;
3135       safe_buffer_increment(pStubMsg, 2);
3136       break;
3137     case RPC_FC_LONG:
3138     case RPC_FC_ULONG:
3139     case RPC_FC_ENUM32:
3140       size += 4;
3141       safe_buffer_increment(pStubMsg, 4);
3142       break;
3143     case RPC_FC_HYPER:
3144       size += 8;
3145       safe_buffer_increment(pStubMsg, 8);
3146       break;
3147     case RPC_FC_POINTER:
3148     {
3149       unsigned char *saved_buffer;
3150       int pointer_buffer_mark_set = 0;
3151       if (*pPointer != RPC_FC_RP)
3152         ALIGN_POINTER(pStubMsg->Buffer, 4);
3153       saved_buffer = pStubMsg->Buffer;
3154       if (pStubMsg->PointerBufferMark)
3155       {
3156         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3157         pStubMsg->PointerBufferMark = NULL;
3158         pointer_buffer_mark_set = 1;
3159       }
3160       else if (*pPointer != RPC_FC_RP)
3161         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3162
3163       if (!pStubMsg->IgnoreEmbeddedPointers)
3164         PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3165       if (pointer_buffer_mark_set)
3166       {
3167         STD_OVERFLOW_CHECK(pStubMsg);
3168         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3169         pStubMsg->Buffer = saved_buffer;
3170         if (*pPointer != RPC_FC_RP)
3171           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3172       }
3173       pPointer += 4;
3174       size += sizeof(void *);
3175       break;
3176     }
3177     case RPC_FC_ALIGNM2:
3178       ALIGN_LENGTH(size, 2);
3179       break;
3180     case RPC_FC_ALIGNM4:
3181       ALIGN_LENGTH(size, 4);
3182       break;
3183     case RPC_FC_ALIGNM8:
3184       ALIGN_LENGTH(size, 8);
3185       break;
3186     case RPC_FC_STRUCTPAD1:
3187     case RPC_FC_STRUCTPAD2:
3188     case RPC_FC_STRUCTPAD3:
3189     case RPC_FC_STRUCTPAD4:
3190     case RPC_FC_STRUCTPAD5:
3191     case RPC_FC_STRUCTPAD6:
3192     case RPC_FC_STRUCTPAD7:
3193       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3194       break;
3195     case RPC_FC_EMBEDDED_COMPLEX:
3196       size += pFormat[1];
3197       pFormat += 2;
3198       desc = pFormat + *(const SHORT*)pFormat;
3199       size += EmbeddedComplexMemorySize(pStubMsg, desc);
3200       pFormat += 2;
3201       continue;
3202     case RPC_FC_PAD:
3203       break;
3204     default:
3205       FIXME("unhandled format 0x%02x\n", *pFormat);
3206     }
3207     pFormat++;
3208   }
3209
3210   return size;
3211 }
3212
3213 ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
3214 {
3215   PFORMAT_STRING desc;
3216   ULONG size = 0;
3217
3218   while (*pFormat != RPC_FC_END) {
3219     switch (*pFormat) {
3220     case RPC_FC_BYTE:
3221     case RPC_FC_CHAR:
3222     case RPC_FC_SMALL:
3223     case RPC_FC_USMALL:
3224       size += 1;
3225       break;
3226     case RPC_FC_WCHAR:
3227     case RPC_FC_SHORT:
3228     case RPC_FC_USHORT:
3229       size += 2;
3230       break;
3231     case RPC_FC_LONG:
3232     case RPC_FC_ULONG:
3233     case RPC_FC_ENUM16:
3234     case RPC_FC_ENUM32:
3235       size += 4;
3236       break;
3237     case RPC_FC_HYPER:
3238       size += 8;
3239       break;
3240     case RPC_FC_POINTER:
3241       size += sizeof(void *);
3242       break;
3243     case RPC_FC_ALIGNM2:
3244       ALIGN_LENGTH(size, 2);
3245       break;
3246     case RPC_FC_ALIGNM4:
3247       ALIGN_LENGTH(size, 4);
3248       break;
3249     case RPC_FC_ALIGNM8:
3250       ALIGN_LENGTH(size, 8);
3251       break;
3252     case RPC_FC_STRUCTPAD1:
3253     case RPC_FC_STRUCTPAD2:
3254     case RPC_FC_STRUCTPAD3:
3255     case RPC_FC_STRUCTPAD4:
3256     case RPC_FC_STRUCTPAD5:
3257     case RPC_FC_STRUCTPAD6:
3258     case RPC_FC_STRUCTPAD7:
3259       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3260       break;
3261     case RPC_FC_EMBEDDED_COMPLEX:
3262       size += pFormat[1];
3263       pFormat += 2;
3264       desc = pFormat + *(const SHORT*)pFormat;
3265       size += EmbeddedComplexSize(pStubMsg, desc);
3266       pFormat += 2;
3267       continue;
3268     case RPC_FC_PAD:
3269       break;
3270     default:
3271       FIXME("unhandled format 0x%02x\n", *pFormat);
3272     }
3273     pFormat++;
3274   }
3275
3276   return size;
3277 }
3278
3279 /***********************************************************************
3280  *           NdrComplexStructMarshall [RPCRT4.@]
3281  */
3282 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3283                                                 unsigned char *pMemory,
3284                                                 PFORMAT_STRING pFormat)
3285 {
3286   PFORMAT_STRING conf_array = NULL;
3287   PFORMAT_STRING pointer_desc = NULL;
3288   unsigned char *OldMemory = pStubMsg->Memory;
3289   int pointer_buffer_mark_set = 0;
3290   ULONG count = 0;
3291   ULONG max_count = 0;
3292   ULONG offset = 0;
3293
3294   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3295
3296   if (!pStubMsg->PointerBufferMark)
3297   {
3298     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3299     /* save buffer length */
3300     ULONG saved_buffer_length = pStubMsg->BufferLength;
3301
3302     /* get the buffer pointer after complex array data, but before
3303      * pointer data */
3304     pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3305     pStubMsg->IgnoreEmbeddedPointers = 1;
3306     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3307     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3308
3309     /* save it for use by embedded pointer code later */
3310     pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3311     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
3312     pointer_buffer_mark_set = 1;
3313
3314     /* restore the original buffer length */
3315     pStubMsg->BufferLength = saved_buffer_length;
3316   }
3317
3318   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
3319
3320   pFormat += 4;
3321   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3322   pFormat += 2;
3323   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3324   pFormat += 2;
3325
3326   pStubMsg->Memory = pMemory;
3327
3328   if (conf_array)
3329   {
3330     ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3331     array_compute_and_write_conformance(conf_array[0], pStubMsg,
3332                                         pMemory + struct_size, conf_array);
3333     /* these could be changed in ComplexMarshall so save them for later */
3334     max_count = pStubMsg->MaxCount;
3335     count = pStubMsg->ActualCount;
3336     offset = pStubMsg->Offset;
3337   }
3338
3339   pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3340
3341   if (conf_array)
3342   {
3343     pStubMsg->MaxCount = max_count;
3344     pStubMsg->ActualCount = count;
3345     pStubMsg->Offset = offset;
3346     array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3347                                       conf_array, TRUE /* fHasPointers */);
3348   }
3349
3350   pStubMsg->Memory = OldMemory;
3351
3352   if (pointer_buffer_mark_set)
3353   {
3354     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3355     pStubMsg->PointerBufferMark = NULL;
3356   }
3357
3358   STD_OVERFLOW_CHECK(pStubMsg);
3359
3360   return NULL;
3361 }
3362
3363 /***********************************************************************
3364  *           NdrComplexStructUnmarshall [RPCRT4.@]
3365  */
3366 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3367                                                   unsigned char **ppMemory,
3368                                                   PFORMAT_STRING pFormat,
3369                                                   unsigned char fMustAlloc)
3370 {
3371   unsigned size = *(const WORD*)(pFormat+2);
3372   PFORMAT_STRING conf_array = NULL;
3373   PFORMAT_STRING pointer_desc = NULL;
3374   unsigned char *pMemory;
3375   int pointer_buffer_mark_set = 0;
3376   ULONG count = 0;
3377   ULONG max_count = 0;
3378   ULONG offset = 0;
3379   ULONG array_size = 0;
3380
3381   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3382
3383   if (!pStubMsg->PointerBufferMark)
3384   {
3385     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3386     /* save buffer pointer */
3387     unsigned char *saved_buffer = pStubMsg->Buffer;
3388
3389     /* get the buffer pointer after complex array data, but before
3390      * pointer data */
3391     pStubMsg->IgnoreEmbeddedPointers = 1;
3392     NdrComplexStructMemorySize(pStubMsg, pFormat);
3393     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3394
3395     /* save it for use by embedded pointer code later */
3396     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3397     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
3398     pointer_buffer_mark_set = 1;
3399
3400     /* restore the original buffer */
3401     pStubMsg->Buffer = saved_buffer;
3402   }
3403
3404   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3405
3406   pFormat += 4;
3407   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3408   pFormat += 2;
3409   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3410   pFormat += 2;
3411
3412   if (conf_array)
3413   {
3414     array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3415     size += array_size;
3416
3417     /* these could be changed in ComplexMarshall so save them for later */
3418     max_count = pStubMsg->MaxCount;
3419     count = pStubMsg->ActualCount;
3420     offset = pStubMsg->Offset;
3421   }
3422
3423   if (!fMustAlloc && !*ppMemory)
3424     fMustAlloc = TRUE;
3425   if (fMustAlloc)
3426     *ppMemory = NdrAllocate(pStubMsg, size);
3427
3428   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3429
3430   if (conf_array)
3431   {
3432     pStubMsg->MaxCount = max_count;
3433     pStubMsg->ActualCount = count;
3434     pStubMsg->Offset = offset;
3435     if (fMustAlloc)
3436       memset(pMemory, 0, array_size);
3437     array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3438                                        conf_array, FALSE,
3439                                        FALSE /* fUseBufferMemoryServer */,
3440                                        TRUE /* fUnmarshall */);
3441   }
3442
3443   if (pointer_buffer_mark_set)
3444   {
3445     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3446     pStubMsg->PointerBufferMark = NULL;
3447   }
3448
3449   return NULL;
3450 }
3451
3452 /***********************************************************************
3453  *           NdrComplexStructBufferSize [RPCRT4.@]
3454  */
3455 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3456                                        unsigned char *pMemory,
3457                                        PFORMAT_STRING pFormat)
3458 {
3459   PFORMAT_STRING conf_array = NULL;
3460   PFORMAT_STRING pointer_desc = NULL;
3461   unsigned char *OldMemory = pStubMsg->Memory;
3462   int pointer_length_set = 0;
3463   ULONG count = 0;
3464   ULONG max_count = 0;
3465   ULONG offset = 0;
3466
3467   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3468
3469   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
3470
3471   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3472   {
3473     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3474     ULONG saved_buffer_length = pStubMsg->BufferLength;
3475
3476     /* get the buffer length after complex struct data, but before
3477      * pointer data */
3478     pStubMsg->IgnoreEmbeddedPointers = 1;
3479     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3480     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3481
3482     /* save it for use by embedded pointer code later */
3483     pStubMsg->PointerLength = pStubMsg->BufferLength;
3484     pointer_length_set = 1;
3485     TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
3486
3487     /* restore the original buffer length */
3488     pStubMsg->BufferLength = saved_buffer_length;
3489   }
3490
3491   pFormat += 4;
3492   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3493   pFormat += 2;
3494   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3495   pFormat += 2;
3496
3497   pStubMsg->Memory = pMemory;
3498
3499   if (conf_array)
3500   {
3501     ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3502     array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3503                                        conf_array);
3504
3505     /* these could be changed in ComplexMarshall so save them for later */
3506     max_count = pStubMsg->MaxCount;
3507     count = pStubMsg->ActualCount;
3508     offset = pStubMsg->Offset;
3509   }
3510
3511   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3512
3513   if (conf_array)
3514   {
3515     pStubMsg->MaxCount = max_count;
3516     pStubMsg->ActualCount = count;
3517     pStubMsg->Offset = offset;
3518     array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3519                       TRUE /* fHasPointers */);
3520   }
3521
3522   pStubMsg->Memory = OldMemory;
3523
3524   if(pointer_length_set)
3525   {
3526     pStubMsg->BufferLength = pStubMsg->PointerLength;
3527     pStubMsg->PointerLength = 0;
3528   }
3529
3530 }
3531
3532 /***********************************************************************
3533  *           NdrComplexStructMemorySize [RPCRT4.@]
3534  */
3535 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3536                                         PFORMAT_STRING pFormat)
3537 {
3538   unsigned size = *(const WORD*)(pFormat+2);
3539   PFORMAT_STRING conf_array = NULL;
3540   PFORMAT_STRING pointer_desc = NULL;
3541   ULONG count = 0;
3542   ULONG max_count = 0;
3543   ULONG offset = 0;
3544
3545   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3546
3547   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3548
3549   pFormat += 4;
3550   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3551   pFormat += 2;
3552   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3553   pFormat += 2;
3554
3555   if (conf_array)
3556   {
3557     array_read_conformance(conf_array[0], pStubMsg, conf_array);
3558
3559     /* these could be changed in ComplexStructMemorySize so save them for
3560      * later */
3561     max_count = pStubMsg->MaxCount;
3562     count = pStubMsg->ActualCount;
3563     offset = pStubMsg->Offset;
3564   }
3565
3566   ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3567
3568   if (conf_array)
3569   {
3570     pStubMsg->MaxCount = max_count;
3571     pStubMsg->ActualCount = count;
3572     pStubMsg->Offset = offset;
3573     array_memory_size(conf_array[0], pStubMsg, conf_array,
3574                       TRUE /* fHasPointers */);
3575   }
3576
3577   return size;
3578 }
3579
3580 /***********************************************************************
3581  *           NdrComplexStructFree [RPCRT4.@]
3582  */
3583 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3584                                  unsigned char *pMemory,
3585                                  PFORMAT_STRING pFormat)
3586 {
3587   PFORMAT_STRING conf_array = NULL;
3588   PFORMAT_STRING pointer_desc = NULL;
3589   unsigned char *OldMemory = pStubMsg->Memory;
3590
3591   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3592
3593   pFormat += 4;
3594   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3595   pFormat += 2;
3596   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3597   pFormat += 2;
3598
3599   pStubMsg->Memory = pMemory;
3600
3601   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3602
3603   if (conf_array)
3604     array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3605                TRUE /* fHasPointers */);
3606
3607   pStubMsg->Memory = OldMemory;
3608 }
3609
3610 /***********************************************************************
3611  *           NdrConformantArrayMarshall [RPCRT4.@]
3612  */
3613 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3614                                                   unsigned char *pMemory,
3615                                                   PFORMAT_STRING pFormat)
3616 {
3617   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3618   if (pFormat[0] != RPC_FC_CARRAY)
3619   {
3620     ERR("invalid format = 0x%x\n", pFormat[0]);
3621     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3622   }
3623
3624   array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
3625                                       pFormat);
3626   array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3627                                     TRUE /* fHasPointers */);
3628
3629   return NULL;
3630 }
3631
3632 /***********************************************************************
3633  *           NdrConformantArrayUnmarshall [RPCRT4.@]
3634  */
3635 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3636                                                     unsigned char **ppMemory,
3637                                                     PFORMAT_STRING pFormat,
3638                                                     unsigned char fMustAlloc)
3639 {
3640   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3641   if (pFormat[0] != RPC_FC_CARRAY)
3642   {
3643     ERR("invalid format = 0x%x\n", pFormat[0]);
3644     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3645   }
3646
3647   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3648   array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
3649                                      fMustAlloc,
3650                                      TRUE /* fUseBufferMemoryServer */,
3651                                      TRUE /* fUnmarshall */);
3652
3653   return NULL;
3654 }
3655
3656 /***********************************************************************
3657  *           NdrConformantArrayBufferSize [RPCRT4.@]
3658  */
3659 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3660                                          unsigned char *pMemory,
3661                                          PFORMAT_STRING pFormat)
3662 {
3663   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3664   if (pFormat[0] != RPC_FC_CARRAY)
3665   {
3666     ERR("invalid format = 0x%x\n", pFormat[0]);
3667     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3668   }
3669
3670   array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat);
3671   array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3672                     TRUE /* fHasPointers */);
3673 }
3674
3675 /***********************************************************************
3676  *           NdrConformantArrayMemorySize [RPCRT4.@]
3677  */
3678 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3679                                           PFORMAT_STRING pFormat)
3680 {
3681   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3682   if (pFormat[0] != RPC_FC_CARRAY)
3683   {
3684     ERR("invalid format = 0x%x\n", pFormat[0]);
3685     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3686   }
3687
3688   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3689   array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
3690
3691   return pStubMsg->MemorySize;
3692 }
3693
3694 /***********************************************************************
3695  *           NdrConformantArrayFree [RPCRT4.@]
3696  */
3697 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3698                                    unsigned char *pMemory,
3699                                    PFORMAT_STRING pFormat)
3700 {
3701   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3702   if (pFormat[0] != RPC_FC_CARRAY)
3703   {
3704     ERR("invalid format = 0x%x\n", pFormat[0]);
3705     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3706   }
3707
3708   array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3709              TRUE /* fHasPointers */);
3710 }
3711
3712
3713 /***********************************************************************
3714  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
3715  */
3716 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
3717                                                          unsigned char* pMemory,
3718                                                          PFORMAT_STRING pFormat )
3719 {
3720     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3721
3722     if (pFormat[0] != RPC_FC_CVARRAY)
3723     {
3724         ERR("invalid format type %x\n", pFormat[0]);
3725         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3726         return NULL;
3727     }
3728
3729     array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3730                                         pFormat);
3731     array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory,
3732                                       pFormat, TRUE /* fHasPointers */);
3733
3734     return NULL;
3735 }
3736
3737
3738 /***********************************************************************
3739  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
3740  */
3741 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
3742                                                            unsigned char** ppMemory,
3743                                                            PFORMAT_STRING pFormat,
3744                                                            unsigned char fMustAlloc )
3745 {
3746     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3747
3748     if (pFormat[0] != RPC_FC_CVARRAY)
3749     {
3750         ERR("invalid format type %x\n", pFormat[0]);
3751         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3752         return NULL;
3753     }
3754
3755     array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3756     array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory,
3757                                        pFormat, fMustAlloc,
3758                                        TRUE /* fUseBufferMemoryServer */,
3759                                        TRUE /* fUnmarshall */);
3760
3761     return NULL;
3762 }
3763
3764
3765 /***********************************************************************
3766  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
3767  */
3768 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
3769                                            unsigned char* pMemory,
3770                                            PFORMAT_STRING pFormat )
3771 {
3772     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3773
3774     if (pFormat[0] != RPC_FC_CVARRAY)
3775     {
3776         ERR("invalid format type %x\n", pFormat[0]);
3777         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3778         return;
3779     }
3780
3781     array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3782                TRUE /* fHasPointers */);
3783 }
3784
3785
3786 /***********************************************************************
3787  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
3788  */
3789 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
3790                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
3791 {
3792     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3793
3794     if (pFormat[0] != RPC_FC_CVARRAY)
3795     {
3796         ERR("invalid format type %x\n", pFormat[0]);
3797         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3798         return;
3799     }
3800
3801     array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3802                                        pFormat);
3803     array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3804                       TRUE /* fHasPointers */);
3805 }
3806
3807
3808 /***********************************************************************
3809  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
3810  */
3811 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
3812                                                   PFORMAT_STRING pFormat )
3813 {
3814     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3815
3816     if (pFormat[0] != RPC_FC_CVARRAY)
3817     {
3818         ERR("invalid format type %x\n", pFormat[0]);
3819         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3820         return pStubMsg->MemorySize;
3821     }
3822
3823     array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3824     array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat,
3825                       TRUE /* fHasPointers */);
3826
3827     return pStubMsg->MemorySize;
3828 }
3829
3830
3831 /***********************************************************************
3832  *           NdrComplexArrayMarshall [RPCRT4.@]
3833  */
3834 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3835                                                unsigned char *pMemory,
3836                                                PFORMAT_STRING pFormat)
3837 {
3838   ULONG i, count, def;
3839   BOOL variance_present;
3840   unsigned char alignment;
3841   int pointer_buffer_mark_set = 0;
3842
3843   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3844
3845   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3846   {
3847       ERR("invalid format type %x\n", pFormat[0]);
3848       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3849       return NULL;
3850   }
3851
3852   alignment = pFormat[1] + 1;
3853
3854   if (!pStubMsg->PointerBufferMark)
3855   {
3856     /* save buffer fields that may be changed by buffer sizer functions
3857      * and that may be needed later on */
3858     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3859     ULONG saved_buffer_length = pStubMsg->BufferLength;
3860     ULONG_PTR saved_max_count = pStubMsg->MaxCount;
3861     ULONG saved_offset = pStubMsg->Offset;
3862     ULONG saved_actual_count = pStubMsg->ActualCount;
3863
3864     /* get the buffer pointer after complex array data, but before
3865      * pointer data */
3866     pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3867     pStubMsg->IgnoreEmbeddedPointers = 1;
3868     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3869     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3870
3871     /* save it for use by embedded pointer code later */
3872     pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3873     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
3874     pointer_buffer_mark_set = 1;
3875
3876     /* restore fields */
3877     pStubMsg->ActualCount = saved_actual_count;
3878     pStubMsg->Offset = saved_offset;
3879     pStubMsg->MaxCount = saved_max_count;
3880     pStubMsg->BufferLength = saved_buffer_length;
3881   }
3882
3883   def = *(const WORD*)&pFormat[2];
3884   pFormat += 4;
3885
3886   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3887   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3888
3889   variance_present = IsConformanceOrVariancePresent(pFormat);
3890   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3891   TRACE("variance = %d\n", pStubMsg->ActualCount);
3892
3893   WriteConformance(pStubMsg);
3894   if (variance_present)
3895     WriteVariance(pStubMsg);
3896
3897   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3898
3899   count = pStubMsg->ActualCount;
3900   for (i = 0; i < count; i++)
3901     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3902
3903   STD_OVERFLOW_CHECK(pStubMsg);
3904
3905   if (pointer_buffer_mark_set)
3906   {
3907     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3908     pStubMsg->PointerBufferMark = NULL;
3909   }
3910
3911   return NULL;
3912 }
3913
3914 /***********************************************************************
3915  *           NdrComplexArrayUnmarshall [RPCRT4.@]
3916  */
3917 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3918                                                  unsigned char **ppMemory,
3919                                                  PFORMAT_STRING pFormat,
3920                                                  unsigned char fMustAlloc)
3921 {
3922   ULONG i, count, size;
3923   unsigned char alignment;
3924   unsigned char *pMemory;
3925   unsigned char *saved_buffer;
3926   int pointer_buffer_mark_set = 0;
3927   int saved_ignore_embedded;
3928
3929   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3930
3931   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3932   {
3933       ERR("invalid format type %x\n", pFormat[0]);
3934       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3935       return NULL;
3936   }
3937
3938   alignment = pFormat[1] + 1;
3939
3940   saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3941   /* save buffer pointer */
3942   saved_buffer = pStubMsg->Buffer;
3943   /* get the buffer pointer after complex array data, but before
3944    * pointer data */
3945   pStubMsg->IgnoreEmbeddedPointers = 1;
3946   pStubMsg->MemorySize = 0;
3947   NdrComplexArrayMemorySize(pStubMsg, pFormat);
3948   size = pStubMsg->MemorySize;
3949   pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3950
3951   TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer));
3952   if (!pStubMsg->PointerBufferMark)
3953   {
3954     /* save it for use by embedded pointer code later */
3955     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3956     pointer_buffer_mark_set = 1;
3957   }
3958   /* restore the original buffer */
3959   pStubMsg->Buffer = saved_buffer;
3960
3961   pFormat += 4;
3962
3963   pFormat = ReadConformance(pStubMsg, pFormat);
3964   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3965
3966   if (!fMustAlloc && !*ppMemory)
3967     fMustAlloc = TRUE;
3968   if (fMustAlloc)
3969     *ppMemory = NdrAllocate(pStubMsg, size);
3970
3971   ALIGN_POINTER(pStubMsg->Buffer, alignment);
3972
3973   pMemory = *ppMemory;
3974   count = pStubMsg->ActualCount;
3975   for (i = 0; i < count; i++)
3976     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
3977
3978   if (pointer_buffer_mark_set)
3979   {
3980     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3981     pStubMsg->PointerBufferMark = NULL;
3982   }
3983
3984   return NULL;
3985 }
3986
3987 /***********************************************************************
3988  *           NdrComplexArrayBufferSize [RPCRT4.@]
3989  */
3990 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3991                                       unsigned char *pMemory,
3992                                       PFORMAT_STRING pFormat)
3993 {
3994   ULONG i, count, def;
3995   unsigned char alignment;
3996   BOOL variance_present;
3997   int pointer_length_set = 0;
3998
3999   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4000
4001   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4002   {
4003       ERR("invalid format type %x\n", pFormat[0]);
4004       RpcRaiseException(RPC_S_INTERNAL_ERROR);
4005       return;
4006   }
4007
4008   alignment = pFormat[1] + 1;
4009
4010   if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
4011   {
4012     /* save buffer fields that may be changed by buffer sizer functions
4013      * and that may be needed later on */
4014     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4015     ULONG saved_buffer_length = pStubMsg->BufferLength;
4016     ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4017     ULONG saved_offset = pStubMsg->Offset;
4018     ULONG saved_actual_count = pStubMsg->ActualCount;
4019
4020     /* get the buffer pointer after complex array data, but before
4021      * pointer data */
4022     pStubMsg->IgnoreEmbeddedPointers = 1;
4023     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4024     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4025
4026     /* save it for use by embedded pointer code later */
4027     pStubMsg->PointerLength = pStubMsg->BufferLength;
4028     pointer_length_set = 1;
4029
4030     /* restore fields */
4031     pStubMsg->ActualCount = saved_actual_count;
4032     pStubMsg->Offset = saved_offset;
4033     pStubMsg->MaxCount = saved_max_count;
4034     pStubMsg->BufferLength = saved_buffer_length;
4035   }
4036   def = *(const WORD*)&pFormat[2];
4037   pFormat += 4;
4038
4039   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4040   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4041   SizeConformance(pStubMsg);
4042
4043   variance_present = IsConformanceOrVariancePresent(pFormat);
4044   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4045   TRACE("variance = %d\n", pStubMsg->ActualCount);
4046
4047   if (variance_present)
4048     SizeVariance(pStubMsg);
4049
4050   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4051
4052   count = pStubMsg->ActualCount;
4053   for (i = 0; i < count; i++)
4054     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
4055
4056   if(pointer_length_set)
4057   {
4058     pStubMsg->BufferLength = pStubMsg->PointerLength;
4059     pStubMsg->PointerLength = 0;
4060   }
4061 }
4062
4063 /***********************************************************************
4064  *           NdrComplexArrayMemorySize [RPCRT4.@]
4065  */
4066 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4067                                        PFORMAT_STRING pFormat)
4068 {
4069   ULONG i, count, esize, SavedMemorySize, MemorySize;
4070   unsigned char alignment;
4071
4072   TRACE("(%p,%p)\n", pStubMsg, pFormat);
4073
4074   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4075   {
4076       ERR("invalid format type %x\n", pFormat[0]);
4077       RpcRaiseException(RPC_S_INTERNAL_ERROR);
4078       return 0;
4079   }
4080
4081   alignment = pFormat[1] + 1;
4082
4083   pFormat += 4;
4084
4085   pFormat = ReadConformance(pStubMsg, pFormat);
4086   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
4087
4088   ALIGN_POINTER(pStubMsg->Buffer, alignment);
4089
4090   SavedMemorySize = pStubMsg->MemorySize;
4091
4092   esize = ComplexStructSize(pStubMsg, pFormat);
4093
4094   MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
4095
4096   count = pStubMsg->ActualCount;
4097   for (i = 0; i < count; i++)
4098     ComplexStructMemorySize(pStubMsg, pFormat, NULL);
4099
4100   pStubMsg->MemorySize = SavedMemorySize;
4101
4102   pStubMsg->MemorySize += MemorySize;
4103   return MemorySize;
4104 }
4105
4106 /***********************************************************************
4107  *           NdrComplexArrayFree [RPCRT4.@]
4108  */
4109 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4110                                 unsigned char *pMemory,
4111                                 PFORMAT_STRING pFormat)
4112 {
4113   ULONG i, count, def;
4114
4115   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4116
4117   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4118   {
4119       ERR("invalid format type %x\n", pFormat[0]);
4120       RpcRaiseException(RPC_S_INTERNAL_ERROR);
4121       return;
4122   }
4123
4124   def = *(const WORD*)&pFormat[2];
4125   pFormat += 4;
4126
4127   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4128   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4129
4130   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4131   TRACE("variance = %d\n", pStubMsg->ActualCount);
4132
4133   count = pStubMsg->ActualCount;
4134   for (i = 0; i < count; i++)
4135     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
4136 }
4137
4138 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
4139                           USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
4140                           USER_MARSHAL_CB *umcb)
4141 {
4142   umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
4143                          pStubMsg->RpcMsg->DataRepresentation);
4144   umcb->pStubMsg = pStubMsg;
4145   umcb->pReserve = NULL;
4146   umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
4147   umcb->CBType = cbtype;
4148   umcb->pFormat = pFormat;
4149   umcb->pTypeFormat = NULL /* FIXME */;
4150 }
4151
4152 #define USER_MARSHAL_PTR_PREFIX \
4153         ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
4154         ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
4155
4156 /***********************************************************************
4157  *           NdrUserMarshalMarshall [RPCRT4.@]
4158  */
4159 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4160                                               unsigned char *pMemory,
4161                                               PFORMAT_STRING pFormat)
4162 {
4163   unsigned flags = pFormat[1];
4164   unsigned index = *(const WORD*)&pFormat[2];
4165   unsigned char *saved_buffer = NULL;
4166   USER_MARSHAL_CB umcb;
4167
4168   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4169   TRACE("index=%d\n", index);
4170
4171   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
4172
4173   if (flags & USER_MARSHAL_POINTER)
4174   {
4175     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
4176     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
4177     pStubMsg->Buffer += 4;
4178     if (pStubMsg->PointerBufferMark)
4179     {
4180       saved_buffer = pStubMsg->Buffer;
4181       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4182       pStubMsg->PointerBufferMark = NULL;
4183     }
4184     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8);
4185   }
4186   else
4187     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1);
4188
4189   pStubMsg->Buffer =
4190     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
4191       &umcb.Flags, pStubMsg->Buffer, pMemory);
4192
4193   if (saved_buffer)
4194   {
4195     STD_OVERFLOW_CHECK(pStubMsg);
4196     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4197     pStubMsg->Buffer = saved_buffer;
4198   }
4199
4200   STD_OVERFLOW_CHECK(pStubMsg);
4201
4202   return NULL;
4203 }
4204
4205 /***********************************************************************
4206  *           NdrUserMarshalUnmarshall [RPCRT4.@]
4207  */
4208 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4209                                                  unsigned char **ppMemory,
4210                                                  PFORMAT_STRING pFormat,
4211                                                  unsigned char fMustAlloc)
4212 {
4213   unsigned flags = pFormat[1];
4214   unsigned index = *(const WORD*)&pFormat[2];
4215   DWORD memsize = *(const WORD*)&pFormat[4];
4216   unsigned char *saved_buffer = NULL;
4217   USER_MARSHAL_CB umcb;
4218
4219   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4220   TRACE("index=%d\n", index);
4221
4222   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
4223
4224   if (flags & USER_MARSHAL_POINTER)
4225   {
4226     ALIGN_POINTER(pStubMsg->Buffer, 4);
4227     /* skip pointer prefix */
4228     pStubMsg->Buffer += 4;
4229     if (pStubMsg->PointerBufferMark)
4230     {
4231       saved_buffer = pStubMsg->Buffer;
4232       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4233       pStubMsg->PointerBufferMark = NULL;
4234     }
4235     ALIGN_POINTER(pStubMsg->Buffer, 8);
4236   }
4237   else
4238     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4239
4240   if (!fMustAlloc && !*ppMemory)
4241     fMustAlloc = TRUE;
4242   if (fMustAlloc)
4243   {
4244     *ppMemory = NdrAllocate(pStubMsg, memsize);
4245     memset(*ppMemory, 0, memsize);
4246   }
4247
4248   pStubMsg->Buffer =
4249     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
4250       &umcb.Flags, pStubMsg->Buffer, *ppMemory);
4251
4252   if (saved_buffer)
4253   {
4254     STD_OVERFLOW_CHECK(pStubMsg);
4255     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4256     pStubMsg->Buffer = saved_buffer;
4257   }
4258
4259   return NULL;
4260 }
4261
4262 /***********************************************************************
4263  *           NdrUserMarshalBufferSize [RPCRT4.@]
4264  */
4265 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4266                                       unsigned char *pMemory,
4267                                       PFORMAT_STRING pFormat)
4268 {
4269   unsigned flags = pFormat[1];
4270   unsigned index = *(const WORD*)&pFormat[2];
4271   DWORD bufsize = *(const WORD*)&pFormat[6];
4272   USER_MARSHAL_CB umcb;
4273   ULONG saved_buffer_length = 0;
4274
4275   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4276   TRACE("index=%d\n", index);
4277
4278   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
4279
4280   if (flags & USER_MARSHAL_POINTER)
4281   {
4282     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4283     /* skip pointer prefix */
4284     safe_buffer_length_increment(pStubMsg, 4);
4285     if (pStubMsg->IgnoreEmbeddedPointers)
4286       return;
4287     if (pStubMsg->PointerLength)
4288     {
4289       saved_buffer_length = pStubMsg->BufferLength;
4290       pStubMsg->BufferLength = pStubMsg->PointerLength;
4291       pStubMsg->PointerLength = 0;
4292     }
4293     ALIGN_LENGTH(pStubMsg->BufferLength, 8);
4294   }
4295   else
4296     ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
4297
4298   if (bufsize) {
4299     TRACE("size=%d\n", bufsize);
4300     safe_buffer_length_increment(pStubMsg, bufsize);
4301   }
4302   else
4303     pStubMsg->BufferLength =
4304         pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
4305                              &umcb.Flags, pStubMsg->BufferLength, pMemory);
4306
4307   if (saved_buffer_length)
4308   {
4309     pStubMsg->PointerLength = pStubMsg->BufferLength;
4310     pStubMsg->BufferLength = saved_buffer_length;
4311   }
4312
4313 }
4314
4315 /***********************************************************************
4316  *           NdrUserMarshalMemorySize [RPCRT4.@]
4317  */
4318 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4319                                       PFORMAT_STRING pFormat)
4320 {
4321   unsigned flags = pFormat[1];
4322   unsigned index = *(const WORD*)&pFormat[2];
4323   DWORD memsize = *(const WORD*)&pFormat[4];
4324   DWORD bufsize = *(const WORD*)&pFormat[6];
4325
4326   TRACE("(%p,%p)\n", pStubMsg, pFormat);
4327   TRACE("index=%d\n", index);
4328
4329   pStubMsg->MemorySize += memsize;
4330
4331   if (flags & USER_MARSHAL_POINTER)
4332   {
4333     ALIGN_POINTER(pStubMsg->Buffer, 4);
4334     /* skip pointer prefix */
4335     pStubMsg->Buffer += 4;
4336     if (pStubMsg->IgnoreEmbeddedPointers)
4337       return pStubMsg->MemorySize;
4338     ALIGN_POINTER(pStubMsg->Buffer, 8);
4339   }
4340   else
4341     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4342
4343   if (!bufsize)
4344     FIXME("not implemented for varying buffer size\n");
4345
4346   pStubMsg->Buffer += bufsize;
4347
4348   return pStubMsg->MemorySize;
4349 }
4350
4351 /***********************************************************************
4352  *           NdrUserMarshalFree [RPCRT4.@]
4353  */
4354 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
4355                                 unsigned char *pMemory,
4356                                 PFORMAT_STRING pFormat)
4357 {
4358 /*  unsigned flags = pFormat[1]; */
4359   unsigned index = *(const WORD*)&pFormat[2];
4360   USER_MARSHAL_CB umcb;
4361
4362   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4363   TRACE("index=%d\n", index);
4364
4365   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
4366
4367   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
4368     &umcb.Flags, pMemory);
4369 }
4370
4371 /***********************************************************************
4372  *           NdrGetUserMarshalInfo [RPCRT4.@]
4373  */
4374 RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi)
4375 {
4376     USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags);
4377
4378     TRACE("(%p,%u,%p)\n", flags, level, umi);
4379
4380     if (level != 1)
4381         return RPC_S_INVALID_ARG;
4382
4383     memset(&umi->u1.Level1, 0, sizeof(umi->u1.Level1));
4384     umi->InformationLevel = level;
4385
4386     if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE)
4387         return RPC_S_INVALID_ARG;
4388
4389     umi->u1.Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate;
4390     umi->u1.Level1.pfnFree = umcb->pStubMsg->pfnFree;
4391     umi->u1.Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer;
4392
4393     switch (umcb->CBType)
4394     {
4395     case USER_MARSHAL_CB_MARSHALL:
4396     case USER_MARSHAL_CB_UNMARSHALL:
4397     {
4398         RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg;
4399         unsigned char *buffer_start = msg->Buffer;
4400         unsigned char *buffer_end =
4401             (unsigned char *)msg->Buffer + msg->BufferLength;
4402
4403         if (umcb->pStubMsg->Buffer < buffer_start ||
4404             umcb->pStubMsg->Buffer > buffer_end)
4405             return ERROR_INVALID_USER_BUFFER;
4406
4407         umi->u1.Level1.Buffer = umcb->pStubMsg->Buffer;
4408         umi->u1.Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer;
4409         break;
4410     }
4411     case USER_MARSHAL_CB_BUFFER_SIZE:
4412     case USER_MARSHAL_CB_FREE:
4413         break;
4414     default:
4415         WARN("unrecognised CBType %d\n", umcb->CBType);
4416     }
4417
4418     return RPC_S_OK;
4419 }
4420
4421 /***********************************************************************
4422  *           NdrClearOutParameters [RPCRT4.@]
4423  */
4424 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
4425                                   PFORMAT_STRING pFormat,
4426                                   void *ArgAddr)
4427 {
4428   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
4429 }
4430
4431 /***********************************************************************
4432  *           NdrConvert [RPCRT4.@]
4433  */
4434 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
4435 {
4436   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
4437   /* FIXME: since this stub doesn't do any converting, the proper behavior
4438      is to raise an exception */
4439 }
4440
4441 /***********************************************************************
4442  *           NdrConvert2 [RPCRT4.@]
4443  */
4444 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
4445 {
4446   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
4447     pStubMsg, pFormat, NumberParams);
4448   /* FIXME: since this stub doesn't do any converting, the proper behavior
4449      is to raise an exception */
4450 }
4451
4452 #include "pshpack1.h"
4453 typedef struct _NDR_CSTRUCT_FORMAT
4454 {
4455     unsigned char type;
4456     unsigned char alignment;
4457     unsigned short memory_size;
4458     short offset_to_array_description;
4459 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
4460 #include "poppack.h"
4461
4462 /***********************************************************************
4463  *           NdrConformantStructMarshall [RPCRT4.@]
4464  */
4465 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4466                                 unsigned char *pMemory,
4467                                 PFORMAT_STRING pFormat)
4468 {
4469     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4470     PFORMAT_STRING pCArrayFormat;
4471     ULONG esize, bufsize;
4472
4473     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4474
4475     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4476     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4477     {
4478         ERR("invalid format type %x\n", pCStructFormat->type);
4479         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4480         return NULL;
4481     }
4482
4483     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4484         pCStructFormat->offset_to_array_description;
4485     if (*pCArrayFormat != RPC_FC_CARRAY)
4486     {
4487         ERR("invalid array format type %x\n", pCStructFormat->type);
4488         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4489         return NULL;
4490     }
4491     esize = *(const WORD*)(pCArrayFormat+2);
4492
4493     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4494                        pCArrayFormat + 4, 0);
4495
4496     WriteConformance(pStubMsg);
4497
4498     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4499
4500     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4501
4502     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4503     if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4504     {
4505         ERR("integer overflow of memory_size %u with bufsize %u\n",
4506             pCStructFormat->memory_size, bufsize);
4507         RpcRaiseException(RPC_X_BAD_STUB_DATA);
4508     }
4509     /* copy constant sized part of struct */
4510     pStubMsg->BufferMark = pStubMsg->Buffer;
4511     safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
4512
4513     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4514         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4515
4516     return NULL;
4517 }
4518
4519 /***********************************************************************
4520  *           NdrConformantStructUnmarshall [RPCRT4.@]
4521  */
4522 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4523                                 unsigned char **ppMemory,
4524                                 PFORMAT_STRING pFormat,
4525                                 unsigned char fMustAlloc)
4526 {
4527     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4528     PFORMAT_STRING pCArrayFormat;
4529     ULONG esize, bufsize;
4530     unsigned char *saved_buffer;
4531
4532     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4533
4534     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4535     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4536     {
4537         ERR("invalid format type %x\n", pCStructFormat->type);
4538         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4539         return NULL;
4540     }
4541     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4542         pCStructFormat->offset_to_array_description;
4543     if (*pCArrayFormat != RPC_FC_CARRAY)
4544     {
4545         ERR("invalid array format type %x\n", pCStructFormat->type);
4546         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4547         return NULL;
4548     }
4549     esize = *(const WORD*)(pCArrayFormat+2);
4550
4551     pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
4552
4553     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4554
4555     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4556
4557     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4558     if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4559     {
4560         ERR("integer overflow of memory_size %u with bufsize %u\n",
4561             pCStructFormat->memory_size, bufsize);
4562         RpcRaiseException(RPC_X_BAD_STUB_DATA);
4563     }
4564
4565     if (fMustAlloc)
4566     {
4567         SIZE_T size = pCStructFormat->memory_size + bufsize;
4568         *ppMemory = NdrAllocate(pStubMsg, size);
4569     }
4570     else
4571     {
4572         if (!pStubMsg->IsClient && !*ppMemory)
4573             /* for servers, we just point straight into the RPC buffer */
4574             *ppMemory = pStubMsg->Buffer;
4575     }
4576
4577     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4578     safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
4579     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4580         EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4581
4582     TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4583     if (*ppMemory != saved_buffer)
4584         memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
4585
4586     return NULL;
4587 }
4588
4589 /***********************************************************************
4590  *           NdrConformantStructBufferSize [RPCRT4.@]
4591  */
4592 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4593                                 unsigned char *pMemory,
4594                                 PFORMAT_STRING pFormat)
4595 {
4596     const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4597     PFORMAT_STRING pCArrayFormat;
4598     ULONG esize;
4599
4600     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4601
4602     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4603     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4604     {
4605         ERR("invalid format type %x\n", pCStructFormat->type);
4606         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4607         return;
4608     }
4609     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4610         pCStructFormat->offset_to_array_description;
4611     if (*pCArrayFormat != RPC_FC_CARRAY)
4612     {
4613         ERR("invalid array format type %x\n", pCStructFormat->type);
4614         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4615         return;
4616     }
4617     esize = *(const WORD*)(pCArrayFormat+2);
4618
4619     pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
4620     SizeConformance(pStubMsg);
4621
4622     ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
4623
4624     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4625
4626     safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
4627     safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4628
4629     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4630         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4631 }
4632
4633 /***********************************************************************
4634  *           NdrConformantStructMemorySize [RPCRT4.@]
4635  */
4636 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4637                                 PFORMAT_STRING pFormat)
4638 {
4639     FIXME("stub\n");
4640     return 0;
4641 }
4642
4643 /***********************************************************************
4644  *           NdrConformantStructFree [RPCRT4.@]
4645  */
4646 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4647                                 unsigned char *pMemory,
4648                                 PFORMAT_STRING pFormat)
4649 {
4650     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4651     PFORMAT_STRING pCArrayFormat;
4652
4653     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4654
4655     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4656     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4657     {
4658         ERR("invalid format type %x\n", pCStructFormat->type);
4659         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4660         return;
4661     }
4662
4663     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4664         pCStructFormat->offset_to_array_description;
4665     if (*pCArrayFormat != RPC_FC_CARRAY)
4666     {
4667         ERR("invalid array format type %x\n", pCStructFormat->type);
4668         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4669         return;
4670     }
4671
4672     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4673                        pCArrayFormat + 4, 0);
4674
4675     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4676
4677     /* copy constant sized part of struct */
4678     pStubMsg->BufferMark = pStubMsg->Buffer;
4679
4680     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4681         EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4682 }
4683
4684 /***********************************************************************
4685  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
4686  */
4687 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4688                                 unsigned char *pMemory,
4689                                 PFORMAT_STRING pFormat)
4690 {
4691     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4692     PFORMAT_STRING pCVArrayFormat;
4693
4694     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4695
4696     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4697     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4698     {
4699         ERR("invalid format type %x\n", pCVStructFormat->type);
4700         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4701         return NULL;
4702     }
4703
4704     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4705         pCVStructFormat->offset_to_array_description;
4706
4707     array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg,
4708                                         pMemory + pCVStructFormat->memory_size,
4709                                         pCVArrayFormat);
4710
4711     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4712
4713     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4714
4715     /* write constant sized part */
4716     pStubMsg->BufferMark = pStubMsg->Buffer;
4717     safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
4718
4719     array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg,
4720                                       pMemory + pCVStructFormat->memory_size,
4721                                       pCVArrayFormat, FALSE /* fHasPointers */);
4722
4723     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4724
4725     return NULL;
4726 }
4727
4728 /***********************************************************************
4729  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
4730  */
4731 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4732                                 unsigned char **ppMemory,
4733                                 PFORMAT_STRING pFormat,
4734                                 unsigned char fMustAlloc)
4735 {
4736     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4737     PFORMAT_STRING pCVArrayFormat;
4738     ULONG memsize, bufsize;
4739     unsigned char *saved_buffer, *saved_array_buffer;
4740     ULONG offset;
4741     unsigned char *array_memory;
4742
4743     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4744
4745     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4746     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4747     {
4748         ERR("invalid format type %x\n", pCVStructFormat->type);
4749         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4750         return NULL;
4751     }
4752
4753     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4754         pCVStructFormat->offset_to_array_description;
4755
4756     memsize = array_read_conformance(*pCVArrayFormat, pStubMsg,
4757                                      pCVArrayFormat);
4758
4759     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4760
4761     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4762
4763     /* work out how much memory to allocate if we need to do so */
4764     if (!fMustAlloc && !*ppMemory)
4765         fMustAlloc = TRUE;
4766     if (fMustAlloc)
4767     {
4768         SIZE_T size = pCVStructFormat->memory_size + memsize;
4769         *ppMemory = NdrAllocate(pStubMsg, size);
4770     }
4771
4772     /* mark the start of the constant data */
4773     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4774     safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4775
4776     array_memory = *ppMemory + pCVStructFormat->memory_size;
4777     bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg,
4778                                                  &array_memory, pCVArrayFormat,
4779                                                  FALSE /* fMustAlloc */,
4780                                                  FALSE /* fUseServerBufferMemory */,
4781                                                  FALSE /* fUnmarshall */);
4782
4783     /* save offset in case unmarshalling pointers changes it */
4784     offset = pStubMsg->Offset;
4785
4786     /* mark the start of the array data */
4787     saved_array_buffer = pStubMsg->Buffer;
4788     safe_buffer_increment(pStubMsg, bufsize);
4789
4790     EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4791
4792     /* copy the constant data */
4793     memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size);
4794     /* copy the array data */
4795     TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size);
4796     memcpy(*ppMemory + pCVStructFormat->memory_size + offset,
4797            saved_array_buffer, bufsize);
4798
4799     if (*pCVArrayFormat == RPC_FC_C_CSTRING)
4800         TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
4801     else if (*pCVArrayFormat == RPC_FC_C_WSTRING)
4802         TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
4803
4804     return NULL;
4805 }
4806
4807 /***********************************************************************
4808  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
4809  */
4810 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4811                                 unsigned char *pMemory,
4812                                 PFORMAT_STRING pFormat)
4813 {
4814     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4815     PFORMAT_STRING pCVArrayFormat;
4816
4817     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4818
4819     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4820     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4821     {
4822         ERR("invalid format type %x\n", pCVStructFormat->type);
4823         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4824         return;
4825     }
4826
4827     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4828         pCVStructFormat->offset_to_array_description;
4829     array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg,
4830                                        pMemory + pCVStructFormat->memory_size,
4831                                        pCVArrayFormat);
4832
4833     ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4834
4835     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4836
4837     safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4838
4839     array_buffer_size(*pCVArrayFormat, pStubMsg,
4840                       pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4841                       FALSE /* fHasPointers */);
4842
4843     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4844 }
4845
4846 /***********************************************************************
4847  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
4848  */
4849 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4850                                 PFORMAT_STRING pFormat)
4851 {
4852     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4853     PFORMAT_STRING pCVArrayFormat;
4854
4855     TRACE("(%p, %p)\n", pStubMsg, pFormat);
4856
4857     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4858     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4859     {
4860         ERR("invalid format type %x\n", pCVStructFormat->type);
4861         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4862         return 0;
4863     }
4864
4865     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4866         pCVStructFormat->offset_to_array_description;
4867     array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat);
4868
4869     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4870
4871     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4872
4873     safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4874     array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat,
4875                       FALSE /* fHasPointers */);
4876
4877     pStubMsg->MemorySize += pCVStructFormat->memory_size;
4878
4879     EmbeddedPointerMemorySize(pStubMsg, pFormat);
4880
4881     return pStubMsg->MemorySize;
4882 }
4883
4884 /***********************************************************************
4885  *           NdrConformantVaryingStructFree [RPCRT4.@]
4886  */
4887 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4888                                 unsigned char *pMemory,
4889                                 PFORMAT_STRING pFormat)
4890 {
4891     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4892     PFORMAT_STRING pCVArrayFormat;
4893
4894     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4895
4896     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4897     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4898     {
4899         ERR("invalid format type %x\n", pCVStructFormat->type);
4900         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4901         return;
4902     }
4903
4904     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4905         pCVStructFormat->offset_to_array_description;
4906     array_free(*pCVArrayFormat, pStubMsg,
4907                pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4908                FALSE /* fHasPointers */);
4909
4910     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4911
4912     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4913 }
4914
4915 #include "pshpack1.h"
4916 typedef struct
4917 {
4918     unsigned char type;
4919     unsigned char alignment;
4920     unsigned short total_size;
4921 } NDR_SMFARRAY_FORMAT;
4922
4923 typedef struct
4924 {
4925     unsigned char type;
4926     unsigned char alignment;
4927     ULONG total_size;
4928 } NDR_LGFARRAY_FORMAT;
4929 #include "poppack.h"
4930
4931 /***********************************************************************
4932  *           NdrFixedArrayMarshall [RPCRT4.@]
4933  */
4934 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4935                                 unsigned char *pMemory,
4936                                 PFORMAT_STRING pFormat)
4937 {
4938     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4939     ULONG total_size;
4940
4941     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4942
4943     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4944         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4945     {
4946         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4947         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4948         return NULL;
4949     }
4950
4951     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4952
4953     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4954     {
4955         total_size = pSmFArrayFormat->total_size;
4956         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4957     }
4958     else
4959     {
4960         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4961         total_size = pLgFArrayFormat->total_size;
4962         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4963     }
4964
4965     pStubMsg->BufferMark = pStubMsg->Buffer;
4966     safe_copy_to_buffer(pStubMsg, pMemory, total_size);
4967
4968     pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4969
4970     return NULL;
4971 }
4972
4973 /***********************************************************************
4974  *           NdrFixedArrayUnmarshall [RPCRT4.@]
4975  */
4976 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4977                                 unsigned char **ppMemory,
4978                                 PFORMAT_STRING pFormat,
4979                                 unsigned char fMustAlloc)
4980 {
4981     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4982     ULONG total_size;
4983     unsigned char *saved_buffer;
4984
4985     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4986
4987     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4988         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4989     {
4990         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4991         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4992         return NULL;
4993     }
4994
4995     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4996
4997     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4998     {
4999         total_size = pSmFArrayFormat->total_size;
5000         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5001     }
5002     else
5003     {
5004         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5005         total_size = pLgFArrayFormat->total_size;
5006         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5007     }
5008
5009     if (fMustAlloc)
5010         *ppMemory = NdrAllocate(pStubMsg, total_size);
5011     else
5012     {
5013         if (!pStubMsg->IsClient && !*ppMemory)
5014             /* for servers, we just point straight into the RPC buffer */
5015             *ppMemory = pStubMsg->Buffer;
5016     }
5017
5018     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5019     safe_buffer_increment(pStubMsg, total_size);
5020     pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5021
5022     TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
5023     if (*ppMemory != saved_buffer)
5024         memcpy(*ppMemory, saved_buffer, total_size);
5025
5026     return NULL;
5027 }
5028
5029 /***********************************************************************
5030  *           NdrFixedArrayBufferSize [RPCRT4.@]
5031  */
5032 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5033                                 unsigned char *pMemory,
5034                                 PFORMAT_STRING pFormat)
5035 {
5036     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5037     ULONG total_size;
5038
5039     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5040
5041     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5042         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5043     {
5044         ERR("invalid format type %x\n", pSmFArrayFormat->type);
5045         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5046         return;
5047     }
5048
5049     ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
5050
5051     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5052     {
5053         total_size = pSmFArrayFormat->total_size;
5054         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5055     }
5056     else
5057     {
5058         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5059         total_size = pLgFArrayFormat->total_size;
5060         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5061     }
5062     safe_buffer_length_increment(pStubMsg, total_size);
5063
5064     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5065 }
5066
5067 /***********************************************************************
5068  *           NdrFixedArrayMemorySize [RPCRT4.@]
5069  */
5070 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5071                                 PFORMAT_STRING pFormat)
5072 {
5073     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5074     ULONG total_size;
5075
5076     TRACE("(%p, %p)\n", pStubMsg, pFormat);
5077
5078     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5079         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5080     {
5081         ERR("invalid format type %x\n", pSmFArrayFormat->type);
5082         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5083         return 0;
5084     }
5085
5086     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5087
5088     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5089     {
5090         total_size = pSmFArrayFormat->total_size;
5091         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5092     }
5093     else
5094     {
5095         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5096         total_size = pLgFArrayFormat->total_size;
5097         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5098     }
5099     pStubMsg->BufferMark = pStubMsg->Buffer;
5100     safe_buffer_increment(pStubMsg, total_size);
5101     pStubMsg->MemorySize += total_size;
5102
5103     EmbeddedPointerMemorySize(pStubMsg, pFormat);
5104
5105     return total_size;
5106 }
5107
5108 /***********************************************************************
5109  *           NdrFixedArrayFree [RPCRT4.@]
5110  */
5111 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5112                                 unsigned char *pMemory,
5113                                 PFORMAT_STRING pFormat)
5114 {
5115     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5116
5117     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5118
5119     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5120         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5121     {
5122         ERR("invalid format type %x\n", pSmFArrayFormat->type);
5123         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5124         return;
5125     }
5126
5127     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5128         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5129     else
5130     {
5131         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5132         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5133     }
5134
5135     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5136 }
5137
5138 /***********************************************************************
5139  *           NdrVaryingArrayMarshall [RPCRT4.@]
5140  */
5141 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5142                                 unsigned char *pMemory,
5143                                 PFORMAT_STRING pFormat)
5144 {
5145     unsigned char alignment;
5146     DWORD elements, esize;
5147     ULONG bufsize;
5148
5149     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5150
5151     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5152         (pFormat[0] != RPC_FC_LGVARRAY))
5153     {
5154         ERR("invalid format type %x\n", pFormat[0]);
5155         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5156         return NULL;
5157     }
5158
5159     alignment = pFormat[1] + 1;
5160
5161     if (pFormat[0] == RPC_FC_SMVARRAY)
5162     {
5163         pFormat += 2;
5164         pFormat += sizeof(WORD);
5165         elements = *(const WORD*)pFormat;
5166         pFormat += sizeof(WORD);
5167     }
5168     else
5169     {
5170         pFormat += 2;
5171         pFormat += sizeof(DWORD);
5172         elements = *(const DWORD*)pFormat;
5173         pFormat += sizeof(DWORD);
5174     }
5175
5176     esize = *(const WORD*)pFormat;
5177     pFormat += sizeof(WORD);
5178
5179     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5180     if ((pStubMsg->ActualCount > elements) ||
5181         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5182     {
5183         RpcRaiseException(RPC_S_INVALID_BOUND);
5184         return NULL;
5185     }
5186
5187     WriteVariance(pStubMsg);
5188
5189     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
5190
5191     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5192     pStubMsg->BufferMark = pStubMsg->Buffer;
5193     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
5194
5195     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5196
5197     return NULL;
5198 }
5199
5200 /***********************************************************************
5201  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
5202  */
5203 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5204                                 unsigned char **ppMemory,
5205                                 PFORMAT_STRING pFormat,
5206                                 unsigned char fMustAlloc)
5207 {
5208     unsigned char alignment;
5209     DWORD size, elements, esize;
5210     ULONG bufsize;
5211     unsigned char *saved_buffer;
5212     ULONG offset;
5213
5214     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5215
5216     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5217         (pFormat[0] != RPC_FC_LGVARRAY))
5218     {
5219         ERR("invalid format type %x\n", pFormat[0]);
5220         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5221         return NULL;
5222     }
5223
5224     alignment = pFormat[1] + 1;
5225
5226     if (pFormat[0] == RPC_FC_SMVARRAY)
5227     {
5228         pFormat += 2;
5229         size = *(const WORD*)pFormat;
5230         pFormat += sizeof(WORD);
5231         elements = *(const WORD*)pFormat;
5232         pFormat += sizeof(WORD);
5233     }
5234     else
5235     {
5236         pFormat += 2;
5237         size = *(const DWORD*)pFormat;
5238         pFormat += sizeof(DWORD);
5239         elements = *(const DWORD*)pFormat;
5240         pFormat += sizeof(DWORD);
5241     }
5242
5243     esize = *(const WORD*)pFormat;
5244     pFormat += sizeof(WORD);
5245
5246     pFormat = ReadVariance(pStubMsg, pFormat, elements);
5247
5248     ALIGN_POINTER(pStubMsg->Buffer, alignment);
5249
5250     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5251     offset = pStubMsg->Offset;
5252
5253     if (!fMustAlloc && !*ppMemory)
5254         fMustAlloc = TRUE;
5255     if (fMustAlloc)
5256         *ppMemory = NdrAllocate(pStubMsg, size);
5257     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5258     safe_buffer_increment(pStubMsg, bufsize);
5259
5260     EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5261
5262     memcpy(*ppMemory + offset, saved_buffer, bufsize);
5263
5264     return NULL;
5265 }
5266
5267 /***********************************************************************
5268  *           NdrVaryingArrayBufferSize [RPCRT4.@]
5269  */
5270 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5271                                 unsigned char *pMemory,
5272                                 PFORMAT_STRING pFormat)
5273 {
5274     unsigned char alignment;
5275     DWORD elements, esize;
5276
5277     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5278
5279     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5280         (pFormat[0] != RPC_FC_LGVARRAY))
5281     {
5282         ERR("invalid format type %x\n", pFormat[0]);
5283         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5284         return;
5285     }
5286
5287     alignment = pFormat[1] + 1;
5288
5289     if (pFormat[0] == RPC_FC_SMVARRAY)
5290     {
5291         pFormat += 2;
5292         pFormat += sizeof(WORD);
5293         elements = *(const WORD*)pFormat;
5294         pFormat += sizeof(WORD);
5295     }
5296     else
5297     {
5298         pFormat += 2;
5299         pFormat += sizeof(DWORD);
5300         elements = *(const DWORD*)pFormat;
5301         pFormat += sizeof(DWORD);
5302     }
5303
5304     esize = *(const WORD*)pFormat;
5305     pFormat += sizeof(WORD);
5306
5307     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5308     if ((pStubMsg->ActualCount > elements) ||
5309         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5310     {
5311         RpcRaiseException(RPC_S_INVALID_BOUND);
5312         return;
5313     }
5314
5315     SizeVariance(pStubMsg);
5316
5317     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
5318
5319     safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5320
5321     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5322 }
5323
5324 /***********************************************************************
5325  *           NdrVaryingArrayMemorySize [RPCRT4.@]
5326  */
5327 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5328                                 PFORMAT_STRING pFormat)
5329 {
5330     unsigned char alignment;
5331     DWORD size, elements, esize;
5332
5333     TRACE("(%p, %p)\n", pStubMsg, pFormat);
5334
5335     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5336         (pFormat[0] != RPC_FC_LGVARRAY))
5337     {
5338         ERR("invalid format type %x\n", pFormat[0]);
5339         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5340         return 0;
5341     }
5342
5343     alignment = pFormat[1] + 1;
5344
5345     if (pFormat[0] == RPC_FC_SMVARRAY)
5346     {
5347         pFormat += 2;
5348         size = *(const WORD*)pFormat;
5349         pFormat += sizeof(WORD);
5350         elements = *(const WORD*)pFormat;
5351         pFormat += sizeof(WORD);
5352     }
5353     else
5354     {
5355         pFormat += 2;
5356         size = *(const DWORD*)pFormat;
5357         pFormat += sizeof(DWORD);
5358         elements = *(const DWORD*)pFormat;
5359         pFormat += sizeof(DWORD);
5360     }
5361
5362     esize = *(const WORD*)pFormat;
5363     pFormat += sizeof(WORD);
5364
5365     pFormat = ReadVariance(pStubMsg, pFormat, elements);
5366
5367     ALIGN_POINTER(pStubMsg->Buffer, alignment);
5368
5369     safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5370     pStubMsg->MemorySize += size;
5371
5372     EmbeddedPointerMemorySize(pStubMsg, pFormat);
5373
5374     return pStubMsg->MemorySize;
5375 }
5376
5377 /***********************************************************************
5378  *           NdrVaryingArrayFree [RPCRT4.@]
5379  */
5380 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5381                                 unsigned char *pMemory,
5382                                 PFORMAT_STRING pFormat)
5383 {
5384     DWORD elements;
5385
5386     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5387
5388     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5389         (pFormat[0] != RPC_FC_LGVARRAY))
5390     {
5391         ERR("invalid format type %x\n", pFormat[0]);
5392         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5393         return;
5394     }
5395
5396     if (pFormat[0] == RPC_FC_SMVARRAY)
5397     {
5398         pFormat += 2;
5399         pFormat += sizeof(WORD);
5400         elements = *(const WORD*)pFormat;
5401         pFormat += sizeof(WORD);
5402     }
5403     else
5404     {
5405         pFormat += 2;
5406         pFormat += sizeof(DWORD);
5407         elements = *(const DWORD*)pFormat;
5408         pFormat += sizeof(DWORD);
5409     }
5410
5411     pFormat += sizeof(WORD);
5412
5413     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5414     if ((pStubMsg->ActualCount > elements) ||
5415         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5416     {
5417         RpcRaiseException(RPC_S_INVALID_BOUND);
5418         return;
5419     }
5420
5421     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5422 }
5423
5424 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
5425 {
5426     switch (fc)
5427     {
5428     case RPC_FC_BYTE:
5429     case RPC_FC_CHAR:
5430     case RPC_FC_SMALL:
5431     case RPC_FC_USMALL:
5432         return *pMemory;
5433     case RPC_FC_WCHAR:
5434     case RPC_FC_SHORT:
5435     case RPC_FC_USHORT:
5436     case RPC_FC_ENUM16:
5437         return *(const USHORT *)pMemory;
5438     case RPC_FC_LONG:
5439     case RPC_FC_ULONG:
5440     case RPC_FC_ENUM32:
5441         return *(const ULONG *)pMemory;
5442     default:
5443         FIXME("Unhandled base type: 0x%02x\n", fc);
5444         return 0;
5445     }
5446 }
5447
5448 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
5449                                                              ULONG discriminant,
5450                                                              PFORMAT_STRING pFormat)
5451 {
5452     unsigned short num_arms, arm, type;
5453
5454     num_arms = *(const SHORT*)pFormat & 0x0fff;
5455     pFormat += 2;
5456     for(arm = 0; arm < num_arms; arm++)
5457     {
5458         if(discriminant == *(const ULONG*)pFormat)
5459         {
5460             pFormat += 4;
5461             break;
5462         }
5463         pFormat += 6;
5464     }
5465
5466     type = *(const unsigned short*)pFormat;
5467     TRACE("type %04x\n", type);
5468     if(arm == num_arms) /* default arm extras */
5469     {
5470         if(type == 0xffff)
5471         {
5472             ERR("no arm for 0x%x and no default case\n", discriminant);
5473             RpcRaiseException(RPC_S_INVALID_TAG);
5474             return NULL;
5475         }
5476         if(type == 0)
5477         {
5478             TRACE("falling back to empty default case for 0x%x\n", discriminant);
5479             return NULL;
5480         }
5481     }
5482     return pFormat;
5483 }
5484
5485 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
5486 {
5487     unsigned short type;
5488
5489     pFormat += 2;
5490
5491     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5492     if(!pFormat)
5493         return NULL;
5494
5495     type = *(const unsigned short*)pFormat;
5496     if((type & 0xff00) == 0x8000)
5497     {
5498         unsigned char basetype = LOBYTE(type);
5499         return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
5500     }
5501     else
5502     {
5503         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5504         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
5505         if (m)
5506         {
5507             unsigned char *saved_buffer = NULL;
5508             int pointer_buffer_mark_set = 0;
5509             switch(*desc)
5510             {
5511             case RPC_FC_RP:
5512             case RPC_FC_UP:
5513             case RPC_FC_OP:
5514             case RPC_FC_FP:
5515                 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
5516                 saved_buffer = pStubMsg->Buffer;
5517                 if (pStubMsg->PointerBufferMark)
5518                 {
5519                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5520                   pStubMsg->PointerBufferMark = NULL;
5521                   pointer_buffer_mark_set = 1;
5522                 }
5523                 else
5524                   safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
5525
5526                 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
5527                 if (pointer_buffer_mark_set)
5528                 {
5529                   STD_OVERFLOW_CHECK(pStubMsg);
5530                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5531                   if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5532                   {
5533                       ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5534                           saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5535                       RpcRaiseException(RPC_X_BAD_STUB_DATA);
5536                   }
5537                   pStubMsg->Buffer = saved_buffer + 4;
5538                 }
5539                 break;
5540             default:
5541                 m(pStubMsg, pMemory, desc);
5542             }
5543         }
5544         else FIXME("no marshaller for embedded type %02x\n", *desc);
5545     }
5546     return NULL;
5547 }
5548
5549 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5550                                 unsigned char **ppMemory,
5551                                 ULONG discriminant,
5552                                 PFORMAT_STRING pFormat,
5553                                 unsigned char fMustAlloc)
5554 {
5555     unsigned short type;
5556
5557     pFormat += 2;
5558
5559     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5560     if(!pFormat)
5561         return NULL;
5562
5563     type = *(const unsigned short*)pFormat;
5564     if((type & 0xff00) == 0x8000)
5565     {
5566         unsigned char basetype = LOBYTE(type);
5567         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
5568     }
5569     else
5570     {
5571         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5572         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
5573         if (m)
5574         {
5575             unsigned char *saved_buffer = NULL;
5576             int pointer_buffer_mark_set = 0;
5577             switch(*desc)
5578             {
5579             case RPC_FC_RP:
5580             case RPC_FC_UP:
5581             case RPC_FC_OP:
5582             case RPC_FC_FP:
5583                 ALIGN_POINTER(pStubMsg->Buffer, 4);
5584                 saved_buffer = pStubMsg->Buffer;
5585                 if (pStubMsg->PointerBufferMark)
5586                 {
5587                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5588                   pStubMsg->PointerBufferMark = NULL;
5589                   pointer_buffer_mark_set = 1;
5590                 }
5591                 else
5592                   pStubMsg->Buffer += 4; /* for pointer ID */
5593
5594                 if (saved_buffer + 4 > pStubMsg->BufferEnd)
5595                 {
5596                     ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5597                         saved_buffer, pStubMsg->BufferEnd);
5598                     RpcRaiseException(RPC_X_BAD_STUB_DATA);
5599                 }
5600
5601                 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
5602                 if (pointer_buffer_mark_set)
5603                 {
5604                   STD_OVERFLOW_CHECK(pStubMsg);
5605                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5606                   pStubMsg->Buffer = saved_buffer + 4;
5607                 }
5608                 break;
5609             default:
5610                 m(pStubMsg, ppMemory, desc, fMustAlloc);
5611             }
5612         }
5613         else FIXME("no marshaller for embedded type %02x\n", *desc);
5614     }
5615     return NULL;
5616 }
5617
5618 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
5619                                   unsigned char *pMemory,
5620                                   ULONG discriminant,
5621                                   PFORMAT_STRING pFormat)
5622 {
5623     unsigned short type;
5624
5625     pFormat += 2;
5626
5627     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5628     if(!pFormat)
5629         return;
5630
5631     type = *(const unsigned short*)pFormat;
5632     if((type & 0xff00) == 0x8000)
5633     {
5634         unsigned char basetype = LOBYTE(type);
5635         NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
5636     }
5637     else
5638     {
5639         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5640         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
5641         if (m)
5642         {
5643             switch(*desc)
5644             {
5645             case RPC_FC_RP:
5646             case RPC_FC_UP:
5647             case RPC_FC_OP:
5648             case RPC_FC_FP:
5649                 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5650                 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
5651                 if (!pStubMsg->IgnoreEmbeddedPointers)
5652                 {
5653                     int saved_buffer_length = pStubMsg->BufferLength;
5654                     pStubMsg->BufferLength = pStubMsg->PointerLength;
5655                     pStubMsg->PointerLength = 0;
5656                     if(!pStubMsg->BufferLength)
5657                         ERR("BufferLength == 0??\n");
5658                     PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
5659                     pStubMsg->PointerLength = pStubMsg->BufferLength;
5660                     pStubMsg->BufferLength = saved_buffer_length;
5661                 }
5662                 break;
5663             default:
5664                 m(pStubMsg, pMemory, desc);
5665             }
5666         }
5667         else FIXME("no buffersizer for embedded type %02x\n", *desc);
5668     }
5669 }
5670
5671 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
5672                                    ULONG discriminant,
5673                                    PFORMAT_STRING pFormat)
5674 {
5675     unsigned short type, size;
5676
5677     size = *(const unsigned short*)pFormat;
5678     pStubMsg->Memory += size;
5679     pFormat += 2;
5680
5681     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5682     if(!pFormat)
5683         return 0;
5684
5685     type = *(const unsigned short*)pFormat;
5686     if((type & 0xff00) == 0x8000)
5687     {
5688         return NdrBaseTypeMemorySize(pStubMsg, pFormat);
5689     }
5690     else
5691     {
5692         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5693         NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
5694         unsigned char *saved_buffer;
5695         if (m)
5696         {
5697             switch(*desc)
5698             {
5699             case RPC_FC_RP:
5700             case RPC_FC_UP:
5701             case RPC_FC_OP:
5702             case RPC_FC_FP:
5703                 ALIGN_POINTER(pStubMsg->Buffer, 4);
5704                 saved_buffer = pStubMsg->Buffer;
5705                 safe_buffer_increment(pStubMsg, 4);
5706                 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
5707                 pStubMsg->MemorySize += sizeof(void *);
5708                 if (!pStubMsg->IgnoreEmbeddedPointers)
5709                     PointerMemorySize(pStubMsg, saved_buffer, pFormat);
5710                 break;
5711             default:
5712                 return m(pStubMsg, desc);
5713             }
5714         }
5715         else FIXME("no marshaller for embedded type %02x\n", *desc);
5716     }
5717
5718     TRACE("size %d\n", size);
5719     return size;
5720 }
5721
5722 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
5723                            unsigned char *pMemory,
5724                            ULONG discriminant,
5725                            PFORMAT_STRING pFormat)
5726 {
5727     unsigned short type;
5728
5729     pFormat += 2;
5730
5731     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5732     if(!pFormat)
5733         return;
5734
5735     type = *(const unsigned short*)pFormat;
5736     if((type & 0xff00) != 0x8000)
5737     {
5738         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5739         NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5740         if (m)
5741         {
5742             switch(*desc)
5743             {
5744             case RPC_FC_RP:
5745             case RPC_FC_UP:
5746             case RPC_FC_OP:
5747             case RPC_FC_FP:
5748                 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5749                 break;
5750             default:
5751                 m(pStubMsg, pMemory, desc);
5752             }
5753         }
5754     }
5755 }
5756
5757 /***********************************************************************
5758  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
5759  */
5760 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5761                                 unsigned char *pMemory,
5762                                 PFORMAT_STRING pFormat)
5763 {
5764     unsigned char switch_type;
5765     unsigned char increment;
5766     ULONG switch_value;
5767
5768     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5769     pFormat++;
5770
5771     switch_type = *pFormat & 0xf;
5772     increment = (*pFormat & 0xf0) >> 4;
5773     pFormat++;
5774
5775     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment);
5776
5777     switch_value = get_discriminant(switch_type, pMemory);
5778     TRACE("got switch value 0x%x\n", switch_value);
5779
5780     NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5781     pMemory += increment;
5782
5783     return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5784 }
5785
5786 /***********************************************************************
5787  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5788  */
5789 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5790                                 unsigned char **ppMemory,
5791                                 PFORMAT_STRING pFormat,
5792                                 unsigned char fMustAlloc)
5793 {
5794     unsigned char switch_type;
5795     unsigned char increment;
5796     ULONG switch_value;
5797     unsigned short size;
5798     unsigned char *pMemoryArm;
5799
5800     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5801     pFormat++;
5802
5803     switch_type = *pFormat & 0xf;
5804     increment = (*pFormat & 0xf0) >> 4;
5805     pFormat++;
5806
5807     ALIGN_POINTER(pStubMsg->Buffer, increment);
5808     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5809     TRACE("got switch value 0x%x\n", switch_value);
5810
5811     size = *(const unsigned short*)pFormat + increment;
5812     if (!fMustAlloc && !*ppMemory)
5813         fMustAlloc = TRUE;
5814     if (fMustAlloc)
5815         *ppMemory = NdrAllocate(pStubMsg, size);
5816
5817     /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
5818      * since the arm is part of the memory block that is encompassed by
5819      * the whole union. Memory is forced to allocate when pointers
5820      * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
5821      * clearing the memory we pass in to the unmarshaller */
5822     if (fMustAlloc)
5823         memset(*ppMemory, 0, size);
5824
5825     NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5826     pMemoryArm = *ppMemory + increment;
5827
5828     return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE);
5829 }
5830
5831 /***********************************************************************
5832  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5833  */
5834 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5835                                 unsigned char *pMemory,
5836                                 PFORMAT_STRING pFormat)
5837 {
5838     unsigned char switch_type;
5839     unsigned char increment;
5840     ULONG switch_value;
5841
5842     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5843     pFormat++;
5844
5845     switch_type = *pFormat & 0xf;
5846     increment = (*pFormat & 0xf0) >> 4;
5847     pFormat++;
5848
5849     ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5850     switch_value = get_discriminant(switch_type, pMemory);
5851     TRACE("got switch value 0x%x\n", switch_value);
5852
5853     /* Add discriminant size */
5854     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5855     pMemory += increment;
5856
5857     union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5858 }
5859
5860 /***********************************************************************
5861  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5862  */
5863 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5864                                 PFORMAT_STRING pFormat)
5865 {
5866     unsigned char switch_type;
5867     unsigned char increment;
5868     ULONG switch_value;
5869
5870     switch_type = *pFormat & 0xf;
5871     increment = (*pFormat & 0xf0) >> 4;
5872     pFormat++;
5873
5874     ALIGN_POINTER(pStubMsg->Buffer, increment);
5875     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5876     TRACE("got switch value 0x%x\n", switch_value);
5877
5878     pStubMsg->Memory += increment;
5879
5880     return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5881 }
5882
5883 /***********************************************************************
5884  *           NdrEncapsulatedUnionFree [RPCRT4.@]
5885  */
5886 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5887                                 unsigned char *pMemory,
5888                                 PFORMAT_STRING pFormat)
5889 {
5890     unsigned char switch_type;
5891     unsigned char increment;
5892     ULONG switch_value;
5893
5894     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5895     pFormat++;
5896
5897     switch_type = *pFormat & 0xf;
5898     increment = (*pFormat & 0xf0) >> 4;
5899     pFormat++;
5900
5901     switch_value = get_discriminant(switch_type, pMemory);
5902     TRACE("got switch value 0x%x\n", switch_value);
5903
5904     pMemory += increment;
5905
5906     union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5907 }
5908
5909 /***********************************************************************
5910  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5911  */
5912 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5913                                 unsigned char *pMemory,
5914                                 PFORMAT_STRING pFormat)
5915 {
5916     unsigned char switch_type;
5917
5918     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5919     pFormat++;
5920
5921     switch_type = *pFormat;
5922     pFormat++;
5923
5924     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5925     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5926     /* Marshall discriminant */
5927     NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5928
5929     return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5930 }
5931
5932 static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
5933                                     PFORMAT_STRING *ppFormat)
5934 {
5935     LONG discriminant = 0;
5936
5937     switch(**ppFormat)
5938     {
5939     case RPC_FC_BYTE:
5940     case RPC_FC_CHAR:
5941     case RPC_FC_SMALL:
5942     case RPC_FC_USMALL:
5943     {
5944         UCHAR d;
5945         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5946         discriminant = d;
5947         break;
5948     }
5949     case RPC_FC_WCHAR:
5950     case RPC_FC_SHORT:
5951     case RPC_FC_USHORT:
5952     {
5953         USHORT d;
5954         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5955         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5956         discriminant = d;
5957         break;
5958     }
5959     case RPC_FC_LONG:
5960     case RPC_FC_ULONG:
5961     {
5962         ULONG d;
5963         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5964         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5965         discriminant = d;
5966         break;
5967     }
5968     default:
5969         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
5970     }
5971     (*ppFormat)++;
5972
5973     if (pStubMsg->fHasNewCorrDesc)
5974         *ppFormat += 6;
5975     else
5976         *ppFormat += 4;
5977     return discriminant;
5978 }
5979
5980 /**********************************************************************
5981  *           NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
5982  */
5983 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5984                                 unsigned char **ppMemory,
5985                                 PFORMAT_STRING pFormat,
5986                                 unsigned char fMustAlloc)
5987 {
5988     LONG discriminant;
5989     unsigned short size;
5990
5991     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5992     pFormat++;
5993
5994     /* Unmarshall discriminant */
5995     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5996     TRACE("unmarshalled discriminant %x\n", discriminant);
5997
5998     pFormat += *(const SHORT*)pFormat;
5999
6000     size = *(const unsigned short*)pFormat;
6001
6002     if (!fMustAlloc && !*ppMemory)
6003         fMustAlloc = TRUE;
6004     if (fMustAlloc)
6005         *ppMemory = NdrAllocate(pStubMsg, size);
6006
6007     /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6008      * since the arm is part of the memory block that is encompassed by
6009      * the whole union. Memory is forced to allocate when pointers
6010      * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6011      * clearing the memory we pass in to the unmarshaller */
6012     if (fMustAlloc)
6013         memset(*ppMemory, 0, size);
6014
6015     return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
6016 }
6017
6018 /***********************************************************************
6019  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
6020  */
6021 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6022                                 unsigned char *pMemory,
6023                                 PFORMAT_STRING pFormat)
6024 {
6025     unsigned char switch_type;
6026
6027     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6028     pFormat++;
6029
6030     switch_type = *pFormat;
6031     pFormat++;
6032
6033     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6034     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6035     /* Add discriminant size */
6036     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6037
6038     union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6039 }
6040
6041 /***********************************************************************
6042  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
6043  */
6044 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6045                                 PFORMAT_STRING pFormat)
6046 {
6047     ULONG discriminant;
6048
6049     pFormat++;
6050     /* Unmarshall discriminant */
6051     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6052     TRACE("unmarshalled discriminant 0x%x\n", discriminant);
6053
6054     return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
6055 }
6056
6057 /***********************************************************************
6058  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
6059  */
6060 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6061                                 unsigned char *pMemory,
6062                                 PFORMAT_STRING pFormat)
6063 {
6064     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6065     pFormat++;
6066     pFormat++;
6067
6068     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6069     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6070
6071     union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6072 }
6073
6074 /***********************************************************************
6075  *           NdrByteCountPointerMarshall [RPCRT4.@]
6076  */
6077 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6078                                 unsigned char *pMemory,
6079                                 PFORMAT_STRING pFormat)
6080 {
6081     FIXME("stub\n");
6082     return NULL;
6083 }
6084
6085 /***********************************************************************
6086  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
6087  */
6088 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6089                                 unsigned char **ppMemory,
6090                                 PFORMAT_STRING pFormat,
6091                                 unsigned char fMustAlloc)
6092 {
6093     FIXME("stub\n");
6094     return NULL;
6095 }
6096
6097 /***********************************************************************
6098  *           NdrByteCountPointerBufferSize [RPCRT4.@]
6099  */
6100 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6101                                 unsigned char *pMemory,
6102                                 PFORMAT_STRING pFormat)
6103 {
6104     FIXME("stub\n");
6105 }
6106
6107 /***********************************************************************
6108  *           NdrByteCountPointerMemorySize [internal]
6109  */
6110 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6111                                                   PFORMAT_STRING pFormat)
6112 {
6113     FIXME("stub\n");
6114     return 0;
6115 }
6116
6117 /***********************************************************************
6118  *           NdrByteCountPointerFree [RPCRT4.@]
6119  */
6120 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
6121                                 unsigned char *pMemory,
6122                                 PFORMAT_STRING pFormat)
6123 {
6124     FIXME("stub\n");
6125 }
6126
6127 /***********************************************************************
6128  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
6129  */
6130 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6131                                 unsigned char *pMemory,
6132                                 PFORMAT_STRING pFormat)
6133 {
6134     FIXME("stub\n");
6135     return NULL;
6136 }
6137
6138 /***********************************************************************
6139  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
6140  */
6141 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6142                                 unsigned char **ppMemory,
6143                                 PFORMAT_STRING pFormat,
6144                                 unsigned char fMustAlloc)
6145 {
6146     FIXME("stub\n");
6147     return NULL;
6148 }
6149
6150 /***********************************************************************
6151  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
6152  */
6153 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6154                                 unsigned char *pMemory,
6155                                 PFORMAT_STRING pFormat)
6156 {
6157     FIXME("stub\n");
6158 }
6159
6160 /***********************************************************************
6161  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
6162  */
6163 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6164                                 PFORMAT_STRING pFormat)
6165 {
6166     FIXME("stub\n");
6167     return 0;
6168 }
6169
6170 /***********************************************************************
6171  *           NdrXmitOrRepAsFree [RPCRT4.@]
6172  */
6173 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
6174                                 unsigned char *pMemory,
6175                                 PFORMAT_STRING pFormat)
6176 {
6177     FIXME("stub\n");
6178 }
6179
6180 /***********************************************************************
6181  *           NdrRangeMarshall [internal]
6182  */
6183 static unsigned char *WINAPI NdrRangeMarshall(
6184     PMIDL_STUB_MESSAGE pStubMsg,
6185     unsigned char *pMemory,
6186     PFORMAT_STRING pFormat)
6187 {
6188     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6189     unsigned char base_type;
6190
6191     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6192
6193     if (pRange->type != RPC_FC_RANGE)
6194     {
6195         ERR("invalid format type %x\n", pRange->type);
6196         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6197         return NULL;
6198     }
6199
6200     base_type = pRange->flags_type & 0xf;
6201
6202     return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
6203 }
6204
6205 /***********************************************************************
6206  *           NdrRangeUnmarshall [RPCRT4.@]
6207  */
6208 unsigned char *WINAPI NdrRangeUnmarshall(
6209     PMIDL_STUB_MESSAGE pStubMsg,
6210     unsigned char **ppMemory,
6211     PFORMAT_STRING pFormat,
6212     unsigned char fMustAlloc)
6213 {
6214     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6215     unsigned char base_type;
6216
6217     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6218
6219     if (pRange->type != RPC_FC_RANGE)
6220     {
6221         ERR("invalid format type %x\n", pRange->type);
6222         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6223         return NULL;
6224     }
6225     base_type = pRange->flags_type & 0xf;
6226
6227     TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
6228         base_type, pRange->low_value, pRange->high_value);
6229
6230 #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
6231     do \
6232     { \
6233         ALIGN_POINTER(pStubMsg->Buffer, sizeof(wire_type)); \
6234         if (!fMustAlloc && !*ppMemory) \
6235             fMustAlloc = TRUE; \
6236         if (fMustAlloc) \
6237             *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
6238         if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
6239         { \
6240             ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
6241                 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
6242             RpcRaiseException(RPC_X_BAD_STUB_DATA); \
6243         } \
6244         if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
6245             (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
6246         { \
6247             ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
6248                 *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
6249                 (mem_type)pRange->high_value); \
6250             RpcRaiseException(RPC_S_INVALID_BOUND); \
6251             return NULL; \
6252         } \
6253         TRACE("*ppMemory: %p\n", *ppMemory); \
6254         **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
6255         pStubMsg->Buffer += sizeof(wire_type); \
6256     } while (0)
6257
6258     switch(base_type)
6259     {
6260     case RPC_FC_CHAR:
6261     case RPC_FC_SMALL:
6262         RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
6263         TRACE("value: 0x%02x\n", **ppMemory);
6264         break;
6265     case RPC_FC_BYTE:
6266     case RPC_FC_USMALL:
6267         RANGE_UNMARSHALL(CHAR, CHAR, "%u");
6268         TRACE("value: 0x%02x\n", **ppMemory);
6269         break;
6270     case RPC_FC_WCHAR: /* FIXME: valid? */
6271     case RPC_FC_USHORT:
6272         RANGE_UNMARSHALL(USHORT, USHORT, "%u");
6273         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6274         break;
6275     case RPC_FC_SHORT:
6276         RANGE_UNMARSHALL(SHORT, SHORT, "%d");
6277         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6278         break;
6279     case RPC_FC_LONG:
6280     case RPC_FC_ENUM32:
6281         RANGE_UNMARSHALL(LONG, LONG, "%d");
6282         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6283         break;
6284     case RPC_FC_ULONG:
6285         RANGE_UNMARSHALL(ULONG, ULONG, "%u");
6286         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6287         break;
6288     case RPC_FC_ENUM16:
6289         RANGE_UNMARSHALL(UINT, USHORT, "%u");
6290         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6291         break;
6292     case RPC_FC_FLOAT:
6293     case RPC_FC_DOUBLE:
6294     case RPC_FC_HYPER:
6295     default:
6296         ERR("invalid range base type: 0x%02x\n", base_type);
6297         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6298     }
6299
6300     return NULL;
6301 }
6302
6303 /***********************************************************************
6304  *           NdrRangeBufferSize [internal]
6305  */
6306 static void WINAPI NdrRangeBufferSize(
6307     PMIDL_STUB_MESSAGE pStubMsg,
6308     unsigned char *pMemory,
6309     PFORMAT_STRING pFormat)
6310 {
6311     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6312     unsigned char base_type;
6313
6314     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6315
6316     if (pRange->type != RPC_FC_RANGE)
6317     {
6318         ERR("invalid format type %x\n", pRange->type);
6319         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6320     }
6321     base_type = pRange->flags_type & 0xf;
6322
6323     NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
6324 }
6325
6326 /***********************************************************************
6327  *           NdrRangeMemorySize [internal]
6328  */
6329 static ULONG WINAPI NdrRangeMemorySize(
6330     PMIDL_STUB_MESSAGE pStubMsg,
6331     PFORMAT_STRING pFormat)
6332 {
6333     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6334     unsigned char base_type;
6335
6336     if (pRange->type != RPC_FC_RANGE)
6337     {
6338         ERR("invalid format type %x\n", pRange->type);
6339         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6340         return 0;
6341     }
6342     base_type = pRange->flags_type & 0xf;
6343
6344     return NdrBaseTypeMemorySize(pStubMsg, &base_type);
6345 }
6346
6347 /***********************************************************************
6348  *           NdrRangeFree [internal]
6349  */
6350 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
6351                                 unsigned char *pMemory,
6352                                 PFORMAT_STRING pFormat)
6353 {
6354    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6355
6356    /* nothing to do */
6357 }
6358
6359 /***********************************************************************
6360  *           NdrBaseTypeMarshall [internal]
6361  */
6362 static unsigned char *WINAPI NdrBaseTypeMarshall(
6363     PMIDL_STUB_MESSAGE pStubMsg,
6364     unsigned char *pMemory,
6365     PFORMAT_STRING pFormat)
6366 {
6367     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6368
6369     switch(*pFormat)
6370     {
6371     case RPC_FC_BYTE:
6372     case RPC_FC_CHAR:
6373     case RPC_FC_SMALL:
6374     case RPC_FC_USMALL:
6375         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
6376         TRACE("value: 0x%02x\n", *pMemory);
6377         break;
6378     case RPC_FC_WCHAR:
6379     case RPC_FC_SHORT:
6380     case RPC_FC_USHORT:
6381         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6382         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
6383         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
6384         break;
6385     case RPC_FC_LONG:
6386     case RPC_FC_ULONG:
6387     case RPC_FC_ERROR_STATUS_T:
6388     case RPC_FC_ENUM32:
6389         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG));
6390         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
6391         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
6392         break;
6393     case RPC_FC_FLOAT:
6394         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float));
6395         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
6396         break;
6397     case RPC_FC_DOUBLE:
6398         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double));
6399         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
6400         break;
6401     case RPC_FC_HYPER:
6402         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG));
6403         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
6404         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
6405         break;
6406     case RPC_FC_ENUM16:
6407         /* only 16-bits on the wire, so do a sanity check */
6408         if (*(UINT *)pMemory > SHRT_MAX)
6409             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
6410         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6411         if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6412             RpcRaiseException(RPC_X_BAD_STUB_DATA);
6413         *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
6414         pStubMsg->Buffer += sizeof(USHORT);
6415         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
6416         break;
6417     case RPC_FC_IGNORE:
6418         break;
6419     default:
6420         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6421     }
6422
6423     /* FIXME: what is the correct return value? */
6424     return NULL;
6425 }
6426
6427 /***********************************************************************
6428  *           NdrBaseTypeUnmarshall [internal]
6429  */
6430 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
6431     PMIDL_STUB_MESSAGE pStubMsg,
6432     unsigned char **ppMemory,
6433     PFORMAT_STRING pFormat,
6434     unsigned char fMustAlloc)
6435 {
6436     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6437
6438 #define BASE_TYPE_UNMARSHALL(type) \
6439         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
6440         if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
6441         { \
6442             *ppMemory = pStubMsg->Buffer; \
6443             TRACE("*ppMemory: %p\n", *ppMemory); \
6444             safe_buffer_increment(pStubMsg, sizeof(type)); \
6445         } \
6446         else \
6447         {  \
6448             if (fMustAlloc) \
6449                 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
6450             TRACE("*ppMemory: %p\n", *ppMemory); \
6451             safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \
6452         }
6453
6454     switch(*pFormat)
6455     {
6456     case RPC_FC_BYTE:
6457     case RPC_FC_CHAR:
6458     case RPC_FC_SMALL:
6459     case RPC_FC_USMALL:
6460         BASE_TYPE_UNMARSHALL(UCHAR);
6461         TRACE("value: 0x%02x\n", **ppMemory);
6462         break;
6463     case RPC_FC_WCHAR:
6464     case RPC_FC_SHORT:
6465     case RPC_FC_USHORT:
6466         BASE_TYPE_UNMARSHALL(USHORT);
6467         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6468         break;
6469     case RPC_FC_LONG:
6470     case RPC_FC_ULONG:
6471     case RPC_FC_ERROR_STATUS_T:
6472     case RPC_FC_ENUM32:
6473         BASE_TYPE_UNMARSHALL(ULONG);
6474         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6475         break;
6476    case RPC_FC_FLOAT:
6477         BASE_TYPE_UNMARSHALL(float);
6478         TRACE("value: %f\n", **(float **)ppMemory);
6479         break;
6480     case RPC_FC_DOUBLE:
6481         BASE_TYPE_UNMARSHALL(double);
6482         TRACE("value: %f\n", **(double **)ppMemory);
6483         break;
6484     case RPC_FC_HYPER:
6485         BASE_TYPE_UNMARSHALL(ULONGLONG);
6486         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
6487         break;
6488     case RPC_FC_ENUM16:
6489         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6490         if (!fMustAlloc && !*ppMemory)
6491             fMustAlloc = TRUE;
6492         if (fMustAlloc)
6493             *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
6494         if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
6495             RpcRaiseException(RPC_X_BAD_STUB_DATA);
6496         TRACE("*ppMemory: %p\n", *ppMemory);
6497         /* 16-bits on the wire, but int in memory */
6498         **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
6499         pStubMsg->Buffer += sizeof(USHORT);
6500         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6501         break;
6502     case RPC_FC_IGNORE:
6503         break;
6504     default:
6505         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6506     }
6507 #undef BASE_TYPE_UNMARSHALL
6508
6509     /* FIXME: what is the correct return value? */
6510
6511     return NULL;
6512 }
6513
6514 /***********************************************************************
6515  *           NdrBaseTypeBufferSize [internal]
6516  */
6517 static void WINAPI NdrBaseTypeBufferSize(
6518     PMIDL_STUB_MESSAGE pStubMsg,
6519     unsigned char *pMemory,
6520     PFORMAT_STRING pFormat)
6521 {
6522     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6523
6524     switch(*pFormat)
6525     {
6526     case RPC_FC_BYTE:
6527     case RPC_FC_CHAR:
6528     case RPC_FC_SMALL:
6529     case RPC_FC_USMALL:
6530         safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6531         break;
6532     case RPC_FC_WCHAR:
6533     case RPC_FC_SHORT:
6534     case RPC_FC_USHORT:
6535     case RPC_FC_ENUM16:
6536         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
6537         safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6538         break;
6539     case RPC_FC_LONG:
6540     case RPC_FC_ULONG:
6541     case RPC_FC_ENUM32:
6542         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
6543         safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6544         break;
6545     case RPC_FC_FLOAT:
6546         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
6547         safe_buffer_length_increment(pStubMsg, sizeof(float));
6548         break;
6549     case RPC_FC_DOUBLE:
6550         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
6551         safe_buffer_length_increment(pStubMsg, sizeof(double));
6552         break;
6553     case RPC_FC_HYPER:
6554         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
6555         safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6556         break;
6557     case RPC_FC_ERROR_STATUS_T:
6558         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
6559         safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6560         break;
6561     case RPC_FC_IGNORE:
6562         break;
6563     default:
6564         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6565     }
6566 }
6567
6568 /***********************************************************************
6569  *           NdrBaseTypeMemorySize [internal]
6570  */
6571 static ULONG WINAPI NdrBaseTypeMemorySize(
6572     PMIDL_STUB_MESSAGE pStubMsg,
6573     PFORMAT_STRING pFormat)
6574 {
6575     TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6576
6577     switch(*pFormat)
6578     {
6579     case RPC_FC_BYTE:
6580     case RPC_FC_CHAR:
6581     case RPC_FC_SMALL:
6582     case RPC_FC_USMALL:
6583         safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6584         pStubMsg->MemorySize += sizeof(UCHAR);
6585         return sizeof(UCHAR);
6586     case RPC_FC_WCHAR:
6587     case RPC_FC_SHORT:
6588     case RPC_FC_USHORT:
6589         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6590         safe_buffer_increment(pStubMsg, sizeof(USHORT));
6591         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(USHORT));
6592         pStubMsg->MemorySize += sizeof(USHORT);
6593         return sizeof(USHORT);
6594     case RPC_FC_LONG:
6595     case RPC_FC_ULONG:
6596     case RPC_FC_ENUM32:
6597         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
6598         safe_buffer_increment(pStubMsg, sizeof(ULONG));
6599         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONG));
6600         pStubMsg->MemorySize += sizeof(ULONG);
6601         return sizeof(ULONG);
6602     case RPC_FC_FLOAT:
6603         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
6604         safe_buffer_increment(pStubMsg, sizeof(float));
6605         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(float));
6606         pStubMsg->MemorySize += sizeof(float);
6607         return sizeof(float);
6608     case RPC_FC_DOUBLE:
6609         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
6610         safe_buffer_increment(pStubMsg, sizeof(double));
6611         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(double));
6612         pStubMsg->MemorySize += sizeof(double);
6613         return sizeof(double);
6614     case RPC_FC_HYPER:
6615         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
6616         safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6617         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONGLONG));
6618         pStubMsg->MemorySize += sizeof(ULONGLONG);
6619         return sizeof(ULONGLONG);
6620     case RPC_FC_ERROR_STATUS_T:
6621         ALIGN_POINTER(pStubMsg->Buffer, sizeof(error_status_t));
6622         safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6623         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(error_status_t));
6624         pStubMsg->MemorySize += sizeof(error_status_t);
6625         return sizeof(error_status_t);
6626     case RPC_FC_ENUM16:
6627         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6628         safe_buffer_increment(pStubMsg, sizeof(USHORT));
6629         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(UINT));
6630         pStubMsg->MemorySize += sizeof(UINT);
6631         return sizeof(UINT);
6632     case RPC_FC_IGNORE:
6633         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
6634         pStubMsg->MemorySize += sizeof(void *);
6635         return sizeof(void *);
6636     default:
6637         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6638        return 0;
6639     }
6640 }
6641
6642 /***********************************************************************
6643  *           NdrBaseTypeFree [internal]
6644  */
6645 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6646                                 unsigned char *pMemory,
6647                                 PFORMAT_STRING pFormat)
6648 {
6649    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6650
6651    /* nothing to do */
6652 }
6653
6654 /***********************************************************************
6655  *           NdrContextHandleBufferSize [internal]
6656  */
6657 static void WINAPI NdrContextHandleBufferSize(
6658     PMIDL_STUB_MESSAGE pStubMsg,
6659     unsigned char *pMemory,
6660     PFORMAT_STRING pFormat)
6661 {
6662     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6663
6664     if (*pFormat != RPC_FC_BIND_CONTEXT)
6665     {
6666         ERR("invalid format type %x\n", *pFormat);
6667         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6668     }
6669     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
6670     safe_buffer_length_increment(pStubMsg, cbNDRContext);
6671 }
6672
6673 /***********************************************************************
6674  *           NdrContextHandleMarshall [internal]
6675  */
6676 static unsigned char *WINAPI NdrContextHandleMarshall(
6677     PMIDL_STUB_MESSAGE pStubMsg,
6678     unsigned char *pMemory,
6679     PFORMAT_STRING pFormat)
6680 {
6681     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6682
6683     if (*pFormat != RPC_FC_BIND_CONTEXT)
6684     {
6685         ERR("invalid format type %x\n", *pFormat);
6686         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6687     }
6688     TRACE("flags: 0x%02x\n", pFormat[1]);
6689
6690     if (pFormat[1] & 0x80)
6691         NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6692     else
6693         NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
6694
6695     return NULL;
6696 }
6697
6698 /***********************************************************************
6699  *           NdrContextHandleUnmarshall [internal]
6700  */
6701 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6702     PMIDL_STUB_MESSAGE pStubMsg,
6703     unsigned char **ppMemory,
6704     PFORMAT_STRING pFormat,
6705     unsigned char fMustAlloc)
6706 {
6707     TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg,
6708         ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE");
6709
6710     if (*pFormat != RPC_FC_BIND_CONTEXT)
6711     {
6712         ERR("invalid format type %x\n", *pFormat);
6713         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6714     }
6715     TRACE("flags: 0x%02x\n", pFormat[1]);
6716
6717     /* [out]-only or [ret] param */
6718     if ((pFormat[1] & 0x60) == 0x20)
6719         **(NDR_CCONTEXT **)ppMemory = NULL;
6720     NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
6721
6722     return NULL;
6723 }
6724
6725 /***********************************************************************
6726  *           NdrClientContextMarshall [RPCRT4.@]
6727  */
6728 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6729                                      NDR_CCONTEXT ContextHandle,
6730                                      int fCheck)
6731 {
6732     TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
6733
6734     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
6735
6736     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6737     {
6738         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6739             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6740         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6741     }
6742
6743     /* FIXME: what does fCheck do? */
6744     NDRCContextMarshall(ContextHandle,
6745                         pStubMsg->Buffer);
6746
6747     pStubMsg->Buffer += cbNDRContext;
6748 }
6749
6750 /***********************************************************************
6751  *           NdrClientContextUnmarshall [RPCRT4.@]
6752  */
6753 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6754                                        NDR_CCONTEXT * pContextHandle,
6755                                        RPC_BINDING_HANDLE BindHandle)
6756 {
6757     TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
6758
6759     ALIGN_POINTER(pStubMsg->Buffer, 4);
6760
6761     if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
6762         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6763
6764     NDRCContextUnmarshall(pContextHandle,
6765                           BindHandle,
6766                           pStubMsg->Buffer,
6767                           pStubMsg->RpcMsg->DataRepresentation);
6768
6769     pStubMsg->Buffer += cbNDRContext;
6770 }
6771
6772 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6773                                      NDR_SCONTEXT ContextHandle,
6774                                      NDR_RUNDOWN RundownRoutine )
6775 {
6776     TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
6777
6778     ALIGN_POINTER(pStubMsg->Buffer, 4);
6779
6780     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6781     {
6782         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6783             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6784         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6785     }
6786
6787     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6788                          pStubMsg->Buffer, RundownRoutine, NULL,
6789                          RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6790     pStubMsg->Buffer += cbNDRContext;
6791 }
6792
6793 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
6794 {
6795     NDR_SCONTEXT ContextHandle;
6796
6797     TRACE("(%p)\n", pStubMsg);
6798
6799     ALIGN_POINTER(pStubMsg->Buffer, 4);
6800
6801     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6802     {
6803         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6804             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6805         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6806     }
6807
6808     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6809                                            pStubMsg->Buffer,
6810                                            pStubMsg->RpcMsg->DataRepresentation,
6811                                            NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6812     pStubMsg->Buffer += cbNDRContext;
6813
6814     return ContextHandle;
6815 }
6816
6817 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
6818                                  unsigned char* pMemory,
6819                                  PFORMAT_STRING pFormat)
6820 {
6821     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
6822 }
6823
6824 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
6825                                                PFORMAT_STRING pFormat)
6826 {
6827     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6828     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6829
6830     TRACE("(%p, %p)\n", pStubMsg, pFormat);
6831
6832     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6833         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6834     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6835         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6836     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6837     {
6838         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6839         if_id = &sif->InterfaceId;
6840     }
6841
6842     return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
6843                                   pStubMsg->RpcMsg->DataRepresentation, if_id,
6844                                   flags);
6845 }
6846
6847 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6848                                         NDR_SCONTEXT ContextHandle,
6849                                         NDR_RUNDOWN RundownRoutine,
6850                                         PFORMAT_STRING pFormat)
6851 {
6852     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6853     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6854
6855     TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
6856
6857     ALIGN_POINTER(pStubMsg->Buffer, 4);
6858
6859     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6860     {
6861         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6862             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6863         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6864     }
6865
6866     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6867         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6868     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6869         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6870     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6871     {
6872         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6873         if_id = &sif->InterfaceId;
6874     }
6875
6876     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6877                           pStubMsg->Buffer, RundownRoutine, if_id, flags);
6878     pStubMsg->Buffer += cbNDRContext;
6879 }
6880
6881 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6882                                                   PFORMAT_STRING pFormat)
6883 {
6884     NDR_SCONTEXT ContextHandle;
6885     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6886     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6887
6888     TRACE("(%p, %p)\n", pStubMsg, pFormat);
6889
6890     ALIGN_POINTER(pStubMsg->Buffer, 4);
6891
6892     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6893     {
6894         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6895             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6896         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6897     }
6898
6899     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6900         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6901     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6902         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6903     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6904     {
6905         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6906         if_id = &sif->InterfaceId;
6907     }
6908
6909     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6910                                            pStubMsg->Buffer,
6911                                            pStubMsg->RpcMsg->DataRepresentation,
6912                                            if_id, flags);
6913     pStubMsg->Buffer += cbNDRContext;
6914
6915     return ContextHandle;
6916 }
6917
6918 /***********************************************************************
6919  *           NdrCorrelationInitialize [RPCRT4.@]
6920  *
6921  * Initializes correlation validity checking.
6922  *
6923  * PARAMS
6924  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
6925  *  pMemory     [I] Pointer to memory to use as a cache.
6926  *  CacheSize   [I] Size of the memory pointed to by pMemory.
6927  *  Flags       [I] Reserved. Set to zero.
6928  *
6929  * RETURNS
6930  *  Nothing.
6931  */
6932 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
6933 {
6934     FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
6935     pStubMsg->fHasNewCorrDesc = TRUE;
6936 }
6937
6938 /***********************************************************************
6939  *           NdrCorrelationPass [RPCRT4.@]
6940  *
6941  * Performs correlation validity checking.
6942  *
6943  * PARAMS
6944  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
6945  *
6946  * RETURNS
6947  *  Nothing.
6948  */
6949 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
6950 {
6951     FIXME("(%p): stub\n", pStubMsg);
6952 }
6953
6954 /***********************************************************************
6955  *           NdrCorrelationFree [RPCRT4.@]
6956  *
6957  * Frees any resources used while unmarshalling parameters that need
6958  * correlation validity checking.
6959  *
6960  * PARAMS
6961  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
6962  *
6963  * RETURNS
6964  *  Nothing.
6965  */
6966 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
6967 {
6968     FIXME("(%p): stub\n", pStubMsg);
6969 }