rpcrt4: Implement encapsulated union NDR functions.
[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 + (i * stride);
1141       unsigned char *bufbase = Mark + (i * stride);
1142       unsigned u;
1143       /* ofs doesn't seem to matter in this context */
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 + (i * stride);
1214       unsigned char *bufbase = Mark + (i * stride);
1215       unsigned u;
1216       for (u=0; u<count; u++,info+=8) {
1217         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1218         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1219         PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, TRUE);
1220       }
1221     }
1222     pFormat += 8 * count;
1223   }
1224
1225   return NULL;
1226 }
1227
1228 /***********************************************************************
1229  *           EmbeddedPointerBufferSize
1230  */
1231 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1232                                       unsigned char *pMemory,
1233                                       PFORMAT_STRING pFormat)
1234 {
1235   unsigned long Offset = pStubMsg->Offset;
1236   unsigned ofs, rep, count, stride, xofs;
1237   unsigned i;
1238
1239   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1240
1241   if (pStubMsg->IgnoreEmbeddedPointers) return;
1242
1243   if (*pFormat != RPC_FC_PP) return;
1244   pFormat += 2;
1245
1246   while (pFormat[0] != RPC_FC_END) {
1247     switch (pFormat[0]) {
1248     default:
1249       FIXME("unknown repeat type %d\n", pFormat[0]);
1250     case RPC_FC_NO_REPEAT:
1251       rep = 1;
1252       stride = 0;
1253       ofs = 0;
1254       count = 1;
1255       xofs = 0;
1256       pFormat += 2;
1257       break;
1258     case RPC_FC_FIXED_REPEAT:
1259       rep = *(const WORD*)&pFormat[2];
1260       stride = *(const WORD*)&pFormat[4];
1261       ofs = *(const WORD*)&pFormat[6];
1262       count = *(const WORD*)&pFormat[8];
1263       xofs = 0;
1264       pFormat += 10;
1265       break;
1266     case RPC_FC_VARIABLE_REPEAT:
1267       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1268       stride = *(const WORD*)&pFormat[2];
1269       ofs = *(const WORD*)&pFormat[4];
1270       count = *(const WORD*)&pFormat[6];
1271       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1272       pFormat += 8;
1273       break;
1274     }
1275     /* ofs doesn't seem to matter in this context */
1276     for (i = 0; i < rep; i++) {
1277       PFORMAT_STRING info = pFormat;
1278       unsigned char *membase = pMemory + (i * stride);
1279       unsigned u;
1280       for (u=0; u<count; u++,info+=8) {
1281         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1282         unsigned char *saved_memory = pStubMsg->Memory;
1283
1284         pStubMsg->Memory = pMemory;
1285         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1286         pStubMsg->Memory = saved_memory;
1287       }
1288     }
1289     pFormat += 8 * count;
1290   }
1291 }
1292
1293 /***********************************************************************
1294  *           EmbeddedPointerMemorySize [internal]
1295  */
1296 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1297                                                PFORMAT_STRING pFormat)
1298 {
1299   unsigned long Offset = pStubMsg->Offset;
1300   unsigned char *Mark = pStubMsg->BufferMark;
1301   unsigned ofs, rep, count, stride, xofs;
1302   unsigned i;
1303
1304   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1305
1306   if (*pFormat != RPC_FC_PP) return 0;
1307   pFormat += 2;
1308
1309   while (pFormat[0] != RPC_FC_END) {
1310     switch (pFormat[0]) {
1311     default:
1312       FIXME("unknown repeat type %d\n", pFormat[0]);
1313     case RPC_FC_NO_REPEAT:
1314       rep = 1;
1315       stride = 0;
1316       ofs = 0;
1317       count = 1;
1318       xofs = 0;
1319       pFormat += 2;
1320       break;
1321     case RPC_FC_FIXED_REPEAT:
1322       rep = *(const WORD*)&pFormat[2];
1323       stride = *(const WORD*)&pFormat[4];
1324       ofs = *(const WORD*)&pFormat[6];
1325       count = *(const WORD*)&pFormat[8];
1326       xofs = 0;
1327       pFormat += 10;
1328       break;
1329     case RPC_FC_VARIABLE_REPEAT:
1330       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1331       stride = *(const WORD*)&pFormat[2];
1332       ofs = *(const WORD*)&pFormat[4];
1333       count = *(const WORD*)&pFormat[6];
1334       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1335       pFormat += 8;
1336       break;
1337     }
1338     /* ofs doesn't seem to matter in this context */
1339     for (i = 0; i < rep; i++) {
1340       PFORMAT_STRING info = pFormat;
1341       unsigned char *bufbase = Mark + (i * stride);
1342       unsigned u;
1343       for (u=0; u<count; u++,info+=8) {
1344         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1345         PointerMemorySize(pStubMsg, bufptr, info+4);
1346       }
1347     }
1348     pFormat += 8 * count;
1349   }
1350
1351   return 0;
1352 }
1353
1354 /***********************************************************************
1355  *           EmbeddedPointerFree [internal]
1356  */
1357 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1358                                 unsigned char *pMemory,
1359                                 PFORMAT_STRING pFormat)
1360 {
1361   unsigned long Offset = pStubMsg->Offset;
1362   unsigned ofs, rep, count, stride, xofs;
1363   unsigned i;
1364
1365   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1366   if (*pFormat != RPC_FC_PP) return;
1367   pFormat += 2;
1368
1369   while (pFormat[0] != RPC_FC_END) {
1370     switch (pFormat[0]) {
1371     default:
1372       FIXME("unknown repeat type %d\n", pFormat[0]);
1373     case RPC_FC_NO_REPEAT:
1374       rep = 1;
1375       stride = 0;
1376       ofs = 0;
1377       count = 1;
1378       xofs = 0;
1379       pFormat += 2;
1380       break;
1381     case RPC_FC_FIXED_REPEAT:
1382       rep = *(const WORD*)&pFormat[2];
1383       stride = *(const WORD*)&pFormat[4];
1384       ofs = *(const WORD*)&pFormat[6];
1385       count = *(const WORD*)&pFormat[8];
1386       xofs = 0;
1387       pFormat += 10;
1388       break;
1389     case RPC_FC_VARIABLE_REPEAT:
1390       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1391       stride = *(const WORD*)&pFormat[2];
1392       ofs = *(const WORD*)&pFormat[4];
1393       count = *(const WORD*)&pFormat[6];
1394       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1395       pFormat += 8;
1396       break;
1397     }
1398     /* ofs doesn't seem to matter in this context */
1399     for (i = 0; i < rep; i++) {
1400       PFORMAT_STRING info = pFormat;
1401       unsigned char *membase = pMemory + (i * stride);
1402       unsigned u;
1403       for (u=0; u<count; u++,info+=8) {
1404         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1405         unsigned char *saved_memory = pStubMsg->Memory;
1406
1407         pStubMsg->Memory = pMemory;
1408         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1409         pStubMsg->Memory = saved_memory;
1410       }
1411     }
1412     pFormat += 8 * count;
1413   }
1414 }
1415
1416 /***********************************************************************
1417  *           NdrPointerMarshall [RPCRT4.@]
1418  */
1419 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1420                                           unsigned char *pMemory,
1421                                           PFORMAT_STRING pFormat)
1422 {
1423   unsigned char *Buffer;
1424
1425   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1426
1427   /* incremement the buffer here instead of in PointerMarshall,
1428    * as that is used by embedded pointers which already handle the incrementing
1429    * the buffer, and shouldn't write any additional pointer data to the wire */
1430   if (*pFormat != RPC_FC_RP)
1431   {
1432     ALIGN_POINTER(pStubMsg->Buffer, 4);
1433     Buffer = pStubMsg->Buffer;
1434     pStubMsg->Buffer += 4;
1435   }
1436   else
1437     Buffer = pStubMsg->Buffer;
1438
1439   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1440
1441   STD_OVERFLOW_CHECK(pStubMsg);
1442
1443   return NULL;
1444 }
1445
1446 /***********************************************************************
1447  *           NdrPointerUnmarshall [RPCRT4.@]
1448  */
1449 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1450                                             unsigned char **ppMemory,
1451                                             PFORMAT_STRING pFormat,
1452                                             unsigned char fMustAlloc)
1453 {
1454   unsigned char *Buffer;
1455
1456   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1457
1458   /* incremement the buffer here instead of in PointerUnmarshall,
1459    * as that is used by embedded pointers which already handle the incrementing
1460    * the buffer, and shouldn't read any additional pointer data from the
1461    * buffer */
1462   if (*pFormat != RPC_FC_RP)
1463   {
1464     ALIGN_POINTER(pStubMsg->Buffer, 4);
1465     Buffer = pStubMsg->Buffer;
1466     pStubMsg->Buffer += 4;
1467   }
1468   else
1469     Buffer = pStubMsg->Buffer;
1470
1471   PointerUnmarshall(pStubMsg, Buffer, ppMemory, pFormat, fMustAlloc);
1472
1473   return NULL;
1474 }
1475
1476 /***********************************************************************
1477  *           NdrPointerBufferSize [RPCRT4.@]
1478  */
1479 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1480                                       unsigned char *pMemory,
1481                                       PFORMAT_STRING pFormat)
1482 {
1483   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1484
1485   /* incremement the buffer length here instead of in PointerBufferSize,
1486    * as that is used by embedded pointers which already handle the buffer
1487    * length, and shouldn't write anything more to the wire */
1488   if (*pFormat != RPC_FC_RP)
1489   {
1490     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1491     pStubMsg->BufferLength += 4;
1492   }
1493
1494   PointerBufferSize(pStubMsg, pMemory, pFormat);
1495 }
1496
1497 /***********************************************************************
1498  *           NdrPointerMemorySize [RPCRT4.@]
1499  */
1500 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1501                                   PFORMAT_STRING pFormat)
1502 {
1503   /* unsigned size = *(LPWORD)(pFormat+2); */
1504   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1505   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1506   return 0;
1507 }
1508
1509 /***********************************************************************
1510  *           NdrPointerFree [RPCRT4.@]
1511  */
1512 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1513                            unsigned char *pMemory,
1514                            PFORMAT_STRING pFormat)
1515 {
1516   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1517   PointerFree(pStubMsg, pMemory, pFormat);
1518 }
1519
1520 /***********************************************************************
1521  *           NdrSimpleTypeMarshall [RPCRT4.@]
1522  */
1523 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1524                                    unsigned char FormatChar )
1525 {
1526     NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1527 }
1528
1529 /***********************************************************************
1530  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
1531  */
1532 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1533                                      unsigned char FormatChar )
1534 {
1535     NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0);
1536 }
1537
1538 /***********************************************************************
1539  *           NdrSimpleStructMarshall [RPCRT4.@]
1540  */
1541 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1542                                                unsigned char *pMemory,
1543                                                PFORMAT_STRING pFormat)
1544 {
1545   unsigned size = *(const WORD*)(pFormat+2);
1546   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1547
1548   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1549
1550   memcpy(pStubMsg->Buffer, pMemory, size);
1551   pStubMsg->BufferMark = pStubMsg->Buffer;
1552   pStubMsg->Buffer += size;
1553
1554   if (pFormat[0] != RPC_FC_STRUCT)
1555     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1556
1557   STD_OVERFLOW_CHECK(pStubMsg);
1558
1559   return NULL;
1560 }
1561
1562 /***********************************************************************
1563  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1564  */
1565 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1566                                                  unsigned char **ppMemory,
1567                                                  PFORMAT_STRING pFormat,
1568                                                  unsigned char fMustAlloc)
1569 {
1570   unsigned size = *(const WORD*)(pFormat+2);
1571   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1572
1573   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1574
1575   if (fMustAlloc) {
1576     *ppMemory = NdrAllocate(pStubMsg, size);
1577     memcpy(*ppMemory, pStubMsg->Buffer, size);
1578   } else {
1579     if (!pStubMsg->IsClient && !*ppMemory)
1580       /* for servers, we just point straight into the RPC buffer */
1581       *ppMemory = pStubMsg->Buffer;
1582     else
1583       /* for clients, memory should be provided by caller */
1584       memcpy(*ppMemory, pStubMsg->Buffer, size);
1585   }
1586
1587   pStubMsg->BufferMark = pStubMsg->Buffer;
1588   pStubMsg->Buffer += size;
1589
1590   if (pFormat[0] != RPC_FC_STRUCT)
1591     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1592
1593   return NULL;
1594 }
1595
1596 /***********************************************************************
1597  *           NdrSimpleStructBufferSize [RPCRT4.@]
1598  */
1599 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1600                                       unsigned char *pMemory,
1601                                       PFORMAT_STRING pFormat)
1602 {
1603   unsigned size = *(const WORD*)(pFormat+2);
1604   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1605
1606   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1607
1608   pStubMsg->BufferLength += size;
1609   if (pFormat[0] != RPC_FC_STRUCT)
1610     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1611 }
1612
1613 /***********************************************************************
1614  *           NdrSimpleStructMemorySize [RPCRT4.@]
1615  */
1616 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1617                                        PFORMAT_STRING pFormat)
1618 {
1619   unsigned short size = *(const WORD *)(pFormat+2);
1620
1621   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1622
1623   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1624   pStubMsg->MemorySize += size;
1625   pStubMsg->Buffer += size;
1626
1627   if (pFormat[0] != RPC_FC_STRUCT)
1628     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1629   return size;
1630 }
1631
1632 /***********************************************************************
1633  *           NdrSimpleStructFree [RPCRT4.@]
1634  */
1635 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1636                                 unsigned char *pMemory,
1637                                 PFORMAT_STRING pFormat)
1638 {
1639   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1640   if (pFormat[0] != RPC_FC_STRUCT)
1641     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1642 }
1643
1644
1645 static unsigned long EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg,
1646                                          PFORMAT_STRING pFormat)
1647 {
1648   switch (*pFormat) {
1649   case RPC_FC_STRUCT:
1650   case RPC_FC_PSTRUCT:
1651   case RPC_FC_CSTRUCT:
1652   case RPC_FC_BOGUS_STRUCT:
1653   case RPC_FC_SMFARRAY:
1654   case RPC_FC_SMVARRAY:
1655     return *(const WORD*)&pFormat[2];
1656   case RPC_FC_USER_MARSHAL:
1657     return *(const WORD*)&pFormat[4];
1658   case RPC_FC_NON_ENCAPSULATED_UNION:
1659     pFormat += 2;
1660     if (pStubMsg->fHasNewCorrDesc)
1661         pFormat += 6;
1662     else
1663         pFormat += 4;
1664
1665     pFormat += *(const SHORT*)pFormat;
1666     return *(const SHORT*)pFormat;
1667   case RPC_FC_IP:
1668     return sizeof(void *);
1669   default:
1670     FIXME("unhandled embedded type %02x\n", *pFormat);
1671   }
1672   return 0;
1673 }
1674
1675
1676 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1677                                                PFORMAT_STRING pFormat)
1678 {
1679   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1680
1681   if (!m)
1682   {
1683     FIXME("no memorysizer for data type=%02x\n", *pFormat);
1684     return 0;
1685   }
1686
1687   return m(pStubMsg, pFormat);
1688 }
1689
1690
1691 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1692                                        unsigned char *pMemory,
1693                                        PFORMAT_STRING pFormat,
1694                                        PFORMAT_STRING pPointer)
1695 {
1696   PFORMAT_STRING desc;
1697   NDR_MARSHALL m;
1698   unsigned long size;
1699
1700   while (*pFormat != RPC_FC_END) {
1701     switch (*pFormat) {
1702     case RPC_FC_BYTE:
1703     case RPC_FC_CHAR:
1704     case RPC_FC_SMALL:
1705     case RPC_FC_USMALL:
1706       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
1707       memcpy(pStubMsg->Buffer, pMemory, 1);
1708       pStubMsg->Buffer += 1;
1709       pMemory += 1;
1710       break;
1711     case RPC_FC_WCHAR:
1712     case RPC_FC_SHORT:
1713     case RPC_FC_USHORT:
1714       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1715       memcpy(pStubMsg->Buffer, pMemory, 2);
1716       pStubMsg->Buffer += 2;
1717       pMemory += 2;
1718       break;
1719     case RPC_FC_LONG:
1720     case RPC_FC_ULONG:
1721     case RPC_FC_ENUM32:
1722       TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
1723       memcpy(pStubMsg->Buffer, pMemory, 4);
1724       pStubMsg->Buffer += 4;
1725       pMemory += 4;
1726       break;
1727     case RPC_FC_HYPER:
1728       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1729       memcpy(pStubMsg->Buffer, pMemory, 8);
1730       pStubMsg->Buffer += 8;
1731       pMemory += 8;
1732       break;
1733     case RPC_FC_POINTER:
1734       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1735       NdrPointerMarshall(pStubMsg, *(unsigned char**)pMemory, pPointer);
1736       pPointer += 4;
1737       pMemory += 4;
1738       break;
1739     case RPC_FC_ALIGNM4:
1740       ALIGN_POINTER(pMemory, 4);
1741       break;
1742     case RPC_FC_ALIGNM8:
1743       ALIGN_POINTER(pMemory, 8);
1744       break;
1745     case RPC_FC_STRUCTPAD1:
1746     case RPC_FC_STRUCTPAD2:
1747     case RPC_FC_STRUCTPAD3:
1748     case RPC_FC_STRUCTPAD4:
1749     case RPC_FC_STRUCTPAD5:
1750     case RPC_FC_STRUCTPAD6:
1751     case RPC_FC_STRUCTPAD7:
1752       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1753       break;
1754     case RPC_FC_EMBEDDED_COMPLEX:
1755       pMemory += pFormat[1];
1756       pFormat += 2;
1757       desc = pFormat + *(const SHORT*)pFormat;
1758       size = EmbeddedComplexSize(pStubMsg, desc);
1759       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1760       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1761       if (m) m(pStubMsg, pMemory, desc);
1762       else FIXME("no marshaller for embedded type %02x\n", *desc);
1763       pMemory += size;
1764       pFormat += 2;
1765       continue;
1766     case RPC_FC_PAD:
1767       break;
1768     default:
1769       FIXME("unhandled format 0x%02x\n", *pFormat);
1770     }
1771     pFormat++;
1772   }
1773
1774   return pMemory;
1775 }
1776
1777 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1778                                          unsigned char *pMemory,
1779                                          PFORMAT_STRING pFormat,
1780                                          PFORMAT_STRING pPointer)
1781 {
1782   PFORMAT_STRING desc;
1783   NDR_UNMARSHALL m;
1784   unsigned long size;
1785
1786   while (*pFormat != RPC_FC_END) {
1787     switch (*pFormat) {
1788     case RPC_FC_BYTE:
1789     case RPC_FC_CHAR:
1790     case RPC_FC_SMALL:
1791     case RPC_FC_USMALL:
1792       memcpy(pMemory, pStubMsg->Buffer, 1);
1793       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
1794       pStubMsg->Buffer += 1;
1795       pMemory += 1;
1796       break;
1797     case RPC_FC_WCHAR:
1798     case RPC_FC_SHORT:
1799     case RPC_FC_USHORT:
1800       memcpy(pMemory, pStubMsg->Buffer, 2);
1801       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1802       pStubMsg->Buffer += 2;
1803       pMemory += 2;
1804       break;
1805     case RPC_FC_LONG:
1806     case RPC_FC_ULONG:
1807     case RPC_FC_ENUM32:
1808       memcpy(pMemory, pStubMsg->Buffer, 4);
1809       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
1810       pStubMsg->Buffer += 4;
1811       pMemory += 4;
1812       break;
1813     case RPC_FC_HYPER:
1814       memcpy(pMemory, pStubMsg->Buffer, 8);
1815       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1816       pStubMsg->Buffer += 8;
1817       pMemory += 8;
1818       break;
1819     case RPC_FC_POINTER:
1820       TRACE("pointer => %p\n", pMemory);
1821       NdrPointerUnmarshall(pStubMsg, (unsigned char**)pMemory, pPointer, TRUE);
1822       pPointer += 4;
1823       pMemory += 4;
1824       break;
1825     case RPC_FC_ALIGNM4:
1826       ALIGN_POINTER(pMemory, 4);
1827       break;
1828     case RPC_FC_ALIGNM8:
1829       ALIGN_POINTER(pMemory, 8);
1830       break;
1831     case RPC_FC_STRUCTPAD1:
1832     case RPC_FC_STRUCTPAD2:
1833     case RPC_FC_STRUCTPAD3:
1834     case RPC_FC_STRUCTPAD4:
1835     case RPC_FC_STRUCTPAD5:
1836     case RPC_FC_STRUCTPAD6:
1837     case RPC_FC_STRUCTPAD7:
1838       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1839       break;
1840     case RPC_FC_EMBEDDED_COMPLEX:
1841       pMemory += pFormat[1];
1842       pFormat += 2;
1843       desc = pFormat + *(const SHORT*)pFormat;
1844       size = EmbeddedComplexSize(pStubMsg, desc);
1845       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1846       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1847       memset(pMemory, 0, size); /* just in case */
1848       if (m) m(pStubMsg, &pMemory, desc, FALSE);
1849       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
1850       pMemory += size;
1851       pFormat += 2;
1852       continue;
1853     case RPC_FC_PAD:
1854       break;
1855     default:
1856       FIXME("unhandled format %d\n", *pFormat);
1857     }
1858     pFormat++;
1859   }
1860
1861   return pMemory;
1862 }
1863
1864 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1865                                          unsigned char *pMemory,
1866                                          PFORMAT_STRING pFormat,
1867                                          PFORMAT_STRING pPointer)
1868 {
1869   PFORMAT_STRING desc;
1870   NDR_BUFFERSIZE m;
1871   unsigned long size;
1872
1873   while (*pFormat != RPC_FC_END) {
1874     switch (*pFormat) {
1875     case RPC_FC_BYTE:
1876     case RPC_FC_CHAR:
1877     case RPC_FC_SMALL:
1878     case RPC_FC_USMALL:
1879       pStubMsg->BufferLength += 1;
1880       pMemory += 1;
1881       break;
1882     case RPC_FC_WCHAR:
1883     case RPC_FC_SHORT:
1884     case RPC_FC_USHORT:
1885       pStubMsg->BufferLength += 2;
1886       pMemory += 2;
1887       break;
1888     case RPC_FC_LONG:
1889     case RPC_FC_ULONG:
1890     case RPC_FC_ENUM32:
1891       pStubMsg->BufferLength += 4;
1892       pMemory += 4;
1893       break;
1894     case RPC_FC_HYPER:
1895       pStubMsg->BufferLength += 8;
1896       pMemory += 8;
1897       break;
1898     case RPC_FC_POINTER:
1899       NdrPointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
1900       pPointer += 4;
1901       pMemory += 4;
1902       break;
1903     case RPC_FC_ALIGNM4:
1904       ALIGN_POINTER(pMemory, 4);
1905       break;
1906     case RPC_FC_ALIGNM8:
1907       ALIGN_POINTER(pMemory, 8);
1908       break;
1909     case RPC_FC_STRUCTPAD1:
1910     case RPC_FC_STRUCTPAD2:
1911     case RPC_FC_STRUCTPAD3:
1912     case RPC_FC_STRUCTPAD4:
1913     case RPC_FC_STRUCTPAD5:
1914     case RPC_FC_STRUCTPAD6:
1915     case RPC_FC_STRUCTPAD7:
1916       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1917       break;
1918     case RPC_FC_EMBEDDED_COMPLEX:
1919       pMemory += pFormat[1];
1920       pFormat += 2;
1921       desc = pFormat + *(const SHORT*)pFormat;
1922       size = EmbeddedComplexSize(pStubMsg, desc);
1923       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1924       if (m) m(pStubMsg, pMemory, desc);
1925       else FIXME("no buffersizer for embedded type %02x\n", *desc);
1926       pMemory += size;
1927       pFormat += 2;
1928       continue;
1929     case RPC_FC_PAD:
1930       break;
1931     default:
1932       FIXME("unhandled format 0x%02x\n", *pFormat);
1933     }
1934     pFormat++;
1935   }
1936
1937   return pMemory;
1938 }
1939
1940 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
1941                                    unsigned char *pMemory,
1942                                    PFORMAT_STRING pFormat,
1943                                    PFORMAT_STRING pPointer)
1944 {
1945   PFORMAT_STRING desc;
1946   NDR_FREE m;
1947   unsigned long size;
1948
1949   while (*pFormat != RPC_FC_END) {
1950     switch (*pFormat) {
1951     case RPC_FC_BYTE:
1952     case RPC_FC_CHAR:
1953     case RPC_FC_SMALL:
1954     case RPC_FC_USMALL:
1955       pMemory += 1;
1956       break;
1957     case RPC_FC_WCHAR:
1958     case RPC_FC_SHORT:
1959     case RPC_FC_USHORT:
1960       pMemory += 2;
1961       break;
1962     case RPC_FC_LONG:
1963     case RPC_FC_ULONG:
1964     case RPC_FC_ENUM32:
1965       pMemory += 4;
1966       break;
1967     case RPC_FC_HYPER:
1968       pMemory += 8;
1969       break;
1970     case RPC_FC_POINTER:
1971       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
1972       pPointer += 4;
1973       pMemory += 4;
1974       break;
1975     case RPC_FC_ALIGNM4:
1976       ALIGN_POINTER(pMemory, 4);
1977       break;
1978     case RPC_FC_ALIGNM8:
1979       ALIGN_POINTER(pMemory, 8);
1980       break;
1981     case RPC_FC_STRUCTPAD1:
1982     case RPC_FC_STRUCTPAD2:
1983     case RPC_FC_STRUCTPAD3:
1984     case RPC_FC_STRUCTPAD4:
1985     case RPC_FC_STRUCTPAD5:
1986     case RPC_FC_STRUCTPAD6:
1987     case RPC_FC_STRUCTPAD7:
1988       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1989       break;
1990     case RPC_FC_EMBEDDED_COMPLEX:
1991       pMemory += pFormat[1];
1992       pFormat += 2;
1993       desc = pFormat + *(const SHORT*)pFormat;
1994       size = EmbeddedComplexSize(pStubMsg, desc);
1995       m = NdrFreer[*desc & NDR_TABLE_MASK];
1996       if (m) m(pStubMsg, pMemory, desc);
1997       else FIXME("no freer for embedded type %02x\n", *desc);
1998       pMemory += size;
1999       pFormat += 2;
2000       continue;
2001     case RPC_FC_PAD:
2002       break;
2003     default:
2004       FIXME("unhandled format 0x%02x\n", *pFormat);
2005     }
2006     pFormat++;
2007   }
2008
2009   return pMemory;
2010 }
2011
2012 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2013                                        PFORMAT_STRING pFormat)
2014 {
2015   PFORMAT_STRING desc;
2016   unsigned long size = 0;
2017
2018   while (*pFormat != RPC_FC_END) {
2019     switch (*pFormat) {
2020     case RPC_FC_BYTE:
2021     case RPC_FC_CHAR:
2022     case RPC_FC_SMALL:
2023     case RPC_FC_USMALL:
2024       size += 1;
2025       pStubMsg->Buffer += 1;
2026       break;
2027     case RPC_FC_WCHAR:
2028     case RPC_FC_SHORT:
2029     case RPC_FC_USHORT:
2030       size += 2;
2031       pStubMsg->Buffer += 2;
2032       break;
2033     case RPC_FC_LONG:
2034     case RPC_FC_ULONG:
2035     case RPC_FC_ENUM32:
2036       size += 4;
2037       pStubMsg->Buffer += 4;
2038       break;
2039     case RPC_FC_HYPER:
2040       size += 8;
2041       pStubMsg->Buffer += 8;
2042       break;
2043     case RPC_FC_POINTER:
2044       size += 4;
2045       pStubMsg->Buffer += 4;
2046       break;
2047     case RPC_FC_ALIGNM4:
2048       ALIGN_LENGTH(size, 4);
2049       ALIGN_POINTER(pStubMsg->Buffer, 4);
2050       break;
2051     case RPC_FC_ALIGNM8:
2052       ALIGN_LENGTH(size, 8);
2053       ALIGN_POINTER(pStubMsg->Buffer, 8);
2054       break;
2055     case RPC_FC_STRUCTPAD1:
2056     case RPC_FC_STRUCTPAD2:
2057     case RPC_FC_STRUCTPAD3:
2058     case RPC_FC_STRUCTPAD4:
2059     case RPC_FC_STRUCTPAD5:
2060     case RPC_FC_STRUCTPAD6:
2061     case RPC_FC_STRUCTPAD7:
2062       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2063       break;
2064     case RPC_FC_EMBEDDED_COMPLEX:
2065       size += pFormat[1];
2066       pFormat += 2;
2067       desc = pFormat + *(const SHORT*)pFormat;
2068       size += EmbeddedComplexMemorySize(pStubMsg, desc);
2069       pFormat += 2;
2070       continue;
2071     case RPC_FC_PAD:
2072       break;
2073     default:
2074       FIXME("unhandled format 0x%02x\n", *pFormat);
2075     }
2076     pFormat++;
2077   }
2078
2079   return size;
2080 }
2081
2082 /***********************************************************************
2083  *           NdrComplexStructMarshall [RPCRT4.@]
2084  */
2085 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2086                                                 unsigned char *pMemory,
2087                                                 PFORMAT_STRING pFormat)
2088 {
2089   PFORMAT_STRING conf_array = NULL;
2090   PFORMAT_STRING pointer_desc = NULL;
2091   unsigned char *OldMemory = pStubMsg->Memory;
2092
2093   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2094
2095   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2096
2097   pFormat += 4;
2098   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2099   pFormat += 2;
2100   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2101   pFormat += 2;
2102
2103   pStubMsg->Memory = pMemory;
2104
2105   ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2106
2107   if (conf_array)
2108     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2109
2110   pStubMsg->Memory = OldMemory;
2111
2112   STD_OVERFLOW_CHECK(pStubMsg);
2113
2114   return NULL;
2115 }
2116
2117 /***********************************************************************
2118  *           NdrComplexStructUnmarshall [RPCRT4.@]
2119  */
2120 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2121                                                   unsigned char **ppMemory,
2122                                                   PFORMAT_STRING pFormat,
2123                                                   unsigned char fMustAlloc)
2124 {
2125   unsigned size = *(const WORD*)(pFormat+2);
2126   PFORMAT_STRING conf_array = NULL;
2127   PFORMAT_STRING pointer_desc = NULL;
2128   unsigned char *pMemory;
2129
2130   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2131
2132   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2133
2134   if (fMustAlloc || !*ppMemory)
2135   {
2136     *ppMemory = NdrAllocate(pStubMsg, size);
2137     memset(*ppMemory, 0, size);
2138   }
2139
2140   pFormat += 4;
2141   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2142   pFormat += 2;
2143   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2144   pFormat += 2;
2145
2146   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2147
2148   if (conf_array)
2149     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2150
2151   return NULL;
2152 }
2153
2154 /***********************************************************************
2155  *           NdrComplexStructBufferSize [RPCRT4.@]
2156  */
2157 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2158                                        unsigned char *pMemory,
2159                                        PFORMAT_STRING pFormat)
2160 {
2161   PFORMAT_STRING conf_array = NULL;
2162   PFORMAT_STRING pointer_desc = NULL;
2163   unsigned char *OldMemory = pStubMsg->Memory;
2164
2165   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2166
2167   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2168
2169   pFormat += 4;
2170   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2171   pFormat += 2;
2172   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2173   pFormat += 2;
2174
2175   pStubMsg->Memory = pMemory;
2176
2177   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2178
2179   if (conf_array)
2180     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2181
2182   pStubMsg->Memory = OldMemory;
2183 }
2184
2185 /***********************************************************************
2186  *           NdrComplexStructMemorySize [RPCRT4.@]
2187  */
2188 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2189                                         PFORMAT_STRING pFormat)
2190 {
2191   unsigned size = *(const WORD*)(pFormat+2);
2192   PFORMAT_STRING conf_array = NULL;
2193   PFORMAT_STRING pointer_desc = NULL;
2194
2195   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2196
2197   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2198
2199   pFormat += 4;
2200   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2201   pFormat += 2;
2202   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2203   pFormat += 2;
2204
2205   ComplexStructMemorySize(pStubMsg, pFormat);
2206
2207   if (conf_array)
2208     NdrConformantArrayMemorySize(pStubMsg, conf_array);
2209
2210   return size;
2211 }
2212
2213 /***********************************************************************
2214  *           NdrComplexStructFree [RPCRT4.@]
2215  */
2216 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2217                                  unsigned char *pMemory,
2218                                  PFORMAT_STRING pFormat)
2219 {
2220   PFORMAT_STRING conf_array = NULL;
2221   PFORMAT_STRING pointer_desc = NULL;
2222   unsigned char *OldMemory = pStubMsg->Memory;
2223
2224   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2225
2226   pFormat += 4;
2227   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2228   pFormat += 2;
2229   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2230   pFormat += 2;
2231
2232   pStubMsg->Memory = pMemory;
2233
2234   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2235
2236   if (conf_array)
2237     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2238
2239   pStubMsg->Memory = OldMemory;
2240 }
2241
2242 /***********************************************************************
2243  *           NdrConformantArrayMarshall [RPCRT4.@]
2244  */
2245 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2246                                                   unsigned char *pMemory,
2247                                                   PFORMAT_STRING pFormat)
2248 {
2249   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2250   unsigned char alignment = pFormat[1] + 1;
2251
2252   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2253   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2254
2255   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2256
2257   WriteConformance(pStubMsg);
2258
2259   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2260
2261   size = safe_multiply(esize, pStubMsg->MaxCount);
2262   memcpy(pStubMsg->Buffer, pMemory, size);
2263   pStubMsg->BufferMark = pStubMsg->Buffer;
2264   pStubMsg->Buffer += size;
2265
2266   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2267
2268   STD_OVERFLOW_CHECK(pStubMsg);
2269
2270   return NULL;
2271 }
2272
2273 /***********************************************************************
2274  *           NdrConformantArrayUnmarshall [RPCRT4.@]
2275  */
2276 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2277                                                     unsigned char **ppMemory,
2278                                                     PFORMAT_STRING pFormat,
2279                                                     unsigned char fMustAlloc)
2280 {
2281   DWORD size, esize = *(const WORD*)(pFormat+2);
2282   unsigned char alignment = pFormat[1] + 1;
2283
2284   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2285   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2286
2287   pFormat = ReadConformance(pStubMsg, pFormat+4);
2288
2289   size = safe_multiply(esize, pStubMsg->MaxCount);
2290
2291   if (fMustAlloc || !*ppMemory)
2292     *ppMemory = NdrAllocate(pStubMsg, size);
2293
2294   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2295
2296   memcpy(*ppMemory, pStubMsg->Buffer, size);
2297
2298   pStubMsg->BufferMark = pStubMsg->Buffer;
2299   pStubMsg->Buffer += size;
2300
2301   EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2302
2303   return NULL;
2304 }
2305
2306 /***********************************************************************
2307  *           NdrConformantArrayBufferSize [RPCRT4.@]
2308  */
2309 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2310                                          unsigned char *pMemory,
2311                                          PFORMAT_STRING pFormat)
2312 {
2313   DWORD size, esize = *(const WORD*)(pFormat+2);
2314   unsigned char alignment = pFormat[1] + 1;
2315
2316   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2317   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2318
2319   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2320
2321   SizeConformance(pStubMsg);
2322
2323   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2324
2325   size = safe_multiply(esize, pStubMsg->MaxCount);
2326   /* conformance value plus array */
2327   pStubMsg->BufferLength += size;
2328
2329   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2330 }
2331
2332 /***********************************************************************
2333  *           NdrConformantArrayMemorySize [RPCRT4.@]
2334  */
2335 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2336                                           PFORMAT_STRING pFormat)
2337 {
2338   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2339   unsigned char alignment = pFormat[1] + 1;
2340
2341   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2342   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2343
2344   pFormat = ReadConformance(pStubMsg, pFormat+4);
2345   size = safe_multiply(esize, pStubMsg->MaxCount);
2346   pStubMsg->MemorySize += size;
2347
2348   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2349   pStubMsg->BufferMark = pStubMsg->Buffer;
2350   pStubMsg->Buffer += size;
2351
2352   EmbeddedPointerMemorySize(pStubMsg, pFormat);
2353
2354   return pStubMsg->MemorySize;
2355 }
2356
2357 /***********************************************************************
2358  *           NdrConformantArrayFree [RPCRT4.@]
2359  */
2360 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2361                                    unsigned char *pMemory,
2362                                    PFORMAT_STRING pFormat)
2363 {
2364   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2365   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2366
2367   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2368
2369   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2370 }
2371
2372
2373 /***********************************************************************
2374  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
2375  */
2376 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2377                                                          unsigned char* pMemory,
2378                                                          PFORMAT_STRING pFormat )
2379 {
2380     ULONG bufsize;
2381     unsigned char alignment = pFormat[1] + 1;
2382     DWORD esize = *(const WORD*)(pFormat+2);
2383
2384     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2385
2386     if (pFormat[0] != RPC_FC_CVARRAY)
2387     {
2388         ERR("invalid format type %x\n", pFormat[0]);
2389         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2390         return NULL;
2391     }
2392
2393     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2394     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2395
2396     WriteConformance(pStubMsg);
2397     WriteVariance(pStubMsg);
2398
2399     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2400
2401     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2402
2403     memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize);
2404     pStubMsg->BufferMark = pStubMsg->Buffer;
2405     pStubMsg->Buffer += bufsize;
2406
2407     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2408
2409     STD_OVERFLOW_CHECK(pStubMsg);
2410
2411     return NULL;
2412 }
2413
2414
2415 /***********************************************************************
2416  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
2417  */
2418 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2419                                                            unsigned char** ppMemory,
2420                                                            PFORMAT_STRING pFormat,
2421                                                            unsigned char fMustAlloc )
2422 {
2423     ULONG bufsize, memsize;
2424     unsigned char alignment = pFormat[1] + 1;
2425     DWORD esize = *(const WORD*)(pFormat+2);
2426
2427     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2428
2429     if (pFormat[0] != RPC_FC_CVARRAY)
2430     {
2431         ERR("invalid format type %x\n", pFormat[0]);
2432         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2433         return NULL;
2434     }
2435
2436     pFormat = ReadConformance(pStubMsg, pFormat+4);
2437     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2438
2439     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2440
2441     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2442     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2443
2444     if (!*ppMemory || fMustAlloc)
2445         *ppMemory = NdrAllocate(pStubMsg, memsize);
2446     memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, bufsize);
2447     pStubMsg->Buffer += bufsize;
2448
2449     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2450
2451     return NULL;
2452 }
2453
2454
2455 /***********************************************************************
2456  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
2457  */
2458 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2459                                            unsigned char* pMemory,
2460                                            PFORMAT_STRING pFormat )
2461 {
2462     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2463
2464     if (pFormat[0] != RPC_FC_CVARRAY)
2465     {
2466         ERR("invalid format type %x\n", pFormat[0]);
2467         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2468         return;
2469     }
2470
2471     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2472     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2473
2474     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2475 }
2476
2477
2478 /***********************************************************************
2479  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
2480  */
2481 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2482                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
2483 {
2484     unsigned char alignment = pFormat[1] + 1;
2485     DWORD esize = *(const WORD*)(pFormat+2);
2486
2487     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2488
2489     if (pFormat[0] != RPC_FC_CVARRAY)
2490     {
2491         ERR("invalid format type %x\n", pFormat[0]);
2492         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2493         return;
2494     }
2495
2496     /* compute size */
2497     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2498     /* compute length */
2499     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2500
2501     SizeConformance(pStubMsg);
2502     SizeVariance(pStubMsg);
2503
2504     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2505
2506     pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
2507
2508     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2509 }
2510
2511
2512 /***********************************************************************
2513  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
2514  */
2515 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2516                                                   PFORMAT_STRING pFormat )
2517 {
2518     FIXME( "stub\n" );
2519     return 0;
2520 }
2521
2522
2523 /***********************************************************************
2524  *           NdrComplexArrayMarshall [RPCRT4.@]
2525  */
2526 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2527                                                unsigned char *pMemory,
2528                                                PFORMAT_STRING pFormat)
2529 {
2530   ULONG i, count, def;
2531   BOOL variance_present;
2532   unsigned char alignment;
2533
2534   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2535
2536   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2537   {
2538       ERR("invalid format type %x\n", pFormat[0]);
2539       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2540       return NULL;
2541   }
2542
2543   alignment = pFormat[1] + 1;
2544
2545   def = *(const WORD*)&pFormat[2];
2546   pFormat += 4;
2547
2548   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2549   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2550
2551   variance_present = IsConformanceOrVariancePresent(pFormat);
2552   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2553   TRACE("variance = %d\n", pStubMsg->ActualCount);
2554
2555   WriteConformance(pStubMsg);
2556   if (variance_present)
2557     WriteVariance(pStubMsg);
2558
2559   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2560
2561   count = pStubMsg->ActualCount;
2562   for (i = 0; i < count; i++)
2563     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2564
2565   STD_OVERFLOW_CHECK(pStubMsg);
2566
2567   return NULL;
2568 }
2569
2570 /***********************************************************************
2571  *           NdrComplexArrayUnmarshall [RPCRT4.@]
2572  */
2573 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2574                                                  unsigned char **ppMemory,
2575                                                  PFORMAT_STRING pFormat,
2576                                                  unsigned char fMustAlloc)
2577 {
2578   ULONG i, count, esize, memsize;
2579   unsigned char alignment;
2580   unsigned char *pMemory;
2581   unsigned char *Buffer;
2582
2583   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2584
2585   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2586   {
2587       ERR("invalid format type %x\n", pFormat[0]);
2588       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2589       return NULL;
2590   }
2591
2592   alignment = pFormat[1] + 1;
2593
2594   pFormat += 4;
2595
2596   pFormat = ReadConformance(pStubMsg, pFormat);
2597   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2598
2599   Buffer = pStubMsg->Buffer;
2600   pStubMsg->MemorySize = 0;
2601   esize = ComplexStructMemorySize(pStubMsg, pFormat);
2602   pStubMsg->Buffer = Buffer;
2603
2604   /* do multiply here instead of inside if block to verify MaxCount */
2605   memsize = safe_multiply(esize, pStubMsg->MaxCount);
2606   if (fMustAlloc || !*ppMemory)
2607   {
2608     *ppMemory = NdrAllocate(pStubMsg, memsize);
2609     memset(*ppMemory, 0, memsize);
2610   }
2611
2612   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2613
2614   pMemory = *ppMemory;
2615   count = pStubMsg->ActualCount;
2616   for (i = 0; i < count; i++)
2617     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
2618
2619   return NULL;
2620 }
2621
2622 /***********************************************************************
2623  *           NdrComplexArrayBufferSize [RPCRT4.@]
2624  */
2625 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2626                                       unsigned char *pMemory,
2627                                       PFORMAT_STRING pFormat)
2628 {
2629   ULONG i, count, def;
2630   unsigned char alignment;
2631   BOOL variance_present;
2632
2633   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2634
2635   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2636   {
2637       ERR("invalid format type %x\n", pFormat[0]);
2638       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2639       return;
2640   }
2641
2642   alignment = pFormat[1] + 1;
2643
2644   def = *(const WORD*)&pFormat[2];
2645   pFormat += 4;
2646
2647   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2648   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2649   SizeConformance(pStubMsg);
2650
2651   variance_present = IsConformanceOrVariancePresent(pFormat);
2652   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2653   TRACE("variance = %d\n", pStubMsg->ActualCount);
2654
2655   if (variance_present)
2656     SizeVariance(pStubMsg);
2657
2658   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2659
2660   count = pStubMsg->ActualCount;
2661   for (i = 0; i < count; i++)
2662     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
2663 }
2664
2665 /***********************************************************************
2666  *           NdrComplexArrayMemorySize [RPCRT4.@]
2667  */
2668 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2669                                        PFORMAT_STRING pFormat)
2670 {
2671   ULONG i, count, esize, SavedMemorySize, MemorySize;
2672   unsigned char alignment;
2673   unsigned char *Buffer;
2674
2675   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2676
2677   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2678   {
2679       ERR("invalid format type %x\n", pFormat[0]);
2680       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2681       return 0;
2682   }
2683
2684   alignment = pFormat[1] + 1;
2685
2686   pFormat += 4;
2687
2688   pFormat = ReadConformance(pStubMsg, pFormat);
2689   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2690
2691   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2692
2693   SavedMemorySize = pStubMsg->MemorySize;
2694
2695   Buffer = pStubMsg->Buffer;
2696   pStubMsg->MemorySize = 0;
2697   esize = ComplexStructMemorySize(pStubMsg, pFormat);
2698   pStubMsg->Buffer = Buffer;
2699
2700   MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
2701
2702   count = pStubMsg->ActualCount;
2703   for (i = 0; i < count; i++)
2704     ComplexStructMemorySize(pStubMsg, pFormat);
2705
2706   pStubMsg->MemorySize = SavedMemorySize;
2707
2708   pStubMsg->MemorySize += MemorySize;
2709   return MemorySize;
2710 }
2711
2712 /***********************************************************************
2713  *           NdrComplexArrayFree [RPCRT4.@]
2714  */
2715 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2716                                 unsigned char *pMemory,
2717                                 PFORMAT_STRING pFormat)
2718 {
2719   ULONG i, count, def;
2720
2721   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2722
2723   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2724   {
2725       ERR("invalid format type %x\n", pFormat[0]);
2726       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2727       return;
2728   }
2729
2730   def = *(const WORD*)&pFormat[2];
2731   pFormat += 4;
2732
2733   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2734   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2735
2736   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2737   TRACE("variance = %d\n", pStubMsg->ActualCount);
2738
2739   count = pStubMsg->ActualCount;
2740   for (i = 0; i < count; i++)
2741     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2742 }
2743
2744 static ULONG UserMarshalFlags(PMIDL_STUB_MESSAGE pStubMsg)
2745 {
2746   return MAKELONG(pStubMsg->dwDestContext,
2747                   pStubMsg->RpcMsg->DataRepresentation);
2748 }
2749
2750 #define USER_MARSHAL_PTR_PREFIX \
2751         ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
2752         ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
2753
2754 /***********************************************************************
2755  *           NdrUserMarshalMarshall [RPCRT4.@]
2756  */
2757 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2758                                               unsigned char *pMemory,
2759                                               PFORMAT_STRING pFormat)
2760 {
2761   unsigned flags = pFormat[1];
2762   unsigned index = *(const WORD*)&pFormat[2];
2763   ULONG uflag = UserMarshalFlags(pStubMsg);
2764   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2765   TRACE("index=%d\n", index);
2766
2767   if (flags & USER_MARSHAL_POINTER)
2768   {
2769     ALIGN_POINTER(pStubMsg->Buffer, 4);
2770     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
2771     pStubMsg->Buffer += 4;
2772     ALIGN_POINTER(pStubMsg->Buffer, 8);
2773   }
2774   else
2775     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2776
2777   pStubMsg->Buffer =
2778     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
2779       &uflag, pStubMsg->Buffer, pMemory);
2780
2781   STD_OVERFLOW_CHECK(pStubMsg);
2782
2783   return NULL;
2784 }
2785
2786 /***********************************************************************
2787  *           NdrUserMarshalUnmarshall [RPCRT4.@]
2788  */
2789 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2790                                                  unsigned char **ppMemory,
2791                                                  PFORMAT_STRING pFormat,
2792                                                  unsigned char fMustAlloc)
2793 {
2794   unsigned flags = pFormat[1];
2795   unsigned index = *(const WORD*)&pFormat[2];
2796   DWORD memsize = *(const WORD*)&pFormat[4];
2797   ULONG uflag = UserMarshalFlags(pStubMsg);
2798   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2799   TRACE("index=%d\n", index);
2800
2801   if (flags & USER_MARSHAL_POINTER)
2802   {
2803     ALIGN_POINTER(pStubMsg->Buffer, 4);
2804     /* skip pointer prefix */
2805     pStubMsg->Buffer += 4;
2806     ALIGN_POINTER(pStubMsg->Buffer, 8);
2807   }
2808   else
2809     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2810
2811   if (fMustAlloc || !*ppMemory)
2812     *ppMemory = NdrAllocate(pStubMsg, memsize);
2813
2814   pStubMsg->Buffer =
2815     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
2816       &uflag, pStubMsg->Buffer, *ppMemory);
2817
2818   return NULL;
2819 }
2820
2821 /***********************************************************************
2822  *           NdrUserMarshalBufferSize [RPCRT4.@]
2823  */
2824 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2825                                       unsigned char *pMemory,
2826                                       PFORMAT_STRING pFormat)
2827 {
2828   unsigned flags = pFormat[1];
2829   unsigned index = *(const WORD*)&pFormat[2];
2830   DWORD bufsize = *(const WORD*)&pFormat[6];
2831   ULONG uflag = UserMarshalFlags(pStubMsg);
2832   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2833   TRACE("index=%d\n", index);
2834
2835   if (flags & USER_MARSHAL_POINTER)
2836   {
2837     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2838     /* skip pointer prefix */
2839     pStubMsg->BufferLength += 4;
2840     ALIGN_LENGTH(pStubMsg->BufferLength, 8);
2841   }
2842   else
2843     ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
2844
2845   if (bufsize) {
2846     TRACE("size=%d\n", bufsize);
2847     pStubMsg->BufferLength += bufsize;
2848     return;
2849   }
2850
2851   pStubMsg->BufferLength =
2852     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
2853       &uflag, pStubMsg->BufferLength, pMemory);
2854 }
2855
2856 /***********************************************************************
2857  *           NdrUserMarshalMemorySize [RPCRT4.@]
2858  */
2859 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2860                                       PFORMAT_STRING pFormat)
2861 {
2862   unsigned flags = pFormat[1];
2863   unsigned index = *(const WORD*)&pFormat[2];
2864   DWORD memsize = *(const WORD*)&pFormat[4];
2865   DWORD bufsize = *(const WORD*)&pFormat[6];
2866
2867   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2868   TRACE("index=%d\n", index);
2869
2870   pStubMsg->MemorySize += memsize;
2871
2872   if (flags & USER_MARSHAL_POINTER)
2873   {
2874     ALIGN_POINTER(pStubMsg->Buffer, 4);
2875     /* skip pointer prefix */
2876     pStubMsg->Buffer += 4;
2877     ALIGN_POINTER(pStubMsg->Buffer, 8);
2878   }
2879   else
2880     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2881
2882   pStubMsg->Buffer += bufsize;
2883
2884   return pStubMsg->MemorySize;
2885 }
2886
2887 /***********************************************************************
2888  *           NdrUserMarshalFree [RPCRT4.@]
2889  */
2890 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
2891                                 unsigned char *pMemory,
2892                                 PFORMAT_STRING pFormat)
2893 {
2894 /*  unsigned flags = pFormat[1]; */
2895   unsigned index = *(const WORD*)&pFormat[2];
2896   ULONG uflag = UserMarshalFlags(pStubMsg);
2897   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2898   TRACE("index=%d\n", index);
2899
2900   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
2901     &uflag, pMemory);
2902 }
2903
2904 /***********************************************************************
2905  *           NdrClearOutParameters [RPCRT4.@]
2906  */
2907 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
2908                                   PFORMAT_STRING pFormat,
2909                                   void *ArgAddr)
2910 {
2911   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
2912 }
2913
2914 /***********************************************************************
2915  *           NdrConvert [RPCRT4.@]
2916  */
2917 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
2918 {
2919   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
2920   /* FIXME: since this stub doesn't do any converting, the proper behavior
2921      is to raise an exception */
2922 }
2923
2924 /***********************************************************************
2925  *           NdrConvert2 [RPCRT4.@]
2926  */
2927 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
2928 {
2929   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
2930     pStubMsg, pFormat, NumberParams);
2931   /* FIXME: since this stub doesn't do any converting, the proper behavior
2932      is to raise an exception */
2933 }
2934
2935 #include "pshpack1.h"
2936 typedef struct _NDR_CSTRUCT_FORMAT
2937 {
2938     unsigned char type;
2939     unsigned char alignment;
2940     unsigned short memory_size;
2941     short offset_to_array_description;
2942 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
2943 #include "poppack.h"
2944
2945 /***********************************************************************
2946  *           NdrConformantStructMarshall [RPCRT4.@]
2947  */
2948 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2949                                 unsigned char *pMemory,
2950                                 PFORMAT_STRING pFormat)
2951 {
2952     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
2953     PFORMAT_STRING pCArrayFormat;
2954     ULONG esize, bufsize;
2955
2956     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2957
2958     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2959     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2960     {
2961         ERR("invalid format type %x\n", pCStructFormat->type);
2962         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2963         return NULL;
2964     }
2965
2966     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
2967         pCStructFormat->offset_to_array_description;
2968     if (*pCArrayFormat != RPC_FC_CARRAY)
2969     {
2970         ERR("invalid array format type %x\n", pCStructFormat->type);
2971         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2972         return NULL;
2973     }
2974     esize = *(const WORD*)(pCArrayFormat+2);
2975
2976     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
2977                        pCArrayFormat + 4, 0);
2978
2979     WriteConformance(pStubMsg);
2980
2981     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
2982
2983     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2984
2985     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
2986     /* copy constant sized part of struct */
2987     pStubMsg->BufferMark = pStubMsg->Buffer;
2988     memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size + bufsize);
2989     pStubMsg->Buffer += pCStructFormat->memory_size + bufsize;
2990
2991     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2992         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2993
2994     STD_OVERFLOW_CHECK(pStubMsg);
2995
2996     return NULL;
2997 }
2998
2999 /***********************************************************************
3000  *           NdrConformantStructUnmarshall [RPCRT4.@]
3001  */
3002 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3003                                 unsigned char **ppMemory,
3004                                 PFORMAT_STRING pFormat,
3005                                 unsigned char fMustAlloc)
3006 {
3007     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3008     PFORMAT_STRING pCArrayFormat;
3009     ULONG esize, bufsize;
3010
3011     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3012
3013     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3014     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3015     {
3016         ERR("invalid format type %x\n", pCStructFormat->type);
3017         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3018         return NULL;
3019     }
3020     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3021         pCStructFormat->offset_to_array_description;
3022     if (*pCArrayFormat != RPC_FC_CARRAY)
3023     {
3024         ERR("invalid array format type %x\n", pCStructFormat->type);
3025         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3026         return NULL;
3027     }
3028     esize = *(const WORD*)(pCArrayFormat+2);
3029
3030     pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
3031
3032     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3033
3034     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3035
3036     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3037     /* work out how much memory to allocate if we need to do so */
3038     if (!*ppMemory || fMustAlloc)
3039     {
3040         SIZE_T size = pCStructFormat->memory_size + bufsize;
3041         *ppMemory = NdrAllocate(pStubMsg, size);
3042     }
3043
3044     /* now copy the data */
3045     pStubMsg->BufferMark = pStubMsg->Buffer;
3046     memcpy(*ppMemory, pStubMsg->Buffer, pCStructFormat->memory_size + bufsize);
3047     pStubMsg->Buffer += pCStructFormat->memory_size + bufsize;
3048
3049     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3050         EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3051
3052     return NULL;
3053 }
3054
3055 /***********************************************************************
3056  *           NdrConformantStructBufferSize [RPCRT4.@]
3057  */
3058 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3059                                 unsigned char *pMemory,
3060                                 PFORMAT_STRING pFormat)
3061 {
3062     const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3063     PFORMAT_STRING pCArrayFormat;
3064     ULONG esize;
3065
3066     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3067
3068     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3069     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3070     {
3071         ERR("invalid format type %x\n", pCStructFormat->type);
3072         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3073         return;
3074     }
3075     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3076         pCStructFormat->offset_to_array_description;
3077     if (*pCArrayFormat != RPC_FC_CARRAY)
3078     {
3079         ERR("invalid array format type %x\n", pCStructFormat->type);
3080         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3081         return;
3082     }
3083     esize = *(const WORD*)(pCArrayFormat+2);
3084
3085     pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
3086     SizeConformance(pStubMsg);
3087
3088     ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
3089
3090     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3091
3092     pStubMsg->BufferLength += pCStructFormat->memory_size +
3093         safe_multiply(pStubMsg->MaxCount, esize);
3094
3095     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3096         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3097 }
3098
3099 /***********************************************************************
3100  *           NdrConformantStructMemorySize [RPCRT4.@]
3101  */
3102 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3103                                 PFORMAT_STRING pFormat)
3104 {
3105     FIXME("stub\n");
3106     return 0;
3107 }
3108
3109 /***********************************************************************
3110  *           NdrConformantStructFree [RPCRT4.@]
3111  */
3112 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3113                                 unsigned char *pMemory,
3114                                 PFORMAT_STRING pFormat)
3115 {
3116     FIXME("stub\n");
3117 }
3118
3119 /***********************************************************************
3120  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
3121  */
3122 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3123                                 unsigned char *pMemory,
3124                                 PFORMAT_STRING pFormat)
3125 {
3126     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3127     PFORMAT_STRING pCVArrayFormat;
3128     ULONG esize, bufsize;
3129
3130     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3131
3132     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3133     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3134     {
3135         ERR("invalid format type %x\n", pCVStructFormat->type);
3136         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3137         return NULL;
3138     }
3139
3140     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3141         pCVStructFormat->offset_to_array_description;
3142     switch (*pCVArrayFormat)
3143     {
3144     case RPC_FC_CVARRAY:
3145         esize = *(const WORD*)(pCVArrayFormat+2);
3146
3147         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3148                                             pCVArrayFormat + 4, 0);
3149         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3150                                          pCVArrayFormat, 0);
3151         break;
3152     case RPC_FC_C_CSTRING:
3153         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3154         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3155         esize = sizeof(char);
3156         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3157             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3158                                                 pCVArrayFormat + 2, 0);
3159         else
3160             pStubMsg->MaxCount = pStubMsg->ActualCount;
3161         break;
3162     case RPC_FC_C_WSTRING:
3163         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3164         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3165         esize = sizeof(WCHAR);
3166         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3167             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3168                                                 pCVArrayFormat + 2, 0);
3169         else
3170             pStubMsg->MaxCount = pStubMsg->ActualCount;
3171         break;
3172     default:
3173         ERR("invalid array format type %x\n", *pCVArrayFormat);
3174         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3175         return NULL;
3176     }
3177
3178     WriteConformance(pStubMsg);
3179
3180     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3181
3182     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3183
3184     /* write constant sized part */
3185     pStubMsg->BufferMark = pStubMsg->Buffer;
3186     memcpy(pStubMsg->Buffer, pMemory, pCVStructFormat->memory_size);
3187     pStubMsg->Buffer += pCVStructFormat->memory_size;
3188
3189     WriteVariance(pStubMsg);
3190
3191     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3192
3193     /* write array part */
3194     memcpy(pStubMsg->Buffer, pMemory + pCVStructFormat->memory_size, bufsize);
3195     pStubMsg->Buffer += bufsize;
3196
3197     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3198
3199     STD_OVERFLOW_CHECK(pStubMsg);
3200
3201     return NULL;
3202 }
3203
3204 /***********************************************************************
3205  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
3206  */
3207 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3208                                 unsigned char **ppMemory,
3209                                 PFORMAT_STRING pFormat,
3210                                 unsigned char fMustAlloc)
3211 {
3212     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3213     PFORMAT_STRING pCVArrayFormat;
3214     ULONG esize, bufsize;
3215     unsigned char cvarray_type;
3216
3217     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3218
3219     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3220     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3221     {
3222         ERR("invalid format type %x\n", pCVStructFormat->type);
3223         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3224         return NULL;
3225     }
3226
3227     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3228         pCVStructFormat->offset_to_array_description;
3229     cvarray_type = *pCVArrayFormat;
3230     switch (cvarray_type)
3231     {
3232     case RPC_FC_CVARRAY:
3233         esize = *(const WORD*)(pCVArrayFormat+2);
3234         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3235         break;
3236     case RPC_FC_C_CSTRING:
3237         esize = sizeof(char);
3238         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3239             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3240         else
3241             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3242         break;
3243     case RPC_FC_C_WSTRING:
3244         esize = sizeof(WCHAR);
3245         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3246             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3247         else
3248             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3249         break;
3250     default:
3251         ERR("invalid array format type %x\n", *pCVArrayFormat);
3252         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3253         return NULL;
3254     }
3255
3256     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3257
3258     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3259
3260     /* work out how much memory to allocate if we need to do so */
3261     if (!*ppMemory || fMustAlloc)
3262     {
3263         SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3264         *ppMemory = NdrAllocate(pStubMsg, size);
3265     }
3266
3267     /* copy the constant data */
3268     pStubMsg->BufferMark = pStubMsg->Buffer;
3269     memcpy(*ppMemory, pStubMsg->Buffer, pCVStructFormat->memory_size);
3270     pStubMsg->Buffer += pCVStructFormat->memory_size;
3271
3272     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3273
3274     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3275
3276     if ((cvarray_type == RPC_FC_C_CSTRING) ||
3277         (cvarray_type == RPC_FC_C_WSTRING))
3278     {
3279         ULONG i;
3280         /* strings must always have null terminating bytes */
3281         if (bufsize < esize)
3282         {
3283             ERR("invalid string length of %d\n", pStubMsg->ActualCount);
3284             RpcRaiseException(RPC_S_INVALID_BOUND);
3285             return NULL;
3286         }
3287         for (i = bufsize - esize; i < bufsize; i++)
3288             if (pStubMsg->Buffer[i] != 0)
3289             {
3290                 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
3291                     i, pStubMsg->Buffer[i]);
3292                 RpcRaiseException(RPC_S_INVALID_BOUND);
3293                 return NULL;
3294             }
3295     }
3296
3297     /* copy the array data */
3298     memcpy(*ppMemory + pCVStructFormat->memory_size, pStubMsg->Buffer,
3299            bufsize);
3300     pStubMsg->Buffer += bufsize;
3301
3302     if (cvarray_type == RPC_FC_C_CSTRING)
3303         TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3304     else if (cvarray_type == RPC_FC_C_WSTRING)
3305         TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3306
3307     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3308
3309     return NULL;
3310 }
3311
3312 /***********************************************************************
3313  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
3314  */
3315 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3316                                 unsigned char *pMemory,
3317                                 PFORMAT_STRING pFormat)
3318 {
3319     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3320     PFORMAT_STRING pCVArrayFormat;
3321     ULONG esize;
3322
3323     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3324
3325     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3326     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3327     {
3328         ERR("invalid format type %x\n", pCVStructFormat->type);
3329         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3330         return;
3331     }
3332
3333     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3334         pCVStructFormat->offset_to_array_description;
3335     switch (*pCVArrayFormat)
3336     {
3337     case RPC_FC_CVARRAY:
3338         esize = *(const WORD*)(pCVArrayFormat+2);
3339
3340         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3341                                             pCVArrayFormat + 4, 0);
3342         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3343                                          pCVArrayFormat, 0);
3344         break;
3345     case RPC_FC_C_CSTRING:
3346         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3347         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3348         esize = sizeof(char);
3349         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3350             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3351                                                 pCVArrayFormat + 2, 0);
3352         else
3353             pStubMsg->MaxCount = pStubMsg->ActualCount;
3354         break;
3355     case RPC_FC_C_WSTRING:
3356         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3357         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3358         esize = sizeof(WCHAR);
3359         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3360             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3361                                                 pCVArrayFormat + 2, 0);
3362         else
3363             pStubMsg->MaxCount = pStubMsg->ActualCount;
3364         break;
3365     default:
3366         ERR("invalid array format type %x\n", *pCVArrayFormat);
3367         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3368         return;
3369     }
3370
3371     SizeConformance(pStubMsg);
3372
3373     ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
3374
3375     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3376
3377     pStubMsg->BufferLength += pCVStructFormat->memory_size;
3378     SizeVariance(pStubMsg);
3379     pStubMsg->BufferLength += safe_multiply(pStubMsg->MaxCount, esize);
3380
3381     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3382 }
3383
3384 /***********************************************************************
3385  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
3386  */
3387 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3388                                 PFORMAT_STRING pFormat)
3389 {
3390     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3391     PFORMAT_STRING pCVArrayFormat;
3392     ULONG esize;
3393     unsigned char cvarray_type;
3394
3395     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3396
3397     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3398     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3399     {
3400         ERR("invalid format type %x\n", pCVStructFormat->type);
3401         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3402         return 0;
3403     }
3404
3405     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3406         pCVStructFormat->offset_to_array_description;
3407     cvarray_type = *pCVArrayFormat;
3408     switch (cvarray_type)
3409     {
3410     case RPC_FC_CVARRAY:
3411         esize = *(const WORD*)(pCVArrayFormat+2);
3412         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3413         break;
3414     case RPC_FC_C_CSTRING:
3415         esize = sizeof(char);
3416         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3417             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3418         else
3419             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3420         break;
3421     case RPC_FC_C_WSTRING:
3422         esize = sizeof(WCHAR);
3423         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3424             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3425         else
3426             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3427         break;
3428     default:
3429         ERR("invalid array format type %x\n", *pCVArrayFormat);
3430         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3431         return 0;
3432     }
3433
3434     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3435
3436     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3437
3438     pStubMsg->Buffer += pCVStructFormat->memory_size;
3439     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3440     pStubMsg->Buffer += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->ActualCount);
3441
3442     pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3443
3444     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3445
3446     return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3447 }
3448
3449 /***********************************************************************
3450  *           NdrConformantVaryingStructFree [RPCRT4.@]
3451  */
3452 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3453                                 unsigned char *pMemory,
3454                                 PFORMAT_STRING pFormat)
3455 {
3456     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3457     PFORMAT_STRING pCVArrayFormat;
3458     ULONG esize;
3459
3460     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3461
3462     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3463     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3464     {
3465         ERR("invalid format type %x\n", pCVStructFormat->type);
3466         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3467         return;
3468     }
3469
3470     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3471         pCVStructFormat->offset_to_array_description;
3472     switch (*pCVArrayFormat)
3473     {
3474     case RPC_FC_CVARRAY:
3475         esize = *(const WORD*)(pCVArrayFormat+2);
3476
3477         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3478                                             pCVArrayFormat + 4, 0);
3479         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3480                                          pCVArrayFormat, 0);
3481         break;
3482     case RPC_FC_C_CSTRING:
3483         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3484         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3485         esize = sizeof(char);
3486         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3487             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3488                                                 pCVArrayFormat + 2, 0);
3489         else
3490             pStubMsg->MaxCount = pStubMsg->ActualCount;
3491         break;
3492     case RPC_FC_C_WSTRING:
3493         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3494         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3495         esize = sizeof(WCHAR);
3496         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3497             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3498                                                 pCVArrayFormat + 2, 0);
3499         else
3500             pStubMsg->MaxCount = pStubMsg->ActualCount;
3501         break;
3502     default:
3503         ERR("invalid array format type %x\n", *pCVArrayFormat);
3504         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3505         return;
3506     }
3507
3508     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3509
3510     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3511 }
3512
3513 #include "pshpack1.h"
3514 typedef struct
3515 {
3516     unsigned char type;
3517     unsigned char alignment;
3518     unsigned short total_size;
3519 } NDR_SMFARRAY_FORMAT;
3520
3521 typedef struct
3522 {
3523     unsigned char type;
3524     unsigned char alignment;
3525     unsigned long total_size;
3526 } NDR_LGFARRAY_FORMAT;
3527 #include "poppack.h"
3528
3529 /***********************************************************************
3530  *           NdrFixedArrayMarshall [RPCRT4.@]
3531  */
3532 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3533                                 unsigned char *pMemory,
3534                                 PFORMAT_STRING pFormat)
3535 {
3536     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3537     unsigned long total_size;
3538
3539     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3540
3541     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3542         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3543     {
3544         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3545         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3546         return NULL;
3547     }
3548
3549     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3550
3551     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3552     {
3553         total_size = pSmFArrayFormat->total_size;
3554         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3555     }
3556     else
3557     {
3558         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3559         total_size = pLgFArrayFormat->total_size;
3560         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3561     }
3562
3563     memcpy(pStubMsg->Buffer, pMemory, total_size);
3564     pStubMsg->BufferMark = pStubMsg->Buffer;
3565     pStubMsg->Buffer += total_size;
3566
3567     pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3568
3569     return NULL;
3570 }
3571
3572 /***********************************************************************
3573  *           NdrFixedArrayUnmarshall [RPCRT4.@]
3574  */
3575 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3576                                 unsigned char **ppMemory,
3577                                 PFORMAT_STRING pFormat,
3578                                 unsigned char fMustAlloc)
3579 {
3580     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3581     unsigned long total_size;
3582
3583     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3584
3585     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3586         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3587     {
3588         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3589         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3590         return NULL;
3591     }
3592
3593     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3594
3595     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3596     {
3597         total_size = pSmFArrayFormat->total_size;
3598         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3599     }
3600     else
3601     {
3602         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3603         total_size = pLgFArrayFormat->total_size;
3604         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3605     }
3606
3607     if (fMustAlloc || !*ppMemory)
3608         *ppMemory = NdrAllocate(pStubMsg, total_size);
3609     memcpy(*ppMemory, pStubMsg->Buffer, total_size);
3610     pStubMsg->BufferMark = pStubMsg->Buffer;
3611     pStubMsg->Buffer += total_size;
3612
3613     pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3614
3615     return NULL;
3616 }
3617
3618 /***********************************************************************
3619  *           NdrFixedArrayBufferSize [RPCRT4.@]
3620  */
3621 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3622                                 unsigned char *pMemory,
3623                                 PFORMAT_STRING pFormat)
3624 {
3625     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3626     unsigned long total_size;
3627
3628     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3629
3630     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3631         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3632     {
3633         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3634         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3635         return;
3636     }
3637
3638     ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
3639
3640     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3641     {
3642         total_size = pSmFArrayFormat->total_size;
3643         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3644     }
3645     else
3646     {
3647         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3648         total_size = pLgFArrayFormat->total_size;
3649         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3650     }
3651     pStubMsg->BufferLength += total_size;
3652
3653     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3654 }
3655
3656 /***********************************************************************
3657  *           NdrFixedArrayMemorySize [RPCRT4.@]
3658  */
3659 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3660                                 PFORMAT_STRING pFormat)
3661 {
3662     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3663     ULONG total_size;
3664
3665     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3666
3667     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3668         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3669     {
3670         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3671         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3672         return 0;
3673     }
3674
3675     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3676
3677     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3678     {
3679         total_size = pSmFArrayFormat->total_size;
3680         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3681     }
3682     else
3683     {
3684         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3685         total_size = pLgFArrayFormat->total_size;
3686         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3687     }
3688     pStubMsg->BufferMark = pStubMsg->Buffer;
3689     pStubMsg->Buffer += total_size;
3690     pStubMsg->MemorySize += total_size;
3691
3692     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3693
3694     return total_size;
3695 }
3696
3697 /***********************************************************************
3698  *           NdrFixedArrayFree [RPCRT4.@]
3699  */
3700 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3701                                 unsigned char *pMemory,
3702                                 PFORMAT_STRING pFormat)
3703 {
3704     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3705
3706     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3707
3708     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3709         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3710     {
3711         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3712         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3713         return;
3714     }
3715
3716     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3717         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3718     else
3719     {
3720         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3721         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3722     }
3723
3724     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3725 }
3726
3727 /***********************************************************************
3728  *           NdrVaryingArrayMarshall [RPCRT4.@]
3729  */
3730 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3731                                 unsigned char *pMemory,
3732                                 PFORMAT_STRING pFormat)
3733 {
3734     unsigned char alignment;
3735     DWORD elements, esize;
3736     ULONG bufsize;
3737
3738     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3739
3740     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3741         (pFormat[0] != RPC_FC_LGVARRAY))
3742     {
3743         ERR("invalid format type %x\n", pFormat[0]);
3744         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3745         return NULL;
3746     }
3747
3748     alignment = pFormat[1] + 1;
3749
3750     if (pFormat[0] == RPC_FC_SMVARRAY)
3751     {
3752         pFormat += 2;
3753         pFormat += sizeof(WORD);
3754         elements = *(const WORD*)pFormat;
3755         pFormat += sizeof(WORD);
3756     }
3757     else
3758     {
3759         pFormat += 2;
3760         pFormat += sizeof(DWORD);
3761         elements = *(const DWORD*)pFormat;
3762         pFormat += sizeof(DWORD);
3763     }
3764
3765     esize = *(const WORD*)pFormat;
3766     pFormat += sizeof(WORD);
3767
3768     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3769     if ((pStubMsg->ActualCount > elements) ||
3770         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
3771     {
3772         RpcRaiseException(RPC_S_INVALID_BOUND);
3773         return NULL;
3774     }
3775
3776     WriteVariance(pStubMsg);
3777
3778     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3779
3780     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3781     memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize);
3782     pStubMsg->BufferMark = pStubMsg->Buffer;
3783     pStubMsg->Buffer += bufsize;
3784
3785     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3786
3787     STD_OVERFLOW_CHECK(pStubMsg);
3788
3789     return NULL;
3790 }
3791
3792 /***********************************************************************
3793  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
3794  */
3795 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3796                                 unsigned char **ppMemory,
3797                                 PFORMAT_STRING pFormat,
3798                                 unsigned char fMustAlloc)
3799 {
3800     unsigned char alignment;
3801     DWORD size, elements, esize;
3802     ULONG bufsize;
3803
3804     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3805
3806     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3807         (pFormat[0] != RPC_FC_LGVARRAY))
3808     {
3809         ERR("invalid format type %x\n", pFormat[0]);
3810         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3811         return NULL;
3812     }
3813
3814     alignment = pFormat[1] + 1;
3815
3816     if (pFormat[0] == RPC_FC_SMVARRAY)
3817     {
3818         pFormat += 2;
3819         size = *(const WORD*)pFormat;
3820         pFormat += sizeof(WORD);
3821         elements = *(const WORD*)pFormat;
3822         pFormat += sizeof(WORD);
3823     }
3824     else
3825     {
3826         pFormat += 2;
3827         size = *(const DWORD*)pFormat;
3828         pFormat += sizeof(DWORD);
3829         elements = *(const DWORD*)pFormat;
3830         pFormat += sizeof(DWORD);
3831     }
3832
3833     esize = *(const WORD*)pFormat;
3834     pFormat += sizeof(WORD);
3835
3836     pFormat = ReadVariance(pStubMsg, pFormat, elements);
3837
3838     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3839
3840     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3841
3842     if (!*ppMemory || fMustAlloc)
3843         *ppMemory = NdrAllocate(pStubMsg, size);
3844     memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, bufsize);
3845     pStubMsg->Buffer += bufsize;
3846
3847     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3848
3849     return NULL;
3850 }
3851
3852 /***********************************************************************
3853  *           NdrVaryingArrayBufferSize [RPCRT4.@]
3854  */
3855 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3856                                 unsigned char *pMemory,
3857                                 PFORMAT_STRING pFormat)
3858 {
3859     unsigned char alignment;
3860     DWORD elements, esize;
3861
3862     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3863
3864     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3865         (pFormat[0] != RPC_FC_LGVARRAY))
3866     {
3867         ERR("invalid format type %x\n", pFormat[0]);
3868         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3869         return;
3870     }
3871
3872     alignment = pFormat[1] + 1;
3873
3874     if (pFormat[0] == RPC_FC_SMVARRAY)
3875     {
3876         pFormat += 2;
3877         pFormat += sizeof(WORD);
3878         elements = *(const WORD*)pFormat;
3879         pFormat += sizeof(WORD);
3880     }
3881     else
3882     {
3883         pFormat += 2;
3884         pFormat += sizeof(DWORD);
3885         elements = *(const DWORD*)pFormat;
3886         pFormat += sizeof(DWORD);
3887     }
3888
3889     esize = *(const WORD*)pFormat;
3890     pFormat += sizeof(WORD);
3891
3892     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3893     if ((pStubMsg->ActualCount > elements) ||
3894         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
3895     {
3896         RpcRaiseException(RPC_S_INVALID_BOUND);
3897         return;
3898     }
3899
3900     SizeVariance(pStubMsg);
3901
3902     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3903
3904     pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
3905
3906     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3907 }
3908
3909 /***********************************************************************
3910  *           NdrVaryingArrayMemorySize [RPCRT4.@]
3911  */
3912 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3913                                 PFORMAT_STRING pFormat)
3914 {
3915     unsigned char alignment;
3916     DWORD size, elements, esize;
3917
3918     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3919
3920     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3921         (pFormat[0] != RPC_FC_LGVARRAY))
3922     {
3923         ERR("invalid format type %x\n", pFormat[0]);
3924         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3925         return 0;
3926     }
3927
3928     alignment = pFormat[1] + 1;
3929
3930     if (pFormat[0] == RPC_FC_SMVARRAY)
3931     {
3932         pFormat += 2;
3933         size = *(const WORD*)pFormat;
3934         pFormat += sizeof(WORD);
3935         elements = *(const WORD*)pFormat;
3936         pFormat += sizeof(WORD);
3937     }
3938     else
3939     {
3940         pFormat += 2;
3941         size = *(const DWORD*)pFormat;
3942         pFormat += sizeof(DWORD);
3943         elements = *(const DWORD*)pFormat;
3944         pFormat += sizeof(DWORD);
3945     }
3946
3947     esize = *(const WORD*)pFormat;
3948     pFormat += sizeof(WORD);
3949
3950     pFormat = ReadVariance(pStubMsg, pFormat, elements);
3951
3952     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3953
3954     pStubMsg->Buffer += safe_multiply(esize, pStubMsg->ActualCount);
3955     pStubMsg->MemorySize += size;
3956
3957     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3958
3959     return pStubMsg->MemorySize;
3960 }
3961
3962 /***********************************************************************
3963  *           NdrVaryingArrayFree [RPCRT4.@]
3964  */
3965 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3966                                 unsigned char *pMemory,
3967                                 PFORMAT_STRING pFormat)
3968 {
3969     unsigned char alignment;
3970     DWORD elements;
3971
3972     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3973
3974     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3975         (pFormat[0] != RPC_FC_LGVARRAY))
3976     {
3977         ERR("invalid format type %x\n", pFormat[0]);
3978         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3979         return;
3980     }
3981
3982     alignment = pFormat[1] + 1;
3983
3984     if (pFormat[0] == RPC_FC_SMVARRAY)
3985     {
3986         pFormat += 2;
3987         pFormat += sizeof(WORD);
3988         elements = *(const WORD*)pFormat;
3989         pFormat += sizeof(WORD);
3990     }
3991     else
3992     {
3993         pFormat += 2;
3994         pFormat += sizeof(DWORD);
3995         elements = *(const DWORD*)pFormat;
3996         pFormat += sizeof(DWORD);
3997     }
3998
3999     pFormat += sizeof(WORD);
4000
4001     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4002     if ((pStubMsg->ActualCount > elements) ||
4003         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4004     {
4005         RpcRaiseException(RPC_S_INVALID_BOUND);
4006         return;
4007     }
4008
4009     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4010 }
4011
4012 static ULONG get_discriminant(unsigned char fc, unsigned char *pMemory)
4013 {
4014     switch (fc)
4015     {
4016     case RPC_FC_BYTE:
4017     case RPC_FC_CHAR:
4018     case RPC_FC_SMALL:
4019     case RPC_FC_USMALL:
4020         return *(UCHAR *)pMemory;
4021     case RPC_FC_WCHAR:
4022     case RPC_FC_SHORT:
4023     case RPC_FC_USHORT:
4024         return *(USHORT *)pMemory;
4025     case RPC_FC_LONG:
4026     case RPC_FC_ULONG:
4027         return *(ULONG *)pMemory;
4028     default:
4029         FIXME("Unhandled base type: 0x%02x\n", fc);
4030         return 0;
4031     }
4032 }
4033
4034 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
4035                                                              unsigned long discriminant,
4036                                                              PFORMAT_STRING pFormat)
4037 {
4038     unsigned short num_arms, arm, type;
4039
4040     num_arms = *(const SHORT*)pFormat & 0x0fff;
4041     pFormat += 2;
4042     for(arm = 0; arm < num_arms; arm++)
4043     {
4044         if(discriminant == *(const ULONG*)pFormat)
4045         {
4046             pFormat += 4;
4047             break;
4048         }
4049         pFormat += 6;
4050     }
4051
4052     type = *(const unsigned short*)pFormat;
4053     TRACE("type %04x\n", type);
4054     if(arm == num_arms) /* default arm extras */
4055     {
4056         if(type == 0xffff)
4057         {
4058             ERR("no arm for 0x%lx and no default case\n", discriminant);
4059             RpcRaiseException(RPC_S_INVALID_TAG);
4060             return NULL;
4061         }
4062         if(type == 0)
4063         {
4064             TRACE("falling back to empty default case for 0x%lx\n", discriminant);
4065             return NULL;
4066         }
4067     }
4068     return pFormat;
4069 }
4070
4071 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
4072 {
4073     unsigned short type;
4074
4075     pFormat += 2;
4076
4077     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4078     if(!pFormat)
4079         return NULL;
4080
4081     type = *(const unsigned short*)pFormat;
4082     if((type & 0xff00) == 0x8000)
4083     {
4084         unsigned char basetype = LOBYTE(type);
4085         return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4086     }
4087     else
4088     {
4089         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4090         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4091         if (m)
4092         {
4093             unsigned char *saved_buffer = NULL;
4094             switch(*desc)
4095             {
4096             case RPC_FC_RP:
4097             case RPC_FC_UP:
4098             case RPC_FC_OP:
4099             case RPC_FC_FP:
4100                 saved_buffer = pStubMsg->Buffer;
4101                 pStubMsg->Buffer += 4; /* for pointer ID */
4102                 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
4103                 break;
4104             default:
4105                 m(pStubMsg, pMemory, desc);
4106             }
4107         }
4108         else FIXME("no marshaller for embedded type %02x\n", *desc);
4109     }
4110     return NULL;
4111 }
4112
4113 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4114                                 unsigned char **ppMemory,
4115                                 ULONG discriminant,
4116                                 PFORMAT_STRING pFormat,
4117                                 unsigned char fMustAlloc)
4118 {
4119     unsigned short type;
4120
4121     pFormat += 2;
4122
4123     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4124     if(!pFormat)
4125         return NULL;
4126
4127     type = *(const unsigned short*)pFormat;
4128     if((type & 0xff00) == 0x8000)
4129     {
4130         unsigned char basetype = LOBYTE(type);
4131         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, fMustAlloc);
4132     }
4133     else
4134     {
4135         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4136         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
4137         if (m)
4138         {
4139             unsigned char *saved_buffer = NULL;
4140             switch(*desc)
4141             {
4142             case RPC_FC_RP:
4143             case RPC_FC_UP:
4144             case RPC_FC_OP:
4145             case RPC_FC_FP:
4146                 ALIGN_POINTER(pStubMsg->Buffer, 4);
4147                 saved_buffer = pStubMsg->Buffer;
4148                 pStubMsg->Buffer += 4; /* for pointer ID */
4149                 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, TRUE);
4150                 break;
4151             default:
4152                 m(pStubMsg, ppMemory, desc, fMustAlloc);
4153             }
4154         }
4155         else FIXME("no marshaller for embedded type %02x\n", *desc);
4156     }
4157     return NULL;
4158 }
4159
4160 /***********************************************************************
4161  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
4162  */
4163 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
4164                                   unsigned char *pMemory,
4165                                   ULONG discriminant,
4166                                   PFORMAT_STRING pFormat)
4167 {
4168     unsigned short type;
4169
4170     pFormat += 2;
4171
4172     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4173     if(!pFormat)
4174         return;
4175
4176     type = *(const unsigned short*)pFormat;
4177     if((type & 0xff00) == 0x8000)
4178     {
4179         unsigned char basetype = LOBYTE(type);
4180         NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
4181     }
4182     else
4183     {
4184         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4185         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
4186         if (m)
4187         {
4188             switch(*desc)
4189             {
4190             case RPC_FC_RP:
4191             case RPC_FC_UP:
4192             case RPC_FC_OP:
4193             case RPC_FC_FP:
4194                 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4195                 pStubMsg->BufferLength += 4; /* for pointer ID */
4196                 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
4197                 break;
4198             default:
4199                 m(pStubMsg, pMemory, desc);
4200             }
4201         }
4202         else FIXME("no buffersizer for embedded type %02x\n", *desc);
4203     }
4204 }
4205
4206 /***********************************************************************
4207  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
4208  */
4209 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
4210                                    ULONG discriminant,
4211                                    PFORMAT_STRING pFormat)
4212 {
4213     unsigned short type, size;
4214
4215     size = *(const unsigned short*)pFormat;
4216     pStubMsg->Memory += size;
4217     pFormat += 2;
4218
4219     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4220     if(!pFormat)
4221         return 0;
4222
4223     type = *(const unsigned short*)pFormat;
4224     if((type & 0xff00) == 0x8000)
4225     {
4226         return NdrBaseTypeMemorySize(pStubMsg, pFormat);
4227     }
4228     else
4229     {
4230         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4231         NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
4232         unsigned char *saved_buffer;
4233         if (m)
4234         {
4235             switch(*desc)
4236             {
4237             case RPC_FC_RP:
4238             case RPC_FC_UP:
4239             case RPC_FC_OP:
4240             case RPC_FC_FP:
4241                 ALIGN_POINTER(pStubMsg->Buffer, 4);
4242                 saved_buffer = pStubMsg->Buffer;
4243                 pStubMsg->Buffer += 4;
4244                 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
4245                 pStubMsg->MemorySize += 4;
4246                 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
4247                 break;
4248             default:
4249                 return m(pStubMsg, desc);
4250             }
4251         }
4252         else FIXME("no marshaller for embedded type %02x\n", *desc);
4253     }
4254
4255     TRACE("size %d\n", size);
4256     return size;
4257 }
4258
4259 /***********************************************************************
4260  *           NdrEncapsulatedUnionFree [RPCRT4.@]
4261  */
4262 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
4263                            unsigned char *pMemory,
4264                            ULONG discriminant,
4265                            PFORMAT_STRING pFormat)
4266 {
4267     unsigned short type;
4268
4269     pFormat += 2;
4270
4271     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4272     if(!pFormat)
4273         return;
4274
4275     type = *(const unsigned short*)pFormat;
4276     if((type & 0xff00) != 0x8000)
4277     {
4278         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4279         NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
4280         if (m)
4281         {
4282             switch(*desc)
4283             {
4284             case RPC_FC_RP:
4285             case RPC_FC_UP:
4286             case RPC_FC_OP:
4287             case RPC_FC_FP:
4288                 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
4289                 break;
4290             default:
4291                 m(pStubMsg, pMemory, desc);
4292             }
4293         }
4294         else FIXME("no freer for embedded type %02x\n", *desc);
4295     }
4296 }
4297
4298 /***********************************************************************
4299  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
4300  */
4301 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4302                                 unsigned char *pMemory,
4303                                 PFORMAT_STRING pFormat)
4304 {
4305     unsigned char switch_type;
4306     unsigned char increment;
4307     ULONG switch_value;
4308
4309     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4310     pFormat++;
4311
4312     switch_type = *pFormat & 0xf;
4313     increment = *pFormat & 0xf0 >> 4;
4314     pFormat++;
4315
4316     ALIGN_POINTER(pStubMsg->Buffer, increment);
4317
4318     switch_value = get_discriminant(switch_type, pMemory);
4319     TRACE("got switch value 0x%x\n", switch_value);
4320
4321     NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
4322     pMemory += increment;
4323
4324     return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
4325 }
4326
4327 /***********************************************************************
4328  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
4329  */
4330 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4331                                 unsigned char **ppMemory,
4332                                 PFORMAT_STRING pFormat,
4333                                 unsigned char fMustAlloc)
4334 {
4335     unsigned char switch_type;
4336     unsigned char increment;
4337     ULONG switch_value;
4338     unsigned short size;
4339     unsigned char *pMemoryArm;
4340
4341     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4342     pFormat++;
4343
4344     switch_type = *pFormat & 0xf;
4345     increment = *pFormat & 0xf0 >> 4;
4346     pFormat++;
4347
4348     ALIGN_POINTER(pStubMsg->Buffer, increment);
4349     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
4350     TRACE("got switch value 0x%x\n", switch_value);
4351
4352     size = *(const unsigned short*)pFormat + increment;
4353     if(!*ppMemory || fMustAlloc)
4354         *ppMemory = NdrAllocate(pStubMsg, size);
4355
4356     NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
4357     pMemoryArm = *ppMemory + increment;
4358
4359     return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
4360 }
4361
4362 /***********************************************************************
4363  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
4364  */
4365 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4366                                 unsigned char *pMemory,
4367                                 PFORMAT_STRING pFormat)
4368 {
4369     unsigned char switch_type;
4370     unsigned char increment;
4371     ULONG switch_value;
4372
4373     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4374     pFormat++;
4375
4376     switch_type = *pFormat & 0xf;
4377     increment = *pFormat & 0xf0 >> 4;
4378     pFormat++;
4379
4380     ALIGN_LENGTH(pStubMsg->BufferLength, increment);
4381     switch_value = get_discriminant(switch_value, pMemory);
4382     TRACE("got switch value 0x%x\n", switch_value);
4383
4384     /* Add discriminant size */
4385     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
4386     pMemory += increment;
4387
4388     union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
4389 }
4390
4391 /***********************************************************************
4392  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
4393  */
4394 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4395                                 PFORMAT_STRING pFormat)
4396 {
4397     unsigned char switch_type;
4398     unsigned char increment;
4399     ULONG switch_value;
4400
4401     switch_type = *pFormat & 0xf;
4402     increment = *pFormat & 0xf0 >> 4;
4403     pFormat++;
4404
4405     ALIGN_POINTER(pStubMsg->Buffer, increment);
4406     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
4407     TRACE("got switch value 0x%x\n", switch_value);
4408
4409     pStubMsg->Memory += increment;
4410
4411     return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
4412 }
4413
4414 /***********************************************************************
4415  *           NdrEncapsulatedUnionFree [RPCRT4.@]
4416  */
4417 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
4418                                 unsigned char *pMemory,
4419                                 PFORMAT_STRING pFormat)
4420 {
4421     unsigned char switch_type;
4422     unsigned char increment;
4423     ULONG switch_value;
4424
4425     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4426     pFormat++;
4427
4428     switch_type = *pFormat & 0xf;
4429     increment = *pFormat & 0xf0 >> 4;
4430     pFormat++;
4431
4432     switch_value = get_discriminant(switch_type, pMemory);
4433     TRACE("got switch value 0x%x\n", switch_value);
4434
4435     pMemory += increment;
4436
4437     return union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
4438 }
4439
4440 /***********************************************************************
4441  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
4442  */
4443 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4444                                 unsigned char *pMemory,
4445                                 PFORMAT_STRING pFormat)
4446 {
4447     unsigned char switch_type;
4448
4449     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4450     pFormat++;
4451
4452     switch_type = *pFormat;
4453     pFormat++;
4454
4455     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4456     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4457     /* Marshall discriminant */
4458     NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
4459
4460     return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
4461 }
4462
4463 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
4464                                     PFORMAT_STRING *ppFormat)
4465 {
4466     long discriminant = 0;
4467
4468     switch(**ppFormat)
4469     {
4470     case RPC_FC_BYTE:
4471     case RPC_FC_CHAR:
4472     case RPC_FC_SMALL:
4473     case RPC_FC_USMALL:
4474         discriminant = *(UCHAR *)pStubMsg->Buffer;
4475         pStubMsg->Buffer += sizeof(UCHAR);
4476         break;
4477     case RPC_FC_WCHAR:
4478     case RPC_FC_SHORT:
4479     case RPC_FC_USHORT:
4480         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4481         discriminant = *(USHORT *)pStubMsg->Buffer;
4482         pStubMsg->Buffer += sizeof(USHORT);
4483         break;
4484     case RPC_FC_LONG:
4485     case RPC_FC_ULONG:
4486         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4487         discriminant = *(ULONG *)pStubMsg->Buffer;
4488         pStubMsg->Buffer += sizeof(ULONG);
4489         break;
4490     default:
4491         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
4492     }
4493     (*ppFormat)++;
4494
4495     if (pStubMsg->fHasNewCorrDesc)
4496         *ppFormat += 6;
4497     else
4498         *ppFormat += 4;
4499     return discriminant;
4500 }
4501
4502 /**********************************************************************
4503  *           NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
4504  */
4505 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4506                                 unsigned char **ppMemory,
4507                                 PFORMAT_STRING pFormat,
4508                                 unsigned char fMustAlloc)
4509 {
4510     long discriminant;
4511     unsigned short size;
4512
4513     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4514     pFormat++;
4515
4516     /* Unmarshall discriminant */
4517     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
4518     TRACE("unmarshalled discriminant %lx\n", discriminant);
4519
4520     pFormat += *(const SHORT*)pFormat;
4521
4522     size = *(const unsigned short*)pFormat;
4523
4524     if(!*ppMemory || fMustAlloc)
4525         *ppMemory = NdrAllocate(pStubMsg, size);
4526
4527     return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
4528 }
4529
4530 /***********************************************************************
4531  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
4532  */
4533 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4534                                 unsigned char *pMemory,
4535                                 PFORMAT_STRING pFormat)
4536 {
4537     unsigned char switch_type;
4538
4539     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4540     pFormat++;
4541
4542     switch_type = *pFormat;
4543     pFormat++;
4544
4545     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4546     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4547     /* Add discriminant size */
4548     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
4549
4550     union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
4551 }
4552
4553 /***********************************************************************
4554  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
4555  */
4556 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4557                                 PFORMAT_STRING pFormat)
4558 {
4559     ULONG discriminant;
4560
4561     pFormat++;
4562     /* Unmarshall discriminant */
4563     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
4564     TRACE("unmarshalled discriminant 0x%x\n", discriminant);
4565
4566     return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
4567 }
4568
4569 /***********************************************************************
4570  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
4571  */
4572 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
4573                                 unsigned char *pMemory,
4574                                 PFORMAT_STRING pFormat)
4575 {
4576     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4577     pFormat++;
4578     pFormat++;
4579
4580     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4581     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4582
4583     return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
4584 }
4585
4586 /***********************************************************************
4587  *           NdrByteCountPointerMarshall [RPCRT4.@]
4588  */
4589 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4590                                 unsigned char *pMemory,
4591                                 PFORMAT_STRING pFormat)
4592 {
4593     FIXME("stub\n");
4594     return NULL;
4595 }
4596
4597 /***********************************************************************
4598  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
4599  */
4600 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4601                                 unsigned char **ppMemory,
4602                                 PFORMAT_STRING pFormat,
4603                                 unsigned char fMustAlloc)
4604 {
4605     FIXME("stub\n");
4606     return NULL;
4607 }
4608
4609 /***********************************************************************
4610  *           NdrByteCountPointerBufferSize [RPCRT4.@]
4611  */
4612 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4613                                 unsigned char *pMemory,
4614                                 PFORMAT_STRING pFormat)
4615 {
4616     FIXME("stub\n");
4617 }
4618
4619 /***********************************************************************
4620  *           NdrByteCountPointerMemorySize [RPCRT4.@]
4621  */
4622 ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4623                                 PFORMAT_STRING pFormat)
4624 {
4625     FIXME("stub\n");
4626     return 0;
4627 }
4628
4629 /***********************************************************************
4630  *           NdrByteCountPointerFree [RPCRT4.@]
4631  */
4632 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
4633                                 unsigned char *pMemory,
4634                                 PFORMAT_STRING pFormat)
4635 {
4636     FIXME("stub\n");
4637 }
4638
4639 /***********************************************************************
4640  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
4641  */
4642 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4643                                 unsigned char *pMemory,
4644                                 PFORMAT_STRING pFormat)
4645 {
4646     FIXME("stub\n");
4647     return NULL;
4648 }
4649
4650 /***********************************************************************
4651  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
4652  */
4653 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4654                                 unsigned char **ppMemory,
4655                                 PFORMAT_STRING pFormat,
4656                                 unsigned char fMustAlloc)
4657 {
4658     FIXME("stub\n");
4659     return NULL;
4660 }
4661
4662 /***********************************************************************
4663  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
4664  */
4665 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4666                                 unsigned char *pMemory,
4667                                 PFORMAT_STRING pFormat)
4668 {
4669     FIXME("stub\n");
4670 }
4671
4672 /***********************************************************************
4673  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
4674  */
4675 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4676                                 PFORMAT_STRING pFormat)
4677 {
4678     FIXME("stub\n");
4679     return 0;
4680 }
4681
4682 /***********************************************************************
4683  *           NdrXmitOrRepAsFree [RPCRT4.@]
4684  */
4685 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
4686                                 unsigned char *pMemory,
4687                                 PFORMAT_STRING pFormat)
4688 {
4689     FIXME("stub\n");
4690 }
4691
4692 /***********************************************************************
4693  *           NdrBaseTypeMarshall [internal]
4694  */
4695 static unsigned char *WINAPI NdrBaseTypeMarshall(
4696     PMIDL_STUB_MESSAGE pStubMsg,
4697     unsigned char *pMemory,
4698     PFORMAT_STRING pFormat)
4699 {
4700     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4701
4702     switch(*pFormat)
4703     {
4704     case RPC_FC_BYTE:
4705     case RPC_FC_CHAR:
4706     case RPC_FC_SMALL:
4707     case RPC_FC_USMALL:
4708         *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory;
4709         pStubMsg->Buffer += sizeof(UCHAR);
4710         TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
4711         break;
4712     case RPC_FC_WCHAR:
4713     case RPC_FC_SHORT:
4714     case RPC_FC_USHORT:
4715         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4716         *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory;
4717         pStubMsg->Buffer += sizeof(USHORT);
4718         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
4719         break;
4720     case RPC_FC_LONG:
4721     case RPC_FC_ULONG:
4722     case RPC_FC_ERROR_STATUS_T:
4723     case RPC_FC_ENUM32:
4724         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4725         *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory;
4726         pStubMsg->Buffer += sizeof(ULONG);
4727         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
4728         break;
4729     case RPC_FC_FLOAT:
4730         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
4731         *(float *)pStubMsg->Buffer = *(float *)pMemory;
4732         pStubMsg->Buffer += sizeof(float);
4733         break;
4734     case RPC_FC_DOUBLE:
4735         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
4736         *(double *)pStubMsg->Buffer = *(double *)pMemory;
4737         pStubMsg->Buffer += sizeof(double);
4738         break;
4739     case RPC_FC_HYPER:
4740         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
4741         *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory;
4742         pStubMsg->Buffer += sizeof(ULONGLONG);
4743         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
4744         break;
4745     case RPC_FC_ENUM16:
4746         /* only 16-bits on the wire, so do a sanity check */
4747         if (*(UINT *)pMemory > USHRT_MAX)
4748             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
4749         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4750         *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
4751         pStubMsg->Buffer += sizeof(USHORT);
4752         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
4753         break;
4754     default:
4755         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4756     }
4757
4758     STD_OVERFLOW_CHECK(pStubMsg);
4759
4760     /* FIXME: what is the correct return value? */
4761     return NULL;
4762 }
4763
4764 /***********************************************************************
4765  *           NdrBaseTypeUnmarshall [internal]
4766  */
4767 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
4768     PMIDL_STUB_MESSAGE pStubMsg,
4769     unsigned char **ppMemory,
4770     PFORMAT_STRING pFormat,
4771     unsigned char fMustAlloc)
4772 {
4773     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
4774
4775 #define BASE_TYPE_UNMARSHALL(type) \
4776         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
4777         if (fMustAlloc || !*ppMemory) \
4778             *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
4779         TRACE("*ppMemory: %p\n", *ppMemory); \
4780         **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
4781         pStubMsg->Buffer += sizeof(type);
4782
4783     switch(*pFormat)
4784     {
4785     case RPC_FC_BYTE:
4786     case RPC_FC_CHAR:
4787     case RPC_FC_SMALL:
4788     case RPC_FC_USMALL:
4789         BASE_TYPE_UNMARSHALL(UCHAR);
4790         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
4791         break;
4792     case RPC_FC_WCHAR:
4793     case RPC_FC_SHORT:
4794     case RPC_FC_USHORT:
4795         BASE_TYPE_UNMARSHALL(USHORT);
4796         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
4797         break;
4798     case RPC_FC_LONG:
4799     case RPC_FC_ULONG:
4800     case RPC_FC_ERROR_STATUS_T:
4801     case RPC_FC_ENUM32:
4802         BASE_TYPE_UNMARSHALL(ULONG);
4803         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
4804         break;
4805    case RPC_FC_FLOAT:
4806         BASE_TYPE_UNMARSHALL(float);
4807         TRACE("value: %f\n", **(float **)ppMemory);
4808         break;
4809     case RPC_FC_DOUBLE:
4810         BASE_TYPE_UNMARSHALL(double);
4811         TRACE("value: %f\n", **(double **)ppMemory);
4812         break;
4813     case RPC_FC_HYPER:
4814         BASE_TYPE_UNMARSHALL(ULONGLONG);
4815         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
4816         break;
4817     case RPC_FC_ENUM16:
4818         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4819         if (fMustAlloc || !*ppMemory)
4820             *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
4821         TRACE("*ppMemory: %p\n", *ppMemory);
4822         /* 16-bits on the wire, but int in memory */
4823         **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
4824         pStubMsg->Buffer += sizeof(USHORT);
4825         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
4826         break;
4827     default:
4828         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4829     }
4830 #undef BASE_TYPE_UNMARSHALL
4831
4832     /* FIXME: what is the correct return value? */
4833
4834     return NULL;
4835 }
4836
4837 /***********************************************************************
4838  *           NdrBaseTypeBufferSize [internal]
4839  */
4840 static void WINAPI NdrBaseTypeBufferSize(
4841     PMIDL_STUB_MESSAGE pStubMsg,
4842     unsigned char *pMemory,
4843     PFORMAT_STRING pFormat)
4844 {
4845     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4846
4847     switch(*pFormat)
4848     {
4849     case RPC_FC_BYTE:
4850     case RPC_FC_CHAR:
4851     case RPC_FC_SMALL:
4852     case RPC_FC_USMALL:
4853         pStubMsg->BufferLength += sizeof(UCHAR);
4854         break;
4855     case RPC_FC_WCHAR:
4856     case RPC_FC_SHORT:
4857     case RPC_FC_USHORT:
4858     case RPC_FC_ENUM16:
4859         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
4860         pStubMsg->BufferLength += sizeof(USHORT);
4861         break;
4862     case RPC_FC_LONG:
4863     case RPC_FC_ULONG:
4864     case RPC_FC_ENUM32:
4865         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
4866         pStubMsg->BufferLength += sizeof(ULONG);
4867         break;
4868     case RPC_FC_FLOAT:
4869         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
4870         pStubMsg->BufferLength += sizeof(float);
4871         break;
4872     case RPC_FC_DOUBLE:
4873         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
4874         pStubMsg->BufferLength += sizeof(double);
4875         break;
4876     case RPC_FC_HYPER:
4877         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
4878         pStubMsg->BufferLength += sizeof(ULONGLONG);
4879         break;
4880     case RPC_FC_ERROR_STATUS_T:
4881         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
4882         pStubMsg->BufferLength += sizeof(error_status_t);
4883         break;
4884     default:
4885         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4886     }
4887 }
4888
4889 /***********************************************************************
4890  *           NdrBaseTypeMemorySize [internal]
4891  */
4892 static ULONG WINAPI NdrBaseTypeMemorySize(
4893     PMIDL_STUB_MESSAGE pStubMsg,
4894     PFORMAT_STRING pFormat)
4895 {
4896     switch(*pFormat)
4897     {
4898     case RPC_FC_BYTE:
4899     case RPC_FC_CHAR:
4900     case RPC_FC_SMALL:
4901     case RPC_FC_USMALL:
4902         pStubMsg->Buffer += sizeof(UCHAR);
4903         pStubMsg->MemorySize += sizeof(UCHAR);
4904         return sizeof(UCHAR);
4905     case RPC_FC_WCHAR:
4906     case RPC_FC_SHORT:
4907     case RPC_FC_USHORT:
4908         pStubMsg->Buffer += sizeof(USHORT);
4909         pStubMsg->MemorySize += sizeof(USHORT);
4910         return sizeof(USHORT);
4911     case RPC_FC_LONG:
4912     case RPC_FC_ULONG:
4913         pStubMsg->Buffer += sizeof(ULONG);
4914         pStubMsg->MemorySize += sizeof(ULONG);
4915         return sizeof(ULONG);
4916     case RPC_FC_FLOAT:
4917         pStubMsg->Buffer += sizeof(float);
4918         pStubMsg->MemorySize += sizeof(float);
4919         return sizeof(float);
4920     case RPC_FC_DOUBLE:
4921         pStubMsg->Buffer += sizeof(double);
4922         pStubMsg->MemorySize += sizeof(double);
4923         return sizeof(double);
4924     case RPC_FC_HYPER:
4925         pStubMsg->Buffer += sizeof(ULONGLONG);
4926         pStubMsg->MemorySize += sizeof(ULONGLONG);
4927         return sizeof(ULONGLONG);
4928     case RPC_FC_ERROR_STATUS_T:
4929         pStubMsg->Buffer += sizeof(error_status_t);
4930         pStubMsg->MemorySize += sizeof(error_status_t);
4931         return sizeof(error_status_t);
4932     case RPC_FC_ENUM16:
4933     case RPC_FC_ENUM32:
4934         pStubMsg->Buffer += sizeof(INT);
4935         pStubMsg->MemorySize += sizeof(INT);
4936         return sizeof(INT);
4937     default:
4938         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4939        return 0;
4940     }
4941 }
4942
4943 /***********************************************************************
4944  *           NdrBaseTypeFree [internal]
4945  */
4946 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
4947                                 unsigned char *pMemory,
4948                                 PFORMAT_STRING pFormat)
4949 {
4950    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4951
4952    /* nothing to do */
4953 }
4954
4955 /***********************************************************************
4956  *           NdrClientContextMarshall [RPCRT4.@]
4957  */
4958 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4959                                      NDR_CCONTEXT ContextHandle,
4960                                      int fCheck)
4961 {
4962     TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
4963
4964     ALIGN_POINTER(pStubMsg->Buffer, 4);
4965
4966     /* FIXME: what does fCheck do? */
4967     NDRCContextMarshall(ContextHandle,
4968                         pStubMsg->Buffer);
4969
4970     pStubMsg->Buffer += cbNDRContext;
4971 }
4972
4973 /***********************************************************************
4974  *           NdrClientContextUnmarshall [RPCRT4.@]
4975  */
4976 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4977                                        NDR_CCONTEXT * pContextHandle,
4978                                        RPC_BINDING_HANDLE BindHandle)
4979 {
4980     TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
4981
4982     ALIGN_POINTER(pStubMsg->Buffer, 4);
4983
4984     NDRCContextUnmarshall(pContextHandle,
4985                           BindHandle,
4986                           pStubMsg->Buffer,
4987                           pStubMsg->RpcMsg->DataRepresentation);
4988
4989     pStubMsg->Buffer += cbNDRContext;
4990 }
4991
4992 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4993                                      NDR_SCONTEXT ContextHandle,
4994                                      NDR_RUNDOWN RundownRoutine )
4995 {
4996     FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
4997 }
4998
4999 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
5000 {
5001     FIXME("(%p): stub\n", pStubMsg);
5002     return NULL;
5003 }
5004
5005 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
5006                                  unsigned char* pMemory,
5007                                  PFORMAT_STRING pFormat)
5008 {
5009     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
5010 }
5011
5012 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
5013                                                PFORMAT_STRING pFormat)
5014 {
5015     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5016     return NULL;
5017 }
5018
5019 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5020                                         NDR_SCONTEXT ContextHandle,
5021                                         NDR_RUNDOWN RundownRoutine,
5022                                         PFORMAT_STRING pFormat)
5023 {
5024     FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
5025 }
5026
5027 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5028                                                   PFORMAT_STRING pFormat)
5029 {
5030     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5031     return NULL;
5032 }
5033
5034 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e
5035
5036 typedef struct ndr_context_handle
5037 {
5038     DWORD      attributes;
5039     GUID       uuid;
5040 } ndr_context_handle;
5041
5042 struct context_handle_entry
5043 {
5044     struct list entry;
5045     DWORD magic;
5046     RPC_BINDING_HANDLE handle;
5047     ndr_context_handle wire_data;
5048 };
5049
5050 static struct list context_handle_list = LIST_INIT(context_handle_list);
5051
5052 static CRITICAL_SECTION ndr_context_cs;
5053 static CRITICAL_SECTION_DEBUG ndr_context_debug =
5054 {
5055     0, 0, &ndr_context_cs,
5056     { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList },
5057       0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") }
5058 };
5059 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 };
5060
5061 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
5062 {
5063     struct context_handle_entry *che = (struct context_handle_entry*) CContext;
5064
5065     if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
5066         return NULL;
5067     return che;
5068 }
5069
5070 static struct context_handle_entry *context_entry_from_guid(LPGUID uuid)
5071 {
5072     struct context_handle_entry *che;
5073     LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry)
5074         if (IsEqualGUID(&che->wire_data.uuid, uuid))
5075             return che;
5076     return NULL;
5077 }
5078
5079 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
5080 {
5081     struct context_handle_entry *che;
5082     RPC_BINDING_HANDLE handle = NULL;
5083
5084     TRACE("%p\n", CContext);
5085
5086     EnterCriticalSection(&ndr_context_cs);
5087     che = get_context_entry(CContext);
5088     if (che)
5089         handle = che->handle;
5090     LeaveCriticalSection(&ndr_context_cs);
5091
5092     if (!handle)
5093         RpcRaiseException(ERROR_INVALID_HANDLE);
5094     return handle;
5095 }
5096
5097 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
5098 {
5099     struct context_handle_entry *che;
5100
5101     TRACE("%p %p\n", CContext, pBuff);
5102
5103     if (CContext)
5104     {
5105         EnterCriticalSection(&ndr_context_cs);
5106         che = get_context_entry(CContext);
5107         memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle));
5108         LeaveCriticalSection(&ndr_context_cs);
5109     }
5110     else
5111     {
5112         ndr_context_handle *wire_data = (ndr_context_handle *)pBuff;
5113         wire_data->attributes = 0;
5114         wire_data->uuid = GUID_NULL;
5115     }
5116 }
5117
5118 static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext,
5119                                       RPC_BINDING_HANDLE hBinding,
5120                                       ndr_context_handle *chi)
5121 {
5122     struct context_handle_entry *che = NULL;
5123
5124     /* a null UUID means we should free the context handle */
5125     if (IsEqualGUID(&chi->uuid, &GUID_NULL))
5126     {
5127         if (*CContext)
5128         {
5129             che = get_context_entry(*CContext);
5130             if (!che)
5131                 return ERROR_INVALID_HANDLE;
5132             list_remove(&che->entry);
5133             RpcBindingFree(&che->handle);
5134             HeapFree(GetProcessHeap(), 0, che);
5135             che = NULL;
5136         }
5137     }
5138     /* if there's no existing entry matching the GUID, allocate one */
5139     else if (!(che = context_entry_from_guid(&chi->uuid)))
5140     {
5141         che = HeapAlloc(GetProcessHeap(), 0, sizeof *che);
5142         if (!che)
5143             return ERROR_NOT_ENOUGH_MEMORY;
5144         che->magic = NDR_CONTEXT_HANDLE_MAGIC;
5145         RpcBindingCopy(hBinding, &che->handle);
5146         list_add_tail(&context_handle_list, &che->entry);
5147         memcpy(&che->wire_data, chi, sizeof *chi);
5148     }
5149
5150     *CContext = che;
5151
5152     return ERROR_SUCCESS;
5153 }
5154
5155 /***********************************************************************
5156  *           NDRCContextUnmarshall [RPCRT4.@]
5157  */
5158 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext,
5159                                   RPC_BINDING_HANDLE hBinding,
5160                                   void *pBuff, ULONG DataRepresentation)
5161 {
5162     UINT r;
5163
5164     TRACE("*%p=(%p) %p %p %08x\n",
5165           CContext, *CContext, hBinding, pBuff, DataRepresentation);
5166
5167     EnterCriticalSection(&ndr_context_cs);
5168     r = ndr_update_context_handle(CContext, hBinding, pBuff);
5169     LeaveCriticalSection(&ndr_context_cs);
5170     if (r)
5171         RpcRaiseException(r);
5172 }
5173
5174 /***********************************************************************
5175  *           NDRSContextMarshall [RPCRT4.@]
5176  */
5177 void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext,
5178                                void *pBuff,
5179                                NDR_RUNDOWN userRunDownIn)
5180 {
5181     FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn);
5182 }
5183
5184 /***********************************************************************
5185  *           NDRSContextMarshallEx [RPCRT4.@]
5186  */
5187 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding,
5188                                   NDR_SCONTEXT CContext,
5189                                   void *pBuff,
5190                                   NDR_RUNDOWN userRunDownIn)
5191 {
5192     FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn);
5193 }
5194
5195 /***********************************************************************
5196  *           NDRSContextMarshall2 [RPCRT4.@]
5197  */
5198 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
5199                                  NDR_SCONTEXT CContext,
5200                                  void *pBuff,
5201                                  NDR_RUNDOWN userRunDownIn,
5202                                  void *CtxGuard, ULONG Flags)
5203 {
5204     FIXME("(%p %p %p %p %p %u): stub\n",
5205           hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags);
5206 }
5207
5208 /***********************************************************************
5209  *           NDRSContextUnmarshall [RPCRT4.@]
5210  */
5211 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff,
5212                                           ULONG DataRepresentation)
5213 {
5214     FIXME("(%p %08x): stub\n", pBuff, DataRepresentation);
5215     return NULL;
5216 }
5217
5218 /***********************************************************************
5219  *           NDRSContextUnmarshallEx [RPCRT4.@]
5220  */
5221 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding,
5222                                             void *pBuff,
5223                                             ULONG DataRepresentation)
5224 {
5225     FIXME("(%p %p %08x): stub\n", hBinding, pBuff, DataRepresentation);
5226     return NULL;
5227 }
5228
5229 /***********************************************************************
5230  *           NDRSContextUnmarshall2 [RPCRT4.@]
5231  */
5232 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
5233                                            void *pBuff,
5234                                            ULONG DataRepresentation,
5235                                            void *CtxGuard, ULONG Flags)
5236 {
5237     FIXME("(%p %p %08x %p %u): stub\n",
5238           hBinding, pBuff, DataRepresentation, CtxGuard, Flags);
5239     return NULL;
5240 }