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