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