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