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