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