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