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