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