rpcrt4: Make more internal functions static.
[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 (*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         *(void **)memptr = NULL;
1113         PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, fMustAlloc);
1114       }
1115     }
1116     pFormat += 8 * count;
1117   }
1118
1119   return NULL;
1120 }
1121
1122 /***********************************************************************
1123  *           EmbeddedPointerBufferSize
1124  */
1125 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1126                                       unsigned char *pMemory,
1127                                       PFORMAT_STRING pFormat)
1128 {
1129   unsigned long Offset = pStubMsg->Offset;
1130   unsigned ofs, rep, count, stride, xofs;
1131   unsigned i;
1132
1133   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1134
1135   if (pStubMsg->IgnoreEmbeddedPointers) return;
1136
1137   if (*pFormat != RPC_FC_PP) return;
1138   pFormat += 2;
1139
1140   while (pFormat[0] != RPC_FC_END) {
1141     switch (pFormat[0]) {
1142     default:
1143       FIXME("unknown repeat type %d\n", pFormat[0]);
1144     case RPC_FC_NO_REPEAT:
1145       rep = 1;
1146       stride = 0;
1147       ofs = 0;
1148       count = 1;
1149       xofs = 0;
1150       pFormat += 2;
1151       break;
1152     case RPC_FC_FIXED_REPEAT:
1153       rep = *(const WORD*)&pFormat[2];
1154       stride = *(const WORD*)&pFormat[4];
1155       ofs = *(const WORD*)&pFormat[6];
1156       count = *(const WORD*)&pFormat[8];
1157       xofs = 0;
1158       pFormat += 10;
1159       break;
1160     case RPC_FC_VARIABLE_REPEAT:
1161       rep = pStubMsg->MaxCount;
1162       stride = *(const WORD*)&pFormat[2];
1163       ofs = *(const WORD*)&pFormat[4];
1164       count = *(const WORD*)&pFormat[6];
1165       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1166       pFormat += 8;
1167       break;
1168     }
1169     /* ofs doesn't seem to matter in this context */
1170     for (i = 0; i < rep; i++) {
1171       PFORMAT_STRING info = pFormat;
1172       unsigned char *membase = pMemory + (i * stride);
1173       unsigned u;
1174       for (u=0; u<count; u++,info+=8) {
1175         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1176         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1177       }
1178     }
1179     pFormat += 8 * count;
1180   }
1181 }
1182
1183 /***********************************************************************
1184  *           EmbeddedPointerMemorySize
1185  */
1186 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1187                                                PFORMAT_STRING pFormat)
1188 {
1189   unsigned long Offset = pStubMsg->Offset;
1190   unsigned char *Mark = pStubMsg->BufferMark;
1191   unsigned ofs, rep, count, stride, xofs;
1192   unsigned i;
1193
1194   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1195
1196   if (*pFormat != RPC_FC_PP) return 0;
1197   pFormat += 2;
1198
1199   while (pFormat[0] != RPC_FC_END) {
1200     switch (pFormat[0]) {
1201     default:
1202       FIXME("unknown repeat type %d\n", pFormat[0]);
1203     case RPC_FC_NO_REPEAT:
1204       rep = 1;
1205       stride = 0;
1206       ofs = 0;
1207       count = 1;
1208       xofs = 0;
1209       pFormat += 2;
1210       break;
1211     case RPC_FC_FIXED_REPEAT:
1212       rep = *(const WORD*)&pFormat[2];
1213       stride = *(const WORD*)&pFormat[4];
1214       ofs = *(const WORD*)&pFormat[6];
1215       count = *(const WORD*)&pFormat[8];
1216       xofs = 0;
1217       pFormat += 10;
1218       break;
1219     case RPC_FC_VARIABLE_REPEAT:
1220       rep = pStubMsg->MaxCount;
1221       stride = *(const WORD*)&pFormat[2];
1222       ofs = *(const WORD*)&pFormat[4];
1223       count = *(const WORD*)&pFormat[6];
1224       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1225       pFormat += 8;
1226       break;
1227     }
1228     /* ofs doesn't seem to matter in this context */
1229     for (i = 0; i < rep; i++) {
1230       PFORMAT_STRING info = pFormat;
1231       unsigned char *bufbase = Mark + (i * stride);
1232       unsigned u;
1233       for (u=0; u<count; u++,info+=8) {
1234         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1235         PointerMemorySize(pStubMsg, bufptr, info+4);
1236       }
1237     }
1238     pFormat += 8 * count;
1239   }
1240
1241   return 0;
1242 }
1243
1244 /***********************************************************************
1245  *           EmbeddedPointerFree
1246  */
1247 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1248                                 unsigned char *pMemory,
1249                                 PFORMAT_STRING pFormat)
1250 {
1251   unsigned long Offset = pStubMsg->Offset;
1252   unsigned ofs, rep, count, stride, xofs;
1253   unsigned i;
1254
1255   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1256   if (*pFormat != RPC_FC_PP) return;
1257   pFormat += 2;
1258
1259   while (pFormat[0] != RPC_FC_END) {
1260     switch (pFormat[0]) {
1261     default:
1262       FIXME("unknown repeat type %d\n", pFormat[0]);
1263     case RPC_FC_NO_REPEAT:
1264       rep = 1;
1265       stride = 0;
1266       ofs = 0;
1267       count = 1;
1268       xofs = 0;
1269       pFormat += 2;
1270       break;
1271     case RPC_FC_FIXED_REPEAT:
1272       rep = *(const WORD*)&pFormat[2];
1273       stride = *(const WORD*)&pFormat[4];
1274       ofs = *(const WORD*)&pFormat[6];
1275       count = *(const WORD*)&pFormat[8];
1276       xofs = 0;
1277       pFormat += 10;
1278       break;
1279     case RPC_FC_VARIABLE_REPEAT:
1280       rep = pStubMsg->MaxCount;
1281       stride = *(const WORD*)&pFormat[2];
1282       ofs = *(const WORD*)&pFormat[4];
1283       count = *(const WORD*)&pFormat[6];
1284       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1285       pFormat += 8;
1286       break;
1287     }
1288     /* ofs doesn't seem to matter in this context */
1289     for (i = 0; i < rep; i++) {
1290       PFORMAT_STRING info = pFormat;
1291       unsigned char *membase = pMemory + (i * stride);
1292       unsigned u;
1293       for (u=0; u<count; u++,info+=8) {
1294         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1295         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1296       }
1297     }
1298     pFormat += 8 * count;
1299   }
1300 }
1301
1302 /***********************************************************************
1303  *           NdrPointerMarshall [RPCRT4.@]
1304  */
1305 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1306                                           unsigned char *pMemory,
1307                                           PFORMAT_STRING pFormat)
1308 {
1309   unsigned char *Buffer;
1310
1311   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1312
1313   /* incremement the buffer here instead of in PointerMarshall,
1314    * as that is used by embedded pointers which already handle the incrementing
1315    * the buffer, and shouldn't write any additional pointer data to the wire */
1316   if (*pFormat != RPC_FC_RP)
1317   {
1318     ALIGN_POINTER(pStubMsg->Buffer, 4);
1319     Buffer = pStubMsg->Buffer;
1320     pStubMsg->Buffer += 4;
1321   }
1322   else
1323     Buffer = pStubMsg->Buffer;
1324
1325   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1326
1327   STD_OVERFLOW_CHECK(pStubMsg);
1328
1329   return NULL;
1330 }
1331
1332 /***********************************************************************
1333  *           NdrPointerUnmarshall [RPCRT4.@]
1334  */
1335 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1336                                             unsigned char **ppMemory,
1337                                             PFORMAT_STRING pFormat,
1338                                             unsigned char fMustAlloc)
1339 {
1340   unsigned char *Buffer;
1341
1342   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1343
1344   /* incremement the buffer here instead of in PointerUnmarshall,
1345    * as that is used by embedded pointers which already handle the incrementing
1346    * the buffer, and shouldn't read any additional pointer data from the
1347    * buffer */
1348   if (*pFormat != RPC_FC_RP)
1349   {
1350     ALIGN_POINTER(pStubMsg->Buffer, 4);
1351     Buffer = pStubMsg->Buffer;
1352     pStubMsg->Buffer += 4;
1353   }
1354   else
1355     Buffer = pStubMsg->Buffer;
1356
1357   PointerUnmarshall(pStubMsg, Buffer, ppMemory, pFormat, fMustAlloc);
1358
1359   return NULL;
1360 }
1361
1362 /***********************************************************************
1363  *           NdrPointerBufferSize [RPCRT4.@]
1364  */
1365 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1366                                       unsigned char *pMemory,
1367                                       PFORMAT_STRING pFormat)
1368 {
1369   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1370
1371   /* incremement the buffer length here instead of in PointerBufferSize,
1372    * as that is used by embedded pointers which already handle the buffer
1373    * length, and shouldn't write anything more to the wire */
1374   if (*pFormat != RPC_FC_RP)
1375   {
1376     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1377     pStubMsg->BufferLength += 4;
1378   }
1379
1380   PointerBufferSize(pStubMsg, pMemory, pFormat);
1381 }
1382
1383 /***********************************************************************
1384  *           NdrPointerMemorySize [RPCRT4.@]
1385  */
1386 unsigned long WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1387                                           PFORMAT_STRING pFormat)
1388 {
1389   /* unsigned size = *(LPWORD)(pFormat+2); */
1390   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1391   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1392   return 0;
1393 }
1394
1395 /***********************************************************************
1396  *           NdrPointerFree [RPCRT4.@]
1397  */
1398 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1399                            unsigned char *pMemory,
1400                            PFORMAT_STRING pFormat)
1401 {
1402   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1403   PointerFree(pStubMsg, pMemory, pFormat);
1404 }
1405
1406 /***********************************************************************
1407  *           NdrSimpleStructMarshall [RPCRT4.@]
1408  */
1409 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1410                                                unsigned char *pMemory,
1411                                                PFORMAT_STRING pFormat)
1412 {
1413   unsigned size = *(const WORD*)(pFormat+2);
1414   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1415
1416   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1417
1418   memcpy(pStubMsg->Buffer, pMemory, size);
1419   pStubMsg->BufferMark = pStubMsg->Buffer;
1420   pStubMsg->Buffer += size;
1421
1422   if (pFormat[0] != RPC_FC_STRUCT)
1423     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1424
1425   STD_OVERFLOW_CHECK(pStubMsg);
1426
1427   return NULL;
1428 }
1429
1430 /***********************************************************************
1431  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1432  */
1433 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1434                                                  unsigned char **ppMemory,
1435                                                  PFORMAT_STRING pFormat,
1436                                                  unsigned char fMustAlloc)
1437 {
1438   unsigned size = *(const WORD*)(pFormat+2);
1439   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1440
1441   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1442
1443   if (fMustAlloc) {
1444     *ppMemory = NdrAllocate(pStubMsg, size);
1445     memcpy(*ppMemory, pStubMsg->Buffer, size);
1446   } else {
1447     if (!pStubMsg->IsClient && !*ppMemory)
1448       /* for servers, we just point straight into the RPC buffer */
1449       *ppMemory = pStubMsg->Buffer;
1450     else
1451       /* for clients, memory should be provided by caller */
1452       memcpy(*ppMemory, pStubMsg->Buffer, size);
1453   }
1454
1455   pStubMsg->BufferMark = pStubMsg->Buffer;
1456   pStubMsg->Buffer += size;
1457
1458   if (pFormat[0] != RPC_FC_STRUCT)
1459     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1460
1461   return NULL;
1462 }
1463
1464
1465 /***********************************************************************
1466  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1467  */
1468 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1469                                    unsigned char FormatChar )
1470 {
1471     FIXME("stub\n");
1472 }
1473
1474
1475 /***********************************************************************
1476  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1477  */
1478 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1479                                      unsigned char FormatChar )
1480 {
1481     FIXME("stub\n");
1482 }
1483
1484
1485 /***********************************************************************
1486  *           NdrSimpleStructBufferSize [RPCRT4.@]
1487  */
1488 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1489                                       unsigned char *pMemory,
1490                                       PFORMAT_STRING pFormat)
1491 {
1492   unsigned size = *(const WORD*)(pFormat+2);
1493   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1494
1495   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1496
1497   pStubMsg->BufferLength += size;
1498   if (pFormat[0] != RPC_FC_STRUCT)
1499     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1500 }
1501
1502 /***********************************************************************
1503  *           NdrSimpleStructMemorySize [RPCRT4.@]
1504  */
1505 unsigned long WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1506                                                PFORMAT_STRING pFormat)
1507 {
1508   unsigned short size = *(LPWORD)(pFormat+2);
1509
1510   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1511
1512   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1513   pStubMsg->MemorySize += size;
1514   pStubMsg->Buffer += size;
1515
1516   if (pFormat[0] != RPC_FC_STRUCT)
1517     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1518   return size;
1519 }
1520
1521 /***********************************************************************
1522  *           NdrSimpleStructFree [RPCRT4.@]
1523  */
1524 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1525                                 unsigned char *pMemory,
1526                                 PFORMAT_STRING pFormat)
1527 {
1528   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1529   if (pFormat[0] != RPC_FC_STRUCT)
1530     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1531 }
1532
1533
1534 static unsigned long EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg,
1535                                          PFORMAT_STRING pFormat)
1536 {
1537   switch (*pFormat) {
1538   case RPC_FC_STRUCT:
1539   case RPC_FC_PSTRUCT:
1540   case RPC_FC_CSTRUCT:
1541   case RPC_FC_BOGUS_STRUCT:
1542     return *(const WORD*)&pFormat[2];
1543   case RPC_FC_USER_MARSHAL:
1544     return *(const WORD*)&pFormat[4];
1545   case RPC_FC_NON_ENCAPSULATED_UNION:
1546     pFormat += 2;
1547     if (pStubMsg->fHasNewCorrDesc)
1548         pFormat += 6;
1549     else
1550         pFormat += 4;
1551
1552     pFormat += *(const SHORT*)pFormat;
1553     return *(const SHORT*)pFormat;
1554   case RPC_FC_IP:
1555     return sizeof(void *);
1556   default:
1557     FIXME("unhandled embedded type %02x\n", *pFormat);
1558   }
1559   return 0;
1560 }
1561
1562
1563 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1564                                                PFORMAT_STRING pFormat)
1565 {
1566   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1567
1568   if (!m)
1569   {
1570     FIXME("no memorysizer for data type=%02x\n", *pFormat);
1571     return 0;
1572   }
1573
1574   return m(pStubMsg, pFormat);
1575 }
1576
1577
1578 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1579                                        unsigned char *pMemory,
1580                                        PFORMAT_STRING pFormat,
1581                                        PFORMAT_STRING pPointer)
1582 {
1583   PFORMAT_STRING desc;
1584   NDR_MARSHALL m;
1585   unsigned long size;
1586
1587   while (*pFormat != RPC_FC_END) {
1588     switch (*pFormat) {
1589     case RPC_FC_SHORT:
1590     case RPC_FC_USHORT:
1591       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1592       memcpy(pStubMsg->Buffer, pMemory, 2);
1593       pStubMsg->Buffer += 2;
1594       pMemory += 2;
1595       break;
1596     case RPC_FC_LONG:
1597     case RPC_FC_ULONG:
1598     case RPC_FC_ENUM32:
1599       TRACE("long=%ld <= %p\n", *(DWORD*)pMemory, pMemory);
1600       memcpy(pStubMsg->Buffer, pMemory, 4);
1601       pStubMsg->Buffer += 4;
1602       pMemory += 4;
1603       break;
1604     case RPC_FC_POINTER:
1605       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1606       NdrPointerMarshall(pStubMsg, *(unsigned char**)pMemory, pPointer);
1607       pPointer += 4;
1608       pMemory += 4;
1609       break;
1610     case RPC_FC_ALIGNM4:
1611       ALIGN_POINTER(pMemory, 4);
1612       break;
1613     case RPC_FC_ALIGNM8:
1614       ALIGN_POINTER(pMemory, 8);
1615       break;
1616     case RPC_FC_STRUCTPAD2:
1617       pMemory += 2;
1618       break;
1619     case RPC_FC_EMBEDDED_COMPLEX:
1620       pMemory += pFormat[1];
1621       pFormat += 2;
1622       desc = pFormat + *(const SHORT*)pFormat;
1623       size = EmbeddedComplexSize(pStubMsg, desc);
1624       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1625       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1626       if (m) m(pStubMsg, pMemory, desc);
1627       else FIXME("no marshaller for embedded type %02x\n", *desc);
1628       pMemory += size;
1629       pFormat += 2;
1630       continue;
1631     case RPC_FC_PAD:
1632       break;
1633     default:
1634       FIXME("unhandled format %02x\n", *pFormat);
1635     }
1636     pFormat++;
1637   }
1638
1639   return pMemory;
1640 }
1641
1642 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1643                                          unsigned char *pMemory,
1644                                          PFORMAT_STRING pFormat,
1645                                          PFORMAT_STRING pPointer,
1646                                          unsigned char fMustAlloc)
1647 {
1648   PFORMAT_STRING desc;
1649   NDR_UNMARSHALL m;
1650   unsigned long size;
1651
1652   while (*pFormat != RPC_FC_END) {
1653     switch (*pFormat) {
1654     case RPC_FC_SHORT:
1655     case RPC_FC_USHORT:
1656       memcpy(pMemory, pStubMsg->Buffer, 2);
1657       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1658       pStubMsg->Buffer += 2;
1659       pMemory += 2;
1660       break;
1661     case RPC_FC_LONG:
1662     case RPC_FC_ULONG:
1663     case RPC_FC_ENUM32:
1664       memcpy(pMemory, pStubMsg->Buffer, 4);
1665       TRACE("long=%ld => %p\n", *(DWORD*)pMemory, pMemory);
1666       pStubMsg->Buffer += 4;
1667       pMemory += 4;
1668       break;
1669     case RPC_FC_POINTER:
1670       *(unsigned char**)pMemory = NULL;
1671       TRACE("pointer => %p\n", pMemory);
1672       NdrPointerUnmarshall(pStubMsg, (unsigned char**)pMemory, pPointer, fMustAlloc);
1673       pPointer += 4;
1674       pMemory += 4;
1675       break;
1676     case RPC_FC_ALIGNM4:
1677       ALIGN_POINTER(pMemory, 4);
1678       break;
1679     case RPC_FC_ALIGNM8:
1680       ALIGN_POINTER(pMemory, 8);
1681       break;
1682     case RPC_FC_STRUCTPAD2:
1683       pMemory += 2;
1684       break;
1685     case RPC_FC_EMBEDDED_COMPLEX:
1686       pMemory += pFormat[1];
1687       pFormat += 2;
1688       desc = pFormat + *(const SHORT*)pFormat;
1689       size = EmbeddedComplexSize(pStubMsg, desc);
1690       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1691       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1692       memset(pMemory, 0, size); /* just in case */
1693       if (m) m(pStubMsg, &pMemory, desc, fMustAlloc);
1694       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
1695       pMemory += size;
1696       pFormat += 2;
1697       continue;
1698     case RPC_FC_PAD:
1699       break;
1700     default:
1701       FIXME("unhandled format %d\n", *pFormat);
1702     }
1703     pFormat++;
1704   }
1705
1706   return pMemory;
1707 }
1708
1709 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1710                                          unsigned char *pMemory,
1711                                          PFORMAT_STRING pFormat,
1712                                          PFORMAT_STRING pPointer)
1713 {
1714   PFORMAT_STRING desc;
1715   NDR_BUFFERSIZE m;
1716   unsigned long size;
1717
1718   while (*pFormat != RPC_FC_END) {
1719     switch (*pFormat) {
1720     case RPC_FC_SHORT:
1721     case RPC_FC_USHORT:
1722       pStubMsg->BufferLength += 2;
1723       pMemory += 2;
1724       break;
1725     case RPC_FC_LONG:
1726     case RPC_FC_ULONG:
1727     case RPC_FC_ENUM32:
1728       pStubMsg->BufferLength += 4;
1729       pMemory += 4;
1730       break;
1731     case RPC_FC_POINTER:
1732       NdrPointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
1733       pPointer += 4;
1734       pMemory += 4;
1735       break;
1736     case RPC_FC_ALIGNM4:
1737       ALIGN_POINTER(pMemory, 4);
1738       break;
1739     case RPC_FC_ALIGNM8:
1740       ALIGN_POINTER(pMemory, 8);
1741       break;
1742     case RPC_FC_STRUCTPAD2:
1743       pMemory += 2;
1744       break;
1745     case RPC_FC_EMBEDDED_COMPLEX:
1746       pMemory += pFormat[1];
1747       pFormat += 2;
1748       desc = pFormat + *(const SHORT*)pFormat;
1749       size = EmbeddedComplexSize(pStubMsg, desc);
1750       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1751       if (m) m(pStubMsg, pMemory, desc);
1752       else FIXME("no buffersizer for embedded type %02x\n", *desc);
1753       pMemory += size;
1754       pFormat += 2;
1755       continue;
1756     case RPC_FC_PAD:
1757       break;
1758     default:
1759       FIXME("unhandled format %d\n", *pFormat);
1760     }
1761     pFormat++;
1762   }
1763
1764   return pMemory;
1765 }
1766
1767 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
1768                                    unsigned char *pMemory,
1769                                    PFORMAT_STRING pFormat,
1770                                    PFORMAT_STRING pPointer)
1771 {
1772   PFORMAT_STRING desc;
1773   NDR_FREE m;
1774   unsigned long size;
1775
1776   while (*pFormat != RPC_FC_END) {
1777     switch (*pFormat) {
1778     case RPC_FC_SHORT:
1779     case RPC_FC_USHORT:
1780       pMemory += 2;
1781       break;
1782     case RPC_FC_LONG:
1783     case RPC_FC_ULONG:
1784     case RPC_FC_ENUM32:
1785       pMemory += 4;
1786       break;
1787     case RPC_FC_POINTER:
1788       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
1789       pPointer += 4;
1790       pMemory += 4;
1791       break;
1792     case RPC_FC_ALIGNM4:
1793       ALIGN_POINTER(pMemory, 4);
1794       break;
1795     case RPC_FC_ALIGNM8:
1796       ALIGN_POINTER(pMemory, 8);
1797       break;
1798     case RPC_FC_STRUCTPAD2:
1799       pMemory += 2;
1800       break;
1801     case RPC_FC_EMBEDDED_COMPLEX:
1802       pMemory += pFormat[1];
1803       pFormat += 2;
1804       desc = pFormat + *(const SHORT*)pFormat;
1805       size = EmbeddedComplexSize(pStubMsg, desc);
1806       m = NdrFreer[*desc & NDR_TABLE_MASK];
1807       if (m) m(pStubMsg, pMemory, desc);
1808       else FIXME("no freer for embedded type %02x\n", *desc);
1809       pMemory += size;
1810       pFormat += 2;
1811       continue;
1812     case RPC_FC_PAD:
1813       break;
1814     default:
1815       FIXME("unhandled format %d\n", *pFormat);
1816     }
1817     pFormat++;
1818   }
1819
1820   return pMemory;
1821 }
1822
1823 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1824                                        PFORMAT_STRING pFormat)
1825 {
1826   PFORMAT_STRING desc;
1827   unsigned long size = 0;
1828
1829   while (*pFormat != RPC_FC_END) {
1830     switch (*pFormat) {
1831     case RPC_FC_SHORT:
1832     case RPC_FC_USHORT:
1833       size += 2;
1834       pStubMsg->Buffer += 2;
1835       break;
1836     case RPC_FC_LONG:
1837     case RPC_FC_ULONG:
1838       size += 4;
1839       pStubMsg->Buffer += 4;
1840       break;
1841     case RPC_FC_POINTER:
1842       size += 4;
1843       pStubMsg->Buffer += 4;
1844       break;
1845     case RPC_FC_ALIGNM4:
1846       ALIGN_LENGTH(size, 4);
1847       ALIGN_POINTER(pStubMsg->Buffer, 4);
1848       break;
1849     case RPC_FC_ALIGNM8:
1850       ALIGN_LENGTH(size, 8);
1851       ALIGN_POINTER(pStubMsg->Buffer, 8);
1852       break;
1853     case RPC_FC_STRUCTPAD2:
1854       size += 2;
1855       pStubMsg->Buffer += 2;
1856       break;
1857     case RPC_FC_EMBEDDED_COMPLEX:
1858       size += pFormat[1];
1859       pFormat += 2;
1860       desc = pFormat + *(const SHORT*)pFormat;
1861       size += EmbeddedComplexMemorySize(pStubMsg, desc);
1862       pFormat += 2;
1863       continue;
1864     case RPC_FC_PAD:
1865       break;
1866     default:
1867       FIXME("unhandled format %d\n", *pFormat);
1868     }
1869     pFormat++;
1870   }
1871
1872   return size;
1873 }
1874
1875 /***********************************************************************
1876  *           NdrComplexStructMarshall [RPCRT4.@]
1877  */
1878 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1879                                                 unsigned char *pMemory,
1880                                                 PFORMAT_STRING pFormat)
1881 {
1882   PFORMAT_STRING conf_array = NULL;
1883   PFORMAT_STRING pointer_desc = NULL;
1884   unsigned char *OldMemory = pStubMsg->Memory;
1885
1886   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1887
1888   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1889
1890   pFormat += 4;
1891   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1892   pFormat += 2;
1893   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1894   pFormat += 2;
1895
1896   pStubMsg->Memory = pMemory;
1897
1898   ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
1899
1900   if (conf_array)
1901     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
1902
1903   pStubMsg->Memory = OldMemory;
1904
1905   STD_OVERFLOW_CHECK(pStubMsg);
1906
1907   return NULL;
1908 }
1909
1910 /***********************************************************************
1911  *           NdrComplexStructUnmarshall [RPCRT4.@]
1912  */
1913 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1914                                                   unsigned char **ppMemory,
1915                                                   PFORMAT_STRING pFormat,
1916                                                   unsigned char fMustAlloc)
1917 {
1918   unsigned size = *(const WORD*)(pFormat+2);
1919   PFORMAT_STRING conf_array = NULL;
1920   PFORMAT_STRING pointer_desc = NULL;
1921   unsigned char *pMemory;
1922
1923   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1924
1925   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1926
1927   if (fMustAlloc || !*ppMemory)
1928   {
1929     *ppMemory = NdrAllocate(pStubMsg, size);
1930     memset(*ppMemory, 0, size);
1931   }
1932
1933   pFormat += 4;
1934   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1935   pFormat += 2;
1936   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1937   pFormat += 2;
1938
1939   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
1940
1941   if (conf_array)
1942     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
1943
1944   return NULL;
1945 }
1946
1947 /***********************************************************************
1948  *           NdrComplexStructBufferSize [RPCRT4.@]
1949  */
1950 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1951                                        unsigned char *pMemory,
1952                                        PFORMAT_STRING pFormat)
1953 {
1954   PFORMAT_STRING conf_array = NULL;
1955   PFORMAT_STRING pointer_desc = NULL;
1956   unsigned char *OldMemory = pStubMsg->Memory;
1957
1958   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1959
1960   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1961
1962   pFormat += 4;
1963   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1964   pFormat += 2;
1965   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1966   pFormat += 2;
1967
1968   pStubMsg->Memory = pMemory;
1969
1970   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
1971
1972   if (conf_array)
1973     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
1974
1975   pStubMsg->Memory = OldMemory;
1976 }
1977
1978 /***********************************************************************
1979  *           NdrComplexStructMemorySize [RPCRT4.@]
1980  */
1981 unsigned long WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1982                                                 PFORMAT_STRING pFormat)
1983 {
1984   unsigned size = *(const WORD*)(pFormat+2);
1985   PFORMAT_STRING conf_array = NULL;
1986   PFORMAT_STRING pointer_desc = NULL;
1987
1988   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1989
1990   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1991
1992   pFormat += 4;
1993   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1994   pFormat += 2;
1995   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1996   pFormat += 2;
1997
1998   ComplexStructMemorySize(pStubMsg, pFormat);
1999
2000   if (conf_array)
2001     NdrConformantArrayMemorySize(pStubMsg, conf_array);
2002
2003   return size;
2004 }
2005
2006 /***********************************************************************
2007  *           NdrComplexStructFree [RPCRT4.@]
2008  */
2009 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2010                                  unsigned char *pMemory,
2011                                  PFORMAT_STRING pFormat)
2012 {
2013   PFORMAT_STRING conf_array = NULL;
2014   PFORMAT_STRING pointer_desc = NULL;
2015   unsigned char *OldMemory = pStubMsg->Memory;
2016
2017   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2018
2019   pFormat += 4;
2020   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2021   pFormat += 2;
2022   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2023   pFormat += 2;
2024
2025   pStubMsg->Memory = pMemory;
2026
2027   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2028
2029   if (conf_array)
2030     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2031
2032   pStubMsg->Memory = OldMemory;
2033 }
2034
2035 /***********************************************************************
2036  *           NdrConformantArrayMarshall [RPCRT4.@]
2037  */
2038 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2039                                                   unsigned char *pMemory,
2040                                                   PFORMAT_STRING pFormat)
2041 {
2042   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2043   unsigned char alignment = pFormat[1] + 1;
2044
2045   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2046   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2047
2048   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2049   size = pStubMsg->MaxCount;
2050
2051   WriteConformance(pStubMsg);
2052
2053   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2054
2055   memcpy(pStubMsg->Buffer, pMemory, size*esize);
2056   pStubMsg->BufferMark = pStubMsg->Buffer;
2057   pStubMsg->Buffer += size*esize;
2058
2059   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2060
2061   STD_OVERFLOW_CHECK(pStubMsg);
2062
2063   return NULL;
2064 }
2065
2066 /***********************************************************************
2067  *           NdrConformantArrayUnmarshall [RPCRT4.@]
2068  */
2069 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2070                                                     unsigned char **ppMemory,
2071                                                     PFORMAT_STRING pFormat,
2072                                                     unsigned char fMustAlloc)
2073 {
2074   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2075   unsigned char alignment = pFormat[1] + 1;
2076
2077   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2078   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2079
2080   pFormat = ReadConformance(pStubMsg, pFormat+4);
2081   size = pStubMsg->MaxCount;
2082
2083   if (fMustAlloc || !*ppMemory)
2084     *ppMemory = NdrAllocate(pStubMsg, size*esize);
2085
2086   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2087
2088   memcpy(*ppMemory, pStubMsg->Buffer, size*esize);
2089
2090   pStubMsg->BufferMark = pStubMsg->Buffer;
2091   pStubMsg->Buffer += size*esize;
2092
2093   EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2094
2095   return NULL;
2096 }
2097
2098 /***********************************************************************
2099  *           NdrConformantArrayBufferSize [RPCRT4.@]
2100  */
2101 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2102                                          unsigned char *pMemory,
2103                                          PFORMAT_STRING pFormat)
2104 {
2105   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2106   unsigned char alignment = pFormat[1] + 1;
2107
2108   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2109   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2110
2111   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2112   size = pStubMsg->MaxCount;
2113
2114   SizeConformance(pStubMsg);
2115
2116   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2117
2118   /* conformance value plus array */
2119   pStubMsg->BufferLength += size*esize;
2120
2121   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2122 }
2123
2124 /***********************************************************************
2125  *           NdrConformantArrayMemorySize [RPCRT4.@]
2126  */
2127 unsigned long WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2128                                                   PFORMAT_STRING pFormat)
2129 {
2130   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2131   unsigned char alignment = pFormat[1] + 1;
2132
2133   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2134   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2135
2136   pFormat = ReadConformance(pStubMsg, pFormat+4);
2137   size = pStubMsg->MaxCount;
2138   pStubMsg->MemorySize += size*esize;
2139
2140   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2141   pStubMsg->BufferMark = pStubMsg->Buffer;
2142   pStubMsg->Buffer += size*esize;
2143
2144   EmbeddedPointerMemorySize(pStubMsg, pFormat);
2145
2146   return pStubMsg->MemorySize;
2147 }
2148
2149 /***********************************************************************
2150  *           NdrConformantArrayFree [RPCRT4.@]
2151  */
2152 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2153                                    unsigned char *pMemory,
2154                                    PFORMAT_STRING pFormat)
2155 {
2156   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2157   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2158
2159   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2160 }
2161
2162
2163 /***********************************************************************
2164  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
2165  */
2166 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2167                                                          unsigned char* pMemory,
2168                                                          PFORMAT_STRING pFormat )
2169 {
2170     unsigned char alignment = pFormat[1] + 1;
2171     DWORD esize = *(const WORD*)(pFormat+2);
2172
2173     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2174
2175     if (pFormat[0] != RPC_FC_CVARRAY)
2176     {
2177         ERR("invalid format type %x\n", pFormat[0]);
2178         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2179         return NULL;
2180     }
2181
2182     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2183     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2184
2185     WriteConformance(pStubMsg);
2186     WriteVariance(pStubMsg);
2187
2188     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2189
2190     memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, pStubMsg->ActualCount*esize);
2191     pStubMsg->BufferMark = pStubMsg->Buffer;
2192     pStubMsg->Buffer += pStubMsg->ActualCount*esize;
2193
2194     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2195
2196     STD_OVERFLOW_CHECK(pStubMsg);
2197
2198     return NULL;
2199 }
2200
2201
2202 /***********************************************************************
2203  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
2204  */
2205 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2206                                                            unsigned char** ppMemory,
2207                                                            PFORMAT_STRING pFormat,
2208                                                            unsigned char fMustAlloc )
2209 {
2210     unsigned char alignment = pFormat[1] + 1;
2211     DWORD esize = *(const WORD*)(pFormat+2);
2212
2213     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2214
2215     if (pFormat[0] != RPC_FC_CVARRAY)
2216     {
2217         ERR("invalid format type %x\n", pFormat[0]);
2218         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2219         return NULL;
2220     }
2221
2222     pFormat = ReadConformance(pStubMsg, pFormat);
2223     pFormat = ReadVariance(pStubMsg, pFormat);
2224
2225     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2226
2227     if (!*ppMemory || fMustAlloc)
2228         *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
2229     memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, pStubMsg->ActualCount * esize);
2230     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
2231
2232     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2233
2234     return NULL;
2235 }
2236
2237
2238 /***********************************************************************
2239  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
2240  */
2241 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2242                                            unsigned char* pMemory,
2243                                            PFORMAT_STRING pFormat )
2244 {
2245     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2246
2247     if (pFormat[0] != RPC_FC_CVARRAY)
2248     {
2249         ERR("invalid format type %x\n", pFormat[0]);
2250         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2251         return;
2252     }
2253
2254     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2255     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2256
2257     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2258 }
2259
2260
2261 /***********************************************************************
2262  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
2263  */
2264 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2265                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
2266 {
2267     unsigned char alignment = pFormat[1] + 1;
2268     DWORD esize = *(const WORD*)(pFormat+2);
2269
2270     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2271
2272     if (pFormat[0] != RPC_FC_CVARRAY)
2273     {
2274         ERR("invalid format type %x\n", pFormat[0]);
2275         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2276         return;
2277     }
2278
2279     /* compute size */
2280     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2281     /* compute length */
2282     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2283
2284     SizeConformance(pStubMsg);
2285     SizeVariance(pStubMsg);
2286
2287     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2288
2289     pStubMsg->BufferLength += pStubMsg->ActualCount*esize;
2290
2291     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2292 }
2293
2294
2295 /***********************************************************************
2296  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
2297  */
2298 unsigned long WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2299                                                           PFORMAT_STRING pFormat )
2300 {
2301     FIXME( "stub\n" );
2302     return 0;
2303 }
2304
2305
2306 /***********************************************************************
2307  *           NdrComplexArrayMarshall [RPCRT4.@]
2308  */
2309 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2310                                                unsigned char *pMemory,
2311                                                PFORMAT_STRING pFormat)
2312 {
2313   ULONG i, count, def;
2314   BOOL variance_present;
2315   unsigned char alignment;
2316
2317   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2318
2319   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2320   {
2321       ERR("invalid format type %x\n", pFormat[0]);
2322       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2323       return NULL;
2324   }
2325
2326   alignment = pFormat[1] + 1;
2327
2328   def = *(const WORD*)&pFormat[2];
2329   pFormat += 4;
2330
2331   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2332   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2333
2334   variance_present = IsConformanceOrVariancePresent(pFormat);
2335   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2336   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2337
2338   WriteConformance(pStubMsg);
2339   if (variance_present)
2340     WriteVariance(pStubMsg);
2341
2342   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2343
2344   count = pStubMsg->ActualCount;
2345   for (i = 0; i < count; i++)
2346     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2347
2348   STD_OVERFLOW_CHECK(pStubMsg);
2349
2350   return NULL;
2351 }
2352
2353 /***********************************************************************
2354  *           NdrComplexArrayUnmarshall [RPCRT4.@]
2355  */
2356 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2357                                                  unsigned char **ppMemory,
2358                                                  PFORMAT_STRING pFormat,
2359                                                  unsigned char fMustAlloc)
2360 {
2361   ULONG i, count, esize;
2362   unsigned char alignment;
2363   unsigned char *pMemory;
2364   unsigned char *Buffer;
2365
2366   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2367
2368   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2369   {
2370       ERR("invalid format type %x\n", pFormat[0]);
2371       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2372       return NULL;
2373   }
2374
2375   alignment = pFormat[1] + 1;
2376
2377   pFormat += 4;
2378
2379   pFormat = ReadConformance(pStubMsg, pFormat);
2380   pFormat = ReadVariance(pStubMsg, pFormat);
2381
2382   Buffer = pStubMsg->Buffer;
2383   esize = ComplexStructMemorySize(pStubMsg, pFormat);
2384   pStubMsg->Buffer = Buffer;
2385
2386   if (fMustAlloc || !*ppMemory)
2387   {
2388     *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
2389     memset(*ppMemory, 0, pStubMsg->MaxCount * esize);
2390   }
2391
2392   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2393
2394   pMemory = *ppMemory;
2395   count = pStubMsg->ActualCount;
2396   for (i = 0; i < count; i++)
2397     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
2398
2399   return NULL;
2400 }
2401
2402 /***********************************************************************
2403  *           NdrComplexArrayBufferSize [RPCRT4.@]
2404  */
2405 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2406                                       unsigned char *pMemory,
2407                                       PFORMAT_STRING pFormat)
2408 {
2409   ULONG i, count, def;
2410   unsigned char alignment;
2411   BOOL variance_present;
2412
2413   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2414
2415   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2416   {
2417       ERR("invalid format type %x\n", pFormat[0]);
2418       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2419       return;
2420   }
2421
2422   alignment = pFormat[1] + 1;
2423
2424   def = *(const WORD*)&pFormat[2];
2425   pFormat += 4;
2426
2427   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2428   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2429   SizeConformance(pStubMsg);
2430
2431   variance_present = IsConformanceOrVariancePresent(pFormat);
2432   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2433   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2434
2435   if (variance_present)
2436     SizeVariance(pStubMsg);
2437
2438   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2439
2440   count = pStubMsg->ActualCount;
2441   for (i = 0; i < count; i++)
2442     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
2443 }
2444
2445 /***********************************************************************
2446  *           NdrComplexArrayMemorySize [RPCRT4.@]
2447  */
2448 unsigned long WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2449                                                PFORMAT_STRING pFormat)
2450 {
2451   ULONG i, count, esize;
2452   unsigned char alignment;
2453   unsigned char *Buffer;
2454   unsigned long SavedMemorySize;
2455   unsigned long MemorySize;
2456
2457   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2458
2459   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2460   {
2461       ERR("invalid format type %x\n", pFormat[0]);
2462       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2463       return 0;
2464   }
2465
2466   alignment = pFormat[1] + 1;
2467
2468   pFormat += 4;
2469
2470   pFormat = ReadConformance(pStubMsg, pFormat);
2471   pFormat = ReadVariance(pStubMsg, pFormat);
2472
2473   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2474
2475   SavedMemorySize = pStubMsg->MemorySize;
2476
2477   Buffer = pStubMsg->Buffer;
2478   esize = ComplexStructMemorySize(pStubMsg, pFormat);
2479   pStubMsg->Buffer = Buffer;
2480
2481   MemorySize = esize * pStubMsg->MaxCount;
2482
2483   count = pStubMsg->ActualCount;
2484   for (i = 0; i < count; i++)
2485     ComplexStructMemorySize(pStubMsg, pFormat);
2486
2487   pStubMsg->MemorySize = SavedMemorySize;
2488
2489   pStubMsg->MemorySize += MemorySize;
2490   return MemorySize;
2491 }
2492
2493 /***********************************************************************
2494  *           NdrComplexArrayFree [RPCRT4.@]
2495  */
2496 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2497                                 unsigned char *pMemory,
2498                                 PFORMAT_STRING pFormat)
2499 {
2500   ULONG i, count, def;
2501
2502   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2503
2504   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2505   {
2506       ERR("invalid format type %x\n", pFormat[0]);
2507       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2508       return;
2509   }
2510
2511   def = *(const WORD*)&pFormat[2];
2512   pFormat += 4;
2513
2514   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2515   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2516
2517   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2518   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2519
2520   count = pStubMsg->ActualCount;
2521   for (i = 0; i < count; i++)
2522     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2523 }
2524
2525 unsigned long UserMarshalFlags(PMIDL_STUB_MESSAGE pStubMsg)
2526 {
2527   return MAKELONG(pStubMsg->dwDestContext,
2528                   pStubMsg->RpcMsg->DataRepresentation);
2529 }
2530
2531 #define USER_MARSHAL_PTR_PREFIX \
2532         ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
2533         ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
2534
2535 /***********************************************************************
2536  *           NdrUserMarshalMarshall [RPCRT4.@]
2537  */
2538 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2539                                               unsigned char *pMemory,
2540                                               PFORMAT_STRING pFormat)
2541 {
2542   unsigned flags = pFormat[1];
2543   unsigned index = *(const WORD*)&pFormat[2];
2544   unsigned long uflag = UserMarshalFlags(pStubMsg);
2545   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2546   TRACE("index=%d\n", index);
2547
2548   if (flags & USER_MARSHAL_POINTER)
2549   {
2550     ALIGN_POINTER(pStubMsg->Buffer, 4);
2551     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
2552     pStubMsg->Buffer += 4;
2553     ALIGN_POINTER(pStubMsg->Buffer, 8);
2554   }
2555   else
2556     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2557
2558   pStubMsg->Buffer =
2559     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
2560       &uflag, pStubMsg->Buffer, pMemory);
2561
2562   STD_OVERFLOW_CHECK(pStubMsg);
2563
2564   return NULL;
2565 }
2566
2567 /***********************************************************************
2568  *           NdrUserMarshalUnmarshall [RPCRT4.@]
2569  */
2570 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2571                                                  unsigned char **ppMemory,
2572                                                  PFORMAT_STRING pFormat,
2573                                                  unsigned char fMustAlloc)
2574 {
2575   unsigned flags = pFormat[1];
2576   unsigned index = *(const WORD*)&pFormat[2];
2577   DWORD memsize = *(const WORD*)&pFormat[4];
2578   unsigned long uflag = UserMarshalFlags(pStubMsg);
2579   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2580   TRACE("index=%d\n", index);
2581
2582   if (flags & USER_MARSHAL_POINTER)
2583   {
2584     ALIGN_POINTER(pStubMsg->Buffer, 4);
2585     /* skip pointer prefix */
2586     pStubMsg->Buffer += 4;
2587     ALIGN_POINTER(pStubMsg->Buffer, 8);
2588   }
2589   else
2590     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2591
2592   if (fMustAlloc || !*ppMemory)
2593     *ppMemory = NdrAllocate(pStubMsg, memsize);
2594
2595   pStubMsg->Buffer =
2596     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
2597       &uflag, pStubMsg->Buffer, *ppMemory);
2598
2599   return NULL;
2600 }
2601
2602 /***********************************************************************
2603  *           NdrUserMarshalBufferSize [RPCRT4.@]
2604  */
2605 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2606                                       unsigned char *pMemory,
2607                                       PFORMAT_STRING pFormat)
2608 {
2609   unsigned flags = pFormat[1];
2610   unsigned index = *(const WORD*)&pFormat[2];
2611   DWORD bufsize = *(const WORD*)&pFormat[6];
2612   unsigned long uflag = UserMarshalFlags(pStubMsg);
2613   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2614   TRACE("index=%d\n", index);
2615
2616   if (flags & USER_MARSHAL_POINTER)
2617   {
2618     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2619     /* skip pointer prefix */
2620     pStubMsg->BufferLength += 4;
2621     ALIGN_LENGTH(pStubMsg->BufferLength, 8);
2622   }
2623   else
2624     ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
2625
2626   if (bufsize) {
2627     TRACE("size=%ld\n", bufsize);
2628     pStubMsg->BufferLength += bufsize;
2629     return;
2630   }
2631
2632   pStubMsg->BufferLength =
2633     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
2634       &uflag, pStubMsg->BufferLength, pMemory);
2635 }
2636
2637 /***********************************************************************
2638  *           NdrUserMarshalMemorySize [RPCRT4.@]
2639  */
2640 unsigned long WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2641                                               PFORMAT_STRING pFormat)
2642 {
2643   unsigned flags = pFormat[1];
2644   unsigned index = *(const WORD*)&pFormat[2];
2645   DWORD memsize = *(const WORD*)&pFormat[4];
2646   DWORD bufsize = *(const WORD*)&pFormat[6];
2647
2648   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2649   TRACE("index=%d\n", index);
2650
2651   pStubMsg->MemorySize += memsize;
2652
2653   if (flags & USER_MARSHAL_POINTER)
2654   {
2655     ALIGN_POINTER(pStubMsg->Buffer, 4);
2656     /* skip pointer prefix */
2657     pStubMsg->Buffer += 4;
2658     ALIGN_POINTER(pStubMsg->Buffer, 8);
2659   }
2660   else
2661     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2662
2663   pStubMsg->Buffer += bufsize;
2664
2665   return pStubMsg->MemorySize;
2666 }
2667
2668 /***********************************************************************
2669  *           NdrUserMarshalFree [RPCRT4.@]
2670  */
2671 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
2672                                 unsigned char *pMemory,
2673                                 PFORMAT_STRING pFormat)
2674 {
2675 /*  unsigned flags = pFormat[1]; */
2676   unsigned index = *(const WORD*)&pFormat[2];
2677   unsigned long uflag = UserMarshalFlags(pStubMsg);
2678   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2679   TRACE("index=%d\n", index);
2680
2681   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
2682     &uflag, pMemory);
2683 }
2684
2685 /***********************************************************************
2686  *           NdrClearOutParameters [RPCRT4.@]
2687  */
2688 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
2689                                   PFORMAT_STRING pFormat,
2690                                   void *ArgAddr)
2691 {
2692   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
2693 }
2694
2695 /***********************************************************************
2696  *           NdrConvert [RPCRT4.@]
2697  */
2698 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
2699 {
2700   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
2701   /* FIXME: since this stub doesn't do any converting, the proper behavior
2702      is to raise an exception */
2703 }
2704
2705 /***********************************************************************
2706  *           NdrConvert2 [RPCRT4.@]
2707  */
2708 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )
2709 {
2710   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n",
2711     pStubMsg, pFormat, NumberParams);
2712   /* FIXME: since this stub doesn't do any converting, the proper behavior
2713      is to raise an exception */
2714 }
2715
2716 typedef struct _NDR_CSTRUCT_FORMAT
2717 {
2718     unsigned char type;
2719     unsigned char alignment;
2720     unsigned short memory_size;
2721     short offset_to_array_description;
2722 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
2723
2724 /***********************************************************************
2725  *           NdrConformantStructMarshall [RPCRT4.@]
2726  */
2727 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2728                                 unsigned char *pMemory,
2729                                 PFORMAT_STRING pFormat)
2730 {
2731     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2732     PFORMAT_STRING pCArrayFormat;
2733     ULONG esize;
2734
2735     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2736
2737     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2738     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2739     {
2740         ERR("invalid format type %x\n", pCStructFormat->type);
2741         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2742         return NULL;
2743     }
2744
2745     pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2746         pCStructFormat->offset_to_array_description;
2747     if (*pCArrayFormat != RPC_FC_CARRAY)
2748     {
2749         ERR("invalid array format type %x\n", pCStructFormat->type);
2750         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2751         return NULL;
2752     }
2753     esize = *(const WORD*)(pCArrayFormat+2);
2754
2755     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
2756                        pCArrayFormat + 4, 0);
2757
2758     WriteConformance(pStubMsg);
2759
2760     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
2761
2762     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2763
2764     /* copy constant sized part of struct */
2765     pStubMsg->BufferMark = pStubMsg->Buffer;
2766     memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size + pStubMsg->MaxCount * esize);
2767     pStubMsg->Buffer += pCStructFormat->memory_size + pStubMsg->MaxCount * esize;
2768
2769     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2770         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2771
2772     STD_OVERFLOW_CHECK(pStubMsg);
2773
2774     return NULL;
2775 }
2776
2777 /***********************************************************************
2778  *           NdrConformantStructUnmarshall [RPCRT4.@]
2779  */
2780 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2781                                 unsigned char **ppMemory,
2782                                 PFORMAT_STRING pFormat,
2783                                 unsigned char fMustAlloc)
2784 {
2785     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2786     PFORMAT_STRING pCArrayFormat;
2787     ULONG esize;
2788
2789     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2790
2791     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2792     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2793     {
2794         ERR("invalid format type %x\n", pCStructFormat->type);
2795         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2796         return NULL;
2797     }
2798     pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2799         pCStructFormat->offset_to_array_description;
2800     if (*pCArrayFormat != RPC_FC_CARRAY)
2801     {
2802         ERR("invalid array format type %x\n", pCStructFormat->type);
2803         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2804         return NULL;
2805     }
2806     esize = *(const WORD*)(pCArrayFormat+2);
2807
2808     pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
2809
2810     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
2811
2812     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2813
2814     /* work out how much memory to allocate if we need to do so */
2815     if (!*ppMemory || fMustAlloc)
2816     {
2817         SIZE_T size = pCStructFormat->memory_size + pStubMsg->MaxCount * esize;
2818         *ppMemory = NdrAllocate(pStubMsg, size);
2819     }
2820
2821     /* now copy the data */
2822     pStubMsg->BufferMark = pStubMsg->Buffer;
2823     memcpy(*ppMemory, pStubMsg->Buffer, pCStructFormat->memory_size + pStubMsg->MaxCount * esize);
2824     pStubMsg->Buffer += pCStructFormat->memory_size + pStubMsg->MaxCount * esize;
2825
2826     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2827         EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2828
2829     return NULL;
2830 }
2831
2832 /***********************************************************************
2833  *           NdrConformantStructBufferSize [RPCRT4.@]
2834  */
2835 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2836                                 unsigned char *pMemory,
2837                                 PFORMAT_STRING pFormat)
2838 {
2839     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2840     PFORMAT_STRING pCArrayFormat;
2841     ULONG esize;
2842
2843     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2844
2845     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2846     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2847     {
2848         ERR("invalid format type %x\n", pCStructFormat->type);
2849         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2850         return;
2851     }
2852     pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2853         pCStructFormat->offset_to_array_description;
2854     if (*pCArrayFormat != RPC_FC_CARRAY)
2855     {
2856         ERR("invalid array format type %x\n", pCStructFormat->type);
2857         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2858         return;
2859     }
2860     esize = *(const WORD*)(pCArrayFormat+2);
2861
2862     pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
2863     SizeConformance(pStubMsg);
2864
2865     ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
2866
2867     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2868
2869     pStubMsg->BufferLength += pCStructFormat->memory_size + esize * pStubMsg->MaxCount;
2870
2871     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2872         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2873 }
2874
2875 /***********************************************************************
2876  *           NdrConformantStructMemorySize [RPCRT4.@]
2877  */
2878 unsigned long WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2879                                 PFORMAT_STRING pFormat)
2880 {
2881     FIXME("stub\n");
2882     return 0;
2883 }
2884
2885 /***********************************************************************
2886  *           NdrConformantStructFree [RPCRT4.@]
2887  */
2888 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2889                                 unsigned char *pMemory,
2890                                 PFORMAT_STRING pFormat)
2891 {
2892     FIXME("stub\n");
2893 }
2894
2895 /***********************************************************************
2896  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
2897  */
2898 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2899                                 unsigned char *pMemory,
2900                                 PFORMAT_STRING pFormat)
2901 {
2902     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
2903     PFORMAT_STRING pCVArrayFormat;
2904     ULONG esize;
2905
2906     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2907
2908     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
2909     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
2910     {
2911         ERR("invalid format type %x\n", pCVStructFormat->type);
2912         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2913         return NULL;
2914     }
2915
2916     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
2917         pCVStructFormat->offset_to_array_description;
2918     switch (*pCVArrayFormat)
2919     {
2920     case RPC_FC_CVARRAY:
2921         esize = *(const WORD*)(pCVArrayFormat+2);
2922
2923         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
2924                                             pCVArrayFormat + 4, 0);
2925         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
2926                                          pCVArrayFormat, 0);
2927         break;
2928     case RPC_FC_C_CSTRING:
2929         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
2930         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
2931         esize = sizeof(char);
2932         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
2933             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
2934                                                 pCVArrayFormat + 2, 0);
2935         else
2936             pStubMsg->MaxCount = pStubMsg->ActualCount;
2937         break;
2938     case RPC_FC_C_WSTRING:
2939         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
2940         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
2941         esize = sizeof(WCHAR);
2942         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
2943             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
2944                                                 pCVArrayFormat + 2, 0);
2945         else
2946             pStubMsg->MaxCount = pStubMsg->ActualCount;
2947         break;
2948     default:
2949         ERR("invalid array format type %x\n", *pCVArrayFormat);
2950         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2951         return NULL;
2952     }
2953
2954     WriteConformance(pStubMsg);
2955
2956     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
2957
2958     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
2959
2960     /* write constant sized part */
2961     pStubMsg->BufferMark = pStubMsg->Buffer;
2962     memcpy(pStubMsg->Buffer, pMemory, pCVStructFormat->memory_size);
2963     pStubMsg->Buffer += pCVStructFormat->memory_size;
2964
2965     WriteVariance(pStubMsg);
2966
2967     /* write array part */
2968     memcpy(pStubMsg->Buffer, pMemory + pCVStructFormat->memory_size, pStubMsg->ActualCount * esize);
2969     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
2970
2971     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2972
2973     STD_OVERFLOW_CHECK(pStubMsg);
2974
2975     return NULL;
2976 }
2977
2978 /***********************************************************************
2979  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
2980  */
2981 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2982                                 unsigned char **ppMemory,
2983                                 PFORMAT_STRING pFormat,
2984                                 unsigned char fMustAlloc)
2985 {
2986     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
2987     PFORMAT_STRING pCVArrayFormat;
2988     ULONG esize;
2989     unsigned char cvarray_type;
2990
2991     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2992
2993     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
2994     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
2995     {
2996         ERR("invalid format type %x\n", pCVStructFormat->type);
2997         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2998         return NULL;
2999     }
3000
3001     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3002         pCVStructFormat->offset_to_array_description;
3003     cvarray_type = *pCVArrayFormat;
3004     switch (cvarray_type)
3005     {
3006     case RPC_FC_CVARRAY:
3007         esize = *(const WORD*)(pCVArrayFormat+2);
3008         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3009         break;
3010     case RPC_FC_C_CSTRING:
3011         esize = sizeof(char);
3012         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3013             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3014         else
3015             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3016         break;
3017     case RPC_FC_C_WSTRING:
3018         esize = sizeof(WCHAR);
3019         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3020             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3021         else
3022             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3023         break;
3024     default:
3025         ERR("invalid array format type %x\n", *pCVArrayFormat);
3026         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3027         return NULL;
3028     }
3029
3030     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3031
3032     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3033
3034     /* work out how much memory to allocate if we need to do so */
3035     if (!*ppMemory || fMustAlloc)
3036     {
3037         SIZE_T size = pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3038         *ppMemory = NdrAllocate(pStubMsg, size);
3039     }
3040
3041     /* copy the constant data */
3042     pStubMsg->BufferMark = pStubMsg->Buffer;
3043     memcpy(*ppMemory, pStubMsg->Buffer, pCVStructFormat->memory_size);
3044     pStubMsg->Buffer += pCVStructFormat->memory_size;
3045
3046     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat);
3047
3048     /* copy the array data */
3049     memcpy(*ppMemory + pCVStructFormat->memory_size, pStubMsg->Buffer,
3050            pStubMsg->ActualCount * esize);
3051     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
3052
3053     if (cvarray_type == RPC_FC_C_CSTRING)
3054         TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3055     else if (cvarray_type == RPC_FC_C_WSTRING)
3056         TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3057
3058     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3059
3060     return NULL;
3061 }
3062
3063 /***********************************************************************
3064  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
3065  */
3066 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3067                                 unsigned char *pMemory,
3068                                 PFORMAT_STRING pFormat)
3069 {
3070     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3071     PFORMAT_STRING pCVArrayFormat;
3072     ULONG esize;
3073
3074     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3075
3076     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3077     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3078     {
3079         ERR("invalid format type %x\n", pCVStructFormat->type);
3080         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3081         return;
3082     }
3083
3084     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3085         pCVStructFormat->offset_to_array_description;
3086     switch (*pCVArrayFormat)
3087     {
3088     case RPC_FC_CVARRAY:
3089         esize = *(const WORD*)(pCVArrayFormat+2);
3090
3091         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3092                                             pCVArrayFormat + 4, 0);
3093         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3094                                          pCVArrayFormat + 4, 0);
3095         break;
3096     case RPC_FC_C_CSTRING:
3097         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3098         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3099         esize = sizeof(char);
3100         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3101             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3102                                                 pCVArrayFormat + 2, 0);
3103         else
3104             pStubMsg->MaxCount = pStubMsg->ActualCount;
3105         break;
3106     case RPC_FC_C_WSTRING:
3107         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3108         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3109         esize = sizeof(WCHAR);
3110         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3111             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3112                                                 pCVArrayFormat + 2, 0);
3113         else
3114             pStubMsg->MaxCount = pStubMsg->ActualCount;
3115         break;
3116     default:
3117         ERR("invalid array format type %x\n", *pCVArrayFormat);
3118         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3119         return;
3120     }
3121
3122     SizeConformance(pStubMsg);
3123
3124     ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
3125
3126     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3127
3128     pStubMsg->BufferLength += pCVStructFormat->memory_size;
3129     SizeVariance(pStubMsg);
3130     pStubMsg->BufferLength += esize * pStubMsg->MaxCount;
3131
3132     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3133 }
3134
3135 /***********************************************************************
3136  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
3137  */
3138 unsigned long WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3139                                 PFORMAT_STRING pFormat)
3140 {
3141     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3142     PFORMAT_STRING pCVArrayFormat;
3143     ULONG esize;
3144     unsigned char cvarray_type;
3145
3146     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3147
3148     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3149     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3150     {
3151         ERR("invalid format type %x\n", pCVStructFormat->type);
3152         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3153         return 0;
3154     }
3155
3156     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3157         pCVStructFormat->offset_to_array_description;
3158     cvarray_type = *pCVArrayFormat;
3159     switch (cvarray_type)
3160     {
3161     case RPC_FC_CVARRAY:
3162         esize = *(const WORD*)(pCVArrayFormat+2);
3163         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3164         break;
3165     case RPC_FC_C_CSTRING:
3166         esize = sizeof(char);
3167         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3168             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3169         else
3170             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3171         break;
3172     case RPC_FC_C_WSTRING:
3173         esize = sizeof(WCHAR);
3174         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3175             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3176         else
3177             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3178         break;
3179     default:
3180         ERR("invalid array format type %x\n", *pCVArrayFormat);
3181         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3182         return 0;
3183     }
3184
3185     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3186
3187     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3188
3189     pStubMsg->Buffer += pCVStructFormat->memory_size;
3190     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat);
3191     pStubMsg->Buffer += pCVStructFormat->memory_size + pStubMsg->ActualCount * esize;
3192
3193     pStubMsg->MemorySize += pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3194
3195     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3196
3197     return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3198 }
3199
3200 /***********************************************************************
3201  *           NdrConformantVaryingStructFree [RPCRT4.@]
3202  */
3203 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3204                                 unsigned char *pMemory,
3205                                 PFORMAT_STRING pFormat)
3206 {
3207     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3208     PFORMAT_STRING pCVArrayFormat;
3209     ULONG esize;
3210
3211     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3212
3213     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3214     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3215     {
3216         ERR("invalid format type %x\n", pCVStructFormat->type);
3217         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3218         return;
3219     }
3220
3221     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3222         pCVStructFormat->offset_to_array_description;
3223     switch (*pCVArrayFormat)
3224     {
3225     case RPC_FC_CVARRAY:
3226         esize = *(const WORD*)(pCVArrayFormat+2);
3227
3228         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3229                                             pCVArrayFormat + 4, 0);
3230         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3231                                          pCVArrayFormat, 0);
3232         break;
3233     case RPC_FC_C_CSTRING:
3234         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3235         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3236         esize = sizeof(char);
3237         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3238             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3239                                                 pCVArrayFormat + 2, 0);
3240         else
3241             pStubMsg->MaxCount = pStubMsg->ActualCount;
3242         break;
3243     case RPC_FC_C_WSTRING:
3244         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3245         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3246         esize = sizeof(WCHAR);
3247         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3248             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3249                                                 pCVArrayFormat + 2, 0);
3250         else
3251             pStubMsg->MaxCount = pStubMsg->ActualCount;
3252         break;
3253     default:
3254         ERR("invalid array format type %x\n", *pCVArrayFormat);
3255         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3256         return;
3257     }
3258
3259     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3260
3261     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3262 }
3263
3264 typedef struct
3265 {
3266     unsigned char type;
3267     unsigned char alignment;
3268     unsigned short total_size;
3269 } NDR_SMFARRAY_FORMAT;
3270
3271 typedef struct
3272 {
3273     unsigned char type;
3274     unsigned char alignment;
3275     unsigned long total_size;
3276 } NDR_LGFARRAY_FORMAT;
3277
3278 /***********************************************************************
3279  *           NdrFixedArrayMarshall [RPCRT4.@]
3280  */
3281 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3282                                 unsigned char *pMemory,
3283                                 PFORMAT_STRING pFormat)
3284 {
3285     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3286     unsigned long total_size;
3287
3288     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3289
3290     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3291         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3292     {
3293         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3294         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3295         return NULL;
3296     }
3297
3298     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3299
3300     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3301     {
3302         total_size = pSmFArrayFormat->total_size;
3303         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3304     }
3305     else
3306     {
3307         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3308         total_size = pLgFArrayFormat->total_size;
3309         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3310     }
3311     memcpy(pStubMsg->Buffer, pMemory, total_size);
3312     pStubMsg->Buffer += total_size;
3313
3314     pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3315
3316     return NULL;
3317 }
3318
3319 /***********************************************************************
3320  *           NdrFixedArrayUnmarshall [RPCRT4.@]
3321  */
3322 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3323                                 unsigned char **ppMemory,
3324                                 PFORMAT_STRING pFormat,
3325                                 unsigned char fMustAlloc)
3326 {
3327     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3328     unsigned long total_size;
3329
3330     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3331
3332     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3333         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3334     {
3335         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3336         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3337         return NULL;
3338     }
3339
3340     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3341
3342     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3343     {
3344         total_size = pSmFArrayFormat->total_size;
3345         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3346     }
3347     else
3348     {
3349         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3350         total_size = pLgFArrayFormat->total_size;
3351         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3352     }
3353
3354     if (fMustAlloc || !*ppMemory)
3355         *ppMemory = NdrAllocate(pStubMsg, total_size);
3356     memcpy(*ppMemory, pStubMsg->Buffer, total_size);
3357     pStubMsg->Buffer += total_size;
3358
3359     pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3360
3361     return NULL;
3362 }
3363
3364 /***********************************************************************
3365  *           NdrFixedArrayBufferSize [RPCRT4.@]
3366  */
3367 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3368                                 unsigned char *pMemory,
3369                                 PFORMAT_STRING pFormat)
3370 {
3371     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3372     unsigned long total_size;
3373
3374     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3375
3376     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3377         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3378     {
3379         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3380         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3381         return;
3382     }
3383
3384     ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
3385
3386     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3387     {
3388         total_size = pSmFArrayFormat->total_size;
3389         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3390     }
3391     else
3392     {
3393         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3394         total_size = pLgFArrayFormat->total_size;
3395         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3396     }
3397     pStubMsg->BufferLength += total_size;
3398
3399     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3400 }
3401
3402 /***********************************************************************
3403  *           NdrFixedArrayMemorySize [RPCRT4.@]
3404  */
3405 unsigned long WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3406                                 PFORMAT_STRING pFormat)
3407 {
3408     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3409     unsigned long total_size;
3410
3411     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3412
3413     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3414         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3415     {
3416         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3417         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3418         return 0;
3419     }
3420
3421     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3422
3423     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3424     {
3425         total_size = pSmFArrayFormat->total_size;
3426         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3427     }
3428     else
3429     {
3430         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3431         total_size = pLgFArrayFormat->total_size;
3432         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3433     }
3434     pStubMsg->Buffer += total_size;
3435     pStubMsg->MemorySize += total_size;
3436
3437     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3438
3439     return total_size;
3440 }
3441
3442 /***********************************************************************
3443  *           NdrFixedArrayFree [RPCRT4.@]
3444  */
3445 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3446                                 unsigned char *pMemory,
3447                                 PFORMAT_STRING pFormat)
3448 {
3449     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3450
3451     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3452
3453     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3454         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3455     {
3456         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3457         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3458         return;
3459     }
3460
3461     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3462         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3463     else
3464     {
3465         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3466         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3467     }
3468
3469     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3470 }
3471
3472 /***********************************************************************
3473  *           NdrVaryingArrayMarshall [RPCRT4.@]
3474  */
3475 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3476                                 unsigned char *pMemory,
3477                                 PFORMAT_STRING pFormat)
3478 {
3479     FIXME("stub\n");
3480     return NULL;
3481 }
3482
3483 /***********************************************************************
3484  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
3485  */
3486 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3487                                 unsigned char **ppMemory,
3488                                 PFORMAT_STRING pFormat,
3489                                 unsigned char fMustAlloc)
3490 {
3491     FIXME("stub\n");
3492     return NULL;
3493 }
3494
3495 /***********************************************************************
3496  *           NdrVaryingArrayBufferSize [RPCRT4.@]
3497  */
3498 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3499                                 unsigned char *pMemory,
3500                                 PFORMAT_STRING pFormat)
3501 {
3502     FIXME("stub\n");
3503 }
3504
3505 /***********************************************************************
3506  *           NdrVaryingArrayMemorySize [RPCRT4.@]
3507  */
3508 unsigned long WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3509                                 PFORMAT_STRING pFormat)
3510 {
3511     FIXME("stub\n");
3512     return 0;
3513 }
3514
3515 /***********************************************************************
3516  *           NdrVaryingArrayFree [RPCRT4.@]
3517  */
3518 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3519                                 unsigned char *pMemory,
3520                                 PFORMAT_STRING pFormat)
3521 {
3522     FIXME("stub\n");
3523 }
3524
3525 /***********************************************************************
3526  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
3527  */
3528 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3529                                 unsigned char *pMemory,
3530                                 PFORMAT_STRING pFormat)
3531 {
3532     FIXME("stub\n");
3533     return NULL;
3534 }
3535
3536 /***********************************************************************
3537  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
3538  */
3539 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3540                                 unsigned char **ppMemory,
3541                                 PFORMAT_STRING pFormat,
3542                                 unsigned char fMustAlloc)
3543 {
3544     FIXME("stub\n");
3545     return NULL;
3546 }
3547
3548 /***********************************************************************
3549  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
3550  */
3551 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3552                                 unsigned char *pMemory,
3553                                 PFORMAT_STRING pFormat)
3554 {
3555     FIXME("stub\n");
3556 }
3557
3558 /***********************************************************************
3559  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
3560  */
3561 unsigned long WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3562                                 PFORMAT_STRING pFormat)
3563 {
3564     FIXME("stub\n");
3565     return 0;
3566 }
3567
3568 /***********************************************************************
3569  *           NdrEncapsulatedUnionFree [RPCRT4.@]
3570  */
3571 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
3572                                 unsigned char *pMemory,
3573                                 PFORMAT_STRING pFormat)
3574 {
3575     FIXME("stub\n");
3576 }
3577
3578 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
3579                                                              unsigned long discriminant,
3580                                                              PFORMAT_STRING pFormat)
3581 {
3582     unsigned short num_arms, arm, type;
3583
3584     num_arms = *(const SHORT*)pFormat & 0x0fff;
3585     pFormat += 2;
3586     for(arm = 0; arm < num_arms; arm++)
3587     {
3588         if(discriminant == *(const ULONG*)pFormat)
3589         {
3590             pFormat += 4;
3591             break;
3592         }
3593         pFormat += 6;
3594     }
3595
3596     type = *(const unsigned short*)pFormat;
3597     TRACE("type %04x\n", type);
3598     if(arm == num_arms) /* default arm extras */
3599     {
3600         if(type == 0xffff)
3601         {
3602             ERR("no arm for 0x%lx and no default case\n", discriminant);
3603             RpcRaiseException(RPC_S_INVALID_TAG);
3604             return NULL;
3605         }
3606         if(type == 0)
3607         {
3608             TRACE("falling back to empty default case for 0x%lx\n", discriminant);
3609             return NULL;
3610         }
3611     }
3612     return pFormat;
3613 }
3614
3615 static PFORMAT_STRING get_non_encapsulated_union_arm(PMIDL_STUB_MESSAGE pStubMsg,
3616                                                      ULONG value,
3617                                                      PFORMAT_STRING pFormat)
3618 {
3619     pFormat += *(const SHORT*)pFormat;
3620     pFormat += 2;
3621
3622     return get_arm_offset_from_union_arm_selector(pStubMsg, value, pFormat);
3623 }
3624
3625 /***********************************************************************
3626  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
3627  */
3628 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3629                                 unsigned char *pMemory,
3630                                 PFORMAT_STRING pFormat)
3631 {
3632     unsigned short type;
3633     unsigned char switch_type;
3634
3635     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3636     pFormat++;
3637
3638     switch_type = *pFormat;
3639     pFormat++;
3640
3641     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
3642     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
3643     /* Marshall discriminant */
3644     NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
3645
3646     pFormat = get_non_encapsulated_union_arm(pStubMsg, pStubMsg->MaxCount, pFormat);
3647     if(!pFormat)
3648         return NULL;
3649
3650     type = *(const unsigned short*)pFormat;
3651     if((type & 0xff00) == 0x8000)
3652     {
3653         unsigned char basetype = LOBYTE(type);
3654         return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
3655     }
3656     else
3657     {
3658         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3659         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
3660         if (m)
3661         {
3662             unsigned char *saved_buffer = NULL;
3663             switch(*desc)
3664             {
3665             case RPC_FC_RP:
3666             case RPC_FC_UP:
3667             case RPC_FC_OP:
3668             case RPC_FC_FP:
3669                 saved_buffer = pStubMsg->Buffer;
3670                 pStubMsg->Buffer += 4; /* for pointer ID */
3671                 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
3672                 break;
3673             default:
3674                 m(pStubMsg, pMemory, desc);
3675             }
3676         }
3677         else FIXME("no marshaller for embedded type %02x\n", *desc);
3678     }
3679     return NULL;
3680 }
3681
3682 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
3683                                     PFORMAT_STRING *ppFormat)
3684 {
3685     long discriminant = 0;
3686
3687     switch(**ppFormat)
3688     {
3689     case RPC_FC_BYTE:
3690     case RPC_FC_CHAR:
3691     case RPC_FC_SMALL:
3692     case RPC_FC_USMALL:
3693         discriminant = *(UCHAR *)pStubMsg->Buffer;
3694         pStubMsg->Buffer += sizeof(UCHAR);
3695         break;
3696     case RPC_FC_WCHAR:
3697     case RPC_FC_SHORT:
3698     case RPC_FC_USHORT:
3699         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
3700         discriminant = *(USHORT *)pStubMsg->Buffer;
3701         pStubMsg->Buffer += sizeof(USHORT);
3702         break;
3703     case RPC_FC_LONG:
3704     case RPC_FC_ULONG:
3705         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
3706         discriminant = *(ULONG *)pStubMsg->Buffer;
3707         pStubMsg->Buffer += sizeof(ULONG);
3708         break;
3709     default:
3710         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
3711     }
3712     (*ppFormat)++;
3713
3714     if (pStubMsg->fHasNewCorrDesc)
3715         *ppFormat += 6;
3716     else
3717         *ppFormat += 4;
3718     return discriminant;
3719 }
3720
3721 /**********************************************************************
3722  *           NdrNonEncapsulatedUnionUnmarshall[RPCRT4.@]
3723  */
3724 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3725                                 unsigned char **ppMemory,
3726                                 PFORMAT_STRING pFormat,
3727                                 unsigned char fMustAlloc)
3728 {
3729     long discriminant;
3730     unsigned short type, size;
3731
3732     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3733     pFormat++;
3734
3735     /* Unmarshall discriminant */
3736     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
3737     TRACE("unmarshalled discriminant %lx\n", discriminant);
3738
3739     pFormat += *(const SHORT*)pFormat;
3740
3741     size = *(const unsigned short*)pFormat;
3742     pFormat += 2;
3743
3744     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
3745     if(!pFormat)
3746         return NULL;
3747
3748     if(!*ppMemory || fMustAlloc)
3749         *ppMemory = NdrAllocate(pStubMsg, size);
3750
3751     type = *(const unsigned short*)pFormat;
3752     if((type & 0xff00) == 0x8000)
3753     {
3754         unsigned char basetype = LOBYTE(type);
3755         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, fMustAlloc);
3756     }
3757     else
3758     {
3759         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3760         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
3761         if (m)
3762         {
3763             unsigned char *saved_buffer = NULL;
3764             switch(*desc)
3765             {
3766             case RPC_FC_RP:
3767             case RPC_FC_UP:
3768             case RPC_FC_OP:
3769             case RPC_FC_FP:
3770                 **(void***)ppMemory = NULL;
3771                 ALIGN_POINTER(pStubMsg->Buffer, 4);
3772                 saved_buffer = pStubMsg->Buffer;
3773                 pStubMsg->Buffer += 4; /* for pointer ID */
3774                 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, fMustAlloc);
3775                 break;
3776             default:
3777                 m(pStubMsg, ppMemory, desc, fMustAlloc);
3778             }
3779         }
3780         else FIXME("no marshaller for embedded type %02x\n", *desc);
3781     }
3782     return NULL;
3783 }
3784
3785 /***********************************************************************
3786  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
3787  */
3788 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3789                                 unsigned char *pMemory,
3790                                 PFORMAT_STRING pFormat)
3791 {
3792     unsigned short type;
3793     unsigned char switch_type;
3794
3795     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3796     pFormat++;
3797
3798     switch_type = *pFormat;
3799     pFormat++;
3800
3801     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
3802     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
3803     /* Add discriminant size */
3804     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
3805
3806     pFormat = get_non_encapsulated_union_arm(pStubMsg, pStubMsg->MaxCount, pFormat);
3807     if(!pFormat)
3808         return;
3809
3810     type = *(const unsigned short*)pFormat;
3811     if((type & 0xff00) == 0x8000)
3812     {
3813         unsigned char basetype = LOBYTE(type);
3814         NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
3815     }
3816     else
3817     {
3818         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3819         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3820         if (m)
3821         {
3822             switch(*desc)
3823             {
3824             case RPC_FC_RP:
3825             case RPC_FC_UP:
3826             case RPC_FC_OP:
3827             case RPC_FC_FP:
3828                 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3829                 pStubMsg->BufferLength += 4; /* for pointer ID */
3830                 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
3831                 break;
3832             default:
3833                 m(pStubMsg, pMemory, desc);
3834             }
3835         }
3836         else FIXME("no buffersizer for embedded type %02x\n", *desc);
3837     }
3838     return;
3839 }
3840
3841 /***********************************************************************
3842  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
3843  */
3844 unsigned long WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3845                                 PFORMAT_STRING pFormat)
3846 {
3847     unsigned long discriminant;
3848     unsigned short type, size;
3849
3850     pFormat++;
3851     /* Unmarshall discriminant */
3852     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
3853     TRACE("unmarshalled discriminant 0x%lx\n", discriminant);
3854
3855     pFormat += *(const SHORT*)pFormat;
3856
3857     size = *(const unsigned short*)pFormat;
3858     pFormat += 2;
3859
3860     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
3861     if(!pFormat)
3862         return 0;
3863
3864     pStubMsg->Memory += size;
3865
3866     type = *(const unsigned short*)pFormat;
3867     if((type & 0xff00) == 0x8000)
3868     {
3869         return NdrBaseTypeMemorySize(pStubMsg, pFormat);
3870     }
3871     else
3872     {
3873         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3874         NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
3875         unsigned char *saved_buffer;
3876         if (m)
3877         {
3878             switch(*desc)
3879             {
3880             case RPC_FC_RP:
3881             case RPC_FC_UP:
3882             case RPC_FC_OP:
3883             case RPC_FC_FP:
3884                 ALIGN_POINTER(pStubMsg->Buffer, 4);
3885                 saved_buffer = pStubMsg->Buffer;
3886                 pStubMsg->Buffer += 4;
3887                 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
3888                 pStubMsg->MemorySize += 4;
3889                 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
3890                 break;
3891             default:
3892                 return m(pStubMsg, desc);
3893             }
3894         }
3895         else FIXME("no marshaller for embedded type %02x\n", *desc);
3896     }
3897
3898     TRACE("size %d\n", size);
3899     return size;
3900 }
3901
3902 /***********************************************************************
3903  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
3904  */
3905 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
3906                                 unsigned char *pMemory,
3907                                 PFORMAT_STRING pFormat)
3908 {
3909     FIXME("stub\n");
3910 }
3911
3912 /***********************************************************************
3913  *           NdrByteCountPointerMarshall [RPCRT4.@]
3914  */
3915 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3916                                 unsigned char *pMemory,
3917                                 PFORMAT_STRING pFormat)
3918 {
3919     FIXME("stub\n");
3920     return NULL;
3921 }
3922
3923 /***********************************************************************
3924  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
3925  */
3926 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3927                                 unsigned char **ppMemory,
3928                                 PFORMAT_STRING pFormat,
3929                                 unsigned char fMustAlloc)
3930 {
3931     FIXME("stub\n");
3932     return NULL;
3933 }
3934
3935 /***********************************************************************
3936  *           NdrByteCountPointerBufferSize [RPCRT4.@]
3937  */
3938 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3939                                 unsigned char *pMemory,
3940                                 PFORMAT_STRING pFormat)
3941 {
3942     FIXME("stub\n");
3943 }
3944
3945 /***********************************************************************
3946  *           NdrByteCountPointerMemorySize [RPCRT4.@]
3947  */
3948 unsigned long WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3949                                 PFORMAT_STRING pFormat)
3950 {
3951     FIXME("stub\n");
3952     return 0;
3953 }
3954
3955 /***********************************************************************
3956  *           NdrByteCountPointerFree [RPCRT4.@]
3957  */
3958 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
3959                                 unsigned char *pMemory,
3960                                 PFORMAT_STRING pFormat)
3961 {
3962     FIXME("stub\n");
3963 }
3964
3965 /***********************************************************************
3966  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
3967  */
3968 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3969                                 unsigned char *pMemory,
3970                                 PFORMAT_STRING pFormat)
3971 {
3972     FIXME("stub\n");
3973     return NULL;
3974 }
3975
3976 /***********************************************************************
3977  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
3978  */
3979 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3980                                 unsigned char **ppMemory,
3981                                 PFORMAT_STRING pFormat,
3982                                 unsigned char fMustAlloc)
3983 {
3984     FIXME("stub\n");
3985     return NULL;
3986 }
3987
3988 /***********************************************************************
3989  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
3990  */
3991 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3992                                 unsigned char *pMemory,
3993                                 PFORMAT_STRING pFormat)
3994 {
3995     FIXME("stub\n");
3996 }
3997
3998 /***********************************************************************
3999  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
4000  */
4001 unsigned long WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4002                                 PFORMAT_STRING pFormat)
4003 {
4004     FIXME("stub\n");
4005     return 0;
4006 }
4007
4008 /***********************************************************************
4009  *           NdrXmitOrRepAsFree [RPCRT4.@]
4010  */
4011 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
4012                                 unsigned char *pMemory,
4013                                 PFORMAT_STRING pFormat)
4014 {
4015     FIXME("stub\n");
4016 }
4017
4018 /***********************************************************************
4019  *           NdrBaseTypeMarshall [internal]
4020  */
4021 static unsigned char *WINAPI NdrBaseTypeMarshall(
4022     PMIDL_STUB_MESSAGE pStubMsg,
4023     unsigned char *pMemory,
4024     PFORMAT_STRING pFormat)
4025 {
4026     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4027
4028     switch(*pFormat)
4029     {
4030     case RPC_FC_BYTE:
4031     case RPC_FC_CHAR:
4032     case RPC_FC_SMALL:
4033     case RPC_FC_USMALL:
4034         *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory;
4035         pStubMsg->Buffer += sizeof(UCHAR);
4036         TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
4037         break;
4038     case RPC_FC_WCHAR:
4039     case RPC_FC_SHORT:
4040     case RPC_FC_USHORT:
4041         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4042         *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory;
4043         pStubMsg->Buffer += sizeof(USHORT);
4044         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
4045         break;
4046     case RPC_FC_LONG:
4047     case RPC_FC_ULONG:
4048     case RPC_FC_ERROR_STATUS_T:
4049     case RPC_FC_ENUM32:
4050         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4051         *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory;
4052         pStubMsg->Buffer += sizeof(ULONG);
4053         TRACE("value: 0x%08lx\n", *(ULONG *)pMemory);
4054         break;
4055     case RPC_FC_FLOAT:
4056         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
4057         *(float *)pStubMsg->Buffer = *(float *)pMemory;
4058         pStubMsg->Buffer += sizeof(float);
4059         break;
4060     case RPC_FC_DOUBLE:
4061         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
4062         *(double *)pStubMsg->Buffer = *(double *)pMemory;
4063         pStubMsg->Buffer += sizeof(double);
4064         break;
4065     case RPC_FC_HYPER:
4066         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
4067         *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory;
4068         pStubMsg->Buffer += sizeof(ULONGLONG);
4069         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
4070         break;
4071     case RPC_FC_ENUM16:
4072         /* only 16-bits on the wire, so do a sanity check */
4073         if (*(UINT *)pMemory > USHRT_MAX)
4074             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
4075         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4076         *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
4077         pStubMsg->Buffer += sizeof(USHORT);
4078         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
4079         break;
4080     default:
4081         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4082     }
4083
4084     STD_OVERFLOW_CHECK(pStubMsg);
4085
4086     /* FIXME: what is the correct return value? */
4087     return NULL;
4088 }
4089
4090 /***********************************************************************
4091  *           NdrBaseTypeUnmarshall [internal]
4092  */
4093 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
4094     PMIDL_STUB_MESSAGE pStubMsg,
4095     unsigned char **ppMemory,
4096     PFORMAT_STRING pFormat,
4097     unsigned char fMustAlloc)
4098 {
4099     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
4100
4101     if (fMustAlloc || !*ppMemory)
4102     {
4103         unsigned char *Buffer = pStubMsg->Buffer;
4104         unsigned long MemorySize = pStubMsg->MemorySize;
4105         *ppMemory = NdrAllocate(pStubMsg, NdrBaseTypeMemorySize(pStubMsg, pFormat));
4106         pStubMsg->MemorySize = MemorySize;
4107         pStubMsg->Buffer = Buffer;
4108     }
4109
4110     TRACE("*ppMemory: %p\n", *ppMemory);
4111
4112     switch(*pFormat)
4113     {
4114     case RPC_FC_BYTE:
4115     case RPC_FC_CHAR:
4116     case RPC_FC_SMALL:
4117     case RPC_FC_USMALL:
4118         **(UCHAR **)ppMemory = *(UCHAR *)pStubMsg->Buffer;
4119         pStubMsg->Buffer += sizeof(UCHAR);
4120         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
4121         break;
4122     case RPC_FC_WCHAR:
4123     case RPC_FC_SHORT:
4124     case RPC_FC_USHORT:
4125         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4126         **(USHORT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
4127         pStubMsg->Buffer += sizeof(USHORT);
4128         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
4129         break;
4130     case RPC_FC_LONG:
4131     case RPC_FC_ULONG:
4132     case RPC_FC_ERROR_STATUS_T:
4133     case RPC_FC_ENUM32:
4134         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4135         **(ULONG **)ppMemory = *(ULONG *)pStubMsg->Buffer;
4136         pStubMsg->Buffer += sizeof(ULONG);
4137         TRACE("value: 0x%08lx\n", **(ULONG **)ppMemory);
4138         break;
4139    case RPC_FC_FLOAT:
4140         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
4141         **(float **)ppMemory = *(float *)pStubMsg->Buffer;
4142         pStubMsg->Buffer += sizeof(float);
4143         TRACE("value: %f\n", **(float **)ppMemory);
4144         break;
4145     case RPC_FC_DOUBLE:
4146         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
4147         **(double **)ppMemory = *(double*)pStubMsg->Buffer;
4148         pStubMsg->Buffer += sizeof(double);
4149         TRACE("value: %f\n", **(double **)ppMemory);
4150         break;
4151     case RPC_FC_HYPER:
4152         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
4153         **(ULONGLONG **)ppMemory = *(ULONGLONG *)pStubMsg->Buffer;
4154         pStubMsg->Buffer += sizeof(ULONGLONG);
4155         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
4156         break;
4157     case RPC_FC_ENUM16:
4158         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4159         /* 16-bits on the wire, but int in memory */
4160         **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
4161         pStubMsg->Buffer += sizeof(USHORT);
4162         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
4163         break;
4164     default:
4165         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4166     }
4167
4168     /* FIXME: what is the correct return value? */
4169
4170     return NULL;
4171 }
4172
4173 /***********************************************************************
4174  *           NdrBaseTypeBufferSize [internal]
4175  */
4176 static void WINAPI NdrBaseTypeBufferSize(
4177     PMIDL_STUB_MESSAGE pStubMsg,
4178     unsigned char *pMemory,
4179     PFORMAT_STRING pFormat)
4180 {
4181     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4182
4183     switch(*pFormat)
4184     {
4185     case RPC_FC_BYTE:
4186     case RPC_FC_CHAR:
4187     case RPC_FC_SMALL:
4188     case RPC_FC_USMALL:
4189         pStubMsg->BufferLength += sizeof(UCHAR);
4190         break;
4191     case RPC_FC_WCHAR:
4192     case RPC_FC_SHORT:
4193     case RPC_FC_USHORT:
4194     case RPC_FC_ENUM16:
4195         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
4196         pStubMsg->BufferLength += sizeof(USHORT);
4197         break;
4198     case RPC_FC_LONG:
4199     case RPC_FC_ULONG:
4200     case RPC_FC_ENUM32:
4201         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
4202         pStubMsg->BufferLength += sizeof(ULONG);
4203         break;
4204     case RPC_FC_FLOAT:
4205         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
4206         pStubMsg->BufferLength += sizeof(float);
4207         break;
4208     case RPC_FC_DOUBLE:
4209         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
4210         pStubMsg->BufferLength += sizeof(double);
4211         break;
4212     case RPC_FC_HYPER:
4213         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
4214         pStubMsg->BufferLength += sizeof(ULONGLONG);
4215         break;
4216     case RPC_FC_ERROR_STATUS_T:
4217         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
4218         pStubMsg->BufferLength += sizeof(error_status_t);
4219         break;
4220     default:
4221         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4222     }
4223 }
4224
4225 /***********************************************************************
4226  *           NdrBaseTypeMemorySize [internal]
4227  */
4228 static unsigned long WINAPI NdrBaseTypeMemorySize(
4229     PMIDL_STUB_MESSAGE pStubMsg,
4230     PFORMAT_STRING pFormat)
4231 {
4232     switch(*pFormat)
4233     {
4234     case RPC_FC_BYTE:
4235     case RPC_FC_CHAR:
4236     case RPC_FC_SMALL:
4237     case RPC_FC_USMALL:
4238         pStubMsg->Buffer += sizeof(UCHAR);
4239         pStubMsg->MemorySize += sizeof(UCHAR);
4240         return sizeof(UCHAR);
4241     case RPC_FC_WCHAR:
4242     case RPC_FC_SHORT:
4243     case RPC_FC_USHORT:
4244         pStubMsg->Buffer += sizeof(USHORT);
4245         pStubMsg->MemorySize += sizeof(USHORT);
4246         return sizeof(USHORT);
4247     case RPC_FC_LONG:
4248     case RPC_FC_ULONG:
4249         pStubMsg->Buffer += sizeof(ULONG);
4250         pStubMsg->MemorySize += sizeof(ULONG);
4251         return sizeof(ULONG);
4252     case RPC_FC_FLOAT:
4253         pStubMsg->Buffer += sizeof(float);
4254         pStubMsg->MemorySize += sizeof(float);
4255         return sizeof(float);
4256     case RPC_FC_DOUBLE:
4257         pStubMsg->Buffer += sizeof(double);
4258         pStubMsg->MemorySize += sizeof(double);
4259         return sizeof(double);
4260     case RPC_FC_HYPER:
4261         pStubMsg->Buffer += sizeof(ULONGLONG);
4262         pStubMsg->MemorySize += sizeof(ULONGLONG);
4263         return sizeof(ULONGLONG);
4264     case RPC_FC_ERROR_STATUS_T:
4265         pStubMsg->Buffer += sizeof(error_status_t);
4266         pStubMsg->MemorySize += sizeof(error_status_t);
4267         return sizeof(error_status_t);
4268     case RPC_FC_ENUM16:
4269     case RPC_FC_ENUM32:
4270         pStubMsg->Buffer += sizeof(INT);
4271         pStubMsg->MemorySize += sizeof(INT);
4272         return sizeof(INT);
4273     default:
4274         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4275        return 0;
4276     }
4277 }
4278
4279 /***********************************************************************
4280  *           NdrBaseTypeFree [internal]
4281  */
4282 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
4283                                 unsigned char *pMemory,
4284                                 PFORMAT_STRING pFormat)
4285 {
4286    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4287
4288    /* nothing to do */
4289 }
4290
4291 /***********************************************************************
4292  *           NdrClientContextMarshall
4293  */
4294 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4295                                      NDR_CCONTEXT ContextHandle,
4296                                      int fCheck)
4297 {
4298     FIXME("(%p, %p, %d): stub\n", pStubMsg, ContextHandle, fCheck);
4299 }
4300
4301 /***********************************************************************
4302  *           NdrClientContextUnmarshall
4303  */
4304 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4305                                        NDR_CCONTEXT * pContextHandle,
4306                                        RPC_BINDING_HANDLE BindHandle)
4307 {
4308     FIXME("(%p, %p, %p): stub\n", pStubMsg, pContextHandle, BindHandle);
4309 }
4310
4311 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4312                                      NDR_SCONTEXT ContextHandle,
4313                                      NDR_RUNDOWN RundownRoutine )
4314 {
4315     FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
4316 }
4317
4318 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
4319 {
4320     FIXME("(%p): stub\n", pStubMsg);
4321     return NULL;
4322 }
4323
4324 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
4325                                  unsigned char* pMemory,
4326                                  PFORMAT_STRING pFormat)
4327 {
4328     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
4329 }
4330
4331 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
4332                                                PFORMAT_STRING pFormat)
4333 {
4334     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
4335     return NULL;
4336 }
4337
4338 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4339                                         NDR_SCONTEXT ContextHandle,
4340                                         NDR_RUNDOWN RundownRoutine,
4341                                         PFORMAT_STRING pFormat)
4342 {
4343     FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
4344 }
4345
4346 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4347                                                   PFORMAT_STRING pFormat)
4348 {
4349     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
4350     return NULL;
4351 }
4352
4353 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
4354 {
4355     FIXME("(%p): stub\n", CContext);
4356     return NULL;
4357 }