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