dinput: Window supplied to SetCooperativeLevel have to be top level window.
[wine] / dlls / rpcrt4 / ndr_marshall.c
1 /*
2  * NDR data marshalling
3  *
4  * Copyright 2002 Greg Turner
5  * Copyright 2003-2006 CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * TODO:
22  *  - String structs
23  *  - Byte count pointers
24  *  - transmit_as/represent as
25  *  - Multi-dimensional arrays
26  *  - Conversion functions (NdrConvert)
27  *  - Checks for integer addition overflow in user marshall functions
28  */
29
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <limits.h>
35
36 #define NONAMELESSUNION
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winerror.h"
40
41 #include "ndr_misc.h"
42 #include "rpcndr.h"
43 #include "ndrtypes.h"
44
45 #include "wine/unicode.h"
46 #include "wine/rpcfc.h"
47
48 #include "wine/debug.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(ole);
51
52 #if defined(__i386__)
53 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
54     (*((UINT32 *)(pchar)) = (uint32))
55
56 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
57     (*((UINT32 *)(pchar)))
58 #else
59   /* these would work for i386 too, but less efficient */
60 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
61     (*(pchar)     = LOBYTE(LOWORD(uint32)), \
62      *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
63      *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
64      *((pchar)+3) = HIBYTE(HIWORD(uint32)))
65
66 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
67     (MAKELONG( \
68       MAKEWORD(*(pchar), *((pchar)+1)), \
69       MAKEWORD(*((pchar)+2), *((pchar)+3))))
70 #endif
71
72 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
73   (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
74    *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
75    *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
76    *(pchar)     = HIBYTE(HIWORD(uint32)))
77
78 #define BIG_ENDIAN_UINT32_READ(pchar) \
79   (MAKELONG( \
80     MAKEWORD(*((pchar)+3), *((pchar)+2)), \
81     MAKEWORD(*((pchar)+1), *(pchar))))
82
83 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
84 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
85     BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
86 # define NDR_LOCAL_UINT32_READ(pchar) \
87     BIG_ENDIAN_UINT32_READ(pchar)
88 #else
89 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
90     LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
91 # define NDR_LOCAL_UINT32_READ(pchar) \
92     LITTLE_ENDIAN_UINT32_READ(pchar)
93 #endif
94
95 static inline void align_length( ULONG *len, unsigned int align )
96 {
97     *len = (*len + align - 1) & ~(align - 1);
98 }
99
100 static inline void align_pointer( unsigned char **ptr, unsigned int align )
101 {
102     ULONG_PTR mask = align - 1;
103     *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
104 }
105
106 static inline void align_pointer_clear( unsigned char **ptr, unsigned int align )
107 {
108     ULONG_PTR mask = align - 1;
109     memset( *ptr, 0, (align - (ULONG_PTR)*ptr) & mask );
110     *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
111 }
112
113 #define STD_OVERFLOW_CHECK(_Msg) do { \
114     TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
115     if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
116         ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
117   } while (0)
118
119 #define NDR_POINTER_ID_BASE 0x20000
120 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
121 #define NDR_TABLE_SIZE 128
122 #define NDR_TABLE_MASK 127
123
124 #define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL))
125
126 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
127 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
128 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
129 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
130 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
131
132 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
133 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
134 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
135
136 static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
137 static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
138 static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
139 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
140
141 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
142
143 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
144                                          unsigned char *pMemory,
145                                          PFORMAT_STRING pFormat,
146                                          PFORMAT_STRING pPointer);
147 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
148                                        unsigned char *pMemory,
149                                        PFORMAT_STRING pFormat,
150                                        PFORMAT_STRING pPointer);
151 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
152                                          unsigned char *pMemory,
153                                          PFORMAT_STRING pFormat,
154                                          PFORMAT_STRING pPointer,
155                                          unsigned char fMustAlloc);
156 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
157                                      PFORMAT_STRING pFormat,
158                                      PFORMAT_STRING pPointer);
159 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
160                                    unsigned char *pMemory,
161                                    PFORMAT_STRING pFormat,
162                                    PFORMAT_STRING pPointer);
163
164 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
165   0,
166   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
167   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
168   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
169   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
170   /* 0x10 */
171   NdrBaseTypeMarshall,
172   /* 0x11 */
173   NdrPointerMarshall, NdrPointerMarshall,
174   NdrPointerMarshall, NdrPointerMarshall,
175   /* 0x15 */
176   NdrSimpleStructMarshall, NdrSimpleStructMarshall,
177   NdrConformantStructMarshall, NdrConformantStructMarshall,
178   NdrConformantVaryingStructMarshall,
179   NdrComplexStructMarshall,
180   /* 0x1b */
181   NdrConformantArrayMarshall, 
182   NdrConformantVaryingArrayMarshall,
183   NdrFixedArrayMarshall, NdrFixedArrayMarshall,
184   NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
185   NdrComplexArrayMarshall,
186   /* 0x22 */
187   NdrConformantStringMarshall, 0, 0,
188   NdrConformantStringMarshall,
189   NdrNonConformantStringMarshall, 0, 0, 0,
190   /* 0x2a */
191   NdrEncapsulatedUnionMarshall,
192   NdrNonEncapsulatedUnionMarshall,
193   NdrByteCountPointerMarshall,
194   NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
195   /* 0x2f */
196   NdrInterfacePointerMarshall,
197   /* 0x30 */
198   NdrContextHandleMarshall,
199   /* 0xb1 */
200   0, 0, 0,
201   NdrUserMarshalMarshall,
202   0, 0,
203   /* 0xb7 */
204   NdrRangeMarshall
205 };
206 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
207   0,
208   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
209   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
210   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
211   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
212   /* 0x10 */
213   NdrBaseTypeUnmarshall,
214   /* 0x11 */
215   NdrPointerUnmarshall, NdrPointerUnmarshall,
216   NdrPointerUnmarshall, NdrPointerUnmarshall,
217   /* 0x15 */
218   NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
219   NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
220   NdrConformantVaryingStructUnmarshall,
221   NdrComplexStructUnmarshall,
222   /* 0x1b */
223   NdrConformantArrayUnmarshall, 
224   NdrConformantVaryingArrayUnmarshall,
225   NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
226   NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
227   NdrComplexArrayUnmarshall,
228   /* 0x22 */
229   NdrConformantStringUnmarshall, 0, 0,
230   NdrConformantStringUnmarshall,
231   NdrNonConformantStringUnmarshall, 0, 0, 0,
232   /* 0x2a */
233   NdrEncapsulatedUnionUnmarshall,
234   NdrNonEncapsulatedUnionUnmarshall,
235   NdrByteCountPointerUnmarshall,
236   NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
237   /* 0x2f */
238   NdrInterfacePointerUnmarshall,
239   /* 0x30 */
240   NdrContextHandleUnmarshall,
241   /* 0xb1 */
242   0, 0, 0,
243   NdrUserMarshalUnmarshall,
244   0, 0,
245   /* 0xb7 */
246   NdrRangeUnmarshall
247 };
248 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
249   0,
250   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
251   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
252   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
253   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
254   /* 0x10 */
255   NdrBaseTypeBufferSize,
256   /* 0x11 */
257   NdrPointerBufferSize, NdrPointerBufferSize,
258   NdrPointerBufferSize, NdrPointerBufferSize,
259   /* 0x15 */
260   NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
261   NdrConformantStructBufferSize, NdrConformantStructBufferSize,
262   NdrConformantVaryingStructBufferSize,
263   NdrComplexStructBufferSize,
264   /* 0x1b */
265   NdrConformantArrayBufferSize, 
266   NdrConformantVaryingArrayBufferSize,
267   NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
268   NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
269   NdrComplexArrayBufferSize,
270   /* 0x22 */
271   NdrConformantStringBufferSize, 0, 0,
272   NdrConformantStringBufferSize,
273   NdrNonConformantStringBufferSize, 0, 0, 0,
274   /* 0x2a */
275   NdrEncapsulatedUnionBufferSize,
276   NdrNonEncapsulatedUnionBufferSize,
277   NdrByteCountPointerBufferSize,
278   NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
279   /* 0x2f */
280   NdrInterfacePointerBufferSize,
281   /* 0x30 */
282   NdrContextHandleBufferSize,
283   /* 0xb1 */
284   0, 0, 0,
285   NdrUserMarshalBufferSize,
286   0, 0,
287   /* 0xb7 */
288   NdrRangeBufferSize
289 };
290 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
291   0,
292   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
293   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
294   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
295   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
296   /* 0x10 */
297   NdrBaseTypeMemorySize,
298   /* 0x11 */
299   NdrPointerMemorySize, NdrPointerMemorySize,
300   NdrPointerMemorySize, NdrPointerMemorySize,
301   /* 0x15 */
302   NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
303   NdrConformantStructMemorySize, NdrConformantStructMemorySize,
304   NdrConformantVaryingStructMemorySize,
305   NdrComplexStructMemorySize,
306   /* 0x1b */
307   NdrConformantArrayMemorySize,
308   NdrConformantVaryingArrayMemorySize,
309   NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
310   NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
311   NdrComplexArrayMemorySize,
312   /* 0x22 */
313   NdrConformantStringMemorySize, 0, 0,
314   NdrConformantStringMemorySize,
315   NdrNonConformantStringMemorySize, 0, 0, 0,
316   /* 0x2a */
317   NdrEncapsulatedUnionMemorySize,
318   NdrNonEncapsulatedUnionMemorySize,
319   NdrByteCountPointerMemorySize,
320   NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
321   /* 0x2f */
322   NdrInterfacePointerMemorySize,
323   /* 0x30 */
324   0,
325   /* 0xb1 */
326   0, 0, 0,
327   NdrUserMarshalMemorySize,
328   0, 0,
329   /* 0xb7 */
330   NdrRangeMemorySize
331 };
332 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
333   0,
334   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
335   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
336   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
337   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
338   /* 0x10 */
339   NdrBaseTypeFree,
340   /* 0x11 */
341   NdrPointerFree, NdrPointerFree,
342   NdrPointerFree, NdrPointerFree,
343   /* 0x15 */
344   NdrSimpleStructFree, NdrSimpleStructFree,
345   NdrConformantStructFree, NdrConformantStructFree,
346   NdrConformantVaryingStructFree,
347   NdrComplexStructFree,
348   /* 0x1b */
349   NdrConformantArrayFree, 
350   NdrConformantVaryingArrayFree,
351   NdrFixedArrayFree, NdrFixedArrayFree,
352   NdrVaryingArrayFree, NdrVaryingArrayFree,
353   NdrComplexArrayFree,
354   /* 0x22 */
355   0, 0, 0,
356   0, 0, 0, 0, 0,
357   /* 0x2a */
358   NdrEncapsulatedUnionFree,
359   NdrNonEncapsulatedUnionFree,
360   0,
361   NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
362   /* 0x2f */
363   NdrInterfacePointerFree,
364   /* 0x30 */
365   0,
366   /* 0xb1 */
367   0, 0, 0,
368   NdrUserMarshalFree,
369   0, 0,
370   /* 0xb7 */
371   NdrRangeFree
372 };
373
374 typedef struct _NDR_MEMORY_LIST
375 {
376     ULONG magic;
377     ULONG size;
378     ULONG reserved;
379     struct _NDR_MEMORY_LIST *next;
380 } NDR_MEMORY_LIST;
381
382 #define MEML_MAGIC  ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
383
384 /***********************************************************************
385  *            NdrAllocate [RPCRT4.@]
386  *
387  * Allocates a block of memory using pStubMsg->pfnAllocate.
388  *
389  * PARAMS
390  *  pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
391  *  len      [I]   Size of memory block to allocate.
392  *
393  * RETURNS
394  *  The memory block of size len that was allocated.
395  *
396  * NOTES
397  *  The memory block is always 8-byte aligned.
398  *  If the function is unable to allocate memory an ERROR_OUTOFMEMORY
399  *  exception is raised.
400  */
401 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len)
402 {
403     SIZE_T aligned_len;
404     SIZE_T adjusted_len;
405     void *p;
406     NDR_MEMORY_LIST *mem_list;
407
408     aligned_len = (len + 7) & ~7;
409     adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
410     /* check for overflow */
411     if (adjusted_len < len)
412     {
413         ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len);
414         RpcRaiseException(RPC_X_BAD_STUB_DATA);
415     }
416
417     p = pStubMsg->pfnAllocate(adjusted_len);
418     if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
419
420     mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
421     mem_list->magic = MEML_MAGIC;
422     mem_list->size = aligned_len;
423     mem_list->reserved = 0;
424     mem_list->next = pStubMsg->pMemoryList;
425     pStubMsg->pMemoryList = mem_list;
426
427     TRACE("-- %p\n", p);
428     return p;
429 }
430
431 static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
432 {
433     TRACE("(%p, %p)\n", pStubMsg, Pointer);
434
435     pStubMsg->pfnFree(Pointer);
436 }
437
438 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
439 {
440     return (*(const ULONG *)pFormat != -1);
441 }
442
443 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
444 {
445   align_pointer(&pStubMsg->Buffer, 4);
446   if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
447       RpcRaiseException(RPC_X_BAD_STUB_DATA);
448   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
449   pStubMsg->Buffer += 4;
450   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
451   if (pStubMsg->fHasNewCorrDesc)
452     return pFormat+6;
453   else
454     return pFormat+4;
455 }
456
457 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
458 {
459   if (pFormat && !IsConformanceOrVariancePresent(pFormat))
460   {
461     pStubMsg->Offset = 0;
462     pStubMsg->ActualCount = pStubMsg->MaxCount;
463     goto done;
464   }
465
466   align_pointer(&pStubMsg->Buffer, 4);
467   if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
468     RpcRaiseException(RPC_X_BAD_STUB_DATA);
469   pStubMsg->Offset      = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
470   pStubMsg->Buffer += 4;
471   TRACE("offset is %d\n", pStubMsg->Offset);
472   pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
473   pStubMsg->Buffer += 4;
474   TRACE("variance is %d\n", pStubMsg->ActualCount);
475
476   if ((pStubMsg->ActualCount > MaxValue) ||
477       (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
478   {
479     ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
480         pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
481     RpcRaiseException(RPC_S_INVALID_BOUND);
482     return NULL;
483   }
484
485 done:
486   if (pStubMsg->fHasNewCorrDesc)
487     return pFormat+6;
488   else
489     return pFormat+4;
490 }
491
492 /* writes the conformance value to the buffer */
493 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
494 {
495     align_pointer_clear(&pStubMsg->Buffer, 4);
496     if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
497         RpcRaiseException(RPC_X_BAD_STUB_DATA);
498     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
499     pStubMsg->Buffer += 4;
500 }
501
502 /* writes the variance values to the buffer */
503 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
504 {
505     align_pointer_clear(&pStubMsg->Buffer, 4);
506     if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
507         RpcRaiseException(RPC_X_BAD_STUB_DATA);
508     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
509     pStubMsg->Buffer += 4;
510     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
511     pStubMsg->Buffer += 4;
512 }
513
514 /* requests buffer space for the conformance value */
515 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
516 {
517     align_length(&pStubMsg->BufferLength, 4);
518     if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
519         RpcRaiseException(RPC_X_BAD_STUB_DATA);
520     pStubMsg->BufferLength += 4;
521 }
522
523 /* requests buffer space for the variance values */
524 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
525 {
526     align_length(&pStubMsg->BufferLength, 4);
527     if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
528         RpcRaiseException(RPC_X_BAD_STUB_DATA);
529     pStubMsg->BufferLength += 8;
530 }
531
532 PFORMAT_STRING ComputeConformanceOrVariance(
533     MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
534     PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
535 {
536   BYTE dtype = pFormat[0] & 0xf;
537   short ofs = *(const short *)&pFormat[2];
538   LPVOID ptr = NULL;
539   ULONG_PTR data = 0;
540
541   if (!IsConformanceOrVariancePresent(pFormat)) {
542     /* null descriptor */
543     *pCount = def;
544     goto finish_conf;
545   }
546
547   switch (pFormat[0] & 0xf0) {
548   case RPC_FC_NORMAL_CONFORMANCE:
549     TRACE("normal conformance, ofs=%d\n", ofs);
550     ptr = pMemory;
551     break;
552   case RPC_FC_POINTER_CONFORMANCE:
553     TRACE("pointer conformance, ofs=%d\n", ofs);
554     ptr = pStubMsg->Memory;
555     break;
556   case RPC_FC_TOP_LEVEL_CONFORMANCE:
557     TRACE("toplevel conformance, ofs=%d\n", ofs);
558     if (pStubMsg->StackTop) {
559       ptr = pStubMsg->StackTop;
560     }
561     else {
562       /* -Os mode, *pCount is already set */
563       goto finish_conf;
564     }
565     break;
566   case RPC_FC_CONSTANT_CONFORMANCE:
567     data = ofs | ((DWORD)pFormat[1] << 16);
568     TRACE("constant conformance, val=%ld\n", data);
569     *pCount = data;
570     goto finish_conf;
571   case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
572     FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
573     if (pStubMsg->StackTop) {
574       ptr = pStubMsg->StackTop;
575     }
576     else {
577       /* ? */
578       goto done_conf_grab;
579     }
580     break;
581   default:
582     FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0);
583     goto finish_conf;
584   }
585
586   switch (pFormat[1]) {
587   case RPC_FC_DEREFERENCE:
588     ptr = *(LPVOID*)((char *)ptr + ofs);
589     break;
590   case RPC_FC_CALLBACK:
591   {
592     unsigned char *old_stack_top = pStubMsg->StackTop;
593     ULONG_PTR max_count, old_max_count = pStubMsg->MaxCount;
594
595     pStubMsg->StackTop = ptr;
596
597     /* ofs is index into StubDesc->apfnExprEval */
598     TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
599     pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
600
601     pStubMsg->StackTop = old_stack_top;
602
603     /* the callback function always stores the computed value in MaxCount */
604     max_count = pStubMsg->MaxCount;
605     pStubMsg->MaxCount = old_max_count;
606     *pCount = max_count;
607     goto finish_conf;
608   }
609   default:
610     ptr = (char *)ptr + ofs;
611     break;
612   }
613
614   switch (dtype) {
615   case RPC_FC_LONG:
616   case RPC_FC_ULONG:
617     data = *(DWORD*)ptr;
618     break;
619   case RPC_FC_SHORT:
620     data = *(SHORT*)ptr;
621     break;
622   case RPC_FC_USHORT:
623     data = *(USHORT*)ptr;
624     break;
625   case RPC_FC_CHAR:
626   case RPC_FC_SMALL:
627     data = *(CHAR*)ptr;
628     break;
629   case RPC_FC_BYTE:
630   case RPC_FC_USMALL:
631     data = *(UCHAR*)ptr;
632     break;
633   case RPC_FC_HYPER:
634     data = *(ULONGLONG *)ptr;
635     break;
636   default:
637     FIXME("unknown conformance data type %x\n", dtype);
638     goto done_conf_grab;
639   }
640   TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);
641
642 done_conf_grab:
643   switch (pFormat[1]) {
644   case RPC_FC_DEREFERENCE: /* already handled */
645   case 0: /* no op */
646     *pCount = data;
647     break;
648   case RPC_FC_ADD_1:
649     *pCount = data + 1;
650     break;
651   case RPC_FC_SUB_1:
652     *pCount = data - 1;
653     break;
654   case RPC_FC_MULT_2:
655     *pCount = data * 2;
656     break;
657   case RPC_FC_DIV_2:
658     *pCount = data / 2;
659     break;
660   default:
661     FIXME("unknown conformance op %d\n", pFormat[1]);
662     goto finish_conf;
663   }
664
665 finish_conf:
666   TRACE("resulting conformance is %ld\n", *pCount);
667   if (pStubMsg->fHasNewCorrDesc)
668     return pFormat+6;
669   else
670     return pFormat+4;
671 }
672
673 static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg,
674                                              PFORMAT_STRING pFormat)
675 {
676     if (pStubMsg->fHasNewCorrDesc)
677       pFormat += 6;
678     else
679       pFormat += 4;
680     return pFormat;
681 }
682
683 static inline PFORMAT_STRING SkipVariance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
684 {
685     return SkipConformance( pStubMsg, pFormat );
686 }
687
688 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
689  * the result overflows 32-bits */
690 static inline ULONG safe_multiply(ULONG a, ULONG b)
691 {
692     ULONGLONG ret = (ULONGLONG)a * b;
693     if (ret > 0xffffffff)
694     {
695         RpcRaiseException(RPC_S_INVALID_BOUND);
696         return 0;
697     }
698     return ret;
699 }
700
701 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
702 {
703     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
704         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
705         RpcRaiseException(RPC_X_BAD_STUB_DATA);
706     pStubMsg->Buffer += size;
707 }
708
709 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
710 {
711     if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
712     {
713         ERR("buffer length overflow - BufferLength = %u, size = %u\n",
714             pStubMsg->BufferLength, size);
715         RpcRaiseException(RPC_X_BAD_STUB_DATA);
716     }
717     pStubMsg->BufferLength += size;
718 }
719
720 /* copies data from the buffer, checking that there is enough data in the buffer
721  * to do so */
722 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
723 {
724     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
725         (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
726     {
727         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
728             pStubMsg->Buffer, pStubMsg->BufferEnd, size);
729         RpcRaiseException(RPC_X_BAD_STUB_DATA);
730     }
731     if (p == pStubMsg->Buffer)
732         ERR("pointer is the same as the buffer\n");
733     memcpy(p, pStubMsg->Buffer, size);
734     pStubMsg->Buffer += size;
735 }
736
737 /* copies data to the buffer, checking that there is enough space to do so */
738 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
739 {
740     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
741         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
742     {
743         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
744             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
745             size);
746         RpcRaiseException(RPC_X_BAD_STUB_DATA);
747     }
748     memcpy(pStubMsg->Buffer, p, size);
749     pStubMsg->Buffer += size;
750 }
751
752 /* verify that string data sitting in the buffer is valid and safe to
753  * unmarshall */
754 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
755 {
756     ULONG i;
757
758     /* verify the buffer is safe to access */
759     if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
760         (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
761     {
762         ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
763             pStubMsg->BufferEnd, pStubMsg->Buffer);
764         RpcRaiseException(RPC_X_BAD_STUB_DATA);
765     }
766
767     /* strings must always have null terminating bytes */
768     if (bufsize < esize)
769     {
770         ERR("invalid string length of %d\n", bufsize / esize);
771         RpcRaiseException(RPC_S_INVALID_BOUND);
772     }
773
774     for (i = bufsize - esize; i < bufsize; i++)
775         if (pStubMsg->Buffer[i] != 0)
776         {
777             ERR("string not null-terminated at byte position %d, data is 0x%x\n",
778                 i, pStubMsg->Buffer[i]);
779             RpcRaiseException(RPC_S_INVALID_BOUND);
780         }
781 }
782
783 static inline void dump_pointer_attr(unsigned char attr)
784 {
785     if (attr & RPC_FC_P_ALLOCALLNODES)
786         TRACE(" RPC_FC_P_ALLOCALLNODES");
787     if (attr & RPC_FC_P_DONTFREE)
788         TRACE(" RPC_FC_P_DONTFREE");
789     if (attr & RPC_FC_P_ONSTACK)
790         TRACE(" RPC_FC_P_ONSTACK");
791     if (attr & RPC_FC_P_SIMPLEPOINTER)
792         TRACE(" RPC_FC_P_SIMPLEPOINTER");
793     if (attr & RPC_FC_P_DEREF)
794         TRACE(" RPC_FC_P_DEREF");
795     TRACE("\n");
796 }
797
798 /***********************************************************************
799  *           PointerMarshall [internal]
800  */
801 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
802                             unsigned char *Buffer,
803                             unsigned char *Pointer,
804                             PFORMAT_STRING pFormat)
805 {
806   unsigned type = pFormat[0], attr = pFormat[1];
807   PFORMAT_STRING desc;
808   NDR_MARSHALL m;
809   ULONG pointer_id;
810   int pointer_needs_marshaling;
811
812   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
813   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
814   pFormat += 2;
815   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
816   else desc = pFormat + *(const SHORT*)pFormat;
817
818   switch (type) {
819   case RPC_FC_RP: /* ref pointer (always non-null) */
820     if (!Pointer)
821     {
822       ERR("NULL ref pointer is not allowed\n");
823       RpcRaiseException(RPC_X_NULL_REF_POINTER);
824     }
825     pointer_needs_marshaling = 1;
826     break;
827   case RPC_FC_UP: /* unique pointer */
828   case RPC_FC_OP: /* object pointer - same as unique here */
829     if (Pointer)
830       pointer_needs_marshaling = 1;
831     else
832       pointer_needs_marshaling = 0;
833     pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
834     TRACE("writing 0x%08x to buffer\n", pointer_id);
835     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
836     break;
837   case RPC_FC_FP:
838     pointer_needs_marshaling = !NdrFullPointerQueryPointer(
839       pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
840     TRACE("writing 0x%08x to buffer\n", pointer_id);
841     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
842     break;
843   default:
844     FIXME("unhandled ptr type=%02x\n", type);
845     RpcRaiseException(RPC_X_BAD_STUB_DATA);
846     return;
847   }
848
849   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
850
851   if (pointer_needs_marshaling) {
852     if (attr & RPC_FC_P_DEREF) {
853       Pointer = *(unsigned char**)Pointer;
854       TRACE("deref => %p\n", Pointer);
855     }
856     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
857     if (m) m(pStubMsg, Pointer, desc);
858     else FIXME("no marshaller for data type=%02x\n", *desc);
859   }
860
861   STD_OVERFLOW_CHECK(pStubMsg);
862 }
863
864 /***********************************************************************
865  *           PointerUnmarshall [internal]
866  */
867 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
868                               unsigned char *Buffer,
869                               unsigned char **pPointer,
870                               unsigned char *pSrcPointer,
871                               PFORMAT_STRING pFormat,
872                               unsigned char fMustAlloc)
873 {
874   unsigned type = pFormat[0], attr = pFormat[1];
875   PFORMAT_STRING desc;
876   NDR_UNMARSHALL m;
877   DWORD pointer_id = 0;
878   int pointer_needs_unmarshaling;
879
880   TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
881   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
882   pFormat += 2;
883   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
884   else desc = pFormat + *(const SHORT*)pFormat;
885
886   switch (type) {
887   case RPC_FC_RP: /* ref pointer (always non-null) */
888     pointer_needs_unmarshaling = 1;
889     break;
890   case RPC_FC_UP: /* unique pointer */
891     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
892     TRACE("pointer_id is 0x%08x\n", pointer_id);
893     if (pointer_id)
894       pointer_needs_unmarshaling = 1;
895     else {
896       *pPointer = NULL;
897       pointer_needs_unmarshaling = 0;
898     }
899     break;
900   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
901     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
902     TRACE("pointer_id is 0x%08x\n", pointer_id);
903     if (!fMustAlloc && pSrcPointer)
904     {
905         FIXME("free object pointer %p\n", pSrcPointer);
906         fMustAlloc = TRUE;
907     }
908     if (pointer_id)
909       pointer_needs_unmarshaling = 1;
910     else
911     {
912       *pPointer = NULL;    
913       pointer_needs_unmarshaling = 0;
914     }
915     break;
916   case RPC_FC_FP:
917     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
918     TRACE("pointer_id is 0x%08x\n", pointer_id);
919     pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
920       pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
921     break;
922   default:
923     FIXME("unhandled ptr type=%02x\n", type);
924     RpcRaiseException(RPC_X_BAD_STUB_DATA);
925     return;
926   }
927
928   if (pointer_needs_unmarshaling) {
929     unsigned char **current_ptr = pPointer;
930     if (pStubMsg->IsClient) {
931       TRACE("client\n");
932       /* if we aren't forcing allocation of memory then try to use the existing
933        * (source) pointer to unmarshall the data into so that [in,out]
934        * parameters behave correctly. it doesn't matter if the parameter is
935        * [out] only since in that case the pointer will be NULL. we force
936        * allocation when the source pointer is NULL here instead of in the type
937        * unmarshalling routine for the benefit of the deref code below */
938       if (!fMustAlloc) {
939         if (pSrcPointer) {
940           TRACE("setting *pPointer to %p\n", pSrcPointer);
941           *pPointer = pSrcPointer;
942         } else
943           fMustAlloc = TRUE;
944       }
945     } else {
946       TRACE("server\n");
947       /* the memory in a stub is never initialised, so we have to work out here
948        * whether we have to initialise it so we can use the optimisation of
949        * setting the pointer to the buffer, if possible, or set fMustAlloc to
950        * TRUE. */
951       if (attr & RPC_FC_P_DEREF) {
952         fMustAlloc = TRUE;
953       } else {
954         *current_ptr = NULL;
955       }
956     }
957
958     if (attr & RPC_FC_P_ALLOCALLNODES)
959         FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
960
961     if (attr & RPC_FC_P_DEREF) {
962       if (fMustAlloc) {
963         unsigned char *base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
964         *pPointer = base_ptr_val;
965         current_ptr = (unsigned char **)base_ptr_val;
966       } else
967         current_ptr = *(unsigned char***)current_ptr;
968       TRACE("deref => %p\n", current_ptr);
969       if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
970     }
971     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
972     if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
973     else FIXME("no unmarshaller for data type=%02x\n", *desc);
974
975     if (type == RPC_FC_FP)
976       NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
977                                 *pPointer);
978   }
979
980   TRACE("pointer=%p\n", *pPointer);
981 }
982
983 /***********************************************************************
984  *           PointerBufferSize [internal]
985  */
986 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
987                               unsigned char *Pointer,
988                               PFORMAT_STRING pFormat)
989 {
990   unsigned type = pFormat[0], attr = pFormat[1];
991   PFORMAT_STRING desc;
992   NDR_BUFFERSIZE m;
993   int pointer_needs_sizing;
994   ULONG pointer_id;
995
996   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
997   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
998   pFormat += 2;
999   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1000   else desc = pFormat + *(const SHORT*)pFormat;
1001
1002   switch (type) {
1003   case RPC_FC_RP: /* ref pointer (always non-null) */
1004     if (!Pointer)
1005     {
1006       ERR("NULL ref pointer is not allowed\n");
1007       RpcRaiseException(RPC_X_NULL_REF_POINTER);
1008     }
1009     break;
1010   case RPC_FC_OP:
1011   case RPC_FC_UP:
1012     /* NULL pointer has no further representation */
1013     if (!Pointer)
1014         return;
1015     break;
1016   case RPC_FC_FP:
1017     pointer_needs_sizing = !NdrFullPointerQueryPointer(
1018       pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1019     if (!pointer_needs_sizing)
1020       return;
1021     break;
1022   default:
1023     FIXME("unhandled ptr type=%02x\n", type);
1024     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1025     return;
1026   }
1027
1028   if (attr & RPC_FC_P_DEREF) {
1029     Pointer = *(unsigned char**)Pointer;
1030     TRACE("deref => %p\n", Pointer);
1031   }
1032
1033   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1034   if (m) m(pStubMsg, Pointer, desc);
1035   else FIXME("no buffersizer for data type=%02x\n", *desc);
1036 }
1037
1038 /***********************************************************************
1039  *           PointerMemorySize [internal]
1040  */
1041 static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1042                                unsigned char *Buffer, PFORMAT_STRING pFormat)
1043 {
1044   unsigned type = pFormat[0], attr = pFormat[1];
1045   PFORMAT_STRING desc;
1046   NDR_MEMORYSIZE m;
1047   DWORD pointer_id = 0;
1048   int pointer_needs_sizing;
1049
1050   TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1051   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1052   pFormat += 2;
1053   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1054   else desc = pFormat + *(const SHORT*)pFormat;
1055
1056   switch (type) {
1057   case RPC_FC_RP: /* ref pointer (always non-null) */
1058     pointer_needs_sizing = 1;
1059     break;
1060   case RPC_FC_UP: /* unique pointer */
1061   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1062     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1063     TRACE("pointer_id is 0x%08x\n", pointer_id);
1064     if (pointer_id)
1065       pointer_needs_sizing = 1;
1066     else
1067       pointer_needs_sizing = 0;
1068     break;
1069   case RPC_FC_FP:
1070   {
1071     void *pointer;
1072     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1073     TRACE("pointer_id is 0x%08x\n", pointer_id);
1074     pointer_needs_sizing = !NdrFullPointerQueryRefId(
1075       pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1076     break;
1077   }
1078   default:
1079     FIXME("unhandled ptr type=%02x\n", type);
1080     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1081     return 0;
1082   }
1083
1084   if (attr & RPC_FC_P_DEREF) {
1085     align_length(&pStubMsg->MemorySize, sizeof(void*));
1086     pStubMsg->MemorySize += sizeof(void*);
1087     TRACE("deref\n");
1088   }
1089
1090   if (pointer_needs_sizing) {
1091     m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1092     if (m) m(pStubMsg, desc);
1093     else FIXME("no memorysizer for data type=%02x\n", *desc);
1094   }
1095
1096   return pStubMsg->MemorySize;
1097 }
1098
1099 /***********************************************************************
1100  *           PointerFree [internal]
1101  */
1102 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1103                         unsigned char *Pointer,
1104                         PFORMAT_STRING pFormat)
1105 {
1106   unsigned type = pFormat[0], attr = pFormat[1];
1107   PFORMAT_STRING desc;
1108   NDR_FREE m;
1109   unsigned char *current_pointer = Pointer;
1110
1111   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1112   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1113   if (attr & RPC_FC_P_DONTFREE) return;
1114   pFormat += 2;
1115   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1116   else desc = pFormat + *(const SHORT*)pFormat;
1117
1118   if (!Pointer) return;
1119
1120   if (type == RPC_FC_FP) {
1121     int pointer_needs_freeing = NdrFullPointerFree(
1122       pStubMsg->FullPtrXlatTables, Pointer);
1123     if (!pointer_needs_freeing)
1124       return;
1125   }
1126
1127   if (attr & RPC_FC_P_DEREF) {
1128     current_pointer = *(unsigned char**)Pointer;
1129     TRACE("deref => %p\n", current_pointer);
1130   }
1131
1132   m = NdrFreer[*desc & NDR_TABLE_MASK];
1133   if (m) m(pStubMsg, current_pointer, desc);
1134
1135   /* this check stops us from trying to free buffer memory. we don't have to
1136    * worry about clients, since they won't call this function.
1137    * we don't have to check for the buffer being reallocated because
1138    * BufferStart and BufferEnd won't be reset when allocating memory for
1139    * sending the response. we don't have to check for the new buffer here as
1140    * it won't be used a type memory, only for buffer memory */
1141   if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd)
1142       goto notfree;
1143
1144   if (attr & RPC_FC_P_ONSTACK) {
1145     TRACE("not freeing stack ptr %p\n", Pointer);
1146     return;
1147   }
1148   TRACE("freeing %p\n", Pointer);
1149   NdrFree(pStubMsg, Pointer);
1150   return;
1151 notfree:
1152   TRACE("not freeing %p\n", Pointer);
1153 }
1154
1155 /***********************************************************************
1156  *           EmbeddedPointerMarshall
1157  */
1158 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1159                                                unsigned char *pMemory,
1160                                                PFORMAT_STRING pFormat)
1161 {
1162   unsigned char *Mark = pStubMsg->BufferMark;
1163   unsigned rep, count, stride;
1164   unsigned i;
1165   unsigned char *saved_buffer = NULL;
1166
1167   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1168
1169   if (*pFormat != RPC_FC_PP) return NULL;
1170   pFormat += 2;
1171
1172   if (pStubMsg->PointerBufferMark)
1173   {
1174     saved_buffer = pStubMsg->Buffer;
1175     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1176     pStubMsg->PointerBufferMark = NULL;
1177   }
1178
1179   while (pFormat[0] != RPC_FC_END) {
1180     switch (pFormat[0]) {
1181     default:
1182       FIXME("unknown repeat type %d\n", pFormat[0]);
1183     case RPC_FC_NO_REPEAT:
1184       rep = 1;
1185       stride = 0;
1186       count = 1;
1187       pFormat += 2;
1188       break;
1189     case RPC_FC_FIXED_REPEAT:
1190       rep = *(const WORD*)&pFormat[2];
1191       stride = *(const WORD*)&pFormat[4];
1192       count = *(const WORD*)&pFormat[8];
1193       pFormat += 10;
1194       break;
1195     case RPC_FC_VARIABLE_REPEAT:
1196       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1197       stride = *(const WORD*)&pFormat[2];
1198       count = *(const WORD*)&pFormat[6];
1199       pFormat += 8;
1200       break;
1201     }
1202     for (i = 0; i < rep; i++) {
1203       PFORMAT_STRING info = pFormat;
1204       unsigned char *membase = pMemory + (i * stride);
1205       unsigned char *bufbase = Mark + (i * stride);
1206       unsigned u;
1207
1208       for (u=0; u<count; u++,info+=8) {
1209         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1210         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1211         unsigned char *saved_memory = pStubMsg->Memory;
1212
1213         pStubMsg->Memory = pMemory;
1214         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1215         pStubMsg->Memory = saved_memory;
1216       }
1217     }
1218     pFormat += 8 * count;
1219   }
1220
1221   if (saved_buffer)
1222   {
1223     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1224     pStubMsg->Buffer = saved_buffer;
1225   }
1226
1227   STD_OVERFLOW_CHECK(pStubMsg);
1228
1229   return NULL;
1230 }
1231
1232 /***********************************************************************
1233  *           EmbeddedPointerUnmarshall
1234  */
1235 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1236                                                  unsigned char *pDstBuffer,
1237                                                  unsigned char *pSrcMemoryPtrs,
1238                                                  PFORMAT_STRING pFormat,
1239                                                  unsigned char fMustAlloc)
1240 {
1241   unsigned char *Mark = pStubMsg->BufferMark;
1242   unsigned rep, count, stride;
1243   unsigned i;
1244   unsigned char *saved_buffer = NULL;
1245
1246   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1247
1248   if (*pFormat != RPC_FC_PP) return NULL;
1249   pFormat += 2;
1250
1251   if (pStubMsg->PointerBufferMark)
1252   {
1253     saved_buffer = pStubMsg->Buffer;
1254     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1255     pStubMsg->PointerBufferMark = NULL;
1256   }
1257
1258   while (pFormat[0] != RPC_FC_END) {
1259     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1260     switch (pFormat[0]) {
1261     default:
1262       FIXME("unknown repeat type %d\n", pFormat[0]);
1263     case RPC_FC_NO_REPEAT:
1264       rep = 1;
1265       stride = 0;
1266       count = 1;
1267       pFormat += 2;
1268       break;
1269     case RPC_FC_FIXED_REPEAT:
1270       rep = *(const WORD*)&pFormat[2];
1271       stride = *(const WORD*)&pFormat[4];
1272       count = *(const WORD*)&pFormat[8];
1273       pFormat += 10;
1274       break;
1275     case RPC_FC_VARIABLE_REPEAT:
1276       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1277       stride = *(const WORD*)&pFormat[2];
1278       count = *(const WORD*)&pFormat[6];
1279       pFormat += 8;
1280       break;
1281     }
1282     for (i = 0; i < rep; i++) {
1283       PFORMAT_STRING info = pFormat;
1284       unsigned char *bufdstbase = pDstBuffer + (i * stride);
1285       unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1286       unsigned char *bufbase = Mark + (i * stride);
1287       unsigned u;
1288
1289       for (u=0; u<count; u++,info+=8) {
1290         unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1291         unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1292         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1293         PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1294       }
1295     }
1296     pFormat += 8 * count;
1297   }
1298
1299   if (saved_buffer)
1300   {
1301     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1302     pStubMsg->Buffer = saved_buffer;
1303   }
1304
1305   return NULL;
1306 }
1307
1308 /***********************************************************************
1309  *           EmbeddedPointerBufferSize
1310  */
1311 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1312                                       unsigned char *pMemory,
1313                                       PFORMAT_STRING pFormat)
1314 {
1315   unsigned rep, count, stride;
1316   unsigned i;
1317   ULONG saved_buffer_length = 0;
1318
1319   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1320
1321   if (pStubMsg->IgnoreEmbeddedPointers) return;
1322
1323   if (*pFormat != RPC_FC_PP) return;
1324   pFormat += 2;
1325
1326   if (pStubMsg->PointerLength)
1327   {
1328     saved_buffer_length = pStubMsg->BufferLength;
1329     pStubMsg->BufferLength = pStubMsg->PointerLength;
1330     pStubMsg->PointerLength = 0;
1331   }
1332
1333   while (pFormat[0] != RPC_FC_END) {
1334     switch (pFormat[0]) {
1335     default:
1336       FIXME("unknown repeat type %d\n", pFormat[0]);
1337     case RPC_FC_NO_REPEAT:
1338       rep = 1;
1339       stride = 0;
1340       count = 1;
1341       pFormat += 2;
1342       break;
1343     case RPC_FC_FIXED_REPEAT:
1344       rep = *(const WORD*)&pFormat[2];
1345       stride = *(const WORD*)&pFormat[4];
1346       count = *(const WORD*)&pFormat[8];
1347       pFormat += 10;
1348       break;
1349     case RPC_FC_VARIABLE_REPEAT:
1350       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1351       stride = *(const WORD*)&pFormat[2];
1352       count = *(const WORD*)&pFormat[6];
1353       pFormat += 8;
1354       break;
1355     }
1356     for (i = 0; i < rep; i++) {
1357       PFORMAT_STRING info = pFormat;
1358       unsigned char *membase = pMemory + (i * stride);
1359       unsigned u;
1360
1361       for (u=0; u<count; u++,info+=8) {
1362         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1363         unsigned char *saved_memory = pStubMsg->Memory;
1364
1365         pStubMsg->Memory = pMemory;
1366         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1367         pStubMsg->Memory = saved_memory;
1368       }
1369     }
1370     pFormat += 8 * count;
1371   }
1372
1373   if (saved_buffer_length)
1374   {
1375     pStubMsg->PointerLength = pStubMsg->BufferLength;
1376     pStubMsg->BufferLength = saved_buffer_length;
1377   }
1378 }
1379
1380 /***********************************************************************
1381  *           EmbeddedPointerMemorySize [internal]
1382  */
1383 static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1384                                        PFORMAT_STRING pFormat)
1385 {
1386   unsigned char *Mark = pStubMsg->BufferMark;
1387   unsigned rep, count, stride;
1388   unsigned i;
1389   unsigned char *saved_buffer = NULL;
1390
1391   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1392
1393   if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1394
1395   if (pStubMsg->PointerBufferMark)
1396   {
1397     saved_buffer = pStubMsg->Buffer;
1398     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1399     pStubMsg->PointerBufferMark = NULL;
1400   }
1401
1402   if (*pFormat != RPC_FC_PP) return 0;
1403   pFormat += 2;
1404
1405   while (pFormat[0] != RPC_FC_END) {
1406     switch (pFormat[0]) {
1407     default:
1408       FIXME("unknown repeat type %d\n", pFormat[0]);
1409     case RPC_FC_NO_REPEAT:
1410       rep = 1;
1411       stride = 0;
1412       count = 1;
1413       pFormat += 2;
1414       break;
1415     case RPC_FC_FIXED_REPEAT:
1416       rep = *(const WORD*)&pFormat[2];
1417       stride = *(const WORD*)&pFormat[4];
1418       count = *(const WORD*)&pFormat[8];
1419       pFormat += 10;
1420       break;
1421     case RPC_FC_VARIABLE_REPEAT:
1422       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1423       stride = *(const WORD*)&pFormat[2];
1424       count = *(const WORD*)&pFormat[6];
1425       pFormat += 8;
1426       break;
1427     }
1428     for (i = 0; i < rep; i++) {
1429       PFORMAT_STRING info = pFormat;
1430       unsigned char *bufbase = Mark + (i * stride);
1431       unsigned u;
1432       for (u=0; u<count; u++,info+=8) {
1433         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1434         PointerMemorySize(pStubMsg, bufptr, info+4);
1435       }
1436     }
1437     pFormat += 8 * count;
1438   }
1439
1440   if (saved_buffer)
1441   {
1442     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1443     pStubMsg->Buffer = saved_buffer;
1444   }
1445
1446   return 0;
1447 }
1448
1449 /***********************************************************************
1450  *           EmbeddedPointerFree [internal]
1451  */
1452 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1453                                 unsigned char *pMemory,
1454                                 PFORMAT_STRING pFormat)
1455 {
1456   unsigned rep, count, stride;
1457   unsigned i;
1458
1459   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1460   if (*pFormat != RPC_FC_PP) return;
1461   pFormat += 2;
1462
1463   while (pFormat[0] != RPC_FC_END) {
1464     switch (pFormat[0]) {
1465     default:
1466       FIXME("unknown repeat type %d\n", pFormat[0]);
1467     case RPC_FC_NO_REPEAT:
1468       rep = 1;
1469       stride = 0;
1470       count = 1;
1471       pFormat += 2;
1472       break;
1473     case RPC_FC_FIXED_REPEAT:
1474       rep = *(const WORD*)&pFormat[2];
1475       stride = *(const WORD*)&pFormat[4];
1476       count = *(const WORD*)&pFormat[8];
1477       pFormat += 10;
1478       break;
1479     case RPC_FC_VARIABLE_REPEAT:
1480       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1481       stride = *(const WORD*)&pFormat[2];
1482       count = *(const WORD*)&pFormat[6];
1483       pFormat += 8;
1484       break;
1485     }
1486     for (i = 0; i < rep; i++) {
1487       PFORMAT_STRING info = pFormat;
1488       unsigned char *membase = pMemory + (i * stride);
1489       unsigned u;
1490
1491       for (u=0; u<count; u++,info+=8) {
1492         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1493         unsigned char *saved_memory = pStubMsg->Memory;
1494
1495         pStubMsg->Memory = pMemory;
1496         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1497         pStubMsg->Memory = saved_memory;
1498       }
1499     }
1500     pFormat += 8 * count;
1501   }
1502 }
1503
1504 /***********************************************************************
1505  *           NdrPointerMarshall [RPCRT4.@]
1506  */
1507 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1508                                           unsigned char *pMemory,
1509                                           PFORMAT_STRING pFormat)
1510 {
1511   unsigned char *Buffer;
1512
1513   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1514
1515   /* Increment the buffer here instead of in PointerMarshall,
1516    * as that is used by embedded pointers which already handle the incrementing
1517    * the buffer, and shouldn't write any additional pointer data to the wire */
1518   if (*pFormat != RPC_FC_RP)
1519   {
1520     align_pointer_clear(&pStubMsg->Buffer, 4);
1521     Buffer = pStubMsg->Buffer;
1522     safe_buffer_increment(pStubMsg, 4);
1523   }
1524   else
1525     Buffer = pStubMsg->Buffer;
1526
1527   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1528
1529   return NULL;
1530 }
1531
1532 /***********************************************************************
1533  *           NdrPointerUnmarshall [RPCRT4.@]
1534  */
1535 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1536                                             unsigned char **ppMemory,
1537                                             PFORMAT_STRING pFormat,
1538                                             unsigned char fMustAlloc)
1539 {
1540   unsigned char *Buffer;
1541
1542   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1543
1544   if (*pFormat == RPC_FC_RP)
1545   {
1546     Buffer = pStubMsg->Buffer;
1547     /* Do the NULL ref pointer check here because embedded pointers can be
1548      * NULL if the type the pointer is embedded in was allocated rather than
1549      * being passed in by the client */
1550     if (pStubMsg->IsClient && !*ppMemory)
1551     {
1552       ERR("NULL ref pointer is not allowed\n");
1553       RpcRaiseException(RPC_X_NULL_REF_POINTER);
1554     }
1555   }
1556   else
1557   {
1558     /* Increment the buffer here instead of in PointerUnmarshall,
1559      * as that is used by embedded pointers which already handle the incrementing
1560      * the buffer, and shouldn't read any additional pointer data from the
1561      * buffer */
1562     align_pointer(&pStubMsg->Buffer, 4);
1563     Buffer = pStubMsg->Buffer;
1564     safe_buffer_increment(pStubMsg, 4);
1565   }
1566
1567   PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1568
1569   return NULL;
1570 }
1571
1572 /***********************************************************************
1573  *           NdrPointerBufferSize [RPCRT4.@]
1574  */
1575 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1576                                       unsigned char *pMemory,
1577                                       PFORMAT_STRING pFormat)
1578 {
1579   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1580
1581   /* Increment the buffer length here instead of in PointerBufferSize,
1582    * as that is used by embedded pointers which already handle the buffer
1583    * length, and shouldn't write anything more to the wire */
1584   if (*pFormat != RPC_FC_RP)
1585   {
1586     align_length(&pStubMsg->BufferLength, 4);
1587     safe_buffer_length_increment(pStubMsg, 4);
1588   }
1589
1590   PointerBufferSize(pStubMsg, pMemory, pFormat);
1591 }
1592
1593 /***********************************************************************
1594  *           NdrPointerMemorySize [RPCRT4.@]
1595  */
1596 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1597                                   PFORMAT_STRING pFormat)
1598 {
1599     unsigned char *Buffer = pStubMsg->Buffer;
1600     if (*pFormat != RPC_FC_RP)
1601     {
1602         align_pointer(&pStubMsg->Buffer, 4);
1603         safe_buffer_increment(pStubMsg, 4);
1604     }
1605     align_length(&pStubMsg->MemorySize, sizeof(void *));
1606     return PointerMemorySize(pStubMsg, Buffer, pFormat);
1607 }
1608
1609 /***********************************************************************
1610  *           NdrPointerFree [RPCRT4.@]
1611  */
1612 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1613                            unsigned char *pMemory,
1614                            PFORMAT_STRING pFormat)
1615 {
1616   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1617   PointerFree(pStubMsg, pMemory, pFormat);
1618 }
1619
1620 /***********************************************************************
1621  *           NdrSimpleTypeMarshall [RPCRT4.@]
1622  */
1623 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1624                                    unsigned char FormatChar )
1625 {
1626     NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1627 }
1628
1629 /***********************************************************************
1630  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
1631  *
1632  * Unmarshall a base type.
1633  *
1634  * NOTES
1635  *  Doesn't check that the buffer is long enough before copying, so the caller
1636  * should do this.
1637  */
1638 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1639                                      unsigned char FormatChar )
1640 {
1641 #define BASE_TYPE_UNMARSHALL(type) \
1642         align_pointer(&pStubMsg->Buffer, sizeof(type)); \
1643         TRACE("pMemory: %p\n", pMemory); \
1644         *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1645         pStubMsg->Buffer += sizeof(type);
1646
1647     switch(FormatChar)
1648     {
1649     case RPC_FC_BYTE:
1650     case RPC_FC_CHAR:
1651     case RPC_FC_SMALL:
1652     case RPC_FC_USMALL:
1653         BASE_TYPE_UNMARSHALL(UCHAR);
1654         TRACE("value: 0x%02x\n", *pMemory);
1655         break;
1656     case RPC_FC_WCHAR:
1657     case RPC_FC_SHORT:
1658     case RPC_FC_USHORT:
1659         BASE_TYPE_UNMARSHALL(USHORT);
1660         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1661         break;
1662     case RPC_FC_LONG:
1663     case RPC_FC_ULONG:
1664     case RPC_FC_ERROR_STATUS_T:
1665     case RPC_FC_ENUM32:
1666         BASE_TYPE_UNMARSHALL(ULONG);
1667         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1668         break;
1669    case RPC_FC_FLOAT:
1670         BASE_TYPE_UNMARSHALL(float);
1671         TRACE("value: %f\n", *(float *)pMemory);
1672         break;
1673     case RPC_FC_DOUBLE:
1674         BASE_TYPE_UNMARSHALL(double);
1675         TRACE("value: %f\n", *(double *)pMemory);
1676         break;
1677     case RPC_FC_HYPER:
1678         BASE_TYPE_UNMARSHALL(ULONGLONG);
1679         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1680         break;
1681     case RPC_FC_ENUM16:
1682         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
1683         TRACE("pMemory: %p\n", pMemory);
1684         /* 16-bits on the wire, but int in memory */
1685         *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1686         pStubMsg->Buffer += sizeof(USHORT);
1687         TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1688         break;
1689     case RPC_FC_INT3264:
1690         align_pointer(&pStubMsg->Buffer, sizeof(INT));
1691         /* 32-bits on the wire, but int_ptr in memory */
1692         *(INT_PTR *)pMemory = *(INT *)pStubMsg->Buffer;
1693         pStubMsg->Buffer += sizeof(INT);
1694         TRACE("value: 0x%08lx\n", *(INT_PTR *)pMemory);
1695         break;
1696     case RPC_FC_UINT3264:
1697         align_pointer(&pStubMsg->Buffer, sizeof(UINT));
1698         /* 32-bits on the wire, but int_ptr in memory */
1699         *(UINT_PTR *)pMemory = *(UINT *)pStubMsg->Buffer;
1700         pStubMsg->Buffer += sizeof(UINT);
1701         TRACE("value: 0x%08lx\n", *(UINT_PTR *)pMemory);
1702         break;
1703     case RPC_FC_IGNORE:
1704         break;
1705     default:
1706         FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1707     }
1708 #undef BASE_TYPE_UNMARSHALL
1709 }
1710
1711 /***********************************************************************
1712  *           NdrSimpleStructMarshall [RPCRT4.@]
1713  */
1714 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1715                                                unsigned char *pMemory,
1716                                                PFORMAT_STRING pFormat)
1717 {
1718   unsigned size = *(const WORD*)(pFormat+2);
1719   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1720
1721   align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
1722
1723   pStubMsg->BufferMark = pStubMsg->Buffer;
1724   safe_copy_to_buffer(pStubMsg, pMemory, size);
1725
1726   if (pFormat[0] != RPC_FC_STRUCT)
1727     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1728
1729   return NULL;
1730 }
1731
1732 /***********************************************************************
1733  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1734  */
1735 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1736                                                  unsigned char **ppMemory,
1737                                                  PFORMAT_STRING pFormat,
1738                                                  unsigned char fMustAlloc)
1739 {
1740   unsigned size = *(const WORD*)(pFormat+2);
1741   unsigned char *saved_buffer;
1742   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1743
1744   align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1745
1746   if (fMustAlloc)
1747     *ppMemory = NdrAllocate(pStubMsg, size);
1748   else
1749   {
1750     if (!pStubMsg->IsClient && !*ppMemory)
1751       /* for servers, we just point straight into the RPC buffer */
1752       *ppMemory = pStubMsg->Buffer;
1753   }
1754
1755   saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1756   safe_buffer_increment(pStubMsg, size);
1757   if (pFormat[0] == RPC_FC_PSTRUCT)
1758       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1759
1760   TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1761   if (*ppMemory != saved_buffer)
1762       memcpy(*ppMemory, saved_buffer, size);
1763
1764   return NULL;
1765 }
1766
1767 /***********************************************************************
1768  *           NdrSimpleStructBufferSize [RPCRT4.@]
1769  */
1770 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1771                                       unsigned char *pMemory,
1772                                       PFORMAT_STRING pFormat)
1773 {
1774   unsigned size = *(const WORD*)(pFormat+2);
1775   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1776
1777   align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
1778
1779   safe_buffer_length_increment(pStubMsg, size);
1780   if (pFormat[0] != RPC_FC_STRUCT)
1781     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1782 }
1783
1784 /***********************************************************************
1785  *           NdrSimpleStructMemorySize [RPCRT4.@]
1786  */
1787 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1788                                        PFORMAT_STRING pFormat)
1789 {
1790   unsigned short size = *(const WORD *)(pFormat+2);
1791
1792   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1793
1794   align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1795   pStubMsg->MemorySize += size;
1796   safe_buffer_increment(pStubMsg, size);
1797
1798   if (pFormat[0] != RPC_FC_STRUCT)
1799     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1800   return pStubMsg->MemorySize;
1801 }
1802
1803 /***********************************************************************
1804  *           NdrSimpleStructFree [RPCRT4.@]
1805  */
1806 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1807                                 unsigned char *pMemory,
1808                                 PFORMAT_STRING pFormat)
1809 {
1810   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1811   if (pFormat[0] != RPC_FC_STRUCT)
1812     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1813 }
1814
1815 /* Array helpers */
1816
1817 static inline void array_compute_and_size_conformance(
1818     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1819     PFORMAT_STRING pFormat)
1820 {
1821   DWORD count;
1822
1823   switch (fc)
1824   {
1825   case RPC_FC_CARRAY:
1826     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1827     SizeConformance(pStubMsg);
1828     break;
1829   case RPC_FC_CVARRAY:
1830     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1831     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1832     SizeConformance(pStubMsg);
1833     break;
1834   case RPC_FC_C_CSTRING:
1835   case RPC_FC_C_WSTRING:
1836     if (fc == RPC_FC_C_CSTRING)
1837     {
1838       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1839       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1840     }
1841     else
1842     {
1843       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1844       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1845     }
1846
1847     if (pFormat[1] == RPC_FC_STRING_SIZED)
1848       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1849     else
1850       pStubMsg->MaxCount = pStubMsg->ActualCount;
1851
1852     SizeConformance(pStubMsg);
1853     break;
1854   case RPC_FC_BOGUS_ARRAY:
1855     count = *(const WORD *)(pFormat + 2);
1856     pFormat += 4;
1857     if (IsConformanceOrVariancePresent(pFormat)) SizeConformance(pStubMsg);
1858     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, count);
1859     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
1860     break;
1861   default:
1862     ERR("unknown array format 0x%x\n", fc);
1863     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1864   }
1865 }
1866
1867 static inline void array_buffer_size(
1868     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1869     PFORMAT_STRING pFormat, unsigned char fHasPointers)
1870 {
1871   DWORD i, size;
1872   DWORD esize;
1873   unsigned char alignment;
1874
1875   switch (fc)
1876   {
1877   case RPC_FC_CARRAY:
1878     esize = *(const WORD*)(pFormat+2);
1879     alignment = pFormat[1] + 1;
1880
1881     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1882
1883     align_length(&pStubMsg->BufferLength, alignment);
1884
1885     size = safe_multiply(esize, pStubMsg->MaxCount);
1886     /* conformance value plus array */
1887     safe_buffer_length_increment(pStubMsg, size);
1888
1889     if (fHasPointers)
1890       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1891     break;
1892   case RPC_FC_CVARRAY:
1893     esize = *(const WORD*)(pFormat+2);
1894     alignment = pFormat[1] + 1;
1895
1896     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1897     pFormat = SkipVariance(pStubMsg, pFormat);
1898
1899     SizeVariance(pStubMsg);
1900
1901     align_length(&pStubMsg->BufferLength, alignment);
1902
1903     size = safe_multiply(esize, pStubMsg->ActualCount);
1904     safe_buffer_length_increment(pStubMsg, size);
1905
1906     if (fHasPointers)
1907       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1908     break;
1909   case RPC_FC_C_CSTRING:
1910   case RPC_FC_C_WSTRING:
1911     if (fc == RPC_FC_C_CSTRING)
1912       esize = 1;
1913     else
1914       esize = 2;
1915
1916     SizeVariance(pStubMsg);
1917
1918     size = safe_multiply(esize, pStubMsg->ActualCount);
1919     safe_buffer_length_increment(pStubMsg, size);
1920     break;
1921   case RPC_FC_BOGUS_ARRAY:
1922     alignment = pFormat[1] + 1;
1923     pFormat = SkipConformance(pStubMsg, pFormat + 4);
1924     if (IsConformanceOrVariancePresent(pFormat)) SizeVariance(pStubMsg);
1925     pFormat = SkipVariance(pStubMsg, pFormat);
1926
1927     align_length(&pStubMsg->BufferLength, alignment);
1928
1929     size = pStubMsg->ActualCount;
1930     for (i = 0; i < size; i++)
1931       pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
1932     break;
1933   default:
1934     ERR("unknown array format 0x%x\n", fc);
1935     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1936   }
1937 }
1938
1939 static inline void array_compute_and_write_conformance(
1940     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1941     PFORMAT_STRING pFormat)
1942 {
1943   ULONG def;
1944   BOOL conformance_present;
1945
1946   switch (fc)
1947   {
1948   case RPC_FC_CARRAY:
1949     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1950     WriteConformance(pStubMsg);
1951     break;
1952   case RPC_FC_CVARRAY:
1953     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1954     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1955     WriteConformance(pStubMsg);
1956     break;
1957   case RPC_FC_C_CSTRING:
1958   case RPC_FC_C_WSTRING:
1959     if (fc == RPC_FC_C_CSTRING)
1960     {
1961       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1962       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1963     }
1964     else
1965     {
1966       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1967       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1968     }
1969     if (pFormat[1] == RPC_FC_STRING_SIZED)
1970       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1971     else
1972       pStubMsg->MaxCount = pStubMsg->ActualCount;
1973     pStubMsg->Offset = 0;
1974     WriteConformance(pStubMsg);
1975     break;
1976   case RPC_FC_BOGUS_ARRAY:
1977     def = *(const WORD *)(pFormat + 2);
1978     pFormat += 4;
1979     conformance_present = IsConformanceOrVariancePresent(pFormat);
1980     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
1981     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
1982     if (conformance_present) WriteConformance(pStubMsg);
1983     break;
1984   default:
1985     ERR("unknown array format 0x%x\n", fc);
1986     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1987   }
1988 }
1989
1990 static inline void array_write_variance_and_marshall(
1991     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1992     PFORMAT_STRING pFormat, unsigned char fHasPointers)
1993 {
1994   DWORD i, size;
1995   DWORD esize;
1996   unsigned char alignment;
1997
1998   switch (fc)
1999   {
2000   case RPC_FC_CARRAY:
2001     esize = *(const WORD*)(pFormat+2);
2002     alignment = pFormat[1] + 1;
2003
2004     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2005
2006     align_pointer_clear(&pStubMsg->Buffer, alignment);
2007
2008     size = safe_multiply(esize, pStubMsg->MaxCount);
2009     if (fHasPointers)
2010       pStubMsg->BufferMark = pStubMsg->Buffer;
2011     safe_copy_to_buffer(pStubMsg, pMemory, size);
2012
2013     if (fHasPointers)
2014       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2015     break;
2016   case RPC_FC_CVARRAY:
2017     esize = *(const WORD*)(pFormat+2);
2018     alignment = pFormat[1] + 1;
2019
2020     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2021     pFormat = SkipVariance(pStubMsg, pFormat);
2022
2023     WriteVariance(pStubMsg);
2024
2025     align_pointer_clear(&pStubMsg->Buffer, alignment);
2026
2027     size = safe_multiply(esize, pStubMsg->ActualCount);
2028
2029     if (fHasPointers)
2030       pStubMsg->BufferMark = pStubMsg->Buffer;
2031     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
2032
2033     if (fHasPointers)
2034       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2035     break;
2036   case RPC_FC_C_CSTRING:
2037   case RPC_FC_C_WSTRING:
2038     if (fc == RPC_FC_C_CSTRING)
2039       esize = 1;
2040     else
2041       esize = 2;
2042
2043     WriteVariance(pStubMsg);
2044
2045     size = safe_multiply(esize, pStubMsg->ActualCount);
2046     safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2047     break;
2048   case RPC_FC_BOGUS_ARRAY:
2049     alignment = pFormat[1] + 1;
2050     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2051     if (IsConformanceOrVariancePresent(pFormat)) WriteVariance(pStubMsg);
2052     pFormat = SkipVariance(pStubMsg, pFormat);
2053
2054     align_pointer_clear(&pStubMsg->Buffer, alignment);
2055
2056     size = pStubMsg->ActualCount;
2057     for (i = 0; i < size; i++)
2058       pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2059     break;
2060   default:
2061     ERR("unknown array format 0x%x\n", fc);
2062     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2063   }
2064 }
2065
2066 static inline ULONG array_read_conformance(
2067     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
2068 {
2069   DWORD def, esize;
2070
2071   switch (fc)
2072   {
2073   case RPC_FC_CARRAY:
2074     esize = *(const WORD*)(pFormat+2);
2075     pFormat = ReadConformance(pStubMsg, pFormat+4);
2076     return safe_multiply(esize, pStubMsg->MaxCount);
2077   case RPC_FC_CVARRAY:
2078     esize = *(const WORD*)(pFormat+2);
2079     pFormat = ReadConformance(pStubMsg, pFormat+4);
2080     return safe_multiply(esize, pStubMsg->MaxCount);
2081   case RPC_FC_C_CSTRING:
2082   case RPC_FC_C_WSTRING:
2083     if (fc == RPC_FC_C_CSTRING)
2084       esize = 1;
2085     else
2086       esize = 2;
2087
2088     if (pFormat[1] == RPC_FC_STRING_SIZED)
2089       ReadConformance(pStubMsg, pFormat + 2);
2090     else
2091       ReadConformance(pStubMsg, NULL);
2092     return safe_multiply(esize, pStubMsg->MaxCount);
2093   case RPC_FC_BOGUS_ARRAY:
2094     def = *(const WORD *)(pFormat + 2);
2095     pFormat += 4;
2096     if (IsConformanceOrVariancePresent(pFormat)) pFormat = ReadConformance(pStubMsg, pFormat);
2097     else
2098     {
2099         pStubMsg->MaxCount = def;
2100         pFormat = SkipConformance( pStubMsg, pFormat );
2101     }
2102     pFormat = SkipVariance( pStubMsg, pFormat );
2103
2104     esize = ComplexStructSize(pStubMsg, pFormat);
2105     return safe_multiply(pStubMsg->MaxCount, esize);
2106   default:
2107     ERR("unknown array format 0x%x\n", fc);
2108     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2109   }
2110 }
2111
2112 static inline ULONG array_read_variance_and_unmarshall(
2113     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
2114     PFORMAT_STRING pFormat, unsigned char fMustAlloc,
2115     unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
2116 {
2117   ULONG bufsize, memsize;
2118   WORD esize;
2119   unsigned char alignment;
2120   unsigned char *saved_buffer, *pMemory;
2121   ULONG i, offset, count;
2122
2123   switch (fc)
2124   {
2125   case RPC_FC_CARRAY:
2126     esize = *(const WORD*)(pFormat+2);
2127     alignment = pFormat[1] + 1;
2128
2129     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2130
2131     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2132
2133     align_pointer(&pStubMsg->Buffer, alignment);
2134
2135     if (fUnmarshall)
2136     {
2137       if (fMustAlloc)
2138         *ppMemory = NdrAllocate(pStubMsg, memsize);
2139       else
2140       {
2141         if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2142           /* for servers, we just point straight into the RPC buffer */
2143           *ppMemory = pStubMsg->Buffer;
2144       }
2145
2146       saved_buffer = pStubMsg->Buffer;
2147       safe_buffer_increment(pStubMsg, bufsize);
2148
2149       pStubMsg->BufferMark = saved_buffer;
2150       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2151
2152       TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2153       if (*ppMemory != saved_buffer)
2154         memcpy(*ppMemory, saved_buffer, bufsize);
2155     }
2156     return bufsize;
2157   case RPC_FC_CVARRAY:
2158     esize = *(const WORD*)(pFormat+2);
2159     alignment = pFormat[1] + 1;
2160
2161     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2162
2163     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2164
2165     align_pointer(&pStubMsg->Buffer, alignment);
2166
2167     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2168     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2169
2170     if (fUnmarshall)
2171     {
2172       offset = pStubMsg->Offset;
2173
2174       if (!fMustAlloc && !*ppMemory)
2175         fMustAlloc = TRUE;
2176       if (fMustAlloc)
2177         *ppMemory = NdrAllocate(pStubMsg, memsize);
2178       saved_buffer = pStubMsg->Buffer;
2179       safe_buffer_increment(pStubMsg, bufsize);
2180
2181       pStubMsg->BufferMark = saved_buffer;
2182       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2183                                 fMustAlloc);
2184
2185       memcpy(*ppMemory + offset, saved_buffer, bufsize);
2186     }
2187     return bufsize;
2188   case RPC_FC_C_CSTRING:
2189   case RPC_FC_C_WSTRING:
2190     if (fc == RPC_FC_C_CSTRING)
2191       esize = 1;
2192     else
2193       esize = 2;
2194
2195     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2196
2197     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2198     {
2199       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2200           pStubMsg->ActualCount, pStubMsg->MaxCount);
2201       RpcRaiseException(RPC_S_INVALID_BOUND);
2202     }
2203     if (pStubMsg->Offset)
2204     {
2205       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2206       RpcRaiseException(RPC_S_INVALID_BOUND);
2207     }
2208
2209     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2210     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2211
2212     validate_string_data(pStubMsg, bufsize, esize);
2213
2214     if (fUnmarshall)
2215     {
2216       if (fMustAlloc)
2217         *ppMemory = NdrAllocate(pStubMsg, memsize);
2218       else
2219       {
2220         if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2221             !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2222           /* if the data in the RPC buffer is big enough, we just point
2223            * straight into it */
2224           *ppMemory = pStubMsg->Buffer;
2225         else if (!*ppMemory)
2226           *ppMemory = NdrAllocate(pStubMsg, memsize);
2227       }
2228
2229       if (*ppMemory == pStubMsg->Buffer)
2230         safe_buffer_increment(pStubMsg, bufsize);
2231       else
2232         safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2233
2234       if (*pFormat == RPC_FC_C_CSTRING)
2235         TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2236       else
2237         TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2238     }
2239     return bufsize;
2240
2241   case RPC_FC_BOGUS_ARRAY:
2242     alignment = pFormat[1] + 1;
2243     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2244     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2245
2246     esize = ComplexStructSize(pStubMsg, pFormat);
2247     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2248
2249     assert( fUnmarshall );
2250
2251     if (!fMustAlloc && !*ppMemory)
2252       fMustAlloc = TRUE;
2253     if (fMustAlloc)
2254       *ppMemory = NdrAllocate(pStubMsg, memsize);
2255
2256     align_pointer(&pStubMsg->Buffer, alignment);
2257     saved_buffer = pStubMsg->Buffer;
2258
2259     pMemory = *ppMemory;
2260     count = pStubMsg->ActualCount;
2261     for (i = 0; i < count; i++)
2262         pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
2263     return pStubMsg->Buffer - saved_buffer;
2264
2265   default:
2266     ERR("unknown array format 0x%x\n", fc);
2267     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2268   }
2269 }
2270
2271 static inline void array_memory_size(
2272     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2273     unsigned char fHasPointers)
2274 {
2275   ULONG i, count, SavedMemorySize;
2276   ULONG bufsize, memsize;
2277   DWORD esize;
2278   unsigned char alignment;
2279
2280   switch (fc)
2281   {
2282   case RPC_FC_CARRAY:
2283     esize = *(const WORD*)(pFormat+2);
2284     alignment = pFormat[1] + 1;
2285
2286     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2287
2288     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2289     pStubMsg->MemorySize += memsize;
2290
2291     align_pointer(&pStubMsg->Buffer, alignment);
2292     if (fHasPointers)
2293       pStubMsg->BufferMark = pStubMsg->Buffer;
2294     safe_buffer_increment(pStubMsg, bufsize);
2295
2296     if (fHasPointers)
2297       EmbeddedPointerMemorySize(pStubMsg, pFormat);
2298     break;
2299   case RPC_FC_CVARRAY:
2300     esize = *(const WORD*)(pFormat+2);
2301     alignment = pFormat[1] + 1;
2302
2303     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2304
2305     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2306
2307     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2308     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2309     pStubMsg->MemorySize += memsize;
2310
2311     align_pointer(&pStubMsg->Buffer, alignment);
2312     if (fHasPointers)
2313       pStubMsg->BufferMark = pStubMsg->Buffer;
2314     safe_buffer_increment(pStubMsg, bufsize);
2315
2316     if (fHasPointers)
2317       EmbeddedPointerMemorySize(pStubMsg, pFormat);
2318     break;
2319   case RPC_FC_C_CSTRING:
2320   case RPC_FC_C_WSTRING:
2321     if (fc == RPC_FC_C_CSTRING)
2322       esize = 1;
2323     else
2324       esize = 2;
2325
2326     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2327
2328     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2329     {
2330       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2331           pStubMsg->ActualCount, pStubMsg->MaxCount);
2332       RpcRaiseException(RPC_S_INVALID_BOUND);
2333     }
2334     if (pStubMsg->Offset)
2335     {
2336       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2337       RpcRaiseException(RPC_S_INVALID_BOUND);
2338     }
2339
2340     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2341     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2342
2343     validate_string_data(pStubMsg, bufsize, esize);
2344
2345     safe_buffer_increment(pStubMsg, bufsize);
2346     pStubMsg->MemorySize += memsize;
2347     break;
2348   case RPC_FC_BOGUS_ARRAY:
2349     alignment = pFormat[1] + 1;
2350     pFormat = SkipConformance(pStubMsg, pFormat + 4);
2351     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2352
2353     align_pointer(&pStubMsg->Buffer, alignment);
2354
2355     SavedMemorySize = pStubMsg->MemorySize;
2356
2357     esize = ComplexStructSize(pStubMsg, pFormat);
2358     memsize = safe_multiply(pStubMsg->MaxCount, esize);
2359
2360     count = pStubMsg->ActualCount;
2361     for (i = 0; i < count; i++)
2362         ComplexStructMemorySize(pStubMsg, pFormat, NULL);
2363
2364     pStubMsg->MemorySize = SavedMemorySize + memsize;
2365     break;
2366   default:
2367     ERR("unknown array format 0x%x\n", fc);
2368     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2369   }
2370 }
2371
2372 static inline void array_free(
2373     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2374     unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2375 {
2376   DWORD i, count;
2377
2378   switch (fc)
2379   {
2380   case RPC_FC_CARRAY:
2381     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2382     if (fHasPointers)
2383       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2384     break;
2385   case RPC_FC_CVARRAY:
2386     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2387     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2388     if (fHasPointers)
2389       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2390     break;
2391   case RPC_FC_C_CSTRING:
2392   case RPC_FC_C_WSTRING:
2393     /* No embedded pointers so nothing to do */
2394     break;
2395   case RPC_FC_BOGUS_ARRAY:
2396       count = *(const WORD *)(pFormat + 2);
2397       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, count);
2398       pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2399
2400       count = pStubMsg->ActualCount;
2401       for (i = 0; i < count; i++)
2402           pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2403     break;
2404   default:
2405     ERR("unknown array format 0x%x\n", fc);
2406     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2407   }
2408 }
2409
2410 /*
2411  * NdrConformantString:
2412  *
2413  * What MS calls a ConformantString is, in DCE terminology,
2414  * a Varying-Conformant String.
2415  * [
2416  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2417  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
2418  *           into unmarshalled string)
2419  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2420  *   [
2421  *     data: CHARTYPE[maxlen]
2422  *   ]
2423  * ], where CHARTYPE is the appropriate character type (specified externally)
2424  *
2425  */
2426
2427 /***********************************************************************
2428  *            NdrConformantStringMarshall [RPCRT4.@]
2429  */
2430 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
2431   unsigned char *pszMessage, PFORMAT_STRING pFormat)
2432 {
2433   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2434
2435   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2436     ERR("Unhandled string type: %#x\n", pFormat[0]);
2437     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2438   }
2439
2440   /* allow compiler to optimise inline function by passing constant into
2441    * these functions */
2442   if (pFormat[0] == RPC_FC_C_CSTRING) {
2443     array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2444                                         pFormat);
2445     array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2446                                       pFormat, TRUE /* fHasPointers */);
2447   } else {
2448     array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2449                                         pFormat);
2450     array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2451                                       pFormat, TRUE /* fHasPointers */);
2452   }
2453
2454   return NULL;
2455 }
2456
2457 /***********************************************************************
2458  *           NdrConformantStringBufferSize [RPCRT4.@]
2459  */
2460 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2461   unsigned char* pMemory, PFORMAT_STRING pFormat)
2462 {
2463   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2464
2465   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2466     ERR("Unhandled string type: %#x\n", pFormat[0]);
2467     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2468   }
2469
2470   /* allow compiler to optimise inline function by passing constant into
2471    * these functions */
2472   if (pFormat[0] == RPC_FC_C_CSTRING) {
2473     array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory,
2474                                        pFormat);
2475     array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2476                       TRUE /* fHasPointers */);
2477   } else {
2478     array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory,
2479                                        pFormat);
2480     array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2481                       TRUE /* fHasPointers */);
2482   }
2483 }
2484
2485 /************************************************************************
2486  *            NdrConformantStringMemorySize [RPCRT4.@]
2487  */
2488 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2489   PFORMAT_STRING pFormat )
2490 {
2491   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2492
2493   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2494     ERR("Unhandled string type: %#x\n", pFormat[0]);
2495     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2496   }
2497
2498   /* allow compiler to optimise inline function by passing constant into
2499    * these functions */
2500   if (pFormat[0] == RPC_FC_C_CSTRING) {
2501     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2502     array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat,
2503                       TRUE /* fHasPointers */);
2504   } else {
2505     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2506     array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat,
2507                       TRUE /* fHasPointers */);
2508   }
2509
2510   return pStubMsg->MemorySize;
2511 }
2512
2513 /************************************************************************
2514  *           NdrConformantStringUnmarshall [RPCRT4.@]
2515  */
2516 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2517   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2518 {
2519   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2520     pStubMsg, *ppMemory, pFormat, fMustAlloc);
2521
2522   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2523     ERR("Unhandled string type: %#x\n", *pFormat);
2524     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2525   }
2526
2527   /* allow compiler to optimise inline function by passing constant into
2528    * these functions */
2529   if (pFormat[0] == RPC_FC_C_CSTRING) {
2530     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2531     array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory,
2532                                        pFormat, fMustAlloc,
2533                                        TRUE /* fUseBufferMemoryServer */,
2534                                        TRUE /* fUnmarshall */);
2535   } else {
2536     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2537     array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory,
2538                                        pFormat, fMustAlloc,
2539                                        TRUE /* fUseBufferMemoryServer */,
2540                                        TRUE /* fUnmarshall */);
2541   }
2542
2543   return NULL;
2544 }
2545
2546 /***********************************************************************
2547  *           NdrNonConformantStringMarshall [RPCRT4.@]
2548  */
2549 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2550                                 unsigned char *pMemory,
2551                                 PFORMAT_STRING pFormat)
2552 {
2553   ULONG esize, size, maxsize;
2554
2555   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2556
2557   maxsize = *(const USHORT *)&pFormat[2];
2558
2559   if (*pFormat == RPC_FC_CSTRING)
2560   {
2561     ULONG i = 0;
2562     const char *str = (const char *)pMemory;
2563     while (i < maxsize && str[i]) i++;
2564     TRACE("string=%s\n", debugstr_an(str, i));
2565     pStubMsg->ActualCount = i + 1;
2566     esize = 1;
2567   }
2568   else if (*pFormat == RPC_FC_WSTRING)
2569   {
2570     ULONG i = 0;
2571     const WCHAR *str = (const WCHAR *)pMemory;
2572     while (i < maxsize && str[i]) i++;
2573     TRACE("string=%s\n", debugstr_wn(str, i));
2574     pStubMsg->ActualCount = i + 1;
2575     esize = 2;
2576   }
2577   else
2578   {
2579     ERR("Unhandled string type: %#x\n", *pFormat);
2580     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2581   }
2582
2583   pStubMsg->Offset = 0;
2584   WriteVariance(pStubMsg);
2585
2586   size = safe_multiply(esize, pStubMsg->ActualCount);
2587   safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2588
2589   return NULL;
2590 }
2591
2592 /***********************************************************************
2593  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
2594  */
2595 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2596                                 unsigned char **ppMemory,
2597                                 PFORMAT_STRING pFormat,
2598                                 unsigned char fMustAlloc)
2599 {
2600   ULONG bufsize, memsize, esize, maxsize;
2601
2602   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2603     pStubMsg, *ppMemory, pFormat, fMustAlloc);
2604
2605   maxsize = *(const USHORT *)&pFormat[2];
2606
2607   ReadVariance(pStubMsg, NULL, maxsize);
2608   if (pStubMsg->Offset)
2609   {
2610     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2611     RpcRaiseException(RPC_S_INVALID_BOUND);
2612   }
2613
2614   if (*pFormat == RPC_FC_CSTRING) esize = 1;
2615   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2616   else
2617   {
2618     ERR("Unhandled string type: %#x\n", *pFormat);
2619     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2620   }
2621
2622   memsize = esize * maxsize;
2623   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2624
2625   validate_string_data(pStubMsg, bufsize, esize);
2626
2627   if (!fMustAlloc && !*ppMemory)
2628     fMustAlloc = TRUE;
2629   if (fMustAlloc)
2630     *ppMemory = NdrAllocate(pStubMsg, memsize);
2631
2632   safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2633
2634   if (*pFormat == RPC_FC_CSTRING) {
2635     TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2636   }
2637   else if (*pFormat == RPC_FC_WSTRING) {
2638     TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2639   }
2640
2641   return NULL;
2642 }
2643
2644 /***********************************************************************
2645  *           NdrNonConformantStringBufferSize [RPCRT4.@]
2646  */
2647 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2648                                 unsigned char *pMemory,
2649                                 PFORMAT_STRING pFormat)
2650 {
2651   ULONG esize, maxsize;
2652
2653   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2654
2655   maxsize = *(const USHORT *)&pFormat[2];
2656
2657   SizeVariance(pStubMsg);
2658
2659   if (*pFormat == RPC_FC_CSTRING)
2660   {
2661     ULONG i = 0;
2662     const char *str = (const char *)pMemory;
2663     while (i < maxsize && str[i]) i++;
2664     TRACE("string=%s\n", debugstr_an(str, i));
2665     pStubMsg->ActualCount = i + 1;
2666     esize = 1;
2667   }
2668   else if (*pFormat == RPC_FC_WSTRING)
2669   {
2670     ULONG i = 0;
2671     const WCHAR *str = (const WCHAR *)pMemory;
2672     while (i < maxsize && str[i]) i++;
2673     TRACE("string=%s\n", debugstr_wn(str, i));
2674     pStubMsg->ActualCount = i + 1;
2675     esize = 2;
2676   }
2677   else
2678   {
2679     ERR("Unhandled string type: %#x\n", *pFormat);
2680     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2681   }
2682
2683   safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2684 }
2685
2686 /***********************************************************************
2687  *           NdrNonConformantStringMemorySize [RPCRT4.@]
2688  */
2689 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2690                                 PFORMAT_STRING pFormat)
2691 {
2692   ULONG bufsize, memsize, esize, maxsize;
2693
2694   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2695
2696   maxsize = *(const USHORT *)&pFormat[2];
2697
2698   ReadVariance(pStubMsg, NULL, maxsize);
2699
2700   if (pStubMsg->Offset)
2701   {
2702     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2703     RpcRaiseException(RPC_S_INVALID_BOUND);
2704   }
2705
2706   if (*pFormat == RPC_FC_CSTRING) esize = 1;
2707   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2708   else
2709   {
2710     ERR("Unhandled string type: %#x\n", *pFormat);
2711     RpcRaiseException(RPC_X_BAD_STUB_DATA);
2712   }
2713
2714   memsize = esize * maxsize;
2715   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2716
2717   validate_string_data(pStubMsg, bufsize, esize);
2718
2719   safe_buffer_increment(pStubMsg, bufsize);
2720   pStubMsg->MemorySize += memsize;
2721
2722   return pStubMsg->MemorySize;
2723 }
2724
2725 /* Complex types */
2726
2727 #include "pshpack1.h"
2728 typedef struct
2729 {
2730     unsigned char type;
2731     unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2732     ULONG low_value;
2733     ULONG high_value;
2734 } NDR_RANGE;
2735 #include "poppack.h"
2736
2737 static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2738                                  PFORMAT_STRING pFormat)
2739 {
2740   switch (*pFormat) {
2741   case RPC_FC_STRUCT:
2742   case RPC_FC_PSTRUCT:
2743   case RPC_FC_CSTRUCT:
2744   case RPC_FC_BOGUS_STRUCT:
2745   case RPC_FC_SMFARRAY:
2746   case RPC_FC_SMVARRAY:
2747   case RPC_FC_CSTRING:
2748     return *(const WORD*)&pFormat[2];
2749   case RPC_FC_USER_MARSHAL:
2750     return *(const WORD*)&pFormat[4];
2751   case RPC_FC_RANGE: {
2752     switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2753     case RPC_FC_BYTE:
2754     case RPC_FC_CHAR:
2755     case RPC_FC_SMALL:
2756     case RPC_FC_USMALL:
2757         return sizeof(UCHAR);
2758     case RPC_FC_WCHAR:
2759     case RPC_FC_SHORT:
2760     case RPC_FC_USHORT:
2761         return sizeof(USHORT);
2762     case RPC_FC_LONG:
2763     case RPC_FC_ULONG:
2764     case RPC_FC_ENUM32:
2765     case RPC_FC_INT3264:
2766     case RPC_FC_UINT3264:
2767         return sizeof(ULONG);
2768     case RPC_FC_FLOAT:
2769         return sizeof(float);
2770     case RPC_FC_DOUBLE:
2771         return sizeof(double);
2772     case RPC_FC_HYPER:
2773         return sizeof(ULONGLONG);
2774     case RPC_FC_ENUM16:
2775         return sizeof(UINT);
2776     default:
2777         ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2778         RpcRaiseException(RPC_X_BAD_STUB_DATA);
2779     }
2780   }
2781   case RPC_FC_NON_ENCAPSULATED_UNION:
2782     pFormat += 2;
2783     if (pStubMsg->fHasNewCorrDesc)
2784         pFormat += 6;
2785     else
2786         pFormat += 4;
2787
2788     pFormat += *(const SHORT*)pFormat;
2789     return *(const SHORT*)pFormat;
2790   case RPC_FC_IP:
2791     return sizeof(void *);
2792   case RPC_FC_WSTRING:
2793     return *(const WORD*)&pFormat[2] * 2;
2794   default:
2795     FIXME("unhandled embedded type %02x\n", *pFormat);
2796   }
2797   return 0;
2798 }
2799
2800
2801 static ULONG EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2802                                        PFORMAT_STRING pFormat)
2803 {
2804   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2805
2806   if (!m)
2807   {
2808     FIXME("no memorysizer for data type=%02x\n", *pFormat);
2809     return 0;
2810   }
2811
2812   return m(pStubMsg, pFormat);
2813 }
2814
2815
2816 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2817                                        unsigned char *pMemory,
2818                                        PFORMAT_STRING pFormat,
2819                                        PFORMAT_STRING pPointer)
2820 {
2821   PFORMAT_STRING desc;
2822   NDR_MARSHALL m;
2823   ULONG size;
2824
2825   while (*pFormat != RPC_FC_END) {
2826     switch (*pFormat) {
2827     case RPC_FC_BYTE:
2828     case RPC_FC_CHAR:
2829     case RPC_FC_SMALL:
2830     case RPC_FC_USMALL:
2831       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2832       safe_copy_to_buffer(pStubMsg, pMemory, 1);
2833       pMemory += 1;
2834       break;
2835     case RPC_FC_WCHAR:
2836     case RPC_FC_SHORT:
2837     case RPC_FC_USHORT:
2838       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2839       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2840       pMemory += 2;
2841       break;
2842     case RPC_FC_ENUM16:
2843     {
2844       USHORT val = *(DWORD *)pMemory;
2845       TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2846       if (32767 < *(DWORD*)pMemory)
2847         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2848       safe_copy_to_buffer(pStubMsg, &val, 2);
2849       pMemory += 4;
2850       break;
2851     }
2852     case RPC_FC_LONG:
2853     case RPC_FC_ULONG:
2854     case RPC_FC_ENUM32:
2855       TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2856       safe_copy_to_buffer(pStubMsg, pMemory, 4);
2857       pMemory += 4;
2858       break;
2859     case RPC_FC_INT3264:
2860     case RPC_FC_UINT3264:
2861     {
2862       UINT val = *(UINT_PTR *)pMemory;
2863       TRACE("int3264=%ld <= %p\n", *(UINT_PTR *)pMemory, pMemory);
2864       safe_copy_to_buffer(pStubMsg, &val, sizeof(UINT));
2865       pMemory += sizeof(UINT_PTR);
2866       break;
2867     }
2868     case RPC_FC_FLOAT:
2869       TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
2870       safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
2871       pMemory += sizeof(float);
2872       break;
2873     case RPC_FC_HYPER:
2874       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2875       safe_copy_to_buffer(pStubMsg, pMemory, 8);
2876       pMemory += 8;
2877       break;
2878     case RPC_FC_DOUBLE:
2879       TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
2880       safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
2881       pMemory += sizeof(double);
2882       break;
2883     case RPC_FC_RP:
2884     case RPC_FC_UP:
2885     case RPC_FC_OP:
2886     case RPC_FC_FP:
2887     case RPC_FC_POINTER:
2888     {
2889       unsigned char *saved_buffer;
2890       int pointer_buffer_mark_set = 0;
2891       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2892       TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2893       if (*pFormat != RPC_FC_POINTER)
2894         pPointer = pFormat;
2895       if (*pPointer != RPC_FC_RP)
2896         align_pointer_clear(&pStubMsg->Buffer, 4);
2897       saved_buffer = pStubMsg->Buffer;
2898       if (pStubMsg->PointerBufferMark)
2899       {
2900         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2901         pStubMsg->PointerBufferMark = NULL;
2902         pointer_buffer_mark_set = 1;
2903       }
2904       else if (*pPointer != RPC_FC_RP)
2905         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2906       PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2907       if (pointer_buffer_mark_set)
2908       {
2909         STD_OVERFLOW_CHECK(pStubMsg);
2910         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2911         pStubMsg->Buffer = saved_buffer;
2912         if (*pPointer != RPC_FC_RP)
2913           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2914       }
2915       TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2916       if (*pFormat == RPC_FC_POINTER)
2917         pPointer += 4;
2918       else
2919         pFormat += 4;
2920       pMemory += sizeof(void *);
2921       break;
2922     }
2923     case RPC_FC_ALIGNM2:
2924       align_pointer(&pMemory, 2);
2925       break;
2926     case RPC_FC_ALIGNM4:
2927       align_pointer(&pMemory, 4);
2928       break;
2929     case RPC_FC_ALIGNM8:
2930       align_pointer(&pMemory, 8);
2931       break;
2932     case RPC_FC_STRUCTPAD1:
2933     case RPC_FC_STRUCTPAD2:
2934     case RPC_FC_STRUCTPAD3:
2935     case RPC_FC_STRUCTPAD4:
2936     case RPC_FC_STRUCTPAD5:
2937     case RPC_FC_STRUCTPAD6:
2938     case RPC_FC_STRUCTPAD7:
2939       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2940       break;
2941     case RPC_FC_EMBEDDED_COMPLEX:
2942       pMemory += pFormat[1];
2943       pFormat += 2;
2944       desc = pFormat + *(const SHORT*)pFormat;
2945       size = EmbeddedComplexSize(pStubMsg, desc);
2946       TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2947       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2948       if (m)
2949       {
2950         /* for some reason interface pointers aren't generated as
2951          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2952          * they still need the derefencing treatment that pointers are
2953          * given */
2954         if (*desc == RPC_FC_IP)
2955           m(pStubMsg, *(unsigned char **)pMemory, desc);
2956         else
2957           m(pStubMsg, pMemory, desc);
2958       }
2959       else FIXME("no marshaller for embedded type %02x\n", *desc);
2960       pMemory += size;
2961       pFormat += 2;
2962       continue;
2963     case RPC_FC_PAD:
2964       break;
2965     default:
2966       FIXME("unhandled format 0x%02x\n", *pFormat);
2967     }
2968     pFormat++;
2969   }
2970
2971   return pMemory;
2972 }
2973
2974 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2975                                          unsigned char *pMemory,
2976                                          PFORMAT_STRING pFormat,
2977                                          PFORMAT_STRING pPointer,
2978                                          unsigned char fMustAlloc)
2979 {
2980   PFORMAT_STRING desc;
2981   NDR_UNMARSHALL m;
2982   ULONG size;
2983
2984   while (*pFormat != RPC_FC_END) {
2985     switch (*pFormat) {
2986     case RPC_FC_BYTE:
2987     case RPC_FC_CHAR:
2988     case RPC_FC_SMALL:
2989     case RPC_FC_USMALL:
2990       safe_copy_from_buffer(pStubMsg, pMemory, 1);
2991       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2992       pMemory += 1;
2993       break;
2994     case RPC_FC_WCHAR:
2995     case RPC_FC_SHORT:
2996     case RPC_FC_USHORT:
2997       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2998       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2999       pMemory += 2;
3000       break;
3001     case RPC_FC_ENUM16:
3002     {
3003       WORD val;
3004       safe_copy_from_buffer(pStubMsg, &val, 2);
3005       *(DWORD*)pMemory = val;
3006       TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
3007       if (32767 < *(DWORD*)pMemory)
3008         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
3009       pMemory += 4;
3010       break;
3011     }
3012     case RPC_FC_LONG:
3013     case RPC_FC_ULONG:
3014     case RPC_FC_ENUM32:
3015       safe_copy_from_buffer(pStubMsg, pMemory, 4);
3016       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
3017       pMemory += 4;
3018       break;
3019     case RPC_FC_INT3264:
3020     {
3021       INT val;
3022       safe_copy_from_buffer(pStubMsg, &val, 4);
3023       *(INT_PTR *)pMemory = val;
3024       TRACE("int3264=%ld => %p\n", *(INT_PTR*)pMemory, pMemory);
3025       pMemory += sizeof(INT_PTR);
3026       break;
3027     }
3028     case RPC_FC_UINT3264:
3029     {
3030       UINT val;
3031       safe_copy_from_buffer(pStubMsg, &val, 4);
3032       *(UINT_PTR *)pMemory = val;
3033       TRACE("uint3264=%ld => %p\n", *(UINT_PTR*)pMemory, pMemory);
3034       pMemory += sizeof(UINT_PTR);
3035       break;
3036     }
3037     case RPC_FC_FLOAT:
3038       safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
3039       TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
3040       pMemory += sizeof(float);
3041       break;
3042     case RPC_FC_HYPER:
3043       safe_copy_from_buffer(pStubMsg, pMemory, 8);
3044       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
3045       pMemory += 8;
3046       break;
3047     case RPC_FC_DOUBLE:
3048       safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
3049       TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
3050       pMemory += sizeof(double);
3051       break;
3052     case RPC_FC_RP:
3053     case RPC_FC_UP:
3054     case RPC_FC_OP:
3055     case RPC_FC_FP:
3056     case RPC_FC_POINTER:
3057     {
3058       unsigned char *saved_buffer;
3059       int pointer_buffer_mark_set = 0;
3060       TRACE("pointer => %p\n", pMemory);
3061       if (*pFormat != RPC_FC_POINTER)
3062         pPointer = pFormat;
3063       if (*pPointer != RPC_FC_RP)
3064         align_pointer(&pStubMsg->Buffer, 4);
3065       saved_buffer = pStubMsg->Buffer;
3066       if (pStubMsg->PointerBufferMark)
3067       {
3068         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3069         pStubMsg->PointerBufferMark = NULL;
3070         pointer_buffer_mark_set = 1;
3071       }
3072       else if (*pPointer != RPC_FC_RP)
3073         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3074
3075       PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
3076       if (pointer_buffer_mark_set)
3077       {
3078         STD_OVERFLOW_CHECK(pStubMsg);
3079         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3080         pStubMsg->Buffer = saved_buffer;
3081         if (*pPointer != RPC_FC_RP)
3082           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3083       }
3084       if (*pFormat == RPC_FC_POINTER)
3085         pPointer += 4;
3086       else
3087         pFormat += 4;
3088       pMemory += sizeof(void *);
3089       break;
3090     }
3091     case RPC_FC_ALIGNM2:
3092       align_pointer_clear(&pMemory, 2);
3093       break;
3094     case RPC_FC_ALIGNM4:
3095       align_pointer_clear(&pMemory, 4);
3096       break;
3097     case RPC_FC_ALIGNM8:
3098       align_pointer_clear(&pMemory, 8);
3099       break;
3100     case RPC_FC_STRUCTPAD1:
3101     case RPC_FC_STRUCTPAD2:
3102     case RPC_FC_STRUCTPAD3:
3103     case RPC_FC_STRUCTPAD4:
3104     case RPC_FC_STRUCTPAD5:
3105     case RPC_FC_STRUCTPAD6:
3106     case RPC_FC_STRUCTPAD7:
3107       memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
3108       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3109       break;
3110     case RPC_FC_EMBEDDED_COMPLEX:
3111       pMemory += pFormat[1];
3112       pFormat += 2;
3113       desc = pFormat + *(const SHORT*)pFormat;
3114       size = EmbeddedComplexSize(pStubMsg, desc);
3115       TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
3116       if (fMustAlloc)
3117         /* we can't pass fMustAlloc=TRUE into the marshaller for this type
3118          * since the type is part of the memory block that is encompassed by
3119          * the whole complex type. Memory is forced to allocate when pointers
3120          * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
3121          * clearing the memory we pass in to the unmarshaller */
3122         memset(pMemory, 0, size);
3123       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
3124       if (m)
3125       {
3126         /* for some reason interface pointers aren't generated as
3127          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3128          * they still need the derefencing treatment that pointers are
3129          * given */
3130         if (*desc == RPC_FC_IP)
3131           m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
3132         else
3133           m(pStubMsg, &pMemory, desc, FALSE);
3134       }
3135       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
3136       pMemory += size;
3137       pFormat += 2;
3138       continue;
3139     case RPC_FC_PAD:
3140       break;
3141     default:
3142       FIXME("unhandled format %d\n", *pFormat);
3143     }
3144     pFormat++;
3145   }
3146
3147   return pMemory;
3148 }
3149
3150 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3151                                          unsigned char *pMemory,
3152                                          PFORMAT_STRING pFormat,
3153                                          PFORMAT_STRING pPointer)
3154 {
3155   PFORMAT_STRING desc;
3156   NDR_BUFFERSIZE m;
3157   ULONG size;
3158
3159   while (*pFormat != RPC_FC_END) {
3160     switch (*pFormat) {
3161     case RPC_FC_BYTE:
3162     case RPC_FC_CHAR:
3163     case RPC_FC_SMALL:
3164     case RPC_FC_USMALL:
3165       safe_buffer_length_increment(pStubMsg, 1);
3166       pMemory += 1;
3167       break;
3168     case RPC_FC_WCHAR:
3169     case RPC_FC_SHORT:
3170     case RPC_FC_USHORT:
3171       safe_buffer_length_increment(pStubMsg, 2);
3172       pMemory += 2;
3173       break;
3174     case RPC_FC_ENUM16:
3175       safe_buffer_length_increment(pStubMsg, 2);
3176       pMemory += 4;
3177       break;
3178     case RPC_FC_LONG:
3179     case RPC_FC_ULONG:
3180     case RPC_FC_ENUM32:
3181     case RPC_FC_FLOAT:
3182       safe_buffer_length_increment(pStubMsg, 4);
3183       pMemory += 4;
3184       break;
3185     case RPC_FC_INT3264:
3186     case RPC_FC_UINT3264:
3187       safe_buffer_length_increment(pStubMsg, 4);
3188       pMemory += sizeof(INT_PTR);
3189       break;
3190     case RPC_FC_HYPER:
3191     case RPC_FC_DOUBLE:
3192       safe_buffer_length_increment(pStubMsg, 8);
3193       pMemory += 8;
3194       break;
3195     case RPC_FC_RP:
3196     case RPC_FC_UP:
3197     case RPC_FC_OP:
3198     case RPC_FC_FP:
3199     case RPC_FC_POINTER:
3200       if (*pFormat != RPC_FC_POINTER)
3201         pPointer = pFormat;
3202       if (!pStubMsg->IgnoreEmbeddedPointers)
3203       {
3204         int saved_buffer_length = pStubMsg->BufferLength;
3205         pStubMsg->BufferLength = pStubMsg->PointerLength;
3206         pStubMsg->PointerLength = 0;
3207         if(!pStubMsg->BufferLength)
3208           ERR("BufferLength == 0??\n");
3209         PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
3210         pStubMsg->PointerLength = pStubMsg->BufferLength;
3211         pStubMsg->BufferLength = saved_buffer_length;
3212       }
3213       if (*pPointer != RPC_FC_RP)
3214       {
3215         align_length(&pStubMsg->BufferLength, 4);
3216         safe_buffer_length_increment(pStubMsg, 4);
3217       }
3218       if (*pFormat == RPC_FC_POINTER)
3219         pPointer += 4;
3220       else
3221         pFormat += 4;
3222       pMemory += sizeof(void*);
3223       break;
3224     case RPC_FC_ALIGNM2:
3225       align_pointer(&pMemory, 2);
3226       break;
3227     case RPC_FC_ALIGNM4:
3228       align_pointer(&pMemory, 4);
3229       break;
3230     case RPC_FC_ALIGNM8:
3231       align_pointer(&pMemory, 8);
3232       break;
3233     case RPC_FC_STRUCTPAD1:
3234     case RPC_FC_STRUCTPAD2:
3235     case RPC_FC_STRUCTPAD3:
3236     case RPC_FC_STRUCTPAD4:
3237     case RPC_FC_STRUCTPAD5:
3238     case RPC_FC_STRUCTPAD6:
3239     case RPC_FC_STRUCTPAD7:
3240       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3241       break;
3242     case RPC_FC_EMBEDDED_COMPLEX:
3243       pMemory += pFormat[1];
3244       pFormat += 2;
3245       desc = pFormat + *(const SHORT*)pFormat;
3246       size = EmbeddedComplexSize(pStubMsg, desc);
3247       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3248       if (m)
3249       {
3250         /* for some reason interface pointers aren't generated as
3251          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3252          * they still need the derefencing treatment that pointers are
3253          * given */
3254         if (*desc == RPC_FC_IP)
3255           m(pStubMsg, *(unsigned char **)pMemory, desc);
3256         else
3257           m(pStubMsg, pMemory, desc);
3258       }
3259       else FIXME("no buffersizer for embedded type %02x\n", *desc);
3260       pMemory += size;
3261       pFormat += 2;
3262       continue;
3263     case RPC_FC_PAD:
3264       break;
3265     default:
3266       FIXME("unhandled format 0x%02x\n", *pFormat);
3267     }
3268     pFormat++;
3269   }
3270
3271   return pMemory;
3272 }
3273
3274 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
3275                                    unsigned char *pMemory,
3276                                    PFORMAT_STRING pFormat,
3277                                    PFORMAT_STRING pPointer)
3278 {
3279   PFORMAT_STRING desc;
3280   NDR_FREE m;
3281   ULONG size;
3282
3283   while (*pFormat != RPC_FC_END) {
3284     switch (*pFormat) {
3285     case RPC_FC_BYTE:
3286     case RPC_FC_CHAR:
3287     case RPC_FC_SMALL:
3288     case RPC_FC_USMALL:
3289       pMemory += 1;
3290       break;
3291     case RPC_FC_WCHAR:
3292     case RPC_FC_SHORT:
3293     case RPC_FC_USHORT:
3294       pMemory += 2;
3295       break;
3296     case RPC_FC_LONG:
3297     case RPC_FC_ULONG:
3298     case RPC_FC_ENUM16:
3299     case RPC_FC_ENUM32:
3300     case RPC_FC_FLOAT:
3301       pMemory += 4;
3302       break;
3303     case RPC_FC_INT3264:
3304     case RPC_FC_UINT3264:
3305       pMemory += sizeof(INT_PTR);
3306       break;
3307     case RPC_FC_HYPER:
3308     case RPC_FC_DOUBLE:
3309       pMemory += 8;
3310       break;
3311     case RPC_FC_RP:
3312     case RPC_FC_UP:
3313     case RPC_FC_OP:
3314     case RPC_FC_FP:
3315     case RPC_FC_POINTER:
3316       if (*pFormat != RPC_FC_POINTER)
3317         pPointer = pFormat;
3318       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3319       if (*pFormat == RPC_FC_POINTER)
3320         pPointer += 4;
3321       else
3322         pFormat += 4;
3323       pMemory += sizeof(void *);
3324       break;
3325     case RPC_FC_ALIGNM2:
3326       align_pointer(&pMemory, 2);
3327       break;
3328     case RPC_FC_ALIGNM4:
3329       align_pointer(&pMemory, 4);
3330       break;
3331     case RPC_FC_ALIGNM8:
3332       align_pointer(&pMemory, 8);
3333       break;
3334     case RPC_FC_STRUCTPAD1:
3335     case RPC_FC_STRUCTPAD2:
3336     case RPC_FC_STRUCTPAD3:
3337     case RPC_FC_STRUCTPAD4:
3338     case RPC_FC_STRUCTPAD5:
3339     case RPC_FC_STRUCTPAD6:
3340     case RPC_FC_STRUCTPAD7:
3341       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3342       break;
3343     case RPC_FC_EMBEDDED_COMPLEX:
3344       pMemory += pFormat[1];
3345       pFormat += 2;
3346       desc = pFormat + *(const SHORT*)pFormat;
3347       size = EmbeddedComplexSize(pStubMsg, desc);
3348       m = NdrFreer[*desc & NDR_TABLE_MASK];
3349       if (m)
3350       {
3351         /* for some reason interface pointers aren't generated as
3352          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3353          * they still need the derefencing treatment that pointers are
3354          * given */
3355         if (*desc == RPC_FC_IP)
3356           m(pStubMsg, *(unsigned char **)pMemory, desc);
3357         else
3358           m(pStubMsg, pMemory, desc);
3359       }
3360       pMemory += size;
3361       pFormat += 2;
3362       continue;
3363     case RPC_FC_PAD:
3364       break;
3365     default:
3366       FIXME("unhandled format 0x%02x\n", *pFormat);
3367     }
3368     pFormat++;
3369   }
3370
3371   return pMemory;
3372 }
3373
3374 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3375                                      PFORMAT_STRING pFormat,
3376                                      PFORMAT_STRING pPointer)
3377 {
3378   PFORMAT_STRING desc;
3379   ULONG size = 0;
3380
3381   while (*pFormat != RPC_FC_END) {
3382     switch (*pFormat) {
3383     case RPC_FC_BYTE:
3384     case RPC_FC_CHAR:
3385     case RPC_FC_SMALL:
3386     case RPC_FC_USMALL:
3387       size += 1;
3388       safe_buffer_increment(pStubMsg, 1);
3389       break;
3390     case RPC_FC_WCHAR:
3391     case RPC_FC_SHORT:
3392     case RPC_FC_USHORT:
3393       size += 2;
3394       safe_buffer_increment(pStubMsg, 2);
3395       break;
3396     case RPC_FC_ENUM16:
3397       size += 4;
3398       safe_buffer_increment(pStubMsg, 2);
3399       break;
3400     case RPC_FC_LONG:
3401     case RPC_FC_ULONG:
3402     case RPC_FC_ENUM32:
3403     case RPC_FC_FLOAT:
3404       size += 4;
3405       safe_buffer_increment(pStubMsg, 4);
3406       break;
3407     case RPC_FC_INT3264:
3408     case RPC_FC_UINT3264:
3409       size += sizeof(INT_PTR);
3410       safe_buffer_increment(pStubMsg, 4);
3411       break;
3412     case RPC_FC_HYPER:
3413     case RPC_FC_DOUBLE:
3414       size += 8;
3415       safe_buffer_increment(pStubMsg, 8);
3416       break;
3417     case RPC_FC_RP:
3418     case RPC_FC_UP:
3419     case RPC_FC_OP:
3420     case RPC_FC_FP:
3421     case RPC_FC_POINTER:
3422     {
3423       unsigned char *saved_buffer;
3424       int pointer_buffer_mark_set = 0;
3425       if (*pFormat != RPC_FC_POINTER)
3426         pPointer = pFormat;
3427       if (*pPointer != RPC_FC_RP)
3428         align_pointer(&pStubMsg->Buffer, 4);
3429       saved_buffer = pStubMsg->Buffer;
3430       if (pStubMsg->PointerBufferMark)
3431       {
3432         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3433         pStubMsg->PointerBufferMark = NULL;
3434         pointer_buffer_mark_set = 1;
3435       }
3436       else if (*pPointer != RPC_FC_RP)
3437         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3438
3439       if (!pStubMsg->IgnoreEmbeddedPointers)
3440         PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3441       if (pointer_buffer_mark_set)
3442       {
3443         STD_OVERFLOW_CHECK(pStubMsg);
3444         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3445         pStubMsg->Buffer = saved_buffer;
3446         if (*pPointer != RPC_FC_RP)
3447           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3448       }
3449       if (*pFormat == RPC_FC_POINTER)
3450         pPointer += 4;
3451       else
3452         pFormat += 4;
3453       size += sizeof(void *);
3454       break;
3455     }
3456     case RPC_FC_ALIGNM2:
3457       align_length(&size, 2);
3458       break;
3459     case RPC_FC_ALIGNM4:
3460       align_length(&size, 4);
3461       break;
3462     case RPC_FC_ALIGNM8:
3463       align_length(&size, 8);
3464       break;
3465     case RPC_FC_STRUCTPAD1:
3466     case RPC_FC_STRUCTPAD2:
3467     case RPC_FC_STRUCTPAD3:
3468     case RPC_FC_STRUCTPAD4:
3469     case RPC_FC_STRUCTPAD5:
3470     case RPC_FC_STRUCTPAD6:
3471     case RPC_FC_STRUCTPAD7:
3472       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3473       break;
3474     case RPC_FC_EMBEDDED_COMPLEX:
3475       size += pFormat[1];
3476       pFormat += 2;
3477       desc = pFormat + *(const SHORT*)pFormat;
3478       size += EmbeddedComplexMemorySize(pStubMsg, desc);
3479       pFormat += 2;
3480       continue;
3481     case RPC_FC_PAD:
3482       break;
3483     default:
3484       FIXME("unhandled format 0x%02x\n", *pFormat);
3485     }
3486     pFormat++;
3487   }
3488
3489   return size;
3490 }
3491
3492 ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
3493 {
3494   PFORMAT_STRING desc;
3495   ULONG size = 0;
3496
3497   while (*pFormat != RPC_FC_END) {
3498     switch (*pFormat) {
3499     case RPC_FC_BYTE:
3500     case RPC_FC_CHAR:
3501     case RPC_FC_SMALL:
3502     case RPC_FC_USMALL:
3503       size += 1;
3504       break;
3505     case RPC_FC_WCHAR:
3506     case RPC_FC_SHORT:
3507     case RPC_FC_USHORT:
3508       size += 2;
3509       break;
3510     case RPC_FC_LONG:
3511     case RPC_FC_ULONG:
3512     case RPC_FC_ENUM16:
3513     case RPC_FC_ENUM32:
3514     case RPC_FC_FLOAT:
3515       size += 4;
3516       break;
3517     case RPC_FC_INT3264:
3518     case RPC_FC_UINT3264:
3519       size += sizeof(INT_PTR);
3520       break;
3521     case RPC_FC_HYPER:
3522     case RPC_FC_DOUBLE:
3523       size += 8;
3524       break;
3525     case RPC_FC_RP:
3526     case RPC_FC_UP:
3527     case RPC_FC_OP:
3528     case RPC_FC_FP:
3529     case RPC_FC_POINTER:
3530       size += sizeof(void *);
3531       if (*pFormat != RPC_FC_POINTER)
3532         pFormat += 4;
3533       break;
3534     case RPC_FC_ALIGNM2:
3535       align_length(&size, 2);
3536       break;
3537     case RPC_FC_ALIGNM4:
3538       align_length(&size, 4);
3539       break;
3540     case RPC_FC_ALIGNM8:
3541       align_length(&size, 8);
3542       break;
3543     case RPC_FC_STRUCTPAD1:
3544     case RPC_FC_STRUCTPAD2:
3545     case RPC_FC_STRUCTPAD3:
3546     case RPC_FC_STRUCTPAD4:
3547     case RPC_FC_STRUCTPAD5:
3548     case RPC_FC_STRUCTPAD6:
3549     case RPC_FC_STRUCTPAD7:
3550       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3551       break;
3552     case RPC_FC_EMBEDDED_COMPLEX:
3553       size += pFormat[1];
3554       pFormat += 2;
3555       desc = pFormat + *(const SHORT*)pFormat;
3556       size += EmbeddedComplexSize(pStubMsg, desc);
3557       pFormat += 2;
3558       continue;
3559     case RPC_FC_PAD:
3560       break;
3561     default:
3562       FIXME("unhandled format 0x%02x\n", *pFormat);
3563     }
3564     pFormat++;
3565   }
3566
3567   return size;
3568 }
3569
3570 /***********************************************************************
3571  *           NdrComplexStructMarshall [RPCRT4.@]
3572  */
3573 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3574                                                 unsigned char *pMemory,
3575                                                 PFORMAT_STRING pFormat)
3576 {
3577   PFORMAT_STRING conf_array = NULL;
3578   PFORMAT_STRING pointer_desc = NULL;
3579   unsigned char *OldMemory = pStubMsg->Memory;
3580   int pointer_buffer_mark_set = 0;
3581   ULONG count = 0;
3582   ULONG max_count = 0;
3583   ULONG offset = 0;
3584
3585   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3586
3587   if (!pStubMsg->PointerBufferMark)
3588   {
3589     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3590     /* save buffer length */
3591     ULONG saved_buffer_length = pStubMsg->BufferLength;
3592
3593     /* get the buffer pointer after complex array data, but before
3594      * pointer data */
3595     pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3596     pStubMsg->IgnoreEmbeddedPointers = 1;
3597     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3598     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3599
3600     /* save it for use by embedded pointer code later */
3601     pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3602     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
3603     pointer_buffer_mark_set = 1;
3604
3605     /* restore the original buffer length */
3606     pStubMsg->BufferLength = saved_buffer_length;
3607   }
3608
3609   align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
3610
3611   pFormat += 4;
3612   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3613   pFormat += 2;
3614   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3615   pFormat += 2;
3616
3617   pStubMsg->Memory = pMemory;
3618
3619   if (conf_array)
3620   {
3621     ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3622     array_compute_and_write_conformance(conf_array[0], pStubMsg,
3623                                         pMemory + struct_size, conf_array);
3624     /* these could be changed in ComplexMarshall so save them for later */
3625     max_count = pStubMsg->MaxCount;
3626     count = pStubMsg->ActualCount;
3627     offset = pStubMsg->Offset;
3628   }
3629
3630   pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3631
3632   if (conf_array)
3633   {
3634     pStubMsg->MaxCount = max_count;
3635     pStubMsg->ActualCount = count;
3636     pStubMsg->Offset = offset;
3637     array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3638                                       conf_array, TRUE /* fHasPointers */);
3639   }
3640
3641   pStubMsg->Memory = OldMemory;
3642
3643   if (pointer_buffer_mark_set)
3644   {
3645     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3646     pStubMsg->PointerBufferMark = NULL;
3647   }
3648
3649   STD_OVERFLOW_CHECK(pStubMsg);
3650
3651   return NULL;
3652 }
3653
3654 /***********************************************************************
3655  *           NdrComplexStructUnmarshall [RPCRT4.@]
3656  */
3657 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3658                                                   unsigned char **ppMemory,
3659                                                   PFORMAT_STRING pFormat,
3660                                                   unsigned char fMustAlloc)
3661 {
3662   unsigned size = *(const WORD*)(pFormat+2);
3663   PFORMAT_STRING conf_array = NULL;
3664   PFORMAT_STRING pointer_desc = NULL;
3665   unsigned char *pMemory;
3666   int pointer_buffer_mark_set = 0;
3667   ULONG count = 0;
3668   ULONG max_count = 0;
3669   ULONG offset = 0;
3670   ULONG array_size = 0;
3671
3672   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3673
3674   if (!pStubMsg->PointerBufferMark)
3675   {
3676     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3677     /* save buffer pointer */
3678     unsigned char *saved_buffer = pStubMsg->Buffer;
3679
3680     /* get the buffer pointer after complex array data, but before
3681      * pointer data */
3682     pStubMsg->IgnoreEmbeddedPointers = 1;
3683     NdrComplexStructMemorySize(pStubMsg, pFormat);
3684     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3685
3686     /* save it for use by embedded pointer code later */
3687     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3688     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
3689     pointer_buffer_mark_set = 1;
3690
3691     /* restore the original buffer */
3692     pStubMsg->Buffer = saved_buffer;
3693   }
3694
3695   align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
3696
3697   pFormat += 4;
3698   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3699   pFormat += 2;
3700   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3701   pFormat += 2;
3702
3703   if (conf_array)
3704   {
3705     array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3706     size += array_size;
3707
3708     /* these could be changed in ComplexMarshall so save them for later */
3709     max_count = pStubMsg->MaxCount;
3710     count = pStubMsg->ActualCount;
3711     offset = pStubMsg->Offset;
3712   }
3713
3714   if (!fMustAlloc && !*ppMemory)
3715     fMustAlloc = TRUE;
3716   if (fMustAlloc)
3717     *ppMemory = NdrAllocate(pStubMsg, size);
3718
3719   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3720
3721   if (conf_array)
3722   {
3723     pStubMsg->MaxCount = max_count;
3724     pStubMsg->ActualCount = count;
3725     pStubMsg->Offset = offset;
3726     if (fMustAlloc)
3727       memset(pMemory, 0, array_size);
3728     array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3729                                        conf_array, FALSE,
3730                                        FALSE /* fUseBufferMemoryServer */,
3731                                        TRUE /* fUnmarshall */);
3732   }
3733
3734   if (pointer_buffer_mark_set)
3735   {
3736     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3737     pStubMsg->PointerBufferMark = NULL;
3738   }
3739
3740   return NULL;
3741 }
3742
3743 /***********************************************************************
3744  *           NdrComplexStructBufferSize [RPCRT4.@]
3745  */
3746 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3747                                        unsigned char *pMemory,
3748                                        PFORMAT_STRING pFormat)
3749 {
3750   PFORMAT_STRING conf_array = NULL;
3751   PFORMAT_STRING pointer_desc = NULL;
3752   unsigned char *OldMemory = pStubMsg->Memory;
3753   int pointer_length_set = 0;
3754   ULONG count = 0;
3755   ULONG max_count = 0;
3756   ULONG offset = 0;
3757
3758   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3759
3760   align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
3761
3762   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3763   {
3764     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3765     ULONG saved_buffer_length = pStubMsg->BufferLength;
3766
3767     /* get the buffer length after complex struct data, but before
3768      * pointer data */
3769     pStubMsg->IgnoreEmbeddedPointers = 1;
3770     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3771     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3772
3773     /* save it for use by embedded pointer code later */
3774     pStubMsg->PointerLength = pStubMsg->BufferLength;
3775     pointer_length_set = 1;
3776     TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
3777
3778     /* restore the original buffer length */
3779     pStubMsg->BufferLength = saved_buffer_length;
3780   }
3781
3782   pFormat += 4;
3783   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3784   pFormat += 2;
3785   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3786   pFormat += 2;
3787
3788   pStubMsg->Memory = pMemory;
3789
3790   if (conf_array)
3791   {
3792     ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3793     array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3794                                        conf_array);
3795
3796     /* these could be changed in ComplexMarshall so save them for later */
3797     max_count = pStubMsg->MaxCount;
3798     count = pStubMsg->ActualCount;
3799     offset = pStubMsg->Offset;
3800   }
3801
3802   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3803
3804   if (conf_array)
3805   {
3806     pStubMsg->MaxCount = max_count;
3807     pStubMsg->ActualCount = count;
3808     pStubMsg->Offset = offset;
3809     array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3810                       TRUE /* fHasPointers */);
3811   }
3812
3813   pStubMsg->Memory = OldMemory;
3814
3815   if(pointer_length_set)
3816   {
3817     pStubMsg->BufferLength = pStubMsg->PointerLength;
3818     pStubMsg->PointerLength = 0;
3819   }
3820
3821 }
3822
3823 /***********************************************************************
3824  *           NdrComplexStructMemorySize [RPCRT4.@]
3825  */
3826 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3827                                         PFORMAT_STRING pFormat)
3828 {
3829   unsigned size = *(const WORD*)(pFormat+2);
3830   PFORMAT_STRING conf_array = NULL;
3831   PFORMAT_STRING pointer_desc = NULL;
3832   ULONG count = 0;
3833   ULONG max_count = 0;
3834   ULONG offset = 0;
3835
3836   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3837
3838   align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
3839
3840   pFormat += 4;
3841   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3842   pFormat += 2;
3843   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3844   pFormat += 2;
3845
3846   if (conf_array)
3847   {
3848     array_read_conformance(conf_array[0], pStubMsg, conf_array);
3849
3850     /* these could be changed in ComplexStructMemorySize so save them for
3851      * later */
3852     max_count = pStubMsg->MaxCount;
3853     count = pStubMsg->ActualCount;
3854     offset = pStubMsg->Offset;
3855   }
3856
3857   ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3858
3859   if (conf_array)
3860   {
3861     pStubMsg->MaxCount = max_count;
3862     pStubMsg->ActualCount = count;
3863     pStubMsg->Offset = offset;
3864     array_memory_size(conf_array[0], pStubMsg, conf_array,
3865                       TRUE /* fHasPointers */);
3866   }
3867
3868   return size;
3869 }
3870
3871 /***********************************************************************
3872  *           NdrComplexStructFree [RPCRT4.@]
3873  */
3874 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3875                                  unsigned char *pMemory,
3876                                  PFORMAT_STRING pFormat)
3877 {
3878   PFORMAT_STRING conf_array = NULL;
3879   PFORMAT_STRING pointer_desc = NULL;
3880   unsigned char *OldMemory = pStubMsg->Memory;
3881
3882   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3883
3884   pFormat += 4;
3885   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3886   pFormat += 2;
3887   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3888   pFormat += 2;
3889
3890   pStubMsg->Memory = pMemory;
3891
3892   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3893
3894   if (conf_array)
3895     array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3896                TRUE /* fHasPointers */);
3897
3898   pStubMsg->Memory = OldMemory;
3899 }
3900
3901 /***********************************************************************
3902  *           NdrConformantArrayMarshall [RPCRT4.@]
3903  */
3904 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3905                                                   unsigned char *pMemory,
3906                                                   PFORMAT_STRING pFormat)
3907 {
3908   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3909   if (pFormat[0] != RPC_FC_CARRAY)
3910   {
3911     ERR("invalid format = 0x%x\n", pFormat[0]);
3912     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3913   }
3914
3915   array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
3916                                       pFormat);
3917   array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3918                                     TRUE /* fHasPointers */);
3919
3920   return NULL;
3921 }
3922
3923 /***********************************************************************
3924  *           NdrConformantArrayUnmarshall [RPCRT4.@]
3925  */
3926 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3927                                                     unsigned char **ppMemory,
3928                                                     PFORMAT_STRING pFormat,
3929                                                     unsigned char fMustAlloc)
3930 {
3931   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3932   if (pFormat[0] != RPC_FC_CARRAY)
3933   {
3934     ERR("invalid format = 0x%x\n", pFormat[0]);
3935     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3936   }
3937
3938   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3939   array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
3940                                      fMustAlloc,
3941                                      TRUE /* fUseBufferMemoryServer */,
3942                                      TRUE /* fUnmarshall */);
3943
3944   return NULL;
3945 }
3946
3947 /***********************************************************************
3948  *           NdrConformantArrayBufferSize [RPCRT4.@]
3949  */
3950 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3951                                          unsigned char *pMemory,
3952                                          PFORMAT_STRING pFormat)
3953 {
3954   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3955   if (pFormat[0] != RPC_FC_CARRAY)
3956   {
3957     ERR("invalid format = 0x%x\n", pFormat[0]);
3958     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3959   }
3960
3961   array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat);
3962   array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3963                     TRUE /* fHasPointers */);
3964 }
3965
3966 /***********************************************************************
3967  *           NdrConformantArrayMemorySize [RPCRT4.@]
3968  */
3969 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3970                                           PFORMAT_STRING pFormat)
3971 {
3972   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3973   if (pFormat[0] != RPC_FC_CARRAY)
3974   {
3975     ERR("invalid format = 0x%x\n", pFormat[0]);
3976     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3977   }
3978
3979   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3980   array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
3981
3982   return pStubMsg->MemorySize;
3983 }
3984
3985 /***********************************************************************
3986  *           NdrConformantArrayFree [RPCRT4.@]
3987  */
3988 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3989                                    unsigned char *pMemory,
3990                                    PFORMAT_STRING pFormat)
3991 {
3992   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3993   if (pFormat[0] != RPC_FC_CARRAY)
3994   {
3995     ERR("invalid format = 0x%x\n", pFormat[0]);
3996     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3997   }
3998
3999   array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
4000              TRUE /* fHasPointers */);
4001 }
4002
4003
4004 /***********************************************************************
4005  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
4006  */
4007 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
4008                                                          unsigned char* pMemory,
4009                                                          PFORMAT_STRING pFormat )
4010 {
4011     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4012
4013     if (pFormat[0] != RPC_FC_CVARRAY)
4014     {
4015         ERR("invalid format type %x\n", pFormat[0]);
4016         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4017         return NULL;
4018     }
4019
4020     array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
4021                                         pFormat);
4022     array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory,
4023                                       pFormat, TRUE /* fHasPointers */);
4024
4025     return NULL;
4026 }
4027
4028
4029 /***********************************************************************
4030  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
4031  */
4032 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
4033                                                            unsigned char** ppMemory,
4034                                                            PFORMAT_STRING pFormat,
4035                                                            unsigned char fMustAlloc )
4036 {
4037     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4038
4039     if (pFormat[0] != RPC_FC_CVARRAY)
4040     {
4041         ERR("invalid format type %x\n", pFormat[0]);
4042         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4043         return NULL;
4044     }
4045
4046     array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
4047     array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory,
4048                                        pFormat, fMustAlloc,
4049                                        TRUE /* fUseBufferMemoryServer */,
4050                                        TRUE /* fUnmarshall */);
4051
4052     return NULL;
4053 }
4054
4055
4056 /***********************************************************************
4057  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
4058  */
4059 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
4060                                            unsigned char* pMemory,
4061                                            PFORMAT_STRING pFormat )
4062 {
4063     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4064
4065     if (pFormat[0] != RPC_FC_CVARRAY)
4066     {
4067         ERR("invalid format type %x\n", pFormat[0]);
4068         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4069         return;
4070     }
4071
4072     array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
4073                TRUE /* fHasPointers */);
4074 }
4075
4076
4077 /***********************************************************************
4078  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
4079  */
4080 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
4081                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
4082 {
4083     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4084
4085     if (pFormat[0] != RPC_FC_CVARRAY)
4086     {
4087         ERR("invalid format type %x\n", pFormat[0]);
4088         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4089         return;
4090     }
4091
4092     array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
4093                                        pFormat);
4094     array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
4095                       TRUE /* fHasPointers */);
4096 }
4097
4098
4099 /***********************************************************************
4100  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
4101  */
4102 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
4103                                                   PFORMAT_STRING pFormat )
4104 {
4105     TRACE("(%p, %p)\n", pStubMsg, pFormat);
4106
4107     if (pFormat[0] != RPC_FC_CVARRAY)
4108     {
4109         ERR("invalid format type %x\n", pFormat[0]);
4110         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4111         return pStubMsg->MemorySize;
4112     }
4113
4114     array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
4115     array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat,
4116                       TRUE /* fHasPointers */);
4117
4118     return pStubMsg->MemorySize;
4119 }
4120
4121
4122 /***********************************************************************
4123  *           NdrComplexArrayMarshall [RPCRT4.@]
4124  */
4125 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4126                                                unsigned char *pMemory,
4127                                                PFORMAT_STRING pFormat)
4128 {
4129   int pointer_buffer_mark_set = 0;
4130
4131   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4132
4133   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4134   {
4135       ERR("invalid format type %x\n", pFormat[0]);
4136       RpcRaiseException(RPC_S_INTERNAL_ERROR);
4137       return NULL;
4138   }
4139
4140   if (!pStubMsg->PointerBufferMark)
4141   {
4142     /* save buffer fields that may be changed by buffer sizer functions
4143      * and that may be needed later on */
4144     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4145     ULONG saved_buffer_length = pStubMsg->BufferLength;
4146     ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4147     ULONG saved_offset = pStubMsg->Offset;
4148     ULONG saved_actual_count = pStubMsg->ActualCount;
4149
4150     /* get the buffer pointer after complex array data, but before
4151      * pointer data */
4152     pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
4153     pStubMsg->IgnoreEmbeddedPointers = 1;
4154     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4155     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4156
4157     /* save it for use by embedded pointer code later */
4158     pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
4159     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
4160     pointer_buffer_mark_set = 1;
4161
4162     /* restore fields */
4163     pStubMsg->ActualCount = saved_actual_count;
4164     pStubMsg->Offset = saved_offset;
4165     pStubMsg->MaxCount = saved_max_count;
4166     pStubMsg->BufferLength = saved_buffer_length;
4167   }
4168
4169   array_compute_and_write_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat);
4170   array_write_variance_and_marshall(RPC_FC_BOGUS_ARRAY, pStubMsg,
4171                                     pMemory, pFormat, TRUE /* fHasPointers */);
4172
4173   STD_OVERFLOW_CHECK(pStubMsg);
4174
4175   if (pointer_buffer_mark_set)
4176   {
4177     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4178     pStubMsg->PointerBufferMark = NULL;
4179   }
4180
4181   return NULL;
4182 }
4183
4184 /***********************************************************************
4185  *           NdrComplexArrayUnmarshall [RPCRT4.@]
4186  */
4187 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4188                                                  unsigned char **ppMemory,
4189                                                  PFORMAT_STRING pFormat,
4190                                                  unsigned char fMustAlloc)
4191 {
4192   unsigned char *saved_buffer;
4193   int pointer_buffer_mark_set = 0;
4194   int saved_ignore_embedded;
4195
4196   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4197
4198   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4199   {
4200       ERR("invalid format type %x\n", pFormat[0]);
4201       RpcRaiseException(RPC_S_INTERNAL_ERROR);
4202       return NULL;
4203   }
4204
4205   saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4206   /* save buffer pointer */
4207   saved_buffer = pStubMsg->Buffer;
4208   /* get the buffer pointer after complex array data, but before
4209    * pointer data */
4210   pStubMsg->IgnoreEmbeddedPointers = 1;
4211   pStubMsg->MemorySize = 0;
4212   NdrComplexArrayMemorySize(pStubMsg, pFormat);
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     case RPC_FC_ENUM16:
6163     {
6164         USHORT d;
6165         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6166         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6167         discriminant = d;
6168         break;
6169     }
6170     case RPC_FC_LONG:
6171     case RPC_FC_ULONG:
6172     {
6173         ULONG d;
6174         align_pointer(&pStubMsg->Buffer, sizeof(ULONG));
6175         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6176         discriminant = d;
6177         break;
6178     }
6179     default:
6180         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
6181     }
6182     (*ppFormat)++;
6183
6184     if (pStubMsg->fHasNewCorrDesc)
6185         *ppFormat += 6;
6186     else
6187         *ppFormat += 4;
6188     return discriminant;
6189 }
6190
6191 /**********************************************************************
6192  *           NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
6193  */
6194 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6195                                 unsigned char **ppMemory,
6196                                 PFORMAT_STRING pFormat,
6197                                 unsigned char fMustAlloc)
6198 {
6199     LONG discriminant;
6200     unsigned short size;
6201
6202     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
6203     pFormat++;
6204
6205     /* Unmarshall discriminant */
6206     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6207     TRACE("unmarshalled discriminant %x\n", discriminant);
6208
6209     pFormat += *(const SHORT*)pFormat;
6210
6211     size = *(const unsigned short*)pFormat;
6212
6213     if (!fMustAlloc && !*ppMemory)
6214         fMustAlloc = TRUE;
6215     if (fMustAlloc)
6216         *ppMemory = NdrAllocate(pStubMsg, size);
6217
6218     /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6219      * since the arm is part of the memory block that is encompassed by
6220      * the whole union. Memory is forced to allocate when pointers
6221      * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6222      * clearing the memory we pass in to the unmarshaller */
6223     if (fMustAlloc)
6224         memset(*ppMemory, 0, size);
6225
6226     return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
6227 }
6228
6229 /***********************************************************************
6230  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
6231  */
6232 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6233                                 unsigned char *pMemory,
6234                                 PFORMAT_STRING pFormat)
6235 {
6236     unsigned char switch_type;
6237
6238     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6239     pFormat++;
6240
6241     switch_type = *pFormat;
6242     pFormat++;
6243
6244     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6245     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6246     /* Add discriminant size */
6247     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6248
6249     union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6250 }
6251
6252 /***********************************************************************
6253  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
6254  */
6255 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6256                                 PFORMAT_STRING pFormat)
6257 {
6258     ULONG discriminant;
6259
6260     pFormat++;
6261     /* Unmarshall discriminant */
6262     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6263     TRACE("unmarshalled discriminant 0x%x\n", discriminant);
6264
6265     return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
6266 }
6267
6268 /***********************************************************************
6269  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
6270  */
6271 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6272                                 unsigned char *pMemory,
6273                                 PFORMAT_STRING pFormat)
6274 {
6275     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6276     pFormat++;
6277     pFormat++;
6278
6279     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6280     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6281
6282     union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6283 }
6284
6285 /***********************************************************************
6286  *           NdrByteCountPointerMarshall [RPCRT4.@]
6287  */
6288 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6289                                 unsigned char *pMemory,
6290                                 PFORMAT_STRING pFormat)
6291 {
6292     FIXME("stub\n");
6293     return NULL;
6294 }
6295
6296 /***********************************************************************
6297  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
6298  */
6299 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6300                                 unsigned char **ppMemory,
6301                                 PFORMAT_STRING pFormat,
6302                                 unsigned char fMustAlloc)
6303 {
6304     FIXME("stub\n");
6305     return NULL;
6306 }
6307
6308 /***********************************************************************
6309  *           NdrByteCountPointerBufferSize [RPCRT4.@]
6310  */
6311 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6312                                 unsigned char *pMemory,
6313                                 PFORMAT_STRING pFormat)
6314 {
6315     FIXME("stub\n");
6316 }
6317
6318 /***********************************************************************
6319  *           NdrByteCountPointerMemorySize [internal]
6320  */
6321 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6322                                                   PFORMAT_STRING pFormat)
6323 {
6324     FIXME("stub\n");
6325     return 0;
6326 }
6327
6328 /***********************************************************************
6329  *           NdrByteCountPointerFree [RPCRT4.@]
6330  */
6331 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
6332                                 unsigned char *pMemory,
6333                                 PFORMAT_STRING pFormat)
6334 {
6335     FIXME("stub\n");
6336 }
6337
6338 /***********************************************************************
6339  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
6340  */
6341 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6342                                 unsigned char *pMemory,
6343                                 PFORMAT_STRING pFormat)
6344 {
6345     FIXME("stub\n");
6346     return NULL;
6347 }
6348
6349 /***********************************************************************
6350  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
6351  */
6352 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6353                                 unsigned char **ppMemory,
6354                                 PFORMAT_STRING pFormat,
6355                                 unsigned char fMustAlloc)
6356 {
6357     FIXME("stub\n");
6358     return NULL;
6359 }
6360
6361 /***********************************************************************
6362  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
6363  */
6364 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6365                                 unsigned char *pMemory,
6366                                 PFORMAT_STRING pFormat)
6367 {
6368     FIXME("stub\n");
6369 }
6370
6371 /***********************************************************************
6372  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
6373  */
6374 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6375                                 PFORMAT_STRING pFormat)
6376 {
6377     FIXME("stub\n");
6378     return 0;
6379 }
6380
6381 /***********************************************************************
6382  *           NdrXmitOrRepAsFree [RPCRT4.@]
6383  */
6384 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
6385                                 unsigned char *pMemory,
6386                                 PFORMAT_STRING pFormat)
6387 {
6388     FIXME("stub\n");
6389 }
6390
6391 /***********************************************************************
6392  *           NdrRangeMarshall [internal]
6393  */
6394 static unsigned char *WINAPI NdrRangeMarshall(
6395     PMIDL_STUB_MESSAGE pStubMsg,
6396     unsigned char *pMemory,
6397     PFORMAT_STRING pFormat)
6398 {
6399     const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6400     unsigned char base_type;
6401
6402     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6403
6404     if (pRange->type != RPC_FC_RANGE)
6405     {
6406         ERR("invalid format type %x\n", pRange->type);
6407         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6408         return NULL;
6409     }
6410
6411     base_type = pRange->flags_type & 0xf;
6412
6413     return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
6414 }
6415
6416 /***********************************************************************
6417  *           NdrRangeUnmarshall [RPCRT4.@]
6418  */
6419 unsigned char *WINAPI NdrRangeUnmarshall(
6420     PMIDL_STUB_MESSAGE pStubMsg,
6421     unsigned char **ppMemory,
6422     PFORMAT_STRING pFormat,
6423     unsigned char fMustAlloc)
6424 {
6425     const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6426     unsigned char base_type;
6427
6428     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6429
6430     if (pRange->type != RPC_FC_RANGE)
6431     {
6432         ERR("invalid format type %x\n", pRange->type);
6433         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6434         return NULL;
6435     }
6436     base_type = pRange->flags_type & 0xf;
6437
6438     TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
6439         base_type, pRange->low_value, pRange->high_value);
6440
6441 #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
6442     do \
6443     { \
6444         align_pointer(&pStubMsg->Buffer, sizeof(wire_type)); \
6445         if (!fMustAlloc && !*ppMemory) \
6446             fMustAlloc = TRUE; \
6447         if (fMustAlloc) \
6448             *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
6449         if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
6450         { \
6451             ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
6452                 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
6453             RpcRaiseException(RPC_X_BAD_STUB_DATA); \
6454         } \
6455         if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
6456             (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
6457         { \
6458             ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
6459                 *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
6460                 (mem_type)pRange->high_value); \
6461             RpcRaiseException(RPC_S_INVALID_BOUND); \
6462             return NULL; \
6463         } \
6464         TRACE("*ppMemory: %p\n", *ppMemory); \
6465         **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
6466         pStubMsg->Buffer += sizeof(wire_type); \
6467     } while (0)
6468
6469     switch(base_type)
6470     {
6471     case RPC_FC_CHAR:
6472     case RPC_FC_SMALL:
6473         RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
6474         TRACE("value: 0x%02x\n", **ppMemory);
6475         break;
6476     case RPC_FC_BYTE:
6477     case RPC_FC_USMALL:
6478         RANGE_UNMARSHALL(CHAR, CHAR, "%u");
6479         TRACE("value: 0x%02x\n", **ppMemory);
6480         break;
6481     case RPC_FC_WCHAR: /* FIXME: valid? */
6482     case RPC_FC_USHORT:
6483         RANGE_UNMARSHALL(USHORT, USHORT, "%u");
6484         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6485         break;
6486     case RPC_FC_SHORT:
6487         RANGE_UNMARSHALL(SHORT, SHORT, "%d");
6488         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6489         break;
6490     case RPC_FC_LONG:
6491     case RPC_FC_ENUM32:
6492         RANGE_UNMARSHALL(LONG, LONG, "%d");
6493         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6494         break;
6495     case RPC_FC_ULONG:
6496         RANGE_UNMARSHALL(ULONG, ULONG, "%u");
6497         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6498         break;
6499     case RPC_FC_ENUM16:
6500         RANGE_UNMARSHALL(UINT, USHORT, "%u");
6501         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6502         break;
6503     case RPC_FC_FLOAT:
6504     case RPC_FC_DOUBLE:
6505     case RPC_FC_HYPER:
6506     default:
6507         ERR("invalid range base type: 0x%02x\n", base_type);
6508         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6509     }
6510
6511     return NULL;
6512 }
6513
6514 /***********************************************************************
6515  *           NdrRangeBufferSize [internal]
6516  */
6517 static void WINAPI NdrRangeBufferSize(
6518     PMIDL_STUB_MESSAGE pStubMsg,
6519     unsigned char *pMemory,
6520     PFORMAT_STRING pFormat)
6521 {
6522     const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6523     unsigned char base_type;
6524
6525     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6526
6527     if (pRange->type != RPC_FC_RANGE)
6528     {
6529         ERR("invalid format type %x\n", pRange->type);
6530         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6531     }
6532     base_type = pRange->flags_type & 0xf;
6533
6534     NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
6535 }
6536
6537 /***********************************************************************
6538  *           NdrRangeMemorySize [internal]
6539  */
6540 static ULONG WINAPI NdrRangeMemorySize(
6541     PMIDL_STUB_MESSAGE pStubMsg,
6542     PFORMAT_STRING pFormat)
6543 {
6544     const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6545     unsigned char base_type;
6546
6547     if (pRange->type != RPC_FC_RANGE)
6548     {
6549         ERR("invalid format type %x\n", pRange->type);
6550         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6551         return 0;
6552     }
6553     base_type = pRange->flags_type & 0xf;
6554
6555     return NdrBaseTypeMemorySize(pStubMsg, &base_type);
6556 }
6557
6558 /***********************************************************************
6559  *           NdrRangeFree [internal]
6560  */
6561 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
6562                                 unsigned char *pMemory,
6563                                 PFORMAT_STRING pFormat)
6564 {
6565    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6566
6567    /* nothing to do */
6568 }
6569
6570 /***********************************************************************
6571  *           NdrBaseTypeMarshall [internal]
6572  */
6573 static unsigned char *WINAPI NdrBaseTypeMarshall(
6574     PMIDL_STUB_MESSAGE pStubMsg,
6575     unsigned char *pMemory,
6576     PFORMAT_STRING pFormat)
6577 {
6578     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6579
6580     switch(*pFormat)
6581     {
6582     case RPC_FC_BYTE:
6583     case RPC_FC_CHAR:
6584     case RPC_FC_SMALL:
6585     case RPC_FC_USMALL:
6586         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
6587         TRACE("value: 0x%02x\n", *pMemory);
6588         break;
6589     case RPC_FC_WCHAR:
6590     case RPC_FC_SHORT:
6591     case RPC_FC_USHORT:
6592         align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT));
6593         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
6594         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
6595         break;
6596     case RPC_FC_LONG:
6597     case RPC_FC_ULONG:
6598     case RPC_FC_ERROR_STATUS_T:
6599     case RPC_FC_ENUM32:
6600         align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONG));
6601         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
6602         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
6603         break;
6604     case RPC_FC_FLOAT:
6605         align_pointer_clear(&pStubMsg->Buffer, sizeof(float));
6606         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
6607         break;
6608     case RPC_FC_DOUBLE:
6609         align_pointer_clear(&pStubMsg->Buffer, sizeof(double));
6610         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
6611         break;
6612     case RPC_FC_HYPER:
6613         align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONGLONG));
6614         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
6615         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
6616         break;
6617     case RPC_FC_ENUM16:
6618     {
6619         USHORT val = *(UINT *)pMemory;
6620         /* only 16-bits on the wire, so do a sanity check */
6621         if (*(UINT *)pMemory > SHRT_MAX)
6622             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
6623         align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT));
6624         safe_copy_to_buffer(pStubMsg, &val, sizeof(val));
6625         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
6626         break;
6627     }
6628     case RPC_FC_INT3264:
6629     case RPC_FC_UINT3264:
6630     {
6631         UINT val = *(UINT_PTR *)pMemory;
6632         align_pointer_clear(&pStubMsg->Buffer, sizeof(UINT));
6633         safe_copy_to_buffer(pStubMsg, &val, sizeof(val));
6634         break;
6635     }
6636     case RPC_FC_IGNORE:
6637         break;
6638     default:
6639         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6640     }
6641
6642     /* FIXME: what is the correct return value? */
6643     return NULL;
6644 }
6645
6646 /***********************************************************************
6647  *           NdrBaseTypeUnmarshall [internal]
6648  */
6649 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
6650     PMIDL_STUB_MESSAGE pStubMsg,
6651     unsigned char **ppMemory,
6652     PFORMAT_STRING pFormat,
6653     unsigned char fMustAlloc)
6654 {
6655     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6656
6657 #define BASE_TYPE_UNMARSHALL(type) do { \
6658         align_pointer(&pStubMsg->Buffer, sizeof(type)); \
6659         if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
6660         { \
6661             *ppMemory = pStubMsg->Buffer; \
6662             TRACE("*ppMemory: %p\n", *ppMemory); \
6663             safe_buffer_increment(pStubMsg, sizeof(type)); \
6664         } \
6665         else \
6666         {  \
6667             if (fMustAlloc) \
6668                 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
6669             TRACE("*ppMemory: %p\n", *ppMemory); \
6670             safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \
6671         } \
6672     } while (0)
6673
6674     switch(*pFormat)
6675     {
6676     case RPC_FC_BYTE:
6677     case RPC_FC_CHAR:
6678     case RPC_FC_SMALL:
6679     case RPC_FC_USMALL:
6680         BASE_TYPE_UNMARSHALL(UCHAR);
6681         TRACE("value: 0x%02x\n", **ppMemory);
6682         break;
6683     case RPC_FC_WCHAR:
6684     case RPC_FC_SHORT:
6685     case RPC_FC_USHORT:
6686         BASE_TYPE_UNMARSHALL(USHORT);
6687         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6688         break;
6689     case RPC_FC_LONG:
6690     case RPC_FC_ULONG:
6691     case RPC_FC_ERROR_STATUS_T:
6692     case RPC_FC_ENUM32:
6693         BASE_TYPE_UNMARSHALL(ULONG);
6694         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6695         break;
6696    case RPC_FC_FLOAT:
6697         BASE_TYPE_UNMARSHALL(float);
6698         TRACE("value: %f\n", **(float **)ppMemory);
6699         break;
6700     case RPC_FC_DOUBLE:
6701         BASE_TYPE_UNMARSHALL(double);
6702         TRACE("value: %f\n", **(double **)ppMemory);
6703         break;
6704     case RPC_FC_HYPER:
6705         BASE_TYPE_UNMARSHALL(ULONGLONG);
6706         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
6707         break;
6708     case RPC_FC_ENUM16:
6709     {
6710         USHORT val;
6711         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6712         if (!fMustAlloc && !*ppMemory)
6713             fMustAlloc = TRUE;
6714         if (fMustAlloc)
6715             *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
6716         safe_copy_from_buffer(pStubMsg, &val, sizeof(USHORT));
6717         /* 16-bits on the wire, but int in memory */
6718         **(UINT **)ppMemory = val;
6719         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6720         break;
6721     }
6722     case RPC_FC_INT3264:
6723         if (sizeof(INT_PTR) == sizeof(INT)) BASE_TYPE_UNMARSHALL(INT);
6724         else
6725         {
6726             INT val;
6727             align_pointer(&pStubMsg->Buffer, sizeof(INT));
6728             if (!fMustAlloc && !*ppMemory)
6729                 fMustAlloc = TRUE;
6730             if (fMustAlloc)
6731                 *ppMemory = NdrAllocate(pStubMsg, sizeof(INT_PTR));
6732             safe_copy_from_buffer(pStubMsg, &val, sizeof(INT));
6733             **(INT_PTR **)ppMemory = val;
6734             TRACE("value: 0x%08lx\n", **(INT_PTR **)ppMemory);
6735         }
6736         break;
6737     case RPC_FC_UINT3264:
6738         if (sizeof(UINT_PTR) == sizeof(UINT)) BASE_TYPE_UNMARSHALL(UINT);
6739         else
6740         {
6741             UINT val;
6742             align_pointer(&pStubMsg->Buffer, sizeof(UINT));
6743             if (!fMustAlloc && !*ppMemory)
6744                 fMustAlloc = TRUE;
6745             if (fMustAlloc)
6746                 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT_PTR));
6747             safe_copy_from_buffer(pStubMsg, &val, sizeof(UINT));
6748             **(UINT_PTR **)ppMemory = val;
6749             TRACE("value: 0x%08lx\n", **(UINT_PTR **)ppMemory);
6750         }
6751         break;
6752     case RPC_FC_IGNORE:
6753         break;
6754     default:
6755         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6756     }
6757 #undef BASE_TYPE_UNMARSHALL
6758
6759     /* FIXME: what is the correct return value? */
6760
6761     return NULL;
6762 }
6763
6764 /***********************************************************************
6765  *           NdrBaseTypeBufferSize [internal]
6766  */
6767 static void WINAPI NdrBaseTypeBufferSize(
6768     PMIDL_STUB_MESSAGE pStubMsg,
6769     unsigned char *pMemory,
6770     PFORMAT_STRING pFormat)
6771 {
6772     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6773
6774     switch(*pFormat)
6775     {
6776     case RPC_FC_BYTE:
6777     case RPC_FC_CHAR:
6778     case RPC_FC_SMALL:
6779     case RPC_FC_USMALL:
6780         safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6781         break;
6782     case RPC_FC_WCHAR:
6783     case RPC_FC_SHORT:
6784     case RPC_FC_USHORT:
6785     case RPC_FC_ENUM16:
6786         align_length(&pStubMsg->BufferLength, sizeof(USHORT));
6787         safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6788         break;
6789     case RPC_FC_LONG:
6790     case RPC_FC_ULONG:
6791     case RPC_FC_ENUM32:
6792     case RPC_FC_INT3264:
6793     case RPC_FC_UINT3264:
6794         align_length(&pStubMsg->BufferLength, sizeof(ULONG));
6795         safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6796         break;
6797     case RPC_FC_FLOAT:
6798         align_length(&pStubMsg->BufferLength, sizeof(float));
6799         safe_buffer_length_increment(pStubMsg, sizeof(float));
6800         break;
6801     case RPC_FC_DOUBLE:
6802         align_length(&pStubMsg->BufferLength, sizeof(double));
6803         safe_buffer_length_increment(pStubMsg, sizeof(double));
6804         break;
6805     case RPC_FC_HYPER:
6806         align_length(&pStubMsg->BufferLength, sizeof(ULONGLONG));
6807         safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6808         break;
6809     case RPC_FC_ERROR_STATUS_T:
6810         align_length(&pStubMsg->BufferLength, sizeof(error_status_t));
6811         safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6812         break;
6813     case RPC_FC_IGNORE:
6814         break;
6815     default:
6816         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6817     }
6818 }
6819
6820 /***********************************************************************
6821  *           NdrBaseTypeMemorySize [internal]
6822  */
6823 static ULONG WINAPI NdrBaseTypeMemorySize(
6824     PMIDL_STUB_MESSAGE pStubMsg,
6825     PFORMAT_STRING pFormat)
6826 {
6827     TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6828
6829     switch(*pFormat)
6830     {
6831     case RPC_FC_BYTE:
6832     case RPC_FC_CHAR:
6833     case RPC_FC_SMALL:
6834     case RPC_FC_USMALL:
6835         safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6836         pStubMsg->MemorySize += sizeof(UCHAR);
6837         return sizeof(UCHAR);
6838     case RPC_FC_WCHAR:
6839     case RPC_FC_SHORT:
6840     case RPC_FC_USHORT:
6841         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6842         safe_buffer_increment(pStubMsg, sizeof(USHORT));
6843         align_length(&pStubMsg->MemorySize, sizeof(USHORT));
6844         pStubMsg->MemorySize += sizeof(USHORT);
6845         return sizeof(USHORT);
6846     case RPC_FC_LONG:
6847     case RPC_FC_ULONG:
6848     case RPC_FC_ENUM32:
6849         align_pointer(&pStubMsg->Buffer, sizeof(ULONG));
6850         safe_buffer_increment(pStubMsg, sizeof(ULONG));
6851         align_length(&pStubMsg->MemorySize, sizeof(ULONG));
6852         pStubMsg->MemorySize += sizeof(ULONG);
6853         return sizeof(ULONG);
6854     case RPC_FC_FLOAT:
6855         align_pointer(&pStubMsg->Buffer, sizeof(float));
6856         safe_buffer_increment(pStubMsg, sizeof(float));
6857         align_length(&pStubMsg->MemorySize, sizeof(float));
6858         pStubMsg->MemorySize += sizeof(float);
6859         return sizeof(float);
6860     case RPC_FC_DOUBLE:
6861         align_pointer(&pStubMsg->Buffer, sizeof(double));
6862         safe_buffer_increment(pStubMsg, sizeof(double));
6863         align_length(&pStubMsg->MemorySize, sizeof(double));
6864         pStubMsg->MemorySize += sizeof(double);
6865         return sizeof(double);
6866     case RPC_FC_HYPER:
6867         align_pointer(&pStubMsg->Buffer, sizeof(ULONGLONG));
6868         safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6869         align_length(&pStubMsg->MemorySize, sizeof(ULONGLONG));
6870         pStubMsg->MemorySize += sizeof(ULONGLONG);
6871         return sizeof(ULONGLONG);
6872     case RPC_FC_ERROR_STATUS_T:
6873         align_pointer(&pStubMsg->Buffer, sizeof(error_status_t));
6874         safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6875         align_length(&pStubMsg->MemorySize, sizeof(error_status_t));
6876         pStubMsg->MemorySize += sizeof(error_status_t);
6877         return sizeof(error_status_t);
6878     case RPC_FC_ENUM16:
6879         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6880         safe_buffer_increment(pStubMsg, sizeof(USHORT));
6881         align_length(&pStubMsg->MemorySize, sizeof(UINT));
6882         pStubMsg->MemorySize += sizeof(UINT);
6883         return sizeof(UINT);
6884     case RPC_FC_INT3264:
6885     case RPC_FC_UINT3264:
6886         align_pointer(&pStubMsg->Buffer, sizeof(UINT));
6887         safe_buffer_increment(pStubMsg, sizeof(UINT));
6888         align_length(&pStubMsg->MemorySize, sizeof(UINT_PTR));
6889         pStubMsg->MemorySize += sizeof(UINT_PTR);
6890         return sizeof(UINT_PTR);
6891     case RPC_FC_IGNORE:
6892         align_length(&pStubMsg->MemorySize, sizeof(void *));
6893         pStubMsg->MemorySize += sizeof(void *);
6894         return sizeof(void *);
6895     default:
6896         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6897        return 0;
6898     }
6899 }
6900
6901 /***********************************************************************
6902  *           NdrBaseTypeFree [internal]
6903  */
6904 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6905                                 unsigned char *pMemory,
6906                                 PFORMAT_STRING pFormat)
6907 {
6908    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6909
6910    /* nothing to do */
6911 }
6912
6913 /***********************************************************************
6914  *           NdrContextHandleBufferSize [internal]
6915  */
6916 static void WINAPI NdrContextHandleBufferSize(
6917     PMIDL_STUB_MESSAGE pStubMsg,
6918     unsigned char *pMemory,
6919     PFORMAT_STRING pFormat)
6920 {
6921     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6922
6923     if (*pFormat != RPC_FC_BIND_CONTEXT)
6924     {
6925         ERR("invalid format type %x\n", *pFormat);
6926         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6927     }
6928     align_length(&pStubMsg->BufferLength, 4);
6929     safe_buffer_length_increment(pStubMsg, cbNDRContext);
6930 }
6931
6932 /***********************************************************************
6933  *           NdrContextHandleMarshall [internal]
6934  */
6935 static unsigned char *WINAPI NdrContextHandleMarshall(
6936     PMIDL_STUB_MESSAGE pStubMsg,
6937     unsigned char *pMemory,
6938     PFORMAT_STRING pFormat)
6939 {
6940     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6941
6942     if (*pFormat != RPC_FC_BIND_CONTEXT)
6943     {
6944         ERR("invalid format type %x\n", *pFormat);
6945         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6946     }
6947     TRACE("flags: 0x%02x\n", pFormat[1]);
6948
6949     if (pStubMsg->IsClient)
6950     {
6951         if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6952             NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6953         else
6954             NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
6955     }
6956     else
6957     {
6958         NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
6959         NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
6960         NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
6961     }
6962
6963     return NULL;
6964 }
6965
6966 /***********************************************************************
6967  *           NdrContextHandleUnmarshall [internal]
6968  */
6969 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6970     PMIDL_STUB_MESSAGE pStubMsg,
6971     unsigned char **ppMemory,
6972     PFORMAT_STRING pFormat,
6973     unsigned char fMustAlloc)
6974 {
6975     TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg,
6976         ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE");
6977
6978     if (*pFormat != RPC_FC_BIND_CONTEXT)
6979     {
6980         ERR("invalid format type %x\n", *pFormat);
6981         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6982     }
6983     TRACE("flags: 0x%02x\n", pFormat[1]);
6984
6985     if (pStubMsg->IsClient)
6986     {
6987         /* [out]-only or [ret] param */
6988         if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT)
6989             **(NDR_CCONTEXT **)ppMemory = NULL;
6990         NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
6991     }
6992     else
6993     {
6994         NDR_SCONTEXT ctxt;
6995         ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat);
6996         if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6997             *(void **)ppMemory = NDRSContextValue(ctxt);
6998         else
6999             *(void **)ppMemory = *NDRSContextValue(ctxt);
7000     }
7001
7002     return NULL;
7003 }
7004
7005 /***********************************************************************
7006  *           NdrClientContextMarshall [RPCRT4.@]
7007  */
7008 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
7009                                      NDR_CCONTEXT ContextHandle,
7010                                      int fCheck)
7011 {
7012     TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
7013
7014     align_pointer_clear(&pStubMsg->Buffer, 4);
7015
7016     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7017     {
7018         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7019             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7020         RpcRaiseException(RPC_X_BAD_STUB_DATA);
7021     }
7022
7023     /* FIXME: what does fCheck do? */
7024     NDRCContextMarshall(ContextHandle,
7025                         pStubMsg->Buffer);
7026
7027     pStubMsg->Buffer += cbNDRContext;
7028 }
7029
7030 /***********************************************************************
7031  *           NdrClientContextUnmarshall [RPCRT4.@]
7032  */
7033 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
7034                                        NDR_CCONTEXT * pContextHandle,
7035                                        RPC_BINDING_HANDLE BindHandle)
7036 {
7037     TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
7038
7039     align_pointer(&pStubMsg->Buffer, 4);
7040
7041     if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
7042         RpcRaiseException(RPC_X_BAD_STUB_DATA);
7043
7044     NDRCContextUnmarshall(pContextHandle,
7045                           BindHandle,
7046                           pStubMsg->Buffer,
7047                           pStubMsg->RpcMsg->DataRepresentation);
7048
7049     pStubMsg->Buffer += cbNDRContext;
7050 }
7051
7052 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
7053                                      NDR_SCONTEXT ContextHandle,
7054                                      NDR_RUNDOWN RundownRoutine )
7055 {
7056     TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
7057
7058     align_pointer(&pStubMsg->Buffer, 4);
7059
7060     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7061     {
7062         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7063             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7064         RpcRaiseException(RPC_X_BAD_STUB_DATA);
7065     }
7066
7067     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
7068                          pStubMsg->Buffer, RundownRoutine, NULL,
7069                          RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
7070     pStubMsg->Buffer += cbNDRContext;
7071 }
7072
7073 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
7074 {
7075     NDR_SCONTEXT ContextHandle;
7076
7077     TRACE("(%p)\n", pStubMsg);
7078
7079     align_pointer(&pStubMsg->Buffer, 4);
7080
7081     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7082     {
7083         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7084             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7085         RpcRaiseException(RPC_X_BAD_STUB_DATA);
7086     }
7087
7088     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
7089                                            pStubMsg->Buffer,
7090                                            pStubMsg->RpcMsg->DataRepresentation,
7091                                            NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
7092     pStubMsg->Buffer += cbNDRContext;
7093
7094     return ContextHandle;
7095 }
7096
7097 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
7098                                  unsigned char* pMemory,
7099                                  PFORMAT_STRING pFormat)
7100 {
7101     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
7102 }
7103
7104 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
7105                                                PFORMAT_STRING pFormat)
7106 {
7107     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
7108     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
7109
7110     TRACE("(%p, %p)\n", pStubMsg, pFormat);
7111
7112     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7113         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7114     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
7115         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7116     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7117     {
7118         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7119         if_id = &sif->InterfaceId;
7120     }
7121
7122     return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
7123                                   pStubMsg->RpcMsg->DataRepresentation, if_id,
7124                                   flags);
7125 }
7126
7127 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
7128                                         NDR_SCONTEXT ContextHandle,
7129                                         NDR_RUNDOWN RundownRoutine,
7130                                         PFORMAT_STRING pFormat)
7131 {
7132     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
7133     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
7134
7135     TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
7136
7137     align_pointer(&pStubMsg->Buffer, 4);
7138
7139     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7140     {
7141         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7142             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7143         RpcRaiseException(RPC_X_BAD_STUB_DATA);
7144     }
7145
7146     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7147         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7148     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
7149         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7150     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7151     {
7152         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7153         if_id = &sif->InterfaceId;
7154     }
7155
7156     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
7157                           pStubMsg->Buffer, RundownRoutine, if_id, flags);
7158     pStubMsg->Buffer += cbNDRContext;
7159 }
7160
7161 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
7162                                                   PFORMAT_STRING pFormat)
7163 {
7164     NDR_SCONTEXT ContextHandle;
7165     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
7166     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
7167
7168     TRACE("(%p, %p)\n", pStubMsg, pFormat);
7169
7170     align_pointer(&pStubMsg->Buffer, 4);
7171
7172     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7173     {
7174         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7175             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7176         RpcRaiseException(RPC_X_BAD_STUB_DATA);
7177     }
7178
7179     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7180         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7181     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
7182         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7183     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7184     {
7185         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7186         if_id = &sif->InterfaceId;
7187     }
7188
7189     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
7190                                            pStubMsg->Buffer,
7191                                            pStubMsg->RpcMsg->DataRepresentation,
7192                                            if_id, flags);
7193     pStubMsg->Buffer += cbNDRContext;
7194
7195     return ContextHandle;
7196 }
7197
7198 /***********************************************************************
7199  *           NdrCorrelationInitialize [RPCRT4.@]
7200  *
7201  * Initializes correlation validity checking.
7202  *
7203  * PARAMS
7204  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
7205  *  pMemory     [I] Pointer to memory to use as a cache.
7206  *  CacheSize   [I] Size of the memory pointed to by pMemory.
7207  *  Flags       [I] Reserved. Set to zero.
7208  *
7209  * RETURNS
7210  *  Nothing.
7211  */
7212 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
7213 {
7214     FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
7215     pStubMsg->fHasNewCorrDesc = TRUE;
7216 }
7217
7218 /***********************************************************************
7219  *           NdrCorrelationPass [RPCRT4.@]
7220  *
7221  * Performs correlation validity checking.
7222  *
7223  * PARAMS
7224  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
7225  *
7226  * RETURNS
7227  *  Nothing.
7228  */
7229 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
7230 {
7231     FIXME("(%p): stub\n", pStubMsg);
7232 }
7233
7234 /***********************************************************************
7235  *           NdrCorrelationFree [RPCRT4.@]
7236  *
7237  * Frees any resources used while unmarshalling parameters that need
7238  * correlation validity checking.
7239  *
7240  * PARAMS
7241  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
7242  *
7243  * RETURNS
7244  *  Nothing.
7245  */
7246 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
7247 {
7248     FIXME("(%p): stub\n", pStubMsg);
7249 }