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