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