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