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