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