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