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