rpcrt4: Move the writing and sizing of variances and conformances to common functions.
[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   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
312   pStubMsg->Buffer += 4;
313   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
314   if (pStubMsg->fHasNewCorrDesc)
315     return pFormat+6;
316   else
317     return pFormat+4;
318 }
319
320 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
321 {
322   if (!IsConformanceOrVariancePresent(pFormat))
323   {
324     pStubMsg->Offset = 0;
325     pStubMsg->ActualCount = pStubMsg->MaxCount;
326     goto done;
327   }
328
329   pStubMsg->Offset      = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
330   pStubMsg->Buffer += 4;
331   TRACE("offset is %ld\n", pStubMsg->Offset);
332   pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
333   pStubMsg->Buffer += 4;
334   TRACE("variance is %ld\n", pStubMsg->ActualCount);
335
336 done:
337   if (pStubMsg->fHasNewCorrDesc)
338     return pFormat+6;
339   else
340     return pFormat+4;
341 }
342
343 /* writes the conformance value to the buffer */
344 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
345 {
346     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
347     pStubMsg->Buffer += 4;
348 }
349
350 /* writes the variance values to the buffer */
351 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
352 {
353     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
354     pStubMsg->Buffer += 4;
355     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
356     pStubMsg->Buffer += 4;
357 }
358
359 /* requests buffer space for the conformance value */
360 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
361 {
362     pStubMsg->BufferLength += 4;
363 }
364
365 /* requests buffer space for the variance values */
366 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
367 {
368     pStubMsg->BufferLength += 8;
369 }
370
371 PFORMAT_STRING ComputeConformanceOrVariance(
372     MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
373     PFORMAT_STRING pFormat, ULONG_PTR def, ULONG *pCount)
374 {
375   BYTE dtype = pFormat[0] & 0xf;
376   short ofs = *(short *)&pFormat[2];
377   LPVOID ptr = NULL;
378   DWORD data = 0;
379
380   if (!IsConformanceOrVariancePresent(pFormat)) {
381     /* null descriptor */
382     *pCount = def;
383     goto finish_conf;
384   }
385
386   switch (pFormat[0] & 0xf0) {
387   case RPC_FC_NORMAL_CONFORMANCE:
388     TRACE("normal conformance, ofs=%d\n", ofs);
389     ptr = pMemory;
390     break;
391   case RPC_FC_POINTER_CONFORMANCE:
392     TRACE("pointer conformance, ofs=%d\n", ofs);
393     ptr = pStubMsg->Memory;
394     break;
395   case RPC_FC_TOP_LEVEL_CONFORMANCE:
396     TRACE("toplevel conformance, ofs=%d\n", ofs);
397     if (pStubMsg->StackTop) {
398       ptr = pStubMsg->StackTop;
399     }
400     else {
401       /* -Os mode, *pCount is already set */
402       goto finish_conf;
403     }
404     break;
405   case RPC_FC_CONSTANT_CONFORMANCE:
406     data = ofs | ((DWORD)pFormat[1] << 16);
407     TRACE("constant conformance, val=%ld\n", data);
408     *pCount = data;
409     goto finish_conf;
410   case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
411     FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
412     if (pStubMsg->StackTop) {
413       ptr = pStubMsg->StackTop;
414     }
415     else {
416       /* ? */
417       goto done_conf_grab;
418     }
419     break;
420   default:
421     FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
422   }
423
424   switch (pFormat[1]) {
425   case RPC_FC_DEREFERENCE:
426     ptr = *(LPVOID*)((char *)ptr + ofs);
427     break;
428   case RPC_FC_CALLBACK:
429   {
430     unsigned char *old_stack_top = pStubMsg->StackTop;
431     pStubMsg->StackTop = ptr;
432
433     /* ofs is index into StubDesc->apfnExprEval */
434     TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
435     pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
436
437     pStubMsg->StackTop = old_stack_top;
438     goto finish_conf;
439   }
440   default:
441     ptr = (char *)ptr + ofs;
442     break;
443   }
444
445   switch (dtype) {
446   case RPC_FC_LONG:
447   case RPC_FC_ULONG:
448     data = *(DWORD*)ptr;
449     break;
450   case RPC_FC_SHORT:
451     data = *(SHORT*)ptr;
452     break;
453   case RPC_FC_USHORT:
454     data = *(USHORT*)ptr;
455     break;
456   case RPC_FC_SMALL:
457     data = *(CHAR*)ptr;
458     break;
459   case RPC_FC_USMALL:
460     data = *(UCHAR*)ptr;
461     break;
462   default:
463     FIXME("unknown conformance data type %x\n", dtype);
464     goto done_conf_grab;
465   }
466   TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);
467
468 done_conf_grab:
469   switch (pFormat[1]) {
470   case 0: /* no op */
471     *pCount = data;
472     break;
473   case RPC_FC_DEREFERENCE:
474     /* already handled */
475     break;
476   default:
477     FIXME("unknown conformance op %d\n", pFormat[1]);
478     goto finish_conf;
479   }
480
481 finish_conf:
482   TRACE("resulting conformance is %ld\n", *pCount);
483   if (pStubMsg->fHasNewCorrDesc)
484     return pFormat+6;
485   else
486     return pFormat+4;
487 }
488
489
490 /*
491  * NdrConformantString:
492  * 
493  * What MS calls a ConformantString is, in DCE terminology,
494  * a Varying-Conformant String.
495  * [
496  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
497  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
498  *           into unmarshalled string) 
499  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
500  *   [ 
501  *     data: CHARTYPE[maxlen]
502  *   ] 
503  * ], where CHARTYPE is the appropriate character type (specified externally)
504  *
505  */
506
507 /***********************************************************************
508  *            NdrConformantStringMarshall [RPCRT4.@]
509  */
510 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
511   unsigned char *pszMessage, PFORMAT_STRING pFormat)
512
513   unsigned long len, esize;
514
515   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
516   
517   assert(pFormat);
518   if (*pFormat == RPC_FC_C_CSTRING) {
519     TRACE("string=%s\n", debugstr_a((char*)pszMessage));
520     len = strlen((char*)pszMessage)+1;
521     esize = 1;
522   }
523   else if (*pFormat == RPC_FC_C_WSTRING) {
524     TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
525     len = strlenW((LPWSTR)pszMessage)+1;
526     esize = 2;
527   }
528   else {
529     ERR("Unhandled string type: %#x\n", *pFormat); 
530     /* FIXME: raise an exception. */
531     return NULL;
532   }
533
534   if (pFormat[1] != RPC_FC_PAD) {
535     FIXME("sized string format=%d\n", pFormat[1]);
536   }
537
538   assert( (pStubMsg->BufferLength >= (len*esize + 13)) && (pStubMsg->Buffer != NULL) );
539
540   pStubMsg->MaxCount = pStubMsg->ActualCount = len;
541   pStubMsg->Offset = 0;
542   WriteConformance(pStubMsg);
543   WriteVariance(pStubMsg);
544
545   memcpy(pStubMsg->Buffer, pszMessage, len*esize); /* the string itself */
546   pStubMsg->Buffer += len*esize;
547
548   STD_OVERFLOW_CHECK(pStubMsg);
549
550   /* success */
551   return NULL; /* is this always right? */
552 }
553
554 /***********************************************************************
555  *           NdrConformantStringBufferSize [RPCRT4.@]
556  */
557 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
558   unsigned char* pMemory, PFORMAT_STRING pFormat)
559 {
560   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
561
562   SizeConformance(pStubMsg);
563   SizeVariance(pStubMsg);
564
565   assert(pFormat);
566   if (*pFormat == RPC_FC_C_CSTRING) {
567     /* we need + 1 octet for '\0' */
568     TRACE("string=%s\n", debugstr_a((char*)pMemory));
569     pStubMsg->BufferLength += strlen((char*)pMemory) + 1 + BUFFER_PARANOIA;
570   }
571   else if (*pFormat == RPC_FC_C_WSTRING) {
572     /* we need + 2 octets for L'\0' */
573     TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
574     pStubMsg->BufferLength += strlenW((LPWSTR)pMemory)*2 + 2 + BUFFER_PARANOIA;
575   }
576   else {
577     ERR("Unhandled string type: %#x\n", *pFormat); 
578     /* FIXME: raise an exception */
579   }
580
581   if (pFormat[1] != RPC_FC_PAD) {
582     FIXME("sized string format=%d\n", pFormat[1]);
583   }
584 }
585
586 /************************************************************************
587  *            NdrConformantStringMemorySize [RPCRT4.@]
588  */
589 unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
590   PFORMAT_STRING pFormat )
591 {
592   unsigned long rslt = 0;
593
594   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
595    
596   assert(pStubMsg && pFormat);
597
598   if (*pFormat == RPC_FC_C_CSTRING) {
599     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
600   }
601   else if (*pFormat == RPC_FC_C_WSTRING) {
602     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */
603   }
604   else {
605     ERR("Unhandled string type: %#x\n", *pFormat);
606     /* FIXME: raise an exception */
607   }
608
609   if (pFormat[1] != RPC_FC_PAD) {
610     FIXME("sized string format=%d\n", pFormat[1]);
611   }
612
613   TRACE("  --> %lu\n", rslt);
614   return rslt;
615 }
616
617 /************************************************************************
618  *           NdrConformantStringUnmarshall [RPCRT4.@]
619  */
620 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
621   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
622 {
623   unsigned long len, esize, ofs;
624
625   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
626     pStubMsg, *ppMemory, pFormat, fMustAlloc);
627
628   assert(pFormat && ppMemory && pStubMsg);
629
630   pStubMsg->Buffer += 4;
631   ofs = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
632   pStubMsg->Buffer += 4;
633   len = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
634   pStubMsg->Buffer += 4;
635
636   if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
637   else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
638   else {
639     ERR("Unhandled string type: %#x\n", *pFormat);
640     /* FIXME: raise an exception */
641     esize = 0;
642   }
643
644   if (pFormat[1] != RPC_FC_PAD) {
645     FIXME("sized string format=%d\n", pFormat[1]);
646   }
647
648   if (fMustAlloc || !*ppMemory)
649     *ppMemory = NdrAllocate(pStubMsg, len*esize + BUFFER_PARANOIA);
650
651   memcpy(*ppMemory, pStubMsg->Buffer, len*esize);
652
653   pStubMsg->Buffer += len*esize;
654
655   if (*pFormat == RPC_FC_C_CSTRING) {
656     TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
657   }
658   else if (*pFormat == RPC_FC_C_WSTRING) {
659     TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
660   }
661
662   return NULL; /* FIXME: is this always right? */
663 }
664
665 /***********************************************************************
666  *           NdrNonConformantStringMarshall [RPCRT4.@]
667  */
668 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
669                                 unsigned char *pMemory,
670                                 PFORMAT_STRING pFormat)
671 {
672     FIXME("stub\n");
673     return NULL;
674 }
675
676 /***********************************************************************
677  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
678  */
679 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
680                                 unsigned char **ppMemory,
681                                 PFORMAT_STRING pFormat,
682                                 unsigned char fMustAlloc)
683 {
684     FIXME("stub\n");
685     return NULL;
686 }
687
688 /***********************************************************************
689  *           NdrNonConformantStringBufferSize [RPCRT4.@]
690  */
691 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
692                                 unsigned char *pMemory,
693                                 PFORMAT_STRING pFormat)
694 {
695     FIXME("stub\n");
696 }
697
698 /***********************************************************************
699  *           NdrNonConformantStringMemorySize [RPCRT4.@]
700  */
701 unsigned long WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
702                                 PFORMAT_STRING pFormat)
703 {
704     FIXME("stub\n");
705     return 0;
706 }
707
708 static inline void dump_pointer_attr(unsigned char attr)
709 {
710     if (attr & RPC_FC_P_ALLOCALLNODES)
711         TRACE(" RPC_FC_P_ALLOCALLNODES");
712     if (attr & RPC_FC_P_DONTFREE)
713         TRACE(" RPC_FC_P_DONTFREE");
714     if (attr & RPC_FC_P_ONSTACK)
715         TRACE(" RPC_FC_P_ONSTACK");
716     if (attr & RPC_FC_P_SIMPLEPOINTER)
717         TRACE(" RPC_FC_P_SIMPLEPOINTER");
718     if (attr & RPC_FC_P_DEREF)
719         TRACE(" RPC_FC_P_DEREF");
720     TRACE("\n");
721 }
722
723 /***********************************************************************
724  *           PointerMarshall
725  */
726 void WINAPI PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
727                             unsigned char *Buffer,
728                             unsigned char *Pointer,
729                             PFORMAT_STRING pFormat)
730 {
731   unsigned type = pFormat[0], attr = pFormat[1];
732   PFORMAT_STRING desc;
733   NDR_MARSHALL m;
734
735   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
736   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
737   pFormat += 2;
738   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
739   else desc = pFormat + *(const SHORT*)pFormat;
740
741   switch (type) {
742   case RPC_FC_RP: /* ref pointer (always non-null) */
743 #if 0 /* this causes problems for InstallShield so is disabled - we need more tests */
744     if (!Pointer)
745       RpcRaiseException(RPC_X_NULL_REF_POINTER);
746 #endif
747     break;
748   case RPC_FC_UP: /* unique pointer */
749   case RPC_FC_OP: /* object pointer - same as unique here */
750     TRACE("writing %p to buffer\n", Pointer);
751     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, (unsigned long)Pointer);
752     pStubMsg->Buffer += 4;
753     break;
754   case RPC_FC_FP:
755   default:
756     FIXME("unhandled ptr type=%02x\n", type);
757     RpcRaiseException(RPC_X_BAD_STUB_DATA);
758   }
759
760   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
761
762   if (Pointer) {
763     if (attr & RPC_FC_P_DEREF) {
764       Pointer = *(unsigned char**)Pointer;
765       TRACE("deref => %p\n", Pointer);
766     }
767     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
768     if (m) m(pStubMsg, Pointer, desc);
769     else FIXME("no marshaller for data type=%02x\n", *desc);
770   }
771
772   STD_OVERFLOW_CHECK(pStubMsg);
773 }
774
775 /***********************************************************************
776  *           PointerUnmarshall
777  */
778 void WINAPI PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
779                               unsigned char *Buffer,
780                               unsigned char **pPointer,
781                               PFORMAT_STRING pFormat,
782                               unsigned char fMustAlloc)
783 {
784   unsigned type = pFormat[0], attr = pFormat[1];
785   PFORMAT_STRING desc;
786   NDR_UNMARSHALL m;
787   DWORD pointer_id = 0;
788
789   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc);
790   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
791   pFormat += 2;
792   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
793   else desc = pFormat + *(const SHORT*)pFormat;
794
795   switch (type) {
796   case RPC_FC_RP: /* ref pointer (always non-null) */
797     pointer_id = ~0UL;
798     break;
799   case RPC_FC_UP: /* unique pointer */
800     pointer_id = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
801     pStubMsg->Buffer += 4;
802     break;
803   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
804     pointer_id = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
805     pStubMsg->Buffer += 4;
806     if (*pPointer)
807         FIXME("free object pointer %p\n", *pPointer);
808     break;
809   case RPC_FC_FP:
810   default:
811     FIXME("unhandled ptr type=%02x\n", type);
812     RpcRaiseException(RPC_X_BAD_STUB_DATA);
813   }
814
815   if (pointer_id) {
816     if (attr & RPC_FC_P_DEREF) {
817       if (!*pPointer || fMustAlloc)
818         *pPointer = NdrAllocate(pStubMsg, sizeof(void *));
819       pPointer = *(unsigned char***)pPointer;
820       TRACE("deref => %p\n", pPointer);
821     }
822     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
823     if (m) m(pStubMsg, pPointer, desc, fMustAlloc);
824     else FIXME("no unmarshaller for data type=%02x\n", *desc);
825   }
826
827   TRACE("pointer=%p\n", *pPointer);
828 }
829
830 /***********************************************************************
831  *           PointerBufferSize
832  */
833 void WINAPI PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
834                               unsigned char *Pointer,
835                               PFORMAT_STRING pFormat)
836 {
837   unsigned type = pFormat[0], attr = pFormat[1];
838   PFORMAT_STRING desc;
839   NDR_BUFFERSIZE m;
840
841   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
842   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
843   pFormat += 2;
844   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
845   else desc = pFormat + *(const SHORT*)pFormat;
846
847   switch (type) {
848   case RPC_FC_RP: /* ref pointer (always non-null) */
849     break;
850   case RPC_FC_OP:
851   case RPC_FC_UP:
852     pStubMsg->BufferLength += 4;
853     /* NULL pointer has no further representation */
854     if (!Pointer)
855         return;
856     break;
857   case RPC_FC_FP:
858   default:
859     FIXME("unhandled ptr type=%02x\n", type);
860     RpcRaiseException(RPC_X_BAD_STUB_DATA);
861   }
862
863   if (attr & RPC_FC_P_DEREF) {
864     Pointer = *(unsigned char**)Pointer;
865     TRACE("deref => %p\n", Pointer);
866   }
867
868   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
869   if (m) m(pStubMsg, Pointer, desc);
870   else FIXME("no buffersizer for data type=%02x\n", *desc);
871 }
872
873 /***********************************************************************
874  *           PointerMemorySize [RPCRT4.@]
875  */
876 unsigned long WINAPI PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
877                                        unsigned char *Buffer,
878                                        PFORMAT_STRING pFormat)
879 {
880   unsigned type = pFormat[0], attr = pFormat[1];
881   PFORMAT_STRING desc;
882   NDR_MEMORYSIZE m;
883
884   FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat);
885   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
886   pFormat += 2;
887   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
888   else desc = pFormat + *(const SHORT*)pFormat;
889
890   switch (type) {
891   case RPC_FC_RP: /* ref pointer (always non-null) */
892     break;
893   default:
894     FIXME("unhandled ptr type=%02x\n", type);
895     RpcRaiseException(RPC_X_BAD_STUB_DATA);
896   }
897
898   if (attr & RPC_FC_P_DEREF) {
899     TRACE("deref\n");
900   }
901
902   m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
903   if (m) m(pStubMsg, desc);
904   else FIXME("no memorysizer for data type=%02x\n", *desc);
905
906   return 0;
907 }
908
909 /***********************************************************************
910  *           PointerFree [RPCRT4.@]
911  */
912 void WINAPI PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
913                         unsigned char *Pointer,
914                         PFORMAT_STRING pFormat)
915 {
916   unsigned type = pFormat[0], attr = pFormat[1];
917   PFORMAT_STRING desc;
918   NDR_FREE m;
919
920   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
921   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
922   if (attr & RPC_FC_P_DONTFREE) return;
923   pFormat += 2;
924   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
925   else desc = pFormat + *(const SHORT*)pFormat;
926
927   if (!Pointer) return;
928
929   if (attr & RPC_FC_P_DEREF) {
930     Pointer = *(unsigned char**)Pointer;
931     TRACE("deref => %p\n", Pointer);
932   }
933
934   m = NdrFreer[*desc & NDR_TABLE_MASK];
935   if (m) m(pStubMsg, Pointer, desc);
936
937   /* hmm... is this sensible?
938    * perhaps we should check if the memory comes from NdrAllocate,
939    * and deallocate only if so - checking if the pointer is between
940    * BufferStart and BufferEnd is probably no good since the buffer
941    * may be reallocated when the server wants to marshal the reply */
942   switch (*desc) {
943   case RPC_FC_BOGUS_STRUCT:
944   case RPC_FC_BOGUS_ARRAY:
945   case RPC_FC_USER_MARSHAL:
946   case RPC_FC_CARRAY:
947   case RPC_FC_CVARRAY:
948     break;
949   default:
950     FIXME("unhandled data type=%02x\n", *desc);
951     break;
952   case RPC_FC_C_CSTRING:
953   case RPC_FC_C_WSTRING:
954     if (pStubMsg->ReuseBuffer) goto notfree;
955     break;
956   case RPC_FC_IP:
957     goto notfree;
958   }
959
960   if (attr & RPC_FC_P_ONSTACK) {
961     TRACE("not freeing stack ptr %p\n", Pointer);
962     return;
963   }
964   TRACE("freeing %p\n", Pointer);
965   NdrFree(pStubMsg, Pointer);
966   return;
967 notfree:
968   TRACE("not freeing %p\n", Pointer);
969 }
970
971 /***********************************************************************
972  *           EmbeddedPointerMarshall
973  */
974 unsigned char * WINAPI EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
975                                                unsigned char *pMemory,
976                                                PFORMAT_STRING pFormat)
977 {
978   unsigned char *Mark = pStubMsg->BufferMark;
979   unsigned long Offset = pStubMsg->Offset;
980   unsigned ofs, rep, count, stride, xofs;
981
982   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
983
984   if (*pFormat != RPC_FC_PP) return NULL;
985   pFormat += 2;
986
987   while (pFormat[0] != RPC_FC_END) {
988     switch (pFormat[0]) {
989     default:
990       FIXME("unknown repeat type %d\n", pFormat[0]);
991     case RPC_FC_NO_REPEAT:
992       rep = 1;
993       stride = 0;
994       ofs = 0;
995       count = 1;
996       xofs = 0;
997       pFormat += 2;
998       break;
999     case RPC_FC_FIXED_REPEAT:
1000       rep = *(const WORD*)&pFormat[2];
1001       stride = *(const WORD*)&pFormat[4];
1002       ofs = *(const WORD*)&pFormat[6];
1003       count = *(const WORD*)&pFormat[8];
1004       xofs = 0;
1005       pFormat += 10;
1006       break;
1007     case RPC_FC_VARIABLE_REPEAT:
1008       rep = pStubMsg->MaxCount;
1009       stride = *(const WORD*)&pFormat[2];
1010       ofs = *(const WORD*)&pFormat[4];
1011       count = *(const WORD*)&pFormat[6];
1012       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1013       pFormat += 8;
1014       break;
1015     }
1016     /* ofs doesn't seem to matter in this context */
1017     while (rep) {
1018       PFORMAT_STRING info = pFormat;
1019       unsigned char *membase = pMemory + xofs;
1020       unsigned u;
1021       for (u=0; u<count; u++,info+=8) {
1022         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1023         unsigned char *bufptr = Mark + *(const SHORT*)&info[2];
1024         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1025       }
1026       rep--;
1027     }
1028     pFormat += 8 * count;
1029   }
1030
1031   STD_OVERFLOW_CHECK(pStubMsg);
1032
1033   return NULL;
1034 }
1035
1036 /***********************************************************************
1037  *           EmbeddedPointerUnmarshall
1038  */
1039 unsigned char * WINAPI EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1040                                                  unsigned char **ppMemory,
1041                                                  PFORMAT_STRING pFormat,
1042                                                  unsigned char fMustAlloc)
1043 {
1044   unsigned char *Mark = pStubMsg->BufferMark;
1045   unsigned long Offset = pStubMsg->Offset;
1046   unsigned ofs, rep, count, stride, xofs;
1047
1048   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1049
1050   if (*pFormat != RPC_FC_PP) return NULL;
1051   pFormat += 2;
1052
1053   while (pFormat[0] != RPC_FC_END) {
1054     switch (pFormat[0]) {
1055     default:
1056       FIXME("unknown repeat type %d\n", pFormat[0]);
1057     case RPC_FC_NO_REPEAT:
1058       rep = 1;
1059       stride = 0;
1060       ofs = 0;
1061       count = 1;
1062       xofs = 0;
1063       pFormat += 2;
1064       break;
1065     case RPC_FC_FIXED_REPEAT:
1066       rep = *(const WORD*)&pFormat[2];
1067       stride = *(const WORD*)&pFormat[4];
1068       ofs = *(const WORD*)&pFormat[6];
1069       count = *(const WORD*)&pFormat[8];
1070       xofs = 0;
1071       pFormat += 10;
1072       break;
1073     case RPC_FC_VARIABLE_REPEAT:
1074       rep = pStubMsg->MaxCount;
1075       stride = *(const WORD*)&pFormat[2];
1076       ofs = *(const WORD*)&pFormat[4];
1077       count = *(const WORD*)&pFormat[6];
1078       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1079       pFormat += 8;
1080       break;
1081     }
1082     /* ofs doesn't seem to matter in this context */
1083     while (rep) {
1084       PFORMAT_STRING info = pFormat;
1085       unsigned char *membase = *ppMemory + xofs;
1086       unsigned u;
1087       for (u=0; u<count; u++,info+=8) {
1088         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1089         unsigned char *bufptr = Mark + *(const SHORT*)&info[2];
1090         PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, fMustAlloc);
1091       }
1092       rep--;
1093     }
1094     pFormat += 8 * count;
1095   }
1096
1097   return NULL;
1098 }
1099
1100 /***********************************************************************
1101  *           EmbeddedPointerBufferSize
1102  */
1103 void WINAPI EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1104                                       unsigned char *pMemory,
1105                                       PFORMAT_STRING pFormat)
1106 {
1107   unsigned long Offset = pStubMsg->Offset;
1108   unsigned ofs, rep, count, stride, xofs;
1109
1110   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1111   if (*pFormat != RPC_FC_PP) return;
1112   pFormat += 2;
1113
1114   while (pFormat[0] != RPC_FC_END) {
1115     switch (pFormat[0]) {
1116     default:
1117       FIXME("unknown repeat type %d\n", pFormat[0]);
1118     case RPC_FC_NO_REPEAT:
1119       rep = 1;
1120       stride = 0;
1121       ofs = 0;
1122       count = 1;
1123       xofs = 0;
1124       pFormat += 2;
1125       break;
1126     case RPC_FC_FIXED_REPEAT:
1127       rep = *(const WORD*)&pFormat[2];
1128       stride = *(const WORD*)&pFormat[4];
1129       ofs = *(const WORD*)&pFormat[6];
1130       count = *(const WORD*)&pFormat[8];
1131       xofs = 0;
1132       pFormat += 10;
1133       break;
1134     case RPC_FC_VARIABLE_REPEAT:
1135       rep = pStubMsg->MaxCount;
1136       stride = *(const WORD*)&pFormat[2];
1137       ofs = *(const WORD*)&pFormat[4];
1138       count = *(const WORD*)&pFormat[6];
1139       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1140       pFormat += 8;
1141       break;
1142     }
1143     /* ofs doesn't seem to matter in this context */
1144     while (rep) {
1145       PFORMAT_STRING info = pFormat;
1146       unsigned char *membase = pMemory + xofs;
1147       unsigned u;
1148       for (u=0; u<count; u++,info+=8) {
1149         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1150         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1151       }
1152       rep--;
1153     }
1154     pFormat += 8 * count;
1155   }
1156 }
1157
1158 /***********************************************************************
1159  *           EmbeddedPointerMemorySize
1160  */
1161 unsigned long WINAPI EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1162                                                PFORMAT_STRING pFormat)
1163 {
1164   unsigned long Offset = pStubMsg->Offset;
1165   unsigned char *Mark = pStubMsg->BufferMark;
1166   unsigned ofs, rep, count, stride, xofs;
1167
1168   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1169   if (*pFormat != RPC_FC_PP) return 0;
1170   pFormat += 2;
1171
1172   while (pFormat[0] != RPC_FC_END) {
1173     switch (pFormat[0]) {
1174     default:
1175       FIXME("unknown repeat type %d\n", pFormat[0]);
1176     case RPC_FC_NO_REPEAT:
1177       rep = 1;
1178       stride = 0;
1179       ofs = 0;
1180       count = 1;
1181       xofs = 0;
1182       pFormat += 2;
1183       break;
1184     case RPC_FC_FIXED_REPEAT:
1185       rep = *(const WORD*)&pFormat[2];
1186       stride = *(const WORD*)&pFormat[4];
1187       ofs = *(const WORD*)&pFormat[6];
1188       count = *(const WORD*)&pFormat[8];
1189       xofs = 0;
1190       pFormat += 10;
1191       break;
1192     case RPC_FC_VARIABLE_REPEAT:
1193       rep = pStubMsg->MaxCount;
1194       stride = *(const WORD*)&pFormat[2];
1195       ofs = *(const WORD*)&pFormat[4];
1196       count = *(const WORD*)&pFormat[6];
1197       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1198       pFormat += 8;
1199       break;
1200     }
1201     /* ofs doesn't seem to matter in this context */
1202     while (rep) {
1203       PFORMAT_STRING info = pFormat;
1204       unsigned u;
1205       for (u=0; u<count; u++,info+=8) {
1206         unsigned char *bufptr = Mark + *(const SHORT*)&info[2];
1207         PointerMemorySize(pStubMsg, bufptr, info+4);
1208       }
1209       rep--;
1210     }
1211     pFormat += 8 * count;
1212   }
1213
1214   return 0;
1215 }
1216
1217 /***********************************************************************
1218  *           EmbeddedPointerFree
1219  */
1220 void WINAPI EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1221                                 unsigned char *pMemory,
1222                                 PFORMAT_STRING pFormat)
1223 {
1224   unsigned long Offset = pStubMsg->Offset;
1225   unsigned ofs, rep, count, stride, xofs;
1226
1227   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1228   if (*pFormat != RPC_FC_PP) return;
1229   pFormat += 2;
1230
1231   while (pFormat[0] != RPC_FC_END) {
1232     switch (pFormat[0]) {
1233     default:
1234       FIXME("unknown repeat type %d\n", pFormat[0]);
1235     case RPC_FC_NO_REPEAT:
1236       rep = 1;
1237       stride = 0;
1238       ofs = 0;
1239       count = 1;
1240       xofs = 0;
1241       pFormat += 2;
1242       break;
1243     case RPC_FC_FIXED_REPEAT:
1244       rep = *(const WORD*)&pFormat[2];
1245       stride = *(const WORD*)&pFormat[4];
1246       ofs = *(const WORD*)&pFormat[6];
1247       count = *(const WORD*)&pFormat[8];
1248       xofs = 0;
1249       pFormat += 10;
1250       break;
1251     case RPC_FC_VARIABLE_REPEAT:
1252       rep = pStubMsg->MaxCount;
1253       stride = *(const WORD*)&pFormat[2];
1254       ofs = *(const WORD*)&pFormat[4];
1255       count = *(const WORD*)&pFormat[6];
1256       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1257       pFormat += 8;
1258       break;
1259     }
1260     /* ofs doesn't seem to matter in this context */
1261     while (rep) {
1262       PFORMAT_STRING info = pFormat;
1263       unsigned char *membase = pMemory + xofs;
1264       unsigned u;
1265       for (u=0; u<count; u++,info+=8) {
1266         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1267         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1268       }
1269       rep--;
1270     }
1271     pFormat += 8 * count;
1272   }
1273 }
1274
1275 /***********************************************************************
1276  *           NdrPointerMarshall [RPCRT4.@]
1277  */
1278 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1279                                           unsigned char *pMemory,
1280                                           PFORMAT_STRING pFormat)
1281 {
1282   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1283
1284   pStubMsg->BufferMark = pStubMsg->Buffer;
1285   PointerMarshall(pStubMsg, pStubMsg->Buffer, pMemory, pFormat);
1286
1287   STD_OVERFLOW_CHECK(pStubMsg);
1288
1289   return NULL;
1290 }
1291
1292 /***********************************************************************
1293  *           NdrPointerUnmarshall [RPCRT4.@]
1294  */
1295 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1296                                             unsigned char **ppMemory,
1297                                             PFORMAT_STRING pFormat,
1298                                             unsigned char fMustAlloc)
1299 {
1300   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1301
1302   pStubMsg->BufferMark = pStubMsg->Buffer;
1303   PointerUnmarshall(pStubMsg, pStubMsg->Buffer, ppMemory, pFormat, fMustAlloc);
1304
1305   return NULL;
1306 }
1307
1308 /***********************************************************************
1309  *           NdrPointerBufferSize [RPCRT4.@]
1310  */
1311 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1312                                       unsigned char *pMemory,
1313                                       PFORMAT_STRING pFormat)
1314 {
1315   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1316   PointerBufferSize(pStubMsg, pMemory, pFormat);
1317 }
1318
1319 /***********************************************************************
1320  *           NdrPointerMemorySize [RPCRT4.@]
1321  */
1322 unsigned long WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1323                                           PFORMAT_STRING pFormat)
1324 {
1325   /* unsigned size = *(LPWORD)(pFormat+2); */
1326   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1327   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1328   return 0;
1329 }
1330
1331 /***********************************************************************
1332  *           NdrPointerFree [RPCRT4.@]
1333  */
1334 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1335                            unsigned char *pMemory,
1336                            PFORMAT_STRING pFormat)
1337 {
1338   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1339   PointerFree(pStubMsg, pMemory, pFormat);
1340 }
1341
1342 /***********************************************************************
1343  *           NdrSimpleStructMarshall [RPCRT4.@]
1344  */
1345 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1346                                                unsigned char *pMemory,
1347                                                PFORMAT_STRING pFormat)
1348 {
1349   unsigned size = *(const WORD*)(pFormat+2);
1350   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1351
1352   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1353
1354   memcpy(pStubMsg->Buffer, pMemory, size);
1355   pStubMsg->BufferMark = pStubMsg->Buffer;
1356   pStubMsg->Buffer += size;
1357
1358   if (pFormat[0] != RPC_FC_STRUCT)
1359     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1360
1361   STD_OVERFLOW_CHECK(pStubMsg);
1362
1363   return NULL;
1364 }
1365
1366 /***********************************************************************
1367  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1368  */
1369 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1370                                                  unsigned char **ppMemory,
1371                                                  PFORMAT_STRING pFormat,
1372                                                  unsigned char fMustAlloc)
1373 {
1374   unsigned size = *(const WORD*)(pFormat+2);
1375   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1376
1377   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1378
1379   if (fMustAlloc) {
1380     *ppMemory = NdrAllocate(pStubMsg, size);
1381     memcpy(*ppMemory, pStubMsg->Buffer, size);
1382   } else {
1383     if (pStubMsg->ReuseBuffer && !*ppMemory)
1384       /* for servers, we may just point straight into the RPC buffer, I think
1385        * (I guess that's what MS does since MIDL code doesn't try to free) */
1386       *ppMemory = pStubMsg->Buffer;
1387     else
1388       /* for clients, memory should be provided by caller */
1389       memcpy(*ppMemory, pStubMsg->Buffer, size);
1390   }
1391
1392   pStubMsg->BufferMark = pStubMsg->Buffer;
1393   pStubMsg->Buffer += size;
1394
1395   if (pFormat[0] != RPC_FC_STRUCT)
1396     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1397
1398   return NULL;
1399 }
1400
1401
1402 /***********************************************************************
1403  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1404  */
1405 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1406                                    unsigned char FormatChar )
1407 {
1408     FIXME("stub\n");
1409 }
1410
1411
1412 /***********************************************************************
1413  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1414  */
1415 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1416                                      unsigned char FormatChar )
1417 {
1418     FIXME("stub\n");
1419 }
1420
1421
1422 /***********************************************************************
1423  *           NdrSimpleStructBufferSize [RPCRT4.@]
1424  */
1425 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1426                                       unsigned char *pMemory,
1427                                       PFORMAT_STRING pFormat)
1428 {
1429   unsigned size = *(const WORD*)(pFormat+2);
1430   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1431
1432   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1433
1434   pStubMsg->BufferLength += size;
1435   if (pFormat[0] != RPC_FC_STRUCT)
1436     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1437 }
1438
1439 /***********************************************************************
1440  *           NdrSimpleStructMemorySize [RPCRT4.@]
1441  */
1442 unsigned long WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1443                                                PFORMAT_STRING pFormat)
1444 {
1445   /* unsigned size = *(LPWORD)(pFormat+2); */
1446   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1447   if (pFormat[0] != RPC_FC_STRUCT)
1448     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1449   return 0;
1450 }
1451
1452 /***********************************************************************
1453  *           NdrSimpleStructFree [RPCRT4.@]
1454  */
1455 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1456                                 unsigned char *pMemory,
1457                                 PFORMAT_STRING pFormat)
1458 {
1459   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1460   if (pFormat[0] != RPC_FC_STRUCT)
1461     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1462 }
1463
1464
1465 unsigned long WINAPI EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg,
1466                                          PFORMAT_STRING pFormat)
1467 {
1468   switch (*pFormat) {
1469   case RPC_FC_STRUCT:
1470   case RPC_FC_PSTRUCT:
1471   case RPC_FC_CSTRUCT:
1472   case RPC_FC_BOGUS_STRUCT:
1473     return *(const WORD*)&pFormat[2];
1474   case RPC_FC_USER_MARSHAL:
1475     return *(const WORD*)&pFormat[4];
1476   case RPC_FC_NON_ENCAPSULATED_UNION:
1477     return NdrNonEncapsulatedUnionMemorySize(pStubMsg, pFormat);
1478   default:
1479     FIXME("unhandled embedded type %02x\n", *pFormat);
1480   }
1481   return 0;
1482 }
1483
1484
1485 unsigned char * WINAPI ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1486                                        unsigned char *pMemory,
1487                                        PFORMAT_STRING pFormat,
1488                                        PFORMAT_STRING pPointer)
1489 {
1490   PFORMAT_STRING desc;
1491   NDR_MARSHALL m;
1492   unsigned long size;
1493
1494   while (*pFormat != RPC_FC_END) {
1495     switch (*pFormat) {
1496     case RPC_FC_SHORT:
1497     case RPC_FC_USHORT:
1498       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1499       memcpy(pStubMsg->Buffer, pMemory, 2);
1500       pStubMsg->Buffer += 2;
1501       pMemory += 2;
1502       break;
1503     case RPC_FC_LONG:
1504     case RPC_FC_ULONG:
1505     case RPC_FC_ENUM32:
1506       TRACE("long=%ld <= %p\n", *(DWORD*)pMemory, pMemory);
1507       memcpy(pStubMsg->Buffer, pMemory, 4);
1508       pStubMsg->Buffer += 4;
1509       pMemory += 4;
1510       break;
1511     case RPC_FC_POINTER:
1512       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1513       NdrPointerMarshall(pStubMsg, *(unsigned char**)pMemory, pPointer);
1514       pPointer += 4;
1515       pMemory += 4;
1516       break;
1517     case RPC_FC_ALIGNM4:
1518       ALIGN_POINTER(pMemory, 4);
1519       break;
1520     case RPC_FC_ALIGNM8:
1521       ALIGN_POINTER(pMemory, 8);
1522       break;
1523     case RPC_FC_STRUCTPAD2:
1524       pMemory += 2;
1525       break;
1526     case RPC_FC_EMBEDDED_COMPLEX:
1527       pMemory += pFormat[1];
1528       pFormat += 2;
1529       desc = pFormat + *(const SHORT*)pFormat;
1530       size = EmbeddedComplexSize(pStubMsg, desc);
1531       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1532       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1533       if (m) m(pStubMsg, pMemory, desc);
1534       else FIXME("no marshaller for embedded type %02x\n", *desc);
1535       pMemory += size;
1536       pFormat += 2;
1537       continue;
1538     case RPC_FC_PAD:
1539       break;
1540     default:
1541       FIXME("unhandled format %02x\n", *pFormat);
1542     }
1543     pFormat++;
1544   }
1545
1546   return pMemory;
1547 }
1548
1549 unsigned char * WINAPI ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1550                                          unsigned char *pMemory,
1551                                          PFORMAT_STRING pFormat,
1552                                          PFORMAT_STRING pPointer,
1553                                          unsigned char fMustAlloc)
1554 {
1555   PFORMAT_STRING desc;
1556   NDR_UNMARSHALL m;
1557   unsigned long size;
1558
1559   while (*pFormat != RPC_FC_END) {
1560     switch (*pFormat) {
1561     case RPC_FC_SHORT:
1562     case RPC_FC_USHORT:
1563       memcpy(pMemory, pStubMsg->Buffer, 2);
1564       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1565       pStubMsg->Buffer += 2;
1566       pMemory += 2;
1567       break;
1568     case RPC_FC_LONG:
1569     case RPC_FC_ULONG:
1570     case RPC_FC_ENUM32:
1571       memcpy(pMemory, pStubMsg->Buffer, 4);
1572       TRACE("long=%ld => %p\n", *(DWORD*)pMemory, pMemory);
1573       pStubMsg->Buffer += 4;
1574       pMemory += 4;
1575       break;
1576     case RPC_FC_POINTER:
1577       *(unsigned char**)pMemory = NULL;
1578       TRACE("pointer => %p\n", pMemory);
1579       NdrPointerUnmarshall(pStubMsg, (unsigned char**)pMemory, pPointer, fMustAlloc);
1580       pPointer += 4;
1581       pMemory += 4;
1582       break;
1583     case RPC_FC_ALIGNM4:
1584       ALIGN_POINTER(pMemory, 4);
1585       break;
1586     case RPC_FC_ALIGNM8:
1587       ALIGN_POINTER(pMemory, 8);
1588       break;
1589     case RPC_FC_STRUCTPAD2:
1590       pMemory += 2;
1591       break;
1592     case RPC_FC_EMBEDDED_COMPLEX:
1593       pMemory += pFormat[1];
1594       pFormat += 2;
1595       desc = pFormat + *(const SHORT*)pFormat;
1596       size = EmbeddedComplexSize(pStubMsg, desc);
1597       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1598       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1599       memset(pMemory, 0, size); /* just in case */
1600       if (m) m(pStubMsg, &pMemory, desc, fMustAlloc);
1601       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
1602       pMemory += size;
1603       pFormat += 2;
1604       continue;
1605     case RPC_FC_PAD:
1606       break;
1607     default:
1608       FIXME("unhandled format %d\n", *pFormat);
1609     }
1610     pFormat++;
1611   }
1612
1613   return pMemory;
1614 }
1615
1616 unsigned char * WINAPI ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1617                                          unsigned char *pMemory,
1618                                          PFORMAT_STRING pFormat,
1619                                          PFORMAT_STRING pPointer)
1620 {
1621   PFORMAT_STRING desc;
1622   NDR_BUFFERSIZE m;
1623   unsigned long size;
1624
1625   while (*pFormat != RPC_FC_END) {
1626     switch (*pFormat) {
1627     case RPC_FC_SHORT:
1628     case RPC_FC_USHORT:
1629       pStubMsg->BufferLength += 2;
1630       pMemory += 2;
1631       break;
1632     case RPC_FC_LONG:
1633     case RPC_FC_ULONG:
1634     case RPC_FC_ENUM32:
1635       pStubMsg->BufferLength += 4;
1636       pMemory += 4;
1637       break;
1638     case RPC_FC_POINTER:
1639       NdrPointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
1640       pPointer += 4;
1641       pMemory += 4;
1642       break;
1643     case RPC_FC_ALIGNM4:
1644       ALIGN_POINTER(pMemory, 4);
1645       break;
1646     case RPC_FC_ALIGNM8:
1647       ALIGN_POINTER(pMemory, 8);
1648       break;
1649     case RPC_FC_STRUCTPAD2:
1650       pMemory += 2;
1651       break;
1652     case RPC_FC_EMBEDDED_COMPLEX:
1653       pMemory += pFormat[1];
1654       pFormat += 2;
1655       desc = pFormat + *(const SHORT*)pFormat;
1656       size = EmbeddedComplexSize(pStubMsg, desc);
1657       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1658       if (m) m(pStubMsg, pMemory, desc);
1659       else FIXME("no buffersizer for embedded type %02x\n", *desc);
1660       pMemory += size;
1661       pFormat += 2;
1662       continue;
1663     case RPC_FC_PAD:
1664       break;
1665     default:
1666       FIXME("unhandled format %d\n", *pFormat);
1667     }
1668     pFormat++;
1669   }
1670
1671   return pMemory;
1672 }
1673
1674 unsigned char * WINAPI ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
1675                                    unsigned char *pMemory,
1676                                    PFORMAT_STRING pFormat,
1677                                    PFORMAT_STRING pPointer)
1678 {
1679   PFORMAT_STRING desc;
1680   NDR_FREE m;
1681   unsigned long size;
1682
1683   while (*pFormat != RPC_FC_END) {
1684     switch (*pFormat) {
1685     case RPC_FC_SHORT:
1686     case RPC_FC_USHORT:
1687       pMemory += 2;
1688       break;
1689     case RPC_FC_LONG:
1690     case RPC_FC_ULONG:
1691     case RPC_FC_ENUM32:
1692       pMemory += 4;
1693       break;
1694     case RPC_FC_POINTER:
1695       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
1696       pPointer += 4;
1697       pMemory += 4;
1698       break;
1699     case RPC_FC_ALIGNM4:
1700       ALIGN_POINTER(pMemory, 4);
1701       break;
1702     case RPC_FC_ALIGNM8:
1703       ALIGN_POINTER(pMemory, 8);
1704       break;
1705     case RPC_FC_STRUCTPAD2:
1706       pMemory += 2;
1707       break;
1708     case RPC_FC_EMBEDDED_COMPLEX:
1709       pMemory += pFormat[1];
1710       pFormat += 2;
1711       desc = pFormat + *(const SHORT*)pFormat;
1712       size = EmbeddedComplexSize(pStubMsg, desc);
1713       m = NdrFreer[*desc & NDR_TABLE_MASK];
1714       if (m) m(pStubMsg, pMemory, desc);
1715       else FIXME("no freer for embedded type %02x\n", *desc);
1716       pMemory += size;
1717       pFormat += 2;
1718       continue;
1719     case RPC_FC_PAD:
1720       break;
1721     default:
1722       FIXME("unhandled format %d\n", *pFormat);
1723     }
1724     pFormat++;
1725   }
1726
1727   return pMemory;
1728 }
1729
1730 unsigned long WINAPI ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,
1731                                        PFORMAT_STRING pFormat)
1732 {
1733   PFORMAT_STRING desc;
1734   unsigned long size = 0;
1735
1736   while (*pFormat != RPC_FC_END) {
1737     switch (*pFormat) {
1738     case RPC_FC_SHORT:
1739     case RPC_FC_USHORT:
1740       size += 2;
1741       break;
1742     case RPC_FC_LONG:
1743     case RPC_FC_ULONG:
1744       size += 4;
1745       break;
1746     case RPC_FC_POINTER:
1747       size += 4;
1748       break;
1749     case RPC_FC_ALIGNM4:
1750       ALIGN_LENGTH(size, 4);
1751       break;
1752     case RPC_FC_ALIGNM8:
1753       ALIGN_LENGTH(size, 8);
1754       break;
1755     case RPC_FC_STRUCTPAD2:
1756       size += 2;
1757       break;
1758     case RPC_FC_EMBEDDED_COMPLEX:
1759       size += pFormat[1];
1760       pFormat += 2;
1761       desc = pFormat + *(const SHORT*)pFormat;
1762       size += EmbeddedComplexSize(pStubMsg, desc);
1763       pFormat += 2;
1764       continue;
1765     case RPC_FC_PAD:
1766       break;
1767     default:
1768       FIXME("unhandled format %d\n", *pFormat);
1769     }
1770     pFormat++;
1771   }
1772
1773   return size;
1774 }
1775
1776 /***********************************************************************
1777  *           NdrComplexStructMarshall [RPCRT4.@]
1778  */
1779 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1780                                                 unsigned char *pMemory,
1781                                                 PFORMAT_STRING pFormat)
1782 {
1783   PFORMAT_STRING conf_array = NULL;
1784   PFORMAT_STRING pointer_desc = NULL;
1785   unsigned char *OldMemory = pStubMsg->Memory;
1786
1787   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1788
1789   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1790
1791   pFormat += 4;
1792   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1793   pFormat += 2;
1794   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1795   pFormat += 2;
1796
1797   pStubMsg->Memory = pMemory;
1798
1799   ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
1800
1801   if (conf_array)
1802     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
1803
1804   pStubMsg->Memory = OldMemory;
1805
1806   STD_OVERFLOW_CHECK(pStubMsg);
1807
1808   return NULL;
1809 }
1810
1811 /***********************************************************************
1812  *           NdrComplexStructUnmarshall [RPCRT4.@]
1813  */
1814 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1815                                                   unsigned char **ppMemory,
1816                                                   PFORMAT_STRING pFormat,
1817                                                   unsigned char fMustAlloc)
1818 {
1819   unsigned size = *(const WORD*)(pFormat+2);
1820   PFORMAT_STRING conf_array = NULL;
1821   PFORMAT_STRING pointer_desc = NULL;
1822   unsigned char *pMemory;
1823
1824   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1825
1826   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1827
1828   if (fMustAlloc || !*ppMemory)
1829   {
1830     *ppMemory = NdrAllocate(pStubMsg, size);
1831     memset(*ppMemory, 0, size);
1832   }
1833
1834   pFormat += 4;
1835   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1836   pFormat += 2;
1837   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1838   pFormat += 2;
1839
1840   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
1841
1842   if (conf_array)
1843     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
1844
1845   return NULL;
1846 }
1847
1848 /***********************************************************************
1849  *           NdrComplexStructBufferSize [RPCRT4.@]
1850  */
1851 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1852                                        unsigned char *pMemory,
1853                                        PFORMAT_STRING pFormat)
1854 {
1855   PFORMAT_STRING conf_array = NULL;
1856   PFORMAT_STRING pointer_desc = NULL;
1857   unsigned char *OldMemory = pStubMsg->Memory;
1858
1859   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1860
1861   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1862
1863   pFormat += 4;
1864   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1865   pFormat += 2;
1866   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1867   pFormat += 2;
1868
1869   pStubMsg->Memory = pMemory;
1870
1871   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
1872
1873   if (conf_array)
1874     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
1875
1876   pStubMsg->Memory = OldMemory;
1877 }
1878
1879 /***********************************************************************
1880  *           NdrComplexStructMemorySize [RPCRT4.@]
1881  */
1882 unsigned long WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1883                                                 PFORMAT_STRING pFormat)
1884 {
1885   /* unsigned size = *(LPWORD)(pFormat+2); */
1886   PFORMAT_STRING conf_array = NULL;
1887   PFORMAT_STRING pointer_desc = NULL;
1888
1889   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1890
1891   pFormat += 4;
1892   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1893   pFormat += 2;
1894   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1895   pFormat += 2;
1896
1897   return 0;
1898 }
1899
1900 /***********************************************************************
1901  *           NdrComplexStructFree [RPCRT4.@]
1902  */
1903 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1904                                  unsigned char *pMemory,
1905                                  PFORMAT_STRING pFormat)
1906 {
1907   PFORMAT_STRING conf_array = NULL;
1908   PFORMAT_STRING pointer_desc = NULL;
1909   unsigned char *OldMemory = pStubMsg->Memory;
1910
1911   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1912
1913   pFormat += 4;
1914   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1915   pFormat += 2;
1916   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1917   pFormat += 2;
1918
1919   pStubMsg->Memory = pMemory;
1920
1921   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
1922
1923   if (conf_array)
1924     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
1925
1926   pStubMsg->Memory = OldMemory;
1927 }
1928
1929 /***********************************************************************
1930  *           NdrConformantArrayMarshall [RPCRT4.@]
1931  */
1932 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1933                                                   unsigned char *pMemory,
1934                                                   PFORMAT_STRING pFormat)
1935 {
1936   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
1937   unsigned char alignment = pFormat[1] + 1;
1938
1939   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1940   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1941
1942   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1943   size = pStubMsg->MaxCount;
1944
1945   WriteConformance(pStubMsg);
1946
1947   ALIGN_POINTER(pStubMsg->Buffer, alignment);
1948
1949   memcpy(pStubMsg->Buffer, pMemory, size*esize);
1950   pStubMsg->BufferMark = pStubMsg->Buffer;
1951   pStubMsg->Buffer += size*esize;
1952
1953   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1954
1955   STD_OVERFLOW_CHECK(pStubMsg);
1956
1957   return NULL;
1958 }
1959
1960 /***********************************************************************
1961  *           NdrConformantArrayUnmarshall [RPCRT4.@]
1962  */
1963 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1964                                                     unsigned char **ppMemory,
1965                                                     PFORMAT_STRING pFormat,
1966                                                     unsigned char fMustAlloc)
1967 {
1968   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
1969   unsigned char alignment = pFormat[1] + 1;
1970
1971   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1972   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1973
1974   pFormat = ReadConformance(pStubMsg, pFormat+4);
1975   size = pStubMsg->MaxCount;
1976
1977   if (fMustAlloc || !*ppMemory)
1978     *ppMemory = NdrAllocate(pStubMsg, size*esize);
1979
1980   ALIGN_POINTER(pStubMsg->Buffer, alignment);
1981
1982   memcpy(*ppMemory, pStubMsg->Buffer, size*esize);
1983
1984   pStubMsg->BufferMark = pStubMsg->Buffer;
1985   pStubMsg->Buffer += size*esize;
1986
1987   EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
1988
1989   return NULL;
1990 }
1991
1992 /***********************************************************************
1993  *           NdrConformantArrayBufferSize [RPCRT4.@]
1994  */
1995 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1996                                          unsigned char *pMemory,
1997                                          PFORMAT_STRING pFormat)
1998 {
1999   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2000   unsigned char alignment = pFormat[1] + 1;
2001
2002   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2003   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2004
2005   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2006   size = pStubMsg->MaxCount;
2007
2008   SizeVariance(pStubMsg);
2009
2010   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2011
2012   /* conformance value plus array */
2013   pStubMsg->BufferLength += size*esize;
2014
2015   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2016 }
2017
2018 /***********************************************************************
2019  *           NdrConformantArrayMemorySize [RPCRT4.@]
2020  */
2021 unsigned long WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2022                                                   PFORMAT_STRING pFormat)
2023 {
2024   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2025   unsigned char *buffer;
2026
2027   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2028   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2029
2030   buffer = pStubMsg->Buffer;
2031   pFormat = ReadConformance(pStubMsg, pFormat+4);
2032   pStubMsg->Buffer = buffer;
2033   size = pStubMsg->MaxCount;
2034
2035   return size*esize;
2036 }
2037
2038 /***********************************************************************
2039  *           NdrConformantArrayFree [RPCRT4.@]
2040  */
2041 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2042                                    unsigned char *pMemory,
2043                                    PFORMAT_STRING pFormat)
2044 {
2045   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2046   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2047
2048   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2049 }
2050
2051
2052 /***********************************************************************
2053  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
2054  */
2055 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2056                                                          unsigned char* pMemory,
2057                                                          PFORMAT_STRING pFormat )
2058 {
2059     unsigned char alignment = pFormat[1] + 1;
2060     DWORD esize = *(const WORD*)(pFormat+2);
2061
2062     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2063
2064     if (pFormat[0] != RPC_FC_CVARRAY)
2065     {
2066         ERR("invalid format type %x\n", pFormat[0]);
2067         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2068         return NULL;
2069     }
2070
2071     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2072     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2073
2074     WriteConformance(pStubMsg);
2075     WriteVariance(pStubMsg);
2076
2077     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2078
2079     memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, pStubMsg->ActualCount*esize);
2080     pStubMsg->BufferMark = pStubMsg->Buffer;
2081     pStubMsg->Buffer += pStubMsg->ActualCount*esize;
2082
2083     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2084
2085     STD_OVERFLOW_CHECK(pStubMsg);
2086
2087     return NULL;
2088 }
2089
2090
2091 /***********************************************************************
2092  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
2093  */
2094 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2095                                                            unsigned char** ppMemory,
2096                                                            PFORMAT_STRING pFormat,
2097                                                            unsigned char fMustAlloc )
2098 {
2099     unsigned char alignment = pFormat[1] + 1;
2100     DWORD esize = *(const WORD*)(pFormat+2);
2101
2102     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2103
2104     if (pFormat[0] != RPC_FC_CVARRAY)
2105     {
2106         ERR("invalid format type %x\n", pFormat[0]);
2107         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2108         return NULL;
2109     }
2110
2111     pFormat = ReadConformance(pStubMsg, pFormat);
2112     pFormat = ReadVariance(pStubMsg, pFormat);
2113
2114     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2115
2116     if (!*ppMemory || fMustAlloc)
2117         *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
2118     memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, pStubMsg->ActualCount * esize);
2119     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
2120
2121     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2122
2123     return NULL;
2124 }
2125
2126
2127 /***********************************************************************
2128  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
2129  */
2130 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2131                                            unsigned char* pMemory,
2132                                            PFORMAT_STRING pFormat )
2133 {
2134     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2135
2136     if (pFormat[0] != RPC_FC_CVARRAY)
2137     {
2138         ERR("invalid format type %x\n", pFormat[0]);
2139         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2140         return;
2141     }
2142
2143     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2144     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2145
2146     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2147 }
2148
2149
2150 /***********************************************************************
2151  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
2152  */
2153 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2154                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
2155 {
2156     unsigned char alignment = pFormat[1] + 1;
2157     DWORD esize = *(const WORD*)(pFormat+2);
2158
2159     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2160
2161     if (pFormat[0] != RPC_FC_CVARRAY)
2162     {
2163         ERR("invalid format type %x\n", pFormat[0]);
2164         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2165         return;
2166     }
2167
2168     /* compute size */
2169     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2170     /* compute length */
2171     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2172
2173     SizeConformance(pStubMsg);
2174     SizeVariance(pStubMsg);
2175
2176     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2177
2178     pStubMsg->BufferLength += pStubMsg->ActualCount*esize;
2179
2180     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2181 }
2182
2183
2184 /***********************************************************************
2185  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
2186  */
2187 unsigned long WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2188                                                           PFORMAT_STRING pFormat )
2189 {
2190     FIXME( "stub\n" );
2191     return 0;
2192 }
2193
2194
2195 /***********************************************************************
2196  *           NdrComplexArrayMarshall [RPCRT4.@]
2197  */
2198 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2199                                                unsigned char *pMemory,
2200                                                PFORMAT_STRING pFormat)
2201 {
2202   ULONG count, def;
2203   BOOL variance_present;
2204   unsigned char alignment;
2205
2206   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2207
2208   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2209   {
2210       ERR("invalid format type %x\n", pFormat[0]);
2211       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2212       return NULL;
2213   }
2214
2215   alignment = pFormat[1] + 1;
2216
2217   def = *(const WORD*)&pFormat[2];
2218   pFormat += 4;
2219
2220   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2221   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2222
2223   variance_present = IsConformanceOrVariancePresent(pFormat);
2224   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2225   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2226
2227   WriteConformance(pStubMsg);
2228   if (variance_present)
2229     WriteVariance(pStubMsg);
2230
2231   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2232
2233   for (count = 0; count < pStubMsg->ActualCount; count++)
2234     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2235
2236   STD_OVERFLOW_CHECK(pStubMsg);
2237
2238   return NULL;
2239 }
2240
2241 /***********************************************************************
2242  *           NdrComplexArrayUnmarshall [RPCRT4.@]
2243  */
2244 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2245                                                  unsigned char **ppMemory,
2246                                                  PFORMAT_STRING pFormat,
2247                                                  unsigned char fMustAlloc)
2248 {
2249   ULONG count, esize;
2250   unsigned char alignment;
2251   unsigned char *pMemory;
2252
2253   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2254
2255   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2256   {
2257       ERR("invalid format type %x\n", pFormat[0]);
2258       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2259       return NULL;
2260   }
2261
2262   alignment = pFormat[1] + 1;
2263
2264   pFormat += 4;
2265
2266   pFormat = ReadConformance(pStubMsg, pFormat);
2267   pFormat = ReadVariance(pStubMsg, pFormat);
2268
2269   esize = ComplexStructSize(pStubMsg, pFormat);
2270
2271   if (fMustAlloc || !*ppMemory)
2272   {
2273     *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
2274     memset(*ppMemory, 0, pStubMsg->MaxCount * esize);
2275   }
2276
2277   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2278
2279   pMemory = *ppMemory;
2280   for (count = 0; count < pStubMsg->ActualCount; count++)
2281     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
2282
2283   return NULL;
2284 }
2285
2286 /***********************************************************************
2287  *           NdrComplexArrayBufferSize [RPCRT4.@]
2288  */
2289 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2290                                       unsigned char *pMemory,
2291                                       PFORMAT_STRING pFormat)
2292 {
2293   ULONG count, def;
2294   unsigned char alignment;
2295   BOOL variance_present;
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;
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   SizeConformance(pStubMsg);
2314
2315   variance_present = IsConformanceOrVariancePresent(pFormat);
2316   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2317   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2318
2319   if (variance_present)
2320     SizeVariance(pStubMsg);
2321
2322   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2323
2324   for (count=0; count < pStubMsg->ActualCount; count++)
2325     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
2326 }
2327
2328 /***********************************************************************
2329  *           NdrComplexArrayMemorySize [RPCRT4.@]
2330  */
2331 unsigned long WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2332                                                PFORMAT_STRING pFormat)
2333 {
2334   DWORD size = 0;
2335   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
2336
2337   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2338   {
2339       ERR("invalid format type %x\n", pFormat[0]);
2340       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2341       return 0;
2342   }
2343
2344   pFormat += 4;
2345
2346   pFormat = ReadConformance(pStubMsg, pFormat);
2347   size = pStubMsg->MaxCount;
2348   TRACE("conformance=%ld\n", size);
2349
2350   pFormat += 4;
2351
2352   return 0;
2353 }
2354
2355 /***********************************************************************
2356  *           NdrComplexArrayFree [RPCRT4.@]
2357  */
2358 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2359                                 unsigned char *pMemory,
2360                                 PFORMAT_STRING pFormat)
2361 {
2362   ULONG count, def;
2363
2364   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2365
2366   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2367   {
2368       ERR("invalid format type %x\n", pFormat[0]);
2369       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2370       return;
2371   }
2372
2373   def = *(const WORD*)&pFormat[2];
2374   pFormat += 4;
2375
2376   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2377   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2378
2379   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2380   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2381
2382   for (count=0; count < pStubMsg->ActualCount; count++)
2383     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2384 }
2385
2386 unsigned long UserMarshalFlags(PMIDL_STUB_MESSAGE pStubMsg)
2387 {
2388   return MAKELONG(pStubMsg->dwDestContext,
2389                   pStubMsg->RpcMsg->DataRepresentation);
2390 }
2391
2392 /***********************************************************************
2393  *           NdrUserMarshalMarshall [RPCRT4.@]
2394  */
2395 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2396                                               unsigned char *pMemory,
2397                                               PFORMAT_STRING pFormat)
2398 {
2399 /*  unsigned flags = pFormat[1]; */
2400   unsigned index = *(const WORD*)&pFormat[2];
2401   unsigned long uflag = UserMarshalFlags(pStubMsg);
2402   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2403   TRACE("index=%d\n", index);
2404
2405   pStubMsg->Buffer =
2406     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
2407       &uflag, pStubMsg->Buffer, pMemory);
2408
2409   STD_OVERFLOW_CHECK(pStubMsg);
2410
2411   return NULL;
2412 }
2413
2414 /***********************************************************************
2415  *           NdrUserMarshalUnmarshall [RPCRT4.@]
2416  */
2417 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2418                                                  unsigned char **ppMemory,
2419                                                  PFORMAT_STRING pFormat,
2420                                                  unsigned char fMustAlloc)
2421 {
2422 /*  unsigned flags = pFormat[1];*/
2423   unsigned index = *(const WORD*)&pFormat[2];
2424   DWORD memsize = *(const WORD*)&pFormat[4];
2425   unsigned long uflag = UserMarshalFlags(pStubMsg);
2426   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2427   TRACE("index=%d\n", index);
2428
2429   if (fMustAlloc || !*ppMemory)
2430     *ppMemory = NdrAllocate(pStubMsg, memsize);
2431
2432   pStubMsg->Buffer =
2433     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
2434       &uflag, pStubMsg->Buffer, *ppMemory);
2435
2436   return NULL;
2437 }
2438
2439 /***********************************************************************
2440  *           NdrUserMarshalBufferSize [RPCRT4.@]
2441  */
2442 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2443                                       unsigned char *pMemory,
2444                                       PFORMAT_STRING pFormat)
2445 {
2446 /*  unsigned flags = pFormat[1];*/
2447   unsigned index = *(const WORD*)&pFormat[2];
2448   DWORD bufsize = *(const WORD*)&pFormat[6];
2449   unsigned long uflag = UserMarshalFlags(pStubMsg);
2450   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2451   TRACE("index=%d\n", index);
2452
2453   if (bufsize) {
2454     TRACE("size=%ld\n", bufsize);
2455     pStubMsg->BufferLength += bufsize;
2456     return;
2457   }
2458
2459   pStubMsg->BufferLength =
2460     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
2461       &uflag, pStubMsg->BufferLength, pMemory);
2462 }
2463
2464 /***********************************************************************
2465  *           NdrUserMarshalMemorySize [RPCRT4.@]
2466  */
2467 unsigned long WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2468                                               PFORMAT_STRING pFormat)
2469 {
2470   unsigned index = *(const WORD*)&pFormat[2];
2471 /*  DWORD memsize = *(const WORD*)&pFormat[4]; */
2472   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
2473   TRACE("index=%d\n", index);
2474
2475   return 0;
2476 }
2477
2478 /***********************************************************************
2479  *           NdrUserMarshalFree [RPCRT4.@]
2480  */
2481 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
2482                                 unsigned char *pMemory,
2483                                 PFORMAT_STRING pFormat)
2484 {
2485 /*  unsigned flags = pFormat[1]; */
2486   unsigned index = *(const WORD*)&pFormat[2];
2487   unsigned long uflag = UserMarshalFlags(pStubMsg);
2488   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2489   TRACE("index=%d\n", index);
2490
2491   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
2492     &uflag, pMemory);
2493 }
2494
2495 /***********************************************************************
2496  *           NdrClearOutParameters [RPCRT4.@]
2497  */
2498 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
2499                                   PFORMAT_STRING pFormat,
2500                                   void *ArgAddr)
2501 {
2502   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
2503 }
2504
2505 /***********************************************************************
2506  *           NdrConvert [RPCRT4.@]
2507  */
2508 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
2509 {
2510   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
2511   /* FIXME: since this stub doesn't do any converting, the proper behavior
2512      is to raise an exception */
2513 }
2514
2515 /***********************************************************************
2516  *           NdrConvert2 [RPCRT4.@]
2517  */
2518 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )
2519 {
2520   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n",
2521     pStubMsg, pFormat, NumberParams);
2522   /* FIXME: since this stub doesn't do any converting, the proper behavior
2523      is to raise an exception */
2524 }
2525
2526 typedef struct _NDR_CSTRUCT_FORMAT
2527 {
2528     unsigned char type;
2529     unsigned char alignment;
2530     unsigned short memory_size;
2531     short offset_to_array_description;
2532 } NDR_CSTRUCT_FORMAT;
2533
2534 /***********************************************************************
2535  *           NdrConformantStructMarshall [RPCRT4.@]
2536  */
2537 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2538                                 unsigned char *pMemory,
2539                                 PFORMAT_STRING pFormat)
2540 {
2541     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2542     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2543
2544     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2545
2546     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2547     {
2548         ERR("invalid format type %x\n", pCStructFormat->type);
2549         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2550         return NULL;
2551     }
2552
2553     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
2554
2555     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2556
2557     /* copy constant sized part of struct */
2558     memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size);
2559     pStubMsg->Buffer += pCStructFormat->memory_size;
2560
2561     if (pCStructFormat->offset_to_array_description)
2562     {
2563         PFORMAT_STRING pArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2564             pCStructFormat->offset_to_array_description;
2565         NdrConformantArrayMarshall(pStubMsg, pMemory + pCStructFormat->memory_size, pArrayFormat);
2566     }
2567     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2568         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2569     return NULL;
2570 }
2571
2572 /***********************************************************************
2573  *           NdrConformantStructUnmarshall [RPCRT4.@]
2574  */
2575 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2576                                 unsigned char **ppMemory,
2577                                 PFORMAT_STRING pFormat,
2578                                 unsigned char fMustAlloc)
2579 {
2580     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2581     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2582
2583     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2584
2585     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2586     {
2587         ERR("invalid format type %x\n", pCStructFormat->type);
2588         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2589         return NULL;
2590     }
2591
2592     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
2593
2594     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2595
2596     /* work out how much memory to allocate if we need to do so */
2597     if (!*ppMemory || fMustAlloc)
2598     {
2599         SIZE_T size = pCStructFormat->memory_size;
2600     
2601         if (pCStructFormat->offset_to_array_description)
2602         {
2603             unsigned char *buffer;
2604             PFORMAT_STRING pArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2605                 pCStructFormat->offset_to_array_description;
2606             buffer = pStubMsg->Buffer;
2607             pStubMsg->Buffer += pCStructFormat->memory_size;
2608             size += NdrConformantArrayMemorySize(pStubMsg, pArrayFormat);
2609             pStubMsg->Buffer = buffer;
2610         }
2611         *ppMemory = NdrAllocate(pStubMsg, size);
2612     }
2613
2614     /* now copy the data */
2615     memcpy(*ppMemory, pStubMsg->Buffer, pCStructFormat->memory_size);
2616     pStubMsg->Buffer += pCStructFormat->memory_size;
2617     if (pCStructFormat->offset_to_array_description)
2618     {
2619         PFORMAT_STRING pArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2620             pCStructFormat->offset_to_array_description;
2621         unsigned char *pMemoryArray = *ppMemory + pCStructFormat->memory_size;
2622         /* note that we pass fMustAlloc as 0 as we have already allocated the
2623          * memory */
2624         NdrConformantArrayUnmarshall(pStubMsg, &pMemoryArray, pArrayFormat, 0);
2625     }
2626     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2627         EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2628     return NULL;
2629 }
2630
2631 /***********************************************************************
2632  *           NdrConformantStructBufferSize [RPCRT4.@]
2633  */
2634 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2635                                 unsigned char *pMemory,
2636                                 PFORMAT_STRING pFormat)
2637 {
2638     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2639     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2640     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2641
2642     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2643     {
2644         ERR("invalid format type %x\n", pCStructFormat->type);
2645         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2646         return;
2647     }
2648
2649     ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
2650
2651     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2652
2653     /* add constant sized part of struct to buffer size */
2654     pStubMsg->BufferLength += pCStructFormat->memory_size;
2655
2656     if (pCStructFormat->offset_to_array_description)
2657     {
2658         PFORMAT_STRING pArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2659             pCStructFormat->offset_to_array_description;
2660         NdrConformantArrayBufferSize(pStubMsg, pMemory + pCStructFormat->memory_size, pArrayFormat);
2661     }
2662     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2663         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2664 }
2665
2666 /***********************************************************************
2667  *           NdrConformantStructMemorySize [RPCRT4.@]
2668  */
2669 unsigned long WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2670                                 PFORMAT_STRING pFormat)
2671 {
2672     FIXME("stub\n");
2673     return 0;
2674 }
2675
2676 /***********************************************************************
2677  *           NdrConformantStructFree [RPCRT4.@]
2678  */
2679 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2680                                 unsigned char *pMemory,
2681                                 PFORMAT_STRING pFormat)
2682 {
2683     FIXME("stub\n");
2684 }
2685
2686 /***********************************************************************
2687  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
2688  */
2689 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2690                                 unsigned char *pMemory,
2691                                 PFORMAT_STRING pFormat)
2692 {
2693     FIXME("stub\n");
2694     return NULL;
2695 }
2696
2697 /***********************************************************************
2698  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
2699  */
2700 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2701                                 unsigned char **ppMemory,
2702                                 PFORMAT_STRING pFormat,
2703                                 unsigned char fMustAlloc)
2704 {
2705     FIXME("stub\n");
2706     return NULL;
2707 }
2708
2709 /***********************************************************************
2710  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
2711  */
2712 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2713                                 unsigned char *pMemory,
2714                                 PFORMAT_STRING pFormat)
2715 {
2716     FIXME("stub\n");
2717 }
2718
2719 /***********************************************************************
2720  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
2721  */
2722 unsigned long WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2723                                 PFORMAT_STRING pFormat)
2724 {
2725     FIXME("stub\n");
2726     return 0;
2727 }
2728
2729 /***********************************************************************
2730  *           NdrConformantVaryingStructFree [RPCRT4.@]
2731  */
2732 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2733                                 unsigned char *pMemory,
2734                                 PFORMAT_STRING pFormat)
2735 {
2736     FIXME("stub\n");
2737 }
2738
2739 /***********************************************************************
2740  *           NdrFixedArrayMarshall [RPCRT4.@]
2741  */
2742 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2743                                 unsigned char *pMemory,
2744                                 PFORMAT_STRING pFormat)
2745 {
2746     FIXME("stub\n");
2747     return NULL;
2748 }
2749
2750 /***********************************************************************
2751  *           NdrFixedArrayUnmarshall [RPCRT4.@]
2752  */
2753 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2754                                 unsigned char **ppMemory,
2755                                 PFORMAT_STRING pFormat,
2756                                 unsigned char fMustAlloc)
2757 {
2758     FIXME("stub\n");
2759     return NULL;
2760 }
2761
2762 /***********************************************************************
2763  *           NdrFixedArrayBufferSize [RPCRT4.@]
2764  */
2765 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2766                                 unsigned char *pMemory,
2767                                 PFORMAT_STRING pFormat)
2768 {
2769     FIXME("stub\n");
2770 }
2771
2772 /***********************************************************************
2773  *           NdrFixedArrayMemorySize [RPCRT4.@]
2774  */
2775 unsigned long WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2776                                 PFORMAT_STRING pFormat)
2777 {
2778     FIXME("stub\n");
2779     return 0;
2780 }
2781
2782 /***********************************************************************
2783  *           NdrFixedArrayFree [RPCRT4.@]
2784  */
2785 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2786                                 unsigned char *pMemory,
2787                                 PFORMAT_STRING pFormat)
2788 {
2789     FIXME("stub\n");
2790 }
2791
2792 /***********************************************************************
2793  *           NdrVaryingArrayMarshall [RPCRT4.@]
2794  */
2795 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2796                                 unsigned char *pMemory,
2797                                 PFORMAT_STRING pFormat)
2798 {
2799     FIXME("stub\n");
2800     return NULL;
2801 }
2802
2803 /***********************************************************************
2804  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
2805  */
2806 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2807                                 unsigned char **ppMemory,
2808                                 PFORMAT_STRING pFormat,
2809                                 unsigned char fMustAlloc)
2810 {
2811     FIXME("stub\n");
2812     return NULL;
2813 }
2814
2815 /***********************************************************************
2816  *           NdrVaryingArrayBufferSize [RPCRT4.@]
2817  */
2818 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2819                                 unsigned char *pMemory,
2820                                 PFORMAT_STRING pFormat)
2821 {
2822     FIXME("stub\n");
2823 }
2824
2825 /***********************************************************************
2826  *           NdrVaryingArrayMemorySize [RPCRT4.@]
2827  */
2828 unsigned long WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2829                                 PFORMAT_STRING pFormat)
2830 {
2831     FIXME("stub\n");
2832     return 0;
2833 }
2834
2835 /***********************************************************************
2836  *           NdrVaryingArrayFree [RPCRT4.@]
2837  */
2838 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2839                                 unsigned char *pMemory,
2840                                 PFORMAT_STRING pFormat)
2841 {
2842     FIXME("stub\n");
2843 }
2844
2845 /***********************************************************************
2846  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
2847  */
2848 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2849                                 unsigned char *pMemory,
2850                                 PFORMAT_STRING pFormat)
2851 {
2852     FIXME("stub\n");
2853     return NULL;
2854 }
2855
2856 /***********************************************************************
2857  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
2858  */
2859 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2860                                 unsigned char **ppMemory,
2861                                 PFORMAT_STRING pFormat,
2862                                 unsigned char fMustAlloc)
2863 {
2864     FIXME("stub\n");
2865     return NULL;
2866 }
2867
2868 /***********************************************************************
2869  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
2870  */
2871 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2872                                 unsigned char *pMemory,
2873                                 PFORMAT_STRING pFormat)
2874 {
2875     FIXME("stub\n");
2876 }
2877
2878 /***********************************************************************
2879  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
2880  */
2881 unsigned long WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2882                                 PFORMAT_STRING pFormat)
2883 {
2884     FIXME("stub\n");
2885     return 0;
2886 }
2887
2888 /***********************************************************************
2889  *           NdrEncapsulatedUnionFree [RPCRT4.@]
2890  */
2891 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
2892                                 unsigned char *pMemory,
2893                                 PFORMAT_STRING pFormat)
2894 {
2895     FIXME("stub\n");
2896 }
2897
2898 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
2899                                                              unsigned long discriminant,
2900                                                              PFORMAT_STRING pFormat)
2901 {
2902     unsigned short num_arms, arm, type;
2903
2904     num_arms = *(const SHORT*)pFormat & 0x0fff;
2905     pFormat += 2;
2906     for(arm = 0; arm < num_arms; arm++)
2907     {
2908         if(discriminant == *(const ULONG*)pFormat)
2909         {
2910             pFormat += 4;
2911             break;
2912         }
2913         pFormat += 6;
2914     }
2915
2916     type = *(const unsigned short*)pFormat;
2917     TRACE("type %04x\n", type);
2918     if(arm == num_arms) /* default arm extras */
2919     {
2920         if(type == 0xffff)
2921         {
2922             FIXME("should raise an exception here\n");
2923             return NULL;
2924         }
2925         if(type == 0)
2926         {
2927             /* Don't marshall any type. FIXME is this correct? */
2928             return NULL;
2929         }
2930     }
2931     return pFormat;
2932 }
2933
2934 static PFORMAT_STRING get_non_encapsulated_union_arm(PMIDL_STUB_MESSAGE pStubMsg,
2935                                                      unsigned char *pMemory,
2936                                                      PFORMAT_STRING pFormat)
2937 {
2938     ULONG value;
2939
2940     pFormat = ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat,
2941                                            0, &value);
2942     TRACE("got switch value %lx\n", value);
2943     pFormat += *(const SHORT*)pFormat;
2944     pFormat += 2;
2945
2946     return get_arm_offset_from_union_arm_selector(pStubMsg, value, pFormat);
2947 }
2948
2949 static unsigned char *get_conformance_address(PMIDL_STUB_MESSAGE pStubMsg,
2950                                               unsigned char *pMemory,
2951                                               PFORMAT_STRING pFormat)
2952 {
2953     short ofs = *(short *)&pFormat[2];
2954     LPVOID ptr = NULL;
2955
2956     switch (pFormat[0] & 0xf0)
2957     {
2958     case RPC_FC_NORMAL_CONFORMANCE:
2959         ptr = pMemory;
2960         break;
2961     default:
2962         FIXME("Conformance type %x\n", pFormat[0]);
2963         return NULL;
2964     }
2965
2966     if(pFormat[1])
2967     {
2968         FIXME("Conformance op %x\n", pFormat[1]);
2969         return NULL;
2970     }
2971
2972     return (unsigned char *)ptr + ofs;
2973 }
2974
2975 /***********************************************************************
2976  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
2977  */
2978 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2979                                 unsigned char *pMemory,
2980                                 PFORMAT_STRING pFormat)
2981 {
2982     unsigned char *discriminant;
2983     unsigned short type;
2984
2985     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2986     pFormat++;
2987
2988     /* Marshall discriminant */
2989     discriminant = get_conformance_address(pStubMsg, pMemory, pFormat + 1);
2990     NdrBaseTypeMarshall(pStubMsg, discriminant, pFormat);
2991     pFormat++;
2992
2993     pFormat = get_non_encapsulated_union_arm(pStubMsg, pMemory, pFormat);
2994     if(!pFormat)
2995         return NULL;
2996
2997     type = *(const unsigned short*)pFormat;
2998     if(type & 0x8000)
2999     {
3000         pFormat++; 
3001         return NdrBaseTypeMarshall(pStubMsg, pMemory, pFormat);
3002     }
3003     else
3004     {
3005         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3006         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
3007         if (m)
3008         {
3009             switch(*desc)
3010             {
3011             case RPC_FC_RP:
3012             case RPC_FC_UP:
3013             case RPC_FC_OP:
3014             case RPC_FC_FP:
3015                 pMemory = *(void**)pMemory;
3016                 break;
3017             }
3018             m(pStubMsg, pMemory, desc);
3019         }
3020         else FIXME("no marshaller for embedded type %02x\n", *desc);
3021     }
3022     return NULL;
3023 }
3024
3025 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
3026                                     PFORMAT_STRING *ppFormat)
3027 {
3028     long discriminant = 0;
3029
3030     switch(**ppFormat)
3031     {
3032     case RPC_FC_BYTE:
3033     case RPC_FC_CHAR:
3034     case RPC_FC_SMALL:
3035     case RPC_FC_USMALL:
3036         discriminant = *(UCHAR *)pStubMsg->Buffer;
3037         pStubMsg->Buffer += sizeof(UCHAR);
3038         break;
3039     case RPC_FC_WCHAR:
3040     case RPC_FC_SHORT:
3041     case RPC_FC_USHORT:
3042         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
3043         discriminant = *(USHORT *)pStubMsg->Buffer;
3044         pStubMsg->Buffer += sizeof(USHORT);
3045         break;
3046     case RPC_FC_LONG:
3047     case RPC_FC_ULONG:
3048         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
3049         discriminant = *(ULONG *)pStubMsg->Buffer;
3050         pStubMsg->Buffer += sizeof(ULONG);
3051         break;
3052     default:
3053         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
3054     }
3055     (*ppFormat)++;
3056
3057     if (pStubMsg->fHasNewCorrDesc)
3058         *ppFormat += 6;
3059     else
3060         *ppFormat += 4;
3061     return discriminant;
3062 }
3063
3064 /**********************************************************************
3065  *           NdrNonEncapsulatedUnionUnmarshall[RPCRT4.@]
3066  */
3067 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3068                                 unsigned char **ppMemory,
3069                                 PFORMAT_STRING pFormat,
3070                                 unsigned char fMustAlloc)
3071 {
3072     long discriminant;
3073     unsigned short type, size;
3074
3075     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3076     pFormat++;
3077
3078     /* Unmarshall discriminant */
3079     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
3080     TRACE("unmarshalled discriminant %lx\n", discriminant);
3081
3082     pFormat += *(const SHORT*)pFormat;
3083
3084     size = *(const unsigned short*)pFormat;
3085     pFormat += 2;
3086
3087     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
3088     if(!pFormat)
3089         return NULL;
3090
3091     if(!*ppMemory || fMustAlloc)
3092         *ppMemory = NdrAllocate(pStubMsg, size);
3093
3094     type = *(const unsigned short*)pFormat;
3095     if(type & 0x8000)
3096     {
3097         pFormat++; 
3098         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3099     }
3100     else
3101     {
3102         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3103         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
3104         if (m)
3105         {
3106             switch(*desc)
3107             {
3108             case RPC_FC_RP:
3109             case RPC_FC_UP:
3110             case RPC_FC_OP:
3111             case RPC_FC_FP:
3112                 **(void***)ppMemory = NULL;
3113                 break;
3114             }
3115             return m(pStubMsg, (unsigned char **)*ppMemory, desc, fMustAlloc);
3116         }
3117         else FIXME("no marshaller for embedded type %02x\n", *desc);
3118     }
3119     return NULL;
3120 }
3121
3122 /***********************************************************************
3123  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
3124  */
3125 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3126                                 unsigned char *pMemory,
3127                                 PFORMAT_STRING pFormat)
3128 {
3129     unsigned short type;
3130     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3131
3132     pFormat++;
3133     /* Add discriminant size */
3134     NdrBaseTypeBufferSize(pStubMsg, pMemory, pFormat);
3135     pFormat++;
3136
3137     pFormat = get_non_encapsulated_union_arm(pStubMsg, pMemory, pFormat);
3138     if(!pFormat)
3139         return;
3140
3141     type = *(const unsigned short*)pFormat;
3142     if(type & 0x8000)
3143     {
3144         pFormat++; 
3145         NdrBaseTypeBufferSize(pStubMsg, pMemory, pFormat);
3146     }
3147     else
3148     {
3149         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3150         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3151         if (m)
3152         {
3153             switch(*desc)
3154             {
3155             case RPC_FC_RP:
3156             case RPC_FC_UP:
3157             case RPC_FC_OP:
3158             case RPC_FC_FP:
3159                 pMemory = *(void**)pMemory;
3160                 break;
3161             }
3162             m(pStubMsg, pMemory, desc);
3163         }
3164         else FIXME("no buffersizer for embedded type %02x\n", *desc);
3165     }
3166     return;
3167 }
3168
3169 /***********************************************************************
3170  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
3171  */
3172 unsigned long WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3173                                 PFORMAT_STRING pFormat)
3174 {
3175     pFormat += 2;
3176     if (pStubMsg->fHasNewCorrDesc)
3177         pFormat += 6;
3178     else
3179         pFormat += 4;
3180
3181     pFormat += *(const SHORT*)pFormat;
3182     TRACE("size %d\n", *(const SHORT*)pFormat);
3183     return *(const SHORT*)pFormat;
3184 }
3185
3186 /***********************************************************************
3187  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
3188  */
3189 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
3190                                 unsigned char *pMemory,
3191                                 PFORMAT_STRING pFormat)
3192 {
3193     FIXME("stub\n");
3194 }
3195
3196 /***********************************************************************
3197  *           NdrByteCountPointerMarshall [RPCRT4.@]
3198  */
3199 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3200                                 unsigned char *pMemory,
3201                                 PFORMAT_STRING pFormat)
3202 {
3203     FIXME("stub\n");
3204     return NULL;
3205 }
3206
3207 /***********************************************************************
3208  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
3209  */
3210 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3211                                 unsigned char **ppMemory,
3212                                 PFORMAT_STRING pFormat,
3213                                 unsigned char fMustAlloc)
3214 {
3215     FIXME("stub\n");
3216     return NULL;
3217 }
3218
3219 /***********************************************************************
3220  *           NdrByteCountPointerBufferSize [RPCRT4.@]
3221  */
3222 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3223                                 unsigned char *pMemory,
3224                                 PFORMAT_STRING pFormat)
3225 {
3226     FIXME("stub\n");
3227 }
3228
3229 /***********************************************************************
3230  *           NdrByteCountPointerMemorySize [RPCRT4.@]
3231  */
3232 unsigned long WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3233                                 PFORMAT_STRING pFormat)
3234 {
3235     FIXME("stub\n");
3236     return 0;
3237 }
3238
3239 /***********************************************************************
3240  *           NdrByteCountPointerFree [RPCRT4.@]
3241  */
3242 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
3243                                 unsigned char *pMemory,
3244                                 PFORMAT_STRING pFormat)
3245 {
3246     FIXME("stub\n");
3247 }
3248
3249 /***********************************************************************
3250  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
3251  */
3252 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3253                                 unsigned char *pMemory,
3254                                 PFORMAT_STRING pFormat)
3255 {
3256     FIXME("stub\n");
3257     return NULL;
3258 }
3259
3260 /***********************************************************************
3261  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
3262  */
3263 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3264                                 unsigned char **ppMemory,
3265                                 PFORMAT_STRING pFormat,
3266                                 unsigned char fMustAlloc)
3267 {
3268     FIXME("stub\n");
3269     return NULL;
3270 }
3271
3272 /***********************************************************************
3273  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
3274  */
3275 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3276                                 unsigned char *pMemory,
3277                                 PFORMAT_STRING pFormat)
3278 {
3279     FIXME("stub\n");
3280 }
3281
3282 /***********************************************************************
3283  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
3284  */
3285 unsigned long WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3286                                 PFORMAT_STRING pFormat)
3287 {
3288     FIXME("stub\n");
3289     return 0;
3290 }
3291
3292 /***********************************************************************
3293  *           NdrXmitOrRepAsFree [RPCRT4.@]
3294  */
3295 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
3296                                 unsigned char *pMemory,
3297                                 PFORMAT_STRING pFormat)
3298 {
3299     FIXME("stub\n");
3300 }
3301
3302 /***********************************************************************
3303  *           NdrBaseTypeMarshall [internal]
3304  */
3305 static unsigned char *WINAPI NdrBaseTypeMarshall(
3306     PMIDL_STUB_MESSAGE pStubMsg,
3307     unsigned char *pMemory,
3308     PFORMAT_STRING pFormat)
3309 {
3310     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
3311
3312     switch(*pFormat)
3313     {
3314     case RPC_FC_BYTE:
3315     case RPC_FC_CHAR:
3316     case RPC_FC_SMALL:
3317     case RPC_FC_USMALL:
3318         *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory;
3319         pStubMsg->Buffer += sizeof(UCHAR);
3320         TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
3321         break;
3322     case RPC_FC_WCHAR:
3323     case RPC_FC_SHORT:
3324     case RPC_FC_USHORT:
3325         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
3326         *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory;
3327         pStubMsg->Buffer += sizeof(USHORT);
3328         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
3329         break;
3330     case RPC_FC_LONG:
3331     case RPC_FC_ULONG:
3332     case RPC_FC_ERROR_STATUS_T:
3333     case RPC_FC_ENUM32:
3334         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
3335         *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory;
3336         pStubMsg->Buffer += sizeof(ULONG);
3337         TRACE("value: 0x%08lx\n", *(ULONG *)pMemory);
3338         break;
3339     case RPC_FC_FLOAT:
3340         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
3341         *(float *)pStubMsg->Buffer = *(float *)pMemory;
3342         pStubMsg->Buffer += sizeof(float);
3343         break;
3344     case RPC_FC_DOUBLE:
3345         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
3346         *(double *)pStubMsg->Buffer = *(double *)pMemory;
3347         pStubMsg->Buffer += sizeof(double);
3348         break;
3349     case RPC_FC_HYPER:
3350         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
3351         *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory;
3352         pStubMsg->Buffer += sizeof(ULONGLONG);
3353         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
3354         break;
3355     case RPC_FC_ENUM16:
3356         /* only 16-bits on the wire, so do a sanity check */
3357         if (*(UINT *)pMemory > USHRT_MAX)
3358             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
3359         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
3360         *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
3361         pStubMsg->Buffer += sizeof(USHORT);
3362         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
3363         break;
3364     default:
3365         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
3366     }
3367
3368     STD_OVERFLOW_CHECK(pStubMsg);
3369
3370     /* FIXME: what is the correct return value? */
3371     return NULL;
3372 }
3373
3374 /***********************************************************************
3375  *           NdrBaseTypeUnmarshall [internal]
3376  */
3377 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
3378     PMIDL_STUB_MESSAGE pStubMsg,
3379     unsigned char **ppMemory,
3380     PFORMAT_STRING pFormat,
3381     unsigned char fMustAlloc)
3382 {
3383     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
3384
3385     if (fMustAlloc || !*ppMemory)
3386         *ppMemory = NdrAllocate(pStubMsg, NdrBaseTypeMemorySize(pStubMsg, pFormat));
3387
3388     TRACE("*ppMemory: %p\n", *ppMemory);
3389
3390     switch(*pFormat)
3391     {
3392     case RPC_FC_BYTE:
3393     case RPC_FC_CHAR:
3394     case RPC_FC_SMALL:
3395     case RPC_FC_USMALL:
3396         **(UCHAR **)ppMemory = *(UCHAR *)pStubMsg->Buffer;
3397         pStubMsg->Buffer += sizeof(UCHAR);
3398         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
3399         break;
3400     case RPC_FC_WCHAR:
3401     case RPC_FC_SHORT:
3402     case RPC_FC_USHORT:
3403         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
3404         **(USHORT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
3405         pStubMsg->Buffer += sizeof(USHORT);
3406         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
3407         break;
3408     case RPC_FC_LONG:
3409     case RPC_FC_ULONG:
3410     case RPC_FC_ERROR_STATUS_T:
3411     case RPC_FC_ENUM32:
3412         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
3413         **(ULONG **)ppMemory = *(ULONG *)pStubMsg->Buffer;
3414         pStubMsg->Buffer += sizeof(ULONG);
3415         TRACE("value: 0x%08lx\n", **(ULONG **)ppMemory);
3416         break;
3417    case RPC_FC_FLOAT:
3418         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
3419         **(float **)ppMemory = *(float *)pStubMsg->Buffer;
3420         pStubMsg->Buffer += sizeof(float);
3421         TRACE("value: %f\n", **(float **)ppMemory);
3422         break;
3423     case RPC_FC_DOUBLE:
3424         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
3425         **(double **)ppMemory = *(double*)pStubMsg->Buffer;
3426         pStubMsg->Buffer += sizeof(double);
3427         TRACE("value: %f\n", **(double **)ppMemory);
3428         break;
3429     case RPC_FC_HYPER:
3430         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
3431         **(ULONGLONG **)ppMemory = *(ULONGLONG *)pStubMsg->Buffer;
3432         pStubMsg->Buffer += sizeof(ULONGLONG);
3433         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
3434         break;
3435     case RPC_FC_ENUM16:
3436         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
3437         /* 16-bits on the wire, but int in memory */
3438         **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
3439         pStubMsg->Buffer += sizeof(USHORT);
3440         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
3441         break;
3442     default:
3443         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
3444     }
3445
3446     /* FIXME: what is the correct return value? */
3447
3448     return NULL;
3449 }
3450
3451 /***********************************************************************
3452  *           NdrBaseTypeBufferSize [internal]
3453  */
3454 static void WINAPI NdrBaseTypeBufferSize(
3455     PMIDL_STUB_MESSAGE pStubMsg,
3456     unsigned char *pMemory,
3457     PFORMAT_STRING pFormat)
3458 {
3459     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
3460
3461     switch(*pFormat)
3462     {
3463     case RPC_FC_BYTE:
3464     case RPC_FC_CHAR:
3465     case RPC_FC_SMALL:
3466     case RPC_FC_USMALL:
3467         pStubMsg->BufferLength += sizeof(UCHAR);
3468         break;
3469     case RPC_FC_WCHAR:
3470     case RPC_FC_SHORT:
3471     case RPC_FC_USHORT:
3472     case RPC_FC_ENUM16:
3473         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
3474         pStubMsg->BufferLength += sizeof(USHORT);
3475         break;
3476     case RPC_FC_LONG:
3477     case RPC_FC_ULONG:
3478     case RPC_FC_ENUM32:
3479         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
3480         pStubMsg->BufferLength += sizeof(ULONG);
3481         break;
3482     case RPC_FC_FLOAT:
3483         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
3484         pStubMsg->BufferLength += sizeof(float);
3485         break;
3486     case RPC_FC_DOUBLE:
3487         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
3488         pStubMsg->BufferLength += sizeof(double);
3489         break;
3490     case RPC_FC_HYPER:
3491         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
3492         pStubMsg->BufferLength += sizeof(ULONGLONG);
3493         break;
3494     case RPC_FC_ERROR_STATUS_T:
3495         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
3496         pStubMsg->BufferLength += sizeof(error_status_t);
3497         break;
3498     default:
3499         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
3500     }
3501 }
3502
3503 /***********************************************************************
3504  *           NdrBaseTypeMemorySize [internal]
3505  */
3506 static unsigned long WINAPI NdrBaseTypeMemorySize(
3507     PMIDL_STUB_MESSAGE pStubMsg,
3508     PFORMAT_STRING pFormat)
3509 {
3510     switch(*pFormat)
3511     {
3512     case RPC_FC_BYTE:
3513     case RPC_FC_CHAR:
3514     case RPC_FC_SMALL:
3515     case RPC_FC_USMALL:
3516         return sizeof(UCHAR);
3517     case RPC_FC_WCHAR:
3518     case RPC_FC_SHORT:
3519     case RPC_FC_USHORT:
3520         return sizeof(USHORT);
3521     case RPC_FC_LONG:
3522     case RPC_FC_ULONG:
3523         return sizeof(ULONG);
3524     case RPC_FC_FLOAT:
3525         return sizeof(float);
3526     case RPC_FC_DOUBLE:
3527         return sizeof(double);
3528     case RPC_FC_HYPER:
3529         return sizeof(ULONGLONG);
3530     case RPC_FC_ERROR_STATUS_T:
3531         return sizeof(error_status_t);
3532     case RPC_FC_ENUM16:
3533     case RPC_FC_ENUM32:
3534         return sizeof(INT);
3535     default:
3536         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
3537        return 0;
3538     }
3539 }
3540
3541 /***********************************************************************
3542  *           NdrBaseTypeFree [internal]
3543  */
3544 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
3545                                 unsigned char *pMemory,
3546                                 PFORMAT_STRING pFormat)
3547 {
3548    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
3549
3550    /* nothing to do */
3551 }
3552
3553 /***********************************************************************
3554  *           NdrClientContextMarshall
3555  */
3556 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3557                                      NDR_CCONTEXT ContextHandle,
3558                                      int fCheck)
3559 {
3560     FIXME("(%p, %p, %d): stub\n", pStubMsg, ContextHandle, fCheck);
3561 }
3562
3563 /***********************************************************************
3564  *           NdrClientContextUnmarshall
3565  */
3566 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3567                                        NDR_CCONTEXT * pContextHandle,
3568                                        RPC_BINDING_HANDLE BindHandle)
3569 {
3570     FIXME("(%p, %p, %p): stub\n", pStubMsg, pContextHandle, BindHandle);
3571 }
3572
3573 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3574                                      NDR_SCONTEXT ContextHandle,
3575                                      NDR_RUNDOWN RundownRoutine )
3576 {
3577     FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
3578 }
3579
3580 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
3581 {
3582     FIXME("(%p): stub\n", pStubMsg);
3583     return NULL;
3584 }
3585
3586 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
3587                                  unsigned char* pMemory,
3588                                  PFORMAT_STRING pFormat)
3589 {
3590     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
3591 }
3592
3593 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
3594                                                PFORMAT_STRING pFormat)
3595 {
3596     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
3597     return NULL;
3598 }
3599
3600 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3601                                         NDR_SCONTEXT ContextHandle,
3602                                         NDR_RUNDOWN RundownRoutine,
3603                                         PFORMAT_STRING pFormat)
3604 {
3605     FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
3606 }
3607
3608 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3609                                                   PFORMAT_STRING pFormat)
3610 {
3611     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
3612     return NULL;
3613 }
3614
3615 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
3616 {
3617     FIXME("(%p): stub\n", CContext);
3618     return NULL;
3619 }