~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/rpcrt4/ndr_marshall.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * NDR data marshalling
  3  *
  4  * Copyright 2002 Greg Turner
  5  * Copyright 2003-2006 CodeWeavers
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  *
 21  * TODO:
 22  *  - String structs
 23  *  - Byte count pointers
 24  *  - transmit_as/represent as
 25  *  - Multi-dimensional arrays
 26  *  - Conversion functions (NdrConvert)
 27  *  - Checks for integer addition overflow in user marshall functions
 28  */
 29 
 30 #include <stdarg.h>
 31 #include <stdio.h>
 32 #include <string.h>
 33 #include <assert.h>
 34 #include <limits.h>
 35 
 36 #include "windef.h"
 37 #include "winbase.h"
 38 #include "winerror.h"
 39 
 40 #include "ndr_misc.h"
 41 #include "rpcndr.h"
 42 
 43 #include "wine/unicode.h"
 44 #include "wine/rpcfc.h"
 45 
 46 #include "wine/debug.h"
 47 
 48 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 49 
 50 #if defined(__i386__)
 51 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
 52     (*((UINT32 *)(pchar)) = (uint32))
 53 
 54 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
 55     (*((UINT32 *)(pchar)))
 56 #else
 57   /* these would work for i386 too, but less efficient */
 58 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
 59     (*(pchar)     = LOBYTE(LOWORD(uint32)), \
 60      *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
 61      *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
 62      *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
 63      (uint32)) /* allow as r-value */
 64 
 65 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
 66     (MAKELONG( \
 67       MAKEWORD(*(pchar), *((pchar)+1)), \
 68       MAKEWORD(*((pchar)+2), *((pchar)+3))))
 69 #endif
 70 
 71 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
 72   (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
 73    *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
 74    *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
 75    *(pchar)     = HIBYTE(HIWORD(uint32)), \
 76    (uint32)) /* allow as r-value */
 77 
 78 #define BIG_ENDIAN_UINT32_READ(pchar) \
 79   (MAKELONG( \
 80     MAKEWORD(*((pchar)+3), *((pchar)+2)), \
 81     MAKEWORD(*((pchar)+1), *(pchar))))
 82 
 83 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
 84 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
 85     BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
 86 # define NDR_LOCAL_UINT32_READ(pchar) \
 87     BIG_ENDIAN_UINT32_READ(pchar)
 88 #else
 89 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
 90     LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
 91 # define NDR_LOCAL_UINT32_READ(pchar) \
 92     LITTLE_ENDIAN_UINT32_READ(pchar)
 93 #endif
 94 
 95 /* _Align must be the desired alignment,
 96  * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
 97 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
 98 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
 99 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
100 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
101 #define ALIGN_POINTER_CLEAR(_Ptr, _Align) \
102     do { \
103         memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \
104         ALIGN_POINTER(_Ptr, _Align); \
105     } while(0)
106 
107 #define STD_OVERFLOW_CHECK(_Msg) do { \
108     TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
109     if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
110         ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
111   } while (0)
112 
113 #define NDR_POINTER_ID_BASE 0x20000
114 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
115 #define NDR_TABLE_SIZE 128
116 #define NDR_TABLE_MASK 127
117 
118 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
119 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
120 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
121 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
122 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
123 
124 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
125 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
126 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
127 
128 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
129   0,
130   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
131   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
132   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
133   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
134   /* 0x10 */
135   NdrBaseTypeMarshall,
136   /* 0x11 */
137   NdrPointerMarshall, NdrPointerMarshall,
138   NdrPointerMarshall, NdrPointerMarshall,
139   /* 0x15 */
140   NdrSimpleStructMarshall, NdrSimpleStructMarshall,
141   NdrConformantStructMarshall, NdrConformantStructMarshall,
142   NdrConformantVaryingStructMarshall,
143   NdrComplexStructMarshall,
144   /* 0x1b */
145   NdrConformantArrayMarshall, 
146   NdrConformantVaryingArrayMarshall,
147   NdrFixedArrayMarshall, NdrFixedArrayMarshall,
148   NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
149   NdrComplexArrayMarshall,
150   /* 0x22 */
151   NdrConformantStringMarshall, 0, 0,
152   NdrConformantStringMarshall,
153   NdrNonConformantStringMarshall, 0, 0, 0,
154   /* 0x2a */
155   NdrEncapsulatedUnionMarshall,
156   NdrNonEncapsulatedUnionMarshall,
157   NdrByteCountPointerMarshall,
158   NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
159   /* 0x2f */
160   NdrInterfacePointerMarshall,
161   /* 0x30 */
162   NdrContextHandleMarshall,
163   /* 0xb1 */
164   0, 0, 0,
165   NdrUserMarshalMarshall,
166   0, 0,
167   /* 0xb7 */
168   NdrRangeMarshall
169 };
170 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
171   0,
172   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
173   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
174   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
175   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
176   /* 0x10 */
177   NdrBaseTypeUnmarshall,
178   /* 0x11 */
179   NdrPointerUnmarshall, NdrPointerUnmarshall,
180   NdrPointerUnmarshall, NdrPointerUnmarshall,
181   /* 0x15 */
182   NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
183   NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
184   NdrConformantVaryingStructUnmarshall,
185   NdrComplexStructUnmarshall,
186   /* 0x1b */
187   NdrConformantArrayUnmarshall, 
188   NdrConformantVaryingArrayUnmarshall,
189   NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
190   NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
191   NdrComplexArrayUnmarshall,
192   /* 0x22 */
193   NdrConformantStringUnmarshall, 0, 0,
194   NdrConformantStringUnmarshall,
195   NdrNonConformantStringUnmarshall, 0, 0, 0,
196   /* 0x2a */
197   NdrEncapsulatedUnionUnmarshall,
198   NdrNonEncapsulatedUnionUnmarshall,
199   NdrByteCountPointerUnmarshall,
200   NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
201   /* 0x2f */
202   NdrInterfacePointerUnmarshall,
203   /* 0x30 */
204   NdrContextHandleUnmarshall,
205   /* 0xb1 */
206   0, 0, 0,
207   NdrUserMarshalUnmarshall,
208   0, 0,
209   /* 0xb7 */
210   NdrRangeUnmarshall
211 };
212 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
213   0,
214   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
215   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
216   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
217   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
218   /* 0x10 */
219   NdrBaseTypeBufferSize,
220   /* 0x11 */
221   NdrPointerBufferSize, NdrPointerBufferSize,
222   NdrPointerBufferSize, NdrPointerBufferSize,
223   /* 0x15 */
224   NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
225   NdrConformantStructBufferSize, NdrConformantStructBufferSize,
226   NdrConformantVaryingStructBufferSize,
227   NdrComplexStructBufferSize,
228   /* 0x1b */
229   NdrConformantArrayBufferSize, 
230   NdrConformantVaryingArrayBufferSize,
231   NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
232   NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
233   NdrComplexArrayBufferSize,
234   /* 0x22 */
235   NdrConformantStringBufferSize, 0, 0,
236   NdrConformantStringBufferSize,
237   NdrNonConformantStringBufferSize, 0, 0, 0,
238   /* 0x2a */
239   NdrEncapsulatedUnionBufferSize,
240   NdrNonEncapsulatedUnionBufferSize,
241   NdrByteCountPointerBufferSize,
242   NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
243   /* 0x2f */
244   NdrInterfacePointerBufferSize,
245   /* 0x30 */
246   NdrContextHandleBufferSize,
247   /* 0xb1 */
248   0, 0, 0,
249   NdrUserMarshalBufferSize,
250   0, 0,
251   /* 0xb7 */
252   NdrRangeBufferSize
253 };
254 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
255   0,
256   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
257   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
258   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
259   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
260   /* 0x10 */
261   NdrBaseTypeMemorySize,
262   /* 0x11 */
263   NdrPointerMemorySize, NdrPointerMemorySize,
264   NdrPointerMemorySize, NdrPointerMemorySize,
265   /* 0x15 */
266   NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
267   NdrConformantStructMemorySize, NdrConformantStructMemorySize,
268   NdrConformantVaryingStructMemorySize,
269   NdrComplexStructMemorySize,
270   /* 0x1b */
271   NdrConformantArrayMemorySize,
272   NdrConformantVaryingArrayMemorySize,
273   NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
274   NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
275   NdrComplexArrayMemorySize,
276   /* 0x22 */
277   NdrConformantStringMemorySize, 0, 0,
278   NdrConformantStringMemorySize,
279   NdrNonConformantStringMemorySize, 0, 0, 0,
280   /* 0x2a */
281   NdrEncapsulatedUnionMemorySize,
282   NdrNonEncapsulatedUnionMemorySize,
283   NdrByteCountPointerMemorySize,
284   NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
285   /* 0x2f */
286   NdrInterfacePointerMemorySize,
287   /* 0x30 */
288   0,
289   /* 0xb1 */
290   0, 0, 0,
291   NdrUserMarshalMemorySize,
292   0, 0,
293   /* 0xb7 */
294   NdrRangeMemorySize
295 };
296 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
297   0,
298   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
299   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
300   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
301   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
302   /* 0x10 */
303   NdrBaseTypeFree,
304   /* 0x11 */
305   NdrPointerFree, NdrPointerFree,
306   NdrPointerFree, NdrPointerFree,
307   /* 0x15 */
308   NdrSimpleStructFree, NdrSimpleStructFree,
309   NdrConformantStructFree, NdrConformantStructFree,
310   NdrConformantVaryingStructFree,
311   NdrComplexStructFree,
312   /* 0x1b */
313   NdrConformantArrayFree, 
314   NdrConformantVaryingArrayFree,
315   NdrFixedArrayFree, NdrFixedArrayFree,
316   NdrVaryingArrayFree, NdrVaryingArrayFree,
317   NdrComplexArrayFree,
318   /* 0x22 */
319   0, 0, 0,
320   0, 0, 0, 0, 0,
321   /* 0x2a */
322   NdrEncapsulatedUnionFree,
323   NdrNonEncapsulatedUnionFree,
324   0,
325   NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
326   /* 0x2f */
327   NdrInterfacePointerFree,
328   /* 0x30 */
329   0,
330   /* 0xb1 */
331   0, 0, 0,
332   NdrUserMarshalFree,
333   0, 0,
334   /* 0xb7 */
335   NdrRangeFree
336 };
337 
338 typedef struct _NDR_MEMORY_LIST
339 {
340     ULONG magic;
341     ULONG size;
342     ULONG reserved;
343     struct _NDR_MEMORY_LIST *next;
344 } NDR_MEMORY_LIST;
345 
346 #define MEML_MAGIC  ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
347 
348 /***********************************************************************
349  *            NdrAllocate [RPCRT4.@]
350  *
351  * Allocates a block of memory using pStubMsg->pfnAllocate.
352  *
353  * PARAMS
354  *  pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
355  *  len      [I]   Size of memory block to allocate.
356  *
357  * RETURNS
358  *  The memory block of size len that was allocated.
359  *
360  * NOTES
361  *  The memory block is always 8-byte aligned.
362  *  If the function is unable to allocate memory an ERROR_OUTOFMEMORY
363  *  exception is raised.
364  */
365 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
366 {
367     size_t aligned_len;
368     size_t adjusted_len;
369     void *p;
370     NDR_MEMORY_LIST *mem_list;
371 
372     aligned_len = ALIGNED_LENGTH(len, 8);
373     adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
374     /* check for overflow */
375     if (adjusted_len < len)
376     {
377         ERR("overflow of adjusted_len %d, len %d\n", adjusted_len, len);
378         RpcRaiseException(RPC_X_BAD_STUB_DATA);
379     }
380 
381     p = pStubMsg->pfnAllocate(adjusted_len);
382     if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
383 
384     mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
385     mem_list->magic = MEML_MAGIC;
386     mem_list->size = aligned_len;
387     mem_list->reserved = 0;
388     mem_list->next = pStubMsg->pMemoryList;
389     pStubMsg->pMemoryList = mem_list;
390 
391     TRACE("-- %p\n", p);
392     return p;
393 }
394 
395 static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
396 {
397     TRACE("(%p, %p)\n", pStubMsg, Pointer);
398 
399     pStubMsg->pfnFree(Pointer);
400 }
401 
402 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
403 {
404     return (*(const ULONG *)pFormat != -1);
405 }
406 
407 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
408 {
409   ALIGN_POINTER(pStubMsg->Buffer, 4);
410   if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
411       RpcRaiseException(RPC_X_BAD_STUB_DATA);
412   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
413   pStubMsg->Buffer += 4;
414   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
415   if (pStubMsg->fHasNewCorrDesc)
416     return pFormat+6;
417   else
418     return pFormat+4;
419 }
420 
421 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
422 {
423   if (pFormat && !IsConformanceOrVariancePresent(pFormat))
424   {
425     pStubMsg->Offset = 0;
426     pStubMsg->ActualCount = pStubMsg->MaxCount;
427     goto done;
428   }
429 
430   ALIGN_POINTER(pStubMsg->Buffer, 4);
431   if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
432     RpcRaiseException(RPC_X_BAD_STUB_DATA);
433   pStubMsg->Offset      = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
434   pStubMsg->Buffer += 4;
435   TRACE("offset is %d\n", pStubMsg->Offset);
436   pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
437   pStubMsg->Buffer += 4;
438   TRACE("variance is %d\n", pStubMsg->ActualCount);
439 
440   if ((pStubMsg->ActualCount > MaxValue) ||
441       (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
442   {
443     ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
444         pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
445     RpcRaiseException(RPC_S_INVALID_BOUND);
446     return NULL;
447   }
448 
449 done:
450   if (pStubMsg->fHasNewCorrDesc)
451     return pFormat+6;
452   else
453     return pFormat+4;
454 }
455 
456 /* writes the conformance value to the buffer */
457 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
458 {
459     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
460     if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
461         RpcRaiseException(RPC_X_BAD_STUB_DATA);
462     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
463     pStubMsg->Buffer += 4;
464 }
465 
466 /* writes the variance values to the buffer */
467 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
468 {
469     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
470     if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
471         RpcRaiseException(RPC_X_BAD_STUB_DATA);
472     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
473     pStubMsg->Buffer += 4;
474     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
475     pStubMsg->Buffer += 4;
476 }
477 
478 /* requests buffer space for the conformance value */
479 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
480 {
481     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
482     if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
483         RpcRaiseException(RPC_X_BAD_STUB_DATA);
484     pStubMsg->BufferLength += 4;
485 }
486 
487 /* requests buffer space for the variance values */
488 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
489 {
490     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
491     if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
492         RpcRaiseException(RPC_X_BAD_STUB_DATA);
493     pStubMsg->BufferLength += 8;
494 }
495 
496 PFORMAT_STRING ComputeConformanceOrVariance(
497     MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
498     PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
499 {
500   BYTE dtype = pFormat[0] & 0xf;
501   short ofs = *(const short *)&pFormat[2];
502   LPVOID ptr = NULL;
503   DWORD data = 0;
504 
505   if (!IsConformanceOrVariancePresent(pFormat)) {
506     /* null descriptor */
507     *pCount = def;
508     goto finish_conf;
509   }
510 
511   switch (pFormat[0] & 0xf0) {
512   case RPC_FC_NORMAL_CONFORMANCE:
513     TRACE("normal conformance, ofs=%d\n", ofs);
514     ptr = pMemory;
515     break;
516   case RPC_FC_POINTER_CONFORMANCE:
517     TRACE("pointer conformance, ofs=%d\n", ofs);
518     ptr = pStubMsg->Memory;
519     break;
520   case RPC_FC_TOP_LEVEL_CONFORMANCE:
521     TRACE("toplevel conformance, ofs=%d\n", ofs);
522     if (pStubMsg->StackTop) {
523       ptr = pStubMsg->StackTop;
524     }
525     else {
526       /* -Os mode, *pCount is already set */
527       goto finish_conf;
528     }
529     break;
530   case RPC_FC_CONSTANT_CONFORMANCE:
531     data = ofs | ((DWORD)pFormat[1] << 16);
532     TRACE("constant conformance, val=%d\n", data);
533     *pCount = data;
534     goto finish_conf;
535   case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
536     FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
537     if (pStubMsg->StackTop) {
538       ptr = pStubMsg->StackTop;
539     }
540     else {
541       /* ? */
542       goto done_conf_grab;
543     }
544     break;
545   default:
546     FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
547   }
548 
549   switch (pFormat[1]) {
550   case RPC_FC_DEREFERENCE:
551     ptr = *(LPVOID*)((char *)ptr + ofs);
552     break;
553   case RPC_FC_CALLBACK:
554   {
555     unsigned char *old_stack_top = pStubMsg->StackTop;
556     pStubMsg->StackTop = ptr;
557 
558     /* ofs is index into StubDesc->apfnExprEval */
559     TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
560     pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
561 
562     pStubMsg->StackTop = old_stack_top;
563 
564     /* the callback function always stores the computed value in MaxCount */
565     *pCount = pStubMsg->MaxCount;
566     goto finish_conf;
567   }
568   default:
569     ptr = (char *)ptr + ofs;
570     break;
571   }
572 
573   switch (dtype) {
574   case RPC_FC_LONG:
575   case RPC_FC_ULONG:
576     data = *(DWORD*)ptr;
577     break;
578   case RPC_FC_SHORT:
579     data = *(SHORT*)ptr;
580     break;
581   case RPC_FC_USHORT:
582     data = *(USHORT*)ptr;
583     break;
584   case RPC_FC_CHAR:
585   case RPC_FC_SMALL:
586     data = *(CHAR*)ptr;
587     break;
588   case RPC_FC_BYTE:
589   case RPC_FC_USMALL:
590     data = *(UCHAR*)ptr;
591     break;
592   default:
593     FIXME("unknown conformance data type %x\n", dtype);
594     goto done_conf_grab;
595   }
596   TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
597 
598 done_conf_grab:
599   switch (pFormat[1]) {
600   case RPC_FC_DEREFERENCE: /* already handled */
601   case 0: /* no op */
602     *pCount = data;
603     break;
604   case RPC_FC_ADD_1:
605     *pCount = data + 1;
606     break;
607   case RPC_FC_SUB_1:
608     *pCount = data - 1;
609     break;
610   case RPC_FC_MULT_2:
611     *pCount = data * 2;
612     break;
613   case RPC_FC_DIV_2:
614     *pCount = data / 2;
615     break;
616   default:
617     FIXME("unknown conformance op %d\n", pFormat[1]);
618     goto finish_conf;
619   }
620 
621 finish_conf:
622   TRACE("resulting conformance is %ld\n", *pCount);
623   if (pStubMsg->fHasNewCorrDesc)
624     return pFormat+6;
625   else
626     return pFormat+4;
627 }
628 
629 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
630  * the result overflows 32-bits */
631 static inline ULONG safe_multiply(ULONG a, ULONG b)
632 {
633     ULONGLONG ret = (ULONGLONG)a * b;
634     if (ret > 0xffffffff)
635     {
636         RpcRaiseException(RPC_S_INVALID_BOUND);
637         return 0;
638     }
639     return ret;
640 }
641 
642 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
643 {
644     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
645         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
646         RpcRaiseException(RPC_X_BAD_STUB_DATA);
647     pStubMsg->Buffer += size;
648 }
649 
650 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
651 {
652     if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
653     {
654         ERR("buffer length overflow - BufferLength = %u, size = %u\n",
655             pStubMsg->BufferLength, size);
656         RpcRaiseException(RPC_X_BAD_STUB_DATA);
657     }
658     pStubMsg->BufferLength += size;
659 }
660 
661 /* copies data from the buffer, checking that there is enough data in the buffer
662  * to do so */
663 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
664 {
665     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
666         (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
667     {
668         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
669             pStubMsg->Buffer, pStubMsg->BufferEnd, size);
670         RpcRaiseException(RPC_X_BAD_STUB_DATA);
671     }
672     if (p == pStubMsg->Buffer)
673         ERR("pointer is the same as the buffer\n");
674     memcpy(p, pStubMsg->Buffer, size);
675     pStubMsg->Buffer += size;
676 }
677 
678 /* copies data to the buffer, checking that there is enough space to do so */
679 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
680 {
681     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
682         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
683     {
684         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
685             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
686             size);
687         RpcRaiseException(RPC_X_BAD_STUB_DATA);
688     }
689     memcpy(pStubMsg->Buffer, p, size);
690     pStubMsg->Buffer += size;
691 }
692 
693 /* verify that string data sitting in the buffer is valid and safe to
694  * unmarshall */
695 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
696 {
697     ULONG i;
698 
699     /* verify the buffer is safe to access */
700     if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
701         (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
702     {
703         ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
704             pStubMsg->BufferEnd, pStubMsg->Buffer);
705         RpcRaiseException(RPC_X_BAD_STUB_DATA);
706     }
707 
708     /* strings must always have null terminating bytes */
709     if (bufsize < esize)
710     {
711         ERR("invalid string length of %d\n", bufsize / esize);
712         RpcRaiseException(RPC_S_INVALID_BOUND);
713     }
714 
715     for (i = bufsize - esize; i < bufsize; i++)
716         if (pStubMsg->Buffer[i] != 0)
717         {
718             ERR("string not null-terminated at byte position %d, data is 0x%x\n",
719                 i, pStubMsg->Buffer[i]);
720             RpcRaiseException(RPC_S_INVALID_BOUND);
721         }
722 }
723 
724 /*
725  * NdrConformantString:
726  * 
727  * What MS calls a ConformantString is, in DCE terminology,
728  * a Varying-Conformant String.
729  * [
730  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
731  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
732  *           into unmarshalled string) 
733  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
734  *   [ 
735  *     data: CHARTYPE[maxlen]
736  *   ] 
737  * ], where CHARTYPE is the appropriate character type (specified externally)
738  *
739  */
740 
741 /***********************************************************************
742  *            NdrConformantStringMarshall [RPCRT4.@]
743  */
744 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
745   unsigned char *pszMessage, PFORMAT_STRING pFormat)
746 { 
747   ULONG esize, size;
748 
749   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
750   
751   if (*pFormat == RPC_FC_C_CSTRING) {
752     TRACE("string=%s\n", debugstr_a((char*)pszMessage));
753     pStubMsg->ActualCount = strlen((char*)pszMessage)+1;
754     esize = 1;
755   }
756   else if (*pFormat == RPC_FC_C_WSTRING) {
757     TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
758     pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1;
759     esize = 2;
760   }
761   else {
762     ERR("Unhandled string type: %#x\n", *pFormat); 
763     /* FIXME: raise an exception. */
764     return NULL;
765   }
766 
767   if (pFormat[1] == RPC_FC_STRING_SIZED)
768     pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0);
769   else
770     pStubMsg->MaxCount = pStubMsg->ActualCount;
771   pStubMsg->Offset = 0;
772   WriteConformance(pStubMsg);
773   WriteVariance(pStubMsg);
774 
775   size = safe_multiply(esize, pStubMsg->ActualCount);
776   safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */
777 
778   /* success */
779   return NULL; /* is this always right? */
780 }
781 
782 /***********************************************************************
783  *           NdrConformantStringBufferSize [RPCRT4.@]
784  */
785 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
786   unsigned char* pMemory, PFORMAT_STRING pFormat)
787 {
788   ULONG esize;
789 
790   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
791 
792   SizeConformance(pStubMsg);
793   SizeVariance(pStubMsg);
794 
795   if (*pFormat == RPC_FC_C_CSTRING) {
796     TRACE("string=%s\n", debugstr_a((char*)pMemory));
797     pStubMsg->ActualCount = strlen((char*)pMemory)+1;
798     esize = 1;
799   }
800   else if (*pFormat == RPC_FC_C_WSTRING) {
801     TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
802     pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1;
803     esize = 2;
804   }
805   else {
806     ERR("Unhandled string type: %#x\n", *pFormat); 
807     /* FIXME: raise an exception */
808     return;
809   }
810 
811   if (pFormat[1] == RPC_FC_STRING_SIZED)
812     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
813   else
814     pStubMsg->MaxCount = pStubMsg->ActualCount;
815 
816   safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
817 }
818 
819 /************************************************************************
820  *            NdrConformantStringMemorySize [RPCRT4.@]
821  */
822 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
823   PFORMAT_STRING pFormat )
824 {
825   ULONG bufsize, memsize, esize;
826 
827   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
828 
829   ReadConformance(pStubMsg, NULL);
830   ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
831 
832   if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
833   {
834     ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
835         pStubMsg->ActualCount, pStubMsg->MaxCount);
836     RpcRaiseException(RPC_S_INVALID_BOUND);
837   }
838   if (pStubMsg->Offset)
839   {
840     ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
841     RpcRaiseException(RPC_S_INVALID_BOUND);
842   }
843 
844   if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
845   else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
846   else {
847     ERR("Unhandled string type: %#x\n", *pFormat);
848     /* FIXME: raise an exception */
849     esize = 0;
850   }
851 
852   memsize = safe_multiply(esize, pStubMsg->MaxCount);
853   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
854 
855   validate_string_data(pStubMsg, bufsize, esize);
856 
857   safe_buffer_increment(pStubMsg, bufsize);
858   pStubMsg->MemorySize += memsize;
859 
860   return pStubMsg->MemorySize;
861 }
862 
863 /************************************************************************
864  *           NdrConformantStringUnmarshall [RPCRT4.@]
865  */
866 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
867   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
868 {
869   ULONG bufsize, memsize, esize;
870 
871   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
872     pStubMsg, *ppMemory, pFormat, fMustAlloc);
873 
874   assert(pFormat && ppMemory && pStubMsg);
875 
876   ReadConformance(pStubMsg, NULL);
877   ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
878 
879   if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
880   {
881     ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
882         pStubMsg->ActualCount, pStubMsg->MaxCount);
883     RpcRaiseException(RPC_S_INVALID_BOUND);
884     return NULL;
885   }
886   if (pStubMsg->Offset)
887   {
888     ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
889     RpcRaiseException(RPC_S_INVALID_BOUND);
890     return NULL;
891   }
892 
893   if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
894   else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
895   else {
896     ERR("Unhandled string type: %#x\n", *pFormat);
897     /* FIXME: raise an exception */
898     esize = 0;
899   }
900 
901   memsize = safe_multiply(esize, pStubMsg->MaxCount);
902   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
903 
904   validate_string_data(pStubMsg, bufsize, esize);
905 
906   if (fMustAlloc)
907     *ppMemory = NdrAllocate(pStubMsg, memsize);
908   else
909   {
910     if (!pStubMsg->IsClient && !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
911       /* if the data in the RPC buffer is big enough, we just point straight
912        * into it */
913       *ppMemory = pStubMsg->Buffer;
914     else if (!*ppMemory)
915       *ppMemory = NdrAllocate(pStubMsg, memsize);
916   }
917 
918   if (*ppMemory == pStubMsg->Buffer)
919     safe_buffer_increment(pStubMsg, bufsize);
920   else
921     safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
922 
923   if (*pFormat == RPC_FC_C_CSTRING) {
924     TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
925   }
926   else if (*pFormat == RPC_FC_C_WSTRING) {
927     TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
928   }
929 
930   return NULL; /* FIXME: is this always right? */
931 }
932 
933 /***********************************************************************
934  *           NdrNonConformantStringMarshall [RPCRT4.@]
935  */
936 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
937                                 unsigned char *pMemory,
938                                 PFORMAT_STRING pFormat)
939 {
940   ULONG esize, size, maxsize;
941 
942   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
943 
944   maxsize = *(USHORT *)&pFormat[2];
945 
946   if (*pFormat == RPC_FC_CSTRING)
947   {
948     ULONG i;
949     const char *str = (const char *)pMemory;
950     for (i = 0; i < maxsize && *str; i++, str++)
951         ;
952     TRACE("string=%s\n", debugstr_an(str, i));
953     pStubMsg->ActualCount = i + 1;
954     esize = 1;
955   }
956   else if (*pFormat == RPC_FC_WSTRING)
957   {
958     ULONG i;
959     const WCHAR *str = (const WCHAR *)pMemory;
960     for (i = 0; i < maxsize && *str; i++, str++)
961         ;
962     TRACE("string=%s\n", debugstr_wn(str, i));
963     pStubMsg->ActualCount = i + 1;
964     esize = 2;
965   }
966   else
967   {
968     ERR("Unhandled string type: %#x\n", *pFormat);
969     RpcRaiseException(RPC_X_BAD_STUB_DATA);
970   }
971 
972   pStubMsg->Offset = 0;
973   WriteVariance(pStubMsg);
974 
975   size = safe_multiply(esize, pStubMsg->ActualCount);
976   safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
977 
978   return NULL;
979 }
980 
981 /***********************************************************************
982  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
983  */
984 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
985                                 unsigned char **ppMemory,
986                                 PFORMAT_STRING pFormat,
987                                 unsigned char fMustAlloc)
988 {
989   ULONG bufsize, memsize, esize, maxsize;
990 
991   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
992     pStubMsg, *ppMemory, pFormat, fMustAlloc);
993 
994   maxsize = *(USHORT *)&pFormat[2];
995 
996   ReadVariance(pStubMsg, NULL, maxsize);
997   if (pStubMsg->Offset)
998   {
999     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
1000     RpcRaiseException(RPC_S_INVALID_BOUND);
1001   }
1002 
1003   if (*pFormat == RPC_FC_CSTRING) esize = 1;
1004   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
1005   else
1006   {
1007     ERR("Unhandled string type: %#x\n", *pFormat);
1008     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1009   }
1010 
1011   memsize = esize * maxsize;
1012   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
1013 
1014   validate_string_data(pStubMsg, bufsize, esize);
1015 
1016   if (fMustAlloc || !*ppMemory)
1017     *ppMemory = NdrAllocate(pStubMsg, memsize);
1018 
1019   safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
1020 
1021   if (*pFormat == RPC_FC_CSTRING) {
1022     TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
1023   }
1024   else if (*pFormat == RPC_FC_WSTRING) {
1025     TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
1026   }
1027 
1028   return NULL;
1029 }
1030 
1031 /***********************************************************************
1032  *           NdrNonConformantStringBufferSize [RPCRT4.@]
1033  */
1034 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1035                                 unsigned char *pMemory,
1036                                 PFORMAT_STRING pFormat)
1037 {
1038   ULONG esize, maxsize;
1039 
1040   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
1041 
1042   maxsize = *(USHORT *)&pFormat[2];
1043 
1044   SizeVariance(pStubMsg);
1045 
1046   if (*pFormat == RPC_FC_CSTRING)
1047   {
1048     ULONG i;
1049     const char *str = (const char *)pMemory;
1050     for (i = 0; i < maxsize && *str; i++, str++)
1051         ;
1052     TRACE("string=%s\n", debugstr_an(str, i));
1053     pStubMsg->ActualCount = i + 1;
1054     esize = 1;
1055   }
1056   else if (*pFormat == RPC_FC_WSTRING)
1057   {
1058     ULONG i;
1059     const WCHAR *str = (const WCHAR *)pMemory;
1060     for (i = 0; i < maxsize && *str; i++, str++)
1061         ;
1062     TRACE("string=%s\n", debugstr_wn(str, i));
1063     pStubMsg->ActualCount = i + 1;
1064     esize = 2;
1065   }
1066   else
1067   {
1068     ERR("Unhandled string type: %#x\n", *pFormat);
1069     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1070   }
1071 
1072   safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
1073 }
1074 
1075 /***********************************************************************
1076  *           NdrNonConformantStringMemorySize [RPCRT4.@]
1077  */
1078 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1079                                 PFORMAT_STRING pFormat)
1080 {
1081   ULONG bufsize, memsize, esize, maxsize;
1082 
1083   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
1084 
1085   maxsize = *(USHORT *)&pFormat[2];
1086 
1087   ReadVariance(pStubMsg, NULL, maxsize);
1088 
1089   if (pStubMsg->Offset)
1090   {
1091     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
1092     RpcRaiseException(RPC_S_INVALID_BOUND);
1093   }
1094 
1095   if (*pFormat == RPC_FC_CSTRING) esize = 1;
1096   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
1097   else
1098   {
1099     ERR("Unhandled string type: %#x\n", *pFormat);
1100     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1101   }
1102 
1103   memsize = esize * maxsize;
1104   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
1105 
1106   validate_string_data(pStubMsg, bufsize, esize);
1107 
1108   safe_buffer_increment(pStubMsg, bufsize);
1109   pStubMsg->MemorySize += memsize;
1110 
1111   return pStubMsg->MemorySize;
1112 }
1113 
1114 static inline void dump_pointer_attr(unsigned char attr)
1115 {
1116     if (attr & RPC_FC_P_ALLOCALLNODES)
1117         TRACE(" RPC_FC_P_ALLOCALLNODES");
1118     if (attr & RPC_FC_P_DONTFREE)
1119         TRACE(" RPC_FC_P_DONTFREE");
1120     if (attr & RPC_FC_P_ONSTACK)
1121         TRACE(" RPC_FC_P_ONSTACK");
1122     if (attr & RPC_FC_P_SIMPLEPOINTER)
1123         TRACE(" RPC_FC_P_SIMPLEPOINTER");
1124     if (attr & RPC_FC_P_DEREF)
1125         TRACE(" RPC_FC_P_DEREF");
1126     TRACE("\n");
1127 }
1128 
1129 /***********************************************************************
1130  *           PointerMarshall [internal]
1131  */
1132 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1133                             unsigned char *Buffer,
1134                             unsigned char *Pointer,
1135                             PFORMAT_STRING pFormat)
1136 {
1137   unsigned type = pFormat[0], attr = pFormat[1];
1138   PFORMAT_STRING desc;
1139   NDR_MARSHALL m;
1140   ULONG pointer_id;
1141   int pointer_needs_marshaling;
1142 
1143   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
1144   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1145   pFormat += 2;
1146   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1147   else desc = pFormat + *(const SHORT*)pFormat;
1148 
1149   switch (type) {
1150   case RPC_FC_RP: /* ref pointer (always non-null) */
1151     if (!Pointer)
1152     {
1153       ERR("NULL ref pointer is not allowed\n");
1154       RpcRaiseException(RPC_X_NULL_REF_POINTER);
1155     }
1156     pointer_needs_marshaling = 1;
1157     break;
1158   case RPC_FC_UP: /* unique pointer */
1159   case RPC_FC_OP: /* object pointer - same as unique here */
1160     if (Pointer)
1161       pointer_needs_marshaling = 1;
1162     else
1163       pointer_needs_marshaling = 0;
1164     pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
1165     TRACE("writing 0x%08x to buffer\n", pointer_id);
1166     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
1167     break;
1168   case RPC_FC_FP:
1169     pointer_needs_marshaling = !NdrFullPointerQueryPointer(
1170       pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
1171     TRACE("writing 0x%08x to buffer\n", pointer_id);
1172     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
1173     break;
1174   default:
1175     FIXME("unhandled ptr type=%02x\n", type);
1176     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1177     return;
1178   }
1179 
1180   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
1181 
1182   if (pointer_needs_marshaling) {
1183     if (attr & RPC_FC_P_DEREF) {
1184       Pointer = *(unsigned char**)Pointer;
1185       TRACE("deref => %p\n", Pointer);
1186     }
1187     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1188     if (m) m(pStubMsg, Pointer, desc);
1189     else FIXME("no marshaller for data type=%02x\n", *desc);
1190   }
1191 
1192   STD_OVERFLOW_CHECK(pStubMsg);
1193 }
1194 
1195 /***********************************************************************
1196  *           PointerUnmarshall [internal]
1197  */
1198 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1199                               unsigned char *Buffer,
1200                               unsigned char **pPointer,
1201                               unsigned char *pSrcPointer,
1202                               PFORMAT_STRING pFormat,
1203                               unsigned char fMustAlloc)
1204 {
1205   unsigned type = pFormat[0], attr = pFormat[1];
1206   PFORMAT_STRING desc;
1207   NDR_UNMARSHALL m;
1208   DWORD pointer_id = 0;
1209   int pointer_needs_unmarshaling;
1210 
1211   TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
1212   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1213   pFormat += 2;
1214   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1215   else desc = pFormat + *(const SHORT*)pFormat;
1216 
1217   switch (type) {
1218   case RPC_FC_RP: /* ref pointer (always non-null) */
1219     pointer_needs_unmarshaling = 1;
1220     break;
1221   case RPC_FC_UP: /* unique pointer */
1222     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1223     TRACE("pointer_id is 0x%08x\n", pointer_id);
1224     if (pointer_id)
1225       pointer_needs_unmarshaling = 1;
1226     else {
1227       *pPointer = NULL;
1228       pointer_needs_unmarshaling = 0;
1229     }
1230     break;
1231   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1232     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1233     TRACE("pointer_id is 0x%08x\n", pointer_id);
1234     if (!fMustAlloc && pSrcPointer)
1235     {
1236         FIXME("free object pointer %p\n", pSrcPointer);
1237         fMustAlloc = TRUE;
1238     }
1239     if (pointer_id)
1240       pointer_needs_unmarshaling = 1;
1241     else
1242       pointer_needs_unmarshaling = 0;
1243     break;
1244   case RPC_FC_FP:
1245     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1246     TRACE("pointer_id is 0x%08x\n", pointer_id);
1247     pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
1248       pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
1249     break;
1250   default:
1251     FIXME("unhandled ptr type=%02x\n", type);
1252     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1253     return;
1254   }
1255 
1256   if (pointer_needs_unmarshaling) {
1257     unsigned char *base_ptr_val = *pPointer;
1258     unsigned char **current_ptr = pPointer;
1259     if (pStubMsg->IsClient) {
1260       TRACE("client\n");
1261       /* if we aren't forcing allocation of memory then try to use the existing
1262        * (source) pointer to unmarshall the data into so that [in,out]
1263        * parameters behave correctly. it doesn't matter if the parameter is
1264        * [out] only since in that case the pointer will be NULL. we force
1265        * allocation when the source pointer is NULL here instead of in the type
1266        * unmarshalling routine for the benefit of the deref code below */
1267       if (!fMustAlloc) {
1268         if (pSrcPointer) {
1269           TRACE("setting *pPointer to %p\n", pSrcPointer);
1270           *pPointer = base_ptr_val = pSrcPointer;
1271         } else
1272           fMustAlloc = TRUE;
1273       }
1274     } else {
1275       TRACE("server\n");
1276       /* the memory in a stub is never initialised, so we have to work out here
1277        * whether we have to initialise it so we can use the optimisation of
1278        * setting the pointer to the buffer, if possible, or set fMustAlloc to
1279        * TRUE. */
1280       if (attr & RPC_FC_P_DEREF) {
1281         fMustAlloc = TRUE;
1282       } else {
1283         base_ptr_val = NULL;
1284         *current_ptr = NULL;
1285       }
1286     }
1287 
1288     if (attr & RPC_FC_P_ALLOCALLNODES)
1289         FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
1290 
1291     if (attr & RPC_FC_P_DEREF) {
1292       if (fMustAlloc) {
1293         base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
1294         *pPointer = base_ptr_val;
1295         current_ptr = (unsigned char **)base_ptr_val;
1296       } else
1297         current_ptr = *(unsigned char***)current_ptr;
1298       TRACE("deref => %p\n", current_ptr);
1299       if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
1300     }
1301     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1302     if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
1303     else FIXME("no unmarshaller for data type=%02x\n", *desc);
1304 
1305     if (type == RPC_FC_FP)
1306       NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
1307                                 base_ptr_val);
1308   }
1309 
1310   TRACE("pointer=%p\n", *pPointer);
1311 }
1312 
1313 /***********************************************************************
1314  *           PointerBufferSize [internal]
1315  */
1316 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1317                               unsigned char *Pointer,
1318                               PFORMAT_STRING pFormat)
1319 {
1320   unsigned type = pFormat[0], attr = pFormat[1];
1321   PFORMAT_STRING desc;
1322   NDR_BUFFERSIZE m;
1323   int pointer_needs_sizing;
1324   ULONG pointer_id;
1325 
1326   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1327   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1328   pFormat += 2;
1329   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1330   else desc = pFormat + *(const SHORT*)pFormat;
1331 
1332   switch (type) {
1333   case RPC_FC_RP: /* ref pointer (always non-null) */
1334     if (!Pointer)
1335     {
1336       ERR("NULL ref pointer is not allowed\n");
1337       RpcRaiseException(RPC_X_NULL_REF_POINTER);
1338     }
1339     break;
1340   case RPC_FC_OP:
1341   case RPC_FC_UP:
1342     /* NULL pointer has no further representation */
1343     if (!Pointer)
1344         return;
1345     break;
1346   case RPC_FC_FP:
1347     pointer_needs_sizing = !NdrFullPointerQueryPointer(
1348       pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1349     if (!pointer_needs_sizing)
1350       return;
1351     break;
1352   default:
1353     FIXME("unhandled ptr type=%02x\n", type);
1354     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1355     return;
1356   }
1357 
1358   if (attr & RPC_FC_P_DEREF) {
1359     Pointer = *(unsigned char**)Pointer;
1360     TRACE("deref => %p\n", Pointer);
1361   }
1362 
1363   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1364   if (m) m(pStubMsg, Pointer, desc);
1365   else FIXME("no buffersizer for data type=%02x\n", *desc);
1366 }
1367 
1368 /***********************************************************************
1369  *           PointerMemorySize [internal]
1370  */
1371 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1372                                        unsigned char *Buffer,
1373                                        PFORMAT_STRING pFormat)
1374 {
1375   unsigned type = pFormat[0], attr = pFormat[1];
1376   PFORMAT_STRING desc;
1377   NDR_MEMORYSIZE m;
1378   DWORD pointer_id = 0;
1379   int pointer_needs_sizing;
1380 
1381   TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1382   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1383   pFormat += 2;
1384   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1385   else desc = pFormat + *(const SHORT*)pFormat;
1386 
1387   switch (type) {
1388   case RPC_FC_RP: /* ref pointer (always non-null) */
1389     pointer_needs_sizing = 1;
1390     break;
1391   case RPC_FC_UP: /* unique pointer */
1392   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1393     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1394     TRACE("pointer_id is 0x%08x\n", pointer_id);
1395     if (pointer_id)
1396       pointer_needs_sizing = 1;
1397     else
1398       pointer_needs_sizing = 0;
1399     break;
1400   case RPC_FC_FP:
1401   {
1402     void *pointer;
1403     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1404     TRACE("pointer_id is 0x%08x\n", pointer_id);
1405     pointer_needs_sizing = !NdrFullPointerQueryRefId(
1406       pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1407     break;
1408   }
1409   default:
1410     FIXME("unhandled ptr type=%02x\n", type);
1411     RpcRaiseException(RPC_X_BAD_STUB_DATA);
1412     return 0;
1413   }
1414 
1415   if (attr & RPC_FC_P_DEREF) {
1416     TRACE("deref\n");
1417   }
1418 
1419   if (pointer_needs_sizing) {
1420     m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1421     if (m) m(pStubMsg, desc);
1422     else FIXME("no memorysizer for data type=%02x\n", *desc);
1423   }
1424 
1425   return pStubMsg->MemorySize;
1426 }
1427 
1428 /***********************************************************************
1429  *           PointerFree [internal]
1430  */
1431 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1432                         unsigned char *Pointer,
1433                         PFORMAT_STRING pFormat)
1434 {
1435   unsigned type = pFormat[0], attr = pFormat[1];
1436   PFORMAT_STRING desc;
1437   NDR_FREE m;
1438   unsigned char *current_pointer = Pointer;
1439 
1440   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1441   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1442   if (attr & RPC_FC_P_DONTFREE) return;
1443   pFormat += 2;
1444   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1445   else desc = pFormat + *(const SHORT*)pFormat;
1446 
1447   if (!Pointer) return;
1448 
1449   if (type == RPC_FC_FP) {
1450     int pointer_needs_freeing = NdrFullPointerFree(
1451       pStubMsg->FullPtrXlatTables, Pointer);
1452     if (!pointer_needs_freeing)
1453       return;
1454   }
1455 
1456   if (attr & RPC_FC_P_DEREF) {
1457     current_pointer = *(unsigned char**)Pointer;
1458     TRACE("deref => %p\n", current_pointer);
1459   }
1460 
1461   m = NdrFreer[*desc & NDR_TABLE_MASK];
1462   if (m) m(pStubMsg, current_pointer, desc);
1463 
1464   /* this check stops us from trying to free buffer memory. we don't have to
1465    * worry about clients, since they won't call this function.
1466    * we don't have to check for the buffer being reallocated because
1467    * BufferStart and BufferEnd won't be reset when allocating memory for
1468    * sending the response. we don't have to check for the new buffer here as
1469    * it won't be used a type memory, only for buffer memory */
1470   if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd)
1471       goto notfree;
1472 
1473   if (attr & RPC_FC_P_ONSTACK) {
1474     TRACE("not freeing stack ptr %p\n", Pointer);
1475     return;
1476   }
1477   TRACE("freeing %p\n", Pointer);
1478   NdrFree(pStubMsg, Pointer);
1479   return;
1480 notfree:
1481   TRACE("not freeing %p\n", Pointer);
1482 }
1483 
1484 /***********************************************************************
1485  *           EmbeddedPointerMarshall
1486  */
1487 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1488                                                unsigned char *pMemory,
1489                                                PFORMAT_STRING pFormat)
1490 {
1491   unsigned char *Mark = pStubMsg->BufferMark;
1492   unsigned rep, count, stride;
1493   unsigned i;
1494   unsigned char *saved_buffer = NULL;
1495 
1496   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1497 
1498   if (*pFormat != RPC_FC_PP) return NULL;
1499   pFormat += 2;
1500 
1501   if (pStubMsg->PointerBufferMark)
1502   {
1503     saved_buffer = pStubMsg->Buffer;
1504     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1505     pStubMsg->PointerBufferMark = NULL;
1506   }
1507 
1508   while (pFormat[0] != RPC_FC_END) {
1509     switch (pFormat[0]) {
1510     default:
1511       FIXME("unknown repeat type %d\n", pFormat[0]);
1512     case RPC_FC_NO_REPEAT:
1513       rep = 1;
1514       stride = 0;
1515       count = 1;
1516       pFormat += 2;
1517       break;
1518     case RPC_FC_FIXED_REPEAT:
1519       rep = *(const WORD*)&pFormat[2];
1520       stride = *(const WORD*)&pFormat[4];
1521       count = *(const WORD*)&pFormat[8];
1522       pFormat += 10;
1523       break;
1524     case RPC_FC_VARIABLE_REPEAT:
1525       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1526       stride = *(const WORD*)&pFormat[2];
1527       count = *(const WORD*)&pFormat[6];
1528       pFormat += 8;
1529       break;
1530     }
1531     for (i = 0; i < rep; i++) {
1532       PFORMAT_STRING info = pFormat;
1533       unsigned char *membase = pMemory + (i * stride);
1534       unsigned char *bufbase = Mark + (i * stride);
1535       unsigned u;
1536 
1537       for (u=0; u<count; u++,info+=8) {
1538         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1539         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1540         unsigned char *saved_memory = pStubMsg->Memory;
1541 
1542         pStubMsg->Memory = pMemory;
1543         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1544         pStubMsg->Memory = saved_memory;
1545       }
1546     }
1547     pFormat += 8 * count;
1548   }
1549 
1550   if (saved_buffer)
1551   {
1552     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1553     pStubMsg->Buffer = saved_buffer;
1554   }
1555 
1556   STD_OVERFLOW_CHECK(pStubMsg);
1557 
1558   return NULL;
1559 }
1560 
1561 /***********************************************************************
1562  *           EmbeddedPointerUnmarshall
1563  */
1564 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1565                                                  unsigned char *pDstBuffer,
1566                                                  unsigned char *pSrcMemoryPtrs,
1567                                                  PFORMAT_STRING pFormat,
1568                                                  unsigned char fMustAlloc)
1569 {
1570   unsigned char *Mark = pStubMsg->BufferMark;
1571   unsigned rep, count, stride;
1572   unsigned i;
1573   unsigned char *saved_buffer = NULL;
1574 
1575   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1576 
1577   if (*pFormat != RPC_FC_PP) return NULL;
1578   pFormat += 2;
1579 
1580   if (pStubMsg->PointerBufferMark)
1581   {
1582     saved_buffer = pStubMsg->Buffer;
1583     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1584     pStubMsg->PointerBufferMark = NULL;
1585   }
1586 
1587   while (pFormat[0] != RPC_FC_END) {
1588     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1589     switch (pFormat[0]) {
1590     default:
1591       FIXME("unknown repeat type %d\n", pFormat[0]);
1592     case RPC_FC_NO_REPEAT:
1593       rep = 1;
1594       stride = 0;
1595       count = 1;
1596       pFormat += 2;
1597       break;
1598     case RPC_FC_FIXED_REPEAT:
1599       rep = *(const WORD*)&pFormat[2];
1600       stride = *(const WORD*)&pFormat[4];
1601       count = *(const WORD*)&pFormat[8];
1602       pFormat += 10;
1603       break;
1604     case RPC_FC_VARIABLE_REPEAT:
1605       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1606       stride = *(const WORD*)&pFormat[2];
1607       count = *(const WORD*)&pFormat[6];
1608       pFormat += 8;
1609       break;
1610     }
1611     for (i = 0; i < rep; i++) {
1612       PFORMAT_STRING info = pFormat;
1613       unsigned char *bufdstbase = pDstBuffer + (i * stride);
1614       unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1615       unsigned char *bufbase = Mark + (i * stride);
1616       unsigned u;
1617 
1618       for (u=0; u<count; u++,info+=8) {
1619         unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1620         unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1621         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1622         PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1623       }
1624     }
1625     pFormat += 8 * count;
1626   }
1627 
1628   if (saved_buffer)
1629   {
1630     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1631     pStubMsg->Buffer = saved_buffer;
1632   }
1633 
1634   return NULL;
1635 }
1636 
1637 /***********************************************************************
1638  *           EmbeddedPointerBufferSize
1639  */
1640 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1641                                       unsigned char *pMemory,
1642                                       PFORMAT_STRING pFormat)
1643 {
1644   unsigned rep, count, stride;
1645   unsigned i;
1646   ULONG saved_buffer_length = 0;
1647 
1648   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1649 
1650   if (pStubMsg->IgnoreEmbeddedPointers) return;
1651 
1652   if (*pFormat != RPC_FC_PP) return;
1653   pFormat += 2;
1654 
1655   if (pStubMsg->PointerLength)
1656   {
1657     saved_buffer_length = pStubMsg->BufferLength;
1658     pStubMsg->BufferLength = pStubMsg->PointerLength;
1659     pStubMsg->PointerLength = 0;
1660   }
1661 
1662   while (pFormat[0] != RPC_FC_END) {
1663     switch (pFormat[0]) {
1664     default:
1665       FIXME("unknown repeat type %d\n", pFormat[0]);
1666     case RPC_FC_NO_REPEAT:
1667       rep = 1;
1668       stride = 0;
1669       count = 1;
1670       pFormat += 2;
1671       break;
1672     case RPC_FC_FIXED_REPEAT:
1673       rep = *(const WORD*)&pFormat[2];
1674       stride = *(const WORD*)&pFormat[4];
1675       count = *(const WORD*)&pFormat[8];
1676       pFormat += 10;
1677       break;
1678     case RPC_FC_VARIABLE_REPEAT:
1679       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1680       stride = *(const WORD*)&pFormat[2];
1681       count = *(const WORD*)&pFormat[6];
1682       pFormat += 8;
1683       break;
1684     }
1685     for (i = 0; i < rep; i++) {
1686       PFORMAT_STRING info = pFormat;
1687       unsigned char *membase = pMemory + (i * stride);
1688       unsigned u;
1689 
1690       for (u=0; u<count; u++,info+=8) {
1691         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1692         unsigned char *saved_memory = pStubMsg->Memory;
1693 
1694         pStubMsg->Memory = pMemory;
1695         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1696         pStubMsg->Memory = saved_memory;
1697       }
1698     }
1699     pFormat += 8 * count;
1700   }
1701 
1702   if (saved_buffer_length)
1703   {
1704     pStubMsg->PointerLength = pStubMsg->BufferLength;
1705     pStubMsg->BufferLength = saved_buffer_length;
1706   }
1707 }
1708 
1709 /***********************************************************************
1710  *           EmbeddedPointerMemorySize [internal]
1711  */
1712 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1713                                                PFORMAT_STRING pFormat)
1714 {
1715   unsigned char *Mark = pStubMsg->BufferMark;
1716   unsigned rep, count, stride;
1717   unsigned i;
1718   unsigned char *saved_buffer = NULL;
1719 
1720   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1721 
1722   if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1723 
1724   if (pStubMsg->PointerBufferMark)
1725   {
1726     saved_buffer = pStubMsg->Buffer;
1727     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1728     pStubMsg->PointerBufferMark = NULL;
1729   }
1730 
1731   if (*pFormat != RPC_FC_PP) return 0;
1732   pFormat += 2;
1733 
1734   while (pFormat[0] != RPC_FC_END) {
1735     switch (pFormat[0]) {
1736     default:
1737       FIXME("unknown repeat type %d\n", pFormat[0]);
1738     case RPC_FC_NO_REPEAT:
1739       rep = 1;
1740       stride = 0;
1741       count = 1;
1742       pFormat += 2;
1743       break;
1744     case RPC_FC_FIXED_REPEAT:
1745       rep = *(const WORD*)&pFormat[2];
1746       stride = *(const WORD*)&pFormat[4];
1747       count = *(const WORD*)&pFormat[8];
1748       pFormat += 10;
1749       break;
1750     case RPC_FC_VARIABLE_REPEAT:
1751       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1752       stride = *(const WORD*)&pFormat[2];
1753       count = *(const WORD*)&pFormat[6];
1754       pFormat += 8;
1755       break;
1756     }
1757     for (i = 0; i < rep; i++) {
1758       PFORMAT_STRING info = pFormat;
1759       unsigned char *bufbase = Mark + (i * stride);
1760       unsigned u;
1761       for (u=0; u<count; u++,info+=8) {
1762         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1763         PointerMemorySize(pStubMsg, bufptr, info+4);
1764       }
1765     }
1766     pFormat += 8 * count;
1767   }
1768 
1769   if (saved_buffer)
1770   {
1771     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1772     pStubMsg->Buffer = saved_buffer;
1773   }
1774 
1775   return 0;
1776 }
1777 
1778 /***********************************************************************
1779  *           EmbeddedPointerFree [internal]
1780  */
1781 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1782                                 unsigned char *pMemory,
1783                                 PFORMAT_STRING pFormat)
1784 {
1785   unsigned rep, count, stride;
1786   unsigned i;
1787 
1788   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1789   if (*pFormat != RPC_FC_PP) return;
1790   pFormat += 2;
1791 
1792   while (pFormat[0] != RPC_FC_END) {
1793     switch (pFormat[0]) {
1794     default:
1795       FIXME("unknown repeat type %d\n", pFormat[0]);
1796     case RPC_FC_NO_REPEAT:
1797       rep = 1;
1798       stride = 0;
1799       count = 1;
1800       pFormat += 2;
1801       break;
1802     case RPC_FC_FIXED_REPEAT:
1803       rep = *(const WORD*)&pFormat[2];
1804       stride = *(const WORD*)&pFormat[4];
1805       count = *(const WORD*)&pFormat[8];
1806       pFormat += 10;
1807       break;
1808     case RPC_FC_VARIABLE_REPEAT:
1809       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1810       stride = *(const WORD*)&pFormat[2];
1811       count = *(const WORD*)&pFormat[6];
1812       pFormat += 8;
1813       break;
1814     }
1815     for (i = 0; i < rep; i++) {
1816       PFORMAT_STRING info = pFormat;
1817       unsigned char *membase = pMemory + (i * stride);
1818       unsigned u;
1819 
1820       for (u=0; u<count; u++,info+=8) {
1821         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1822         unsigned char *saved_memory = pStubMsg->Memory;
1823 
1824         pStubMsg->Memory = pMemory;
1825         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1826         pStubMsg->Memory = saved_memory;
1827       }
1828     }
1829     pFormat += 8 * count;
1830   }
1831 }
1832 
1833 /***********************************************************************
1834  *           NdrPointerMarshall [RPCRT4.@]
1835  */
1836 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1837                                           unsigned char *pMemory,
1838                                           PFORMAT_STRING pFormat)
1839 {
1840   unsigned char *Buffer;
1841 
1842   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1843 
1844   /* Increment the buffer here instead of in PointerMarshall,
1845    * as that is used by embedded pointers which already handle the incrementing
1846    * the buffer, and shouldn't write any additional pointer data to the wire */
1847   if (*pFormat != RPC_FC_RP)
1848   {
1849     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1850     Buffer = pStubMsg->Buffer;
1851     safe_buffer_increment(pStubMsg, 4);
1852   }
1853   else
1854     Buffer = pStubMsg->Buffer;
1855 
1856   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1857 
1858   return NULL;
1859 }
1860 
1861 /***********************************************************************
1862  *           NdrPointerUnmarshall [RPCRT4.@]
1863  */
1864 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1865                                             unsigned char **ppMemory,
1866                                             PFORMAT_STRING pFormat,
1867                                             unsigned char fMustAlloc)
1868 {
1869   unsigned char *Buffer;
1870 
1871   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1872 
1873   /* Increment the buffer here instead of in PointerUnmarshall,
1874    * as that is used by embedded pointers which already handle the incrementing
1875    * the buffer, and shouldn't read any additional pointer data from the
1876    * buffer */
1877   if (*pFormat != RPC_FC_RP)
1878   {
1879     ALIGN_POINTER(pStubMsg->Buffer, 4);
1880     Buffer = pStubMsg->Buffer;
1881     safe_buffer_increment(pStubMsg, 4);
1882   }
1883   else
1884     Buffer = pStubMsg->Buffer;
1885 
1886   PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1887 
1888   return NULL;
1889 }
1890 
1891 /***********************************************************************
1892  *           NdrPointerBufferSize [RPCRT4.@]
1893  */
1894 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1895                                       unsigned char *pMemory,
1896                                       PFORMAT_STRING pFormat)
1897 {
1898   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1899 
1900   /* Increment the buffer length here instead of in PointerBufferSize,
1901    * as that is used by embedded pointers which already handle the buffer
1902    * length, and shouldn't write anything more to the wire */
1903   if (*pFormat != RPC_FC_RP)
1904   {
1905     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1906     safe_buffer_length_increment(pStubMsg, 4);
1907   }
1908 
1909   PointerBufferSize(pStubMsg, pMemory, pFormat);
1910 }
1911 
1912 /***********************************************************************
1913  *           NdrPointerMemorySize [RPCRT4.@]
1914  */
1915 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1916                                   PFORMAT_STRING pFormat)
1917 {
1918   /* unsigned size = *(LPWORD)(pFormat+2); */
1919   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1920   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1921   return 0;
1922 }
1923 
1924 /***********************************************************************
1925  *           NdrPointerFree [RPCRT4.@]
1926  */
1927 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1928                            unsigned char *pMemory,
1929                            PFORMAT_STRING pFormat)
1930 {
1931   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1932   PointerFree(pStubMsg, pMemory, pFormat);
1933 }
1934 
1935 /***********************************************************************
1936  *           NdrSimpleTypeMarshall [RPCRT4.@]
1937  */
1938 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1939                                    unsigned char FormatChar )
1940 {
1941     NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1942 }
1943 
1944 /***********************************************************************
1945  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
1946  *
1947  * Unmarshall a base type.
1948  *
1949  * NOTES
1950  *  Doesn't check that the buffer is long enough before copying, so the caller
1951  * should do this.
1952  */
1953 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1954                                      unsigned char FormatChar )
1955 {
1956 #define BASE_TYPE_UNMARSHALL(type) \
1957         ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
1958         TRACE("pMemory: %p\n", pMemory); \
1959         *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1960         pStubMsg->Buffer += sizeof(type);
1961 
1962     switch(FormatChar)
1963     {
1964     case RPC_FC_BYTE:
1965     case RPC_FC_CHAR:
1966     case RPC_FC_SMALL:
1967     case RPC_FC_USMALL:
1968         BASE_TYPE_UNMARSHALL(UCHAR);
1969         TRACE("value: 0x%02x\n", *pMemory);
1970         break;
1971     case RPC_FC_WCHAR:
1972     case RPC_FC_SHORT:
1973     case RPC_FC_USHORT:
1974         BASE_TYPE_UNMARSHALL(USHORT);
1975         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1976         break;
1977     case RPC_FC_LONG:
1978     case RPC_FC_ULONG:
1979     case RPC_FC_ERROR_STATUS_T:
1980     case RPC_FC_ENUM32:
1981         BASE_TYPE_UNMARSHALL(ULONG);
1982         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1983         break;
1984    case RPC_FC_FLOAT:
1985         BASE_TYPE_UNMARSHALL(float);
1986         TRACE("value: %f\n", *(float *)pMemory);
1987         break;
1988     case RPC_FC_DOUBLE:
1989         BASE_TYPE_UNMARSHALL(double);
1990         TRACE("value: %f\n", *(double *)pMemory);
1991         break;
1992     case RPC_FC_HYPER:
1993         BASE_TYPE_UNMARSHALL(ULONGLONG);
1994         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1995         break;
1996     case RPC_FC_ENUM16:
1997         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
1998         TRACE("pMemory: %p\n", pMemory);
1999         /* 16-bits on the wire, but int in memory */
2000         *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
2001         pStubMsg->Buffer += sizeof(USHORT);
2002         TRACE("value: 0x%08x\n", *(UINT *)pMemory);
2003         break;
2004     case RPC_FC_IGNORE:
2005         break;
2006     default:
2007         FIXME("Unhandled base type: 0x%02x\n", FormatChar);
2008     }
2009 #undef BASE_TYPE_UNMARSHALL
2010 }
2011 
2012 /***********************************************************************
2013  *           NdrSimpleStructMarshall [RPCRT4.@]
2014  */
2015 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2016                                                unsigned char *pMemory,
2017                                                PFORMAT_STRING pFormat)
2018 {
2019   unsigned size = *(const WORD*)(pFormat+2);
2020   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2021 
2022   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
2023 
2024   pStubMsg->BufferMark = pStubMsg->Buffer;
2025   safe_copy_to_buffer(pStubMsg, pMemory, size);
2026 
2027   if (pFormat[0] != RPC_FC_STRUCT)
2028     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
2029 
2030   return NULL;
2031 }
2032 
2033 /***********************************************************************
2034  *           NdrSimpleStructUnmarshall [RPCRT4.@]
2035  */
2036 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2037                                                  unsigned char **ppMemory,
2038                                                  PFORMAT_STRING pFormat,
2039                                                  unsigned char fMustAlloc)
2040 {
2041   unsigned size = *(const WORD*)(pFormat+2);
2042   unsigned char *saved_buffer;
2043   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2044 
2045   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2046 
2047   if (fMustAlloc)
2048     *ppMemory = NdrAllocate(pStubMsg, size);
2049   else
2050   {
2051     if (!pStubMsg->IsClient && !*ppMemory)
2052       /* for servers, we just point straight into the RPC buffer */
2053       *ppMemory = pStubMsg->Buffer;
2054   }
2055 
2056   saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
2057   safe_buffer_increment(pStubMsg, size);
2058   if (pFormat[0] == RPC_FC_PSTRUCT)
2059       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
2060 
2061   TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2062   if (*ppMemory != saved_buffer)
2063       memcpy(*ppMemory, saved_buffer, size);
2064 
2065   return NULL;
2066 }
2067 
2068 /***********************************************************************
2069  *           NdrSimpleStructBufferSize [RPCRT4.@]
2070  */
2071 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2072                                       unsigned char *pMemory,
2073                                       PFORMAT_STRING pFormat)
2074 {
2075   unsigned size = *(const WORD*)(pFormat+2);
2076   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2077 
2078   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2079 
2080   safe_buffer_length_increment(pStubMsg, size);
2081   if (pFormat[0] != RPC_FC_STRUCT)
2082     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
2083 }
2084 
2085 /***********************************************************************
2086  *           NdrSimpleStructMemorySize [RPCRT4.@]
2087  */
2088 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2089                                        PFORMAT_STRING pFormat)
2090 {
2091   unsigned short size = *(const WORD *)(pFormat+2);
2092 
2093   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2094 
2095   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2096   pStubMsg->MemorySize += size;
2097   safe_buffer_increment(pStubMsg, size);
2098 
2099   if (pFormat[0] != RPC_FC_STRUCT)
2100     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
2101   return pStubMsg->MemorySize;
2102 }
2103 
2104 /***********************************************************************
2105  *           NdrSimpleStructFree [RPCRT4.@]
2106  */
2107 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2108                                 unsigned char *pMemory,
2109                                 PFORMAT_STRING pFormat)
2110 {
2111   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2112   if (pFormat[0] != RPC_FC_STRUCT)
2113     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
2114 }
2115 
2116 
2117 #include "pshpack1.h"
2118 typedef struct
2119 {
2120     unsigned char type;
2121     unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2122     ULONG low_value;
2123     ULONG high_value;
2124 } NDR_RANGE;
2125 #include "poppack.h"
2126 
2127 static unsigned long EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2128                                          PFORMAT_STRING pFormat)
2129 {
2130   switch (*pFormat) {
2131   case RPC_FC_STRUCT:
2132   case RPC_FC_PSTRUCT:
2133   case RPC_FC_CSTRUCT:
2134   case RPC_FC_BOGUS_STRUCT:
2135   case RPC_FC_SMFARRAY:
2136   case RPC_FC_SMVARRAY:
2137   case RPC_FC_CSTRING:
2138     return *(const WORD*)&pFormat[2];
2139   case RPC_FC_USER_MARSHAL:
2140     return *(const WORD*)&pFormat[4];
2141   case RPC_FC_RANGE: {
2142     switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2143     case RPC_FC_BYTE:
2144     case RPC_FC_CHAR:
2145     case RPC_FC_SMALL:
2146     case RPC_FC_USMALL:
2147         return sizeof(UCHAR);
2148     case RPC_FC_WCHAR:
2149     case RPC_FC_SHORT:
2150     case RPC_FC_USHORT:
2151         return sizeof(USHORT);
2152     case RPC_FC_LONG:
2153     case RPC_FC_ULONG:
2154     case RPC_FC_ENUM32:
2155         return sizeof(ULONG);
2156     case RPC_FC_FLOAT:
2157         return sizeof(float);
2158     case RPC_FC_DOUBLE:
2159         return sizeof(double);
2160     case RPC_FC_HYPER:
2161         return sizeof(ULONGLONG);
2162     case RPC_FC_ERROR_STATUS_T:
2163         return sizeof(error_status_t);
2164     case RPC_FC_ENUM16:
2165         return sizeof(UINT);
2166     default:
2167         ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2168         RpcRaiseException(RPC_X_BAD_STUB_DATA);
2169     }
2170   }
2171   case RPC_FC_NON_ENCAPSULATED_UNION:
2172     pFormat += 2;
2173     if (pStubMsg->fHasNewCorrDesc)
2174         pFormat += 6;
2175     else
2176         pFormat += 4;
2177 
2178     pFormat += *(const SHORT*)pFormat;
2179     return *(const SHORT*)pFormat;
2180   case RPC_FC_IP:
2181     return sizeof(void *);
2182   case RPC_FC_WSTRING:
2183     return *(const WORD*)&pFormat[2] * 2;
2184   default:
2185     FIXME("unhandled embedded type %02x\n", *pFormat);
2186   }
2187   return 0;
2188 }
2189 
2190 
2191 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2192                                                PFORMAT_STRING pFormat)
2193 {
2194   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2195 
2196   if (!m)
2197   {
2198     FIXME("no memorysizer for data type=%02x\n", *pFormat);
2199     return 0;
2200   }
2201 
2202   return m(pStubMsg, pFormat);
2203 }
2204 
2205 
2206 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2207                                        unsigned char *pMemory,
2208                                        PFORMAT_STRING pFormat,
2209                                        PFORMAT_STRING pPointer)
2210 {
2211   PFORMAT_STRING desc;
2212   NDR_MARSHALL m;
2213   unsigned long size;
2214 
2215   while (*pFormat != RPC_FC_END) {
2216     switch (*pFormat) {
2217     case RPC_FC_BYTE:
2218     case RPC_FC_CHAR:
2219     case RPC_FC_SMALL:
2220     case RPC_FC_USMALL:
2221       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2222       safe_copy_to_buffer(pStubMsg, pMemory, 1);
2223       pMemory += 1;
2224       break;
2225     case RPC_FC_WCHAR:
2226     case RPC_FC_SHORT:
2227     case RPC_FC_USHORT:
2228       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2229       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2230       pMemory += 2;
2231       break;
2232     case RPC_FC_ENUM16:
2233       TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2234       if (32767 < *(DWORD*)pMemory)
2235         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2236       safe_copy_to_buffer(pStubMsg, pMemory, 2);
2237       pMemory += 4;
2238       break;
2239     case RPC_FC_LONG:
2240     case RPC_FC_ULONG:
2241     case RPC_FC_ENUM32:
2242       TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2243       safe_copy_to_buffer(pStubMsg, pMemory, 4);
2244       pMemory += 4;
2245       break;
2246     case RPC_FC_HYPER:
2247       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2248       safe_copy_to_buffer(pStubMsg, pMemory, 8);
2249       pMemory += 8;
2250       break;
2251     case RPC_FC_POINTER:
2252     {
2253       unsigned char *saved_buffer;
2254       int pointer_buffer_mark_set = 0;
2255       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2256       TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2257       if (*pPointer != RPC_FC_RP)
2258         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2259       saved_buffer = pStubMsg->Buffer;
2260       if (pStubMsg->PointerBufferMark)
2261       {
2262         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2263         pStubMsg->PointerBufferMark = NULL;
2264         pointer_buffer_mark_set = 1;
2265       }
2266       else if (*pPointer != RPC_FC_RP)
2267         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2268       PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2269       if (pointer_buffer_mark_set)
2270       {
2271         STD_OVERFLOW_CHECK(pStubMsg);
2272         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2273         pStubMsg->Buffer = saved_buffer;
2274         if (*pPointer != RPC_FC_RP)
2275           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2276       }
2277       TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2278       pPointer += 4;
2279       pMemory += 4;
2280       break;
2281     }
2282     case RPC_FC_ALIGNM4:
2283       ALIGN_POINTER(pMemory, 4);
2284       break;
2285     case RPC_FC_ALIGNM8:
2286       ALIGN_POINTER(pMemory, 8);
2287       break;
2288     case RPC_FC_STRUCTPAD1:
2289     case RPC_FC_STRUCTPAD2:
2290     case RPC_FC_STRUCTPAD3:
2291     case RPC_FC_STRUCTPAD4:
2292     case RPC_FC_STRUCTPAD5:
2293     case RPC_FC_STRUCTPAD6:
2294     case RPC_FC_STRUCTPAD7:
2295       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2296       break;
2297     case RPC_FC_EMBEDDED_COMPLEX:
2298       pMemory += pFormat[1];
2299       pFormat += 2;
2300       desc = pFormat + *(const SHORT*)pFormat;
2301       size = EmbeddedComplexSize(pStubMsg, desc);
2302       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
2303       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2304       if (m)
2305       {
2306         /* for some reason interface pointers aren't generated as
2307          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2308          * they still need the derefencing treatment that pointers are
2309          * given */
2310         if (*desc == RPC_FC_IP)
2311           m(pStubMsg, *(unsigned char **)pMemory, desc);
2312         else
2313           m(pStubMsg, pMemory, desc);
2314       }
2315       else FIXME("no marshaller for embedded type %02x\n", *desc);
2316       pMemory += size;
2317       pFormat += 2;
2318       continue;
2319     case RPC_FC_PAD:
2320       break;
2321     default:
2322       FIXME("unhandled format 0x%02x\n", *pFormat);
2323     }
2324     pFormat++;
2325   }
2326 
2327   return pMemory;
2328 }
2329 
2330 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2331                                          unsigned char *pMemory,
2332                                          PFORMAT_STRING pFormat,
2333                                          PFORMAT_STRING pPointer,
2334                                          unsigned char fMustAlloc)
2335 {
2336   PFORMAT_STRING desc;
2337   NDR_UNMARSHALL m;
2338   unsigned long size;
2339 
2340   while (*pFormat != RPC_FC_END) {
2341     switch (*pFormat) {
2342     case RPC_FC_BYTE:
2343     case RPC_FC_CHAR:
2344     case RPC_FC_SMALL:
2345     case RPC_FC_USMALL:
2346       safe_copy_from_buffer(pStubMsg, pMemory, 1);
2347       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2348       pMemory += 1;
2349       break;
2350     case RPC_FC_WCHAR:
2351     case RPC_FC_SHORT:
2352     case RPC_FC_USHORT:
2353       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2354       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2355       pMemory += 2;
2356       break;
2357     case RPC_FC_ENUM16:
2358       safe_copy_from_buffer(pStubMsg, pMemory, 2);
2359       *(DWORD*)pMemory &= 0xffff;
2360       TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2361       if (32767 < *(DWORD*)pMemory)
2362         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2363       pMemory += 4;
2364       break;
2365     case RPC_FC_LONG:
2366     case RPC_FC_ULONG:
2367     case RPC_FC_ENUM32:
2368       safe_copy_from_buffer(pStubMsg, pMemory, 4);
2369       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2370       pMemory += 4;
2371       break;
2372     case RPC_FC_HYPER:
2373       safe_copy_from_buffer(pStubMsg, pMemory, 8);
2374       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2375       pMemory += 8;
2376       break;
2377     case RPC_FC_POINTER:
2378     {
2379       unsigned char *saved_buffer;
2380       int pointer_buffer_mark_set = 0;
2381       TRACE("pointer => %p\n", pMemory);
2382       if (*pPointer != RPC_FC_RP)
2383         ALIGN_POINTER(pStubMsg->Buffer, 4);
2384       saved_buffer = pStubMsg->Buffer;
2385       if (pStubMsg->PointerBufferMark)
2386       {
2387         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2388         pStubMsg->PointerBufferMark = NULL;
2389         pointer_buffer_mark_set = 1;
2390       }
2391       else if (*pPointer != RPC_FC_RP)
2392         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2393 
2394       PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
2395       if (pointer_buffer_mark_set)
2396       {
2397         STD_OVERFLOW_CHECK(pStubMsg);
2398         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2399         pStubMsg->Buffer = saved_buffer;
2400         if (*pPointer != RPC_FC_RP)
2401           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2402       }
2403       pPointer += 4;
2404       pMemory += 4;
2405       break;
2406     }
2407     case RPC_FC_ALIGNM4:
2408       ALIGN_POINTER_CLEAR(pMemory, 4);
2409       break;
2410     case RPC_FC_ALIGNM8:
2411       ALIGN_POINTER_CLEAR(pMemory, 8);
2412       break;
2413     case RPC_FC_STRUCTPAD1:
2414     case RPC_FC_STRUCTPAD2:
2415     case RPC_FC_STRUCTPAD3:
2416     case RPC_FC_STRUCTPAD4:
2417     case RPC_FC_STRUCTPAD5:
2418     case RPC_FC_STRUCTPAD6:
2419     case RPC_FC_STRUCTPAD7:
2420       memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2421       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2422       break;
2423     case RPC_FC_EMBEDDED_COMPLEX:
2424       pMemory += pFormat[1];
2425       pFormat += 2;
2426       desc = pFormat + *(const SHORT*)pFormat;
2427       size = EmbeddedComplexSize(pStubMsg, desc);
2428       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
2429       if (fMustAlloc)
2430         /* we can't pass fMustAlloc=TRUE into the marshaller for this type
2431          * since the type is part of the memory block that is encompassed by
2432          * the whole complex type. Memory is forced to allocate when pointers
2433          * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
2434          * clearing the memory we pass in to the unmarshaller */
2435         memset(pMemory, 0, size);
2436       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2437       if (m)
2438       {
2439         /* for some reason interface pointers aren't generated as
2440          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2441          * they still need the derefencing treatment that pointers are
2442          * given */
2443         if (*desc == RPC_FC_IP)
2444           m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2445         else
2446           m(pStubMsg, &pMemory, desc, FALSE);
2447       }
2448       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2449       pMemory += size;
2450       pFormat += 2;
2451       continue;
2452     case RPC_FC_PAD:
2453       break;
2454     default:
2455       FIXME("unhandled format %d\n", *pFormat);
2456     }
2457     pFormat++;
2458   }
2459 
2460   return pMemory;
2461 }
2462 
2463 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2464                                          unsigned char *pMemory,
2465                                          PFORMAT_STRING pFormat,
2466                                          PFORMAT_STRING pPointer)
2467 {
2468   PFORMAT_STRING desc;
2469   NDR_BUFFERSIZE m;
2470   unsigned long size;
2471 
2472   while (*pFormat != RPC_FC_END) {
2473     switch (*pFormat) {
2474     case RPC_FC_BYTE:
2475     case RPC_FC_CHAR:
2476     case RPC_FC_SMALL:
2477     case RPC_FC_USMALL:
2478       safe_buffer_length_increment(pStubMsg, 1);
2479       pMemory += 1;
2480       break;
2481     case RPC_FC_WCHAR:
2482     case RPC_FC_SHORT:
2483     case RPC_FC_USHORT:
2484       safe_buffer_length_increment(pStubMsg, 2);
2485       pMemory += 2;
2486       break;
2487     case RPC_FC_ENUM16:
2488       safe_buffer_length_increment(pStubMsg, 2);
2489       pMemory += 4;
2490       break;
2491     case RPC_FC_LONG:
2492     case RPC_FC_ULONG:
2493     case RPC_FC_ENUM32:
2494       safe_buffer_length_increment(pStubMsg, 4);
2495       pMemory += 4;
2496       break;
2497     case RPC_FC_HYPER:
2498       safe_buffer_length_increment(pStubMsg, 8);
2499       pMemory += 8;
2500       break;
2501     case RPC_FC_POINTER:
2502       if (!pStubMsg->IgnoreEmbeddedPointers)
2503       {
2504         int saved_buffer_length = pStubMsg->BufferLength;
2505         pStubMsg->BufferLength = pStubMsg->PointerLength;
2506         pStubMsg->PointerLength = 0;
2507         if(!pStubMsg->BufferLength)
2508           ERR("BufferLength == 0??\n");
2509         PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2510         pStubMsg->PointerLength = pStubMsg->BufferLength;
2511         pStubMsg->BufferLength = saved_buffer_length;
2512       }
2513       if (*pPointer != RPC_FC_RP)
2514       {
2515         ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2516         safe_buffer_length_increment(pStubMsg, 4);
2517       }
2518       pPointer += 4;
2519       pMemory += 4;
2520       break;
2521     case RPC_FC_ALIGNM4:
2522       ALIGN_POINTER(pMemory, 4);
2523       break;
2524     case RPC_FC_ALIGNM8:
2525       ALIGN_POINTER(pMemory, 8);
2526       break;
2527     case RPC_FC_STRUCTPAD1:
2528     case RPC_FC_STRUCTPAD2:
2529     case RPC_FC_STRUCTPAD3:
2530     case RPC_FC_STRUCTPAD4:
2531     case RPC_FC_STRUCTPAD5:
2532     case RPC_FC_STRUCTPAD6:
2533     case RPC_FC_STRUCTPAD7:
2534       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2535       break;
2536     case RPC_FC_EMBEDDED_COMPLEX:
2537       pMemory += pFormat[1];
2538       pFormat += 2;
2539       desc = pFormat + *(const SHORT*)pFormat;
2540       size = EmbeddedComplexSize(pStubMsg, desc);
2541       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2542       if (m)
2543       {
2544         /* for some reason interface pointers aren't generated as
2545          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2546          * they still need the derefencing treatment that pointers are
2547          * given */
2548         if (*desc == RPC_FC_IP)
2549           m(pStubMsg, *(unsigned char **)pMemory, desc);
2550         else
2551           m(pStubMsg, pMemory, desc);
2552       }
2553       else FIXME("no buffersizer for embedded type %02x\n", *desc);
2554       pMemory += size;
2555       pFormat += 2;
2556       continue;
2557     case RPC_FC_PAD:
2558       break;
2559     default:
2560       FIXME("unhandled format 0x%02x\n", *pFormat);
2561     }
2562     pFormat++;
2563   }
2564 
2565   return pMemory;
2566 }
2567 
2568 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2569                                    unsigned char *pMemory,
2570                                    PFORMAT_STRING pFormat,
2571                                    PFORMAT_STRING pPointer)
2572 {
2573   PFORMAT_STRING desc;
2574   NDR_FREE m;
2575   unsigned long size;
2576 
2577   while (*pFormat != RPC_FC_END) {
2578     switch (*pFormat) {
2579     case RPC_FC_BYTE:
2580     case RPC_FC_CHAR:
2581     case RPC_FC_SMALL:
2582     case RPC_FC_USMALL:
2583       pMemory += 1;
2584       break;
2585     case RPC_FC_WCHAR:
2586     case RPC_FC_SHORT:
2587     case RPC_FC_USHORT:
2588       pMemory += 2;
2589       break;
2590     case RPC_FC_LONG:
2591     case RPC_FC_ULONG:
2592     case RPC_FC_ENUM16:
2593     case RPC_FC_ENUM32:
2594       pMemory += 4;
2595       break;
2596     case RPC_FC_HYPER:
2597       pMemory += 8;
2598       break;
2599     case RPC_FC_POINTER:
2600       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2601       pPointer += 4;
2602       pMemory += 4;
2603       break;
2604     case RPC_FC_ALIGNM4:
2605       ALIGN_POINTER(pMemory, 4);
2606       break;
2607     case RPC_FC_ALIGNM8:
2608       ALIGN_POINTER(pMemory, 8);
2609       break;
2610     case RPC_FC_STRUCTPAD1:
2611     case RPC_FC_STRUCTPAD2:
2612     case RPC_FC_STRUCTPAD3:
2613     case RPC_FC_STRUCTPAD4:
2614     case RPC_FC_STRUCTPAD5:
2615     case RPC_FC_STRUCTPAD6:
2616     case RPC_FC_STRUCTPAD7:
2617       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2618       break;
2619     case RPC_FC_EMBEDDED_COMPLEX:
2620       pMemory += pFormat[1];
2621       pFormat += 2;
2622       desc = pFormat + *(const SHORT*)pFormat;
2623       size = EmbeddedComplexSize(pStubMsg, desc);
2624       m = NdrFreer[*desc & NDR_TABLE_MASK];
2625       if (m)
2626       {
2627         /* for some reason interface pointers aren't generated as
2628          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2629          * they still need the derefencing treatment that pointers are
2630          * given */
2631         if (*desc == RPC_FC_IP)
2632           m(pStubMsg, *(unsigned char **)pMemory, desc);
2633         else
2634           m(pStubMsg, pMemory, desc);
2635       }
2636       pMemory += size;
2637       pFormat += 2;
2638       continue;
2639     case RPC_FC_PAD:
2640       break;
2641     default:
2642       FIXME("unhandled format 0x%02x\n", *pFormat);
2643     }
2644     pFormat++;
2645   }
2646 
2647   return pMemory;
2648 }
2649 
2650 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2651                                              PFORMAT_STRING pFormat,
2652                                              PFORMAT_STRING pPointer)
2653 {
2654   PFORMAT_STRING desc;
2655   unsigned long size = 0;
2656 
2657   while (*pFormat != RPC_FC_END) {
2658     switch (*pFormat) {
2659     case RPC_FC_BYTE:
2660     case RPC_FC_CHAR:
2661     case RPC_FC_SMALL:
2662     case RPC_FC_USMALL:
2663       size += 1;
2664       safe_buffer_increment(pStubMsg, 1);
2665       break;
2666     case RPC_FC_WCHAR:
2667     case RPC_FC_SHORT:
2668     case RPC_FC_USHORT:
2669       size += 2;
2670       safe_buffer_increment(pStubMsg, 2);
2671       break;
2672     case RPC_FC_ENUM16:
2673       size += 4;
2674       safe_buffer_increment(pStubMsg, 2);
2675       break;
2676     case RPC_FC_LONG:
2677     case RPC_FC_ULONG:
2678     case RPC_FC_ENUM32:
2679       size += 4;
2680       safe_buffer_increment(pStubMsg, 4);
2681       break;
2682     case RPC_FC_HYPER:
2683       size += 8;
2684       safe_buffer_increment(pStubMsg, 8);
2685       break;
2686     case RPC_FC_POINTER:
2687     {
2688       unsigned char *saved_buffer;
2689       int pointer_buffer_mark_set = 0;
2690       if (*pPointer != RPC_FC_RP)
2691         ALIGN_POINTER(pStubMsg->Buffer, 4);
2692       saved_buffer = pStubMsg->Buffer;
2693       if (pStubMsg->PointerBufferMark)
2694       {
2695         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2696         pStubMsg->PointerBufferMark = NULL;
2697         pointer_buffer_mark_set = 1;
2698       }
2699       else if (*pPointer != RPC_FC_RP)
2700         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2701 
2702       if (!pStubMsg->IgnoreEmbeddedPointers)
2703         PointerMemorySize(pStubMsg, saved_buffer, pPointer);
2704       if (pointer_buffer_mark_set)
2705       {
2706         STD_OVERFLOW_CHECK(pStubMsg);
2707         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2708         pStubMsg->Buffer = saved_buffer;
2709         if (*pPointer != RPC_FC_RP)
2710           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2711       }
2712       pPointer += 4;
2713       size += 4;
2714       break;
2715     }
2716     case RPC_FC_ALIGNM4:
2717       ALIGN_LENGTH(size, 4);
2718       ALIGN_POINTER(pStubMsg->Buffer, 4);
2719       break;
2720     case RPC_FC_ALIGNM8:
2721       ALIGN_LENGTH(size, 8);
2722       ALIGN_POINTER(pStubMsg->Buffer, 8);
2723       break;
2724     case RPC_FC_STRUCTPAD1:
2725     case RPC_FC_STRUCTPAD2:
2726     case RPC_FC_STRUCTPAD3:
2727     case RPC_FC_STRUCTPAD4:
2728     case RPC_FC_STRUCTPAD5:
2729     case RPC_FC_STRUCTPAD6:
2730     case RPC_FC_STRUCTPAD7:
2731       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2732       break;
2733     case RPC_FC_EMBEDDED_COMPLEX:
2734       size += pFormat[1];
2735       pFormat += 2;
2736       desc = pFormat + *(const SHORT*)pFormat;
2737       size += EmbeddedComplexMemorySize(pStubMsg, desc);
2738       pFormat += 2;
2739       continue;
2740     case RPC_FC_PAD:
2741       break;
2742     default:
2743       FIXME("unhandled format 0x%02x\n", *pFormat);
2744     }
2745     pFormat++;
2746   }
2747 
2748   return size;
2749 }
2750 
2751 unsigned long ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,
2752                                 PFORMAT_STRING pFormat)
2753 {
2754   PFORMAT_STRING desc;
2755   unsigned long size = 0;
2756 
2757   while (*pFormat != RPC_FC_END) {
2758     switch (*pFormat) {
2759     case RPC_FC_BYTE:
2760     case RPC_FC_CHAR:
2761     case RPC_FC_SMALL:
2762     case RPC_FC_USMALL:
2763       size += 1;
2764       break;
2765     case RPC_FC_WCHAR:
2766     case RPC_FC_SHORT:
2767     case RPC_FC_USHORT:
2768       size += 2;
2769       break;
2770     case RPC_FC_LONG:
2771     case RPC_FC_ULONG:
2772     case RPC_FC_ENUM16:
2773     case RPC_FC_ENUM32:
2774       size += 4;
2775       break;
2776     case RPC_FC_HYPER:
2777       size += 8;
2778       break;
2779     case RPC_FC_POINTER:
2780       size += sizeof(void *);
2781       break;
2782     case RPC_FC_ALIGNM4:
2783       ALIGN_LENGTH(size, 4);
2784       break;
2785     case RPC_FC_ALIGNM8:
2786       ALIGN_LENGTH(size, 8);
2787       break;
2788     case RPC_FC_STRUCTPAD1:
2789     case RPC_FC_STRUCTPAD2:
2790     case RPC_FC_STRUCTPAD3:
2791     case RPC_FC_STRUCTPAD4:
2792     case RPC_FC_STRUCTPAD5:
2793     case RPC_FC_STRUCTPAD6:
2794     case RPC_FC_STRUCTPAD7:
2795       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2796       break;
2797     case RPC_FC_EMBEDDED_COMPLEX:
2798       size += pFormat[1];
2799       pFormat += 2;
2800       desc = pFormat + *(const SHORT*)pFormat;
2801       size += EmbeddedComplexSize(pStubMsg, desc);
2802       pFormat += 2;
2803       continue;
2804     case RPC_FC_PAD:
2805       break;
2806     default:
2807       FIXME("unhandled format 0x%02x\n", *pFormat);
2808     }
2809     pFormat++;
2810   }
2811 
2812   return size;
2813 }
2814 
2815 /***********************************************************************
2816  *           NdrComplexStructMarshall [RPCRT4.@]
2817  */
2818 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2819                                                 unsigned char *pMemory,
2820                                                 PFORMAT_STRING pFormat)
2821 {
2822   PFORMAT_STRING conf_array = NULL;
2823   PFORMAT_STRING pointer_desc = NULL;
2824   unsigned char *OldMemory = pStubMsg->Memory;
2825   int pointer_buffer_mark_set = 0;
2826 
2827   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2828 
2829   if (!pStubMsg->PointerBufferMark)
2830   {
2831     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2832     /* save buffer length */
2833     unsigned long saved_buffer_length = pStubMsg->BufferLength;
2834 
2835     /* get the buffer pointer after complex array data, but before
2836      * pointer data */
2837     pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2838     pStubMsg->IgnoreEmbeddedPointers = 1;
2839     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2840     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2841 
2842     /* save it for use by embedded pointer code later */
2843     pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2844     TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2845     pointer_buffer_mark_set = 1;
2846 
2847     /* restore the original buffer length */
2848     pStubMsg->BufferLength = saved_buffer_length;
2849   }
2850 
2851   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
2852 
2853   pFormat += 4;
2854   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
2855   pFormat += 2;
2856   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2857   pFormat += 2;
2858 
2859   pStubMsg->Memory = pMemory;
2860 
2861   pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2862 
2863   if (conf_array)
2864     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2865 
2866   pStubMsg->Memory = OldMemory;
2867 
2868   if (pointer_buffer_mark_set)
2869   {
2870     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2871     pStubMsg->PointerBufferMark = NULL;
2872   }
2873 
2874   STD_OVERFLOW_CHECK(pStubMsg);
2875 
2876   return NULL;
2877 }
2878 
2879 /***********************************************************************
2880  *           NdrComplexStructUnmarshall [RPCRT4.@]
2881  */
2882 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2883                                                   unsigned char **ppMemory,
2884                                                   PFORMAT_STRING pFormat,
2885                                                   unsigned char fMustAlloc)
2886 {
2887   unsigned size = *(const WORD*)(pFormat+2);
2888   PFORMAT_STRING conf_array = NULL;
2889   PFORMAT_STRING pointer_desc = NULL;
2890   unsigned char *pMemory;
2891   int pointer_buffer_mark_set = 0;
2892 
2893   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2894 
2895   if (!pStubMsg->PointerBufferMark)
2896   {
2897     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2898     /* save buffer pointer */
2899     unsigned char *saved_buffer = pStubMsg->Buffer;
2900 
2901     /* get the buffer pointer after complex array data, but before
2902      * pointer data */
2903     pStubMsg->IgnoreEmbeddedPointers = 1;
2904     NdrComplexStructMemorySize(pStubMsg, pFormat);
2905     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2906 
2907     /* save it for use by embedded pointer code later */
2908     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2909     TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2910     pointer_buffer_mark_set = 1;
2911 
2912     /* restore the original buffer */
2913     pStubMsg->Buffer = saved_buffer;
2914   }
2915 
2916   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2917 
2918   if (fMustAlloc || !*ppMemory)
2919     *ppMemory = NdrAllocate(pStubMsg, size);
2920 
2921   pFormat += 4;
2922   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
2923   pFormat += 2;
2924   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2925   pFormat += 2;
2926 
2927   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
2928 
2929   if (conf_array)
2930     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2931 
2932   if (pointer_buffer_mark_set)
2933   {
2934     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2935     pStubMsg->PointerBufferMark = NULL;
2936   }
2937 
2938   return NULL;
2939 }
2940 
2941 /***********************************************************************
2942  *           NdrComplexStructBufferSize [RPCRT4.@]
2943  */
2944 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2945                                        unsigned char *pMemory,
2946                                        PFORMAT_STRING pFormat)
2947 {
2948   PFORMAT_STRING conf_array = NULL;
2949   PFORMAT_STRING pointer_desc = NULL;
2950   unsigned char *OldMemory = pStubMsg->Memory;
2951   int pointer_length_set = 0;
2952 
2953   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2954 
2955   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2956 
2957   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2958   {
2959     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2960     unsigned long saved_buffer_length = pStubMsg->BufferLength;
2961 
2962     /* get the buffer length after complex struct data, but before
2963      * pointer data */
2964     pStubMsg->IgnoreEmbeddedPointers = 1;
2965     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2966     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2967 
2968     /* save it for use by embedded pointer code later */
2969     pStubMsg->PointerLength = pStubMsg->BufferLength;
2970     pointer_length_set = 1;
2971     TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2972 
2973     /* restore the original buffer length */
2974     pStubMsg->BufferLength = saved_buffer_length;
2975   }
2976 
2977   pFormat += 4;
2978   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
2979   pFormat += 2;
2980   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2981   pFormat += 2;
2982 
2983   pStubMsg->Memory = pMemory;
2984 
2985   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2986 
2987   if (conf_array)
2988     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2989 
2990   pStubMsg->Memory = OldMemory;
2991 
2992   if(pointer_length_set)
2993   {
2994     pStubMsg->BufferLength = pStubMsg->PointerLength;
2995     pStubMsg->PointerLength = 0;
2996   }
2997 
2998 }
2999 
3000 /***********************************************************************
3001  *           NdrComplexStructMemorySize [RPCRT4.@]
3002  */
3003 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3004                                         PFORMAT_STRING pFormat)
3005 {
3006   unsigned size = *(const WORD*)(pFormat+2);
3007   PFORMAT_STRING conf_array = NULL;
3008   PFORMAT_STRING pointer_desc = NULL;
3009 
3010   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3011 
3012   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3013 
3014   pFormat += 4;
3015   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3016   pFormat += 2;
3017   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3018   pFormat += 2;
3019 
3020   ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3021 
3022   if (conf_array)
3023     NdrConformantArrayMemorySize(pStubMsg, conf_array);
3024 
3025   return size;
3026 }
3027 
3028 /***********************************************************************
3029  *           NdrComplexStructFree [RPCRT4.@]
3030  */
3031 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3032                                  unsigned char *pMemory,
3033                                  PFORMAT_STRING pFormat)
3034 {
3035   PFORMAT_STRING conf_array = NULL;
3036   PFORMAT_STRING pointer_desc = NULL;
3037   unsigned char *OldMemory = pStubMsg->Memory;
3038 
3039   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3040 
3041   pFormat += 4;
3042   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3043   pFormat += 2;
3044   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3045   pFormat += 2;
3046 
3047   pStubMsg->Memory = pMemory;
3048 
3049   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3050 
3051   if (conf_array)
3052     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
3053 
3054   pStubMsg->Memory = OldMemory;
3055 }
3056 
3057 /***********************************************************************
3058  *           NdrConformantArrayMarshall [RPCRT4.@]
3059  */
3060 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3061                                                   unsigned char *pMemory,
3062                                                   PFORMAT_STRING pFormat)
3063 {
3064   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
3065   unsigned char alignment = pFormat[1] + 1;
3066 
3067   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3068   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3069 
3070   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3071 
3072   WriteConformance(pStubMsg);
3073 
3074   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3075 
3076   size = safe_multiply(esize, pStubMsg->MaxCount);
3077   pStubMsg->BufferMark = pStubMsg->Buffer;
3078   safe_copy_to_buffer(pStubMsg, pMemory, size);
3079 
3080   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3081 
3082   return NULL;
3083 }
3084 
3085 /***********************************************************************
3086  *           NdrConformantArrayUnmarshall [RPCRT4.@]
3087  */
3088 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3089                                                     unsigned char **ppMemory,
3090                                                     PFORMAT_STRING pFormat,
3091                                                     unsigned char fMustAlloc)
3092 {
3093   DWORD size, esize = *(const WORD*)(pFormat+2);
3094   unsigned char alignment = pFormat[1] + 1;
3095   unsigned char *saved_buffer;
3096 
3097   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3098   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3099 
3100   pFormat = ReadConformance(pStubMsg, pFormat+4);
3101 
3102   size = safe_multiply(esize, pStubMsg->MaxCount);
3103   ALIGN_POINTER(pStubMsg->Buffer, alignment);
3104 
3105   if (fMustAlloc)
3106     *ppMemory = NdrAllocate(pStubMsg, size);
3107   else
3108   {
3109     if (!pStubMsg->IsClient && !*ppMemory)
3110       /* for servers, we just point straight into the RPC buffer */
3111       *ppMemory = pStubMsg->Buffer;
3112   }
3113 
3114   saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3115   safe_buffer_increment(pStubMsg, size);
3116   EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3117 
3118   TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
3119   if (*ppMemory != saved_buffer)
3120       memcpy(*ppMemory, saved_buffer, size);
3121 
3122   return NULL;
3123 }
3124 
3125 /***********************************************************************
3126  *           NdrConformantArrayBufferSize [RPCRT4.@]
3127  */
3128 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3129                                          unsigned char *pMemory,
3130                                          PFORMAT_STRING pFormat)
3131 {
3132   DWORD size, esize = *(const WORD*)(pFormat+2);
3133   unsigned char alignment = pFormat[1] + 1;
3134 
3135   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3136   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3137 
3138   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3139 
3140   SizeConformance(pStubMsg);
3141 
3142   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3143 
3144   size = safe_multiply(esize, pStubMsg->MaxCount);
3145   /* conformance value plus array */
3146   safe_buffer_length_increment(pStubMsg, size);
3147 
3148   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3149 }
3150 
3151 /***********************************************************************
3152  *           NdrConformantArrayMemorySize [RPCRT4.@]
3153  */
3154 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3155                                           PFORMAT_STRING pFormat)
3156 {
3157   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
3158   unsigned char alignment = pFormat[1] + 1;
3159 
3160   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3161   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3162 
3163   pFormat = ReadConformance(pStubMsg, pFormat+4);
3164   size = safe_multiply(esize, pStubMsg->MaxCount);
3165   pStubMsg->MemorySize += size;
3166 
3167   ALIGN_POINTER(pStubMsg->Buffer, alignment);
3168   pStubMsg->BufferMark = pStubMsg->Buffer;
3169   safe_buffer_increment(pStubMsg, size);
3170 
3171   EmbeddedPointerMemorySize(pStubMsg, pFormat);
3172 
3173   return pStubMsg->MemorySize;
3174 }
3175 
3176 /***********************************************************************
3177  *           NdrConformantArrayFree [RPCRT4.@]
3178  */
3179 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3180                                    unsigned char *pMemory,
3181                                    PFORMAT_STRING pFormat)
3182 {
3183   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3184   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3185 
3186   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3187 
3188   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3189 }
3190 
3191 
3192 /***********************************************************************
3193  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
3194  */
3195 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
3196                                                          unsigned char* pMemory,
3197                                                          PFORMAT_STRING pFormat )
3198 {
3199     ULONG bufsize;
3200     unsigned char alignment = pFormat[1] + 1;
3201     DWORD esize = *(const WORD*)(pFormat+2);
3202 
3203     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3204 
3205     if (pFormat[0] != RPC_FC_CVARRAY)
3206     {
3207         ERR("invalid format type %x\n", pFormat[0]);
3208         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3209         return NULL;
3210     }
3211 
3212     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3213     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3214 
3215     WriteConformance(pStubMsg);
3216     WriteVariance(pStubMsg);
3217 
3218     ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3219 
3220     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3221 
3222     pStubMsg->BufferMark = pStubMsg->Buffer;
3223     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
3224 
3225     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3226 
3227     return NULL;
3228 }
3229 
3230 
3231 /***********************************************************************
3232  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
3233  */
3234 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
3235                                                            unsigned char** ppMemory,
3236                                                            PFORMAT_STRING pFormat,
3237                                                            unsigned char fMustAlloc )
3238 {
3239     ULONG bufsize, memsize;
3240     unsigned char alignment = pFormat[1] + 1;
3241     DWORD esize = *(const WORD*)(pFormat+2);
3242     unsigned char *saved_buffer;
3243     ULONG offset;
3244 
3245     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3246 
3247     if (pFormat[0] != RPC_FC_CVARRAY)
3248     {
3249         ERR("invalid format type %x\n", pFormat[0]);
3250         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3251         return NULL;
3252     }
3253 
3254     pFormat = ReadConformance(pStubMsg, pFormat+4);
3255     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3256 
3257     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3258 
3259     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3260     memsize = safe_multiply(esize, pStubMsg->MaxCount);
3261     offset = pStubMsg->Offset;
3262 
3263     if (!*ppMemory || fMustAlloc)
3264         *ppMemory = NdrAllocate(pStubMsg, memsize);
3265     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3266     safe_buffer_increment(pStubMsg, bufsize);
3267 
3268     EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3269 
3270     memcpy(*ppMemory + offset, saved_buffer, bufsize);
3271 
3272     return NULL;
3273 }
3274 
3275 
3276 /***********************************************************************
3277  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
3278  */
3279 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
3280                                            unsigned char* pMemory,
3281                                            PFORMAT_STRING pFormat )
3282 {
3283     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3284 
3285     if (pFormat[0] != RPC_FC_CVARRAY)
3286     {
3287         ERR("invalid format type %x\n", pFormat[0]);
3288         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3289         return;
3290     }
3291 
3292     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3293     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3294 
3295     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3296 }
3297 
3298 
3299 /***********************************************************************
3300  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
3301  */
3302 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
3303                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
3304 {
3305     unsigned char alignment = pFormat[1] + 1;
3306     DWORD esize = *(const WORD*)(pFormat+2);
3307 
3308     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3309 
3310     if (pFormat[0] != RPC_FC_CVARRAY)
3311     {
3312         ERR("invalid format type %x\n", pFormat[0]);
3313         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3314         return;
3315     }
3316 
3317     /* compute size */
3318     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3319     /* compute length */
3320     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3321 
3322     SizeConformance(pStubMsg);
3323     SizeVariance(pStubMsg);
3324 
3325     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3326 
3327     safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
3328 
3329     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3330 }
3331 
3332 
3333 /***********************************************************************
3334  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
3335  */
3336 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
3337                                                   PFORMAT_STRING pFormat )
3338 {
3339     ULONG bufsize, memsize;
3340     unsigned char alignment = pFormat[1] + 1;
3341     DWORD esize = *(const WORD*)(pFormat+2);
3342 
3343     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3344 
3345     if (pFormat[0] != RPC_FC_CVARRAY)
3346     {
3347         ERR("invalid format type %x\n", pFormat[0]);
3348         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3349         return pStubMsg->MemorySize;
3350     }
3351 
3352     pFormat = ReadConformance(pStubMsg, pFormat+4);
3353     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3354 
3355     ALIGN_POINTER(pStubMsg->Buffer, alignment);
3356 
3357     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3358     memsize = safe_multiply(esize, pStubMsg->MaxCount);
3359 
3360     safe_buffer_increment(pStubMsg, bufsize);
3361     pStubMsg->MemorySize += memsize;
3362 
3363     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3364 
3365     return pStubMsg->MemorySize;
3366 }
3367 
3368 
3369 /***********************************************************************
3370  *           NdrComplexArrayMarshall [RPCRT4.@]
3371  */
3372 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3373                                                unsigned char *pMemory,
3374                                                PFORMAT_STRING pFormat)
3375 {
3376   ULONG i, count, def;
3377   BOOL variance_present;
3378   unsigned char alignment;
3379   int pointer_buffer_mark_set = 0;
3380 
3381   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3382 
3383   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3384   {
3385       ERR("invalid format type %x\n", pFormat[0]);
3386       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3387       return NULL;
3388   }
3389 
3390   alignment = pFormat[1] + 1;
3391 
3392   if (!pStubMsg->PointerBufferMark)
3393   {
3394     /* save buffer fields that may be changed by buffer sizer functions
3395      * and that may be needed later on */
3396     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3397     unsigned long saved_buffer_length = pStubMsg->BufferLength;
3398     unsigned long saved_max_count = pStubMsg->MaxCount;
3399     unsigned long saved_offset = pStubMsg->Offset;
3400     unsigned long saved_actual_count = pStubMsg->ActualCount;
3401 
3402     /* get the buffer pointer after complex array data, but before
3403      * pointer data */
3404     pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
3405     pStubMsg->IgnoreEmbeddedPointers = 1;
3406     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3407     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3408 
3409     /* save it for use by embedded pointer code later */
3410     pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
3411     TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
3412     pointer_buffer_mark_set = 1;
3413 
3414     /* restore fields */
3415     pStubMsg->ActualCount = saved_actual_count;
3416     pStubMsg->Offset = saved_offset;
3417     pStubMsg->MaxCount = saved_max_count;
3418     pStubMsg->BufferLength = saved_buffer_length;
3419   }
3420 
3421   def = *(const WORD*)&pFormat[2];
3422   pFormat += 4;
3423 
3424   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3425   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3426 
3427   variance_present = IsConformanceOrVariancePresent(pFormat);
3428   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3429   TRACE("variance = %d\n", pStubMsg->ActualCount);
3430 
3431   WriteConformance(pStubMsg);
3432   if (variance_present)
3433     WriteVariance(pStubMsg);
3434 
3435   ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3436 
3437   count = pStubMsg->ActualCount;
3438   for (i = 0; i < count; i++)
3439     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3440 
3441   STD_OVERFLOW_CHECK(pStubMsg);
3442 
3443   if (pointer_buffer_mark_set)
3444   {
3445     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3446     pStubMsg->PointerBufferMark = NULL;
3447   }
3448 
3449   return NULL;
3450 }
3451 
3452 /***********************************************************************
3453  *           NdrComplexArrayUnmarshall [RPCRT4.@]
3454  */
3455 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3456                                                  unsigned char **ppMemory,
3457                                                  PFORMAT_STRING pFormat,
3458                                                  unsigned char fMustAlloc)
3459 {
3460   ULONG i, count, size;
3461   unsigned char alignment;
3462   unsigned char *pMemory;
3463   unsigned char *saved_buffer;
3464   int pointer_buffer_mark_set = 0;
3465   int saved_ignore_embedded;
3466 
3467   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3468 
3469   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3470   {
3471       ERR("invalid format type %x\n", pFormat[0]);
3472       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3473       return NULL;
3474   }
3475 
3476   alignment = pFormat[1] + 1;
3477 
3478   saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3479   /* save buffer pointer */
3480   saved_buffer = pStubMsg->Buffer;
3481   /* get the buffer pointer after complex array data, but before
3482    * pointer data */
3483   pStubMsg->IgnoreEmbeddedPointers = 1;
3484   pStubMsg->MemorySize = 0;
3485   NdrComplexArrayMemorySize(pStubMsg, pFormat);
3486   size = pStubMsg->MemorySize;
3487   pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3488 
3489   TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
3490   if (!pStubMsg->PointerBufferMark)
3491   {
3492     /* save it for use by embedded pointer code later */
3493     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3494     pointer_buffer_mark_set = 1;
3495   }
3496   /* restore the original buffer */
3497   pStubMsg->Buffer = saved_buffer;
3498 
3499   pFormat += 4;
3500 
3501   pFormat = ReadConformance(pStubMsg, pFormat);
3502   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3503 
3504   if (fMustAlloc || !*ppMemory)
3505     *ppMemory = NdrAllocate(pStubMsg, size);
3506 
3507   ALIGN_POINTER(pStubMsg->Buffer, alignment);
3508 
3509   pMemory = *ppMemory;
3510   count = pStubMsg->ActualCount;
3511   for (i = 0; i < count; i++)
3512     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
3513 
3514   if (pointer_buffer_mark_set)
3515   {
3516     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3517     pStubMsg->PointerBufferMark = NULL;
3518   }
3519 
3520   return NULL;
3521 }
3522 
3523 /***********************************************************************
3524  *           NdrComplexArrayBufferSize [RPCRT4.@]
3525  */
3526 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3527                                       unsigned char *pMemory,
3528                                       PFORMAT_STRING pFormat)
3529 {
3530   ULONG i, count, def;
3531   unsigned char alignment;
3532   BOOL variance_present;
3533   int pointer_length_set = 0;
3534 
3535   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3536 
3537   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3538   {
3539       ERR("invalid format type %x\n", pFormat[0]);
3540       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3541       return;
3542   }
3543 
3544   alignment = pFormat[1] + 1;
3545 
3546   if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3547   {
3548     /* save buffer fields that may be changed by buffer sizer functions
3549      * and that may be needed later on */
3550     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3551     unsigned long saved_buffer_length = pStubMsg->BufferLength;
3552     unsigned long saved_max_count = pStubMsg->MaxCount;
3553     unsigned long saved_offset = pStubMsg->Offset;
3554     unsigned long saved_actual_count = pStubMsg->ActualCount;
3555 
3556     /* get the buffer pointer after complex array data, but before
3557      * pointer data */
3558     pStubMsg->IgnoreEmbeddedPointers = 1;
3559     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3560     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3561 
3562     /* save it for use by embedded pointer code later */
3563     pStubMsg->PointerLength = pStubMsg->BufferLength;
3564     pointer_length_set = 1;
3565 
3566     /* restore fields */
3567     pStubMsg->ActualCount = saved_actual_count;
3568     pStubMsg->Offset = saved_offset;
3569     pStubMsg->MaxCount = saved_max_count;
3570     pStubMsg->BufferLength = saved_buffer_length;
3571   }
3572   def = *(const WORD*)&pFormat[2];
3573   pFormat += 4;
3574 
3575   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3576   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3577   SizeConformance(pStubMsg);
3578 
3579   variance_present = IsConformanceOrVariancePresent(pFormat);
3580   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3581   TRACE("variance = %d\n", pStubMsg->ActualCount);
3582 
3583   if (variance_present)
3584     SizeVariance(pStubMsg);
3585 
3586   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3587 
3588   count = pStubMsg->ActualCount;
3589   for (i = 0; i < count; i++)
3590     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
3591 
3592   if(pointer_length_set)
3593   {
3594     pStubMsg->BufferLength = pStubMsg->PointerLength;
3595     pStubMsg->PointerLength = 0;
3596   }
3597 }
3598 
3599 /***********************************************************************
3600  *           NdrComplexArrayMemorySize [RPCRT4.@]
3601  */
3602 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3603                                        PFORMAT_STRING pFormat)
3604 {
3605   ULONG i, count, esize, SavedMemorySize, MemorySize;
3606   unsigned char alignment;
3607 
3608   TRACE("(%p,%p)\n", pStubMsg, pFormat);
3609 
3610   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3611   {
3612       ERR("invalid format type %x\n", pFormat[0]);
3613       RpcRaiseException(RPC_S_INTERNAL_ERROR);
3614       return 0;
3615   }
3616 
3617   alignment = pFormat[1] + 1;
3618 
3619   pFormat += 4;
3620 
3621   pFormat = ReadConformance(pStubMsg, pFormat);
3622   pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3623 
3624   ALIGN_POINTER(pStubMsg->Buffer, alignment);
3625 
3626   SavedMemorySize = pStubMsg->MemorySize;
3627 
3628   esize = ComplexStructSize(pStubMsg, pFormat);
3629 
3630   MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3631