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