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