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