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