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