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