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