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