rpcrt4: Add support for calculating the memory size of complex types with embedded...
[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 >= (unsigned char *)pStubMsg->BufferStart &&
1531       Pointer < (unsigned char *)pStubMsg->BufferEnd)
1532       goto notfree;
1533
1534   if (attr & RPC_FC_P_ONSTACK) {
1535     TRACE("not freeing stack ptr %p\n", Pointer);
1536     return;
1537   }
1538   TRACE("freeing %p\n", Pointer);
1539   NdrFree(pStubMsg, Pointer);
1540   return;
1541 notfree:
1542   TRACE("not freeing %p\n", Pointer);
1543 }
1544
1545 /***********************************************************************
1546  *           EmbeddedPointerMarshall
1547  */
1548 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1549                                                unsigned char *pMemory,
1550                                                PFORMAT_STRING pFormat)
1551 {
1552   unsigned char *Mark = pStubMsg->BufferMark;
1553   unsigned rep, count, stride;
1554   unsigned i;
1555   unsigned char *saved_buffer = NULL;
1556
1557   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1558
1559   if (*pFormat != RPC_FC_PP) return NULL;
1560   pFormat += 2;
1561
1562   if (pStubMsg->PointerBufferMark)
1563   {
1564     saved_buffer = pStubMsg->Buffer;
1565     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1566     pStubMsg->PointerBufferMark = NULL;
1567   }
1568
1569   while (pFormat[0] != RPC_FC_END) {
1570     switch (pFormat[0]) {
1571     default:
1572       FIXME("unknown repeat type %d\n", pFormat[0]);
1573     case RPC_FC_NO_REPEAT:
1574       rep = 1;
1575       stride = 0;
1576       count = 1;
1577       pFormat += 2;
1578       break;
1579     case RPC_FC_FIXED_REPEAT:
1580       rep = *(const WORD*)&pFormat[2];
1581       stride = *(const WORD*)&pFormat[4];
1582       count = *(const WORD*)&pFormat[8];
1583       pFormat += 10;
1584       break;
1585     case RPC_FC_VARIABLE_REPEAT:
1586       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1587       stride = *(const WORD*)&pFormat[2];
1588       count = *(const WORD*)&pFormat[6];
1589       pFormat += 8;
1590       break;
1591     }
1592     for (i = 0; i < rep; i++) {
1593       PFORMAT_STRING info = pFormat;
1594       unsigned char *membase = pMemory + (i * stride);
1595       unsigned char *bufbase = Mark + (i * stride);
1596       unsigned u;
1597
1598       for (u=0; u<count; u++,info+=8) {
1599         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1600         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1601         unsigned char *saved_memory = pStubMsg->Memory;
1602
1603         pStubMsg->Memory = pMemory;
1604         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1605         pStubMsg->Memory = saved_memory;
1606       }
1607     }
1608     pFormat += 8 * count;
1609   }
1610
1611   if (saved_buffer)
1612   {
1613     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1614     pStubMsg->Buffer = saved_buffer;
1615   }
1616
1617   STD_OVERFLOW_CHECK(pStubMsg);
1618
1619   return NULL;
1620 }
1621
1622 /***********************************************************************
1623  *           EmbeddedPointerUnmarshall
1624  */
1625 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1626                                                  unsigned char *pDstMemoryPtrs,
1627                                                  unsigned char *pSrcMemoryPtrs,
1628                                                  PFORMAT_STRING pFormat,
1629                                                  unsigned char fMustAlloc)
1630 {
1631   unsigned char *Mark = pStubMsg->BufferMark;
1632   unsigned rep, count, stride;
1633   unsigned i;
1634   unsigned char *saved_buffer = NULL;
1635
1636   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstMemoryPtrs, pSrcMemoryPtrs, pFormat, fMustAlloc);
1637
1638   if (*pFormat != RPC_FC_PP) return NULL;
1639   pFormat += 2;
1640
1641   if (pStubMsg->PointerBufferMark)
1642   {
1643     saved_buffer = pStubMsg->Buffer;
1644     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1645     pStubMsg->PointerBufferMark = NULL;
1646   }
1647
1648   while (pFormat[0] != RPC_FC_END) {
1649     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1650     switch (pFormat[0]) {
1651     default:
1652       FIXME("unknown repeat type %d\n", pFormat[0]);
1653     case RPC_FC_NO_REPEAT:
1654       rep = 1;
1655       stride = 0;
1656       count = 1;
1657       pFormat += 2;
1658       break;
1659     case RPC_FC_FIXED_REPEAT:
1660       rep = *(const WORD*)&pFormat[2];
1661       stride = *(const WORD*)&pFormat[4];
1662       count = *(const WORD*)&pFormat[8];
1663       pFormat += 10;
1664       break;
1665     case RPC_FC_VARIABLE_REPEAT:
1666       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1667       stride = *(const WORD*)&pFormat[2];
1668       count = *(const WORD*)&pFormat[6];
1669       pFormat += 8;
1670       break;
1671     }
1672     for (i = 0; i < rep; i++) {
1673       PFORMAT_STRING info = pFormat;
1674       unsigned char *memdstbase = pDstMemoryPtrs + (i * stride);
1675       unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1676       unsigned char *bufbase = Mark + (i * stride);
1677       unsigned u;
1678
1679       for (u=0; u<count; u++,info+=8) {
1680         unsigned char **memdstptr = (unsigned char **)(memdstbase + *(const SHORT*)&info[0]);
1681         unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1682         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1683         PointerUnmarshall(pStubMsg, bufptr, memdstptr, *memsrcptr, info+4, fMustAlloc);
1684       }
1685     }
1686     pFormat += 8 * count;
1687   }
1688
1689   if (saved_buffer)
1690   {
1691     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1692     pStubMsg->Buffer = saved_buffer;
1693   }
1694
1695   return NULL;
1696 }
1697
1698 /***********************************************************************
1699  *           EmbeddedPointerBufferSize
1700  */
1701 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1702                                       unsigned char *pMemory,
1703                                       PFORMAT_STRING pFormat)
1704 {
1705   unsigned rep, count, stride;
1706   unsigned i;
1707   ULONG saved_buffer_length = 0;
1708
1709   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1710
1711   if (pStubMsg->IgnoreEmbeddedPointers) return;
1712
1713   if (*pFormat != RPC_FC_PP) return;
1714   pFormat += 2;
1715
1716   if (pStubMsg->PointerLength)
1717   {
1718     saved_buffer_length = pStubMsg->BufferLength;
1719     pStubMsg->BufferLength = pStubMsg->PointerLength;
1720     pStubMsg->PointerLength = 0;
1721   }
1722
1723   while (pFormat[0] != RPC_FC_END) {
1724     switch (pFormat[0]) {
1725     default:
1726       FIXME("unknown repeat type %d\n", pFormat[0]);
1727     case RPC_FC_NO_REPEAT:
1728       rep = 1;
1729       stride = 0;
1730       count = 1;
1731       pFormat += 2;
1732       break;
1733     case RPC_FC_FIXED_REPEAT:
1734       rep = *(const WORD*)&pFormat[2];
1735       stride = *(const WORD*)&pFormat[4];
1736       count = *(const WORD*)&pFormat[8];
1737       pFormat += 10;
1738       break;
1739     case RPC_FC_VARIABLE_REPEAT:
1740       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1741       stride = *(const WORD*)&pFormat[2];
1742       count = *(const WORD*)&pFormat[6];
1743       pFormat += 8;
1744       break;
1745     }
1746     for (i = 0; i < rep; i++) {
1747       PFORMAT_STRING info = pFormat;
1748       unsigned char *membase = pMemory + (i * stride);
1749       unsigned u;
1750
1751       for (u=0; u<count; u++,info+=8) {
1752         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1753         unsigned char *saved_memory = pStubMsg->Memory;
1754
1755         pStubMsg->Memory = pMemory;
1756         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1757         pStubMsg->Memory = saved_memory;
1758       }
1759     }
1760     pFormat += 8 * count;
1761   }
1762
1763   if (saved_buffer_length)
1764   {
1765     pStubMsg->PointerLength = pStubMsg->BufferLength;
1766     pStubMsg->BufferLength = saved_buffer_length;
1767   }
1768 }
1769
1770 /***********************************************************************
1771  *           EmbeddedPointerMemorySize [internal]
1772  */
1773 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1774                                                PFORMAT_STRING pFormat)
1775 {
1776   unsigned char *Mark = pStubMsg->BufferMark;
1777   unsigned rep, count, stride;
1778   unsigned i;
1779   unsigned char *saved_buffer = NULL;
1780
1781   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1782
1783   if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1784
1785   if (pStubMsg->PointerBufferMark)
1786   {
1787     saved_buffer = pStubMsg->Buffer;
1788     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1789     pStubMsg->PointerBufferMark = NULL;
1790   }
1791
1792   if (*pFormat != RPC_FC_PP) return 0;
1793   pFormat += 2;
1794
1795   while (pFormat[0] != RPC_FC_END) {
1796     switch (pFormat[0]) {
1797     default:
1798       FIXME("unknown repeat type %d\n", pFormat[0]);
1799     case RPC_FC_NO_REPEAT:
1800       rep = 1;
1801       stride = 0;
1802       count = 1;
1803       pFormat += 2;
1804       break;
1805     case RPC_FC_FIXED_REPEAT:
1806       rep = *(const WORD*)&pFormat[2];
1807       stride = *(const WORD*)&pFormat[4];
1808       count = *(const WORD*)&pFormat[8];
1809       pFormat += 10;
1810       break;
1811     case RPC_FC_VARIABLE_REPEAT:
1812       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1813       stride = *(const WORD*)&pFormat[2];
1814       count = *(const WORD*)&pFormat[6];
1815       pFormat += 8;
1816       break;
1817     }
1818     for (i = 0; i < rep; i++) {
1819       PFORMAT_STRING info = pFormat;
1820       unsigned char *bufbase = Mark + (i * stride);
1821       unsigned u;
1822       for (u=0; u<count; u++,info+=8) {
1823         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1824         PointerMemorySize(pStubMsg, bufptr, info+4);
1825       }
1826     }
1827     pFormat += 8 * count;
1828   }
1829
1830   if (saved_buffer)
1831   {
1832     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1833     pStubMsg->Buffer = saved_buffer;
1834   }
1835
1836   return 0;
1837 }
1838
1839 /***********************************************************************
1840  *           EmbeddedPointerFree [internal]
1841  */
1842 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1843                                 unsigned char *pMemory,
1844                                 PFORMAT_STRING pFormat)
1845 {
1846   unsigned rep, count, stride;
1847   unsigned i;
1848
1849   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1850   if (*pFormat != RPC_FC_PP) return;
1851   pFormat += 2;
1852
1853   while (pFormat[0] != RPC_FC_END) {
1854     switch (pFormat[0]) {
1855     default:
1856       FIXME("unknown repeat type %d\n", pFormat[0]);
1857     case RPC_FC_NO_REPEAT:
1858       rep = 1;
1859       stride = 0;
1860       count = 1;
1861       pFormat += 2;
1862       break;
1863     case RPC_FC_FIXED_REPEAT:
1864       rep = *(const WORD*)&pFormat[2];
1865       stride = *(const WORD*)&pFormat[4];
1866       count = *(const WORD*)&pFormat[8];
1867       pFormat += 10;
1868       break;
1869     case RPC_FC_VARIABLE_REPEAT:
1870       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1871       stride = *(const WORD*)&pFormat[2];
1872       count = *(const WORD*)&pFormat[6];
1873       pFormat += 8;
1874       break;
1875     }
1876     for (i = 0; i < rep; i++) {
1877       PFORMAT_STRING info = pFormat;
1878       unsigned char *membase = pMemory + (i * stride);
1879       unsigned u;
1880
1881       for (u=0; u<count; u++,info+=8) {
1882         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1883         unsigned char *saved_memory = pStubMsg->Memory;
1884
1885         pStubMsg->Memory = pMemory;
1886         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1887         pStubMsg->Memory = saved_memory;
1888       }
1889     }
1890     pFormat += 8 * count;
1891   }
1892 }
1893
1894 /***********************************************************************
1895  *           NdrPointerMarshall [RPCRT4.@]
1896  */
1897 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1898                                           unsigned char *pMemory,
1899                                           PFORMAT_STRING pFormat)
1900 {
1901   unsigned char *Buffer;
1902
1903   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1904
1905   /* incremement the buffer here instead of in PointerMarshall,
1906    * as that is used by embedded pointers which already handle the incrementing
1907    * the buffer, and shouldn't write any additional pointer data to the wire */
1908   if (*pFormat != RPC_FC_RP)
1909   {
1910     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1911     Buffer = pStubMsg->Buffer;
1912     safe_buffer_increment(pStubMsg, 4);
1913   }
1914   else
1915     Buffer = pStubMsg->Buffer;
1916
1917   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1918
1919   return NULL;
1920 }
1921
1922 /***********************************************************************
1923  *           NdrPointerUnmarshall [RPCRT4.@]
1924  */
1925 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1926                                             unsigned char **ppMemory,
1927                                             PFORMAT_STRING pFormat,
1928                                             unsigned char fMustAlloc)
1929 {
1930   unsigned char *Buffer;
1931
1932   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1933
1934   /* incremement the buffer here instead of in PointerUnmarshall,
1935    * as that is used by embedded pointers which already handle the incrementing
1936    * the buffer, and shouldn't read any additional pointer data from the
1937    * buffer */
1938   if (*pFormat != RPC_FC_RP)
1939   {
1940     ALIGN_POINTER(pStubMsg->Buffer, 4);
1941     Buffer = pStubMsg->Buffer;
1942     safe_buffer_increment(pStubMsg, 4);
1943   }
1944   else
1945     Buffer = pStubMsg->Buffer;
1946
1947   PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1948
1949   return NULL;
1950 }
1951
1952 /***********************************************************************
1953  *           NdrPointerBufferSize [RPCRT4.@]
1954  */
1955 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1956                                       unsigned char *pMemory,
1957                                       PFORMAT_STRING pFormat)
1958 {
1959   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1960
1961   /* incremement the buffer length here instead of in PointerBufferSize,
1962    * as that is used by embedded pointers which already handle the buffer
1963    * length, and shouldn't write anything more to the wire */
1964   if (*pFormat != RPC_FC_RP)
1965   {
1966     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1967     safe_buffer_length_increment(pStubMsg, 4);
1968   }
1969
1970   PointerBufferSize(pStubMsg, pMemory, pFormat);
1971 }
1972
1973 /***********************************************************************
1974  *           NdrPointerMemorySize [RPCRT4.@]
1975  */
1976 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1977                                   PFORMAT_STRING pFormat)
1978 {
1979   /* unsigned size = *(LPWORD)(pFormat+2); */
1980   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1981   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1982   return 0;
1983 }
1984
1985 /***********************************************************************
1986  *           NdrPointerFree [RPCRT4.@]
1987  */
1988 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1989                            unsigned char *pMemory,
1990                            PFORMAT_STRING pFormat)
1991 {
1992   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1993   PointerFree(pStubMsg, pMemory, pFormat);
1994 }
1995
1996 /***********************************************************************
1997  *           NdrSimpleTypeMarshall [RPCRT4.@]
1998  */
1999 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
2000                                    unsigned char FormatChar )
2001 {
2002     NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
2003 }
2004
2005 /***********************************************************************
2006  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
2007  */
2008 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
2009                                      unsigned char FormatChar )
2010 {
2011     NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0);
2012 }
2013
2014 /***********************************************************************
2015  *           NdrSimpleStructMarshall [RPCRT4.@]
2016  */
2017 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2018                                                unsigned char *pMemory,
2019                                                PFORMAT_STRING pFormat)
2020 {
2021   unsigned size = *(const WORD*)(pFormat+2);
2022   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2023
2024   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
2025
2026   pStubMsg->BufferMark = pStubMsg->Buffer;
2027   safe_copy_to_buffer(pStubMsg, pMemory, size);
2028
2029   if (pFormat[0] != RPC_FC_STRUCT)
2030     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
2031
2032   return NULL;
2033 }
2034
2035 /***********************************************************************
2036  *           NdrSimpleStructUnmarshall [RPCRT4.@]
2037  */
2038 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2039                                                  unsigned char **ppMemory,
2040                                                  PFORMAT_STRING pFormat,
2041                                                  unsigned char fMustAlloc)
2042 {
2043   unsigned size = *(const WORD*)(pFormat+2);
2044   unsigned char *saved_buffer;
2045   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2046
2047   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2048
2049   if (fMustAlloc)
2050     *ppMemory = NdrAllocate(pStubMsg, size);
2051   else
2052   {
2053     if (!pStubMsg->IsClient && !*ppMemory)
2054       /* for servers, we just point straight into the RPC buffer */
2055       *ppMemory = pStubMsg->Buffer;
2056   }
2057
2058   saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
2059   safe_buffer_increment(pStubMsg, size);
2060   if (pFormat[0] == RPC_FC_PSTRUCT)
2061       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
2062
2063   TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2064   if (*ppMemory != saved_buffer)
2065       memcpy(*ppMemory, saved_buffer, size);
2066
2067   return NULL;
2068 }
2069
2070 /***********************************************************************
2071  *           NdrSimpleStructBufferSize [RPCRT4.@]
2072  */
2073 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2074                                       unsigned char *pMemory,
2075                                       PFORMAT_STRING pFormat)
2076 {
2077   unsigned size = *(const WORD*)(pFormat+2);
2078   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2079
2080   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2081
2082   safe_buffer_length_increment(pStubMsg, size);
2083   if (pFormat[0] != RPC_FC_STRUCT)
2084     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
2085 }
2086
2087 /***********************************************************************
2088  *           NdrSimpleStructMemorySize [RPCRT4.@]
2089  */
2090 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2091                                        PFORMAT_STRING pFormat)
2092 {
2093   unsigned short size = *(const WORD *)(pFormat+2);
2094
2095   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2096
2097   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2098   pStubMsg->MemorySize += size;
2099   safe_buffer_increment(pStubMsg, size);
2100
2101   if (pFormat[0] != RPC_FC_STRUCT)
2102     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
2103   return pStubMsg->MemorySize;
2104 }
2105
2106 /***********************************************************************
2107  *           NdrSimpleStructFree [RPCRT4.@]
2108  */
2109 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2110                                 unsigned char *pMemory,
2111                                 PFORMAT_STRING pFormat)
2112 {
2113   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2114   if (pFormat[0] != RPC_FC_STRUCT)
2115     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
2116 }
2117
2118
2119 static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg,
2120                                          PFORMAT_STRING pFormat)
2121 {
2122   switch (*pFormat) {
2123   case RPC_FC_STRUCT:
2124   case RPC_FC_PSTRUCT:
2125   case RPC_FC_CSTRUCT:
2126   case RPC_FC_BOGUS_STRUCT:
2127   case RPC_FC_SMFARRAY:
2128   case RPC_FC_SMVARRAY:
2129   case RPC_FC_CSTRING:
2130     return *(const WORD*)&pFormat[2];
2131   case RPC_FC_USER_MARSHAL:
2132     return *(const WORD*)&pFormat[4];
2133   case RPC_FC_NON_ENCAPSULATED_UNION:
2134     pFormat += 2;
2135     if (pStubMsg->fHasNewCorrDesc)
2136         pFormat += 6;
2137     else
2138         pFormat += 4;
2139
2140     pFormat += *(const SHORT*)pFormat;
2141     return *(const SHORT*)pFormat;
2142   case RPC_FC_IP:
2143     return sizeof(void *);
2144   case RPC_FC_WSTRING:
2145     return *(const WORD*)&pFormat[2] * 2;
2146   default:
2147     FIXME("unhandled embedded type %02x\n", *pFormat);
2148   }
2149   return 0;
2150 }
2151
2152
2153 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2154                                                PFORMAT_STRING pFormat)
2155 {
2156   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2157
2158   if (!m)
2159   {
2160     FIXME("no memorysizer for data type=%02x\n", *pFormat);
2161     return 0;
2162   }
2163
2164   return m(pStubMsg, pFormat);
2165 }
2166
2167
2168 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2169                                        unsigned char *pMemory,
2170                                        PFORMAT_STRING pFormat,
2171                                        PFORMAT_STRING pPointer)
2172 {
2173   PFORMAT_STRING desc;
2174   NDR_MARSHALL m;
2175   unsigned long size;
2176
2177   while (*pFormat != RPC_FC_END) {
2178     switch (*pFormat) {
2179     case RPC_FC_BYTE:
2180     case RPC_FC_CHAR:
2181     case RPC_FC_SMALL:
2182     case RPC_FC_USMALL:
2183       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2184       safe_copy_to_buffer(pStubMsg, pMemory, 1);
2185       pMemory += 1;
2186       break;
2187     case RPC_FC_WCHAR:
2188     case RPC_FC_SHORT:
2189     case RPC_FC_USHORT:
2190       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2191       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2192       pMemory += 2;
2193       break;
2194     case RPC_FC_LONG:
2195     case RPC_FC_ULONG:
2196     case RPC_FC_ENUM32:
2197       TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2198       safe_copy_to_buffer(pStubMsg, pMemory, 4);
2199       pMemory += 4;
2200       break;
2201     case RPC_FC_HYPER:
2202       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2203       safe_copy_to_buffer(pStubMsg, pMemory, 8);
2204       pMemory += 8;
2205       break;
2206     case RPC_FC_POINTER:
2207     {
2208       unsigned char *saved_buffer;
2209       int pointer_buffer_mark_set = 0;
2210       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2211       ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2212       saved_buffer = pStubMsg->Buffer;
2213       if (pStubMsg->PointerBufferMark)
2214       {
2215         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2216         pStubMsg->PointerBufferMark = NULL;
2217         pointer_buffer_mark_set = 1;
2218       }
2219       else
2220         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2221       PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2222       if (pointer_buffer_mark_set)
2223       {
2224         STD_OVERFLOW_CHECK(pStubMsg);
2225         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2226         if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
2227         {
2228             ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
2229                 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
2230             RpcRaiseException(RPC_X_BAD_STUB_DATA);
2231         }
2232         pStubMsg->Buffer = saved_buffer + 4;
2233       }
2234       pPointer += 4;
2235       pMemory += 4;
2236       break;
2237     }
2238     case RPC_FC_ALIGNM4:
2239       ALIGN_POINTER(pMemory, 4);
2240       break;
2241     case RPC_FC_ALIGNM8:
2242       ALIGN_POINTER(pMemory, 8);
2243       break;
2244     case RPC_FC_STRUCTPAD1:
2245     case RPC_FC_STRUCTPAD2:
2246     case RPC_FC_STRUCTPAD3:
2247     case RPC_FC_STRUCTPAD4:
2248     case RPC_FC_STRUCTPAD5:
2249     case RPC_FC_STRUCTPAD6:
2250     case RPC_FC_STRUCTPAD7:
2251       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2252       break;
2253     case RPC_FC_EMBEDDED_COMPLEX:
2254       pMemory += pFormat[1];
2255       pFormat += 2;
2256       desc = pFormat + *(const SHORT*)pFormat;
2257       size = EmbeddedComplexSize(pStubMsg, desc);
2258       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
2259       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2260       if (m)
2261       {
2262         /* for some reason interface pointers aren't generated as
2263          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2264          * they still need the derefencing treatment that pointers are
2265          * given */
2266         if (*desc == RPC_FC_IP)
2267           m(pStubMsg, *(unsigned char **)pMemory, desc);
2268         else
2269           m(pStubMsg, pMemory, desc);
2270       }
2271       else FIXME("no marshaller for embedded type %02x\n", *desc);
2272       pMemory += size;
2273       pFormat += 2;
2274       continue;
2275     case RPC_FC_PAD:
2276       break;
2277     default:
2278       FIXME("unhandled format 0x%02x\n", *pFormat);
2279     }
2280     pFormat++;
2281   }
2282
2283   return pMemory;
2284 }
2285
2286 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2287                                          unsigned char *pMemory,
2288                                          PFORMAT_STRING pFormat,
2289                                          PFORMAT_STRING pPointer)
2290 {
2291   PFORMAT_STRING desc;
2292   NDR_UNMARSHALL m;
2293   unsigned long size;
2294
2295   while (*pFormat != RPC_FC_END) {
2296     switch (*pFormat) {
2297     case RPC_FC_BYTE:
2298     case RPC_FC_CHAR:
2299     case RPC_FC_SMALL:
2300     case RPC_FC_USMALL:
2301       safe_copy_from_buffer(pStubMsg, pMemory, 1);
2302       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2303       pMemory += 1;
2304       break;
2305     case RPC_FC_WCHAR:
2306     case RPC_FC_SHORT:
2307     case RPC_FC_USHORT:
2308       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2309       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2310       pMemory += 2;
2311       break;
2312     case RPC_FC_LONG:
2313     case RPC_FC_ULONG:
2314     case RPC_FC_ENUM32:
2315       safe_copy_from_buffer(pStubMsg, pMemory, 4);
2316       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2317       pMemory += 4;
2318       break;
2319     case RPC_FC_HYPER:
2320       safe_copy_from_buffer(pStubMsg, pMemory, 8);
2321       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2322       pMemory += 8;
2323       break;
2324     case RPC_FC_POINTER:
2325     {
2326       unsigned char *saved_buffer;
2327       int pointer_buffer_mark_set = 0;
2328       TRACE("pointer => %p\n", pMemory);
2329       ALIGN_POINTER(pStubMsg->Buffer, 4);
2330       saved_buffer = pStubMsg->Buffer;
2331       if (pStubMsg->PointerBufferMark)
2332       {
2333         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2334         pStubMsg->PointerBufferMark = NULL;
2335         pointer_buffer_mark_set = 1;
2336       }
2337       else
2338         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2339
2340       PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, TRUE);
2341       if (pointer_buffer_mark_set)
2342       {
2343         STD_OVERFLOW_CHECK(pStubMsg);
2344         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2345         if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
2346         {
2347             ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
2348                 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
2349             RpcRaiseException(RPC_X_BAD_STUB_DATA);
2350         }
2351         pStubMsg->Buffer = saved_buffer + 4;
2352       }
2353       pPointer += 4;
2354       pMemory += 4;
2355       break;
2356     }
2357     case RPC_FC_ALIGNM4:
2358       ALIGN_POINTER_CLEAR(pMemory, 4);
2359       break;
2360     case RPC_FC_ALIGNM8:
2361       ALIGN_POINTER_CLEAR(pMemory, 8);
2362       break;
2363     case RPC_FC_STRUCTPAD1:
2364     case RPC_FC_STRUCTPAD2:
2365     case RPC_FC_STRUCTPAD3:
2366     case RPC_FC_STRUCTPAD4:
2367     case RPC_FC_STRUCTPAD5:
2368     case RPC_FC_STRUCTPAD6:
2369     case RPC_FC_STRUCTPAD7:
2370       memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2371       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2372       break;
2373     case RPC_FC_EMBEDDED_COMPLEX:
2374       pMemory += pFormat[1];
2375       pFormat += 2;
2376       desc = pFormat + *(const SHORT*)pFormat;
2377       size = EmbeddedComplexSize(pStubMsg, desc);
2378       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
2379       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2380       memset(pMemory, 0, size); /* just in case */
2381       if (m)
2382       {
2383         /* for some reason interface pointers aren't generated as
2384          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2385          * they still need the derefencing treatment that pointers are
2386          * given */
2387         if (*desc == RPC_FC_IP)
2388           m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2389         else
2390           m(pStubMsg, &pMemory, desc, FALSE);
2391       }
2392       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2393       pMemory += size;
2394       pFormat += 2;
2395       continue;
2396     case RPC_FC_PAD:
2397       break;
2398     default:
2399       FIXME("unhandled format %d\n", *pFormat);
2400     }
2401     pFormat++;
2402   }
2403
2404   return pMemory;
2405 }
2406
2407 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2408                                          unsigned char *pMemory,
2409                                          PFORMAT_STRING pFormat,
2410                                          PFORMAT_STRING pPointer)
2411 {
2412   PFORMAT_STRING desc;
2413   NDR_BUFFERSIZE m;
2414   unsigned long size;
2415
2416   while (*pFormat != RPC_FC_END) {
2417     switch (*pFormat) {
2418     case RPC_FC_BYTE:
2419     case RPC_FC_CHAR:
2420     case RPC_FC_SMALL:
2421     case RPC_FC_USMALL:
2422       safe_buffer_length_increment(pStubMsg, 1);
2423       pMemory += 1;
2424       break;
2425     case RPC_FC_WCHAR:
2426     case RPC_FC_SHORT:
2427     case RPC_FC_USHORT:
2428       safe_buffer_length_increment(pStubMsg, 2);
2429       pMemory += 2;
2430       break;
2431     case RPC_FC_LONG:
2432     case RPC_FC_ULONG:
2433     case RPC_FC_ENUM32:
2434       safe_buffer_length_increment(pStubMsg, 4);
2435       pMemory += 4;
2436       break;
2437     case RPC_FC_HYPER:
2438       safe_buffer_length_increment(pStubMsg, 8);
2439       pMemory += 8;
2440       break;
2441     case RPC_FC_POINTER:
2442       if (!pStubMsg->IgnoreEmbeddedPointers)
2443       {
2444         int saved_buffer_length = pStubMsg->BufferLength;
2445         pStubMsg->BufferLength = pStubMsg->PointerLength;
2446         pStubMsg->PointerLength = 0;
2447         if(!pStubMsg->BufferLength)
2448           ERR("BufferLength == 0??\n");
2449         PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2450         pStubMsg->PointerLength = pStubMsg->BufferLength;
2451         pStubMsg->BufferLength = saved_buffer_length;
2452       }
2453       safe_buffer_length_increment(pStubMsg, 4);
2454       pPointer += 4;
2455       pMemory += 4;
2456       break;
2457     case RPC_FC_ALIGNM4:
2458       ALIGN_POINTER(pMemory, 4);
2459       break;
2460     case RPC_FC_ALIGNM8:
2461       ALIGN_POINTER(pMemory, 8);
2462       break;
2463     case RPC_FC_STRUCTPAD1:
2464     case RPC_FC_STRUCTPAD2:
2465     case RPC_FC_STRUCTPAD3:
2466     case RPC_FC_STRUCTPAD4:
2467     case RPC_FC_STRUCTPAD5:
2468     case RPC_FC_STRUCTPAD6:
2469     case RPC_FC_STRUCTPAD7:
2470       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2471       break;
2472     case RPC_FC_EMBEDDED_COMPLEX:
2473       pMemory += pFormat[1];
2474       pFormat += 2;
2475       desc = pFormat + *(const SHORT*)pFormat;
2476       size = EmbeddedComplexSize(pStubMsg, desc);
2477       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2478       if (m)
2479       {
2480         /* for some reason interface pointers aren't generated as
2481          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2482          * they still need the derefencing treatment that pointers are
2483          * given */
2484         if (*desc == RPC_FC_IP)
2485           m(pStubMsg, *(unsigned char **)pMemory, desc);
2486         else
2487           m(pStubMsg, pMemory, desc);
2488       }
2489       else FIXME("no buffersizer for embedded type %02x\n", *desc);
2490       pMemory += size;
2491       pFormat += 2;
2492       continue;
2493     case RPC_FC_PAD:
2494       break;
2495     default:
2496       FIXME("unhandled format 0x%02x\n", *pFormat);
2497     }
2498     pFormat++;
2499   }
2500
2501   return pMemory;
2502 }
2503
2504 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2505                                    unsigned char *pMemory,
2506                                    PFORMAT_STRING pFormat,
2507                                    PFORMAT_STRING pPointer)
2508 {
2509   PFORMAT_STRING desc;
2510   NDR_FREE m;
2511   unsigned long size;
2512
2513   while (*pFormat != RPC_FC_END) {
2514     switch (*pFormat) {
2515     case RPC_FC_BYTE:
2516     case RPC_FC_CHAR:
2517     case RPC_FC_SMALL:
2518     case RPC_FC_USMALL:
2519       pMemory += 1;
2520       break;
2521     case RPC_FC_WCHAR:
2522     case RPC_FC_SHORT:
2523     case RPC_FC_USHORT:
2524       pMemory += 2;
2525       break;
2526     case RPC_FC_LONG:
2527     case RPC_FC_ULONG:
2528     case RPC_FC_ENUM32:
2529       pMemory += 4;
2530       break;
2531     case RPC_FC_HYPER:
2532       pMemory += 8;
2533       break;
2534     case RPC_FC_POINTER:
2535       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2536       pPointer += 4;
2537       pMemory += 4;
2538       break;
2539     case RPC_FC_ALIGNM4:
2540       ALIGN_POINTER(pMemory, 4);
2541       break;
2542     case RPC_FC_ALIGNM8:
2543       ALIGN_POINTER(pMemory, 8);
2544       break;
2545     case RPC_FC_STRUCTPAD1:
2546     case RPC_FC_STRUCTPAD2:
2547     case RPC_FC_STRUCTPAD3:
2548     case RPC_FC_STRUCTPAD4:
2549     case RPC_FC_STRUCTPAD5:
2550     case RPC_FC_STRUCTPAD6:
2551     case RPC_FC_STRUCTPAD7:
2552       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2553       break;
2554     case RPC_FC_EMBEDDED_COMPLEX:
2555       pMemory += pFormat[1];
2556       pFormat += 2;
2557       desc = pFormat + *(const SHORT*)pFormat;
2558       size = EmbeddedComplexSize(pStubMsg, desc);
2559       m = NdrFreer[*desc & NDR_TABLE_MASK];
2560       if (m)
2561       {
2562         /* for some reason interface pointers aren't generated as
2563          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2564          * they still need the derefencing treatment that pointers are
2565          * given */
2566         if (*desc == RPC_FC_IP)
2567           m(pStubMsg, *(unsigned char **)pMemory, desc);
2568         else
2569           m(pStubMsg, pMemory, desc);
2570       }
2571       else FIXME("no freer for embedded type %02x\n", *desc);
2572       pMemory += size;
2573       pFormat += 2;
2574       continue;
2575     case RPC_FC_PAD:
2576       break;
2577     default:
2578       FIXME("unhandled format 0x%02x\n", *pFormat);
2579     }
2580     pFormat++;
2581   }
2582
2583   return pMemory;
2584 }
2585
2586 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2587                                        PFORMAT_STRING pFormat)
2588 {
2589   PFORMAT_STRING desc;
2590   unsigned long size = 0;
2591
2592   while (*pFormat != RPC_FC_END) {
2593     switch (*pFormat) {
2594     case RPC_FC_BYTE:
2595     case RPC_FC_CHAR:
2596     case RPC_FC_SMALL:
2597     case RPC_FC_USMALL:
2598       size += 1;
2599       safe_buffer_increment(pStubMsg, 1);
2600       break;
2601     case RPC_FC_WCHAR:
2602     case RPC_FC_SHORT:
2603     case RPC_FC_USHORT:
2604       size += 2;
2605       safe_buffer_increment(pStubMsg, 2);
2606       break;
2607     case RPC_FC_LONG:
2608     case RPC_FC_ULONG:
2609     case RPC_FC_ENUM32:
2610       size += 4;
2611       safe_buffer_increment(pStubMsg, 4);
2612       break;
2613     case RPC_FC_HYPER:
2614       size += 8;
2615       safe_buffer_increment(pStubMsg, 8);
2616       break;
2617     case RPC_FC_POINTER:
2618       size += 4;
2619       safe_buffer_increment(pStubMsg, 4);
2620       if (!pStubMsg->IgnoreEmbeddedPointers)
2621         FIXME("embedded pointers\n");
2622       break;
2623     case RPC_FC_ALIGNM4:
2624       ALIGN_LENGTH(size, 4);
2625       ALIGN_POINTER(pStubMsg->Buffer, 4);
2626       break;
2627     case RPC_FC_ALIGNM8:
2628       ALIGN_LENGTH(size, 8);
2629       ALIGN_POINTER(pStubMsg->Buffer, 8);
2630       break;
2631     case RPC_FC_STRUCTPAD1:
2632     case RPC_FC_STRUCTPAD2:
2633     case RPC_FC_STRUCTPAD3:
2634     case RPC_FC_STRUCTPAD4:
2635     case RPC_FC_STRUCTPAD5:
2636     case RPC_FC_STRUCTPAD6:
2637     case RPC_FC_STRUCTPAD7:
2638       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2639       break;
2640     case RPC_FC_EMBEDDED_COMPLEX:
2641       size += pFormat[1];
2642       pFormat += 2;
2643       desc = pFormat + *(const SHORT*)pFormat;
2644       size += EmbeddedComplexMemorySize(pStubMsg, desc);
2645       pFormat += 2;
2646       continue;
2647     case RPC_FC_PAD:
2648       break;
2649     default:
2650       FIXME("unhandled format 0x%02x\n", *pFormat);
2651     }
2652     pFormat++;
2653   }
2654
2655   return size;
2656 }
2657
2658 /***********************************************************************
2659  *           NdrComplexStructMarshall [RPCRT4.@]
2660  */
2661 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2662                                                 unsigned char *pMemory,
2663                                                 PFORMAT_STRING pFormat)
2664 {
2665   PFORMAT_STRING conf_array = NULL;
2666   PFORMAT_STRING pointer_desc = NULL;
2667   unsigned char *OldMemory = pStubMsg->Memory;
2668   int pointer_buffer_mark_set = 0;
2669
2670   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2671
2672   if (!pStubMsg->PointerBufferMark)
2673   {
2674     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2675     /* save buffer length */
2676     unsigned long saved_buffer_length = pStubMsg->BufferLength;
2677
2678     /* get the buffer pointer after complex array data, but before
2679      * pointer data */
2680     pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2681     pStubMsg->IgnoreEmbeddedPointers = 1;
2682     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2683     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2684
2685     /* save it for use by embedded pointer code later */
2686     pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2687     TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2688     pointer_buffer_mark_set = 1;
2689
2690     /* restore the original buffer length */
2691     pStubMsg->BufferLength = saved_buffer_length;
2692   }
2693
2694   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
2695
2696   pFormat += 4;
2697   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2698   pFormat += 2;
2699   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2700   pFormat += 2;
2701
2702   pStubMsg->Memory = pMemory;
2703
2704   ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2705
2706   if (conf_array)
2707     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2708
2709   pStubMsg->Memory = OldMemory;
2710
2711   if (pointer_buffer_mark_set)
2712   {
2713     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2714     pStubMsg->PointerBufferMark = NULL;
2715   }
2716
2717   STD_OVERFLOW_CHECK(pStubMsg);
2718
2719   return NULL;
2720 }
2721
2722 /***********************************************************************
2723  *           NdrComplexStructUnmarshall [RPCRT4.@]
2724  */
2725 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2726                                                   unsigned char **ppMemory,
2727                                                   PFORMAT_STRING pFormat,
2728                                                   unsigned char fMustAlloc)
2729 {
2730   unsigned size = *(const WORD*)(pFormat+2);
2731   PFORMAT_STRING conf_array = NULL;
2732   PFORMAT_STRING pointer_desc = NULL;
2733   unsigned char *pMemory;
2734   int pointer_buffer_mark_set = 0;
2735
2736   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2737
2738   if (!pStubMsg->PointerBufferMark)
2739   {
2740     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2741     /* save buffer pointer */
2742     unsigned char *saved_buffer = pStubMsg->Buffer;
2743
2744     /* get the buffer pointer after complex array data, but before
2745      * pointer data */
2746     pStubMsg->IgnoreEmbeddedPointers = 1;
2747     NdrComplexStructMemorySize(pStubMsg, pFormat);
2748     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2749
2750     /* save it for use by embedded pointer code later */
2751     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2752     TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2753     pointer_buffer_mark_set = 1;
2754
2755     /* restore the original buffer */
2756     pStubMsg->Buffer = saved_buffer;
2757   }
2758
2759   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2760
2761   if (fMustAlloc || !*ppMemory)
2762   {
2763     *ppMemory = NdrAllocate(pStubMsg, size);
2764     memset(*ppMemory, 0, size);
2765   }
2766
2767   pFormat += 4;
2768   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2769   pFormat += 2;
2770   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2771   pFormat += 2;
2772
2773   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2774
2775   if (conf_array)
2776     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2777
2778   if (pointer_buffer_mark_set)
2779   {
2780     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2781     pStubMsg->PointerBufferMark = NULL;
2782   }
2783
2784   return NULL;
2785 }
2786
2787 /***********************************************************************
2788  *           NdrComplexStructBufferSize [RPCRT4.@]
2789  */
2790 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2791                                        unsigned char *pMemory,
2792                                        PFORMAT_STRING pFormat)
2793 {
2794   PFORMAT_STRING conf_array = NULL;
2795   PFORMAT_STRING pointer_desc = NULL;
2796   unsigned char *OldMemory = pStubMsg->Memory;
2797   int pointer_length_set = 0;
2798
2799   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2800
2801   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2802
2803   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2804   {
2805     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2806     unsigned long saved_buffer_length = pStubMsg->BufferLength;
2807
2808     /* get the buffer length after complex struct data, but before
2809      * pointer data */
2810     pStubMsg->IgnoreEmbeddedPointers = 1;
2811     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2812     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2813
2814     /* save it for use by embedded pointer code later */
2815     pStubMsg->PointerLength = pStubMsg->BufferLength;
2816     pointer_length_set = 1;
2817     TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2818
2819     /* restore the original buffer length */
2820     pStubMsg->BufferLength = saved_buffer_length;
2821   }
2822
2823   pFormat += 4;
2824   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2825   pFormat += 2;
2826   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2827   pFormat += 2;
2828
2829   pStubMsg->Memory = pMemory;
2830
2831   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2832
2833   if (conf_array)
2834     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2835
2836   pStubMsg->Memory = OldMemory;
2837
2838   if(pointer_length_set)
2839   {
2840     pStubMsg->BufferLength = pStubMsg->PointerLength;
2841     pStubMsg->PointerLength = 0;
2842   }
2843
2844 }
2845
2846 /***********************************************************************
2847  *           NdrComplexStructMemorySize [RPCRT4.@]
2848  */
2849 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2850                                         PFORMAT_STRING pFormat)
2851 {
2852   unsigned size = *(const WORD*)(pFormat+2);
2853   PFORMAT_STRING conf_array = NULL;
2854   PFORMAT_STRING pointer_desc = NULL;
2855
2856   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2857
2858   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2859
2860   pFormat += 4;
2861   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2862   pFormat += 2;
2863   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2864   pFormat += 2;
2865
2866   ComplexStructMemorySize(pStubMsg, pFormat);
2867
2868   if (conf_array)
2869     NdrConformantArrayMemorySize(pStubMsg, conf_array);
2870
2871   return size;
2872 }
2873
2874 /***********************************************************************
2875  *           NdrComplexStructFree [RPCRT4.@]
2876  */
2877 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2878                                  unsigned char *pMemory,
2879                                  PFORMAT_STRING pFormat)
2880 {
2881   PFORMAT_STRING conf_array = NULL;
2882   PFORMAT_STRING pointer_desc = NULL;
2883   unsigned char *OldMemory = pStubMsg->Memory;
2884
2885   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2886
2887   pFormat += 4;
2888   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2889   pFormat += 2;
2890   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2891   pFormat += 2;
2892
2893   pStubMsg->Memory = pMemory;
2894
2895   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2896
2897   if (conf_array)
2898     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2899
2900   pStubMsg->Memory = OldMemory;
2901 }
2902
2903 /***********************************************************************
2904  *           NdrConformantArrayMarshall [RPCRT4.@]
2905  */
2906 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2907                                                   unsigned char *pMemory,
2908                                                   PFORMAT_STRING pFormat)
2909 {
2910   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2911   unsigned char alignment = pFormat[1] + 1;
2912
2913   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2914   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2915
2916   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2917
2918   WriteConformance(pStubMsg);
2919
2920   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
2921
2922   size = safe_multiply(esize, pStubMsg->MaxCount);
2923   pStubMsg->BufferMark = pStubMsg->Buffer;
2924   safe_copy_to_buffer(pStubMsg, pMemory, size);
2925
2926   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2927
2928   return NULL;
2929 }
2930
2931 /***********************************************************************
2932  *           NdrConformantArrayUnmarshall [RPCRT4.@]
2933  */
2934 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2935                                                     unsigned char **ppMemory,
2936                                                     PFORMAT_STRING pFormat,
2937                                                     unsigned char fMustAlloc)
2938 {
2939   DWORD size, esize = *(const WORD*)(pFormat+2);
2940   unsigned char alignment = pFormat[1] + 1;
2941   unsigned char *saved_buffer;
2942
2943   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2944   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2945
2946   pFormat = ReadConformance(pStubMsg, pFormat+4);
2947
2948   size = safe_multiply(esize, pStubMsg->MaxCount);
2949   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2950
2951   if (fMustAlloc)
2952     *ppMemory = NdrAllocate(pStubMsg, size);
2953   else
2954   {
2955     if (!pStubMsg->IsClient && !*ppMemory)
2956       /* for servers, we just point straight into the RPC buffer */
2957       *ppMemory = pStubMsg->Buffer;
2958   }
2959
2960   saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
2961   safe_buffer_increment(pStubMsg, size);
2962   EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2963
2964   TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2965   if (*ppMemory != saved_buffer)
2966       memcpy(*ppMemory, saved_buffer, size);
2967
2968   return NULL;
2969 }
2970
2971 /***********************************************************************
2972  *           NdrConformantArrayBufferSize [RPCRT4.@]
2973  */
2974 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2975                                          unsigned char *pMemory,
2976                                          PFORMAT_STRING pFormat)
2977 {
2978   DWORD size, esize = *(const WORD*)(pFormat+2);
2979   unsigned char alignment = pFormat[1] + 1;
2980
2981   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2982   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2983
2984   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2985
2986   SizeConformance(pStubMsg);
2987
2988   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2989
2990   size = safe_multiply(esize, pStubMsg->MaxCount);
2991   /* conformance value plus array */
2992   safe_buffer_length_increment(pStubMsg, size);
2993
2994   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2995 }
2996
2997 /***********************************************************************
2998  *           NdrConformantArrayMemorySize [RPCRT4.@]
2999  */
3000 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3001                                           PFORMAT_STRING pFormat)
3002 {
3003   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
3004   unsigned char alignment = pFormat[1] + 1;
3005
3006   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3007   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3008
3009   pFormat = ReadConformance(pStubMsg, pFormat+4);
3010   size = safe_multiply(esize, pStubMsg->MaxCount);
3011   pStubMsg->MemorySize += size;
3012
3013   ALIGN_POINTER(pStubMsg->Buffer, alignment);
3014   pStubMsg->BufferMark = pStubMsg->Buffer;
3015   safe_buffer_increment(pStubMsg, size);
3016
3017   EmbeddedPointerMemorySize(pStubMsg, pFormat);
3018
3019   return pStubMsg->MemorySize;
3020 }
3021
3022 /***********************************************************************
3023  *           NdrConformantArrayFree [RPCRT4.@]
3024  */
3025 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3026                                    unsigned char *pMemory,
3027                                    PFORMAT_STRING pFormat)
3028 {
3029   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3030   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3031
3032   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3033
3034   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3035 }
3036
3037
3038 /***********************************************************************
3039  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
3040  */
3041 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
3042                                                          unsigned char* pMemory,
3043                                                          PFORMAT_STRING pFormat )
3044 {
3045     ULONG bufsize;
3046     unsigned char alignment = pFormat[1] + 1;
3047     DWORD esize = *(const WORD*)(pFormat+2);
3048
3049     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3050
3051     if (pFormat[0] != RPC_FC_CVARRAY)
3052     {
3053         ERR("invalid format type %x\n", pFormat[0]);
3054         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3055         return NULL;
3056     }
3057
3058     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3059     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3060
3061     WriteConformance(pStubMsg);
3062     WriteVariance(pStubMsg);
3063
3064     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3065
3066     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3067
3068     pStubMsg->BufferMark = pStubMsg->Buffer;
3069     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
3070
3071     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3072
3073     return NULL;
3074 }
3075
3076
3077 /***********************************************************************
3078  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
3079  */
3080 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
3081                                                            unsigned char** ppMemory,
3082                                                            PFORMAT_STRING pFormat,
3083                                                            unsigned char fMustAlloc )
3084 {
3085     ULONG bufsize, memsize;
3086     unsigned char alignment = pFormat[1] + 1;
3087     DWORD esize = *(const WORD*)(pFormat+2);
3088     unsigned char *saved_buffer;
3089     ULONG offset;
3090
3091     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3092
3093     if (pFormat[0] != RPC_FC_CVARRAY)
3094     {
3095         ERR("invalid format type %x\n", pFormat[0]);
3096         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3097         return NULL;
3098     }
3099
3100     pFormat = ReadConformance(pStubMsg, pFormat+4);
3101     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3102
3103     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3104
3105     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3106     memsize = safe_multiply(esize, pStubMsg->MaxCount);
3107     offset = pStubMsg->Offset;
3108
3109     if (!*ppMemory || fMustAlloc)
3110         *ppMemory = NdrAllocate(pStubMsg, memsize);
3111     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3112     safe_buffer_increment(pStubMsg, bufsize);
3113
3114     EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3115
3116     memcpy(*ppMemory + offset, saved_buffer, bufsize);
3117
3118     return NULL;
3119 }
3120
3121
3122 /***********************************************************************
3123  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
3124  */
3125 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
3126                                            unsigned char* pMemory,
3127                                            PFORMAT_STRING pFormat )
3128 {
3129     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3130
3131     if (pFormat[0] != RPC_FC_CVARRAY)
3132     {
3133         ERR("invalid format type %x\n", pFormat[0]);
3134         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3135         return;
3136     }
3137
3138     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3139     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3140
3141     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3142 }
3143
3144
3145 /***********************************************************************
3146  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
3147  */
3148 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
3149                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
3150 {
3151     unsigned char alignment = pFormat[1] + 1;
3152     DWORD esize = *(const WORD*)(pFormat+2);
3153
3154     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3155
3156     if (pFormat[0] != RPC_FC_CVARRAY)
3157     {
3158         ERR("invalid format type %x\n", pFormat[0]);
3159         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3160         return;
3161     }
3162
3163     /* compute size */
3164     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3165     /* compute length */
3166     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3167
3168     SizeConformance(pStubMsg);
3169     SizeVariance(pStubMsg);
3170
3171     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3172
3173     safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
3174
3175     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3176 }
3177
3178
3179 /***********************************************************************
3180  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
3181  */
3182 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
3183                                                   PFORMAT_STRING pFormat )
3184 {
3185     ULONG bufsize, memsize;
3186     unsigned char alignment = pFormat[1] + 1;
3187     DWORD esize = *(const WORD*)(pFormat+2);
3188
3189     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3190
3191     if (pFormat[0] != RPC_FC_CVARRAY)
3192     {
3193         ERR("invalid format type %x\n", pFormat[0]);
3194         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3195         return pStubMsg->MemorySize;
3196     }
3197
3198     pFormat = ReadConformance(pStubMsg, pFormat+4);
3199     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3200
3201     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3202
3203     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3204     memsize = safe_multiply(esize, pStubMsg->MaxCount);
3205
3206     safe_buffer_increment(pStubMsg, bufsize);
3207     pStubMsg->MemorySize += memsize;
3208
3209     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3210
3211     return pStubMsg->MemorySize;
3212 }
3213
3214
3215 /***********************************************************************
3216  *           NdrComplexArrayMarshall [RPCRT4.@]
3217  */
3218 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3219                                                unsigned char *pMemory,
3220                                                PFORMAT_STRING pFormat)
3221 {
3222   ULONG i, count, def;
3223   BOOL variance_present;
3224   unsigned char alignment;
3225   int pointer_buffer_mark_set = 0;
3226
3227   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3228
3229   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3230   {
3231       ERR("invalid format type %x\n", pFormat[0]);
3232       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3233       return NULL;
3234   }
3235
3236   alignment = pFormat[1] + 1;
3237
3238   if (!pStubMsg->PointerBufferMark)
3239   {
3240     /* save buffer fields that may be changed by buffer sizer functions
3241      * and that may be needed later on */
3242     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3243     unsigned long saved_buffer_length = pStubMsg->BufferLength;
3244     unsigned long saved_max_count = pStubMsg->MaxCount;
3245     unsigned long saved_offset = pStubMsg->Offset;
3246     unsigned long saved_actual_count = pStubMsg->ActualCount;
3247
3248     /* get the buffer pointer after complex array data, but before
3249      * pointer data */
3250     pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
3251     pStubMsg->IgnoreEmbeddedPointers = 1;
3252     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3253     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3254
3255     /* save it for use by embedded pointer code later */
3256     pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
3257     TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
3258     pointer_buffer_mark_set = 1;
3259
3260     /* restore fields */
3261     pStubMsg->ActualCount = saved_actual_count;
3262     pStubMsg->Offset = saved_offset;
3263     pStubMsg->MaxCount = saved_max_count;
3264     pStubMsg->BufferLength = saved_buffer_length;
3265   }
3266
3267   def = *(const WORD*)&pFormat[2];
3268   pFormat += 4;
3269
3270   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3271   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3272
3273   variance_present = IsConformanceOrVariancePresent(pFormat);
3274   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3275   TRACE("variance = %d\n", pStubMsg->ActualCount);
3276
3277   WriteConformance(pStubMsg);
3278   if (variance_present)
3279     WriteVariance(pStubMsg);
3280
3281   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3282
3283   count = pStubMsg->ActualCount;
3284   for (i = 0; i < count; i++)
3285     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3286
3287   STD_OVERFLOW_CHECK(pStubMsg);
3288
3289   if (pointer_buffer_mark_set)
3290   {
3291     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3292     pStubMsg->PointerBufferMark = NULL;
3293   }
3294
3295   return NULL;
3296 }
3297
3298 /***********************************************************************
3299  *           NdrComplexArrayUnmarshall [RPCRT4.@]
3300  */
3301 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3302                                                  unsigned char **ppMemory,
3303                                                  PFORMAT_STRING pFormat,
3304                                                  unsigned char fMustAlloc)
3305 {
3306   ULONG i, count, size;
3307   unsigned char alignment;
3308   unsigned char *pMemory;
3309   unsigned char *saved_buffer;
3310   int pointer_buffer_mark_set = 0;
3311   int saved_ignore_embedded;
3312
3313   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
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   saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3325   /* save buffer pointer */
3326   saved_buffer = pStubMsg->Buffer;
3327   /* get the buffer pointer after complex array data, but before
3328    * pointer data */
3329   pStubMsg->IgnoreEmbeddedPointers = 1;
3330   pStubMsg->MemorySize = 0;
3331   NdrComplexArrayMemorySize(pStubMsg, pFormat);
3332   size = pStubMsg->MemorySize;
3333   pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3334
3335   TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
3336   if (!pStubMsg->PointerBufferMark)
3337   {
3338     /* save it for use by embedded pointer code later */
3339     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3340     pointer_buffer_mark_set = 1;
3341   }
3342   /* restore the original buffer */
3343   pStubMsg->Buffer = saved_buffer;
3344
3345   pFormat += 4;
3346
3347   pFormat = ReadConformance(pStubMsg, pFormat);
3348   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3349
3350   if (fMustAlloc || !*ppMemory)
3351   {
3352     *ppMemory = NdrAllocate(pStubMsg, size);
3353     memset(*ppMemory, 0, size);
3354   }
3355
3356   ALIGN_POINTER(pStubMsg->Buffer, alignment);
3357
3358   pMemory = *ppMemory;
3359   count = pStubMsg->ActualCount;
3360   for (i = 0; i < count; i++)
3361     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
3362
3363   if (pointer_buffer_mark_set)
3364   {
3365     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3366     pStubMsg->PointerBufferMark = NULL;
3367   }
3368
3369   return NULL;
3370 }
3371
3372 /***********************************************************************
3373  *           NdrComplexArrayBufferSize [RPCRT4.@]
3374  */
3375 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3376                                       unsigned char *pMemory,
3377                                       PFORMAT_STRING pFormat)
3378 {
3379   ULONG i, count, def;
3380   unsigned char alignment;
3381   BOOL variance_present;
3382   int pointer_length_set = 0;
3383
3384   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3385
3386   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3387   {
3388       ERR("invalid format type %x\n", pFormat[0]);
3389       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3390       return;
3391   }
3392
3393   alignment = pFormat[1] + 1;
3394
3395   if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3396   {
3397     /* save buffer fields that may be changed by buffer sizer functions
3398      * and that may be needed later on */
3399     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3400     unsigned long saved_buffer_length = pStubMsg->BufferLength;
3401     unsigned long saved_max_count = pStubMsg->MaxCount;
3402     unsigned long saved_offset = pStubMsg->Offset;
3403     unsigned long saved_actual_count = pStubMsg->ActualCount;
3404
3405     /* get the buffer pointer after complex array data, but before
3406      * pointer data */
3407     pStubMsg->IgnoreEmbeddedPointers = 1;
3408     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3409     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3410
3411     /* save it for use by embedded pointer code later */
3412     pStubMsg->PointerLength = pStubMsg->BufferLength;
3413     pointer_length_set = 1;
3414
3415     /* restore fields */
3416     pStubMsg->ActualCount = saved_actual_count;
3417     pStubMsg->Offset = saved_offset;
3418     pStubMsg->MaxCount = saved_max_count;
3419     pStubMsg->BufferLength = saved_buffer_length;
3420   }
3421   def = *(const WORD*)&pFormat[2];
3422   pFormat += 4;
3423
3424   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3425   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3426   SizeConformance(pStubMsg);
3427
3428   variance_present = IsConformanceOrVariancePresent(pFormat);
3429   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3430   TRACE("variance = %d\n", pStubMsg->ActualCount);
3431
3432   if (variance_present)
3433     SizeVariance(pStubMsg);
3434
3435   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3436
3437   count = pStubMsg->ActualCount;
3438   for (i = 0; i < count; i++)
3439     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
3440
3441   if(pointer_length_set)
3442   {
3443     pStubMsg->BufferLength = pStubMsg->PointerLength;
3444     pStubMsg->PointerLength = 0;
3445   }
3446 }
3447
3448 /***********************************************************************
3449  *           NdrComplexArrayMemorySize [RPCRT4.@]
3450  */
3451 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3452                                        PFORMAT_STRING pFormat)
3453 {
3454   ULONG i, count, esize, SavedMemorySize, MemorySize;
3455   unsigned char alignment;
3456   unsigned char *Buffer;
3457
3458   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3459
3460   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3461   {
3462       ERR("invalid format type %x\n", pFormat[0]);
3463       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3464       return 0;
3465   }
3466
3467   alignment = pFormat[1] + 1;
3468
3469   pFormat += 4;
3470
3471   pFormat = ReadConformance(pStubMsg, pFormat);
3472   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3473
3474   ALIGN_POINTER(pStubMsg->Buffer, alignment);
3475
3476   SavedMemorySize = pStubMsg->MemorySize;
3477
3478   Buffer = pStubMsg->Buffer;
3479   pStubMsg->MemorySize = 0;
3480   esize = ComplexStructMemorySize(pStubMsg, pFormat);
3481   pStubMsg->Buffer = Buffer;
3482
3483   MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3484
3485   count = pStubMsg->ActualCount;
3486   for (i = 0; i < count; i++)
3487     ComplexStructMemorySize(pStubMsg, pFormat);
3488
3489   pStubMsg->MemorySize = SavedMemorySize;
3490
3491   pStubMsg->MemorySize += MemorySize;
3492   return MemorySize;
3493 }
3494
3495 /***********************************************************************
3496  *           NdrComplexArrayFree [RPCRT4.@]
3497  */
3498 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3499                                 unsigned char *pMemory,
3500                                 PFORMAT_STRING pFormat)
3501 {
3502   ULONG i, count, def;
3503
3504   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3505
3506   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3507   {
3508       ERR("invalid format type %x\n", pFormat[0]);
3509       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3510       return;
3511   }
3512
3513   def = *(const WORD*)&pFormat[2];
3514   pFormat += 4;
3515
3516   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3517   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3518
3519   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3520   TRACE("variance = %d\n", pStubMsg->ActualCount);
3521
3522   count = pStubMsg->ActualCount;
3523   for (i = 0; i < count; i++)
3524     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
3525 }
3526
3527 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
3528                           USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
3529                           USER_MARSHAL_CB *umcb)
3530 {
3531   umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
3532                          pStubMsg->RpcMsg->DataRepresentation);
3533   umcb->pStubMsg = pStubMsg;
3534   umcb->pReserve = NULL;
3535   umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
3536   umcb->CBType = cbtype;
3537   umcb->pFormat = pFormat;
3538   umcb->pTypeFormat = NULL /* FIXME */;
3539 }
3540
3541 #define USER_MARSHAL_PTR_PREFIX \
3542         ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
3543         ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
3544
3545 /***********************************************************************
3546  *           NdrUserMarshalMarshall [RPCRT4.@]
3547  */
3548 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3549                                               unsigned char *pMemory,
3550                                               PFORMAT_STRING pFormat)
3551 {
3552   unsigned flags = pFormat[1];
3553   unsigned index = *(const WORD*)&pFormat[2];
3554   unsigned char *saved_buffer = NULL;
3555   USER_MARSHAL_CB umcb;
3556
3557   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3558   TRACE("index=%d\n", index);
3559
3560   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
3561
3562   if (flags & USER_MARSHAL_POINTER)
3563   {
3564     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
3565     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
3566     pStubMsg->Buffer += 4;
3567     if (pStubMsg->PointerBufferMark)
3568     {
3569       saved_buffer = pStubMsg->Buffer;
3570       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3571       pStubMsg->PointerBufferMark = NULL;
3572     }
3573     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8);
3574   }
3575   else
3576     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1);
3577
3578   pStubMsg->Buffer =
3579     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
3580       &umcb.Flags, pStubMsg->Buffer, pMemory);
3581
3582   if (saved_buffer)
3583   {
3584     STD_OVERFLOW_CHECK(pStubMsg);
3585     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3586     pStubMsg->Buffer = saved_buffer;
3587   }
3588
3589   STD_OVERFLOW_CHECK(pStubMsg);
3590
3591   return NULL;
3592 }
3593
3594 /***********************************************************************
3595  *           NdrUserMarshalUnmarshall [RPCRT4.@]
3596  */
3597 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3598                                                  unsigned char **ppMemory,
3599                                                  PFORMAT_STRING pFormat,
3600                                                  unsigned char fMustAlloc)
3601 {
3602   unsigned flags = pFormat[1];
3603   unsigned index = *(const WORD*)&pFormat[2];
3604   DWORD memsize = *(const WORD*)&pFormat[4];
3605   unsigned char *saved_buffer = NULL;
3606   USER_MARSHAL_CB umcb;
3607
3608   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3609   TRACE("index=%d\n", index);
3610
3611   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
3612
3613   if (flags & USER_MARSHAL_POINTER)
3614   {
3615     ALIGN_POINTER(pStubMsg->Buffer, 4);
3616     /* skip pointer prefix */
3617     pStubMsg->Buffer += 4;
3618     if (pStubMsg->PointerBufferMark)
3619     {
3620       saved_buffer = pStubMsg->Buffer;
3621       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3622       pStubMsg->PointerBufferMark = NULL;
3623     }
3624     ALIGN_POINTER(pStubMsg->Buffer, 8);
3625   }
3626   else
3627     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3628
3629   if (fMustAlloc || !*ppMemory)
3630     *ppMemory = NdrAllocate(pStubMsg, memsize);
3631
3632   pStubMsg->Buffer =
3633     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
3634       &umcb.Flags, pStubMsg->Buffer, *ppMemory);
3635
3636   if (saved_buffer)
3637   {
3638     STD_OVERFLOW_CHECK(pStubMsg);
3639     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3640     pStubMsg->Buffer = saved_buffer;
3641   }
3642
3643   return NULL;
3644 }
3645
3646 /***********************************************************************
3647  *           NdrUserMarshalBufferSize [RPCRT4.@]
3648  */
3649 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3650                                       unsigned char *pMemory,
3651                                       PFORMAT_STRING pFormat)
3652 {
3653   unsigned flags = pFormat[1];
3654   unsigned index = *(const WORD*)&pFormat[2];
3655   DWORD bufsize = *(const WORD*)&pFormat[6];
3656   USER_MARSHAL_CB umcb;
3657   unsigned long saved_buffer_length = 0;
3658
3659   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3660   TRACE("index=%d\n", index);
3661
3662   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
3663
3664   if (flags & USER_MARSHAL_POINTER)
3665   {
3666     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3667     /* skip pointer prefix */
3668     safe_buffer_length_increment(pStubMsg, 4);
3669     if (pStubMsg->IgnoreEmbeddedPointers)
3670       return;
3671     if (pStubMsg->PointerLength)
3672     {
3673       saved_buffer_length = pStubMsg->BufferLength;
3674       pStubMsg->BufferLength = pStubMsg->PointerLength;
3675       pStubMsg->PointerLength = 0;
3676     }
3677     ALIGN_LENGTH(pStubMsg->BufferLength, 8);
3678   }
3679   else
3680     ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
3681
3682   if (bufsize) {
3683     TRACE("size=%d\n", bufsize);
3684     safe_buffer_length_increment(pStubMsg, bufsize);
3685   }
3686   else
3687     pStubMsg->BufferLength =
3688         pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
3689                              &umcb.Flags, pStubMsg->BufferLength, pMemory);
3690
3691   if (saved_buffer_length)
3692   {
3693     pStubMsg->PointerLength = pStubMsg->BufferLength;
3694     pStubMsg->BufferLength = saved_buffer_length;
3695   }
3696
3697 }
3698
3699 /***********************************************************************
3700  *           NdrUserMarshalMemorySize [RPCRT4.@]
3701  */
3702 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3703                                       PFORMAT_STRING pFormat)
3704 {
3705   unsigned flags = pFormat[1];
3706   unsigned index = *(const WORD*)&pFormat[2];
3707   DWORD memsize = *(const WORD*)&pFormat[4];
3708   DWORD bufsize = *(const WORD*)&pFormat[6];
3709
3710   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3711   TRACE("index=%d\n", index);
3712
3713   pStubMsg->MemorySize += memsize;
3714
3715   if (flags & USER_MARSHAL_POINTER)
3716   {
3717     ALIGN_POINTER(pStubMsg->Buffer, 4);
3718     /* skip pointer prefix */
3719     pStubMsg->Buffer += 4;
3720     if (pStubMsg->IgnoreEmbeddedPointers)
3721       return pStubMsg->MemorySize;
3722     ALIGN_POINTER(pStubMsg->Buffer, 8);
3723   }
3724   else
3725     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3726
3727   if (!bufsize)
3728     FIXME("not implemented for varying buffer size\n");
3729
3730   pStubMsg->Buffer += bufsize;
3731
3732   return pStubMsg->MemorySize;
3733 }
3734
3735 /***********************************************************************
3736  *           NdrUserMarshalFree [RPCRT4.@]
3737  */
3738 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
3739                                 unsigned char *pMemory,
3740                                 PFORMAT_STRING pFormat)
3741 {
3742 /*  unsigned flags = pFormat[1]; */
3743   unsigned index = *(const WORD*)&pFormat[2];
3744   USER_MARSHAL_CB umcb;
3745
3746   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3747   TRACE("index=%d\n", index);
3748
3749   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
3750
3751   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
3752     &umcb.Flags, pMemory);
3753 }
3754
3755 /***********************************************************************
3756  *           NdrClearOutParameters [RPCRT4.@]
3757  */
3758 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
3759                                   PFORMAT_STRING pFormat,
3760                                   void *ArgAddr)
3761 {
3762   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
3763 }
3764
3765 /***********************************************************************
3766  *           NdrConvert [RPCRT4.@]
3767  */
3768 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
3769 {
3770   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
3771   /* FIXME: since this stub doesn't do any converting, the proper behavior
3772      is to raise an exception */
3773 }
3774
3775 /***********************************************************************
3776  *           NdrConvert2 [RPCRT4.@]
3777  */
3778 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
3779 {
3780   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
3781     pStubMsg, pFormat, NumberParams);
3782   /* FIXME: since this stub doesn't do any converting, the proper behavior
3783      is to raise an exception */
3784 }
3785
3786 #include "pshpack1.h"
3787 typedef struct _NDR_CSTRUCT_FORMAT
3788 {
3789     unsigned char type;
3790     unsigned char alignment;
3791     unsigned short memory_size;
3792     short offset_to_array_description;
3793 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
3794 #include "poppack.h"
3795
3796 /***********************************************************************
3797  *           NdrConformantStructMarshall [RPCRT4.@]
3798  */
3799 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3800                                 unsigned char *pMemory,
3801                                 PFORMAT_STRING pFormat)
3802 {
3803     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3804     PFORMAT_STRING pCArrayFormat;
3805     ULONG esize, bufsize;
3806
3807     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3808
3809     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3810     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3811     {
3812         ERR("invalid format type %x\n", pCStructFormat->type);
3813         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3814         return NULL;
3815     }
3816
3817     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3818         pCStructFormat->offset_to_array_description;
3819     if (*pCArrayFormat != RPC_FC_CARRAY)
3820     {
3821         ERR("invalid array format type %x\n", pCStructFormat->type);
3822         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3823         return NULL;
3824     }
3825     esize = *(const WORD*)(pCArrayFormat+2);
3826
3827     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3828                        pCArrayFormat + 4, 0);
3829
3830     WriteConformance(pStubMsg);
3831
3832     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3833
3834     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3835
3836     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3837     if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3838     {
3839         ERR("integer overflow of memory_size %u with bufsize %u\n",
3840             pCStructFormat->memory_size, bufsize);
3841         RpcRaiseException(RPC_X_BAD_STUB_DATA);
3842     }
3843     /* copy constant sized part of struct */
3844     pStubMsg->BufferMark = pStubMsg->Buffer;
3845     safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
3846
3847     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3848         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3849
3850     return NULL;
3851 }
3852
3853 /***********************************************************************
3854  *           NdrConformantStructUnmarshall [RPCRT4.@]
3855  */
3856 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3857                                 unsigned char **ppMemory,
3858                                 PFORMAT_STRING pFormat,
3859                                 unsigned char fMustAlloc)
3860 {
3861     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3862     PFORMAT_STRING pCArrayFormat;
3863     ULONG esize, bufsize;
3864     unsigned char *saved_buffer;
3865
3866     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3867
3868     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3869     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3870     {
3871         ERR("invalid format type %x\n", pCStructFormat->type);
3872         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3873         return NULL;
3874     }
3875     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3876         pCStructFormat->offset_to_array_description;
3877     if (*pCArrayFormat != RPC_FC_CARRAY)
3878     {
3879         ERR("invalid array format type %x\n", pCStructFormat->type);
3880         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3881         return NULL;
3882     }
3883     esize = *(const WORD*)(pCArrayFormat+2);
3884
3885     pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
3886
3887     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3888
3889     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3890
3891     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3892     if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3893     {
3894         ERR("integer overflow of memory_size %u with bufsize %u\n",
3895             pCStructFormat->memory_size, bufsize);
3896         RpcRaiseException(RPC_X_BAD_STUB_DATA);
3897     }
3898
3899     if (fMustAlloc)
3900     {
3901         SIZE_T size = pCStructFormat->memory_size + bufsize;
3902         *ppMemory = NdrAllocate(pStubMsg, size);
3903     }
3904     else
3905     {
3906         if (!pStubMsg->IsClient && !*ppMemory)
3907             /* for servers, we just point straight into the RPC buffer */
3908             *ppMemory = pStubMsg->Buffer;
3909     }
3910
3911     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3912     safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
3913     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3914         EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3915
3916     TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
3917     if (*ppMemory != saved_buffer)
3918         memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
3919
3920     return NULL;
3921 }
3922
3923 /***********************************************************************
3924  *           NdrConformantStructBufferSize [RPCRT4.@]
3925  */
3926 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3927                                 unsigned char *pMemory,
3928                                 PFORMAT_STRING pFormat)
3929 {
3930     const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3931     PFORMAT_STRING pCArrayFormat;
3932     ULONG esize;
3933
3934     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3935
3936     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3937     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3938     {
3939         ERR("invalid format type %x\n", pCStructFormat->type);
3940         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3941         return;
3942     }
3943     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3944         pCStructFormat->offset_to_array_description;
3945     if (*pCArrayFormat != RPC_FC_CARRAY)
3946     {
3947         ERR("invalid array format type %x\n", pCStructFormat->type);
3948         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3949         return;
3950     }
3951     esize = *(const WORD*)(pCArrayFormat+2);
3952
3953     pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
3954     SizeConformance(pStubMsg);
3955
3956     ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
3957
3958     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3959
3960     safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
3961     safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
3962
3963     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3964         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3965 }
3966
3967 /***********************************************************************
3968  *           NdrConformantStructMemorySize [RPCRT4.@]
3969  */
3970 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3971                                 PFORMAT_STRING pFormat)
3972 {
3973     FIXME("stub\n");
3974     return 0;
3975 }
3976
3977 /***********************************************************************
3978  *           NdrConformantStructFree [RPCRT4.@]
3979  */
3980 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3981                                 unsigned char *pMemory,
3982                                 PFORMAT_STRING pFormat)
3983 {
3984     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3985     PFORMAT_STRING pCArrayFormat;
3986     ULONG esize;
3987
3988     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3989
3990     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3991     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3992     {
3993         ERR("invalid format type %x\n", pCStructFormat->type);
3994         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3995         return;
3996     }
3997
3998     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3999         pCStructFormat->offset_to_array_description;
4000     if (*pCArrayFormat != RPC_FC_CARRAY)
4001     {
4002         ERR("invalid array format type %x\n", pCStructFormat->type);
4003         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4004         return;
4005     }
4006     esize = *(const WORD*)(pCArrayFormat+2);
4007
4008     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4009                        pCArrayFormat + 4, 0);
4010
4011     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4012
4013     /* copy constant sized part of struct */
4014     pStubMsg->BufferMark = pStubMsg->Buffer;
4015
4016     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4017         EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4018 }
4019
4020 /***********************************************************************
4021  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
4022  */
4023 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4024                                 unsigned char *pMemory,
4025                                 PFORMAT_STRING pFormat)
4026 {
4027     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4028     PFORMAT_STRING pCVArrayFormat;
4029     ULONG esize, bufsize;
4030
4031     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4032
4033     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4034     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4035     {
4036         ERR("invalid format type %x\n", pCVStructFormat->type);
4037         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4038         return NULL;
4039     }
4040
4041     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4042         pCVStructFormat->offset_to_array_description;
4043     switch (*pCVArrayFormat)
4044     {
4045     case RPC_FC_CVARRAY:
4046         esize = *(const WORD*)(pCVArrayFormat+2);
4047
4048         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4049                                             pCVArrayFormat + 4, 0);
4050         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4051                                          pCVArrayFormat, 0);
4052         break;
4053     case RPC_FC_C_CSTRING:
4054         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4055         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4056         esize = sizeof(char);
4057         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4058             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4059                                                 pCVArrayFormat + 2, 0);
4060         else
4061             pStubMsg->MaxCount = pStubMsg->ActualCount;
4062         break;
4063     case RPC_FC_C_WSTRING:
4064         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4065         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4066         esize = sizeof(WCHAR);
4067         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4068             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4069                                                 pCVArrayFormat + 2, 0);
4070         else
4071             pStubMsg->MaxCount = pStubMsg->ActualCount;
4072         break;
4073     default:
4074         ERR("invalid array format type %x\n", *pCVArrayFormat);
4075         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4076         return NULL;
4077     }
4078
4079     WriteConformance(pStubMsg);
4080
4081     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4082
4083     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4084
4085     /* write constant sized part */
4086     pStubMsg->BufferMark = pStubMsg->Buffer;
4087     safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
4088
4089     WriteVariance(pStubMsg);
4090
4091     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4092
4093     /* write array part */
4094     safe_copy_to_buffer(pStubMsg, pMemory + pCVStructFormat->memory_size, bufsize);
4095
4096     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4097
4098     return NULL;
4099 }
4100
4101 /***********************************************************************
4102  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
4103  */
4104 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4105                                 unsigned char **ppMemory,
4106                                 PFORMAT_STRING pFormat,
4107                                 unsigned char fMustAlloc)
4108 {
4109     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4110     PFORMAT_STRING pCVArrayFormat;
4111     ULONG esize, bufsize;
4112     unsigned char cvarray_type;
4113
4114     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4115
4116     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4117     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4118     {
4119         ERR("invalid format type %x\n", pCVStructFormat->type);
4120         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4121         return NULL;
4122     }
4123
4124     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4125         pCVStructFormat->offset_to_array_description;
4126     cvarray_type = *pCVArrayFormat;
4127     switch (cvarray_type)
4128     {
4129     case RPC_FC_CVARRAY:
4130         esize = *(const WORD*)(pCVArrayFormat+2);
4131         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
4132         break;
4133     case RPC_FC_C_CSTRING:
4134         esize = sizeof(char);
4135         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4136             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4137         else
4138             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4139         break;
4140     case RPC_FC_C_WSTRING:
4141         esize = sizeof(WCHAR);
4142         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4143             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4144         else
4145             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4146         break;
4147     default:
4148         ERR("invalid array format type %x\n", *pCVArrayFormat);
4149         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4150         return NULL;
4151     }
4152
4153     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4154
4155     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4156
4157     /* work out how much memory to allocate if we need to do so */
4158     if (!*ppMemory || fMustAlloc)
4159     {
4160         SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
4161         *ppMemory = NdrAllocate(pStubMsg, size);
4162     }
4163
4164     /* copy the constant data */
4165     pStubMsg->BufferMark = pStubMsg->Buffer;
4166     safe_copy_from_buffer(pStubMsg, *ppMemory, pCVStructFormat->memory_size);
4167
4168     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
4169
4170     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4171
4172     if ((cvarray_type == RPC_FC_C_CSTRING) ||
4173         (cvarray_type == RPC_FC_C_WSTRING))
4174     {
4175         ULONG i;
4176         /* strings must always have null terminating bytes */
4177         if (bufsize < esize)
4178         {
4179             ERR("invalid string length of %d\n", pStubMsg->ActualCount);
4180             RpcRaiseException(RPC_S_INVALID_BOUND);
4181             return NULL;
4182         }
4183         for (i = bufsize - esize; i < bufsize; i++)
4184             if (pStubMsg->Buffer[i] != 0)
4185             {
4186                 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
4187                     i, pStubMsg->Buffer[i]);
4188                 RpcRaiseException(RPC_S_INVALID_BOUND);
4189                 return NULL;
4190             }
4191     }
4192
4193     /* copy the array data */
4194     safe_copy_from_buffer(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize);
4195
4196     if (cvarray_type == RPC_FC_C_CSTRING)
4197         TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
4198     else if (cvarray_type == RPC_FC_C_WSTRING)
4199         TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
4200
4201     EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
4202
4203     return NULL;
4204 }
4205
4206 /***********************************************************************
4207  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
4208  */
4209 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4210                                 unsigned char *pMemory,
4211                                 PFORMAT_STRING pFormat)
4212 {
4213     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4214     PFORMAT_STRING pCVArrayFormat;
4215     ULONG esize;
4216
4217     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4218
4219     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4220     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4221     {
4222         ERR("invalid format type %x\n", pCVStructFormat->type);
4223         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4224         return;
4225     }
4226
4227     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4228         pCVStructFormat->offset_to_array_description;
4229     switch (*pCVArrayFormat)
4230     {
4231     case RPC_FC_CVARRAY:
4232         esize = *(const WORD*)(pCVArrayFormat+2);
4233
4234         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4235                                             pCVArrayFormat + 4, 0);
4236         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4237                                          pCVArrayFormat, 0);
4238         break;
4239     case RPC_FC_C_CSTRING:
4240         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4241         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4242         esize = sizeof(char);
4243         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4244             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4245                                                 pCVArrayFormat + 2, 0);
4246         else
4247             pStubMsg->MaxCount = pStubMsg->ActualCount;
4248         break;
4249     case RPC_FC_C_WSTRING:
4250         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4251         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4252         esize = sizeof(WCHAR);
4253         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4254             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4255                                                 pCVArrayFormat + 2, 0);
4256         else
4257             pStubMsg->MaxCount = pStubMsg->ActualCount;
4258         break;
4259     default:
4260         ERR("invalid array format type %x\n", *pCVArrayFormat);
4261         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4262         return;
4263     }
4264
4265     SizeConformance(pStubMsg);
4266
4267     ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4268
4269     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4270
4271     safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4272     SizeVariance(pStubMsg);
4273     safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4274
4275     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4276 }
4277
4278 /***********************************************************************
4279  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
4280  */
4281 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4282                                 PFORMAT_STRING pFormat)
4283 {
4284     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4285     PFORMAT_STRING pCVArrayFormat;
4286     ULONG esize;
4287     unsigned char cvarray_type;
4288
4289     TRACE("(%p, %p)\n", pStubMsg, pFormat);
4290
4291     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4292     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4293     {
4294         ERR("invalid format type %x\n", pCVStructFormat->type);
4295         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4296         return 0;
4297     }
4298
4299     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4300         pCVStructFormat->offset_to_array_description;
4301     cvarray_type = *pCVArrayFormat;
4302     switch (cvarray_type)
4303     {
4304     case RPC_FC_CVARRAY:
4305         esize = *(const WORD*)(pCVArrayFormat+2);
4306         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
4307         break;
4308     case RPC_FC_C_CSTRING:
4309         esize = sizeof(char);
4310         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4311             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4312         else
4313             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4314         break;
4315     case RPC_FC_C_WSTRING:
4316         esize = sizeof(WCHAR);
4317         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4318             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4319         else
4320             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4321         break;
4322     default:
4323         ERR("invalid array format type %x\n", *pCVArrayFormat);
4324         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4325         return 0;
4326     }
4327
4328     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4329
4330     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4331
4332     safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4333     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
4334     safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4335
4336     pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
4337
4338     EmbeddedPointerMemorySize(pStubMsg, pFormat);
4339
4340     return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
4341 }
4342
4343 /***********************************************************************
4344  *           NdrConformantVaryingStructFree [RPCRT4.@]
4345  */
4346 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4347                                 unsigned char *pMemory,
4348                                 PFORMAT_STRING pFormat)
4349 {
4350     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4351     PFORMAT_STRING pCVArrayFormat;
4352     ULONG esize;
4353
4354     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4355
4356     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4357     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4358     {
4359         ERR("invalid format type %x\n", pCVStructFormat->type);
4360         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4361         return;
4362     }
4363
4364     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4365         pCVStructFormat->offset_to_array_description;
4366     switch (*pCVArrayFormat)
4367     {
4368     case RPC_FC_CVARRAY:
4369         esize = *(const WORD*)(pCVArrayFormat+2);
4370
4371         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4372                                             pCVArrayFormat + 4, 0);
4373         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4374                                          pCVArrayFormat, 0);
4375         break;
4376     case RPC_FC_C_CSTRING:
4377         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4378         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4379         esize = sizeof(char);
4380         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4381             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4382                                                 pCVArrayFormat + 2, 0);
4383         else
4384             pStubMsg->MaxCount = pStubMsg->ActualCount;
4385         break;
4386     case RPC_FC_C_WSTRING:
4387         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4388         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4389         esize = sizeof(WCHAR);
4390         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4391             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4392                                                 pCVArrayFormat + 2, 0);
4393         else
4394             pStubMsg->MaxCount = pStubMsg->ActualCount;
4395         break;
4396     default:
4397         ERR("invalid array format type %x\n", *pCVArrayFormat);
4398         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4399         return;
4400     }
4401
4402     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4403
4404     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4405 }
4406
4407 #include "pshpack1.h"
4408 typedef struct
4409 {
4410     unsigned char type;
4411     unsigned char alignment;
4412     unsigned short total_size;
4413 } NDR_SMFARRAY_FORMAT;
4414
4415 typedef struct
4416 {
4417     unsigned char type;
4418     unsigned char alignment;
4419     unsigned long total_size;
4420 } NDR_LGFARRAY_FORMAT;
4421 #include "poppack.h"
4422
4423 /***********************************************************************
4424  *           NdrFixedArrayMarshall [RPCRT4.@]
4425  */
4426 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4427                                 unsigned char *pMemory,
4428                                 PFORMAT_STRING pFormat)
4429 {
4430     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4431     unsigned long total_size;
4432
4433     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4434
4435     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4436         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4437     {
4438         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4439         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4440         return NULL;
4441     }
4442
4443     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4444
4445     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4446     {
4447         total_size = pSmFArrayFormat->total_size;
4448         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4449     }
4450     else
4451     {
4452         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4453         total_size = pLgFArrayFormat->total_size;
4454         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4455     }
4456
4457     pStubMsg->BufferMark = pStubMsg->Buffer;
4458     safe_copy_to_buffer(pStubMsg, pMemory, total_size);
4459
4460     pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4461
4462     return NULL;
4463 }
4464
4465 /***********************************************************************
4466  *           NdrFixedArrayUnmarshall [RPCRT4.@]
4467  */
4468 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4469                                 unsigned char **ppMemory,
4470                                 PFORMAT_STRING pFormat,
4471                                 unsigned char fMustAlloc)
4472 {
4473     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4474     unsigned long total_size;
4475     unsigned char *saved_buffer;
4476
4477     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4478
4479     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4480         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4481     {
4482         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4483         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4484         return NULL;
4485     }
4486
4487     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4488
4489     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4490     {
4491         total_size = pSmFArrayFormat->total_size;
4492         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4493     }
4494     else
4495     {
4496         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4497         total_size = pLgFArrayFormat->total_size;
4498         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4499     }
4500
4501     if (fMustAlloc)
4502         *ppMemory = NdrAllocate(pStubMsg, total_size);
4503     else
4504     {
4505         if (!pStubMsg->IsClient && !*ppMemory)
4506             /* for servers, we just point straight into the RPC buffer */
4507             *ppMemory = pStubMsg->Buffer;
4508     }
4509
4510     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4511     safe_buffer_increment(pStubMsg, total_size);
4512     pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4513
4514     TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4515     if (*ppMemory != saved_buffer)
4516         memcpy(*ppMemory, saved_buffer, total_size);
4517
4518     return NULL;
4519 }
4520
4521 /***********************************************************************
4522  *           NdrFixedArrayBufferSize [RPCRT4.@]
4523  */
4524 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4525                                 unsigned char *pMemory,
4526                                 PFORMAT_STRING pFormat)
4527 {
4528     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4529     unsigned long total_size;
4530
4531     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4532
4533     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4534         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4535     {
4536         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4537         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4538         return;
4539     }
4540
4541     ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
4542
4543     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4544     {
4545         total_size = pSmFArrayFormat->total_size;
4546         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4547     }
4548     else
4549     {
4550         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4551         total_size = pLgFArrayFormat->total_size;
4552         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4553     }
4554     safe_buffer_length_increment(pStubMsg, total_size);
4555
4556     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4557 }
4558
4559 /***********************************************************************
4560  *           NdrFixedArrayMemorySize [RPCRT4.@]
4561  */
4562 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4563                                 PFORMAT_STRING pFormat)
4564 {
4565     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4566     ULONG total_size;
4567
4568     TRACE("(%p, %p)\n", pStubMsg, pFormat);
4569
4570     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4571         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4572     {
4573         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4574         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4575         return 0;
4576     }
4577
4578     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4579
4580     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4581     {
4582         total_size = pSmFArrayFormat->total_size;
4583         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4584     }
4585     else
4586     {
4587         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4588         total_size = pLgFArrayFormat->total_size;
4589         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4590     }
4591     pStubMsg->BufferMark = pStubMsg->Buffer;
4592     safe_buffer_increment(pStubMsg, total_size);
4593     pStubMsg->MemorySize += total_size;
4594
4595     EmbeddedPointerMemorySize(pStubMsg, pFormat);
4596
4597     return total_size;
4598 }
4599
4600 /***********************************************************************
4601  *           NdrFixedArrayFree [RPCRT4.@]
4602  */
4603 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4604                                 unsigned char *pMemory,
4605                                 PFORMAT_STRING pFormat)
4606 {
4607     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4608
4609     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4610
4611     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4612         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4613     {
4614         ERR("invalid format type %x\n", pSmFArrayFormat->type);
4615         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4616         return;
4617     }
4618
4619     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4620         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4621     else
4622     {
4623         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4624         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4625     }
4626
4627     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4628 }
4629
4630 /***********************************************************************
4631  *           NdrVaryingArrayMarshall [RPCRT4.@]
4632  */
4633 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4634                                 unsigned char *pMemory,
4635                                 PFORMAT_STRING pFormat)
4636 {
4637     unsigned char alignment;
4638     DWORD elements, esize;
4639     ULONG bufsize;
4640
4641     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4642
4643     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4644         (pFormat[0] != RPC_FC_LGVARRAY))
4645     {
4646         ERR("invalid format type %x\n", pFormat[0]);
4647         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4648         return NULL;
4649     }
4650
4651     alignment = pFormat[1] + 1;
4652
4653     if (pFormat[0] == RPC_FC_SMVARRAY)
4654     {
4655         pFormat += 2;
4656         pFormat += sizeof(WORD);
4657         elements = *(const WORD*)pFormat;
4658         pFormat += sizeof(WORD);
4659     }
4660     else
4661     {
4662         pFormat += 2;
4663         pFormat += sizeof(DWORD);
4664         elements = *(const DWORD*)pFormat;
4665         pFormat += sizeof(DWORD);
4666     }
4667
4668     esize = *(const WORD*)pFormat;
4669     pFormat += sizeof(WORD);
4670
4671     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4672     if ((pStubMsg->ActualCount > elements) ||
4673         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4674     {
4675         RpcRaiseException(RPC_S_INVALID_BOUND);
4676         return NULL;
4677     }
4678
4679     WriteVariance(pStubMsg);
4680
4681     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
4682
4683     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4684     pStubMsg->BufferMark = pStubMsg->Buffer;
4685     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
4686
4687     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4688
4689     return NULL;
4690 }
4691
4692 /***********************************************************************
4693  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
4694  */
4695 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4696                                 unsigned char **ppMemory,
4697                                 PFORMAT_STRING pFormat,
4698                                 unsigned char fMustAlloc)
4699 {
4700     unsigned char alignment;
4701     DWORD size, elements, esize;
4702     ULONG bufsize;
4703     unsigned char *saved_buffer;
4704     ULONG offset;
4705
4706     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4707
4708     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4709         (pFormat[0] != RPC_FC_LGVARRAY))
4710     {
4711         ERR("invalid format type %x\n", pFormat[0]);
4712         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4713         return NULL;
4714     }
4715
4716     alignment = pFormat[1] + 1;
4717
4718     if (pFormat[0] == RPC_FC_SMVARRAY)
4719     {
4720         pFormat += 2;
4721         size = *(const WORD*)pFormat;
4722         pFormat += sizeof(WORD);
4723         elements = *(const WORD*)pFormat;
4724         pFormat += sizeof(WORD);
4725     }
4726     else
4727     {
4728         pFormat += 2;
4729         size = *(const DWORD*)pFormat;
4730         pFormat += sizeof(DWORD);
4731         elements = *(const DWORD*)pFormat;
4732         pFormat += sizeof(DWORD);
4733     }
4734
4735     esize = *(const WORD*)pFormat;
4736     pFormat += sizeof(WORD);
4737
4738     pFormat = ReadVariance(pStubMsg, pFormat, elements);
4739
4740     ALIGN_POINTER(pStubMsg->Buffer, alignment);
4741
4742     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4743     offset = pStubMsg->Offset;
4744
4745     if (!*ppMemory || fMustAlloc)
4746         *ppMemory = NdrAllocate(pStubMsg, size);
4747     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4748     safe_buffer_increment(pStubMsg, bufsize);
4749
4750     EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4751
4752     memcpy(*ppMemory + offset, saved_buffer, bufsize);
4753
4754     return NULL;
4755 }
4756
4757 /***********************************************************************
4758  *           NdrVaryingArrayBufferSize [RPCRT4.@]
4759  */
4760 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4761                                 unsigned char *pMemory,
4762                                 PFORMAT_STRING pFormat)
4763 {
4764     unsigned char alignment;
4765     DWORD elements, esize;
4766
4767     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4768
4769     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4770         (pFormat[0] != RPC_FC_LGVARRAY))
4771     {
4772         ERR("invalid format type %x\n", pFormat[0]);
4773         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4774         return;
4775     }
4776
4777     alignment = pFormat[1] + 1;
4778
4779     if (pFormat[0] == RPC_FC_SMVARRAY)
4780     {
4781         pFormat += 2;
4782         pFormat += sizeof(WORD);
4783         elements = *(const WORD*)pFormat;
4784         pFormat += sizeof(WORD);
4785     }
4786     else
4787     {
4788         pFormat += 2;
4789         pFormat += sizeof(DWORD);
4790         elements = *(const DWORD*)pFormat;
4791         pFormat += sizeof(DWORD);
4792     }
4793
4794     esize = *(const WORD*)pFormat;
4795     pFormat += sizeof(WORD);
4796
4797     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4798     if ((pStubMsg->ActualCount > elements) ||
4799         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4800     {
4801         RpcRaiseException(RPC_S_INVALID_BOUND);
4802         return;
4803     }
4804
4805     SizeVariance(pStubMsg);
4806
4807     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4808
4809     safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4810
4811     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4812 }
4813
4814 /***********************************************************************
4815  *           NdrVaryingArrayMemorySize [RPCRT4.@]
4816  */
4817 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4818                                 PFORMAT_STRING pFormat)
4819 {
4820     unsigned char alignment;
4821     DWORD size, elements, esize;
4822
4823     TRACE("(%p, %p)\n", pStubMsg, pFormat);
4824
4825     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4826         (pFormat[0] != RPC_FC_LGVARRAY))
4827     {
4828         ERR("invalid format type %x\n", pFormat[0]);
4829         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4830         return 0;
4831     }
4832
4833     alignment = pFormat[1] + 1;
4834
4835     if (pFormat[0] == RPC_FC_SMVARRAY)
4836     {
4837         pFormat += 2;
4838         size = *(const WORD*)pFormat;
4839         pFormat += sizeof(WORD);
4840         elements = *(const WORD*)pFormat;
4841         pFormat += sizeof(WORD);
4842     }
4843     else
4844     {
4845         pFormat += 2;
4846         size = *(const DWORD*)pFormat;
4847         pFormat += sizeof(DWORD);
4848         elements = *(const DWORD*)pFormat;
4849         pFormat += sizeof(DWORD);
4850     }
4851
4852     esize = *(const WORD*)pFormat;
4853     pFormat += sizeof(WORD);
4854
4855     pFormat = ReadVariance(pStubMsg, pFormat, elements);
4856
4857     ALIGN_POINTER(pStubMsg->Buffer, alignment);
4858
4859     safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4860     pStubMsg->MemorySize += size;
4861
4862     EmbeddedPointerMemorySize(pStubMsg, pFormat);
4863
4864     return pStubMsg->MemorySize;
4865 }
4866
4867 /***********************************************************************
4868  *           NdrVaryingArrayFree [RPCRT4.@]
4869  */
4870 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4871                                 unsigned char *pMemory,
4872                                 PFORMAT_STRING pFormat)
4873 {
4874     unsigned char alignment;
4875     DWORD elements;
4876
4877     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4878
4879     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4880         (pFormat[0] != RPC_FC_LGVARRAY))
4881     {
4882         ERR("invalid format type %x\n", pFormat[0]);
4883         RpcRaiseException(RPC_S_INTERNAL_ERROR);
4884         return;
4885     }
4886
4887     alignment = pFormat[1] + 1;
4888
4889     if (pFormat[0] == RPC_FC_SMVARRAY)
4890     {
4891         pFormat += 2;
4892         pFormat += sizeof(WORD);
4893         elements = *(const WORD*)pFormat;
4894         pFormat += sizeof(WORD);
4895     }
4896     else
4897     {
4898         pFormat += 2;
4899         pFormat += sizeof(DWORD);
4900         elements = *(const DWORD*)pFormat;
4901         pFormat += sizeof(DWORD);
4902     }
4903
4904     pFormat += sizeof(WORD);
4905
4906     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4907     if ((pStubMsg->ActualCount > elements) ||
4908         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4909     {
4910         RpcRaiseException(RPC_S_INVALID_BOUND);
4911         return;
4912     }
4913
4914     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4915 }
4916
4917 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
4918 {
4919     switch (fc)
4920     {
4921     case RPC_FC_BYTE:
4922     case RPC_FC_CHAR:
4923     case RPC_FC_SMALL:
4924     case RPC_FC_USMALL:
4925         return *(const UCHAR *)pMemory;
4926     case RPC_FC_WCHAR:
4927     case RPC_FC_SHORT:
4928     case RPC_FC_USHORT:
4929     case RPC_FC_ENUM16:
4930         return *(const USHORT *)pMemory;
4931     case RPC_FC_LONG:
4932     case RPC_FC_ULONG:
4933     case RPC_FC_ENUM32:
4934         return *(const ULONG *)pMemory;
4935     default:
4936         FIXME("Unhandled base type: 0x%02x\n", fc);
4937         return 0;
4938     }
4939 }
4940
4941 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
4942                                                              unsigned long discriminant,
4943                                                              PFORMAT_STRING pFormat)
4944 {
4945     unsigned short num_arms, arm, type;
4946
4947     num_arms = *(const SHORT*)pFormat & 0x0fff;
4948     pFormat += 2;
4949     for(arm = 0; arm < num_arms; arm++)
4950     {
4951         if(discriminant == *(const ULONG*)pFormat)
4952         {
4953             pFormat += 4;
4954             break;
4955         }
4956         pFormat += 6;
4957     }
4958
4959     type = *(const unsigned short*)pFormat;
4960     TRACE("type %04x\n", type);
4961     if(arm == num_arms) /* default arm extras */
4962     {
4963         if(type == 0xffff)
4964         {
4965             ERR("no arm for 0x%lx and no default case\n", discriminant);
4966             RpcRaiseException(RPC_S_INVALID_TAG);
4967             return NULL;
4968         }
4969         if(type == 0)
4970         {
4971             TRACE("falling back to empty default case for 0x%lx\n", discriminant);
4972             return NULL;
4973         }
4974     }
4975     return pFormat;
4976 }
4977
4978 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
4979 {
4980     unsigned short type;
4981
4982     pFormat += 2;
4983
4984     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4985     if(!pFormat)
4986         return NULL;
4987
4988     type = *(const unsigned short*)pFormat;
4989     if((type & 0xff00) == 0x8000)
4990     {
4991         unsigned char basetype = LOBYTE(type);
4992         return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4993     }
4994     else
4995     {
4996         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4997         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4998         if (m)
4999         {
5000             unsigned char *saved_buffer = NULL;
5001             int pointer_buffer_mark_set = 0;
5002             switch(*desc)
5003             {
5004             case RPC_FC_RP:
5005             case RPC_FC_UP:
5006             case RPC_FC_OP:
5007             case RPC_FC_FP:
5008                 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
5009                 saved_buffer = pStubMsg->Buffer;
5010                 if (pStubMsg->PointerBufferMark)
5011                 {
5012                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5013                   pStubMsg->PointerBufferMark = NULL;
5014                   pointer_buffer_mark_set = 1;
5015                 }
5016                 else
5017                   safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
5018
5019                 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
5020                 if (pointer_buffer_mark_set)
5021                 {
5022                   STD_OVERFLOW_CHECK(pStubMsg);
5023                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5024                   if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5025                   {
5026                       ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5027                           saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5028                       RpcRaiseException(RPC_X_BAD_STUB_DATA);
5029                   }
5030                   pStubMsg->Buffer = saved_buffer + 4;
5031                 }
5032                 break;
5033             default:
5034                 m(pStubMsg, pMemory, desc);
5035             }
5036         }
5037         else FIXME("no marshaller for embedded type %02x\n", *desc);
5038     }
5039     return NULL;
5040 }
5041
5042 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5043                                 unsigned char **ppMemory,
5044                                 ULONG discriminant,
5045                                 PFORMAT_STRING pFormat,
5046                                 unsigned char fMustAlloc)
5047 {
5048     unsigned short type;
5049
5050     pFormat += 2;
5051
5052     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5053     if(!pFormat)
5054         return NULL;
5055
5056     type = *(const unsigned short*)pFormat;
5057     if((type & 0xff00) == 0x8000)
5058     {
5059         unsigned char basetype = LOBYTE(type);
5060         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
5061     }
5062     else
5063     {
5064         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5065         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
5066         if (m)
5067         {
5068             unsigned char *saved_buffer = NULL;
5069             int pointer_buffer_mark_set = 0;
5070             switch(*desc)
5071             {
5072             case RPC_FC_RP:
5073             case RPC_FC_UP:
5074             case RPC_FC_OP:
5075             case RPC_FC_FP:
5076                 **(void***)ppMemory = NULL;
5077                 ALIGN_POINTER(pStubMsg->Buffer, 4);
5078                 saved_buffer = pStubMsg->Buffer;
5079                 if (pStubMsg->PointerBufferMark)
5080                 {
5081                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5082                   pStubMsg->PointerBufferMark = NULL;
5083                   pointer_buffer_mark_set = 1;
5084                 }
5085                 else
5086                   pStubMsg->Buffer += 4; /* for pointer ID */
5087
5088                 if (saved_buffer + 4 > pStubMsg->BufferEnd)
5089                 {
5090                     ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5091                         saved_buffer, pStubMsg->BufferEnd);
5092                     RpcRaiseException(RPC_X_BAD_STUB_DATA);
5093                 }
5094
5095                 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
5096                 if (pointer_buffer_mark_set)
5097                 {
5098                   STD_OVERFLOW_CHECK(pStubMsg);
5099                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5100                   pStubMsg->Buffer = saved_buffer + 4;
5101                 }
5102                 break;
5103             default:
5104                 m(pStubMsg, ppMemory, desc, fMustAlloc);
5105             }
5106         }
5107         else FIXME("no marshaller for embedded type %02x\n", *desc);
5108     }
5109     return NULL;
5110 }
5111
5112 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
5113                                   unsigned char *pMemory,
5114                                   ULONG discriminant,
5115                                   PFORMAT_STRING pFormat)
5116 {
5117     unsigned short type;
5118
5119     pFormat += 2;
5120
5121     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5122     if(!pFormat)
5123         return;
5124
5125     type = *(const unsigned short*)pFormat;
5126     if((type & 0xff00) == 0x8000)
5127     {
5128         unsigned char basetype = LOBYTE(type);
5129         NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
5130     }
5131     else
5132     {
5133         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5134         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
5135         if (m)
5136         {
5137             switch(*desc)
5138             {
5139             case RPC_FC_RP:
5140             case RPC_FC_UP:
5141             case RPC_FC_OP:
5142             case RPC_FC_FP:
5143                 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5144                 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
5145                 if (!pStubMsg->IgnoreEmbeddedPointers)
5146                 {
5147                     int saved_buffer_length = pStubMsg->BufferLength;
5148                     pStubMsg->BufferLength = pStubMsg->PointerLength;
5149                     pStubMsg->PointerLength = 0;
5150                     if(!pStubMsg->BufferLength)
5151                         ERR("BufferLength == 0??\n");
5152                     PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
5153                     pStubMsg->PointerLength = pStubMsg->BufferLength;
5154                     pStubMsg->BufferLength = saved_buffer_length;
5155                 }
5156                 break;
5157             default:
5158                 m(pStubMsg, pMemory, desc);
5159             }
5160         }
5161         else FIXME("no buffersizer for embedded type %02x\n", *desc);
5162     }
5163 }
5164
5165 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
5166                                    ULONG discriminant,
5167                                    PFORMAT_STRING pFormat)
5168 {
5169     unsigned short type, size;
5170
5171     size = *(const unsigned short*)pFormat;
5172     pStubMsg->Memory += size;
5173     pFormat += 2;
5174
5175     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5176     if(!pFormat)
5177         return 0;
5178
5179     type = *(const unsigned short*)pFormat;
5180     if((type & 0xff00) == 0x8000)
5181     {
5182         return NdrBaseTypeMemorySize(pStubMsg, pFormat);
5183     }
5184     else
5185     {
5186         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5187         NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
5188         unsigned char *saved_buffer;
5189         if (m)
5190         {
5191             switch(*desc)
5192             {
5193             case RPC_FC_RP:
5194             case RPC_FC_UP:
5195             case RPC_FC_OP:
5196             case RPC_FC_FP:
5197                 ALIGN_POINTER(pStubMsg->Buffer, 4);
5198                 saved_buffer = pStubMsg->Buffer;
5199                 safe_buffer_increment(pStubMsg, 4);
5200                 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
5201                 pStubMsg->MemorySize += 4;
5202                 if (!pStubMsg->IgnoreEmbeddedPointers)
5203                     PointerMemorySize(pStubMsg, saved_buffer, pFormat);
5204                 break;
5205             default:
5206                 return m(pStubMsg, desc);
5207             }
5208         }
5209         else FIXME("no marshaller for embedded type %02x\n", *desc);
5210     }
5211
5212     TRACE("size %d\n", size);
5213     return size;
5214 }
5215
5216 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
5217                            unsigned char *pMemory,
5218                            ULONG discriminant,
5219                            PFORMAT_STRING pFormat)
5220 {
5221     unsigned short type;
5222
5223     pFormat += 2;
5224
5225     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5226     if(!pFormat)
5227         return;
5228
5229     type = *(const unsigned short*)pFormat;
5230     if((type & 0xff00) != 0x8000)
5231     {
5232         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5233         NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5234         if (m)
5235         {
5236             switch(*desc)
5237             {
5238             case RPC_FC_RP:
5239             case RPC_FC_UP:
5240             case RPC_FC_OP:
5241             case RPC_FC_FP:
5242                 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5243                 break;
5244             default:
5245                 m(pStubMsg, pMemory, desc);
5246             }
5247         }
5248         else FIXME("no freer for embedded type %02x\n", *desc);
5249     }
5250 }
5251
5252 /***********************************************************************
5253  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
5254  */
5255 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5256                                 unsigned char *pMemory,
5257                                 PFORMAT_STRING pFormat)
5258 {
5259     unsigned char switch_type;
5260     unsigned char increment;
5261     ULONG switch_value;
5262
5263     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5264     pFormat++;
5265
5266     switch_type = *pFormat & 0xf;
5267     increment = (*pFormat & 0xf0) >> 4;
5268     pFormat++;
5269
5270     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment);
5271
5272     switch_value = get_discriminant(switch_type, pMemory);
5273     TRACE("got switch value 0x%x\n", switch_value);
5274
5275     NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5276     pMemory += increment;
5277
5278     return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5279 }
5280
5281 /***********************************************************************
5282  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5283  */
5284 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5285                                 unsigned char **ppMemory,
5286                                 PFORMAT_STRING pFormat,
5287                                 unsigned char fMustAlloc)
5288 {
5289     unsigned char switch_type;
5290     unsigned char increment;
5291     ULONG switch_value;
5292     unsigned short size;
5293     unsigned char *pMemoryArm;
5294
5295     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5296     pFormat++;
5297
5298     switch_type = *pFormat & 0xf;
5299     increment = (*pFormat & 0xf0) >> 4;
5300     pFormat++;
5301
5302     ALIGN_POINTER(pStubMsg->Buffer, increment);
5303     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5304     TRACE("got switch value 0x%x\n", switch_value);
5305
5306     size = *(const unsigned short*)pFormat + increment;
5307     if(!*ppMemory || fMustAlloc)
5308         *ppMemory = NdrAllocate(pStubMsg, size);
5309
5310     NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5311     pMemoryArm = *ppMemory + increment;
5312
5313     return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
5314 }
5315
5316 /***********************************************************************
5317  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5318  */
5319 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5320                                 unsigned char *pMemory,
5321                                 PFORMAT_STRING pFormat)
5322 {
5323     unsigned char switch_type;
5324     unsigned char increment;
5325     ULONG switch_value;
5326
5327     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5328     pFormat++;
5329
5330     switch_type = *pFormat & 0xf;
5331     increment = (*pFormat & 0xf0) >> 4;
5332     pFormat++;
5333
5334     ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5335     switch_value = get_discriminant(switch_type, pMemory);
5336     TRACE("got switch value 0x%x\n", switch_value);
5337
5338     /* Add discriminant size */
5339     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5340     pMemory += increment;
5341
5342     union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5343 }
5344
5345 /***********************************************************************
5346  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5347  */
5348 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5349                                 PFORMAT_STRING pFormat)
5350 {
5351     unsigned char switch_type;
5352     unsigned char increment;
5353     ULONG switch_value;
5354
5355     switch_type = *pFormat & 0xf;
5356     increment = (*pFormat & 0xf0) >> 4;
5357     pFormat++;
5358
5359     ALIGN_POINTER(pStubMsg->Buffer, increment);
5360     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5361     TRACE("got switch value 0x%x\n", switch_value);
5362
5363     pStubMsg->Memory += increment;
5364
5365     return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5366 }
5367
5368 /***********************************************************************
5369  *           NdrEncapsulatedUnionFree [RPCRT4.@]
5370  */
5371 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5372                                 unsigned char *pMemory,
5373                                 PFORMAT_STRING pFormat)
5374 {
5375     unsigned char switch_type;
5376     unsigned char increment;
5377     ULONG switch_value;
5378
5379     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5380     pFormat++;
5381
5382     switch_type = *pFormat & 0xf;
5383     increment = (*pFormat & 0xf0) >> 4;
5384     pFormat++;
5385
5386     switch_value = get_discriminant(switch_type, pMemory);
5387     TRACE("got switch value 0x%x\n", switch_value);
5388
5389     pMemory += increment;
5390
5391     return union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5392 }
5393
5394 /***********************************************************************
5395  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5396  */
5397 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5398                                 unsigned char *pMemory,
5399                                 PFORMAT_STRING pFormat)
5400 {
5401     unsigned char switch_type;
5402
5403     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5404     pFormat++;
5405
5406     switch_type = *pFormat;
5407     pFormat++;
5408
5409     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5410     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5411     /* Marshall discriminant */
5412     NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5413
5414     return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5415 }
5416
5417 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
5418                                     PFORMAT_STRING *ppFormat)
5419 {
5420     long discriminant = 0;
5421
5422     switch(**ppFormat)
5423     {
5424     case RPC_FC_BYTE:
5425     case RPC_FC_CHAR:
5426     case RPC_FC_SMALL:
5427     case RPC_FC_USMALL:
5428     {
5429         UCHAR d;
5430         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5431         discriminant = d;
5432         break;
5433     }
5434     case RPC_FC_WCHAR:
5435     case RPC_FC_SHORT:
5436     case RPC_FC_USHORT:
5437     {
5438         USHORT d;
5439         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5440         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5441         discriminant = d;
5442         break;
5443     }
5444     case RPC_FC_LONG:
5445     case RPC_FC_ULONG:
5446     {
5447         ULONG d;
5448         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5449         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5450         discriminant = d;
5451         break;
5452     }
5453     default:
5454         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
5455     }
5456     (*ppFormat)++;
5457
5458     if (pStubMsg->fHasNewCorrDesc)
5459         *ppFormat += 6;
5460     else
5461         *ppFormat += 4;
5462     return discriminant;
5463 }
5464
5465 /**********************************************************************
5466  *           NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
5467  */
5468 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5469                                 unsigned char **ppMemory,
5470                                 PFORMAT_STRING pFormat,
5471                                 unsigned char fMustAlloc)
5472 {
5473     long discriminant;
5474     unsigned short size;
5475
5476     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5477     pFormat++;
5478
5479     /* Unmarshall discriminant */
5480     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5481     TRACE("unmarshalled discriminant %lx\n", discriminant);
5482
5483     pFormat += *(const SHORT*)pFormat;
5484
5485     size = *(const unsigned short*)pFormat;
5486
5487     if(!*ppMemory || fMustAlloc)
5488         *ppMemory = NdrAllocate(pStubMsg, size);
5489
5490     return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
5491 }
5492
5493 /***********************************************************************
5494  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
5495  */
5496 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5497                                 unsigned char *pMemory,
5498                                 PFORMAT_STRING pFormat)
5499 {
5500     unsigned char switch_type;
5501
5502     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5503     pFormat++;
5504
5505     switch_type = *pFormat;
5506     pFormat++;
5507
5508     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5509     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5510     /* Add discriminant size */
5511     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5512
5513     union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5514 }
5515
5516 /***********************************************************************
5517  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
5518  */
5519 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5520                                 PFORMAT_STRING pFormat)
5521 {
5522     ULONG discriminant;
5523
5524     pFormat++;
5525     /* Unmarshall discriminant */
5526     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5527     TRACE("unmarshalled discriminant 0x%x\n", discriminant);
5528
5529     return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
5530 }
5531
5532 /***********************************************************************
5533  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
5534  */
5535 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5536                                 unsigned char *pMemory,
5537                                 PFORMAT_STRING pFormat)
5538 {
5539     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5540     pFormat++;
5541     pFormat++;
5542
5543     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5544     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5545
5546     return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5547 }
5548
5549 /***********************************************************************
5550  *           NdrByteCountPointerMarshall [RPCRT4.@]
5551  */
5552 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5553                                 unsigned char *pMemory,
5554                                 PFORMAT_STRING pFormat)
5555 {
5556     FIXME("stub\n");
5557     return NULL;
5558 }
5559
5560 /***********************************************************************
5561  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
5562  */
5563 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5564                                 unsigned char **ppMemory,
5565                                 PFORMAT_STRING pFormat,
5566                                 unsigned char fMustAlloc)
5567 {
5568     FIXME("stub\n");
5569     return NULL;
5570 }
5571
5572 /***********************************************************************
5573  *           NdrByteCountPointerBufferSize [RPCRT4.@]
5574  */
5575 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5576                                 unsigned char *pMemory,
5577                                 PFORMAT_STRING pFormat)
5578 {
5579     FIXME("stub\n");
5580 }
5581
5582 /***********************************************************************
5583  *           NdrByteCountPointerMemorySize [RPCRT4.@]
5584  */
5585 ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5586                                 PFORMAT_STRING pFormat)
5587 {
5588     FIXME("stub\n");
5589     return 0;
5590 }
5591
5592 /***********************************************************************
5593  *           NdrByteCountPointerFree [RPCRT4.@]
5594  */
5595 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
5596                                 unsigned char *pMemory,
5597                                 PFORMAT_STRING pFormat)
5598 {
5599     FIXME("stub\n");
5600 }
5601
5602 /***********************************************************************
5603  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
5604  */
5605 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5606                                 unsigned char *pMemory,
5607                                 PFORMAT_STRING pFormat)
5608 {
5609     FIXME("stub\n");
5610     return NULL;
5611 }
5612
5613 /***********************************************************************
5614  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
5615  */
5616 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5617                                 unsigned char **ppMemory,
5618                                 PFORMAT_STRING pFormat,
5619                                 unsigned char fMustAlloc)
5620 {
5621     FIXME("stub\n");
5622     return NULL;
5623 }
5624
5625 /***********************************************************************
5626  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
5627  */
5628 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5629                                 unsigned char *pMemory,
5630                                 PFORMAT_STRING pFormat)
5631 {
5632     FIXME("stub\n");
5633 }
5634
5635 /***********************************************************************
5636  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
5637  */
5638 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5639                                 PFORMAT_STRING pFormat)
5640 {
5641     FIXME("stub\n");
5642     return 0;
5643 }
5644
5645 /***********************************************************************
5646  *           NdrXmitOrRepAsFree [RPCRT4.@]
5647  */
5648 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
5649                                 unsigned char *pMemory,
5650                                 PFORMAT_STRING pFormat)
5651 {
5652     FIXME("stub\n");
5653 }
5654
5655 #include "pshpack1.h"
5656 typedef struct
5657 {
5658     unsigned char type;
5659     unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
5660     ULONG low_value;
5661     ULONG high_value;
5662 } NDR_RANGE;
5663 #include "poppack.h"
5664
5665 /***********************************************************************
5666  *           NdrRangeMarshall [internal]
5667  */
5668 unsigned char *WINAPI NdrRangeMarshall(
5669     PMIDL_STUB_MESSAGE pStubMsg,
5670     unsigned char *pMemory,
5671     PFORMAT_STRING pFormat)
5672 {
5673     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5674     unsigned char base_type;
5675
5676     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5677
5678     if (pRange->type != RPC_FC_RANGE)
5679     {
5680         ERR("invalid format type %x\n", pRange->type);
5681         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5682         return NULL;
5683     }
5684
5685     base_type = pRange->flags_type & 0xf;
5686
5687     return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
5688 }
5689
5690 /***********************************************************************
5691  *           NdrRangeUnmarshall
5692  */
5693 unsigned char *WINAPI NdrRangeUnmarshall(
5694     PMIDL_STUB_MESSAGE pStubMsg,
5695     unsigned char **ppMemory,
5696     PFORMAT_STRING pFormat,
5697     unsigned char fMustAlloc)
5698 {
5699     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5700     unsigned char base_type;
5701
5702     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5703
5704     if (pRange->type != RPC_FC_RANGE)
5705     {
5706         ERR("invalid format type %x\n", pRange->type);
5707         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5708         return NULL;
5709     }
5710     base_type = pRange->flags_type & 0xf;
5711
5712     TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
5713         base_type, pRange->low_value, pRange->high_value);
5714
5715 #define RANGE_UNMARSHALL(type, format_spec) \
5716     do \
5717     { \
5718         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5719         if (fMustAlloc || !*ppMemory) \
5720             *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5721         if (pStubMsg->Buffer + sizeof(type) > pStubMsg->BufferEnd) \
5722         { \
5723             ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
5724                 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
5725             RpcRaiseException(RPC_X_BAD_STUB_DATA); \
5726         } \
5727         if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \
5728             (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \
5729         { \
5730             ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
5731                 *(type *)pStubMsg->Buffer, (type)pRange->low_value, \
5732                 (type)pRange->high_value); \
5733             RpcRaiseException(RPC_S_INVALID_BOUND); \
5734             return NULL; \
5735         } \
5736         TRACE("*ppMemory: %p\n", *ppMemory); \
5737         **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5738         pStubMsg->Buffer += sizeof(type); \
5739     } while (0)
5740
5741     switch(base_type)
5742     {
5743     case RPC_FC_CHAR:
5744     case RPC_FC_SMALL:
5745         RANGE_UNMARSHALL(UCHAR, "%d");
5746         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5747         break;
5748     case RPC_FC_BYTE:
5749     case RPC_FC_USMALL:
5750         RANGE_UNMARSHALL(CHAR, "%u");
5751         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5752         break;
5753     case RPC_FC_WCHAR: /* FIXME: valid? */
5754     case RPC_FC_USHORT:
5755         RANGE_UNMARSHALL(USHORT, "%u");
5756         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5757         break;
5758     case RPC_FC_SHORT:
5759         RANGE_UNMARSHALL(SHORT, "%d");
5760         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5761         break;
5762     case RPC_FC_LONG:
5763         RANGE_UNMARSHALL(LONG, "%d");
5764         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5765         break;
5766     case RPC_FC_ULONG:
5767         RANGE_UNMARSHALL(ULONG, "%u");
5768         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5769         break;
5770     case RPC_FC_ENUM16:
5771     case RPC_FC_ENUM32:
5772         FIXME("Unhandled enum type\n");
5773         break;
5774     case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */
5775     case RPC_FC_FLOAT:
5776     case RPC_FC_DOUBLE:
5777     case RPC_FC_HYPER:
5778     default:
5779         ERR("invalid range base type: 0x%02x\n", base_type);
5780         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5781     }
5782
5783     return NULL;
5784 }
5785
5786 /***********************************************************************
5787  *           NdrRangeBufferSize [internal]
5788  */
5789 void WINAPI NdrRangeBufferSize(
5790     PMIDL_STUB_MESSAGE pStubMsg,
5791     unsigned char *pMemory,
5792     PFORMAT_STRING pFormat)
5793 {
5794     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5795     unsigned char base_type;
5796
5797     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5798
5799     if (pRange->type != RPC_FC_RANGE)
5800     {
5801         ERR("invalid format type %x\n", pRange->type);
5802         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5803     }
5804     base_type = pRange->flags_type & 0xf;
5805
5806     NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
5807 }
5808
5809 /***********************************************************************
5810  *           NdrRangeMemorySize [internal]
5811  */
5812 ULONG WINAPI NdrRangeMemorySize(
5813     PMIDL_STUB_MESSAGE pStubMsg,
5814     PFORMAT_STRING pFormat)
5815 {
5816     NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5817     unsigned char base_type;
5818
5819     if (pRange->type != RPC_FC_RANGE)
5820     {
5821         ERR("invalid format type %x\n", pRange->type);
5822         RpcRaiseException(RPC_S_INTERNAL_ERROR);
5823         return 0;
5824     }
5825     base_type = pRange->flags_type & 0xf;
5826
5827     return NdrBaseTypeMemorySize(pStubMsg, &base_type);
5828 }
5829
5830 /***********************************************************************
5831  *           NdrRangeFree [internal]
5832  */
5833 void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
5834                                 unsigned char *pMemory,
5835                                 PFORMAT_STRING pFormat)
5836 {
5837    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5838
5839    /* nothing to do */
5840 }
5841
5842 /***********************************************************************
5843  *           NdrBaseTypeMarshall [internal]
5844  */
5845 static unsigned char *WINAPI NdrBaseTypeMarshall(
5846     PMIDL_STUB_MESSAGE pStubMsg,
5847     unsigned char *pMemory,
5848     PFORMAT_STRING pFormat)
5849 {
5850     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5851
5852     switch(*pFormat)
5853     {
5854     case RPC_FC_BYTE:
5855     case RPC_FC_CHAR:
5856     case RPC_FC_SMALL:
5857     case RPC_FC_USMALL:
5858         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
5859         TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
5860         break;
5861     case RPC_FC_WCHAR:
5862     case RPC_FC_SHORT:
5863     case RPC_FC_USHORT:
5864         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
5865         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
5866         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
5867         break;
5868     case RPC_FC_LONG:
5869     case RPC_FC_ULONG:
5870     case RPC_FC_ERROR_STATUS_T:
5871     case RPC_FC_ENUM32:
5872         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG));
5873         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
5874         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
5875         break;
5876     case RPC_FC_FLOAT:
5877         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float));
5878         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
5879         break;
5880     case RPC_FC_DOUBLE:
5881         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double));
5882         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
5883         break;
5884     case RPC_FC_HYPER:
5885         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG));
5886         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
5887         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
5888         break;
5889     case RPC_FC_ENUM16:
5890         /* only 16-bits on the wire, so do a sanity check */
5891         if (*(UINT *)pMemory > SHRT_MAX)
5892             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
5893         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
5894         if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5895             RpcRaiseException(RPC_X_BAD_STUB_DATA);
5896         *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
5897         pStubMsg->Buffer += sizeof(USHORT);
5898         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
5899         break;
5900     case RPC_FC_IGNORE:
5901         break;
5902     default:
5903         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5904     }
5905
5906     /* FIXME: what is the correct return value? */
5907     return NULL;
5908 }
5909
5910 /***********************************************************************
5911  *           NdrBaseTypeUnmarshall [internal]
5912  */
5913 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
5914     PMIDL_STUB_MESSAGE pStubMsg,
5915     unsigned char **ppMemory,
5916     PFORMAT_STRING pFormat,
5917     unsigned char fMustAlloc)
5918 {
5919     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5920
5921 #define BASE_TYPE_UNMARSHALL(type) \
5922         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5923         if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
5924         { \
5925             *ppMemory = pStubMsg->Buffer; \
5926             TRACE("*ppMemory: %p\n", *ppMemory); \
5927         } \
5928         else \
5929         {  \
5930             if (fMustAlloc) \
5931                 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5932             TRACE("*ppMemory: %p\n", *ppMemory); \
5933             **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5934         } \
5935         pStubMsg->Buffer += sizeof(type);
5936
5937     switch(*pFormat)
5938     {
5939     case RPC_FC_BYTE:
5940     case RPC_FC_CHAR:
5941     case RPC_FC_SMALL:
5942     case RPC_FC_USMALL:
5943         BASE_TYPE_UNMARSHALL(UCHAR);
5944         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5945         break;
5946     case RPC_FC_WCHAR:
5947     case RPC_FC_SHORT:
5948     case RPC_FC_USHORT:
5949         BASE_TYPE_UNMARSHALL(USHORT);
5950         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5951         break;
5952     case RPC_FC_LONG:
5953     case RPC_FC_ULONG:
5954     case RPC_FC_ERROR_STATUS_T:
5955     case RPC_FC_ENUM32:
5956         BASE_TYPE_UNMARSHALL(ULONG);
5957         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5958         break;
5959    case RPC_FC_FLOAT:
5960         BASE_TYPE_UNMARSHALL(float);
5961         TRACE("value: %f\n", **(float **)ppMemory);
5962         break;
5963     case RPC_FC_DOUBLE:
5964         BASE_TYPE_UNMARSHALL(double);
5965         TRACE("value: %f\n", **(double **)ppMemory);
5966         break;
5967     case RPC_FC_HYPER:
5968         BASE_TYPE_UNMARSHALL(ULONGLONG);
5969         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
5970         break;
5971     case RPC_FC_ENUM16:
5972         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5973         if (fMustAlloc || !*ppMemory)
5974             *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
5975         if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
5976             RpcRaiseException(RPC_X_BAD_STUB_DATA);
5977         TRACE("*ppMemory: %p\n", *ppMemory);
5978         /* 16-bits on the wire, but int in memory */
5979         **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
5980         pStubMsg->Buffer += sizeof(USHORT);
5981         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
5982         break;
5983     case RPC_FC_IGNORE:
5984         break;
5985     default:
5986         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5987     }
5988 #undef BASE_TYPE_UNMARSHALL
5989
5990     /* FIXME: what is the correct return value? */
5991
5992     return NULL;
5993 }
5994
5995 /***********************************************************************
5996  *           NdrBaseTypeBufferSize [internal]
5997  */
5998 static void WINAPI NdrBaseTypeBufferSize(
5999     PMIDL_STUB_MESSAGE pStubMsg,
6000     unsigned char *pMemory,
6001     PFORMAT_STRING pFormat)
6002 {
6003     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6004
6005     switch(*pFormat)
6006     {
6007     case RPC_FC_BYTE:
6008     case RPC_FC_CHAR:
6009     case RPC_FC_SMALL:
6010     case RPC_FC_USMALL:
6011         safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6012         break;
6013     case RPC_FC_WCHAR:
6014     case RPC_FC_SHORT:
6015     case RPC_FC_USHORT:
6016     case RPC_FC_ENUM16:
6017         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
6018         safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6019         break;
6020     case RPC_FC_LONG:
6021     case RPC_FC_ULONG:
6022     case RPC_FC_ENUM32:
6023         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
6024         safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6025         break;
6026     case RPC_FC_FLOAT:
6027         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
6028         safe_buffer_length_increment(pStubMsg, sizeof(float));
6029         break;
6030     case RPC_FC_DOUBLE:
6031         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
6032         safe_buffer_length_increment(pStubMsg, sizeof(double));
6033         break;
6034     case RPC_FC_HYPER:
6035         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
6036         safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6037         break;
6038     case RPC_FC_ERROR_STATUS_T:
6039         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
6040         safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6041         break;
6042     case RPC_FC_IGNORE:
6043         break;
6044     default:
6045         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6046     }
6047 }
6048
6049 /***********************************************************************
6050  *           NdrBaseTypeMemorySize [internal]
6051  */
6052 static ULONG WINAPI NdrBaseTypeMemorySize(
6053     PMIDL_STUB_MESSAGE pStubMsg,
6054     PFORMAT_STRING pFormat)
6055 {
6056     TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6057
6058     switch(*pFormat)
6059     {
6060     case RPC_FC_BYTE:
6061     case RPC_FC_CHAR:
6062     case RPC_FC_SMALL:
6063     case RPC_FC_USMALL:
6064         safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6065         pStubMsg->MemorySize += sizeof(UCHAR);
6066         return sizeof(UCHAR);
6067     case RPC_FC_WCHAR:
6068     case RPC_FC_SHORT:
6069     case RPC_FC_USHORT:
6070         safe_buffer_increment(pStubMsg, sizeof(USHORT));
6071         pStubMsg->MemorySize += sizeof(USHORT);
6072         return sizeof(USHORT);
6073     case RPC_FC_LONG:
6074     case RPC_FC_ULONG:
6075     case RPC_FC_ENUM32:
6076         safe_buffer_increment(pStubMsg, sizeof(ULONG));
6077         pStubMsg->MemorySize += sizeof(ULONG);
6078         return sizeof(ULONG);
6079     case RPC_FC_FLOAT:
6080         safe_buffer_increment(pStubMsg, sizeof(float));
6081         pStubMsg->MemorySize += sizeof(float);
6082         return sizeof(float);
6083     case RPC_FC_DOUBLE:
6084         safe_buffer_increment(pStubMsg, sizeof(double));
6085         pStubMsg->MemorySize += sizeof(double);
6086         return sizeof(double);
6087     case RPC_FC_HYPER:
6088         safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6089         pStubMsg->MemorySize += sizeof(ULONGLONG);
6090         return sizeof(ULONGLONG);
6091     case RPC_FC_ERROR_STATUS_T:
6092         safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6093         pStubMsg->MemorySize += sizeof(error_status_t);
6094         return sizeof(error_status_t);
6095     case RPC_FC_ENUM16:
6096         safe_buffer_increment(pStubMsg, sizeof(USHORT));
6097         pStubMsg->MemorySize += sizeof(UINT);
6098         return sizeof(UINT);
6099     case RPC_FC_IGNORE:
6100         pStubMsg->MemorySize += sizeof(void *);
6101         return sizeof(void *);
6102     default:
6103         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6104        return 0;
6105     }
6106 }
6107
6108 /***********************************************************************
6109  *           NdrBaseTypeFree [internal]
6110  */
6111 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6112                                 unsigned char *pMemory,
6113                                 PFORMAT_STRING pFormat)
6114 {
6115    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6116
6117    /* nothing to do */
6118 }
6119
6120 /***********************************************************************
6121  *           NdrContextHandleBufferSize [internal]
6122  */
6123 static void WINAPI NdrContextHandleBufferSize(
6124     PMIDL_STUB_MESSAGE pStubMsg,
6125     unsigned char *pMemory,
6126     PFORMAT_STRING pFormat)
6127 {
6128     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6129
6130     if (*pFormat != RPC_FC_BIND_CONTEXT)
6131     {
6132         ERR("invalid format type %x\n", *pFormat);
6133         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6134     }
6135     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
6136     safe_buffer_length_increment(pStubMsg, cbNDRContext);
6137 }
6138
6139 /***********************************************************************
6140  *           NdrContextHandleMarshall [internal]
6141  */
6142 static unsigned char *WINAPI NdrContextHandleMarshall(
6143     PMIDL_STUB_MESSAGE pStubMsg,
6144     unsigned char *pMemory,
6145     PFORMAT_STRING pFormat)
6146 {
6147     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6148
6149     if (*pFormat != RPC_FC_BIND_CONTEXT)
6150     {
6151         ERR("invalid format type %x\n", *pFormat);
6152         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6153     }
6154
6155     if (pFormat[1] & 0x80)
6156         NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6157     else
6158         NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE);
6159
6160     return NULL;
6161 }
6162
6163 /***********************************************************************
6164  *           NdrContextHandleUnmarshall [internal]
6165  */
6166 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6167     PMIDL_STUB_MESSAGE pStubMsg,
6168     unsigned char **ppMemory,
6169     PFORMAT_STRING pFormat,
6170     unsigned char fMustAlloc)
6171 {
6172     if (*pFormat != RPC_FC_BIND_CONTEXT)
6173     {
6174         ERR("invalid format type %x\n", *pFormat);
6175         RpcRaiseException(RPC_S_INTERNAL_ERROR);
6176     }
6177
6178   **(NDR_CCONTEXT **)ppMemory = NULL;
6179   NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
6180
6181   return NULL;
6182 }
6183
6184 /***********************************************************************
6185  *           NdrClientContextMarshall [RPCRT4.@]
6186  */
6187 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6188                                      NDR_CCONTEXT ContextHandle,
6189                                      int fCheck)
6190 {
6191     TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
6192
6193     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
6194
6195     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6196     {
6197         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6198             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6199         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6200     }
6201
6202     /* FIXME: what does fCheck do? */
6203     NDRCContextMarshall(ContextHandle,
6204                         pStubMsg->Buffer);
6205
6206     pStubMsg->Buffer += cbNDRContext;
6207 }
6208
6209 /***********************************************************************
6210  *           NdrClientContextUnmarshall [RPCRT4.@]
6211  */
6212 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6213                                        NDR_CCONTEXT * pContextHandle,
6214                                        RPC_BINDING_HANDLE BindHandle)
6215 {
6216     TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
6217
6218     ALIGN_POINTER(pStubMsg->Buffer, 4);
6219
6220     if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
6221         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6222
6223     NDRCContextUnmarshall(pContextHandle,
6224                           BindHandle,
6225                           pStubMsg->Buffer,
6226                           pStubMsg->RpcMsg->DataRepresentation);
6227
6228     pStubMsg->Buffer += cbNDRContext;
6229 }
6230
6231 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6232                                      NDR_SCONTEXT ContextHandle,
6233                                      NDR_RUNDOWN RundownRoutine )
6234 {
6235     TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
6236
6237     ALIGN_POINTER(pStubMsg->Buffer, 4);
6238
6239     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6240     {
6241         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6242             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6243         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6244     }
6245
6246     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6247                          pStubMsg->Buffer, RundownRoutine, NULL,
6248                          RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6249     pStubMsg->Buffer += cbNDRContext;
6250 }
6251
6252 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
6253 {
6254     NDR_SCONTEXT ContextHandle;
6255
6256     TRACE("(%p)\n", pStubMsg);
6257
6258     ALIGN_POINTER(pStubMsg->Buffer, 4);
6259
6260     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6261     {
6262         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6263             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6264         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6265     }
6266
6267     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6268                                            pStubMsg->Buffer,
6269                                            pStubMsg->RpcMsg->DataRepresentation,
6270                                            NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6271     pStubMsg->Buffer += cbNDRContext;
6272
6273     return ContextHandle;
6274 }
6275
6276 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
6277                                  unsigned char* pMemory,
6278                                  PFORMAT_STRING pFormat)
6279 {
6280     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
6281 }
6282
6283 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
6284                                                PFORMAT_STRING pFormat)
6285 {
6286     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6287     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6288
6289     TRACE("(%p, %p)\n", pStubMsg, pFormat);
6290
6291     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6292         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6293     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6294         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6295     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6296     {
6297         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6298         if_id = &sif->InterfaceId;
6299     }
6300
6301     return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
6302                                   pStubMsg->RpcMsg->DataRepresentation, if_id,
6303                                   flags);
6304 }
6305
6306 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6307                                         NDR_SCONTEXT ContextHandle,
6308                                         NDR_RUNDOWN RundownRoutine,
6309                                         PFORMAT_STRING pFormat)
6310 {
6311     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6312     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6313
6314     TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
6315
6316     ALIGN_POINTER(pStubMsg->Buffer, 4);
6317
6318     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6319     {
6320         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6321             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6322         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6323     }
6324
6325     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6326         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6327     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6328         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6329     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6330     {
6331         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6332         if_id = &sif->InterfaceId;
6333     }
6334
6335     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6336                           pStubMsg->Buffer, RundownRoutine, if_id, flags);
6337     pStubMsg->Buffer += cbNDRContext;
6338 }
6339
6340 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6341                                                   PFORMAT_STRING pFormat)
6342 {
6343     NDR_SCONTEXT ContextHandle;
6344     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6345     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6346
6347     TRACE("(%p, %p)\n", pStubMsg, pFormat);
6348
6349     ALIGN_POINTER(pStubMsg->Buffer, 4);
6350
6351     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6352     {
6353         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6354             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6355         RpcRaiseException(RPC_X_BAD_STUB_DATA);
6356     }
6357
6358     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6359         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6360     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6361         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6362     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6363     {
6364         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6365         if_id = &sif->InterfaceId;
6366     }
6367
6368     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6369                                            pStubMsg->Buffer,
6370                                            pStubMsg->RpcMsg->DataRepresentation,
6371                                            if_id, flags);
6372     pStubMsg->Buffer += cbNDRContext;
6373
6374     return ContextHandle;
6375 }
6376
6377 /***********************************************************************
6378  *           NdrCorrelationInitialize [RPCRT4.@]
6379  *
6380  * Initializes correlation validity checking.
6381  *
6382  * PARAMS
6383  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
6384  *  pMemory     [I] Pointer to memory to use as a cache.
6385  *  CacheSize   [I] Size of the memory pointed to by pMemory.
6386  *  Flags       [I] Reserved. Set to zero.
6387  *
6388  * RETURNS
6389  *  Nothing.
6390  */
6391 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
6392 {
6393     FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
6394     pStubMsg->fHasNewCorrDesc = TRUE;
6395 }
6396
6397 /***********************************************************************
6398  *           NdrCorrelationPass [RPCRT4.@]
6399  *
6400  * Performs correlation validity checking.
6401  *
6402  * PARAMS
6403  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
6404  *
6405  * RETURNS
6406  *  Nothing.
6407  */
6408 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
6409 {
6410     FIXME("(%p): stub\n", pStubMsg);
6411 }
6412
6413 /***********************************************************************
6414  *           NdrCorrelationFree [RPCRT4.@]
6415  *
6416  * Frees any resources used while unmarshalling parameters that need
6417  * correlation validity checking.
6418  *
6419  * PARAMS
6420  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
6421  *
6422  * RETURNS
6423  *  Nothing.
6424  */
6425 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
6426 {
6427     FIXME("(%p): stub\n", pStubMsg);
6428 }