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