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