quartz/tests: Make testpin_{AddRef,Release}() static.
[wine.git] / dlls / rpcrt4 / ndr_marshall.c
blob52e27161473611d5a1df22b1345397f9ca56669e
1 /*
2 * NDR data marshalling
4 * Copyright 2002 Greg Turner
5 * Copyright 2003-2006 CodeWeavers
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.
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.
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
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
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <limits.h>
36 #define NONAMELESSUNION
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winerror.h"
41 #include "ndr_misc.h"
42 #include "rpcndr.h"
43 #include "ndrtypes.h"
45 #include "wine/unicode.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(ole);
50 #if defined(__i386__)
51 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
52 (*((UINT32 *)(pchar)) = (uint32))
54 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
55 (*((UINT32 *)(pchar)))
56 #else
57 /* these would work for i386 too, but less efficient */
58 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
59 (*(pchar) = LOBYTE(LOWORD(uint32)), \
60 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
61 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
62 *((pchar)+3) = HIBYTE(HIWORD(uint32)))
64 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
65 (MAKELONG( \
66 MAKEWORD(*(pchar), *((pchar)+1)), \
67 MAKEWORD(*((pchar)+2), *((pchar)+3))))
68 #endif
70 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
71 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
72 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
73 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
74 *(pchar) = HIBYTE(HIWORD(uint32)))
76 #define BIG_ENDIAN_UINT32_READ(pchar) \
77 (MAKELONG( \
78 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
79 MAKEWORD(*((pchar)+1), *(pchar))))
81 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
82 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
83 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
84 # define NDR_LOCAL_UINT32_READ(pchar) \
85 BIG_ENDIAN_UINT32_READ(pchar)
86 #else
87 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
88 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
89 # define NDR_LOCAL_UINT32_READ(pchar) \
90 LITTLE_ENDIAN_UINT32_READ(pchar)
91 #endif
93 static inline void align_length( ULONG *len, unsigned int align )
95 *len = (*len + align - 1) & ~(align - 1);
98 static inline void align_pointer( unsigned char **ptr, unsigned int align )
100 ULONG_PTR mask = align - 1;
101 *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
104 static inline void align_pointer_clear( unsigned char **ptr, unsigned int align )
106 ULONG_PTR mask = align - 1;
107 memset( *ptr, 0, (align - (ULONG_PTR)*ptr) & mask );
108 *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
111 #define STD_OVERFLOW_CHECK(_Msg) do { \
112 TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
113 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
114 ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
115 } while (0)
117 #define NDR_POINTER_ID_BASE 0x20000
118 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
119 #define NDR_TABLE_SIZE 128
120 #define NDR_TABLE_MASK 127
122 #define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL))
124 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
125 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
126 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
127 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
128 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
130 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
131 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
132 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
134 static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
135 static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
136 static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
137 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
139 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
141 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
142 unsigned char *pMemory,
143 PFORMAT_STRING pFormat,
144 PFORMAT_STRING pPointer);
145 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
146 unsigned char *pMemory,
147 PFORMAT_STRING pFormat,
148 PFORMAT_STRING pPointer);
149 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
150 unsigned char *pMemory,
151 PFORMAT_STRING pFormat,
152 PFORMAT_STRING pPointer,
153 unsigned char fMustAlloc);
154 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
155 PFORMAT_STRING pFormat,
156 PFORMAT_STRING pPointer);
157 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
158 unsigned char *pMemory,
159 PFORMAT_STRING pFormat,
160 PFORMAT_STRING pPointer);
162 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
164 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
165 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
166 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
167 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
168 /* 0x10 */
169 NdrBaseTypeMarshall,
170 /* 0x11 */
171 NdrPointerMarshall, NdrPointerMarshall,
172 NdrPointerMarshall, NdrPointerMarshall,
173 /* 0x15 */
174 NdrSimpleStructMarshall, NdrSimpleStructMarshall,
175 NdrConformantStructMarshall, NdrConformantStructMarshall,
176 NdrConformantVaryingStructMarshall,
177 NdrComplexStructMarshall,
178 /* 0x1b */
179 NdrConformantArrayMarshall,
180 NdrConformantVaryingArrayMarshall,
181 NdrFixedArrayMarshall, NdrFixedArrayMarshall,
182 NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
183 NdrComplexArrayMarshall,
184 /* 0x22 */
185 NdrConformantStringMarshall, 0, 0,
186 NdrConformantStringMarshall,
187 NdrNonConformantStringMarshall, 0, 0, 0,
188 /* 0x2a */
189 NdrEncapsulatedUnionMarshall,
190 NdrNonEncapsulatedUnionMarshall,
191 NdrByteCountPointerMarshall,
192 NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
193 /* 0x2f */
194 NdrInterfacePointerMarshall,
195 /* 0x30 */
196 NdrContextHandleMarshall,
197 /* 0xb1 */
198 0, 0, 0,
199 NdrUserMarshalMarshall,
200 0, 0,
201 /* 0xb7 */
202 NdrRangeMarshall,
203 NdrBaseTypeMarshall,
204 NdrBaseTypeMarshall
206 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
208 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
209 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
210 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
211 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
212 /* 0x10 */
213 NdrBaseTypeUnmarshall,
214 /* 0x11 */
215 NdrPointerUnmarshall, NdrPointerUnmarshall,
216 NdrPointerUnmarshall, NdrPointerUnmarshall,
217 /* 0x15 */
218 NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
219 NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
220 NdrConformantVaryingStructUnmarshall,
221 NdrComplexStructUnmarshall,
222 /* 0x1b */
223 NdrConformantArrayUnmarshall,
224 NdrConformantVaryingArrayUnmarshall,
225 NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
226 NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
227 NdrComplexArrayUnmarshall,
228 /* 0x22 */
229 NdrConformantStringUnmarshall, 0, 0,
230 NdrConformantStringUnmarshall,
231 NdrNonConformantStringUnmarshall, 0, 0, 0,
232 /* 0x2a */
233 NdrEncapsulatedUnionUnmarshall,
234 NdrNonEncapsulatedUnionUnmarshall,
235 NdrByteCountPointerUnmarshall,
236 NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
237 /* 0x2f */
238 NdrInterfacePointerUnmarshall,
239 /* 0x30 */
240 NdrContextHandleUnmarshall,
241 /* 0xb1 */
242 0, 0, 0,
243 NdrUserMarshalUnmarshall,
244 0, 0,
245 /* 0xb7 */
246 NdrRangeUnmarshall,
247 NdrBaseTypeUnmarshall,
248 NdrBaseTypeUnmarshall
250 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
252 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
253 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
254 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
255 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
256 /* 0x10 */
257 NdrBaseTypeBufferSize,
258 /* 0x11 */
259 NdrPointerBufferSize, NdrPointerBufferSize,
260 NdrPointerBufferSize, NdrPointerBufferSize,
261 /* 0x15 */
262 NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
263 NdrConformantStructBufferSize, NdrConformantStructBufferSize,
264 NdrConformantVaryingStructBufferSize,
265 NdrComplexStructBufferSize,
266 /* 0x1b */
267 NdrConformantArrayBufferSize,
268 NdrConformantVaryingArrayBufferSize,
269 NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
270 NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
271 NdrComplexArrayBufferSize,
272 /* 0x22 */
273 NdrConformantStringBufferSize, 0, 0,
274 NdrConformantStringBufferSize,
275 NdrNonConformantStringBufferSize, 0, 0, 0,
276 /* 0x2a */
277 NdrEncapsulatedUnionBufferSize,
278 NdrNonEncapsulatedUnionBufferSize,
279 NdrByteCountPointerBufferSize,
280 NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
281 /* 0x2f */
282 NdrInterfacePointerBufferSize,
283 /* 0x30 */
284 NdrContextHandleBufferSize,
285 /* 0xb1 */
286 0, 0, 0,
287 NdrUserMarshalBufferSize,
288 0, 0,
289 /* 0xb7 */
290 NdrRangeBufferSize,
291 NdrBaseTypeBufferSize,
292 NdrBaseTypeBufferSize
294 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
296 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
297 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
298 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
299 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
300 /* 0x10 */
301 NdrBaseTypeMemorySize,
302 /* 0x11 */
303 NdrPointerMemorySize, NdrPointerMemorySize,
304 NdrPointerMemorySize, NdrPointerMemorySize,
305 /* 0x15 */
306 NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
307 NdrConformantStructMemorySize, NdrConformantStructMemorySize,
308 NdrConformantVaryingStructMemorySize,
309 NdrComplexStructMemorySize,
310 /* 0x1b */
311 NdrConformantArrayMemorySize,
312 NdrConformantVaryingArrayMemorySize,
313 NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
314 NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
315 NdrComplexArrayMemorySize,
316 /* 0x22 */
317 NdrConformantStringMemorySize, 0, 0,
318 NdrConformantStringMemorySize,
319 NdrNonConformantStringMemorySize, 0, 0, 0,
320 /* 0x2a */
321 NdrEncapsulatedUnionMemorySize,
322 NdrNonEncapsulatedUnionMemorySize,
323 NdrByteCountPointerMemorySize,
324 NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
325 /* 0x2f */
326 NdrInterfacePointerMemorySize,
327 /* 0x30 */
329 /* 0xb1 */
330 0, 0, 0,
331 NdrUserMarshalMemorySize,
332 0, 0,
333 /* 0xb7 */
334 NdrRangeMemorySize,
335 NdrBaseTypeMemorySize,
336 NdrBaseTypeMemorySize
338 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
340 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
341 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
342 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
343 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
344 /* 0x10 */
345 NdrBaseTypeFree,
346 /* 0x11 */
347 NdrPointerFree, NdrPointerFree,
348 NdrPointerFree, NdrPointerFree,
349 /* 0x15 */
350 NdrSimpleStructFree, NdrSimpleStructFree,
351 NdrConformantStructFree, NdrConformantStructFree,
352 NdrConformantVaryingStructFree,
353 NdrComplexStructFree,
354 /* 0x1b */
355 NdrConformantArrayFree,
356 NdrConformantVaryingArrayFree,
357 NdrFixedArrayFree, NdrFixedArrayFree,
358 NdrVaryingArrayFree, NdrVaryingArrayFree,
359 NdrComplexArrayFree,
360 /* 0x22 */
361 0, 0, 0,
362 0, 0, 0, 0, 0,
363 /* 0x2a */
364 NdrEncapsulatedUnionFree,
365 NdrNonEncapsulatedUnionFree,
367 NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
368 /* 0x2f */
369 NdrInterfacePointerFree,
370 /* 0x30 */
372 /* 0xb1 */
373 0, 0, 0,
374 NdrUserMarshalFree,
375 0, 0,
376 /* 0xb7 */
377 NdrRangeFree,
378 NdrBaseTypeFree,
379 NdrBaseTypeFree
382 typedef struct _NDR_MEMORY_LIST
384 ULONG magic;
385 ULONG size;
386 ULONG reserved;
387 struct _NDR_MEMORY_LIST *next;
388 } NDR_MEMORY_LIST;
390 #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
392 /***********************************************************************
393 * NdrAllocate [RPCRT4.@]
395 * Allocates a block of memory using pStubMsg->pfnAllocate.
397 * PARAMS
398 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
399 * len [I] Size of memory block to allocate.
401 * RETURNS
402 * The memory block of size len that was allocated.
404 * NOTES
405 * The memory block is always 8-byte aligned.
406 * If the function is unable to allocate memory an RPC_X_NO_MEMORY
407 * exception is raised.
409 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len)
411 SIZE_T aligned_len;
412 SIZE_T adjusted_len;
413 void *p;
414 NDR_MEMORY_LIST *mem_list;
416 aligned_len = (len + 7) & ~7;
417 adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
418 /* check for overflow */
419 if (adjusted_len < len)
421 ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len);
422 RpcRaiseException(RPC_X_BAD_STUB_DATA);
425 p = pStubMsg->pfnAllocate(adjusted_len);
426 if (!p) RpcRaiseException(RPC_X_NO_MEMORY);
428 mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
429 mem_list->magic = MEML_MAGIC;
430 mem_list->size = aligned_len;
431 mem_list->reserved = 0;
432 mem_list->next = pStubMsg->pMemoryList;
433 pStubMsg->pMemoryList = mem_list;
435 TRACE("-- %p\n", p);
436 return p;
439 static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
441 TRACE("(%p, %p)\n", pStubMsg, Pointer);
443 pStubMsg->pfnFree(Pointer);
446 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
448 return (*(const ULONG *)pFormat != -1);
451 static inline PFORMAT_STRING SkipConformance(const PMIDL_STUB_MESSAGE pStubMsg, const PFORMAT_STRING pFormat)
453 return pFormat + 4 + pStubMsg->CorrDespIncrement;
456 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
458 align_pointer(&pStubMsg->Buffer, 4);
459 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
460 RpcRaiseException(RPC_X_BAD_STUB_DATA);
461 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
462 pStubMsg->Buffer += 4;
463 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
464 return SkipConformance(pStubMsg, pFormat);
467 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
469 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
471 pStubMsg->Offset = 0;
472 pStubMsg->ActualCount = pStubMsg->MaxCount;
473 goto done;
476 align_pointer(&pStubMsg->Buffer, 4);
477 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
478 RpcRaiseException(RPC_X_BAD_STUB_DATA);
479 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
480 pStubMsg->Buffer += 4;
481 TRACE("offset is %d\n", pStubMsg->Offset);
482 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
483 pStubMsg->Buffer += 4;
484 TRACE("variance is %d\n", pStubMsg->ActualCount);
486 if ((pStubMsg->ActualCount > MaxValue) ||
487 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
489 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
490 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
491 RpcRaiseException(RPC_S_INVALID_BOUND);
492 return NULL;
495 done:
496 return SkipConformance(pStubMsg, pFormat);
499 /* writes the conformance value to the buffer */
500 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
502 align_pointer_clear(&pStubMsg->Buffer, 4);
503 if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
504 RpcRaiseException(RPC_X_BAD_STUB_DATA);
505 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
506 pStubMsg->Buffer += 4;
509 /* writes the variance values to the buffer */
510 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
512 align_pointer_clear(&pStubMsg->Buffer, 4);
513 if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
514 RpcRaiseException(RPC_X_BAD_STUB_DATA);
515 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
516 pStubMsg->Buffer += 4;
517 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
518 pStubMsg->Buffer += 4;
521 /* requests buffer space for the conformance value */
522 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
524 align_length(&pStubMsg->BufferLength, 4);
525 if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
526 RpcRaiseException(RPC_X_BAD_STUB_DATA);
527 pStubMsg->BufferLength += 4;
530 /* requests buffer space for the variance values */
531 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
533 align_length(&pStubMsg->BufferLength, 4);
534 if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
535 RpcRaiseException(RPC_X_BAD_STUB_DATA);
536 pStubMsg->BufferLength += 8;
539 PFORMAT_STRING ComputeConformanceOrVariance(
540 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
541 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
543 BYTE dtype = pFormat[0] & 0xf;
544 short ofs = *(const short *)&pFormat[2];
545 LPVOID ptr = NULL;
546 ULONG_PTR data = 0;
548 if (!IsConformanceOrVariancePresent(pFormat)) {
549 /* null descriptor */
550 *pCount = def;
551 goto finish_conf;
554 switch (pFormat[0] & 0xf0) {
555 case FC_NORMAL_CONFORMANCE:
556 TRACE("normal conformance, ofs=%d\n", ofs);
557 ptr = pMemory;
558 break;
559 case FC_POINTER_CONFORMANCE:
560 TRACE("pointer conformance, ofs=%d\n", ofs);
561 ptr = pStubMsg->Memory;
562 break;
563 case FC_TOP_LEVEL_CONFORMANCE:
564 TRACE("toplevel conformance, ofs=%d\n", ofs);
565 if (pStubMsg->StackTop) {
566 ptr = pStubMsg->StackTop;
568 else {
569 /* -Os mode, *pCount is already set */
570 goto finish_conf;
572 break;
573 case FC_CONSTANT_CONFORMANCE:
574 data = ofs | ((DWORD)pFormat[1] << 16);
575 TRACE("constant conformance, val=%ld\n", data);
576 *pCount = data;
577 goto finish_conf;
578 case FC_TOP_LEVEL_MULTID_CONFORMANCE:
579 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
580 if (pStubMsg->StackTop) {
581 ptr = pStubMsg->StackTop;
583 else {
584 /* ? */
585 goto done_conf_grab;
587 break;
588 default:
589 FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0);
590 goto finish_conf;
593 switch (pFormat[1]) {
594 case FC_DEREFERENCE:
595 ptr = *(LPVOID*)((char *)ptr + ofs);
596 break;
597 case FC_CALLBACK:
599 unsigned char *old_stack_top = pStubMsg->StackTop;
600 ULONG_PTR max_count, old_max_count = pStubMsg->MaxCount;
602 pStubMsg->StackTop = ptr;
604 /* ofs is index into StubDesc->apfnExprEval */
605 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
606 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
608 pStubMsg->StackTop = old_stack_top;
610 /* the callback function always stores the computed value in MaxCount */
611 max_count = pStubMsg->MaxCount;
612 pStubMsg->MaxCount = old_max_count;
613 *pCount = max_count;
614 goto finish_conf;
616 default:
617 ptr = (char *)ptr + ofs;
618 break;
621 switch (dtype) {
622 case FC_LONG:
623 case FC_ULONG:
624 data = *(DWORD*)ptr;
625 break;
626 case FC_SHORT:
627 data = *(SHORT*)ptr;
628 break;
629 case FC_USHORT:
630 data = *(USHORT*)ptr;
631 break;
632 case FC_CHAR:
633 case FC_SMALL:
634 data = *(CHAR*)ptr;
635 break;
636 case FC_BYTE:
637 case FC_USMALL:
638 data = *(UCHAR*)ptr;
639 break;
640 case FC_HYPER:
641 data = *(ULONGLONG *)ptr;
642 break;
643 default:
644 FIXME("unknown conformance data type %x\n", dtype);
645 goto done_conf_grab;
647 TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);
649 done_conf_grab:
650 switch (pFormat[1]) {
651 case FC_DEREFERENCE: /* already handled */
652 case 0: /* no op */
653 *pCount = data;
654 break;
655 case FC_ADD_1:
656 *pCount = data + 1;
657 break;
658 case FC_SUB_1:
659 *pCount = data - 1;
660 break;
661 case FC_MULT_2:
662 *pCount = data * 2;
663 break;
664 case FC_DIV_2:
665 *pCount = data / 2;
666 break;
667 default:
668 FIXME("unknown conformance op %d\n", pFormat[1]);
669 goto finish_conf;
672 finish_conf:
673 TRACE("resulting conformance is %ld\n", *pCount);
675 return SkipConformance(pStubMsg, pFormat);
678 static inline PFORMAT_STRING SkipVariance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
680 return SkipConformance( pStubMsg, pFormat );
683 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
684 * the result overflows 32-bits */
685 static inline ULONG safe_multiply(ULONG a, ULONG b)
687 ULONGLONG ret = (ULONGLONG)a * b;
688 if (ret > 0xffffffff)
690 RpcRaiseException(RPC_S_INVALID_BOUND);
691 return 0;
693 return ret;
696 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
698 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
699 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
700 RpcRaiseException(RPC_X_BAD_STUB_DATA);
701 pStubMsg->Buffer += size;
704 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
706 if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
708 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
709 pStubMsg->BufferLength, size);
710 RpcRaiseException(RPC_X_BAD_STUB_DATA);
712 pStubMsg->BufferLength += size;
715 /* copies data from the buffer, checking that there is enough data in the buffer
716 * to do so */
717 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
719 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
720 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
722 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
723 pStubMsg->Buffer, pStubMsg->BufferEnd, size);
724 RpcRaiseException(RPC_X_BAD_STUB_DATA);
726 if (p == pStubMsg->Buffer)
727 ERR("pointer is the same as the buffer\n");
728 memcpy(p, pStubMsg->Buffer, size);
729 pStubMsg->Buffer += size;
732 /* copies data to the buffer, checking that there is enough space to do so */
733 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
735 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
736 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
738 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
739 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
740 size);
741 RpcRaiseException(RPC_X_BAD_STUB_DATA);
743 memcpy(pStubMsg->Buffer, p, size);
744 pStubMsg->Buffer += size;
747 /* verify that string data sitting in the buffer is valid and safe to
748 * unmarshall */
749 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
751 ULONG i;
753 /* verify the buffer is safe to access */
754 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
755 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
757 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
758 pStubMsg->BufferEnd, pStubMsg->Buffer);
759 RpcRaiseException(RPC_X_BAD_STUB_DATA);
762 /* strings must always have null terminating bytes */
763 if (bufsize < esize)
765 ERR("invalid string length of %d\n", bufsize / esize);
766 RpcRaiseException(RPC_S_INVALID_BOUND);
769 for (i = bufsize - esize; i < bufsize; i++)
770 if (pStubMsg->Buffer[i] != 0)
772 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
773 i, pStubMsg->Buffer[i]);
774 RpcRaiseException(RPC_S_INVALID_BOUND);
778 static inline void dump_pointer_attr(unsigned char attr)
780 if (attr & FC_ALLOCATE_ALL_NODES)
781 TRACE(" FC_ALLOCATE_ALL_NODES");
782 if (attr & FC_DONT_FREE)
783 TRACE(" FC_DONT_FREE");
784 if (attr & FC_ALLOCED_ON_STACK)
785 TRACE(" FC_ALLOCED_ON_STACK");
786 if (attr & FC_SIMPLE_POINTER)
787 TRACE(" FC_SIMPLE_POINTER");
788 if (attr & FC_POINTER_DEREF)
789 TRACE(" FC_POINTER_DEREF");
790 TRACE("\n");
793 /***********************************************************************
794 * PointerMarshall [internal]
796 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
797 unsigned char *Buffer,
798 unsigned char *Pointer,
799 PFORMAT_STRING pFormat)
801 unsigned type = pFormat[0], attr = pFormat[1];
802 PFORMAT_STRING desc;
803 NDR_MARSHALL m;
804 ULONG pointer_id;
805 BOOL pointer_needs_marshaling;
807 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
808 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
809 pFormat += 2;
810 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
811 else desc = pFormat + *(const SHORT*)pFormat;
813 switch (type) {
814 case FC_RP: /* ref pointer (always non-null) */
815 if (!Pointer)
817 ERR("NULL ref pointer is not allowed\n");
818 RpcRaiseException(RPC_X_NULL_REF_POINTER);
820 pointer_needs_marshaling = TRUE;
821 break;
822 case FC_UP: /* unique pointer */
823 case FC_OP: /* object pointer - same as unique here */
824 if (Pointer)
825 pointer_needs_marshaling = TRUE;
826 else
827 pointer_needs_marshaling = FALSE;
828 pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
829 TRACE("writing 0x%08x to buffer\n", pointer_id);
830 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
831 break;
832 case FC_FP:
833 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
834 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
835 TRACE("writing 0x%08x to buffer\n", pointer_id);
836 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
837 break;
838 default:
839 FIXME("unhandled ptr type=%02x\n", type);
840 RpcRaiseException(RPC_X_BAD_STUB_DATA);
841 return;
844 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
846 if (pointer_needs_marshaling) {
847 if (attr & FC_POINTER_DEREF) {
848 Pointer = *(unsigned char**)Pointer;
849 TRACE("deref => %p\n", Pointer);
851 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
852 if (m) m(pStubMsg, Pointer, desc);
853 else FIXME("no marshaller for data type=%02x\n", *desc);
856 STD_OVERFLOW_CHECK(pStubMsg);
859 /***********************************************************************
860 * PointerUnmarshall [internal]
862 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
863 unsigned char *Buffer,
864 unsigned char **pPointer,
865 unsigned char *pSrcPointer,
866 PFORMAT_STRING pFormat,
867 unsigned char fMustAlloc)
869 unsigned type = pFormat[0], attr = pFormat[1];
870 PFORMAT_STRING desc;
871 NDR_UNMARSHALL m;
872 DWORD pointer_id = 0;
873 BOOL pointer_needs_unmarshaling;
875 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
876 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
877 pFormat += 2;
878 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
879 else desc = pFormat + *(const SHORT*)pFormat;
881 switch (type) {
882 case FC_RP: /* ref pointer (always non-null) */
883 pointer_needs_unmarshaling = TRUE;
884 break;
885 case FC_UP: /* unique pointer */
886 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
887 TRACE("pointer_id is 0x%08x\n", pointer_id);
888 if (pointer_id)
889 pointer_needs_unmarshaling = TRUE;
890 else {
891 *pPointer = NULL;
892 pointer_needs_unmarshaling = FALSE;
894 break;
895 case FC_OP: /* object pointer - we must free data before overwriting it */
896 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
897 TRACE("pointer_id is 0x%08x\n", pointer_id);
898 if (!fMustAlloc && pSrcPointer)
900 FIXME("free object pointer %p\n", pSrcPointer);
901 fMustAlloc = TRUE;
903 if (pointer_id)
904 pointer_needs_unmarshaling = TRUE;
905 else
907 *pPointer = NULL;
908 pointer_needs_unmarshaling = FALSE;
910 break;
911 case FC_FP:
912 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
913 TRACE("pointer_id is 0x%08x\n", pointer_id);
914 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
915 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
916 break;
917 default:
918 FIXME("unhandled ptr type=%02x\n", type);
919 RpcRaiseException(RPC_X_BAD_STUB_DATA);
920 return;
923 if (pointer_needs_unmarshaling) {
924 unsigned char **current_ptr = pPointer;
925 if (pStubMsg->IsClient) {
926 TRACE("client\n");
927 /* if we aren't forcing allocation of memory then try to use the existing
928 * (source) pointer to unmarshall the data into so that [in,out]
929 * parameters behave correctly. it doesn't matter if the parameter is
930 * [out] only since in that case the pointer will be NULL. we force
931 * allocation when the source pointer is NULL here instead of in the type
932 * unmarshalling routine for the benefit of the deref code below */
933 if (!fMustAlloc) {
934 if (pSrcPointer) {
935 TRACE("setting *pPointer to %p\n", pSrcPointer);
936 *pPointer = pSrcPointer;
937 } else
938 fMustAlloc = TRUE;
940 } else {
941 TRACE("server\n");
942 /* the memory in a stub is never initialised, so we have to work out here
943 * whether we have to initialise it so we can use the optimisation of
944 * setting the pointer to the buffer, if possible, or set fMustAlloc to
945 * TRUE. */
946 if (attr & FC_POINTER_DEREF) {
947 fMustAlloc = TRUE;
948 } else {
949 *current_ptr = NULL;
953 if (attr & FC_ALLOCATE_ALL_NODES)
954 FIXME("FC_ALLOCATE_ALL_NODES not implemented\n");
956 if (attr & FC_POINTER_DEREF) {
957 if (fMustAlloc) {
958 unsigned char *base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
959 *pPointer = base_ptr_val;
960 current_ptr = (unsigned char **)base_ptr_val;
961 } else
962 current_ptr = *(unsigned char***)current_ptr;
963 TRACE("deref => %p\n", current_ptr);
964 if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
966 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
967 if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
968 else FIXME("no unmarshaller for data type=%02x\n", *desc);
970 if (type == FC_FP)
971 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
972 *pPointer);
975 TRACE("pointer=%p\n", *pPointer);
978 /***********************************************************************
979 * PointerBufferSize [internal]
981 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
982 unsigned char *Pointer,
983 PFORMAT_STRING pFormat)
985 unsigned type = pFormat[0], attr = pFormat[1];
986 PFORMAT_STRING desc;
987 NDR_BUFFERSIZE m;
988 BOOL pointer_needs_sizing;
989 ULONG pointer_id;
991 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
992 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
993 pFormat += 2;
994 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
995 else desc = pFormat + *(const SHORT*)pFormat;
997 switch (type) {
998 case FC_RP: /* ref pointer (always non-null) */
999 if (!Pointer)
1001 ERR("NULL ref pointer is not allowed\n");
1002 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1004 break;
1005 case FC_OP:
1006 case FC_UP:
1007 /* NULL pointer has no further representation */
1008 if (!Pointer)
1009 return;
1010 break;
1011 case FC_FP:
1012 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1013 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1014 if (!pointer_needs_sizing)
1015 return;
1016 break;
1017 default:
1018 FIXME("unhandled ptr type=%02x\n", type);
1019 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1020 return;
1023 if (attr & FC_POINTER_DEREF) {
1024 Pointer = *(unsigned char**)Pointer;
1025 TRACE("deref => %p\n", Pointer);
1028 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1029 if (m) m(pStubMsg, Pointer, desc);
1030 else FIXME("no buffersizer for data type=%02x\n", *desc);
1033 /***********************************************************************
1034 * PointerMemorySize [internal]
1036 static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1037 unsigned char *Buffer, PFORMAT_STRING pFormat)
1039 unsigned type = pFormat[0], attr = pFormat[1];
1040 PFORMAT_STRING desc;
1041 NDR_MEMORYSIZE m;
1042 DWORD pointer_id = 0;
1043 BOOL pointer_needs_sizing;
1045 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1046 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1047 pFormat += 2;
1048 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
1049 else desc = pFormat + *(const SHORT*)pFormat;
1051 switch (type) {
1052 case FC_RP: /* ref pointer (always non-null) */
1053 pointer_needs_sizing = TRUE;
1054 break;
1055 case FC_UP: /* unique pointer */
1056 case FC_OP: /* object pointer - we must free data before overwriting it */
1057 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1058 TRACE("pointer_id is 0x%08x\n", pointer_id);
1059 if (pointer_id)
1060 pointer_needs_sizing = TRUE;
1061 else
1062 pointer_needs_sizing = FALSE;
1063 break;
1064 case FC_FP:
1066 void *pointer;
1067 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1068 TRACE("pointer_id is 0x%08x\n", pointer_id);
1069 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1070 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1071 break;
1073 default:
1074 FIXME("unhandled ptr type=%02x\n", type);
1075 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1076 return 0;
1079 if (attr & FC_POINTER_DEREF) {
1080 align_length(&pStubMsg->MemorySize, sizeof(void*));
1081 pStubMsg->MemorySize += sizeof(void*);
1082 TRACE("deref\n");
1085 if (pointer_needs_sizing) {
1086 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1087 if (m) m(pStubMsg, desc);
1088 else FIXME("no memorysizer for data type=%02x\n", *desc);
1091 return pStubMsg->MemorySize;
1094 /***********************************************************************
1095 * PointerFree [internal]
1097 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1098 unsigned char *Pointer,
1099 PFORMAT_STRING pFormat)
1101 unsigned type = pFormat[0], attr = pFormat[1];
1102 PFORMAT_STRING desc;
1103 NDR_FREE m;
1104 unsigned char *current_pointer = Pointer;
1106 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1107 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1108 if (attr & FC_DONT_FREE) return;
1109 pFormat += 2;
1110 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
1111 else desc = pFormat + *(const SHORT*)pFormat;
1113 if (!Pointer) return;
1115 if (type == FC_FP) {
1116 int pointer_needs_freeing = NdrFullPointerFree(
1117 pStubMsg->FullPtrXlatTables, Pointer);
1118 if (!pointer_needs_freeing)
1119 return;
1122 if (attr & FC_POINTER_DEREF) {
1123 current_pointer = *(unsigned char**)Pointer;
1124 TRACE("deref => %p\n", current_pointer);
1127 m = NdrFreer[*desc & NDR_TABLE_MASK];
1128 if (m) m(pStubMsg, current_pointer, desc);
1130 /* this check stops us from trying to free buffer memory. we don't have to
1131 * worry about clients, since they won't call this function.
1132 * we don't have to check for the buffer being reallocated because
1133 * BufferStart and BufferEnd won't be reset when allocating memory for
1134 * sending the response. we don't have to check for the new buffer here as
1135 * it won't be used a type memory, only for buffer memory */
1136 if (Pointer >= pStubMsg->BufferStart && Pointer <= pStubMsg->BufferEnd)
1137 goto notfree;
1139 if (attr & FC_ALLOCED_ON_STACK) {
1140 TRACE("not freeing stack ptr %p\n", Pointer);
1141 return;
1143 TRACE("freeing %p\n", Pointer);
1144 NdrFree(pStubMsg, Pointer);
1145 return;
1146 notfree:
1147 TRACE("not freeing %p\n", Pointer);
1150 /***********************************************************************
1151 * EmbeddedPointerMarshall
1153 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1154 unsigned char *pMemory,
1155 PFORMAT_STRING pFormat)
1157 unsigned char *Mark = pStubMsg->BufferMark;
1158 unsigned rep, count, stride;
1159 unsigned i;
1160 unsigned char *saved_buffer = NULL;
1162 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1164 if (*pFormat != FC_PP) return NULL;
1165 pFormat += 2;
1167 if (pStubMsg->PointerBufferMark)
1169 saved_buffer = pStubMsg->Buffer;
1170 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1171 pStubMsg->PointerBufferMark = NULL;
1174 while (pFormat[0] != FC_END) {
1175 switch (pFormat[0]) {
1176 default:
1177 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1178 /* fallthrough */
1179 case FC_NO_REPEAT:
1180 rep = 1;
1181 stride = 0;
1182 count = 1;
1183 pFormat += 2;
1184 break;
1185 case FC_FIXED_REPEAT:
1186 rep = *(const WORD*)&pFormat[2];
1187 stride = *(const WORD*)&pFormat[4];
1188 count = *(const WORD*)&pFormat[8];
1189 pFormat += 10;
1190 break;
1191 case FC_VARIABLE_REPEAT:
1192 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1193 stride = *(const WORD*)&pFormat[2];
1194 count = *(const WORD*)&pFormat[6];
1195 pFormat += 8;
1196 break;
1198 for (i = 0; i < rep; i++) {
1199 PFORMAT_STRING info = pFormat;
1200 unsigned char *membase = pMemory + (i * stride);
1201 unsigned char *bufbase = Mark + (i * stride);
1202 unsigned u;
1204 for (u=0; u<count; u++,info+=8) {
1205 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1206 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1207 unsigned char *saved_memory = pStubMsg->Memory;
1209 pStubMsg->Memory = membase;
1210 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1211 pStubMsg->Memory = saved_memory;
1214 pFormat += 8 * count;
1217 if (saved_buffer)
1219 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1220 pStubMsg->Buffer = saved_buffer;
1223 STD_OVERFLOW_CHECK(pStubMsg);
1225 return NULL;
1228 /***********************************************************************
1229 * EmbeddedPointerUnmarshall
1231 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1232 unsigned char *pDstBuffer,
1233 unsigned char *pSrcMemoryPtrs,
1234 PFORMAT_STRING pFormat,
1235 unsigned char fMustAlloc)
1237 unsigned char *Mark = pStubMsg->BufferMark;
1238 unsigned rep, count, stride;
1239 unsigned i;
1240 unsigned char *saved_buffer = NULL;
1242 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1244 if (*pFormat != FC_PP) return NULL;
1245 pFormat += 2;
1247 if (pStubMsg->PointerBufferMark)
1249 saved_buffer = pStubMsg->Buffer;
1250 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1251 pStubMsg->PointerBufferMark = NULL;
1254 while (pFormat[0] != FC_END) {
1255 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1256 switch (pFormat[0]) {
1257 default:
1258 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1259 /* fallthrough */
1260 case FC_NO_REPEAT:
1261 rep = 1;
1262 stride = 0;
1263 count = 1;
1264 pFormat += 2;
1265 break;
1266 case FC_FIXED_REPEAT:
1267 rep = *(const WORD*)&pFormat[2];
1268 stride = *(const WORD*)&pFormat[4];
1269 count = *(const WORD*)&pFormat[8];
1270 pFormat += 10;
1271 break;
1272 case FC_VARIABLE_REPEAT:
1273 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1274 stride = *(const WORD*)&pFormat[2];
1275 count = *(const WORD*)&pFormat[6];
1276 pFormat += 8;
1277 break;
1279 for (i = 0; i < rep; i++) {
1280 PFORMAT_STRING info = pFormat;
1281 unsigned char *bufdstbase = pDstBuffer + (i * stride);
1282 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1283 unsigned char *bufbase = Mark + (i * stride);
1284 unsigned u;
1286 for (u=0; u<count; u++,info+=8) {
1287 unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1288 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1289 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1290 PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1293 pFormat += 8 * count;
1296 if (saved_buffer)
1298 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1299 pStubMsg->Buffer = saved_buffer;
1302 return NULL;
1305 /***********************************************************************
1306 * EmbeddedPointerBufferSize
1308 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1309 unsigned char *pMemory,
1310 PFORMAT_STRING pFormat)
1312 unsigned rep, count, stride;
1313 unsigned i;
1314 ULONG saved_buffer_length = 0;
1316 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1318 if (pStubMsg->IgnoreEmbeddedPointers) return;
1320 if (*pFormat != FC_PP) return;
1321 pFormat += 2;
1323 if (pStubMsg->PointerLength)
1325 saved_buffer_length = pStubMsg->BufferLength;
1326 pStubMsg->BufferLength = pStubMsg->PointerLength;
1327 pStubMsg->PointerLength = 0;
1330 while (pFormat[0] != FC_END) {
1331 switch (pFormat[0]) {
1332 default:
1333 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1334 /* fallthrough */
1335 case FC_NO_REPEAT:
1336 rep = 1;
1337 stride = 0;
1338 count = 1;
1339 pFormat += 2;
1340 break;
1341 case FC_FIXED_REPEAT:
1342 rep = *(const WORD*)&pFormat[2];
1343 stride = *(const WORD*)&pFormat[4];
1344 count = *(const WORD*)&pFormat[8];
1345 pFormat += 10;
1346 break;
1347 case FC_VARIABLE_REPEAT:
1348 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1349 stride = *(const WORD*)&pFormat[2];
1350 count = *(const WORD*)&pFormat[6];
1351 pFormat += 8;
1352 break;
1354 for (i = 0; i < rep; i++) {
1355 PFORMAT_STRING info = pFormat;
1356 unsigned char *membase = pMemory + (i * stride);
1357 unsigned u;
1359 for (u=0; u<count; u++,info+=8) {
1360 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1361 unsigned char *saved_memory = pStubMsg->Memory;
1363 pStubMsg->Memory = membase;
1364 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1365 pStubMsg->Memory = saved_memory;
1368 pFormat += 8 * count;
1371 if (saved_buffer_length)
1373 pStubMsg->PointerLength = pStubMsg->BufferLength;
1374 pStubMsg->BufferLength = saved_buffer_length;
1378 /***********************************************************************
1379 * EmbeddedPointerMemorySize [internal]
1381 static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1382 PFORMAT_STRING pFormat)
1384 unsigned char *Mark = pStubMsg->BufferMark;
1385 unsigned rep, count, stride;
1386 unsigned i;
1387 unsigned char *saved_buffer = NULL;
1389 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1391 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1393 if (pStubMsg->PointerBufferMark)
1395 saved_buffer = pStubMsg->Buffer;
1396 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1397 pStubMsg->PointerBufferMark = NULL;
1400 if (*pFormat != FC_PP) return 0;
1401 pFormat += 2;
1403 while (pFormat[0] != FC_END) {
1404 switch (pFormat[0]) {
1405 default:
1406 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1407 /* fallthrough */
1408 case FC_NO_REPEAT:
1409 rep = 1;
1410 stride = 0;
1411 count = 1;
1412 pFormat += 2;
1413 break;
1414 case FC_FIXED_REPEAT:
1415 rep = *(const WORD*)&pFormat[2];
1416 stride = *(const WORD*)&pFormat[4];
1417 count = *(const WORD*)&pFormat[8];
1418 pFormat += 10;
1419 break;
1420 case FC_VARIABLE_REPEAT:
1421 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1422 stride = *(const WORD*)&pFormat[2];
1423 count = *(const WORD*)&pFormat[6];
1424 pFormat += 8;
1425 break;
1427 for (i = 0; i < rep; i++) {
1428 PFORMAT_STRING info = pFormat;
1429 unsigned char *bufbase = Mark + (i * stride);
1430 unsigned u;
1431 for (u=0; u<count; u++,info+=8) {
1432 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1433 PointerMemorySize(pStubMsg, bufptr, info+4);
1436 pFormat += 8 * count;
1439 if (saved_buffer)
1441 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1442 pStubMsg->Buffer = saved_buffer;
1445 return 0;
1448 /***********************************************************************
1449 * EmbeddedPointerFree [internal]
1451 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1452 unsigned char *pMemory,
1453 PFORMAT_STRING pFormat)
1455 unsigned rep, count, stride;
1456 unsigned i;
1458 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1459 if (*pFormat != FC_PP) return;
1460 pFormat += 2;
1462 while (pFormat[0] != FC_END) {
1463 switch (pFormat[0]) {
1464 default:
1465 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1466 /* fallthrough */
1467 case FC_NO_REPEAT:
1468 rep = 1;
1469 stride = 0;
1470 count = 1;
1471 pFormat += 2;
1472 break;
1473 case FC_FIXED_REPEAT:
1474 rep = *(const WORD*)&pFormat[2];
1475 stride = *(const WORD*)&pFormat[4];
1476 count = *(const WORD*)&pFormat[8];
1477 pFormat += 10;
1478 break;
1479 case FC_VARIABLE_REPEAT:
1480 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1481 stride = *(const WORD*)&pFormat[2];
1482 count = *(const WORD*)&pFormat[6];
1483 pFormat += 8;
1484 break;
1486 for (i = 0; i < rep; i++) {
1487 PFORMAT_STRING info = pFormat;
1488 unsigned char *membase = pMemory + (i * stride);
1489 unsigned u;
1491 for (u=0; u<count; u++,info+=8) {
1492 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1493 unsigned char *saved_memory = pStubMsg->Memory;
1495 pStubMsg->Memory = membase;
1496 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1497 pStubMsg->Memory = saved_memory;
1500 pFormat += 8 * count;
1504 /***********************************************************************
1505 * NdrPointerMarshall [RPCRT4.@]
1507 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1508 unsigned char *pMemory,
1509 PFORMAT_STRING pFormat)
1511 unsigned char *Buffer;
1513 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1515 /* Increment the buffer here instead of in PointerMarshall,
1516 * as that is used by embedded pointers which already handle the incrementing
1517 * the buffer, and shouldn't write any additional pointer data to the wire */
1518 if (*pFormat != FC_RP)
1520 align_pointer_clear(&pStubMsg->Buffer, 4);
1521 Buffer = pStubMsg->Buffer;
1522 safe_buffer_increment(pStubMsg, 4);
1524 else
1525 Buffer = pStubMsg->Buffer;
1527 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1529 return NULL;
1532 /***********************************************************************
1533 * NdrPointerUnmarshall [RPCRT4.@]
1535 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1536 unsigned char **ppMemory,
1537 PFORMAT_STRING pFormat,
1538 unsigned char fMustAlloc)
1540 unsigned char *Buffer;
1542 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1544 if (*pFormat == FC_RP)
1546 Buffer = pStubMsg->Buffer;
1547 /* Do the NULL ref pointer check here because embedded pointers can be
1548 * NULL if the type the pointer is embedded in was allocated rather than
1549 * being passed in by the client */
1550 if (pStubMsg->IsClient && !*ppMemory)
1552 ERR("NULL ref pointer is not allowed\n");
1553 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1556 else
1558 /* Increment the buffer here instead of in PointerUnmarshall,
1559 * as that is used by embedded pointers which already handle the incrementing
1560 * the buffer, and shouldn't read any additional pointer data from the
1561 * buffer */
1562 align_pointer(&pStubMsg->Buffer, 4);
1563 Buffer = pStubMsg->Buffer;
1564 safe_buffer_increment(pStubMsg, 4);
1567 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1569 return NULL;
1572 /***********************************************************************
1573 * NdrPointerBufferSize [RPCRT4.@]
1575 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1576 unsigned char *pMemory,
1577 PFORMAT_STRING pFormat)
1579 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1581 /* Increment the buffer length here instead of in PointerBufferSize,
1582 * as that is used by embedded pointers which already handle the buffer
1583 * length, and shouldn't write anything more to the wire */
1584 if (*pFormat != FC_RP)
1586 align_length(&pStubMsg->BufferLength, 4);
1587 safe_buffer_length_increment(pStubMsg, 4);
1590 PointerBufferSize(pStubMsg, pMemory, pFormat);
1593 /***********************************************************************
1594 * NdrPointerMemorySize [RPCRT4.@]
1596 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1597 PFORMAT_STRING pFormat)
1599 unsigned char *Buffer = pStubMsg->Buffer;
1600 if (*pFormat != FC_RP)
1602 align_pointer(&pStubMsg->Buffer, 4);
1603 safe_buffer_increment(pStubMsg, 4);
1605 align_length(&pStubMsg->MemorySize, sizeof(void *));
1606 return PointerMemorySize(pStubMsg, Buffer, pFormat);
1609 /***********************************************************************
1610 * NdrPointerFree [RPCRT4.@]
1612 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1613 unsigned char *pMemory,
1614 PFORMAT_STRING pFormat)
1616 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1617 PointerFree(pStubMsg, pMemory, pFormat);
1620 /***********************************************************************
1621 * NdrSimpleTypeMarshall [RPCRT4.@]
1623 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1624 unsigned char FormatChar )
1626 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1629 /***********************************************************************
1630 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1632 * Unmarshall a base type.
1634 * NOTES
1635 * Doesn't check that the buffer is long enough before copying, so the caller
1636 * should do this.
1638 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1639 unsigned char FormatChar )
1641 #define BASE_TYPE_UNMARSHALL(type) \
1642 align_pointer(&pStubMsg->Buffer, sizeof(type)); \
1643 TRACE("pMemory: %p\n", pMemory); \
1644 *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1645 pStubMsg->Buffer += sizeof(type);
1647 switch(FormatChar)
1649 case FC_BYTE:
1650 case FC_CHAR:
1651 case FC_SMALL:
1652 case FC_USMALL:
1653 BASE_TYPE_UNMARSHALL(UCHAR);
1654 TRACE("value: 0x%02x\n", *pMemory);
1655 break;
1656 case FC_WCHAR:
1657 case FC_SHORT:
1658 case FC_USHORT:
1659 BASE_TYPE_UNMARSHALL(USHORT);
1660 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1661 break;
1662 case FC_LONG:
1663 case FC_ULONG:
1664 case FC_ERROR_STATUS_T:
1665 case FC_ENUM32:
1666 BASE_TYPE_UNMARSHALL(ULONG);
1667 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1668 break;
1669 case FC_FLOAT:
1670 BASE_TYPE_UNMARSHALL(float);
1671 TRACE("value: %f\n", *(float *)pMemory);
1672 break;
1673 case FC_DOUBLE:
1674 BASE_TYPE_UNMARSHALL(double);
1675 TRACE("value: %f\n", *(double *)pMemory);
1676 break;
1677 case FC_HYPER:
1678 BASE_TYPE_UNMARSHALL(ULONGLONG);
1679 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1680 break;
1681 case FC_ENUM16:
1682 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
1683 TRACE("pMemory: %p\n", pMemory);
1684 /* 16-bits on the wire, but int in memory */
1685 *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1686 pStubMsg->Buffer += sizeof(USHORT);
1687 TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1688 break;
1689 case FC_INT3264:
1690 align_pointer(&pStubMsg->Buffer, sizeof(INT));
1691 /* 32-bits on the wire, but int_ptr in memory */
1692 *(INT_PTR *)pMemory = *(INT *)pStubMsg->Buffer;
1693 pStubMsg->Buffer += sizeof(INT);
1694 TRACE("value: 0x%08lx\n", *(INT_PTR *)pMemory);
1695 break;
1696 case FC_UINT3264:
1697 align_pointer(&pStubMsg->Buffer, sizeof(UINT));
1698 /* 32-bits on the wire, but int_ptr in memory */
1699 *(UINT_PTR *)pMemory = *(UINT *)pStubMsg->Buffer;
1700 pStubMsg->Buffer += sizeof(UINT);
1701 TRACE("value: 0x%08lx\n", *(UINT_PTR *)pMemory);
1702 break;
1703 case FC_IGNORE:
1704 break;
1705 default:
1706 FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1708 #undef BASE_TYPE_UNMARSHALL
1711 /***********************************************************************
1712 * NdrSimpleStructMarshall [RPCRT4.@]
1714 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1715 unsigned char *pMemory,
1716 PFORMAT_STRING pFormat)
1718 unsigned size = *(const WORD*)(pFormat+2);
1719 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1721 align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
1723 pStubMsg->BufferMark = pStubMsg->Buffer;
1724 safe_copy_to_buffer(pStubMsg, pMemory, size);
1726 if (pFormat[0] != FC_STRUCT)
1727 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1729 return NULL;
1732 /***********************************************************************
1733 * NdrSimpleStructUnmarshall [RPCRT4.@]
1735 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1736 unsigned char **ppMemory,
1737 PFORMAT_STRING pFormat,
1738 unsigned char fMustAlloc)
1740 unsigned size = *(const WORD*)(pFormat+2);
1741 unsigned char *saved_buffer;
1742 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1744 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1746 if (fMustAlloc)
1747 *ppMemory = NdrAllocate(pStubMsg, size);
1748 else
1750 if (!pStubMsg->IsClient && !*ppMemory)
1751 /* for servers, we just point straight into the RPC buffer */
1752 *ppMemory = pStubMsg->Buffer;
1755 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1756 safe_buffer_increment(pStubMsg, size);
1757 if (pFormat[0] == FC_PSTRUCT)
1758 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1760 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1761 if (*ppMemory != saved_buffer)
1762 memcpy(*ppMemory, saved_buffer, size);
1764 return NULL;
1767 /***********************************************************************
1768 * NdrSimpleStructBufferSize [RPCRT4.@]
1770 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1771 unsigned char *pMemory,
1772 PFORMAT_STRING pFormat)
1774 unsigned size = *(const WORD*)(pFormat+2);
1775 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1777 align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
1779 safe_buffer_length_increment(pStubMsg, size);
1780 if (pFormat[0] != FC_STRUCT)
1781 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1784 /***********************************************************************
1785 * NdrSimpleStructMemorySize [RPCRT4.@]
1787 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1788 PFORMAT_STRING pFormat)
1790 unsigned short size = *(const WORD *)(pFormat+2);
1792 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1794 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1795 pStubMsg->MemorySize += size;
1796 safe_buffer_increment(pStubMsg, size);
1798 if (pFormat[0] != FC_STRUCT)
1799 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1800 return pStubMsg->MemorySize;
1803 /***********************************************************************
1804 * NdrSimpleStructFree [RPCRT4.@]
1806 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1807 unsigned char *pMemory,
1808 PFORMAT_STRING pFormat)
1810 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1811 if (pFormat[0] != FC_STRUCT)
1812 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1815 /* Array helpers */
1817 static inline void array_compute_and_size_conformance(
1818 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1819 PFORMAT_STRING pFormat)
1821 DWORD count;
1823 switch (fc)
1825 case FC_CARRAY:
1826 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1827 SizeConformance(pStubMsg);
1828 break;
1829 case FC_CVARRAY:
1830 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1831 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1832 SizeConformance(pStubMsg);
1833 break;
1834 case FC_C_CSTRING:
1835 case FC_C_WSTRING:
1836 if (fc == FC_C_CSTRING)
1838 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1839 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1841 else
1843 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1844 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1847 if (pFormat[1] == FC_STRING_SIZED)
1848 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1849 else
1850 pStubMsg->MaxCount = pStubMsg->ActualCount;
1852 SizeConformance(pStubMsg);
1853 break;
1854 case FC_BOGUS_ARRAY:
1855 count = *(const WORD *)(pFormat + 2);
1856 pFormat += 4;
1857 if (IsConformanceOrVariancePresent(pFormat)) SizeConformance(pStubMsg);
1858 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, count);
1859 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
1860 break;
1861 default:
1862 ERR("unknown array format 0x%x\n", fc);
1863 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1867 static inline void array_buffer_size(
1868 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1869 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1871 DWORD i, size;
1872 DWORD esize;
1873 unsigned char alignment;
1875 switch (fc)
1877 case FC_CARRAY:
1878 esize = *(const WORD*)(pFormat+2);
1879 alignment = pFormat[1] + 1;
1881 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1883 align_length(&pStubMsg->BufferLength, alignment);
1885 size = safe_multiply(esize, pStubMsg->MaxCount);
1886 /* conformance value plus array */
1887 safe_buffer_length_increment(pStubMsg, size);
1889 if (fHasPointers)
1890 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1891 break;
1892 case FC_CVARRAY:
1893 esize = *(const WORD*)(pFormat+2);
1894 alignment = pFormat[1] + 1;
1896 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1897 pFormat = SkipVariance(pStubMsg, pFormat);
1899 SizeVariance(pStubMsg);
1901 align_length(&pStubMsg->BufferLength, alignment);
1903 size = safe_multiply(esize, pStubMsg->ActualCount);
1904 safe_buffer_length_increment(pStubMsg, size);
1906 if (fHasPointers)
1907 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1908 break;
1909 case FC_C_CSTRING:
1910 case FC_C_WSTRING:
1911 if (fc == FC_C_CSTRING)
1912 esize = 1;
1913 else
1914 esize = 2;
1916 SizeVariance(pStubMsg);
1918 size = safe_multiply(esize, pStubMsg->ActualCount);
1919 safe_buffer_length_increment(pStubMsg, size);
1920 break;
1921 case FC_BOGUS_ARRAY:
1922 alignment = pFormat[1] + 1;
1923 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1924 if (IsConformanceOrVariancePresent(pFormat)) SizeVariance(pStubMsg);
1925 pFormat = SkipVariance(pStubMsg, pFormat);
1927 align_length(&pStubMsg->BufferLength, alignment);
1929 size = pStubMsg->ActualCount;
1930 for (i = 0; i < size; i++)
1931 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
1932 break;
1933 default:
1934 ERR("unknown array format 0x%x\n", fc);
1935 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1939 static inline void array_compute_and_write_conformance(
1940 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1941 PFORMAT_STRING pFormat)
1943 ULONG def;
1944 BOOL conformance_present;
1946 switch (fc)
1948 case FC_CARRAY:
1949 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1950 WriteConformance(pStubMsg);
1951 break;
1952 case FC_CVARRAY:
1953 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1954 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1955 WriteConformance(pStubMsg);
1956 break;
1957 case FC_C_CSTRING:
1958 case FC_C_WSTRING:
1959 if (fc == FC_C_CSTRING)
1961 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1962 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1964 else
1966 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1967 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1969 if (pFormat[1] == FC_STRING_SIZED)
1970 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1971 else
1972 pStubMsg->MaxCount = pStubMsg->ActualCount;
1973 pStubMsg->Offset = 0;
1974 WriteConformance(pStubMsg);
1975 break;
1976 case FC_BOGUS_ARRAY:
1977 def = *(const WORD *)(pFormat + 2);
1978 pFormat += 4;
1979 conformance_present = IsConformanceOrVariancePresent(pFormat);
1980 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
1981 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
1982 if (conformance_present) WriteConformance(pStubMsg);
1983 break;
1984 default:
1985 ERR("unknown array format 0x%x\n", fc);
1986 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1990 static inline void array_write_variance_and_marshall(
1991 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1992 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1994 DWORD i, size;
1995 DWORD esize;
1996 unsigned char alignment;
1998 switch (fc)
2000 case FC_CARRAY:
2001 esize = *(const WORD*)(pFormat+2);
2002 alignment = pFormat[1] + 1;
2004 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2006 align_pointer_clear(&pStubMsg->Buffer, alignment);
2008 size = safe_multiply(esize, pStubMsg->MaxCount);
2009 if (fHasPointers)
2010 pStubMsg->BufferMark = pStubMsg->Buffer;
2011 safe_copy_to_buffer(pStubMsg, pMemory, size);
2013 if (fHasPointers)
2014 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2015 break;
2016 case FC_CVARRAY:
2017 esize = *(const WORD*)(pFormat+2);
2018 alignment = pFormat[1] + 1;
2020 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2021 pFormat = SkipVariance(pStubMsg, pFormat);
2023 WriteVariance(pStubMsg);
2025 align_pointer_clear(&pStubMsg->Buffer, alignment);
2027 size = safe_multiply(esize, pStubMsg->ActualCount);
2029 if (fHasPointers)
2030 pStubMsg->BufferMark = pStubMsg->Buffer;
2031 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
2033 if (fHasPointers)
2034 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2035 break;
2036 case FC_C_CSTRING:
2037 case FC_C_WSTRING:
2038 if (fc == FC_C_CSTRING)
2039 esize = 1;
2040 else
2041 esize = 2;
2043 WriteVariance(pStubMsg);
2045 size = safe_multiply(esize, pStubMsg->ActualCount);
2046 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2047 break;
2048 case FC_BOGUS_ARRAY:
2049 alignment = pFormat[1] + 1;
2050 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2051 if (IsConformanceOrVariancePresent(pFormat)) WriteVariance(pStubMsg);
2052 pFormat = SkipVariance(pStubMsg, pFormat);
2054 align_pointer_clear(&pStubMsg->Buffer, alignment);
2056 size = pStubMsg->ActualCount;
2057 for (i = 0; i < size; i++)
2058 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2059 break;
2060 default:
2061 ERR("unknown array format 0x%x\n", fc);
2062 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2066 static inline ULONG array_read_conformance(
2067 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
2069 DWORD def, esize;
2071 switch (fc)
2073 case FC_CARRAY:
2074 esize = *(const WORD*)(pFormat+2);
2075 pFormat = ReadConformance(pStubMsg, pFormat+4);
2076 return safe_multiply(esize, pStubMsg->MaxCount);
2077 case FC_CVARRAY:
2078 esize = *(const WORD*)(pFormat+2);
2079 pFormat = ReadConformance(pStubMsg, pFormat+4);
2080 return safe_multiply(esize, pStubMsg->MaxCount);
2081 case FC_C_CSTRING:
2082 case FC_C_WSTRING:
2083 if (fc == FC_C_CSTRING)
2084 esize = 1;
2085 else
2086 esize = 2;
2088 if (pFormat[1] == FC_STRING_SIZED)
2089 ReadConformance(pStubMsg, pFormat + 2);
2090 else
2091 ReadConformance(pStubMsg, NULL);
2092 return safe_multiply(esize, pStubMsg->MaxCount);
2093 case FC_BOGUS_ARRAY:
2094 def = *(const WORD *)(pFormat + 2);
2095 pFormat += 4;
2096 if (IsConformanceOrVariancePresent(pFormat)) pFormat = ReadConformance(pStubMsg, pFormat);
2097 else
2099 pStubMsg->MaxCount = def;
2100 pFormat = SkipConformance( pStubMsg, pFormat );
2102 pFormat = SkipVariance( pStubMsg, pFormat );
2104 esize = ComplexStructSize(pStubMsg, pFormat);
2105 return safe_multiply(pStubMsg->MaxCount, esize);
2106 default:
2107 ERR("unknown array format 0x%x\n", fc);
2108 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2112 static inline ULONG array_read_variance_and_unmarshall(
2113 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
2114 PFORMAT_STRING pFormat, unsigned char fMustAlloc,
2115 unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
2117 ULONG bufsize, memsize;
2118 WORD esize;
2119 unsigned char alignment;
2120 unsigned char *saved_buffer, *pMemory;
2121 ULONG i, offset, count;
2123 switch (fc)
2125 case FC_CARRAY:
2126 esize = *(const WORD*)(pFormat+2);
2127 alignment = pFormat[1] + 1;
2129 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2131 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2133 align_pointer(&pStubMsg->Buffer, alignment);
2135 if (fUnmarshall)
2137 if (fMustAlloc)
2138 *ppMemory = NdrAllocate(pStubMsg, memsize);
2139 else
2141 if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2142 /* for servers, we just point straight into the RPC buffer */
2143 *ppMemory = pStubMsg->Buffer;
2146 saved_buffer = pStubMsg->Buffer;
2147 safe_buffer_increment(pStubMsg, bufsize);
2149 pStubMsg->BufferMark = saved_buffer;
2150 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2152 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2153 if (*ppMemory != saved_buffer)
2154 memcpy(*ppMemory, saved_buffer, bufsize);
2156 return bufsize;
2157 case FC_CVARRAY:
2158 esize = *(const WORD*)(pFormat+2);
2159 alignment = pFormat[1] + 1;
2161 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2163 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2165 align_pointer(&pStubMsg->Buffer, alignment);
2167 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2168 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2170 if (fUnmarshall)
2172 offset = pStubMsg->Offset;
2174 if (!fMustAlloc && !*ppMemory)
2175 fMustAlloc = TRUE;
2176 if (fMustAlloc)
2177 *ppMemory = NdrAllocate(pStubMsg, memsize);
2178 saved_buffer = pStubMsg->Buffer;
2179 safe_buffer_increment(pStubMsg, bufsize);
2181 pStubMsg->BufferMark = saved_buffer;
2182 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2183 fMustAlloc);
2185 memcpy(*ppMemory + offset, saved_buffer, bufsize);
2187 return bufsize;
2188 case FC_C_CSTRING:
2189 case FC_C_WSTRING:
2190 if (fc == FC_C_CSTRING)
2191 esize = 1;
2192 else
2193 esize = 2;
2195 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2197 if (pFormat[1] != FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2199 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2200 pStubMsg->ActualCount, pStubMsg->MaxCount);
2201 RpcRaiseException(RPC_S_INVALID_BOUND);
2203 if (pStubMsg->Offset)
2205 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2206 RpcRaiseException(RPC_S_INVALID_BOUND);
2209 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2210 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2212 validate_string_data(pStubMsg, bufsize, esize);
2214 if (fUnmarshall)
2216 if (fMustAlloc)
2217 *ppMemory = NdrAllocate(pStubMsg, memsize);
2218 else
2220 if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2221 !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2222 /* if the data in the RPC buffer is big enough, we just point
2223 * straight into it */
2224 *ppMemory = pStubMsg->Buffer;
2225 else if (!*ppMemory)
2226 *ppMemory = NdrAllocate(pStubMsg, memsize);
2229 if (*ppMemory == pStubMsg->Buffer)
2230 safe_buffer_increment(pStubMsg, bufsize);
2231 else
2232 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2234 if (*pFormat == FC_C_CSTRING)
2235 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2236 else
2237 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2239 return bufsize;
2241 case FC_BOGUS_ARRAY:
2242 alignment = pFormat[1] + 1;
2243 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2244 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2246 esize = ComplexStructSize(pStubMsg, pFormat);
2247 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2249 assert( fUnmarshall );
2251 if (!fMustAlloc && !*ppMemory)
2252 fMustAlloc = TRUE;
2253 if (fMustAlloc)
2254 *ppMemory = NdrAllocate(pStubMsg, memsize);
2256 align_pointer(&pStubMsg->Buffer, alignment);
2257 saved_buffer = pStubMsg->Buffer;
2259 pMemory = *ppMemory;
2260 count = pStubMsg->ActualCount;
2261 for (i = 0; i < count; i++)
2262 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
2263 return pStubMsg->Buffer - saved_buffer;
2265 default:
2266 ERR("unknown array format 0x%x\n", fc);
2267 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2271 static inline void array_memory_size(
2272 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2273 unsigned char fHasPointers)
2275 ULONG i, count, SavedMemorySize;
2276 ULONG bufsize, memsize;
2277 DWORD esize;
2278 unsigned char alignment;
2280 switch (fc)
2282 case FC_CARRAY:
2283 esize = *(const WORD*)(pFormat+2);
2284 alignment = pFormat[1] + 1;
2286 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2288 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2289 pStubMsg->MemorySize += memsize;
2291 align_pointer(&pStubMsg->Buffer, alignment);
2292 if (fHasPointers)
2293 pStubMsg->BufferMark = pStubMsg->Buffer;
2294 safe_buffer_increment(pStubMsg, bufsize);
2296 if (fHasPointers)
2297 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2298 break;
2299 case FC_CVARRAY:
2300 esize = *(const WORD*)(pFormat+2);
2301 alignment = pFormat[1] + 1;
2303 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2305 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2307 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2308 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2309 pStubMsg->MemorySize += memsize;
2311 align_pointer(&pStubMsg->Buffer, alignment);
2312 if (fHasPointers)
2313 pStubMsg->BufferMark = pStubMsg->Buffer;
2314 safe_buffer_increment(pStubMsg, bufsize);
2316 if (fHasPointers)
2317 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2318 break;
2319 case FC_C_CSTRING:
2320 case FC_C_WSTRING:
2321 if (fc == FC_C_CSTRING)
2322 esize = 1;
2323 else
2324 esize = 2;
2326 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2328 if (pFormat[1] != FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2330 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2331 pStubMsg->ActualCount, pStubMsg->MaxCount);
2332 RpcRaiseException(RPC_S_INVALID_BOUND);
2334 if (pStubMsg->Offset)
2336 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2337 RpcRaiseException(RPC_S_INVALID_BOUND);
2340 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2341 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2343 validate_string_data(pStubMsg, bufsize, esize);
2345 safe_buffer_increment(pStubMsg, bufsize);
2346 pStubMsg->MemorySize += memsize;
2347 break;
2348 case FC_BOGUS_ARRAY:
2349 alignment = pFormat[1] + 1;
2350 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2351 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2353 align_pointer(&pStubMsg->Buffer, alignment);
2355 SavedMemorySize = pStubMsg->MemorySize;
2357 esize = ComplexStructSize(pStubMsg, pFormat);
2358 memsize = safe_multiply(pStubMsg->MaxCount, esize);
2360 count = pStubMsg->ActualCount;
2361 for (i = 0; i < count; i++)
2362 ComplexStructMemorySize(pStubMsg, pFormat, NULL);
2364 pStubMsg->MemorySize = SavedMemorySize + memsize;
2365 break;
2366 default:
2367 ERR("unknown array format 0x%x\n", fc);
2368 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2372 static inline void array_free(
2373 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2374 unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2376 DWORD i, count;
2378 switch (fc)
2380 case FC_CARRAY:
2381 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2382 if (fHasPointers)
2383 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2384 break;
2385 case FC_CVARRAY:
2386 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2387 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2388 if (fHasPointers)
2389 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2390 break;
2391 case FC_C_CSTRING:
2392 case FC_C_WSTRING:
2393 /* No embedded pointers so nothing to do */
2394 break;
2395 case FC_BOGUS_ARRAY:
2396 count = *(const WORD *)(pFormat + 2);
2397 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, count);
2398 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2400 count = pStubMsg->ActualCount;
2401 for (i = 0; i < count; i++)
2402 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2403 break;
2404 default:
2405 ERR("unknown array format 0x%x\n", fc);
2406 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2411 * NdrConformantString:
2413 * What MS calls a ConformantString is, in DCE terminology,
2414 * a Varying-Conformant String.
2416 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2417 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
2418 * into unmarshalled string)
2419 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2421 * data: CHARTYPE[maxlen]
2423 * ], where CHARTYPE is the appropriate character type (specified externally)
2427 /***********************************************************************
2428 * NdrConformantStringMarshall [RPCRT4.@]
2430 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
2431 unsigned char *pszMessage, PFORMAT_STRING pFormat)
2433 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2435 if (pFormat[0] != FC_C_CSTRING && pFormat[0] != FC_C_WSTRING) {
2436 ERR("Unhandled string type: %#x\n", pFormat[0]);
2437 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2440 /* allow compiler to optimise inline function by passing constant into
2441 * these functions */
2442 if (pFormat[0] == FC_C_CSTRING) {
2443 array_compute_and_write_conformance(FC_C_CSTRING, pStubMsg, pszMessage,
2444 pFormat);
2445 array_write_variance_and_marshall(FC_C_CSTRING, pStubMsg, pszMessage,
2446 pFormat, TRUE /* fHasPointers */);
2447 } else {
2448 array_compute_and_write_conformance(FC_C_WSTRING, pStubMsg, pszMessage,
2449 pFormat);
2450 array_write_variance_and_marshall(FC_C_WSTRING, pStubMsg, pszMessage,
2451 pFormat, TRUE /* fHasPointers */);
2454 return NULL;
2457 /***********************************************************************
2458 * NdrConformantStringBufferSize [RPCRT4.@]
2460 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2461 unsigned char* pMemory, PFORMAT_STRING pFormat)
2463 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2465 if (pFormat[0] != FC_C_CSTRING && pFormat[0] != FC_C_WSTRING) {
2466 ERR("Unhandled string type: %#x\n", pFormat[0]);
2467 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2470 /* allow compiler to optimise inline function by passing constant into
2471 * these functions */
2472 if (pFormat[0] == FC_C_CSTRING) {
2473 array_compute_and_size_conformance(FC_C_CSTRING, pStubMsg, pMemory,
2474 pFormat);
2475 array_buffer_size(FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2476 TRUE /* fHasPointers */);
2477 } else {
2478 array_compute_and_size_conformance(FC_C_WSTRING, pStubMsg, pMemory,
2479 pFormat);
2480 array_buffer_size(FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2481 TRUE /* fHasPointers */);
2485 /************************************************************************
2486 * NdrConformantStringMemorySize [RPCRT4.@]
2488 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2489 PFORMAT_STRING pFormat )
2491 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2493 if (pFormat[0] != FC_C_CSTRING && pFormat[0] != FC_C_WSTRING) {
2494 ERR("Unhandled string type: %#x\n", pFormat[0]);
2495 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2498 /* allow compiler to optimise inline function by passing constant into
2499 * these functions */
2500 if (pFormat[0] == FC_C_CSTRING) {
2501 array_read_conformance(FC_C_CSTRING, pStubMsg, pFormat);
2502 array_memory_size(FC_C_CSTRING, pStubMsg, pFormat,
2503 TRUE /* fHasPointers */);
2504 } else {
2505 array_read_conformance(FC_C_WSTRING, pStubMsg, pFormat);
2506 array_memory_size(FC_C_WSTRING, pStubMsg, pFormat,
2507 TRUE /* fHasPointers */);
2510 return pStubMsg->MemorySize;
2513 /************************************************************************
2514 * NdrConformantStringUnmarshall [RPCRT4.@]
2516 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2517 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2519 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2520 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2522 if (pFormat[0] != FC_C_CSTRING && pFormat[0] != FC_C_WSTRING) {
2523 ERR("Unhandled string type: %#x\n", *pFormat);
2524 RpcRaiseException(RPC_X_BAD_STUB_DATA);
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_read_variance_and_unmarshall(FC_C_CSTRING, pStubMsg, ppMemory,
2532 pFormat, fMustAlloc,
2533 TRUE /* fUseBufferMemoryServer */,
2534 TRUE /* fUnmarshall */);
2535 } else {
2536 array_read_conformance(FC_C_WSTRING, pStubMsg, pFormat);
2537 array_read_variance_and_unmarshall(FC_C_WSTRING, pStubMsg, ppMemory,
2538 pFormat, fMustAlloc,
2539 TRUE /* fUseBufferMemoryServer */,
2540 TRUE /* fUnmarshall */);
2543 return NULL;
2546 /***********************************************************************
2547 * NdrNonConformantStringMarshall [RPCRT4.@]
2549 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2550 unsigned char *pMemory,
2551 PFORMAT_STRING pFormat)
2553 ULONG esize, size, maxsize;
2555 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2557 maxsize = *(const USHORT *)&pFormat[2];
2559 if (*pFormat == FC_CSTRING)
2561 ULONG i = 0;
2562 const char *str = (const char *)pMemory;
2563 while (i < maxsize && str[i]) i++;
2564 TRACE("string=%s\n", debugstr_an(str, i));
2565 pStubMsg->ActualCount = i + 1;
2566 esize = 1;
2568 else if (*pFormat == FC_WSTRING)
2570 ULONG i = 0;
2571 const WCHAR *str = (const WCHAR *)pMemory;
2572 while (i < maxsize && str[i]) i++;
2573 TRACE("string=%s\n", debugstr_wn(str, i));
2574 pStubMsg->ActualCount = i + 1;
2575 esize = 2;
2577 else
2579 ERR("Unhandled string type: %#x\n", *pFormat);
2580 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2583 pStubMsg->Offset = 0;
2584 WriteVariance(pStubMsg);
2586 size = safe_multiply(esize, pStubMsg->ActualCount);
2587 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2589 return NULL;
2592 /***********************************************************************
2593 * NdrNonConformantStringUnmarshall [RPCRT4.@]
2595 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2596 unsigned char **ppMemory,
2597 PFORMAT_STRING pFormat,
2598 unsigned char fMustAlloc)
2600 ULONG bufsize, memsize, esize, maxsize;
2602 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2603 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2605 maxsize = *(const USHORT *)&pFormat[2];
2607 ReadVariance(pStubMsg, NULL, maxsize);
2608 if (pStubMsg->Offset)
2610 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2611 RpcRaiseException(RPC_S_INVALID_BOUND);
2614 if (*pFormat == FC_CSTRING) esize = 1;
2615 else if (*pFormat == FC_WSTRING) esize = 2;
2616 else
2618 ERR("Unhandled string type: %#x\n", *pFormat);
2619 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2622 memsize = esize * maxsize;
2623 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2625 validate_string_data(pStubMsg, bufsize, esize);
2627 if (!fMustAlloc && !*ppMemory)
2628 fMustAlloc = TRUE;
2629 if (fMustAlloc)
2630 *ppMemory = NdrAllocate(pStubMsg, memsize);
2632 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2634 if (*pFormat == FC_CSTRING) {
2635 TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2637 else if (*pFormat == FC_WSTRING) {
2638 TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2641 return NULL;
2644 /***********************************************************************
2645 * NdrNonConformantStringBufferSize [RPCRT4.@]
2647 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2648 unsigned char *pMemory,
2649 PFORMAT_STRING pFormat)
2651 ULONG esize, maxsize;
2653 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2655 maxsize = *(const USHORT *)&pFormat[2];
2657 SizeVariance(pStubMsg);
2659 if (*pFormat == FC_CSTRING)
2661 ULONG i = 0;
2662 const char *str = (const char *)pMemory;
2663 while (i < maxsize && str[i]) i++;
2664 TRACE("string=%s\n", debugstr_an(str, i));
2665 pStubMsg->ActualCount = i + 1;
2666 esize = 1;
2668 else if (*pFormat == FC_WSTRING)
2670 ULONG i = 0;
2671 const WCHAR *str = (const WCHAR *)pMemory;
2672 while (i < maxsize && str[i]) i++;
2673 TRACE("string=%s\n", debugstr_wn(str, i));
2674 pStubMsg->ActualCount = i + 1;
2675 esize = 2;
2677 else
2679 ERR("Unhandled string type: %#x\n", *pFormat);
2680 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2683 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2686 /***********************************************************************
2687 * NdrNonConformantStringMemorySize [RPCRT4.@]
2689 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2690 PFORMAT_STRING pFormat)
2692 ULONG bufsize, memsize, esize, maxsize;
2694 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2696 maxsize = *(const USHORT *)&pFormat[2];
2698 ReadVariance(pStubMsg, NULL, maxsize);
2700 if (pStubMsg->Offset)
2702 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2703 RpcRaiseException(RPC_S_INVALID_BOUND);
2706 if (*pFormat == FC_CSTRING) esize = 1;
2707 else if (*pFormat == FC_WSTRING) esize = 2;
2708 else
2710 ERR("Unhandled string type: %#x\n", *pFormat);
2711 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2714 memsize = esize * maxsize;
2715 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2717 validate_string_data(pStubMsg, bufsize, esize);
2719 safe_buffer_increment(pStubMsg, bufsize);
2720 pStubMsg->MemorySize += memsize;
2722 return pStubMsg->MemorySize;
2725 /* Complex types */
2727 #include "pshpack1.h"
2728 typedef struct
2730 unsigned char type;
2731 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2732 ULONG low_value;
2733 ULONG high_value;
2734 } NDR_RANGE;
2735 #include "poppack.h"
2737 static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2738 PFORMAT_STRING pFormat)
2740 switch (*pFormat) {
2741 case FC_STRUCT:
2742 case FC_PSTRUCT:
2743 case FC_CSTRUCT:
2744 case FC_BOGUS_STRUCT:
2745 case FC_SMFARRAY:
2746 case FC_SMVARRAY:
2747 case FC_CSTRING:
2748 return *(const WORD*)&pFormat[2];
2749 case FC_USER_MARSHAL:
2750 return *(const WORD*)&pFormat[4];
2751 case FC_RANGE: {
2752 switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2753 case FC_BYTE:
2754 case FC_CHAR:
2755 case FC_SMALL:
2756 case FC_USMALL:
2757 return sizeof(UCHAR);
2758 case FC_WCHAR:
2759 case FC_SHORT:
2760 case FC_USHORT:
2761 return sizeof(USHORT);
2762 case FC_LONG:
2763 case FC_ULONG:
2764 case FC_ENUM32:
2765 case FC_INT3264:
2766 case FC_UINT3264:
2767 return sizeof(ULONG);
2768 case FC_FLOAT:
2769 return sizeof(float);
2770 case FC_DOUBLE:
2771 return sizeof(double);
2772 case FC_HYPER:
2773 return sizeof(ULONGLONG);
2774 case FC_ENUM16:
2775 return sizeof(UINT);
2776 default:
2777 ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2778 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2781 case FC_NON_ENCAPSULATED_UNION:
2782 pFormat += 2;
2783 pFormat = SkipConformance(pStubMsg, pFormat);
2784 pFormat += *(const SHORT*)pFormat;
2785 return *(const SHORT*)pFormat;
2786 case FC_IP:
2787 return sizeof(void *);
2788 case FC_WSTRING:
2789 return *(const WORD*)&pFormat[2] * 2;
2790 default:
2791 FIXME("unhandled embedded type %02x\n", *pFormat);
2793 return 0;
2797 static ULONG EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2798 PFORMAT_STRING pFormat)
2800 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2802 if (!m)
2804 FIXME("no memorysizer for data type=%02x\n", *pFormat);
2805 return 0;
2808 return m(pStubMsg, pFormat);
2812 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2813 unsigned char *pMemory,
2814 PFORMAT_STRING pFormat,
2815 PFORMAT_STRING pPointer)
2817 PFORMAT_STRING desc;
2818 NDR_MARSHALL m;
2819 ULONG size;
2821 while (*pFormat != FC_END) {
2822 switch (*pFormat) {
2823 case FC_BYTE:
2824 case FC_CHAR:
2825 case FC_SMALL:
2826 case FC_USMALL:
2827 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2828 safe_copy_to_buffer(pStubMsg, pMemory, 1);
2829 pMemory += 1;
2830 break;
2831 case FC_WCHAR:
2832 case FC_SHORT:
2833 case FC_USHORT:
2834 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2835 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2836 pMemory += 2;
2837 break;
2838 case FC_ENUM16:
2840 USHORT val = *(DWORD *)pMemory;
2841 TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2842 if (32767 < *(DWORD*)pMemory)
2843 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2844 safe_copy_to_buffer(pStubMsg, &val, 2);
2845 pMemory += 4;
2846 break;
2848 case FC_LONG:
2849 case FC_ULONG:
2850 case FC_ENUM32:
2851 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2852 safe_copy_to_buffer(pStubMsg, pMemory, 4);
2853 pMemory += 4;
2854 break;
2855 case FC_INT3264:
2856 case FC_UINT3264:
2858 UINT val = *(UINT_PTR *)pMemory;
2859 TRACE("int3264=%ld <= %p\n", *(UINT_PTR *)pMemory, pMemory);
2860 safe_copy_to_buffer(pStubMsg, &val, sizeof(UINT));
2861 pMemory += sizeof(UINT_PTR);
2862 break;
2864 case FC_FLOAT:
2865 TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
2866 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
2867 pMemory += sizeof(float);
2868 break;
2869 case FC_HYPER:
2870 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2871 safe_copy_to_buffer(pStubMsg, pMemory, 8);
2872 pMemory += 8;
2873 break;
2874 case FC_DOUBLE:
2875 TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
2876 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
2877 pMemory += sizeof(double);
2878 break;
2879 case FC_RP:
2880 case FC_UP:
2881 case FC_OP:
2882 case FC_FP:
2883 case FC_POINTER:
2885 unsigned char *saved_buffer;
2886 BOOL pointer_buffer_mark_set = FALSE;
2887 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2888 TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2889 if (*pFormat != FC_POINTER)
2890 pPointer = pFormat;
2891 if (*pPointer != FC_RP)
2892 align_pointer_clear(&pStubMsg->Buffer, 4);
2893 saved_buffer = pStubMsg->Buffer;
2894 if (pStubMsg->PointerBufferMark)
2896 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2897 pStubMsg->PointerBufferMark = NULL;
2898 pointer_buffer_mark_set = TRUE;
2900 else if (*pPointer != FC_RP)
2901 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2902 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2903 if (pointer_buffer_mark_set)
2905 STD_OVERFLOW_CHECK(pStubMsg);
2906 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2907 pStubMsg->Buffer = saved_buffer;
2908 if (*pPointer != FC_RP)
2909 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2911 TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2912 if (*pFormat == FC_POINTER)
2913 pPointer += 4;
2914 else
2915 pFormat += 4;
2916 pMemory += sizeof(void *);
2917 break;
2919 case FC_ALIGNM2:
2920 align_pointer(&pMemory, 2);
2921 break;
2922 case FC_ALIGNM4:
2923 align_pointer(&pMemory, 4);
2924 break;
2925 case FC_ALIGNM8:
2926 align_pointer(&pMemory, 8);
2927 break;
2928 case FC_STRUCTPAD1:
2929 case FC_STRUCTPAD2:
2930 case FC_STRUCTPAD3:
2931 case FC_STRUCTPAD4:
2932 case FC_STRUCTPAD5:
2933 case FC_STRUCTPAD6:
2934 case FC_STRUCTPAD7:
2935 pMemory += *pFormat - FC_STRUCTPAD1 + 1;
2936 break;
2937 case FC_EMBEDDED_COMPLEX:
2938 pMemory += pFormat[1];
2939 pFormat += 2;
2940 desc = pFormat + *(const SHORT*)pFormat;
2941 size = EmbeddedComplexSize(pStubMsg, desc);
2942 TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2943 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2944 if (m)
2946 /* for some reason interface pointers aren't generated as
2947 * FC_POINTER, but instead as FC_EMBEDDED_COMPLEX, yet
2948 * they still need the dereferencing treatment that pointers are
2949 * given */
2950 if (*desc == FC_IP)
2951 m(pStubMsg, *(unsigned char **)pMemory, desc);
2952 else
2953 m(pStubMsg, pMemory, desc);
2955 else FIXME("no marshaller for embedded type %02x\n", *desc);
2956 pMemory += size;
2957 pFormat += 2;
2958 continue;
2959 case FC_PAD:
2960 break;
2961 default:
2962 FIXME("unhandled format 0x%02x\n", *pFormat);
2964 pFormat++;
2967 return pMemory;
2970 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2971 unsigned char *pMemory,
2972 PFORMAT_STRING pFormat,
2973 PFORMAT_STRING pPointer,
2974 unsigned char fMustAlloc)
2976 PFORMAT_STRING desc;
2977 NDR_UNMARSHALL m;
2978 ULONG size;
2980 while (*pFormat != FC_END) {
2981 switch (*pFormat) {
2982 case FC_BYTE:
2983 case FC_CHAR:
2984 case FC_SMALL:
2985 case FC_USMALL:
2986 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2987 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2988 pMemory += 1;
2989 break;
2990 case FC_WCHAR:
2991 case FC_SHORT:
2992 case FC_USHORT:
2993 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2994 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2995 pMemory += 2;
2996 break;
2997 case FC_ENUM16:
2999 WORD val;
3000 safe_copy_from_buffer(pStubMsg, &val, 2);
3001 *(DWORD*)pMemory = val;
3002 TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
3003 if (32767 < *(DWORD*)pMemory)
3004 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
3005 pMemory += 4;
3006 break;
3008 case FC_LONG:
3009 case FC_ULONG:
3010 case FC_ENUM32:
3011 safe_copy_from_buffer(pStubMsg, pMemory, 4);
3012 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
3013 pMemory += 4;
3014 break;
3015 case FC_INT3264:
3017 INT val;
3018 safe_copy_from_buffer(pStubMsg, &val, 4);
3019 *(INT_PTR *)pMemory = val;
3020 TRACE("int3264=%ld => %p\n", *(INT_PTR*)pMemory, pMemory);
3021 pMemory += sizeof(INT_PTR);
3022 break;
3024 case FC_UINT3264:
3026 UINT val;
3027 safe_copy_from_buffer(pStubMsg, &val, 4);
3028 *(UINT_PTR *)pMemory = val;
3029 TRACE("uint3264=%ld => %p\n", *(UINT_PTR*)pMemory, pMemory);
3030 pMemory += sizeof(UINT_PTR);
3031 break;
3033 case FC_FLOAT:
3034 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
3035 TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
3036 pMemory += sizeof(float);
3037 break;
3038 case FC_HYPER:
3039 safe_copy_from_buffer(pStubMsg, pMemory, 8);
3040 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
3041 pMemory += 8;
3042 break;
3043 case FC_DOUBLE:
3044 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
3045 TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
3046 pMemory += sizeof(double);
3047 break;
3048 case FC_RP:
3049 case FC_UP:
3050 case FC_OP:
3051 case FC_FP:
3052 case FC_POINTER:
3054 unsigned char *saved_buffer;
3055 BOOL pointer_buffer_mark_set = FALSE;
3056 TRACE("pointer => %p\n", pMemory);
3057 if (*pFormat != FC_POINTER)
3058 pPointer = pFormat;
3059 if (*pPointer != FC_RP)
3060 align_pointer(&pStubMsg->Buffer, 4);
3061 saved_buffer = pStubMsg->Buffer;
3062 if (pStubMsg->PointerBufferMark)
3064 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3065 pStubMsg->PointerBufferMark = NULL;
3066 pointer_buffer_mark_set = TRUE;
3068 else if (*pPointer != FC_RP)
3069 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3071 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
3072 if (pointer_buffer_mark_set)
3074 STD_OVERFLOW_CHECK(pStubMsg);
3075 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3076 pStubMsg->Buffer = saved_buffer;
3077 if (*pPointer != FC_RP)
3078 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3080 if (*pFormat == FC_POINTER)
3081 pPointer += 4;
3082 else
3083 pFormat += 4;
3084 pMemory += sizeof(void *);
3085 break;
3087 case FC_ALIGNM2:
3088 align_pointer_clear(&pMemory, 2);
3089 break;
3090 case FC_ALIGNM4:
3091 align_pointer_clear(&pMemory, 4);
3092 break;
3093 case FC_ALIGNM8:
3094 align_pointer_clear(&pMemory, 8);
3095 break;
3096 case FC_STRUCTPAD1:
3097 case FC_STRUCTPAD2:
3098 case FC_STRUCTPAD3:
3099 case FC_STRUCTPAD4:
3100 case FC_STRUCTPAD5:
3101 case FC_STRUCTPAD6:
3102 case FC_STRUCTPAD7:
3103 memset(pMemory, 0, *pFormat - FC_STRUCTPAD1 + 1);
3104 pMemory += *pFormat - FC_STRUCTPAD1 + 1;
3105 break;
3106 case FC_EMBEDDED_COMPLEX:
3107 pMemory += pFormat[1];
3108 pFormat += 2;
3109 desc = pFormat + *(const SHORT*)pFormat;
3110 size = EmbeddedComplexSize(pStubMsg, desc);
3111 TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
3112 if (fMustAlloc)
3113 /* we can't pass fMustAlloc=TRUE into the marshaller for this type
3114 * since the type is part of the memory block that is encompassed by
3115 * the whole complex type. Memory is forced to allocate when pointers
3116 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
3117 * clearing the memory we pass in to the unmarshaller */
3118 memset(pMemory, 0, size);
3119 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
3120 if (m)
3122 /* for some reason interface pointers aren't generated as
3123 * FC_POINTER, but instead as FC_EMBEDDED_COMPLEX, yet
3124 * they still need the dereferencing treatment that pointers are
3125 * given */
3126 if (*desc == FC_IP)
3127 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
3128 else
3129 m(pStubMsg, &pMemory, desc, FALSE);
3131 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
3132 pMemory += size;
3133 pFormat += 2;
3134 continue;
3135 case FC_PAD:
3136 break;
3137 default:
3138 FIXME("unhandled format %d\n", *pFormat);
3140 pFormat++;
3143 return pMemory;
3146 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3147 unsigned char *pMemory,
3148 PFORMAT_STRING pFormat,
3149 PFORMAT_STRING pPointer)
3151 PFORMAT_STRING desc;
3152 NDR_BUFFERSIZE m;
3153 ULONG size;
3155 while (*pFormat != FC_END) {
3156 switch (*pFormat) {
3157 case FC_BYTE:
3158 case FC_CHAR:
3159 case FC_SMALL:
3160 case FC_USMALL:
3161 safe_buffer_length_increment(pStubMsg, 1);
3162 pMemory += 1;
3163 break;
3164 case FC_WCHAR:
3165 case FC_SHORT:
3166 case FC_USHORT:
3167 safe_buffer_length_increment(pStubMsg, 2);
3168 pMemory += 2;
3169 break;
3170 case FC_ENUM16:
3171 safe_buffer_length_increment(pStubMsg, 2);
3172 pMemory += 4;
3173 break;
3174 case FC_LONG:
3175 case FC_ULONG:
3176 case FC_ENUM32:
3177 case FC_FLOAT:
3178 safe_buffer_length_increment(pStubMsg, 4);
3179 pMemory += 4;
3180 break;
3181 case FC_INT3264:
3182 case FC_UINT3264:
3183 safe_buffer_length_increment(pStubMsg, 4);
3184 pMemory += sizeof(INT_PTR);
3185 break;
3186 case FC_HYPER:
3187 case FC_DOUBLE:
3188 safe_buffer_length_increment(pStubMsg, 8);
3189 pMemory += 8;
3190 break;
3191 case FC_RP:
3192 case FC_UP:
3193 case FC_OP:
3194 case FC_FP:
3195 case FC_POINTER:
3196 if (*pFormat != FC_POINTER)
3197 pPointer = pFormat;
3198 if (!pStubMsg->IgnoreEmbeddedPointers)
3200 int saved_buffer_length = pStubMsg->BufferLength;
3201 pStubMsg->BufferLength = pStubMsg->PointerLength;
3202 pStubMsg->PointerLength = 0;
3203 if(!pStubMsg->BufferLength)
3204 ERR("BufferLength == 0??\n");
3205 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
3206 pStubMsg->PointerLength = pStubMsg->BufferLength;
3207 pStubMsg->BufferLength = saved_buffer_length;
3209 if (*pPointer != FC_RP)
3211 align_length(&pStubMsg->BufferLength, 4);
3212 safe_buffer_length_increment(pStubMsg, 4);
3214 if (*pFormat == FC_POINTER)
3215 pPointer += 4;
3216 else
3217 pFormat += 4;
3218 pMemory += sizeof(void*);
3219 break;
3220 case FC_ALIGNM2:
3221 align_pointer(&pMemory, 2);
3222 break;
3223 case FC_ALIGNM4:
3224 align_pointer(&pMemory, 4);
3225 break;
3226 case FC_ALIGNM8:
3227 align_pointer(&pMemory, 8);
3228 break;
3229 case FC_STRUCTPAD1:
3230 case FC_STRUCTPAD2:
3231 case FC_STRUCTPAD3:
3232 case FC_STRUCTPAD4:
3233 case FC_STRUCTPAD5:
3234 case FC_STRUCTPAD6:
3235 case FC_STRUCTPAD7:
3236 pMemory += *pFormat - FC_STRUCTPAD1 + 1;
3237 break;
3238 case FC_EMBEDDED_COMPLEX:
3239 pMemory += pFormat[1];
3240 pFormat += 2;
3241 desc = pFormat + *(const SHORT*)pFormat;
3242 size = EmbeddedComplexSize(pStubMsg, desc);
3243 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3244 if (m)
3246 /* for some reason interface pointers aren't generated as
3247 * FC_POINTER, but instead as FC_EMBEDDED_COMPLEX, yet
3248 * they still need the dereferencing treatment that pointers are
3249 * given */
3250 if (*desc == FC_IP)
3251 m(pStubMsg, *(unsigned char **)pMemory, desc);
3252 else
3253 m(pStubMsg, pMemory, desc);
3255 else FIXME("no buffersizer for embedded type %02x\n", *desc);
3256 pMemory += size;
3257 pFormat += 2;
3258 continue;
3259 case FC_PAD:
3260 break;
3261 default:
3262 FIXME("unhandled format 0x%02x\n", *pFormat);
3264 pFormat++;
3267 return pMemory;
3270 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
3271 unsigned char *pMemory,
3272 PFORMAT_STRING pFormat,
3273 PFORMAT_STRING pPointer)
3275 PFORMAT_STRING desc;
3276 NDR_FREE m;
3277 ULONG size;
3279 while (*pFormat != FC_END) {
3280 switch (*pFormat) {
3281 case FC_BYTE:
3282 case FC_CHAR:
3283 case FC_SMALL:
3284 case FC_USMALL:
3285 pMemory += 1;
3286 break;
3287 case FC_WCHAR:
3288 case FC_SHORT:
3289 case FC_USHORT:
3290 pMemory += 2;
3291 break;
3292 case FC_LONG:
3293 case FC_ULONG:
3294 case FC_ENUM16:
3295 case FC_ENUM32:
3296 case FC_FLOAT:
3297 pMemory += 4;
3298 break;
3299 case FC_INT3264:
3300 case FC_UINT3264:
3301 pMemory += sizeof(INT_PTR);
3302 break;
3303 case FC_HYPER:
3304 case FC_DOUBLE:
3305 pMemory += 8;
3306 break;
3307 case FC_RP:
3308 case FC_UP:
3309 case FC_OP:
3310 case FC_FP:
3311 case FC_POINTER:
3312 if (*pFormat != FC_POINTER)
3313 pPointer = pFormat;
3314 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3315 if (*pFormat == FC_POINTER)
3316 pPointer += 4;
3317 else
3318 pFormat += 4;
3319 pMemory += sizeof(void *);
3320 break;
3321 case FC_ALIGNM2:
3322 align_pointer(&pMemory, 2);
3323 break;
3324 case FC_ALIGNM4:
3325 align_pointer(&pMemory, 4);
3326 break;
3327 case FC_ALIGNM8:
3328 align_pointer(&pMemory, 8);
3329 break;
3330 case FC_STRUCTPAD1:
3331 case FC_STRUCTPAD2:
3332 case FC_STRUCTPAD3:
3333 case FC_STRUCTPAD4:
3334 case FC_STRUCTPAD5:
3335 case FC_STRUCTPAD6:
3336 case FC_STRUCTPAD7:
3337 pMemory += *pFormat - FC_STRUCTPAD1 + 1;
3338 break;
3339 case FC_EMBEDDED_COMPLEX:
3340 pMemory += pFormat[1];
3341 pFormat += 2;
3342 desc = pFormat + *(const SHORT*)pFormat;
3343 size = EmbeddedComplexSize(pStubMsg, desc);
3344 m = NdrFreer[*desc & NDR_TABLE_MASK];
3345 if (m)
3347 /* for some reason interface pointers aren't generated as
3348 * FC_POINTER, but instead as FC_EMBEDDED_COMPLEX, yet
3349 * they still need the dereferencing treatment that pointers are
3350 * given */
3351 if (*desc == FC_IP)
3352 m(pStubMsg, *(unsigned char **)pMemory, desc);
3353 else
3354 m(pStubMsg, pMemory, desc);
3356 pMemory += size;
3357 pFormat += 2;
3358 continue;
3359 case FC_PAD:
3360 break;
3361 default:
3362 FIXME("unhandled format 0x%02x\n", *pFormat);
3364 pFormat++;
3367 return pMemory;
3370 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3371 PFORMAT_STRING pFormat,
3372 PFORMAT_STRING pPointer)
3374 PFORMAT_STRING desc;
3375 ULONG size = 0;
3377 while (*pFormat != FC_END) {
3378 switch (*pFormat) {
3379 case FC_BYTE:
3380 case FC_CHAR:
3381 case FC_SMALL:
3382 case FC_USMALL:
3383 size += 1;
3384 safe_buffer_increment(pStubMsg, 1);
3385 break;
3386 case FC_WCHAR:
3387 case FC_SHORT:
3388 case FC_USHORT:
3389 size += 2;
3390 safe_buffer_increment(pStubMsg, 2);
3391 break;
3392 case FC_ENUM16:
3393 size += 4;
3394 safe_buffer_increment(pStubMsg, 2);
3395 break;
3396 case FC_LONG:
3397 case FC_ULONG:
3398 case FC_ENUM32:
3399 case FC_FLOAT:
3400 size += 4;
3401 safe_buffer_increment(pStubMsg, 4);
3402 break;
3403 case FC_INT3264:
3404 case FC_UINT3264:
3405 size += sizeof(INT_PTR);
3406 safe_buffer_increment(pStubMsg, 4);
3407 break;
3408 case FC_HYPER:
3409 case FC_DOUBLE:
3410 size += 8;
3411 safe_buffer_increment(pStubMsg, 8);
3412 break;
3413 case FC_RP:
3414 case FC_UP:
3415 case FC_OP:
3416 case FC_FP:
3417 case FC_POINTER:
3419 unsigned char *saved_buffer;
3420 BOOL pointer_buffer_mark_set = FALSE;
3421 if (*pFormat != FC_POINTER)
3422 pPointer = pFormat;
3423 if (*pPointer != FC_RP)
3424 align_pointer(&pStubMsg->Buffer, 4);
3425 saved_buffer = pStubMsg->Buffer;
3426 if (pStubMsg->PointerBufferMark)
3428 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3429 pStubMsg->PointerBufferMark = NULL;
3430 pointer_buffer_mark_set = TRUE;
3432 else if (*pPointer != FC_RP)
3433 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3435 if (!pStubMsg->IgnoreEmbeddedPointers)
3436 PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3437 if (pointer_buffer_mark_set)
3439 STD_OVERFLOW_CHECK(pStubMsg);
3440 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3441 pStubMsg->Buffer = saved_buffer;
3442 if (*pPointer != FC_RP)
3443 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3445 if (*pFormat == FC_POINTER)
3446 pPointer += 4;
3447 else
3448 pFormat += 4;
3449 size += sizeof(void *);
3450 break;
3452 case FC_ALIGNM2:
3453 align_length(&size, 2);
3454 break;
3455 case FC_ALIGNM4:
3456 align_length(&size, 4);
3457 break;
3458 case FC_ALIGNM8:
3459 align_length(&size, 8);
3460 break;
3461 case FC_STRUCTPAD1:
3462 case FC_STRUCTPAD2:
3463 case FC_STRUCTPAD3:
3464 case FC_STRUCTPAD4:
3465 case FC_STRUCTPAD5:
3466 case FC_STRUCTPAD6:
3467 case FC_STRUCTPAD7:
3468 size += *pFormat - FC_STRUCTPAD1 + 1;
3469 break;
3470 case FC_EMBEDDED_COMPLEX:
3471 size += pFormat[1];
3472 pFormat += 2;
3473 desc = pFormat + *(const SHORT*)pFormat;
3474 size += EmbeddedComplexMemorySize(pStubMsg, desc);
3475 pFormat += 2;
3476 continue;
3477 case FC_PAD:
3478 break;
3479 default:
3480 FIXME("unhandled format 0x%02x\n", *pFormat);
3482 pFormat++;
3485 return size;
3488 ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
3490 PFORMAT_STRING desc;
3491 ULONG size = 0;
3493 while (*pFormat != FC_END) {
3494 switch (*pFormat) {
3495 case FC_BYTE:
3496 case FC_CHAR:
3497 case FC_SMALL:
3498 case FC_USMALL:
3499 size += 1;
3500 break;
3501 case FC_WCHAR:
3502 case FC_SHORT:
3503 case FC_USHORT:
3504 size += 2;
3505 break;
3506 case FC_LONG:
3507 case FC_ULONG:
3508 case FC_ENUM16:
3509 case FC_ENUM32:
3510 case FC_FLOAT:
3511 size += 4;
3512 break;
3513 case FC_INT3264:
3514 case FC_UINT3264:
3515 size += sizeof(INT_PTR);
3516 break;
3517 case FC_HYPER:
3518 case FC_DOUBLE:
3519 size += 8;
3520 break;
3521 case FC_RP:
3522 case FC_UP:
3523 case FC_OP:
3524 case FC_FP:
3525 case FC_POINTER:
3526 size += sizeof(void *);
3527 if (*pFormat != FC_POINTER)
3528 pFormat += 4;
3529 break;
3530 case FC_ALIGNM2:
3531 align_length(&size, 2);
3532 break;
3533 case FC_ALIGNM4:
3534 align_length(&size, 4);
3535 break;
3536 case FC_ALIGNM8:
3537 align_length(&size, 8);
3538 break;
3539 case FC_STRUCTPAD1:
3540 case FC_STRUCTPAD2:
3541 case FC_STRUCTPAD3:
3542 case FC_STRUCTPAD4:
3543 case FC_STRUCTPAD5:
3544 case FC_STRUCTPAD6:
3545 case FC_STRUCTPAD7:
3546 size += *pFormat - FC_STRUCTPAD1 + 1;
3547 break;
3548 case FC_EMBEDDED_COMPLEX:
3549 size += pFormat[1];
3550 pFormat += 2;
3551 desc = pFormat + *(const SHORT*)pFormat;
3552 size += EmbeddedComplexSize(pStubMsg, desc);
3553 pFormat += 2;
3554 continue;
3555 case FC_PAD:
3556 break;
3557 default:
3558 FIXME("unhandled format 0x%02x\n", *pFormat);
3560 pFormat++;
3563 return size;
3566 /***********************************************************************
3567 * NdrComplexStructMarshall [RPCRT4.@]
3569 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3570 unsigned char *pMemory,
3571 PFORMAT_STRING pFormat)
3573 PFORMAT_STRING conf_array = NULL;
3574 PFORMAT_STRING pointer_desc = NULL;
3575 unsigned char *OldMemory = pStubMsg->Memory;
3576 BOOL pointer_buffer_mark_set = FALSE;
3577 ULONG count = 0;
3578 ULONG max_count = 0;
3579 ULONG offset = 0;
3581 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3583 if (!pStubMsg->PointerBufferMark)
3585 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3586 /* save buffer length */
3587 ULONG saved_buffer_length = pStubMsg->BufferLength;
3589 /* get the buffer pointer after complex array data, but before
3590 * pointer data */
3591 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3592 pStubMsg->IgnoreEmbeddedPointers = 1;
3593 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3594 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3596 /* save it for use by embedded pointer code later */
3597 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3598 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
3599 pointer_buffer_mark_set = TRUE;
3601 /* restore the original buffer length */
3602 pStubMsg->BufferLength = saved_buffer_length;
3605 align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
3607 pFormat += 4;
3608 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3609 pFormat += 2;
3610 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3611 pFormat += 2;
3613 pStubMsg->Memory = pMemory;
3615 if (conf_array)
3617 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3618 array_compute_and_write_conformance(conf_array[0], pStubMsg,
3619 pMemory + struct_size, conf_array);
3620 /* these could be changed in ComplexMarshall so save them for later */
3621 max_count = pStubMsg->MaxCount;
3622 count = pStubMsg->ActualCount;
3623 offset = pStubMsg->Offset;
3626 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3628 if (conf_array)
3630 pStubMsg->MaxCount = max_count;
3631 pStubMsg->ActualCount = count;
3632 pStubMsg->Offset = offset;
3633 array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3634 conf_array, TRUE /* fHasPointers */);
3637 pStubMsg->Memory = OldMemory;
3639 if (pointer_buffer_mark_set)
3641 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3642 pStubMsg->PointerBufferMark = NULL;
3645 STD_OVERFLOW_CHECK(pStubMsg);
3647 return NULL;
3650 /***********************************************************************
3651 * NdrComplexStructUnmarshall [RPCRT4.@]
3653 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3654 unsigned char **ppMemory,
3655 PFORMAT_STRING pFormat,
3656 unsigned char fMustAlloc)
3658 unsigned size = *(const WORD*)(pFormat+2);
3659 PFORMAT_STRING conf_array = NULL;
3660 PFORMAT_STRING pointer_desc = NULL;
3661 unsigned char *pMemory;
3662 BOOL pointer_buffer_mark_set = FALSE;
3663 ULONG count = 0;
3664 ULONG max_count = 0;
3665 ULONG offset = 0;
3666 ULONG array_size = 0;
3668 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3670 if (!pStubMsg->PointerBufferMark)
3672 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3673 /* save buffer pointer */
3674 unsigned char *saved_buffer = pStubMsg->Buffer;
3676 /* get the buffer pointer after complex array data, but before
3677 * pointer data */
3678 pStubMsg->IgnoreEmbeddedPointers = 1;
3679 NdrComplexStructMemorySize(pStubMsg, pFormat);
3680 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3682 /* save it for use by embedded pointer code later */
3683 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3684 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
3685 pointer_buffer_mark_set = TRUE;
3687 /* restore the original buffer */
3688 pStubMsg->Buffer = saved_buffer;
3691 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
3693 pFormat += 4;
3694 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3695 pFormat += 2;
3696 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3697 pFormat += 2;
3699 if (conf_array)
3701 array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3702 size += array_size;
3704 /* these could be changed in ComplexMarshall so save them for later */
3705 max_count = pStubMsg->MaxCount;
3706 count = pStubMsg->ActualCount;
3707 offset = pStubMsg->Offset;
3710 if (!fMustAlloc && !*ppMemory)
3711 fMustAlloc = TRUE;
3712 if (fMustAlloc)
3713 *ppMemory = NdrAllocate(pStubMsg, size);
3715 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3717 if (conf_array)
3719 pStubMsg->MaxCount = max_count;
3720 pStubMsg->ActualCount = count;
3721 pStubMsg->Offset = offset;
3722 if (fMustAlloc)
3723 memset(pMemory, 0, array_size);
3724 array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3725 conf_array, FALSE,
3726 FALSE /* fUseBufferMemoryServer */,
3727 TRUE /* fUnmarshall */);
3730 if (pointer_buffer_mark_set)
3732 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3733 pStubMsg->PointerBufferMark = NULL;
3736 return NULL;
3739 /***********************************************************************
3740 * NdrComplexStructBufferSize [RPCRT4.@]
3742 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3743 unsigned char *pMemory,
3744 PFORMAT_STRING pFormat)
3746 PFORMAT_STRING conf_array = NULL;
3747 PFORMAT_STRING pointer_desc = NULL;
3748 unsigned char *OldMemory = pStubMsg->Memory;
3749 int pointer_length_set = 0;
3750 ULONG count = 0;
3751 ULONG max_count = 0;
3752 ULONG offset = 0;
3754 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3756 align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
3758 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3760 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3761 ULONG saved_buffer_length = pStubMsg->BufferLength;
3763 /* get the buffer length after complex struct data, but before
3764 * pointer data */
3765 pStubMsg->IgnoreEmbeddedPointers = 1;
3766 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3767 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3769 /* save it for use by embedded pointer code later */
3770 pStubMsg->PointerLength = pStubMsg->BufferLength;
3771 pointer_length_set = 1;
3772 TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
3774 /* restore the original buffer length */
3775 pStubMsg->BufferLength = saved_buffer_length;
3778 pFormat += 4;
3779 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3780 pFormat += 2;
3781 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3782 pFormat += 2;
3784 pStubMsg->Memory = pMemory;
3786 if (conf_array)
3788 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3789 array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3790 conf_array);
3792 /* these could be changed in ComplexMarshall so save them for later */
3793 max_count = pStubMsg->MaxCount;
3794 count = pStubMsg->ActualCount;
3795 offset = pStubMsg->Offset;
3798 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3800 if (conf_array)
3802 pStubMsg->MaxCount = max_count;
3803 pStubMsg->ActualCount = count;
3804 pStubMsg->Offset = offset;
3805 array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3806 TRUE /* fHasPointers */);
3809 pStubMsg->Memory = OldMemory;
3811 if(pointer_length_set)
3813 pStubMsg->BufferLength = pStubMsg->PointerLength;
3814 pStubMsg->PointerLength = 0;
3819 /***********************************************************************
3820 * NdrComplexStructMemorySize [RPCRT4.@]
3822 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3823 PFORMAT_STRING pFormat)
3825 unsigned size = *(const WORD*)(pFormat+2);
3826 PFORMAT_STRING conf_array = NULL;
3827 PFORMAT_STRING pointer_desc = NULL;
3828 ULONG count = 0;
3829 ULONG max_count = 0;
3830 ULONG offset = 0;
3832 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3834 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
3836 pFormat += 4;
3837 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3838 pFormat += 2;
3839 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3840 pFormat += 2;
3842 if (conf_array)
3844 array_read_conformance(conf_array[0], pStubMsg, conf_array);
3846 /* these could be changed in ComplexStructMemorySize so save them for
3847 * later */
3848 max_count = pStubMsg->MaxCount;
3849 count = pStubMsg->ActualCount;
3850 offset = pStubMsg->Offset;
3853 ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3855 if (conf_array)
3857 pStubMsg->MaxCount = max_count;
3858 pStubMsg->ActualCount = count;
3859 pStubMsg->Offset = offset;
3860 array_memory_size(conf_array[0], pStubMsg, conf_array,
3861 TRUE /* fHasPointers */);
3864 return size;
3867 /***********************************************************************
3868 * NdrComplexStructFree [RPCRT4.@]
3870 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3871 unsigned char *pMemory,
3872 PFORMAT_STRING pFormat)
3874 PFORMAT_STRING conf_array = NULL;
3875 PFORMAT_STRING pointer_desc = NULL;
3876 unsigned char *OldMemory = pStubMsg->Memory;
3878 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3880 pFormat += 4;
3881 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3882 pFormat += 2;
3883 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3884 pFormat += 2;
3886 pStubMsg->Memory = pMemory;
3888 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3890 if (conf_array)
3891 array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3892 TRUE /* fHasPointers */);
3894 pStubMsg->Memory = OldMemory;
3897 /***********************************************************************
3898 * NdrConformantArrayMarshall [RPCRT4.@]
3900 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3901 unsigned char *pMemory,
3902 PFORMAT_STRING pFormat)
3904 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3905 if (pFormat[0] != FC_CARRAY)
3907 ERR("invalid format = 0x%x\n", pFormat[0]);
3908 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3911 array_compute_and_write_conformance(FC_CARRAY, pStubMsg, pMemory,
3912 pFormat);
3913 array_write_variance_and_marshall(FC_CARRAY, pStubMsg, pMemory, pFormat,
3914 TRUE /* fHasPointers */);
3916 return NULL;
3919 /***********************************************************************
3920 * NdrConformantArrayUnmarshall [RPCRT4.@]
3922 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3923 unsigned char **ppMemory,
3924 PFORMAT_STRING pFormat,
3925 unsigned char fMustAlloc)
3927 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3928 if (pFormat[0] != FC_CARRAY)
3930 ERR("invalid format = 0x%x\n", pFormat[0]);
3931 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3934 array_read_conformance(FC_CARRAY, pStubMsg, pFormat);
3935 array_read_variance_and_unmarshall(FC_CARRAY, pStubMsg, ppMemory, pFormat,
3936 fMustAlloc,
3937 TRUE /* fUseBufferMemoryServer */,
3938 TRUE /* fUnmarshall */);
3940 return NULL;
3943 /***********************************************************************
3944 * NdrConformantArrayBufferSize [RPCRT4.@]
3946 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3947 unsigned char *pMemory,
3948 PFORMAT_STRING pFormat)
3950 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3951 if (pFormat[0] != FC_CARRAY)
3953 ERR("invalid format = 0x%x\n", pFormat[0]);
3954 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3957 array_compute_and_size_conformance(FC_CARRAY, pStubMsg, pMemory, pFormat);
3958 array_buffer_size(FC_CARRAY, pStubMsg, pMemory, pFormat,
3959 TRUE /* fHasPointers */);
3962 /***********************************************************************
3963 * NdrConformantArrayMemorySize [RPCRT4.@]
3965 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3966 PFORMAT_STRING pFormat)
3968 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3969 if (pFormat[0] != FC_CARRAY)
3971 ERR("invalid format = 0x%x\n", pFormat[0]);
3972 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3975 array_read_conformance(FC_CARRAY, pStubMsg, pFormat);
3976 array_memory_size(FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
3978 return pStubMsg->MemorySize;
3981 /***********************************************************************
3982 * NdrConformantArrayFree [RPCRT4.@]
3984 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3985 unsigned char *pMemory,
3986 PFORMAT_STRING pFormat)
3988 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3989 if (pFormat[0] != FC_CARRAY)
3991 ERR("invalid format = 0x%x\n", pFormat[0]);
3992 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3995 array_free(FC_CARRAY, pStubMsg, pMemory, pFormat,
3996 TRUE /* fHasPointers */);
4000 /***********************************************************************
4001 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
4003 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
4004 unsigned char* pMemory,
4005 PFORMAT_STRING pFormat )
4007 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4009 if (pFormat[0] != FC_CVARRAY)
4011 ERR("invalid format type %x\n", pFormat[0]);
4012 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4013 return NULL;
4016 array_compute_and_write_conformance(FC_CVARRAY, pStubMsg, pMemory,
4017 pFormat);
4018 array_write_variance_and_marshall(FC_CVARRAY, pStubMsg, pMemory,
4019 pFormat, TRUE /* fHasPointers */);
4021 return NULL;
4025 /***********************************************************************
4026 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
4028 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
4029 unsigned char** ppMemory,
4030 PFORMAT_STRING pFormat,
4031 unsigned char fMustAlloc )
4033 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4035 if (pFormat[0] != FC_CVARRAY)
4037 ERR("invalid format type %x\n", pFormat[0]);
4038 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4039 return NULL;
4042 array_read_conformance(FC_CVARRAY, pStubMsg, pFormat);
4043 array_read_variance_and_unmarshall(FC_CVARRAY, pStubMsg, ppMemory,
4044 pFormat, fMustAlloc,
4045 TRUE /* fUseBufferMemoryServer */,
4046 TRUE /* fUnmarshall */);
4048 return NULL;
4052 /***********************************************************************
4053 * NdrConformantVaryingArrayFree [RPCRT4.@]
4055 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
4056 unsigned char* pMemory,
4057 PFORMAT_STRING pFormat )
4059 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4061 if (pFormat[0] != FC_CVARRAY)
4063 ERR("invalid format type %x\n", pFormat[0]);
4064 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4065 return;
4068 array_free(FC_CVARRAY, pStubMsg, pMemory, pFormat,
4069 TRUE /* fHasPointers */);
4073 /***********************************************************************
4074 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
4076 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
4077 unsigned char* pMemory, PFORMAT_STRING pFormat )
4079 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4081 if (pFormat[0] != FC_CVARRAY)
4083 ERR("invalid format type %x\n", pFormat[0]);
4084 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4085 return;
4088 array_compute_and_size_conformance(FC_CVARRAY, pStubMsg, pMemory,
4089 pFormat);
4090 array_buffer_size(FC_CVARRAY, pStubMsg, pMemory, pFormat,
4091 TRUE /* fHasPointers */);
4095 /***********************************************************************
4096 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
4098 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
4099 PFORMAT_STRING pFormat )
4101 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4103 if (pFormat[0] != FC_CVARRAY)
4105 ERR("invalid format type %x\n", pFormat[0]);
4106 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4107 return pStubMsg->MemorySize;
4110 array_read_conformance(FC_CVARRAY, pStubMsg, pFormat);
4111 array_memory_size(FC_CVARRAY, pStubMsg, pFormat,
4112 TRUE /* fHasPointers */);
4114 return pStubMsg->MemorySize;
4118 /***********************************************************************
4119 * NdrComplexArrayMarshall [RPCRT4.@]
4121 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4122 unsigned char *pMemory,
4123 PFORMAT_STRING pFormat)
4125 BOOL pointer_buffer_mark_set = FALSE;
4127 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4129 if (pFormat[0] != FC_BOGUS_ARRAY)
4131 ERR("invalid format type %x\n", pFormat[0]);
4132 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4133 return NULL;
4136 if (!pStubMsg->PointerBufferMark)
4138 /* save buffer fields that may be changed by buffer sizer functions
4139 * and that may be needed later on */
4140 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4141 ULONG saved_buffer_length = pStubMsg->BufferLength;
4142 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4143 ULONG saved_offset = pStubMsg->Offset;
4144 ULONG saved_actual_count = pStubMsg->ActualCount;
4146 /* get the buffer pointer after complex array data, but before
4147 * pointer data */
4148 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
4149 pStubMsg->IgnoreEmbeddedPointers = 1;
4150 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4151 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4153 /* save it for use by embedded pointer code later */
4154 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
4155 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
4156 pointer_buffer_mark_set = TRUE;
4158 /* restore fields */
4159 pStubMsg->ActualCount = saved_actual_count;
4160 pStubMsg->Offset = saved_offset;
4161 pStubMsg->MaxCount = saved_max_count;
4162 pStubMsg->BufferLength = saved_buffer_length;
4165 array_compute_and_write_conformance(FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat);
4166 array_write_variance_and_marshall(FC_BOGUS_ARRAY, pStubMsg,
4167 pMemory, pFormat, TRUE /* fHasPointers */);
4169 STD_OVERFLOW_CHECK(pStubMsg);
4171 if (pointer_buffer_mark_set)
4173 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4174 pStubMsg->PointerBufferMark = NULL;
4177 return NULL;
4180 /***********************************************************************
4181 * NdrComplexArrayUnmarshall [RPCRT4.@]
4183 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4184 unsigned char **ppMemory,
4185 PFORMAT_STRING pFormat,
4186 unsigned char fMustAlloc)
4188 unsigned char *saved_buffer;
4189 BOOL pointer_buffer_mark_set = FALSE;
4190 int saved_ignore_embedded;
4192 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4194 if (pFormat[0] != FC_BOGUS_ARRAY)
4196 ERR("invalid format type %x\n", pFormat[0]);
4197 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4198 return NULL;
4201 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4202 /* save buffer pointer */
4203 saved_buffer = pStubMsg->Buffer;
4204 /* get the buffer pointer after complex array data, but before
4205 * pointer data */
4206 pStubMsg->IgnoreEmbeddedPointers = 1;
4207 pStubMsg->MemorySize = 0;
4208 NdrComplexArrayMemorySize(pStubMsg, pFormat);
4209 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4211 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer));
4212 if (!pStubMsg->PointerBufferMark)
4214 /* save it for use by embedded pointer code later */
4215 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4216 pointer_buffer_mark_set = TRUE;
4218 /* restore the original buffer */
4219 pStubMsg->Buffer = saved_buffer;
4221 array_read_conformance(FC_BOGUS_ARRAY, pStubMsg, pFormat);
4222 array_read_variance_and_unmarshall(FC_BOGUS_ARRAY, pStubMsg, ppMemory, pFormat, fMustAlloc,
4223 TRUE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */);
4225 if (pointer_buffer_mark_set)
4227 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4228 pStubMsg->PointerBufferMark = NULL;
4231 return NULL;
4234 /***********************************************************************
4235 * NdrComplexArrayBufferSize [RPCRT4.@]
4237 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4238 unsigned char *pMemory,
4239 PFORMAT_STRING pFormat)
4241 int pointer_length_set = 0;
4243 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4245 if (pFormat[0] != FC_BOGUS_ARRAY)
4247 ERR("invalid format type %x\n", pFormat[0]);
4248 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4249 return;
4252 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
4254 /* save buffer fields that may be changed by buffer sizer functions
4255 * and that may be needed later on */
4256 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4257 ULONG saved_buffer_length = pStubMsg->BufferLength;
4258 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4259 ULONG saved_offset = pStubMsg->Offset;
4260 ULONG saved_actual_count = pStubMsg->ActualCount;
4262 /* get the buffer pointer after complex array data, but before
4263 * pointer data */
4264 pStubMsg->IgnoreEmbeddedPointers = 1;
4265 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4266 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4268 /* save it for use by embedded pointer code later */
4269 pStubMsg->PointerLength = pStubMsg->BufferLength;
4270 pointer_length_set = 1;
4272 /* restore fields */
4273 pStubMsg->ActualCount = saved_actual_count;
4274 pStubMsg->Offset = saved_offset;
4275 pStubMsg->MaxCount = saved_max_count;
4276 pStubMsg->BufferLength = saved_buffer_length;
4279 array_compute_and_size_conformance(FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat);
4280 array_buffer_size(FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */);
4282 if(pointer_length_set)
4284 pStubMsg->BufferLength = pStubMsg->PointerLength;
4285 pStubMsg->PointerLength = 0;
4289 /***********************************************************************
4290 * NdrComplexArrayMemorySize [RPCRT4.@]
4292 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4293 PFORMAT_STRING pFormat)
4295 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4297 if (pFormat[0] != FC_BOGUS_ARRAY)
4299 ERR("invalid format type %x\n", pFormat[0]);
4300 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4301 return 0;
4304 array_read_conformance(FC_BOGUS_ARRAY, pStubMsg, pFormat);
4305 array_memory_size(FC_BOGUS_ARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
4306 return pStubMsg->MemorySize;
4309 /***********************************************************************
4310 * NdrComplexArrayFree [RPCRT4.@]
4312 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4313 unsigned char *pMemory,
4314 PFORMAT_STRING pFormat)
4316 ULONG i, count, def;
4318 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4320 if (pFormat[0] != FC_BOGUS_ARRAY)
4322 ERR("invalid format type %x\n", pFormat[0]);
4323 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4324 return;
4327 def = *(const WORD*)&pFormat[2];
4328 pFormat += 4;
4330 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4331 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4333 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4334 TRACE("variance = %d\n", pStubMsg->ActualCount);
4336 count = pStubMsg->ActualCount;
4337 for (i = 0; i < count; i++)
4338 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
4341 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
4342 USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
4343 USER_MARSHAL_CB *umcb)
4345 umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
4346 pStubMsg->RpcMsg->DataRepresentation);
4347 umcb->pStubMsg = pStubMsg;
4348 umcb->pReserve = NULL;
4349 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
4350 umcb->CBType = cbtype;
4351 umcb->pFormat = pFormat;
4352 umcb->pTypeFormat = NULL /* FIXME */;
4355 #define USER_MARSHAL_PTR_PREFIX \
4356 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
4357 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
4359 /***********************************************************************
4360 * NdrUserMarshalMarshall [RPCRT4.@]
4362 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4363 unsigned char *pMemory,
4364 PFORMAT_STRING pFormat)
4366 unsigned flags = pFormat[1];
4367 unsigned index = *(const WORD*)&pFormat[2];
4368 unsigned char *saved_buffer = NULL;
4369 USER_MARSHAL_CB umcb;
4371 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4372 TRACE("index=%d\n", index);
4374 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
4376 if (flags & USER_MARSHAL_POINTER)
4378 align_pointer_clear(&pStubMsg->Buffer, 4);
4379 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
4380 pStubMsg->Buffer += 4;
4381 if (pStubMsg->PointerBufferMark)
4383 saved_buffer = pStubMsg->Buffer;
4384 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4385 pStubMsg->PointerBufferMark = NULL;
4387 align_pointer_clear(&pStubMsg->Buffer, 8);
4389 else
4390 align_pointer_clear(&pStubMsg->Buffer, (flags & 0xf) + 1);
4392 pStubMsg->Buffer =
4393 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
4394 &umcb.Flags, pStubMsg->Buffer, pMemory);
4396 if (saved_buffer)
4398 STD_OVERFLOW_CHECK(pStubMsg);
4399 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4400 pStubMsg->Buffer = saved_buffer;
4403 STD_OVERFLOW_CHECK(pStubMsg);
4405 return NULL;
4408 /***********************************************************************
4409 * NdrUserMarshalUnmarshall [RPCRT4.@]
4411 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4412 unsigned char **ppMemory,
4413 PFORMAT_STRING pFormat,
4414 unsigned char fMustAlloc)
4416 unsigned flags = pFormat[1];
4417 unsigned index = *(const WORD*)&pFormat[2];
4418 DWORD memsize = *(const WORD*)&pFormat[4];
4419 unsigned char *saved_buffer = NULL;
4420 USER_MARSHAL_CB umcb;
4422 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4423 TRACE("index=%d\n", index);
4425 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
4427 if (flags & USER_MARSHAL_POINTER)
4429 align_pointer(&pStubMsg->Buffer, 4);
4430 /* skip pointer prefix */
4431 pStubMsg->Buffer += 4;
4432 if (pStubMsg->PointerBufferMark)
4434 saved_buffer = pStubMsg->Buffer;
4435 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4436 pStubMsg->PointerBufferMark = NULL;
4438 align_pointer(&pStubMsg->Buffer, 8);
4440 else
4441 align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1);
4443 if (!fMustAlloc && !*ppMemory)
4444 fMustAlloc = TRUE;
4445 if (fMustAlloc)
4447 *ppMemory = NdrAllocate(pStubMsg, memsize);
4448 memset(*ppMemory, 0, memsize);
4451 pStubMsg->Buffer =
4452 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
4453 &umcb.Flags, pStubMsg->Buffer, *ppMemory);
4455 if (saved_buffer)
4457 STD_OVERFLOW_CHECK(pStubMsg);
4458 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4459 pStubMsg->Buffer = saved_buffer;
4462 return NULL;
4465 /***********************************************************************
4466 * NdrUserMarshalBufferSize [RPCRT4.@]
4468 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4469 unsigned char *pMemory,
4470 PFORMAT_STRING pFormat)
4472 unsigned flags = pFormat[1];
4473 unsigned index = *(const WORD*)&pFormat[2];
4474 DWORD bufsize = *(const WORD*)&pFormat[6];
4475 USER_MARSHAL_CB umcb;
4476 ULONG saved_buffer_length = 0;
4478 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4479 TRACE("index=%d\n", index);
4481 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
4483 if (flags & USER_MARSHAL_POINTER)
4485 align_length(&pStubMsg->BufferLength, 4);
4486 /* skip pointer prefix */
4487 safe_buffer_length_increment(pStubMsg, 4);
4488 if (pStubMsg->IgnoreEmbeddedPointers)
4489 return;
4490 if (pStubMsg->PointerLength)
4492 saved_buffer_length = pStubMsg->BufferLength;
4493 pStubMsg->BufferLength = pStubMsg->PointerLength;
4494 pStubMsg->PointerLength = 0;
4496 align_length(&pStubMsg->BufferLength, 8);
4498 else
4499 align_length(&pStubMsg->BufferLength, (flags & 0xf) + 1);
4501 if (bufsize) {
4502 TRACE("size=%d\n", bufsize);
4503 safe_buffer_length_increment(pStubMsg, bufsize);
4505 else
4506 pStubMsg->BufferLength =
4507 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
4508 &umcb.Flags, pStubMsg->BufferLength, pMemory);
4510 if (saved_buffer_length)
4512 pStubMsg->PointerLength = pStubMsg->BufferLength;
4513 pStubMsg->BufferLength = saved_buffer_length;
4518 /***********************************************************************
4519 * NdrUserMarshalMemorySize [RPCRT4.@]
4521 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4522 PFORMAT_STRING pFormat)
4524 unsigned flags = pFormat[1];
4525 unsigned index = *(const WORD*)&pFormat[2];
4526 DWORD memsize = *(const WORD*)&pFormat[4];
4527 DWORD bufsize = *(const WORD*)&pFormat[6];
4529 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4530 TRACE("index=%d\n", index);
4532 pStubMsg->MemorySize += memsize;
4534 if (flags & USER_MARSHAL_POINTER)
4536 align_pointer(&pStubMsg->Buffer, 4);
4537 /* skip pointer prefix */
4538 pStubMsg->Buffer += 4;
4539 if (pStubMsg->IgnoreEmbeddedPointers)
4540 return pStubMsg->MemorySize;
4541 align_pointer(&pStubMsg->Buffer, 8);
4543 else
4544 align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1);
4546 if (!bufsize)
4547 FIXME("not implemented for varying buffer size\n");
4549 pStubMsg->Buffer += bufsize;
4551 return pStubMsg->MemorySize;
4554 /***********************************************************************
4555 * NdrUserMarshalFree [RPCRT4.@]
4557 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
4558 unsigned char *pMemory,
4559 PFORMAT_STRING pFormat)
4561 /* unsigned flags = pFormat[1]; */
4562 unsigned index = *(const WORD*)&pFormat[2];
4563 USER_MARSHAL_CB umcb;
4565 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4566 TRACE("index=%d\n", index);
4568 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
4570 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
4571 &umcb.Flags, pMemory);
4574 /***********************************************************************
4575 * NdrGetUserMarshalInfo [RPCRT4.@]
4577 RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi)
4579 USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags);
4581 TRACE("(%p,%u,%p)\n", flags, level, umi);
4583 if (level != 1)
4584 return RPC_S_INVALID_ARG;
4586 memset(&umi->u1.Level1, 0, sizeof(umi->u1.Level1));
4587 umi->InformationLevel = level;
4589 if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE)
4590 return RPC_S_INVALID_ARG;
4592 umi->u1.Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate;
4593 umi->u1.Level1.pfnFree = umcb->pStubMsg->pfnFree;
4594 umi->u1.Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer;
4596 switch (umcb->CBType)
4598 case USER_MARSHAL_CB_MARSHALL:
4599 case USER_MARSHAL_CB_UNMARSHALL:
4601 RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg;
4602 unsigned char *buffer_start = msg->Buffer;
4603 unsigned char *buffer_end =
4604 (unsigned char *)msg->Buffer + msg->BufferLength;
4606 if (umcb->pStubMsg->Buffer < buffer_start ||
4607 umcb->pStubMsg->Buffer > buffer_end)
4608 return RPC_X_INVALID_BUFFER;
4610 umi->u1.Level1.Buffer = umcb->pStubMsg->Buffer;
4611 umi->u1.Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer;
4612 break;
4614 case USER_MARSHAL_CB_BUFFER_SIZE:
4615 case USER_MARSHAL_CB_FREE:
4616 break;
4617 default:
4618 WARN("unrecognised CBType %d\n", umcb->CBType);
4621 return RPC_S_OK;
4624 /***********************************************************************
4625 * NdrClearOutParameters [RPCRT4.@]
4627 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
4628 PFORMAT_STRING pFormat,
4629 void *ArgAddr)
4631 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
4634 /***********************************************************************
4635 * NdrConvert [RPCRT4.@]
4637 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
4639 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
4640 /* FIXME: since this stub doesn't do any converting, the proper behavior
4641 is to raise an exception */
4644 /***********************************************************************
4645 * NdrConvert2 [RPCRT4.@]
4647 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
4649 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
4650 pStubMsg, pFormat, NumberParams);
4651 /* FIXME: since this stub doesn't do any converting, the proper behavior
4652 is to raise an exception */
4655 #include "pshpack1.h"
4656 typedef struct _NDR_CSTRUCT_FORMAT
4658 unsigned char type;
4659 unsigned char alignment;
4660 unsigned short memory_size;
4661 short offset_to_array_description;
4662 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
4663 #include "poppack.h"
4665 /***********************************************************************
4666 * NdrConformantStructMarshall [RPCRT4.@]
4668 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4669 unsigned char *pMemory,
4670 PFORMAT_STRING pFormat)
4672 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4673 PFORMAT_STRING pCArrayFormat;
4674 ULONG esize, bufsize;
4676 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4678 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4679 if ((pCStructFormat->type != FC_CPSTRUCT) && (pCStructFormat->type != FC_CSTRUCT))
4681 ERR("invalid format type %x\n", pCStructFormat->type);
4682 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4683 return NULL;
4686 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4687 pCStructFormat->offset_to_array_description;
4688 if (*pCArrayFormat != FC_CARRAY)
4690 ERR("invalid array format type %x\n", pCStructFormat->type);
4691 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4692 return NULL;
4694 esize = *(const WORD*)(pCArrayFormat+2);
4696 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4697 pCArrayFormat + 4, 0);
4699 WriteConformance(pStubMsg);
4701 align_pointer_clear(&pStubMsg->Buffer, pCStructFormat->alignment + 1);
4703 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4705 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4706 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4708 ERR("integer overflow of memory_size %u with bufsize %u\n",
4709 pCStructFormat->memory_size, bufsize);
4710 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4712 /* copy constant sized part of struct */
4713 pStubMsg->BufferMark = pStubMsg->Buffer;
4714 safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
4716 if (pCStructFormat->type == FC_CPSTRUCT)
4717 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4719 return NULL;
4722 /***********************************************************************
4723 * NdrConformantStructUnmarshall [RPCRT4.@]
4725 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4726 unsigned char **ppMemory,
4727 PFORMAT_STRING pFormat,
4728 unsigned char fMustAlloc)
4730 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4731 PFORMAT_STRING pCArrayFormat;
4732 ULONG esize, bufsize;
4733 unsigned char *saved_buffer;
4735 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4737 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4738 if ((pCStructFormat->type != FC_CPSTRUCT) && (pCStructFormat->type != FC_CSTRUCT))
4740 ERR("invalid format type %x\n", pCStructFormat->type);
4741 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4742 return NULL;
4744 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4745 pCStructFormat->offset_to_array_description;
4746 if (*pCArrayFormat != FC_CARRAY)
4748 ERR("invalid array format type %x\n", pCStructFormat->type);
4749 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4750 return NULL;
4752 esize = *(const WORD*)(pCArrayFormat+2);
4754 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
4756 align_pointer(&pStubMsg->Buffer, pCStructFormat->alignment + 1);
4758 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4760 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4761 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4763 ERR("integer overflow of memory_size %u with bufsize %u\n",
4764 pCStructFormat->memory_size, bufsize);
4765 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4768 if (fMustAlloc)
4770 SIZE_T size = pCStructFormat->memory_size + bufsize;
4771 *ppMemory = NdrAllocate(pStubMsg, size);
4773 else
4775 if (!pStubMsg->IsClient && !*ppMemory)
4776 /* for servers, we just point straight into the RPC buffer */
4777 *ppMemory = pStubMsg->Buffer;
4780 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4781 safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
4782 if (pCStructFormat->type == FC_CPSTRUCT)
4783 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4785 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4786 if (*ppMemory != saved_buffer)
4787 memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
4789 return NULL;
4792 /***********************************************************************
4793 * NdrConformantStructBufferSize [RPCRT4.@]
4795 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4796 unsigned char *pMemory,
4797 PFORMAT_STRING pFormat)
4799 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4800 PFORMAT_STRING pCArrayFormat;
4801 ULONG esize;
4803 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4805 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4806 if ((pCStructFormat->type != FC_CPSTRUCT) && (pCStructFormat->type != FC_CSTRUCT))
4808 ERR("invalid format type %x\n", pCStructFormat->type);
4809 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4810 return;
4812 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4813 pCStructFormat->offset_to_array_description;
4814 if (*pCArrayFormat != FC_CARRAY)
4816 ERR("invalid array format type %x\n", pCStructFormat->type);
4817 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4818 return;
4820 esize = *(const WORD*)(pCArrayFormat+2);
4822 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
4823 SizeConformance(pStubMsg);
4825 align_length(&pStubMsg->BufferLength, pCStructFormat->alignment + 1);
4827 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4829 safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
4830 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4832 if (pCStructFormat->type == FC_CPSTRUCT)
4833 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4836 /***********************************************************************
4837 * NdrConformantStructMemorySize [RPCRT4.@]
4839 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4840 PFORMAT_STRING pFormat)
4842 FIXME("stub\n");
4843 return 0;
4846 /***********************************************************************
4847 * NdrConformantStructFree [RPCRT4.@]
4849 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4850 unsigned char *pMemory,
4851 PFORMAT_STRING pFormat)
4853 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4854 PFORMAT_STRING pCArrayFormat;
4856 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4858 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4859 if ((pCStructFormat->type != FC_CPSTRUCT) && (pCStructFormat->type != FC_CSTRUCT))
4861 ERR("invalid format type %x\n", pCStructFormat->type);
4862 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4863 return;
4866 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4867 pCStructFormat->offset_to_array_description;
4868 if (*pCArrayFormat != FC_CARRAY)
4870 ERR("invalid array format type %x\n", pCStructFormat->type);
4871 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4872 return;
4875 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4876 pCArrayFormat + 4, 0);
4878 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4880 /* copy constant sized part of struct */
4881 pStubMsg->BufferMark = pStubMsg->Buffer;
4883 if (pCStructFormat->type == FC_CPSTRUCT)
4884 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4887 /***********************************************************************
4888 * NdrConformantVaryingStructMarshall [RPCRT4.@]
4890 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4891 unsigned char *pMemory,
4892 PFORMAT_STRING pFormat)
4894 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4895 PFORMAT_STRING pCVArrayFormat;
4897 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4899 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4900 if (pCVStructFormat->type != FC_CVSTRUCT)
4902 ERR("invalid format type %x\n", pCVStructFormat->type);
4903 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4904 return NULL;
4907 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4908 pCVStructFormat->offset_to_array_description;
4910 array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg,
4911 pMemory + pCVStructFormat->memory_size,
4912 pCVArrayFormat);
4914 align_pointer_clear(&pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4916 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4918 /* write constant sized part */
4919 pStubMsg->BufferMark = pStubMsg->Buffer;
4920 safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
4922 array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg,
4923 pMemory + pCVStructFormat->memory_size,
4924 pCVArrayFormat, FALSE /* fHasPointers */);
4926 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4928 return NULL;
4931 /***********************************************************************
4932 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
4934 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4935 unsigned char **ppMemory,
4936 PFORMAT_STRING pFormat,
4937 unsigned char fMustAlloc)
4939 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4940 PFORMAT_STRING pCVArrayFormat;
4941 ULONG memsize, bufsize;
4942 unsigned char *saved_buffer, *saved_array_buffer;
4943 ULONG offset;
4944 unsigned char *array_memory;
4946 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4948 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4949 if (pCVStructFormat->type != FC_CVSTRUCT)
4951 ERR("invalid format type %x\n", pCVStructFormat->type);
4952 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4953 return NULL;
4956 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4957 pCVStructFormat->offset_to_array_description;
4959 memsize = array_read_conformance(*pCVArrayFormat, pStubMsg,
4960 pCVArrayFormat);
4962 align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4964 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4966 /* work out how much memory to allocate if we need to do so */
4967 if (!fMustAlloc && !*ppMemory)
4968 fMustAlloc = TRUE;
4969 if (fMustAlloc)
4971 SIZE_T size = pCVStructFormat->memory_size + memsize;
4972 *ppMemory = NdrAllocate(pStubMsg, size);
4975 /* mark the start of the constant data */
4976 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4977 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4979 array_memory = *ppMemory + pCVStructFormat->memory_size;
4980 bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg,
4981 &array_memory, pCVArrayFormat,
4982 FALSE /* fMustAlloc */,
4983 FALSE /* fUseServerBufferMemory */,
4984 FALSE /* fUnmarshall */);
4986 /* save offset in case unmarshalling pointers changes it */
4987 offset = pStubMsg->Offset;
4989 /* mark the start of the array data */
4990 saved_array_buffer = pStubMsg->Buffer;
4991 safe_buffer_increment(pStubMsg, bufsize);
4993 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4995 /* copy the constant data */
4996 memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size);
4997 /* copy the array data */
4998 TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size);
4999 memcpy(*ppMemory + pCVStructFormat->memory_size + offset,
5000 saved_array_buffer, bufsize);
5002 if (*pCVArrayFormat == FC_C_CSTRING)
5003 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
5004 else if (*pCVArrayFormat == FC_C_WSTRING)
5005 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
5007 return NULL;
5010 /***********************************************************************
5011 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
5013 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5014 unsigned char *pMemory,
5015 PFORMAT_STRING pFormat)
5017 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
5018 PFORMAT_STRING pCVArrayFormat;
5020 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5022 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
5023 if (pCVStructFormat->type != FC_CVSTRUCT)
5025 ERR("invalid format type %x\n", pCVStructFormat->type);
5026 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5027 return;
5030 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
5031 pCVStructFormat->offset_to_array_description;
5032 array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg,
5033 pMemory + pCVStructFormat->memory_size,
5034 pCVArrayFormat);
5036 align_length(&pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
5038 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
5040 safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
5042 array_buffer_size(*pCVArrayFormat, pStubMsg,
5043 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
5044 FALSE /* fHasPointers */);
5046 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5049 /***********************************************************************
5050 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
5052 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5053 PFORMAT_STRING pFormat)
5055 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
5056 PFORMAT_STRING pCVArrayFormat;
5058 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5060 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
5061 if (pCVStructFormat->type != FC_CVSTRUCT)
5063 ERR("invalid format type %x\n", pCVStructFormat->type);
5064 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5065 return 0;
5068 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
5069 pCVStructFormat->offset_to_array_description;
5070 array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat);
5072 align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1);
5074 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
5076 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
5077 array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat,
5078 FALSE /* fHasPointers */);
5080 pStubMsg->MemorySize += pCVStructFormat->memory_size;
5082 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5084 return pStubMsg->MemorySize;
5087 /***********************************************************************
5088 * NdrConformantVaryingStructFree [RPCRT4.@]
5090 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
5091 unsigned char *pMemory,
5092 PFORMAT_STRING pFormat)
5094 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
5095 PFORMAT_STRING pCVArrayFormat;
5097 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5099 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
5100 if (pCVStructFormat->type != FC_CVSTRUCT)
5102 ERR("invalid format type %x\n", pCVStructFormat->type);
5103 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5104 return;
5107 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
5108 pCVStructFormat->offset_to_array_description;
5109 array_free(*pCVArrayFormat, pStubMsg,
5110 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
5111 FALSE /* fHasPointers */);
5113 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
5115 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5118 #include "pshpack1.h"
5119 typedef struct
5121 unsigned char type;
5122 unsigned char alignment;
5123 unsigned short total_size;
5124 } NDR_SMFARRAY_FORMAT;
5126 typedef struct
5128 unsigned char type;
5129 unsigned char alignment;
5130 ULONG total_size;
5131 } NDR_LGFARRAY_FORMAT;
5132 #include "poppack.h"
5134 /***********************************************************************
5135 * NdrFixedArrayMarshall [RPCRT4.@]
5137 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5138 unsigned char *pMemory,
5139 PFORMAT_STRING pFormat)
5141 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5142 ULONG total_size;
5144 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5146 if ((pSmFArrayFormat->type != FC_SMFARRAY) &&
5147 (pSmFArrayFormat->type != FC_LGFARRAY))
5149 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5150 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5151 return NULL;
5154 align_pointer_clear(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5156 if (pSmFArrayFormat->type == FC_SMFARRAY)
5158 total_size = pSmFArrayFormat->total_size;
5159 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5161 else
5163 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5164 total_size = pLgFArrayFormat->total_size;
5165 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5168 pStubMsg->BufferMark = pStubMsg->Buffer;
5169 safe_copy_to_buffer(pStubMsg, pMemory, total_size);
5171 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5173 return NULL;
5176 /***********************************************************************
5177 * NdrFixedArrayUnmarshall [RPCRT4.@]
5179 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5180 unsigned char **ppMemory,
5181 PFORMAT_STRING pFormat,
5182 unsigned char fMustAlloc)
5184 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5185 ULONG total_size;
5186 unsigned char *saved_buffer;
5188 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5190 if ((pSmFArrayFormat->type != FC_SMFARRAY) &&
5191 (pSmFArrayFormat->type != FC_LGFARRAY))
5193 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5194 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5195 return NULL;
5198 align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5200 if (pSmFArrayFormat->type == FC_SMFARRAY)
5202 total_size = pSmFArrayFormat->total_size;
5203 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5205 else
5207 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5208 total_size = pLgFArrayFormat->total_size;
5209 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5212 if (fMustAlloc)
5213 *ppMemory = NdrAllocate(pStubMsg, total_size);
5214 else
5216 if (!pStubMsg->IsClient && !*ppMemory)
5217 /* for servers, we just point straight into the RPC buffer */
5218 *ppMemory = pStubMsg->Buffer;
5221 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5222 safe_buffer_increment(pStubMsg, total_size);
5223 pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5225 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
5226 if (*ppMemory != saved_buffer)
5227 memcpy(*ppMemory, saved_buffer, total_size);
5229 return NULL;
5232 /***********************************************************************
5233 * NdrFixedArrayBufferSize [RPCRT4.@]
5235 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5236 unsigned char *pMemory,
5237 PFORMAT_STRING pFormat)
5239 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5240 ULONG total_size;
5242 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5244 if ((pSmFArrayFormat->type != FC_SMFARRAY) &&
5245 (pSmFArrayFormat->type != FC_LGFARRAY))
5247 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5248 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5249 return;
5252 align_length(&pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
5254 if (pSmFArrayFormat->type == FC_SMFARRAY)
5256 total_size = pSmFArrayFormat->total_size;
5257 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5259 else
5261 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5262 total_size = pLgFArrayFormat->total_size;
5263 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5265 safe_buffer_length_increment(pStubMsg, total_size);
5267 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5270 /***********************************************************************
5271 * NdrFixedArrayMemorySize [RPCRT4.@]
5273 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5274 PFORMAT_STRING pFormat)
5276 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5277 ULONG total_size;
5279 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5281 if ((pSmFArrayFormat->type != FC_SMFARRAY) &&
5282 (pSmFArrayFormat->type != FC_LGFARRAY))
5284 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5285 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5286 return 0;
5289 align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5291 if (pSmFArrayFormat->type == FC_SMFARRAY)
5293 total_size = pSmFArrayFormat->total_size;
5294 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5296 else
5298 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5299 total_size = pLgFArrayFormat->total_size;
5300 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5302 pStubMsg->BufferMark = pStubMsg->Buffer;
5303 safe_buffer_increment(pStubMsg, total_size);
5304 pStubMsg->MemorySize += total_size;
5306 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5308 return total_size;
5311 /***********************************************************************
5312 * NdrFixedArrayFree [RPCRT4.@]
5314 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5315 unsigned char *pMemory,
5316 PFORMAT_STRING pFormat)
5318 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5320 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5322 if ((pSmFArrayFormat->type != FC_SMFARRAY) &&
5323 (pSmFArrayFormat->type != FC_LGFARRAY))
5325 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5326 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5327 return;
5330 if (pSmFArrayFormat->type == FC_SMFARRAY)
5331 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5332 else
5334 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5335 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5338 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5341 /***********************************************************************
5342 * NdrVaryingArrayMarshall [RPCRT4.@]
5344 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5345 unsigned char *pMemory,
5346 PFORMAT_STRING pFormat)
5348 unsigned char alignment;
5349 DWORD elements, esize;
5350 ULONG bufsize;
5352 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5354 if ((pFormat[0] != FC_SMVARRAY) &&
5355 (pFormat[0] != FC_LGVARRAY))
5357 ERR("invalid format type %x\n", pFormat[0]);
5358 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5359 return NULL;
5362 alignment = pFormat[1] + 1;
5364 if (pFormat[0] == FC_SMVARRAY)
5366 pFormat += 2;
5367 pFormat += sizeof(WORD);
5368 elements = *(const WORD*)pFormat;
5369 pFormat += sizeof(WORD);
5371 else
5373 pFormat += 2;
5374 pFormat += sizeof(DWORD);
5375 elements = *(const DWORD*)pFormat;
5376 pFormat += sizeof(DWORD);
5379 esize = *(const WORD*)pFormat;
5380 pFormat += sizeof(WORD);
5382 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5383 if ((pStubMsg->ActualCount > elements) ||
5384 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5386 RpcRaiseException(RPC_S_INVALID_BOUND);
5387 return NULL;
5390 WriteVariance(pStubMsg);
5392 align_pointer_clear(&pStubMsg->Buffer, alignment);
5394 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5395 pStubMsg->BufferMark = pStubMsg->Buffer;
5396 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
5398 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5400 return NULL;
5403 /***********************************************************************
5404 * NdrVaryingArrayUnmarshall [RPCRT4.@]
5406 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5407 unsigned char **ppMemory,
5408 PFORMAT_STRING pFormat,
5409 unsigned char fMustAlloc)
5411 unsigned char alignment;
5412 DWORD size, elements, esize;
5413 ULONG bufsize;
5414 unsigned char *saved_buffer;
5415 ULONG offset;
5417 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5419 if ((pFormat[0] != FC_SMVARRAY) &&
5420 (pFormat[0] != FC_LGVARRAY))
5422 ERR("invalid format type %x\n", pFormat[0]);
5423 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5424 return NULL;
5427 alignment = pFormat[1] + 1;
5429 if (pFormat[0] == FC_SMVARRAY)
5431 pFormat += 2;
5432 size = *(const WORD*)pFormat;
5433 pFormat += sizeof(WORD);
5434 elements = *(const WORD*)pFormat;
5435 pFormat += sizeof(WORD);
5437 else
5439 pFormat += 2;
5440 size = *(const DWORD*)pFormat;
5441 pFormat += sizeof(DWORD);
5442 elements = *(const DWORD*)pFormat;
5443 pFormat += sizeof(DWORD);
5446 esize = *(const WORD*)pFormat;
5447 pFormat += sizeof(WORD);
5449 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5451 align_pointer(&pStubMsg->Buffer, alignment);
5453 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5454 offset = pStubMsg->Offset;
5456 if (!fMustAlloc && !*ppMemory)
5457 fMustAlloc = TRUE;
5458 if (fMustAlloc)
5459 *ppMemory = NdrAllocate(pStubMsg, size);
5460 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5461 safe_buffer_increment(pStubMsg, bufsize);
5463 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5465 memcpy(*ppMemory + offset, saved_buffer, bufsize);
5467 return NULL;
5470 /***********************************************************************
5471 * NdrVaryingArrayBufferSize [RPCRT4.@]
5473 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5474 unsigned char *pMemory,
5475 PFORMAT_STRING pFormat)
5477 unsigned char alignment;
5478 DWORD elements, esize;
5480 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5482 if ((pFormat[0] != FC_SMVARRAY) &&
5483 (pFormat[0] != FC_LGVARRAY))
5485 ERR("invalid format type %x\n", pFormat[0]);
5486 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5487 return;
5490 alignment = pFormat[1] + 1;
5492 if (pFormat[0] == FC_SMVARRAY)
5494 pFormat += 2;
5495 pFormat += sizeof(WORD);
5496 elements = *(const WORD*)pFormat;
5497 pFormat += sizeof(WORD);
5499 else
5501 pFormat += 2;
5502 pFormat += sizeof(DWORD);
5503 elements = *(const DWORD*)pFormat;
5504 pFormat += sizeof(DWORD);
5507 esize = *(const WORD*)pFormat;
5508 pFormat += sizeof(WORD);
5510 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5511 if ((pStubMsg->ActualCount > elements) ||
5512 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5514 RpcRaiseException(RPC_S_INVALID_BOUND);
5515 return;
5518 SizeVariance(pStubMsg);
5520 align_length(&pStubMsg->BufferLength, alignment);
5522 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5524 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5527 /***********************************************************************
5528 * NdrVaryingArrayMemorySize [RPCRT4.@]
5530 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5531 PFORMAT_STRING pFormat)
5533 unsigned char alignment;
5534 DWORD size, elements, esize;
5536 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5538 if ((pFormat[0] != FC_SMVARRAY) &&
5539 (pFormat[0] != FC_LGVARRAY))
5541 ERR("invalid format type %x\n", pFormat[0]);
5542 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5543 return 0;
5546 alignment = pFormat[1] + 1;
5548 if (pFormat[0] == FC_SMVARRAY)
5550 pFormat += 2;
5551 size = *(const WORD*)pFormat;
5552 pFormat += sizeof(WORD);
5553 elements = *(const WORD*)pFormat;
5554 pFormat += sizeof(WORD);
5556 else
5558 pFormat += 2;
5559 size = *(const DWORD*)pFormat;
5560 pFormat += sizeof(DWORD);
5561 elements = *(const DWORD*)pFormat;
5562 pFormat += sizeof(DWORD);
5565 esize = *(const WORD*)pFormat;
5566 pFormat += sizeof(WORD);
5568 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5570 align_pointer(&pStubMsg->Buffer, alignment);
5572 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5573 pStubMsg->MemorySize += size;
5575 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5577 return pStubMsg->MemorySize;
5580 /***********************************************************************
5581 * NdrVaryingArrayFree [RPCRT4.@]
5583 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5584 unsigned char *pMemory,
5585 PFORMAT_STRING pFormat)
5587 DWORD elements;
5589 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5591 if ((pFormat[0] != FC_SMVARRAY) &&
5592 (pFormat[0] != FC_LGVARRAY))
5594 ERR("invalid format type %x\n", pFormat[0]);
5595 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5596 return;
5599 if (pFormat[0] == FC_SMVARRAY)
5601 pFormat += 2;
5602 pFormat += sizeof(WORD);
5603 elements = *(const WORD*)pFormat;
5604 pFormat += sizeof(WORD);
5606 else
5608 pFormat += 2;
5609 pFormat += sizeof(DWORD);
5610 elements = *(const DWORD*)pFormat;
5611 pFormat += sizeof(DWORD);
5614 pFormat += sizeof(WORD);
5616 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5617 if ((pStubMsg->ActualCount > elements) ||
5618 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5620 RpcRaiseException(RPC_S_INVALID_BOUND);
5621 return;
5624 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5627 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
5629 switch (fc)
5631 case FC_BYTE:
5632 case FC_CHAR:
5633 case FC_SMALL:
5634 case FC_USMALL:
5635 return *pMemory;
5636 case FC_WCHAR:
5637 case FC_SHORT:
5638 case FC_USHORT:
5639 case FC_ENUM16:
5640 return *(const USHORT *)pMemory;
5641 case FC_LONG:
5642 case FC_ULONG:
5643 case FC_ENUM32:
5644 return *(const ULONG *)pMemory;
5645 case FC_INT3264:
5646 case FC_UINT3264:
5647 return *(const ULONG_PTR *)pMemory;
5648 default:
5649 FIXME("Unhandled base type: 0x%02x\n", fc);
5650 return 0;
5654 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
5655 ULONG discriminant,
5656 PFORMAT_STRING pFormat)
5658 unsigned short num_arms, arm, type;
5660 num_arms = *(const SHORT*)pFormat & 0x0fff;
5661 pFormat += 2;
5662 for(arm = 0; arm < num_arms; arm++)
5664 if(discriminant == *(const ULONG*)pFormat)
5666 pFormat += 4;
5667 break;
5669 pFormat += 6;
5672 type = *(const unsigned short*)pFormat;
5673 TRACE("type %04x\n", type);
5674 if(arm == num_arms) /* default arm extras */
5676 if(type == 0xffff)
5678 ERR("no arm for 0x%x and no default case\n", discriminant);
5679 RpcRaiseException(RPC_S_INVALID_TAG);
5680 return NULL;
5682 if(type == 0)
5684 TRACE("falling back to empty default case for 0x%x\n", discriminant);
5685 return NULL;
5688 return pFormat;
5691 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
5693 unsigned short type;
5695 pFormat += 2;
5697 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5698 if(!pFormat)
5699 return NULL;
5701 type = *(const unsigned short*)pFormat;
5702 if((type & 0xff00) == 0x8000)
5704 unsigned char basetype = LOBYTE(type);
5705 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
5707 else
5709 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5710 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
5711 if (m)
5713 unsigned char *saved_buffer = NULL;
5714 BOOL pointer_buffer_mark_set = FALSE;
5715 switch(*desc)
5717 case FC_RP:
5718 case FC_UP:
5719 case FC_OP:
5720 case FC_FP:
5721 align_pointer_clear(&pStubMsg->Buffer, 4);
5722 saved_buffer = pStubMsg->Buffer;
5723 if (pStubMsg->PointerBufferMark)
5725 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5726 pStubMsg->PointerBufferMark = NULL;
5727 pointer_buffer_mark_set = TRUE;
5729 else
5730 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
5732 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
5733 if (pointer_buffer_mark_set)
5735 STD_OVERFLOW_CHECK(pStubMsg);
5736 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5737 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5739 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5740 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5741 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5743 pStubMsg->Buffer = saved_buffer + 4;
5745 break;
5746 case FC_IP:
5747 /* must be dereferenced first */
5748 m(pStubMsg, *(unsigned char **)pMemory, desc);
5749 break;
5750 default:
5751 m(pStubMsg, pMemory, desc);
5754 else if (*desc)
5755 FIXME("no marshaller for embedded type %02x\n", *desc);
5757 return NULL;
5760 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5761 unsigned char **ppMemory,
5762 ULONG discriminant,
5763 PFORMAT_STRING pFormat,
5764 unsigned char fMustAlloc)
5766 unsigned short type;
5768 pFormat += 2;
5770 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5771 if(!pFormat)
5772 return NULL;
5774 type = *(const unsigned short*)pFormat;
5775 if((type & 0xff00) == 0x8000)
5777 unsigned char basetype = LOBYTE(type);
5778 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
5780 else
5782 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5783 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
5784 if (m)
5786 unsigned char *saved_buffer = NULL;
5787 BOOL pointer_buffer_mark_set = FALSE;
5788 switch(*desc)
5790 case FC_RP:
5791 case FC_UP:
5792 case FC_OP:
5793 case FC_FP:
5794 align_pointer(&pStubMsg->Buffer, 4);
5795 saved_buffer = pStubMsg->Buffer;
5796 if (pStubMsg->PointerBufferMark)
5798 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5799 pStubMsg->PointerBufferMark = NULL;
5800 pointer_buffer_mark_set = TRUE;
5802 else
5803 pStubMsg->Buffer += 4; /* for pointer ID */
5805 if (saved_buffer + 4 > pStubMsg->BufferEnd)
5807 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5808 saved_buffer, pStubMsg->BufferEnd);
5809 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5812 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
5813 if (pointer_buffer_mark_set)
5815 STD_OVERFLOW_CHECK(pStubMsg);
5816 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5817 pStubMsg->Buffer = saved_buffer + 4;
5819 break;
5820 case FC_IP:
5821 /* must be dereferenced first */
5822 m(pStubMsg, *(unsigned char ***)ppMemory, desc, fMustAlloc);
5823 break;
5824 default:
5825 m(pStubMsg, ppMemory, desc, fMustAlloc);
5828 else if (*desc)
5829 FIXME("no marshaller for embedded type %02x\n", *desc);
5831 return NULL;
5834 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
5835 unsigned char *pMemory,
5836 ULONG discriminant,
5837 PFORMAT_STRING pFormat)
5839 unsigned short type;
5841 pFormat += 2;
5843 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5844 if(!pFormat)
5845 return;
5847 type = *(const unsigned short*)pFormat;
5848 if((type & 0xff00) == 0x8000)
5850 unsigned char basetype = LOBYTE(type);
5851 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
5853 else
5855 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5856 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
5857 if (m)
5859 switch(*desc)
5861 case FC_RP:
5862 case FC_UP:
5863 case FC_OP:
5864 case FC_FP:
5865 align_length(&pStubMsg->BufferLength, 4);
5866 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
5867 if (!pStubMsg->IgnoreEmbeddedPointers)
5869 int saved_buffer_length = pStubMsg->BufferLength;
5870 pStubMsg->BufferLength = pStubMsg->PointerLength;
5871 pStubMsg->PointerLength = 0;
5872 if(!pStubMsg->BufferLength)
5873 ERR("BufferLength == 0??\n");
5874 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
5875 pStubMsg->PointerLength = pStubMsg->BufferLength;
5876 pStubMsg->BufferLength = saved_buffer_length;
5878 break;
5879 case FC_IP:
5880 /* must be dereferenced first */
5881 m(pStubMsg, *(unsigned char **)pMemory, desc);
5882 break;
5883 default:
5884 m(pStubMsg, pMemory, desc);
5887 else if (*desc)
5888 FIXME("no buffersizer for embedded type %02x\n", *desc);
5892 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
5893 ULONG discriminant,
5894 PFORMAT_STRING pFormat)
5896 unsigned short type, size;
5898 size = *(const unsigned short*)pFormat;
5899 pStubMsg->Memory += size;
5900 pFormat += 2;
5902 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5903 if(!pFormat)
5904 return 0;
5906 type = *(const unsigned short*)pFormat;
5907 if((type & 0xff00) == 0x8000)
5909 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
5911 else
5913 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5914 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
5915 unsigned char *saved_buffer;
5916 if (m)
5918 switch(*desc)
5920 case FC_RP:
5921 case FC_UP:
5922 case FC_OP:
5923 case FC_FP:
5924 align_pointer(&pStubMsg->Buffer, 4);
5925 saved_buffer = pStubMsg->Buffer;
5926 safe_buffer_increment(pStubMsg, 4);
5927 align_length(&pStubMsg->MemorySize, sizeof(void *));
5928 pStubMsg->MemorySize += sizeof(void *);
5929 if (!pStubMsg->IgnoreEmbeddedPointers)
5930 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
5931 break;
5932 default:
5933 return m(pStubMsg, desc);
5936 else if (*desc)
5937 FIXME("no marshaller for embedded type %02x\n", *desc);
5940 TRACE("size %d\n", size);
5941 return size;
5944 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
5945 unsigned char *pMemory,
5946 ULONG discriminant,
5947 PFORMAT_STRING pFormat)
5949 unsigned short type;
5951 pFormat += 2;
5953 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5954 if(!pFormat)
5955 return;
5957 type = *(const unsigned short*)pFormat;
5958 if((type & 0xff00) != 0x8000)
5960 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5961 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5962 if (m)
5964 switch(*desc)
5966 case FC_RP:
5967 case FC_UP:
5968 case FC_OP:
5969 case FC_FP:
5970 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5971 break;
5972 case FC_IP:
5973 /* must be dereferenced first */
5974 m(pStubMsg, *(unsigned char **)pMemory, desc);
5975 break;
5976 default:
5977 m(pStubMsg, pMemory, desc);
5983 /***********************************************************************
5984 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
5986 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5987 unsigned char *pMemory,
5988 PFORMAT_STRING pFormat)
5990 unsigned char switch_type;
5991 unsigned char increment;
5992 ULONG switch_value;
5994 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5995 pFormat++;
5997 switch_type = *pFormat & 0xf;
5998 increment = (*pFormat & 0xf0) >> 4;
5999 pFormat++;
6001 align_pointer_clear(&pStubMsg->Buffer, increment);
6003 switch_value = get_discriminant(switch_type, pMemory);
6004 TRACE("got switch value 0x%x\n", switch_value);
6006 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
6007 pMemory += increment;
6009 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
6012 /***********************************************************************
6013 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
6015 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6016 unsigned char **ppMemory,
6017 PFORMAT_STRING pFormat,
6018 unsigned char fMustAlloc)
6020 unsigned char switch_type;
6021 unsigned char increment;
6022 ULONG switch_value;
6023 unsigned short size;
6024 unsigned char *pMemoryArm;
6026 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
6027 pFormat++;
6029 switch_type = *pFormat & 0xf;
6030 increment = (*pFormat & 0xf0) >> 4;
6031 pFormat++;
6033 align_pointer(&pStubMsg->Buffer, increment);
6034 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
6035 TRACE("got switch value 0x%x\n", switch_value);
6037 size = *(const unsigned short*)pFormat + increment;
6038 if (!fMustAlloc && !*ppMemory)
6039 fMustAlloc = TRUE;
6040 if (fMustAlloc)
6041 *ppMemory = NdrAllocate(pStubMsg, size);
6043 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6044 * since the arm is part of the memory block that is encompassed by
6045 * the whole union. Memory is forced to allocate when pointers
6046 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6047 * clearing the memory we pass in to the unmarshaller */
6048 if (fMustAlloc)
6049 memset(*ppMemory, 0, size);
6051 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
6052 pMemoryArm = *ppMemory + increment;
6054 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE);
6057 /***********************************************************************
6058 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
6060 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6061 unsigned char *pMemory,
6062 PFORMAT_STRING pFormat)
6064 unsigned char switch_type;
6065 unsigned char increment;
6066 ULONG switch_value;
6068 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6069 pFormat++;
6071 switch_type = *pFormat & 0xf;
6072 increment = (*pFormat & 0xf0) >> 4;
6073 pFormat++;
6075 align_length(&pStubMsg->BufferLength, increment);
6076 switch_value = get_discriminant(switch_type, pMemory);
6077 TRACE("got switch value 0x%x\n", switch_value);
6079 /* Add discriminant size */
6080 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
6081 pMemory += increment;
6083 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
6086 /***********************************************************************
6087 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
6089 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6090 PFORMAT_STRING pFormat)
6092 unsigned char switch_type;
6093 unsigned char increment;
6094 ULONG switch_value;
6096 switch_type = *pFormat & 0xf;
6097 increment = (*pFormat & 0xf0) >> 4;
6098 pFormat++;
6100 align_pointer(&pStubMsg->Buffer, increment);
6101 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
6102 TRACE("got switch value 0x%x\n", switch_value);
6104 pStubMsg->Memory += increment;
6106 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
6109 /***********************************************************************
6110 * NdrEncapsulatedUnionFree [RPCRT4.@]
6112 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6113 unsigned char *pMemory,
6114 PFORMAT_STRING pFormat)
6116 unsigned char switch_type;
6117 unsigned char increment;
6118 ULONG switch_value;
6120 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6121 pFormat++;
6123 switch_type = *pFormat & 0xf;
6124 increment = (*pFormat & 0xf0) >> 4;
6125 pFormat++;
6127 switch_value = get_discriminant(switch_type, pMemory);
6128 TRACE("got switch value 0x%x\n", switch_value);
6130 pMemory += increment;
6132 union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
6135 /***********************************************************************
6136 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
6138 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6139 unsigned char *pMemory,
6140 PFORMAT_STRING pFormat)
6142 unsigned char switch_type;
6144 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6145 pFormat++;
6147 switch_type = *pFormat;
6148 pFormat++;
6150 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6151 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6152 /* Marshall discriminant */
6153 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6155 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6158 static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
6159 PFORMAT_STRING *ppFormat)
6161 LONG discriminant = 0;
6163 switch(**ppFormat)
6165 case FC_BYTE:
6166 case FC_CHAR:
6167 case FC_SMALL:
6168 case FC_USMALL:
6170 UCHAR d;
6171 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6172 discriminant = d;
6173 break;
6175 case FC_WCHAR:
6176 case FC_SHORT:
6177 case FC_USHORT:
6178 case FC_ENUM16:
6180 USHORT d;
6181 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6182 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6183 discriminant = d;
6184 break;
6186 case FC_LONG:
6187 case FC_ULONG:
6189 ULONG d;
6190 align_pointer(&pStubMsg->Buffer, sizeof(ULONG));
6191 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6192 discriminant = d;
6193 break;
6195 default:
6196 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
6198 (*ppFormat)++;
6200 *ppFormat = SkipConformance(pStubMsg, *ppFormat);
6201 return discriminant;
6204 /**********************************************************************
6205 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
6207 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6208 unsigned char **ppMemory,
6209 PFORMAT_STRING pFormat,
6210 unsigned char fMustAlloc)
6212 LONG discriminant;
6213 unsigned short size;
6215 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
6216 pFormat++;
6218 /* Unmarshall discriminant */
6219 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6220 TRACE("unmarshalled discriminant %x\n", discriminant);
6222 pFormat += *(const SHORT*)pFormat;
6224 size = *(const unsigned short*)pFormat;
6226 if (!fMustAlloc && !*ppMemory)
6227 fMustAlloc = TRUE;
6228 if (fMustAlloc)
6229 *ppMemory = NdrAllocate(pStubMsg, size);
6231 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6232 * since the arm is part of the memory block that is encompassed by
6233 * the whole union. Memory is forced to allocate when pointers
6234 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6235 * clearing the memory we pass in to the unmarshaller */
6236 if (fMustAlloc)
6237 memset(*ppMemory, 0, size);
6239 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
6242 /***********************************************************************
6243 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
6245 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6246 unsigned char *pMemory,
6247 PFORMAT_STRING pFormat)
6249 unsigned char switch_type;
6251 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6252 pFormat++;
6254 switch_type = *pFormat;
6255 pFormat++;
6257 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6258 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6259 /* Add discriminant size */
6260 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6262 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6265 /***********************************************************************
6266 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
6268 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6269 PFORMAT_STRING pFormat)
6271 ULONG discriminant;
6273 pFormat++;
6274 /* Unmarshall discriminant */
6275 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6276 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
6278 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
6281 /***********************************************************************
6282 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
6284 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6285 unsigned char *pMemory,
6286 PFORMAT_STRING pFormat)
6288 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6289 pFormat++;
6290 pFormat++;
6292 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6293 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6295 union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6298 /***********************************************************************
6299 * NdrByteCountPointerMarshall [RPCRT4.@]
6301 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6302 unsigned char *pMemory,
6303 PFORMAT_STRING pFormat)
6305 FIXME("stub\n");
6306 return NULL;
6309 /***********************************************************************
6310 * NdrByteCountPointerUnmarshall [RPCRT4.@]
6312 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6313 unsigned char **ppMemory,
6314 PFORMAT_STRING pFormat,
6315 unsigned char fMustAlloc)
6317 FIXME("stub\n");
6318 return NULL;
6321 /***********************************************************************
6322 * NdrByteCountPointerBufferSize [RPCRT4.@]
6324 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6325 unsigned char *pMemory,
6326 PFORMAT_STRING pFormat)
6328 FIXME("stub\n");
6331 /***********************************************************************
6332 * NdrByteCountPointerMemorySize [internal]
6334 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6335 PFORMAT_STRING pFormat)
6337 FIXME("stub\n");
6338 return 0;
6341 /***********************************************************************
6342 * NdrByteCountPointerFree [RPCRT4.@]
6344 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
6345 unsigned char *pMemory,
6346 PFORMAT_STRING pFormat)
6348 FIXME("stub\n");
6351 /***********************************************************************
6352 * NdrXmitOrRepAsMarshall [RPCRT4.@]
6354 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6355 unsigned char *pMemory,
6356 PFORMAT_STRING pFormat)
6358 FIXME("stub\n");
6359 return NULL;
6362 /***********************************************************************
6363 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
6365 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6366 unsigned char **ppMemory,
6367 PFORMAT_STRING pFormat,
6368 unsigned char fMustAlloc)
6370 FIXME("stub\n");
6371 return NULL;
6374 /***********************************************************************
6375 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
6377 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6378 unsigned char *pMemory,
6379 PFORMAT_STRING pFormat)
6381 FIXME("stub\n");
6384 /***********************************************************************
6385 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
6387 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6388 PFORMAT_STRING pFormat)
6390 FIXME("stub\n");
6391 return 0;
6394 /***********************************************************************
6395 * NdrXmitOrRepAsFree [RPCRT4.@]
6397 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
6398 unsigned char *pMemory,
6399 PFORMAT_STRING pFormat)
6401 FIXME("stub\n");
6404 /***********************************************************************
6405 * NdrRangeMarshall [internal]
6407 static unsigned char *WINAPI NdrRangeMarshall(
6408 PMIDL_STUB_MESSAGE pStubMsg,
6409 unsigned char *pMemory,
6410 PFORMAT_STRING pFormat)
6412 const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6413 unsigned char base_type;
6415 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6417 if (pRange->type != FC_RANGE)
6419 ERR("invalid format type %x\n", pRange->type);
6420 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6421 return NULL;
6424 base_type = pRange->flags_type & 0xf;
6426 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
6429 /***********************************************************************
6430 * NdrRangeUnmarshall [RPCRT4.@]
6432 unsigned char *WINAPI NdrRangeUnmarshall(
6433 PMIDL_STUB_MESSAGE pStubMsg,
6434 unsigned char **ppMemory,
6435 PFORMAT_STRING pFormat,
6436 unsigned char fMustAlloc)
6438 const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6439 unsigned char base_type;
6441 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6443 if (pRange->type != FC_RANGE)
6445 ERR("invalid format type %x\n", pRange->type);
6446 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6447 return NULL;
6449 base_type = pRange->flags_type & 0xf;
6451 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
6452 base_type, pRange->low_value, pRange->high_value);
6454 #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
6455 do \
6457 align_pointer(&pStubMsg->Buffer, sizeof(wire_type)); \
6458 if (!fMustAlloc && !*ppMemory) \
6459 fMustAlloc = TRUE; \
6460 if (fMustAlloc) \
6461 *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
6462 if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
6464 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
6465 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
6466 RpcRaiseException(RPC_X_BAD_STUB_DATA); \
6468 if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
6469 (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
6471 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
6472 *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
6473 (mem_type)pRange->high_value); \
6474 RpcRaiseException(RPC_S_INVALID_BOUND); \
6475 return NULL; \
6477 TRACE("*ppMemory: %p\n", *ppMemory); \
6478 **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
6479 pStubMsg->Buffer += sizeof(wire_type); \
6480 } while (0)
6482 switch(base_type)
6484 case FC_CHAR:
6485 case FC_SMALL:
6486 RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
6487 TRACE("value: 0x%02x\n", **ppMemory);
6488 break;
6489 case FC_BYTE:
6490 case FC_USMALL:
6491 RANGE_UNMARSHALL(CHAR, CHAR, "%u");
6492 TRACE("value: 0x%02x\n", **ppMemory);
6493 break;
6494 case FC_WCHAR: /* FIXME: valid? */
6495 case FC_USHORT:
6496 RANGE_UNMARSHALL(USHORT, USHORT, "%u");
6497 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6498 break;
6499 case FC_SHORT:
6500 RANGE_UNMARSHALL(SHORT, SHORT, "%d");
6501 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6502 break;
6503 case FC_LONG:
6504 case FC_ENUM32:
6505 RANGE_UNMARSHALL(LONG, LONG, "%d");
6506 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6507 break;
6508 case FC_ULONG:
6509 RANGE_UNMARSHALL(ULONG, ULONG, "%u");
6510 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6511 break;
6512 case FC_ENUM16:
6513 RANGE_UNMARSHALL(UINT, USHORT, "%u");
6514 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6515 break;
6516 case FC_FLOAT:
6517 case FC_DOUBLE:
6518 case FC_HYPER:
6519 default:
6520 ERR("invalid range base type: 0x%02x\n", base_type);
6521 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6524 return NULL;
6527 /***********************************************************************
6528 * NdrRangeBufferSize [internal]
6530 static void WINAPI NdrRangeBufferSize(
6531 PMIDL_STUB_MESSAGE pStubMsg,
6532 unsigned char *pMemory,
6533 PFORMAT_STRING pFormat)
6535 const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6536 unsigned char base_type;
6538 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6540 if (pRange->type != FC_RANGE)
6542 ERR("invalid format type %x\n", pRange->type);
6543 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6545 base_type = pRange->flags_type & 0xf;
6547 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
6550 /***********************************************************************
6551 * NdrRangeMemorySize [internal]
6553 static ULONG WINAPI NdrRangeMemorySize(
6554 PMIDL_STUB_MESSAGE pStubMsg,
6555 PFORMAT_STRING pFormat)
6557 const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6558 unsigned char base_type;
6560 if (pRange->type != FC_RANGE)
6562 ERR("invalid format type %x\n", pRange->type);
6563 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6564 return 0;
6566 base_type = pRange->flags_type & 0xf;
6568 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
6571 /***********************************************************************
6572 * NdrRangeFree [internal]
6574 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
6575 unsigned char *pMemory,
6576 PFORMAT_STRING pFormat)
6578 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6580 /* nothing to do */
6583 /***********************************************************************
6584 * NdrBaseTypeMarshall [internal]
6586 static unsigned char *WINAPI NdrBaseTypeMarshall(
6587 PMIDL_STUB_MESSAGE pStubMsg,
6588 unsigned char *pMemory,
6589 PFORMAT_STRING pFormat)
6591 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6593 switch(*pFormat)
6595 case FC_BYTE:
6596 case FC_CHAR:
6597 case FC_SMALL:
6598 case FC_USMALL:
6599 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
6600 TRACE("value: 0x%02x\n", *pMemory);
6601 break;
6602 case FC_WCHAR:
6603 case FC_SHORT:
6604 case FC_USHORT:
6605 align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT));
6606 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
6607 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
6608 break;
6609 case FC_LONG:
6610 case FC_ULONG:
6611 case FC_ERROR_STATUS_T:
6612 case FC_ENUM32:
6613 align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONG));
6614 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
6615 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
6616 break;
6617 case FC_FLOAT:
6618 align_pointer_clear(&pStubMsg->Buffer, sizeof(float));
6619 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
6620 break;
6621 case FC_DOUBLE:
6622 align_pointer_clear(&pStubMsg->Buffer, sizeof(double));
6623 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
6624 break;
6625 case FC_HYPER:
6626 align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONGLONG));
6627 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
6628 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
6629 break;
6630 case FC_ENUM16:
6632 USHORT val = *(UINT *)pMemory;
6633 /* only 16-bits on the wire, so do a sanity check */
6634 if (*(UINT *)pMemory > SHRT_MAX)
6635 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
6636 align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT));
6637 safe_copy_to_buffer(pStubMsg, &val, sizeof(val));
6638 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
6639 break;
6641 case FC_INT3264:
6642 case FC_UINT3264:
6644 UINT val = *(UINT_PTR *)pMemory;
6645 align_pointer_clear(&pStubMsg->Buffer, sizeof(UINT));
6646 safe_copy_to_buffer(pStubMsg, &val, sizeof(val));
6647 break;
6649 case FC_IGNORE:
6650 break;
6651 default:
6652 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6655 /* FIXME: what is the correct return value? */
6656 return NULL;
6659 /***********************************************************************
6660 * NdrBaseTypeUnmarshall [internal]
6662 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
6663 PMIDL_STUB_MESSAGE pStubMsg,
6664 unsigned char **ppMemory,
6665 PFORMAT_STRING pFormat,
6666 unsigned char fMustAlloc)
6668 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6670 #define BASE_TYPE_UNMARSHALL(type) do { \
6671 align_pointer(&pStubMsg->Buffer, sizeof(type)); \
6672 if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
6674 *ppMemory = pStubMsg->Buffer; \
6675 TRACE("*ppMemory: %p\n", *ppMemory); \
6676 safe_buffer_increment(pStubMsg, sizeof(type)); \
6678 else \
6680 if (fMustAlloc) \
6681 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
6682 TRACE("*ppMemory: %p\n", *ppMemory); \
6683 safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \
6685 } while (0)
6687 switch(*pFormat)
6689 case FC_BYTE:
6690 case FC_CHAR:
6691 case FC_SMALL:
6692 case FC_USMALL:
6693 BASE_TYPE_UNMARSHALL(UCHAR);
6694 TRACE("value: 0x%02x\n", **ppMemory);
6695 break;
6696 case FC_WCHAR:
6697 case FC_SHORT:
6698 case FC_USHORT:
6699 BASE_TYPE_UNMARSHALL(USHORT);
6700 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6701 break;
6702 case FC_LONG:
6703 case FC_ULONG:
6704 case FC_ERROR_STATUS_T:
6705 case FC_ENUM32:
6706 BASE_TYPE_UNMARSHALL(ULONG);
6707 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6708 break;
6709 case FC_FLOAT:
6710 BASE_TYPE_UNMARSHALL(float);
6711 TRACE("value: %f\n", **(float **)ppMemory);
6712 break;
6713 case FC_DOUBLE:
6714 BASE_TYPE_UNMARSHALL(double);
6715 TRACE("value: %f\n", **(double **)ppMemory);
6716 break;
6717 case FC_HYPER:
6718 BASE_TYPE_UNMARSHALL(ULONGLONG);
6719 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
6720 break;
6721 case FC_ENUM16:
6723 USHORT val;
6724 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6725 if (!fMustAlloc && !*ppMemory)
6726 fMustAlloc = TRUE;
6727 if (fMustAlloc)
6728 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
6729 safe_copy_from_buffer(pStubMsg, &val, sizeof(USHORT));
6730 /* 16-bits on the wire, but int in memory */
6731 **(UINT **)ppMemory = val;
6732 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6733 break;
6735 case FC_INT3264:
6736 if (sizeof(INT_PTR) == sizeof(INT)) BASE_TYPE_UNMARSHALL(INT);
6737 else
6739 INT val;
6740 align_pointer(&pStubMsg->Buffer, sizeof(INT));
6741 if (!fMustAlloc && !*ppMemory)
6742 fMustAlloc = TRUE;
6743 if (fMustAlloc)
6744 *ppMemory = NdrAllocate(pStubMsg, sizeof(INT_PTR));
6745 safe_copy_from_buffer(pStubMsg, &val, sizeof(INT));
6746 **(INT_PTR **)ppMemory = val;
6747 TRACE("value: 0x%08lx\n", **(INT_PTR **)ppMemory);
6749 break;
6750 case FC_UINT3264:
6751 if (sizeof(UINT_PTR) == sizeof(UINT)) BASE_TYPE_UNMARSHALL(UINT);
6752 else
6754 UINT val;
6755 align_pointer(&pStubMsg->Buffer, sizeof(UINT));
6756 if (!fMustAlloc && !*ppMemory)
6757 fMustAlloc = TRUE;
6758 if (fMustAlloc)
6759 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT_PTR));
6760 safe_copy_from_buffer(pStubMsg, &val, sizeof(UINT));
6761 **(UINT_PTR **)ppMemory = val;
6762 TRACE("value: 0x%08lx\n", **(UINT_PTR **)ppMemory);
6764 break;
6765 case FC_IGNORE:
6766 break;
6767 default:
6768 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6770 #undef BASE_TYPE_UNMARSHALL
6772 /* FIXME: what is the correct return value? */
6774 return NULL;
6777 /***********************************************************************
6778 * NdrBaseTypeBufferSize [internal]
6780 static void WINAPI NdrBaseTypeBufferSize(
6781 PMIDL_STUB_MESSAGE pStubMsg,
6782 unsigned char *pMemory,
6783 PFORMAT_STRING pFormat)
6785 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6787 switch(*pFormat)
6789 case FC_BYTE:
6790 case FC_CHAR:
6791 case FC_SMALL:
6792 case FC_USMALL:
6793 safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6794 break;
6795 case FC_WCHAR:
6796 case FC_SHORT:
6797 case FC_USHORT:
6798 case FC_ENUM16:
6799 align_length(&pStubMsg->BufferLength, sizeof(USHORT));
6800 safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6801 break;
6802 case FC_LONG:
6803 case FC_ULONG:
6804 case FC_ENUM32:
6805 case FC_INT3264:
6806 case FC_UINT3264:
6807 align_length(&pStubMsg->BufferLength, sizeof(ULONG));
6808 safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6809 break;
6810 case FC_FLOAT:
6811 align_length(&pStubMsg->BufferLength, sizeof(float));
6812 safe_buffer_length_increment(pStubMsg, sizeof(float));
6813 break;
6814 case FC_DOUBLE:
6815 align_length(&pStubMsg->BufferLength, sizeof(double));
6816 safe_buffer_length_increment(pStubMsg, sizeof(double));
6817 break;
6818 case FC_HYPER:
6819 align_length(&pStubMsg->BufferLength, sizeof(ULONGLONG));
6820 safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6821 break;
6822 case FC_ERROR_STATUS_T:
6823 align_length(&pStubMsg->BufferLength, sizeof(error_status_t));
6824 safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6825 break;
6826 case FC_IGNORE:
6827 break;
6828 default:
6829 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6833 /***********************************************************************
6834 * NdrBaseTypeMemorySize [internal]
6836 static ULONG WINAPI NdrBaseTypeMemorySize(
6837 PMIDL_STUB_MESSAGE pStubMsg,
6838 PFORMAT_STRING pFormat)
6840 TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6842 switch(*pFormat)
6844 case FC_BYTE:
6845 case FC_CHAR:
6846 case FC_SMALL:
6847 case FC_USMALL:
6848 safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6849 pStubMsg->MemorySize += sizeof(UCHAR);
6850 return sizeof(UCHAR);
6851 case FC_WCHAR:
6852 case FC_SHORT:
6853 case FC_USHORT:
6854 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6855 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6856 align_length(&pStubMsg->MemorySize, sizeof(USHORT));
6857 pStubMsg->MemorySize += sizeof(USHORT);
6858 return sizeof(USHORT);
6859 case FC_LONG:
6860 case FC_ULONG:
6861 case FC_ENUM32:
6862 align_pointer(&pStubMsg->Buffer, sizeof(ULONG));
6863 safe_buffer_increment(pStubMsg, sizeof(ULONG));
6864 align_length(&pStubMsg->MemorySize, sizeof(ULONG));
6865 pStubMsg->MemorySize += sizeof(ULONG);
6866 return sizeof(ULONG);
6867 case FC_FLOAT:
6868 align_pointer(&pStubMsg->Buffer, sizeof(float));
6869 safe_buffer_increment(pStubMsg, sizeof(float));
6870 align_length(&pStubMsg->MemorySize, sizeof(float));
6871 pStubMsg->MemorySize += sizeof(float);
6872 return sizeof(float);
6873 case FC_DOUBLE:
6874 align_pointer(&pStubMsg->Buffer, sizeof(double));
6875 safe_buffer_increment(pStubMsg, sizeof(double));
6876 align_length(&pStubMsg->MemorySize, sizeof(double));
6877 pStubMsg->MemorySize += sizeof(double);
6878 return sizeof(double);
6879 case FC_HYPER:
6880 align_pointer(&pStubMsg->Buffer, sizeof(ULONGLONG));
6881 safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6882 align_length(&pStubMsg->MemorySize, sizeof(ULONGLONG));
6883 pStubMsg->MemorySize += sizeof(ULONGLONG);
6884 return sizeof(ULONGLONG);
6885 case FC_ERROR_STATUS_T:
6886 align_pointer(&pStubMsg->Buffer, sizeof(error_status_t));
6887 safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6888 align_length(&pStubMsg->MemorySize, sizeof(error_status_t));
6889 pStubMsg->MemorySize += sizeof(error_status_t);
6890 return sizeof(error_status_t);
6891 case FC_ENUM16:
6892 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6893 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6894 align_length(&pStubMsg->MemorySize, sizeof(UINT));
6895 pStubMsg->MemorySize += sizeof(UINT);
6896 return sizeof(UINT);
6897 case FC_INT3264:
6898 case FC_UINT3264:
6899 align_pointer(&pStubMsg->Buffer, sizeof(UINT));
6900 safe_buffer_increment(pStubMsg, sizeof(UINT));
6901 align_length(&pStubMsg->MemorySize, sizeof(UINT_PTR));
6902 pStubMsg->MemorySize += sizeof(UINT_PTR);
6903 return sizeof(UINT_PTR);
6904 case FC_IGNORE:
6905 align_length(&pStubMsg->MemorySize, sizeof(void *));
6906 pStubMsg->MemorySize += sizeof(void *);
6907 return sizeof(void *);
6908 default:
6909 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6910 return 0;
6914 /***********************************************************************
6915 * NdrBaseTypeFree [internal]
6917 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6918 unsigned char *pMemory,
6919 PFORMAT_STRING pFormat)
6921 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6923 /* nothing to do */
6926 /***********************************************************************
6927 * NdrContextHandleBufferSize [internal]
6929 static void WINAPI NdrContextHandleBufferSize(
6930 PMIDL_STUB_MESSAGE pStubMsg,
6931 unsigned char *pMemory,
6932 PFORMAT_STRING pFormat)
6934 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6936 if (*pFormat != FC_BIND_CONTEXT)
6938 ERR("invalid format type %x\n", *pFormat);
6939 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6941 align_length(&pStubMsg->BufferLength, 4);
6942 safe_buffer_length_increment(pStubMsg, cbNDRContext);
6945 /***********************************************************************
6946 * NdrContextHandleMarshall [internal]
6948 static unsigned char *WINAPI NdrContextHandleMarshall(
6949 PMIDL_STUB_MESSAGE pStubMsg,
6950 unsigned char *pMemory,
6951 PFORMAT_STRING pFormat)
6953 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6955 if (*pFormat != FC_BIND_CONTEXT)
6957 ERR("invalid format type %x\n", *pFormat);
6958 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6960 TRACE("flags: 0x%02x\n", pFormat[1]);
6962 if (pStubMsg->IsClient)
6964 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6965 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6966 else
6967 NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
6969 else
6971 NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
6972 NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
6973 NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
6976 return NULL;
6979 /***********************************************************************
6980 * NdrContextHandleUnmarshall [internal]
6982 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6983 PMIDL_STUB_MESSAGE pStubMsg,
6984 unsigned char **ppMemory,
6985 PFORMAT_STRING pFormat,
6986 unsigned char fMustAlloc)
6988 TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg,
6989 ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE");
6991 if (*pFormat != FC_BIND_CONTEXT)
6993 ERR("invalid format type %x\n", *pFormat);
6994 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6996 TRACE("flags: 0x%02x\n", pFormat[1]);
6998 if (pStubMsg->IsClient)
7000 /* [out]-only or [ret] param */
7001 if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT)
7002 **(NDR_CCONTEXT **)ppMemory = NULL;
7003 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
7005 else
7007 NDR_SCONTEXT ctxt;
7008 ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat);
7009 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
7010 *(void **)ppMemory = NDRSContextValue(ctxt);
7011 else
7012 *(void **)ppMemory = *NDRSContextValue(ctxt);
7015 return NULL;
7018 /***********************************************************************
7019 * NdrClientContextMarshall [RPCRT4.@]
7021 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
7022 NDR_CCONTEXT ContextHandle,
7023 int fCheck)
7025 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
7027 align_pointer_clear(&pStubMsg->Buffer, 4);
7029 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7031 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7032 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7033 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7036 /* FIXME: what does fCheck do? */
7037 NDRCContextMarshall(ContextHandle,
7038 pStubMsg->Buffer);
7040 pStubMsg->Buffer += cbNDRContext;
7043 /***********************************************************************
7044 * NdrClientContextUnmarshall [RPCRT4.@]
7046 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
7047 NDR_CCONTEXT * pContextHandle,
7048 RPC_BINDING_HANDLE BindHandle)
7050 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
7052 align_pointer(&pStubMsg->Buffer, 4);
7054 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
7055 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7057 NDRCContextUnmarshall(pContextHandle,
7058 BindHandle,
7059 pStubMsg->Buffer,
7060 pStubMsg->RpcMsg->DataRepresentation);
7062 pStubMsg->Buffer += cbNDRContext;
7065 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
7066 NDR_SCONTEXT ContextHandle,
7067 NDR_RUNDOWN RundownRoutine )
7069 TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
7071 align_pointer(&pStubMsg->Buffer, 4);
7073 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7075 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7076 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7077 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7080 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
7081 pStubMsg->Buffer, RundownRoutine, NULL,
7082 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
7083 pStubMsg->Buffer += cbNDRContext;
7086 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
7088 NDR_SCONTEXT ContextHandle;
7090 TRACE("(%p)\n", pStubMsg);
7092 align_pointer(&pStubMsg->Buffer, 4);
7094 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7096 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7097 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7098 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7101 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
7102 pStubMsg->Buffer,
7103 pStubMsg->RpcMsg->DataRepresentation,
7104 NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
7105 pStubMsg->Buffer += cbNDRContext;
7107 return ContextHandle;
7110 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
7111 unsigned char* pMemory,
7112 PFORMAT_STRING pFormat)
7114 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
7117 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
7118 PFORMAT_STRING pFormat)
7120 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
7121 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
7123 TRACE("(%p, %p)\n", pStubMsg, pFormat);
7125 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7126 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7127 if (pFormat[1] & NDR_CONTEXT_HANDLE_NOSERIALIZE)
7128 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7129 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7131 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7132 if_id = &sif->InterfaceId;
7135 return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
7136 pStubMsg->RpcMsg->DataRepresentation, if_id,
7137 flags);
7140 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
7141 NDR_SCONTEXT ContextHandle,
7142 NDR_RUNDOWN RundownRoutine,
7143 PFORMAT_STRING pFormat)
7145 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
7146 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
7148 TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
7150 align_pointer(&pStubMsg->Buffer, 4);
7152 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7154 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7155 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7156 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7159 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7160 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7161 if (pFormat[1] & NDR_CONTEXT_HANDLE_NOSERIALIZE)
7162 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7163 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7165 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7166 if_id = &sif->InterfaceId;
7169 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
7170 pStubMsg->Buffer, RundownRoutine, if_id, flags);
7171 pStubMsg->Buffer += cbNDRContext;
7174 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
7175 PFORMAT_STRING pFormat)
7177 NDR_SCONTEXT ContextHandle;
7178 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
7179 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
7181 TRACE("(%p, %p)\n", pStubMsg, pFormat);
7183 align_pointer(&pStubMsg->Buffer, 4);
7185 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7187 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7188 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7189 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7192 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7193 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7194 if (pFormat[1] & NDR_CONTEXT_HANDLE_NOSERIALIZE)
7195 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7196 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7198 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7199 if_id = &sif->InterfaceId;
7202 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
7203 pStubMsg->Buffer,
7204 pStubMsg->RpcMsg->DataRepresentation,
7205 if_id, flags);
7206 pStubMsg->Buffer += cbNDRContext;
7208 return ContextHandle;
7211 /***********************************************************************
7212 * NdrCorrelationInitialize [RPCRT4.@]
7214 * Initializes correlation validity checking.
7216 * PARAMS
7217 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7218 * pMemory [I] Pointer to memory to use as a cache.
7219 * CacheSize [I] Size of the memory pointed to by pMemory.
7220 * Flags [I] Reserved. Set to zero.
7222 * RETURNS
7223 * Nothing.
7225 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
7227 FIXME("(%p, %p, %d, 0x%x): semi-stub\n", pStubMsg, pMemory, CacheSize, Flags);
7229 if (pStubMsg->CorrDespIncrement == 0)
7230 pStubMsg->CorrDespIncrement = 2; /* size of the normal (non-range) /robust payload */
7232 pStubMsg->fHasNewCorrDesc = TRUE;
7235 /***********************************************************************
7236 * NdrCorrelationPass [RPCRT4.@]
7238 * Performs correlation validity checking.
7240 * PARAMS
7241 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7243 * RETURNS
7244 * Nothing.
7246 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
7248 FIXME("(%p): stub\n", pStubMsg);
7251 /***********************************************************************
7252 * NdrCorrelationFree [RPCRT4.@]
7254 * Frees any resources used while unmarshalling parameters that need
7255 * correlation validity checking.
7257 * PARAMS
7258 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7260 * RETURNS
7261 * Nothing.
7263 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
7265 FIXME("(%p): stub\n", pStubMsg);