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