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