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