makefiles: Bypass the normal substitution mechanism for the makefile dependencies.
[wine/multimedia.git] / dlls / rpcrt4 / ndr_marshall.c
blob9946bd13d57124d0bcb69a6cbaae4db4bdb45059
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 <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <limits.h>
35 #define NONAMELESSUNION
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winerror.h"
40 #include "ndr_misc.h"
41 #include "rpcndr.h"
42 #include "ndrtypes.h"
44 #include "wine/unicode.h"
45 #include "wine/rpcfc.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(ole);
51 #if defined(__i386__)
52 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
53 (*((UINT32 *)(pchar)) = (uint32))
55 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
56 (*((UINT32 *)(pchar)))
57 #else
58 /* these would work for i386 too, but less efficient */
59 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
60 (*(pchar) = LOBYTE(LOWORD(uint32)), \
61 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
62 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
63 *((pchar)+3) = HIBYTE(HIWORD(uint32)))
65 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
66 (MAKELONG( \
67 MAKEWORD(*(pchar), *((pchar)+1)), \
68 MAKEWORD(*((pchar)+2), *((pchar)+3))))
69 #endif
71 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
72 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
73 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
74 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
75 *(pchar) = HIBYTE(HIWORD(uint32)))
77 #define BIG_ENDIAN_UINT32_READ(pchar) \
78 (MAKELONG( \
79 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
80 MAKEWORD(*((pchar)+1), *(pchar))))
82 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
83 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
84 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
85 # define NDR_LOCAL_UINT32_READ(pchar) \
86 BIG_ENDIAN_UINT32_READ(pchar)
87 #else
88 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
89 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
90 # define NDR_LOCAL_UINT32_READ(pchar) \
91 LITTLE_ENDIAN_UINT32_READ(pchar)
92 #endif
94 /* _Align must be the desired alignment,
95 * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
96 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
97 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
98 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
99 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
100 #define ALIGN_POINTER_CLEAR(_Ptr, _Align) \
101 do { \
102 memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \
103 ALIGN_POINTER(_Ptr, _Align); \
104 } while(0)
106 #define STD_OVERFLOW_CHECK(_Msg) do { \
107 TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
108 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
109 ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
110 } while (0)
112 #define NDR_POINTER_ID_BASE 0x20000
113 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
114 #define NDR_TABLE_SIZE 128
115 #define NDR_TABLE_MASK 127
117 #define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL))
119 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
120 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
121 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
122 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
123 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
125 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
126 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
127 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
129 static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
130 static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
131 static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
132 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
134 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
136 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
138 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
139 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
140 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
141 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
142 /* 0x10 */
143 NdrBaseTypeMarshall,
144 /* 0x11 */
145 NdrPointerMarshall, NdrPointerMarshall,
146 NdrPointerMarshall, NdrPointerMarshall,
147 /* 0x15 */
148 NdrSimpleStructMarshall, NdrSimpleStructMarshall,
149 NdrConformantStructMarshall, NdrConformantStructMarshall,
150 NdrConformantVaryingStructMarshall,
151 NdrComplexStructMarshall,
152 /* 0x1b */
153 NdrConformantArrayMarshall,
154 NdrConformantVaryingArrayMarshall,
155 NdrFixedArrayMarshall, NdrFixedArrayMarshall,
156 NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
157 NdrComplexArrayMarshall,
158 /* 0x22 */
159 NdrConformantStringMarshall, 0, 0,
160 NdrConformantStringMarshall,
161 NdrNonConformantStringMarshall, 0, 0, 0,
162 /* 0x2a */
163 NdrEncapsulatedUnionMarshall,
164 NdrNonEncapsulatedUnionMarshall,
165 NdrByteCountPointerMarshall,
166 NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
167 /* 0x2f */
168 NdrInterfacePointerMarshall,
169 /* 0x30 */
170 NdrContextHandleMarshall,
171 /* 0xb1 */
172 0, 0, 0,
173 NdrUserMarshalMarshall,
174 0, 0,
175 /* 0xb7 */
176 NdrRangeMarshall
178 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
180 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
181 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
182 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
183 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
184 /* 0x10 */
185 NdrBaseTypeUnmarshall,
186 /* 0x11 */
187 NdrPointerUnmarshall, NdrPointerUnmarshall,
188 NdrPointerUnmarshall, NdrPointerUnmarshall,
189 /* 0x15 */
190 NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
191 NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
192 NdrConformantVaryingStructUnmarshall,
193 NdrComplexStructUnmarshall,
194 /* 0x1b */
195 NdrConformantArrayUnmarshall,
196 NdrConformantVaryingArrayUnmarshall,
197 NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
198 NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
199 NdrComplexArrayUnmarshall,
200 /* 0x22 */
201 NdrConformantStringUnmarshall, 0, 0,
202 NdrConformantStringUnmarshall,
203 NdrNonConformantStringUnmarshall, 0, 0, 0,
204 /* 0x2a */
205 NdrEncapsulatedUnionUnmarshall,
206 NdrNonEncapsulatedUnionUnmarshall,
207 NdrByteCountPointerUnmarshall,
208 NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
209 /* 0x2f */
210 NdrInterfacePointerUnmarshall,
211 /* 0x30 */
212 NdrContextHandleUnmarshall,
213 /* 0xb1 */
214 0, 0, 0,
215 NdrUserMarshalUnmarshall,
216 0, 0,
217 /* 0xb7 */
218 NdrRangeUnmarshall
220 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
222 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
223 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
224 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
225 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
226 /* 0x10 */
227 NdrBaseTypeBufferSize,
228 /* 0x11 */
229 NdrPointerBufferSize, NdrPointerBufferSize,
230 NdrPointerBufferSize, NdrPointerBufferSize,
231 /* 0x15 */
232 NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
233 NdrConformantStructBufferSize, NdrConformantStructBufferSize,
234 NdrConformantVaryingStructBufferSize,
235 NdrComplexStructBufferSize,
236 /* 0x1b */
237 NdrConformantArrayBufferSize,
238 NdrConformantVaryingArrayBufferSize,
239 NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
240 NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
241 NdrComplexArrayBufferSize,
242 /* 0x22 */
243 NdrConformantStringBufferSize, 0, 0,
244 NdrConformantStringBufferSize,
245 NdrNonConformantStringBufferSize, 0, 0, 0,
246 /* 0x2a */
247 NdrEncapsulatedUnionBufferSize,
248 NdrNonEncapsulatedUnionBufferSize,
249 NdrByteCountPointerBufferSize,
250 NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
251 /* 0x2f */
252 NdrInterfacePointerBufferSize,
253 /* 0x30 */
254 NdrContextHandleBufferSize,
255 /* 0xb1 */
256 0, 0, 0,
257 NdrUserMarshalBufferSize,
258 0, 0,
259 /* 0xb7 */
260 NdrRangeBufferSize
262 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
264 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
265 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
266 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
267 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
268 /* 0x10 */
269 NdrBaseTypeMemorySize,
270 /* 0x11 */
271 NdrPointerMemorySize, NdrPointerMemorySize,
272 NdrPointerMemorySize, NdrPointerMemorySize,
273 /* 0x15 */
274 NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
275 NdrConformantStructMemorySize, NdrConformantStructMemorySize,
276 NdrConformantVaryingStructMemorySize,
277 NdrComplexStructMemorySize,
278 /* 0x1b */
279 NdrConformantArrayMemorySize,
280 NdrConformantVaryingArrayMemorySize,
281 NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
282 NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
283 NdrComplexArrayMemorySize,
284 /* 0x22 */
285 NdrConformantStringMemorySize, 0, 0,
286 NdrConformantStringMemorySize,
287 NdrNonConformantStringMemorySize, 0, 0, 0,
288 /* 0x2a */
289 NdrEncapsulatedUnionMemorySize,
290 NdrNonEncapsulatedUnionMemorySize,
291 NdrByteCountPointerMemorySize,
292 NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
293 /* 0x2f */
294 NdrInterfacePointerMemorySize,
295 /* 0x30 */
297 /* 0xb1 */
298 0, 0, 0,
299 NdrUserMarshalMemorySize,
300 0, 0,
301 /* 0xb7 */
302 NdrRangeMemorySize
304 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
306 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
307 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
308 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
309 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
310 /* 0x10 */
311 NdrBaseTypeFree,
312 /* 0x11 */
313 NdrPointerFree, NdrPointerFree,
314 NdrPointerFree, NdrPointerFree,
315 /* 0x15 */
316 NdrSimpleStructFree, NdrSimpleStructFree,
317 NdrConformantStructFree, NdrConformantStructFree,
318 NdrConformantVaryingStructFree,
319 NdrComplexStructFree,
320 /* 0x1b */
321 NdrConformantArrayFree,
322 NdrConformantVaryingArrayFree,
323 NdrFixedArrayFree, NdrFixedArrayFree,
324 NdrVaryingArrayFree, NdrVaryingArrayFree,
325 NdrComplexArrayFree,
326 /* 0x22 */
327 0, 0, 0,
328 0, 0, 0, 0, 0,
329 /* 0x2a */
330 NdrEncapsulatedUnionFree,
331 NdrNonEncapsulatedUnionFree,
333 NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
334 /* 0x2f */
335 NdrInterfacePointerFree,
336 /* 0x30 */
338 /* 0xb1 */
339 0, 0, 0,
340 NdrUserMarshalFree,
341 0, 0,
342 /* 0xb7 */
343 NdrRangeFree
346 typedef struct _NDR_MEMORY_LIST
348 ULONG magic;
349 ULONG size;
350 ULONG reserved;
351 struct _NDR_MEMORY_LIST *next;
352 } NDR_MEMORY_LIST;
354 #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
356 /***********************************************************************
357 * NdrAllocate [RPCRT4.@]
359 * Allocates a block of memory using pStubMsg->pfnAllocate.
361 * PARAMS
362 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
363 * len [I] Size of memory block to allocate.
365 * RETURNS
366 * The memory block of size len that was allocated.
368 * NOTES
369 * The memory block is always 8-byte aligned.
370 * If the function is unable to allocate memory an ERROR_OUTOFMEMORY
371 * exception is raised.
373 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len)
375 SIZE_T aligned_len;
376 SIZE_T adjusted_len;
377 void *p;
378 NDR_MEMORY_LIST *mem_list;
380 aligned_len = ALIGNED_LENGTH(len, 8);
381 adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
382 /* check for overflow */
383 if (adjusted_len < len)
385 ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len);
386 RpcRaiseException(RPC_X_BAD_STUB_DATA);
389 p = pStubMsg->pfnAllocate(adjusted_len);
390 if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
392 mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
393 mem_list->magic = MEML_MAGIC;
394 mem_list->size = aligned_len;
395 mem_list->reserved = 0;
396 mem_list->next = pStubMsg->pMemoryList;
397 pStubMsg->pMemoryList = mem_list;
399 TRACE("-- %p\n", p);
400 return p;
403 static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
405 TRACE("(%p, %p)\n", pStubMsg, Pointer);
407 pStubMsg->pfnFree(Pointer);
410 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
412 return (*(const ULONG *)pFormat != -1);
415 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
417 ALIGN_POINTER(pStubMsg->Buffer, 4);
418 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
419 RpcRaiseException(RPC_X_BAD_STUB_DATA);
420 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
421 pStubMsg->Buffer += 4;
422 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
423 if (pStubMsg->fHasNewCorrDesc)
424 return pFormat+6;
425 else
426 return pFormat+4;
429 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
431 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
433 pStubMsg->Offset = 0;
434 pStubMsg->ActualCount = pStubMsg->MaxCount;
435 goto done;
438 ALIGN_POINTER(pStubMsg->Buffer, 4);
439 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
440 RpcRaiseException(RPC_X_BAD_STUB_DATA);
441 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
442 pStubMsg->Buffer += 4;
443 TRACE("offset is %d\n", pStubMsg->Offset);
444 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
445 pStubMsg->Buffer += 4;
446 TRACE("variance is %d\n", pStubMsg->ActualCount);
448 if ((pStubMsg->ActualCount > MaxValue) ||
449 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
451 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
452 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
453 RpcRaiseException(RPC_S_INVALID_BOUND);
454 return NULL;
457 done:
458 if (pStubMsg->fHasNewCorrDesc)
459 return pFormat+6;
460 else
461 return pFormat+4;
464 /* writes the conformance value to the buffer */
465 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
467 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
468 if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
469 RpcRaiseException(RPC_X_BAD_STUB_DATA);
470 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
471 pStubMsg->Buffer += 4;
474 /* writes the variance values to the buffer */
475 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
477 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
478 if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
479 RpcRaiseException(RPC_X_BAD_STUB_DATA);
480 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
481 pStubMsg->Buffer += 4;
482 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
483 pStubMsg->Buffer += 4;
486 /* requests buffer space for the conformance value */
487 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
489 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
490 if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
491 RpcRaiseException(RPC_X_BAD_STUB_DATA);
492 pStubMsg->BufferLength += 4;
495 /* requests buffer space for the variance values */
496 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
498 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
499 if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
500 RpcRaiseException(RPC_X_BAD_STUB_DATA);
501 pStubMsg->BufferLength += 8;
504 PFORMAT_STRING ComputeConformanceOrVariance(
505 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
506 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
508 BYTE dtype = pFormat[0] & 0xf;
509 short ofs = *(const short *)&pFormat[2];
510 LPVOID ptr = NULL;
511 DWORD data = 0;
513 if (!IsConformanceOrVariancePresent(pFormat)) {
514 /* null descriptor */
515 *pCount = def;
516 goto finish_conf;
519 switch (pFormat[0] & 0xf0) {
520 case RPC_FC_NORMAL_CONFORMANCE:
521 TRACE("normal conformance, ofs=%d\n", ofs);
522 ptr = pMemory;
523 break;
524 case RPC_FC_POINTER_CONFORMANCE:
525 TRACE("pointer conformance, ofs=%d\n", ofs);
526 ptr = pStubMsg->Memory;
527 break;
528 case RPC_FC_TOP_LEVEL_CONFORMANCE:
529 TRACE("toplevel conformance, ofs=%d\n", ofs);
530 if (pStubMsg->StackTop) {
531 ptr = pStubMsg->StackTop;
533 else {
534 /* -Os mode, *pCount is already set */
535 goto finish_conf;
537 break;
538 case RPC_FC_CONSTANT_CONFORMANCE:
539 data = ofs | ((DWORD)pFormat[1] << 16);
540 TRACE("constant conformance, val=%d\n", data);
541 *pCount = data;
542 goto finish_conf;
543 case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
544 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
545 if (pStubMsg->StackTop) {
546 ptr = pStubMsg->StackTop;
548 else {
549 /* ? */
550 goto done_conf_grab;
552 break;
553 default:
554 FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0);
555 goto finish_conf;
558 switch (pFormat[1]) {
559 case RPC_FC_DEREFERENCE:
560 ptr = *(LPVOID*)((char *)ptr + ofs);
561 break;
562 case RPC_FC_CALLBACK:
564 unsigned char *old_stack_top = pStubMsg->StackTop;
565 pStubMsg->StackTop = ptr;
567 /* ofs is index into StubDesc->apfnExprEval */
568 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
569 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
571 pStubMsg->StackTop = old_stack_top;
573 /* the callback function always stores the computed value in MaxCount */
574 *pCount = pStubMsg->MaxCount;
575 goto finish_conf;
577 default:
578 ptr = (char *)ptr + ofs;
579 break;
582 switch (dtype) {
583 case RPC_FC_LONG:
584 case RPC_FC_ULONG:
585 data = *(DWORD*)ptr;
586 break;
587 case RPC_FC_SHORT:
588 data = *(SHORT*)ptr;
589 break;
590 case RPC_FC_USHORT:
591 data = *(USHORT*)ptr;
592 break;
593 case RPC_FC_CHAR:
594 case RPC_FC_SMALL:
595 data = *(CHAR*)ptr;
596 break;
597 case RPC_FC_BYTE:
598 case RPC_FC_USMALL:
599 data = *(UCHAR*)ptr;
600 break;
601 default:
602 FIXME("unknown conformance data type %x\n", dtype);
603 goto done_conf_grab;
605 TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
607 done_conf_grab:
608 switch (pFormat[1]) {
609 case RPC_FC_DEREFERENCE: /* already handled */
610 case 0: /* no op */
611 *pCount = data;
612 break;
613 case RPC_FC_ADD_1:
614 *pCount = data + 1;
615 break;
616 case RPC_FC_SUB_1:
617 *pCount = data - 1;
618 break;
619 case RPC_FC_MULT_2:
620 *pCount = data * 2;
621 break;
622 case RPC_FC_DIV_2:
623 *pCount = data / 2;
624 break;
625 default:
626 FIXME("unknown conformance op %d\n", pFormat[1]);
627 goto finish_conf;
630 finish_conf:
631 TRACE("resulting conformance is %ld\n", *pCount);
632 if (pStubMsg->fHasNewCorrDesc)
633 return pFormat+6;
634 else
635 return pFormat+4;
638 static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg,
639 PFORMAT_STRING pFormat)
641 if (IsConformanceOrVariancePresent(pFormat))
643 if (pStubMsg->fHasNewCorrDesc)
644 pFormat += 6;
645 else
646 pFormat += 4;
648 return pFormat;
651 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
652 * the result overflows 32-bits */
653 static inline ULONG safe_multiply(ULONG a, ULONG b)
655 ULONGLONG ret = (ULONGLONG)a * b;
656 if (ret > 0xffffffff)
658 RpcRaiseException(RPC_S_INVALID_BOUND);
659 return 0;
661 return ret;
664 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
666 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
667 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
668 RpcRaiseException(RPC_X_BAD_STUB_DATA);
669 pStubMsg->Buffer += size;
672 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
674 if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
676 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
677 pStubMsg->BufferLength, size);
678 RpcRaiseException(RPC_X_BAD_STUB_DATA);
680 pStubMsg->BufferLength += size;
683 /* copies data from the buffer, checking that there is enough data in the buffer
684 * to do so */
685 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
687 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
688 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
690 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
691 pStubMsg->Buffer, pStubMsg->BufferEnd, size);
692 RpcRaiseException(RPC_X_BAD_STUB_DATA);
694 if (p == pStubMsg->Buffer)
695 ERR("pointer is the same as the buffer\n");
696 memcpy(p, pStubMsg->Buffer, size);
697 pStubMsg->Buffer += size;
700 /* copies data to the buffer, checking that there is enough space to do so */
701 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
703 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
704 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
706 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
707 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
708 size);
709 RpcRaiseException(RPC_X_BAD_STUB_DATA);
711 memcpy(pStubMsg->Buffer, p, size);
712 pStubMsg->Buffer += size;
715 /* verify that string data sitting in the buffer is valid and safe to
716 * unmarshall */
717 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
719 ULONG i;
721 /* verify the buffer is safe to access */
722 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
723 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
725 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
726 pStubMsg->BufferEnd, pStubMsg->Buffer);
727 RpcRaiseException(RPC_X_BAD_STUB_DATA);
730 /* strings must always have null terminating bytes */
731 if (bufsize < esize)
733 ERR("invalid string length of %d\n", bufsize / esize);
734 RpcRaiseException(RPC_S_INVALID_BOUND);
737 for (i = bufsize - esize; i < bufsize; i++)
738 if (pStubMsg->Buffer[i] != 0)
740 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
741 i, pStubMsg->Buffer[i]);
742 RpcRaiseException(RPC_S_INVALID_BOUND);
746 static inline void dump_pointer_attr(unsigned char attr)
748 if (attr & RPC_FC_P_ALLOCALLNODES)
749 TRACE(" RPC_FC_P_ALLOCALLNODES");
750 if (attr & RPC_FC_P_DONTFREE)
751 TRACE(" RPC_FC_P_DONTFREE");
752 if (attr & RPC_FC_P_ONSTACK)
753 TRACE(" RPC_FC_P_ONSTACK");
754 if (attr & RPC_FC_P_SIMPLEPOINTER)
755 TRACE(" RPC_FC_P_SIMPLEPOINTER");
756 if (attr & RPC_FC_P_DEREF)
757 TRACE(" RPC_FC_P_DEREF");
758 TRACE("\n");
761 /***********************************************************************
762 * PointerMarshall [internal]
764 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
765 unsigned char *Buffer,
766 unsigned char *Pointer,
767 PFORMAT_STRING pFormat)
769 unsigned type = pFormat[0], attr = pFormat[1];
770 PFORMAT_STRING desc;
771 NDR_MARSHALL m;
772 ULONG pointer_id;
773 int pointer_needs_marshaling;
775 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
776 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
777 pFormat += 2;
778 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
779 else desc = pFormat + *(const SHORT*)pFormat;
781 switch (type) {
782 case RPC_FC_RP: /* ref pointer (always non-null) */
783 if (!Pointer)
785 ERR("NULL ref pointer is not allowed\n");
786 RpcRaiseException(RPC_X_NULL_REF_POINTER);
788 pointer_needs_marshaling = 1;
789 break;
790 case RPC_FC_UP: /* unique pointer */
791 case RPC_FC_OP: /* object pointer - same as unique here */
792 if (Pointer)
793 pointer_needs_marshaling = 1;
794 else
795 pointer_needs_marshaling = 0;
796 pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
797 TRACE("writing 0x%08x to buffer\n", pointer_id);
798 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
799 break;
800 case RPC_FC_FP:
801 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
802 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
803 TRACE("writing 0x%08x to buffer\n", pointer_id);
804 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
805 break;
806 default:
807 FIXME("unhandled ptr type=%02x\n", type);
808 RpcRaiseException(RPC_X_BAD_STUB_DATA);
809 return;
812 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
814 if (pointer_needs_marshaling) {
815 if (attr & RPC_FC_P_DEREF) {
816 Pointer = *(unsigned char**)Pointer;
817 TRACE("deref => %p\n", Pointer);
819 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
820 if (m) m(pStubMsg, Pointer, desc);
821 else FIXME("no marshaller for data type=%02x\n", *desc);
824 STD_OVERFLOW_CHECK(pStubMsg);
827 /***********************************************************************
828 * PointerUnmarshall [internal]
830 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
831 unsigned char *Buffer,
832 unsigned char **pPointer,
833 unsigned char *pSrcPointer,
834 PFORMAT_STRING pFormat,
835 unsigned char fMustAlloc)
837 unsigned type = pFormat[0], attr = pFormat[1];
838 PFORMAT_STRING desc;
839 NDR_UNMARSHALL m;
840 DWORD pointer_id = 0;
841 int pointer_needs_unmarshaling;
843 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
844 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
845 pFormat += 2;
846 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
847 else desc = pFormat + *(const SHORT*)pFormat;
849 switch (type) {
850 case RPC_FC_RP: /* ref pointer (always non-null) */
851 pointer_needs_unmarshaling = 1;
852 break;
853 case RPC_FC_UP: /* unique pointer */
854 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
855 TRACE("pointer_id is 0x%08x\n", pointer_id);
856 if (pointer_id)
857 pointer_needs_unmarshaling = 1;
858 else {
859 *pPointer = NULL;
860 pointer_needs_unmarshaling = 0;
862 break;
863 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
864 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
865 TRACE("pointer_id is 0x%08x\n", pointer_id);
866 if (!fMustAlloc && pSrcPointer)
868 FIXME("free object pointer %p\n", pSrcPointer);
869 fMustAlloc = TRUE;
871 if (pointer_id)
872 pointer_needs_unmarshaling = 1;
873 else
875 *pPointer = NULL;
876 pointer_needs_unmarshaling = 0;
878 break;
879 case RPC_FC_FP:
880 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
881 TRACE("pointer_id is 0x%08x\n", pointer_id);
882 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
883 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
884 break;
885 default:
886 FIXME("unhandled ptr type=%02x\n", type);
887 RpcRaiseException(RPC_X_BAD_STUB_DATA);
888 return;
891 if (pointer_needs_unmarshaling) {
892 unsigned char *base_ptr_val = *pPointer;
893 unsigned char **current_ptr = pPointer;
894 if (pStubMsg->IsClient) {
895 TRACE("client\n");
896 /* if we aren't forcing allocation of memory then try to use the existing
897 * (source) pointer to unmarshall the data into so that [in,out]
898 * parameters behave correctly. it doesn't matter if the parameter is
899 * [out] only since in that case the pointer will be NULL. we force
900 * allocation when the source pointer is NULL here instead of in the type
901 * unmarshalling routine for the benefit of the deref code below */
902 if (!fMustAlloc) {
903 if (pSrcPointer) {
904 TRACE("setting *pPointer to %p\n", pSrcPointer);
905 *pPointer = base_ptr_val = pSrcPointer;
906 } else
907 fMustAlloc = TRUE;
909 } else {
910 TRACE("server\n");
911 /* the memory in a stub is never initialised, so we have to work out here
912 * whether we have to initialise it so we can use the optimisation of
913 * setting the pointer to the buffer, if possible, or set fMustAlloc to
914 * TRUE. */
915 if (attr & RPC_FC_P_DEREF) {
916 fMustAlloc = TRUE;
917 } else {
918 base_ptr_val = NULL;
919 *current_ptr = NULL;
923 if (attr & RPC_FC_P_ALLOCALLNODES)
924 FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
926 if (attr & RPC_FC_P_DEREF) {
927 if (fMustAlloc) {
928 base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
929 *pPointer = base_ptr_val;
930 current_ptr = (unsigned char **)base_ptr_val;
931 } else
932 current_ptr = *(unsigned char***)current_ptr;
933 TRACE("deref => %p\n", current_ptr);
934 if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
936 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
937 if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
938 else FIXME("no unmarshaller for data type=%02x\n", *desc);
940 if (type == RPC_FC_FP)
941 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
942 *pPointer);
945 TRACE("pointer=%p\n", *pPointer);
948 /***********************************************************************
949 * PointerBufferSize [internal]
951 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
952 unsigned char *Pointer,
953 PFORMAT_STRING pFormat)
955 unsigned type = pFormat[0], attr = pFormat[1];
956 PFORMAT_STRING desc;
957 NDR_BUFFERSIZE m;
958 int pointer_needs_sizing;
959 ULONG pointer_id;
961 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
962 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
963 pFormat += 2;
964 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
965 else desc = pFormat + *(const SHORT*)pFormat;
967 switch (type) {
968 case RPC_FC_RP: /* ref pointer (always non-null) */
969 if (!Pointer)
971 ERR("NULL ref pointer is not allowed\n");
972 RpcRaiseException(RPC_X_NULL_REF_POINTER);
974 break;
975 case RPC_FC_OP:
976 case RPC_FC_UP:
977 /* NULL pointer has no further representation */
978 if (!Pointer)
979 return;
980 break;
981 case RPC_FC_FP:
982 pointer_needs_sizing = !NdrFullPointerQueryPointer(
983 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
984 if (!pointer_needs_sizing)
985 return;
986 break;
987 default:
988 FIXME("unhandled ptr type=%02x\n", type);
989 RpcRaiseException(RPC_X_BAD_STUB_DATA);
990 return;
993 if (attr & RPC_FC_P_DEREF) {
994 Pointer = *(unsigned char**)Pointer;
995 TRACE("deref => %p\n", Pointer);
998 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
999 if (m) m(pStubMsg, Pointer, desc);
1000 else FIXME("no buffersizer for data type=%02x\n", *desc);
1003 /***********************************************************************
1004 * PointerMemorySize [internal]
1006 static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1007 unsigned char *Buffer, PFORMAT_STRING pFormat)
1009 unsigned type = pFormat[0], attr = pFormat[1];
1010 PFORMAT_STRING desc;
1011 NDR_MEMORYSIZE m;
1012 DWORD pointer_id = 0;
1013 int pointer_needs_sizing;
1015 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1016 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1017 pFormat += 2;
1018 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1019 else desc = pFormat + *(const SHORT*)pFormat;
1021 switch (type) {
1022 case RPC_FC_RP: /* ref pointer (always non-null) */
1023 pointer_needs_sizing = 1;
1024 break;
1025 case RPC_FC_UP: /* unique pointer */
1026 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1027 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1028 TRACE("pointer_id is 0x%08x\n", pointer_id);
1029 if (pointer_id)
1030 pointer_needs_sizing = 1;
1031 else
1032 pointer_needs_sizing = 0;
1033 break;
1034 case RPC_FC_FP:
1036 void *pointer;
1037 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1038 TRACE("pointer_id is 0x%08x\n", pointer_id);
1039 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1040 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1041 break;
1043 default:
1044 FIXME("unhandled ptr type=%02x\n", type);
1045 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1046 return 0;
1049 if (attr & RPC_FC_P_DEREF) {
1050 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void*));
1051 pStubMsg->MemorySize += sizeof(void*);
1052 TRACE("deref\n");
1055 if (pointer_needs_sizing) {
1056 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1057 if (m) m(pStubMsg, desc);
1058 else FIXME("no memorysizer for data type=%02x\n", *desc);
1061 return pStubMsg->MemorySize;
1064 /***********************************************************************
1065 * PointerFree [internal]
1067 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1068 unsigned char *Pointer,
1069 PFORMAT_STRING pFormat)
1071 unsigned type = pFormat[0], attr = pFormat[1];
1072 PFORMAT_STRING desc;
1073 NDR_FREE m;
1074 unsigned char *current_pointer = Pointer;
1076 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1077 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1078 if (attr & RPC_FC_P_DONTFREE) return;
1079 pFormat += 2;
1080 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1081 else desc = pFormat + *(const SHORT*)pFormat;
1083 if (!Pointer) return;
1085 if (type == RPC_FC_FP) {
1086 int pointer_needs_freeing = NdrFullPointerFree(
1087 pStubMsg->FullPtrXlatTables, Pointer);
1088 if (!pointer_needs_freeing)
1089 return;
1092 if (attr & RPC_FC_P_DEREF) {
1093 current_pointer = *(unsigned char**)Pointer;
1094 TRACE("deref => %p\n", current_pointer);
1097 m = NdrFreer[*desc & NDR_TABLE_MASK];
1098 if (m) m(pStubMsg, current_pointer, desc);
1100 /* this check stops us from trying to free buffer memory. we don't have to
1101 * worry about clients, since they won't call this function.
1102 * we don't have to check for the buffer being reallocated because
1103 * BufferStart and BufferEnd won't be reset when allocating memory for
1104 * sending the response. we don't have to check for the new buffer here as
1105 * it won't be used a type memory, only for buffer memory */
1106 if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd)
1107 goto notfree;
1109 if (attr & RPC_FC_P_ONSTACK) {
1110 TRACE("not freeing stack ptr %p\n", Pointer);
1111 return;
1113 TRACE("freeing %p\n", Pointer);
1114 NdrFree(pStubMsg, Pointer);
1115 return;
1116 notfree:
1117 TRACE("not freeing %p\n", Pointer);
1120 /***********************************************************************
1121 * EmbeddedPointerMarshall
1123 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1124 unsigned char *pMemory,
1125 PFORMAT_STRING pFormat)
1127 unsigned char *Mark = pStubMsg->BufferMark;
1128 unsigned rep, count, stride;
1129 unsigned i;
1130 unsigned char *saved_buffer = NULL;
1132 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1134 if (*pFormat != RPC_FC_PP) return NULL;
1135 pFormat += 2;
1137 if (pStubMsg->PointerBufferMark)
1139 saved_buffer = pStubMsg->Buffer;
1140 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1141 pStubMsg->PointerBufferMark = NULL;
1144 while (pFormat[0] != RPC_FC_END) {
1145 switch (pFormat[0]) {
1146 default:
1147 FIXME("unknown repeat type %d\n", pFormat[0]);
1148 case RPC_FC_NO_REPEAT:
1149 rep = 1;
1150 stride = 0;
1151 count = 1;
1152 pFormat += 2;
1153 break;
1154 case RPC_FC_FIXED_REPEAT:
1155 rep = *(const WORD*)&pFormat[2];
1156 stride = *(const WORD*)&pFormat[4];
1157 count = *(const WORD*)&pFormat[8];
1158 pFormat += 10;
1159 break;
1160 case RPC_FC_VARIABLE_REPEAT:
1161 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1162 stride = *(const WORD*)&pFormat[2];
1163 count = *(const WORD*)&pFormat[6];
1164 pFormat += 8;
1165 break;
1167 for (i = 0; i < rep; i++) {
1168 PFORMAT_STRING info = pFormat;
1169 unsigned char *membase = pMemory + (i * stride);
1170 unsigned char *bufbase = Mark + (i * stride);
1171 unsigned u;
1173 for (u=0; u<count; u++,info+=8) {
1174 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1175 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1176 unsigned char *saved_memory = pStubMsg->Memory;
1178 pStubMsg->Memory = pMemory;
1179 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1180 pStubMsg->Memory = saved_memory;
1183 pFormat += 8 * count;
1186 if (saved_buffer)
1188 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1189 pStubMsg->Buffer = saved_buffer;
1192 STD_OVERFLOW_CHECK(pStubMsg);
1194 return NULL;
1197 /***********************************************************************
1198 * EmbeddedPointerUnmarshall
1200 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1201 unsigned char *pDstBuffer,
1202 unsigned char *pSrcMemoryPtrs,
1203 PFORMAT_STRING pFormat,
1204 unsigned char fMustAlloc)
1206 unsigned char *Mark = pStubMsg->BufferMark;
1207 unsigned rep, count, stride;
1208 unsigned i;
1209 unsigned char *saved_buffer = NULL;
1211 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1213 if (*pFormat != RPC_FC_PP) return NULL;
1214 pFormat += 2;
1216 if (pStubMsg->PointerBufferMark)
1218 saved_buffer = pStubMsg->Buffer;
1219 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1220 pStubMsg->PointerBufferMark = NULL;
1223 while (pFormat[0] != RPC_FC_END) {
1224 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1225 switch (pFormat[0]) {
1226 default:
1227 FIXME("unknown repeat type %d\n", pFormat[0]);
1228 case RPC_FC_NO_REPEAT:
1229 rep = 1;
1230 stride = 0;
1231 count = 1;
1232 pFormat += 2;
1233 break;
1234 case RPC_FC_FIXED_REPEAT:
1235 rep = *(const WORD*)&pFormat[2];
1236 stride = *(const WORD*)&pFormat[4];
1237 count = *(const WORD*)&pFormat[8];
1238 pFormat += 10;
1239 break;
1240 case RPC_FC_VARIABLE_REPEAT:
1241 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1242 stride = *(const WORD*)&pFormat[2];
1243 count = *(const WORD*)&pFormat[6];
1244 pFormat += 8;
1245 break;
1247 for (i = 0; i < rep; i++) {
1248 PFORMAT_STRING info = pFormat;
1249 unsigned char *bufdstbase = pDstBuffer + (i * stride);
1250 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1251 unsigned char *bufbase = Mark + (i * stride);
1252 unsigned u;
1254 for (u=0; u<count; u++,info+=8) {
1255 unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1256 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1257 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1258 PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1261 pFormat += 8 * count;
1264 if (saved_buffer)
1266 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1267 pStubMsg->Buffer = saved_buffer;
1270 return NULL;
1273 /***********************************************************************
1274 * EmbeddedPointerBufferSize
1276 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1277 unsigned char *pMemory,
1278 PFORMAT_STRING pFormat)
1280 unsigned rep, count, stride;
1281 unsigned i;
1282 ULONG saved_buffer_length = 0;
1284 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1286 if (pStubMsg->IgnoreEmbeddedPointers) return;
1288 if (*pFormat != RPC_FC_PP) return;
1289 pFormat += 2;
1291 if (pStubMsg->PointerLength)
1293 saved_buffer_length = pStubMsg->BufferLength;
1294 pStubMsg->BufferLength = pStubMsg->PointerLength;
1295 pStubMsg->PointerLength = 0;
1298 while (pFormat[0] != RPC_FC_END) {
1299 switch (pFormat[0]) {
1300 default:
1301 FIXME("unknown repeat type %d\n", pFormat[0]);
1302 case RPC_FC_NO_REPEAT:
1303 rep = 1;
1304 stride = 0;
1305 count = 1;
1306 pFormat += 2;
1307 break;
1308 case RPC_FC_FIXED_REPEAT:
1309 rep = *(const WORD*)&pFormat[2];
1310 stride = *(const WORD*)&pFormat[4];
1311 count = *(const WORD*)&pFormat[8];
1312 pFormat += 10;
1313 break;
1314 case RPC_FC_VARIABLE_REPEAT:
1315 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1316 stride = *(const WORD*)&pFormat[2];
1317 count = *(const WORD*)&pFormat[6];
1318 pFormat += 8;
1319 break;
1321 for (i = 0; i < rep; i++) {
1322 PFORMAT_STRING info = pFormat;
1323 unsigned char *membase = pMemory + (i * stride);
1324 unsigned u;
1326 for (u=0; u<count; u++,info+=8) {
1327 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1328 unsigned char *saved_memory = pStubMsg->Memory;
1330 pStubMsg->Memory = pMemory;
1331 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1332 pStubMsg->Memory = saved_memory;
1335 pFormat += 8 * count;
1338 if (saved_buffer_length)
1340 pStubMsg->PointerLength = pStubMsg->BufferLength;
1341 pStubMsg->BufferLength = saved_buffer_length;
1345 /***********************************************************************
1346 * EmbeddedPointerMemorySize [internal]
1348 static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1349 PFORMAT_STRING pFormat)
1351 unsigned char *Mark = pStubMsg->BufferMark;
1352 unsigned rep, count, stride;
1353 unsigned i;
1354 unsigned char *saved_buffer = NULL;
1356 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1358 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1360 if (pStubMsg->PointerBufferMark)
1362 saved_buffer = pStubMsg->Buffer;
1363 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1364 pStubMsg->PointerBufferMark = NULL;
1367 if (*pFormat != RPC_FC_PP) return 0;
1368 pFormat += 2;
1370 while (pFormat[0] != RPC_FC_END) {
1371 switch (pFormat[0]) {
1372 default:
1373 FIXME("unknown repeat type %d\n", pFormat[0]);
1374 case RPC_FC_NO_REPEAT:
1375 rep = 1;
1376 stride = 0;
1377 count = 1;
1378 pFormat += 2;
1379 break;
1380 case RPC_FC_FIXED_REPEAT:
1381 rep = *(const WORD*)&pFormat[2];
1382 stride = *(const WORD*)&pFormat[4];
1383 count = *(const WORD*)&pFormat[8];
1384 pFormat += 10;
1385 break;
1386 case RPC_FC_VARIABLE_REPEAT:
1387 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1388 stride = *(const WORD*)&pFormat[2];
1389 count = *(const WORD*)&pFormat[6];
1390 pFormat += 8;
1391 break;
1393 for (i = 0; i < rep; i++) {
1394 PFORMAT_STRING info = pFormat;
1395 unsigned char *bufbase = Mark + (i * stride);
1396 unsigned u;
1397 for (u=0; u<count; u++,info+=8) {
1398 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1399 PointerMemorySize(pStubMsg, bufptr, info+4);
1402 pFormat += 8 * count;
1405 if (saved_buffer)
1407 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1408 pStubMsg->Buffer = saved_buffer;
1411 return 0;
1414 /***********************************************************************
1415 * EmbeddedPointerFree [internal]
1417 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1418 unsigned char *pMemory,
1419 PFORMAT_STRING pFormat)
1421 unsigned rep, count, stride;
1422 unsigned i;
1424 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1425 if (*pFormat != RPC_FC_PP) return;
1426 pFormat += 2;
1428 while (pFormat[0] != RPC_FC_END) {
1429 switch (pFormat[0]) {
1430 default:
1431 FIXME("unknown repeat type %d\n", pFormat[0]);
1432 case RPC_FC_NO_REPEAT:
1433 rep = 1;
1434 stride = 0;
1435 count = 1;
1436 pFormat += 2;
1437 break;
1438 case RPC_FC_FIXED_REPEAT:
1439 rep = *(const WORD*)&pFormat[2];
1440 stride = *(const WORD*)&pFormat[4];
1441 count = *(const WORD*)&pFormat[8];
1442 pFormat += 10;
1443 break;
1444 case RPC_FC_VARIABLE_REPEAT:
1445 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1446 stride = *(const WORD*)&pFormat[2];
1447 count = *(const WORD*)&pFormat[6];
1448 pFormat += 8;
1449 break;
1451 for (i = 0; i < rep; i++) {
1452 PFORMAT_STRING info = pFormat;
1453 unsigned char *membase = pMemory + (i * stride);
1454 unsigned u;
1456 for (u=0; u<count; u++,info+=8) {
1457 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1458 unsigned char *saved_memory = pStubMsg->Memory;
1460 pStubMsg->Memory = pMemory;
1461 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1462 pStubMsg->Memory = saved_memory;
1465 pFormat += 8 * count;
1469 /***********************************************************************
1470 * NdrPointerMarshall [RPCRT4.@]
1472 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1473 unsigned char *pMemory,
1474 PFORMAT_STRING pFormat)
1476 unsigned char *Buffer;
1478 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1480 /* Increment the buffer here instead of in PointerMarshall,
1481 * as that is used by embedded pointers which already handle the incrementing
1482 * the buffer, and shouldn't write any additional pointer data to the wire */
1483 if (*pFormat != RPC_FC_RP)
1485 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1486 Buffer = pStubMsg->Buffer;
1487 safe_buffer_increment(pStubMsg, 4);
1489 else
1490 Buffer = pStubMsg->Buffer;
1492 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1494 return NULL;
1497 /***********************************************************************
1498 * NdrPointerUnmarshall [RPCRT4.@]
1500 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1501 unsigned char **ppMemory,
1502 PFORMAT_STRING pFormat,
1503 unsigned char fMustAlloc)
1505 unsigned char *Buffer;
1507 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1509 if (*pFormat == RPC_FC_RP)
1511 Buffer = pStubMsg->Buffer;
1512 /* Do the NULL ref pointer check here because embedded pointers can be
1513 * NULL if the type the pointer is embedded in was allocated rather than
1514 * being passed in by the client */
1515 if (pStubMsg->IsClient && !*ppMemory)
1517 ERR("NULL ref pointer is not allowed\n");
1518 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1521 else
1523 /* Increment the buffer here instead of in PointerUnmarshall,
1524 * as that is used by embedded pointers which already handle the incrementing
1525 * the buffer, and shouldn't read any additional pointer data from the
1526 * buffer */
1527 ALIGN_POINTER(pStubMsg->Buffer, 4);
1528 Buffer = pStubMsg->Buffer;
1529 safe_buffer_increment(pStubMsg, 4);
1532 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1534 return NULL;
1537 /***********************************************************************
1538 * NdrPointerBufferSize [RPCRT4.@]
1540 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1541 unsigned char *pMemory,
1542 PFORMAT_STRING pFormat)
1544 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1546 /* Increment the buffer length here instead of in PointerBufferSize,
1547 * as that is used by embedded pointers which already handle the buffer
1548 * length, and shouldn't write anything more to the wire */
1549 if (*pFormat != RPC_FC_RP)
1551 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1552 safe_buffer_length_increment(pStubMsg, 4);
1555 PointerBufferSize(pStubMsg, pMemory, pFormat);
1558 /***********************************************************************
1559 * NdrPointerMemorySize [RPCRT4.@]
1561 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1562 PFORMAT_STRING pFormat)
1564 unsigned char *Buffer = pStubMsg->Buffer;
1565 if (*pFormat != RPC_FC_RP)
1567 ALIGN_POINTER(pStubMsg->Buffer, 4);
1568 safe_buffer_increment(pStubMsg, 4);
1570 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
1571 return PointerMemorySize(pStubMsg, Buffer, pFormat);
1574 /***********************************************************************
1575 * NdrPointerFree [RPCRT4.@]
1577 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1578 unsigned char *pMemory,
1579 PFORMAT_STRING pFormat)
1581 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1582 PointerFree(pStubMsg, pMemory, pFormat);
1585 /***********************************************************************
1586 * NdrSimpleTypeMarshall [RPCRT4.@]
1588 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1589 unsigned char FormatChar )
1591 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1594 /***********************************************************************
1595 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1597 * Unmarshall a base type.
1599 * NOTES
1600 * Doesn't check that the buffer is long enough before copying, so the caller
1601 * should do this.
1603 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1604 unsigned char FormatChar )
1606 #define BASE_TYPE_UNMARSHALL(type) \
1607 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
1608 TRACE("pMemory: %p\n", pMemory); \
1609 *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1610 pStubMsg->Buffer += sizeof(type);
1612 switch(FormatChar)
1614 case RPC_FC_BYTE:
1615 case RPC_FC_CHAR:
1616 case RPC_FC_SMALL:
1617 case RPC_FC_USMALL:
1618 BASE_TYPE_UNMARSHALL(UCHAR);
1619 TRACE("value: 0x%02x\n", *pMemory);
1620 break;
1621 case RPC_FC_WCHAR:
1622 case RPC_FC_SHORT:
1623 case RPC_FC_USHORT:
1624 BASE_TYPE_UNMARSHALL(USHORT);
1625 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1626 break;
1627 case RPC_FC_LONG:
1628 case RPC_FC_ULONG:
1629 case RPC_FC_ERROR_STATUS_T:
1630 case RPC_FC_ENUM32:
1631 BASE_TYPE_UNMARSHALL(ULONG);
1632 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1633 break;
1634 case RPC_FC_FLOAT:
1635 BASE_TYPE_UNMARSHALL(float);
1636 TRACE("value: %f\n", *(float *)pMemory);
1637 break;
1638 case RPC_FC_DOUBLE:
1639 BASE_TYPE_UNMARSHALL(double);
1640 TRACE("value: %f\n", *(double *)pMemory);
1641 break;
1642 case RPC_FC_HYPER:
1643 BASE_TYPE_UNMARSHALL(ULONGLONG);
1644 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1645 break;
1646 case RPC_FC_ENUM16:
1647 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
1648 TRACE("pMemory: %p\n", pMemory);
1649 /* 16-bits on the wire, but int in memory */
1650 *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1651 pStubMsg->Buffer += sizeof(USHORT);
1652 TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1653 break;
1654 case RPC_FC_IGNORE:
1655 break;
1656 default:
1657 FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1659 #undef BASE_TYPE_UNMARSHALL
1662 /***********************************************************************
1663 * NdrSimpleStructMarshall [RPCRT4.@]
1665 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1666 unsigned char *pMemory,
1667 PFORMAT_STRING pFormat)
1669 unsigned size = *(const WORD*)(pFormat+2);
1670 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1672 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
1674 pStubMsg->BufferMark = pStubMsg->Buffer;
1675 safe_copy_to_buffer(pStubMsg, pMemory, size);
1677 if (pFormat[0] != RPC_FC_STRUCT)
1678 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1680 return NULL;
1683 /***********************************************************************
1684 * NdrSimpleStructUnmarshall [RPCRT4.@]
1686 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1687 unsigned char **ppMemory,
1688 PFORMAT_STRING pFormat,
1689 unsigned char fMustAlloc)
1691 unsigned size = *(const WORD*)(pFormat+2);
1692 unsigned char *saved_buffer;
1693 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1695 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1697 if (fMustAlloc)
1698 *ppMemory = NdrAllocate(pStubMsg, size);
1699 else
1701 if (!pStubMsg->IsClient && !*ppMemory)
1702 /* for servers, we just point straight into the RPC buffer */
1703 *ppMemory = pStubMsg->Buffer;
1706 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1707 safe_buffer_increment(pStubMsg, size);
1708 if (pFormat[0] == RPC_FC_PSTRUCT)
1709 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1711 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1712 if (*ppMemory != saved_buffer)
1713 memcpy(*ppMemory, saved_buffer, size);
1715 return NULL;
1718 /***********************************************************************
1719 * NdrSimpleStructBufferSize [RPCRT4.@]
1721 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1722 unsigned char *pMemory,
1723 PFORMAT_STRING pFormat)
1725 unsigned size = *(const WORD*)(pFormat+2);
1726 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1728 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1730 safe_buffer_length_increment(pStubMsg, size);
1731 if (pFormat[0] != RPC_FC_STRUCT)
1732 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1735 /***********************************************************************
1736 * NdrSimpleStructMemorySize [RPCRT4.@]
1738 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1739 PFORMAT_STRING pFormat)
1741 unsigned short size = *(const WORD *)(pFormat+2);
1743 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1745 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1746 pStubMsg->MemorySize += size;
1747 safe_buffer_increment(pStubMsg, size);
1749 if (pFormat[0] != RPC_FC_STRUCT)
1750 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1751 return pStubMsg->MemorySize;
1754 /***********************************************************************
1755 * NdrSimpleStructFree [RPCRT4.@]
1757 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1758 unsigned char *pMemory,
1759 PFORMAT_STRING pFormat)
1761 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1762 if (pFormat[0] != RPC_FC_STRUCT)
1763 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1766 /* Array helpers */
1768 static inline void array_compute_and_size_conformance(
1769 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1770 PFORMAT_STRING pFormat)
1772 switch (fc)
1774 case RPC_FC_CARRAY:
1775 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1776 SizeConformance(pStubMsg);
1777 break;
1778 case RPC_FC_CVARRAY:
1779 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1780 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1781 SizeConformance(pStubMsg);
1782 break;
1783 case RPC_FC_C_CSTRING:
1784 case RPC_FC_C_WSTRING:
1785 if (fc == RPC_FC_C_CSTRING)
1787 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1788 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1790 else
1792 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1793 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1796 if (pFormat[1] == RPC_FC_STRING_SIZED)
1797 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1798 else
1799 pStubMsg->MaxCount = pStubMsg->ActualCount;
1801 SizeConformance(pStubMsg);
1802 break;
1803 default:
1804 ERR("unknown array format 0x%x\n", fc);
1805 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1809 static inline void array_buffer_size(
1810 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1811 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1813 DWORD size;
1814 DWORD esize;
1815 unsigned char alignment;
1817 switch (fc)
1819 case RPC_FC_CARRAY:
1820 esize = *(const WORD*)(pFormat+2);
1821 alignment = pFormat[1] + 1;
1823 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1825 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1827 size = safe_multiply(esize, pStubMsg->MaxCount);
1828 /* conformance value plus array */
1829 safe_buffer_length_increment(pStubMsg, size);
1831 if (fHasPointers)
1832 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1833 break;
1834 case RPC_FC_CVARRAY:
1835 esize = *(const WORD*)(pFormat+2);
1836 alignment = pFormat[1] + 1;
1838 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1839 pFormat = SkipConformance(pStubMsg, pFormat);
1841 SizeVariance(pStubMsg);
1843 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1845 size = safe_multiply(esize, pStubMsg->ActualCount);
1846 safe_buffer_length_increment(pStubMsg, size);
1848 if (fHasPointers)
1849 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1850 break;
1851 case RPC_FC_C_CSTRING:
1852 case RPC_FC_C_WSTRING:
1853 if (fc == RPC_FC_C_CSTRING)
1854 esize = 1;
1855 else
1856 esize = 2;
1858 SizeVariance(pStubMsg);
1860 size = safe_multiply(esize, pStubMsg->ActualCount);
1861 safe_buffer_length_increment(pStubMsg, size);
1862 break;
1863 default:
1864 ERR("unknown array format 0x%x\n", fc);
1865 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1869 static inline void array_compute_and_write_conformance(
1870 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1871 PFORMAT_STRING pFormat)
1873 switch (fc)
1875 case RPC_FC_CARRAY:
1876 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1877 WriteConformance(pStubMsg);
1878 break;
1879 case RPC_FC_CVARRAY:
1880 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1881 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1882 WriteConformance(pStubMsg);
1883 break;
1884 case RPC_FC_C_CSTRING:
1885 case RPC_FC_C_WSTRING:
1886 if (fc == RPC_FC_C_CSTRING)
1888 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1889 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1891 else
1893 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1894 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1896 if (pFormat[1] == RPC_FC_STRING_SIZED)
1897 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1898 else
1899 pStubMsg->MaxCount = pStubMsg->ActualCount;
1900 pStubMsg->Offset = 0;
1901 WriteConformance(pStubMsg);
1902 break;
1903 default:
1904 ERR("unknown array format 0x%x\n", fc);
1905 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1909 static inline void array_write_variance_and_marshall(
1910 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1911 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1913 DWORD size;
1914 DWORD esize;
1915 unsigned char alignment;
1917 switch (fc)
1919 case RPC_FC_CARRAY:
1920 esize = *(const WORD*)(pFormat+2);
1921 alignment = pFormat[1] + 1;
1923 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1925 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1927 size = safe_multiply(esize, pStubMsg->MaxCount);
1928 if (fHasPointers)
1929 pStubMsg->BufferMark = pStubMsg->Buffer;
1930 safe_copy_to_buffer(pStubMsg, pMemory, size);
1932 if (fHasPointers)
1933 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1934 break;
1935 case RPC_FC_CVARRAY:
1936 esize = *(const WORD*)(pFormat+2);
1937 alignment = pFormat[1] + 1;
1939 /* conformance */
1940 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1941 /* variance */
1942 pFormat = SkipConformance(pStubMsg, pFormat);
1944 WriteVariance(pStubMsg);
1946 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1948 size = safe_multiply(esize, pStubMsg->ActualCount);
1950 if (fHasPointers)
1951 pStubMsg->BufferMark = pStubMsg->Buffer;
1952 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
1954 if (fHasPointers)
1955 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1956 break;
1957 case RPC_FC_C_CSTRING:
1958 case RPC_FC_C_WSTRING:
1959 if (fc == RPC_FC_C_CSTRING)
1960 esize = 1;
1961 else
1962 esize = 2;
1964 WriteVariance(pStubMsg);
1966 size = safe_multiply(esize, pStubMsg->ActualCount);
1967 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
1968 break;
1969 default:
1970 ERR("unknown array format 0x%x\n", fc);
1971 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1975 static inline ULONG array_read_conformance(
1976 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
1978 DWORD esize;
1980 switch (fc)
1982 case RPC_FC_CARRAY:
1983 esize = *(const WORD*)(pFormat+2);
1984 pFormat = ReadConformance(pStubMsg, pFormat+4);
1985 return safe_multiply(esize, pStubMsg->MaxCount);
1986 case RPC_FC_CVARRAY:
1987 esize = *(const WORD*)(pFormat+2);
1988 pFormat = ReadConformance(pStubMsg, pFormat+4);
1989 return safe_multiply(esize, pStubMsg->MaxCount);
1990 case RPC_FC_C_CSTRING:
1991 case RPC_FC_C_WSTRING:
1992 if (fc == RPC_FC_C_CSTRING)
1993 esize = 1;
1994 else
1995 esize = 2;
1997 if (pFormat[1] == RPC_FC_STRING_SIZED)
1998 ReadConformance(pStubMsg, pFormat + 2);
1999 else
2000 ReadConformance(pStubMsg, NULL);
2001 return safe_multiply(esize, pStubMsg->MaxCount);
2002 default:
2003 ERR("unknown array format 0x%x\n", fc);
2004 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2008 static inline ULONG array_read_variance_and_unmarshall(
2009 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
2010 PFORMAT_STRING pFormat, unsigned char fMustAlloc,
2011 unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
2013 ULONG bufsize, memsize;
2014 WORD esize;
2015 unsigned char alignment;
2016 unsigned char *saved_buffer;
2017 ULONG offset;
2019 switch (fc)
2021 case RPC_FC_CARRAY:
2022 esize = *(const WORD*)(pFormat+2);
2023 alignment = pFormat[1] + 1;
2025 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2027 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2029 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2031 if (fUnmarshall)
2033 if (fMustAlloc)
2034 *ppMemory = NdrAllocate(pStubMsg, memsize);
2035 else
2037 if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2038 /* for servers, we just point straight into the RPC buffer */
2039 *ppMemory = pStubMsg->Buffer;
2042 saved_buffer = pStubMsg->Buffer;
2043 safe_buffer_increment(pStubMsg, bufsize);
2045 pStubMsg->BufferMark = saved_buffer;
2046 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2048 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2049 if (*ppMemory != saved_buffer)
2050 memcpy(*ppMemory, saved_buffer, bufsize);
2052 return bufsize;
2053 case RPC_FC_CVARRAY:
2054 esize = *(const WORD*)(pFormat+2);
2055 alignment = pFormat[1] + 1;
2057 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2059 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2061 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2063 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2064 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2066 if (fUnmarshall)
2068 offset = pStubMsg->Offset;
2070 if (!fMustAlloc && !*ppMemory)
2071 fMustAlloc = TRUE;
2072 if (fMustAlloc)
2073 *ppMemory = NdrAllocate(pStubMsg, memsize);
2074 saved_buffer = pStubMsg->Buffer;
2075 safe_buffer_increment(pStubMsg, bufsize);
2077 pStubMsg->BufferMark = saved_buffer;
2078 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2079 fMustAlloc);
2081 memcpy(*ppMemory + offset, saved_buffer, bufsize);
2083 return bufsize;
2084 case RPC_FC_C_CSTRING:
2085 case RPC_FC_C_WSTRING:
2086 if (fc == RPC_FC_C_CSTRING)
2087 esize = 1;
2088 else
2089 esize = 2;
2091 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2093 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2095 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2096 pStubMsg->ActualCount, pStubMsg->MaxCount);
2097 RpcRaiseException(RPC_S_INVALID_BOUND);
2099 if (pStubMsg->Offset)
2101 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2102 RpcRaiseException(RPC_S_INVALID_BOUND);
2105 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2106 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2108 validate_string_data(pStubMsg, bufsize, esize);
2110 if (fUnmarshall)
2112 if (fMustAlloc)
2113 *ppMemory = NdrAllocate(pStubMsg, memsize);
2114 else
2116 if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2117 !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2118 /* if the data in the RPC buffer is big enough, we just point
2119 * straight into it */
2120 *ppMemory = pStubMsg->Buffer;
2121 else if (!*ppMemory)
2122 *ppMemory = NdrAllocate(pStubMsg, memsize);
2125 if (*ppMemory == pStubMsg->Buffer)
2126 safe_buffer_increment(pStubMsg, bufsize);
2127 else
2128 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2130 if (*pFormat == RPC_FC_C_CSTRING)
2131 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2132 else
2133 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2135 return bufsize;
2136 default:
2137 ERR("unknown array format 0x%x\n", fc);
2138 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2142 static inline void array_memory_size(
2143 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2144 unsigned char fHasPointers)
2146 ULONG bufsize, memsize;
2147 DWORD esize;
2148 unsigned char alignment;
2150 switch (fc)
2152 case RPC_FC_CARRAY:
2153 esize = *(const WORD*)(pFormat+2);
2154 alignment = pFormat[1] + 1;
2156 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2158 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2159 pStubMsg->MemorySize += memsize;
2161 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2162 if (fHasPointers)
2163 pStubMsg->BufferMark = pStubMsg->Buffer;
2164 safe_buffer_increment(pStubMsg, bufsize);
2166 if (fHasPointers)
2167 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2168 break;
2169 case RPC_FC_CVARRAY:
2170 esize = *(const WORD*)(pFormat+2);
2171 alignment = pFormat[1] + 1;
2173 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2175 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2177 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2178 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2179 pStubMsg->MemorySize += memsize;
2181 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2182 if (fHasPointers)
2183 pStubMsg->BufferMark = pStubMsg->Buffer;
2184 safe_buffer_increment(pStubMsg, bufsize);
2186 if (fHasPointers)
2187 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2188 break;
2189 case RPC_FC_C_CSTRING:
2190 case RPC_FC_C_WSTRING:
2191 if (fc == RPC_FC_C_CSTRING)
2192 esize = 1;
2193 else
2194 esize = 2;
2196 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2198 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2200 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2201 pStubMsg->ActualCount, pStubMsg->MaxCount);
2202 RpcRaiseException(RPC_S_INVALID_BOUND);
2204 if (pStubMsg->Offset)
2206 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2207 RpcRaiseException(RPC_S_INVALID_BOUND);
2210 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2211 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2213 validate_string_data(pStubMsg, bufsize, esize);
2215 safe_buffer_increment(pStubMsg, bufsize);
2216 pStubMsg->MemorySize += memsize;
2217 break;
2218 default:
2219 ERR("unknown array format 0x%x\n", fc);
2220 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2224 static inline void array_free(
2225 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2226 unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2228 switch (fc)
2230 case RPC_FC_CARRAY:
2231 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2232 if (fHasPointers)
2233 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2234 break;
2235 case RPC_FC_CVARRAY:
2236 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2237 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2238 if (fHasPointers)
2239 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2240 break;
2241 case RPC_FC_C_CSTRING:
2242 case RPC_FC_C_WSTRING:
2243 /* No embedded pointers so nothing to do */
2244 break;
2245 default:
2246 ERR("unknown array format 0x%x\n", fc);
2247 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2252 * NdrConformantString:
2254 * What MS calls a ConformantString is, in DCE terminology,
2255 * a Varying-Conformant String.
2257 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2258 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
2259 * into unmarshalled string)
2260 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2262 * data: CHARTYPE[maxlen]
2264 * ], where CHARTYPE is the appropriate character type (specified externally)
2268 /***********************************************************************
2269 * NdrConformantStringMarshall [RPCRT4.@]
2271 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
2272 unsigned char *pszMessage, PFORMAT_STRING pFormat)
2274 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2276 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2277 ERR("Unhandled string type: %#x\n", pFormat[0]);
2278 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2281 /* allow compiler to optimise inline function by passing constant into
2282 * these functions */
2283 if (pFormat[0] == RPC_FC_C_CSTRING) {
2284 array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2285 pFormat);
2286 array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2287 pFormat, TRUE /* fHasPointers */);
2288 } else {
2289 array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2290 pFormat);
2291 array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2292 pFormat, TRUE /* fHasPointers */);
2295 return NULL;
2298 /***********************************************************************
2299 * NdrConformantStringBufferSize [RPCRT4.@]
2301 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2302 unsigned char* pMemory, PFORMAT_STRING pFormat)
2304 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2306 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2307 ERR("Unhandled string type: %#x\n", pFormat[0]);
2308 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2311 /* allow compiler to optimise inline function by passing constant into
2312 * these functions */
2313 if (pFormat[0] == RPC_FC_C_CSTRING) {
2314 array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory,
2315 pFormat);
2316 array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2317 TRUE /* fHasPointers */);
2318 } else {
2319 array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory,
2320 pFormat);
2321 array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2322 TRUE /* fHasPointers */);
2326 /************************************************************************
2327 * NdrConformantStringMemorySize [RPCRT4.@]
2329 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2330 PFORMAT_STRING pFormat )
2332 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2334 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2335 ERR("Unhandled string type: %#x\n", pFormat[0]);
2336 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2339 /* allow compiler to optimise inline function by passing constant into
2340 * these functions */
2341 if (pFormat[0] == RPC_FC_C_CSTRING) {
2342 array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2343 array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat,
2344 TRUE /* fHasPointers */);
2345 } else {
2346 array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2347 array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat,
2348 TRUE /* fHasPointers */);
2351 return pStubMsg->MemorySize;
2354 /************************************************************************
2355 * NdrConformantStringUnmarshall [RPCRT4.@]
2357 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2358 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2360 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2361 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2363 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2364 ERR("Unhandled string type: %#x\n", *pFormat);
2365 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2368 /* allow compiler to optimise inline function by passing constant into
2369 * these functions */
2370 if (pFormat[0] == RPC_FC_C_CSTRING) {
2371 array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2372 array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory,
2373 pFormat, fMustAlloc,
2374 TRUE /* fUseBufferMemoryServer */,
2375 TRUE /* fUnmarshall */);
2376 } else {
2377 array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2378 array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory,
2379 pFormat, fMustAlloc,
2380 TRUE /* fUseBufferMemoryServer */,
2381 TRUE /* fUnmarshall */);
2384 return NULL;
2387 /***********************************************************************
2388 * NdrNonConformantStringMarshall [RPCRT4.@]
2390 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2391 unsigned char *pMemory,
2392 PFORMAT_STRING pFormat)
2394 ULONG esize, size, maxsize;
2396 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2398 maxsize = *(USHORT *)&pFormat[2];
2400 if (*pFormat == RPC_FC_CSTRING)
2402 ULONG i;
2403 const char *str = (const char *)pMemory;
2404 for (i = 0; i < maxsize && *str; i++, str++)
2406 TRACE("string=%s\n", debugstr_an(str, i));
2407 pStubMsg->ActualCount = i + 1;
2408 esize = 1;
2410 else if (*pFormat == RPC_FC_WSTRING)
2412 ULONG i;
2413 const WCHAR *str = (const WCHAR *)pMemory;
2414 for (i = 0; i < maxsize && *str; i++, str++)
2416 TRACE("string=%s\n", debugstr_wn(str, i));
2417 pStubMsg->ActualCount = i + 1;
2418 esize = 2;
2420 else
2422 ERR("Unhandled string type: %#x\n", *pFormat);
2423 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2426 pStubMsg->Offset = 0;
2427 WriteVariance(pStubMsg);
2429 size = safe_multiply(esize, pStubMsg->ActualCount);
2430 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2432 return NULL;
2435 /***********************************************************************
2436 * NdrNonConformantStringUnmarshall [RPCRT4.@]
2438 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2439 unsigned char **ppMemory,
2440 PFORMAT_STRING pFormat,
2441 unsigned char fMustAlloc)
2443 ULONG bufsize, memsize, esize, maxsize;
2445 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2446 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2448 maxsize = *(USHORT *)&pFormat[2];
2450 ReadVariance(pStubMsg, NULL, maxsize);
2451 if (pStubMsg->Offset)
2453 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2454 RpcRaiseException(RPC_S_INVALID_BOUND);
2457 if (*pFormat == RPC_FC_CSTRING) esize = 1;
2458 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2459 else
2461 ERR("Unhandled string type: %#x\n", *pFormat);
2462 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2465 memsize = esize * maxsize;
2466 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2468 validate_string_data(pStubMsg, bufsize, esize);
2470 if (!fMustAlloc && !*ppMemory)
2471 fMustAlloc = TRUE;
2472 if (fMustAlloc)
2473 *ppMemory = NdrAllocate(pStubMsg, memsize);
2475 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2477 if (*pFormat == RPC_FC_CSTRING) {
2478 TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2480 else if (*pFormat == RPC_FC_WSTRING) {
2481 TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2484 return NULL;
2487 /***********************************************************************
2488 * NdrNonConformantStringBufferSize [RPCRT4.@]
2490 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2491 unsigned char *pMemory,
2492 PFORMAT_STRING pFormat)
2494 ULONG esize, maxsize;
2496 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2498 maxsize = *(USHORT *)&pFormat[2];
2500 SizeVariance(pStubMsg);
2502 if (*pFormat == RPC_FC_CSTRING)
2504 ULONG i;
2505 const char *str = (const char *)pMemory;
2506 for (i = 0; i < maxsize && *str; i++, str++)
2508 TRACE("string=%s\n", debugstr_an(str, i));
2509 pStubMsg->ActualCount = i + 1;
2510 esize = 1;
2512 else if (*pFormat == RPC_FC_WSTRING)
2514 ULONG i;
2515 const WCHAR *str = (const WCHAR *)pMemory;
2516 for (i = 0; i < maxsize && *str; i++, str++)
2518 TRACE("string=%s\n", debugstr_wn(str, i));
2519 pStubMsg->ActualCount = i + 1;
2520 esize = 2;
2522 else
2524 ERR("Unhandled string type: %#x\n", *pFormat);
2525 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2528 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2531 /***********************************************************************
2532 * NdrNonConformantStringMemorySize [RPCRT4.@]
2534 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2535 PFORMAT_STRING pFormat)
2537 ULONG bufsize, memsize, esize, maxsize;
2539 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2541 maxsize = *(USHORT *)&pFormat[2];
2543 ReadVariance(pStubMsg, NULL, maxsize);
2545 if (pStubMsg->Offset)
2547 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2548 RpcRaiseException(RPC_S_INVALID_BOUND);
2551 if (*pFormat == RPC_FC_CSTRING) esize = 1;
2552 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2553 else
2555 ERR("Unhandled string type: %#x\n", *pFormat);
2556 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2559 memsize = esize * maxsize;
2560 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2562 validate_string_data(pStubMsg, bufsize, esize);
2564 safe_buffer_increment(pStubMsg, bufsize);
2565 pStubMsg->MemorySize += memsize;
2567 return pStubMsg->MemorySize;
2570 /* Complex types */
2572 #include "pshpack1.h"
2573 typedef struct
2575 unsigned char type;
2576 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2577 ULONG low_value;
2578 ULONG high_value;
2579 } NDR_RANGE;
2580 #include "poppack.h"
2582 static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2583 PFORMAT_STRING pFormat)
2585 switch (*pFormat) {
2586 case RPC_FC_STRUCT:
2587 case RPC_FC_PSTRUCT:
2588 case RPC_FC_CSTRUCT:
2589 case RPC_FC_BOGUS_STRUCT:
2590 case RPC_FC_SMFARRAY:
2591 case RPC_FC_SMVARRAY:
2592 case RPC_FC_CSTRING:
2593 return *(const WORD*)&pFormat[2];
2594 case RPC_FC_USER_MARSHAL:
2595 return *(const WORD*)&pFormat[4];
2596 case RPC_FC_RANGE: {
2597 switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2598 case RPC_FC_BYTE:
2599 case RPC_FC_CHAR:
2600 case RPC_FC_SMALL:
2601 case RPC_FC_USMALL:
2602 return sizeof(UCHAR);
2603 case RPC_FC_WCHAR:
2604 case RPC_FC_SHORT:
2605 case RPC_FC_USHORT:
2606 return sizeof(USHORT);
2607 case RPC_FC_LONG:
2608 case RPC_FC_ULONG:
2609 case RPC_FC_ENUM32:
2610 return sizeof(ULONG);
2611 case RPC_FC_FLOAT:
2612 return sizeof(float);
2613 case RPC_FC_DOUBLE:
2614 return sizeof(double);
2615 case RPC_FC_HYPER:
2616 return sizeof(ULONGLONG);
2617 case RPC_FC_ENUM16:
2618 return sizeof(UINT);
2619 default:
2620 ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2621 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2624 case RPC_FC_NON_ENCAPSULATED_UNION:
2625 pFormat += 2;
2626 if (pStubMsg->fHasNewCorrDesc)
2627 pFormat += 6;
2628 else
2629 pFormat += 4;
2631 pFormat += *(const SHORT*)pFormat;
2632 return *(const SHORT*)pFormat;
2633 case RPC_FC_IP:
2634 return sizeof(void *);
2635 case RPC_FC_WSTRING:
2636 return *(const WORD*)&pFormat[2] * 2;
2637 default:
2638 FIXME("unhandled embedded type %02x\n", *pFormat);
2640 return 0;
2644 static ULONG EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2645 PFORMAT_STRING pFormat)
2647 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2649 if (!m)
2651 FIXME("no memorysizer for data type=%02x\n", *pFormat);
2652 return 0;
2655 return m(pStubMsg, pFormat);
2659 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2660 unsigned char *pMemory,
2661 PFORMAT_STRING pFormat,
2662 PFORMAT_STRING pPointer)
2664 PFORMAT_STRING desc;
2665 NDR_MARSHALL m;
2666 ULONG size;
2668 while (*pFormat != RPC_FC_END) {
2669 switch (*pFormat) {
2670 case RPC_FC_BYTE:
2671 case RPC_FC_CHAR:
2672 case RPC_FC_SMALL:
2673 case RPC_FC_USMALL:
2674 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2675 safe_copy_to_buffer(pStubMsg, pMemory, 1);
2676 pMemory += 1;
2677 break;
2678 case RPC_FC_WCHAR:
2679 case RPC_FC_SHORT:
2680 case RPC_FC_USHORT:
2681 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2682 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2683 pMemory += 2;
2684 break;
2685 case RPC_FC_ENUM16:
2686 TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2687 if (32767 < *(DWORD*)pMemory)
2688 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2689 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2690 pMemory += 4;
2691 break;
2692 case RPC_FC_LONG:
2693 case RPC_FC_ULONG:
2694 case RPC_FC_ENUM32:
2695 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2696 safe_copy_to_buffer(pStubMsg, pMemory, 4);
2697 pMemory += 4;
2698 break;
2699 case RPC_FC_FLOAT:
2700 TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
2701 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
2702 pMemory += sizeof(float);
2703 break;
2704 case RPC_FC_HYPER:
2705 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2706 safe_copy_to_buffer(pStubMsg, pMemory, 8);
2707 pMemory += 8;
2708 break;
2709 case RPC_FC_DOUBLE:
2710 TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
2711 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
2712 pMemory += sizeof(double);
2713 break;
2714 case RPC_FC_RP:
2715 case RPC_FC_UP:
2716 case RPC_FC_OP:
2717 case RPC_FC_FP:
2718 case RPC_FC_POINTER:
2720 unsigned char *saved_buffer;
2721 int pointer_buffer_mark_set = 0;
2722 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2723 TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2724 if (*pFormat != RPC_FC_POINTER)
2725 pPointer = pFormat;
2726 if (*pPointer != RPC_FC_RP)
2727 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2728 saved_buffer = pStubMsg->Buffer;
2729 if (pStubMsg->PointerBufferMark)
2731 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2732 pStubMsg->PointerBufferMark = NULL;
2733 pointer_buffer_mark_set = 1;
2735 else if (*pPointer != RPC_FC_RP)
2736 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2737 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2738 if (pointer_buffer_mark_set)
2740 STD_OVERFLOW_CHECK(pStubMsg);
2741 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2742 pStubMsg->Buffer = saved_buffer;
2743 if (*pPointer != RPC_FC_RP)
2744 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2746 TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2747 if (*pFormat == RPC_FC_POINTER)
2748 pPointer += 4;
2749 else
2750 pFormat += 4;
2751 pMemory += sizeof(void *);
2752 break;
2754 case RPC_FC_ALIGNM2:
2755 ALIGN_POINTER(pMemory, 2);
2756 break;
2757 case RPC_FC_ALIGNM4:
2758 ALIGN_POINTER(pMemory, 4);
2759 break;
2760 case RPC_FC_ALIGNM8:
2761 ALIGN_POINTER(pMemory, 8);
2762 break;
2763 case RPC_FC_STRUCTPAD1:
2764 case RPC_FC_STRUCTPAD2:
2765 case RPC_FC_STRUCTPAD3:
2766 case RPC_FC_STRUCTPAD4:
2767 case RPC_FC_STRUCTPAD5:
2768 case RPC_FC_STRUCTPAD6:
2769 case RPC_FC_STRUCTPAD7:
2770 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2771 break;
2772 case RPC_FC_EMBEDDED_COMPLEX:
2773 pMemory += pFormat[1];
2774 pFormat += 2;
2775 desc = pFormat + *(const SHORT*)pFormat;
2776 size = EmbeddedComplexSize(pStubMsg, desc);
2777 TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2778 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2779 if (m)
2781 /* for some reason interface pointers aren't generated as
2782 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2783 * they still need the derefencing treatment that pointers are
2784 * given */
2785 if (*desc == RPC_FC_IP)
2786 m(pStubMsg, *(unsigned char **)pMemory, desc);
2787 else
2788 m(pStubMsg, pMemory, desc);
2790 else FIXME("no marshaller for embedded type %02x\n", *desc);
2791 pMemory += size;
2792 pFormat += 2;
2793 continue;
2794 case RPC_FC_PAD:
2795 break;
2796 default:
2797 FIXME("unhandled format 0x%02x\n", *pFormat);
2799 pFormat++;
2802 return pMemory;
2805 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2806 unsigned char *pMemory,
2807 PFORMAT_STRING pFormat,
2808 PFORMAT_STRING pPointer,
2809 unsigned char fMustAlloc)
2811 PFORMAT_STRING desc;
2812 NDR_UNMARSHALL m;
2813 ULONG size;
2815 while (*pFormat != RPC_FC_END) {
2816 switch (*pFormat) {
2817 case RPC_FC_BYTE:
2818 case RPC_FC_CHAR:
2819 case RPC_FC_SMALL:
2820 case RPC_FC_USMALL:
2821 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2822 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2823 pMemory += 1;
2824 break;
2825 case RPC_FC_WCHAR:
2826 case RPC_FC_SHORT:
2827 case RPC_FC_USHORT:
2828 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2829 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2830 pMemory += 2;
2831 break;
2832 case RPC_FC_ENUM16:
2833 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2834 *(DWORD*)pMemory &= 0xffff;
2835 TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2836 if (32767 < *(DWORD*)pMemory)
2837 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2838 pMemory += 4;
2839 break;
2840 case RPC_FC_LONG:
2841 case RPC_FC_ULONG:
2842 case RPC_FC_ENUM32:
2843 safe_copy_from_buffer(pStubMsg, pMemory, 4);
2844 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2845 pMemory += 4;
2846 break;
2847 case RPC_FC_FLOAT:
2848 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
2849 TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
2850 pMemory += sizeof(float);
2851 break;
2852 case RPC_FC_HYPER:
2853 safe_copy_from_buffer(pStubMsg, pMemory, 8);
2854 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2855 pMemory += 8;
2856 break;
2857 case RPC_FC_DOUBLE:
2858 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
2859 TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
2860 pMemory += sizeof(double);
2861 break;
2862 case RPC_FC_RP:
2863 case RPC_FC_UP:
2864 case RPC_FC_OP:
2865 case RPC_FC_FP:
2866 case RPC_FC_POINTER:
2868 unsigned char *saved_buffer;
2869 int pointer_buffer_mark_set = 0;
2870 TRACE("pointer => %p\n", pMemory);
2871 if (*pFormat != RPC_FC_POINTER)
2872 pPointer = pFormat;
2873 if (*pPointer != RPC_FC_RP)
2874 ALIGN_POINTER(pStubMsg->Buffer, 4);
2875 saved_buffer = pStubMsg->Buffer;
2876 if (pStubMsg->PointerBufferMark)
2878 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2879 pStubMsg->PointerBufferMark = NULL;
2880 pointer_buffer_mark_set = 1;
2882 else if (*pPointer != RPC_FC_RP)
2883 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2885 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
2886 if (pointer_buffer_mark_set)
2888 STD_OVERFLOW_CHECK(pStubMsg);
2889 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2890 pStubMsg->Buffer = saved_buffer;
2891 if (*pPointer != RPC_FC_RP)
2892 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2894 if (*pFormat == RPC_FC_POINTER)
2895 pPointer += 4;
2896 else
2897 pFormat += 4;
2898 pMemory += sizeof(void *);
2899 break;
2901 case RPC_FC_ALIGNM2:
2902 ALIGN_POINTER_CLEAR(pMemory, 2);
2903 break;
2904 case RPC_FC_ALIGNM4:
2905 ALIGN_POINTER_CLEAR(pMemory, 4);
2906 break;
2907 case RPC_FC_ALIGNM8:
2908 ALIGN_POINTER_CLEAR(pMemory, 8);
2909 break;
2910 case RPC_FC_STRUCTPAD1:
2911 case RPC_FC_STRUCTPAD2:
2912 case RPC_FC_STRUCTPAD3:
2913 case RPC_FC_STRUCTPAD4:
2914 case RPC_FC_STRUCTPAD5:
2915 case RPC_FC_STRUCTPAD6:
2916 case RPC_FC_STRUCTPAD7:
2917 memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2918 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2919 break;
2920 case RPC_FC_EMBEDDED_COMPLEX:
2921 pMemory += pFormat[1];
2922 pFormat += 2;
2923 desc = pFormat + *(const SHORT*)pFormat;
2924 size = EmbeddedComplexSize(pStubMsg, desc);
2925 TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
2926 if (fMustAlloc)
2927 /* we can't pass fMustAlloc=TRUE into the marshaller for this type
2928 * since the type is part of the memory block that is encompassed by
2929 * the whole complex type. Memory is forced to allocate when pointers
2930 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
2931 * clearing the memory we pass in to the unmarshaller */
2932 memset(pMemory, 0, size);
2933 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2934 if (m)
2936 /* for some reason interface pointers aren't generated as
2937 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2938 * they still need the derefencing treatment that pointers are
2939 * given */
2940 if (*desc == RPC_FC_IP)
2941 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2942 else
2943 m(pStubMsg, &pMemory, desc, FALSE);
2945 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2946 pMemory += size;
2947 pFormat += 2;
2948 continue;
2949 case RPC_FC_PAD:
2950 break;
2951 default:
2952 FIXME("unhandled format %d\n", *pFormat);
2954 pFormat++;
2957 return pMemory;
2960 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2961 unsigned char *pMemory,
2962 PFORMAT_STRING pFormat,
2963 PFORMAT_STRING pPointer)
2965 PFORMAT_STRING desc;
2966 NDR_BUFFERSIZE m;
2967 ULONG size;
2969 while (*pFormat != RPC_FC_END) {
2970 switch (*pFormat) {
2971 case RPC_FC_BYTE:
2972 case RPC_FC_CHAR:
2973 case RPC_FC_SMALL:
2974 case RPC_FC_USMALL:
2975 safe_buffer_length_increment(pStubMsg, 1);
2976 pMemory += 1;
2977 break;
2978 case RPC_FC_WCHAR:
2979 case RPC_FC_SHORT:
2980 case RPC_FC_USHORT:
2981 safe_buffer_length_increment(pStubMsg, 2);
2982 pMemory += 2;
2983 break;
2984 case RPC_FC_ENUM16:
2985 safe_buffer_length_increment(pStubMsg, 2);
2986 pMemory += 4;
2987 break;
2988 case RPC_FC_LONG:
2989 case RPC_FC_ULONG:
2990 case RPC_FC_ENUM32:
2991 case RPC_FC_FLOAT:
2992 safe_buffer_length_increment(pStubMsg, 4);
2993 pMemory += 4;
2994 break;
2995 case RPC_FC_HYPER:
2996 case RPC_FC_DOUBLE:
2997 safe_buffer_length_increment(pStubMsg, 8);
2998 pMemory += 8;
2999 break;
3000 case RPC_FC_RP:
3001 case RPC_FC_UP:
3002 case RPC_FC_OP:
3003 case RPC_FC_FP:
3004 case RPC_FC_POINTER:
3005 if (*pFormat != RPC_FC_POINTER)
3006 pPointer = pFormat;
3007 if (!pStubMsg->IgnoreEmbeddedPointers)
3009 int saved_buffer_length = pStubMsg->BufferLength;
3010 pStubMsg->BufferLength = pStubMsg->PointerLength;
3011 pStubMsg->PointerLength = 0;
3012 if(!pStubMsg->BufferLength)
3013 ERR("BufferLength == 0??\n");
3014 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
3015 pStubMsg->PointerLength = pStubMsg->BufferLength;
3016 pStubMsg->BufferLength = saved_buffer_length;
3018 if (*pPointer != RPC_FC_RP)
3020 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3021 safe_buffer_length_increment(pStubMsg, 4);
3023 if (*pFormat == RPC_FC_POINTER)
3024 pPointer += 4;
3025 else
3026 pFormat += 4;
3027 pMemory += sizeof(void*);
3028 break;
3029 case RPC_FC_ALIGNM2:
3030 ALIGN_POINTER(pMemory, 2);
3031 break;
3032 case RPC_FC_ALIGNM4:
3033 ALIGN_POINTER(pMemory, 4);
3034 break;
3035 case RPC_FC_ALIGNM8:
3036 ALIGN_POINTER(pMemory, 8);
3037 break;
3038 case RPC_FC_STRUCTPAD1:
3039 case RPC_FC_STRUCTPAD2:
3040 case RPC_FC_STRUCTPAD3:
3041 case RPC_FC_STRUCTPAD4:
3042 case RPC_FC_STRUCTPAD5:
3043 case RPC_FC_STRUCTPAD6:
3044 case RPC_FC_STRUCTPAD7:
3045 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3046 break;
3047 case RPC_FC_EMBEDDED_COMPLEX:
3048 pMemory += pFormat[1];
3049 pFormat += 2;
3050 desc = pFormat + *(const SHORT*)pFormat;
3051 size = EmbeddedComplexSize(pStubMsg, desc);
3052 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3053 if (m)
3055 /* for some reason interface pointers aren't generated as
3056 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3057 * they still need the derefencing treatment that pointers are
3058 * given */
3059 if (*desc == RPC_FC_IP)
3060 m(pStubMsg, *(unsigned char **)pMemory, desc);
3061 else
3062 m(pStubMsg, pMemory, desc);
3064 else FIXME("no buffersizer for embedded type %02x\n", *desc);
3065 pMemory += size;
3066 pFormat += 2;
3067 continue;
3068 case RPC_FC_PAD:
3069 break;
3070 default:
3071 FIXME("unhandled format 0x%02x\n", *pFormat);
3073 pFormat++;
3076 return pMemory;
3079 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
3080 unsigned char *pMemory,
3081 PFORMAT_STRING pFormat,
3082 PFORMAT_STRING pPointer)
3084 PFORMAT_STRING desc;
3085 NDR_FREE m;
3086 ULONG size;
3088 while (*pFormat != RPC_FC_END) {
3089 switch (*pFormat) {
3090 case RPC_FC_BYTE:
3091 case RPC_FC_CHAR:
3092 case RPC_FC_SMALL:
3093 case RPC_FC_USMALL:
3094 pMemory += 1;
3095 break;
3096 case RPC_FC_WCHAR:
3097 case RPC_FC_SHORT:
3098 case RPC_FC_USHORT:
3099 pMemory += 2;
3100 break;
3101 case RPC_FC_LONG:
3102 case RPC_FC_ULONG:
3103 case RPC_FC_ENUM16:
3104 case RPC_FC_ENUM32:
3105 case RPC_FC_FLOAT:
3106 pMemory += 4;
3107 break;
3108 case RPC_FC_HYPER:
3109 case RPC_FC_DOUBLE:
3110 pMemory += 8;
3111 break;
3112 case RPC_FC_RP:
3113 case RPC_FC_UP:
3114 case RPC_FC_OP:
3115 case RPC_FC_FP:
3116 case RPC_FC_POINTER:
3117 if (*pFormat != RPC_FC_POINTER)
3118 pPointer = pFormat;
3119 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3120 if (*pFormat == RPC_FC_POINTER)
3121 pPointer += 4;
3122 else
3123 pFormat += 4;
3124 pMemory += sizeof(void *);
3125 break;
3126 case RPC_FC_ALIGNM2:
3127 ALIGN_POINTER(pMemory, 2);
3128 break;
3129 case RPC_FC_ALIGNM4:
3130 ALIGN_POINTER(pMemory, 4);
3131 break;
3132 case RPC_FC_ALIGNM8:
3133 ALIGN_POINTER(pMemory, 8);
3134 break;
3135 case RPC_FC_STRUCTPAD1:
3136 case RPC_FC_STRUCTPAD2:
3137 case RPC_FC_STRUCTPAD3:
3138 case RPC_FC_STRUCTPAD4:
3139 case RPC_FC_STRUCTPAD5:
3140 case RPC_FC_STRUCTPAD6:
3141 case RPC_FC_STRUCTPAD7:
3142 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3143 break;
3144 case RPC_FC_EMBEDDED_COMPLEX:
3145 pMemory += pFormat[1];
3146 pFormat += 2;
3147 desc = pFormat + *(const SHORT*)pFormat;
3148 size = EmbeddedComplexSize(pStubMsg, desc);
3149 m = NdrFreer[*desc & NDR_TABLE_MASK];
3150 if (m)
3152 /* for some reason interface pointers aren't generated as
3153 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3154 * they still need the derefencing treatment that pointers are
3155 * given */
3156 if (*desc == RPC_FC_IP)
3157 m(pStubMsg, *(unsigned char **)pMemory, desc);
3158 else
3159 m(pStubMsg, pMemory, desc);
3161 pMemory += size;
3162 pFormat += 2;
3163 continue;
3164 case RPC_FC_PAD:
3165 break;
3166 default:
3167 FIXME("unhandled format 0x%02x\n", *pFormat);
3169 pFormat++;
3172 return pMemory;
3175 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3176 PFORMAT_STRING pFormat,
3177 PFORMAT_STRING pPointer)
3179 PFORMAT_STRING desc;
3180 ULONG size = 0;
3182 while (*pFormat != RPC_FC_END) {
3183 switch (*pFormat) {
3184 case RPC_FC_BYTE:
3185 case RPC_FC_CHAR:
3186 case RPC_FC_SMALL:
3187 case RPC_FC_USMALL:
3188 size += 1;
3189 safe_buffer_increment(pStubMsg, 1);
3190 break;
3191 case RPC_FC_WCHAR:
3192 case RPC_FC_SHORT:
3193 case RPC_FC_USHORT:
3194 size += 2;
3195 safe_buffer_increment(pStubMsg, 2);
3196 break;
3197 case RPC_FC_ENUM16:
3198 size += 4;
3199 safe_buffer_increment(pStubMsg, 2);
3200 break;
3201 case RPC_FC_LONG:
3202 case RPC_FC_ULONG:
3203 case RPC_FC_ENUM32:
3204 case RPC_FC_FLOAT:
3205 size += 4;
3206 safe_buffer_increment(pStubMsg, 4);
3207 break;
3208 case RPC_FC_HYPER:
3209 case RPC_FC_DOUBLE:
3210 size += 8;
3211 safe_buffer_increment(pStubMsg, 8);
3212 break;
3213 case RPC_FC_RP:
3214 case RPC_FC_UP:
3215 case RPC_FC_OP:
3216 case RPC_FC_FP:
3217 case RPC_FC_POINTER:
3219 unsigned char *saved_buffer;
3220 int pointer_buffer_mark_set = 0;
3221 if (*pFormat != RPC_FC_POINTER)
3222 pPointer = pFormat;
3223 if (*pPointer != RPC_FC_RP)
3224 ALIGN_POINTER(pStubMsg->Buffer, 4);
3225 saved_buffer = pStubMsg->Buffer;
3226 if (pStubMsg->PointerBufferMark)
3228 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3229 pStubMsg->PointerBufferMark = NULL;
3230 pointer_buffer_mark_set = 1;
3232 else if (*pPointer != RPC_FC_RP)
3233 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3235 if (!pStubMsg->IgnoreEmbeddedPointers)
3236 PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3237 if (pointer_buffer_mark_set)
3239 STD_OVERFLOW_CHECK(pStubMsg);
3240 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3241 pStubMsg->Buffer = saved_buffer;
3242 if (*pPointer != RPC_FC_RP)
3243 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3245 if (*pFormat == RPC_FC_POINTER)
3246 pPointer += 4;
3247 else
3248 pFormat += 4;
3249 size += sizeof(void *);
3250 break;
3252 case RPC_FC_ALIGNM2:
3253 ALIGN_LENGTH(size, 2);
3254 break;
3255 case RPC_FC_ALIGNM4:
3256 ALIGN_LENGTH(size, 4);
3257 break;
3258 case RPC_FC_ALIGNM8:
3259 ALIGN_LENGTH(size, 8);
3260 break;
3261 case RPC_FC_STRUCTPAD1:
3262 case RPC_FC_STRUCTPAD2:
3263 case RPC_FC_STRUCTPAD3:
3264 case RPC_FC_STRUCTPAD4:
3265 case RPC_FC_STRUCTPAD5:
3266 case RPC_FC_STRUCTPAD6:
3267 case RPC_FC_STRUCTPAD7:
3268 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3269 break;
3270 case RPC_FC_EMBEDDED_COMPLEX:
3271 size += pFormat[1];
3272 pFormat += 2;
3273 desc = pFormat + *(const SHORT*)pFormat;
3274 size += EmbeddedComplexMemorySize(pStubMsg, desc);
3275 pFormat += 2;
3276 continue;
3277 case RPC_FC_PAD:
3278 break;
3279 default:
3280 FIXME("unhandled format 0x%02x\n", *pFormat);
3282 pFormat++;
3285 return size;
3288 ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
3290 PFORMAT_STRING desc;
3291 ULONG size = 0;
3293 while (*pFormat != RPC_FC_END) {
3294 switch (*pFormat) {
3295 case RPC_FC_BYTE:
3296 case RPC_FC_CHAR:
3297 case RPC_FC_SMALL:
3298 case RPC_FC_USMALL:
3299 size += 1;
3300 break;
3301 case RPC_FC_WCHAR:
3302 case RPC_FC_SHORT:
3303 case RPC_FC_USHORT:
3304 size += 2;
3305 break;
3306 case RPC_FC_LONG:
3307 case RPC_FC_ULONG:
3308 case RPC_FC_ENUM16:
3309 case RPC_FC_ENUM32:
3310 case RPC_FC_FLOAT:
3311 size += 4;
3312 break;
3313 case RPC_FC_HYPER:
3314 case RPC_FC_DOUBLE:
3315 size += 8;
3316 break;
3317 case RPC_FC_RP:
3318 case RPC_FC_UP:
3319 case RPC_FC_OP:
3320 case RPC_FC_FP:
3321 case RPC_FC_POINTER:
3322 size += sizeof(void *);
3323 if (*pFormat != RPC_FC_POINTER)
3324 pFormat += 4;
3325 break;
3326 case RPC_FC_ALIGNM2:
3327 ALIGN_LENGTH(size, 2);
3328 break;
3329 case RPC_FC_ALIGNM4:
3330 ALIGN_LENGTH(size, 4);
3331 break;
3332 case RPC_FC_ALIGNM8:
3333 ALIGN_LENGTH(size, 8);
3334 break;
3335 case RPC_FC_STRUCTPAD1:
3336 case RPC_FC_STRUCTPAD2:
3337 case RPC_FC_STRUCTPAD3:
3338 case RPC_FC_STRUCTPAD4:
3339 case RPC_FC_STRUCTPAD5:
3340 case RPC_FC_STRUCTPAD6:
3341 case RPC_FC_STRUCTPAD7:
3342 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3343 break;
3344 case RPC_FC_EMBEDDED_COMPLEX:
3345 size += pFormat[1];
3346 pFormat += 2;
3347 desc = pFormat + *(const SHORT*)pFormat;
3348 size += EmbeddedComplexSize(pStubMsg, desc);
3349 pFormat += 2;
3350 continue;
3351 case RPC_FC_PAD:
3352 break;
3353 default:
3354 FIXME("unhandled format 0x%02x\n", *pFormat);
3356 pFormat++;
3359 return size;
3362 /***********************************************************************
3363 * NdrComplexStructMarshall [RPCRT4.@]
3365 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3366 unsigned char *pMemory,
3367 PFORMAT_STRING pFormat)
3369 PFORMAT_STRING conf_array = NULL;
3370 PFORMAT_STRING pointer_desc = NULL;
3371 unsigned char *OldMemory = pStubMsg->Memory;
3372 int pointer_buffer_mark_set = 0;
3373 ULONG count = 0;
3374 ULONG max_count = 0;
3375 ULONG offset = 0;
3377 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3379 if (!pStubMsg->PointerBufferMark)
3381 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3382 /* save buffer length */
3383 ULONG saved_buffer_length = pStubMsg->BufferLength;
3385 /* get the buffer pointer after complex array data, but before
3386 * pointer data */
3387 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3388 pStubMsg->IgnoreEmbeddedPointers = 1;
3389 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3390 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3392 /* save it for use by embedded pointer code later */
3393 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3394 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
3395 pointer_buffer_mark_set = 1;
3397 /* restore the original buffer length */
3398 pStubMsg->BufferLength = saved_buffer_length;
3401 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
3403 pFormat += 4;
3404 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3405 pFormat += 2;
3406 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3407 pFormat += 2;
3409 pStubMsg->Memory = pMemory;
3411 if (conf_array)
3413 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3414 array_compute_and_write_conformance(conf_array[0], pStubMsg,
3415 pMemory + struct_size, conf_array);
3416 /* these could be changed in ComplexMarshall so save them for later */
3417 max_count = pStubMsg->MaxCount;
3418 count = pStubMsg->ActualCount;
3419 offset = pStubMsg->Offset;
3422 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3424 if (conf_array)
3426 pStubMsg->MaxCount = max_count;
3427 pStubMsg->ActualCount = count;
3428 pStubMsg->Offset = offset;
3429 array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3430 conf_array, TRUE /* fHasPointers */);
3433 pStubMsg->Memory = OldMemory;
3435 if (pointer_buffer_mark_set)
3437 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3438 pStubMsg->PointerBufferMark = NULL;
3441 STD_OVERFLOW_CHECK(pStubMsg);
3443 return NULL;
3446 /***********************************************************************
3447 * NdrComplexStructUnmarshall [RPCRT4.@]
3449 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3450 unsigned char **ppMemory,
3451 PFORMAT_STRING pFormat,
3452 unsigned char fMustAlloc)
3454 unsigned size = *(const WORD*)(pFormat+2);
3455 PFORMAT_STRING conf_array = NULL;
3456 PFORMAT_STRING pointer_desc = NULL;
3457 unsigned char *pMemory;
3458 int pointer_buffer_mark_set = 0;
3459 ULONG count = 0;
3460 ULONG max_count = 0;
3461 ULONG offset = 0;
3462 ULONG array_size = 0;
3464 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3466 if (!pStubMsg->PointerBufferMark)
3468 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3469 /* save buffer pointer */
3470 unsigned char *saved_buffer = pStubMsg->Buffer;
3472 /* get the buffer pointer after complex array data, but before
3473 * pointer data */
3474 pStubMsg->IgnoreEmbeddedPointers = 1;
3475 NdrComplexStructMemorySize(pStubMsg, pFormat);
3476 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3478 /* save it for use by embedded pointer code later */
3479 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3480 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
3481 pointer_buffer_mark_set = 1;
3483 /* restore the original buffer */
3484 pStubMsg->Buffer = saved_buffer;
3487 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3489 pFormat += 4;
3490 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3491 pFormat += 2;
3492 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3493 pFormat += 2;
3495 if (conf_array)
3497 array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3498 size += array_size;
3500 /* these could be changed in ComplexMarshall so save them for later */
3501 max_count = pStubMsg->MaxCount;
3502 count = pStubMsg->ActualCount;
3503 offset = pStubMsg->Offset;
3506 if (!fMustAlloc && !*ppMemory)
3507 fMustAlloc = TRUE;
3508 if (fMustAlloc)
3509 *ppMemory = NdrAllocate(pStubMsg, size);
3511 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3513 if (conf_array)
3515 pStubMsg->MaxCount = max_count;
3516 pStubMsg->ActualCount = count;
3517 pStubMsg->Offset = offset;
3518 if (fMustAlloc)
3519 memset(pMemory, 0, array_size);
3520 array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3521 conf_array, FALSE,
3522 FALSE /* fUseBufferMemoryServer */,
3523 TRUE /* fUnmarshall */);
3526 if (pointer_buffer_mark_set)
3528 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3529 pStubMsg->PointerBufferMark = NULL;
3532 return NULL;
3535 /***********************************************************************
3536 * NdrComplexStructBufferSize [RPCRT4.@]
3538 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3539 unsigned char *pMemory,
3540 PFORMAT_STRING pFormat)
3542 PFORMAT_STRING conf_array = NULL;
3543 PFORMAT_STRING pointer_desc = NULL;
3544 unsigned char *OldMemory = pStubMsg->Memory;
3545 int pointer_length_set = 0;
3546 ULONG count = 0;
3547 ULONG max_count = 0;
3548 ULONG offset = 0;
3550 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3552 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
3554 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3556 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3557 ULONG saved_buffer_length = pStubMsg->BufferLength;
3559 /* get the buffer length after complex struct data, but before
3560 * pointer data */
3561 pStubMsg->IgnoreEmbeddedPointers = 1;
3562 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3563 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3565 /* save it for use by embedded pointer code later */
3566 pStubMsg->PointerLength = pStubMsg->BufferLength;
3567 pointer_length_set = 1;
3568 TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
3570 /* restore the original buffer length */
3571 pStubMsg->BufferLength = saved_buffer_length;
3574 pFormat += 4;
3575 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3576 pFormat += 2;
3577 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3578 pFormat += 2;
3580 pStubMsg->Memory = pMemory;
3582 if (conf_array)
3584 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3585 array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3586 conf_array);
3588 /* these could be changed in ComplexMarshall so save them for later */
3589 max_count = pStubMsg->MaxCount;
3590 count = pStubMsg->ActualCount;
3591 offset = pStubMsg->Offset;
3594 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3596 if (conf_array)
3598 pStubMsg->MaxCount = max_count;
3599 pStubMsg->ActualCount = count;
3600 pStubMsg->Offset = offset;
3601 array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3602 TRUE /* fHasPointers */);
3605 pStubMsg->Memory = OldMemory;
3607 if(pointer_length_set)
3609 pStubMsg->BufferLength = pStubMsg->PointerLength;
3610 pStubMsg->PointerLength = 0;
3615 /***********************************************************************
3616 * NdrComplexStructMemorySize [RPCRT4.@]
3618 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3619 PFORMAT_STRING pFormat)
3621 unsigned size = *(const WORD*)(pFormat+2);
3622 PFORMAT_STRING conf_array = NULL;
3623 PFORMAT_STRING pointer_desc = NULL;
3624 ULONG count = 0;
3625 ULONG max_count = 0;
3626 ULONG offset = 0;
3628 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3630 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3632 pFormat += 4;
3633 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3634 pFormat += 2;
3635 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3636 pFormat += 2;
3638 if (conf_array)
3640 array_read_conformance(conf_array[0], pStubMsg, conf_array);
3642 /* these could be changed in ComplexStructMemorySize so save them for
3643 * later */
3644 max_count = pStubMsg->MaxCount;
3645 count = pStubMsg->ActualCount;
3646 offset = pStubMsg->Offset;
3649 ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3651 if (conf_array)
3653 pStubMsg->MaxCount = max_count;
3654 pStubMsg->ActualCount = count;
3655 pStubMsg->Offset = offset;
3656 array_memory_size(conf_array[0], pStubMsg, conf_array,
3657 TRUE /* fHasPointers */);
3660 return size;
3663 /***********************************************************************
3664 * NdrComplexStructFree [RPCRT4.@]
3666 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3667 unsigned char *pMemory,
3668 PFORMAT_STRING pFormat)
3670 PFORMAT_STRING conf_array = NULL;
3671 PFORMAT_STRING pointer_desc = NULL;
3672 unsigned char *OldMemory = pStubMsg->Memory;
3674 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3676 pFormat += 4;
3677 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3678 pFormat += 2;
3679 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3680 pFormat += 2;
3682 pStubMsg->Memory = pMemory;
3684 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3686 if (conf_array)
3687 array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3688 TRUE /* fHasPointers */);
3690 pStubMsg->Memory = OldMemory;
3693 /***********************************************************************
3694 * NdrConformantArrayMarshall [RPCRT4.@]
3696 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3697 unsigned char *pMemory,
3698 PFORMAT_STRING pFormat)
3700 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3701 if (pFormat[0] != RPC_FC_CARRAY)
3703 ERR("invalid format = 0x%x\n", pFormat[0]);
3704 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3707 array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
3708 pFormat);
3709 array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3710 TRUE /* fHasPointers */);
3712 return NULL;
3715 /***********************************************************************
3716 * NdrConformantArrayUnmarshall [RPCRT4.@]
3718 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3719 unsigned char **ppMemory,
3720 PFORMAT_STRING pFormat,
3721 unsigned char fMustAlloc)
3723 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3724 if (pFormat[0] != RPC_FC_CARRAY)
3726 ERR("invalid format = 0x%x\n", pFormat[0]);
3727 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3730 array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3731 array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
3732 fMustAlloc,
3733 TRUE /* fUseBufferMemoryServer */,
3734 TRUE /* fUnmarshall */);
3736 return NULL;
3739 /***********************************************************************
3740 * NdrConformantArrayBufferSize [RPCRT4.@]
3742 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3743 unsigned char *pMemory,
3744 PFORMAT_STRING pFormat)
3746 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3747 if (pFormat[0] != RPC_FC_CARRAY)
3749 ERR("invalid format = 0x%x\n", pFormat[0]);
3750 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3753 array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat);
3754 array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3755 TRUE /* fHasPointers */);
3758 /***********************************************************************
3759 * NdrConformantArrayMemorySize [RPCRT4.@]
3761 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3762 PFORMAT_STRING pFormat)
3764 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3765 if (pFormat[0] != RPC_FC_CARRAY)
3767 ERR("invalid format = 0x%x\n", pFormat[0]);
3768 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3771 array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3772 array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
3774 return pStubMsg->MemorySize;
3777 /***********************************************************************
3778 * NdrConformantArrayFree [RPCRT4.@]
3780 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3781 unsigned char *pMemory,
3782 PFORMAT_STRING pFormat)
3784 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3785 if (pFormat[0] != RPC_FC_CARRAY)
3787 ERR("invalid format = 0x%x\n", pFormat[0]);
3788 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3791 array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3792 TRUE /* fHasPointers */);
3796 /***********************************************************************
3797 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
3799 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
3800 unsigned char* pMemory,
3801 PFORMAT_STRING pFormat )
3803 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3805 if (pFormat[0] != RPC_FC_CVARRAY)
3807 ERR("invalid format type %x\n", pFormat[0]);
3808 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3809 return NULL;
3812 array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3813 pFormat);
3814 array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory,
3815 pFormat, TRUE /* fHasPointers */);
3817 return NULL;
3821 /***********************************************************************
3822 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
3824 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
3825 unsigned char** ppMemory,
3826 PFORMAT_STRING pFormat,
3827 unsigned char fMustAlloc )
3829 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3831 if (pFormat[0] != RPC_FC_CVARRAY)
3833 ERR("invalid format type %x\n", pFormat[0]);
3834 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3835 return NULL;
3838 array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3839 array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory,
3840 pFormat, fMustAlloc,
3841 TRUE /* fUseBufferMemoryServer */,
3842 TRUE /* fUnmarshall */);
3844 return NULL;
3848 /***********************************************************************
3849 * NdrConformantVaryingArrayFree [RPCRT4.@]
3851 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
3852 unsigned char* pMemory,
3853 PFORMAT_STRING pFormat )
3855 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3857 if (pFormat[0] != RPC_FC_CVARRAY)
3859 ERR("invalid format type %x\n", pFormat[0]);
3860 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3861 return;
3864 array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3865 TRUE /* fHasPointers */);
3869 /***********************************************************************
3870 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
3872 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
3873 unsigned char* pMemory, PFORMAT_STRING pFormat )
3875 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3877 if (pFormat[0] != RPC_FC_CVARRAY)
3879 ERR("invalid format type %x\n", pFormat[0]);
3880 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3881 return;
3884 array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3885 pFormat);
3886 array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3887 TRUE /* fHasPointers */);
3891 /***********************************************************************
3892 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
3894 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
3895 PFORMAT_STRING pFormat )
3897 TRACE("(%p, %p)\n", pStubMsg, pFormat);
3899 if (pFormat[0] != RPC_FC_CVARRAY)
3901 ERR("invalid format type %x\n", pFormat[0]);
3902 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3903 return pStubMsg->MemorySize;
3906 array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3907 array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat,
3908 TRUE /* fHasPointers */);
3910 return pStubMsg->MemorySize;
3914 /***********************************************************************
3915 * NdrComplexArrayMarshall [RPCRT4.@]
3917 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3918 unsigned char *pMemory,
3919 PFORMAT_STRING pFormat)
3921 ULONG i, count, def;
3922 BOOL variance_present;
3923 unsigned char alignment;
3924 int pointer_buffer_mark_set = 0;
3926 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3928 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3930 ERR("invalid format type %x\n", pFormat[0]);
3931 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3932 return NULL;
3935 alignment = pFormat[1] + 1;
3937 if (!pStubMsg->PointerBufferMark)
3939 /* save buffer fields that may be changed by buffer sizer functions
3940 * and that may be needed later on */
3941 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3942 ULONG saved_buffer_length = pStubMsg->BufferLength;
3943 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
3944 ULONG saved_offset = pStubMsg->Offset;
3945 ULONG saved_actual_count = pStubMsg->ActualCount;
3947 /* get the buffer pointer after complex array data, but before
3948 * pointer data */
3949 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3950 pStubMsg->IgnoreEmbeddedPointers = 1;
3951 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3952 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3954 /* save it for use by embedded pointer code later */
3955 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3956 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
3957 pointer_buffer_mark_set = 1;
3959 /* restore fields */
3960 pStubMsg->ActualCount = saved_actual_count;
3961 pStubMsg->Offset = saved_offset;
3962 pStubMsg->MaxCount = saved_max_count;
3963 pStubMsg->BufferLength = saved_buffer_length;
3966 def = *(const WORD*)&pFormat[2];
3967 pFormat += 4;
3969 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3970 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3972 variance_present = IsConformanceOrVariancePresent(pFormat);
3973 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3974 TRACE("variance = %d\n", pStubMsg->ActualCount);
3976 WriteConformance(pStubMsg);
3977 if (variance_present)
3978 WriteVariance(pStubMsg);
3980 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3982 count = pStubMsg->ActualCount;
3983 for (i = 0; i < count; i++)
3984 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3986 STD_OVERFLOW_CHECK(pStubMsg);
3988 if (pointer_buffer_mark_set)
3990 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3991 pStubMsg->PointerBufferMark = NULL;
3994 return NULL;
3997 /***********************************************************************
3998 * NdrComplexArrayUnmarshall [RPCRT4.@]
4000 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4001 unsigned char **ppMemory,
4002 PFORMAT_STRING pFormat,
4003 unsigned char fMustAlloc)
4005 ULONG i, count, size;
4006 unsigned char alignment;
4007 unsigned char *pMemory;
4008 unsigned char *saved_buffer;
4009 int pointer_buffer_mark_set = 0;
4010 int saved_ignore_embedded;
4012 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4014 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4016 ERR("invalid format type %x\n", pFormat[0]);
4017 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4018 return NULL;
4021 alignment = pFormat[1] + 1;
4023 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4024 /* save buffer pointer */
4025 saved_buffer = pStubMsg->Buffer;
4026 /* get the buffer pointer after complex array data, but before
4027 * pointer data */
4028 pStubMsg->IgnoreEmbeddedPointers = 1;
4029 pStubMsg->MemorySize = 0;
4030 NdrComplexArrayMemorySize(pStubMsg, pFormat);
4031 size = pStubMsg->MemorySize;
4032 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4034 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer));
4035 if (!pStubMsg->PointerBufferMark)
4037 /* save it for use by embedded pointer code later */
4038 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4039 pointer_buffer_mark_set = 1;
4041 /* restore the original buffer */
4042 pStubMsg->Buffer = saved_buffer;
4044 pFormat += 4;
4046 pFormat = ReadConformance(pStubMsg, pFormat);
4047 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
4049 if (!fMustAlloc && !*ppMemory)
4050 fMustAlloc = TRUE;
4051 if (fMustAlloc)
4052 *ppMemory = NdrAllocate(pStubMsg, size);
4054 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4056 pMemory = *ppMemory;
4057 count = pStubMsg->ActualCount;
4058 for (i = 0; i < count; i++)
4059 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
4061 if (pointer_buffer_mark_set)
4063 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4064 pStubMsg->PointerBufferMark = NULL;
4067 return NULL;
4070 /***********************************************************************
4071 * NdrComplexArrayBufferSize [RPCRT4.@]
4073 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4074 unsigned char *pMemory,
4075 PFORMAT_STRING pFormat)
4077 ULONG i, count, def;
4078 unsigned char alignment;
4079 BOOL variance_present;
4080 int pointer_length_set = 0;
4082 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4084 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4086 ERR("invalid format type %x\n", pFormat[0]);
4087 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4088 return;
4091 alignment = pFormat[1] + 1;
4093 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
4095 /* save buffer fields that may be changed by buffer sizer functions
4096 * and that may be needed later on */
4097 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4098 ULONG saved_buffer_length = pStubMsg->BufferLength;
4099 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4100 ULONG saved_offset = pStubMsg->Offset;
4101 ULONG saved_actual_count = pStubMsg->ActualCount;
4103 /* get the buffer pointer after complex array data, but before
4104 * pointer data */
4105 pStubMsg->IgnoreEmbeddedPointers = 1;
4106 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4107 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4109 /* save it for use by embedded pointer code later */
4110 pStubMsg->PointerLength = pStubMsg->BufferLength;
4111 pointer_length_set = 1;
4113 /* restore fields */
4114 pStubMsg->ActualCount = saved_actual_count;
4115 pStubMsg->Offset = saved_offset;
4116 pStubMsg->MaxCount = saved_max_count;
4117 pStubMsg->BufferLength = saved_buffer_length;
4119 def = *(const WORD*)&pFormat[2];
4120 pFormat += 4;
4122 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4123 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4124 SizeConformance(pStubMsg);
4126 variance_present = IsConformanceOrVariancePresent(pFormat);
4127 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4128 TRACE("variance = %d\n", pStubMsg->ActualCount);
4130 if (variance_present)
4131 SizeVariance(pStubMsg);
4133 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4135 count = pStubMsg->ActualCount;
4136 for (i = 0; i < count; i++)
4137 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
4139 if(pointer_length_set)
4141 pStubMsg->BufferLength = pStubMsg->PointerLength;
4142 pStubMsg->PointerLength = 0;
4146 /***********************************************************************
4147 * NdrComplexArrayMemorySize [RPCRT4.@]
4149 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4150 PFORMAT_STRING pFormat)
4152 ULONG i, count, esize, SavedMemorySize, MemorySize;
4153 unsigned char alignment;
4155 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4157 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4159 ERR("invalid format type %x\n", pFormat[0]);
4160 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4161 return 0;
4164 alignment = pFormat[1] + 1;
4166 pFormat += 4;
4168 pFormat = ReadConformance(pStubMsg, pFormat);
4169 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
4171 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4173 SavedMemorySize = pStubMsg->MemorySize;
4175 esize = ComplexStructSize(pStubMsg, pFormat);
4177 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
4179 count = pStubMsg->ActualCount;
4180 for (i = 0; i < count; i++)
4181 ComplexStructMemorySize(pStubMsg, pFormat, NULL);
4183 pStubMsg->MemorySize = SavedMemorySize;
4185 pStubMsg->MemorySize += MemorySize;
4186 return MemorySize;
4189 /***********************************************************************
4190 * NdrComplexArrayFree [RPCRT4.@]
4192 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4193 unsigned char *pMemory,
4194 PFORMAT_STRING pFormat)
4196 ULONG i, count, def;
4198 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4200 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4202 ERR("invalid format type %x\n", pFormat[0]);
4203 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4204 return;
4207 def = *(const WORD*)&pFormat[2];
4208 pFormat += 4;
4210 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4211 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4213 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4214 TRACE("variance = %d\n", pStubMsg->ActualCount);
4216 count = pStubMsg->ActualCount;
4217 for (i = 0; i < count; i++)
4218 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
4221 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
4222 USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
4223 USER_MARSHAL_CB *umcb)
4225 umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
4226 pStubMsg->RpcMsg->DataRepresentation);
4227 umcb->pStubMsg = pStubMsg;
4228 umcb->pReserve = NULL;
4229 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
4230 umcb->CBType = cbtype;
4231 umcb->pFormat = pFormat;
4232 umcb->pTypeFormat = NULL /* FIXME */;
4235 #define USER_MARSHAL_PTR_PREFIX \
4236 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
4237 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
4239 /***********************************************************************
4240 * NdrUserMarshalMarshall [RPCRT4.@]
4242 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4243 unsigned char *pMemory,
4244 PFORMAT_STRING pFormat)
4246 unsigned flags = pFormat[1];
4247 unsigned index = *(const WORD*)&pFormat[2];
4248 unsigned char *saved_buffer = NULL;
4249 USER_MARSHAL_CB umcb;
4251 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4252 TRACE("index=%d\n", index);
4254 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
4256 if (flags & USER_MARSHAL_POINTER)
4258 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
4259 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
4260 pStubMsg->Buffer += 4;
4261 if (pStubMsg->PointerBufferMark)
4263 saved_buffer = pStubMsg->Buffer;
4264 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4265 pStubMsg->PointerBufferMark = NULL;
4267 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8);
4269 else
4270 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1);
4272 pStubMsg->Buffer =
4273 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
4274 &umcb.Flags, pStubMsg->Buffer, pMemory);
4276 if (saved_buffer)
4278 STD_OVERFLOW_CHECK(pStubMsg);
4279 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4280 pStubMsg->Buffer = saved_buffer;
4283 STD_OVERFLOW_CHECK(pStubMsg);
4285 return NULL;
4288 /***********************************************************************
4289 * NdrUserMarshalUnmarshall [RPCRT4.@]
4291 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4292 unsigned char **ppMemory,
4293 PFORMAT_STRING pFormat,
4294 unsigned char fMustAlloc)
4296 unsigned flags = pFormat[1];
4297 unsigned index = *(const WORD*)&pFormat[2];
4298 DWORD memsize = *(const WORD*)&pFormat[4];
4299 unsigned char *saved_buffer = NULL;
4300 USER_MARSHAL_CB umcb;
4302 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4303 TRACE("index=%d\n", index);
4305 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
4307 if (flags & USER_MARSHAL_POINTER)
4309 ALIGN_POINTER(pStubMsg->Buffer, 4);
4310 /* skip pointer prefix */
4311 pStubMsg->Buffer += 4;
4312 if (pStubMsg->PointerBufferMark)
4314 saved_buffer = pStubMsg->Buffer;
4315 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4316 pStubMsg->PointerBufferMark = NULL;
4318 ALIGN_POINTER(pStubMsg->Buffer, 8);
4320 else
4321 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4323 if (!fMustAlloc && !*ppMemory)
4324 fMustAlloc = TRUE;
4325 if (fMustAlloc)
4327 *ppMemory = NdrAllocate(pStubMsg, memsize);
4328 memset(*ppMemory, 0, memsize);
4331 pStubMsg->Buffer =
4332 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
4333 &umcb.Flags, pStubMsg->Buffer, *ppMemory);
4335 if (saved_buffer)
4337 STD_OVERFLOW_CHECK(pStubMsg);
4338 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4339 pStubMsg->Buffer = saved_buffer;
4342 return NULL;
4345 /***********************************************************************
4346 * NdrUserMarshalBufferSize [RPCRT4.@]
4348 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4349 unsigned char *pMemory,
4350 PFORMAT_STRING pFormat)
4352 unsigned flags = pFormat[1];
4353 unsigned index = *(const WORD*)&pFormat[2];
4354 DWORD bufsize = *(const WORD*)&pFormat[6];
4355 USER_MARSHAL_CB umcb;
4356 ULONG saved_buffer_length = 0;
4358 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4359 TRACE("index=%d\n", index);
4361 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
4363 if (flags & USER_MARSHAL_POINTER)
4365 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4366 /* skip pointer prefix */
4367 safe_buffer_length_increment(pStubMsg, 4);
4368 if (pStubMsg->IgnoreEmbeddedPointers)
4369 return;
4370 if (pStubMsg->PointerLength)
4372 saved_buffer_length = pStubMsg->BufferLength;
4373 pStubMsg->BufferLength = pStubMsg->PointerLength;
4374 pStubMsg->PointerLength = 0;
4376 ALIGN_LENGTH(pStubMsg->BufferLength, 8);
4378 else
4379 ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
4381 if (bufsize) {
4382 TRACE("size=%d\n", bufsize);
4383 safe_buffer_length_increment(pStubMsg, bufsize);
4385 else
4386 pStubMsg->BufferLength =
4387 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
4388 &umcb.Flags, pStubMsg->BufferLength, pMemory);
4390 if (saved_buffer_length)
4392 pStubMsg->PointerLength = pStubMsg->BufferLength;
4393 pStubMsg->BufferLength = saved_buffer_length;
4398 /***********************************************************************
4399 * NdrUserMarshalMemorySize [RPCRT4.@]
4401 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4402 PFORMAT_STRING pFormat)
4404 unsigned flags = pFormat[1];
4405 unsigned index = *(const WORD*)&pFormat[2];
4406 DWORD memsize = *(const WORD*)&pFormat[4];
4407 DWORD bufsize = *(const WORD*)&pFormat[6];
4409 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4410 TRACE("index=%d\n", index);
4412 pStubMsg->MemorySize += memsize;
4414 if (flags & USER_MARSHAL_POINTER)
4416 ALIGN_POINTER(pStubMsg->Buffer, 4);
4417 /* skip pointer prefix */
4418 pStubMsg->Buffer += 4;
4419 if (pStubMsg->IgnoreEmbeddedPointers)
4420 return pStubMsg->MemorySize;
4421 ALIGN_POINTER(pStubMsg->Buffer, 8);
4423 else
4424 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4426 if (!bufsize)
4427 FIXME("not implemented for varying buffer size\n");
4429 pStubMsg->Buffer += bufsize;
4431 return pStubMsg->MemorySize;
4434 /***********************************************************************
4435 * NdrUserMarshalFree [RPCRT4.@]
4437 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
4438 unsigned char *pMemory,
4439 PFORMAT_STRING pFormat)
4441 /* unsigned flags = pFormat[1]; */
4442 unsigned index = *(const WORD*)&pFormat[2];
4443 USER_MARSHAL_CB umcb;
4445 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4446 TRACE("index=%d\n", index);
4448 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
4450 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
4451 &umcb.Flags, pMemory);
4454 /***********************************************************************
4455 * NdrGetUserMarshalInfo [RPCRT4.@]
4457 RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi)
4459 USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags);
4461 TRACE("(%p,%u,%p)\n", flags, level, umi);
4463 if (level != 1)
4464 return RPC_S_INVALID_ARG;
4466 memset(&umi->u1.Level1, 0, sizeof(umi->u1.Level1));
4467 umi->InformationLevel = level;
4469 if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE)
4470 return RPC_S_INVALID_ARG;
4472 umi->u1.Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate;
4473 umi->u1.Level1.pfnFree = umcb->pStubMsg->pfnFree;
4474 umi->u1.Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer;
4476 switch (umcb->CBType)
4478 case USER_MARSHAL_CB_MARSHALL:
4479 case USER_MARSHAL_CB_UNMARSHALL:
4481 RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg;
4482 unsigned char *buffer_start = msg->Buffer;
4483 unsigned char *buffer_end =
4484 (unsigned char *)msg->Buffer + msg->BufferLength;
4486 if (umcb->pStubMsg->Buffer < buffer_start ||
4487 umcb->pStubMsg->Buffer > buffer_end)
4488 return ERROR_INVALID_USER_BUFFER;
4490 umi->u1.Level1.Buffer = umcb->pStubMsg->Buffer;
4491 umi->u1.Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer;
4492 break;
4494 case USER_MARSHAL_CB_BUFFER_SIZE:
4495 case USER_MARSHAL_CB_FREE:
4496 break;
4497 default:
4498 WARN("unrecognised CBType %d\n", umcb->CBType);
4501 return RPC_S_OK;
4504 /***********************************************************************
4505 * NdrClearOutParameters [RPCRT4.@]
4507 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
4508 PFORMAT_STRING pFormat,
4509 void *ArgAddr)
4511 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
4514 /***********************************************************************
4515 * NdrConvert [RPCRT4.@]
4517 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
4519 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
4520 /* FIXME: since this stub doesn't do any converting, the proper behavior
4521 is to raise an exception */
4524 /***********************************************************************
4525 * NdrConvert2 [RPCRT4.@]
4527 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
4529 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
4530 pStubMsg, pFormat, NumberParams);
4531 /* FIXME: since this stub doesn't do any converting, the proper behavior
4532 is to raise an exception */
4535 #include "pshpack1.h"
4536 typedef struct _NDR_CSTRUCT_FORMAT
4538 unsigned char type;
4539 unsigned char alignment;
4540 unsigned short memory_size;
4541 short offset_to_array_description;
4542 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
4543 #include "poppack.h"
4545 /***********************************************************************
4546 * NdrConformantStructMarshall [RPCRT4.@]
4548 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4549 unsigned char *pMemory,
4550 PFORMAT_STRING pFormat)
4552 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4553 PFORMAT_STRING pCArrayFormat;
4554 ULONG esize, bufsize;
4556 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4558 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4559 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4561 ERR("invalid format type %x\n", pCStructFormat->type);
4562 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4563 return NULL;
4566 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4567 pCStructFormat->offset_to_array_description;
4568 if (*pCArrayFormat != RPC_FC_CARRAY)
4570 ERR("invalid array format type %x\n", pCStructFormat->type);
4571 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4572 return NULL;
4574 esize = *(const WORD*)(pCArrayFormat+2);
4576 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4577 pCArrayFormat + 4, 0);
4579 WriteConformance(pStubMsg);
4581 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4583 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4585 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4586 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4588 ERR("integer overflow of memory_size %u with bufsize %u\n",
4589 pCStructFormat->memory_size, bufsize);
4590 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4592 /* copy constant sized part of struct */
4593 pStubMsg->BufferMark = pStubMsg->Buffer;
4594 safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
4596 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4597 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4599 return NULL;
4602 /***********************************************************************
4603 * NdrConformantStructUnmarshall [RPCRT4.@]
4605 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4606 unsigned char **ppMemory,
4607 PFORMAT_STRING pFormat,
4608 unsigned char fMustAlloc)
4610 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4611 PFORMAT_STRING pCArrayFormat;
4612 ULONG esize, bufsize;
4613 unsigned char *saved_buffer;
4615 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4617 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4618 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4620 ERR("invalid format type %x\n", pCStructFormat->type);
4621 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4622 return NULL;
4624 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4625 pCStructFormat->offset_to_array_description;
4626 if (*pCArrayFormat != RPC_FC_CARRAY)
4628 ERR("invalid array format type %x\n", pCStructFormat->type);
4629 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4630 return NULL;
4632 esize = *(const WORD*)(pCArrayFormat+2);
4634 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
4636 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4638 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4640 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4641 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4643 ERR("integer overflow of memory_size %u with bufsize %u\n",
4644 pCStructFormat->memory_size, bufsize);
4645 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4648 if (fMustAlloc)
4650 SIZE_T size = pCStructFormat->memory_size + bufsize;
4651 *ppMemory = NdrAllocate(pStubMsg, size);
4653 else
4655 if (!pStubMsg->IsClient && !*ppMemory)
4656 /* for servers, we just point straight into the RPC buffer */
4657 *ppMemory = pStubMsg->Buffer;
4660 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4661 safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
4662 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4663 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4665 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4666 if (*ppMemory != saved_buffer)
4667 memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
4669 return NULL;
4672 /***********************************************************************
4673 * NdrConformantStructBufferSize [RPCRT4.@]
4675 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4676 unsigned char *pMemory,
4677 PFORMAT_STRING pFormat)
4679 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4680 PFORMAT_STRING pCArrayFormat;
4681 ULONG esize;
4683 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4685 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4686 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4688 ERR("invalid format type %x\n", pCStructFormat->type);
4689 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4690 return;
4692 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4693 pCStructFormat->offset_to_array_description;
4694 if (*pCArrayFormat != RPC_FC_CARRAY)
4696 ERR("invalid array format type %x\n", pCStructFormat->type);
4697 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4698 return;
4700 esize = *(const WORD*)(pCArrayFormat+2);
4702 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
4703 SizeConformance(pStubMsg);
4705 ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
4707 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4709 safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
4710 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4712 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4713 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4716 /***********************************************************************
4717 * NdrConformantStructMemorySize [RPCRT4.@]
4719 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4720 PFORMAT_STRING pFormat)
4722 FIXME("stub\n");
4723 return 0;
4726 /***********************************************************************
4727 * NdrConformantStructFree [RPCRT4.@]
4729 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4730 unsigned char *pMemory,
4731 PFORMAT_STRING pFormat)
4733 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4734 PFORMAT_STRING pCArrayFormat;
4736 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4738 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4739 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4741 ERR("invalid format type %x\n", pCStructFormat->type);
4742 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4743 return;
4746 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4747 pCStructFormat->offset_to_array_description;
4748 if (*pCArrayFormat != RPC_FC_CARRAY)
4750 ERR("invalid array format type %x\n", pCStructFormat->type);
4751 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4752 return;
4755 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4756 pCArrayFormat + 4, 0);
4758 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4760 /* copy constant sized part of struct */
4761 pStubMsg->BufferMark = pStubMsg->Buffer;
4763 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4764 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4767 /***********************************************************************
4768 * NdrConformantVaryingStructMarshall [RPCRT4.@]
4770 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4771 unsigned char *pMemory,
4772 PFORMAT_STRING pFormat)
4774 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4775 PFORMAT_STRING pCVArrayFormat;
4777 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4779 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4780 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4782 ERR("invalid format type %x\n", pCVStructFormat->type);
4783 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4784 return NULL;
4787 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4788 pCVStructFormat->offset_to_array_description;
4790 array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg,
4791 pMemory + pCVStructFormat->memory_size,
4792 pCVArrayFormat);
4794 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4796 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4798 /* write constant sized part */
4799 pStubMsg->BufferMark = pStubMsg->Buffer;
4800 safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
4802 array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg,
4803 pMemory + pCVStructFormat->memory_size,
4804 pCVArrayFormat, FALSE /* fHasPointers */);
4806 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4808 return NULL;
4811 /***********************************************************************
4812 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
4814 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4815 unsigned char **ppMemory,
4816 PFORMAT_STRING pFormat,
4817 unsigned char fMustAlloc)
4819 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4820 PFORMAT_STRING pCVArrayFormat;
4821 ULONG memsize, bufsize;
4822 unsigned char *saved_buffer, *saved_array_buffer;
4823 ULONG offset;
4824 unsigned char *array_memory;
4826 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4828 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4829 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4831 ERR("invalid format type %x\n", pCVStructFormat->type);
4832 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4833 return NULL;
4836 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4837 pCVStructFormat->offset_to_array_description;
4839 memsize = array_read_conformance(*pCVArrayFormat, pStubMsg,
4840 pCVArrayFormat);
4842 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4844 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4846 /* work out how much memory to allocate if we need to do so */
4847 if (!fMustAlloc && !*ppMemory)
4848 fMustAlloc = TRUE;
4849 if (fMustAlloc)
4851 SIZE_T size = pCVStructFormat->memory_size + memsize;
4852 *ppMemory = NdrAllocate(pStubMsg, size);
4855 /* mark the start of the constant data */
4856 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4857 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4859 array_memory = *ppMemory + pCVStructFormat->memory_size;
4860 bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg,
4861 &array_memory, pCVArrayFormat,
4862 FALSE /* fMustAlloc */,
4863 FALSE /* fUseServerBufferMemory */,
4864 FALSE /* fUnmarshall */);
4866 /* save offset in case unmarshalling pointers changes it */
4867 offset = pStubMsg->Offset;
4869 /* mark the start of the array data */
4870 saved_array_buffer = pStubMsg->Buffer;
4871 safe_buffer_increment(pStubMsg, bufsize);
4873 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4875 /* copy the constant data */
4876 memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size);
4877 /* copy the array data */
4878 TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size);
4879 memcpy(*ppMemory + pCVStructFormat->memory_size + offset,
4880 saved_array_buffer, bufsize);
4882 if (*pCVArrayFormat == RPC_FC_C_CSTRING)
4883 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
4884 else if (*pCVArrayFormat == RPC_FC_C_WSTRING)
4885 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
4887 return NULL;
4890 /***********************************************************************
4891 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
4893 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4894 unsigned char *pMemory,
4895 PFORMAT_STRING pFormat)
4897 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4898 PFORMAT_STRING pCVArrayFormat;
4900 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4902 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4903 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4905 ERR("invalid format type %x\n", pCVStructFormat->type);
4906 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4907 return;
4910 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4911 pCVStructFormat->offset_to_array_description;
4912 array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg,
4913 pMemory + pCVStructFormat->memory_size,
4914 pCVArrayFormat);
4916 ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4918 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4920 safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4922 array_buffer_size(*pCVArrayFormat, pStubMsg,
4923 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4924 FALSE /* fHasPointers */);
4926 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4929 /***********************************************************************
4930 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
4932 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4933 PFORMAT_STRING pFormat)
4935 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4936 PFORMAT_STRING pCVArrayFormat;
4938 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4940 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4941 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4943 ERR("invalid format type %x\n", pCVStructFormat->type);
4944 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4945 return 0;
4948 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4949 pCVStructFormat->offset_to_array_description;
4950 array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat);
4952 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4954 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4956 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4957 array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat,
4958 FALSE /* fHasPointers */);
4960 pStubMsg->MemorySize += pCVStructFormat->memory_size;
4962 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4964 return pStubMsg->MemorySize;
4967 /***********************************************************************
4968 * NdrConformantVaryingStructFree [RPCRT4.@]
4970 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4971 unsigned char *pMemory,
4972 PFORMAT_STRING pFormat)
4974 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4975 PFORMAT_STRING pCVArrayFormat;
4977 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4979 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4980 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4982 ERR("invalid format type %x\n", pCVStructFormat->type);
4983 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4984 return;
4987 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4988 pCVStructFormat->offset_to_array_description;
4989 array_free(*pCVArrayFormat, pStubMsg,
4990 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4991 FALSE /* fHasPointers */);
4993 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4995 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4998 #include "pshpack1.h"
4999 typedef struct
5001 unsigned char type;
5002 unsigned char alignment;
5003 unsigned short total_size;
5004 } NDR_SMFARRAY_FORMAT;
5006 typedef struct
5008 unsigned char type;
5009 unsigned char alignment;
5010 ULONG total_size;
5011 } NDR_LGFARRAY_FORMAT;
5012 #include "poppack.h"
5014 /***********************************************************************
5015 * NdrFixedArrayMarshall [RPCRT4.@]
5017 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5018 unsigned char *pMemory,
5019 PFORMAT_STRING pFormat)
5021 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5022 ULONG total_size;
5024 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5026 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5027 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5029 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5030 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5031 return NULL;
5034 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5036 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5038 total_size = pSmFArrayFormat->total_size;
5039 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5041 else
5043 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5044 total_size = pLgFArrayFormat->total_size;
5045 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5048 pStubMsg->BufferMark = pStubMsg->Buffer;
5049 safe_copy_to_buffer(pStubMsg, pMemory, total_size);
5051 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5053 return NULL;
5056 /***********************************************************************
5057 * NdrFixedArrayUnmarshall [RPCRT4.@]
5059 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5060 unsigned char **ppMemory,
5061 PFORMAT_STRING pFormat,
5062 unsigned char fMustAlloc)
5064 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5065 ULONG total_size;
5066 unsigned char *saved_buffer;
5068 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5070 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5071 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5073 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5074 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5075 return NULL;
5078 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5080 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5082 total_size = pSmFArrayFormat->total_size;
5083 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5085 else
5087 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5088 total_size = pLgFArrayFormat->total_size;
5089 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5092 if (fMustAlloc)
5093 *ppMemory = NdrAllocate(pStubMsg, total_size);
5094 else
5096 if (!pStubMsg->IsClient && !*ppMemory)
5097 /* for servers, we just point straight into the RPC buffer */
5098 *ppMemory = pStubMsg->Buffer;
5101 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5102 safe_buffer_increment(pStubMsg, total_size);
5103 pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5105 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
5106 if (*ppMemory != saved_buffer)
5107 memcpy(*ppMemory, saved_buffer, total_size);
5109 return NULL;
5112 /***********************************************************************
5113 * NdrFixedArrayBufferSize [RPCRT4.@]
5115 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5116 unsigned char *pMemory,
5117 PFORMAT_STRING pFormat)
5119 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5120 ULONG total_size;
5122 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5124 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5125 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5127 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5128 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5129 return;
5132 ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
5134 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5136 total_size = pSmFArrayFormat->total_size;
5137 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5139 else
5141 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5142 total_size = pLgFArrayFormat->total_size;
5143 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5145 safe_buffer_length_increment(pStubMsg, total_size);
5147 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5150 /***********************************************************************
5151 * NdrFixedArrayMemorySize [RPCRT4.@]
5153 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5154 PFORMAT_STRING pFormat)
5156 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5157 ULONG total_size;
5159 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5161 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5162 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5164 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5165 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5166 return 0;
5169 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5171 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5173 total_size = pSmFArrayFormat->total_size;
5174 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5176 else
5178 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5179 total_size = pLgFArrayFormat->total_size;
5180 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5182 pStubMsg->BufferMark = pStubMsg->Buffer;
5183 safe_buffer_increment(pStubMsg, total_size);
5184 pStubMsg->MemorySize += total_size;
5186 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5188 return total_size;
5191 /***********************************************************************
5192 * NdrFixedArrayFree [RPCRT4.@]
5194 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5195 unsigned char *pMemory,
5196 PFORMAT_STRING pFormat)
5198 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5200 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5202 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5203 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5205 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5206 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5207 return;
5210 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5211 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5212 else
5214 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5215 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5218 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5221 /***********************************************************************
5222 * NdrVaryingArrayMarshall [RPCRT4.@]
5224 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5225 unsigned char *pMemory,
5226 PFORMAT_STRING pFormat)
5228 unsigned char alignment;
5229 DWORD elements, esize;
5230 ULONG bufsize;
5232 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5234 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5235 (pFormat[0] != RPC_FC_LGVARRAY))
5237 ERR("invalid format type %x\n", pFormat[0]);
5238 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5239 return NULL;
5242 alignment = pFormat[1] + 1;
5244 if (pFormat[0] == RPC_FC_SMVARRAY)
5246 pFormat += 2;
5247 pFormat += sizeof(WORD);
5248 elements = *(const WORD*)pFormat;
5249 pFormat += sizeof(WORD);
5251 else
5253 pFormat += 2;
5254 pFormat += sizeof(DWORD);
5255 elements = *(const DWORD*)pFormat;
5256 pFormat += sizeof(DWORD);
5259 esize = *(const WORD*)pFormat;
5260 pFormat += sizeof(WORD);
5262 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5263 if ((pStubMsg->ActualCount > elements) ||
5264 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5266 RpcRaiseException(RPC_S_INVALID_BOUND);
5267 return NULL;
5270 WriteVariance(pStubMsg);
5272 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
5274 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5275 pStubMsg->BufferMark = pStubMsg->Buffer;
5276 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
5278 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5280 return NULL;
5283 /***********************************************************************
5284 * NdrVaryingArrayUnmarshall [RPCRT4.@]
5286 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5287 unsigned char **ppMemory,
5288 PFORMAT_STRING pFormat,
5289 unsigned char fMustAlloc)
5291 unsigned char alignment;
5292 DWORD size, elements, esize;
5293 ULONG bufsize;
5294 unsigned char *saved_buffer;
5295 ULONG offset;
5297 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5299 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5300 (pFormat[0] != RPC_FC_LGVARRAY))
5302 ERR("invalid format type %x\n", pFormat[0]);
5303 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5304 return NULL;
5307 alignment = pFormat[1] + 1;
5309 if (pFormat[0] == RPC_FC_SMVARRAY)
5311 pFormat += 2;
5312 size = *(const WORD*)pFormat;
5313 pFormat += sizeof(WORD);
5314 elements = *(const WORD*)pFormat;
5315 pFormat += sizeof(WORD);
5317 else
5319 pFormat += 2;
5320 size = *(const DWORD*)pFormat;
5321 pFormat += sizeof(DWORD);
5322 elements = *(const DWORD*)pFormat;
5323 pFormat += sizeof(DWORD);
5326 esize = *(const WORD*)pFormat;
5327 pFormat += sizeof(WORD);
5329 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5331 ALIGN_POINTER(pStubMsg->Buffer, alignment);
5333 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5334 offset = pStubMsg->Offset;
5336 if (!fMustAlloc && !*ppMemory)
5337 fMustAlloc = TRUE;
5338 if (fMustAlloc)
5339 *ppMemory = NdrAllocate(pStubMsg, size);
5340 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5341 safe_buffer_increment(pStubMsg, bufsize);
5343 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5345 memcpy(*ppMemory + offset, saved_buffer, bufsize);
5347 return NULL;
5350 /***********************************************************************
5351 * NdrVaryingArrayBufferSize [RPCRT4.@]
5353 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5354 unsigned char *pMemory,
5355 PFORMAT_STRING pFormat)
5357 unsigned char alignment;
5358 DWORD elements, esize;
5360 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5362 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5363 (pFormat[0] != RPC_FC_LGVARRAY))
5365 ERR("invalid format type %x\n", pFormat[0]);
5366 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5367 return;
5370 alignment = pFormat[1] + 1;
5372 if (pFormat[0] == RPC_FC_SMVARRAY)
5374 pFormat += 2;
5375 pFormat += sizeof(WORD);
5376 elements = *(const WORD*)pFormat;
5377 pFormat += sizeof(WORD);
5379 else
5381 pFormat += 2;
5382 pFormat += sizeof(DWORD);
5383 elements = *(const DWORD*)pFormat;
5384 pFormat += sizeof(DWORD);
5387 esize = *(const WORD*)pFormat;
5388 pFormat += sizeof(WORD);
5390 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5391 if ((pStubMsg->ActualCount > elements) ||
5392 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5394 RpcRaiseException(RPC_S_INVALID_BOUND);
5395 return;
5398 SizeVariance(pStubMsg);
5400 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
5402 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5404 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5407 /***********************************************************************
5408 * NdrVaryingArrayMemorySize [RPCRT4.@]
5410 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5411 PFORMAT_STRING pFormat)
5413 unsigned char alignment;
5414 DWORD size, elements, esize;
5416 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5418 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5419 (pFormat[0] != RPC_FC_LGVARRAY))
5421 ERR("invalid format type %x\n", pFormat[0]);
5422 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5423 return 0;
5426 alignment = pFormat[1] + 1;
5428 if (pFormat[0] == RPC_FC_SMVARRAY)
5430 pFormat += 2;
5431 size = *(const WORD*)pFormat;
5432 pFormat += sizeof(WORD);
5433 elements = *(const WORD*)pFormat;
5434 pFormat += sizeof(WORD);
5436 else
5438 pFormat += 2;
5439 size = *(const DWORD*)pFormat;
5440 pFormat += sizeof(DWORD);
5441 elements = *(const DWORD*)pFormat;
5442 pFormat += sizeof(DWORD);
5445 esize = *(const WORD*)pFormat;
5446 pFormat += sizeof(WORD);
5448 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5450 ALIGN_POINTER(pStubMsg->Buffer, alignment);
5452 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5453 pStubMsg->MemorySize += size;
5455 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5457 return pStubMsg->MemorySize;
5460 /***********************************************************************
5461 * NdrVaryingArrayFree [RPCRT4.@]
5463 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5464 unsigned char *pMemory,
5465 PFORMAT_STRING pFormat)
5467 DWORD elements;
5469 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5471 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5472 (pFormat[0] != RPC_FC_LGVARRAY))
5474 ERR("invalid format type %x\n", pFormat[0]);
5475 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5476 return;
5479 if (pFormat[0] == RPC_FC_SMVARRAY)
5481 pFormat += 2;
5482 pFormat += sizeof(WORD);
5483 elements = *(const WORD*)pFormat;
5484 pFormat += sizeof(WORD);
5486 else
5488 pFormat += 2;
5489 pFormat += sizeof(DWORD);
5490 elements = *(const DWORD*)pFormat;
5491 pFormat += sizeof(DWORD);
5494 pFormat += sizeof(WORD);
5496 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5497 if ((pStubMsg->ActualCount > elements) ||
5498 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5500 RpcRaiseException(RPC_S_INVALID_BOUND);
5501 return;
5504 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5507 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
5509 switch (fc)
5511 case RPC_FC_BYTE:
5512 case RPC_FC_CHAR:
5513 case RPC_FC_SMALL:
5514 case RPC_FC_USMALL:
5515 return *pMemory;
5516 case RPC_FC_WCHAR:
5517 case RPC_FC_SHORT:
5518 case RPC_FC_USHORT:
5519 case RPC_FC_ENUM16:
5520 return *(const USHORT *)pMemory;
5521 case RPC_FC_LONG:
5522 case RPC_FC_ULONG:
5523 case RPC_FC_ENUM32:
5524 return *(const ULONG *)pMemory;
5525 default:
5526 FIXME("Unhandled base type: 0x%02x\n", fc);
5527 return 0;
5531 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
5532 ULONG discriminant,
5533 PFORMAT_STRING pFormat)
5535 unsigned short num_arms, arm, type;
5537 num_arms = *(const SHORT*)pFormat & 0x0fff;
5538 pFormat += 2;
5539 for(arm = 0; arm < num_arms; arm++)
5541 if(discriminant == *(const ULONG*)pFormat)
5543 pFormat += 4;
5544 break;
5546 pFormat += 6;
5549 type = *(const unsigned short*)pFormat;
5550 TRACE("type %04x\n", type);
5551 if(arm == num_arms) /* default arm extras */
5553 if(type == 0xffff)
5555 ERR("no arm for 0x%x and no default case\n", discriminant);
5556 RpcRaiseException(RPC_S_INVALID_TAG);
5557 return NULL;
5559 if(type == 0)
5561 TRACE("falling back to empty default case for 0x%x\n", discriminant);
5562 return NULL;
5565 return pFormat;
5568 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
5570 unsigned short type;
5572 pFormat += 2;
5574 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5575 if(!pFormat)
5576 return NULL;
5578 type = *(const unsigned short*)pFormat;
5579 if((type & 0xff00) == 0x8000)
5581 unsigned char basetype = LOBYTE(type);
5582 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
5584 else
5586 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5587 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
5588 if (m)
5590 unsigned char *saved_buffer = NULL;
5591 int pointer_buffer_mark_set = 0;
5592 switch(*desc)
5594 case RPC_FC_RP:
5595 case RPC_FC_UP:
5596 case RPC_FC_OP:
5597 case RPC_FC_FP:
5598 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
5599 saved_buffer = pStubMsg->Buffer;
5600 if (pStubMsg->PointerBufferMark)
5602 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5603 pStubMsg->PointerBufferMark = NULL;
5604 pointer_buffer_mark_set = 1;
5606 else
5607 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
5609 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
5610 if (pointer_buffer_mark_set)
5612 STD_OVERFLOW_CHECK(pStubMsg);
5613 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5614 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5616 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5617 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5618 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5620 pStubMsg->Buffer = saved_buffer + 4;
5622 break;
5623 default:
5624 m(pStubMsg, pMemory, desc);
5627 else FIXME("no marshaller for embedded type %02x\n", *desc);
5629 return NULL;
5632 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5633 unsigned char **ppMemory,
5634 ULONG discriminant,
5635 PFORMAT_STRING pFormat,
5636 unsigned char fMustAlloc)
5638 unsigned short type;
5640 pFormat += 2;
5642 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5643 if(!pFormat)
5644 return NULL;
5646 type = *(const unsigned short*)pFormat;
5647 if((type & 0xff00) == 0x8000)
5649 unsigned char basetype = LOBYTE(type);
5650 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
5652 else
5654 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5655 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
5656 if (m)
5658 unsigned char *saved_buffer = NULL;
5659 int pointer_buffer_mark_set = 0;
5660 switch(*desc)
5662 case RPC_FC_RP:
5663 case RPC_FC_UP:
5664 case RPC_FC_OP:
5665 case RPC_FC_FP:
5666 ALIGN_POINTER(pStubMsg->Buffer, 4);
5667 saved_buffer = pStubMsg->Buffer;
5668 if (pStubMsg->PointerBufferMark)
5670 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5671 pStubMsg->PointerBufferMark = NULL;
5672 pointer_buffer_mark_set = 1;
5674 else
5675 pStubMsg->Buffer += 4; /* for pointer ID */
5677 if (saved_buffer + 4 > pStubMsg->BufferEnd)
5679 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5680 saved_buffer, pStubMsg->BufferEnd);
5681 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5684 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
5685 if (pointer_buffer_mark_set)
5687 STD_OVERFLOW_CHECK(pStubMsg);
5688 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5689 pStubMsg->Buffer = saved_buffer + 4;
5691 break;
5692 default:
5693 m(pStubMsg, ppMemory, desc, fMustAlloc);
5696 else FIXME("no marshaller for embedded type %02x\n", *desc);
5698 return NULL;
5701 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
5702 unsigned char *pMemory,
5703 ULONG discriminant,
5704 PFORMAT_STRING pFormat)
5706 unsigned short type;
5708 pFormat += 2;
5710 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5711 if(!pFormat)
5712 return;
5714 type = *(const unsigned short*)pFormat;
5715 if((type & 0xff00) == 0x8000)
5717 unsigned char basetype = LOBYTE(type);
5718 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
5720 else
5722 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5723 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
5724 if (m)
5726 switch(*desc)
5728 case RPC_FC_RP:
5729 case RPC_FC_UP:
5730 case RPC_FC_OP:
5731 case RPC_FC_FP:
5732 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5733 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
5734 if (!pStubMsg->IgnoreEmbeddedPointers)
5736 int saved_buffer_length = pStubMsg->BufferLength;
5737 pStubMsg->BufferLength = pStubMsg->PointerLength;
5738 pStubMsg->PointerLength = 0;
5739 if(!pStubMsg->BufferLength)
5740 ERR("BufferLength == 0??\n");
5741 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
5742 pStubMsg->PointerLength = pStubMsg->BufferLength;
5743 pStubMsg->BufferLength = saved_buffer_length;
5745 break;
5746 default:
5747 m(pStubMsg, pMemory, desc);
5750 else FIXME("no buffersizer for embedded type %02x\n", *desc);
5754 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
5755 ULONG discriminant,
5756 PFORMAT_STRING pFormat)
5758 unsigned short type, size;
5760 size = *(const unsigned short*)pFormat;
5761 pStubMsg->Memory += size;
5762 pFormat += 2;
5764 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5765 if(!pFormat)
5766 return 0;
5768 type = *(const unsigned short*)pFormat;
5769 if((type & 0xff00) == 0x8000)
5771 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
5773 else
5775 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5776 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
5777 unsigned char *saved_buffer;
5778 if (m)
5780 switch(*desc)
5782 case RPC_FC_RP:
5783 case RPC_FC_UP:
5784 case RPC_FC_OP:
5785 case RPC_FC_FP:
5786 ALIGN_POINTER(pStubMsg->Buffer, 4);
5787 saved_buffer = pStubMsg->Buffer;
5788 safe_buffer_increment(pStubMsg, 4);
5789 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
5790 pStubMsg->MemorySize += sizeof(void *);
5791 if (!pStubMsg->IgnoreEmbeddedPointers)
5792 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
5793 break;
5794 default:
5795 return m(pStubMsg, desc);
5798 else FIXME("no marshaller for embedded type %02x\n", *desc);
5801 TRACE("size %d\n", size);
5802 return size;
5805 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
5806 unsigned char *pMemory,
5807 ULONG discriminant,
5808 PFORMAT_STRING pFormat)
5810 unsigned short type;
5812 pFormat += 2;
5814 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5815 if(!pFormat)
5816 return;
5818 type = *(const unsigned short*)pFormat;
5819 if((type & 0xff00) != 0x8000)
5821 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5822 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5823 if (m)
5825 switch(*desc)
5827 case RPC_FC_RP:
5828 case RPC_FC_UP:
5829 case RPC_FC_OP:
5830 case RPC_FC_FP:
5831 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5832 break;
5833 default:
5834 m(pStubMsg, pMemory, desc);
5840 /***********************************************************************
5841 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
5843 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5844 unsigned char *pMemory,
5845 PFORMAT_STRING pFormat)
5847 unsigned char switch_type;
5848 unsigned char increment;
5849 ULONG switch_value;
5851 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5852 pFormat++;
5854 switch_type = *pFormat & 0xf;
5855 increment = (*pFormat & 0xf0) >> 4;
5856 pFormat++;
5858 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment);
5860 switch_value = get_discriminant(switch_type, pMemory);
5861 TRACE("got switch value 0x%x\n", switch_value);
5863 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5864 pMemory += increment;
5866 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5869 /***********************************************************************
5870 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5872 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5873 unsigned char **ppMemory,
5874 PFORMAT_STRING pFormat,
5875 unsigned char fMustAlloc)
5877 unsigned char switch_type;
5878 unsigned char increment;
5879 ULONG switch_value;
5880 unsigned short size;
5881 unsigned char *pMemoryArm;
5883 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5884 pFormat++;
5886 switch_type = *pFormat & 0xf;
5887 increment = (*pFormat & 0xf0) >> 4;
5888 pFormat++;
5890 ALIGN_POINTER(pStubMsg->Buffer, increment);
5891 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5892 TRACE("got switch value 0x%x\n", switch_value);
5894 size = *(const unsigned short*)pFormat + increment;
5895 if (!fMustAlloc && !*ppMemory)
5896 fMustAlloc = TRUE;
5897 if (fMustAlloc)
5898 *ppMemory = NdrAllocate(pStubMsg, size);
5900 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
5901 * since the arm is part of the memory block that is encompassed by
5902 * the whole union. Memory is forced to allocate when pointers
5903 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
5904 * clearing the memory we pass in to the unmarshaller */
5905 if (fMustAlloc)
5906 memset(*ppMemory, 0, size);
5908 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5909 pMemoryArm = *ppMemory + increment;
5911 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE);
5914 /***********************************************************************
5915 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5917 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5918 unsigned char *pMemory,
5919 PFORMAT_STRING pFormat)
5921 unsigned char switch_type;
5922 unsigned char increment;
5923 ULONG switch_value;
5925 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5926 pFormat++;
5928 switch_type = *pFormat & 0xf;
5929 increment = (*pFormat & 0xf0) >> 4;
5930 pFormat++;
5932 ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5933 switch_value = get_discriminant(switch_type, pMemory);
5934 TRACE("got switch value 0x%x\n", switch_value);
5936 /* Add discriminant size */
5937 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5938 pMemory += increment;
5940 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5943 /***********************************************************************
5944 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5946 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5947 PFORMAT_STRING pFormat)
5949 unsigned char switch_type;
5950 unsigned char increment;
5951 ULONG switch_value;
5953 switch_type = *pFormat & 0xf;
5954 increment = (*pFormat & 0xf0) >> 4;
5955 pFormat++;
5957 ALIGN_POINTER(pStubMsg->Buffer, increment);
5958 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5959 TRACE("got switch value 0x%x\n", switch_value);
5961 pStubMsg->Memory += increment;
5963 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5966 /***********************************************************************
5967 * NdrEncapsulatedUnionFree [RPCRT4.@]
5969 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5970 unsigned char *pMemory,
5971 PFORMAT_STRING pFormat)
5973 unsigned char switch_type;
5974 unsigned char increment;
5975 ULONG switch_value;
5977 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5978 pFormat++;
5980 switch_type = *pFormat & 0xf;
5981 increment = (*pFormat & 0xf0) >> 4;
5982 pFormat++;
5984 switch_value = get_discriminant(switch_type, pMemory);
5985 TRACE("got switch value 0x%x\n", switch_value);
5987 pMemory += increment;
5989 union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5992 /***********************************************************************
5993 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5995 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5996 unsigned char *pMemory,
5997 PFORMAT_STRING pFormat)
5999 unsigned char switch_type;
6001 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6002 pFormat++;
6004 switch_type = *pFormat;
6005 pFormat++;
6007 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6008 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6009 /* Marshall discriminant */
6010 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6012 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6015 static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
6016 PFORMAT_STRING *ppFormat)
6018 LONG discriminant = 0;
6020 switch(**ppFormat)
6022 case RPC_FC_BYTE:
6023 case RPC_FC_CHAR:
6024 case RPC_FC_SMALL:
6025 case RPC_FC_USMALL:
6027 UCHAR d;
6028 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6029 discriminant = d;
6030 break;
6032 case RPC_FC_WCHAR:
6033 case RPC_FC_SHORT:
6034 case RPC_FC_USHORT:
6036 USHORT d;
6037 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6038 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6039 discriminant = d;
6040 break;
6042 case RPC_FC_LONG:
6043 case RPC_FC_ULONG:
6045 ULONG d;
6046 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
6047 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6048 discriminant = d;
6049 break;
6051 default:
6052 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
6054 (*ppFormat)++;
6056 if (pStubMsg->fHasNewCorrDesc)
6057 *ppFormat += 6;
6058 else
6059 *ppFormat += 4;
6060 return discriminant;
6063 /**********************************************************************
6064 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
6066 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6067 unsigned char **ppMemory,
6068 PFORMAT_STRING pFormat,
6069 unsigned char fMustAlloc)
6071 LONG discriminant;
6072 unsigned short size;
6074 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
6075 pFormat++;
6077 /* Unmarshall discriminant */
6078 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6079 TRACE("unmarshalled discriminant %x\n", discriminant);
6081 pFormat += *(const SHORT*)pFormat;
6083 size = *(const unsigned short*)pFormat;
6085 if (!fMustAlloc && !*ppMemory)
6086 fMustAlloc = TRUE;
6087 if (fMustAlloc)
6088 *ppMemory = NdrAllocate(pStubMsg, size);
6090 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6091 * since the arm is part of the memory block that is encompassed by
6092 * the whole union. Memory is forced to allocate when pointers
6093 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6094 * clearing the memory we pass in to the unmarshaller */
6095 if (fMustAlloc)
6096 memset(*ppMemory, 0, size);
6098 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
6101 /***********************************************************************
6102 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
6104 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6105 unsigned char *pMemory,
6106 PFORMAT_STRING pFormat)
6108 unsigned char switch_type;
6110 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6111 pFormat++;
6113 switch_type = *pFormat;
6114 pFormat++;
6116 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6117 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6118 /* Add discriminant size */
6119 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6121 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6124 /***********************************************************************
6125 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
6127 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6128 PFORMAT_STRING pFormat)
6130 ULONG discriminant;
6132 pFormat++;
6133 /* Unmarshall discriminant */
6134 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6135 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
6137 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
6140 /***********************************************************************
6141 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
6143 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6144 unsigned char *pMemory,
6145 PFORMAT_STRING pFormat)
6147 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6148 pFormat++;
6149 pFormat++;
6151 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6152 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6154 union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6157 /***********************************************************************
6158 * NdrByteCountPointerMarshall [RPCRT4.@]
6160 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6161 unsigned char *pMemory,
6162 PFORMAT_STRING pFormat)
6164 FIXME("stub\n");
6165 return NULL;
6168 /***********************************************************************
6169 * NdrByteCountPointerUnmarshall [RPCRT4.@]
6171 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6172 unsigned char **ppMemory,
6173 PFORMAT_STRING pFormat,
6174 unsigned char fMustAlloc)
6176 FIXME("stub\n");
6177 return NULL;
6180 /***********************************************************************
6181 * NdrByteCountPointerBufferSize [RPCRT4.@]
6183 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6184 unsigned char *pMemory,
6185 PFORMAT_STRING pFormat)
6187 FIXME("stub\n");
6190 /***********************************************************************
6191 * NdrByteCountPointerMemorySize [internal]
6193 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6194 PFORMAT_STRING pFormat)
6196 FIXME("stub\n");
6197 return 0;
6200 /***********************************************************************
6201 * NdrByteCountPointerFree [RPCRT4.@]
6203 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
6204 unsigned char *pMemory,
6205 PFORMAT_STRING pFormat)
6207 FIXME("stub\n");
6210 /***********************************************************************
6211 * NdrXmitOrRepAsMarshall [RPCRT4.@]
6213 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6214 unsigned char *pMemory,
6215 PFORMAT_STRING pFormat)
6217 FIXME("stub\n");
6218 return NULL;
6221 /***********************************************************************
6222 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
6224 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6225 unsigned char **ppMemory,
6226 PFORMAT_STRING pFormat,
6227 unsigned char fMustAlloc)
6229 FIXME("stub\n");
6230 return NULL;
6233 /***********************************************************************
6234 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
6236 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6237 unsigned char *pMemory,
6238 PFORMAT_STRING pFormat)
6240 FIXME("stub\n");
6243 /***********************************************************************
6244 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
6246 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6247 PFORMAT_STRING pFormat)
6249 FIXME("stub\n");
6250 return 0;
6253 /***********************************************************************
6254 * NdrXmitOrRepAsFree [RPCRT4.@]
6256 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
6257 unsigned char *pMemory,
6258 PFORMAT_STRING pFormat)
6260 FIXME("stub\n");
6263 /***********************************************************************
6264 * NdrRangeMarshall [internal]
6266 static unsigned char *WINAPI NdrRangeMarshall(
6267 PMIDL_STUB_MESSAGE pStubMsg,
6268 unsigned char *pMemory,
6269 PFORMAT_STRING pFormat)
6271 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6272 unsigned char base_type;
6274 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6276 if (pRange->type != RPC_FC_RANGE)
6278 ERR("invalid format type %x\n", pRange->type);
6279 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6280 return NULL;
6283 base_type = pRange->flags_type & 0xf;
6285 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
6288 /***********************************************************************
6289 * NdrRangeUnmarshall [RPCRT4.@]
6291 unsigned char *WINAPI NdrRangeUnmarshall(
6292 PMIDL_STUB_MESSAGE pStubMsg,
6293 unsigned char **ppMemory,
6294 PFORMAT_STRING pFormat,
6295 unsigned char fMustAlloc)
6297 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6298 unsigned char base_type;
6300 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6302 if (pRange->type != RPC_FC_RANGE)
6304 ERR("invalid format type %x\n", pRange->type);
6305 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6306 return NULL;
6308 base_type = pRange->flags_type & 0xf;
6310 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
6311 base_type, pRange->low_value, pRange->high_value);
6313 #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
6314 do \
6316 ALIGN_POINTER(pStubMsg->Buffer, sizeof(wire_type)); \
6317 if (!fMustAlloc && !*ppMemory) \
6318 fMustAlloc = TRUE; \
6319 if (fMustAlloc) \
6320 *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
6321 if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
6323 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
6324 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
6325 RpcRaiseException(RPC_X_BAD_STUB_DATA); \
6327 if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
6328 (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
6330 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
6331 *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
6332 (mem_type)pRange->high_value); \
6333 RpcRaiseException(RPC_S_INVALID_BOUND); \
6334 return NULL; \
6336 TRACE("*ppMemory: %p\n", *ppMemory); \
6337 **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
6338 pStubMsg->Buffer += sizeof(wire_type); \
6339 } while (0)
6341 switch(base_type)
6343 case RPC_FC_CHAR:
6344 case RPC_FC_SMALL:
6345 RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
6346 TRACE("value: 0x%02x\n", **ppMemory);
6347 break;
6348 case RPC_FC_BYTE:
6349 case RPC_FC_USMALL:
6350 RANGE_UNMARSHALL(CHAR, CHAR, "%u");
6351 TRACE("value: 0x%02x\n", **ppMemory);
6352 break;
6353 case RPC_FC_WCHAR: /* FIXME: valid? */
6354 case RPC_FC_USHORT:
6355 RANGE_UNMARSHALL(USHORT, USHORT, "%u");
6356 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6357 break;
6358 case RPC_FC_SHORT:
6359 RANGE_UNMARSHALL(SHORT, SHORT, "%d");
6360 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6361 break;
6362 case RPC_FC_LONG:
6363 case RPC_FC_ENUM32:
6364 RANGE_UNMARSHALL(LONG, LONG, "%d");
6365 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6366 break;
6367 case RPC_FC_ULONG:
6368 RANGE_UNMARSHALL(ULONG, ULONG, "%u");
6369 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6370 break;
6371 case RPC_FC_ENUM16:
6372 RANGE_UNMARSHALL(UINT, USHORT, "%u");
6373 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6374 break;
6375 case RPC_FC_FLOAT:
6376 case RPC_FC_DOUBLE:
6377 case RPC_FC_HYPER:
6378 default:
6379 ERR("invalid range base type: 0x%02x\n", base_type);
6380 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6383 return NULL;
6386 /***********************************************************************
6387 * NdrRangeBufferSize [internal]
6389 static void WINAPI NdrRangeBufferSize(
6390 PMIDL_STUB_MESSAGE pStubMsg,
6391 unsigned char *pMemory,
6392 PFORMAT_STRING pFormat)
6394 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6395 unsigned char base_type;
6397 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6399 if (pRange->type != RPC_FC_RANGE)
6401 ERR("invalid format type %x\n", pRange->type);
6402 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6404 base_type = pRange->flags_type & 0xf;
6406 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
6409 /***********************************************************************
6410 * NdrRangeMemorySize [internal]
6412 static ULONG WINAPI NdrRangeMemorySize(
6413 PMIDL_STUB_MESSAGE pStubMsg,
6414 PFORMAT_STRING pFormat)
6416 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6417 unsigned char base_type;
6419 if (pRange->type != RPC_FC_RANGE)
6421 ERR("invalid format type %x\n", pRange->type);
6422 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6423 return 0;
6425 base_type = pRange->flags_type & 0xf;
6427 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
6430 /***********************************************************************
6431 * NdrRangeFree [internal]
6433 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
6434 unsigned char *pMemory,
6435 PFORMAT_STRING pFormat)
6437 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6439 /* nothing to do */
6442 /***********************************************************************
6443 * NdrBaseTypeMarshall [internal]
6445 static unsigned char *WINAPI NdrBaseTypeMarshall(
6446 PMIDL_STUB_MESSAGE pStubMsg,
6447 unsigned char *pMemory,
6448 PFORMAT_STRING pFormat)
6450 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6452 switch(*pFormat)
6454 case RPC_FC_BYTE:
6455 case RPC_FC_CHAR:
6456 case RPC_FC_SMALL:
6457 case RPC_FC_USMALL:
6458 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
6459 TRACE("value: 0x%02x\n", *pMemory);
6460 break;
6461 case RPC_FC_WCHAR:
6462 case RPC_FC_SHORT:
6463 case RPC_FC_USHORT:
6464 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6465 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
6466 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
6467 break;
6468 case RPC_FC_LONG:
6469 case RPC_FC_ULONG:
6470 case RPC_FC_ERROR_STATUS_T:
6471 case RPC_FC_ENUM32:
6472 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG));
6473 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
6474 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
6475 break;
6476 case RPC_FC_FLOAT:
6477 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float));
6478 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
6479 break;
6480 case RPC_FC_DOUBLE:
6481 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double));
6482 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
6483 break;
6484 case RPC_FC_HYPER:
6485 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG));
6486 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
6487 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
6488 break;
6489 case RPC_FC_ENUM16:
6490 /* only 16-bits on the wire, so do a sanity check */
6491 if (*(UINT *)pMemory > SHRT_MAX)
6492 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
6493 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6494 if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6495 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6496 *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
6497 pStubMsg->Buffer += sizeof(USHORT);
6498 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
6499 break;
6500 case RPC_FC_IGNORE:
6501 break;
6502 default:
6503 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6506 /* FIXME: what is the correct return value? */
6507 return NULL;
6510 /***********************************************************************
6511 * NdrBaseTypeUnmarshall [internal]
6513 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
6514 PMIDL_STUB_MESSAGE pStubMsg,
6515 unsigned char **ppMemory,
6516 PFORMAT_STRING pFormat,
6517 unsigned char fMustAlloc)
6519 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6521 #define BASE_TYPE_UNMARSHALL(type) \
6522 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
6523 if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
6525 *ppMemory = pStubMsg->Buffer; \
6526 TRACE("*ppMemory: %p\n", *ppMemory); \
6527 safe_buffer_increment(pStubMsg, sizeof(type)); \
6529 else \
6531 if (fMustAlloc) \
6532 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
6533 TRACE("*ppMemory: %p\n", *ppMemory); \
6534 safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \
6537 switch(*pFormat)
6539 case RPC_FC_BYTE:
6540 case RPC_FC_CHAR:
6541 case RPC_FC_SMALL:
6542 case RPC_FC_USMALL:
6543 BASE_TYPE_UNMARSHALL(UCHAR);
6544 TRACE("value: 0x%02x\n", **ppMemory);
6545 break;
6546 case RPC_FC_WCHAR:
6547 case RPC_FC_SHORT:
6548 case RPC_FC_USHORT:
6549 BASE_TYPE_UNMARSHALL(USHORT);
6550 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6551 break;
6552 case RPC_FC_LONG:
6553 case RPC_FC_ULONG:
6554 case RPC_FC_ERROR_STATUS_T:
6555 case RPC_FC_ENUM32:
6556 BASE_TYPE_UNMARSHALL(ULONG);
6557 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6558 break;
6559 case RPC_FC_FLOAT:
6560 BASE_TYPE_UNMARSHALL(float);
6561 TRACE("value: %f\n", **(float **)ppMemory);
6562 break;
6563 case RPC_FC_DOUBLE:
6564 BASE_TYPE_UNMARSHALL(double);
6565 TRACE("value: %f\n", **(double **)ppMemory);
6566 break;
6567 case RPC_FC_HYPER:
6568 BASE_TYPE_UNMARSHALL(ULONGLONG);
6569 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
6570 break;
6571 case RPC_FC_ENUM16:
6572 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6573 if (!fMustAlloc && !*ppMemory)
6574 fMustAlloc = TRUE;
6575 if (fMustAlloc)
6576 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
6577 if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
6578 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6579 TRACE("*ppMemory: %p\n", *ppMemory);
6580 /* 16-bits on the wire, but int in memory */
6581 **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
6582 pStubMsg->Buffer += sizeof(USHORT);
6583 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6584 break;
6585 case RPC_FC_IGNORE:
6586 break;
6587 default:
6588 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6590 #undef BASE_TYPE_UNMARSHALL
6592 /* FIXME: what is the correct return value? */
6594 return NULL;
6597 /***********************************************************************
6598 * NdrBaseTypeBufferSize [internal]
6600 static void WINAPI NdrBaseTypeBufferSize(
6601 PMIDL_STUB_MESSAGE pStubMsg,
6602 unsigned char *pMemory,
6603 PFORMAT_STRING pFormat)
6605 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6607 switch(*pFormat)
6609 case RPC_FC_BYTE:
6610 case RPC_FC_CHAR:
6611 case RPC_FC_SMALL:
6612 case RPC_FC_USMALL:
6613 safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6614 break;
6615 case RPC_FC_WCHAR:
6616 case RPC_FC_SHORT:
6617 case RPC_FC_USHORT:
6618 case RPC_FC_ENUM16:
6619 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
6620 safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6621 break;
6622 case RPC_FC_LONG:
6623 case RPC_FC_ULONG:
6624 case RPC_FC_ENUM32:
6625 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
6626 safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6627 break;
6628 case RPC_FC_FLOAT:
6629 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
6630 safe_buffer_length_increment(pStubMsg, sizeof(float));
6631 break;
6632 case RPC_FC_DOUBLE:
6633 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
6634 safe_buffer_length_increment(pStubMsg, sizeof(double));
6635 break;
6636 case RPC_FC_HYPER:
6637 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
6638 safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6639 break;
6640 case RPC_FC_ERROR_STATUS_T:
6641 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
6642 safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6643 break;
6644 case RPC_FC_IGNORE:
6645 break;
6646 default:
6647 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6651 /***********************************************************************
6652 * NdrBaseTypeMemorySize [internal]
6654 static ULONG WINAPI NdrBaseTypeMemorySize(
6655 PMIDL_STUB_MESSAGE pStubMsg,
6656 PFORMAT_STRING pFormat)
6658 TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6660 switch(*pFormat)
6662 case RPC_FC_BYTE:
6663 case RPC_FC_CHAR:
6664 case RPC_FC_SMALL:
6665 case RPC_FC_USMALL:
6666 safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6667 pStubMsg->MemorySize += sizeof(UCHAR);
6668 return sizeof(UCHAR);
6669 case RPC_FC_WCHAR:
6670 case RPC_FC_SHORT:
6671 case RPC_FC_USHORT:
6672 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6673 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6674 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(USHORT));
6675 pStubMsg->MemorySize += sizeof(USHORT);
6676 return sizeof(USHORT);
6677 case RPC_FC_LONG:
6678 case RPC_FC_ULONG:
6679 case RPC_FC_ENUM32:
6680 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
6681 safe_buffer_increment(pStubMsg, sizeof(ULONG));
6682 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONG));
6683 pStubMsg->MemorySize += sizeof(ULONG);
6684 return sizeof(ULONG);
6685 case RPC_FC_FLOAT:
6686 ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
6687 safe_buffer_increment(pStubMsg, sizeof(float));
6688 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(float));
6689 pStubMsg->MemorySize += sizeof(float);
6690 return sizeof(float);
6691 case RPC_FC_DOUBLE:
6692 ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
6693 safe_buffer_increment(pStubMsg, sizeof(double));
6694 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(double));
6695 pStubMsg->MemorySize += sizeof(double);
6696 return sizeof(double);
6697 case RPC_FC_HYPER:
6698 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
6699 safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6700 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONGLONG));
6701 pStubMsg->MemorySize += sizeof(ULONGLONG);
6702 return sizeof(ULONGLONG);
6703 case RPC_FC_ERROR_STATUS_T:
6704 ALIGN_POINTER(pStubMsg->Buffer, sizeof(error_status_t));
6705 safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6706 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(error_status_t));
6707 pStubMsg->MemorySize += sizeof(error_status_t);
6708 return sizeof(error_status_t);
6709 case RPC_FC_ENUM16:
6710 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6711 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6712 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(UINT));
6713 pStubMsg->MemorySize += sizeof(UINT);
6714 return sizeof(UINT);
6715 case RPC_FC_IGNORE:
6716 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
6717 pStubMsg->MemorySize += sizeof(void *);
6718 return sizeof(void *);
6719 default:
6720 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6721 return 0;
6725 /***********************************************************************
6726 * NdrBaseTypeFree [internal]
6728 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6729 unsigned char *pMemory,
6730 PFORMAT_STRING pFormat)
6732 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6734 /* nothing to do */
6737 /***********************************************************************
6738 * NdrContextHandleBufferSize [internal]
6740 static void WINAPI NdrContextHandleBufferSize(
6741 PMIDL_STUB_MESSAGE pStubMsg,
6742 unsigned char *pMemory,
6743 PFORMAT_STRING pFormat)
6745 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6747 if (*pFormat != RPC_FC_BIND_CONTEXT)
6749 ERR("invalid format type %x\n", *pFormat);
6750 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6752 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
6753 safe_buffer_length_increment(pStubMsg, cbNDRContext);
6756 /***********************************************************************
6757 * NdrContextHandleMarshall [internal]
6759 static unsigned char *WINAPI NdrContextHandleMarshall(
6760 PMIDL_STUB_MESSAGE pStubMsg,
6761 unsigned char *pMemory,
6762 PFORMAT_STRING pFormat)
6764 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6766 if (*pFormat != RPC_FC_BIND_CONTEXT)
6768 ERR("invalid format type %x\n", *pFormat);
6769 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6771 TRACE("flags: 0x%02x\n", pFormat[1]);
6773 if (pStubMsg->IsClient)
6775 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6776 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6777 else
6778 NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
6780 else
6782 NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
6783 NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
6784 NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
6787 return NULL;
6790 /***********************************************************************
6791 * NdrContextHandleUnmarshall [internal]
6793 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6794 PMIDL_STUB_MESSAGE pStubMsg,
6795 unsigned char **ppMemory,
6796 PFORMAT_STRING pFormat,
6797 unsigned char fMustAlloc)
6799 TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg,
6800 ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE");
6802 if (*pFormat != RPC_FC_BIND_CONTEXT)
6804 ERR("invalid format type %x\n", *pFormat);
6805 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6807 TRACE("flags: 0x%02x\n", pFormat[1]);
6809 if (pStubMsg->IsClient)
6811 /* [out]-only or [ret] param */
6812 if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT)
6813 **(NDR_CCONTEXT **)ppMemory = NULL;
6814 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
6816 else
6818 NDR_SCONTEXT ctxt;
6819 ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat);
6820 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6821 *(void **)ppMemory = NDRSContextValue(ctxt);
6822 else
6823 *(void **)ppMemory = *NDRSContextValue(ctxt);
6826 return NULL;
6829 /***********************************************************************
6830 * NdrClientContextMarshall [RPCRT4.@]
6832 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6833 NDR_CCONTEXT ContextHandle,
6834 int fCheck)
6836 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
6838 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
6840 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6842 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6843 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6844 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6847 /* FIXME: what does fCheck do? */
6848 NDRCContextMarshall(ContextHandle,
6849 pStubMsg->Buffer);
6851 pStubMsg->Buffer += cbNDRContext;
6854 /***********************************************************************
6855 * NdrClientContextUnmarshall [RPCRT4.@]
6857 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6858 NDR_CCONTEXT * pContextHandle,
6859 RPC_BINDING_HANDLE BindHandle)
6861 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
6863 ALIGN_POINTER(pStubMsg->Buffer, 4);
6865 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
6866 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6868 NDRCContextUnmarshall(pContextHandle,
6869 BindHandle,
6870 pStubMsg->Buffer,
6871 pStubMsg->RpcMsg->DataRepresentation);
6873 pStubMsg->Buffer += cbNDRContext;
6876 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6877 NDR_SCONTEXT ContextHandle,
6878 NDR_RUNDOWN RundownRoutine )
6880 TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
6882 ALIGN_POINTER(pStubMsg->Buffer, 4);
6884 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6886 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6887 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6888 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6891 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6892 pStubMsg->Buffer, RundownRoutine, NULL,
6893 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6894 pStubMsg->Buffer += cbNDRContext;
6897 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
6899 NDR_SCONTEXT ContextHandle;
6901 TRACE("(%p)\n", pStubMsg);
6903 ALIGN_POINTER(pStubMsg->Buffer, 4);
6905 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6907 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6908 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6909 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6912 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6913 pStubMsg->Buffer,
6914 pStubMsg->RpcMsg->DataRepresentation,
6915 NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6916 pStubMsg->Buffer += cbNDRContext;
6918 return ContextHandle;
6921 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
6922 unsigned char* pMemory,
6923 PFORMAT_STRING pFormat)
6925 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
6928 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
6929 PFORMAT_STRING pFormat)
6931 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6932 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6934 TRACE("(%p, %p)\n", pStubMsg, pFormat);
6936 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6937 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6938 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6939 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6940 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6942 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6943 if_id = &sif->InterfaceId;
6946 return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
6947 pStubMsg->RpcMsg->DataRepresentation, if_id,
6948 flags);
6951 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6952 NDR_SCONTEXT ContextHandle,
6953 NDR_RUNDOWN RundownRoutine,
6954 PFORMAT_STRING pFormat)
6956 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6957 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6959 TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
6961 ALIGN_POINTER(pStubMsg->Buffer, 4);
6963 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6965 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6966 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6967 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6970 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6971 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6972 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6973 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6974 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6976 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6977 if_id = &sif->InterfaceId;
6980 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6981 pStubMsg->Buffer, RundownRoutine, if_id, flags);
6982 pStubMsg->Buffer += cbNDRContext;
6985 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6986 PFORMAT_STRING pFormat)
6988 NDR_SCONTEXT ContextHandle;
6989 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6990 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6992 TRACE("(%p, %p)\n", pStubMsg, pFormat);
6994 ALIGN_POINTER(pStubMsg->Buffer, 4);
6996 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6998 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6999 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7000 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7003 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7004 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7005 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
7006 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7007 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7009 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7010 if_id = &sif->InterfaceId;
7013 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
7014 pStubMsg->Buffer,
7015 pStubMsg->RpcMsg->DataRepresentation,
7016 if_id, flags);
7017 pStubMsg->Buffer += cbNDRContext;
7019 return ContextHandle;
7022 /***********************************************************************
7023 * NdrCorrelationInitialize [RPCRT4.@]
7025 * Initializes correlation validity checking.
7027 * PARAMS
7028 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7029 * pMemory [I] Pointer to memory to use as a cache.
7030 * CacheSize [I] Size of the memory pointed to by pMemory.
7031 * Flags [I] Reserved. Set to zero.
7033 * RETURNS
7034 * Nothing.
7036 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
7038 FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
7039 pStubMsg->fHasNewCorrDesc = TRUE;
7042 /***********************************************************************
7043 * NdrCorrelationPass [RPCRT4.@]
7045 * Performs correlation validity checking.
7047 * PARAMS
7048 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7050 * RETURNS
7051 * Nothing.
7053 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
7055 FIXME("(%p): stub\n", pStubMsg);
7058 /***********************************************************************
7059 * NdrCorrelationFree [RPCRT4.@]
7061 * Frees any resources used while unmarshalling parameters that need
7062 * correlation validity checking.
7064 * PARAMS
7065 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7067 * RETURNS
7068 * Nothing.
7070 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
7072 FIXME("(%p): stub\n", pStubMsg);