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