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