rpcrt4: Add support for marshalling/unmarshalling complex arrays of pointers.
[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_FLOAT:
2700       TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
2701       safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
2702       pMemory += sizeof(float);
2703       break;
2704     case RPC_FC_HYPER:
2705       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2706       safe_copy_to_buffer(pStubMsg, pMemory, 8);
2707       pMemory += 8;
2708       break;
2709     case RPC_FC_DOUBLE:
2710       TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
2711       safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
2712       pMemory += sizeof(double);
2713       break;
2714     case RPC_FC_RP:
2715     case RPC_FC_UP:
2716     case RPC_FC_OP:
2717     case RPC_FC_FP:
2718     case RPC_FC_POINTER:
2719     {
2720       unsigned char *saved_buffer;
2721       int pointer_buffer_mark_set = 0;
2722       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2723       TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2724       if (*pFormat != RPC_FC_POINTER)
2725         pPointer = pFormat;
2726       if (*pPointer != RPC_FC_RP)
2727         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2728       saved_buffer = pStubMsg->Buffer;
2729       if (pStubMsg->PointerBufferMark)
2730       {
2731         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2732         pStubMsg->PointerBufferMark = NULL;
2733         pointer_buffer_mark_set = 1;
2734       }
2735       else if (*pPointer != RPC_FC_RP)
2736         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2737       PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2738       if (pointer_buffer_mark_set)
2739       {
2740         STD_OVERFLOW_CHECK(pStubMsg);
2741         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2742         pStubMsg->Buffer = saved_buffer;
2743         if (*pPointer != RPC_FC_RP)
2744           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2745       }
2746       TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2747       if (*pFormat == RPC_FC_POINTER)
2748         pPointer += 4;
2749       else
2750         pFormat += 4;
2751       pMemory += sizeof(void *);
2752       break;
2753     }
2754     case RPC_FC_ALIGNM2:
2755       ALIGN_POINTER(pMemory, 2);
2756       break;
2757     case RPC_FC_ALIGNM4:
2758       ALIGN_POINTER(pMemory, 4);
2759       break;
2760     case RPC_FC_ALIGNM8:
2761       ALIGN_POINTER(pMemory, 8);
2762       break;
2763     case RPC_FC_STRUCTPAD1:
2764     case RPC_FC_STRUCTPAD2:
2765     case RPC_FC_STRUCTPAD3:
2766     case RPC_FC_STRUCTPAD4:
2767     case RPC_FC_STRUCTPAD5:
2768     case RPC_FC_STRUCTPAD6:
2769     case RPC_FC_STRUCTPAD7:
2770       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2771       break;
2772     case RPC_FC_EMBEDDED_COMPLEX:
2773       pMemory += pFormat[1];
2774       pFormat += 2;
2775       desc = pFormat + *(const SHORT*)pFormat;
2776       size = EmbeddedComplexSize(pStubMsg, desc);
2777       TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2778       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2779       if (m)
2780       {
2781         /* for some reason interface pointers aren't generated as
2782          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2783          * they still need the derefencing treatment that pointers are
2784          * given */
2785         if (*desc == RPC_FC_IP)
2786           m(pStubMsg, *(unsigned char **)pMemory, desc);
2787         else
2788           m(pStubMsg, pMemory, desc);
2789       }
2790       else FIXME("no marshaller for embedded type %02x\n", *desc);
2791       pMemory += size;
2792       pFormat += 2;
2793       continue;
2794     case RPC_FC_PAD:
2795       break;
2796     default:
2797       FIXME("unhandled format 0x%02x\n", *pFormat);
2798     }
2799     pFormat++;
2800   }
2801
2802   return pMemory;
2803 }
2804
2805 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2806                                          unsigned char *pMemory,
2807                                          PFORMAT_STRING pFormat,
2808                                          PFORMAT_STRING pPointer,
2809                                          unsigned char fMustAlloc)
2810 {
2811   PFORMAT_STRING desc;
2812   NDR_UNMARSHALL m;
2813   ULONG size;
2814
2815   while (*pFormat != RPC_FC_END) {
2816     switch (*pFormat) {
2817     case RPC_FC_BYTE:
2818     case RPC_FC_CHAR:
2819     case RPC_FC_SMALL:
2820     case RPC_FC_USMALL:
2821       safe_copy_from_buffer(pStubMsg, pMemory, 1);
2822       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2823       pMemory += 1;
2824       break;
2825     case RPC_FC_WCHAR:
2826     case RPC_FC_SHORT:
2827     case RPC_FC_USHORT:
2828       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2829       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2830       pMemory += 2;
2831       break;
2832     case RPC_FC_ENUM16:
2833       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2834       *(DWORD*)pMemory &= 0xffff;
2835       TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2836       if (32767 < *(DWORD*)pMemory)
2837         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2838       pMemory += 4;
2839       break;
2840     case RPC_FC_LONG:
2841     case RPC_FC_ULONG:
2842     case RPC_FC_ENUM32:
2843       safe_copy_from_buffer(pStubMsg, pMemory, 4);
2844       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2845       pMemory += 4;
2846       break;
2847     case RPC_FC_FLOAT:
2848       safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
2849       TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
2850       pMemory += sizeof(float);
2851       break;
2852     case RPC_FC_HYPER:
2853       safe_copy_from_buffer(pStubMsg, pMemory, 8);
2854       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2855       pMemory += 8;
2856       break;
2857     case RPC_FC_DOUBLE:
2858       safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
2859       TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
2860       pMemory += sizeof(double);
2861       break;
2862     case RPC_FC_RP:
2863     case RPC_FC_UP:
2864     case RPC_FC_OP:
2865     case RPC_FC_FP:
2866     case RPC_FC_POINTER:
2867     {
2868       unsigned char *saved_buffer;
2869       int pointer_buffer_mark_set = 0;
2870       TRACE("pointer => %p\n", pMemory);
2871       if (*pFormat != RPC_FC_POINTER)
2872         pPointer = pFormat;
2873       if (*pPointer != RPC_FC_RP)
2874         ALIGN_POINTER(pStubMsg->Buffer, 4);
2875       saved_buffer = pStubMsg->Buffer;
2876       if (pStubMsg->PointerBufferMark)
2877       {
2878         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2879         pStubMsg->PointerBufferMark = NULL;
2880         pointer_buffer_mark_set = 1;
2881       }
2882       else if (*pPointer != RPC_FC_RP)
2883         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2884
2885       PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
2886       if (pointer_buffer_mark_set)
2887       {
2888         STD_OVERFLOW_CHECK(pStubMsg);
2889         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2890         pStubMsg->Buffer = saved_buffer;
2891         if (*pPointer != RPC_FC_RP)
2892           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2893       }
2894       if (*pFormat == RPC_FC_POINTER)
2895         pPointer += 4;
2896       else
2897         pFormat += 4;
2898       pMemory += sizeof(void *);
2899       break;
2900     }
2901     case RPC_FC_ALIGNM2:
2902       ALIGN_POINTER_CLEAR(pMemory, 2);
2903       break;
2904     case RPC_FC_ALIGNM4:
2905       ALIGN_POINTER_CLEAR(pMemory, 4);
2906       break;
2907     case RPC_FC_ALIGNM8:
2908       ALIGN_POINTER_CLEAR(pMemory, 8);
2909       break;
2910     case RPC_FC_STRUCTPAD1:
2911     case RPC_FC_STRUCTPAD2:
2912     case RPC_FC_STRUCTPAD3:
2913     case RPC_FC_STRUCTPAD4:
2914     case RPC_FC_STRUCTPAD5:
2915     case RPC_FC_STRUCTPAD6:
2916     case RPC_FC_STRUCTPAD7:
2917       memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2918       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2919       break;
2920     case RPC_FC_EMBEDDED_COMPLEX:
2921       pMemory += pFormat[1];
2922       pFormat += 2;
2923       desc = pFormat + *(const SHORT*)pFormat;
2924       size = EmbeddedComplexSize(pStubMsg, desc);
2925       TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
2926       if (fMustAlloc)
2927         /* we can't pass fMustAlloc=TRUE into the marshaller for this type
2928          * since the type is part of the memory block that is encompassed by
2929          * the whole complex type. Memory is forced to allocate when pointers
2930          * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
2931          * clearing the memory we pass in to the unmarshaller */
2932         memset(pMemory, 0, size);
2933       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2934       if (m)
2935       {
2936         /* for some reason interface pointers aren't generated as
2937          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2938          * they still need the derefencing treatment that pointers are
2939          * given */
2940         if (*desc == RPC_FC_IP)
2941           m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2942         else
2943           m(pStubMsg, &pMemory, desc, FALSE);
2944       }
2945       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2946       pMemory += size;
2947       pFormat += 2;
2948       continue;
2949     case RPC_FC_PAD:
2950       break;
2951     default:
2952       FIXME("unhandled format %d\n", *pFormat);
2953     }
2954     pFormat++;
2955   }
2956
2957   return pMemory;
2958 }
2959
2960 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2961                                          unsigned char *pMemory,
2962                                          PFORMAT_STRING pFormat,
2963                                          PFORMAT_STRING pPointer)
2964 {
2965   PFORMAT_STRING desc;
2966   NDR_BUFFERSIZE m;
2967   ULONG size;
2968
2969   while (*pFormat != RPC_FC_END) {
2970     switch (*pFormat) {
2971     case RPC_FC_BYTE:
2972     case RPC_FC_CHAR:
2973     case RPC_FC_SMALL:
2974     case RPC_FC_USMALL:
2975       safe_buffer_length_increment(pStubMsg, 1);
2976       pMemory += 1;
2977       break;
2978     case RPC_FC_WCHAR:
2979     case RPC_FC_SHORT:
2980     case RPC_FC_USHORT:
2981       safe_buffer_length_increment(pStubMsg, 2);
2982       pMemory += 2;
2983       break;
2984     case RPC_FC_ENUM16:
2985       safe_buffer_length_increment(pStubMsg, 2);
2986       pMemory += 4;
2987       break;
2988     case RPC_FC_LONG:
2989     case RPC_FC_ULONG:
2990     case RPC_FC_ENUM32:
2991     case RPC_FC_FLOAT:
2992       safe_buffer_length_increment(pStubMsg, 4);
2993       pMemory += 4;
2994       break;
2995     case RPC_FC_HYPER:
2996     case RPC_FC_DOUBLE:
2997       safe_buffer_length_increment(pStubMsg, 8);
2998       pMemory += 8;
2999       break;
3000     case RPC_FC_RP:
3001     case RPC_FC_UP:
3002     case RPC_FC_OP:
3003     case RPC_FC_FP:
3004     case RPC_FC_POINTER:
3005       if (*pFormat != RPC_FC_POINTER)
3006         pPointer = pFormat;
3007       if (!pStubMsg->IgnoreEmbeddedPointers)
3008       {
3009         int saved_buffer_length = pStubMsg->BufferLength;
3010         pStubMsg->BufferLength = pStubMsg->PointerLength;
3011         pStubMsg->PointerLength = 0;
3012         if(!pStubMsg->BufferLength)
3013           ERR("BufferLength == 0??\n");
3014         PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
3015         pStubMsg->PointerLength = pStubMsg->BufferLength;
3016         pStubMsg->BufferLength = saved_buffer_length;
3017       }
3018       if (*pPointer != RPC_FC_RP)
3019       {
3020         ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3021         safe_buffer_length_increment(pStubMsg, 4);
3022       }
3023       if (*pFormat == RPC_FC_POINTER)
3024         pPointer += 4;
3025       else
3026         pFormat += 4;
3027       pMemory += sizeof(void*);
3028       break;
3029     case RPC_FC_ALIGNM2:
3030       ALIGN_POINTER(pMemory, 2);
3031       break;
3032     case RPC_FC_ALIGNM4:
3033       ALIGN_POINTER(pMemory, 4);
3034       break;
3035     case RPC_FC_ALIGNM8:
3036       ALIGN_POINTER(pMemory, 8);
3037       break;
3038     case RPC_FC_STRUCTPAD1:
3039     case RPC_FC_STRUCTPAD2:
3040     case RPC_FC_STRUCTPAD3:
3041     case RPC_FC_STRUCTPAD4:
3042     case RPC_FC_STRUCTPAD5:
3043     case RPC_FC_STRUCTPAD6:
3044     case RPC_FC_STRUCTPAD7:
3045       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3046       break;
3047     case RPC_FC_EMBEDDED_COMPLEX:
3048       pMemory += pFormat[1];
3049       pFormat += 2;
3050       desc = pFormat + *(const SHORT*)pFormat;
3051       size = EmbeddedComplexSize(pStubMsg, desc);
3052       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3053       if (m)
3054       {
3055         /* for some reason interface pointers aren't generated as
3056          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3057          * they still need the derefencing treatment that pointers are
3058          * given */
3059         if (*desc == RPC_FC_IP)
3060           m(pStubMsg, *(unsigned char **)pMemory, desc);
3061         else
3062           m(pStubMsg, pMemory, desc);
3063       }
3064       else FIXME("no buffersizer for embedded type %02x\n", *desc);
3065       pMemory += size;
3066       pFormat += 2;
3067       continue;
3068     case RPC_FC_PAD:
3069       break;
3070     default:
3071       FIXME("unhandled format 0x%02x\n", *pFormat);
3072     }
3073     pFormat++;
3074   }
3075
3076   return pMemory;
3077 }
3078
3079 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
3080                                    unsigned char *pMemory,
3081                                    PFORMAT_STRING pFormat,
3082                                    PFORMAT_STRING pPointer)
3083 {
3084   PFORMAT_STRING desc;
3085   NDR_FREE m;
3086   ULONG size;
3087
3088   while (*pFormat != RPC_FC_END) {
3089     switch (*pFormat) {
3090     case RPC_FC_BYTE:
3091     case RPC_FC_CHAR:
3092     case RPC_FC_SMALL:
3093     case RPC_FC_USMALL:
3094       pMemory += 1;
3095       break;
3096     case RPC_FC_WCHAR:
3097     case RPC_FC_SHORT:
3098     case RPC_FC_USHORT:
3099       pMemory += 2;
3100       break;
3101     case RPC_FC_LONG:
3102     case RPC_FC_ULONG:
3103     case RPC_FC_ENUM16:
3104     case RPC_FC_ENUM32:
3105     case RPC_FC_FLOAT:
3106       pMemory += 4;
3107       break;
3108     case RPC_FC_HYPER:
3109     case RPC_FC_DOUBLE:
3110       pMemory += 8;
3111       break;
3112     case RPC_FC_RP:
3113     case RPC_FC_UP:
3114     case RPC_FC_OP:
3115     case RPC_FC_FP:
3116     case RPC_FC_POINTER:
3117       if (*pFormat != RPC_FC_POINTER)
3118         pPointer = pFormat;
3119       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3120       if (*pFormat == RPC_FC_POINTER)
3121         pPointer += 4;
3122       else
3123         pFormat += 4;
3124       pMemory += sizeof(void *);
3125       break;
3126     case RPC_FC_ALIGNM2:
3127       ALIGN_POINTER(pMemory, 2);
3128       break;
3129     case RPC_FC_ALIGNM4:
3130       ALIGN_POINTER(pMemory, 4);
3131       break;
3132     case RPC_FC_ALIGNM8:
3133       ALIGN_POINTER(pMemory, 8);
3134       break;
3135     case RPC_FC_STRUCTPAD1:
3136     case RPC_FC_STRUCTPAD2:
3137     case RPC_FC_STRUCTPAD3:
3138     case RPC_FC_STRUCTPAD4:
3139     case RPC_FC_STRUCTPAD5:
3140     case RPC_FC_STRUCTPAD6:
3141     case RPC_FC_STRUCTPAD7:
3142       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3143       break;
3144     case RPC_FC_EMBEDDED_COMPLEX:
3145       pMemory += pFormat[1];
3146       pFormat += 2;
3147       desc = pFormat + *(const SHORT*)pFormat;
3148       size = EmbeddedComplexSize(pStubMsg, desc);
3149       m = NdrFreer[*desc & NDR_TABLE_MASK];
3150       if (m)
3151       {
3152         /* for some reason interface pointers aren't generated as
3153          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3154          * they still need the derefencing treatment that pointers are
3155          * given */
3156         if (*desc == RPC_FC_IP)
3157           m(pStubMsg, *(unsigned char **)pMemory, desc);
3158         else
3159           m(pStubMsg, pMemory, desc);
3160       }
3161       pMemory += size;
3162       pFormat += 2;
3163       continue;
3164     case RPC_FC_PAD:
3165       break;
3166     default:
3167       FIXME("unhandled format 0x%02x\n", *pFormat);
3168     }
3169     pFormat++;
3170   }
3171
3172   return pMemory;
3173 }
3174
3175 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3176                                      PFORMAT_STRING pFormat,
3177                                      PFORMAT_STRING pPointer)
3178 {
3179   PFORMAT_STRING desc;
3180   ULONG size = 0;
3181
3182   while (*pFormat != RPC_FC_END) {
3183     switch (*pFormat) {
3184     case RPC_FC_BYTE:
3185     case RPC_FC_CHAR:
3186     case RPC_FC_SMALL:
3187     case RPC_FC_USMALL:
3188       size += 1;
3189       safe_buffer_increment(pStubMsg, 1);
3190       break;
3191     case RPC_FC_WCHAR:
3192     case RPC_FC_SHORT:
3193     case RPC_FC_USHORT:
3194       size += 2;
3195       safe_buffer_increment(pStubMsg, 2);
3196       break;
3197     case RPC_FC_ENUM16:
3198       size += 4;
3199       safe_buffer_increment(pStubMsg, 2);
3200       break;
3201     case RPC_FC_LONG:
3202     case RPC_FC_ULONG:
3203     case RPC_FC_ENUM32:
3204     case RPC_FC_FLOAT:
3205       size += 4;
3206       safe_buffer_increment(pStubMsg, 4);
3207       break;
3208     case RPC_FC_HYPER:
3209     case RPC_FC_DOUBLE:
3210       size += 8;
3211       safe_buffer_increment(pStubMsg, 8);
3212       break;
3213     case RPC_FC_RP:
3214     case RPC_FC_UP:
3215     case RPC_FC_OP:
3216     case RPC_FC_FP:
3217     case RPC_FC_POINTER:
3218     {
3219       unsigned char *saved_buffer;
3220       int pointer_buffer_mark_set = 0;
3221       if (*pFormat != RPC_FC_POINTER)
3222         pPointer = pFormat;
3223       if (*pPointer != RPC_FC_RP)
3224         ALIGN_POINTER(pStubMsg->Buffer, 4);
3225       saved_buffer = pStubMsg->Buffer;
3226       if (pStubMsg->PointerBufferMark)
3227       {
3228         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3229         pStubMsg->PointerBufferMark = NULL;
3230         pointer_buffer_mark_set = 1;
3231       }
3232       else if (*pPointer != RPC_FC_RP)
3233         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3234
3235       if (!pStubMsg->IgnoreEmbeddedPointers)
3236         PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3237       if (pointer_buffer_mark_set)
3238       {
3239         STD_OVERFLOW_CHECK(pStubMsg);
3240         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3241         pStubMsg->Buffer = saved_buffer;
3242         if (*pPointer != RPC_FC_RP)
3243           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3244       }
3245       if (*pFormat == RPC_FC_POINTER)
3246         pPointer += 4;
3247       else
3248         pFormat += 4;
3249       size += sizeof(void *);
3250       break;
3251     }
3252     case RPC_FC_ALIGNM2:
3253       ALIGN_LENGTH(size, 2);
3254       break;
3255     case RPC_FC_ALIGNM4:
3256       ALIGN_LENGTH(size, 4);
3257       break;
3258     case RPC_FC_ALIGNM8:
3259       ALIGN_LENGTH(size, 8);
3260       break;
3261     case RPC_FC_STRUCTPAD1:
3262     case RPC_FC_STRUCTPAD2:
3263     case RPC_FC_STRUCTPAD3:
3264     case RPC_FC_STRUCTPAD4:
3265     case RPC_FC_STRUCTPAD5:
3266     case RPC_FC_STRUCTPAD6:
3267     case RPC_FC_STRUCTPAD7:
3268       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3269       break;
3270     case RPC_FC_EMBEDDED_COMPLEX:
3271       size += pFormat[1];
3272       pFormat += 2;
3273       desc = pFormat + *(const SHORT*)pFormat;
3274       size += EmbeddedComplexMemorySize(pStubMsg, desc);
3275       pFormat += 2;
3276       continue;
3277     case RPC_FC_PAD:
3278       break;
3279     default:
3280       FIXME("unhandled format 0x%02x\n", *pFormat);
3281     }
3282     pFormat++;
3283   }
3284
3285   return size;
3286 }
3287
3288 ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
3289 {
3290   PFORMAT_STRING desc;
3291   ULONG size = 0;
3292
3293   while (*pFormat != RPC_FC_END) {
3294     switch (*pFormat) {
3295     case RPC_FC_BYTE:
3296     case RPC_FC_CHAR:
3297     case RPC_FC_SMALL:
3298     case RPC_FC_USMALL:
3299       size += 1;
3300       break;
3301     case RPC_FC_WCHAR:
3302     case RPC_FC_SHORT:
3303     case RPC_FC_USHORT:
3304       size += 2;
3305       break;
3306     case RPC_FC_LONG:
3307     case RPC_FC_ULONG:
3308     case RPC_FC_ENUM16:
3309     case RPC_FC_ENUM32:
3310     case RPC_FC_FLOAT:
3311       size += 4;
3312       break;
3313     case RPC_FC_HYPER:
3314     case RPC_FC_DOUBLE:
3315       size += 8;
3316       break;
3317     case RPC_FC_RP:
3318     case RPC_FC_UP:
3319     case RPC_FC_OP:
3320     case RPC_FC_FP:
3321     case RPC_FC_POINTER:
3322       size += sizeof(void *);
3323       if (*pFormat != RPC_FC_POINTER)
3324         pFormat += 4;
3325       break;
3326     case RPC_FC_ALIGNM2:
3327       ALIGN_LENGTH(size, 2);
3328       break;
3329     case RPC_FC_ALIGNM4:
3330       ALIGN_LENGTH(size, 4);
3331       break;
3332     case RPC_FC_ALIGNM8:
3333       ALIGN_LENGTH(size, 8);
3334       break;
3335     case RPC_FC_STRUCTPAD1:
3336     case RPC_FC_STRUCTPAD2:
3337     case RPC_FC_STRUCTPAD3:
3338     case RPC_FC_STRUCTPAD4:
3339     case RPC_FC_STRUCTPAD5:
3340     case RPC_FC_STRUCTPAD6:
3341     case RPC_FC_STRUCTPAD7:
3342       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3343       break;
3344     case RPC_FC_EMBEDDED_COMPLEX:
3345       size += pFormat[1];
3346       pFormat += 2;
3347       desc = pFormat + *(const SHORT*)pFormat;
3348       size += EmbeddedComplexSize(pStubMsg, desc);
3349       pFormat += 2;
3350       continue;
3351     case RPC_FC_PAD:
3352       break;
3353     default:
3354       FIXME("unhandled format 0x%02x\n", *pFormat);
3355     }
3356     pFormat++;
3357   }
3358
3359   return size;
3360 }
3361
3362 /***********************************************************************
3363  *           NdrComplexStructMarshall [RPCRT4.@]
3364  */
3365 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3366                                                 unsigned char *pMemory,
3367                                                 PFORMAT_STRING pFormat)
3368 {
3369   PFORMAT_STRING conf_array = NULL;
3370   PFORMAT_STRING pointer_desc = NULL;
3371   unsigned char *OldMemory = pStubMsg->Memory;
3372   int pointer_buffer_mark_set = 0;
3373   ULONG count = 0;
3374   ULONG max_count = 0;
3375   ULONG offset = 0;
3376
3377   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3378
3379   if (!pStubMsg->PointerBufferMark)
3380   {
3381     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3382     /* save buffer length */
3383     ULONG saved_buffer_length = pStubMsg->BufferLength;
3384
3385     /* get the buffer pointer after complex array data, but before
3386      * pointer data */
3387     pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3388     pStubMsg->IgnoreEmbeddedPointers = 1;
3389     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3390     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3391
3392     /* save it for use by embedded pointer code later */
3393     pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3394     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
3395     pointer_buffer_mark_set = 1;
3396
3397     /* restore the original buffer length */
3398     pStubMsg->BufferLength = saved_buffer_length;
3399   }
3400
3401   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
3402
3403   pFormat += 4;
3404   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3405   pFormat += 2;
3406   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3407   pFormat += 2;
3408
3409   pStubMsg->Memory = pMemory;
3410
3411   if (conf_array)
3412   {
3413     ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3414     array_compute_and_write_conformance(conf_array[0], pStubMsg,
3415                                         pMemory + struct_size, conf_array);
3416     /* these could be changed in ComplexMarshall so save them for later */
3417     max_count = pStubMsg->MaxCount;
3418     count = pStubMsg->ActualCount;
3419     offset = pStubMsg->Offset;
3420   }
3421
3422   pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3423
3424   if (conf_array)
3425   {
3426     pStubMsg->MaxCount = max_count;
3427     pStubMsg->ActualCount = count;
3428     pStubMsg->Offset = offset;
3429     array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3430                                       conf_array, TRUE /* fHasPointers */);
3431   }
3432
3433   pStubMsg->Memory = OldMemory;
3434
3435   if (pointer_buffer_mark_set)
3436   {
3437     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3438     pStubMsg->PointerBufferMark = NULL;
3439   }
3440
3441   STD_OVERFLOW_CHECK(pStubMsg);
3442
3443   return NULL;
3444 }
3445
3446 /***********************************************************************
3447  *           NdrComplexStructUnmarshall [RPCRT4.@]
3448  */
3449 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3450                                                   unsigned char **ppMemory,
3451                                                   PFORMAT_STRING pFormat,
3452                                                   unsigned char fMustAlloc)
3453 {
3454   unsigned size = *(const WORD*)(pFormat+2);
3455   PFORMAT_STRING conf_array = NULL;
3456   PFORMAT_STRING pointer_desc = NULL;
3457   unsigned char *pMemory;
3458   int pointer_buffer_mark_set = 0;
3459   ULONG count = 0;
3460   ULONG max_count = 0;
3461   ULONG offset = 0;
3462   ULONG array_size = 0;
3463
3464   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3465
3466   if (!pStubMsg->PointerBufferMark)
3467   {
3468     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3469     /* save buffer pointer */
3470     unsigned char *saved_buffer = pStubMsg->Buffer;
3471
3472     /* get the buffer pointer after complex array data, but before
3473      * pointer data */
3474     pStubMsg->IgnoreEmbeddedPointers = 1;
3475     NdrComplexStructMemorySize(pStubMsg, pFormat);
3476     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3477
3478     /* save it for use by embedded pointer code later */
3479     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3480     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
3481     pointer_buffer_mark_set = 1;
3482
3483     /* restore the original buffer */
3484     pStubMsg->Buffer = saved_buffer;
3485   }
3486
3487   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3488
3489   pFormat += 4;
3490   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3491   pFormat += 2;
3492   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3493   pFormat += 2;
3494
3495   if (conf_array)
3496   {
3497     array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3498     size += array_size;
3499
3500     /* these could be changed in ComplexMarshall so save them for later */
3501     max_count = pStubMsg->MaxCount;
3502     count = pStubMsg->ActualCount;
3503     offset = pStubMsg->Offset;
3504   }
3505
3506   if (!fMustAlloc && !*ppMemory)
3507     fMustAlloc = TRUE;
3508   if (fMustAlloc)
3509     *ppMemory = NdrAllocate(pStubMsg, size);
3510
3511   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3512
3513   if (conf_array)
3514   {
3515     pStubMsg->MaxCount = max_count;
3516     pStubMsg->ActualCount = count;
3517     pStubMsg->Offset = offset;
3518     if (fMustAlloc)
3519       memset(pMemory, 0, array_size);
3520     array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3521                                        conf_array, FALSE,
3522                                        FALSE /* fUseBufferMemoryServer */,
3523                                        TRUE /* fUnmarshall */);
3524   }
3525
3526   if (pointer_buffer_mark_set)
3527   {
3528     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3529     pStubMsg->PointerBufferMark = NULL;
3530   }
3531
3532   return NULL;
3533 }
3534
3535 /***********************************************************************
3536  *           NdrComplexStructBufferSize [RPCRT4.@]
3537  */
3538 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3539                                        unsigned char *pMemory,
3540                                        PFORMAT_STRING pFormat)
3541 {
3542   PFORMAT_STRING conf_array = NULL;
3543   PFORMAT_STRING pointer_desc = NULL;
3544   unsigned char *OldMemory = pStubMsg->Memory;
3545   int pointer_length_set = 0;
3546   ULONG count = 0;
3547   ULONG max_count = 0;
3548   ULONG offset = 0;
3549
3550   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3551
3552   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
3553
3554   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3555   {
3556     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3557     ULONG saved_buffer_length = pStubMsg->BufferLength;
3558
3559     /* get the buffer length after complex struct data, but before
3560      * pointer data */
3561     pStubMsg->IgnoreEmbeddedPointers = 1;
3562     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3563     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3564
3565     /* save it for use by embedded pointer code later */
3566     pStubMsg->PointerLength = pStubMsg->BufferLength;
3567     pointer_length_set = 1;
3568     TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
3569
3570     /* restore the original buffer length */
3571     pStubMsg->BufferLength = saved_buffer_length;
3572   }
3573
3574   pFormat += 4;
3575   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3576   pFormat += 2;
3577   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3578   pFormat += 2;
3579
3580   pStubMsg->Memory = pMemory;
3581
3582   if (conf_array)
3583   {
3584     ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3585     array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3586                                        conf_array);
3587
3588     /* these could be changed in ComplexMarshall so save them for later */
3589     max_count = pStubMsg->MaxCount;
3590     count = pStubMsg->ActualCount;
3591     offset = pStubMsg->Offset;
3592   }
3593
3594   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3595
3596   if (conf_array)
3597   {
3598     pStubMsg->MaxCount = max_count;
3599     pStubMsg->ActualCount = count;
3600     pStubMsg->Offset = offset;
3601     array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3602                       TRUE /* fHasPointers */);
3603   }
3604
3605   pStubMsg->Memory = OldMemory;
3606
3607   if(pointer_length_set)
3608   {
3609     pStubMsg->BufferLength = pStubMsg->PointerLength;
3610     pStubMsg->PointerLength = 0;
3611   }
3612
3613 }
3614
3615 /***********************************************************************
3616  *           NdrComplexStructMemorySize [RPCRT4.@]
3617  */
3618 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3619                                         PFORMAT_STRING pFormat)
3620 {
3621   unsigned size = *(const WORD*)(pFormat+2);
3622   PFORMAT_STRING conf_array = NULL;
3623   PFORMAT_STRING pointer_desc = NULL;
3624   ULONG count = 0;
3625   ULONG max_count = 0;
3626   ULONG offset = 0;
3627
3628   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3629
3630   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3631
3632   pFormat += 4;
3633   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3634   pFormat += 2;
3635   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3636   pFormat += 2;
3637
3638   if (conf_array)
3639   {
3640     array_read_conformance(conf_array[0], pStubMsg, conf_array);
3641
3642     /* these could be changed in ComplexStructMemorySize so save them for
3643      * later */
3644     max_count = pStubMsg->MaxCount;
3645     count = pStubMsg->ActualCount;
3646     offset = pStubMsg->Offset;
3647   }
3648
3649   ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3650
3651   if (conf_array)
3652   {
3653     pStubMsg->MaxCount = max_count;
3654     pStubMsg->ActualCount = count;
3655     pStubMsg->Offset = offset;
3656     array_memory_size(conf_array[0], pStubMsg, conf_array,
3657                       TRUE /* fHasPointers */);
3658   }
3659
3660   return size;
3661 }
3662
3663 /***********************************************************************
3664  *           NdrComplexStructFree [RPCRT4.@]
3665  */
3666 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3667                                  unsigned char *pMemory,
3668                                  PFORMAT_STRING pFormat)
3669 {
3670   PFORMAT_STRING conf_array = NULL;
3671   PFORMAT_STRING pointer_desc = NULL;
3672   unsigned char *OldMemory = pStubMsg->Memory;
3673
3674   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3675
3676   pFormat += 4;
3677   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3678   pFormat += 2;
3679   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3680   pFormat += 2;
3681
3682   pStubMsg->Memory = pMemory;
3683
3684   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3685
3686   if (conf_array)
3687     array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3688                TRUE /* fHasPointers */);
3689
3690   pStubMsg->Memory = OldMemory;
3691 }
3692
3693 /***********************************************************************
3694  *           NdrConformantArrayMarshall [RPCRT4.@]
3695  */
3696 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3697                                                   unsigned char *pMemory,
3698                                                   PFORMAT_STRING pFormat)
3699 {
3700   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3701   if (pFormat[0] != RPC_FC_CARRAY)
3702   {
3703     ERR("invalid format = 0x%x\n", pFormat[0]);
3704     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3705   }
3706
3707   array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
3708                                       pFormat);
3709   array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3710                                     TRUE /* fHasPointers */);
3711
3712   return NULL;
3713 }
3714
3715 /***********************************************************************
3716  *           NdrConformantArrayUnmarshall [RPCRT4.@]
3717  */
3718 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3719                                                     unsigned char **ppMemory,
3720                                                     PFORMAT_STRING pFormat,
3721                                                     unsigned char fMustAlloc)
3722 {
3723   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3724   if (pFormat[0] != RPC_FC_CARRAY)
3725   {
3726     ERR("invalid format = 0x%x\n", pFormat[0]);
3727     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3728   }
3729
3730   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3731   array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
3732                                      fMustAlloc,
3733                                      TRUE /* fUseBufferMemoryServer */,
3734                                      TRUE /* fUnmarshall */);
3735
3736   return NULL;
3737 }
3738
3739 /***********************************************************************
3740  *           NdrConformantArrayBufferSize [RPCRT4.@]
3741  */
3742 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3743                                          unsigned char *pMemory,
3744                                          PFORMAT_STRING pFormat)
3745 {
3746   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3747   if (pFormat[0] != RPC_FC_CARRAY)
3748   {
3749     ERR("invalid format = 0x%x\n", pFormat[0]);
3750     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3751   }
3752
3753   array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat);
3754   array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3755                     TRUE /* fHasPointers */);
3756 }
3757
3758 /***********************************************************************
3759  *           NdrConformantArrayMemorySize [RPCRT4.@]
3760  */
3761 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3762                                           PFORMAT_STRING pFormat)
3763 {
3764   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3765   if (pFormat[0] != RPC_FC_CARRAY)
3766   {
3767     ERR("invalid format = 0x%x\n", pFormat[0]);
3768     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3769   }
3770
3771   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3772   array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
3773
3774   return pStubMsg->MemorySize;
3775 }
3776
3777 /***********************************************************************
3778  *           NdrConformantArrayFree [RPCRT4.@]
3779  */
3780 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3781                                    unsigned char *pMemory,
3782                                    PFORMAT_STRING pFormat)
3783 {
3784   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3785   if (pFormat[0] != RPC_FC_CARRAY)
3786   {
3787     ERR("invalid format = 0x%x\n", pFormat[0]);
3788     RpcRaiseException(RPC_X_BAD_STUB_DATA);
3789   }
3790
3791   array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3792              TRUE /* fHasPointers */);
3793 }
3794
3795
3796 /***********************************************************************
3797  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
3798  */
3799 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
3800                                                          unsigned char* pMemory,
3801                                                          PFORMAT_STRING pFormat )
3802 {
3803     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3804
3805     if (pFormat[0] != RPC_FC_CVARRAY)
3806     {
3807         ERR("invalid format type %x\n", pFormat[0]);
3808         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3809         return NULL;
3810     }
3811
3812     array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3813                                         pFormat);
3814     array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory,
3815                                       pFormat, TRUE /* fHasPointers */);
3816
3817     return NULL;
3818 }
3819
3820
3821 /***********************************************************************
3822  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
3823  */
3824 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
3825                                                            unsigned char** ppMemory,
3826                                                            PFORMAT_STRING pFormat,
3827                                                            unsigned char fMustAlloc )
3828 {
3829     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3830
3831     if (pFormat[0] != RPC_FC_CVARRAY)
3832     {
3833         ERR("invalid format type %x\n", pFormat[0]);
3834         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3835         return NULL;
3836     }
3837
3838     array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3839     array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory,
3840                                        pFormat, fMustAlloc,
3841                                        TRUE /* fUseBufferMemoryServer */,
3842                                        TRUE /* fUnmarshall */);
3843
3844     return NULL;
3845 }
3846
3847
3848 /***********************************************************************
3849  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
3850  */
3851 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
3852                                            unsigned char* pMemory,
3853                                            PFORMAT_STRING pFormat )
3854 {
3855     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3856
3857     if (pFormat[0] != RPC_FC_CVARRAY)
3858     {
3859         ERR("invalid format type %x\n", pFormat[0]);
3860         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3861         return;
3862     }
3863
3864     array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3865                TRUE /* fHasPointers */);
3866 }
3867
3868
3869 /***********************************************************************
3870  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
3871  */
3872 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
3873                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
3874 {
3875     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3876
3877     if (pFormat[0] != RPC_FC_CVARRAY)
3878     {
3879         ERR("invalid format type %x\n", pFormat[0]);
3880         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3881         return;
3882     }
3883
3884     array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3885                                        pFormat);
3886     array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3887                       TRUE /* fHasPointers */);
3888 }
3889
3890
3891 /***********************************************************************
3892  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
3893  */
3894 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
3895                                                   PFORMAT_STRING pFormat )
3896 {
3897     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3898
3899     if (pFormat[0] != RPC_FC_CVARRAY)
3900     {
3901         ERR("invalid format type %x\n", pFormat[0]);
3902         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3903         return pStubMsg->MemorySize;
3904     }
3905
3906     array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3907     array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat,
3908                       TRUE /* fHasPointers */);
3909
3910     return pStubMsg->MemorySize;
3911 }
3912
3913
3914 /***********************************************************************
3915  *           NdrComplexArrayMarshall [RPCRT4.@]
3916  */
3917 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3918                                                unsigned char *pMemory,
3919                                                PFORMAT_STRING pFormat)
3920 {
3921   ULONG i, count, def;
3922   BOOL variance_present;
3923   unsigned char alignment;
3924   int pointer_buffer_mark_set = 0;
3925
3926   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3927
3928   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3929   {
3930       ERR("invalid format type %x\n", pFormat[0]);
3931       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3932       return NULL;
3933   }
3934
3935   alignment = pFormat[1] + 1;
3936
3937   if (!pStubMsg->PointerBufferMark)
3938   {
3939     /* save buffer fields that may be changed by buffer sizer functions
3940      * and that may be needed later on */
3941     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3942     ULONG saved_buffer_length = pStubMsg->BufferLength;
3943     ULONG_PTR saved_max_count = pStubMsg->MaxCount;
3944     ULONG saved_offset = pStubMsg->Offset;
3945     ULONG saved_actual_count = pStubMsg->ActualCount;
3946
3947     /* get the buffer pointer after complex array data, but before
3948      * pointer data */
3949     pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3950     pStubMsg->IgnoreEmbeddedPointers = 1;
3951     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3952     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3953
3954     /* save it for use by embedded pointer code later */
3955     pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3956     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
3957     pointer_buffer_mark_set = 1;
3958
3959     /* restore fields */
3960     pStubMsg->ActualCount = saved_actual_count;
3961     pStubMsg->Offset = saved_offset;
3962     pStubMsg->MaxCount = saved_max_count;
3963     pStubMsg->BufferLength = saved_buffer_length;
3964   }
3965
3966   def = *(const WORD*)&pFormat[2];
3967   pFormat += 4;
3968
3969   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3970   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3971
3972   variance_present = IsConformanceOrVariancePresent(pFormat);
3973   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3974   TRACE("variance = %d\n", pStubMsg->ActualCount);
3975
3976   WriteConformance(pStubMsg);
3977   if (variance_present)
3978     WriteVariance(pStubMsg);
3979
3980   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3981
3982   count = pStubMsg->ActualCount;
3983   for (i = 0; i < count; i++)
3984     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3985
3986   STD_OVERFLOW_CHECK(pStubMsg);
3987
3988   if (pointer_buffer_mark_set)
3989   {
3990     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3991     pStubMsg->PointerBufferMark = NULL;
3992   }
3993
3994   return NULL;
3995 }
3996
3997 /***********************************************************************
3998  *           NdrComplexArrayUnmarshall [RPCRT4.@]
3999  */
4000 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4001                                                  unsigned char **ppMemory,
4002                                                  PFORMAT_STRING pFormat,
4003                                                  unsigned char fMustAlloc)
4004 {
4005   ULONG i, count, size;
4006   unsigned char alignment;
4007   unsigned char *pMemory;
4008   unsigned char *saved_buffer;
4009   int pointer_buffer_mark_set = 0;
4010   int saved_ignore_embedded;
4011
4012   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4013
4014   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4015   {
4016       ERR("invalid format type %x\n", pFormat[0]);
4017       RpcRaiseException(RPC_S_INTERNAL_ERROR);
4018       return NULL;
4019   }
4020
4021   alignment = pFormat[1] + 1;
4022
4023   saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4024   /* save buffer pointer */
4025   saved_buffer = pStubMsg->Buffer;
4026   /* get the buffer pointer after complex array data, but before
4027    * pointer data */
4028   pStubMsg->IgnoreEmbeddedPointers = 1;
4029   pStubMsg->MemorySize = 0;
4030   NdrComplexArrayMemorySize(pStubMsg, pFormat);
4031   size = pStubMsg->MemorySize;
4032   pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4033
4034   TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer));
4035   if (!pStubMsg->PointerBufferMark)
4036   {
4037     /* save it for use by embedded pointer code later */
4038     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4039     pointer_buffer_mark_set = 1;
4040   }
4041   /* restore the original buffer */
4042   pStubMsg->Buffer = saved_buffer;
4043
4044   pFormat += 4;
4045
4046   pFormat = ReadConformance(pStubMsg, pFormat);
4047   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
4048
4049   if (!fMustAlloc && !*ppMemory)
4050     fMustAlloc = TRUE;
4051   if (fMustAlloc)
4052     *ppMemory = NdrAllocate(pStubMsg, size);
4053
4054   ALIGN_POINTER(pStubMsg->Buffer, alignment);
4055
4056   pMemory = *ppMemory;
4057   count = pStubMsg->ActualCount;
4058   for (i = 0; i < count; i++)
4059     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
4060
4061   if (pointer_buffer_mark_set)
4062   {
4063     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4064     pStubMsg->PointerBufferMark = NULL;
4065   }
4066
4067   return NULL;
4068 }
4069
4070 /***********************************************************************
4071  *           NdrComplexArrayBufferSize [RPCRT4.@]
4072  */
4073 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4074                                       unsigned char *pMemory,
4075                                       PFORMAT_STRING pFormat)
4076 {
4077   ULONG i, count, def;
4078   unsigned char alignment;
4079   BOOL variance_present;
4080   int pointer_length_set = 0;
4081
4082   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4083
4084   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4085   {
4086       ERR("invalid format type %x\n", pFormat[0]);
4087       RpcRaiseException(RPC_S_INTERNAL_ERROR);
4088       return;
4089   }
4090
4091   alignment = pFormat[1] + 1;
4092
4093   if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
4094   {
4095     /* save buffer fields that may be changed by buffer sizer functions
4096      * and that may be needed later on */
4097     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4098     ULONG saved_buffer_length = pStubMsg->BufferLength;
4099     ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4100     ULONG saved_offset = pStubMsg->Offset;
4101     ULONG saved_actual_count = pStubMsg->ActualCount;
4102
4103     /* get the buffer pointer after complex array data, but before
4104      * pointer data */
4105     pStubMsg->IgnoreEmbeddedPointers = 1;
4106     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4107     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4108
4109     /* save it for use by embedded pointer code later */
4110     pStubMsg->PointerLength = pStubMsg->BufferLength;
4111     pointer_length_set = 1;
4112
4113     /* restore fields */
4114     pStubMsg->ActualCount = saved_actual_count;
4115     pStubMsg->Offset = saved_offset;
4116     pStubMsg->MaxCount = saved_max_count;
4117     pStubMsg->BufferLength = saved_buffer_length;
4118   }
4119   def = *(const WORD*)&pFormat[2];
4120   pFormat += 4;
4121
4122   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4123   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4124   SizeConformance(pStubMsg);
4125
4126   variance_present = IsConformanceOrVariancePresent(pFormat);
4127   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4128   TRACE("variance = %d\n", pStubMsg->ActualCount);
4129
4130   if (variance_present)
4131     SizeVariance(pStubMsg);
4132
4133   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4134
4135   count = pStubMsg->ActualCount;
4136   for (i = 0; i < count; i++)
4137     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
4138
4139   if(pointer_length_set)
4140   {
4141     pStubMsg->BufferLength = pStubMsg->PointerLength;
4142     pStubMsg->PointerLength = 0;
4143   }
4144 }
4145
4146 /***********************************************************************
4147  *           NdrComplexArrayMemorySize [RPCRT4.@]
4148  */
4149 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4150                                        PFORMAT_STRING pFormat)
4151 {
4152   ULONG i, count, esize, SavedMemorySize, MemorySize;
4153   unsigned char alignment;
4154
4155   TRACE("(%p,%p)\n", pStubMsg, pFormat);
4156
4157   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4158   {
4159       ERR("invalid format type %x\n", pFormat[0]);
4160       RpcRaiseException(RPC_S_INTERNAL_ERROR);
4161       return 0;
4162   }
4163
4164   alignment = pFormat[1] + 1;
4165
4166   pFormat += 4;
4167
4168   pFormat = ReadConformance(pStubMsg, pFormat);
4169   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
4170
4171   ALIGN_POINTER(pStubMsg->Buffer, alignment);
4172
4173   SavedMemorySize = pStubMsg->MemorySize;
4174
4175   esize = ComplexStructSize(pStubMsg, pFormat);
4176
4177   MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
4178
4179   count = pStubMsg->ActualCount;
4180   for (i = 0; i < count; i++)
4181     ComplexStructMemorySize(pStubMsg, pFormat, NULL);
4182
4183   pStubMsg->MemorySize = SavedMemorySize;
4184
4185   pStubMsg->MemorySize += MemorySize;
4186   return MemorySize;
4187 }
4188
4189 /***********************************************************************
4190  *           NdrComplexArrayFree [RPCRT4.@]
4191  */
4192 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4193                                 unsigned char *pMemory,
4194                                 PFORMAT_STRING pFormat)
4195 {
4196   ULONG i, count, def;
4197
4198   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4199
4200   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4201   {
4202       ERR("invalid format type %x\n", pFormat[0]);
4203       RpcRaiseException(RPC_S_INTERNAL_ERROR);
4204       return;
4205   }
4206
4207   def = *(const WORD*)&pFormat[2];
4208   pFormat += 4;
4209
4210   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4211   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4212
4213   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4214   TRACE("variance = %d\n", pStubMsg->ActualCount);
4215
4216   count = pStubMsg->ActualCount;
4217   for (i = 0; i < count; i++)
4218     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
4219 }
4220
4221 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
4222                           USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
4223                           USER_MARSHAL_CB *umcb)
4224 {
4225   umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
4226                          pStubMsg->RpcMsg->DataRepresentation);
4227   umcb->pStubMsg = pStubMsg;
4228   umcb->pReserve = NULL;
4229   umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
4230   umcb->CBType = cbtype;
4231   umcb->pFormat = pFormat;
4232   umcb->pTypeFormat = NULL /* FIXME */;
4233 }
4234
4235 #define USER_MARSHAL_PTR_PREFIX \
4236         ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
4237         ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
4238
4239 /***********************************************************************
4240  *           NdrUserMarshalMarshall [RPCRT4.@]
4241  */
4242 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4243                                               unsigned char *pMemory,
4244                                               PFORMAT_STRING pFormat)
4245 {
4246   unsigned flags = pFormat[1];
4247   unsigned index = *(const WORD*)&pFormat[2];
4248   unsigned char *saved_buffer = NULL;
4249   USER_MARSHAL_CB umcb;
4250
4251   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4252   TRACE("index=%d\n", index);
4253
4254   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
4255
4256   if (flags & USER_MARSHAL_POINTER)
4257   {
4258     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
4259     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
4260     pStubMsg->Buffer += 4;
4261     if (pStubMsg->PointerBufferMark)
4262     {
4263       saved_buffer = pStubMsg->Buffer;
4264       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4265       pStubMsg->PointerBufferMark = NULL;
4266     }
4267     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8);
4268   }
4269   else
4270     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1);
4271
4272   pStubMsg->Buffer =
4273     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
4274       &umcb.Flags, pStubMsg->Buffer, pMemory);
4275
4276   if (saved_buffer)
4277   {
4278     STD_OVERFLOW_CHECK(pStubMsg);
4279     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4280     pStubMsg->Buffer = saved_buffer;
4281   }
4282
4283   STD_OVERFLOW_CHECK(pStubMsg);
4284
4285   return NULL;
4286 }
4287
4288 /***********************************************************************
4289  *           NdrUserMarshalUnmarshall [RPCRT4.@]
4290  */
4291 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4292                                                  unsigned char **ppMemory,
4293                                                  PFORMAT_STRING pFormat,
4294                                                  unsigned char fMustAlloc)
4295 {
4296   unsigned flags = pFormat[1];
4297   unsigned index = *(const WORD*)&pFormat[2];
4298   DWORD memsize = *(const WORD*)&pFormat[4];
4299   unsigned char *saved_buffer = NULL;
4300   USER_MARSHAL_CB umcb;
4301
4302   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4303   TRACE("index=%d\n", index);
4304
4305   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
4306
4307   if (flags & USER_MARSHAL_POINTER)
4308   {
4309     ALIGN_POINTER(pStubMsg->Buffer, 4);
4310     /* skip pointer prefix */
4311     pStubMsg->Buffer += 4;
4312     if (pStubMsg->PointerBufferMark)
4313     {
4314       saved_buffer = pStubMsg->Buffer;
4315       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4316       pStubMsg->PointerBufferMark = NULL;
4317     }
4318     ALIGN_POINTER(pStubMsg->Buffer, 8);
4319   }
4320   else
4321     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4322
4323   if (!fMustAlloc && !*ppMemory)
4324     fMustAlloc = TRUE;
4325   if (fMustAlloc)
4326   {
4327     *ppMemory = NdrAllocate(pStubMsg, memsize);
4328     memset(*ppMemory, 0, memsize);
4329   }
4330
4331   pStubMsg->Buffer =
4332     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
4333       &umcb.Flags, pStubMsg->Buffer, *ppMemory);
4334
4335   if (saved_buffer)
4336   {
4337     STD_OVERFLOW_CHECK(pStubMsg);
4338     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4339     pStubMsg->Buffer = saved_buffer;
4340   }
4341
4342   return NULL;
4343 }
4344
4345 /***********************************************************************
4346  *           NdrUserMarshalBufferSize [RPCRT4.@]
4347  */
4348 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4349                                       unsigned char *pMemory,
4350                                       PFORMAT_STRING pFormat)
4351 {
4352   unsigned flags = pFormat[1];
4353   unsigned index = *(const WORD*)&pFormat[2];
4354   DWORD bufsize = *(const WORD*)&pFormat[6];
4355   USER_MARSHAL_CB umcb;
4356   ULONG saved_buffer_length = 0;
4357
4358   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4359   TRACE("index=%d\n", index);
4360
4361   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
4362
4363   if (flags & USER_MARSHAL_POINTER)
4364   {
4365     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4366     /* skip pointer prefix */
4367     safe_buffer_length_increment(pStubMsg, 4);
4368     if (pStubMsg->IgnoreEmbeddedPointers)
4369       return;
4370     if (pStubMsg->PointerLength)
4371     {
4372       saved_buffer_length = pStubMsg->BufferLength;
4373       pStubMsg->BufferLength = pStubMsg->PointerLength;
4374       pStubMsg->PointerLength = 0;
4375     }
4376     ALIGN_LENGTH(pStubMsg->BufferLength, 8);
4377   }
4378   else
4379     ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
4380
4381   if (bufsize) {
4382     TRACE("size=%d\n", bufsize);
4383     safe_buffer_length_increment(pStubMsg, bufsize);
4384   }
4385   else
4386     pStubMsg->BufferLength =
4387         pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
4388                              &umcb.Flags, pStubMsg->BufferLength, pMemory);
4389
4390   if (saved_buffer_length)
4391   {
4392     pStubMsg->PointerLength = pStubMsg->BufferLength;
4393     pStubMsg->BufferLength = saved_buffer_length;
4394   }
4395
4396 }
4397
4398 /***********************************************************************
4399  *           NdrUserMarshalMemorySize [RPCRT4.@]
4400  */
4401 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4402                                       PFORMAT_STRING pFormat)
4403 {
4404   unsigned flags = pFormat[1];
4405   unsigned index = *(const WORD*)&pFormat[2];
4406   DWORD memsize = *(const WORD*)&pFormat[4];
4407   DWORD bufsize = *(const WORD*)&pFormat[6];
4408
4409   TRACE("(%p,%p)\n", pStubMsg, pFormat);
4410   TRACE("index=%d\n", index);
4411
4412   pStubMsg->MemorySize += memsize;
4413
4414   if (flags & USER_MARSHAL_POINTER)
4415   {
4416     ALIGN_POINTER(pStubMsg->Buffer, 4);
4417     /* skip pointer prefix */
4418     pStubMsg->Buffer += 4;
4419     if (pStubMsg->IgnoreEmbeddedPointers)
4420       return pStubMsg->MemorySize;
4421     ALIGN_POINTER(pStubMsg->Buffer, 8);
4422   }
4423   else
4424     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4425
4426   if (!bufsize)
4427     FIXME("not implemented for varying buffer size\n");
4428
4429   pStubMsg->Buffer += bufsize;
4430
4431   return pStubMsg->MemorySize;
4432 }
4433
4434 /***********************************************************************
4435  *           NdrUserMarshalFree [RPCRT4.@]
4436  */
4437 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
4438                                 unsigned char *pMemory,
4439                                 PFORMAT_STRING pFormat)
4440 {
4441 /*  unsigned flags = pFormat[1]; */
4442   unsigned index = *(const WORD*)&pFormat[2];
4443   USER_MARSHAL_CB umcb;
4444
4445   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4446   TRACE("index=%d\n", index);
4447
4448   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
4449
4450   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
4451     &umcb.Flags, pMemory);
4452 }
4453
4454 /***********************************************************************
4455  *           NdrGetUserMarshalInfo [RPCRT4.@]
4456  */
4457 RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi)
4458 {
4459     USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags);
4460
4461     TRACE("(%p,%u,%p)\n", flags, level, umi);
4462
4463     if (level != 1)
4464         return RPC_S_INVALID_ARG;
4465
4466     memset(&umi->u1.Level1, 0, sizeof(umi->u1.Level1));
4467     umi->InformationLevel = level;
4468
4469     if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE)
4470         return RPC_S_INVALID_ARG;
4471
4472     umi->u1.Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate;
4473     umi->u1.Level1.pfnFree = umcb->pStubMsg->pfnFree;
4474     umi->u1.Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer;
4475
4476     switch (umcb->CBType)
4477     {
4478     case USER_MARSHAL_CB_MARSHALL:
4479     case USER_MARSHAL_CB_UNMARSHALL:
4480     {
4481         RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg;
4482         unsigned char *buffer_start = msg->Buffer;
4483         unsigned char *buffer_end =
4484             (unsigned char *)msg->Buffer + msg->BufferLength;
4485
4486         if (umcb->pStubMsg->Buffer < buffer_start ||
4487             umcb->pStubMsg->Buffer > buffer_end)
4488             return ERROR_INVALID_USER_BUFFER;
4489
4490         umi->u1.Level1.Buffer = umcb->pStubMsg->Buffer;
4491         umi->u1.Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer;
4492         break;
4493     }
4494     case USER_MARSHAL_CB_BUFFER_SIZE:
4495     case USER_MARSHAL_CB_FREE:
4496         break;
4497     default:
4498         WARN("unrecognised CBType %d\n", umcb->CBType);
4499     }
4500
4501     return RPC_S_OK;
4502 }
4503
4504 /***********************************************************************
4505  *           NdrClearOutParameters [RPCRT4.@]
4506  */
4507 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
4508                                   PFORMAT_STRING pFormat,
4509                                   void *ArgAddr)
4510 {
4511   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
4512 }
4513
4514 /***********************************************************************
4515  *           NdrConvert [RPCRT4.@]
4516  */
4517 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
4518 {
4519   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
4520   /* FIXME: since this stub doesn't do any converting, the proper behavior
4521      is to raise an exception */
4522 }
4523
4524 /***********************************************************************
4525  *           NdrConvert2 [RPCRT4.@]
4526  */
4527 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
4528 {
4529   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
4530     pStubMsg, pFormat, NumberParams);
4531   /* FIXME: since this stub doesn't do any converting, the proper behavior
4532      is to raise an exception */
4533 }
4534
4535 #include "pshpack1.h"
4536 typedef struct _NDR_CSTRUCT_FORMAT
4537 {
4538     unsigned char type;
4539     unsigned char alignment;
4540     unsigned short memory_size;
4541     short offset_to_array_description;
4542 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
4543 #include "poppack.h"
4544
4545 /***********************************************************************
4546  *           NdrConformantStructMarshall [RPCRT4.@]
4547  */
4548 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4549                                 unsigned char *pMemory,
4550                                 PFORMAT_STRING pFormat)
4551 {
4552     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4553     PFORMAT_STRING pCArrayFormat;
4554     ULONG esize, bufsize;
4555
4556     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4557
4558     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4559     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4560     {
4561         ERR("invalid format type %x\n", pCStructFormat->type);
4562         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4563         return NULL;
4564     }
4565
4566     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4567         pCStructFormat->offset_to_array_description;
4568     if (*pCArrayFormat != RPC_FC_CARRAY)
4569     {
4570         ERR("invalid array format type %x\n", pCStructFormat->type);
4571         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4572         return NULL;
4573     }
4574     esize = *(const WORD*)(pCArrayFormat+2);
4575
4576     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4577                        pCArrayFormat + 4, 0);
4578
4579     WriteConformance(pStubMsg);
4580
4581     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4582
4583     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4584
4585     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4586     if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4587     {
4588         ERR("integer overflow of memory_size %u with bufsize %u\n",
4589             pCStructFormat->memory_size, bufsize);
4590         RpcRaiseException(RPC_X_BAD_STUB_DATA);
4591     }
4592     /* copy constant sized part of struct */
4593     pStubMsg->BufferMark = pStubMsg->Buffer;
4594     safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
4595
4596     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4597         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4598
4599     return NULL;
4600 }
4601
4602 /***********************************************************************
4603  *           NdrConformantStructUnmarshall [RPCRT4.@]
4604  */
4605 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4606                                 unsigned char **ppMemory,
4607                                 PFORMAT_STRING pFormat,
4608                                 unsigned char fMustAlloc)
4609 {
4610     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4611     PFORMAT_STRING pCArrayFormat;
4612     ULONG esize, bufsize;
4613     unsigned char *saved_buffer;
4614
4615     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4616
4617     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4618     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4619     {
4620         ERR("invalid format type %x\n", pCStructFormat->type);
4621         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4622         return NULL;
4623     }
4624     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4625         pCStructFormat->offset_to_array_description;
4626     if (*pCArrayFormat != RPC_FC_CARRAY)
4627     {
4628         ERR("invalid array format type %x\n", pCStructFormat->type);
4629         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4630         return NULL;
4631     }
4632     esize = *(const WORD*)(pCArrayFormat+2);
4633
4634     pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
4635
4636     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4637
4638     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4639
4640     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4641     if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4642     {
4643         ERR("integer overflow of memory_size %u with bufsize %u\n",
4644             pCStructFormat->memory_size, bufsize);
4645         RpcRaiseException(RPC_X_BAD_STUB_DATA);
4646     }
4647
4648     if (fMustAlloc)
4649     {
4650         SIZE_T size = pCStructFormat->memory_size + bufsize;
4651         *ppMemory = NdrAllocate(pStubMsg, size);
4652     }
4653     else
4654     {
4655         if (!pStubMsg->IsClient && !*ppMemory)
4656             /* for servers, we just point straight into the RPC buffer */
4657             *ppMemory = pStubMsg->Buffer;
4658     }
4659
4660     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4661     safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
4662     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4663         EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4664
4665     TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4666     if (*ppMemory != saved_buffer)
4667         memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
4668
4669     return NULL;
4670 }
4671
4672 /***********************************************************************
4673  *           NdrConformantStructBufferSize [RPCRT4.@]
4674  */
4675 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4676                                 unsigned char *pMemory,
4677                                 PFORMAT_STRING pFormat)
4678 {
4679     const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4680     PFORMAT_STRING pCArrayFormat;
4681     ULONG esize;
4682
4683     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4684
4685     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4686     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4687     {
4688         ERR("invalid format type %x\n", pCStructFormat->type);
4689         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4690         return;
4691     }
4692     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4693         pCStructFormat->offset_to_array_description;
4694     if (*pCArrayFormat != RPC_FC_CARRAY)
4695     {
4696         ERR("invalid array format type %x\n", pCStructFormat->type);
4697         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4698         return;
4699     }
4700     esize = *(const WORD*)(pCArrayFormat+2);
4701
4702     pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
4703     SizeConformance(pStubMsg);
4704
4705     ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
4706
4707     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4708
4709     safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
4710     safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4711
4712     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4713         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4714 }
4715
4716 /***********************************************************************
4717  *           NdrConformantStructMemorySize [RPCRT4.@]
4718  */
4719 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4720                                 PFORMAT_STRING pFormat)
4721 {
4722     FIXME("stub\n");
4723     return 0;
4724 }
4725
4726 /***********************************************************************
4727  *           NdrConformantStructFree [RPCRT4.@]
4728  */
4729 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4730                                 unsigned char *pMemory,
4731                                 PFORMAT_STRING pFormat)
4732 {
4733     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4734     PFORMAT_STRING pCArrayFormat;
4735
4736     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4737
4738     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4739     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4740     {
4741         ERR("invalid format type %x\n", pCStructFormat->type);
4742         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4743         return;
4744     }
4745
4746     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4747         pCStructFormat->offset_to_array_description;
4748     if (*pCArrayFormat != RPC_FC_CARRAY)
4749     {
4750         ERR("invalid array format type %x\n", pCStructFormat->type);
4751         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4752         return;
4753     }
4754
4755     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4756                        pCArrayFormat + 4, 0);
4757
4758     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4759
4760     /* copy constant sized part of struct */
4761     pStubMsg->BufferMark = pStubMsg->Buffer;
4762
4763     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4764         EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4765 }
4766
4767 /***********************************************************************
4768  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
4769  */
4770 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4771                                 unsigned char *pMemory,
4772                                 PFORMAT_STRING pFormat)
4773 {
4774     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4775     PFORMAT_STRING pCVArrayFormat;
4776
4777     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4778
4779     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4780     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4781     {
4782         ERR("invalid format type %x\n", pCVStructFormat->type);
4783         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4784         return NULL;
4785     }
4786
4787     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4788         pCVStructFormat->offset_to_array_description;
4789
4790     array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg,
4791                                         pMemory + pCVStructFormat->memory_size,
4792                                         pCVArrayFormat);
4793
4794     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4795
4796     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4797
4798     /* write constant sized part */
4799     pStubMsg->BufferMark = pStubMsg->Buffer;
4800     safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
4801
4802     array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg,
4803                                       pMemory + pCVStructFormat->memory_size,
4804                                       pCVArrayFormat, FALSE /* fHasPointers */);
4805
4806     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4807
4808     return NULL;
4809 }
4810
4811 /***********************************************************************
4812  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
4813  */
4814 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4815                                 unsigned char **ppMemory,
4816                                 PFORMAT_STRING pFormat,
4817                                 unsigned char fMustAlloc)
4818 {
4819     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4820     PFORMAT_STRING pCVArrayFormat;
4821     ULONG memsize, bufsize;
4822     unsigned char *saved_buffer, *saved_array_buffer;
4823     ULONG offset;
4824     unsigned char *array_memory;
4825
4826     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4827
4828     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4829     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4830     {
4831         ERR("invalid format type %x\n", pCVStructFormat->type);
4832         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4833         return NULL;
4834     }
4835
4836     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4837         pCVStructFormat->offset_to_array_description;
4838
4839     memsize = array_read_conformance(*pCVArrayFormat, pStubMsg,
4840                                      pCVArrayFormat);
4841
4842     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4843
4844     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4845
4846     /* work out how much memory to allocate if we need to do so */
4847     if (!fMustAlloc && !*ppMemory)
4848         fMustAlloc = TRUE;
4849     if (fMustAlloc)
4850     {
4851         SIZE_T size = pCVStructFormat->memory_size + memsize;
4852         *ppMemory = NdrAllocate(pStubMsg, size);
4853     }
4854
4855     /* mark the start of the constant data */
4856     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4857     safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4858
4859     array_memory = *ppMemory + pCVStructFormat->memory_size;
4860     bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg,
4861                                                  &array_memory, pCVArrayFormat,
4862                                                  FALSE /* fMustAlloc */,
4863                                                  FALSE /* fUseServerBufferMemory */,
4864                                                  FALSE /* fUnmarshall */);
4865
4866     /* save offset in case unmarshalling pointers changes it */
4867     offset = pStubMsg->Offset;
4868
4869     /* mark the start of the array data */
4870     saved_array_buffer = pStubMsg->Buffer;
4871     safe_buffer_increment(pStubMsg, bufsize);
4872
4873     EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4874
4875     /* copy the constant data */
4876     memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size);
4877     /* copy the array data */
4878     TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size);
4879     memcpy(*ppMemory + pCVStructFormat->memory_size + offset,
4880            saved_array_buffer, bufsize);
4881
4882     if (*pCVArrayFormat == RPC_FC_C_CSTRING)
4883         TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
4884     else if (*pCVArrayFormat == RPC_FC_C_WSTRING)
4885         TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
4886
4887     return NULL;
4888 }
4889
4890 /***********************************************************************
4891  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
4892  */
4893 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4894                                 unsigned char *pMemory,
4895                                 PFORMAT_STRING pFormat)
4896 {
4897     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4898     PFORMAT_STRING pCVArrayFormat;
4899
4900     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4901
4902     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4903     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4904     {
4905         ERR("invalid format type %x\n", pCVStructFormat->type);
4906         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4907         return;
4908     }
4909
4910     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4911         pCVStructFormat->offset_to_array_description;
4912     array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg,
4913                                        pMemory + pCVStructFormat->memory_size,
4914                                        pCVArrayFormat);
4915
4916     ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4917
4918     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4919
4920     safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4921
4922     array_buffer_size(*pCVArrayFormat, pStubMsg,
4923                       pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4924                       FALSE /* fHasPointers */);
4925
4926     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4927 }
4928
4929 /***********************************************************************
4930  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
4931  */
4932 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4933                                 PFORMAT_STRING pFormat)
4934 {
4935     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4936     PFORMAT_STRING pCVArrayFormat;
4937
4938     TRACE("(%p, %p)\n", pStubMsg, pFormat);
4939
4940     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4941     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4942     {
4943         ERR("invalid format type %x\n", pCVStructFormat->type);
4944         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4945         return 0;
4946     }
4947
4948     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4949         pCVStructFormat->offset_to_array_description;
4950     array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat);
4951
4952     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4953
4954     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4955
4956     safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4957     array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat,
4958                       FALSE /* fHasPointers */);
4959
4960     pStubMsg->MemorySize += pCVStructFormat->memory_size;
4961
4962     EmbeddedPointerMemorySize(pStubMsg, pFormat);
4963
4964     return pStubMsg->MemorySize;
4965 }
4966
4967 /***********************************************************************
4968  *           NdrConformantVaryingStructFree [RPCRT4.@]
4969  */
4970 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4971                                 unsigned char *pMemory,
4972                                 PFORMAT_STRING pFormat)
4973 {
4974     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4975     PFORMAT_STRING pCVArrayFormat;
4976
4977     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4978
4979     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4980     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4981     {
4982         ERR("invalid format type %x\n", pCVStructFormat->type);
4983         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4984         return;
4985     }
4986
4987     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4988         pCVStructFormat->offset_to_array_description;
4989     array_free(*pCVArrayFormat, pStubMsg,
4990                pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4991                FALSE /* fHasPointers */);
4992
4993     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4994
4995     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4996 }
4997
4998 #include "pshpack1.h"
4999 typedef struct
5000 {
5001     unsigned char type;
5002     unsigned char alignment;
5003     unsigned short total_size;
5004 } NDR_SMFARRAY_FORMAT;
5005
5006 typedef struct
5007 {
5008     unsigned char type;
5009     unsigned char alignment;
5010     ULONG total_size;
5011 } NDR_LGFARRAY_FORMAT;
5012 #include "poppack.h"
5013
5014 /***********************************************************************
5015  *           NdrFixedArrayMarshall [RPCRT4.@]
5016  */
5017 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5018                                 unsigned char *pMemory,
5019                                 PFORMAT_STRING pFormat)
5020 {
5021     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5022     ULONG total_size;
5023
5024     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5025
5026     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5027         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5028     {
5029         ERR("invalid format type %x\n", pSmFArrayFormat->type);
5030         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5031         return NULL;
5032     }
5033
5034     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5035
5036     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5037     {
5038         total_size = pSmFArrayFormat->total_size;
5039         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5040     }
5041     else
5042     {
5043         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5044         total_size = pLgFArrayFormat->total_size;
5045         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5046     }
5047
5048     pStubMsg->BufferMark = pStubMsg->Buffer;
5049     safe_copy_to_buffer(pStubMsg, pMemory, total_size);
5050
5051     pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5052
5053     return NULL;
5054 }
5055
5056 /***********************************************************************
5057  *           NdrFixedArrayUnmarshall [RPCRT4.@]
5058  */
5059 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5060                                 unsigned char **ppMemory,
5061                                 PFORMAT_STRING pFormat,
5062                                 unsigned char fMustAlloc)
5063 {
5064     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5065     ULONG total_size;
5066     unsigned char *saved_buffer;
5067
5068     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5069
5070     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5071         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5072     {
5073         ERR("invalid format type %x\n", pSmFArrayFormat->type);
5074         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5075         return NULL;
5076     }
5077
5078     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5079
5080     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5081     {
5082         total_size = pSmFArrayFormat->total_size;
5083         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5084     }
5085     else
5086     {
5087         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5088         total_size = pLgFArrayFormat->total_size;
5089         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5090     }
5091
5092     if (fMustAlloc)
5093         *ppMemory = NdrAllocate(pStubMsg, total_size);
5094     else
5095     {
5096         if (!pStubMsg->IsClient && !*ppMemory)
5097             /* for servers, we just point straight into the RPC buffer */
5098             *ppMemory = pStubMsg->Buffer;
5099     }
5100
5101     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5102     safe_buffer_increment(pStubMsg, total_size);
5103     pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5104
5105     TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
5106     if (*ppMemory != saved_buffer)
5107         memcpy(*ppMemory, saved_buffer, total_size);
5108
5109     return NULL;
5110 }
5111
5112 /***********************************************************************
5113  *           NdrFixedArrayBufferSize [RPCRT4.@]
5114  */
5115 void WINAPI NdrFixedArrayBufferSize(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     ULONG total_size;
5121
5122     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5123
5124     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5125         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5126     {
5127         ERR("invalid format type %x\n", pSmFArrayFormat->type);
5128         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5129         return;
5130     }
5131
5132     ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
5133
5134     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5135     {
5136         total_size = pSmFArrayFormat->total_size;
5137         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5138     }
5139     else
5140     {
5141         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5142         total_size = pLgFArrayFormat->total_size;
5143         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5144     }
5145     safe_buffer_length_increment(pStubMsg, total_size);
5146
5147     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5148 }
5149
5150 /***********************************************************************
5151  *           NdrFixedArrayMemorySize [RPCRT4.@]
5152  */
5153 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5154                                 PFORMAT_STRING pFormat)
5155 {
5156     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5157     ULONG total_size;
5158
5159     TRACE("(%p, %p)\n", pStubMsg, pFormat);
5160
5161     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5162         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5163     {
5164         ERR("invalid format type %x\n", pSmFArrayFormat->type);
5165         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5166         return 0;
5167     }
5168
5169     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5170
5171     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5172     {
5173         total_size = pSmFArrayFormat->total_size;
5174         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5175     }
5176     else
5177     {
5178         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5179         total_size = pLgFArrayFormat->total_size;
5180         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5181     }
5182     pStubMsg->BufferMark = pStubMsg->Buffer;
5183     safe_buffer_increment(pStubMsg, total_size);
5184     pStubMsg->MemorySize += total_size;
5185
5186     EmbeddedPointerMemorySize(pStubMsg, pFormat);
5187
5188     return total_size;
5189 }
5190
5191 /***********************************************************************
5192  *           NdrFixedArrayFree [RPCRT4.@]
5193  */
5194 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5195                                 unsigned char *pMemory,
5196                                 PFORMAT_STRING pFormat)
5197 {
5198     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5199
5200     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5201
5202     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5203         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5204     {
5205         ERR("invalid format type %x\n", pSmFArrayFormat->type);
5206         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5207         return;
5208     }
5209
5210     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5211         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5212     else
5213     {
5214         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5215         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5216     }
5217
5218     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5219 }
5220
5221 /***********************************************************************
5222  *           NdrVaryingArrayMarshall [RPCRT4.@]
5223  */
5224 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5225                                 unsigned char *pMemory,
5226                                 PFORMAT_STRING pFormat)
5227 {
5228     unsigned char alignment;
5229     DWORD elements, esize;
5230     ULONG bufsize;
5231
5232     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5233
5234     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5235         (pFormat[0] != RPC_FC_LGVARRAY))
5236     {
5237         ERR("invalid format type %x\n", pFormat[0]);
5238         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5239         return NULL;
5240     }
5241
5242     alignment = pFormat[1] + 1;
5243
5244     if (pFormat[0] == RPC_FC_SMVARRAY)
5245     {
5246         pFormat += 2;
5247         pFormat += sizeof(WORD);
5248         elements = *(const WORD*)pFormat;
5249         pFormat += sizeof(WORD);
5250     }
5251     else
5252     {
5253         pFormat += 2;
5254         pFormat += sizeof(DWORD);
5255         elements = *(const DWORD*)pFormat;
5256         pFormat += sizeof(DWORD);
5257     }
5258
5259     esize = *(const WORD*)pFormat;
5260     pFormat += sizeof(WORD);
5261
5262     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5263     if ((pStubMsg->ActualCount > elements) ||
5264         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5265     {
5266         RpcRaiseException(RPC_S_INVALID_BOUND);
5267         return NULL;
5268     }
5269
5270     WriteVariance(pStubMsg);
5271
5272     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
5273
5274     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5275     pStubMsg->BufferMark = pStubMsg->Buffer;
5276     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
5277
5278     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5279
5280     return NULL;
5281 }
5282
5283 /***********************************************************************
5284  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
5285  */
5286 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5287                                 unsigned char **ppMemory,
5288                                 PFORMAT_STRING pFormat,
5289                                 unsigned char fMustAlloc)
5290 {
5291     unsigned char alignment;
5292     DWORD size, elements, esize;
5293     ULONG bufsize;
5294     unsigned char *saved_buffer;
5295     ULONG offset;
5296
5297     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5298
5299     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5300         (pFormat[0] != RPC_FC_LGVARRAY))
5301     {
5302         ERR("invalid format type %x\n", pFormat[0]);
5303         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5304         return NULL;
5305     }
5306
5307     alignment = pFormat[1] + 1;
5308
5309     if (pFormat[0] == RPC_FC_SMVARRAY)
5310     {
5311         pFormat += 2;
5312         size = *(const WORD*)pFormat;
5313         pFormat += sizeof(WORD);
5314         elements = *(const WORD*)pFormat;
5315         pFormat += sizeof(WORD);
5316     }
5317     else
5318     {
5319         pFormat += 2;
5320         size = *(const DWORD*)pFormat;
5321         pFormat += sizeof(DWORD);
5322         elements = *(const DWORD*)pFormat;
5323         pFormat += sizeof(DWORD);
5324     }
5325
5326     esize = *(const WORD*)pFormat;
5327     pFormat += sizeof(WORD);
5328
5329     pFormat = ReadVariance(pStubMsg, pFormat, elements);
5330
5331     ALIGN_POINTER(pStubMsg->Buffer, alignment);
5332
5333     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5334     offset = pStubMsg->Offset;
5335
5336     if (!fMustAlloc && !*ppMemory)
5337         fMustAlloc = TRUE;
5338     if (fMustAlloc)
5339         *ppMemory = NdrAllocate(pStubMsg, size);
5340     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5341     safe_buffer_increment(pStubMsg, bufsize);
5342
5343     EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5344
5345     memcpy(*ppMemory + offset, saved_buffer, bufsize);
5346
5347     return NULL;
5348 }
5349
5350 /***********************************************************************
5351  *           NdrVaryingArrayBufferSize [RPCRT4.@]
5352  */
5353 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5354                                 unsigned char *pMemory,
5355                                 PFORMAT_STRING pFormat)
5356 {
5357     unsigned char alignment;
5358     DWORD elements, esize;
5359
5360     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5361
5362     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5363         (pFormat[0] != RPC_FC_LGVARRAY))
5364     {
5365         ERR("invalid format type %x\n", pFormat[0]);
5366         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5367         return;
5368     }
5369
5370     alignment = pFormat[1] + 1;
5371
5372     if (pFormat[0] == RPC_FC_SMVARRAY)
5373     {
5374         pFormat += 2;
5375         pFormat += sizeof(WORD);
5376         elements = *(const WORD*)pFormat;
5377         pFormat += sizeof(WORD);
5378     }
5379     else
5380     {
5381         pFormat += 2;
5382         pFormat += sizeof(DWORD);
5383         elements = *(const DWORD*)pFormat;
5384         pFormat += sizeof(DWORD);
5385     }
5386
5387     esize = *(const WORD*)pFormat;
5388     pFormat += sizeof(WORD);
5389
5390     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5391     if ((pStubMsg->ActualCount > elements) ||
5392         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5393     {
5394         RpcRaiseException(RPC_S_INVALID_BOUND);
5395         return;
5396     }
5397
5398     SizeVariance(pStubMsg);
5399
5400     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
5401
5402     safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5403
5404     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5405 }
5406
5407 /***********************************************************************
5408  *           NdrVaryingArrayMemorySize [RPCRT4.@]
5409  */
5410 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5411                                 PFORMAT_STRING pFormat)
5412 {
5413     unsigned char alignment;
5414     DWORD size, elements, esize;
5415
5416     TRACE("(%p, %p)\n", pStubMsg, pFormat);
5417
5418     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5419         (pFormat[0] != RPC_FC_LGVARRAY))
5420     {
5421         ERR("invalid format type %x\n", pFormat[0]);
5422         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5423         return 0;
5424     }
5425
5426     alignment = pFormat[1] + 1;
5427
5428     if (pFormat[0] == RPC_FC_SMVARRAY)
5429     {
5430         pFormat += 2;
5431         size = *(const WORD*)pFormat;
5432         pFormat += sizeof(WORD);
5433         elements = *(const WORD*)pFormat;
5434         pFormat += sizeof(WORD);
5435     }
5436     else
5437     {
5438         pFormat += 2;
5439         size = *(const DWORD*)pFormat;
5440         pFormat += sizeof(DWORD);
5441         elements = *(const DWORD*)pFormat;
5442         pFormat += sizeof(DWORD);
5443     }
5444
5445     esize = *(const WORD*)pFormat;
5446     pFormat += sizeof(WORD);
5447
5448     pFormat = ReadVariance(pStubMsg, pFormat, elements);
5449
5450     ALIGN_POINTER(pStubMsg->Buffer, alignment);
5451
5452     safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5453     pStubMsg->MemorySize += size;
5454
5455     EmbeddedPointerMemorySize(pStubMsg, pFormat);
5456
5457     return pStubMsg->MemorySize;
5458 }
5459
5460 /***********************************************************************
5461  *           NdrVaryingArrayFree [RPCRT4.@]
5462  */
5463 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5464                                 unsigned char *pMemory,
5465                                 PFORMAT_STRING pFormat)
5466 {
5467     DWORD elements;
5468
5469     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5470
5471     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5472         (pFormat[0] != RPC_FC_LGVARRAY))
5473     {
5474         ERR("invalid format type %x\n", pFormat[0]);
5475         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5476         return;
5477     }
5478
5479     if (pFormat[0] == RPC_FC_SMVARRAY)
5480     {
5481         pFormat += 2;
5482         pFormat += sizeof(WORD);
5483         elements = *(const WORD*)pFormat;
5484         pFormat += sizeof(WORD);
5485     }
5486     else
5487     {
5488         pFormat += 2;
5489         pFormat += sizeof(DWORD);
5490         elements = *(const DWORD*)pFormat;
5491         pFormat += sizeof(DWORD);
5492     }
5493
5494     pFormat += sizeof(WORD);
5495
5496     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5497     if ((pStubMsg->ActualCount > elements) ||
5498         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5499     {
5500         RpcRaiseException(RPC_S_INVALID_BOUND);
5501         return;
5502     }
5503
5504     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5505 }
5506
5507 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
5508 {
5509     switch (fc)
5510     {
5511     case RPC_FC_BYTE:
5512     case RPC_FC_CHAR:
5513     case RPC_FC_SMALL:
5514     case RPC_FC_USMALL:
5515         return *pMemory;
5516     case RPC_FC_WCHAR:
5517     case RPC_FC_SHORT:
5518     case RPC_FC_USHORT:
5519     case RPC_FC_ENUM16:
5520         return *(const USHORT *)pMemory;
5521     case RPC_FC_LONG:
5522     case RPC_FC_ULONG:
5523     case RPC_FC_ENUM32:
5524         return *(const ULONG *)pMemory;
5525     default:
5526         FIXME("Unhandled base type: 0x%02x\n", fc);
5527         return 0;
5528     }
5529 }
5530
5531 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
5532                                                              ULONG discriminant,
5533                                                              PFORMAT_STRING pFormat)
5534 {
5535     unsigned short num_arms, arm, type;
5536
5537     num_arms = *(const SHORT*)pFormat & 0x0fff;
5538     pFormat += 2;
5539     for(arm = 0; arm < num_arms; arm++)
5540     {
5541         if(discriminant == *(const ULONG*)pFormat)
5542         {
5543             pFormat += 4;
5544             break;
5545         }
5546         pFormat += 6;
5547     }
5548
5549     type = *(const unsigned short*)pFormat;
5550     TRACE("type %04x\n", type);
5551     if(arm == num_arms) /* default arm extras */
5552     {
5553         if(type == 0xffff)
5554         {
5555             ERR("no arm for 0x%x and no default case\n", discriminant);
5556             RpcRaiseException(RPC_S_INVALID_TAG);
5557             return NULL;
5558         }
5559         if(type == 0)
5560         {
5561             TRACE("falling back to empty default case for 0x%x\n", discriminant);
5562             return NULL;
5563         }
5564     }
5565     return pFormat;
5566 }
5567
5568 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
5569 {
5570     unsigned short type;
5571
5572     pFormat += 2;
5573
5574     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5575     if(!pFormat)
5576         return NULL;
5577
5578     type = *(const unsigned short*)pFormat;
5579     if((type & 0xff00) == 0x8000)
5580     {
5581         unsigned char basetype = LOBYTE(type);
5582         return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
5583     }
5584     else
5585     {
5586         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5587         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
5588         if (m)
5589         {
5590             unsigned char *saved_buffer = NULL;
5591             int pointer_buffer_mark_set = 0;
5592             switch(*desc)
5593             {
5594             case RPC_FC_RP:
5595             case RPC_FC_UP:
5596             case RPC_FC_OP:
5597             case RPC_FC_FP:
5598                 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
5599                 saved_buffer = pStubMsg->Buffer;
5600                 if (pStubMsg->PointerBufferMark)
5601                 {
5602                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5603                   pStubMsg->PointerBufferMark = NULL;
5604                   pointer_buffer_mark_set = 1;
5605                 }
5606                 else
5607                   safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
5608
5609                 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
5610                 if (pointer_buffer_mark_set)
5611                 {
5612                   STD_OVERFLOW_CHECK(pStubMsg);
5613                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5614                   if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5615                   {
5616                       ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5617                           saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5618                       RpcRaiseException(RPC_X_BAD_STUB_DATA);
5619                   }
5620                   pStubMsg->Buffer = saved_buffer + 4;
5621                 }
5622                 break;
5623             default:
5624                 m(pStubMsg, pMemory, desc);
5625             }
5626         }
5627         else FIXME("no marshaller for embedded type %02x\n", *desc);
5628     }
5629     return NULL;
5630 }
5631
5632 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5633                                 unsigned char **ppMemory,
5634                                 ULONG discriminant,
5635                                 PFORMAT_STRING pFormat,
5636                                 unsigned char fMustAlloc)
5637 {
5638     unsigned short type;
5639
5640     pFormat += 2;
5641
5642     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5643     if(!pFormat)
5644         return NULL;
5645
5646     type = *(const unsigned short*)pFormat;
5647     if((type & 0xff00) == 0x8000)
5648     {
5649         unsigned char basetype = LOBYTE(type);
5650         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
5651     }
5652     else
5653     {
5654         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5655         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
5656         if (m)
5657         {
5658             unsigned char *saved_buffer = NULL;
5659             int pointer_buffer_mark_set = 0;
5660             switch(*desc)
5661             {
5662             case RPC_FC_RP:
5663             case RPC_FC_UP:
5664             case RPC_FC_OP:
5665             case RPC_FC_FP:
5666                 ALIGN_POINTER(pStubMsg->Buffer, 4);
5667                 saved_buffer = pStubMsg->Buffer;
5668                 if (pStubMsg->PointerBufferMark)
5669                 {
5670                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5671                   pStubMsg->PointerBufferMark = NULL;
5672                   pointer_buffer_mark_set = 1;
5673                 }
5674                 else
5675                   pStubMsg->Buffer += 4; /* for pointer ID */
5676
5677                 if (saved_buffer + 4 > pStubMsg->BufferEnd)
5678                 {
5679                     ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5680                         saved_buffer, pStubMsg->BufferEnd);
5681                     RpcRaiseException(RPC_X_BAD_STUB_DATA);
5682                 }
5683
5684                 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
5685                 if (pointer_buffer_mark_set)
5686                 {
5687                   STD_OVERFLOW_CHECK(pStubMsg);
5688                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5689                   pStubMsg->Buffer = saved_buffer + 4;
5690                 }
5691                 break;
5692             default:
5693                 m(pStubMsg, ppMemory, desc, fMustAlloc);
5694             }
5695         }
5696         else FIXME("no marshaller for embedded type %02x\n", *desc);
5697     }
5698     return NULL;
5699 }
5700
5701 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
5702                                   unsigned char *pMemory,
5703                                   ULONG discriminant,
5704                                   PFORMAT_STRING pFormat)
5705 {
5706     unsigned short type;
5707
5708     pFormat += 2;
5709
5710     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5711     if(!pFormat)
5712         return;
5713
5714     type = *(const unsigned short*)pFormat;
5715     if((type & 0xff00) == 0x8000)
5716     {
5717         unsigned char basetype = LOBYTE(type);
5718         NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
5719     }
5720     else
5721     {
5722         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5723         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
5724         if (m)
5725         {
5726             switch(*desc)
5727             {
5728             case RPC_FC_RP:
5729             case RPC_FC_UP:
5730             case RPC_FC_OP:
5731             case RPC_FC_FP:
5732                 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5733                 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
5734                 if (!pStubMsg->IgnoreEmbeddedPointers)
5735                 {
5736                     int saved_buffer_length = pStubMsg->BufferLength;
5737                     pStubMsg->BufferLength = pStubMsg->PointerLength;
5738                     pStubMsg->PointerLength = 0;
5739                     if(!pStubMsg->BufferLength)
5740                         ERR("BufferLength == 0??\n");
5741                     PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
5742                     pStubMsg->PointerLength = pStubMsg->BufferLength;
5743                     pStubMsg->BufferLength = saved_buffer_length;
5744                 }
5745                 break;
5746             default:
5747                 m(pStubMsg, pMemory, desc);
5748             }
5749         }
5750         else FIXME("no buffersizer for embedded type %02x\n", *desc);
5751     }
5752 }
5753
5754 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
5755                                    ULONG discriminant,
5756                                    PFORMAT_STRING pFormat)
5757 {
5758     unsigned short type, size;
5759
5760     size = *(const unsigned short*)pFormat;
5761     pStubMsg->Memory += size;
5762     pFormat += 2;
5763
5764     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5765     if(!pFormat)
5766         return 0;
5767
5768     type = *(const unsigned short*)pFormat;
5769     if((type & 0xff00) == 0x8000)
5770     {
5771         return NdrBaseTypeMemorySize(pStubMsg, pFormat);
5772     }
5773     else
5774     {
5775         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5776         NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
5777         unsigned char *saved_buffer;
5778         if (m)
5779         {
5780             switch(*desc)
5781             {
5782             case RPC_FC_RP:
5783             case RPC_FC_UP:
5784             case RPC_FC_OP:
5785             case RPC_FC_FP:
5786                 ALIGN_POINTER(pStubMsg->Buffer, 4);
5787                 saved_buffer = pStubMsg->Buffer;
5788                 safe_buffer_increment(pStubMsg, 4);
5789                 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
5790                 pStubMsg->MemorySize += sizeof(void *);
5791                 if (!pStubMsg->IgnoreEmbeddedPointers)
5792                     PointerMemorySize(pStubMsg, saved_buffer, pFormat);
5793                 break;
5794             default:
5795                 return m(pStubMsg, desc);
5796             }
5797         }
5798         else FIXME("no marshaller for embedded type %02x\n", *desc);
5799     }
5800
5801     TRACE("size %d\n", size);
5802     return size;
5803 }
5804
5805 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
5806                            unsigned char *pMemory,
5807                            ULONG discriminant,
5808                            PFORMAT_STRING pFormat)
5809 {
5810     unsigned short type;
5811
5812     pFormat += 2;
5813
5814     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5815     if(!pFormat)
5816         return;
5817
5818     type = *(const unsigned short*)pFormat;
5819     if((type & 0xff00) != 0x8000)
5820     {
5821         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5822         NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5823         if (m)
5824         {
5825             switch(*desc)
5826             {
5827             case RPC_FC_RP:
5828             case RPC_FC_UP:
5829             case RPC_FC_OP:
5830             case RPC_FC_FP:
5831                 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5832                 break;
5833             default:
5834                 m(pStubMsg, pMemory, desc);
5835             }
5836         }
5837     }
5838 }
5839
5840 /***********************************************************************
5841  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
5842  */
5843 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5844                                 unsigned char *pMemory,
5845                                 PFORMAT_STRING pFormat)
5846 {
5847     unsigned char switch_type;
5848     unsigned char increment;
5849     ULONG switch_value;
5850
5851     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5852     pFormat++;
5853
5854     switch_type = *pFormat & 0xf;
5855     increment = (*pFormat & 0xf0) >> 4;
5856     pFormat++;
5857
5858     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment);
5859
5860     switch_value = get_discriminant(switch_type, pMemory);
5861     TRACE("got switch value 0x%x\n", switch_value);
5862
5863     NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5864     pMemory += increment;
5865
5866     return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5867 }
5868
5869 /***********************************************************************
5870  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5871  */
5872 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5873                                 unsigned char **ppMemory,
5874                                 PFORMAT_STRING pFormat,
5875                                 unsigned char fMustAlloc)
5876 {
5877     unsigned char switch_type;
5878     unsigned char increment;
5879     ULONG switch_value;
5880     unsigned short size;
5881     unsigned char *pMemoryArm;
5882
5883     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5884     pFormat++;
5885
5886     switch_type = *pFormat & 0xf;
5887     increment = (*pFormat & 0xf0) >> 4;
5888     pFormat++;
5889
5890     ALIGN_POINTER(pStubMsg->Buffer, increment);
5891     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5892     TRACE("got switch value 0x%x\n", switch_value);
5893
5894     size = *(const unsigned short*)pFormat + increment;
5895     if (!fMustAlloc && !*ppMemory)
5896         fMustAlloc = TRUE;
5897     if (fMustAlloc)
5898         *ppMemory = NdrAllocate(pStubMsg, size);
5899
5900     /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
5901      * since the arm is part of the memory block that is encompassed by
5902      * the whole union. Memory is forced to allocate when pointers
5903      * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
5904      * clearing the memory we pass in to the unmarshaller */
5905     if (fMustAlloc)
5906         memset(*ppMemory, 0, size);
5907
5908     NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5909     pMemoryArm = *ppMemory + increment;
5910
5911     return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE);
5912 }
5913
5914 /***********************************************************************
5915  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5916  */
5917 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5918                                 unsigned char *pMemory,
5919                                 PFORMAT_STRING pFormat)
5920 {
5921     unsigned char switch_type;
5922     unsigned char increment;
5923     ULONG switch_value;
5924
5925     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5926     pFormat++;
5927
5928     switch_type = *pFormat & 0xf;
5929     increment = (*pFormat & 0xf0) >> 4;
5930     pFormat++;
5931
5932     ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5933     switch_value = get_discriminant(switch_type, pMemory);
5934     TRACE("got switch value 0x%x\n", switch_value);
5935
5936     /* Add discriminant size */
5937     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5938     pMemory += increment;
5939
5940     union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5941 }
5942
5943 /***********************************************************************
5944  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5945  */
5946 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5947                                 PFORMAT_STRING pFormat)
5948 {
5949     unsigned char switch_type;
5950     unsigned char increment;
5951     ULONG switch_value;
5952
5953     switch_type = *pFormat & 0xf;
5954     increment = (*pFormat & 0xf0) >> 4;
5955     pFormat++;
5956
5957     ALIGN_POINTER(pStubMsg->Buffer, increment);
5958     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5959     TRACE("got switch value 0x%x\n", switch_value);
5960
5961     pStubMsg->Memory += increment;
5962
5963     return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5964 }
5965
5966 /***********************************************************************
5967  *           NdrEncapsulatedUnionFree [RPCRT4.@]
5968  */
5969 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5970                                 unsigned char *pMemory,
5971                                 PFORMAT_STRING pFormat)
5972 {
5973     unsigned char switch_type;
5974     unsigned char increment;
5975     ULONG switch_value;
5976
5977     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5978     pFormat++;
5979
5980     switch_type = *pFormat & 0xf;
5981     increment = (*pFormat & 0xf0) >> 4;
5982     pFormat++;
5983
5984     switch_value = get_discriminant(switch_type, pMemory);
5985     TRACE("got switch value 0x%x\n", switch_value);
5986
5987     pMemory += increment;
5988
5989     union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5990 }
5991
5992 /***********************************************************************
5993  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5994  */
5995 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5996                                 unsigned char *pMemory,
5997                                 PFORMAT_STRING pFormat)
5998 {
5999     unsigned char switch_type;
6000
6001     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6002     pFormat++;
6003
6004     switch_type = *pFormat;
6005     pFormat++;
6006
6007     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6008     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6009     /* Marshall discriminant */
6010     NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6011
6012     return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6013 }
6014
6015 static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
6016                                     PFORMAT_STRING *ppFormat)
6017 {
6018     LONG discriminant = 0;
6019
6020     switch(**ppFormat)
6021     {
6022     case RPC_FC_BYTE:
6023     case RPC_FC_CHAR:
6024     case RPC_FC_SMALL:
6025     case RPC_FC_USMALL:
6026     {
6027         UCHAR d;
6028         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6029         discriminant = d;
6030         break;
6031     }
6032     case RPC_FC_WCHAR:
6033     case RPC_FC_SHORT:
6034     case RPC_FC_USHORT:
6035     {
6036         USHORT d;
6037         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6038         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6039         discriminant = d;
6040         break;
6041     }
6042     case RPC_FC_LONG:
6043     case RPC_FC_ULONG:
6044     {
6045         ULONG d;
6046         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
6047         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6048         discriminant = d;
6049         break;
6050     }
6051     default:
6052         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
6053     }
6054     (*ppFormat)++;
6055
6056     if (pStubMsg->fHasNewCorrDesc)
6057         *ppFormat += 6;
6058     else
6059         *ppFormat += 4;
6060     return discriminant;
6061 }
6062
6063 /**********************************************************************
6064  *           NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
6065  */
6066 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6067                                 unsigned char **ppMemory,
6068                                 PFORMAT_STRING pFormat,
6069                                 unsigned char fMustAlloc)
6070 {
6071     LONG discriminant;
6072     unsigned short size;
6073
6074     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
6075     pFormat++;
6076
6077     /* Unmarshall discriminant */
6078     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6079     TRACE("unmarshalled discriminant %x\n", discriminant);
6080
6081     pFormat += *(const SHORT*)pFormat;
6082
6083     size = *(const unsigned short*)pFormat;
6084
6085     if (!fMustAlloc && !*ppMemory)
6086         fMustAlloc = TRUE;
6087     if (fMustAlloc)
6088         *ppMemory = NdrAllocate(pStubMsg, size);
6089
6090     /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6091      * since the arm is part of the memory block that is encompassed by
6092      * the whole union. Memory is forced to allocate when pointers
6093      * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6094      * clearing the memory we pass in to the unmarshaller */
6095     if (fMustAlloc)
6096         memset(*ppMemory, 0, size);
6097
6098     return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
6099 }
6100
6101 /***********************************************************************
6102  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
6103  */
6104 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6105                                 unsigned char *pMemory,
6106                                 PFORMAT_STRING pFormat)
6107 {
6108     unsigned char switch_type;
6109
6110     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6111     pFormat++;
6112
6113     switch_type = *pFormat;
6114     pFormat++;
6115
6116     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6117     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6118     /* Add discriminant size */
6119     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6120
6121     union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6122 }
6123
6124 /***********************************************************************
6125  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
6126  */
6127 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6128                                 PFORMAT_STRING pFormat)
6129 {
6130     ULONG discriminant;
6131
6132     pFormat++;
6133     /* Unmarshall discriminant */
6134     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6135     TRACE("unmarshalled discriminant 0x%x\n", discriminant);
6136
6137     return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
6138 }
6139
6140 /***********************************************************************
6141  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
6142  */
6143 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6144                                 unsigned char *pMemory,
6145                                 PFORMAT_STRING pFormat)
6146 {
6147     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6148     pFormat++;
6149     pFormat++;
6150
6151     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6152     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6153
6154     union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6155 }
6156
6157 /***********************************************************************
6158  *           NdrByteCountPointerMarshall [RPCRT4.@]
6159  */
6160 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6161                                 unsigned char *pMemory,
6162                                 PFORMAT_STRING pFormat)
6163 {
6164     FIXME("stub\n");
6165     return NULL;
6166 }
6167
6168 /***********************************************************************
6169  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
6170  */
6171 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6172                                 unsigned char **ppMemory,
6173                                 PFORMAT_STRING pFormat,
6174                                 unsigned char fMustAlloc)
6175 {
6176     FIXME("stub\n");
6177     return NULL;
6178 }
6179
6180 /***********************************************************************
6181  *           NdrByteCountPointerBufferSize [RPCRT4.@]
6182  */
6183 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6184                                 unsigned char *pMemory,
6185                                 PFORMAT_STRING pFormat)
6186 {
6187     FIXME("stub\n");
6188 }
6189
6190 /***********************************************************************
6191  *           NdrByteCountPointerMemorySize [internal]
6192  */
6193 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6194                                                   PFORMAT_STRING pFormat)
6195 {
6196     FIXME("stub\n");
6197     return 0;
6198 }
6199
6200 /***********************************************************************
6201  *           NdrByteCountPointerFree [RPCRT4.@]
6202  */
6203 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
6204                                 unsigned char *pMemory,
6205                                 PFORMAT_STRING pFormat)
6206 {
6207     FIXME("stub\n");
6208 }
6209
6210 /***********************************************************************
6211  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
6212  */
6213 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6214                                 unsigned char *pMemory,
6215                                 PFORMAT_STRING pFormat)
6216 {
6217     FIXME("stub\n");
6218     return NULL;
6219 }
6220
6221 /***********************************************************************
6222  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
6223  */
6224 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6225                                 unsigned char **ppMemory,
6226                                 PFORMAT_STRING pFormat,
6227                                 unsigned char fMustAlloc)
6228 {
6229     FIXME("stub\n");
6230     return NULL;
6231 }
6232
6233 /***********************************************************************
6234  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
6235  */
6236 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6237                                 unsigned char *pMemory,
6238                                 PFORMAT_STRING pFormat)
6239 {
6240     FIXME("stub\n");
6241 }
6242
6243 /***********************************************************************
6244  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
6245  */
6246 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6247                                 PFORMAT_STRING pFormat)
6248 {
6249     FIXME("stub\n");
6250     return 0;
6251 }
6252
6253 /***********************************************************************
6254  *           NdrXmitOrRepAsFree [RPCRT4.@]
6255  */
6256 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
6257                                 unsigned char *pMemory,
6258                                 PFORMAT_STRING pFormat)
6259 {
6260     FIXME("stub\n");
6261 }
6262
6263 /***********************************************************************
6264  *           NdrRangeMarshall [internal]
6265  */
6266 static unsigned char *WINAPI NdrRangeMarshall(
6267     PMIDL_STUB_MESSAGE pStubMsg,
6268     unsigned char *pMemory,
6269     PFORMAT_STRING pFormat)
6270 {
6271     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6272     unsigned char base_type;
6273
6274     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6275
6276     if (pRange->type != RPC_FC_RANGE)
6277     {
6278         ERR("invalid format type %x\n", pRange->type);
6279         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6280         return NULL;
6281     }
6282
6283     base_type = pRange->flags_type & 0xf;
6284
6285     return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
6286 }
6287
6288 /***********************************************************************
6289  *           NdrRangeUnmarshall [RPCRT4.@]
6290  */
6291 unsigned char *WINAPI NdrRangeUnmarshall(
6292     PMIDL_STUB_MESSAGE pStubMsg,
6293     unsigned char **ppMemory,
6294     PFORMAT_STRING pFormat,
6295     unsigned char fMustAlloc)
6296 {
6297     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6298     unsigned char base_type;
6299
6300     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6301
6302     if (pRange->type != RPC_FC_RANGE)
6303     {
6304         ERR("invalid format type %x\n", pRange->type);
6305         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6306         return NULL;
6307     }
6308     base_type = pRange->flags_type & 0xf;
6309
6310     TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
6311         base_type, pRange->low_value, pRange->high_value);
6312
6313 #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
6314     do \
6315     { \
6316         ALIGN_POINTER(pStubMsg->Buffer, sizeof(wire_type)); \
6317         if (!fMustAlloc && !*ppMemory) \
6318             fMustAlloc = TRUE; \
6319         if (fMustAlloc) \
6320             *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
6321         if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
6322         { \
6323             ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
6324                 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
6325             RpcRaiseException(RPC_X_BAD_STUB_DATA); \
6326         } \
6327         if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
6328             (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
6329         { \
6330             ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
6331                 *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
6332                 (mem_type)pRange->high_value); \
6333             RpcRaiseException(RPC_S_INVALID_BOUND); \
6334             return NULL; \
6335         } \
6336         TRACE("*ppMemory: %p\n", *ppMemory); \
6337         **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
6338         pStubMsg->Buffer += sizeof(wire_type); \
6339     } while (0)
6340
6341     switch(base_type)
6342     {
6343     case RPC_FC_CHAR:
6344     case RPC_FC_SMALL:
6345         RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
6346         TRACE("value: 0x%02x\n", **ppMemory);
6347         break;
6348     case RPC_FC_BYTE:
6349     case RPC_FC_USMALL:
6350         RANGE_UNMARSHALL(CHAR, CHAR, "%u");
6351         TRACE("value: 0x%02x\n", **ppMemory);
6352         break;
6353     case RPC_FC_WCHAR: /* FIXME: valid? */
6354     case RPC_FC_USHORT:
6355         RANGE_UNMARSHALL(USHORT, USHORT, "%u");
6356         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6357         break;
6358     case RPC_FC_SHORT:
6359         RANGE_UNMARSHALL(SHORT, SHORT, "%d");
6360         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6361         break;
6362     case RPC_FC_LONG:
6363     case RPC_FC_ENUM32:
6364         RANGE_UNMARSHALL(LONG, LONG, "%d");
6365         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6366         break;
6367     case RPC_FC_ULONG:
6368         RANGE_UNMARSHALL(ULONG, ULONG, "%u");
6369         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6370         break;
6371     case RPC_FC_ENUM16:
6372         RANGE_UNMARSHALL(UINT, USHORT, "%u");
6373         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6374         break;
6375     case RPC_FC_FLOAT:
6376     case RPC_FC_DOUBLE:
6377     case RPC_FC_HYPER:
6378     default:
6379         ERR("invalid range base type: 0x%02x\n", base_type);
6380         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6381     }
6382
6383     return NULL;
6384 }
6385
6386 /***********************************************************************
6387  *           NdrRangeBufferSize [internal]
6388  */
6389 static void WINAPI NdrRangeBufferSize(
6390     PMIDL_STUB_MESSAGE pStubMsg,
6391     unsigned char *pMemory,
6392     PFORMAT_STRING pFormat)
6393 {
6394     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6395     unsigned char base_type;
6396
6397     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6398
6399     if (pRange->type != RPC_FC_RANGE)
6400     {
6401         ERR("invalid format type %x\n", pRange->type);
6402         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6403     }
6404     base_type = pRange->flags_type & 0xf;
6405
6406     NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
6407 }
6408
6409 /***********************************************************************
6410  *           NdrRangeMemorySize [internal]
6411  */
6412 static ULONG WINAPI NdrRangeMemorySize(
6413     PMIDL_STUB_MESSAGE pStubMsg,
6414     PFORMAT_STRING pFormat)
6415 {
6416     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6417     unsigned char base_type;
6418
6419     if (pRange->type != RPC_FC_RANGE)
6420     {
6421         ERR("invalid format type %x\n", pRange->type);
6422         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6423         return 0;
6424     }
6425     base_type = pRange->flags_type & 0xf;
6426
6427     return NdrBaseTypeMemorySize(pStubMsg, &base_type);
6428 }
6429
6430 /***********************************************************************
6431  *           NdrRangeFree [internal]
6432  */
6433 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
6434                                 unsigned char *pMemory,
6435                                 PFORMAT_STRING pFormat)
6436 {
6437    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6438
6439    /* nothing to do */
6440 }
6441
6442 /***********************************************************************
6443  *           NdrBaseTypeMarshall [internal]
6444  */
6445 static unsigned char *WINAPI NdrBaseTypeMarshall(
6446     PMIDL_STUB_MESSAGE pStubMsg,
6447     unsigned char *pMemory,
6448     PFORMAT_STRING pFormat)
6449 {
6450     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6451
6452     switch(*pFormat)
6453     {
6454     case RPC_FC_BYTE:
6455     case RPC_FC_CHAR:
6456     case RPC_FC_SMALL:
6457     case RPC_FC_USMALL:
6458         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
6459         TRACE("value: 0x%02x\n", *pMemory);
6460         break;
6461     case RPC_FC_WCHAR:
6462     case RPC_FC_SHORT:
6463     case RPC_FC_USHORT:
6464         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6465         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
6466         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
6467         break;
6468     case RPC_FC_LONG:
6469     case RPC_FC_ULONG:
6470     case RPC_FC_ERROR_STATUS_T:
6471     case RPC_FC_ENUM32:
6472         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG));
6473         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
6474         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
6475         break;
6476     case RPC_FC_FLOAT:
6477         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float));
6478         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
6479         break;
6480     case RPC_FC_DOUBLE:
6481         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double));
6482         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
6483         break;
6484     case RPC_FC_HYPER:
6485         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG));
6486         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
6487         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
6488         break;
6489     case RPC_FC_ENUM16:
6490         /* only 16-bits on the wire, so do a sanity check */
6491         if (*(UINT *)pMemory > SHRT_MAX)
6492             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
6493         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6494         if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6495             RpcRaiseException(RPC_X_BAD_STUB_DATA);
6496         *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
6497         pStubMsg->Buffer += sizeof(USHORT);
6498         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
6499         break;
6500     case RPC_FC_IGNORE:
6501         break;
6502     default:
6503         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6504     }
6505
6506     /* FIXME: what is the correct return value? */
6507     return NULL;
6508 }
6509
6510 /***********************************************************************
6511  *           NdrBaseTypeUnmarshall [internal]
6512  */
6513 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
6514     PMIDL_STUB_MESSAGE pStubMsg,
6515     unsigned char **ppMemory,
6516     PFORMAT_STRING pFormat,
6517     unsigned char fMustAlloc)
6518 {
6519     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6520
6521 #define BASE_TYPE_UNMARSHALL(type) \
6522         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
6523         if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
6524         { \
6525             *ppMemory = pStubMsg->Buffer; \
6526             TRACE("*ppMemory: %p\n", *ppMemory); \
6527             safe_buffer_increment(pStubMsg, sizeof(type)); \
6528         } \
6529         else \
6530         {  \
6531             if (fMustAlloc) \
6532                 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
6533             TRACE("*ppMemory: %p\n", *ppMemory); \
6534             safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \
6535         }
6536
6537     switch(*pFormat)
6538     {
6539     case RPC_FC_BYTE:
6540     case RPC_FC_CHAR:
6541     case RPC_FC_SMALL:
6542     case RPC_FC_USMALL:
6543         BASE_TYPE_UNMARSHALL(UCHAR);
6544         TRACE("value: 0x%02x\n", **ppMemory);
6545         break;
6546     case RPC_FC_WCHAR:
6547     case RPC_FC_SHORT:
6548     case RPC_FC_USHORT:
6549         BASE_TYPE_UNMARSHALL(USHORT);
6550         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6551         break;
6552     case RPC_FC_LONG:
6553     case RPC_FC_ULONG:
6554     case RPC_FC_ERROR_STATUS_T:
6555     case RPC_FC_ENUM32:
6556         BASE_TYPE_UNMARSHALL(ULONG);
6557         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6558         break;
6559    case RPC_FC_FLOAT:
6560         BASE_TYPE_UNMARSHALL(float);
6561         TRACE("value: %f\n", **(float **)ppMemory);
6562         break;
6563     case RPC_FC_DOUBLE:
6564         BASE_TYPE_UNMARSHALL(double);
6565         TRACE("value: %f\n", **(double **)ppMemory);
6566         break;
6567     case RPC_FC_HYPER:
6568         BASE_TYPE_UNMARSHALL(ULONGLONG);
6569         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
6570         break;
6571     case RPC_FC_ENUM16:
6572         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6573         if (!fMustAlloc && !*ppMemory)
6574             fMustAlloc = TRUE;
6575         if (fMustAlloc)
6576             *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
6577         if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
6578             RpcRaiseException(RPC_X_BAD_STUB_DATA);
6579         TRACE("*ppMemory: %p\n", *ppMemory);
6580         /* 16-bits on the wire, but int in memory */
6581         **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
6582         pStubMsg->Buffer += sizeof(USHORT);
6583         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6584         break;
6585     case RPC_FC_IGNORE:
6586         break;
6587     default:
6588         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6589     }
6590 #undef BASE_TYPE_UNMARSHALL
6591
6592     /* FIXME: what is the correct return value? */
6593
6594     return NULL;
6595 }
6596
6597 /***********************************************************************
6598  *           NdrBaseTypeBufferSize [internal]
6599  */
6600 static void WINAPI NdrBaseTypeBufferSize(
6601     PMIDL_STUB_MESSAGE pStubMsg,
6602     unsigned char *pMemory,
6603     PFORMAT_STRING pFormat)
6604 {
6605     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6606
6607     switch(*pFormat)
6608     {
6609     case RPC_FC_BYTE:
6610     case RPC_FC_CHAR:
6611     case RPC_FC_SMALL:
6612     case RPC_FC_USMALL:
6613         safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6614         break;
6615     case RPC_FC_WCHAR:
6616     case RPC_FC_SHORT:
6617     case RPC_FC_USHORT:
6618     case RPC_FC_ENUM16:
6619         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
6620         safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6621         break;
6622     case RPC_FC_LONG:
6623     case RPC_FC_ULONG:
6624     case RPC_FC_ENUM32:
6625         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
6626         safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6627         break;
6628     case RPC_FC_FLOAT:
6629         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
6630         safe_buffer_length_increment(pStubMsg, sizeof(float));
6631         break;
6632     case RPC_FC_DOUBLE:
6633         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
6634         safe_buffer_length_increment(pStubMsg, sizeof(double));
6635         break;
6636     case RPC_FC_HYPER:
6637         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
6638         safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6639         break;
6640     case RPC_FC_ERROR_STATUS_T:
6641         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
6642         safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6643         break;
6644     case RPC_FC_IGNORE:
6645         break;
6646     default:
6647         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6648     }
6649 }
6650
6651 /***********************************************************************
6652  *           NdrBaseTypeMemorySize [internal]
6653  */
6654 static ULONG WINAPI NdrBaseTypeMemorySize(
6655     PMIDL_STUB_MESSAGE pStubMsg,
6656     PFORMAT_STRING pFormat)
6657 {
6658     TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6659
6660     switch(*pFormat)
6661     {
6662     case RPC_FC_BYTE:
6663     case RPC_FC_CHAR:
6664     case RPC_FC_SMALL:
6665     case RPC_FC_USMALL:
6666         safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6667         pStubMsg->MemorySize += sizeof(UCHAR);
6668         return sizeof(UCHAR);
6669     case RPC_FC_WCHAR:
6670     case RPC_FC_SHORT:
6671     case RPC_FC_USHORT:
6672         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6673         safe_buffer_increment(pStubMsg, sizeof(USHORT));
6674         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(USHORT));
6675         pStubMsg->MemorySize += sizeof(USHORT);
6676         return sizeof(USHORT);
6677     case RPC_FC_LONG:
6678     case RPC_FC_ULONG:
6679     case RPC_FC_ENUM32:
6680         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
6681         safe_buffer_increment(pStubMsg, sizeof(ULONG));
6682         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONG));
6683         pStubMsg->MemorySize += sizeof(ULONG);
6684         return sizeof(ULONG);
6685     case RPC_FC_FLOAT:
6686         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
6687         safe_buffer_increment(pStubMsg, sizeof(float));
6688         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(float));
6689         pStubMsg->MemorySize += sizeof(float);
6690         return sizeof(float);
6691     case RPC_FC_DOUBLE:
6692         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
6693         safe_buffer_increment(pStubMsg, sizeof(double));
6694         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(double));
6695         pStubMsg->MemorySize += sizeof(double);
6696         return sizeof(double);
6697     case RPC_FC_HYPER:
6698         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
6699         safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6700         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONGLONG));
6701         pStubMsg->MemorySize += sizeof(ULONGLONG);
6702         return sizeof(ULONGLONG);
6703     case RPC_FC_ERROR_STATUS_T:
6704         ALIGN_POINTER(pStubMsg->Buffer, sizeof(error_status_t));
6705         safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6706         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(error_status_t));
6707         pStubMsg->MemorySize += sizeof(error_status_t);
6708         return sizeof(error_status_t);
6709     case RPC_FC_ENUM16:
6710         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6711         safe_buffer_increment(pStubMsg, sizeof(USHORT));
6712         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(UINT));
6713         pStubMsg->MemorySize += sizeof(UINT);
6714         return sizeof(UINT);
6715     case RPC_FC_IGNORE:
6716         ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
6717         pStubMsg->MemorySize += sizeof(void *);
6718         return sizeof(void *);
6719     default:
6720         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6721        return 0;
6722     }
6723 }
6724
6725 /***********************************************************************
6726  *           NdrBaseTypeFree [internal]
6727  */
6728 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6729                                 unsigned char *pMemory,
6730                                 PFORMAT_STRING pFormat)
6731 {
6732    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6733
6734    /* nothing to do */
6735 }
6736
6737 /***********************************************************************
6738  *           NdrContextHandleBufferSize [internal]
6739  */
6740 static void WINAPI NdrContextHandleBufferSize(
6741     PMIDL_STUB_MESSAGE pStubMsg,
6742     unsigned char *pMemory,
6743     PFORMAT_STRING pFormat)
6744 {
6745     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6746
6747     if (*pFormat != RPC_FC_BIND_CONTEXT)
6748     {
6749         ERR("invalid format type %x\n", *pFormat);
6750         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6751     }
6752     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
6753     safe_buffer_length_increment(pStubMsg, cbNDRContext);
6754 }
6755
6756 /***********************************************************************
6757  *           NdrContextHandleMarshall [internal]
6758  */
6759 static unsigned char *WINAPI NdrContextHandleMarshall(
6760     PMIDL_STUB_MESSAGE pStubMsg,
6761     unsigned char *pMemory,
6762     PFORMAT_STRING pFormat)
6763 {
6764     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6765
6766     if (*pFormat != RPC_FC_BIND_CONTEXT)
6767     {
6768         ERR("invalid format type %x\n", *pFormat);
6769         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6770     }
6771     TRACE("flags: 0x%02x\n", pFormat[1]);
6772
6773     if (pStubMsg->IsClient)
6774     {
6775         if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6776             NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6777         else
6778             NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
6779     }
6780     else
6781     {
6782         NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
6783         NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
6784         NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
6785     }
6786
6787     return NULL;
6788 }
6789
6790 /***********************************************************************
6791  *           NdrContextHandleUnmarshall [internal]
6792  */
6793 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6794     PMIDL_STUB_MESSAGE pStubMsg,
6795     unsigned char **ppMemory,
6796     PFORMAT_STRING pFormat,
6797     unsigned char fMustAlloc)
6798 {
6799     TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg,
6800         ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE");
6801
6802     if (*pFormat != RPC_FC_BIND_CONTEXT)
6803     {
6804         ERR("invalid format type %x\n", *pFormat);
6805         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6806     }
6807     TRACE("flags: 0x%02x\n", pFormat[1]);
6808
6809     if (pStubMsg->IsClient)
6810     {
6811         /* [out]-only or [ret] param */
6812         if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT)
6813             **(NDR_CCONTEXT **)ppMemory = NULL;
6814         NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
6815     }
6816     else
6817     {
6818         NDR_SCONTEXT ctxt;
6819         ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat);
6820         if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6821             *(void **)ppMemory = NDRSContextValue(ctxt);
6822         else
6823             *(void **)ppMemory = *NDRSContextValue(ctxt);
6824     }
6825
6826     return NULL;
6827 }
6828
6829 /***********************************************************************
6830  *           NdrClientContextMarshall [RPCRT4.@]
6831  */
6832 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6833                                      NDR_CCONTEXT ContextHandle,
6834                                      int fCheck)
6835 {
6836     TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
6837
6838     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
6839
6840     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6841     {
6842         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6843             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6844         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6845     }
6846
6847     /* FIXME: what does fCheck do? */
6848     NDRCContextMarshall(ContextHandle,
6849                         pStubMsg->Buffer);
6850
6851     pStubMsg->Buffer += cbNDRContext;
6852 }
6853
6854 /***********************************************************************
6855  *           NdrClientContextUnmarshall [RPCRT4.@]
6856  */
6857 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6858                                        NDR_CCONTEXT * pContextHandle,
6859                                        RPC_BINDING_HANDLE BindHandle)
6860 {
6861     TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
6862
6863     ALIGN_POINTER(pStubMsg->Buffer, 4);
6864
6865     if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
6866         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6867
6868     NDRCContextUnmarshall(pContextHandle,
6869                           BindHandle,
6870                           pStubMsg->Buffer,
6871                           pStubMsg->RpcMsg->DataRepresentation);
6872
6873     pStubMsg->Buffer += cbNDRContext;
6874 }
6875
6876 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6877                                      NDR_SCONTEXT ContextHandle,
6878                                      NDR_RUNDOWN RundownRoutine )
6879 {
6880     TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
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     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6892                          pStubMsg->Buffer, RundownRoutine, NULL,
6893                          RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6894     pStubMsg->Buffer += cbNDRContext;
6895 }
6896
6897 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
6898 {
6899     NDR_SCONTEXT ContextHandle;
6900
6901     TRACE("(%p)\n", pStubMsg);
6902
6903     ALIGN_POINTER(pStubMsg->Buffer, 4);
6904
6905     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6906     {
6907         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6908             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6909         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6910     }
6911
6912     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6913                                            pStubMsg->Buffer,
6914                                            pStubMsg->RpcMsg->DataRepresentation,
6915                                            NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6916     pStubMsg->Buffer += cbNDRContext;
6917
6918     return ContextHandle;
6919 }
6920
6921 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
6922                                  unsigned char* pMemory,
6923                                  PFORMAT_STRING pFormat)
6924 {
6925     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
6926 }
6927
6928 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
6929                                                PFORMAT_STRING pFormat)
6930 {
6931     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6932     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6933
6934     TRACE("(%p, %p)\n", pStubMsg, pFormat);
6935
6936     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6937         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6938     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6939         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6940     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6941     {
6942         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6943         if_id = &sif->InterfaceId;
6944     }
6945
6946     return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
6947                                   pStubMsg->RpcMsg->DataRepresentation, if_id,
6948                                   flags);
6949 }
6950
6951 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6952                                         NDR_SCONTEXT ContextHandle,
6953                                         NDR_RUNDOWN RundownRoutine,
6954                                         PFORMAT_STRING pFormat)
6955 {
6956     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6957     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6958
6959     TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
6960
6961     ALIGN_POINTER(pStubMsg->Buffer, 4);
6962
6963     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6964     {
6965         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6966             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6967         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6968     }
6969
6970     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6971         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6972     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6973         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6974     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6975     {
6976         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6977         if_id = &sif->InterfaceId;
6978     }
6979
6980     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6981                           pStubMsg->Buffer, RundownRoutine, if_id, flags);
6982     pStubMsg->Buffer += cbNDRContext;
6983 }
6984
6985 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6986                                                   PFORMAT_STRING pFormat)
6987 {
6988     NDR_SCONTEXT ContextHandle;
6989     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6990     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6991
6992     TRACE("(%p, %p)\n", pStubMsg, pFormat);
6993
6994     ALIGN_POINTER(pStubMsg->Buffer, 4);
6995
6996     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6997     {
6998         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6999             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7000         RpcRaiseException(RPC_X_BAD_STUB_DATA);
7001     }
7002
7003     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7004         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7005     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
7006         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7007     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7008     {
7009         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7010         if_id = &sif->InterfaceId;
7011     }
7012
7013     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
7014                                            pStubMsg->Buffer,
7015                                            pStubMsg->RpcMsg->DataRepresentation,
7016                                            if_id, flags);
7017     pStubMsg->Buffer += cbNDRContext;
7018
7019     return ContextHandle;
7020 }
7021
7022 /***********************************************************************
7023  *           NdrCorrelationInitialize [RPCRT4.@]
7024  *
7025  * Initializes correlation validity checking.
7026  *
7027  * PARAMS
7028  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
7029  *  pMemory     [I] Pointer to memory to use as a cache.
7030  *  CacheSize   [I] Size of the memory pointed to by pMemory.
7031  *  Flags       [I] Reserved. Set to zero.
7032  *
7033  * RETURNS
7034  *  Nothing.
7035  */
7036 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
7037 {
7038     FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
7039     pStubMsg->fHasNewCorrDesc = TRUE;
7040 }
7041
7042 /***********************************************************************
7043  *           NdrCorrelationPass [RPCRT4.@]
7044  *
7045  * Performs correlation validity checking.
7046  *
7047  * PARAMS
7048  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
7049  *
7050  * RETURNS
7051  *  Nothing.
7052  */
7053 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
7054 {
7055     FIXME("(%p): stub\n", pStubMsg);
7056 }
7057
7058 /***********************************************************************
7059  *           NdrCorrelationFree [RPCRT4.@]
7060  *
7061  * Frees any resources used while unmarshalling parameters that need
7062  * correlation validity checking.
7063  *
7064  * PARAMS
7065  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
7066  *
7067  * RETURNS
7068  *  Nothing.
7069  */
7070 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
7071 {
7072     FIXME("(%p): stub\n", pStubMsg);
7073 }