mshtml: Fixed handling channels without container and necko channel.
[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  *  - Byte count pointers
25  *  - transmit_as/represent as
26  *  - Multi-dimensional arrays
27  *  - Conversion functions (NdrConvert)
28  *  - Checks for integer addition overflow
29  *  - Checks for out-of-memory conditions
30  */
31
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <limits.h>
37
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winerror.h"
41
42 #include "ndr_misc.h"
43 #include "rpcndr.h"
44
45 #include "wine/unicode.h"
46 #include "wine/rpcfc.h"
47
48 #include "wine/debug.h"
49 #include "wine/list.h"
50
51 WINE_DEFAULT_DEBUG_CHANNEL(ole);
52
53 #if defined(__i386__)
54 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
55     (*((UINT32 *)(pchar)) = (uint32))
56
57 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
58     (*((UINT32 *)(pchar)))
59 #else
60   /* these would work for i386 too, but less efficient */
61 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
62     (*(pchar)     = LOBYTE(LOWORD(uint32)), \
63      *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
64      *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
65      *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
66      (uint32)) /* allow as r-value */
67
68 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
69     (MAKELONG( \
70       MAKEWORD(*(pchar), *((pchar)+1)), \
71       MAKEWORD(*((pchar)+2), *((pchar)+3))))
72 #endif
73
74 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
75   (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
76    *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
77    *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
78    *(pchar)     = HIBYTE(HIWORD(uint32)), \
79    (uint32)) /* allow as r-value */
80
81 #define BIG_ENDIAN_UINT32_READ(pchar) \
82   (MAKELONG( \
83     MAKEWORD(*((pchar)+3), *((pchar)+2)), \
84     MAKEWORD(*((pchar)+1), *(pchar))))
85
86 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
87 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
88     BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
89 # define NDR_LOCAL_UINT32_READ(pchar) \
90     BIG_ENDIAN_UINT32_READ(pchar)
91 #else
92 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
93     LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
94 # define NDR_LOCAL_UINT32_READ(pchar) \
95     LITTLE_ENDIAN_UINT32_READ(pchar)
96 #endif
97
98 /* _Align must be the desired alignment,
99  * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
100 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
101 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
102 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
103 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
104
105 #define STD_OVERFLOW_CHECK(_Msg) do { \
106     TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
107     if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
108         ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
109   } while (0)
110
111 #define NDR_TABLE_SIZE 128
112 #define NDR_TABLE_MASK 127
113
114 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
115 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
116 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
117 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
118 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
119
120 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
121 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
122 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
123
124 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
125   0,
126   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
127   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
128   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
129   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
130   /* 0x10 */
131   NdrBaseTypeMarshall,
132   /* 0x11 */
133   NdrPointerMarshall, NdrPointerMarshall,
134   NdrPointerMarshall, NdrPointerMarshall,
135   /* 0x15 */
136   NdrSimpleStructMarshall, NdrSimpleStructMarshall,
137   NdrConformantStructMarshall, NdrConformantStructMarshall,
138   NdrConformantVaryingStructMarshall,
139   NdrComplexStructMarshall,
140   /* 0x1b */
141   NdrConformantArrayMarshall, 
142   NdrConformantVaryingArrayMarshall,
143   NdrFixedArrayMarshall, NdrFixedArrayMarshall,
144   NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
145   NdrComplexArrayMarshall,
146   /* 0x22 */
147   NdrConformantStringMarshall, 0, 0,
148   NdrConformantStringMarshall,
149   NdrNonConformantStringMarshall, 0, 0, 0,
150   /* 0x2a */
151   NdrEncapsulatedUnionMarshall,
152   NdrNonEncapsulatedUnionMarshall,
153   NdrByteCountPointerMarshall,
154   NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
155   /* 0x2f */
156   NdrInterfacePointerMarshall,
157   /* 0x30 */
158   NdrContextHandleMarshall,
159   /* 0xb1 */
160   0, 0, 0,
161   NdrUserMarshalMarshall,
162   0, 0,
163   /* 0xb7 */
164   NdrRangeMarshall
165 };
166 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
167   0,
168   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
169   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
170   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
171   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
172   /* 0x10 */
173   NdrBaseTypeUnmarshall,
174   /* 0x11 */
175   NdrPointerUnmarshall, NdrPointerUnmarshall,
176   NdrPointerUnmarshall, NdrPointerUnmarshall,
177   /* 0x15 */
178   NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
179   NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
180   NdrConformantVaryingStructUnmarshall,
181   NdrComplexStructUnmarshall,
182   /* 0x1b */
183   NdrConformantArrayUnmarshall, 
184   NdrConformantVaryingArrayUnmarshall,
185   NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
186   NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
187   NdrComplexArrayUnmarshall,
188   /* 0x22 */
189   NdrConformantStringUnmarshall, 0, 0,
190   NdrConformantStringUnmarshall,
191   NdrNonConformantStringUnmarshall, 0, 0, 0,
192   /* 0x2a */
193   NdrEncapsulatedUnionUnmarshall,
194   NdrNonEncapsulatedUnionUnmarshall,
195   NdrByteCountPointerUnmarshall,
196   NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
197   /* 0x2f */
198   NdrInterfacePointerUnmarshall,
199   /* 0x30 */
200   NdrContextHandleUnmarshall,
201   /* 0xb1 */
202   0, 0, 0,
203   NdrUserMarshalUnmarshall,
204   0, 0,
205   /* 0xb7 */
206   NdrRangeUnmarshall
207 };
208 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
209   0,
210   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
211   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
212   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
213   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
214   /* 0x10 */
215   NdrBaseTypeBufferSize,
216   /* 0x11 */
217   NdrPointerBufferSize, NdrPointerBufferSize,
218   NdrPointerBufferSize, NdrPointerBufferSize,
219   /* 0x15 */
220   NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
221   NdrConformantStructBufferSize, NdrConformantStructBufferSize,
222   NdrConformantVaryingStructBufferSize,
223   NdrComplexStructBufferSize,
224   /* 0x1b */
225   NdrConformantArrayBufferSize, 
226   NdrConformantVaryingArrayBufferSize,
227   NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
228   NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
229   NdrComplexArrayBufferSize,
230   /* 0x22 */
231   NdrConformantStringBufferSize, 0, 0,
232   NdrConformantStringBufferSize,
233   NdrNonConformantStringBufferSize, 0, 0, 0,
234   /* 0x2a */
235   NdrEncapsulatedUnionBufferSize,
236   NdrNonEncapsulatedUnionBufferSize,
237   NdrByteCountPointerBufferSize,
238   NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
239   /* 0x2f */
240   NdrInterfacePointerBufferSize,
241   /* 0x30 */
242   NdrContextHandleBufferSize,
243   /* 0xb1 */
244   0, 0, 0,
245   NdrUserMarshalBufferSize,
246   0, 0,
247   /* 0xb7 */
248   NdrRangeBufferSize
249 };
250 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
251   0,
252   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
253   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
254   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
255   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
256   /* 0x10 */
257   NdrBaseTypeMemorySize,
258   /* 0x11 */
259   NdrPointerMemorySize, NdrPointerMemorySize,
260   NdrPointerMemorySize, NdrPointerMemorySize,
261   /* 0x15 */
262   NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
263   NdrConformantStructMemorySize, NdrConformantStructMemorySize,
264   NdrConformantVaryingStructMemorySize,
265   NdrComplexStructMemorySize,
266   /* 0x1b */
267   NdrConformantArrayMemorySize,
268   NdrConformantVaryingArrayMemorySize,
269   NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
270   NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
271   NdrComplexArrayMemorySize,
272   /* 0x22 */
273   NdrConformantStringMemorySize, 0, 0,
274   NdrConformantStringMemorySize,
275   NdrNonConformantStringMemorySize, 0, 0, 0,
276   /* 0x2a */
277   NdrEncapsulatedUnionMemorySize,
278   NdrNonEncapsulatedUnionMemorySize,
279   NdrByteCountPointerMemorySize,
280   NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
281   /* 0x2f */
282   NdrInterfacePointerMemorySize,
283   /* 0x30 */
284   0,
285   /* 0xb1 */
286   0, 0, 0,
287   NdrUserMarshalMemorySize,
288   0, 0,
289   /* 0xb7 */
290   NdrRangeMemorySize
291 };
292 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
293   0,
294   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
295   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
296   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
297   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
298   /* 0x10 */
299   NdrBaseTypeFree,
300   /* 0x11 */
301   NdrPointerFree, NdrPointerFree,
302   NdrPointerFree, NdrPointerFree,
303   /* 0x15 */
304   NdrSimpleStructFree, NdrSimpleStructFree,
305   NdrConformantStructFree, NdrConformantStructFree,
306   NdrConformantVaryingStructFree,
307   NdrComplexStructFree,
308   /* 0x1b */
309   NdrConformantArrayFree, 
310   NdrConformantVaryingArrayFree,
311   NdrFixedArrayFree, NdrFixedArrayFree,
312   NdrVaryingArrayFree, NdrVaryingArrayFree,
313   NdrComplexArrayFree,
314   /* 0x22 */
315   0, 0, 0,
316   0, 0, 0, 0, 0,
317   /* 0x2a */
318   NdrEncapsulatedUnionFree,
319   NdrNonEncapsulatedUnionFree,
320   0,
321   NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
322   /* 0x2f */
323   NdrInterfacePointerFree,
324   /* 0x30 */
325   0,
326   /* 0xb1 */
327   0, 0, 0,
328   NdrUserMarshalFree,
329   0, 0,
330   /* 0xb7 */
331   NdrRangeFree
332 };
333
334 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
335 {
336   /* hmm, this is probably supposed to do more? */
337   return pStubMsg->pfnAllocate(len);
338 }
339
340 static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
341 {
342   pStubMsg->pfnFree(Pointer);
343 }
344
345 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
346 {
347     return (*(const ULONG *)pFormat != -1);
348 }
349
350 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
351 {
352   ALIGN_POINTER(pStubMsg->Buffer, 4);
353   if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
354       RpcRaiseException(RPC_X_BAD_STUB_DATA);
355   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
356   pStubMsg->Buffer += 4;
357   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
358   if (pStubMsg->fHasNewCorrDesc)
359     return pFormat+6;
360   else
361     return pFormat+4;
362 }
363
364 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
365 {
366   if (pFormat && !IsConformanceOrVariancePresent(pFormat))
367   {
368     pStubMsg->Offset = 0;
369     pStubMsg->ActualCount = pStubMsg->MaxCount;
370     goto done;
371   }
372
373   ALIGN_POINTER(pStubMsg->Buffer, 4);
374   if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
375     RpcRaiseException(RPC_X_BAD_STUB_DATA);
376   pStubMsg->Offset      = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
377   pStubMsg->Buffer += 4;
378   TRACE("offset is %d\n", pStubMsg->Offset);
379   pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
380   pStubMsg->Buffer += 4;
381   TRACE("variance is %d\n", pStubMsg->ActualCount);
382
383   if ((pStubMsg->ActualCount > MaxValue) ||
384       (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
385   {
386     ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
387         pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
388     RpcRaiseException(RPC_S_INVALID_BOUND);
389     return NULL;
390   }
391
392 done:
393   if (pStubMsg->fHasNewCorrDesc)
394     return pFormat+6;
395   else
396     return pFormat+4;
397 }
398
399 /* writes the conformance value to the buffer */
400 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
401 {
402     ALIGN_POINTER(pStubMsg->Buffer, 4);
403     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
404     pStubMsg->Buffer += 4;
405 }
406
407 /* writes the variance values to the buffer */
408 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
409 {
410     ALIGN_POINTER(pStubMsg->Buffer, 4);
411     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
412     pStubMsg->Buffer += 4;
413     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
414     pStubMsg->Buffer += 4;
415 }
416
417 /* requests buffer space for the conformance value */
418 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
419 {
420     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
421     pStubMsg->BufferLength += 4;
422 }
423
424 /* requests buffer space for the variance values */
425 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
426 {
427     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
428     pStubMsg->BufferLength += 8;
429 }
430
431 PFORMAT_STRING ComputeConformanceOrVariance(
432     MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
433     PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
434 {
435   BYTE dtype = pFormat[0] & 0xf;
436   short ofs = *(const short *)&pFormat[2];
437   LPVOID ptr = NULL;
438   DWORD data = 0;
439
440   if (!IsConformanceOrVariancePresent(pFormat)) {
441     /* null descriptor */
442     *pCount = def;
443     goto finish_conf;
444   }
445
446   switch (pFormat[0] & 0xf0) {
447   case RPC_FC_NORMAL_CONFORMANCE:
448     TRACE("normal conformance, ofs=%d\n", ofs);
449     ptr = pMemory;
450     break;
451   case RPC_FC_POINTER_CONFORMANCE:
452     TRACE("pointer conformance, ofs=%d\n", ofs);
453     ptr = pStubMsg->Memory;
454     break;
455   case RPC_FC_TOP_LEVEL_CONFORMANCE:
456     TRACE("toplevel conformance, ofs=%d\n", ofs);
457     if (pStubMsg->StackTop) {
458       ptr = pStubMsg->StackTop;
459     }
460     else {
461       /* -Os mode, *pCount is already set */
462       goto finish_conf;
463     }
464     break;
465   case RPC_FC_CONSTANT_CONFORMANCE:
466     data = ofs | ((DWORD)pFormat[1] << 16);
467     TRACE("constant conformance, val=%d\n", data);
468     *pCount = data;
469     goto finish_conf;
470   case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
471     FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
472     if (pStubMsg->StackTop) {
473       ptr = pStubMsg->StackTop;
474     }
475     else {
476       /* ? */
477       goto done_conf_grab;
478     }
479     break;
480   default:
481     FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
482   }
483
484   switch (pFormat[1]) {
485   case RPC_FC_DEREFERENCE:
486     ptr = *(LPVOID*)((char *)ptr + ofs);
487     break;
488   case RPC_FC_CALLBACK:
489   {
490     unsigned char *old_stack_top = pStubMsg->StackTop;
491     pStubMsg->StackTop = ptr;
492
493     /* ofs is index into StubDesc->apfnExprEval */
494     TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
495     pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
496
497     pStubMsg->StackTop = old_stack_top;
498
499     /* the callback function always stores the computed value in MaxCount */
500     *pCount = pStubMsg->MaxCount;
501     goto finish_conf;
502   }
503   default:
504     ptr = (char *)ptr + ofs;
505     break;
506   }
507
508   switch (dtype) {
509   case RPC_FC_LONG:
510   case RPC_FC_ULONG:
511     data = *(DWORD*)ptr;
512     break;
513   case RPC_FC_SHORT:
514     data = *(SHORT*)ptr;
515     break;
516   case RPC_FC_USHORT:
517     data = *(USHORT*)ptr;
518     break;
519   case RPC_FC_CHAR:
520   case RPC_FC_SMALL:
521     data = *(CHAR*)ptr;
522     break;
523   case RPC_FC_BYTE:
524   case RPC_FC_USMALL:
525     data = *(UCHAR*)ptr;
526     break;
527   default:
528     FIXME("unknown conformance data type %x\n", dtype);
529     goto done_conf_grab;
530   }
531   TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
532
533 done_conf_grab:
534   switch (pFormat[1]) {
535   case RPC_FC_DEREFERENCE: /* already handled */
536   case 0: /* no op */
537     *pCount = data;
538     break;
539   case RPC_FC_ADD_1:
540     *pCount = data + 1;
541     break;
542   case RPC_FC_SUB_1:
543     *pCount = data - 1;
544     break;
545   case RPC_FC_MULT_2:
546     *pCount = data * 2;
547     break;
548   case RPC_FC_DIV_2:
549     *pCount = data / 2;
550     break;
551   default:
552     FIXME("unknown conformance op %d\n", pFormat[1]);
553     goto finish_conf;
554   }
555
556 finish_conf:
557   TRACE("resulting conformance is %ld\n", *pCount);
558   if (pStubMsg->fHasNewCorrDesc)
559     return pFormat+6;
560   else
561     return pFormat+4;
562 }
563
564 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
565  * the result overflows 32-bits */
566 static inline ULONG safe_multiply(ULONG a, ULONG b)
567 {
568     ULONGLONG ret = (ULONGLONG)a * b;
569     if (ret > 0xffffffff)
570     {
571         RpcRaiseException(RPC_S_INVALID_BOUND);
572         return 0;
573     }
574     return ret;
575 }
576
577 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
578 {
579     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
580         (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
581         RpcRaiseException(RPC_X_BAD_STUB_DATA);
582     pStubMsg->Buffer += size;
583 }
584
585 /* copies data from the buffer, checking that there is enough data in the buffer
586  * to do so */
587 static inline void safe_buffer_copy(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
588 {
589     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
590         (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
591         RpcRaiseException(RPC_X_BAD_STUB_DATA);
592     memcpy(p, pStubMsg->Buffer, size);
593     pStubMsg->Buffer += size;
594 }
595
596 /*
597  * NdrConformantString:
598  * 
599  * What MS calls a ConformantString is, in DCE terminology,
600  * a Varying-Conformant String.
601  * [
602  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
603  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
604  *           into unmarshalled string) 
605  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
606  *   [ 
607  *     data: CHARTYPE[maxlen]
608  *   ] 
609  * ], where CHARTYPE is the appropriate character type (specified externally)
610  *
611  */
612
613 /***********************************************************************
614  *            NdrConformantStringMarshall [RPCRT4.@]
615  */
616 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
617   unsigned char *pszMessage, PFORMAT_STRING pFormat)
618
619   ULONG esize, size;
620
621   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
622   
623   if (*pFormat == RPC_FC_C_CSTRING) {
624     TRACE("string=%s\n", debugstr_a((char*)pszMessage));
625     pStubMsg->ActualCount = strlen((char*)pszMessage)+1;
626     esize = 1;
627   }
628   else if (*pFormat == RPC_FC_C_WSTRING) {
629     TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
630     pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1;
631     esize = 2;
632   }
633   else {
634     ERR("Unhandled string type: %#x\n", *pFormat); 
635     /* FIXME: raise an exception. */
636     return NULL;
637   }
638
639   if (pFormat[1] == RPC_FC_STRING_SIZED)
640     pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0);
641   else
642     pStubMsg->MaxCount = pStubMsg->ActualCount;
643   pStubMsg->Offset = 0;
644   WriteConformance(pStubMsg);
645   WriteVariance(pStubMsg);
646
647   size = safe_multiply(esize, pStubMsg->ActualCount);
648   memcpy(pStubMsg->Buffer, pszMessage, size); /* the string itself */
649   pStubMsg->Buffer += size;
650
651   STD_OVERFLOW_CHECK(pStubMsg);
652
653   /* success */
654   return NULL; /* is this always right? */
655 }
656
657 /***********************************************************************
658  *           NdrConformantStringBufferSize [RPCRT4.@]
659  */
660 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
661   unsigned char* pMemory, PFORMAT_STRING pFormat)
662 {
663   ULONG esize;
664
665   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
666
667   SizeConformance(pStubMsg);
668   SizeVariance(pStubMsg);
669
670   if (*pFormat == RPC_FC_C_CSTRING) {
671     TRACE("string=%s\n", debugstr_a((char*)pMemory));
672     pStubMsg->ActualCount = strlen((char*)pMemory)+1;
673     esize = 1;
674   }
675   else if (*pFormat == RPC_FC_C_WSTRING) {
676     TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
677     pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1;
678     esize = 2;
679   }
680   else {
681     ERR("Unhandled string type: %#x\n", *pFormat); 
682     /* FIXME: raise an exception */
683     return;
684   }
685
686   if (pFormat[1] == RPC_FC_STRING_SIZED)
687     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
688   else
689     pStubMsg->MaxCount = pStubMsg->ActualCount;
690
691   pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
692 }
693
694 /************************************************************************
695  *            NdrConformantStringMemorySize [RPCRT4.@]
696  */
697 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
698   PFORMAT_STRING pFormat )
699 {
700   ULONG rslt = 0;
701
702   FIXME("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
703
704   assert(pStubMsg && pFormat);
705
706   if (*pFormat == RPC_FC_C_CSTRING) {
707     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
708   }
709   else if (*pFormat == RPC_FC_C_WSTRING) {
710     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */
711   }
712   else {
713     ERR("Unhandled string type: %#x\n", *pFormat);
714     /* FIXME: raise an exception */
715   }
716
717   if (pFormat[1] != RPC_FC_PAD) {
718     FIXME("sized string format=%d\n", pFormat[1]);
719   }
720
721   TRACE("  --> %u\n", rslt);
722   return rslt;
723 }
724
725 /************************************************************************
726  *           NdrConformantStringUnmarshall [RPCRT4.@]
727  */
728 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
729   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
730 {
731   ULONG bufsize, memsize, esize, i;
732
733   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
734     pStubMsg, *ppMemory, pFormat, fMustAlloc);
735
736   assert(pFormat && ppMemory && pStubMsg);
737
738   ReadConformance(pStubMsg, NULL);
739   ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
740
741   if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
742   else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
743   else {
744     ERR("Unhandled string type: %#x\n", *pFormat);
745     /* FIXME: raise an exception */
746     esize = 0;
747   }
748
749   memsize = safe_multiply(esize, pStubMsg->MaxCount);
750   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
751
752   /* strings must always have null terminating bytes */
753   if (bufsize < esize)
754   {
755     ERR("invalid string length of %d\n", pStubMsg->ActualCount);
756     RpcRaiseException(RPC_S_INVALID_BOUND);
757     return NULL;
758   }
759
760   /* verify the buffer is safe to access */
761   if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
762       (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
763   {
764     ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
765         pStubMsg->BufferEnd, pStubMsg->Buffer);
766     RpcRaiseException(RPC_X_BAD_STUB_DATA);
767     return NULL;
768   }
769
770   for (i = bufsize - esize; i < bufsize; i++)
771     if (pStubMsg->Buffer[i] != 0)
772     {
773       ERR("string not null-terminated at byte position %d, data is 0x%x\n",
774         i, pStubMsg->Buffer[i]);
775       RpcRaiseException(RPC_S_INVALID_BOUND);
776       return NULL;
777     }
778
779   if (fMustAlloc || !*ppMemory)
780     *ppMemory = NdrAllocate(pStubMsg, memsize);
781
782   safe_buffer_copy(pStubMsg, *ppMemory, bufsize);
783
784   if (*pFormat == RPC_FC_C_CSTRING) {
785     TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
786   }
787   else if (*pFormat == RPC_FC_C_WSTRING) {
788     TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
789   }
790
791   return NULL; /* FIXME: is this always right? */
792 }
793
794 /***********************************************************************
795  *           NdrNonConformantStringMarshall [RPCRT4.@]
796  */
797 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
798                                 unsigned char *pMemory,
799                                 PFORMAT_STRING pFormat)
800 {
801     FIXME("stub\n");
802     return NULL;
803 }
804
805 /***********************************************************************
806  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
807  */
808 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
809                                 unsigned char **ppMemory,
810                                 PFORMAT_STRING pFormat,
811                                 unsigned char fMustAlloc)
812 {
813     FIXME("stub\n");
814     return NULL;
815 }
816
817 /***********************************************************************
818  *           NdrNonConformantStringBufferSize [RPCRT4.@]
819  */
820 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
821                                 unsigned char *pMemory,
822                                 PFORMAT_STRING pFormat)
823 {
824     FIXME("stub\n");
825 }
826
827 /***********************************************************************
828  *           NdrNonConformantStringMemorySize [RPCRT4.@]
829  */
830 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
831                                 PFORMAT_STRING pFormat)
832 {
833     FIXME("stub\n");
834     return 0;
835 }
836
837 static inline void dump_pointer_attr(unsigned char attr)
838 {
839     if (attr & RPC_FC_P_ALLOCALLNODES)
840         TRACE(" RPC_FC_P_ALLOCALLNODES");
841     if (attr & RPC_FC_P_DONTFREE)
842         TRACE(" RPC_FC_P_DONTFREE");
843     if (attr & RPC_FC_P_ONSTACK)
844         TRACE(" RPC_FC_P_ONSTACK");
845     if (attr & RPC_FC_P_SIMPLEPOINTER)
846         TRACE(" RPC_FC_P_SIMPLEPOINTER");
847     if (attr & RPC_FC_P_DEREF)
848         TRACE(" RPC_FC_P_DEREF");
849     TRACE("\n");
850 }
851
852 /***********************************************************************
853  *           PointerMarshall [internal]
854  */
855 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
856                             unsigned char *Buffer,
857                             unsigned char *Pointer,
858                             PFORMAT_STRING pFormat)
859 {
860   unsigned type = pFormat[0], attr = pFormat[1];
861   PFORMAT_STRING desc;
862   NDR_MARSHALL m;
863   ULONG pointer_id;
864   int pointer_needs_marshaling;
865
866   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
867   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
868   pFormat += 2;
869   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
870   else desc = pFormat + *(const SHORT*)pFormat;
871
872   switch (type) {
873   case RPC_FC_RP: /* ref pointer (always non-null) */
874 #if 0 /* this causes problems for InstallShield so is disabled - we need more tests */
875     if (!Pointer)
876       RpcRaiseException(RPC_X_NULL_REF_POINTER);
877 #endif
878     pointer_needs_marshaling = 1;
879     break;
880   case RPC_FC_UP: /* unique pointer */
881   case RPC_FC_OP: /* object pointer - same as unique here */
882     if (Pointer)
883       pointer_needs_marshaling = 1;
884     else
885       pointer_needs_marshaling = 0;
886     pointer_id = (ULONG)Pointer;
887     TRACE("writing 0x%08x to buffer\n", pointer_id);
888     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
889     break;
890   case RPC_FC_FP:
891     pointer_needs_marshaling = !NdrFullPointerQueryPointer(
892       pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
893     TRACE("writing 0x%08x to buffer\n", pointer_id);
894     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
895     break;
896   default:
897     FIXME("unhandled ptr type=%02x\n", type);
898     RpcRaiseException(RPC_X_BAD_STUB_DATA);
899     return;
900   }
901
902   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
903
904   if (pointer_needs_marshaling) {
905     if (attr & RPC_FC_P_DEREF) {
906       Pointer = *(unsigned char**)Pointer;
907       TRACE("deref => %p\n", Pointer);
908     }
909     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
910     if (m) m(pStubMsg, Pointer, desc);
911     else FIXME("no marshaller for data type=%02x\n", *desc);
912   }
913
914   STD_OVERFLOW_CHECK(pStubMsg);
915 }
916
917 /***********************************************************************
918  *           PointerUnmarshall [internal]
919  */
920 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
921                               unsigned char *Buffer,
922                               unsigned char **pPointer,
923                               PFORMAT_STRING pFormat,
924                               unsigned char fMustAlloc)
925 {
926   unsigned type = pFormat[0], attr = pFormat[1];
927   PFORMAT_STRING desc;
928   NDR_UNMARSHALL m;
929   DWORD pointer_id = 0;
930   int pointer_needs_unmarshaling;
931
932   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc);
933   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
934   pFormat += 2;
935   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
936   else desc = pFormat + *(const SHORT*)pFormat;
937
938   switch (type) {
939   case RPC_FC_RP: /* ref pointer (always non-null) */
940     pointer_needs_unmarshaling = 1;
941     break;
942   case RPC_FC_UP: /* unique pointer */
943     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
944     TRACE("pointer_id is 0x%08x\n", pointer_id);
945     if (pointer_id)
946       pointer_needs_unmarshaling = 1;
947     else {
948       *pPointer = NULL;
949       pointer_needs_unmarshaling = 0;
950     }
951     break;
952   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
953     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
954     TRACE("pointer_id is 0x%08x\n", pointer_id);
955     if (!fMustAlloc && *pPointer)
956     {
957         FIXME("free object pointer %p\n", *pPointer);
958         *pPointer = NULL;
959     }
960     if (pointer_id)
961       pointer_needs_unmarshaling = 1;
962     else
963       pointer_needs_unmarshaling = 0;
964     break;
965   case RPC_FC_FP:
966     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
967     TRACE("pointer_id is 0x%08x\n", pointer_id);
968     pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
969       pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
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 (pointer_needs_unmarshaling) {
978     if (attr & RPC_FC_P_DEREF) {
979       if (!*pPointer || fMustAlloc) {
980         *pPointer = NdrAllocate(pStubMsg, sizeof(void *));
981         *(unsigned char**) *pPointer = NULL;
982       }
983       pPointer = *(unsigned char***)pPointer;
984       TRACE("deref => %p\n", pPointer);
985     }
986     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
987     if (m) m(pStubMsg, pPointer, desc, fMustAlloc);
988     else FIXME("no unmarshaller for data type=%02x\n", *desc);
989
990     if (type == RPC_FC_FP)
991       NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
992                                 *pPointer);
993   }
994
995   TRACE("pointer=%p\n", *pPointer);
996 }
997
998 /***********************************************************************
999  *           PointerBufferSize [internal]
1000  */
1001 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1002                               unsigned char *Pointer,
1003                               PFORMAT_STRING pFormat)
1004 {
1005   unsigned type = pFormat[0], attr = pFormat[1];
1006   PFORMAT_STRING desc;
1007   NDR_BUFFERSIZE m;
1008   int pointer_needs_sizing;
1009   ULONG pointer_id;
1010
1011   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1012   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1013   pFormat += 2;
1014   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1015   else desc = pFormat + *(const SHORT*)pFormat;
1016
1017   switch (type) {
1018   case RPC_FC_RP: /* ref pointer (always non-null) */
1019     break;
1020   case RPC_FC_OP:
1021   case RPC_FC_UP:
1022     /* NULL pointer has no further representation */
1023     if (!Pointer)
1024         return;
1025     break;
1026   case RPC_FC_FP:
1027     pointer_needs_sizing = !NdrFullPointerQueryPointer(
1028       pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1029     if (!pointer_needs_sizing)
1030       return;
1031     break;
1032   default:
1033     FIXME("unhandled ptr type=%02x\n", type);
1034     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1035     return;
1036   }
1037
1038   if (attr & RPC_FC_P_DEREF) {
1039     Pointer = *(unsigned char**)Pointer;
1040     TRACE("deref => %p\n", Pointer);
1041   }
1042
1043   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1044   if (m) m(pStubMsg, Pointer, desc);
1045   else FIXME("no buffersizer for data type=%02x\n", *desc);
1046 }
1047
1048 /***********************************************************************
1049  *           PointerMemorySize [internal]
1050  */
1051 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1052                                        unsigned char *Buffer,
1053                                        PFORMAT_STRING pFormat)
1054 {
1055   unsigned type = pFormat[0], attr = pFormat[1];
1056   PFORMAT_STRING desc;
1057   NDR_MEMORYSIZE m;
1058
1059   FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat);
1060   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1061   pFormat += 2;
1062   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1063   else desc = pFormat + *(const SHORT*)pFormat;
1064
1065   switch (type) {
1066   case RPC_FC_RP: /* ref pointer (always non-null) */
1067     break;
1068   default:
1069     FIXME("unhandled ptr type=%02x\n", type);
1070     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1071   }
1072
1073   if (attr & RPC_FC_P_DEREF) {
1074     TRACE("deref\n");
1075   }
1076
1077   m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1078   if (m) m(pStubMsg, desc);
1079   else FIXME("no memorysizer for data type=%02x\n", *desc);
1080
1081   return 0;
1082 }
1083
1084 /***********************************************************************
1085  *           PointerFree [internal]
1086  */
1087 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1088                         unsigned char *Pointer,
1089                         PFORMAT_STRING pFormat)
1090 {
1091   unsigned type = pFormat[0], attr = pFormat[1];
1092   PFORMAT_STRING desc;
1093   NDR_FREE m;
1094
1095   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1096   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1097   if (attr & RPC_FC_P_DONTFREE) return;
1098   pFormat += 2;
1099   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1100   else desc = pFormat + *(const SHORT*)pFormat;
1101
1102   if (!Pointer) return;
1103
1104   if (type == RPC_FC_FP) {
1105     int pointer_needs_freeing = NdrFullPointerFree(
1106       pStubMsg->FullPtrXlatTables, Pointer);
1107     if (!pointer_needs_freeing)
1108       return;
1109   }
1110
1111   if (attr & RPC_FC_P_DEREF) {
1112     Pointer = *(unsigned char**)Pointer;
1113     TRACE("deref => %p\n", Pointer);
1114   }
1115
1116   m = NdrFreer[*desc & NDR_TABLE_MASK];
1117   if (m) m(pStubMsg, Pointer, desc);
1118
1119   /* hmm... is this sensible?
1120    * perhaps we should check if the memory comes from NdrAllocate,
1121    * and deallocate only if so - checking if the pointer is between
1122    * BufferStart and BufferEnd is probably no good since the buffer
1123    * may be reallocated when the server wants to marshal the reply */
1124   switch (*desc) {
1125   case RPC_FC_BOGUS_STRUCT:
1126   case RPC_FC_BOGUS_ARRAY:
1127   case RPC_FC_USER_MARSHAL:
1128   case RPC_FC_CARRAY:
1129   case RPC_FC_CVARRAY:
1130     break;
1131   default:
1132     FIXME("unhandled data type=%02x\n", *desc);
1133     break;
1134   case RPC_FC_C_CSTRING:
1135   case RPC_FC_C_WSTRING:
1136     if (pStubMsg->ReuseBuffer) goto notfree;
1137     break;
1138   case RPC_FC_IP:
1139     goto notfree;
1140   }
1141
1142   if (attr & RPC_FC_P_ONSTACK) {
1143     TRACE("not freeing stack ptr %p\n", Pointer);
1144     return;
1145   }
1146   TRACE("freeing %p\n", Pointer);
1147   NdrFree(pStubMsg, Pointer);
1148   return;
1149 notfree:
1150   TRACE("not freeing %p\n", Pointer);
1151 }
1152
1153 /***********************************************************************
1154  *           EmbeddedPointerMarshall
1155  */
1156 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1157                                                unsigned char *pMemory,
1158                                                PFORMAT_STRING pFormat)
1159 {
1160   unsigned char *Mark = pStubMsg->BufferMark;
1161   unsigned rep, count, stride;
1162   unsigned i;
1163   unsigned char *saved_buffer = NULL;
1164
1165   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1166
1167   if (*pFormat != RPC_FC_PP) return NULL;
1168   pFormat += 2;
1169
1170   if (pStubMsg->PointerBufferMark)
1171   {
1172     saved_buffer = pStubMsg->Buffer;
1173     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1174     pStubMsg->PointerBufferMark = NULL;
1175   }
1176
1177   while (pFormat[0] != RPC_FC_END) {
1178     switch (pFormat[0]) {
1179     default:
1180       FIXME("unknown repeat type %d\n", pFormat[0]);
1181     case RPC_FC_NO_REPEAT:
1182       rep = 1;
1183       stride = 0;
1184       count = 1;
1185       pFormat += 2;
1186       break;
1187     case RPC_FC_FIXED_REPEAT:
1188       rep = *(const WORD*)&pFormat[2];
1189       stride = *(const WORD*)&pFormat[4];
1190       count = *(const WORD*)&pFormat[8];
1191       pFormat += 10;
1192       break;
1193     case RPC_FC_VARIABLE_REPEAT:
1194       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1195       stride = *(const WORD*)&pFormat[2];
1196       count = *(const WORD*)&pFormat[6];
1197       pFormat += 8;
1198       break;
1199     }
1200     for (i = 0; i < rep; i++) {
1201       PFORMAT_STRING info = pFormat;
1202       unsigned char *membase = pMemory + (i * stride);
1203       unsigned char *bufbase = Mark + (i * stride);
1204       unsigned u;
1205
1206       for (u=0; u<count; u++,info+=8) {
1207         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1208         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1209         unsigned char *saved_memory = pStubMsg->Memory;
1210
1211         pStubMsg->Memory = pMemory;
1212         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1213         pStubMsg->Memory = saved_memory;
1214       }
1215     }
1216     pFormat += 8 * count;
1217   }
1218
1219   if (saved_buffer)
1220   {
1221     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1222     pStubMsg->Buffer = saved_buffer;
1223   }
1224
1225   STD_OVERFLOW_CHECK(pStubMsg);
1226
1227   return NULL;
1228 }
1229
1230 /***********************************************************************
1231  *           EmbeddedPointerUnmarshall
1232  */
1233 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1234                                                  unsigned char **ppMemory,
1235                                                  PFORMAT_STRING pFormat,
1236                                                  unsigned char fMustAlloc)
1237 {
1238   unsigned char *Mark = pStubMsg->BufferMark;
1239   unsigned rep, count, stride;
1240   unsigned i;
1241   unsigned char *saved_buffer = NULL;
1242
1243   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1244
1245   if (*pFormat != RPC_FC_PP) return NULL;
1246   pFormat += 2;
1247
1248   if (pStubMsg->PointerBufferMark)
1249   {
1250     saved_buffer = pStubMsg->Buffer;
1251     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1252     pStubMsg->PointerBufferMark = NULL;
1253   }
1254
1255   while (pFormat[0] != RPC_FC_END) {
1256     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1257     switch (pFormat[0]) {
1258     default:
1259       FIXME("unknown repeat type %d\n", pFormat[0]);
1260     case RPC_FC_NO_REPEAT:
1261       rep = 1;
1262       stride = 0;
1263       count = 1;
1264       pFormat += 2;
1265       break;
1266     case RPC_FC_FIXED_REPEAT:
1267       rep = *(const WORD*)&pFormat[2];
1268       stride = *(const WORD*)&pFormat[4];
1269       count = *(const WORD*)&pFormat[8];
1270       pFormat += 10;
1271       break;
1272     case RPC_FC_VARIABLE_REPEAT:
1273       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1274       stride = *(const WORD*)&pFormat[2];
1275       count = *(const WORD*)&pFormat[6];
1276       pFormat += 8;
1277       break;
1278     }
1279     for (i = 0; i < rep; i++) {
1280       PFORMAT_STRING info = pFormat;
1281       unsigned char *membase = *ppMemory + (i * stride);
1282       unsigned char *bufbase = Mark + (i * stride);
1283       unsigned u;
1284
1285       for (u=0; u<count; u++,info+=8) {
1286         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1287         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1288         PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, TRUE);
1289       }
1290     }
1291     pFormat += 8 * count;
1292   }
1293
1294   if (saved_buffer)
1295   {
1296     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1297     pStubMsg->Buffer = saved_buffer;
1298   }
1299
1300   return NULL;
1301 }
1302
1303 /***********************************************************************
1304  *           EmbeddedPointerBufferSize
1305  */
1306 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1307                                       unsigned char *pMemory,
1308                                       PFORMAT_STRING pFormat)
1309 {
1310   unsigned rep, count, stride;
1311   unsigned i;
1312   ULONG saved_buffer_length = 0;
1313
1314   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1315
1316   if (pStubMsg->IgnoreEmbeddedPointers) return;
1317
1318   if (*pFormat != RPC_FC_PP) return;
1319   pFormat += 2;
1320
1321   if (pStubMsg->PointerLength)
1322   {
1323     saved_buffer_length = pStubMsg->BufferLength;
1324     pStubMsg->BufferLength = pStubMsg->PointerLength;
1325     pStubMsg->PointerLength = 0;
1326   }
1327
1328   while (pFormat[0] != RPC_FC_END) {
1329     switch (pFormat[0]) {
1330     default:
1331       FIXME("unknown repeat type %d\n", pFormat[0]);
1332     case RPC_FC_NO_REPEAT:
1333       rep = 1;
1334       stride = 0;
1335       count = 1;
1336       pFormat += 2;
1337       break;
1338     case RPC_FC_FIXED_REPEAT:
1339       rep = *(const WORD*)&pFormat[2];
1340       stride = *(const WORD*)&pFormat[4];
1341       count = *(const WORD*)&pFormat[8];
1342       pFormat += 10;
1343       break;
1344     case RPC_FC_VARIABLE_REPEAT:
1345       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1346       stride = *(const WORD*)&pFormat[2];
1347       count = *(const WORD*)&pFormat[6];
1348       pFormat += 8;
1349       break;
1350     }
1351     for (i = 0; i < rep; i++) {
1352       PFORMAT_STRING info = pFormat;
1353       unsigned char *membase = pMemory + (i * stride);
1354       unsigned u;
1355
1356       for (u=0; u<count; u++,info+=8) {
1357         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1358         unsigned char *saved_memory = pStubMsg->Memory;
1359
1360         pStubMsg->Memory = pMemory;
1361         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1362         pStubMsg->Memory = saved_memory;
1363       }
1364     }
1365     pFormat += 8 * count;
1366   }
1367
1368   if (saved_buffer_length)
1369   {
1370     pStubMsg->PointerLength = pStubMsg->BufferLength;
1371     pStubMsg->BufferLength = saved_buffer_length;
1372   }
1373 }
1374
1375 /***********************************************************************
1376  *           EmbeddedPointerMemorySize [internal]
1377  */
1378 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1379                                                PFORMAT_STRING pFormat)
1380 {
1381   unsigned char *Mark = pStubMsg->BufferMark;
1382   unsigned rep, count, stride;
1383   unsigned i;
1384
1385   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1386
1387   if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1388
1389   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1390
1391   if (*pFormat != RPC_FC_PP) return 0;
1392   pFormat += 2;
1393
1394   while (pFormat[0] != RPC_FC_END) {
1395     switch (pFormat[0]) {
1396     default:
1397       FIXME("unknown repeat type %d\n", pFormat[0]);
1398     case RPC_FC_NO_REPEAT:
1399       rep = 1;
1400       stride = 0;
1401       count = 1;
1402       pFormat += 2;
1403       break;
1404     case RPC_FC_FIXED_REPEAT:
1405       rep = *(const WORD*)&pFormat[2];
1406       stride = *(const WORD*)&pFormat[4];
1407       count = *(const WORD*)&pFormat[8];
1408       pFormat += 10;
1409       break;
1410     case RPC_FC_VARIABLE_REPEAT:
1411       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1412       stride = *(const WORD*)&pFormat[2];
1413       count = *(const WORD*)&pFormat[6];
1414       pFormat += 8;
1415       break;
1416     }
1417     for (i = 0; i < rep; i++) {
1418       PFORMAT_STRING info = pFormat;
1419       unsigned char *bufbase = Mark + (i * stride);
1420       unsigned u;
1421       for (u=0; u<count; u++,info+=8) {
1422         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1423         PointerMemorySize(pStubMsg, bufptr, info+4);
1424       }
1425     }
1426     pFormat += 8 * count;
1427   }
1428
1429   return 0;
1430 }
1431
1432 /***********************************************************************
1433  *           EmbeddedPointerFree [internal]
1434  */
1435 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1436                                 unsigned char *pMemory,
1437                                 PFORMAT_STRING pFormat)
1438 {
1439   unsigned rep, count, stride;
1440   unsigned i;
1441
1442   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1443   if (*pFormat != RPC_FC_PP) return;
1444   pFormat += 2;
1445
1446   while (pFormat[0] != RPC_FC_END) {
1447     switch (pFormat[0]) {
1448     default:
1449       FIXME("unknown repeat type %d\n", pFormat[0]);
1450     case RPC_FC_NO_REPEAT:
1451       rep = 1;
1452       stride = 0;
1453       count = 1;
1454       pFormat += 2;
1455       break;
1456     case RPC_FC_FIXED_REPEAT:
1457       rep = *(const WORD*)&pFormat[2];
1458       stride = *(const WORD*)&pFormat[4];
1459       count = *(const WORD*)&pFormat[8];
1460       pFormat += 10;
1461       break;
1462     case RPC_FC_VARIABLE_REPEAT:
1463       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1464       stride = *(const WORD*)&pFormat[2];
1465       count = *(const WORD*)&pFormat[6];
1466       pFormat += 8;
1467       break;
1468     }
1469     for (i = 0; i < rep; i++) {
1470       PFORMAT_STRING info = pFormat;
1471       unsigned char *membase = pMemory + (i * stride);
1472       unsigned u;
1473
1474       for (u=0; u<count; u++,info+=8) {
1475         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1476         unsigned char *saved_memory = pStubMsg->Memory;
1477
1478         pStubMsg->Memory = pMemory;
1479         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1480         pStubMsg->Memory = saved_memory;
1481       }
1482     }
1483     pFormat += 8 * count;
1484   }
1485 }
1486
1487 /***********************************************************************
1488  *           NdrPointerMarshall [RPCRT4.@]
1489  */
1490 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1491                                           unsigned char *pMemory,
1492                                           PFORMAT_STRING pFormat)
1493 {
1494   unsigned char *Buffer;
1495
1496   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1497
1498   /* incremement the buffer here instead of in PointerMarshall,
1499    * as that is used by embedded pointers which already handle the incrementing
1500    * the buffer, and shouldn't write any additional pointer data to the wire */
1501   if (*pFormat != RPC_FC_RP)
1502   {
1503     ALIGN_POINTER(pStubMsg->Buffer, 4);
1504     Buffer = pStubMsg->Buffer;
1505     pStubMsg->Buffer += 4;
1506   }
1507   else
1508     Buffer = pStubMsg->Buffer;
1509
1510   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1511
1512   STD_OVERFLOW_CHECK(pStubMsg);
1513
1514   return NULL;
1515 }
1516
1517 /***********************************************************************
1518  *           NdrPointerUnmarshall [RPCRT4.@]
1519  */
1520 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1521                                             unsigned char **ppMemory,
1522                                             PFORMAT_STRING pFormat,
1523                                             unsigned char fMustAlloc)
1524 {
1525   unsigned char *Buffer;
1526
1527   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1528
1529   /* incremement the buffer here instead of in PointerUnmarshall,
1530    * as that is used by embedded pointers which already handle the incrementing
1531    * the buffer, and shouldn't read any additional pointer data from the
1532    * buffer */
1533   if (*pFormat != RPC_FC_RP)
1534   {
1535     ALIGN_POINTER(pStubMsg->Buffer, 4);
1536     Buffer = pStubMsg->Buffer;
1537     safe_buffer_increment(pStubMsg, 4);
1538   }
1539   else
1540     Buffer = pStubMsg->Buffer;
1541
1542   PointerUnmarshall(pStubMsg, Buffer, ppMemory, pFormat, fMustAlloc);
1543
1544   return NULL;
1545 }
1546
1547 /***********************************************************************
1548  *           NdrPointerBufferSize [RPCRT4.@]
1549  */
1550 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1551                                       unsigned char *pMemory,
1552                                       PFORMAT_STRING pFormat)
1553 {
1554   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1555
1556   /* incremement the buffer length here instead of in PointerBufferSize,
1557    * as that is used by embedded pointers which already handle the buffer
1558    * length, and shouldn't write anything more to the wire */
1559   if (*pFormat != RPC_FC_RP)
1560   {
1561     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1562     pStubMsg->BufferLength += 4;
1563   }
1564
1565   PointerBufferSize(pStubMsg, pMemory, pFormat);
1566 }
1567
1568 /***********************************************************************
1569  *           NdrPointerMemorySize [RPCRT4.@]
1570  */
1571 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1572                                   PFORMAT_STRING pFormat)
1573 {
1574   /* unsigned size = *(LPWORD)(pFormat+2); */
1575   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1576   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1577   return 0;
1578 }
1579
1580 /***********************************************************************
1581  *           NdrPointerFree [RPCRT4.@]
1582  */
1583 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1584                            unsigned char *pMemory,
1585                            PFORMAT_STRING pFormat)
1586 {
1587   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1588   PointerFree(pStubMsg, pMemory, pFormat);
1589 }
1590
1591 /***********************************************************************
1592  *           NdrSimpleTypeMarshall [RPCRT4.@]
1593  */
1594 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1595                                    unsigned char FormatChar )
1596 {
1597     NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1598 }
1599
1600 /***********************************************************************
1601  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
1602  */
1603 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1604                                      unsigned char FormatChar )
1605 {
1606     NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0);
1607 }
1608
1609 /***********************************************************************
1610  *           NdrSimpleStructMarshall [RPCRT4.@]
1611  */
1612 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1613                                                unsigned char *pMemory,
1614                                                PFORMAT_STRING pFormat)
1615 {
1616   unsigned size = *(const WORD*)(pFormat+2);
1617   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1618
1619   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1620
1621   memcpy(pStubMsg->Buffer, pMemory, size);
1622   pStubMsg->BufferMark = pStubMsg->Buffer;
1623   pStubMsg->Buffer += size;
1624
1625   if (pFormat[0] != RPC_FC_STRUCT)
1626     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1627
1628   STD_OVERFLOW_CHECK(pStubMsg);
1629
1630   return NULL;
1631 }
1632
1633 /***********************************************************************
1634  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1635  */
1636 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1637                                                  unsigned char **ppMemory,
1638                                                  PFORMAT_STRING pFormat,
1639                                                  unsigned char fMustAlloc)
1640 {
1641   unsigned size = *(const WORD*)(pFormat+2);
1642   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1643
1644   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1645
1646   if (fMustAlloc) {
1647     *ppMemory = NdrAllocate(pStubMsg, size);
1648     memcpy(*ppMemory, pStubMsg->Buffer, size);
1649   } else {
1650     if (!pStubMsg->IsClient && !*ppMemory)
1651       /* for servers, we just point straight into the RPC buffer */
1652       *ppMemory = pStubMsg->Buffer;
1653     else
1654       /* for clients, memory should be provided by caller */
1655       memcpy(*ppMemory, pStubMsg->Buffer, size);
1656   }
1657
1658   pStubMsg->BufferMark = pStubMsg->Buffer;
1659   pStubMsg->Buffer += size;
1660
1661   if (pFormat[0] != RPC_FC_STRUCT)
1662     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1663
1664   return NULL;
1665 }
1666
1667 /***********************************************************************
1668  *           NdrSimpleStructBufferSize [RPCRT4.@]
1669  */
1670 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1671                                       unsigned char *pMemory,
1672                                       PFORMAT_STRING pFormat)
1673 {
1674   unsigned size = *(const WORD*)(pFormat+2);
1675   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1676
1677   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1678
1679   pStubMsg->BufferLength += size;
1680   if (pFormat[0] != RPC_FC_STRUCT)
1681     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1682 }
1683
1684 /***********************************************************************
1685  *           NdrSimpleStructMemorySize [RPCRT4.@]
1686  */
1687 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1688                                        PFORMAT_STRING pFormat)
1689 {
1690   unsigned short size = *(const WORD *)(pFormat+2);
1691
1692   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1693
1694   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1695   pStubMsg->MemorySize += size;
1696   pStubMsg->Buffer += size;
1697
1698   if (pFormat[0] != RPC_FC_STRUCT)
1699     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1700   return size;
1701 }
1702
1703 /***********************************************************************
1704  *           NdrSimpleStructFree [RPCRT4.@]
1705  */
1706 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1707                                 unsigned char *pMemory,
1708                                 PFORMAT_STRING pFormat)
1709 {
1710   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1711   if (pFormat[0] != RPC_FC_STRUCT)
1712     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1713 }
1714
1715
1716 static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg,
1717                                          PFORMAT_STRING pFormat)
1718 {
1719   switch (*pFormat) {
1720   case RPC_FC_STRUCT:
1721   case RPC_FC_PSTRUCT:
1722   case RPC_FC_CSTRUCT:
1723   case RPC_FC_BOGUS_STRUCT:
1724   case RPC_FC_SMFARRAY:
1725   case RPC_FC_SMVARRAY:
1726     return *(const WORD*)&pFormat[2];
1727   case RPC_FC_USER_MARSHAL:
1728     return *(const WORD*)&pFormat[4];
1729   case RPC_FC_NON_ENCAPSULATED_UNION:
1730     pFormat += 2;
1731     if (pStubMsg->fHasNewCorrDesc)
1732         pFormat += 6;
1733     else
1734         pFormat += 4;
1735
1736     pFormat += *(const SHORT*)pFormat;
1737     return *(const SHORT*)pFormat;
1738   case RPC_FC_IP:
1739     return sizeof(void *);
1740   default:
1741     FIXME("unhandled embedded type %02x\n", *pFormat);
1742   }
1743   return 0;
1744 }
1745
1746
1747 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1748                                                PFORMAT_STRING pFormat)
1749 {
1750   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1751
1752   if (!m)
1753   {
1754     FIXME("no memorysizer for data type=%02x\n", *pFormat);
1755     return 0;
1756   }
1757
1758   return m(pStubMsg, pFormat);
1759 }
1760
1761
1762 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1763                                        unsigned char *pMemory,
1764                                        PFORMAT_STRING pFormat,
1765                                        PFORMAT_STRING pPointer)
1766 {
1767   PFORMAT_STRING desc;
1768   NDR_MARSHALL m;
1769   unsigned long size;
1770
1771   while (*pFormat != RPC_FC_END) {
1772     switch (*pFormat) {
1773     case RPC_FC_BYTE:
1774     case RPC_FC_CHAR:
1775     case RPC_FC_SMALL:
1776     case RPC_FC_USMALL:
1777       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
1778       memcpy(pStubMsg->Buffer, pMemory, 1);
1779       pStubMsg->Buffer += 1;
1780       pMemory += 1;
1781       break;
1782     case RPC_FC_WCHAR:
1783     case RPC_FC_SHORT:
1784     case RPC_FC_USHORT:
1785       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1786       memcpy(pStubMsg->Buffer, pMemory, 2);
1787       pStubMsg->Buffer += 2;
1788       pMemory += 2;
1789       break;
1790     case RPC_FC_LONG:
1791     case RPC_FC_ULONG:
1792     case RPC_FC_ENUM32:
1793       TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
1794       memcpy(pStubMsg->Buffer, pMemory, 4);
1795       pStubMsg->Buffer += 4;
1796       pMemory += 4;
1797       break;
1798     case RPC_FC_HYPER:
1799       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1800       memcpy(pStubMsg->Buffer, pMemory, 8);
1801       pStubMsg->Buffer += 8;
1802       pMemory += 8;
1803       break;
1804     case RPC_FC_POINTER:
1805     {
1806       unsigned char *saved_buffer;
1807       int pointer_buffer_mark_set = 0;
1808       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1809       saved_buffer = pStubMsg->Buffer;
1810       if (pStubMsg->PointerBufferMark)
1811       {
1812         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1813         pStubMsg->PointerBufferMark = NULL;
1814         pointer_buffer_mark_set = 1;
1815       }
1816       else
1817         pStubMsg->Buffer += 4; /* for pointer ID */
1818       PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
1819       if (pointer_buffer_mark_set)
1820       {
1821         STD_OVERFLOW_CHECK(pStubMsg);
1822         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1823         pStubMsg->Buffer = saved_buffer + 4;
1824       }
1825       pPointer += 4;
1826       pMemory += 4;
1827       break;
1828     }
1829     case RPC_FC_ALIGNM4:
1830       ALIGN_POINTER(pMemory, 4);
1831       break;
1832     case RPC_FC_ALIGNM8:
1833       ALIGN_POINTER(pMemory, 8);
1834       break;
1835     case RPC_FC_STRUCTPAD1:
1836     case RPC_FC_STRUCTPAD2:
1837     case RPC_FC_STRUCTPAD3:
1838     case RPC_FC_STRUCTPAD4:
1839     case RPC_FC_STRUCTPAD5:
1840     case RPC_FC_STRUCTPAD6:
1841     case RPC_FC_STRUCTPAD7:
1842       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1843       break;
1844     case RPC_FC_EMBEDDED_COMPLEX:
1845       pMemory += pFormat[1];
1846       pFormat += 2;
1847       desc = pFormat + *(const SHORT*)pFormat;
1848       size = EmbeddedComplexSize(pStubMsg, desc);
1849       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1850       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1851       if (m)
1852       {
1853         /* for some reason interface pointers aren't generated as
1854          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
1855          * they still need the derefencing treatment that pointers are
1856          * given */
1857         if (*desc == RPC_FC_IP)
1858           m(pStubMsg, *(unsigned char **)pMemory, desc);
1859         else
1860           m(pStubMsg, pMemory, desc);
1861       }
1862       else FIXME("no marshaller for embedded type %02x\n", *desc);
1863       pMemory += size;
1864       pFormat += 2;
1865       continue;
1866     case RPC_FC_PAD:
1867       break;
1868     default:
1869       FIXME("unhandled format 0x%02x\n", *pFormat);
1870     }
1871     pFormat++;
1872   }
1873
1874   return pMemory;
1875 }
1876
1877 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1878                                          unsigned char *pMemory,
1879                                          PFORMAT_STRING pFormat,
1880                                          PFORMAT_STRING pPointer)
1881 {
1882   PFORMAT_STRING desc;
1883   NDR_UNMARSHALL m;
1884   unsigned long size;
1885
1886   while (*pFormat != RPC_FC_END) {
1887     switch (*pFormat) {
1888     case RPC_FC_BYTE:
1889     case RPC_FC_CHAR:
1890     case RPC_FC_SMALL:
1891     case RPC_FC_USMALL:
1892       safe_buffer_copy(pStubMsg, pMemory, 1);
1893       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
1894       pMemory += 1;
1895       break;
1896     case RPC_FC_WCHAR:
1897     case RPC_FC_SHORT:
1898     case RPC_FC_USHORT:
1899       safe_buffer_copy(pStubMsg, pMemory, 2);
1900       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1901       pMemory += 2;
1902       break;
1903     case RPC_FC_LONG:
1904     case RPC_FC_ULONG:
1905     case RPC_FC_ENUM32:
1906       safe_buffer_copy(pStubMsg, pMemory, 4);
1907       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
1908       pMemory += 4;
1909       break;
1910     case RPC_FC_HYPER:
1911       safe_buffer_copy(pStubMsg, pMemory, 8);
1912       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1913       pMemory += 8;
1914       break;
1915     case RPC_FC_POINTER:
1916     {
1917       unsigned char *saved_buffer;
1918       int pointer_buffer_mark_set = 0;
1919       TRACE("pointer => %p\n", pMemory);
1920       ALIGN_POINTER(pStubMsg->Buffer, 4);
1921       saved_buffer = pStubMsg->Buffer;
1922       if (pStubMsg->PointerBufferMark)
1923       {
1924         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1925         pStubMsg->PointerBufferMark = NULL;
1926         pointer_buffer_mark_set = 1;
1927       }
1928       else
1929         pStubMsg->Buffer += 4; /* for pointer ID */
1930
1931       PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, pPointer, TRUE);
1932       if (pointer_buffer_mark_set)
1933       {
1934         STD_OVERFLOW_CHECK(pStubMsg);
1935         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1936         pStubMsg->Buffer = saved_buffer + 4;
1937       }
1938       pPointer += 4;
1939       pMemory += 4;
1940       break;
1941     }
1942     case RPC_FC_ALIGNM4:
1943       ALIGN_POINTER(pMemory, 4);
1944       break;
1945     case RPC_FC_ALIGNM8:
1946       ALIGN_POINTER(pMemory, 8);
1947       break;
1948     case RPC_FC_STRUCTPAD1:
1949     case RPC_FC_STRUCTPAD2:
1950     case RPC_FC_STRUCTPAD3:
1951     case RPC_FC_STRUCTPAD4:
1952     case RPC_FC_STRUCTPAD5:
1953     case RPC_FC_STRUCTPAD6:
1954     case RPC_FC_STRUCTPAD7:
1955       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1956       break;
1957     case RPC_FC_EMBEDDED_COMPLEX:
1958       pMemory += pFormat[1];
1959       pFormat += 2;
1960       desc = pFormat + *(const SHORT*)pFormat;
1961       size = EmbeddedComplexSize(pStubMsg, desc);
1962       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1963       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1964       memset(pMemory, 0, size); /* just in case */
1965       if (m)
1966       {
1967         /* for some reason interface pointers aren't generated as
1968          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
1969          * they still need the derefencing treatment that pointers are
1970          * given */
1971         if (*desc == RPC_FC_IP)
1972           m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
1973         else
1974           m(pStubMsg, &pMemory, desc, FALSE);
1975       }
1976       else FIXME("no unmarshaller 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 char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1992                                          unsigned char *pMemory,
1993                                          PFORMAT_STRING pFormat,
1994                                          PFORMAT_STRING pPointer)
1995 {
1996   PFORMAT_STRING desc;
1997   NDR_BUFFERSIZE m;
1998   unsigned long size;
1999
2000   while (*pFormat != RPC_FC_END) {
2001     switch (*pFormat) {
2002     case RPC_FC_BYTE:
2003     case RPC_FC_CHAR:
2004     case RPC_FC_SMALL:
2005     case RPC_FC_USMALL:
2006       pStubMsg->BufferLength += 1;
2007       pMemory += 1;
2008       break;
2009     case RPC_FC_WCHAR:
2010     case RPC_FC_SHORT:
2011     case RPC_FC_USHORT:
2012       pStubMsg->BufferLength += 2;
2013       pMemory += 2;
2014       break;
2015     case RPC_FC_LONG:
2016     case RPC_FC_ULONG:
2017     case RPC_FC_ENUM32:
2018       pStubMsg->BufferLength += 4;
2019       pMemory += 4;
2020       break;
2021     case RPC_FC_HYPER:
2022       pStubMsg->BufferLength += 8;
2023       pMemory += 8;
2024       break;
2025     case RPC_FC_POINTER:
2026       if (!pStubMsg->IgnoreEmbeddedPointers)
2027       {
2028         int saved_buffer_length = pStubMsg->BufferLength;
2029         pStubMsg->BufferLength = pStubMsg->PointerLength;
2030         pStubMsg->PointerLength = 0;
2031         if(!pStubMsg->BufferLength)
2032           ERR("BufferLength == 0??\n");
2033         PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2034         pStubMsg->PointerLength = pStubMsg->BufferLength;
2035         pStubMsg->BufferLength = saved_buffer_length;
2036       }
2037       pStubMsg->BufferLength += 4;
2038       pPointer += 4;
2039       pMemory += 4;
2040       break;
2041     case RPC_FC_ALIGNM4:
2042       ALIGN_POINTER(pMemory, 4);
2043       break;
2044     case RPC_FC_ALIGNM8:
2045       ALIGN_POINTER(pMemory, 8);
2046       break;
2047     case RPC_FC_STRUCTPAD1:
2048     case RPC_FC_STRUCTPAD2:
2049     case RPC_FC_STRUCTPAD3:
2050     case RPC_FC_STRUCTPAD4:
2051     case RPC_FC_STRUCTPAD5:
2052     case RPC_FC_STRUCTPAD6:
2053     case RPC_FC_STRUCTPAD7:
2054       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2055       break;
2056     case RPC_FC_EMBEDDED_COMPLEX:
2057       pMemory += pFormat[1];
2058       pFormat += 2;
2059       desc = pFormat + *(const SHORT*)pFormat;
2060       size = EmbeddedComplexSize(pStubMsg, desc);
2061       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2062       if (m)
2063       {
2064         /* for some reason interface pointers aren't generated as
2065          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2066          * they still need the derefencing treatment that pointers are
2067          * given */
2068         if (*desc == RPC_FC_IP)
2069           m(pStubMsg, *(unsigned char **)pMemory, desc);
2070         else
2071           m(pStubMsg, pMemory, desc);
2072       }
2073       else FIXME("no buffersizer for embedded type %02x\n", *desc);
2074       pMemory += size;
2075       pFormat += 2;
2076       continue;
2077     case RPC_FC_PAD:
2078       break;
2079     default:
2080       FIXME("unhandled format 0x%02x\n", *pFormat);
2081     }
2082     pFormat++;
2083   }
2084
2085   return pMemory;
2086 }
2087
2088 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2089                                    unsigned char *pMemory,
2090                                    PFORMAT_STRING pFormat,
2091                                    PFORMAT_STRING pPointer)
2092 {
2093   PFORMAT_STRING desc;
2094   NDR_FREE m;
2095   unsigned long size;
2096
2097   while (*pFormat != RPC_FC_END) {
2098     switch (*pFormat) {
2099     case RPC_FC_BYTE:
2100     case RPC_FC_CHAR:
2101     case RPC_FC_SMALL:
2102     case RPC_FC_USMALL:
2103       pMemory += 1;
2104       break;
2105     case RPC_FC_WCHAR:
2106     case RPC_FC_SHORT:
2107     case RPC_FC_USHORT:
2108       pMemory += 2;
2109       break;
2110     case RPC_FC_LONG:
2111     case RPC_FC_ULONG:
2112     case RPC_FC_ENUM32:
2113       pMemory += 4;
2114       break;
2115     case RPC_FC_HYPER:
2116       pMemory += 8;
2117       break;
2118     case RPC_FC_POINTER:
2119       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2120       pPointer += 4;
2121       pMemory += 4;
2122       break;
2123     case RPC_FC_ALIGNM4:
2124       ALIGN_POINTER(pMemory, 4);
2125       break;
2126     case RPC_FC_ALIGNM8:
2127       ALIGN_POINTER(pMemory, 8);
2128       break;
2129     case RPC_FC_STRUCTPAD1:
2130     case RPC_FC_STRUCTPAD2:
2131     case RPC_FC_STRUCTPAD3:
2132     case RPC_FC_STRUCTPAD4:
2133     case RPC_FC_STRUCTPAD5:
2134     case RPC_FC_STRUCTPAD6:
2135     case RPC_FC_STRUCTPAD7:
2136       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2137       break;
2138     case RPC_FC_EMBEDDED_COMPLEX:
2139       pMemory += pFormat[1];
2140       pFormat += 2;
2141       desc = pFormat + *(const SHORT*)pFormat;
2142       size = EmbeddedComplexSize(pStubMsg, desc);
2143       m = NdrFreer[*desc & NDR_TABLE_MASK];
2144       if (m)
2145       {
2146         /* for some reason interface pointers aren't generated as
2147          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2148          * they still need the derefencing treatment that pointers are
2149          * given */
2150         if (*desc == RPC_FC_IP)
2151           m(pStubMsg, *(unsigned char **)pMemory, desc);
2152         else
2153           m(pStubMsg, pMemory, desc);
2154       }
2155       else FIXME("no freer for embedded type %02x\n", *desc);
2156       pMemory += size;
2157       pFormat += 2;
2158       continue;
2159     case RPC_FC_PAD:
2160       break;
2161     default:
2162       FIXME("unhandled format 0x%02x\n", *pFormat);
2163     }
2164     pFormat++;
2165   }
2166
2167   return pMemory;
2168 }
2169
2170 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2171                                        PFORMAT_STRING pFormat)
2172 {
2173   PFORMAT_STRING desc;
2174   unsigned long size = 0;
2175
2176   while (*pFormat != RPC_FC_END) {
2177     switch (*pFormat) {
2178     case RPC_FC_BYTE:
2179     case RPC_FC_CHAR:
2180     case RPC_FC_SMALL:
2181     case RPC_FC_USMALL:
2182       size += 1;
2183       pStubMsg->Buffer += 1;
2184       break;
2185     case RPC_FC_WCHAR:
2186     case RPC_FC_SHORT:
2187     case RPC_FC_USHORT:
2188       size += 2;
2189       pStubMsg->Buffer += 2;
2190       break;
2191     case RPC_FC_LONG:
2192     case RPC_FC_ULONG:
2193     case RPC_FC_ENUM32:
2194       size += 4;
2195       pStubMsg->Buffer += 4;
2196       break;
2197     case RPC_FC_HYPER:
2198       size += 8;
2199       pStubMsg->Buffer += 8;
2200       break;
2201     case RPC_FC_POINTER:
2202       size += 4;
2203       pStubMsg->Buffer += 4;
2204       if (!pStubMsg->IgnoreEmbeddedPointers)
2205         FIXME("embedded pointers\n");
2206       break;
2207     case RPC_FC_ALIGNM4:
2208       ALIGN_LENGTH(size, 4);
2209       ALIGN_POINTER(pStubMsg->Buffer, 4);
2210       break;
2211     case RPC_FC_ALIGNM8:
2212       ALIGN_LENGTH(size, 8);
2213       ALIGN_POINTER(pStubMsg->Buffer, 8);
2214       break;
2215     case RPC_FC_STRUCTPAD1:
2216     case RPC_FC_STRUCTPAD2:
2217     case RPC_FC_STRUCTPAD3:
2218     case RPC_FC_STRUCTPAD4:
2219     case RPC_FC_STRUCTPAD5:
2220     case RPC_FC_STRUCTPAD6:
2221     case RPC_FC_STRUCTPAD7:
2222       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2223       break;
2224     case RPC_FC_EMBEDDED_COMPLEX:
2225       size += pFormat[1];
2226       pFormat += 2;
2227       desc = pFormat + *(const SHORT*)pFormat;
2228       size += EmbeddedComplexMemorySize(pStubMsg, desc);
2229       pFormat += 2;
2230       continue;
2231     case RPC_FC_PAD:
2232       break;
2233     default:
2234       FIXME("unhandled format 0x%02x\n", *pFormat);
2235     }
2236     pFormat++;
2237   }
2238
2239   return size;
2240 }
2241
2242 /***********************************************************************
2243  *           NdrComplexStructMarshall [RPCRT4.@]
2244  */
2245 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2246                                                 unsigned char *pMemory,
2247                                                 PFORMAT_STRING pFormat)
2248 {
2249   PFORMAT_STRING conf_array = NULL;
2250   PFORMAT_STRING pointer_desc = NULL;
2251   unsigned char *OldMemory = pStubMsg->Memory;
2252   int pointer_buffer_mark_set = 0;
2253
2254   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2255
2256   if (!pStubMsg->PointerBufferMark)
2257   {
2258     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2259     /* save buffer length */
2260     unsigned long saved_buffer_length = pStubMsg->BufferLength;
2261
2262     /* get the buffer pointer after complex array data, but before
2263      * pointer data */
2264     pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2265     pStubMsg->IgnoreEmbeddedPointers = 1;
2266     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2267     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2268
2269     /* save it for use by embedded pointer code later */
2270     pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2271     TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2272     pointer_buffer_mark_set = 1;
2273
2274     /* restore the original buffer length */
2275     pStubMsg->BufferLength = saved_buffer_length;
2276   }
2277
2278   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2279
2280   pFormat += 4;
2281   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2282   pFormat += 2;
2283   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2284   pFormat += 2;
2285
2286   pStubMsg->Memory = pMemory;
2287
2288   ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2289
2290   if (conf_array)
2291     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2292
2293   pStubMsg->Memory = OldMemory;
2294
2295   if (pointer_buffer_mark_set)
2296   {
2297     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2298     pStubMsg->PointerBufferMark = NULL;
2299   }
2300
2301   STD_OVERFLOW_CHECK(pStubMsg);
2302
2303   return NULL;
2304 }
2305
2306 /***********************************************************************
2307  *           NdrComplexStructUnmarshall [RPCRT4.@]
2308  */
2309 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2310                                                   unsigned char **ppMemory,
2311                                                   PFORMAT_STRING pFormat,
2312                                                   unsigned char fMustAlloc)
2313 {
2314   unsigned size = *(const WORD*)(pFormat+2);
2315   PFORMAT_STRING conf_array = NULL;
2316   PFORMAT_STRING pointer_desc = NULL;
2317   unsigned char *pMemory;
2318   int pointer_buffer_mark_set = 0;
2319
2320   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2321
2322   if (!pStubMsg->PointerBufferMark)
2323   {
2324     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2325     /* save buffer pointer */
2326     unsigned char *saved_buffer = pStubMsg->Buffer;
2327
2328     /* get the buffer pointer after complex array data, but before
2329      * pointer data */
2330     pStubMsg->IgnoreEmbeddedPointers = 1;
2331     NdrComplexStructMemorySize(pStubMsg, pFormat);
2332     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2333
2334     /* save it for use by embedded pointer code later */
2335     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2336     TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2337     pointer_buffer_mark_set = 1;
2338
2339     /* restore the original buffer */
2340     pStubMsg->Buffer = saved_buffer;
2341   }
2342
2343   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2344
2345   if (fMustAlloc || !*ppMemory)
2346   {
2347     *ppMemory = NdrAllocate(pStubMsg, size);
2348     memset(*ppMemory, 0, size);
2349   }
2350
2351   pFormat += 4;
2352   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2353   pFormat += 2;
2354   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2355   pFormat += 2;
2356
2357   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2358
2359   if (conf_array)
2360     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2361
2362   if (pointer_buffer_mark_set)
2363   {
2364     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2365     pStubMsg->PointerBufferMark = NULL;
2366   }
2367
2368   return NULL;
2369 }
2370
2371 /***********************************************************************
2372  *           NdrComplexStructBufferSize [RPCRT4.@]
2373  */
2374 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2375                                        unsigned char *pMemory,
2376                                        PFORMAT_STRING pFormat)
2377 {
2378   PFORMAT_STRING conf_array = NULL;
2379   PFORMAT_STRING pointer_desc = NULL;
2380   unsigned char *OldMemory = pStubMsg->Memory;
2381   int pointer_length_set = 0;
2382
2383   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2384
2385   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2386
2387   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2388   {
2389     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2390     unsigned long saved_buffer_length = pStubMsg->BufferLength;
2391
2392     /* get the buffer length after complex struct data, but before
2393      * pointer data */
2394     pStubMsg->IgnoreEmbeddedPointers = 1;
2395     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2396     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2397
2398     /* save it for use by embedded pointer code later */
2399     pStubMsg->PointerLength = pStubMsg->BufferLength;
2400     pointer_length_set = 1;
2401     TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2402
2403     /* restore the original buffer length */
2404     pStubMsg->BufferLength = saved_buffer_length;
2405   }
2406
2407   pFormat += 4;
2408   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2409   pFormat += 2;
2410   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2411   pFormat += 2;
2412
2413   pStubMsg->Memory = pMemory;
2414
2415   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2416
2417   if (conf_array)
2418     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2419
2420   pStubMsg->Memory = OldMemory;
2421
2422   if(pointer_length_set)
2423   {
2424     pStubMsg->BufferLength = pStubMsg->PointerLength;
2425     pStubMsg->PointerLength = 0;
2426   }
2427
2428 }
2429
2430 /***********************************************************************
2431  *           NdrComplexStructMemorySize [RPCRT4.@]
2432  */
2433 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2434                                         PFORMAT_STRING pFormat)
2435 {
2436   unsigned size = *(const WORD*)(pFormat+2);
2437   PFORMAT_STRING conf_array = NULL;
2438   PFORMAT_STRING pointer_desc = NULL;
2439
2440   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2441
2442   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2443
2444   pFormat += 4;
2445   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2446   pFormat += 2;
2447   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2448   pFormat += 2;
2449
2450   ComplexStructMemorySize(pStubMsg, pFormat);
2451
2452   if (conf_array)
2453     NdrConformantArrayMemorySize(pStubMsg, conf_array);
2454
2455   return size;
2456 }
2457
2458 /***********************************************************************
2459  *           NdrComplexStructFree [RPCRT4.@]
2460  */
2461 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2462                                  unsigned char *pMemory,
2463                                  PFORMAT_STRING pFormat)
2464 {
2465   PFORMAT_STRING conf_array = NULL;
2466   PFORMAT_STRING pointer_desc = NULL;
2467   unsigned char *OldMemory = pStubMsg->Memory;
2468
2469   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2470
2471   pFormat += 4;
2472   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2473   pFormat += 2;
2474   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2475   pFormat += 2;
2476
2477   pStubMsg->Memory = pMemory;
2478
2479   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2480
2481   if (conf_array)
2482     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2483
2484   pStubMsg->Memory = OldMemory;
2485 }
2486
2487 /***********************************************************************
2488  *           NdrConformantArrayMarshall [RPCRT4.@]
2489  */
2490 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2491                                                   unsigned char *pMemory,
2492                                                   PFORMAT_STRING pFormat)
2493 {
2494   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2495   unsigned char alignment = pFormat[1] + 1;
2496
2497   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2498   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2499
2500   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2501
2502   WriteConformance(pStubMsg);
2503
2504   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2505
2506   size = safe_multiply(esize, pStubMsg->MaxCount);
2507   memcpy(pStubMsg->Buffer, pMemory, size);
2508   pStubMsg->BufferMark = pStubMsg->Buffer;
2509   pStubMsg->Buffer += size;
2510
2511   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2512
2513   STD_OVERFLOW_CHECK(pStubMsg);
2514
2515   return NULL;
2516 }
2517
2518 /***********************************************************************
2519  *           NdrConformantArrayUnmarshall [RPCRT4.@]
2520  */
2521 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2522                                                     unsigned char **ppMemory,
2523                                                     PFORMAT_STRING pFormat,
2524                                                     unsigned char fMustAlloc)
2525 {
2526   DWORD size, esize = *(const WORD*)(pFormat+2);
2527   unsigned char alignment = pFormat[1] + 1;
2528
2529   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2530   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2531
2532   pFormat = ReadConformance(pStubMsg, pFormat+4);
2533
2534   size = safe_multiply(esize, pStubMsg->MaxCount);
2535
2536   if (fMustAlloc || !*ppMemory)
2537     *ppMemory = NdrAllocate(pStubMsg, size);
2538
2539   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2540
2541   pStubMsg->BufferMark = pStubMsg->Buffer;
2542   safe_buffer_copy(pStubMsg, *ppMemory, size);
2543
2544   EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2545
2546   return NULL;
2547 }
2548
2549 /***********************************************************************
2550  *           NdrConformantArrayBufferSize [RPCRT4.@]
2551  */
2552 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2553                                          unsigned char *pMemory,
2554                                          PFORMAT_STRING pFormat)
2555 {
2556   DWORD size, esize = *(const WORD*)(pFormat+2);
2557   unsigned char alignment = pFormat[1] + 1;
2558
2559   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2560   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2561
2562   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2563
2564   SizeConformance(pStubMsg);
2565
2566   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2567
2568   size = safe_multiply(esize, pStubMsg->MaxCount);
2569   /* conformance value plus array */
2570   pStubMsg->BufferLength += size;
2571
2572   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2573 }
2574
2575 /***********************************************************************
2576  *           NdrConformantArrayMemorySize [RPCRT4.@]
2577  */
2578 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2579                                           PFORMAT_STRING pFormat)
2580 {
2581   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2582   unsigned char alignment = pFormat[1] + 1;
2583
2584   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2585   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2586
2587   pFormat = ReadConformance(pStubMsg, pFormat+4);
2588   size = safe_multiply(esize, pStubMsg->MaxCount);
2589   pStubMsg->MemorySize += size;
2590
2591   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2592   pStubMsg->BufferMark = pStubMsg->Buffer;
2593   pStubMsg->Buffer += size;
2594
2595   EmbeddedPointerMemorySize(pStubMsg, pFormat);
2596
2597   return pStubMsg->MemorySize;
2598 }
2599
2600 /***********************************************************************
2601  *           NdrConformantArrayFree [RPCRT4.@]
2602  */
2603 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2604                                    unsigned char *pMemory,
2605                                    PFORMAT_STRING pFormat)
2606 {
2607   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2608   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2609
2610   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2611
2612   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2613 }
2614
2615
2616 /***********************************************************************
2617  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
2618  */
2619 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2620                                                          unsigned char* pMemory,
2621                                                          PFORMAT_STRING pFormat )
2622 {
2623     ULONG bufsize;
2624     unsigned char alignment = pFormat[1] + 1;
2625     DWORD esize = *(const WORD*)(pFormat+2);
2626
2627     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2628
2629     if (pFormat[0] != RPC_FC_CVARRAY)
2630     {
2631         ERR("invalid format type %x\n", pFormat[0]);
2632         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2633         return NULL;
2634     }
2635
2636     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2637     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2638
2639     WriteConformance(pStubMsg);
2640     WriteVariance(pStubMsg);
2641
2642     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2643
2644     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2645
2646     memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize);
2647     pStubMsg->BufferMark = pStubMsg->Buffer;
2648     pStubMsg->Buffer += bufsize;
2649
2650     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2651
2652     STD_OVERFLOW_CHECK(pStubMsg);
2653
2654     return NULL;
2655 }
2656
2657
2658 /***********************************************************************
2659  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
2660  */
2661 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2662                                                            unsigned char** ppMemory,
2663                                                            PFORMAT_STRING pFormat,
2664                                                            unsigned char fMustAlloc )
2665 {
2666     ULONG bufsize, memsize;
2667     unsigned char alignment = pFormat[1] + 1;
2668     DWORD esize = *(const WORD*)(pFormat+2);
2669
2670     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2671
2672     if (pFormat[0] != RPC_FC_CVARRAY)
2673     {
2674         ERR("invalid format type %x\n", pFormat[0]);
2675         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2676         return NULL;
2677     }
2678
2679     pFormat = ReadConformance(pStubMsg, pFormat+4);
2680     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2681
2682     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2683
2684     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2685     memsize = safe_multiply(esize, pStubMsg->MaxCount);
2686
2687     if (!*ppMemory || fMustAlloc)
2688         *ppMemory = NdrAllocate(pStubMsg, memsize);
2689     safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
2690
2691     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2692
2693     return NULL;
2694 }
2695
2696
2697 /***********************************************************************
2698  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
2699  */
2700 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2701                                            unsigned char* pMemory,
2702                                            PFORMAT_STRING pFormat )
2703 {
2704     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2705
2706     if (pFormat[0] != RPC_FC_CVARRAY)
2707     {
2708         ERR("invalid format type %x\n", pFormat[0]);
2709         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2710         return;
2711     }
2712
2713     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2714     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2715
2716     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2717 }
2718
2719
2720 /***********************************************************************
2721  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
2722  */
2723 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2724                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
2725 {
2726     unsigned char alignment = pFormat[1] + 1;
2727     DWORD esize = *(const WORD*)(pFormat+2);
2728
2729     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2730
2731     if (pFormat[0] != RPC_FC_CVARRAY)
2732     {
2733         ERR("invalid format type %x\n", pFormat[0]);
2734         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2735         return;
2736     }
2737
2738     /* compute size */
2739     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2740     /* compute length */
2741     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2742
2743     SizeConformance(pStubMsg);
2744     SizeVariance(pStubMsg);
2745
2746     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2747
2748     pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
2749
2750     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2751 }
2752
2753
2754 /***********************************************************************
2755  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
2756  */
2757 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2758                                                   PFORMAT_STRING pFormat )
2759 {
2760     FIXME( "stub\n" );
2761     return 0;
2762 }
2763
2764
2765 /***********************************************************************
2766  *           NdrComplexArrayMarshall [RPCRT4.@]
2767  */
2768 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2769                                                unsigned char *pMemory,
2770                                                PFORMAT_STRING pFormat)
2771 {
2772   ULONG i, count, def;
2773   BOOL variance_present;
2774   unsigned char alignment;
2775   int pointer_buffer_mark_set = 0;
2776
2777   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2778
2779   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2780   {
2781       ERR("invalid format type %x\n", pFormat[0]);
2782       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2783       return NULL;
2784   }
2785
2786   alignment = pFormat[1] + 1;
2787
2788   if (!pStubMsg->PointerBufferMark)
2789   {
2790     /* save buffer fields that may be changed by buffer sizer functions
2791      * and that may be needed later on */
2792     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2793     unsigned long saved_buffer_length = pStubMsg->BufferLength;
2794     unsigned long saved_max_count = pStubMsg->MaxCount;
2795     unsigned long saved_offset = pStubMsg->Offset;
2796     unsigned long saved_actual_count = pStubMsg->ActualCount;
2797
2798     /* get the buffer pointer after complex array data, but before
2799      * pointer data */
2800     pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2801     pStubMsg->IgnoreEmbeddedPointers = 1;
2802     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
2803     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2804
2805     /* save it for use by embedded pointer code later */
2806     pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2807     TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
2808     pointer_buffer_mark_set = 1;
2809
2810     /* restore fields */
2811     pStubMsg->ActualCount = saved_actual_count;
2812     pStubMsg->Offset = saved_offset;
2813     pStubMsg->MaxCount = saved_max_count;
2814     pStubMsg->BufferLength = saved_buffer_length;
2815   }
2816
2817   def = *(const WORD*)&pFormat[2];
2818   pFormat += 4;
2819
2820   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2821   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2822
2823   variance_present = IsConformanceOrVariancePresent(pFormat);
2824   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2825   TRACE("variance = %d\n", pStubMsg->ActualCount);
2826
2827   WriteConformance(pStubMsg);
2828   if (variance_present)
2829     WriteVariance(pStubMsg);
2830
2831   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2832
2833   count = pStubMsg->ActualCount;
2834   for (i = 0; i < count; i++)
2835     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2836
2837   STD_OVERFLOW_CHECK(pStubMsg);
2838
2839   if (pointer_buffer_mark_set)
2840   {
2841     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2842     pStubMsg->PointerBufferMark = NULL;
2843   }
2844
2845   return NULL;
2846 }
2847
2848 /***********************************************************************
2849  *           NdrComplexArrayUnmarshall [RPCRT4.@]
2850  */
2851 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2852                                                  unsigned char **ppMemory,
2853                                                  PFORMAT_STRING pFormat,
2854                                                  unsigned char fMustAlloc)
2855 {
2856   ULONG i, count, size;
2857   unsigned char alignment;
2858   unsigned char *pMemory;
2859   unsigned char *saved_buffer;
2860   int pointer_buffer_mark_set = 0;
2861   int saved_ignore_embedded;
2862
2863   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2864
2865   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2866   {
2867       ERR("invalid format type %x\n", pFormat[0]);
2868       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2869       return NULL;
2870   }
2871
2872   alignment = pFormat[1] + 1;
2873
2874   saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2875   /* save buffer pointer */
2876   saved_buffer = pStubMsg->Buffer;
2877   /* get the buffer pointer after complex array data, but before
2878    * pointer data */
2879   pStubMsg->IgnoreEmbeddedPointers = 1;
2880   pStubMsg->MemorySize = 0;
2881   NdrComplexArrayMemorySize(pStubMsg, pFormat);
2882   size = pStubMsg->MemorySize;
2883   pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2884
2885   TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
2886   if (!pStubMsg->PointerBufferMark)
2887   {
2888     /* save it for use by embedded pointer code later */
2889     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2890     pointer_buffer_mark_set = 1;
2891   }
2892   /* restore the original buffer */
2893   pStubMsg->Buffer = saved_buffer;
2894
2895   pFormat += 4;
2896
2897   pFormat = ReadConformance(pStubMsg, pFormat);
2898   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2899
2900   if (fMustAlloc || !*ppMemory)
2901   {
2902     *ppMemory = NdrAllocate(pStubMsg, size);
2903     memset(*ppMemory, 0, size);
2904   }
2905
2906   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2907
2908   pMemory = *ppMemory;
2909   count = pStubMsg->ActualCount;
2910   for (i = 0; i < count; i++)
2911     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
2912
2913   if (pointer_buffer_mark_set)
2914   {
2915     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2916     pStubMsg->PointerBufferMark = NULL;
2917   }
2918
2919   return NULL;
2920 }
2921
2922 /***********************************************************************
2923  *           NdrComplexArrayBufferSize [RPCRT4.@]
2924  */
2925 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2926                                       unsigned char *pMemory,
2927                                       PFORMAT_STRING pFormat)
2928 {
2929   ULONG i, count, def;
2930   unsigned char alignment;
2931   BOOL variance_present;
2932   int pointer_length_set = 0;
2933
2934   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2935
2936   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2937   {
2938       ERR("invalid format type %x\n", pFormat[0]);
2939       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2940       return;
2941   }
2942
2943   alignment = pFormat[1] + 1;
2944
2945   if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2946   {
2947     /* save buffer fields that may be changed by buffer sizer functions
2948      * and that may be needed later on */
2949     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2950     unsigned long saved_buffer_length = pStubMsg->BufferLength;
2951     unsigned long saved_max_count = pStubMsg->MaxCount;
2952     unsigned long saved_offset = pStubMsg->Offset;
2953     unsigned long saved_actual_count = pStubMsg->ActualCount;
2954
2955     /* get the buffer pointer after complex array data, but before
2956      * pointer data */
2957     pStubMsg->IgnoreEmbeddedPointers = 1;
2958     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
2959     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2960
2961     /* save it for use by embedded pointer code later */
2962     pStubMsg->PointerLength = pStubMsg->BufferLength;
2963     pointer_length_set = 1;
2964
2965     /* restore fields */
2966     pStubMsg->ActualCount = saved_actual_count;
2967     pStubMsg->Offset = saved_offset;
2968     pStubMsg->MaxCount = saved_max_count;
2969     pStubMsg->BufferLength = saved_buffer_length;
2970   }
2971   def = *(const WORD*)&pFormat[2];
2972   pFormat += 4;
2973
2974   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2975   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2976   SizeConformance(pStubMsg);
2977
2978   variance_present = IsConformanceOrVariancePresent(pFormat);
2979   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2980   TRACE("variance = %d\n", pStubMsg->ActualCount);
2981
2982   if (variance_present)
2983     SizeVariance(pStubMsg);
2984
2985   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2986
2987   count = pStubMsg->ActualCount;
2988   for (i = 0; i < count; i++)
2989     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
2990
2991   if(pointer_length_set)
2992   {
2993     pStubMsg->BufferLength = pStubMsg->PointerLength;
2994     pStubMsg->PointerLength = 0;
2995   }
2996 }
2997
2998 /***********************************************************************
2999  *           NdrComplexArrayMemorySize [RPCRT4.@]
3000  */
3001 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3002                                        PFORMAT_STRING pFormat)
3003 {
3004   ULONG i, count, esize, SavedMemorySize, MemorySize;
3005   unsigned char alignment;
3006   unsigned char *Buffer;
3007
3008   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3009
3010   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3011   {
3012       ERR("invalid format type %x\n", pFormat[0]);
3013       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3014       return 0;
3015   }
3016
3017   alignment = pFormat[1] + 1;
3018
3019   pFormat += 4;
3020
3021   pFormat = ReadConformance(pStubMsg, pFormat);
3022   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3023
3024   ALIGN_POINTER(pStubMsg->Buffer, alignment);
3025
3026   SavedMemorySize = pStubMsg->MemorySize;
3027
3028   Buffer = pStubMsg->Buffer;
3029   pStubMsg->MemorySize = 0;
3030   esize = ComplexStructMemorySize(pStubMsg, pFormat);
3031   pStubMsg->Buffer = Buffer;
3032
3033   MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3034
3035   count = pStubMsg->ActualCount;
3036   for (i = 0; i < count; i++)
3037     ComplexStructMemorySize(pStubMsg, pFormat);
3038
3039   pStubMsg->MemorySize = SavedMemorySize;
3040
3041   pStubMsg->MemorySize += MemorySize;
3042   return MemorySize;
3043 }
3044
3045 /***********************************************************************
3046  *           NdrComplexArrayFree [RPCRT4.@]
3047  */
3048 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3049                                 unsigned char *pMemory,
3050                                 PFORMAT_STRING pFormat)
3051 {
3052   ULONG i, count, def;
3053
3054   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3055
3056   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3057   {
3058       ERR("invalid format type %x\n", pFormat[0]);
3059       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3060       return;
3061   }
3062
3063   def = *(const WORD*)&pFormat[2];
3064   pFormat += 4;
3065
3066   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3067   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3068
3069   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3070   TRACE("variance = %d\n", pStubMsg->ActualCount);
3071
3072   count = pStubMsg->ActualCount;
3073   for (i = 0; i < count; i++)
3074     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
3075 }
3076
3077 static ULONG UserMarshalFlags(const MIDL_STUB_MESSAGE *pStubMsg)
3078 {
3079   return MAKELONG(pStubMsg->dwDestContext,
3080                   pStubMsg->RpcMsg->DataRepresentation);
3081 }
3082
3083 #define USER_MARSHAL_PTR_PREFIX \
3084         ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
3085         ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
3086
3087 /***********************************************************************
3088  *           NdrUserMarshalMarshall [RPCRT4.@]
3089  */
3090 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3091                                               unsigned char *pMemory,
3092                                               PFORMAT_STRING pFormat)
3093 {
3094   unsigned flags = pFormat[1];
3095   unsigned index = *(const WORD*)&pFormat[2];
3096   unsigned char *saved_buffer = NULL;
3097   ULONG uflag = UserMarshalFlags(pStubMsg);
3098   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3099   TRACE("index=%d\n", index);
3100
3101   if (flags & USER_MARSHAL_POINTER)
3102   {
3103     ALIGN_POINTER(pStubMsg->Buffer, 4);
3104     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
3105     pStubMsg->Buffer += 4;
3106     if (pStubMsg->PointerBufferMark)
3107     {
3108       saved_buffer = pStubMsg->Buffer;
3109       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3110       pStubMsg->PointerBufferMark = NULL;
3111     }
3112     ALIGN_POINTER(pStubMsg->Buffer, 8);
3113   }
3114   else
3115     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3116
3117   pStubMsg->Buffer =
3118     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
3119       &uflag, pStubMsg->Buffer, pMemory);
3120
3121   if (saved_buffer)
3122   {
3123     STD_OVERFLOW_CHECK(pStubMsg);
3124     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3125     pStubMsg->Buffer = saved_buffer;
3126   }
3127
3128   STD_OVERFLOW_CHECK(pStubMsg);
3129
3130   return NULL;
3131 }
3132
3133 /***********************************************************************
3134  *           NdrUserMarshalUnmarshall [RPCRT4.@]
3135  */
3136 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3137                                                  unsigned char **ppMemory,
3138                                                  PFORMAT_STRING pFormat,
3139                                                  unsigned char fMustAlloc)
3140 {
3141   unsigned flags = pFormat[1];
3142   unsigned index = *(const WORD*)&pFormat[2];
3143   DWORD memsize = *(const WORD*)&pFormat[4];
3144   unsigned char *saved_buffer = NULL;
3145   ULONG uflag = UserMarshalFlags(pStubMsg);
3146   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3147   TRACE("index=%d\n", index);
3148
3149   if (flags & USER_MARSHAL_POINTER)
3150   {
3151     ALIGN_POINTER(pStubMsg->Buffer, 4);
3152     /* skip pointer prefix */
3153     pStubMsg->Buffer += 4;
3154     if (pStubMsg->PointerBufferMark)
3155     {
3156       saved_buffer = pStubMsg->Buffer;
3157       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3158       pStubMsg->PointerBufferMark = NULL;
3159     }
3160     ALIGN_POINTER(pStubMsg->Buffer, 8);
3161   }
3162   else
3163     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3164
3165   if (fMustAlloc || !*ppMemory)
3166     *ppMemory = NdrAllocate(pStubMsg, memsize);
3167
3168   pStubMsg->Buffer =
3169     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
3170       &uflag, pStubMsg->Buffer, *ppMemory);
3171
3172   if (saved_buffer)
3173   {
3174     STD_OVERFLOW_CHECK(pStubMsg);
3175     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3176     pStubMsg->Buffer = saved_buffer;
3177   }
3178
3179   return NULL;
3180 }
3181
3182 /***********************************************************************
3183  *           NdrUserMarshalBufferSize [RPCRT4.@]
3184  */
3185 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3186                                       unsigned char *pMemory,
3187                                       PFORMAT_STRING pFormat)
3188 {
3189   unsigned flags = pFormat[1];
3190   unsigned index = *(const WORD*)&pFormat[2];
3191   DWORD bufsize = *(const WORD*)&pFormat[6];
3192   ULONG uflag = UserMarshalFlags(pStubMsg);
3193   unsigned long saved_buffer_length = 0;
3194   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3195   TRACE("index=%d\n", index);
3196
3197   if (flags & USER_MARSHAL_POINTER)
3198   {
3199     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3200     /* skip pointer prefix */
3201     pStubMsg->BufferLength += 4;
3202     if (pStubMsg->IgnoreEmbeddedPointers)
3203       return;
3204     if (pStubMsg->PointerLength)
3205     {
3206       saved_buffer_length = pStubMsg->BufferLength;
3207       pStubMsg->BufferLength = pStubMsg->PointerLength;
3208       pStubMsg->PointerLength = 0;
3209     }
3210     ALIGN_LENGTH(pStubMsg->BufferLength, 8);
3211   }
3212   else
3213     ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
3214
3215   if (bufsize) {
3216     TRACE("size=%d\n", bufsize);
3217     pStubMsg->BufferLength += bufsize;
3218   }
3219   else
3220     pStubMsg->BufferLength =
3221         pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
3222                              &uflag, pStubMsg->BufferLength, pMemory);
3223
3224   if (saved_buffer_length)
3225   {
3226     pStubMsg->PointerLength = pStubMsg->BufferLength;
3227     pStubMsg->BufferLength = saved_buffer_length;
3228   }
3229
3230 }
3231
3232 /***********************************************************************
3233  *           NdrUserMarshalMemorySize [RPCRT4.@]
3234  */
3235 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3236                                       PFORMAT_STRING pFormat)
3237 {
3238   unsigned flags = pFormat[1];
3239   unsigned index = *(const WORD*)&pFormat[2];
3240   DWORD memsize = *(const WORD*)&pFormat[4];
3241   DWORD bufsize = *(const WORD*)&pFormat[6];
3242
3243   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3244   TRACE("index=%d\n", index);
3245
3246   pStubMsg->MemorySize += memsize;
3247
3248   if (flags & USER_MARSHAL_POINTER)
3249   {
3250     ALIGN_POINTER(pStubMsg->Buffer, 4);
3251     /* skip pointer prefix */
3252     pStubMsg->Buffer += 4;
3253     if (pStubMsg->IgnoreEmbeddedPointers)
3254       return pStubMsg->MemorySize;
3255     ALIGN_POINTER(pStubMsg->Buffer, 8);
3256   }
3257   else
3258     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3259
3260   if (!bufsize)
3261     FIXME("not implemented for varying buffer size\n");
3262
3263   pStubMsg->Buffer += bufsize;
3264
3265   return pStubMsg->MemorySize;
3266 }
3267
3268 /***********************************************************************
3269  *           NdrUserMarshalFree [RPCRT4.@]
3270  */
3271 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
3272                                 unsigned char *pMemory,
3273                                 PFORMAT_STRING pFormat)
3274 {
3275 /*  unsigned flags = pFormat[1]; */
3276   unsigned index = *(const WORD*)&pFormat[2];
3277   ULONG uflag = UserMarshalFlags(pStubMsg);
3278   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3279   TRACE("index=%d\n", index);
3280
3281   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
3282     &uflag, pMemory);
3283 }
3284
3285 /***********************************************************************
3286  *           NdrClearOutParameters [RPCRT4.@]
3287  */
3288 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
3289                                   PFORMAT_STRING pFormat,
3290                                   void *ArgAddr)
3291 {
3292   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
3293 }
3294
3295 /***********************************************************************
3296  *           NdrConvert [RPCRT4.@]
3297  */
3298 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
3299 {
3300   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
3301   /* FIXME: since this stub doesn't do any converting, the proper behavior
3302      is to raise an exception */
3303 }
3304
3305 /***********************************************************************
3306  *           NdrConvert2 [RPCRT4.@]
3307  */
3308 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
3309 {
3310   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
3311     pStubMsg, pFormat, NumberParams);
3312   /* FIXME: since this stub doesn't do any converting, the proper behavior
3313      is to raise an exception */
3314 }
3315
3316 #include "pshpack1.h"
3317 typedef struct _NDR_CSTRUCT_FORMAT
3318 {
3319     unsigned char type;
3320     unsigned char alignment;
3321     unsigned short memory_size;
3322     short offset_to_array_description;
3323 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
3324 #include "poppack.h"
3325
3326 /***********************************************************************
3327  *           NdrConformantStructMarshall [RPCRT4.@]
3328  */
3329 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3330                                 unsigned char *pMemory,
3331                                 PFORMAT_STRING pFormat)
3332 {
3333     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3334     PFORMAT_STRING pCArrayFormat;
3335     ULONG esize, bufsize;
3336
3337     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3338
3339     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3340     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3341     {
3342         ERR("invalid format type %x\n", pCStructFormat->type);
3343         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3344         return NULL;
3345     }
3346
3347     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3348         pCStructFormat->offset_to_array_description;
3349     if (*pCArrayFormat != RPC_FC_CARRAY)
3350     {
3351         ERR("invalid array format type %x\n", pCStructFormat->type);
3352         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3353         return NULL;
3354     }
3355     esize = *(const WORD*)(pCArrayFormat+2);
3356
3357     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3358                        pCArrayFormat + 4, 0);
3359
3360     WriteConformance(pStubMsg);
3361
3362     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3363
3364     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3365
3366     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3367     /* copy constant sized part of struct */
3368     pStubMsg->BufferMark = pStubMsg->Buffer;
3369     memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size + bufsize);
3370     pStubMsg->Buffer += pCStructFormat->memory_size + bufsize;
3371
3372     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3373         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3374
3375     STD_OVERFLOW_CHECK(pStubMsg);
3376
3377     return NULL;
3378 }
3379
3380 /***********************************************************************
3381  *           NdrConformantStructUnmarshall [RPCRT4.@]
3382  */
3383 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3384                                 unsigned char **ppMemory,
3385                                 PFORMAT_STRING pFormat,
3386                                 unsigned char fMustAlloc)
3387 {
3388     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3389     PFORMAT_STRING pCArrayFormat;
3390     ULONG esize, bufsize;
3391
3392     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3393
3394     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3395     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3396     {
3397         ERR("invalid format type %x\n", pCStructFormat->type);
3398         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3399         return NULL;
3400     }
3401     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3402         pCStructFormat->offset_to_array_description;
3403     if (*pCArrayFormat != RPC_FC_CARRAY)
3404     {
3405         ERR("invalid array format type %x\n", pCStructFormat->type);
3406         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3407         return NULL;
3408     }
3409     esize = *(const WORD*)(pCArrayFormat+2);
3410
3411     pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
3412
3413     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3414
3415     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3416
3417     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3418     /* work out how much memory to allocate if we need to do so */
3419     if (!*ppMemory || fMustAlloc)
3420     {
3421         SIZE_T size = pCStructFormat->memory_size + bufsize;
3422         *ppMemory = NdrAllocate(pStubMsg, size);
3423     }
3424
3425     /* now copy the data */
3426     pStubMsg->BufferMark = pStubMsg->Buffer;
3427     safe_buffer_copy(pStubMsg, *ppMemory, pCStructFormat->memory_size + bufsize);
3428
3429     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3430         EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3431
3432     return NULL;
3433 }
3434
3435 /***********************************************************************
3436  *           NdrConformantStructBufferSize [RPCRT4.@]
3437  */
3438 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3439                                 unsigned char *pMemory,
3440                                 PFORMAT_STRING pFormat)
3441 {
3442     const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3443     PFORMAT_STRING pCArrayFormat;
3444     ULONG esize;
3445
3446     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3447
3448     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3449     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3450     {
3451         ERR("invalid format type %x\n", pCStructFormat->type);
3452         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3453         return;
3454     }
3455     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3456         pCStructFormat->offset_to_array_description;
3457     if (*pCArrayFormat != RPC_FC_CARRAY)
3458     {
3459         ERR("invalid array format type %x\n", pCStructFormat->type);
3460         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3461         return;
3462     }
3463     esize = *(const WORD*)(pCArrayFormat+2);
3464
3465     pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
3466     SizeConformance(pStubMsg);
3467
3468     ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
3469
3470     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3471
3472     pStubMsg->BufferLength += pCStructFormat->memory_size +
3473         safe_multiply(pStubMsg->MaxCount, esize);
3474
3475     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3476         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3477 }
3478
3479 /***********************************************************************
3480  *           NdrConformantStructMemorySize [RPCRT4.@]
3481  */
3482 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3483                                 PFORMAT_STRING pFormat)
3484 {
3485     FIXME("stub\n");
3486     return 0;
3487 }
3488
3489 /***********************************************************************
3490  *           NdrConformantStructFree [RPCRT4.@]
3491  */
3492 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3493                                 unsigned char *pMemory,
3494                                 PFORMAT_STRING pFormat)
3495 {
3496     FIXME("stub\n");
3497 }
3498
3499 /***********************************************************************
3500  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
3501  */
3502 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3503                                 unsigned char *pMemory,
3504                                 PFORMAT_STRING pFormat)
3505 {
3506     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3507     PFORMAT_STRING pCVArrayFormat;
3508     ULONG esize, bufsize;
3509
3510     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3511
3512     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3513     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3514     {
3515         ERR("invalid format type %x\n", pCVStructFormat->type);
3516         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3517         return NULL;
3518     }
3519
3520     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3521         pCVStructFormat->offset_to_array_description;
3522     switch (*pCVArrayFormat)
3523     {
3524     case RPC_FC_CVARRAY:
3525         esize = *(const WORD*)(pCVArrayFormat+2);
3526
3527         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3528                                             pCVArrayFormat + 4, 0);
3529         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3530                                          pCVArrayFormat, 0);
3531         break;
3532     case RPC_FC_C_CSTRING:
3533         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3534         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3535         esize = sizeof(char);
3536         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3537             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3538                                                 pCVArrayFormat + 2, 0);
3539         else
3540             pStubMsg->MaxCount = pStubMsg->ActualCount;
3541         break;
3542     case RPC_FC_C_WSTRING:
3543         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3544         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3545         esize = sizeof(WCHAR);
3546         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3547             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3548                                                 pCVArrayFormat + 2, 0);
3549         else
3550             pStubMsg->MaxCount = pStubMsg->ActualCount;
3551         break;
3552     default:
3553         ERR("invalid array format type %x\n", *pCVArrayFormat);
3554         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3555         return NULL;
3556     }
3557
3558     WriteConformance(pStubMsg);
3559
3560     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3561
3562     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3563
3564     /* write constant sized part */
3565     pStubMsg->BufferMark = pStubMsg->Buffer;
3566     memcpy(pStubMsg->Buffer, pMemory, pCVStructFormat->memory_size);
3567     pStubMsg->Buffer += pCVStructFormat->memory_size;
3568
3569     WriteVariance(pStubMsg);
3570
3571     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3572
3573     /* write array part */
3574     memcpy(pStubMsg->Buffer, pMemory + pCVStructFormat->memory_size, bufsize);
3575     pStubMsg->Buffer += bufsize;
3576
3577     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3578
3579     STD_OVERFLOW_CHECK(pStubMsg);
3580
3581     return NULL;
3582 }
3583
3584 /***********************************************************************
3585  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
3586  */
3587 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3588                                 unsigned char **ppMemory,
3589                                 PFORMAT_STRING pFormat,
3590                                 unsigned char fMustAlloc)
3591 {
3592     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3593     PFORMAT_STRING pCVArrayFormat;
3594     ULONG esize, bufsize;
3595     unsigned char cvarray_type;
3596
3597     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3598
3599     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3600     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3601     {
3602         ERR("invalid format type %x\n", pCVStructFormat->type);
3603         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3604         return NULL;
3605     }
3606
3607     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3608         pCVStructFormat->offset_to_array_description;
3609     cvarray_type = *pCVArrayFormat;
3610     switch (cvarray_type)
3611     {
3612     case RPC_FC_CVARRAY:
3613         esize = *(const WORD*)(pCVArrayFormat+2);
3614         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3615         break;
3616     case RPC_FC_C_CSTRING:
3617         esize = sizeof(char);
3618         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3619             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3620         else
3621             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3622         break;
3623     case RPC_FC_C_WSTRING:
3624         esize = sizeof(WCHAR);
3625         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3626             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3627         else
3628             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3629         break;
3630     default:
3631         ERR("invalid array format type %x\n", *pCVArrayFormat);
3632         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3633         return NULL;
3634     }
3635
3636     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3637
3638     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3639
3640     /* work out how much memory to allocate if we need to do so */
3641     if (!*ppMemory || fMustAlloc)
3642     {
3643         SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3644         *ppMemory = NdrAllocate(pStubMsg, size);
3645     }
3646
3647     /* copy the constant data */
3648     pStubMsg->BufferMark = pStubMsg->Buffer;
3649     safe_buffer_copy(pStubMsg, *ppMemory, pCVStructFormat->memory_size);
3650
3651     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3652
3653     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3654
3655     if ((cvarray_type == RPC_FC_C_CSTRING) ||
3656         (cvarray_type == RPC_FC_C_WSTRING))
3657     {
3658         ULONG i;
3659         /* strings must always have null terminating bytes */
3660         if (bufsize < esize)
3661         {
3662             ERR("invalid string length of %d\n", pStubMsg->ActualCount);
3663             RpcRaiseException(RPC_S_INVALID_BOUND);
3664             return NULL;
3665         }
3666         for (i = bufsize - esize; i < bufsize; i++)
3667             if (pStubMsg->Buffer[i] != 0)
3668             {
3669                 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
3670                     i, pStubMsg->Buffer[i]);
3671                 RpcRaiseException(RPC_S_INVALID_BOUND);
3672                 return NULL;
3673             }
3674     }
3675
3676     /* copy the array data */
3677     safe_buffer_copy(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize);
3678
3679     if (cvarray_type == RPC_FC_C_CSTRING)
3680         TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3681     else if (cvarray_type == RPC_FC_C_WSTRING)
3682         TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3683
3684     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3685
3686     return NULL;
3687 }
3688
3689 /***********************************************************************
3690  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
3691  */
3692 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3693                                 unsigned char *pMemory,
3694                                 PFORMAT_STRING pFormat)
3695 {
3696     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3697     PFORMAT_STRING pCVArrayFormat;
3698     ULONG esize;
3699
3700     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3701
3702     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3703     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3704     {
3705         ERR("invalid format type %x\n", pCVStructFormat->type);
3706         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3707         return;
3708     }
3709
3710     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3711         pCVStructFormat->offset_to_array_description;
3712     switch (*pCVArrayFormat)
3713     {
3714     case RPC_FC_CVARRAY:
3715         esize = *(const WORD*)(pCVArrayFormat+2);
3716
3717         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3718                                             pCVArrayFormat + 4, 0);
3719         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3720                                          pCVArrayFormat, 0);
3721         break;
3722     case RPC_FC_C_CSTRING:
3723         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3724         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3725         esize = sizeof(char);
3726         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3727             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3728                                                 pCVArrayFormat + 2, 0);
3729         else
3730             pStubMsg->MaxCount = pStubMsg->ActualCount;
3731         break;
3732     case RPC_FC_C_WSTRING:
3733         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3734         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3735         esize = sizeof(WCHAR);
3736         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3737             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3738                                                 pCVArrayFormat + 2, 0);
3739         else
3740             pStubMsg->MaxCount = pStubMsg->ActualCount;
3741         break;
3742     default:
3743         ERR("invalid array format type %x\n", *pCVArrayFormat);
3744         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3745         return;
3746     }
3747
3748     SizeConformance(pStubMsg);
3749
3750     ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
3751
3752     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3753
3754     pStubMsg->BufferLength += pCVStructFormat->memory_size;
3755     SizeVariance(pStubMsg);
3756     pStubMsg->BufferLength += safe_multiply(pStubMsg->MaxCount, esize);
3757
3758     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3759 }
3760
3761 /***********************************************************************
3762  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
3763  */
3764 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3765                                 PFORMAT_STRING pFormat)
3766 {
3767     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3768     PFORMAT_STRING pCVArrayFormat;
3769     ULONG esize;
3770     unsigned char cvarray_type;
3771
3772     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3773
3774     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3775     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3776     {
3777         ERR("invalid format type %x\n", pCVStructFormat->type);
3778         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3779         return 0;
3780     }
3781
3782     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3783         pCVStructFormat->offset_to_array_description;
3784     cvarray_type = *pCVArrayFormat;
3785     switch (cvarray_type)
3786     {
3787     case RPC_FC_CVARRAY:
3788         esize = *(const WORD*)(pCVArrayFormat+2);
3789         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3790         break;
3791     case RPC_FC_C_CSTRING:
3792         esize = sizeof(char);
3793         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3794             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3795         else
3796             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3797         break;
3798     case RPC_FC_C_WSTRING:
3799         esize = sizeof(WCHAR);
3800         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3801             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3802         else
3803             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3804         break;
3805     default:
3806         ERR("invalid array format type %x\n", *pCVArrayFormat);
3807         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3808         return 0;
3809     }
3810
3811     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3812
3813     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3814
3815     pStubMsg->Buffer += pCVStructFormat->memory_size;
3816     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3817     pStubMsg->Buffer += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->ActualCount);
3818
3819     pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3820
3821     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3822
3823     return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3824 }
3825
3826 /***********************************************************************
3827  *           NdrConformantVaryingStructFree [RPCRT4.@]
3828  */
3829 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3830                                 unsigned char *pMemory,
3831                                 PFORMAT_STRING pFormat)
3832 {
3833     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3834     PFORMAT_STRING pCVArrayFormat;
3835     ULONG esize;
3836
3837     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3838
3839     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3840     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3841     {
3842         ERR("invalid format type %x\n", pCVStructFormat->type);
3843         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3844         return;
3845     }
3846
3847     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3848         pCVStructFormat->offset_to_array_description;
3849     switch (*pCVArrayFormat)
3850     {
3851     case RPC_FC_CVARRAY:
3852         esize = *(const WORD*)(pCVArrayFormat+2);
3853
3854         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3855                                             pCVArrayFormat + 4, 0);
3856         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3857                                          pCVArrayFormat, 0);
3858         break;
3859     case RPC_FC_C_CSTRING:
3860         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3861         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3862         esize = sizeof(char);
3863         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3864             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3865                                                 pCVArrayFormat + 2, 0);
3866         else
3867             pStubMsg->MaxCount = pStubMsg->ActualCount;
3868         break;
3869     case RPC_FC_C_WSTRING:
3870         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3871         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3872         esize = sizeof(WCHAR);
3873         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3874             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3875                                                 pCVArrayFormat + 2, 0);
3876         else
3877             pStubMsg->MaxCount = pStubMsg->ActualCount;
3878         break;
3879     default:
3880         ERR("invalid array format type %x\n", *pCVArrayFormat);
3881         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3882         return;
3883     }
3884
3885     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3886
3887     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3888 }
3889
3890 #include "pshpack1.h"
3891 typedef struct
3892 {
3893     unsigned char type;
3894     unsigned char alignment;
3895     unsigned short total_size;
3896 } NDR_SMFARRAY_FORMAT;
3897
3898 typedef struct
3899 {
3900     unsigned char type;
3901     unsigned char alignment;
3902     unsigned long total_size;
3903 } NDR_LGFARRAY_FORMAT;
3904 #include "poppack.h"
3905
3906 /***********************************************************************
3907  *           NdrFixedArrayMarshall [RPCRT4.@]
3908  */
3909 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3910                                 unsigned char *pMemory,
3911                                 PFORMAT_STRING pFormat)
3912 {
3913     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3914     unsigned long total_size;
3915
3916     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3917
3918     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3919         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3920     {
3921         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3922         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3923         return NULL;
3924     }
3925
3926     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3927
3928     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3929     {
3930         total_size = pSmFArrayFormat->total_size;
3931         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3932     }
3933     else
3934     {
3935         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3936         total_size = pLgFArrayFormat->total_size;
3937         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3938     }
3939
3940     memcpy(pStubMsg->Buffer, pMemory, total_size);
3941     pStubMsg->BufferMark = pStubMsg->Buffer;
3942     pStubMsg->Buffer += total_size;
3943
3944     pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3945
3946     return NULL;
3947 }
3948
3949 /***********************************************************************
3950  *           NdrFixedArrayUnmarshall [RPCRT4.@]
3951  */
3952 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3953                                 unsigned char **ppMemory,
3954                                 PFORMAT_STRING pFormat,
3955                                 unsigned char fMustAlloc)
3956 {
3957     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3958     unsigned long total_size;
3959
3960     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3961
3962     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3963         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3964     {
3965         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3966         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3967         return NULL;
3968     }
3969
3970     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3971
3972     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3973     {
3974         total_size = pSmFArrayFormat->total_size;
3975         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3976     }
3977     else
3978     {
3979         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3980         total_size = pLgFArrayFormat->total_size;
3981         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3982     }
3983
3984     if (fMustAlloc || !*ppMemory)
3985         *ppMemory = NdrAllocate(pStubMsg, total_size);
3986     pStubMsg->BufferMark = pStubMsg->Buffer;
3987     safe_buffer_copy(pStubMsg, *ppMemory, total_size);
3988
3989     pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3990
3991     return NULL;
3992 }
3993
3994 /***********************************************************************
3995  *           NdrFixedArrayBufferSize [RPCRT4.@]
3996  */
3997 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3998                                 unsigned char *pMemory,
3999                                 PFORMAT_STRING pFormat)
4000 {
4001     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4002     unsigned long total_size;
4003
4004     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4005
4006     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4007         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4008     {
4009         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4010         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4011         return;
4012     }
4013
4014     ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
4015
4016     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4017     {
4018         total_size = pSmFArrayFormat->total_size;
4019         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4020     }
4021     else
4022     {
4023         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4024         total_size = pLgFArrayFormat->total_size;
4025         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4026     }
4027     pStubMsg->BufferLength += total_size;
4028
4029     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4030 }
4031
4032 /***********************************************************************
4033  *           NdrFixedArrayMemorySize [RPCRT4.@]
4034  */
4035 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4036                                 PFORMAT_STRING pFormat)
4037 {
4038     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4039     ULONG total_size;
4040
4041     TRACE("(%p, %p)\n", pStubMsg, pFormat);
4042
4043     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4044         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4045     {
4046         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4047         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4048         return 0;
4049     }
4050
4051     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4052
4053     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4054     {
4055         total_size = pSmFArrayFormat->total_size;
4056         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4057     }
4058     else
4059     {
4060         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4061         total_size = pLgFArrayFormat->total_size;
4062         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4063     }
4064     pStubMsg->BufferMark = pStubMsg->Buffer;
4065     pStubMsg->Buffer += total_size;
4066     pStubMsg->MemorySize += total_size;
4067
4068     EmbeddedPointerMemorySize(pStubMsg, pFormat);
4069
4070     return total_size;
4071 }
4072
4073 /***********************************************************************
4074  *           NdrFixedArrayFree [RPCRT4.@]
4075  */
4076 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4077                                 unsigned char *pMemory,
4078                                 PFORMAT_STRING pFormat)
4079 {
4080     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4081
4082     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4083
4084     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4085         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4086     {
4087         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4088         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4089         return;
4090     }
4091
4092     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4093         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4094     else
4095     {
4096         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4097         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4098     }
4099
4100     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4101 }
4102
4103 /***********************************************************************
4104  *           NdrVaryingArrayMarshall [RPCRT4.@]
4105  */
4106 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4107                                 unsigned char *pMemory,
4108                                 PFORMAT_STRING pFormat)
4109 {
4110     unsigned char alignment;
4111     DWORD elements, esize;
4112     ULONG bufsize;
4113
4114     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4115
4116     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4117         (pFormat[0] != RPC_FC_LGVARRAY))
4118     {
4119         ERR("invalid format type %x\n", pFormat[0]);
4120         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4121         return NULL;
4122     }
4123
4124     alignment = pFormat[1] + 1;
4125
4126     if (pFormat[0] == RPC_FC_SMVARRAY)
4127     {
4128         pFormat += 2;
4129         pFormat += sizeof(WORD);
4130         elements = *(const WORD*)pFormat;
4131         pFormat += sizeof(WORD);
4132     }
4133     else
4134     {
4135         pFormat += 2;
4136         pFormat += sizeof(DWORD);
4137         elements = *(const DWORD*)pFormat;
4138         pFormat += sizeof(DWORD);
4139     }
4140
4141     esize = *(const WORD*)pFormat;
4142     pFormat += sizeof(WORD);
4143
4144     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4145     if ((pStubMsg->ActualCount > elements) ||
4146         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4147     {
4148         RpcRaiseException(RPC_S_INVALID_BOUND);
4149         return NULL;
4150     }
4151
4152     WriteVariance(pStubMsg);
4153
4154     ALIGN_POINTER(pStubMsg->Buffer, alignment);
4155
4156     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4157     memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize);
4158     pStubMsg->BufferMark = pStubMsg->Buffer;
4159     pStubMsg->Buffer += bufsize;
4160
4161     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4162
4163     STD_OVERFLOW_CHECK(pStubMsg);
4164
4165     return NULL;
4166 }
4167
4168 /***********************************************************************
4169  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
4170  */
4171 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4172                                 unsigned char **ppMemory,
4173                                 PFORMAT_STRING pFormat,
4174                                 unsigned char fMustAlloc)
4175 {
4176     unsigned char alignment;
4177     DWORD size, elements, esize;
4178     ULONG bufsize;
4179
4180     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4181
4182     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4183         (pFormat[0] != RPC_FC_LGVARRAY))
4184     {
4185         ERR("invalid format type %x\n", pFormat[0]);
4186         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4187         return NULL;
4188     }
4189
4190     alignment = pFormat[1] + 1;
4191
4192     if (pFormat[0] == RPC_FC_SMVARRAY)
4193     {
4194         pFormat += 2;
4195         size = *(const WORD*)pFormat;
4196         pFormat += sizeof(WORD);
4197         elements = *(const WORD*)pFormat;
4198         pFormat += sizeof(WORD);
4199     }
4200     else
4201     {
4202         pFormat += 2;
4203         size = *(const DWORD*)pFormat;
4204         pFormat += sizeof(DWORD);
4205         elements = *(const DWORD*)pFormat;
4206         pFormat += sizeof(DWORD);
4207     }
4208
4209     esize = *(const WORD*)pFormat;
4210     pFormat += sizeof(WORD);
4211
4212     pFormat = ReadVariance(pStubMsg, pFormat, elements);
4213
4214     ALIGN_POINTER(pStubMsg->Buffer, alignment);
4215
4216     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4217
4218     if (!*ppMemory || fMustAlloc)
4219         *ppMemory = NdrAllocate(pStubMsg, size);
4220     safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
4221
4222     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
4223
4224     return NULL;
4225 }
4226
4227 /***********************************************************************
4228  *           NdrVaryingArrayBufferSize [RPCRT4.@]
4229  */
4230 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4231                                 unsigned char *pMemory,
4232                                 PFORMAT_STRING pFormat)
4233 {
4234     unsigned char alignment;
4235     DWORD elements, esize;
4236
4237     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4238
4239     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4240         (pFormat[0] != RPC_FC_LGVARRAY))
4241     {
4242         ERR("invalid format type %x\n", pFormat[0]);
4243         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4244         return;
4245     }
4246
4247     alignment = pFormat[1] + 1;
4248
4249     if (pFormat[0] == RPC_FC_SMVARRAY)
4250     {
4251         pFormat += 2;
4252         pFormat += sizeof(WORD);
4253         elements = *(const WORD*)pFormat;
4254         pFormat += sizeof(WORD);
4255     }
4256     else
4257     {
4258         pFormat += 2;
4259         pFormat += sizeof(DWORD);
4260         elements = *(const DWORD*)pFormat;
4261         pFormat += sizeof(DWORD);
4262     }
4263
4264     esize = *(const WORD*)pFormat;
4265     pFormat += sizeof(WORD);
4266
4267     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4268     if ((pStubMsg->ActualCount > elements) ||
4269         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4270     {
4271         RpcRaiseException(RPC_S_INVALID_BOUND);
4272         return;
4273     }
4274
4275     SizeVariance(pStubMsg);
4276
4277     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4278
4279     pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
4280
4281     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4282 }
4283
4284 /***********************************************************************
4285  *           NdrVaryingArrayMemorySize [RPCRT4.@]
4286  */
4287 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4288                                 PFORMAT_STRING pFormat)
4289 {
4290     unsigned char alignment;
4291     DWORD size, elements, esize;
4292
4293     TRACE("(%p, %p)\n", pStubMsg, pFormat);
4294
4295     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4296         (pFormat[0] != RPC_FC_LGVARRAY))
4297     {
4298         ERR("invalid format type %x\n", pFormat[0]);
4299         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4300         return 0;
4301     }
4302
4303     alignment = pFormat[1] + 1;
4304
4305     if (pFormat[0] == RPC_FC_SMVARRAY)
4306     {
4307         pFormat += 2;
4308         size = *(const WORD*)pFormat;
4309         pFormat += sizeof(WORD);
4310         elements = *(const WORD*)pFormat;
4311         pFormat += sizeof(WORD);
4312     }
4313     else
4314     {
4315         pFormat += 2;
4316         size = *(const DWORD*)pFormat;
4317         pFormat += sizeof(DWORD);
4318         elements = *(const DWORD*)pFormat;
4319         pFormat += sizeof(DWORD);
4320     }
4321
4322     esize = *(const WORD*)pFormat;
4323     pFormat += sizeof(WORD);
4324
4325     pFormat = ReadVariance(pStubMsg, pFormat, elements);
4326
4327     ALIGN_POINTER(pStubMsg->Buffer, alignment);
4328
4329     pStubMsg->Buffer += safe_multiply(esize, pStubMsg->ActualCount);
4330     pStubMsg->MemorySize += size;
4331
4332     EmbeddedPointerMemorySize(pStubMsg, pFormat);
4333
4334     return pStubMsg->MemorySize;
4335 }
4336
4337 /***********************************************************************
4338  *           NdrVaryingArrayFree [RPCRT4.@]
4339  */
4340 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4341                                 unsigned char *pMemory,
4342                                 PFORMAT_STRING pFormat)
4343 {
4344     unsigned char alignment;
4345     DWORD elements;
4346
4347     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4348
4349     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4350         (pFormat[0] != RPC_FC_LGVARRAY))
4351     {
4352         ERR("invalid format type %x\n", pFormat[0]);
4353         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4354         return;
4355     }
4356
4357     alignment = pFormat[1] + 1;
4358
4359     if (pFormat[0] == RPC_FC_SMVARRAY)
4360     {
4361         pFormat += 2;
4362         pFormat += sizeof(WORD);
4363         elements = *(const WORD*)pFormat;
4364         pFormat += sizeof(WORD);
4365     }
4366     else
4367     {
4368         pFormat += 2;
4369         pFormat += sizeof(DWORD);
4370         elements = *(const DWORD*)pFormat;
4371         pFormat += sizeof(DWORD);
4372     }
4373
4374     pFormat += sizeof(WORD);
4375
4376     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4377     if ((pStubMsg->ActualCount > elements) ||
4378         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4379     {
4380         RpcRaiseException(RPC_S_INVALID_BOUND);
4381         return;
4382     }
4383
4384     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4385 }
4386
4387 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
4388 {
4389     switch (fc)
4390     {
4391     case RPC_FC_BYTE:
4392     case RPC_FC_CHAR:
4393     case RPC_FC_SMALL:
4394     case RPC_FC_USMALL:
4395         return *(const UCHAR *)pMemory;
4396     case RPC_FC_WCHAR:
4397     case RPC_FC_SHORT:
4398     case RPC_FC_USHORT:
4399     case RPC_FC_ENUM16:
4400         return *(const USHORT *)pMemory;
4401     case RPC_FC_LONG:
4402     case RPC_FC_ULONG:
4403     case RPC_FC_ENUM32:
4404         return *(const ULONG *)pMemory;
4405     default:
4406         FIXME("Unhandled base type: 0x%02x\n", fc);
4407         return 0;
4408     }
4409 }
4410
4411 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
4412                                                              unsigned long discriminant,
4413                                                              PFORMAT_STRING pFormat)
4414 {
4415     unsigned short num_arms, arm, type;
4416
4417     num_arms = *(const SHORT*)pFormat & 0x0fff;
4418     pFormat += 2;
4419     for(arm = 0; arm < num_arms; arm++)
4420     {
4421         if(discriminant == *(const ULONG*)pFormat)
4422         {
4423             pFormat += 4;
4424             break;
4425         }
4426         pFormat += 6;
4427     }
4428
4429     type = *(const unsigned short*)pFormat;
4430     TRACE("type %04x\n", type);
4431     if(arm == num_arms) /* default arm extras */
4432     {
4433         if(type == 0xffff)
4434         {
4435             ERR("no arm for 0x%lx and no default case\n", discriminant);
4436             RpcRaiseException(RPC_S_INVALID_TAG);
4437             return NULL;
4438         }
4439         if(type == 0)
4440         {
4441             TRACE("falling back to empty default case for 0x%lx\n", discriminant);
4442             return NULL;
4443         }
4444     }
4445     return pFormat;
4446 }
4447
4448 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
4449 {
4450     unsigned short type;
4451
4452     pFormat += 2;
4453
4454     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4455     if(!pFormat)
4456         return NULL;
4457
4458     type = *(const unsigned short*)pFormat;
4459     if((type & 0xff00) == 0x8000)
4460     {
4461         unsigned char basetype = LOBYTE(type);
4462         return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4463     }
4464     else
4465     {
4466         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4467         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4468         if (m)
4469         {
4470             unsigned char *saved_buffer = NULL;
4471             int pointer_buffer_mark_set = 0;
4472             switch(*desc)
4473             {
4474             case RPC_FC_RP:
4475             case RPC_FC_UP:
4476             case RPC_FC_OP:
4477             case RPC_FC_FP:
4478                 ALIGN_POINTER(pStubMsg->Buffer, 4);
4479                 saved_buffer = pStubMsg->Buffer;
4480                 if (pStubMsg->PointerBufferMark)
4481                 {
4482                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4483                   pStubMsg->PointerBufferMark = NULL;
4484                   pointer_buffer_mark_set = 1;
4485                 }
4486                 else
4487                   pStubMsg->Buffer += 4; /* for pointer ID */
4488
4489                 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
4490                 if (pointer_buffer_mark_set)
4491                 {
4492                   STD_OVERFLOW_CHECK(pStubMsg);
4493                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4494                   pStubMsg->Buffer = saved_buffer + 4;
4495                 }
4496                 break;
4497             default:
4498                 m(pStubMsg, pMemory, desc);
4499             }
4500         }
4501         else FIXME("no marshaller for embedded type %02x\n", *desc);
4502     }
4503     return NULL;
4504 }
4505
4506 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4507                                 unsigned char **ppMemory,
4508                                 ULONG discriminant,
4509                                 PFORMAT_STRING pFormat,
4510                                 unsigned char fMustAlloc)
4511 {
4512     unsigned short type;
4513
4514     pFormat += 2;
4515
4516     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4517     if(!pFormat)
4518         return NULL;
4519
4520     type = *(const unsigned short*)pFormat;
4521     if((type & 0xff00) == 0x8000)
4522     {
4523         unsigned char basetype = LOBYTE(type);
4524         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
4525     }
4526     else
4527     {
4528         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4529         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
4530         if (m)
4531         {
4532             unsigned char *saved_buffer = NULL;
4533             int pointer_buffer_mark_set = 0;
4534             switch(*desc)
4535             {
4536             case RPC_FC_RP:
4537             case RPC_FC_UP:
4538             case RPC_FC_OP:
4539             case RPC_FC_FP:
4540                 **(void***)ppMemory = NULL;
4541                 ALIGN_POINTER(pStubMsg->Buffer, 4);
4542                 saved_buffer = pStubMsg->Buffer;
4543                 if (pStubMsg->PointerBufferMark)
4544                 {
4545                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4546                   pStubMsg->PointerBufferMark = NULL;
4547                   pointer_buffer_mark_set = 1;
4548                 }
4549                 else
4550                   pStubMsg->Buffer += 4; /* for pointer ID */
4551
4552                 if (saved_buffer + 4 > pStubMsg->BufferEnd)
4553                     RpcRaiseException(RPC_X_BAD_STUB_DATA);
4554
4555                 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, fMustAlloc);
4556                 if (pointer_buffer_mark_set)
4557                 {
4558                   STD_OVERFLOW_CHECK(pStubMsg);
4559                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4560                   pStubMsg->Buffer = saved_buffer + 4;
4561                 }
4562                 break;
4563             default:
4564                 m(pStubMsg, ppMemory, desc, fMustAlloc);
4565             }
4566         }
4567         else FIXME("no marshaller for embedded type %02x\n", *desc);
4568     }
4569     return NULL;
4570 }
4571
4572 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
4573                                   unsigned char *pMemory,
4574                                   ULONG discriminant,
4575                                   PFORMAT_STRING pFormat)
4576 {
4577     unsigned short type;
4578
4579     pFormat += 2;
4580
4581     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4582     if(!pFormat)
4583         return;
4584
4585     type = *(const unsigned short*)pFormat;
4586     if((type & 0xff00) == 0x8000)
4587     {
4588         unsigned char basetype = LOBYTE(type);
4589         NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
4590     }
4591     else
4592     {
4593         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4594         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
4595         if (m)
4596         {
4597             switch(*desc)
4598             {
4599             case RPC_FC_RP:
4600             case RPC_FC_UP:
4601             case RPC_FC_OP:
4602             case RPC_FC_FP:
4603                 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4604                 pStubMsg->BufferLength += 4; /* for pointer ID */
4605                 if (!pStubMsg->IgnoreEmbeddedPointers)
4606                 {
4607                     int saved_buffer_length = pStubMsg->BufferLength;
4608                     pStubMsg->BufferLength = pStubMsg->PointerLength;
4609                     pStubMsg->PointerLength = 0;
4610                     if(!pStubMsg->BufferLength)
4611                         ERR("BufferLength == 0??\n");
4612                     PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
4613                     pStubMsg->PointerLength = pStubMsg->BufferLength;
4614                     pStubMsg->BufferLength = saved_buffer_length;
4615                 }
4616                 break;
4617             default:
4618                 m(pStubMsg, pMemory, desc);
4619             }
4620         }
4621         else FIXME("no buffersizer for embedded type %02x\n", *desc);
4622     }
4623 }
4624
4625 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
4626                                    ULONG discriminant,
4627                                    PFORMAT_STRING pFormat)
4628 {
4629     unsigned short type, size;
4630
4631     size = *(const unsigned short*)pFormat;
4632     pStubMsg->Memory += size;
4633     pFormat += 2;
4634
4635     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4636     if(!pFormat)
4637         return 0;
4638
4639     type = *(const unsigned short*)pFormat;
4640     if((type & 0xff00) == 0x8000)
4641     {
4642         return NdrBaseTypeMemorySize(pStubMsg, pFormat);
4643     }
4644     else
4645     {
4646         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4647         NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
4648         unsigned char *saved_buffer;
4649         if (m)
4650         {
4651             switch(*desc)
4652             {
4653             case RPC_FC_RP:
4654             case RPC_FC_UP:
4655             case RPC_FC_OP:
4656             case RPC_FC_FP:
4657                 ALIGN_POINTER(pStubMsg->Buffer, 4);
4658                 saved_buffer = pStubMsg->Buffer;
4659                 pStubMsg->Buffer += 4;
4660                 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
4661                 pStubMsg->MemorySize += 4;
4662                 if (!pStubMsg->IgnoreEmbeddedPointers)
4663                     PointerMemorySize(pStubMsg, saved_buffer, pFormat);
4664                 break;
4665             default:
4666                 return m(pStubMsg, desc);
4667             }
4668         }
4669         else FIXME("no marshaller for embedded type %02x\n", *desc);
4670     }
4671
4672     TRACE("size %d\n", size);
4673     return size;
4674 }
4675
4676 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
4677                            unsigned char *pMemory,
4678                            ULONG discriminant,
4679                            PFORMAT_STRING pFormat)
4680 {
4681     unsigned short type;
4682
4683     pFormat += 2;
4684
4685     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4686     if(!pFormat)
4687         return;
4688
4689     type = *(const unsigned short*)pFormat;
4690     if((type & 0xff00) != 0x8000)
4691     {
4692         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4693         NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
4694         if (m)
4695         {
4696             switch(*desc)
4697             {
4698             case RPC_FC_RP:
4699             case RPC_FC_UP:
4700             case RPC_FC_OP:
4701             case RPC_FC_FP:
4702                 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
4703                 break;
4704             default:
4705                 m(pStubMsg, pMemory, desc);
4706             }
4707         }
4708         else FIXME("no freer for embedded type %02x\n", *desc);
4709     }
4710 }
4711
4712 /***********************************************************************
4713  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
4714  */
4715 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4716                                 unsigned char *pMemory,
4717                                 PFORMAT_STRING pFormat)
4718 {
4719     unsigned char switch_type;
4720     unsigned char increment;
4721     ULONG switch_value;
4722
4723     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4724     pFormat++;
4725
4726     switch_type = *pFormat & 0xf;
4727     increment = (*pFormat & 0xf0) >> 4;
4728     pFormat++;
4729
4730     ALIGN_POINTER(pStubMsg->Buffer, increment);
4731
4732     switch_value = get_discriminant(switch_type, pMemory);
4733     TRACE("got switch value 0x%x\n", switch_value);
4734
4735     NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
4736     pMemory += increment;
4737
4738     return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
4739 }
4740
4741 /***********************************************************************
4742  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
4743  */
4744 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4745                                 unsigned char **ppMemory,
4746                                 PFORMAT_STRING pFormat,
4747                                 unsigned char fMustAlloc)
4748 {
4749     unsigned char switch_type;
4750     unsigned char increment;
4751     ULONG switch_value;
4752     unsigned short size;
4753     unsigned char *pMemoryArm;
4754
4755     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4756     pFormat++;
4757
4758     switch_type = *pFormat & 0xf;
4759     increment = (*pFormat & 0xf0) >> 4;
4760     pFormat++;
4761
4762     ALIGN_POINTER(pStubMsg->Buffer, increment);
4763     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
4764     TRACE("got switch value 0x%x\n", switch_value);
4765
4766     size = *(const unsigned short*)pFormat + increment;
4767     if(!*ppMemory || fMustAlloc)
4768         *ppMemory = NdrAllocate(pStubMsg, size);
4769
4770     NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
4771     pMemoryArm = *ppMemory + increment;
4772
4773     return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
4774 }
4775
4776 /***********************************************************************
4777  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
4778  */
4779 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4780                                 unsigned char *pMemory,
4781                                 PFORMAT_STRING pFormat)
4782 {
4783     unsigned char switch_type;
4784     unsigned char increment;
4785     ULONG switch_value;
4786
4787     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4788     pFormat++;
4789
4790     switch_type = *pFormat & 0xf;
4791     increment = (*pFormat & 0xf0) >> 4;
4792     pFormat++;
4793
4794     ALIGN_LENGTH(pStubMsg->BufferLength, increment);
4795     switch_value = get_discriminant(switch_type, pMemory);
4796     TRACE("got switch value 0x%x\n", switch_value);
4797
4798     /* Add discriminant size */
4799     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
4800     pMemory += increment;
4801
4802     union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
4803 }
4804
4805 /***********************************************************************
4806  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
4807  */
4808 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4809                                 PFORMAT_STRING pFormat)
4810 {
4811     unsigned char switch_type;
4812     unsigned char increment;
4813     ULONG switch_value;
4814
4815     switch_type = *pFormat & 0xf;
4816     increment = (*pFormat & 0xf0) >> 4;
4817     pFormat++;
4818
4819     ALIGN_POINTER(pStubMsg->Buffer, increment);
4820     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
4821     TRACE("got switch value 0x%x\n", switch_value);
4822
4823     pStubMsg->Memory += increment;
4824
4825     return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
4826 }
4827
4828 /***********************************************************************
4829  *           NdrEncapsulatedUnionFree [RPCRT4.@]
4830  */
4831 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
4832                                 unsigned char *pMemory,
4833                                 PFORMAT_STRING pFormat)
4834 {
4835     unsigned char switch_type;
4836     unsigned char increment;
4837     ULONG switch_value;
4838
4839     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4840     pFormat++;
4841
4842     switch_type = *pFormat & 0xf;
4843     increment = (*pFormat & 0xf0) >> 4;
4844     pFormat++;
4845
4846     switch_value = get_discriminant(switch_type, pMemory);
4847     TRACE("got switch value 0x%x\n", switch_value);
4848
4849     pMemory += increment;
4850
4851     return union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
4852 }
4853
4854 /***********************************************************************
4855  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
4856  */
4857 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4858                                 unsigned char *pMemory,
4859                                 PFORMAT_STRING pFormat)
4860 {
4861     unsigned char switch_type;
4862
4863     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4864     pFormat++;
4865
4866     switch_type = *pFormat;
4867     pFormat++;
4868
4869     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4870     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4871     /* Marshall discriminant */
4872     NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
4873
4874     return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
4875 }
4876
4877 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
4878                                     PFORMAT_STRING *ppFormat)
4879 {
4880     long discriminant = 0;
4881
4882     switch(**ppFormat)
4883     {
4884     case RPC_FC_BYTE:
4885     case RPC_FC_CHAR:
4886     case RPC_FC_SMALL:
4887     case RPC_FC_USMALL:
4888     {
4889         UCHAR d;
4890         safe_buffer_copy(pStubMsg, &d, sizeof(d));
4891         discriminant = d;
4892         break;
4893     }
4894     case RPC_FC_WCHAR:
4895     case RPC_FC_SHORT:
4896     case RPC_FC_USHORT:
4897     {
4898         USHORT d;
4899         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4900         safe_buffer_copy(pStubMsg, &d, sizeof(d));
4901         discriminant = d;
4902         break;
4903     }
4904     case RPC_FC_LONG:
4905     case RPC_FC_ULONG:
4906     {
4907         ULONG d;
4908         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4909         safe_buffer_copy(pStubMsg, &d, sizeof(d));
4910         discriminant = d;
4911         break;
4912     }
4913     default:
4914         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
4915     }
4916     (*ppFormat)++;
4917
4918     if (pStubMsg->fHasNewCorrDesc)
4919         *ppFormat += 6;
4920     else
4921         *ppFormat += 4;
4922     return discriminant;
4923 }
4924
4925 /**********************************************************************
4926  *           NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
4927  */
4928 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4929                                 unsigned char **ppMemory,
4930                                 PFORMAT_STRING pFormat,
4931                                 unsigned char fMustAlloc)
4932 {
4933     long discriminant;
4934     unsigned short size;
4935
4936     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4937     pFormat++;
4938
4939     /* Unmarshall discriminant */
4940     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
4941     TRACE("unmarshalled discriminant %lx\n", discriminant);
4942
4943     pFormat += *(const SHORT*)pFormat;
4944
4945     size = *(const unsigned short*)pFormat;
4946
4947     if(!*ppMemory || fMustAlloc)
4948         *ppMemory = NdrAllocate(pStubMsg, size);
4949
4950     return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
4951 }
4952
4953 /***********************************************************************
4954  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
4955  */
4956 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4957                                 unsigned char *pMemory,
4958                                 PFORMAT_STRING pFormat)
4959 {
4960     unsigned char switch_type;
4961
4962     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4963     pFormat++;
4964
4965     switch_type = *pFormat;
4966     pFormat++;
4967
4968     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4969     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4970     /* Add discriminant size */
4971     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
4972
4973     union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
4974 }
4975
4976 /***********************************************************************
4977  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
4978  */
4979 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4980                                 PFORMAT_STRING pFormat)
4981 {
4982     ULONG discriminant;
4983
4984     pFormat++;
4985     /* Unmarshall discriminant */
4986     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
4987     TRACE("unmarshalled discriminant 0x%x\n", discriminant);
4988
4989     return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
4990 }
4991
4992 /***********************************************************************
4993  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
4994  */
4995 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
4996                                 unsigned char *pMemory,
4997                                 PFORMAT_STRING pFormat)
4998 {
4999     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5000     pFormat++;
5001     pFormat++;
5002
5003     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5004     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5005
5006     return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5007 }
5008
5009 /***********************************************************************
5010  *           NdrByteCountPointerMarshall [RPCRT4.@]
5011  */
5012 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5013                                 unsigned char *pMemory,
5014                                 PFORMAT_STRING pFormat)
5015 {
5016     FIXME("stub\n");
5017     return NULL;
5018 }
5019
5020 /***********************************************************************
5021  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
5022  */
5023 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5024                                 unsigned char **ppMemory,
5025                                 PFORMAT_STRING pFormat,
5026                                 unsigned char fMustAlloc)
5027 {
5028     FIXME("stub\n");
5029     return NULL;
5030 }
5031
5032 /***********************************************************************
5033  *           NdrByteCountPointerBufferSize [RPCRT4.@]
5034  */
5035 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5036                                 unsigned char *pMemory,
5037                                 PFORMAT_STRING pFormat)
5038 {
5039     FIXME("stub\n");
5040 }
5041
5042 /***********************************************************************
5043  *           NdrByteCountPointerMemorySize [RPCRT4.@]
5044  */
5045 ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5046                                 PFORMAT_STRING pFormat)
5047 {
5048     FIXME("stub\n");
5049     return 0;
5050 }
5051
5052 /***********************************************************************
5053  *           NdrByteCountPointerFree [RPCRT4.@]
5054  */
5055 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
5056                                 unsigned char *pMemory,
5057                                 PFORMAT_STRING pFormat)
5058 {
5059     FIXME("stub\n");
5060 }
5061
5062 /***********************************************************************
5063  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
5064  */
5065 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5066                                 unsigned char *pMemory,
5067                                 PFORMAT_STRING pFormat)
5068 {
5069     FIXME("stub\n");
5070     return NULL;
5071 }
5072
5073 /***********************************************************************
5074  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
5075  */
5076 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5077                                 unsigned char **ppMemory,
5078                                 PFORMAT_STRING pFormat,
5079                                 unsigned char fMustAlloc)
5080 {
5081     FIXME("stub\n");
5082     return NULL;
5083 }
5084
5085 /***********************************************************************
5086  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
5087  */
5088 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5089                                 unsigned char *pMemory,
5090                                 PFORMAT_STRING pFormat)
5091 {
5092     FIXME("stub\n");
5093 }
5094
5095 /***********************************************************************
5096  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
5097  */
5098 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5099                                 PFORMAT_STRING pFormat)
5100 {
5101     FIXME("stub\n");
5102     return 0;
5103 }
5104
5105 /***********************************************************************
5106  *           NdrXmitOrRepAsFree [RPCRT4.@]
5107  */
5108 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
5109                                 unsigned char *pMemory,
5110                                 PFORMAT_STRING pFormat)
5111 {
5112     FIXME("stub\n");
5113 }
5114
5115 #include "pshpack1.h"
5116 typedef struct
5117 {
5118     unsigned char type;
5119     unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
5120     ULONG low_value;
5121     ULONG high_value;
5122 } NDR_RANGE;
5123 #include "poppack.h"
5124
5125 /***********************************************************************
5126  *           NdrRangeMarshall [internal]
5127  */
5128 unsigned char *WINAPI NdrRangeMarshall(
5129     PMIDL_STUB_MESSAGE pStubMsg,
5130     unsigned char *pMemory,
5131     PFORMAT_STRING pFormat)
5132 {
5133     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5134     unsigned char base_type;
5135
5136     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5137
5138     if (pRange->type != RPC_FC_RANGE)
5139     {
5140         ERR("invalid format type %x\n", pRange->type);
5141         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5142         return NULL;
5143     }
5144
5145     base_type = pRange->flags_type & 0xf;
5146
5147     return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
5148 }
5149
5150 /***********************************************************************
5151  *           NdrRangeUnmarshall
5152  */
5153 unsigned char *WINAPI NdrRangeUnmarshall(
5154     PMIDL_STUB_MESSAGE pStubMsg,
5155     unsigned char **ppMemory,
5156     PFORMAT_STRING pFormat,
5157     unsigned char fMustAlloc)
5158 {
5159     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5160     unsigned char base_type;
5161
5162     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5163
5164     if (pRange->type != RPC_FC_RANGE)
5165     {
5166         ERR("invalid format type %x\n", pRange->type);
5167         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5168         return NULL;
5169     }
5170     base_type = pRange->flags_type & 0xf;
5171
5172     TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
5173         base_type, pRange->low_value, pRange->high_value);
5174
5175 #define RANGE_UNMARSHALL(type, format_spec) \
5176     do \
5177     { \
5178         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5179         if (fMustAlloc || !*ppMemory) \
5180             *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5181         if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \
5182             (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \
5183         { \
5184             ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
5185                 *(type *)pStubMsg->Buffer, (type)pRange->low_value, \
5186                 (type)pRange->high_value); \
5187             RpcRaiseException(RPC_S_INVALID_BOUND); \
5188             return NULL; \
5189         } \
5190         TRACE("*ppMemory: %p\n", *ppMemory); \
5191         **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5192         pStubMsg->Buffer += sizeof(type); \
5193     } while (0)
5194
5195     switch(base_type)
5196     {
5197     case RPC_FC_CHAR:
5198     case RPC_FC_SMALL:
5199         RANGE_UNMARSHALL(UCHAR, "%d");
5200         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5201         break;
5202     case RPC_FC_BYTE:
5203     case RPC_FC_USMALL:
5204         RANGE_UNMARSHALL(CHAR, "%u");
5205         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5206         break;
5207     case RPC_FC_WCHAR: /* FIXME: valid? */
5208     case RPC_FC_USHORT:
5209         RANGE_UNMARSHALL(USHORT, "%u");
5210         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5211         break;
5212     case RPC_FC_SHORT:
5213         RANGE_UNMARSHALL(SHORT, "%d");
5214         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5215         break;
5216     case RPC_FC_LONG:
5217         RANGE_UNMARSHALL(LONG, "%d");
5218         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5219         break;
5220     case RPC_FC_ULONG:
5221         RANGE_UNMARSHALL(ULONG, "%u");
5222         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5223         break;
5224     case RPC_FC_ENUM16:
5225     case RPC_FC_ENUM32:
5226         FIXME("Unhandled enum type\n");
5227         break;
5228     case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */
5229     case RPC_FC_FLOAT:
5230     case RPC_FC_DOUBLE:
5231     case RPC_FC_HYPER:
5232     default:
5233         ERR("invalid range base type: 0x%02x\n", base_type);
5234         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5235     }
5236
5237     return NULL;
5238 }
5239
5240 /***********************************************************************
5241  *           NdrRangeBufferSize [internal]
5242  */
5243 void WINAPI NdrRangeBufferSize(
5244     PMIDL_STUB_MESSAGE pStubMsg,
5245     unsigned char *pMemory,
5246     PFORMAT_STRING pFormat)
5247 {
5248     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5249     unsigned char base_type;
5250
5251     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5252
5253     if (pRange->type != RPC_FC_RANGE)
5254     {
5255         ERR("invalid format type %x\n", pRange->type);
5256         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5257     }
5258     base_type = pRange->flags_type & 0xf;
5259
5260     NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
5261 }
5262
5263 /***********************************************************************
5264  *           NdrRangeMemorySize [internal]
5265  */
5266 ULONG WINAPI NdrRangeMemorySize(
5267     PMIDL_STUB_MESSAGE pStubMsg,
5268     PFORMAT_STRING pFormat)
5269 {
5270     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5271     unsigned char base_type;
5272
5273     if (pRange->type != RPC_FC_RANGE)
5274     {
5275         ERR("invalid format type %x\n", pRange->type);
5276         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5277         return 0;
5278     }
5279     base_type = pRange->flags_type & 0xf;
5280
5281     return NdrBaseTypeMemorySize(pStubMsg, &base_type);
5282 }
5283
5284 /***********************************************************************
5285  *           NdrRangeFree [internal]
5286  */
5287 void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
5288                                 unsigned char *pMemory,
5289                                 PFORMAT_STRING pFormat)
5290 {
5291    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5292
5293    /* nothing to do */
5294 }
5295
5296 /***********************************************************************
5297  *           NdrBaseTypeMarshall [internal]
5298  */
5299 static unsigned char *WINAPI NdrBaseTypeMarshall(
5300     PMIDL_STUB_MESSAGE pStubMsg,
5301     unsigned char *pMemory,
5302     PFORMAT_STRING pFormat)
5303 {
5304     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5305
5306     switch(*pFormat)
5307     {
5308     case RPC_FC_BYTE:
5309     case RPC_FC_CHAR:
5310     case RPC_FC_SMALL:
5311     case RPC_FC_USMALL:
5312         *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory;
5313         pStubMsg->Buffer += sizeof(UCHAR);
5314         TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
5315         break;
5316     case RPC_FC_WCHAR:
5317     case RPC_FC_SHORT:
5318     case RPC_FC_USHORT:
5319         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5320         *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory;
5321         pStubMsg->Buffer += sizeof(USHORT);
5322         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
5323         break;
5324     case RPC_FC_LONG:
5325     case RPC_FC_ULONG:
5326     case RPC_FC_ERROR_STATUS_T:
5327     case RPC_FC_ENUM32:
5328         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5329         *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory;
5330         pStubMsg->Buffer += sizeof(ULONG);
5331         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
5332         break;
5333     case RPC_FC_FLOAT:
5334         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
5335         *(float *)pStubMsg->Buffer = *(float *)pMemory;
5336         pStubMsg->Buffer += sizeof(float);
5337         break;
5338     case RPC_FC_DOUBLE:
5339         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
5340         *(double *)pStubMsg->Buffer = *(double *)pMemory;
5341         pStubMsg->Buffer += sizeof(double);
5342         break;
5343     case RPC_FC_HYPER:
5344         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
5345         *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory;
5346         pStubMsg->Buffer += sizeof(ULONGLONG);
5347         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
5348         break;
5349     case RPC_FC_ENUM16:
5350         /* only 16-bits on the wire, so do a sanity check */
5351         if (*(UINT *)pMemory > SHRT_MAX)
5352             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
5353         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5354         *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
5355         pStubMsg->Buffer += sizeof(USHORT);
5356         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
5357         break;
5358     case RPC_FC_IGNORE:
5359         break;
5360     default:
5361         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5362     }
5363
5364     STD_OVERFLOW_CHECK(pStubMsg);
5365
5366     /* FIXME: what is the correct return value? */
5367     return NULL;
5368 }
5369
5370 /***********************************************************************
5371  *           NdrBaseTypeUnmarshall [internal]
5372  */
5373 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
5374     PMIDL_STUB_MESSAGE pStubMsg,
5375     unsigned char **ppMemory,
5376     PFORMAT_STRING pFormat,
5377     unsigned char fMustAlloc)
5378 {
5379     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5380
5381 #define BASE_TYPE_UNMARSHALL(type) \
5382         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5383         if (fMustAlloc || !*ppMemory) \
5384             *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5385         TRACE("*ppMemory: %p\n", *ppMemory); \
5386         **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5387         pStubMsg->Buffer += sizeof(type);
5388
5389     switch(*pFormat)
5390     {
5391     case RPC_FC_BYTE:
5392     case RPC_FC_CHAR:
5393     case RPC_FC_SMALL:
5394     case RPC_FC_USMALL:
5395         BASE_TYPE_UNMARSHALL(UCHAR);
5396         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5397         break;
5398     case RPC_FC_WCHAR:
5399     case RPC_FC_SHORT:
5400     case RPC_FC_USHORT:
5401         BASE_TYPE_UNMARSHALL(USHORT);
5402         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5403         break;
5404     case RPC_FC_LONG:
5405     case RPC_FC_ULONG:
5406     case RPC_FC_ERROR_STATUS_T:
5407     case RPC_FC_ENUM32:
5408         BASE_TYPE_UNMARSHALL(ULONG);
5409         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5410         break;
5411    case RPC_FC_FLOAT:
5412         BASE_TYPE_UNMARSHALL(float);
5413         TRACE("value: %f\n", **(float **)ppMemory);
5414         break;
5415     case RPC_FC_DOUBLE:
5416         BASE_TYPE_UNMARSHALL(double);
5417         TRACE("value: %f\n", **(double **)ppMemory);
5418         break;
5419     case RPC_FC_HYPER:
5420         BASE_TYPE_UNMARSHALL(ULONGLONG);
5421         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
5422         break;
5423     case RPC_FC_ENUM16:
5424         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5425         if (fMustAlloc || !*ppMemory)
5426             *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
5427         TRACE("*ppMemory: %p\n", *ppMemory);
5428         /* 16-bits on the wire, but int in memory */
5429         **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
5430         pStubMsg->Buffer += sizeof(USHORT);
5431         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
5432         break;
5433     case RPC_FC_IGNORE:
5434         break;
5435     default:
5436         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5437     }
5438 #undef BASE_TYPE_UNMARSHALL
5439
5440     /* FIXME: what is the correct return value? */
5441
5442     return NULL;
5443 }
5444
5445 /***********************************************************************
5446  *           NdrBaseTypeBufferSize [internal]
5447  */
5448 static void WINAPI NdrBaseTypeBufferSize(
5449     PMIDL_STUB_MESSAGE pStubMsg,
5450     unsigned char *pMemory,
5451     PFORMAT_STRING pFormat)
5452 {
5453     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5454
5455     switch(*pFormat)
5456     {
5457     case RPC_FC_BYTE:
5458     case RPC_FC_CHAR:
5459     case RPC_FC_SMALL:
5460     case RPC_FC_USMALL:
5461         pStubMsg->BufferLength += sizeof(UCHAR);
5462         break;
5463     case RPC_FC_WCHAR:
5464     case RPC_FC_SHORT:
5465     case RPC_FC_USHORT:
5466     case RPC_FC_ENUM16:
5467         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
5468         pStubMsg->BufferLength += sizeof(USHORT);
5469         break;
5470     case RPC_FC_LONG:
5471     case RPC_FC_ULONG:
5472     case RPC_FC_ENUM32:
5473         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
5474         pStubMsg->BufferLength += sizeof(ULONG);
5475         break;
5476     case RPC_FC_FLOAT:
5477         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
5478         pStubMsg->BufferLength += sizeof(float);
5479         break;
5480     case RPC_FC_DOUBLE:
5481         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
5482         pStubMsg->BufferLength += sizeof(double);
5483         break;
5484     case RPC_FC_HYPER:
5485         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
5486         pStubMsg->BufferLength += sizeof(ULONGLONG);
5487         break;
5488     case RPC_FC_ERROR_STATUS_T:
5489         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
5490         pStubMsg->BufferLength += sizeof(error_status_t);
5491         break;
5492     case RPC_FC_IGNORE:
5493         break;
5494     default:
5495         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5496     }
5497 }
5498
5499 /***********************************************************************
5500  *           NdrBaseTypeMemorySize [internal]
5501  */
5502 static ULONG WINAPI NdrBaseTypeMemorySize(
5503     PMIDL_STUB_MESSAGE pStubMsg,
5504     PFORMAT_STRING pFormat)
5505 {
5506     switch(*pFormat)
5507     {
5508     case RPC_FC_BYTE:
5509     case RPC_FC_CHAR:
5510     case RPC_FC_SMALL:
5511     case RPC_FC_USMALL:
5512         pStubMsg->Buffer += sizeof(UCHAR);
5513         pStubMsg->MemorySize += sizeof(UCHAR);
5514         return sizeof(UCHAR);
5515     case RPC_FC_WCHAR:
5516     case RPC_FC_SHORT:
5517     case RPC_FC_USHORT:
5518         pStubMsg->Buffer += sizeof(USHORT);
5519         pStubMsg->MemorySize += sizeof(USHORT);
5520         return sizeof(USHORT);
5521     case RPC_FC_LONG:
5522     case RPC_FC_ULONG:
5523         pStubMsg->Buffer += sizeof(ULONG);
5524         pStubMsg->MemorySize += sizeof(ULONG);
5525         return sizeof(ULONG);
5526     case RPC_FC_FLOAT:
5527         pStubMsg->Buffer += sizeof(float);
5528         pStubMsg->MemorySize += sizeof(float);
5529         return sizeof(float);
5530     case RPC_FC_DOUBLE:
5531         pStubMsg->Buffer += sizeof(double);
5532         pStubMsg->MemorySize += sizeof(double);
5533         return sizeof(double);
5534     case RPC_FC_HYPER:
5535         pStubMsg->Buffer += sizeof(ULONGLONG);
5536         pStubMsg->MemorySize += sizeof(ULONGLONG);
5537         return sizeof(ULONGLONG);
5538     case RPC_FC_ERROR_STATUS_T:
5539         pStubMsg->Buffer += sizeof(error_status_t);
5540         pStubMsg->MemorySize += sizeof(error_status_t);
5541         return sizeof(error_status_t);
5542     case RPC_FC_ENUM16:
5543     case RPC_FC_ENUM32:
5544         pStubMsg->Buffer += sizeof(INT);
5545         pStubMsg->MemorySize += sizeof(INT);
5546         return sizeof(INT);
5547     case RPC_FC_IGNORE:
5548         pStubMsg->MemorySize += sizeof(void *);
5549         return sizeof(void *);
5550     default:
5551         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5552        return 0;
5553     }
5554 }
5555
5556 /***********************************************************************
5557  *           NdrBaseTypeFree [internal]
5558  */
5559 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
5560                                 unsigned char *pMemory,
5561                                 PFORMAT_STRING pFormat)
5562 {
5563    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5564
5565    /* nothing to do */
5566 }
5567
5568 /***********************************************************************
5569  *           NdrContextHandleBufferSize [internal]
5570  */
5571 static void WINAPI NdrContextHandleBufferSize(
5572     PMIDL_STUB_MESSAGE pStubMsg,
5573     unsigned char *pMemory,
5574     PFORMAT_STRING pFormat)
5575 {
5576     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5577
5578     if (*pFormat != RPC_FC_BIND_CONTEXT)
5579     {
5580         ERR("invalid format type %x\n", *pFormat);
5581         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5582     }
5583     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5584     pStubMsg->BufferLength += cbNDRContext;
5585 }
5586
5587 /***********************************************************************
5588  *           NdrContextHandleMarshall [internal]
5589  */
5590 static unsigned char *WINAPI NdrContextHandleMarshall(
5591     PMIDL_STUB_MESSAGE pStubMsg,
5592     unsigned char *pMemory,
5593     PFORMAT_STRING pFormat)
5594 {
5595     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5596
5597     if (*pFormat != RPC_FC_BIND_CONTEXT)
5598     {
5599         ERR("invalid format type %x\n", *pFormat);
5600         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5601     }
5602
5603     if (pFormat[1] & 0x80)
5604         NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
5605     else
5606         NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE);
5607
5608     return NULL;
5609 }
5610
5611 /***********************************************************************
5612  *           NdrContextHandleUnmarshall [internal]
5613  */
5614 static unsigned char *WINAPI NdrContextHandleUnmarshall(
5615     PMIDL_STUB_MESSAGE pStubMsg,
5616     unsigned char **ppMemory,
5617     PFORMAT_STRING pFormat,
5618     unsigned char fMustAlloc)
5619 {
5620     if (*pFormat != RPC_FC_BIND_CONTEXT)
5621     {
5622         ERR("invalid format type %x\n", *pFormat);
5623         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5624     }
5625
5626   **(NDR_CCONTEXT **)ppMemory = NULL;
5627   NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
5628
5629   return NULL;
5630 }
5631
5632 /***********************************************************************
5633  *           NdrClientContextMarshall [RPCRT4.@]
5634  */
5635 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5636                                      NDR_CCONTEXT ContextHandle,
5637                                      int fCheck)
5638 {
5639     TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
5640
5641     ALIGN_POINTER(pStubMsg->Buffer, 4);
5642
5643     /* FIXME: what does fCheck do? */
5644     NDRCContextMarshall(ContextHandle,
5645                         pStubMsg->Buffer);
5646
5647     pStubMsg->Buffer += cbNDRContext;
5648 }
5649
5650 /***********************************************************************
5651  *           NdrClientContextUnmarshall [RPCRT4.@]
5652  */
5653 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5654                                        NDR_CCONTEXT * pContextHandle,
5655                                        RPC_BINDING_HANDLE BindHandle)
5656 {
5657     TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
5658
5659     ALIGN_POINTER(pStubMsg->Buffer, 4);
5660
5661     if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
5662         RpcRaiseException(RPC_X_BAD_STUB_DATA);
5663
5664     NDRCContextUnmarshall(pContextHandle,
5665                           BindHandle,
5666                           pStubMsg->Buffer,
5667                           pStubMsg->RpcMsg->DataRepresentation);
5668
5669     pStubMsg->Buffer += cbNDRContext;
5670 }
5671
5672 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5673                                      NDR_SCONTEXT ContextHandle,
5674                                      NDR_RUNDOWN RundownRoutine )
5675 {
5676     FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
5677 }
5678
5679 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
5680 {
5681     FIXME("(%p): stub\n", pStubMsg);
5682     return NULL;
5683 }
5684
5685 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
5686                                  unsigned char* pMemory,
5687                                  PFORMAT_STRING pFormat)
5688 {
5689     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
5690 }
5691
5692 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
5693                                                PFORMAT_STRING pFormat)
5694 {
5695     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5696     return NULL;
5697 }
5698
5699 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5700                                         NDR_SCONTEXT ContextHandle,
5701                                         NDR_RUNDOWN RundownRoutine,
5702                                         PFORMAT_STRING pFormat)
5703 {
5704     FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
5705 }
5706
5707 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5708                                                   PFORMAT_STRING pFormat)
5709 {
5710     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5711     return NULL;
5712 }
5713
5714 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e
5715
5716 typedef struct ndr_context_handle
5717 {
5718     DWORD      attributes;
5719     GUID       uuid;
5720 } ndr_context_handle;
5721
5722 struct context_handle_entry
5723 {
5724     struct list entry;
5725     DWORD magic;
5726     RPC_BINDING_HANDLE handle;
5727     ndr_context_handle wire_data;
5728 };
5729
5730 static struct list context_handle_list = LIST_INIT(context_handle_list);
5731
5732 static CRITICAL_SECTION ndr_context_cs;
5733 static CRITICAL_SECTION_DEBUG ndr_context_debug =
5734 {
5735     0, 0, &ndr_context_cs,
5736     { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList },
5737       0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") }
5738 };
5739 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 };
5740
5741 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
5742 {
5743     struct context_handle_entry *che = (struct context_handle_entry*) CContext;
5744
5745     if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
5746         return NULL;
5747     return che;
5748 }
5749
5750 static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid)
5751 {
5752     struct context_handle_entry *che;
5753     LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry)
5754         if (IsEqualGUID(&che->wire_data.uuid, uuid))
5755             return che;
5756     return NULL;
5757 }
5758
5759 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
5760 {
5761     struct context_handle_entry *che;
5762     RPC_BINDING_HANDLE handle = NULL;
5763
5764     TRACE("%p\n", CContext);
5765
5766     EnterCriticalSection(&ndr_context_cs);
5767     che = get_context_entry(CContext);
5768     if (che)
5769         handle = che->handle;
5770     LeaveCriticalSection(&ndr_context_cs);
5771
5772     if (!handle)
5773         RpcRaiseException(ERROR_INVALID_HANDLE);
5774     return handle;
5775 }
5776
5777 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
5778 {
5779     struct context_handle_entry *che;
5780
5781     TRACE("%p %p\n", CContext, pBuff);
5782
5783     if (CContext)
5784     {
5785         EnterCriticalSection(&ndr_context_cs);
5786         che = get_context_entry(CContext);
5787         memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle));
5788         LeaveCriticalSection(&ndr_context_cs);
5789     }
5790     else
5791     {
5792         ndr_context_handle *wire_data = (ndr_context_handle *)pBuff;
5793         wire_data->attributes = 0;
5794         wire_data->uuid = GUID_NULL;
5795     }
5796 }
5797
5798 /***********************************************************************
5799  *           RpcSmDestroyClientContext [RPCRT4.@]
5800  */
5801 RPC_STATUS WINAPI RpcSmDestroyClientContext(void **ContextHandle)
5802 {
5803     RPC_STATUS status = RPC_X_SS_CONTEXT_MISMATCH;
5804     struct context_handle_entry *che = NULL;
5805
5806     TRACE("(%p)\n", ContextHandle);
5807
5808     EnterCriticalSection(&ndr_context_cs);
5809     che = get_context_entry(*ContextHandle);
5810     *ContextHandle = NULL;
5811     if (che)
5812     {
5813         status = RPC_S_OK;
5814         list_remove(&che->entry);
5815     }
5816
5817     LeaveCriticalSection(&ndr_context_cs);
5818
5819     if (che)
5820     {
5821         RpcBindingFree(&che->handle);
5822         HeapFree(GetProcessHeap(), 0, che);
5823     }
5824
5825     return status;
5826 }
5827
5828 /***********************************************************************
5829  *           RpcSsDestroyClientContext [RPCRT4.@]
5830  */
5831 void WINAPI RpcSsDestroyClientContext(void **ContextHandle)
5832 {
5833     RPC_STATUS status = RpcSmDestroyClientContext(ContextHandle);
5834     if (status != RPC_S_OK)
5835         RpcRaiseException(status);
5836 }
5837
5838 static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext,
5839                                       RPC_BINDING_HANDLE hBinding,
5840                                       const ndr_context_handle *chi)
5841 {
5842     struct context_handle_entry *che = NULL;
5843
5844     /* a null UUID means we should free the context handle */
5845     if (IsEqualGUID(&chi->uuid, &GUID_NULL))
5846     {
5847         if (*CContext)
5848         {
5849             che = get_context_entry(*CContext);
5850             if (!che)
5851                 return ERROR_INVALID_HANDLE;
5852             list_remove(&che->entry);
5853             RpcBindingFree(&che->handle);
5854             HeapFree(GetProcessHeap(), 0, che);
5855             che = NULL;
5856         }
5857     }
5858     /* if there's no existing entry matching the GUID, allocate one */
5859     else if (!(che = context_entry_from_guid(&chi->uuid)))
5860     {
5861         che = HeapAlloc(GetProcessHeap(), 0, sizeof *che);
5862         if (!che)
5863             return ERROR_NOT_ENOUGH_MEMORY;
5864         che->magic = NDR_CONTEXT_HANDLE_MAGIC;
5865         RpcBindingCopy(hBinding, &che->handle);
5866         list_add_tail(&context_handle_list, &che->entry);
5867         memcpy(&che->wire_data, chi, sizeof *chi);
5868     }
5869
5870     *CContext = che;
5871
5872     return ERROR_SUCCESS;
5873 }
5874
5875 /***********************************************************************
5876  *           NDRCContextUnmarshall [RPCRT4.@]
5877  */
5878 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext,
5879                                   RPC_BINDING_HANDLE hBinding,
5880                                   void *pBuff, ULONG DataRepresentation)
5881 {
5882     UINT r;
5883
5884     TRACE("*%p=(%p) %p %p %08x\n",
5885           CContext, *CContext, hBinding, pBuff, DataRepresentation);
5886
5887     EnterCriticalSection(&ndr_context_cs);
5888     r = ndr_update_context_handle(CContext, hBinding, pBuff);
5889     LeaveCriticalSection(&ndr_context_cs);
5890     if (r)
5891         RpcRaiseException(r);
5892 }
5893
5894 /***********************************************************************
5895  *           NDRSContextMarshall [RPCRT4.@]
5896  */
5897 void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext,
5898                                void *pBuff,
5899                                NDR_RUNDOWN userRunDownIn)
5900 {
5901     FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn);
5902 }
5903
5904 /***********************************************************************
5905  *           NDRSContextMarshallEx [RPCRT4.@]
5906  */
5907 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding,
5908                                   NDR_SCONTEXT CContext,
5909                                   void *pBuff,
5910                                   NDR_RUNDOWN userRunDownIn)
5911 {
5912     FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn);
5913 }
5914
5915 /***********************************************************************
5916  *           NDRSContextMarshall2 [RPCRT4.@]
5917  */
5918 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
5919                                  NDR_SCONTEXT CContext,
5920                                  void *pBuff,
5921                                  NDR_RUNDOWN userRunDownIn,
5922                                  void *CtxGuard, ULONG Flags)
5923 {
5924     FIXME("(%p %p %p %p %p %u): stub\n",
5925           hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags);
5926 }
5927
5928 /***********************************************************************
5929  *           NDRSContextUnmarshall [RPCRT4.@]
5930  */
5931 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff,
5932                                           ULONG DataRepresentation)
5933 {
5934     FIXME("(%p %08x): stub\n", pBuff, DataRepresentation);
5935     return NULL;
5936 }
5937
5938 /***********************************************************************
5939  *           NDRSContextUnmarshallEx [RPCRT4.@]
5940  */
5941 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding,
5942                                             void *pBuff,
5943                                             ULONG DataRepresentation)
5944 {
5945     FIXME("(%p %p %08x): stub\n", hBinding, pBuff, DataRepresentation);
5946     return NULL;
5947 }
5948
5949 /***********************************************************************
5950  *           NDRSContextUnmarshall2 [RPCRT4.@]
5951  */
5952 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
5953                                            void *pBuff,
5954                                            ULONG DataRepresentation,
5955                                            void *CtxGuard, ULONG Flags)
5956 {
5957     FIXME("(%p %p %08x %p %u): stub\n",
5958           hBinding, pBuff, DataRepresentation, CtxGuard, Flags);
5959     return NULL;
5960 }