rpcrt4: Introduce a new function, safe_multiply, which will raise an
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * TODO:
22  *  - Non-conformant strings
23  *  - String structs
24  *  - Encapsulated unions
25  *  - Byte count pointers
26  *  - transmit_as/represent as
27  *  - Multi-dimensional arrays
28  *  - Conversion functions (NdrConvert)
29  *  - Checks for integer overflow when calculating array sizes
30  *  - Checks for out-of-memory conditions
31  */
32
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <assert.h>
37 #include <limits.h>
38
39 #include "windef.h"
40 #include "winbase.h"
41 #include "winerror.h"
42 #include "winreg.h"
43
44 #include "ndr_misc.h"
45 #include "rpcndr.h"
46
47 #include "wine/unicode.h"
48 #include "wine/rpcfc.h"
49
50 #include "wine/debug.h"
51 #include "wine/list.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 static 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 RPC_FC_DEREFERENCE: /* already handled */
493   case 0: /* no op */
494     *pCount = data;
495     break;
496   case RPC_FC_ADD_1:
497     *pCount = data + 1;
498     break;
499   case RPC_FC_SUB_1:
500     *pCount = data - 1;
501     break;
502   case RPC_FC_MULT_2:
503     *pCount = data * 2;
504     break;
505   case RPC_FC_DIV_2:
506     *pCount = data / 2;
507     break;
508   default:
509     FIXME("unknown conformance op %d\n", pFormat[1]);
510     goto finish_conf;
511   }
512
513 finish_conf:
514   TRACE("resulting conformance is %ld\n", *pCount);
515   if (pStubMsg->fHasNewCorrDesc)
516     return pFormat+6;
517   else
518     return pFormat+4;
519 }
520
521 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
522  * the result overflows 32-bits */
523 static ULONG inline safe_multiply(ULONG a, ULONG b)
524 {
525     ULONGLONG ret = (ULONGLONG)a * b;
526     if (ret > 0xffffffff)
527     {
528         RpcRaiseException(RPC_S_INVALID_BOUND);
529         return 0;
530     }
531     return ret;
532 }
533
534
535 /*
536  * NdrConformantString:
537  * 
538  * What MS calls a ConformantString is, in DCE terminology,
539  * a Varying-Conformant String.
540  * [
541  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
542  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
543  *           into unmarshalled string) 
544  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
545  *   [ 
546  *     data: CHARTYPE[maxlen]
547  *   ] 
548  * ], where CHARTYPE is the appropriate character type (specified externally)
549  *
550  */
551
552 /***********************************************************************
553  *            NdrConformantStringMarshall [RPCRT4.@]
554  */
555 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
556   unsigned char *pszMessage, PFORMAT_STRING pFormat)
557
558   ULONG esize, size;
559
560   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
561   
562   if (*pFormat == RPC_FC_C_CSTRING) {
563     TRACE("string=%s\n", debugstr_a((char*)pszMessage));
564     pStubMsg->ActualCount = strlen((char*)pszMessage)+1;
565     esize = 1;
566   }
567   else if (*pFormat == RPC_FC_C_WSTRING) {
568     TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
569     pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1;
570     esize = 2;
571   }
572   else {
573     ERR("Unhandled string type: %#x\n", *pFormat); 
574     /* FIXME: raise an exception. */
575     return NULL;
576   }
577
578   if (pFormat[1] == RPC_FC_STRING_SIZED)
579     pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0);
580   else
581     pStubMsg->MaxCount = pStubMsg->ActualCount;
582   pStubMsg->Offset = 0;
583   WriteConformance(pStubMsg);
584   WriteVariance(pStubMsg);
585
586   size = safe_multiply(esize, pStubMsg->ActualCount);
587   memcpy(pStubMsg->Buffer, pszMessage, size); /* the string itself */
588   pStubMsg->Buffer += size;
589
590   STD_OVERFLOW_CHECK(pStubMsg);
591
592   /* success */
593   return NULL; /* is this always right? */
594 }
595
596 /***********************************************************************
597  *           NdrConformantStringBufferSize [RPCRT4.@]
598  */
599 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
600   unsigned char* pMemory, PFORMAT_STRING pFormat)
601 {
602   ULONG esize;
603
604   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
605
606   SizeConformance(pStubMsg);
607   SizeVariance(pStubMsg);
608
609   if (*pFormat == RPC_FC_C_CSTRING) {
610     TRACE("string=%s\n", debugstr_a((char*)pMemory));
611     pStubMsg->ActualCount = strlen((char*)pMemory)+1;
612     esize = 1;
613   }
614   else if (*pFormat == RPC_FC_C_WSTRING) {
615     TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
616     pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1;
617     esize = 2;
618   }
619   else {
620     ERR("Unhandled string type: %#x\n", *pFormat); 
621     /* FIXME: raise an exception */
622     return;
623   }
624
625   if (pFormat[1] == RPC_FC_STRING_SIZED)
626     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
627   else
628     pStubMsg->MaxCount = pStubMsg->ActualCount;
629
630   pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
631 }
632
633 /************************************************************************
634  *            NdrConformantStringMemorySize [RPCRT4.@]
635  */
636 unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
637   PFORMAT_STRING pFormat )
638 {
639   unsigned long rslt = 0;
640
641   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
642    
643   assert(pStubMsg && pFormat);
644
645   if (*pFormat == RPC_FC_C_CSTRING) {
646     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
647   }
648   else if (*pFormat == RPC_FC_C_WSTRING) {
649     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */
650   }
651   else {
652     ERR("Unhandled string type: %#x\n", *pFormat);
653     /* FIXME: raise an exception */
654   }
655
656   if (pFormat[1] != RPC_FC_PAD) {
657     FIXME("sized string format=%d\n", pFormat[1]);
658   }
659
660   TRACE("  --> %lu\n", rslt);
661   return rslt;
662 }
663
664 /************************************************************************
665  *           NdrConformantStringUnmarshall [RPCRT4.@]
666  */
667 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
668   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
669 {
670   unsigned long size, esize;
671
672   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
673     pStubMsg, *ppMemory, pFormat, fMustAlloc);
674
675   assert(pFormat && ppMemory && pStubMsg);
676
677   ReadConformance(pStubMsg, NULL);
678   ReadVariance(pStubMsg, NULL);
679
680   if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
681   else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
682   else {
683     ERR("Unhandled string type: %#x\n", *pFormat);
684     /* FIXME: raise an exception */
685     esize = 0;
686   }
687
688   size = safe_multiply(esize, pStubMsg->ActualCount);
689
690   if (fMustAlloc || !*ppMemory)
691     *ppMemory = NdrAllocate(pStubMsg, size);
692
693   memcpy(*ppMemory, pStubMsg->Buffer, size);
694
695   pStubMsg->Buffer += size;
696
697   if (*pFormat == RPC_FC_C_CSTRING) {
698     TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
699   }
700   else if (*pFormat == RPC_FC_C_WSTRING) {
701     TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
702   }
703
704   return NULL; /* FIXME: is this always right? */
705 }
706
707 /***********************************************************************
708  *           NdrNonConformantStringMarshall [RPCRT4.@]
709  */
710 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
711                                 unsigned char *pMemory,
712                                 PFORMAT_STRING pFormat)
713 {
714     FIXME("stub\n");
715     return NULL;
716 }
717
718 /***********************************************************************
719  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
720  */
721 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
722                                 unsigned char **ppMemory,
723                                 PFORMAT_STRING pFormat,
724                                 unsigned char fMustAlloc)
725 {
726     FIXME("stub\n");
727     return NULL;
728 }
729
730 /***********************************************************************
731  *           NdrNonConformantStringBufferSize [RPCRT4.@]
732  */
733 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
734                                 unsigned char *pMemory,
735                                 PFORMAT_STRING pFormat)
736 {
737     FIXME("stub\n");
738 }
739
740 /***********************************************************************
741  *           NdrNonConformantStringMemorySize [RPCRT4.@]
742  */
743 unsigned long WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
744                                 PFORMAT_STRING pFormat)
745 {
746     FIXME("stub\n");
747     return 0;
748 }
749
750 static inline void dump_pointer_attr(unsigned char attr)
751 {
752     if (attr & RPC_FC_P_ALLOCALLNODES)
753         TRACE(" RPC_FC_P_ALLOCALLNODES");
754     if (attr & RPC_FC_P_DONTFREE)
755         TRACE(" RPC_FC_P_DONTFREE");
756     if (attr & RPC_FC_P_ONSTACK)
757         TRACE(" RPC_FC_P_ONSTACK");
758     if (attr & RPC_FC_P_SIMPLEPOINTER)
759         TRACE(" RPC_FC_P_SIMPLEPOINTER");
760     if (attr & RPC_FC_P_DEREF)
761         TRACE(" RPC_FC_P_DEREF");
762     TRACE("\n");
763 }
764
765 /***********************************************************************
766  *           PointerMarshall
767  */
768 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
769                             unsigned char *Buffer,
770                             unsigned char *Pointer,
771                             PFORMAT_STRING pFormat)
772 {
773   unsigned type = pFormat[0], attr = pFormat[1];
774   PFORMAT_STRING desc;
775   NDR_MARSHALL m;
776   unsigned long pointer_id;
777   int pointer_needs_marshaling;
778
779   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
780   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
781   pFormat += 2;
782   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
783   else desc = pFormat + *(const SHORT*)pFormat;
784
785   switch (type) {
786   case RPC_FC_RP: /* ref pointer (always non-null) */
787 #if 0 /* this causes problems for InstallShield so is disabled - we need more tests */
788     if (!Pointer)
789       RpcRaiseException(RPC_X_NULL_REF_POINTER);
790 #endif
791     pointer_needs_marshaling = 1;
792     break;
793   case RPC_FC_UP: /* unique pointer */
794   case RPC_FC_OP: /* object pointer - same as unique here */
795     if (Pointer)
796       pointer_needs_marshaling = 1;
797     else
798       pointer_needs_marshaling = 0;
799     pointer_id = (unsigned long)Pointer;
800     TRACE("writing 0x%08lx to buffer\n", pointer_id);
801     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
802     break;
803   case RPC_FC_FP:
804     pointer_needs_marshaling = !NdrFullPointerQueryPointer(
805       pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
806     TRACE("writing 0x%08lx to buffer\n", pointer_id);
807     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
808     break;
809   default:
810     FIXME("unhandled ptr type=%02x\n", type);
811     RpcRaiseException(RPC_X_BAD_STUB_DATA);
812     return;
813   }
814
815   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
816
817   if (pointer_needs_marshaling) {
818     if (attr & RPC_FC_P_DEREF) {
819       Pointer = *(unsigned char**)Pointer;
820       TRACE("deref => %p\n", Pointer);
821     }
822     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
823     if (m) m(pStubMsg, Pointer, desc);
824     else FIXME("no marshaller for data type=%02x\n", *desc);
825   }
826
827   STD_OVERFLOW_CHECK(pStubMsg);
828 }
829
830 /***********************************************************************
831  *           PointerUnmarshall
832  */
833 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
834                               unsigned char *Buffer,
835                               unsigned char **pPointer,
836                               PFORMAT_STRING pFormat,
837                               unsigned char fMustAlloc)
838 {
839   unsigned type = pFormat[0], attr = pFormat[1];
840   PFORMAT_STRING desc;
841   NDR_UNMARSHALL m;
842   DWORD pointer_id = 0;
843   int pointer_needs_unmarshaling;
844
845   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc);
846   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
847   pFormat += 2;
848   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
849   else desc = pFormat + *(const SHORT*)pFormat;
850
851   switch (type) {
852   case RPC_FC_RP: /* ref pointer (always non-null) */
853     pointer_needs_unmarshaling = 1;
854     break;
855   case RPC_FC_UP: /* unique pointer */
856     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
857     TRACE("pointer_id is 0x%08lx\n", pointer_id);
858     if (pointer_id)
859       pointer_needs_unmarshaling = 1;
860     else {
861       *pPointer = NULL;
862       pointer_needs_unmarshaling = 0;
863     }
864     break;
865   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
866     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
867     TRACE("pointer_id is 0x%08lx\n", pointer_id);
868     if (!fMustAlloc && *pPointer)
869     {
870         FIXME("free object pointer %p\n", *pPointer);
871         *pPointer = NULL;
872     }
873     if (pointer_id)
874       pointer_needs_unmarshaling = 1;
875     else
876       pointer_needs_unmarshaling = 0;
877     break;
878   case RPC_FC_FP:
879     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
880     TRACE("pointer_id is 0x%08lx\n", pointer_id);
881     pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
882       pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
883     break;
884   default:
885     FIXME("unhandled ptr type=%02x\n", type);
886     RpcRaiseException(RPC_X_BAD_STUB_DATA);
887     return;
888   }
889
890   if (pointer_needs_unmarshaling) {
891     if (attr & RPC_FC_P_DEREF) {
892       if (!*pPointer || fMustAlloc)
893         *pPointer = NdrAllocate(pStubMsg, sizeof(void *));
894       pPointer = *(unsigned char***)pPointer;
895       TRACE("deref => %p\n", pPointer);
896     }
897     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
898     if (m) m(pStubMsg, pPointer, desc, fMustAlloc);
899     else FIXME("no unmarshaller for data type=%02x\n", *desc);
900
901     if (type == RPC_FC_FP)
902       NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
903                                 *pPointer);
904   }
905
906   TRACE("pointer=%p\n", *pPointer);
907 }
908
909 /***********************************************************************
910  *           PointerBufferSize
911  */
912 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
913                               unsigned char *Pointer,
914                               PFORMAT_STRING pFormat)
915 {
916   unsigned type = pFormat[0], attr = pFormat[1];
917   PFORMAT_STRING desc;
918   NDR_BUFFERSIZE m;
919   int pointer_needs_sizing;
920   unsigned long pointer_id;
921
922   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
923   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
924   pFormat += 2;
925   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
926   else desc = pFormat + *(const SHORT*)pFormat;
927
928   switch (type) {
929   case RPC_FC_RP: /* ref pointer (always non-null) */
930     break;
931   case RPC_FC_OP:
932   case RPC_FC_UP:
933     /* NULL pointer has no further representation */
934     if (!Pointer)
935         return;
936     break;
937   case RPC_FC_FP:
938     pointer_needs_sizing = !NdrFullPointerQueryPointer(
939       pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
940     if (!pointer_needs_sizing)
941       return;
942     break;
943   default:
944     FIXME("unhandled ptr type=%02x\n", type);
945     RpcRaiseException(RPC_X_BAD_STUB_DATA);
946     return;
947   }
948
949   if (attr & RPC_FC_P_DEREF) {
950     Pointer = *(unsigned char**)Pointer;
951     TRACE("deref => %p\n", Pointer);
952   }
953
954   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
955   if (m) m(pStubMsg, Pointer, desc);
956   else FIXME("no buffersizer for data type=%02x\n", *desc);
957 }
958
959 /***********************************************************************
960  *           PointerMemorySize [RPCRT4.@]
961  */
962 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
963                                        unsigned char *Buffer,
964                                        PFORMAT_STRING pFormat)
965 {
966   unsigned type = pFormat[0], attr = pFormat[1];
967   PFORMAT_STRING desc;
968   NDR_MEMORYSIZE m;
969
970   FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat);
971   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
972   pFormat += 2;
973   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
974   else desc = pFormat + *(const SHORT*)pFormat;
975
976   switch (type) {
977   case RPC_FC_RP: /* ref pointer (always non-null) */
978     break;
979   default:
980     FIXME("unhandled ptr type=%02x\n", type);
981     RpcRaiseException(RPC_X_BAD_STUB_DATA);
982   }
983
984   if (attr & RPC_FC_P_DEREF) {
985     TRACE("deref\n");
986   }
987
988   m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
989   if (m) m(pStubMsg, desc);
990   else FIXME("no memorysizer for data type=%02x\n", *desc);
991
992   return 0;
993 }
994
995 /***********************************************************************
996  *           PointerFree [RPCRT4.@]
997  */
998 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
999                         unsigned char *Pointer,
1000                         PFORMAT_STRING pFormat)
1001 {
1002   unsigned type = pFormat[0], attr = pFormat[1];
1003   PFORMAT_STRING desc;
1004   NDR_FREE m;
1005
1006   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1007   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1008   if (attr & RPC_FC_P_DONTFREE) return;
1009   pFormat += 2;
1010   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1011   else desc = pFormat + *(const SHORT*)pFormat;
1012
1013   if (!Pointer) return;
1014
1015   if (type == RPC_FC_FP) {
1016     int pointer_needs_freeing = NdrFullPointerFree(
1017       pStubMsg->FullPtrXlatTables, Pointer);
1018     if (!pointer_needs_freeing)
1019       return;
1020   }
1021
1022   if (attr & RPC_FC_P_DEREF) {
1023     Pointer = *(unsigned char**)Pointer;
1024     TRACE("deref => %p\n", Pointer);
1025   }
1026
1027   m = NdrFreer[*desc & NDR_TABLE_MASK];
1028   if (m) m(pStubMsg, Pointer, desc);
1029
1030   /* hmm... is this sensible?
1031    * perhaps we should check if the memory comes from NdrAllocate,
1032    * and deallocate only if so - checking if the pointer is between
1033    * BufferStart and BufferEnd is probably no good since the buffer
1034    * may be reallocated when the server wants to marshal the reply */
1035   switch (*desc) {
1036   case RPC_FC_BOGUS_STRUCT:
1037   case RPC_FC_BOGUS_ARRAY:
1038   case RPC_FC_USER_MARSHAL:
1039   case RPC_FC_CARRAY:
1040   case RPC_FC_CVARRAY:
1041     break;
1042   default:
1043     FIXME("unhandled data type=%02x\n", *desc);
1044     break;
1045   case RPC_FC_C_CSTRING:
1046   case RPC_FC_C_WSTRING:
1047     if (pStubMsg->ReuseBuffer) goto notfree;
1048     break;
1049   case RPC_FC_IP:
1050     goto notfree;
1051   }
1052
1053   if (attr & RPC_FC_P_ONSTACK) {
1054     TRACE("not freeing stack ptr %p\n", Pointer);
1055     return;
1056   }
1057   TRACE("freeing %p\n", Pointer);
1058   NdrFree(pStubMsg, Pointer);
1059   return;
1060 notfree:
1061   TRACE("not freeing %p\n", Pointer);
1062 }
1063
1064 /***********************************************************************
1065  *           EmbeddedPointerMarshall
1066  */
1067 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1068                                                unsigned char *pMemory,
1069                                                PFORMAT_STRING pFormat)
1070 {
1071   unsigned char *Mark = pStubMsg->BufferMark;
1072   unsigned long Offset = pStubMsg->Offset;
1073   unsigned ofs, rep, count, stride, xofs;
1074   unsigned i;
1075
1076   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1077
1078   if (*pFormat != RPC_FC_PP) return NULL;
1079   pFormat += 2;
1080
1081   while (pFormat[0] != RPC_FC_END) {
1082     switch (pFormat[0]) {
1083     default:
1084       FIXME("unknown repeat type %d\n", pFormat[0]);
1085     case RPC_FC_NO_REPEAT:
1086       rep = 1;
1087       stride = 0;
1088       ofs = 0;
1089       count = 1;
1090       xofs = 0;
1091       pFormat += 2;
1092       break;
1093     case RPC_FC_FIXED_REPEAT:
1094       rep = *(const WORD*)&pFormat[2];
1095       stride = *(const WORD*)&pFormat[4];
1096       ofs = *(const WORD*)&pFormat[6];
1097       count = *(const WORD*)&pFormat[8];
1098       xofs = 0;
1099       pFormat += 10;
1100       break;
1101     case RPC_FC_VARIABLE_REPEAT:
1102       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1103       stride = *(const WORD*)&pFormat[2];
1104       ofs = *(const WORD*)&pFormat[4];
1105       count = *(const WORD*)&pFormat[6];
1106       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1107       pFormat += 8;
1108       break;
1109     }
1110     for (i = 0; i < rep; i++) {
1111       PFORMAT_STRING info = pFormat;
1112       unsigned char *membase = pMemory + (i * stride);
1113       unsigned char *bufbase = Mark + (i * stride);
1114       unsigned u;
1115       /* ofs doesn't seem to matter in this context */
1116       for (u=0; u<count; u++,info+=8) {
1117         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1118         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1119         unsigned char *saved_memory = pStubMsg->Memory;
1120
1121         pStubMsg->Memory = pMemory;
1122         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1123         pStubMsg->Memory = saved_memory;
1124       }
1125     }
1126     pFormat += 8 * count;
1127   }
1128
1129   STD_OVERFLOW_CHECK(pStubMsg);
1130
1131   return NULL;
1132 }
1133
1134 /***********************************************************************
1135  *           EmbeddedPointerUnmarshall
1136  */
1137 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1138                                                  unsigned char **ppMemory,
1139                                                  PFORMAT_STRING pFormat,
1140                                                  unsigned char fMustAlloc)
1141 {
1142   unsigned char *Mark = pStubMsg->BufferMark;
1143   unsigned long Offset = pStubMsg->Offset;
1144   unsigned ofs, rep, count, stride, xofs;
1145   unsigned i;
1146
1147   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1148
1149   if (*pFormat != RPC_FC_PP) return NULL;
1150   pFormat += 2;
1151
1152   while (pFormat[0] != RPC_FC_END) {
1153     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1154     switch (pFormat[0]) {
1155     default:
1156       FIXME("unknown repeat type %d\n", pFormat[0]);
1157     case RPC_FC_NO_REPEAT:
1158       rep = 1;
1159       stride = 0;
1160       ofs = 0;
1161       count = 1;
1162       xofs = 0;
1163       pFormat += 2;
1164       break;
1165     case RPC_FC_FIXED_REPEAT:
1166       rep = *(const WORD*)&pFormat[2];
1167       stride = *(const WORD*)&pFormat[4];
1168       ofs = *(const WORD*)&pFormat[6];
1169       count = *(const WORD*)&pFormat[8];
1170       xofs = 0;
1171       pFormat += 10;
1172       break;
1173     case RPC_FC_VARIABLE_REPEAT:
1174       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1175       stride = *(const WORD*)&pFormat[2];
1176       ofs = *(const WORD*)&pFormat[4];
1177       count = *(const WORD*)&pFormat[6];
1178       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1179       pFormat += 8;
1180       break;
1181     }
1182     /* ofs doesn't seem to matter in this context */
1183     for (i = 0; i < rep; i++) {
1184       PFORMAT_STRING info = pFormat;
1185       unsigned char *membase = *ppMemory + (i * stride);
1186       unsigned char *bufbase = Mark + (i * stride);
1187       unsigned u;
1188       for (u=0; u<count; u++,info+=8) {
1189         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1190         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1191         PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, TRUE);
1192       }
1193     }
1194     pFormat += 8 * count;
1195   }
1196
1197   return NULL;
1198 }
1199
1200 /***********************************************************************
1201  *           EmbeddedPointerBufferSize
1202  */
1203 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1204                                       unsigned char *pMemory,
1205                                       PFORMAT_STRING pFormat)
1206 {
1207   unsigned long Offset = pStubMsg->Offset;
1208   unsigned ofs, rep, count, stride, xofs;
1209   unsigned i;
1210
1211   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1212
1213   if (pStubMsg->IgnoreEmbeddedPointers) return;
1214
1215   if (*pFormat != RPC_FC_PP) return;
1216   pFormat += 2;
1217
1218   while (pFormat[0] != RPC_FC_END) {
1219     switch (pFormat[0]) {
1220     default:
1221       FIXME("unknown repeat type %d\n", pFormat[0]);
1222     case RPC_FC_NO_REPEAT:
1223       rep = 1;
1224       stride = 0;
1225       ofs = 0;
1226       count = 1;
1227       xofs = 0;
1228       pFormat += 2;
1229       break;
1230     case RPC_FC_FIXED_REPEAT:
1231       rep = *(const WORD*)&pFormat[2];
1232       stride = *(const WORD*)&pFormat[4];
1233       ofs = *(const WORD*)&pFormat[6];
1234       count = *(const WORD*)&pFormat[8];
1235       xofs = 0;
1236       pFormat += 10;
1237       break;
1238     case RPC_FC_VARIABLE_REPEAT:
1239       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1240       stride = *(const WORD*)&pFormat[2];
1241       ofs = *(const WORD*)&pFormat[4];
1242       count = *(const WORD*)&pFormat[6];
1243       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1244       pFormat += 8;
1245       break;
1246     }
1247     /* ofs doesn't seem to matter in this context */
1248     for (i = 0; i < rep; i++) {
1249       PFORMAT_STRING info = pFormat;
1250       unsigned char *membase = pMemory + (i * stride);
1251       unsigned u;
1252       for (u=0; u<count; u++,info+=8) {
1253         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1254         unsigned char *saved_memory = pStubMsg->Memory;
1255
1256         pStubMsg->Memory = pMemory;
1257         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1258         pStubMsg->Memory = saved_memory;
1259       }
1260     }
1261     pFormat += 8 * count;
1262   }
1263 }
1264
1265 /***********************************************************************
1266  *           EmbeddedPointerMemorySize
1267  */
1268 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1269                                                PFORMAT_STRING pFormat)
1270 {
1271   unsigned long Offset = pStubMsg->Offset;
1272   unsigned char *Mark = pStubMsg->BufferMark;
1273   unsigned ofs, rep, count, stride, xofs;
1274   unsigned i;
1275
1276   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1277
1278   if (*pFormat != RPC_FC_PP) return 0;
1279   pFormat += 2;
1280
1281   while (pFormat[0] != RPC_FC_END) {
1282     switch (pFormat[0]) {
1283     default:
1284       FIXME("unknown repeat type %d\n", pFormat[0]);
1285     case RPC_FC_NO_REPEAT:
1286       rep = 1;
1287       stride = 0;
1288       ofs = 0;
1289       count = 1;
1290       xofs = 0;
1291       pFormat += 2;
1292       break;
1293     case RPC_FC_FIXED_REPEAT:
1294       rep = *(const WORD*)&pFormat[2];
1295       stride = *(const WORD*)&pFormat[4];
1296       ofs = *(const WORD*)&pFormat[6];
1297       count = *(const WORD*)&pFormat[8];
1298       xofs = 0;
1299       pFormat += 10;
1300       break;
1301     case RPC_FC_VARIABLE_REPEAT:
1302       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1303       stride = *(const WORD*)&pFormat[2];
1304       ofs = *(const WORD*)&pFormat[4];
1305       count = *(const WORD*)&pFormat[6];
1306       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1307       pFormat += 8;
1308       break;
1309     }
1310     /* ofs doesn't seem to matter in this context */
1311     for (i = 0; i < rep; i++) {
1312       PFORMAT_STRING info = pFormat;
1313       unsigned char *bufbase = Mark + (i * stride);
1314       unsigned u;
1315       for (u=0; u<count; u++,info+=8) {
1316         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1317         PointerMemorySize(pStubMsg, bufptr, info+4);
1318       }
1319     }
1320     pFormat += 8 * count;
1321   }
1322
1323   return 0;
1324 }
1325
1326 /***********************************************************************
1327  *           EmbeddedPointerFree
1328  */
1329 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1330                                 unsigned char *pMemory,
1331                                 PFORMAT_STRING pFormat)
1332 {
1333   unsigned long Offset = pStubMsg->Offset;
1334   unsigned ofs, rep, count, stride, xofs;
1335   unsigned i;
1336
1337   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1338   if (*pFormat != RPC_FC_PP) return;
1339   pFormat += 2;
1340
1341   while (pFormat[0] != RPC_FC_END) {
1342     switch (pFormat[0]) {
1343     default:
1344       FIXME("unknown repeat type %d\n", pFormat[0]);
1345     case RPC_FC_NO_REPEAT:
1346       rep = 1;
1347       stride = 0;
1348       ofs = 0;
1349       count = 1;
1350       xofs = 0;
1351       pFormat += 2;
1352       break;
1353     case RPC_FC_FIXED_REPEAT:
1354       rep = *(const WORD*)&pFormat[2];
1355       stride = *(const WORD*)&pFormat[4];
1356       ofs = *(const WORD*)&pFormat[6];
1357       count = *(const WORD*)&pFormat[8];
1358       xofs = 0;
1359       pFormat += 10;
1360       break;
1361     case RPC_FC_VARIABLE_REPEAT:
1362       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1363       stride = *(const WORD*)&pFormat[2];
1364       ofs = *(const WORD*)&pFormat[4];
1365       count = *(const WORD*)&pFormat[6];
1366       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1367       pFormat += 8;
1368       break;
1369     }
1370     /* ofs doesn't seem to matter in this context */
1371     for (i = 0; i < rep; i++) {
1372       PFORMAT_STRING info = pFormat;
1373       unsigned char *membase = pMemory + (i * stride);
1374       unsigned u;
1375       for (u=0; u<count; u++,info+=8) {
1376         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1377         unsigned char *saved_memory = pStubMsg->Memory;
1378
1379         pStubMsg->Memory = pMemory;
1380         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1381         pStubMsg->Memory = saved_memory;
1382       }
1383     }
1384     pFormat += 8 * count;
1385   }
1386 }
1387
1388 /***********************************************************************
1389  *           NdrPointerMarshall [RPCRT4.@]
1390  */
1391 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1392                                           unsigned char *pMemory,
1393                                           PFORMAT_STRING pFormat)
1394 {
1395   unsigned char *Buffer;
1396
1397   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1398
1399   /* incremement the buffer here instead of in PointerMarshall,
1400    * as that is used by embedded pointers which already handle the incrementing
1401    * the buffer, and shouldn't write any additional pointer data to the wire */
1402   if (*pFormat != RPC_FC_RP)
1403   {
1404     ALIGN_POINTER(pStubMsg->Buffer, 4);
1405     Buffer = pStubMsg->Buffer;
1406     pStubMsg->Buffer += 4;
1407   }
1408   else
1409     Buffer = pStubMsg->Buffer;
1410
1411   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1412
1413   STD_OVERFLOW_CHECK(pStubMsg);
1414
1415   return NULL;
1416 }
1417
1418 /***********************************************************************
1419  *           NdrPointerUnmarshall [RPCRT4.@]
1420  */
1421 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1422                                             unsigned char **ppMemory,
1423                                             PFORMAT_STRING pFormat,
1424                                             unsigned char fMustAlloc)
1425 {
1426   unsigned char *Buffer;
1427
1428   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1429
1430   /* incremement the buffer here instead of in PointerUnmarshall,
1431    * as that is used by embedded pointers which already handle the incrementing
1432    * the buffer, and shouldn't read any additional pointer data from the
1433    * buffer */
1434   if (*pFormat != RPC_FC_RP)
1435   {
1436     ALIGN_POINTER(pStubMsg->Buffer, 4);
1437     Buffer = pStubMsg->Buffer;
1438     pStubMsg->Buffer += 4;
1439   }
1440   else
1441     Buffer = pStubMsg->Buffer;
1442
1443   PointerUnmarshall(pStubMsg, Buffer, ppMemory, pFormat, fMustAlloc);
1444
1445   return NULL;
1446 }
1447
1448 /***********************************************************************
1449  *           NdrPointerBufferSize [RPCRT4.@]
1450  */
1451 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1452                                       unsigned char *pMemory,
1453                                       PFORMAT_STRING pFormat)
1454 {
1455   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1456
1457   /* incremement the buffer length here instead of in PointerBufferSize,
1458    * as that is used by embedded pointers which already handle the buffer
1459    * length, and shouldn't write anything more to the wire */
1460   if (*pFormat != RPC_FC_RP)
1461   {
1462     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1463     pStubMsg->BufferLength += 4;
1464   }
1465
1466   PointerBufferSize(pStubMsg, pMemory, pFormat);
1467 }
1468
1469 /***********************************************************************
1470  *           NdrPointerMemorySize [RPCRT4.@]
1471  */
1472 unsigned long WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1473                                           PFORMAT_STRING pFormat)
1474 {
1475   /* unsigned size = *(LPWORD)(pFormat+2); */
1476   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1477   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1478   return 0;
1479 }
1480
1481 /***********************************************************************
1482  *           NdrPointerFree [RPCRT4.@]
1483  */
1484 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1485                            unsigned char *pMemory,
1486                            PFORMAT_STRING pFormat)
1487 {
1488   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1489   PointerFree(pStubMsg, pMemory, pFormat);
1490 }
1491
1492 /***********************************************************************
1493  *           NdrSimpleTypeMarshall [RPCRT4.@]
1494  */
1495 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1496                                    unsigned char FormatChar )
1497 {
1498     FIXME("stub\n");
1499 }
1500
1501 /***********************************************************************
1502  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
1503  */
1504 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1505                                      unsigned char FormatChar )
1506 {
1507     FIXME("stub\n");
1508 }
1509
1510 /***********************************************************************
1511  *           NdrSimpleStructMarshall [RPCRT4.@]
1512  */
1513 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1514                                                unsigned char *pMemory,
1515                                                PFORMAT_STRING pFormat)
1516 {
1517   unsigned size = *(const WORD*)(pFormat+2);
1518   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1519
1520   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1521
1522   memcpy(pStubMsg->Buffer, pMemory, size);
1523   pStubMsg->BufferMark = pStubMsg->Buffer;
1524   pStubMsg->Buffer += size;
1525
1526   if (pFormat[0] != RPC_FC_STRUCT)
1527     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1528
1529   STD_OVERFLOW_CHECK(pStubMsg);
1530
1531   return NULL;
1532 }
1533
1534 /***********************************************************************
1535  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1536  */
1537 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1538                                                  unsigned char **ppMemory,
1539                                                  PFORMAT_STRING pFormat,
1540                                                  unsigned char fMustAlloc)
1541 {
1542   unsigned size = *(const WORD*)(pFormat+2);
1543   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1544
1545   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1546
1547   if (fMustAlloc) {
1548     *ppMemory = NdrAllocate(pStubMsg, size);
1549     memcpy(*ppMemory, pStubMsg->Buffer, size);
1550   } else {
1551     if (!pStubMsg->IsClient && !*ppMemory)
1552       /* for servers, we just point straight into the RPC buffer */
1553       *ppMemory = pStubMsg->Buffer;
1554     else
1555       /* for clients, memory should be provided by caller */
1556       memcpy(*ppMemory, pStubMsg->Buffer, size);
1557   }
1558
1559   pStubMsg->BufferMark = pStubMsg->Buffer;
1560   pStubMsg->Buffer += size;
1561
1562   if (pFormat[0] != RPC_FC_STRUCT)
1563     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1564
1565   return NULL;
1566 }
1567
1568 /***********************************************************************
1569  *           NdrSimpleStructBufferSize [RPCRT4.@]
1570  */
1571 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1572                                       unsigned char *pMemory,
1573                                       PFORMAT_STRING pFormat)
1574 {
1575   unsigned size = *(const WORD*)(pFormat+2);
1576   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1577
1578   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1579
1580   pStubMsg->BufferLength += size;
1581   if (pFormat[0] != RPC_FC_STRUCT)
1582     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1583 }
1584
1585 /***********************************************************************
1586  *           NdrSimpleStructMemorySize [RPCRT4.@]
1587  */
1588 unsigned long WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1589                                                PFORMAT_STRING pFormat)
1590 {
1591   unsigned short size = *(LPWORD)(pFormat+2);
1592
1593   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1594
1595   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1596   pStubMsg->MemorySize += size;
1597   pStubMsg->Buffer += size;
1598
1599   if (pFormat[0] != RPC_FC_STRUCT)
1600     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1601   return size;
1602 }
1603
1604 /***********************************************************************
1605  *           NdrSimpleStructFree [RPCRT4.@]
1606  */
1607 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1608                                 unsigned char *pMemory,
1609                                 PFORMAT_STRING pFormat)
1610 {
1611   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1612   if (pFormat[0] != RPC_FC_STRUCT)
1613     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1614 }
1615
1616
1617 static unsigned long EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg,
1618                                          PFORMAT_STRING pFormat)
1619 {
1620   switch (*pFormat) {
1621   case RPC_FC_STRUCT:
1622   case RPC_FC_PSTRUCT:
1623   case RPC_FC_CSTRUCT:
1624   case RPC_FC_BOGUS_STRUCT:
1625     return *(const WORD*)&pFormat[2];
1626   case RPC_FC_USER_MARSHAL:
1627     return *(const WORD*)&pFormat[4];
1628   case RPC_FC_NON_ENCAPSULATED_UNION:
1629     pFormat += 2;
1630     if (pStubMsg->fHasNewCorrDesc)
1631         pFormat += 6;
1632     else
1633         pFormat += 4;
1634
1635     pFormat += *(const SHORT*)pFormat;
1636     return *(const SHORT*)pFormat;
1637   case RPC_FC_IP:
1638     return sizeof(void *);
1639   default:
1640     FIXME("unhandled embedded type %02x\n", *pFormat);
1641   }
1642   return 0;
1643 }
1644
1645
1646 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1647                                                PFORMAT_STRING pFormat)
1648 {
1649   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1650
1651   if (!m)
1652   {
1653     FIXME("no memorysizer for data type=%02x\n", *pFormat);
1654     return 0;
1655   }
1656
1657   return m(pStubMsg, pFormat);
1658 }
1659
1660
1661 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1662                                        unsigned char *pMemory,
1663                                        PFORMAT_STRING pFormat,
1664                                        PFORMAT_STRING pPointer)
1665 {
1666   PFORMAT_STRING desc;
1667   NDR_MARSHALL m;
1668   unsigned long size;
1669
1670   while (*pFormat != RPC_FC_END) {
1671     switch (*pFormat) {
1672     case RPC_FC_BYTE:
1673     case RPC_FC_CHAR:
1674     case RPC_FC_SMALL:
1675     case RPC_FC_USMALL:
1676       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
1677       memcpy(pStubMsg->Buffer, pMemory, 1);
1678       pStubMsg->Buffer += 1;
1679       pMemory += 1;
1680       break;
1681     case RPC_FC_WCHAR:
1682     case RPC_FC_SHORT:
1683     case RPC_FC_USHORT:
1684       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1685       memcpy(pStubMsg->Buffer, pMemory, 2);
1686       pStubMsg->Buffer += 2;
1687       pMemory += 2;
1688       break;
1689     case RPC_FC_LONG:
1690     case RPC_FC_ULONG:
1691     case RPC_FC_ENUM32:
1692       TRACE("long=%ld <= %p\n", *(DWORD*)pMemory, pMemory);
1693       memcpy(pStubMsg->Buffer, pMemory, 4);
1694       pStubMsg->Buffer += 4;
1695       pMemory += 4;
1696       break;
1697     case RPC_FC_POINTER:
1698       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1699       NdrPointerMarshall(pStubMsg, *(unsigned char**)pMemory, pPointer);
1700       pPointer += 4;
1701       pMemory += 4;
1702       break;
1703     case RPC_FC_ALIGNM4:
1704       ALIGN_POINTER(pMemory, 4);
1705       break;
1706     case RPC_FC_ALIGNM8:
1707       ALIGN_POINTER(pMemory, 8);
1708       break;
1709     case RPC_FC_STRUCTPAD2:
1710       pMemory += 2;
1711       break;
1712     case RPC_FC_EMBEDDED_COMPLEX:
1713       pMemory += pFormat[1];
1714       pFormat += 2;
1715       desc = pFormat + *(const SHORT*)pFormat;
1716       size = EmbeddedComplexSize(pStubMsg, desc);
1717       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1718       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1719       if (m) m(pStubMsg, pMemory, desc);
1720       else FIXME("no marshaller for embedded type %02x\n", *desc);
1721       pMemory += size;
1722       pFormat += 2;
1723       continue;
1724     case RPC_FC_PAD:
1725       break;
1726     default:
1727       FIXME("unhandled format %02x\n", *pFormat);
1728     }
1729     pFormat++;
1730   }
1731
1732   return pMemory;
1733 }
1734
1735 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1736                                          unsigned char *pMemory,
1737                                          PFORMAT_STRING pFormat,
1738                                          PFORMAT_STRING pPointer)
1739 {
1740   PFORMAT_STRING desc;
1741   NDR_UNMARSHALL m;
1742   unsigned long size;
1743
1744   while (*pFormat != RPC_FC_END) {
1745     switch (*pFormat) {
1746     case RPC_FC_BYTE:
1747     case RPC_FC_CHAR:
1748     case RPC_FC_SMALL:
1749     case RPC_FC_USMALL:
1750       memcpy(pMemory, pStubMsg->Buffer, 1);
1751       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
1752       pStubMsg->Buffer += 1;
1753       pMemory += 1;
1754       break;
1755     case RPC_FC_WCHAR:
1756     case RPC_FC_SHORT:
1757     case RPC_FC_USHORT:
1758       memcpy(pMemory, pStubMsg->Buffer, 2);
1759       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1760       pStubMsg->Buffer += 2;
1761       pMemory += 2;
1762       break;
1763     case RPC_FC_LONG:
1764     case RPC_FC_ULONG:
1765     case RPC_FC_ENUM32:
1766       memcpy(pMemory, pStubMsg->Buffer, 4);
1767       TRACE("long=%ld => %p\n", *(DWORD*)pMemory, pMemory);
1768       pStubMsg->Buffer += 4;
1769       pMemory += 4;
1770       break;
1771     case RPC_FC_POINTER:
1772       TRACE("pointer => %p\n", pMemory);
1773       NdrPointerUnmarshall(pStubMsg, (unsigned char**)pMemory, pPointer, TRUE);
1774       pPointer += 4;
1775       pMemory += 4;
1776       break;
1777     case RPC_FC_ALIGNM4:
1778       ALIGN_POINTER(pMemory, 4);
1779       break;
1780     case RPC_FC_ALIGNM8:
1781       ALIGN_POINTER(pMemory, 8);
1782       break;
1783     case RPC_FC_STRUCTPAD2:
1784       pMemory += 2;
1785       break;
1786     case RPC_FC_EMBEDDED_COMPLEX:
1787       pMemory += pFormat[1];
1788       pFormat += 2;
1789       desc = pFormat + *(const SHORT*)pFormat;
1790       size = EmbeddedComplexSize(pStubMsg, desc);
1791       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1792       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1793       memset(pMemory, 0, size); /* just in case */
1794       if (m) m(pStubMsg, &pMemory, desc, FALSE);
1795       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
1796       pMemory += size;
1797       pFormat += 2;
1798       continue;
1799     case RPC_FC_PAD:
1800       break;
1801     default:
1802       FIXME("unhandled format %d\n", *pFormat);
1803     }
1804     pFormat++;
1805   }
1806
1807   return pMemory;
1808 }
1809
1810 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1811                                          unsigned char *pMemory,
1812                                          PFORMAT_STRING pFormat,
1813                                          PFORMAT_STRING pPointer)
1814 {
1815   PFORMAT_STRING desc;
1816   NDR_BUFFERSIZE m;
1817   unsigned long size;
1818
1819   while (*pFormat != RPC_FC_END) {
1820     switch (*pFormat) {
1821     case RPC_FC_BYTE:
1822     case RPC_FC_CHAR:
1823     case RPC_FC_SMALL:
1824     case RPC_FC_USMALL:
1825       pStubMsg->BufferLength += 1;
1826       pMemory += 1;
1827       break;
1828     case RPC_FC_WCHAR:
1829     case RPC_FC_SHORT:
1830     case RPC_FC_USHORT:
1831       pStubMsg->BufferLength += 2;
1832       pMemory += 2;
1833       break;
1834     case RPC_FC_LONG:
1835     case RPC_FC_ULONG:
1836     case RPC_FC_ENUM32:
1837       pStubMsg->BufferLength += 4;
1838       pMemory += 4;
1839       break;
1840     case RPC_FC_POINTER:
1841       NdrPointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
1842       pPointer += 4;
1843       pMemory += 4;
1844       break;
1845     case RPC_FC_ALIGNM4:
1846       ALIGN_POINTER(pMemory, 4);
1847       break;
1848     case RPC_FC_ALIGNM8:
1849       ALIGN_POINTER(pMemory, 8);
1850       break;
1851     case RPC_FC_STRUCTPAD2:
1852       pMemory += 2;
1853       break;
1854     case RPC_FC_EMBEDDED_COMPLEX:
1855       pMemory += pFormat[1];
1856       pFormat += 2;
1857       desc = pFormat + *(const SHORT*)pFormat;
1858       size = EmbeddedComplexSize(pStubMsg, desc);
1859       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1860       if (m) m(pStubMsg, pMemory, desc);
1861       else FIXME("no buffersizer for embedded type %02x\n", *desc);
1862       pMemory += size;
1863       pFormat += 2;
1864       continue;
1865     case RPC_FC_PAD:
1866       break;
1867     default:
1868       FIXME("unhandled format %d\n", *pFormat);
1869     }
1870     pFormat++;
1871   }
1872
1873   return pMemory;
1874 }
1875
1876 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
1877                                    unsigned char *pMemory,
1878                                    PFORMAT_STRING pFormat,
1879                                    PFORMAT_STRING pPointer)
1880 {
1881   PFORMAT_STRING desc;
1882   NDR_FREE m;
1883   unsigned long size;
1884
1885   while (*pFormat != RPC_FC_END) {
1886     switch (*pFormat) {
1887     case RPC_FC_BYTE:
1888     case RPC_FC_CHAR:
1889     case RPC_FC_SMALL:
1890     case RPC_FC_USMALL:
1891       pMemory += 1;
1892       break;
1893     case RPC_FC_WCHAR:
1894     case RPC_FC_SHORT:
1895     case RPC_FC_USHORT:
1896       pMemory += 2;
1897       break;
1898     case RPC_FC_LONG:
1899     case RPC_FC_ULONG:
1900     case RPC_FC_ENUM32:
1901       pMemory += 4;
1902       break;
1903     case RPC_FC_POINTER:
1904       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
1905       pPointer += 4;
1906       pMemory += 4;
1907       break;
1908     case RPC_FC_ALIGNM4:
1909       ALIGN_POINTER(pMemory, 4);
1910       break;
1911     case RPC_FC_ALIGNM8:
1912       ALIGN_POINTER(pMemory, 8);
1913       break;
1914     case RPC_FC_STRUCTPAD2:
1915       pMemory += 2;
1916       break;
1917     case RPC_FC_EMBEDDED_COMPLEX:
1918       pMemory += pFormat[1];
1919       pFormat += 2;
1920       desc = pFormat + *(const SHORT*)pFormat;
1921       size = EmbeddedComplexSize(pStubMsg, desc);
1922       m = NdrFreer[*desc & NDR_TABLE_MASK];
1923       if (m) m(pStubMsg, pMemory, desc);
1924       else FIXME("no freer for embedded type %02x\n", *desc);
1925       pMemory += size;
1926       pFormat += 2;
1927       continue;
1928     case RPC_FC_PAD:
1929       break;
1930     default:
1931       FIXME("unhandled format %d\n", *pFormat);
1932     }
1933     pFormat++;
1934   }
1935
1936   return pMemory;
1937 }
1938
1939 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1940                                        PFORMAT_STRING pFormat)
1941 {
1942   PFORMAT_STRING desc;
1943   unsigned long size = 0;
1944
1945   while (*pFormat != RPC_FC_END) {
1946     switch (*pFormat) {
1947     case RPC_FC_BYTE:
1948     case RPC_FC_CHAR:
1949     case RPC_FC_SMALL:
1950     case RPC_FC_USMALL:
1951       size += 1;
1952       pStubMsg->Buffer += 1;
1953       break;
1954     case RPC_FC_WCHAR:
1955     case RPC_FC_SHORT:
1956     case RPC_FC_USHORT:
1957       size += 2;
1958       pStubMsg->Buffer += 2;
1959       break;
1960     case RPC_FC_LONG:
1961     case RPC_FC_ULONG:
1962     case RPC_FC_ENUM32:
1963       size += 4;
1964       pStubMsg->Buffer += 4;
1965       break;
1966     case RPC_FC_POINTER:
1967       size += 4;
1968       pStubMsg->Buffer += 4;
1969       break;
1970     case RPC_FC_ALIGNM4:
1971       ALIGN_LENGTH(size, 4);
1972       ALIGN_POINTER(pStubMsg->Buffer, 4);
1973       break;
1974     case RPC_FC_ALIGNM8:
1975       ALIGN_LENGTH(size, 8);
1976       ALIGN_POINTER(pStubMsg->Buffer, 8);
1977       break;
1978     case RPC_FC_STRUCTPAD2:
1979       size += 2;
1980       pStubMsg->Buffer += 2;
1981       break;
1982     case RPC_FC_EMBEDDED_COMPLEX:
1983       size += pFormat[1];
1984       pFormat += 2;
1985       desc = pFormat + *(const SHORT*)pFormat;
1986       size += EmbeddedComplexMemorySize(pStubMsg, desc);
1987       pFormat += 2;
1988       continue;
1989     case RPC_FC_PAD:
1990       break;
1991     default:
1992       FIXME("unhandled format %d\n", *pFormat);
1993     }
1994     pFormat++;
1995   }
1996
1997   return size;
1998 }
1999
2000 /***********************************************************************
2001  *           NdrComplexStructMarshall [RPCRT4.@]
2002  */
2003 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2004                                                 unsigned char *pMemory,
2005                                                 PFORMAT_STRING pFormat)
2006 {
2007   PFORMAT_STRING conf_array = NULL;
2008   PFORMAT_STRING pointer_desc = NULL;
2009   unsigned char *OldMemory = pStubMsg->Memory;
2010
2011   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2012
2013   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2014
2015   pFormat += 4;
2016   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2017   pFormat += 2;
2018   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2019   pFormat += 2;
2020
2021   pStubMsg->Memory = pMemory;
2022
2023   ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2024
2025   if (conf_array)
2026     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2027
2028   pStubMsg->Memory = OldMemory;
2029
2030   STD_OVERFLOW_CHECK(pStubMsg);
2031
2032   return NULL;
2033 }
2034
2035 /***********************************************************************
2036  *           NdrComplexStructUnmarshall [RPCRT4.@]
2037  */
2038 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2039                                                   unsigned char **ppMemory,
2040                                                   PFORMAT_STRING pFormat,
2041                                                   unsigned char fMustAlloc)
2042 {
2043   unsigned size = *(const WORD*)(pFormat+2);
2044   PFORMAT_STRING conf_array = NULL;
2045   PFORMAT_STRING pointer_desc = NULL;
2046   unsigned char *pMemory;
2047
2048   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2049
2050   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2051
2052   if (fMustAlloc || !*ppMemory)
2053   {
2054     *ppMemory = NdrAllocate(pStubMsg, size);
2055     memset(*ppMemory, 0, size);
2056   }
2057
2058   pFormat += 4;
2059   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2060   pFormat += 2;
2061   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2062   pFormat += 2;
2063
2064   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2065
2066   if (conf_array)
2067     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2068
2069   return NULL;
2070 }
2071
2072 /***********************************************************************
2073  *           NdrComplexStructBufferSize [RPCRT4.@]
2074  */
2075 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2076                                        unsigned char *pMemory,
2077                                        PFORMAT_STRING pFormat)
2078 {
2079   PFORMAT_STRING conf_array = NULL;
2080   PFORMAT_STRING pointer_desc = NULL;
2081   unsigned char *OldMemory = pStubMsg->Memory;
2082
2083   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2084
2085   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2086
2087   pFormat += 4;
2088   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2089   pFormat += 2;
2090   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2091   pFormat += 2;
2092
2093   pStubMsg->Memory = pMemory;
2094
2095   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2096
2097   if (conf_array)
2098     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2099
2100   pStubMsg->Memory = OldMemory;
2101 }
2102
2103 /***********************************************************************
2104  *           NdrComplexStructMemorySize [RPCRT4.@]
2105  */
2106 unsigned long WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2107                                                 PFORMAT_STRING pFormat)
2108 {
2109   unsigned size = *(const WORD*)(pFormat+2);
2110   PFORMAT_STRING conf_array = NULL;
2111   PFORMAT_STRING pointer_desc = NULL;
2112
2113   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2114
2115   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2116
2117   pFormat += 4;
2118   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2119   pFormat += 2;
2120   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2121   pFormat += 2;
2122
2123   ComplexStructMemorySize(pStubMsg, pFormat);
2124
2125   if (conf_array)
2126     NdrConformantArrayMemorySize(pStubMsg, conf_array);
2127
2128   return size;
2129 }
2130
2131 /***********************************************************************
2132  *           NdrComplexStructFree [RPCRT4.@]
2133  */
2134 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2135                                  unsigned char *pMemory,
2136                                  PFORMAT_STRING pFormat)
2137 {
2138   PFORMAT_STRING conf_array = NULL;
2139   PFORMAT_STRING pointer_desc = NULL;
2140   unsigned char *OldMemory = pStubMsg->Memory;
2141
2142   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2143
2144   pFormat += 4;
2145   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2146   pFormat += 2;
2147   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2148   pFormat += 2;
2149
2150   pStubMsg->Memory = pMemory;
2151
2152   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2153
2154   if (conf_array)
2155     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2156
2157   pStubMsg->Memory = OldMemory;
2158 }
2159
2160 /***********************************************************************
2161  *           NdrConformantArrayMarshall [RPCRT4.@]
2162  */
2163 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2164                                                   unsigned char *pMemory,
2165                                                   PFORMAT_STRING pFormat)
2166 {
2167   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2168   unsigned char alignment = pFormat[1] + 1;
2169
2170   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2171   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2172
2173   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2174   size = pStubMsg->MaxCount;
2175
2176   WriteConformance(pStubMsg);
2177
2178   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2179
2180   memcpy(pStubMsg->Buffer, pMemory, size*esize);
2181   pStubMsg->BufferMark = pStubMsg->Buffer;
2182   pStubMsg->Buffer += size*esize;
2183
2184   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2185
2186   STD_OVERFLOW_CHECK(pStubMsg);
2187
2188   return NULL;
2189 }
2190
2191 /***********************************************************************
2192  *           NdrConformantArrayUnmarshall [RPCRT4.@]
2193  */
2194 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2195                                                     unsigned char **ppMemory,
2196                                                     PFORMAT_STRING pFormat,
2197                                                     unsigned char fMustAlloc)
2198 {
2199   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2200   unsigned char alignment = pFormat[1] + 1;
2201
2202   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2203   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2204
2205   pFormat = ReadConformance(pStubMsg, pFormat+4);
2206   size = pStubMsg->MaxCount;
2207
2208   if (fMustAlloc || !*ppMemory)
2209     *ppMemory = NdrAllocate(pStubMsg, size*esize);
2210
2211   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2212
2213   memcpy(*ppMemory, pStubMsg->Buffer, size*esize);
2214
2215   pStubMsg->BufferMark = pStubMsg->Buffer;
2216   pStubMsg->Buffer += size*esize;
2217
2218   EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2219
2220   return NULL;
2221 }
2222
2223 /***********************************************************************
2224  *           NdrConformantArrayBufferSize [RPCRT4.@]
2225  */
2226 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2227                                          unsigned char *pMemory,
2228                                          PFORMAT_STRING pFormat)
2229 {
2230   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2231   unsigned char alignment = pFormat[1] + 1;
2232
2233   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2234   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2235
2236   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2237   size = pStubMsg->MaxCount;
2238
2239   SizeConformance(pStubMsg);
2240
2241   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2242
2243   /* conformance value plus array */
2244   pStubMsg->BufferLength += size*esize;
2245
2246   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2247 }
2248
2249 /***********************************************************************
2250  *           NdrConformantArrayMemorySize [RPCRT4.@]
2251  */
2252 unsigned long WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2253                                                   PFORMAT_STRING pFormat)
2254 {
2255   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2256   unsigned char alignment = pFormat[1] + 1;
2257
2258   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2259   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2260
2261   pFormat = ReadConformance(pStubMsg, pFormat+4);
2262   size = pStubMsg->MaxCount;
2263   pStubMsg->MemorySize += size*esize;
2264
2265   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2266   pStubMsg->BufferMark = pStubMsg->Buffer;
2267   pStubMsg->Buffer += size*esize;
2268
2269   EmbeddedPointerMemorySize(pStubMsg, pFormat);
2270
2271   return pStubMsg->MemorySize;
2272 }
2273
2274 /***********************************************************************
2275  *           NdrConformantArrayFree [RPCRT4.@]
2276  */
2277 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2278                                    unsigned char *pMemory,
2279                                    PFORMAT_STRING pFormat)
2280 {
2281   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2282   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2283
2284   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2285 }
2286
2287
2288 /***********************************************************************
2289  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
2290  */
2291 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2292                                                          unsigned char* pMemory,
2293                                                          PFORMAT_STRING pFormat )
2294 {
2295     unsigned char alignment = pFormat[1] + 1;
2296     DWORD esize = *(const WORD*)(pFormat+2);
2297
2298     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2299
2300     if (pFormat[0] != RPC_FC_CVARRAY)
2301     {
2302         ERR("invalid format type %x\n", pFormat[0]);
2303         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2304         return NULL;
2305     }
2306
2307     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2308     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2309
2310     WriteConformance(pStubMsg);
2311     WriteVariance(pStubMsg);
2312
2313     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2314
2315     memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, pStubMsg->ActualCount*esize);
2316     pStubMsg->BufferMark = pStubMsg->Buffer;
2317     pStubMsg->Buffer += pStubMsg->ActualCount*esize;
2318
2319     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2320
2321     STD_OVERFLOW_CHECK(pStubMsg);
2322
2323     return NULL;
2324 }
2325
2326
2327 /***********************************************************************
2328  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
2329  */
2330 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2331                                                            unsigned char** ppMemory,
2332                                                            PFORMAT_STRING pFormat,
2333                                                            unsigned char fMustAlloc )
2334 {
2335     unsigned char alignment = pFormat[1] + 1;
2336     DWORD esize = *(const WORD*)(pFormat+2);
2337
2338     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2339
2340     if (pFormat[0] != RPC_FC_CVARRAY)
2341     {
2342         ERR("invalid format type %x\n", pFormat[0]);
2343         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2344         return NULL;
2345     }
2346
2347     pFormat = ReadConformance(pStubMsg, pFormat+4);
2348     pFormat = ReadVariance(pStubMsg, pFormat);
2349
2350     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2351
2352     if (!*ppMemory || fMustAlloc)
2353         *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
2354     memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, pStubMsg->ActualCount * esize);
2355     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
2356
2357     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2358
2359     return NULL;
2360 }
2361
2362
2363 /***********************************************************************
2364  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
2365  */
2366 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2367                                            unsigned char* pMemory,
2368                                            PFORMAT_STRING pFormat )
2369 {
2370     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2371
2372     if (pFormat[0] != RPC_FC_CVARRAY)
2373     {
2374         ERR("invalid format type %x\n", pFormat[0]);
2375         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2376         return;
2377     }
2378
2379     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2380     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2381
2382     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2383 }
2384
2385
2386 /***********************************************************************
2387  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
2388  */
2389 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2390                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
2391 {
2392     unsigned char alignment = pFormat[1] + 1;
2393     DWORD esize = *(const WORD*)(pFormat+2);
2394
2395     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2396
2397     if (pFormat[0] != RPC_FC_CVARRAY)
2398     {
2399         ERR("invalid format type %x\n", pFormat[0]);
2400         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2401         return;
2402     }
2403
2404     /* compute size */
2405     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2406     /* compute length */
2407     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2408
2409     SizeConformance(pStubMsg);
2410     SizeVariance(pStubMsg);
2411
2412     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2413
2414     pStubMsg->BufferLength += pStubMsg->ActualCount*esize;
2415
2416     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2417 }
2418
2419
2420 /***********************************************************************
2421  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
2422  */
2423 unsigned long WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2424                                                           PFORMAT_STRING pFormat )
2425 {
2426     FIXME( "stub\n" );
2427     return 0;
2428 }
2429
2430
2431 /***********************************************************************
2432  *           NdrComplexArrayMarshall [RPCRT4.@]
2433  */
2434 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2435                                                unsigned char *pMemory,
2436                                                PFORMAT_STRING pFormat)
2437 {
2438   ULONG i, count, def;
2439   BOOL variance_present;
2440   unsigned char alignment;
2441
2442   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2443
2444   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2445   {
2446       ERR("invalid format type %x\n", pFormat[0]);
2447       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2448       return NULL;
2449   }
2450
2451   alignment = pFormat[1] + 1;
2452
2453   def = *(const WORD*)&pFormat[2];
2454   pFormat += 4;
2455
2456   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2457   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2458
2459   variance_present = IsConformanceOrVariancePresent(pFormat);
2460   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2461   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2462
2463   WriteConformance(pStubMsg);
2464   if (variance_present)
2465     WriteVariance(pStubMsg);
2466
2467   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2468
2469   count = pStubMsg->ActualCount;
2470   for (i = 0; i < count; i++)
2471     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2472
2473   STD_OVERFLOW_CHECK(pStubMsg);
2474
2475   return NULL;
2476 }
2477
2478 /***********************************************************************
2479  *           NdrComplexArrayUnmarshall [RPCRT4.@]
2480  */
2481 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2482                                                  unsigned char **ppMemory,
2483                                                  PFORMAT_STRING pFormat,
2484                                                  unsigned char fMustAlloc)
2485 {
2486   ULONG i, count, esize;
2487   unsigned char alignment;
2488   unsigned char *pMemory;
2489   unsigned char *Buffer;
2490
2491   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2492
2493   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2494   {
2495       ERR("invalid format type %x\n", pFormat[0]);
2496       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2497       return NULL;
2498   }
2499
2500   alignment = pFormat[1] + 1;
2501
2502   pFormat += 4;
2503
2504   pFormat = ReadConformance(pStubMsg, pFormat);
2505   pFormat = ReadVariance(pStubMsg, pFormat);
2506
2507   Buffer = pStubMsg->Buffer;
2508   esize = ComplexStructMemorySize(pStubMsg, pFormat);
2509   pStubMsg->Buffer = Buffer;
2510
2511   if (fMustAlloc || !*ppMemory)
2512   {
2513     *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
2514     memset(*ppMemory, 0, pStubMsg->MaxCount * esize);
2515   }
2516
2517   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2518
2519   pMemory = *ppMemory;
2520   count = pStubMsg->ActualCount;
2521   for (i = 0; i < count; i++)
2522     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
2523
2524   return NULL;
2525 }
2526
2527 /***********************************************************************
2528  *           NdrComplexArrayBufferSize [RPCRT4.@]
2529  */
2530 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2531                                       unsigned char *pMemory,
2532                                       PFORMAT_STRING pFormat)
2533 {
2534   ULONG i, count, def;
2535   unsigned char alignment;
2536   BOOL variance_present;
2537
2538   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2539
2540   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2541   {
2542       ERR("invalid format type %x\n", pFormat[0]);
2543       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2544       return;
2545   }
2546
2547   alignment = pFormat[1] + 1;
2548
2549   def = *(const WORD*)&pFormat[2];
2550   pFormat += 4;
2551
2552   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2553   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2554   SizeConformance(pStubMsg);
2555
2556   variance_present = IsConformanceOrVariancePresent(pFormat);
2557   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2558   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2559
2560   if (variance_present)
2561     SizeVariance(pStubMsg);
2562
2563   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2564
2565   count = pStubMsg->ActualCount;
2566   for (i = 0; i < count; i++)
2567     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
2568 }
2569
2570 /***********************************************************************
2571  *           NdrComplexArrayMemorySize [RPCRT4.@]
2572  */
2573 unsigned long WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2574                                                PFORMAT_STRING pFormat)
2575 {
2576   ULONG i, count, esize;
2577   unsigned char alignment;
2578   unsigned char *Buffer;
2579   unsigned long SavedMemorySize;
2580   unsigned long MemorySize;
2581
2582   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2583
2584   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2585   {
2586       ERR("invalid format type %x\n", pFormat[0]);
2587       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2588       return 0;
2589   }
2590
2591   alignment = pFormat[1] + 1;
2592
2593   pFormat += 4;
2594
2595   pFormat = ReadConformance(pStubMsg, pFormat);
2596   pFormat = ReadVariance(pStubMsg, pFormat);
2597
2598   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2599
2600   SavedMemorySize = pStubMsg->MemorySize;
2601
2602   Buffer = pStubMsg->Buffer;
2603   pStubMsg->MemorySize = 0;
2604   esize = ComplexStructMemorySize(pStubMsg, pFormat);
2605   pStubMsg->Buffer = Buffer;
2606
2607   MemorySize = esize * pStubMsg->MaxCount;
2608
2609   count = pStubMsg->ActualCount;
2610   for (i = 0; i < count; i++)
2611     ComplexStructMemorySize(pStubMsg, pFormat);
2612
2613   pStubMsg->MemorySize = SavedMemorySize;
2614
2615   pStubMsg->MemorySize += MemorySize;
2616   return MemorySize;
2617 }
2618
2619 /***********************************************************************
2620  *           NdrComplexArrayFree [RPCRT4.@]
2621  */
2622 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2623                                 unsigned char *pMemory,
2624                                 PFORMAT_STRING pFormat)
2625 {
2626   ULONG i, count, def;
2627
2628   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2629
2630   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2631   {
2632       ERR("invalid format type %x\n", pFormat[0]);
2633       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2634       return;
2635   }
2636
2637   def = *(const WORD*)&pFormat[2];
2638   pFormat += 4;
2639
2640   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2641   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2642
2643   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2644   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2645
2646   count = pStubMsg->ActualCount;
2647   for (i = 0; i < count; i++)
2648     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2649 }
2650
2651 static unsigned long UserMarshalFlags(PMIDL_STUB_MESSAGE pStubMsg)
2652 {
2653   return MAKELONG(pStubMsg->dwDestContext,
2654                   pStubMsg->RpcMsg->DataRepresentation);
2655 }
2656
2657 #define USER_MARSHAL_PTR_PREFIX \
2658         ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
2659         ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
2660
2661 /***********************************************************************
2662  *           NdrUserMarshalMarshall [RPCRT4.@]
2663  */
2664 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2665                                               unsigned char *pMemory,
2666                                               PFORMAT_STRING pFormat)
2667 {
2668   unsigned flags = pFormat[1];
2669   unsigned index = *(const WORD*)&pFormat[2];
2670   unsigned long uflag = UserMarshalFlags(pStubMsg);
2671   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2672   TRACE("index=%d\n", index);
2673
2674   if (flags & USER_MARSHAL_POINTER)
2675   {
2676     ALIGN_POINTER(pStubMsg->Buffer, 4);
2677     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
2678     pStubMsg->Buffer += 4;
2679     ALIGN_POINTER(pStubMsg->Buffer, 8);
2680   }
2681   else
2682     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2683
2684   pStubMsg->Buffer =
2685     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
2686       &uflag, pStubMsg->Buffer, pMemory);
2687
2688   STD_OVERFLOW_CHECK(pStubMsg);
2689
2690   return NULL;
2691 }
2692
2693 /***********************************************************************
2694  *           NdrUserMarshalUnmarshall [RPCRT4.@]
2695  */
2696 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2697                                                  unsigned char **ppMemory,
2698                                                  PFORMAT_STRING pFormat,
2699                                                  unsigned char fMustAlloc)
2700 {
2701   unsigned flags = pFormat[1];
2702   unsigned index = *(const WORD*)&pFormat[2];
2703   DWORD memsize = *(const WORD*)&pFormat[4];
2704   unsigned long uflag = UserMarshalFlags(pStubMsg);
2705   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2706   TRACE("index=%d\n", index);
2707
2708   if (flags & USER_MARSHAL_POINTER)
2709   {
2710     ALIGN_POINTER(pStubMsg->Buffer, 4);
2711     /* skip pointer prefix */
2712     pStubMsg->Buffer += 4;
2713     ALIGN_POINTER(pStubMsg->Buffer, 8);
2714   }
2715   else
2716     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2717
2718   if (fMustAlloc || !*ppMemory)
2719     *ppMemory = NdrAllocate(pStubMsg, memsize);
2720
2721   pStubMsg->Buffer =
2722     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
2723       &uflag, pStubMsg->Buffer, *ppMemory);
2724
2725   return NULL;
2726 }
2727
2728 /***********************************************************************
2729  *           NdrUserMarshalBufferSize [RPCRT4.@]
2730  */
2731 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2732                                       unsigned char *pMemory,
2733                                       PFORMAT_STRING pFormat)
2734 {
2735   unsigned flags = pFormat[1];
2736   unsigned index = *(const WORD*)&pFormat[2];
2737   DWORD bufsize = *(const WORD*)&pFormat[6];
2738   unsigned long uflag = UserMarshalFlags(pStubMsg);
2739   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2740   TRACE("index=%d\n", index);
2741
2742   if (flags & USER_MARSHAL_POINTER)
2743   {
2744     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2745     /* skip pointer prefix */
2746     pStubMsg->BufferLength += 4;
2747     ALIGN_LENGTH(pStubMsg->BufferLength, 8);
2748   }
2749   else
2750     ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
2751
2752   if (bufsize) {
2753     TRACE("size=%ld\n", bufsize);
2754     pStubMsg->BufferLength += bufsize;
2755     return;
2756   }
2757
2758   pStubMsg->BufferLength =
2759     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
2760       &uflag, pStubMsg->BufferLength, pMemory);
2761 }
2762
2763 /***********************************************************************
2764  *           NdrUserMarshalMemorySize [RPCRT4.@]
2765  */
2766 unsigned long WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2767                                               PFORMAT_STRING pFormat)
2768 {
2769   unsigned flags = pFormat[1];
2770   unsigned index = *(const WORD*)&pFormat[2];
2771   DWORD memsize = *(const WORD*)&pFormat[4];
2772   DWORD bufsize = *(const WORD*)&pFormat[6];
2773
2774   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2775   TRACE("index=%d\n", index);
2776
2777   pStubMsg->MemorySize += memsize;
2778
2779   if (flags & USER_MARSHAL_POINTER)
2780   {
2781     ALIGN_POINTER(pStubMsg->Buffer, 4);
2782     /* skip pointer prefix */
2783     pStubMsg->Buffer += 4;
2784     ALIGN_POINTER(pStubMsg->Buffer, 8);
2785   }
2786   else
2787     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2788
2789   pStubMsg->Buffer += bufsize;
2790
2791   return pStubMsg->MemorySize;
2792 }
2793
2794 /***********************************************************************
2795  *           NdrUserMarshalFree [RPCRT4.@]
2796  */
2797 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
2798                                 unsigned char *pMemory,
2799                                 PFORMAT_STRING pFormat)
2800 {
2801 /*  unsigned flags = pFormat[1]; */
2802   unsigned index = *(const WORD*)&pFormat[2];
2803   unsigned long uflag = UserMarshalFlags(pStubMsg);
2804   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2805   TRACE("index=%d\n", index);
2806
2807   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
2808     &uflag, pMemory);
2809 }
2810
2811 /***********************************************************************
2812  *           NdrClearOutParameters [RPCRT4.@]
2813  */
2814 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
2815                                   PFORMAT_STRING pFormat,
2816                                   void *ArgAddr)
2817 {
2818   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
2819 }
2820
2821 /***********************************************************************
2822  *           NdrConvert [RPCRT4.@]
2823  */
2824 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
2825 {
2826   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
2827   /* FIXME: since this stub doesn't do any converting, the proper behavior
2828      is to raise an exception */
2829 }
2830
2831 /***********************************************************************
2832  *           NdrConvert2 [RPCRT4.@]
2833  */
2834 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )
2835 {
2836   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n",
2837     pStubMsg, pFormat, NumberParams);
2838   /* FIXME: since this stub doesn't do any converting, the proper behavior
2839      is to raise an exception */
2840 }
2841
2842 typedef struct _NDR_CSTRUCT_FORMAT
2843 {
2844     unsigned char type;
2845     unsigned char alignment;
2846     unsigned short memory_size;
2847     short offset_to_array_description;
2848 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
2849
2850 /***********************************************************************
2851  *           NdrConformantStructMarshall [RPCRT4.@]
2852  */
2853 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2854                                 unsigned char *pMemory,
2855                                 PFORMAT_STRING pFormat)
2856 {
2857     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2858     PFORMAT_STRING pCArrayFormat;
2859     ULONG esize;
2860
2861     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2862
2863     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2864     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2865     {
2866         ERR("invalid format type %x\n", pCStructFormat->type);
2867         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2868         return NULL;
2869     }
2870
2871     pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2872         pCStructFormat->offset_to_array_description;
2873     if (*pCArrayFormat != RPC_FC_CARRAY)
2874     {
2875         ERR("invalid array format type %x\n", pCStructFormat->type);
2876         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2877         return NULL;
2878     }
2879     esize = *(const WORD*)(pCArrayFormat+2);
2880
2881     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
2882                        pCArrayFormat + 4, 0);
2883
2884     WriteConformance(pStubMsg);
2885
2886     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
2887
2888     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2889
2890     /* copy constant sized part of struct */
2891     pStubMsg->BufferMark = pStubMsg->Buffer;
2892     memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size + pStubMsg->MaxCount * esize);
2893     pStubMsg->Buffer += pCStructFormat->memory_size + pStubMsg->MaxCount * esize;
2894
2895     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2896         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2897
2898     STD_OVERFLOW_CHECK(pStubMsg);
2899
2900     return NULL;
2901 }
2902
2903 /***********************************************************************
2904  *           NdrConformantStructUnmarshall [RPCRT4.@]
2905  */
2906 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2907                                 unsigned char **ppMemory,
2908                                 PFORMAT_STRING pFormat,
2909                                 unsigned char fMustAlloc)
2910 {
2911     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2912     PFORMAT_STRING pCArrayFormat;
2913     ULONG esize;
2914
2915     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2916
2917     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2918     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2919     {
2920         ERR("invalid format type %x\n", pCStructFormat->type);
2921         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2922         return NULL;
2923     }
2924     pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2925         pCStructFormat->offset_to_array_description;
2926     if (*pCArrayFormat != RPC_FC_CARRAY)
2927     {
2928         ERR("invalid array format type %x\n", pCStructFormat->type);
2929         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2930         return NULL;
2931     }
2932     esize = *(const WORD*)(pCArrayFormat+2);
2933
2934     pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
2935
2936     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
2937
2938     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2939
2940     /* work out how much memory to allocate if we need to do so */
2941     if (!*ppMemory || fMustAlloc)
2942     {
2943         SIZE_T size = pCStructFormat->memory_size + pStubMsg->MaxCount * esize;
2944         *ppMemory = NdrAllocate(pStubMsg, size);
2945     }
2946
2947     /* now copy the data */
2948     pStubMsg->BufferMark = pStubMsg->Buffer;
2949     memcpy(*ppMemory, pStubMsg->Buffer, pCStructFormat->memory_size + pStubMsg->MaxCount * esize);
2950     pStubMsg->Buffer += pCStructFormat->memory_size + pStubMsg->MaxCount * esize;
2951
2952     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2953         EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2954
2955     return NULL;
2956 }
2957
2958 /***********************************************************************
2959  *           NdrConformantStructBufferSize [RPCRT4.@]
2960  */
2961 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2962                                 unsigned char *pMemory,
2963                                 PFORMAT_STRING pFormat)
2964 {
2965     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2966     PFORMAT_STRING pCArrayFormat;
2967     ULONG esize;
2968
2969     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2970
2971     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2972     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2973     {
2974         ERR("invalid format type %x\n", pCStructFormat->type);
2975         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2976         return;
2977     }
2978     pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2979         pCStructFormat->offset_to_array_description;
2980     if (*pCArrayFormat != RPC_FC_CARRAY)
2981     {
2982         ERR("invalid array format type %x\n", pCStructFormat->type);
2983         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2984         return;
2985     }
2986     esize = *(const WORD*)(pCArrayFormat+2);
2987
2988     pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
2989     SizeConformance(pStubMsg);
2990
2991     ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
2992
2993     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2994
2995     pStubMsg->BufferLength += pCStructFormat->memory_size + esize * pStubMsg->MaxCount;
2996
2997     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2998         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2999 }
3000
3001 /***********************************************************************
3002  *           NdrConformantStructMemorySize [RPCRT4.@]
3003  */
3004 unsigned long WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3005                                 PFORMAT_STRING pFormat)
3006 {
3007     FIXME("stub\n");
3008     return 0;
3009 }
3010
3011 /***********************************************************************
3012  *           NdrConformantStructFree [RPCRT4.@]
3013  */
3014 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3015                                 unsigned char *pMemory,
3016                                 PFORMAT_STRING pFormat)
3017 {
3018     FIXME("stub\n");
3019 }
3020
3021 /***********************************************************************
3022  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
3023  */
3024 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3025                                 unsigned char *pMemory,
3026                                 PFORMAT_STRING pFormat)
3027 {
3028     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3029     PFORMAT_STRING pCVArrayFormat;
3030     ULONG esize;
3031
3032     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3033
3034     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3035     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3036     {
3037         ERR("invalid format type %x\n", pCVStructFormat->type);
3038         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3039         return NULL;
3040     }
3041
3042     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3043         pCVStructFormat->offset_to_array_description;
3044     switch (*pCVArrayFormat)
3045     {
3046     case RPC_FC_CVARRAY:
3047         esize = *(const WORD*)(pCVArrayFormat+2);
3048
3049         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3050                                             pCVArrayFormat + 4, 0);
3051         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3052                                          pCVArrayFormat, 0);
3053         break;
3054     case RPC_FC_C_CSTRING:
3055         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3056         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3057         esize = sizeof(char);
3058         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3059             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3060                                                 pCVArrayFormat + 2, 0);
3061         else
3062             pStubMsg->MaxCount = pStubMsg->ActualCount;
3063         break;
3064     case RPC_FC_C_WSTRING:
3065         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3066         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3067         esize = sizeof(WCHAR);
3068         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3069             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3070                                                 pCVArrayFormat + 2, 0);
3071         else
3072             pStubMsg->MaxCount = pStubMsg->ActualCount;
3073         break;
3074     default:
3075         ERR("invalid array format type %x\n", *pCVArrayFormat);
3076         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3077         return NULL;
3078     }
3079
3080     WriteConformance(pStubMsg);
3081
3082     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3083
3084     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3085
3086     /* write constant sized part */
3087     pStubMsg->BufferMark = pStubMsg->Buffer;
3088     memcpy(pStubMsg->Buffer, pMemory, pCVStructFormat->memory_size);
3089     pStubMsg->Buffer += pCVStructFormat->memory_size;
3090
3091     WriteVariance(pStubMsg);
3092
3093     /* write array part */
3094     memcpy(pStubMsg->Buffer, pMemory + pCVStructFormat->memory_size, pStubMsg->ActualCount * esize);
3095     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
3096
3097     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3098
3099     STD_OVERFLOW_CHECK(pStubMsg);
3100
3101     return NULL;
3102 }
3103
3104 /***********************************************************************
3105  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
3106  */
3107 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3108                                 unsigned char **ppMemory,
3109                                 PFORMAT_STRING pFormat,
3110                                 unsigned char fMustAlloc)
3111 {
3112     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3113     PFORMAT_STRING pCVArrayFormat;
3114     ULONG esize;
3115     unsigned char cvarray_type;
3116
3117     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3118
3119     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3120     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3121     {
3122         ERR("invalid format type %x\n", pCVStructFormat->type);
3123         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3124         return NULL;
3125     }
3126
3127     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3128         pCVStructFormat->offset_to_array_description;
3129     cvarray_type = *pCVArrayFormat;
3130     switch (cvarray_type)
3131     {
3132     case RPC_FC_CVARRAY:
3133         esize = *(const WORD*)(pCVArrayFormat+2);
3134         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3135         break;
3136     case RPC_FC_C_CSTRING:
3137         esize = sizeof(char);
3138         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3139             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3140         else
3141             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3142         break;
3143     case RPC_FC_C_WSTRING:
3144         esize = sizeof(WCHAR);
3145         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3146             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3147         else
3148             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3149         break;
3150     default:
3151         ERR("invalid array format type %x\n", *pCVArrayFormat);
3152         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3153         return NULL;
3154     }
3155
3156     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3157
3158     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3159
3160     /* work out how much memory to allocate if we need to do so */
3161     if (!*ppMemory || fMustAlloc)
3162     {
3163         SIZE_T size = pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3164         *ppMemory = NdrAllocate(pStubMsg, size);
3165     }
3166
3167     /* copy the constant data */
3168     pStubMsg->BufferMark = pStubMsg->Buffer;
3169     memcpy(*ppMemory, pStubMsg->Buffer, pCVStructFormat->memory_size);
3170     pStubMsg->Buffer += pCVStructFormat->memory_size;
3171
3172     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat);
3173
3174     /* copy the array data */
3175     memcpy(*ppMemory + pCVStructFormat->memory_size, pStubMsg->Buffer,
3176            pStubMsg->ActualCount * esize);
3177     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
3178
3179     if (cvarray_type == RPC_FC_C_CSTRING)
3180         TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3181     else if (cvarray_type == RPC_FC_C_WSTRING)
3182         TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3183
3184     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3185
3186     return NULL;
3187 }
3188
3189 /***********************************************************************
3190  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
3191  */
3192 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3193                                 unsigned char *pMemory,
3194                                 PFORMAT_STRING pFormat)
3195 {
3196     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3197     PFORMAT_STRING pCVArrayFormat;
3198     ULONG esize;
3199
3200     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3201
3202     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3203     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3204     {
3205         ERR("invalid format type %x\n", pCVStructFormat->type);
3206         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3207         return;
3208     }
3209
3210     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3211         pCVStructFormat->offset_to_array_description;
3212     switch (*pCVArrayFormat)
3213     {
3214     case RPC_FC_CVARRAY:
3215         esize = *(const WORD*)(pCVArrayFormat+2);
3216
3217         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3218                                             pCVArrayFormat + 4, 0);
3219         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3220                                          pCVArrayFormat, 0);
3221         break;
3222     case RPC_FC_C_CSTRING:
3223         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3224         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3225         esize = sizeof(char);
3226         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3227             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3228                                                 pCVArrayFormat + 2, 0);
3229         else
3230             pStubMsg->MaxCount = pStubMsg->ActualCount;
3231         break;
3232     case RPC_FC_C_WSTRING:
3233         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3234         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3235         esize = sizeof(WCHAR);
3236         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3237             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3238                                                 pCVArrayFormat + 2, 0);
3239         else
3240             pStubMsg->MaxCount = pStubMsg->ActualCount;
3241         break;
3242     default:
3243         ERR("invalid array format type %x\n", *pCVArrayFormat);
3244         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3245         return;
3246     }
3247
3248     SizeConformance(pStubMsg);
3249
3250     ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
3251
3252     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3253
3254     pStubMsg->BufferLength += pCVStructFormat->memory_size;
3255     SizeVariance(pStubMsg);
3256     pStubMsg->BufferLength += esize * pStubMsg->MaxCount;
3257
3258     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3259 }
3260
3261 /***********************************************************************
3262  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
3263  */
3264 unsigned long WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3265                                 PFORMAT_STRING pFormat)
3266 {
3267     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3268     PFORMAT_STRING pCVArrayFormat;
3269     ULONG esize;
3270     unsigned char cvarray_type;
3271
3272     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3273
3274     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3275     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3276     {
3277         ERR("invalid format type %x\n", pCVStructFormat->type);
3278         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3279         return 0;
3280     }
3281
3282     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3283         pCVStructFormat->offset_to_array_description;
3284     cvarray_type = *pCVArrayFormat;
3285     switch (cvarray_type)
3286     {
3287     case RPC_FC_CVARRAY:
3288         esize = *(const WORD*)(pCVArrayFormat+2);
3289         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3290         break;
3291     case RPC_FC_C_CSTRING:
3292         esize = sizeof(char);
3293         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3294             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3295         else
3296             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3297         break;
3298     case RPC_FC_C_WSTRING:
3299         esize = sizeof(WCHAR);
3300         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3301             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3302         else
3303             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3304         break;
3305     default:
3306         ERR("invalid array format type %x\n", *pCVArrayFormat);
3307         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3308         return 0;
3309     }
3310
3311     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3312
3313     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3314
3315     pStubMsg->Buffer += pCVStructFormat->memory_size;
3316     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat);
3317     pStubMsg->Buffer += pCVStructFormat->memory_size + pStubMsg->ActualCount * esize;
3318
3319     pStubMsg->MemorySize += pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3320
3321     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3322
3323     return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3324 }
3325
3326 /***********************************************************************
3327  *           NdrConformantVaryingStructFree [RPCRT4.@]
3328  */
3329 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3330                                 unsigned char *pMemory,
3331                                 PFORMAT_STRING pFormat)
3332 {
3333     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3334     PFORMAT_STRING pCVArrayFormat;
3335     ULONG esize;
3336
3337     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3338
3339     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3340     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3341     {
3342         ERR("invalid format type %x\n", pCVStructFormat->type);
3343         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3344         return;
3345     }
3346
3347     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3348         pCVStructFormat->offset_to_array_description;
3349     switch (*pCVArrayFormat)
3350     {
3351     case RPC_FC_CVARRAY:
3352         esize = *(const WORD*)(pCVArrayFormat+2);
3353
3354         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3355                                             pCVArrayFormat + 4, 0);
3356         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3357                                          pCVArrayFormat, 0);
3358         break;
3359     case RPC_FC_C_CSTRING:
3360         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3361         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3362         esize = sizeof(char);
3363         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3364             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3365                                                 pCVArrayFormat + 2, 0);
3366         else
3367             pStubMsg->MaxCount = pStubMsg->ActualCount;
3368         break;
3369     case RPC_FC_C_WSTRING:
3370         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3371         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3372         esize = sizeof(WCHAR);
3373         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3374             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3375                                                 pCVArrayFormat + 2, 0);
3376         else
3377             pStubMsg->MaxCount = pStubMsg->ActualCount;
3378         break;
3379     default:
3380         ERR("invalid array format type %x\n", *pCVArrayFormat);
3381         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3382         return;
3383     }
3384
3385     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3386
3387     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3388 }
3389
3390 typedef struct
3391 {
3392     unsigned char type;
3393     unsigned char alignment;
3394     unsigned short total_size;
3395 } NDR_SMFARRAY_FORMAT;
3396
3397 typedef struct
3398 {
3399     unsigned char type;
3400     unsigned char alignment;
3401     unsigned long total_size;
3402 } NDR_LGFARRAY_FORMAT;
3403
3404 /***********************************************************************
3405  *           NdrFixedArrayMarshall [RPCRT4.@]
3406  */
3407 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3408                                 unsigned char *pMemory,
3409                                 PFORMAT_STRING pFormat)
3410 {
3411     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3412     unsigned long total_size;
3413
3414     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3415
3416     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3417         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3418     {
3419         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3420         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3421         return NULL;
3422     }
3423
3424     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3425
3426     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3427     {
3428         total_size = pSmFArrayFormat->total_size;
3429         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3430     }
3431     else
3432     {
3433         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3434         total_size = pLgFArrayFormat->total_size;
3435         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3436     }
3437     memcpy(pStubMsg->Buffer, pMemory, total_size);
3438     pStubMsg->Buffer += total_size;
3439
3440     pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3441
3442     return NULL;
3443 }
3444
3445 /***********************************************************************
3446  *           NdrFixedArrayUnmarshall [RPCRT4.@]
3447  */
3448 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3449                                 unsigned char **ppMemory,
3450                                 PFORMAT_STRING pFormat,
3451                                 unsigned char fMustAlloc)
3452 {
3453     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3454     unsigned long total_size;
3455
3456     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3457
3458     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3459         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3460     {
3461         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3462         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3463         return NULL;
3464     }
3465
3466     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3467
3468     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3469     {
3470         total_size = pSmFArrayFormat->total_size;
3471         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3472     }
3473     else
3474     {
3475         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3476         total_size = pLgFArrayFormat->total_size;
3477         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3478     }
3479
3480     if (fMustAlloc || !*ppMemory)
3481         *ppMemory = NdrAllocate(pStubMsg, total_size);
3482     memcpy(*ppMemory, pStubMsg->Buffer, total_size);
3483     pStubMsg->Buffer += total_size;
3484
3485     pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3486
3487     return NULL;
3488 }
3489
3490 /***********************************************************************
3491  *           NdrFixedArrayBufferSize [RPCRT4.@]
3492  */
3493 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3494                                 unsigned char *pMemory,
3495                                 PFORMAT_STRING pFormat)
3496 {
3497     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3498     unsigned long total_size;
3499
3500     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3501
3502     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3503         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3504     {
3505         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3506         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3507         return;
3508     }
3509
3510     ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
3511
3512     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3513     {
3514         total_size = pSmFArrayFormat->total_size;
3515         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3516     }
3517     else
3518     {
3519         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3520         total_size = pLgFArrayFormat->total_size;
3521         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3522     }
3523     pStubMsg->BufferLength += total_size;
3524
3525     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3526 }
3527
3528 /***********************************************************************
3529  *           NdrFixedArrayMemorySize [RPCRT4.@]
3530  */
3531 unsigned long WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3532                                 PFORMAT_STRING pFormat)
3533 {
3534     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3535     unsigned long total_size;
3536
3537     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3538
3539     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3540         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3541     {
3542         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3543         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3544         return 0;
3545     }
3546
3547     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3548
3549     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3550     {
3551         total_size = pSmFArrayFormat->total_size;
3552         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3553     }
3554     else
3555     {
3556         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3557         total_size = pLgFArrayFormat->total_size;
3558         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3559     }
3560     pStubMsg->Buffer += total_size;
3561     pStubMsg->MemorySize += total_size;
3562
3563     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3564
3565     return total_size;
3566 }
3567
3568 /***********************************************************************
3569  *           NdrFixedArrayFree [RPCRT4.@]
3570  */
3571 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3572                                 unsigned char *pMemory,
3573                                 PFORMAT_STRING pFormat)
3574 {
3575     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3576
3577     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3578
3579     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3580         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3581     {
3582         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3583         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3584         return;
3585     }
3586
3587     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3588         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3589     else
3590     {
3591         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3592         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3593     }
3594
3595     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3596 }
3597
3598 /***********************************************************************
3599  *           NdrVaryingArrayMarshall [RPCRT4.@]
3600  */
3601 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3602                                 unsigned char *pMemory,
3603                                 PFORMAT_STRING pFormat)
3604 {
3605     unsigned char alignment;
3606     DWORD elements, esize;
3607
3608     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3609
3610     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3611         (pFormat[0] != RPC_FC_LGVARRAY))
3612     {
3613         ERR("invalid format type %x\n", pFormat[0]);
3614         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3615         return NULL;
3616     }
3617
3618     alignment = pFormat[1] + 1;
3619
3620     if (pFormat[0] == RPC_FC_SMVARRAY)
3621     {
3622         pFormat += 2;
3623         pFormat += sizeof(WORD);
3624         elements = *(const WORD*)pFormat;
3625         pFormat += sizeof(WORD);
3626     }
3627     else
3628     {
3629         pFormat += 2;
3630         pFormat += sizeof(DWORD);
3631         elements = *(const DWORD*)pFormat;
3632         pFormat += sizeof(DWORD);
3633     }
3634
3635     esize = *(const WORD*)pFormat;
3636     pFormat += sizeof(WORD);
3637
3638     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3639     if ((pStubMsg->ActualCount > elements) ||
3640         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
3641     {
3642         RpcRaiseException(RPC_S_INVALID_BOUND);
3643         return NULL;
3644     }
3645
3646     WriteVariance(pStubMsg);
3647
3648     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3649
3650     memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, pStubMsg->ActualCount*esize);
3651     pStubMsg->BufferMark = pStubMsg->Buffer;
3652     pStubMsg->Buffer += pStubMsg->ActualCount*esize;
3653
3654     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3655
3656     STD_OVERFLOW_CHECK(pStubMsg);
3657
3658     return NULL;
3659 }
3660
3661 /***********************************************************************
3662  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
3663  */
3664 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3665                                 unsigned char **ppMemory,
3666                                 PFORMAT_STRING pFormat,
3667                                 unsigned char fMustAlloc)
3668 {
3669     unsigned char alignment;
3670     DWORD size, elements, esize;
3671
3672     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3673
3674     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3675         (pFormat[0] != RPC_FC_LGVARRAY))
3676     {
3677         ERR("invalid format type %x\n", pFormat[0]);
3678         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3679         return NULL;
3680     }
3681
3682     alignment = pFormat[1] + 1;
3683
3684     if (pFormat[0] == RPC_FC_SMVARRAY)
3685     {
3686         pFormat += 2;
3687         size = *(const WORD*)pFormat;
3688         pFormat += sizeof(WORD);
3689         elements = *(const WORD*)pFormat;
3690         pFormat += sizeof(WORD);
3691     }
3692     else
3693     {
3694         pFormat += 2;
3695         size = *(const DWORD*)pFormat;
3696         pFormat += sizeof(DWORD);
3697         elements = *(const DWORD*)pFormat;
3698         pFormat += sizeof(DWORD);
3699     }
3700
3701     esize = *(const WORD*)pFormat;
3702     pFormat += sizeof(WORD);
3703
3704     pFormat = ReadVariance(pStubMsg, pFormat);
3705     if ((pStubMsg->ActualCount > elements) ||
3706         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
3707     {
3708         RpcRaiseException(RPC_S_INVALID_BOUND);
3709         return NULL;
3710     }
3711
3712     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3713
3714     if (!*ppMemory || fMustAlloc)
3715         *ppMemory = NdrAllocate(pStubMsg, size);
3716     memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, pStubMsg->ActualCount * esize);
3717     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
3718
3719     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3720
3721     return NULL;
3722 }
3723
3724 /***********************************************************************
3725  *           NdrVaryingArrayBufferSize [RPCRT4.@]
3726  */
3727 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3728                                 unsigned char *pMemory,
3729                                 PFORMAT_STRING pFormat)
3730 {
3731     unsigned char alignment;
3732     DWORD elements, esize;
3733
3734     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3735
3736     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3737         (pFormat[0] != RPC_FC_LGVARRAY))
3738     {
3739         ERR("invalid format type %x\n", pFormat[0]);
3740         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3741         return;
3742     }
3743
3744     alignment = pFormat[1] + 1;
3745
3746     if (pFormat[0] == RPC_FC_SMVARRAY)
3747     {
3748         pFormat += 2;
3749         pFormat += sizeof(WORD);
3750         elements = *(const WORD*)pFormat;
3751         pFormat += sizeof(WORD);
3752     }
3753     else
3754     {
3755         pFormat += 2;
3756         pFormat += sizeof(DWORD);
3757         elements = *(const DWORD*)pFormat;
3758         pFormat += sizeof(DWORD);
3759     }
3760
3761     esize = *(const WORD*)pFormat;
3762     pFormat += sizeof(WORD);
3763
3764     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3765     if ((pStubMsg->ActualCount > elements) ||
3766         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
3767     {
3768         RpcRaiseException(RPC_S_INVALID_BOUND);
3769         return;
3770     }
3771
3772     SizeVariance(pStubMsg);
3773
3774     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3775
3776     pStubMsg->BufferLength += pStubMsg->ActualCount * esize;
3777
3778     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3779 }
3780
3781 /***********************************************************************
3782  *           NdrVaryingArrayMemorySize [RPCRT4.@]
3783  */
3784 unsigned long WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3785                                 PFORMAT_STRING pFormat)
3786 {
3787     unsigned char alignment;
3788     DWORD size, elements, esize;
3789
3790     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3791
3792     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3793         (pFormat[0] != RPC_FC_LGVARRAY))
3794     {
3795         ERR("invalid format type %x\n", pFormat[0]);
3796         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3797         return 0;
3798     }
3799
3800     alignment = pFormat[1] + 1;
3801
3802     if (pFormat[0] == RPC_FC_SMVARRAY)
3803     {
3804         pFormat += 2;
3805         size = *(const WORD*)pFormat;
3806         pFormat += sizeof(WORD);
3807         elements = *(const WORD*)pFormat;
3808         pFormat += sizeof(WORD);
3809     }
3810     else
3811     {
3812         pFormat += 2;
3813         size = *(const DWORD*)pFormat;
3814         pFormat += sizeof(DWORD);
3815         elements = *(const DWORD*)pFormat;
3816         pFormat += sizeof(DWORD);
3817     }
3818
3819     esize = *(const WORD*)pFormat;
3820     pFormat += sizeof(WORD);
3821
3822     pFormat = ReadVariance(pStubMsg, pFormat);
3823     if ((pStubMsg->ActualCount > elements) ||
3824         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
3825     {
3826         RpcRaiseException(RPC_S_INVALID_BOUND);
3827         return 0;
3828     }
3829
3830     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3831
3832     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
3833     pStubMsg->MemorySize += size;
3834
3835     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3836
3837     return pStubMsg->MemorySize;
3838 }
3839
3840 /***********************************************************************
3841  *           NdrVaryingArrayFree [RPCRT4.@]
3842  */
3843 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3844                                 unsigned char *pMemory,
3845                                 PFORMAT_STRING pFormat)
3846 {
3847     unsigned char alignment;
3848     DWORD elements;
3849
3850     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3851
3852     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
3853         (pFormat[0] != RPC_FC_LGVARRAY))
3854     {
3855         ERR("invalid format type %x\n", pFormat[0]);
3856         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3857         return;
3858     }
3859
3860     alignment = pFormat[1] + 1;
3861
3862     if (pFormat[0] == RPC_FC_SMVARRAY)
3863     {
3864         pFormat += 2;
3865         pFormat += sizeof(WORD);
3866         elements = *(const WORD*)pFormat;
3867         pFormat += sizeof(WORD);
3868     }
3869     else
3870     {
3871         pFormat += 2;
3872         pFormat += sizeof(DWORD);
3873         elements = *(const DWORD*)pFormat;
3874         pFormat += sizeof(DWORD);
3875     }
3876
3877     pFormat += sizeof(WORD);
3878
3879     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3880     if ((pStubMsg->ActualCount > elements) ||
3881         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
3882     {
3883         RpcRaiseException(RPC_S_INVALID_BOUND);
3884         return;
3885     }
3886
3887     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3888 }
3889
3890 /***********************************************************************
3891  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
3892  */
3893 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3894                                 unsigned char *pMemory,
3895                                 PFORMAT_STRING pFormat)
3896 {
3897     FIXME("stub\n");
3898     return NULL;
3899 }
3900
3901 /***********************************************************************
3902  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
3903  */
3904 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3905                                 unsigned char **ppMemory,
3906                                 PFORMAT_STRING pFormat,
3907                                 unsigned char fMustAlloc)
3908 {
3909     FIXME("stub\n");
3910     return NULL;
3911 }
3912
3913 /***********************************************************************
3914  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
3915  */
3916 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3917                                 unsigned char *pMemory,
3918                                 PFORMAT_STRING pFormat)
3919 {
3920     FIXME("stub\n");
3921 }
3922
3923 /***********************************************************************
3924  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
3925  */
3926 unsigned long WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3927                                 PFORMAT_STRING pFormat)
3928 {
3929     FIXME("stub\n");
3930     return 0;
3931 }
3932
3933 /***********************************************************************
3934  *           NdrEncapsulatedUnionFree [RPCRT4.@]
3935  */
3936 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
3937                                 unsigned char *pMemory,
3938                                 PFORMAT_STRING pFormat)
3939 {
3940     FIXME("stub\n");
3941 }
3942
3943 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
3944                                                              unsigned long discriminant,
3945                                                              PFORMAT_STRING pFormat)
3946 {
3947     unsigned short num_arms, arm, type;
3948
3949     num_arms = *(const SHORT*)pFormat & 0x0fff;
3950     pFormat += 2;
3951     for(arm = 0; arm < num_arms; arm++)
3952     {
3953         if(discriminant == *(const ULONG*)pFormat)
3954         {
3955             pFormat += 4;
3956             break;
3957         }
3958         pFormat += 6;
3959     }
3960
3961     type = *(const unsigned short*)pFormat;
3962     TRACE("type %04x\n", type);
3963     if(arm == num_arms) /* default arm extras */
3964     {
3965         if(type == 0xffff)
3966         {
3967             ERR("no arm for 0x%lx and no default case\n", discriminant);
3968             RpcRaiseException(RPC_S_INVALID_TAG);
3969             return NULL;
3970         }
3971         if(type == 0)
3972         {
3973             TRACE("falling back to empty default case for 0x%lx\n", discriminant);
3974             return NULL;
3975         }
3976     }
3977     return pFormat;
3978 }
3979
3980 static PFORMAT_STRING get_non_encapsulated_union_arm(PMIDL_STUB_MESSAGE pStubMsg,
3981                                                      ULONG value,
3982                                                      PFORMAT_STRING pFormat)
3983 {
3984     pFormat += *(const SHORT*)pFormat;
3985     pFormat += 2;
3986
3987     return get_arm_offset_from_union_arm_selector(pStubMsg, value, pFormat);
3988 }
3989
3990 /***********************************************************************
3991  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
3992  */
3993 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3994                                 unsigned char *pMemory,
3995                                 PFORMAT_STRING pFormat)
3996 {
3997     unsigned short type;
3998     unsigned char switch_type;
3999
4000     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4001     pFormat++;
4002
4003     switch_type = *pFormat;
4004     pFormat++;
4005
4006     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4007     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4008     /* Marshall discriminant */
4009     NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
4010
4011     pFormat = get_non_encapsulated_union_arm(pStubMsg, pStubMsg->MaxCount, pFormat);
4012     if(!pFormat)
4013         return NULL;
4014
4015     type = *(const unsigned short*)pFormat;
4016     if((type & 0xff00) == 0x8000)
4017     {
4018         unsigned char basetype = LOBYTE(type);
4019         return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4020     }
4021     else
4022     {
4023         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4024         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4025         if (m)
4026         {
4027             unsigned char *saved_buffer = NULL;
4028             switch(*desc)
4029             {
4030             case RPC_FC_RP:
4031             case RPC_FC_UP:
4032             case RPC_FC_OP:
4033             case RPC_FC_FP:
4034                 saved_buffer = pStubMsg->Buffer;
4035                 pStubMsg->Buffer += 4; /* for pointer ID */
4036                 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
4037                 break;
4038             default:
4039                 m(pStubMsg, pMemory, desc);
4040             }
4041         }
4042         else FIXME("no marshaller for embedded type %02x\n", *desc);
4043     }
4044     return NULL;
4045 }
4046
4047 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
4048                                     PFORMAT_STRING *ppFormat)
4049 {
4050     long discriminant = 0;
4051
4052     switch(**ppFormat)
4053     {
4054     case RPC_FC_BYTE:
4055     case RPC_FC_CHAR:
4056     case RPC_FC_SMALL:
4057     case RPC_FC_USMALL:
4058         discriminant = *(UCHAR *)pStubMsg->Buffer;
4059         pStubMsg->Buffer += sizeof(UCHAR);
4060         break;
4061     case RPC_FC_WCHAR:
4062     case RPC_FC_SHORT:
4063     case RPC_FC_USHORT:
4064         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4065         discriminant = *(USHORT *)pStubMsg->Buffer;
4066         pStubMsg->Buffer += sizeof(USHORT);
4067         break;
4068     case RPC_FC_LONG:
4069     case RPC_FC_ULONG:
4070         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4071         discriminant = *(ULONG *)pStubMsg->Buffer;
4072         pStubMsg->Buffer += sizeof(ULONG);
4073         break;
4074     default:
4075         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
4076     }
4077     (*ppFormat)++;
4078
4079     if (pStubMsg->fHasNewCorrDesc)
4080         *ppFormat += 6;
4081     else
4082         *ppFormat += 4;
4083     return discriminant;
4084 }
4085
4086 /**********************************************************************
4087  *           NdrNonEncapsulatedUnionUnmarshall[RPCRT4.@]
4088  */
4089 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4090                                 unsigned char **ppMemory,
4091                                 PFORMAT_STRING pFormat,
4092                                 unsigned char fMustAlloc)
4093 {
4094     long discriminant;
4095     unsigned short type, size;
4096
4097     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4098     pFormat++;
4099
4100     /* Unmarshall discriminant */
4101     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
4102     TRACE("unmarshalled discriminant %lx\n", discriminant);
4103
4104     pFormat += *(const SHORT*)pFormat;
4105
4106     size = *(const unsigned short*)pFormat;
4107     pFormat += 2;
4108
4109     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4110     if(!pFormat)
4111         return NULL;
4112
4113     if(!*ppMemory || fMustAlloc)
4114         *ppMemory = NdrAllocate(pStubMsg, size);
4115
4116     type = *(const unsigned short*)pFormat;
4117     if((type & 0xff00) == 0x8000)
4118     {
4119         unsigned char basetype = LOBYTE(type);
4120         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, fMustAlloc);
4121     }
4122     else
4123     {
4124         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4125         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
4126         if (m)
4127         {
4128             unsigned char *saved_buffer = NULL;
4129             switch(*desc)
4130             {
4131             case RPC_FC_RP:
4132             case RPC_FC_UP:
4133             case RPC_FC_OP:
4134             case RPC_FC_FP:
4135                 ALIGN_POINTER(pStubMsg->Buffer, 4);
4136                 saved_buffer = pStubMsg->Buffer;
4137                 pStubMsg->Buffer += 4; /* for pointer ID */
4138                 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, TRUE);
4139                 break;
4140             default:
4141                 m(pStubMsg, ppMemory, desc, fMustAlloc);
4142             }
4143         }
4144         else FIXME("no marshaller for embedded type %02x\n", *desc);
4145     }
4146     return NULL;
4147 }
4148
4149 /***********************************************************************
4150  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
4151  */
4152 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4153                                 unsigned char *pMemory,
4154                                 PFORMAT_STRING pFormat)
4155 {
4156     unsigned short type;
4157     unsigned char switch_type;
4158
4159     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4160     pFormat++;
4161
4162     switch_type = *pFormat;
4163     pFormat++;
4164
4165     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4166     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4167     /* Add discriminant size */
4168     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
4169
4170     pFormat = get_non_encapsulated_union_arm(pStubMsg, pStubMsg->MaxCount, pFormat);
4171     if(!pFormat)
4172         return;
4173
4174     type = *(const unsigned short*)pFormat;
4175     if((type & 0xff00) == 0x8000)
4176     {
4177         unsigned char basetype = LOBYTE(type);
4178         NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
4179     }
4180     else
4181     {
4182         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4183         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
4184         if (m)
4185         {
4186             switch(*desc)
4187             {
4188             case RPC_FC_RP:
4189             case RPC_FC_UP:
4190             case RPC_FC_OP:
4191             case RPC_FC_FP:
4192                 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4193                 pStubMsg->BufferLength += 4; /* for pointer ID */
4194                 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
4195                 break;
4196             default:
4197                 m(pStubMsg, pMemory, desc);
4198             }
4199         }
4200         else FIXME("no buffersizer for embedded type %02x\n", *desc);
4201     }
4202     return;
4203 }
4204
4205 /***********************************************************************
4206  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
4207  */
4208 unsigned long WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4209                                 PFORMAT_STRING pFormat)
4210 {
4211     unsigned long discriminant;
4212     unsigned short type, size;
4213
4214     pFormat++;
4215     /* Unmarshall discriminant */
4216     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
4217     TRACE("unmarshalled discriminant 0x%lx\n", discriminant);
4218
4219     pFormat += *(const SHORT*)pFormat;
4220
4221     size = *(const unsigned short*)pFormat;
4222     pFormat += 2;
4223
4224     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4225     if(!pFormat)
4226         return 0;
4227
4228     pStubMsg->Memory += size;
4229
4230     type = *(const unsigned short*)pFormat;
4231     if((type & 0xff00) == 0x8000)
4232     {
4233         return NdrBaseTypeMemorySize(pStubMsg, pFormat);
4234     }
4235     else
4236     {
4237         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4238         NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
4239         unsigned char *saved_buffer;
4240         if (m)
4241         {
4242             switch(*desc)
4243             {
4244             case RPC_FC_RP:
4245             case RPC_FC_UP:
4246             case RPC_FC_OP:
4247             case RPC_FC_FP:
4248                 ALIGN_POINTER(pStubMsg->Buffer, 4);
4249                 saved_buffer = pStubMsg->Buffer;
4250                 pStubMsg->Buffer += 4;
4251                 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
4252                 pStubMsg->MemorySize += 4;
4253                 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
4254                 break;
4255             default:
4256                 return m(pStubMsg, desc);
4257             }
4258         }
4259         else FIXME("no marshaller for embedded type %02x\n", *desc);
4260     }
4261
4262     TRACE("size %d\n", size);
4263     return size;
4264 }
4265
4266 /***********************************************************************
4267  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
4268  */
4269 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
4270                                 unsigned char *pMemory,
4271                                 PFORMAT_STRING pFormat)
4272 {
4273     FIXME("stub\n");
4274 }
4275
4276 /***********************************************************************
4277  *           NdrByteCountPointerMarshall [RPCRT4.@]
4278  */
4279 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4280                                 unsigned char *pMemory,
4281                                 PFORMAT_STRING pFormat)
4282 {
4283     FIXME("stub\n");
4284     return NULL;
4285 }
4286
4287 /***********************************************************************
4288  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
4289  */
4290 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4291                                 unsigned char **ppMemory,
4292                                 PFORMAT_STRING pFormat,
4293                                 unsigned char fMustAlloc)
4294 {
4295     FIXME("stub\n");
4296     return NULL;
4297 }
4298
4299 /***********************************************************************
4300  *           NdrByteCountPointerBufferSize [RPCRT4.@]
4301  */
4302 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4303                                 unsigned char *pMemory,
4304                                 PFORMAT_STRING pFormat)
4305 {
4306     FIXME("stub\n");
4307 }
4308
4309 /***********************************************************************
4310  *           NdrByteCountPointerMemorySize [RPCRT4.@]
4311  */
4312 unsigned long WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4313                                 PFORMAT_STRING pFormat)
4314 {
4315     FIXME("stub\n");
4316     return 0;
4317 }
4318
4319 /***********************************************************************
4320  *           NdrByteCountPointerFree [RPCRT4.@]
4321  */
4322 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
4323                                 unsigned char *pMemory,
4324                                 PFORMAT_STRING pFormat)
4325 {
4326     FIXME("stub\n");
4327 }
4328
4329 /***********************************************************************
4330  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
4331  */
4332 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4333                                 unsigned char *pMemory,
4334                                 PFORMAT_STRING pFormat)
4335 {
4336     FIXME("stub\n");
4337     return NULL;
4338 }
4339
4340 /***********************************************************************
4341  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
4342  */
4343 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4344                                 unsigned char **ppMemory,
4345                                 PFORMAT_STRING pFormat,
4346                                 unsigned char fMustAlloc)
4347 {
4348     FIXME("stub\n");
4349     return NULL;
4350 }
4351
4352 /***********************************************************************
4353  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
4354  */
4355 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4356                                 unsigned char *pMemory,
4357                                 PFORMAT_STRING pFormat)
4358 {
4359     FIXME("stub\n");
4360 }
4361
4362 /***********************************************************************
4363  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
4364  */
4365 unsigned long WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4366                                 PFORMAT_STRING pFormat)
4367 {
4368     FIXME("stub\n");
4369     return 0;
4370 }
4371
4372 /***********************************************************************
4373  *           NdrXmitOrRepAsFree [RPCRT4.@]
4374  */
4375 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
4376                                 unsigned char *pMemory,
4377                                 PFORMAT_STRING pFormat)
4378 {
4379     FIXME("stub\n");
4380 }
4381
4382 /***********************************************************************
4383  *           NdrBaseTypeMarshall [internal]
4384  */
4385 static unsigned char *WINAPI NdrBaseTypeMarshall(
4386     PMIDL_STUB_MESSAGE pStubMsg,
4387     unsigned char *pMemory,
4388     PFORMAT_STRING pFormat)
4389 {
4390     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4391
4392     switch(*pFormat)
4393     {
4394     case RPC_FC_BYTE:
4395     case RPC_FC_CHAR:
4396     case RPC_FC_SMALL:
4397     case RPC_FC_USMALL:
4398         *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory;
4399         pStubMsg->Buffer += sizeof(UCHAR);
4400         TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
4401         break;
4402     case RPC_FC_WCHAR:
4403     case RPC_FC_SHORT:
4404     case RPC_FC_USHORT:
4405         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4406         *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory;
4407         pStubMsg->Buffer += sizeof(USHORT);
4408         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
4409         break;
4410     case RPC_FC_LONG:
4411     case RPC_FC_ULONG:
4412     case RPC_FC_ERROR_STATUS_T:
4413     case RPC_FC_ENUM32:
4414         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4415         *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory;
4416         pStubMsg->Buffer += sizeof(ULONG);
4417         TRACE("value: 0x%08lx\n", *(ULONG *)pMemory);
4418         break;
4419     case RPC_FC_FLOAT:
4420         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
4421         *(float *)pStubMsg->Buffer = *(float *)pMemory;
4422         pStubMsg->Buffer += sizeof(float);
4423         break;
4424     case RPC_FC_DOUBLE:
4425         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
4426         *(double *)pStubMsg->Buffer = *(double *)pMemory;
4427         pStubMsg->Buffer += sizeof(double);
4428         break;
4429     case RPC_FC_HYPER:
4430         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
4431         *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory;
4432         pStubMsg->Buffer += sizeof(ULONGLONG);
4433         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
4434         break;
4435     case RPC_FC_ENUM16:
4436         /* only 16-bits on the wire, so do a sanity check */
4437         if (*(UINT *)pMemory > USHRT_MAX)
4438             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
4439         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4440         *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
4441         pStubMsg->Buffer += sizeof(USHORT);
4442         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
4443         break;
4444     default:
4445         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4446     }
4447
4448     STD_OVERFLOW_CHECK(pStubMsg);
4449
4450     /* FIXME: what is the correct return value? */
4451     return NULL;
4452 }
4453
4454 /***********************************************************************
4455  *           NdrBaseTypeUnmarshall [internal]
4456  */
4457 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
4458     PMIDL_STUB_MESSAGE pStubMsg,
4459     unsigned char **ppMemory,
4460     PFORMAT_STRING pFormat,
4461     unsigned char fMustAlloc)
4462 {
4463     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
4464
4465 #define BASE_TYPE_UNMARSHALL(type) \
4466         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
4467         if (fMustAlloc || !*ppMemory) \
4468             *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
4469         TRACE("*ppMemory: %p\n", *ppMemory); \
4470         **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
4471         pStubMsg->Buffer += sizeof(type);
4472
4473     switch(*pFormat)
4474     {
4475     case RPC_FC_BYTE:
4476     case RPC_FC_CHAR:
4477     case RPC_FC_SMALL:
4478     case RPC_FC_USMALL:
4479         BASE_TYPE_UNMARSHALL(UCHAR);
4480         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
4481         break;
4482     case RPC_FC_WCHAR:
4483     case RPC_FC_SHORT:
4484     case RPC_FC_USHORT:
4485         BASE_TYPE_UNMARSHALL(USHORT);
4486         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
4487         break;
4488     case RPC_FC_LONG:
4489     case RPC_FC_ULONG:
4490     case RPC_FC_ERROR_STATUS_T:
4491     case RPC_FC_ENUM32:
4492         BASE_TYPE_UNMARSHALL(ULONG);
4493         TRACE("value: 0x%08lx\n", **(ULONG **)ppMemory);
4494         break;
4495    case RPC_FC_FLOAT:
4496         BASE_TYPE_UNMARSHALL(float);
4497         TRACE("value: %f\n", **(float **)ppMemory);
4498         break;
4499     case RPC_FC_DOUBLE:
4500         BASE_TYPE_UNMARSHALL(double);
4501         TRACE("value: %f\n", **(double **)ppMemory);
4502         break;
4503     case RPC_FC_HYPER:
4504         BASE_TYPE_UNMARSHALL(ULONGLONG);
4505         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
4506         break;
4507     case RPC_FC_ENUM16:
4508         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4509         if (fMustAlloc || !*ppMemory)
4510             *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
4511         TRACE("*ppMemory: %p\n", *ppMemory);
4512         /* 16-bits on the wire, but int in memory */
4513         **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
4514         pStubMsg->Buffer += sizeof(USHORT);
4515         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
4516         break;
4517     default:
4518         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4519     }
4520 #undef BASE_TYPE_UNMARSHALL
4521
4522     /* FIXME: what is the correct return value? */
4523
4524     return NULL;
4525 }
4526
4527 /***********************************************************************
4528  *           NdrBaseTypeBufferSize [internal]
4529  */
4530 static void WINAPI NdrBaseTypeBufferSize(
4531     PMIDL_STUB_MESSAGE pStubMsg,
4532     unsigned char *pMemory,
4533     PFORMAT_STRING pFormat)
4534 {
4535     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4536
4537     switch(*pFormat)
4538     {
4539     case RPC_FC_BYTE:
4540     case RPC_FC_CHAR:
4541     case RPC_FC_SMALL:
4542     case RPC_FC_USMALL:
4543         pStubMsg->BufferLength += sizeof(UCHAR);
4544         break;
4545     case RPC_FC_WCHAR:
4546     case RPC_FC_SHORT:
4547     case RPC_FC_USHORT:
4548     case RPC_FC_ENUM16:
4549         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
4550         pStubMsg->BufferLength += sizeof(USHORT);
4551         break;
4552     case RPC_FC_LONG:
4553     case RPC_FC_ULONG:
4554     case RPC_FC_ENUM32:
4555         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
4556         pStubMsg->BufferLength += sizeof(ULONG);
4557         break;
4558     case RPC_FC_FLOAT:
4559         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
4560         pStubMsg->BufferLength += sizeof(float);
4561         break;
4562     case RPC_FC_DOUBLE:
4563         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
4564         pStubMsg->BufferLength += sizeof(double);
4565         break;
4566     case RPC_FC_HYPER:
4567         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
4568         pStubMsg->BufferLength += sizeof(ULONGLONG);
4569         break;
4570     case RPC_FC_ERROR_STATUS_T:
4571         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
4572         pStubMsg->BufferLength += sizeof(error_status_t);
4573         break;
4574     default:
4575         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4576     }
4577 }
4578
4579 /***********************************************************************
4580  *           NdrBaseTypeMemorySize [internal]
4581  */
4582 static unsigned long WINAPI NdrBaseTypeMemorySize(
4583     PMIDL_STUB_MESSAGE pStubMsg,
4584     PFORMAT_STRING pFormat)
4585 {
4586     switch(*pFormat)
4587     {
4588     case RPC_FC_BYTE:
4589     case RPC_FC_CHAR:
4590     case RPC_FC_SMALL:
4591     case RPC_FC_USMALL:
4592         pStubMsg->Buffer += sizeof(UCHAR);
4593         pStubMsg->MemorySize += sizeof(UCHAR);
4594         return sizeof(UCHAR);
4595     case RPC_FC_WCHAR:
4596     case RPC_FC_SHORT:
4597     case RPC_FC_USHORT:
4598         pStubMsg->Buffer += sizeof(USHORT);
4599         pStubMsg->MemorySize += sizeof(USHORT);
4600         return sizeof(USHORT);
4601     case RPC_FC_LONG:
4602     case RPC_FC_ULONG:
4603         pStubMsg->Buffer += sizeof(ULONG);
4604         pStubMsg->MemorySize += sizeof(ULONG);
4605         return sizeof(ULONG);
4606     case RPC_FC_FLOAT:
4607         pStubMsg->Buffer += sizeof(float);
4608         pStubMsg->MemorySize += sizeof(float);
4609         return sizeof(float);
4610     case RPC_FC_DOUBLE:
4611         pStubMsg->Buffer += sizeof(double);
4612         pStubMsg->MemorySize += sizeof(double);
4613         return sizeof(double);
4614     case RPC_FC_HYPER:
4615         pStubMsg->Buffer += sizeof(ULONGLONG);
4616         pStubMsg->MemorySize += sizeof(ULONGLONG);
4617         return sizeof(ULONGLONG);
4618     case RPC_FC_ERROR_STATUS_T:
4619         pStubMsg->Buffer += sizeof(error_status_t);
4620         pStubMsg->MemorySize += sizeof(error_status_t);
4621         return sizeof(error_status_t);
4622     case RPC_FC_ENUM16:
4623     case RPC_FC_ENUM32:
4624         pStubMsg->Buffer += sizeof(INT);
4625         pStubMsg->MemorySize += sizeof(INT);
4626         return sizeof(INT);
4627     default:
4628         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4629        return 0;
4630     }
4631 }
4632
4633 /***********************************************************************
4634  *           NdrBaseTypeFree [internal]
4635  */
4636 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
4637                                 unsigned char *pMemory,
4638                                 PFORMAT_STRING pFormat)
4639 {
4640    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4641
4642    /* nothing to do */
4643 }
4644
4645 /***********************************************************************
4646  *           NdrClientContextMarshall
4647  */
4648 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4649                                      NDR_CCONTEXT ContextHandle,
4650                                      int fCheck)
4651 {
4652     TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
4653
4654     ALIGN_POINTER(pStubMsg->Buffer, 4);
4655
4656     /* FIXME: what does fCheck do? */
4657     NDRCContextMarshall(ContextHandle,
4658                         pStubMsg->Buffer);
4659
4660     pStubMsg->Buffer += cbNDRContext;
4661 }
4662
4663 /***********************************************************************
4664  *           NdrClientContextUnmarshall
4665  */
4666 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4667                                        NDR_CCONTEXT * pContextHandle,
4668                                        RPC_BINDING_HANDLE BindHandle)
4669 {
4670     TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
4671
4672     ALIGN_POINTER(pStubMsg->Buffer, 4);
4673
4674     NDRCContextUnmarshall(pContextHandle,
4675                           BindHandle,
4676                           pStubMsg->Buffer,
4677                           pStubMsg->RpcMsg->DataRepresentation);
4678
4679     pStubMsg->Buffer += cbNDRContext;
4680 }
4681
4682 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4683                                      NDR_SCONTEXT ContextHandle,
4684                                      NDR_RUNDOWN RundownRoutine )
4685 {
4686     FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
4687 }
4688
4689 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
4690 {
4691     FIXME("(%p): stub\n", pStubMsg);
4692     return NULL;
4693 }
4694
4695 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
4696                                  unsigned char* pMemory,
4697                                  PFORMAT_STRING pFormat)
4698 {
4699     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
4700 }
4701
4702 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
4703                                                PFORMAT_STRING pFormat)
4704 {
4705     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
4706     return NULL;
4707 }
4708
4709 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4710                                         NDR_SCONTEXT ContextHandle,
4711                                         NDR_RUNDOWN RundownRoutine,
4712                                         PFORMAT_STRING pFormat)
4713 {
4714     FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
4715 }
4716
4717 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4718                                                   PFORMAT_STRING pFormat)
4719 {
4720     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
4721     return NULL;
4722 }
4723
4724 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e
4725
4726 typedef struct ndr_context_handle
4727 {
4728     DWORD      attributes;
4729     GUID       uuid;
4730 } ndr_context_handle;
4731
4732 struct context_handle_entry
4733 {
4734     struct list entry;
4735     DWORD magic;
4736     RPC_BINDING_HANDLE handle;
4737     ndr_context_handle wire_data;
4738 };
4739
4740 static struct list context_handle_list = LIST_INIT(context_handle_list);
4741
4742 static CRITICAL_SECTION ndr_context_cs;
4743 static CRITICAL_SECTION_DEBUG ndr_context_debug =
4744 {
4745     0, 0, &ndr_context_cs,
4746     { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList },
4747       0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") }
4748 };
4749 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 };
4750
4751 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
4752 {
4753     struct context_handle_entry *che = (struct context_handle_entry*) CContext;
4754
4755     if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
4756         return NULL;
4757     return che;
4758 }
4759
4760 static struct context_handle_entry *context_entry_from_guid(LPGUID uuid)
4761 {
4762     struct context_handle_entry *che;
4763     LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry)
4764         if (IsEqualGUID(&che->wire_data.uuid, uuid))
4765             return che;
4766     return NULL;
4767 }
4768
4769 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
4770 {
4771     struct context_handle_entry *che;
4772     RPC_BINDING_HANDLE handle = NULL;
4773
4774     TRACE("%p\n", CContext);
4775
4776     EnterCriticalSection(&ndr_context_cs);
4777     che = get_context_entry(CContext);
4778     if (che)
4779         handle = che->handle;
4780     LeaveCriticalSection(&ndr_context_cs);
4781
4782     if (!handle)
4783         RpcRaiseException(ERROR_INVALID_HANDLE);
4784     return handle;
4785 }
4786
4787 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
4788 {
4789     struct context_handle_entry *che;
4790
4791     TRACE("%p %p\n", CContext, pBuff);
4792
4793     if (CContext)
4794     {
4795         EnterCriticalSection(&ndr_context_cs);
4796         che = get_context_entry(CContext);
4797         memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle));
4798         LeaveCriticalSection(&ndr_context_cs);
4799     }
4800     else
4801     {
4802         ndr_context_handle *wire_data = (ndr_context_handle *)pBuff;
4803         wire_data->attributes = 0;
4804         wire_data->uuid = GUID_NULL;
4805     }
4806 }
4807
4808 static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext,
4809                                       RPC_BINDING_HANDLE hBinding,
4810                                       ndr_context_handle *chi)
4811 {
4812     struct context_handle_entry *che = NULL;
4813
4814     /* a null UUID means we should free the context handle */
4815     if (IsEqualGUID(&chi->uuid, &GUID_NULL))
4816     {
4817         if (*CContext)
4818         {
4819             che = get_context_entry(*CContext);
4820             if (!che)
4821                 return ERROR_INVALID_HANDLE;
4822             list_remove(&che->entry);
4823             RpcBindingFree(&che->handle);
4824             HeapFree(GetProcessHeap(), 0, che);
4825             che = NULL;
4826         }
4827     }
4828     /* if there's no existing entry matching the GUID, allocate one */
4829     else if (!(che = context_entry_from_guid(&chi->uuid)))
4830     {
4831         che = HeapAlloc(GetProcessHeap(), 0, sizeof *che);
4832         if (!che)
4833             return ERROR_NOT_ENOUGH_MEMORY;
4834         che->magic = NDR_CONTEXT_HANDLE_MAGIC;
4835         RpcBindingCopy(hBinding, &che->handle);
4836         list_add_tail(&context_handle_list, &che->entry);
4837         memcpy(&che->wire_data, chi, sizeof *chi);
4838     }
4839
4840     *CContext = che;
4841
4842     return ERROR_SUCCESS;
4843 }
4844
4845 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext,
4846                                   RPC_BINDING_HANDLE hBinding,
4847                                   void *pBuff,
4848                                   unsigned long DataRepresentation)
4849 {
4850     UINT r;
4851
4852     TRACE("*%p=(%p) %p %p %08lx\n",
4853           CContext, *CContext, hBinding, pBuff, DataRepresentation);
4854
4855     EnterCriticalSection(&ndr_context_cs);
4856     r = ndr_update_context_handle(CContext, hBinding, pBuff);
4857     LeaveCriticalSection(&ndr_context_cs);
4858     if (r)
4859         RpcRaiseException(r);
4860 }
4861
4862 void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext,
4863                                void *pBuff,
4864                                NDR_RUNDOWN userRunDownIn)
4865 {
4866     FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn);
4867 }
4868
4869 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding,
4870                                   NDR_SCONTEXT CContext,
4871                                   void *pBuff,
4872                                   NDR_RUNDOWN userRunDownIn)
4873 {
4874     FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn);
4875 }
4876
4877 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
4878                                  NDR_SCONTEXT CContext,
4879                                  void *pBuff,
4880                                  NDR_RUNDOWN userRunDownIn,
4881                                  void *CtxGuard,
4882                                  unsigned long Flags)
4883 {
4884     FIXME("(%p %p %p %p %p %lu): stub\n",
4885           hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags);
4886 }
4887
4888 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff,
4889                                           unsigned long DataRepresentation)
4890 {
4891     FIXME("(%p %08lx): stub\n", pBuff, DataRepresentation);
4892     return NULL;
4893 }
4894
4895 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding,
4896                                             void *pBuff,
4897                                             unsigned long DataRepresentation)
4898 {
4899     FIXME("(%p %p %08lx): stub\n", hBinding, pBuff, DataRepresentation);
4900     return NULL;
4901 }
4902
4903 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
4904                                            void *pBuff,
4905                                            unsigned long DataRepresentation,
4906                                            void *CtxGuard,
4907                                            unsigned long Flags)
4908 {
4909     FIXME("(%p %p %08lx %p %lu): stub\n",
4910           hBinding, pBuff, DataRepresentation, CtxGuard, Flags);
4911     return NULL;
4912 }