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