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