msxml3: Don't leak externaly allocated xmlSAXHandler.
[wine/hramrach.git] / dlls / rpcrt4 / ndr_marshall.c
blob3b10af45eee4bb9a7e7ef8ec57bbfbb7e38082e5
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_HYPER:
2700 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2701 safe_copy_to_buffer(pStubMsg, pMemory, 8);
2702 pMemory += 8;
2703 break;
2704 case RPC_FC_POINTER:
2706 unsigned char *saved_buffer;
2707 int pointer_buffer_mark_set = 0;
2708 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2709 TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2710 if (*pPointer != RPC_FC_RP)
2711 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2712 saved_buffer = pStubMsg->Buffer;
2713 if (pStubMsg->PointerBufferMark)
2715 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2716 pStubMsg->PointerBufferMark = NULL;
2717 pointer_buffer_mark_set = 1;
2719 else if (*pPointer != RPC_FC_RP)
2720 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2721 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2722 if (pointer_buffer_mark_set)
2724 STD_OVERFLOW_CHECK(pStubMsg);
2725 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2726 pStubMsg->Buffer = saved_buffer;
2727 if (*pPointer != RPC_FC_RP)
2728 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2730 TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2731 pPointer += 4;
2732 pMemory += sizeof(void *);
2733 break;
2735 case RPC_FC_ALIGNM2:
2736 ALIGN_POINTER(pMemory, 2);
2737 break;
2738 case RPC_FC_ALIGNM4:
2739 ALIGN_POINTER(pMemory, 4);
2740 break;
2741 case RPC_FC_ALIGNM8:
2742 ALIGN_POINTER(pMemory, 8);
2743 break;
2744 case RPC_FC_STRUCTPAD1:
2745 case RPC_FC_STRUCTPAD2:
2746 case RPC_FC_STRUCTPAD3:
2747 case RPC_FC_STRUCTPAD4:
2748 case RPC_FC_STRUCTPAD5:
2749 case RPC_FC_STRUCTPAD6:
2750 case RPC_FC_STRUCTPAD7:
2751 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2752 break;
2753 case RPC_FC_EMBEDDED_COMPLEX:
2754 pMemory += pFormat[1];
2755 pFormat += 2;
2756 desc = pFormat + *(const SHORT*)pFormat;
2757 size = EmbeddedComplexSize(pStubMsg, desc);
2758 TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2759 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2760 if (m)
2762 /* for some reason interface pointers aren't generated as
2763 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2764 * they still need the derefencing treatment that pointers are
2765 * given */
2766 if (*desc == RPC_FC_IP)
2767 m(pStubMsg, *(unsigned char **)pMemory, desc);
2768 else
2769 m(pStubMsg, pMemory, desc);
2771 else FIXME("no marshaller for embedded type %02x\n", *desc);
2772 pMemory += size;
2773 pFormat += 2;
2774 continue;
2775 case RPC_FC_PAD:
2776 break;
2777 default:
2778 FIXME("unhandled format 0x%02x\n", *pFormat);
2780 pFormat++;
2783 return pMemory;
2786 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2787 unsigned char *pMemory,
2788 PFORMAT_STRING pFormat,
2789 PFORMAT_STRING pPointer,
2790 unsigned char fMustAlloc)
2792 PFORMAT_STRING desc;
2793 NDR_UNMARSHALL m;
2794 ULONG size;
2796 while (*pFormat != RPC_FC_END) {
2797 switch (*pFormat) {
2798 case RPC_FC_BYTE:
2799 case RPC_FC_CHAR:
2800 case RPC_FC_SMALL:
2801 case RPC_FC_USMALL:
2802 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2803 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2804 pMemory += 1;
2805 break;
2806 case RPC_FC_WCHAR:
2807 case RPC_FC_SHORT:
2808 case RPC_FC_USHORT:
2809 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2810 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2811 pMemory += 2;
2812 break;
2813 case RPC_FC_ENUM16:
2814 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2815 *(DWORD*)pMemory &= 0xffff;
2816 TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2817 if (32767 < *(DWORD*)pMemory)
2818 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2819 pMemory += 4;
2820 break;
2821 case RPC_FC_LONG:
2822 case RPC_FC_ULONG:
2823 case RPC_FC_ENUM32:
2824 safe_copy_from_buffer(pStubMsg, pMemory, 4);
2825 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2826 pMemory += 4;
2827 break;
2828 case RPC_FC_HYPER:
2829 safe_copy_from_buffer(pStubMsg, pMemory, 8);
2830 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2831 pMemory += 8;
2832 break;
2833 case RPC_FC_POINTER:
2835 unsigned char *saved_buffer;
2836 int pointer_buffer_mark_set = 0;
2837 TRACE("pointer => %p\n", pMemory);
2838 if (*pPointer != RPC_FC_RP)
2839 ALIGN_POINTER(pStubMsg->Buffer, 4);
2840 saved_buffer = pStubMsg->Buffer;
2841 if (pStubMsg->PointerBufferMark)
2843 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2844 pStubMsg->PointerBufferMark = NULL;
2845 pointer_buffer_mark_set = 1;
2847 else if (*pPointer != RPC_FC_RP)
2848 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2850 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
2851 if (pointer_buffer_mark_set)
2853 STD_OVERFLOW_CHECK(pStubMsg);
2854 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2855 pStubMsg->Buffer = saved_buffer;
2856 if (*pPointer != RPC_FC_RP)
2857 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2859 pPointer += 4;
2860 pMemory += sizeof(void *);
2861 break;
2863 case RPC_FC_ALIGNM2:
2864 ALIGN_POINTER_CLEAR(pMemory, 2);
2865 break;
2866 case RPC_FC_ALIGNM4:
2867 ALIGN_POINTER_CLEAR(pMemory, 4);
2868 break;
2869 case RPC_FC_ALIGNM8:
2870 ALIGN_POINTER_CLEAR(pMemory, 8);
2871 break;
2872 case RPC_FC_STRUCTPAD1:
2873 case RPC_FC_STRUCTPAD2:
2874 case RPC_FC_STRUCTPAD3:
2875 case RPC_FC_STRUCTPAD4:
2876 case RPC_FC_STRUCTPAD5:
2877 case RPC_FC_STRUCTPAD6:
2878 case RPC_FC_STRUCTPAD7:
2879 memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2880 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2881 break;
2882 case RPC_FC_EMBEDDED_COMPLEX:
2883 pMemory += pFormat[1];
2884 pFormat += 2;
2885 desc = pFormat + *(const SHORT*)pFormat;
2886 size = EmbeddedComplexSize(pStubMsg, desc);
2887 TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
2888 if (fMustAlloc)
2889 /* we can't pass fMustAlloc=TRUE into the marshaller for this type
2890 * since the type is part of the memory block that is encompassed by
2891 * the whole complex type. Memory is forced to allocate when pointers
2892 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
2893 * clearing the memory we pass in to the unmarshaller */
2894 memset(pMemory, 0, size);
2895 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2896 if (m)
2898 /* for some reason interface pointers aren't generated as
2899 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2900 * they still need the derefencing treatment that pointers are
2901 * given */
2902 if (*desc == RPC_FC_IP)
2903 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2904 else
2905 m(pStubMsg, &pMemory, desc, FALSE);
2907 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2908 pMemory += size;
2909 pFormat += 2;
2910 continue;
2911 case RPC_FC_PAD:
2912 break;
2913 default:
2914 FIXME("unhandled format %d\n", *pFormat);
2916 pFormat++;
2919 return pMemory;
2922 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2923 unsigned char *pMemory,
2924 PFORMAT_STRING pFormat,
2925 PFORMAT_STRING pPointer)
2927 PFORMAT_STRING desc;
2928 NDR_BUFFERSIZE m;
2929 ULONG size;
2931 while (*pFormat != RPC_FC_END) {
2932 switch (*pFormat) {
2933 case RPC_FC_BYTE:
2934 case RPC_FC_CHAR:
2935 case RPC_FC_SMALL:
2936 case RPC_FC_USMALL:
2937 safe_buffer_length_increment(pStubMsg, 1);
2938 pMemory += 1;
2939 break;
2940 case RPC_FC_WCHAR:
2941 case RPC_FC_SHORT:
2942 case RPC_FC_USHORT:
2943 safe_buffer_length_increment(pStubMsg, 2);
2944 pMemory += 2;
2945 break;
2946 case RPC_FC_ENUM16:
2947 safe_buffer_length_increment(pStubMsg, 2);
2948 pMemory += 4;
2949 break;
2950 case RPC_FC_LONG:
2951 case RPC_FC_ULONG:
2952 case RPC_FC_ENUM32:
2953 safe_buffer_length_increment(pStubMsg, 4);
2954 pMemory += 4;
2955 break;
2956 case RPC_FC_HYPER:
2957 safe_buffer_length_increment(pStubMsg, 8);
2958 pMemory += 8;
2959 break;
2960 case RPC_FC_POINTER:
2961 if (!pStubMsg->IgnoreEmbeddedPointers)
2963 int saved_buffer_length = pStubMsg->BufferLength;
2964 pStubMsg->BufferLength = pStubMsg->PointerLength;
2965 pStubMsg->PointerLength = 0;
2966 if(!pStubMsg->BufferLength)
2967 ERR("BufferLength == 0??\n");
2968 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2969 pStubMsg->PointerLength = pStubMsg->BufferLength;
2970 pStubMsg->BufferLength = saved_buffer_length;
2972 if (*pPointer != RPC_FC_RP)
2974 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2975 safe_buffer_length_increment(pStubMsg, 4);
2977 pPointer += 4;
2978 pMemory += sizeof(void*);
2979 break;
2980 case RPC_FC_ALIGNM2:
2981 ALIGN_POINTER(pMemory, 2);
2982 break;
2983 case RPC_FC_ALIGNM4:
2984 ALIGN_POINTER(pMemory, 4);
2985 break;
2986 case RPC_FC_ALIGNM8:
2987 ALIGN_POINTER(pMemory, 8);
2988 break;
2989 case RPC_FC_STRUCTPAD1:
2990 case RPC_FC_STRUCTPAD2:
2991 case RPC_FC_STRUCTPAD3:
2992 case RPC_FC_STRUCTPAD4:
2993 case RPC_FC_STRUCTPAD5:
2994 case RPC_FC_STRUCTPAD6:
2995 case RPC_FC_STRUCTPAD7:
2996 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2997 break;
2998 case RPC_FC_EMBEDDED_COMPLEX:
2999 pMemory += pFormat[1];
3000 pFormat += 2;
3001 desc = pFormat + *(const SHORT*)pFormat;
3002 size = EmbeddedComplexSize(pStubMsg, desc);
3003 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3004 if (m)
3006 /* for some reason interface pointers aren't generated as
3007 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3008 * they still need the derefencing treatment that pointers are
3009 * given */
3010 if (*desc == RPC_FC_IP)
3011 m(pStubMsg, *(unsigned char **)pMemory, desc);
3012 else
3013 m(pStubMsg, pMemory, desc);
3015 else FIXME("no buffersizer for embedded type %02x\n", *desc);
3016 pMemory += size;
3017 pFormat += 2;
3018 continue;
3019 case RPC_FC_PAD:
3020 break;
3021 default:
3022 FIXME("unhandled format 0x%02x\n", *pFormat);
3024 pFormat++;
3027 return pMemory;
3030 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
3031 unsigned char *pMemory,
3032 PFORMAT_STRING pFormat,
3033 PFORMAT_STRING pPointer)
3035 PFORMAT_STRING desc;
3036 NDR_FREE m;
3037 ULONG size;
3039 while (*pFormat != RPC_FC_END) {
3040 switch (*pFormat) {
3041 case RPC_FC_BYTE:
3042 case RPC_FC_CHAR:
3043 case RPC_FC_SMALL:
3044 case RPC_FC_USMALL:
3045 pMemory += 1;
3046 break;
3047 case RPC_FC_WCHAR:
3048 case RPC_FC_SHORT:
3049 case RPC_FC_USHORT:
3050 pMemory += 2;
3051 break;
3052 case RPC_FC_LONG:
3053 case RPC_FC_ULONG:
3054 case RPC_FC_ENUM16:
3055 case RPC_FC_ENUM32:
3056 pMemory += 4;
3057 break;
3058 case RPC_FC_HYPER:
3059 pMemory += 8;
3060 break;
3061 case RPC_FC_POINTER:
3062 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3063 pPointer += 4;
3064 pMemory += sizeof(void *);
3065 break;
3066 case RPC_FC_ALIGNM2:
3067 ALIGN_POINTER(pMemory, 2);
3068 break;
3069 case RPC_FC_ALIGNM4:
3070 ALIGN_POINTER(pMemory, 4);
3071 break;
3072 case RPC_FC_ALIGNM8:
3073 ALIGN_POINTER(pMemory, 8);
3074 break;
3075 case RPC_FC_STRUCTPAD1:
3076 case RPC_FC_STRUCTPAD2:
3077 case RPC_FC_STRUCTPAD3:
3078 case RPC_FC_STRUCTPAD4:
3079 case RPC_FC_STRUCTPAD5:
3080 case RPC_FC_STRUCTPAD6:
3081 case RPC_FC_STRUCTPAD7:
3082 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3083 break;
3084 case RPC_FC_EMBEDDED_COMPLEX:
3085 pMemory += pFormat[1];
3086 pFormat += 2;
3087 desc = pFormat + *(const SHORT*)pFormat;
3088 size = EmbeddedComplexSize(pStubMsg, desc);
3089 m = NdrFreer[*desc & NDR_TABLE_MASK];
3090 if (m)
3092 /* for some reason interface pointers aren't generated as
3093 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3094 * they still need the derefencing treatment that pointers are
3095 * given */
3096 if (*desc == RPC_FC_IP)
3097 m(pStubMsg, *(unsigned char **)pMemory, desc);
3098 else
3099 m(pStubMsg, pMemory, desc);
3101 pMemory += size;
3102 pFormat += 2;
3103 continue;
3104 case RPC_FC_PAD:
3105 break;
3106 default:
3107 FIXME("unhandled format 0x%02x\n", *pFormat);
3109 pFormat++;
3112 return pMemory;
3115 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3116 PFORMAT_STRING pFormat,
3117 PFORMAT_STRING pPointer)
3119 PFORMAT_STRING desc;
3120 ULONG size = 0;
3122 while (*pFormat != RPC_FC_END) {
3123 switch (*pFormat) {
3124 case RPC_FC_BYTE:
3125 case RPC_FC_CHAR:
3126 case RPC_FC_SMALL:
3127 case RPC_FC_USMALL:
3128 size += 1;
3129 safe_buffer_increment(pStubMsg, 1);
3130 break;
3131 case RPC_FC_WCHAR:
3132 case RPC_FC_SHORT:
3133 case RPC_FC_USHORT:
3134 size += 2;
3135 safe_buffer_increment(pStubMsg, 2);
3136 break;
3137 case RPC_FC_ENUM16:
3138 size += 4;
3139 safe_buffer_increment(pStubMsg, 2);
3140 break;
3141 case RPC_FC_LONG:
3142 case RPC_FC_ULONG:
3143 case RPC_FC_ENUM32:
3144 size += 4;
3145 safe_buffer_increment(pStubMsg, 4);
3146 break;
3147 case RPC_FC_HYPER:
3148 size += 8;
3149 safe_buffer_increment(pStubMsg, 8);
3150 break;
3151 case RPC_FC_POINTER:
3153 unsigned char *saved_buffer;
3154 int pointer_buffer_mark_set = 0;
3155 if (*pPointer != RPC_FC_RP)
3156 ALIGN_POINTER(pStubMsg->Buffer, 4);
3157 saved_buffer = pStubMsg->Buffer;
3158 if (pStubMsg->PointerBufferMark)
3160 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3161 pStubMsg->PointerBufferMark = NULL;
3162 pointer_buffer_mark_set = 1;
3164 else if (*pPointer != RPC_FC_RP)
3165 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3167 if (!pStubMsg->IgnoreEmbeddedPointers)
3168 PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3169 if (pointer_buffer_mark_set)
3171 STD_OVERFLOW_CHECK(pStubMsg);
3172 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3173 pStubMsg->Buffer = saved_buffer;
3174 if (*pPointer != RPC_FC_RP)
3175 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3177 pPointer += 4;
3178 size += sizeof(void *);
3179 break;
3181 case RPC_FC_ALIGNM2:
3182 ALIGN_LENGTH(size, 2);
3183 break;
3184 case RPC_FC_ALIGNM4:
3185 ALIGN_LENGTH(size, 4);
3186 break;
3187 case RPC_FC_ALIGNM8:
3188 ALIGN_LENGTH(size, 8);
3189 break;
3190 case RPC_FC_STRUCTPAD1:
3191 case RPC_FC_STRUCTPAD2:
3192 case RPC_FC_STRUCTPAD3:
3193 case RPC_FC_STRUCTPAD4:
3194 case RPC_FC_STRUCTPAD5:
3195 case RPC_FC_STRUCTPAD6:
3196 case RPC_FC_STRUCTPAD7:
3197 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3198 break;
3199 case RPC_FC_EMBEDDED_COMPLEX:
3200 size += pFormat[1];
3201 pFormat += 2;
3202 desc = pFormat + *(const SHORT*)pFormat;
3203 size += EmbeddedComplexMemorySize(pStubMsg, desc);
3204 pFormat += 2;
3205 continue;
3206 case RPC_FC_PAD:
3207 break;
3208 default:
3209 FIXME("unhandled format 0x%02x\n", *pFormat);
3211 pFormat++;
3214 return size;
3217 ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
3219 PFORMAT_STRING desc;
3220 ULONG size = 0;
3222 while (*pFormat != RPC_FC_END) {
3223 switch (*pFormat) {
3224 case RPC_FC_BYTE:
3225 case RPC_FC_CHAR:
3226 case RPC_FC_SMALL:
3227 case RPC_FC_USMALL:
3228 size += 1;
3229 break;
3230 case RPC_FC_WCHAR:
3231 case RPC_FC_SHORT:
3232 case RPC_FC_USHORT:
3233 size += 2;
3234 break;
3235 case RPC_FC_LONG:
3236 case RPC_FC_ULONG:
3237 case RPC_FC_ENUM16:
3238 case RPC_FC_ENUM32:
3239 size += 4;
3240 break;
3241 case RPC_FC_HYPER:
3242 size += 8;
3243 break;
3244 case RPC_FC_POINTER:
3245 size += sizeof(void *);
3246 break;
3247 case RPC_FC_ALIGNM2:
3248 ALIGN_LENGTH(size, 2);
3249 break;
3250 case RPC_FC_ALIGNM4:
3251 ALIGN_LENGTH(size, 4);
3252 break;
3253 case RPC_FC_ALIGNM8:
3254 ALIGN_LENGTH(size, 8);
3255 break;
3256 case RPC_FC_STRUCTPAD1:
3257 case RPC_FC_STRUCTPAD2:
3258 case RPC_FC_STRUCTPAD3:
3259 case RPC_FC_STRUCTPAD4:
3260 case RPC_FC_STRUCTPAD5:
3261 case RPC_FC_STRUCTPAD6:
3262 case RPC_FC_STRUCTPAD7:
3263 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3264 break;
3265 case RPC_FC_EMBEDDED_COMPLEX:
3266 size += pFormat[1];
3267 pFormat += 2;
3268 desc = pFormat + *(const SHORT*)pFormat;
3269 size += EmbeddedComplexSize(pStubMsg, desc);
3270 pFormat += 2;
3271 continue;
3272 case RPC_FC_PAD:
3273 break;
3274 default:
3275 FIXME("unhandled format 0x%02x\n", *pFormat);
3277 pFormat++;
3280 return size;
3283 /***********************************************************************
3284 * NdrComplexStructMarshall [RPCRT4.@]
3286 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3287 unsigned char *pMemory,
3288 PFORMAT_STRING pFormat)
3290 PFORMAT_STRING conf_array = NULL;
3291 PFORMAT_STRING pointer_desc = NULL;
3292 unsigned char *OldMemory = pStubMsg->Memory;
3293 int pointer_buffer_mark_set = 0;
3294 ULONG count = 0;
3295 ULONG max_count = 0;
3296 ULONG offset = 0;
3298 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3300 if (!pStubMsg->PointerBufferMark)
3302 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3303 /* save buffer length */
3304 ULONG saved_buffer_length = pStubMsg->BufferLength;
3306 /* get the buffer pointer after complex array data, but before
3307 * pointer data */
3308 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3309 pStubMsg->IgnoreEmbeddedPointers = 1;
3310 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3311 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3313 /* save it for use by embedded pointer code later */
3314 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3315 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
3316 pointer_buffer_mark_set = 1;
3318 /* restore the original buffer length */
3319 pStubMsg->BufferLength = saved_buffer_length;
3322 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
3324 pFormat += 4;
3325 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3326 pFormat += 2;
3327 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3328 pFormat += 2;
3330 pStubMsg->Memory = pMemory;
3332 if (conf_array)
3334 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3335 array_compute_and_write_conformance(conf_array[0], pStubMsg,
3336 pMemory + struct_size, conf_array);
3337 /* these could be changed in ComplexMarshall so save them for later */
3338 max_count = pStubMsg->MaxCount;
3339 count = pStubMsg->ActualCount;
3340 offset = pStubMsg->Offset;
3343 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3345 if (conf_array)
3347 pStubMsg->MaxCount = max_count;
3348 pStubMsg->ActualCount = count;
3349 pStubMsg->Offset = offset;
3350 array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3351 conf_array, TRUE /* fHasPointers */);
3354 pStubMsg->Memory = OldMemory;
3356 if (pointer_buffer_mark_set)
3358 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3359 pStubMsg->PointerBufferMark = NULL;
3362 STD_OVERFLOW_CHECK(pStubMsg);
3364 return NULL;
3367 /***********************************************************************
3368 * NdrComplexStructUnmarshall [RPCRT4.@]
3370 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3371 unsigned char **ppMemory,
3372 PFORMAT_STRING pFormat,
3373 unsigned char fMustAlloc)
3375 unsigned size = *(const WORD*)(pFormat+2);
3376 PFORMAT_STRING conf_array = NULL;
3377 PFORMAT_STRING pointer_desc = NULL;
3378 unsigned char *pMemory;
3379 int pointer_buffer_mark_set = 0;
3380 ULONG count = 0;
3381 ULONG max_count = 0;
3382 ULONG offset = 0;
3383 ULONG array_size = 0;
3385 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3387 if (!pStubMsg->PointerBufferMark)
3389 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3390 /* save buffer pointer */
3391 unsigned char *saved_buffer = pStubMsg->Buffer;
3393 /* get the buffer pointer after complex array data, but before
3394 * pointer data */
3395 pStubMsg->IgnoreEmbeddedPointers = 1;
3396 NdrComplexStructMemorySize(pStubMsg, pFormat);
3397 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3399 /* save it for use by embedded pointer code later */
3400 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3401 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
3402 pointer_buffer_mark_set = 1;
3404 /* restore the original buffer */
3405 pStubMsg->Buffer = saved_buffer;
3408 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3410 pFormat += 4;
3411 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3412 pFormat += 2;
3413 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3414 pFormat += 2;
3416 if (conf_array)
3418 array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3419 size += array_size;
3421 /* these could be changed in ComplexMarshall so save them for later */
3422 max_count = pStubMsg->MaxCount;
3423 count = pStubMsg->ActualCount;
3424 offset = pStubMsg->Offset;
3427 if (!fMustAlloc && !*ppMemory)
3428 fMustAlloc = TRUE;
3429 if (fMustAlloc)
3430 *ppMemory = NdrAllocate(pStubMsg, size);
3432 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3434 if (conf_array)
3436 pStubMsg->MaxCount = max_count;
3437 pStubMsg->ActualCount = count;
3438 pStubMsg->Offset = offset;
3439 if (fMustAlloc)
3440 memset(pMemory, 0, array_size);
3441 array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3442 conf_array, FALSE,
3443 FALSE /* fUseBufferMemoryServer */,
3444 TRUE /* fUnmarshall */);
3447 if (pointer_buffer_mark_set)
3449 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3450 pStubMsg->PointerBufferMark = NULL;
3453 return NULL;
3456 /***********************************************************************
3457 * NdrComplexStructBufferSize [RPCRT4.@]
3459 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3460 unsigned char *pMemory,
3461 PFORMAT_STRING pFormat)
3463 PFORMAT_STRING conf_array = NULL;
3464 PFORMAT_STRING pointer_desc = NULL;
3465 unsigned char *OldMemory = pStubMsg->Memory;
3466 int pointer_length_set = 0;
3467 ULONG count = 0;
3468 ULONG max_count = 0;
3469 ULONG offset = 0;
3471 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3473 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
3475 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3477 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3478 ULONG saved_buffer_length = pStubMsg->BufferLength;
3480 /* get the buffer length after complex struct data, but before
3481 * pointer data */
3482 pStubMsg->IgnoreEmbeddedPointers = 1;
3483 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3484 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3486 /* save it for use by embedded pointer code later */
3487 pStubMsg->PointerLength = pStubMsg->BufferLength;
3488 pointer_length_set = 1;
3489 TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
3491 /* restore the original buffer length */
3492 pStubMsg->BufferLength = saved_buffer_length;
3495 pFormat += 4;
3496 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3497 pFormat += 2;
3498 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3499 pFormat += 2;
3501 pStubMsg->Memory = pMemory;
3503 if (conf_array)
3505 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3506 array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3507 conf_array);
3509 /* these could be changed in ComplexMarshall so save them for later */
3510 max_count = pStubMsg->MaxCount;
3511 count = pStubMsg->ActualCount;
3512 offset = pStubMsg->Offset;
3515 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3517 if (conf_array)
3519 pStubMsg->MaxCount = max_count;
3520 pStubMsg->ActualCount = count;
3521 pStubMsg->Offset = offset;
3522 array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3523 TRUE /* fHasPointers */);
3526 pStubMsg->Memory = OldMemory;
3528 if(pointer_length_set)
3530 pStubMsg->BufferLength = pStubMsg->PointerLength;
3531 pStubMsg->PointerLength = 0;
3536 /***********************************************************************
3537 * NdrComplexStructMemorySize [RPCRT4.@]
3539 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3540 PFORMAT_STRING pFormat)
3542 unsigned size = *(const WORD*)(pFormat+2);
3543 PFORMAT_STRING conf_array = NULL;
3544 PFORMAT_STRING pointer_desc = NULL;
3545 ULONG count = 0;
3546 ULONG max_count = 0;
3547 ULONG offset = 0;
3549 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3551 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3553 pFormat += 4;
3554 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3555 pFormat += 2;
3556 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3557 pFormat += 2;
3559 if (conf_array)
3561 array_read_conformance(conf_array[0], pStubMsg, conf_array);
3563 /* these could be changed in ComplexStructMemorySize so save them for
3564 * later */
3565 max_count = pStubMsg->MaxCount;
3566 count = pStubMsg->ActualCount;
3567 offset = pStubMsg->Offset;
3570 ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3572 if (conf_array)
3574 pStubMsg->MaxCount = max_count;
3575 pStubMsg->ActualCount = count;
3576 pStubMsg->Offset = offset;
3577 array_memory_size(conf_array[0], pStubMsg, conf_array,
3578 TRUE /* fHasPointers */);
3581 return size;
3584 /***********************************************************************
3585 * NdrComplexStructFree [RPCRT4.@]
3587 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3588 unsigned char *pMemory,
3589 PFORMAT_STRING pFormat)
3591 PFORMAT_STRING conf_array = NULL;
3592 PFORMAT_STRING pointer_desc = NULL;
3593 unsigned char *OldMemory = pStubMsg->Memory;
3595 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3597 pFormat += 4;
3598 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3599 pFormat += 2;
3600 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3601 pFormat += 2;
3603 pStubMsg->Memory = pMemory;
3605 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3607 if (conf_array)
3608 array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3609 TRUE /* fHasPointers */);
3611 pStubMsg->Memory = OldMemory;
3614 /***********************************************************************
3615 * NdrConformantArrayMarshall [RPCRT4.@]
3617 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3618 unsigned char *pMemory,
3619 PFORMAT_STRING pFormat)
3621 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3622 if (pFormat[0] != RPC_FC_CARRAY)
3624 ERR("invalid format = 0x%x\n", pFormat[0]);
3625 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3628 array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
3629 pFormat);
3630 array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3631 TRUE /* fHasPointers */);
3633 return NULL;
3636 /***********************************************************************
3637 * NdrConformantArrayUnmarshall [RPCRT4.@]
3639 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3640 unsigned char **ppMemory,
3641 PFORMAT_STRING pFormat,
3642 unsigned char fMustAlloc)
3644 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3645 if (pFormat[0] != RPC_FC_CARRAY)
3647 ERR("invalid format = 0x%x\n", pFormat[0]);
3648 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3651 array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3652 array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
3653 fMustAlloc,
3654 TRUE /* fUseBufferMemoryServer */,
3655 TRUE /* fUnmarshall */);
3657 return NULL;
3660 /***********************************************************************
3661 * NdrConformantArrayBufferSize [RPCRT4.@]
3663 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3664 unsigned char *pMemory,
3665 PFORMAT_STRING pFormat)
3667 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3668 if (pFormat[0] != RPC_FC_CARRAY)
3670 ERR("invalid format = 0x%x\n", pFormat[0]);
3671 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3674 array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat);
3675 array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3676 TRUE /* fHasPointers */);
3679 /***********************************************************************
3680 * NdrConformantArrayMemorySize [RPCRT4.@]
3682 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3683 PFORMAT_STRING pFormat)
3685 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3686 if (pFormat[0] != RPC_FC_CARRAY)
3688 ERR("invalid format = 0x%x\n", pFormat[0]);
3689 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3692 array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3693 array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
3695 return pStubMsg->MemorySize;
3698 /***********************************************************************
3699 * NdrConformantArrayFree [RPCRT4.@]
3701 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3702 unsigned char *pMemory,
3703 PFORMAT_STRING pFormat)
3705 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3706 if (pFormat[0] != RPC_FC_CARRAY)
3708 ERR("invalid format = 0x%x\n", pFormat[0]);
3709 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3712 array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3713 TRUE /* fHasPointers */);
3717 /***********************************************************************
3718 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
3720 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
3721 unsigned char* pMemory,
3722 PFORMAT_STRING pFormat )
3724 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3726 if (pFormat[0] != RPC_FC_CVARRAY)
3728 ERR("invalid format type %x\n", pFormat[0]);
3729 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3730 return NULL;
3733 array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3734 pFormat);
3735 array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory,
3736 pFormat, TRUE /* fHasPointers */);
3738 return NULL;
3742 /***********************************************************************
3743 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
3745 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
3746 unsigned char** ppMemory,
3747 PFORMAT_STRING pFormat,
3748 unsigned char fMustAlloc )
3750 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3752 if (pFormat[0] != RPC_FC_CVARRAY)
3754 ERR("invalid format type %x\n", pFormat[0]);
3755 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3756 return NULL;
3759 array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3760 array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory,
3761 pFormat, fMustAlloc,
3762 TRUE /* fUseBufferMemoryServer */,
3763 TRUE /* fUnmarshall */);
3765 return NULL;
3769 /***********************************************************************
3770 * NdrConformantVaryingArrayFree [RPCRT4.@]
3772 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
3773 unsigned char* pMemory,
3774 PFORMAT_STRING pFormat )
3776 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3778 if (pFormat[0] != RPC_FC_CVARRAY)
3780 ERR("invalid format type %x\n", pFormat[0]);
3781 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3782 return;
3785 array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3786 TRUE /* fHasPointers */);
3790 /***********************************************************************
3791 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
3793 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
3794 unsigned char* pMemory, PFORMAT_STRING pFormat )
3796 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3798 if (pFormat[0] != RPC_FC_CVARRAY)
3800 ERR("invalid format type %x\n", pFormat[0]);
3801 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3802 return;
3805 array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3806 pFormat);
3807 array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3808 TRUE /* fHasPointers */);
3812 /***********************************************************************
3813 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
3815 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
3816 PFORMAT_STRING pFormat )
3818 TRACE("(%p, %p)\n", pStubMsg, pFormat);
3820 if (pFormat[0] != RPC_FC_CVARRAY)
3822 ERR("invalid format type %x\n", pFormat[0]);
3823 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3824 return pStubMsg->MemorySize;
3827 array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3828 array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat,
3829 TRUE /* fHasPointers */);
3831 return pStubMsg->MemorySize;
3835 /***********************************************************************
3836 * NdrComplexArrayMarshall [RPCRT4.@]
3838 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3839 unsigned char *pMemory,
3840 PFORMAT_STRING pFormat)
3842 ULONG i, count, def;
3843 BOOL variance_present;
3844 unsigned char alignment;
3845 int pointer_buffer_mark_set = 0;
3847 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3849 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3851 ERR("invalid format type %x\n", pFormat[0]);
3852 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3853 return NULL;
3856 alignment = pFormat[1] + 1;
3858 if (!pStubMsg->PointerBufferMark)
3860 /* save buffer fields that may be changed by buffer sizer functions
3861 * and that may be needed later on */
3862 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3863 ULONG saved_buffer_length = pStubMsg->BufferLength;
3864 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
3865 ULONG saved_offset = pStubMsg->Offset;
3866 ULONG saved_actual_count = pStubMsg->ActualCount;
3868 /* get the buffer pointer after complex array data, but before
3869 * pointer data */
3870 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3871 pStubMsg->IgnoreEmbeddedPointers = 1;
3872 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3873 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3875 /* save it for use by embedded pointer code later */
3876 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3877 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
3878 pointer_buffer_mark_set = 1;
3880 /* restore fields */
3881 pStubMsg->ActualCount = saved_actual_count;
3882 pStubMsg->Offset = saved_offset;
3883 pStubMsg->MaxCount = saved_max_count;
3884 pStubMsg->BufferLength = saved_buffer_length;
3887 def = *(const WORD*)&pFormat[2];
3888 pFormat += 4;
3890 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3891 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3893 variance_present = IsConformanceOrVariancePresent(pFormat);
3894 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3895 TRACE("variance = %d\n", pStubMsg->ActualCount);
3897 WriteConformance(pStubMsg);
3898 if (variance_present)
3899 WriteVariance(pStubMsg);
3901 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3903 count = pStubMsg->ActualCount;
3904 for (i = 0; i < count; i++)
3905 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3907 STD_OVERFLOW_CHECK(pStubMsg);
3909 if (pointer_buffer_mark_set)
3911 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3912 pStubMsg->PointerBufferMark = NULL;
3915 return NULL;
3918 /***********************************************************************
3919 * NdrComplexArrayUnmarshall [RPCRT4.@]
3921 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3922 unsigned char **ppMemory,
3923 PFORMAT_STRING pFormat,
3924 unsigned char fMustAlloc)
3926 ULONG i, count, size;
3927 unsigned char alignment;
3928 unsigned char *pMemory;
3929 unsigned char *saved_buffer;
3930 int pointer_buffer_mark_set = 0;
3931 int saved_ignore_embedded;
3933 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3935 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3937 ERR("invalid format type %x\n", pFormat[0]);
3938 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3939 return NULL;
3942 alignment = pFormat[1] + 1;
3944 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3945 /* save buffer pointer */
3946 saved_buffer = pStubMsg->Buffer;
3947 /* get the buffer pointer after complex array data, but before
3948 * pointer data */
3949 pStubMsg->IgnoreEmbeddedPointers = 1;
3950 pStubMsg->MemorySize = 0;
3951 NdrComplexArrayMemorySize(pStubMsg, pFormat);
3952 size = pStubMsg->MemorySize;
3953 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3955 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer));
3956 if (!pStubMsg->PointerBufferMark)
3958 /* save it for use by embedded pointer code later */
3959 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3960 pointer_buffer_mark_set = 1;
3962 /* restore the original buffer */
3963 pStubMsg->Buffer = saved_buffer;
3965 pFormat += 4;
3967 pFormat = ReadConformance(pStubMsg, pFormat);
3968 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3970 if (!fMustAlloc && !*ppMemory)
3971 fMustAlloc = TRUE;
3972 if (fMustAlloc)
3973 *ppMemory = NdrAllocate(pStubMsg, size);
3975 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3977 pMemory = *ppMemory;
3978 count = pStubMsg->ActualCount;
3979 for (i = 0; i < count; i++)
3980 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
3982 if (pointer_buffer_mark_set)
3984 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3985 pStubMsg->PointerBufferMark = NULL;
3988 return NULL;
3991 /***********************************************************************
3992 * NdrComplexArrayBufferSize [RPCRT4.@]
3994 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3995 unsigned char *pMemory,
3996 PFORMAT_STRING pFormat)
3998 ULONG i, count, def;
3999 unsigned char alignment;
4000 BOOL variance_present;
4001 int pointer_length_set = 0;
4003 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4005 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4007 ERR("invalid format type %x\n", pFormat[0]);
4008 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4009 return;
4012 alignment = pFormat[1] + 1;
4014 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
4016 /* save buffer fields that may be changed by buffer sizer functions
4017 * and that may be needed later on */
4018 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4019 ULONG saved_buffer_length = pStubMsg->BufferLength;
4020 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4021 ULONG saved_offset = pStubMsg->Offset;
4022 ULONG saved_actual_count = pStubMsg->ActualCount;
4024 /* get the buffer pointer after complex array data, but before
4025 * pointer data */
4026 pStubMsg->IgnoreEmbeddedPointers = 1;
4027 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4028 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4030 /* save it for use by embedded pointer code later */
4031 pStubMsg->PointerLength = pStubMsg->BufferLength;
4032 pointer_length_set = 1;
4034 /* restore fields */
4035 pStubMsg->ActualCount = saved_actual_count;
4036 pStubMsg->Offset = saved_offset;
4037 pStubMsg->MaxCount = saved_max_count;
4038 pStubMsg->BufferLength = saved_buffer_length;
4040 def = *(const WORD*)&pFormat[2];
4041 pFormat += 4;
4043 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4044 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4045 SizeConformance(pStubMsg);
4047 variance_present = IsConformanceOrVariancePresent(pFormat);
4048 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4049 TRACE("variance = %d\n", pStubMsg->ActualCount);
4051 if (variance_present)
4052 SizeVariance(pStubMsg);
4054 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4056 count = pStubMsg->ActualCount;
4057 for (i = 0; i < count; i++)
4058 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
4060 if(pointer_length_set)
4062 pStubMsg->BufferLength = pStubMsg->PointerLength;
4063 pStubMsg->PointerLength = 0;
4067 /***********************************************************************
4068 * NdrComplexArrayMemorySize [RPCRT4.@]
4070 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4071 PFORMAT_STRING pFormat)
4073 ULONG i, count, esize, SavedMemorySize, MemorySize;
4074 unsigned char alignment;
4076 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4078 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4080 ERR("invalid format type %x\n", pFormat[0]);
4081 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4082 return 0;
4085 alignment = pFormat[1] + 1;
4087 pFormat += 4;
4089 pFormat = ReadConformance(pStubMsg, pFormat);
4090 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
4092 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4094 SavedMemorySize = pStubMsg->MemorySize;
4096 esize = ComplexStructSize(pStubMsg, pFormat);
4098 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
4100 count = pStubMsg->ActualCount;
4101 for (i = 0; i < count; i++)
4102 ComplexStructMemorySize(pStubMsg, pFormat, NULL);
4104 pStubMsg->MemorySize = SavedMemorySize;
4106 pStubMsg->MemorySize += MemorySize;
4107 return MemorySize;
4110 /***********************************************************************
4111 * NdrComplexArrayFree [RPCRT4.@]
4113 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4114 unsigned char *pMemory,
4115 PFORMAT_STRING pFormat)
4117 ULONG i, count, def;
4119 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4121 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4123 ERR("invalid format type %x\n", pFormat[0]);
4124 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4125 return;
4128 def = *(const WORD*)&pFormat[2];
4129 pFormat += 4;
4131 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4132 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4134 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4135 TRACE("variance = %d\n", pStubMsg->ActualCount);
4137 count = pStubMsg->ActualCount;
4138 for (i = 0; i < count; i++)
4139 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
4142 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
4143 USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
4144 USER_MARSHAL_CB *umcb)
4146 umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
4147 pStubMsg->RpcMsg->DataRepresentation);
4148 umcb->pStubMsg = pStubMsg;
4149 umcb->pReserve = NULL;
4150 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
4151 umcb->CBType = cbtype;
4152 umcb->pFormat = pFormat;
4153 umcb->pTypeFormat = NULL /* FIXME */;
4156 #define USER_MARSHAL_PTR_PREFIX \
4157 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
4158 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
4160 /***********************************************************************
4161 * NdrUserMarshalMarshall [RPCRT4.@]
4163 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4164 unsigned char *pMemory,
4165 PFORMAT_STRING pFormat)
4167 unsigned flags = pFormat[1];
4168 unsigned index = *(const WORD*)&pFormat[2];
4169 unsigned char *saved_buffer = NULL;
4170 USER_MARSHAL_CB umcb;
4172 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4173 TRACE("index=%d\n", index);
4175 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
4177 if (flags & USER_MARSHAL_POINTER)
4179 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
4180 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
4181 pStubMsg->Buffer += 4;
4182 if (pStubMsg->PointerBufferMark)
4184 saved_buffer = pStubMsg->Buffer;
4185 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4186 pStubMsg->PointerBufferMark = NULL;
4188 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8);
4190 else
4191 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1);
4193 pStubMsg->Buffer =
4194 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
4195 &umcb.Flags, pStubMsg->Buffer, pMemory);
4197 if (saved_buffer)
4199 STD_OVERFLOW_CHECK(pStubMsg);
4200 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4201 pStubMsg->Buffer = saved_buffer;
4204 STD_OVERFLOW_CHECK(pStubMsg);
4206 return NULL;
4209 /***********************************************************************
4210 * NdrUserMarshalUnmarshall [RPCRT4.@]
4212 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4213 unsigned char **ppMemory,
4214 PFORMAT_STRING pFormat,
4215 unsigned char fMustAlloc)
4217 unsigned flags = pFormat[1];
4218 unsigned index = *(const WORD*)&pFormat[2];
4219 DWORD memsize = *(const WORD*)&pFormat[4];
4220 unsigned char *saved_buffer = NULL;
4221 USER_MARSHAL_CB umcb;
4223 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4224 TRACE("index=%d\n", index);
4226 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
4228 if (flags & USER_MARSHAL_POINTER)
4230 ALIGN_POINTER(pStubMsg->Buffer, 4);
4231 /* skip pointer prefix */
4232 pStubMsg->Buffer += 4;
4233 if (pStubMsg->PointerBufferMark)
4235 saved_buffer = pStubMsg->Buffer;
4236 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4237 pStubMsg->PointerBufferMark = NULL;
4239 ALIGN_POINTER(pStubMsg->Buffer, 8);
4241 else
4242 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4244 if (!fMustAlloc && !*ppMemory)
4245 fMustAlloc = TRUE;
4246 if (fMustAlloc)
4248 *ppMemory = NdrAllocate(pStubMsg, memsize);
4249 memset(*ppMemory, 0, memsize);
4252 pStubMsg->Buffer =
4253 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
4254 &umcb.Flags, pStubMsg->Buffer, *ppMemory);
4256 if (saved_buffer)
4258 STD_OVERFLOW_CHECK(pStubMsg);
4259 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4260 pStubMsg->Buffer = saved_buffer;
4263 return NULL;
4266 /***********************************************************************
4267 * NdrUserMarshalBufferSize [RPCRT4.@]
4269 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4270 unsigned char *pMemory,
4271 PFORMAT_STRING pFormat)
4273 unsigned flags = pFormat[1];
4274 unsigned index = *(const WORD*)&pFormat[2];
4275 DWORD bufsize = *(const WORD*)&pFormat[6];
4276 USER_MARSHAL_CB umcb;
4277 ULONG saved_buffer_length = 0;
4279 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4280 TRACE("index=%d\n", index);
4282 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
4284 if (flags & USER_MARSHAL_POINTER)
4286 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4287 /* skip pointer prefix */
4288 safe_buffer_length_increment(pStubMsg, 4);
4289 if (pStubMsg->IgnoreEmbeddedPointers)
4290 return;
4291 if (pStubMsg->PointerLength)
4293 saved_buffer_length = pStubMsg->BufferLength;
4294 pStubMsg->BufferLength = pStubMsg->PointerLength;
4295 pStubMsg->PointerLength = 0;
4297 ALIGN_LENGTH(pStubMsg->BufferLength, 8);
4299 else
4300 ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
4302 if (bufsize) {
4303 TRACE("size=%d\n", bufsize);
4304 safe_buffer_length_increment(pStubMsg, bufsize);
4306 else
4307 pStubMsg->BufferLength =
4308 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
4309 &umcb.Flags, pStubMsg->BufferLength, pMemory);
4311 if (saved_buffer_length)
4313 pStubMsg->PointerLength = pStubMsg->BufferLength;
4314 pStubMsg->BufferLength = saved_buffer_length;
4319 /***********************************************************************
4320 * NdrUserMarshalMemorySize [RPCRT4.@]
4322 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4323 PFORMAT_STRING pFormat)
4325 unsigned flags = pFormat[1];
4326 unsigned index = *(const WORD*)&pFormat[2];
4327 DWORD memsize = *(const WORD*)&pFormat[4];
4328 DWORD bufsize = *(const WORD*)&pFormat[6];
4330 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4331 TRACE("index=%d\n", index);
4333 pStubMsg->MemorySize += memsize;
4335 if (flags & USER_MARSHAL_POINTER)
4337 ALIGN_POINTER(pStubMsg->Buffer, 4);
4338 /* skip pointer prefix */
4339 pStubMsg->Buffer += 4;
4340 if (pStubMsg->IgnoreEmbeddedPointers)
4341 return pStubMsg->MemorySize;
4342 ALIGN_POINTER(pStubMsg->Buffer, 8);
4344 else
4345 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4347 if (!bufsize)
4348 FIXME("not implemented for varying buffer size\n");
4350 pStubMsg->Buffer += bufsize;
4352 return pStubMsg->MemorySize;
4355 /***********************************************************************
4356 * NdrUserMarshalFree [RPCRT4.@]
4358 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
4359 unsigned char *pMemory,
4360 PFORMAT_STRING pFormat)
4362 /* unsigned flags = pFormat[1]; */
4363 unsigned index = *(const WORD*)&pFormat[2];
4364 USER_MARSHAL_CB umcb;
4366 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4367 TRACE("index=%d\n", index);
4369 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
4371 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
4372 &umcb.Flags, pMemory);
4375 /***********************************************************************
4376 * NdrGetUserMarshalInfo [RPCRT4.@]
4378 RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi)
4380 USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags);
4382 TRACE("(%p,%u,%p)\n", flags, level, umi);
4384 if (level != 1)
4385 return RPC_S_INVALID_ARG;
4387 memset(&umi->u1.Level1, 0, sizeof(umi->u1.Level1));
4388 umi->InformationLevel = level;
4390 if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE)
4391 return RPC_S_INVALID_ARG;
4393 umi->u1.Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate;
4394 umi->u1.Level1.pfnFree = umcb->pStubMsg->pfnFree;
4395 umi->u1.Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer;
4397 switch (umcb->CBType)
4399 case USER_MARSHAL_CB_MARSHALL:
4400 case USER_MARSHAL_CB_UNMARSHALL:
4402 RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg;
4403 unsigned char *buffer_start = msg->Buffer;
4404 unsigned char *buffer_end =
4405 (unsigned char *)msg->Buffer + msg->BufferLength;
4407 if (umcb->pStubMsg->Buffer < buffer_start ||
4408 umcb->pStubMsg->Buffer > buffer_end)
4409 return ERROR_INVALID_USER_BUFFER;
4411 umi->u1.Level1.Buffer = umcb->pStubMsg->Buffer;
4412 umi->u1.Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer;
4413 break;
4415 case USER_MARSHAL_CB_BUFFER_SIZE:
4416 case USER_MARSHAL_CB_FREE:
4417 break;
4418 default:
4419 WARN("unrecognised CBType %d\n", umcb->CBType);
4422 return RPC_S_OK;
4425 /***********************************************************************
4426 * NdrClearOutParameters [RPCRT4.@]
4428 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
4429 PFORMAT_STRING pFormat,
4430 void *ArgAddr)
4432 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
4435 /***********************************************************************
4436 * NdrConvert [RPCRT4.@]
4438 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
4440 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
4441 /* FIXME: since this stub doesn't do any converting, the proper behavior
4442 is to raise an exception */
4445 /***********************************************************************
4446 * NdrConvert2 [RPCRT4.@]
4448 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
4450 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
4451 pStubMsg, pFormat, NumberParams);
4452 /* FIXME: since this stub doesn't do any converting, the proper behavior
4453 is to raise an exception */
4456 #include "pshpack1.h"
4457 typedef struct _NDR_CSTRUCT_FORMAT
4459 unsigned char type;
4460 unsigned char alignment;
4461 unsigned short memory_size;
4462 short offset_to_array_description;
4463 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
4464 #include "poppack.h"
4466 /***********************************************************************
4467 * NdrConformantStructMarshall [RPCRT4.@]
4469 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4470 unsigned char *pMemory,
4471 PFORMAT_STRING pFormat)
4473 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4474 PFORMAT_STRING pCArrayFormat;
4475 ULONG esize, bufsize;
4477 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4479 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4480 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4482 ERR("invalid format type %x\n", pCStructFormat->type);
4483 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4484 return NULL;
4487 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4488 pCStructFormat->offset_to_array_description;
4489 if (*pCArrayFormat != RPC_FC_CARRAY)
4491 ERR("invalid array format type %x\n", pCStructFormat->type);
4492 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4493 return NULL;
4495 esize = *(const WORD*)(pCArrayFormat+2);
4497 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4498 pCArrayFormat + 4, 0);
4500 WriteConformance(pStubMsg);
4502 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4504 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4506 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4507 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4509 ERR("integer overflow of memory_size %u with bufsize %u\n",
4510 pCStructFormat->memory_size, bufsize);
4511 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4513 /* copy constant sized part of struct */
4514 pStubMsg->BufferMark = pStubMsg->Buffer;
4515 safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
4517 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4518 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4520 return NULL;
4523 /***********************************************************************
4524 * NdrConformantStructUnmarshall [RPCRT4.@]
4526 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4527 unsigned char **ppMemory,
4528 PFORMAT_STRING pFormat,
4529 unsigned char fMustAlloc)
4531 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4532 PFORMAT_STRING pCArrayFormat;
4533 ULONG esize, bufsize;
4534 unsigned char *saved_buffer;
4536 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4538 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4539 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4541 ERR("invalid format type %x\n", pCStructFormat->type);
4542 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4543 return NULL;
4545 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4546 pCStructFormat->offset_to_array_description;
4547 if (*pCArrayFormat != RPC_FC_CARRAY)
4549 ERR("invalid array format type %x\n", pCStructFormat->type);
4550 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4551 return NULL;
4553 esize = *(const WORD*)(pCArrayFormat+2);
4555 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
4557 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4559 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4561 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4562 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4564 ERR("integer overflow of memory_size %u with bufsize %u\n",
4565 pCStructFormat->memory_size, bufsize);
4566 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4569 if (fMustAlloc)
4571 SIZE_T size = pCStructFormat->memory_size + bufsize;
4572 *ppMemory = NdrAllocate(pStubMsg, size);
4574 else
4576 if (!pStubMsg->IsClient && !*ppMemory)
4577 /* for servers, we just point straight into the RPC buffer */
4578 *ppMemory = pStubMsg->Buffer;
4581 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4582 safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
4583 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4584 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4586 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4587 if (*ppMemory != saved_buffer)
4588 memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
4590 return NULL;
4593 /***********************************************************************
4594 * NdrConformantStructBufferSize [RPCRT4.@]
4596 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4597 unsigned char *pMemory,
4598 PFORMAT_STRING pFormat)
4600 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4601 PFORMAT_STRING pCArrayFormat;
4602 ULONG esize;
4604 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4606 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4607 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4609 ERR("invalid format type %x\n", pCStructFormat->type);
4610 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4611 return;
4613 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4614 pCStructFormat->offset_to_array_description;
4615 if (*pCArrayFormat != RPC_FC_CARRAY)
4617 ERR("invalid array format type %x\n", pCStructFormat->type);
4618 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4619 return;
4621 esize = *(const WORD*)(pCArrayFormat+2);
4623 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
4624 SizeConformance(pStubMsg);
4626 ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
4628 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4630 safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
4631 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4633 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4634 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4637 /***********************************************************************
4638 * NdrConformantStructMemorySize [RPCRT4.@]
4640 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4641 PFORMAT_STRING pFormat)
4643 FIXME("stub\n");
4644 return 0;
4647 /***********************************************************************
4648 * NdrConformantStructFree [RPCRT4.@]
4650 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4651 unsigned char *pMemory,
4652 PFORMAT_STRING pFormat)
4654 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4655 PFORMAT_STRING pCArrayFormat;
4657 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4659 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4660 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4662 ERR("invalid format type %x\n", pCStructFormat->type);
4663 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4664 return;
4667 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4668 pCStructFormat->offset_to_array_description;
4669 if (*pCArrayFormat != RPC_FC_CARRAY)
4671 ERR("invalid array format type %x\n", pCStructFormat->type);
4672 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4673 return;
4676 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4677 pCArrayFormat + 4, 0);
4679 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4681 /* copy constant sized part of struct */
4682 pStubMsg->BufferMark = pStubMsg->Buffer;
4684 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4685 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4688 /***********************************************************************
4689 * NdrConformantVaryingStructMarshall [RPCRT4.@]
4691 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4692 unsigned char *pMemory,
4693 PFORMAT_STRING pFormat)
4695 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4696 PFORMAT_STRING pCVArrayFormat;
4698 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4700 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4701 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4703 ERR("invalid format type %x\n", pCVStructFormat->type);
4704 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4705 return NULL;
4708 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4709 pCVStructFormat->offset_to_array_description;
4711 array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg,
4712 pMemory + pCVStructFormat->memory_size,
4713 pCVArrayFormat);
4715 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4717 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4719 /* write constant sized part */
4720 pStubMsg->BufferMark = pStubMsg->Buffer;
4721 safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
4723 array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg,
4724 pMemory + pCVStructFormat->memory_size,
4725 pCVArrayFormat, FALSE /* fHasPointers */);
4727 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4729 return NULL;
4732 /***********************************************************************
4733 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
4735 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4736 unsigned char **ppMemory,
4737 PFORMAT_STRING pFormat,
4738 unsigned char fMustAlloc)
4740 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4741 PFORMAT_STRING pCVArrayFormat;
4742 ULONG memsize, bufsize;
4743 unsigned char *saved_buffer, *saved_array_buffer;
4744 ULONG offset;
4745 unsigned char *array_memory;
4747 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4749 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4750 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4752 ERR("invalid format type %x\n", pCVStructFormat->type);
4753 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4754 return NULL;
4757 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4758 pCVStructFormat->offset_to_array_description;
4760 memsize = array_read_conformance(*pCVArrayFormat, pStubMsg,
4761 pCVArrayFormat);
4763 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4765 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4767 /* work out how much memory to allocate if we need to do so */
4768 if (!fMustAlloc && !*ppMemory)
4769 fMustAlloc = TRUE;
4770 if (fMustAlloc)
4772 SIZE_T size = pCVStructFormat->memory_size + memsize;
4773 *ppMemory = NdrAllocate(pStubMsg, size);
4776 /* mark the start of the constant data */
4777 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4778 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4780 array_memory = *ppMemory + pCVStructFormat->memory_size;
4781 bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg,
4782 &array_memory, pCVArrayFormat,
4783 FALSE /* fMustAlloc */,
4784 FALSE /* fUseServerBufferMemory */,
4785 FALSE /* fUnmarshall */);
4787 /* save offset in case unmarshalling pointers changes it */
4788 offset = pStubMsg->Offset;
4790 /* mark the start of the array data */
4791 saved_array_buffer = pStubMsg->Buffer;
4792 safe_buffer_increment(pStubMsg, bufsize);
4794 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4796 /* copy the constant data */
4797 memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size);
4798 /* copy the array data */
4799 TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size);
4800 memcpy(*ppMemory + pCVStructFormat->memory_size + offset,
4801 saved_array_buffer, bufsize);
4803 if (*pCVArrayFormat == RPC_FC_C_CSTRING)
4804 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
4805 else if (*pCVArrayFormat == RPC_FC_C_WSTRING)
4806 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
4808 return NULL;
4811 /***********************************************************************
4812 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
4814 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4815 unsigned char *pMemory,
4816 PFORMAT_STRING pFormat)
4818 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4819 PFORMAT_STRING pCVArrayFormat;
4821 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4823 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4824 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4826 ERR("invalid format type %x\n", pCVStructFormat->type);
4827 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4828 return;
4831 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4832 pCVStructFormat->offset_to_array_description;
4833 array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg,
4834 pMemory + pCVStructFormat->memory_size,
4835 pCVArrayFormat);
4837 ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4839 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4841 safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4843 array_buffer_size(*pCVArrayFormat, pStubMsg,
4844 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4845 FALSE /* fHasPointers */);
4847 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4850 /***********************************************************************
4851 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
4853 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4854 PFORMAT_STRING pFormat)
4856 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4857 PFORMAT_STRING pCVArrayFormat;
4859 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4861 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4862 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4864 ERR("invalid format type %x\n", pCVStructFormat->type);
4865 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4866 return 0;
4869 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4870 pCVStructFormat->offset_to_array_description;
4871 array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat);
4873 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4875 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4877 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4878 array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat,
4879 FALSE /* fHasPointers */);
4881 pStubMsg->MemorySize += pCVStructFormat->memory_size;
4883 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4885 return pStubMsg->MemorySize;
4888 /***********************************************************************
4889 * NdrConformantVaryingStructFree [RPCRT4.@]
4891 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4892 unsigned char *pMemory,
4893 PFORMAT_STRING pFormat)
4895 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4896 PFORMAT_STRING pCVArrayFormat;
4898 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4900 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4901 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4903 ERR("invalid format type %x\n", pCVStructFormat->type);
4904 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4905 return;
4908 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4909 pCVStructFormat->offset_to_array_description;
4910 array_free(*pCVArrayFormat, pStubMsg,
4911 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4912 FALSE /* fHasPointers */);
4914 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4916 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4919 #include "pshpack1.h"
4920 typedef struct
4922 unsigned char type;
4923 unsigned char alignment;
4924 unsigned short total_size;
4925 } NDR_SMFARRAY_FORMAT;
4927 typedef struct
4929 unsigned char type;
4930 unsigned char alignment;
4931 ULONG total_size;
4932 } NDR_LGFARRAY_FORMAT;
4933 #include "poppack.h"
4935 /***********************************************************************
4936 * NdrFixedArrayMarshall [RPCRT4.@]
4938 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4939 unsigned char *pMemory,
4940 PFORMAT_STRING pFormat)
4942 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4943 ULONG total_size;
4945 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4947 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4948 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4950 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4951 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4952 return NULL;
4955 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4957 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4959 total_size = pSmFArrayFormat->total_size;
4960 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4962 else
4964 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4965 total_size = pLgFArrayFormat->total_size;
4966 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4969 pStubMsg->BufferMark = pStubMsg->Buffer;
4970 safe_copy_to_buffer(pStubMsg, pMemory, total_size);
4972 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4974 return NULL;
4977 /***********************************************************************
4978 * NdrFixedArrayUnmarshall [RPCRT4.@]
4980 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4981 unsigned char **ppMemory,
4982 PFORMAT_STRING pFormat,
4983 unsigned char fMustAlloc)
4985 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4986 ULONG total_size;
4987 unsigned char *saved_buffer;
4989 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4991 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4992 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4994 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4995 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4996 return NULL;
4999 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5001 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5003 total_size = pSmFArrayFormat->total_size;
5004 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5006 else
5008 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5009 total_size = pLgFArrayFormat->total_size;
5010 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5013 if (fMustAlloc)
5014 *ppMemory = NdrAllocate(pStubMsg, total_size);
5015 else
5017 if (!pStubMsg->IsClient && !*ppMemory)
5018 /* for servers, we just point straight into the RPC buffer */
5019 *ppMemory = pStubMsg->Buffer;
5022 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5023 safe_buffer_increment(pStubMsg, total_size);
5024 pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5026 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
5027 if (*ppMemory != saved_buffer)
5028 memcpy(*ppMemory, saved_buffer, total_size);
5030 return NULL;
5033 /***********************************************************************
5034 * NdrFixedArrayBufferSize [RPCRT4.@]
5036 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5037 unsigned char *pMemory,
5038 PFORMAT_STRING pFormat)
5040 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5041 ULONG total_size;
5043 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5045 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5046 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5048 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5049 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5050 return;
5053 ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
5055 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5057 total_size = pSmFArrayFormat->total_size;
5058 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5060 else
5062 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5063 total_size = pLgFArrayFormat->total_size;
5064 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5066 safe_buffer_length_increment(pStubMsg, total_size);
5068 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5071 /***********************************************************************
5072 * NdrFixedArrayMemorySize [RPCRT4.@]
5074 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5075 PFORMAT_STRING pFormat)
5077 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5078 ULONG total_size;
5080 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5082 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5083 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5085 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5086 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5087 return 0;
5090 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5092 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5094 total_size = pSmFArrayFormat->total_size;
5095 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5097 else
5099 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5100 total_size = pLgFArrayFormat->total_size;
5101 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5103 pStubMsg->BufferMark = pStubMsg->Buffer;
5104 safe_buffer_increment(pStubMsg, total_size);
5105 pStubMsg->MemorySize += total_size;
5107 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5109 return total_size;
5112 /***********************************************************************
5113 * NdrFixedArrayFree [RPCRT4.@]
5115 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5116 unsigned char *pMemory,
5117 PFORMAT_STRING pFormat)
5119 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5121 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5123 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5124 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5126 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5127 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5128 return;
5131 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5132 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5133 else
5135 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5136 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5139 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5142 /***********************************************************************
5143 * NdrVaryingArrayMarshall [RPCRT4.@]
5145 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5146 unsigned char *pMemory,
5147 PFORMAT_STRING pFormat)
5149 unsigned char alignment;
5150 DWORD elements, esize;
5151 ULONG bufsize;
5153 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5155 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5156 (pFormat[0] != RPC_FC_LGVARRAY))
5158 ERR("invalid format type %x\n", pFormat[0]);
5159 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5160 return NULL;
5163 alignment = pFormat[1] + 1;
5165 if (pFormat[0] == RPC_FC_SMVARRAY)
5167 pFormat += 2;
5168 pFormat += sizeof(WORD);
5169 elements = *(const WORD*)pFormat;
5170 pFormat += sizeof(WORD);
5172 else
5174 pFormat += 2;
5175 pFormat += sizeof(DWORD);
5176 elements = *(const DWORD*)pFormat;
5177 pFormat += sizeof(DWORD);
5180 esize = *(const WORD*)pFormat;
5181 pFormat += sizeof(WORD);
5183 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5184 if ((pStubMsg->ActualCount > elements) ||
5185 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5187 RpcRaiseException(RPC_S_INVALID_BOUND);
5188 return NULL;
5191 WriteVariance(pStubMsg);
5193 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
5195 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5196 pStubMsg->BufferMark = pStubMsg->Buffer;
5197 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
5199 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5201 return NULL;
5204 /***********************************************************************
5205 * NdrVaryingArrayUnmarshall [RPCRT4.@]
5207 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5208 unsigned char **ppMemory,
5209 PFORMAT_STRING pFormat,
5210 unsigned char fMustAlloc)
5212 unsigned char alignment;
5213 DWORD size, elements, esize;
5214 ULONG bufsize;
5215 unsigned char *saved_buffer;
5216 ULONG offset;
5218 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5220 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5221 (pFormat[0] != RPC_FC_LGVARRAY))
5223 ERR("invalid format type %x\n", pFormat[0]);
5224 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5225 return NULL;
5228 alignment = pFormat[1] + 1;
5230 if (pFormat[0] == RPC_FC_SMVARRAY)
5232 pFormat += 2;
5233 size = *(const WORD*)pFormat;
5234 pFormat += sizeof(WORD);
5235 elements = *(const WORD*)pFormat;
5236 pFormat += sizeof(WORD);
5238 else
5240 pFormat += 2;
5241 size = *(const DWORD*)pFormat;
5242 pFormat += sizeof(DWORD);
5243 elements = *(const DWORD*)pFormat;
5244 pFormat += sizeof(DWORD);
5247 esize = *(const WORD*)pFormat;
5248 pFormat += sizeof(WORD);
5250 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5252 ALIGN_POINTER(pStubMsg->Buffer, alignment);
5254 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5255 offset = pStubMsg->Offset;
5257 if (!fMustAlloc && !*ppMemory)
5258 fMustAlloc = TRUE;
5259 if (fMustAlloc)
5260 *ppMemory = NdrAllocate(pStubMsg, size);
5261 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5262 safe_buffer_increment(pStubMsg, bufsize);
5264 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5266 memcpy(*ppMemory + offset, saved_buffer, bufsize);
5268 return NULL;
5271 /***********************************************************************
5272 * NdrVaryingArrayBufferSize [RPCRT4.@]
5274 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5275 unsigned char *pMemory,
5276 PFORMAT_STRING pFormat)
5278 unsigned char alignment;
5279 DWORD elements, esize;
5281 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5283 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5284 (pFormat[0] != RPC_FC_LGVARRAY))
5286 ERR("invalid format type %x\n", pFormat[0]);
5287 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5288 return;
5291 alignment = pFormat[1] + 1;
5293 if (pFormat[0] == RPC_FC_SMVARRAY)
5295 pFormat += 2;
5296 pFormat += sizeof(WORD);
5297 elements = *(const WORD*)pFormat;
5298 pFormat += sizeof(WORD);
5300 else
5302 pFormat += 2;
5303 pFormat += sizeof(DWORD);
5304 elements = *(const DWORD*)pFormat;
5305 pFormat += sizeof(DWORD);
5308 esize = *(const WORD*)pFormat;
5309 pFormat += sizeof(WORD);
5311 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5312 if ((pStubMsg->ActualCount > elements) ||
5313 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5315 RpcRaiseException(RPC_S_INVALID_BOUND);
5316 return;
5319 SizeVariance(pStubMsg);
5321 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
5323 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5325 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5328 /***********************************************************************
5329 * NdrVaryingArrayMemorySize [RPCRT4.@]
5331 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5332 PFORMAT_STRING pFormat)
5334 unsigned char alignment;
5335 DWORD size, elements, esize;
5337 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5339 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5340 (pFormat[0] != RPC_FC_LGVARRAY))
5342 ERR("invalid format type %x\n", pFormat[0]);
5343 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5344 return 0;
5347 alignment = pFormat[1] + 1;
5349 if (pFormat[0] == RPC_FC_SMVARRAY)
5351 pFormat += 2;
5352 size = *(const WORD*)pFormat;
5353 pFormat += sizeof(WORD);
5354 elements = *(const WORD*)pFormat;
5355 pFormat += sizeof(WORD);
5357 else
5359 pFormat += 2;
5360 size = *(const DWORD*)pFormat;
5361 pFormat += sizeof(DWORD);
5362 elements = *(const DWORD*)pFormat;
5363 pFormat += sizeof(DWORD);
5366 esize = *(const WORD*)pFormat;
5367 pFormat += sizeof(WORD);
5369 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5371 ALIGN_POINTER(pStubMsg->Buffer, alignment);
5373 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5374 pStubMsg->MemorySize += size;
5376 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5378 return pStubMsg->MemorySize;
5381 /***********************************************************************
5382 * NdrVaryingArrayFree [RPCRT4.@]
5384 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5385 unsigned char *pMemory,
5386 PFORMAT_STRING pFormat)
5388 DWORD elements;
5390 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5392 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5393 (pFormat[0] != RPC_FC_LGVARRAY))
5395 ERR("invalid format type %x\n", pFormat[0]);
5396 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5397 return;
5400 if (pFormat[0] == RPC_FC_SMVARRAY)
5402 pFormat += 2;
5403 pFormat += sizeof(WORD);
5404 elements = *(const WORD*)pFormat;
5405 pFormat += sizeof(WORD);
5407 else
5409 pFormat += 2;
5410 pFormat += sizeof(DWORD);
5411 elements = *(const DWORD*)pFormat;
5412 pFormat += sizeof(DWORD);
5415 pFormat += sizeof(WORD);
5417 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5418 if ((pStubMsg->ActualCount > elements) ||
5419 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5421 RpcRaiseException(RPC_S_INVALID_BOUND);
5422 return;
5425 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5428 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
5430 switch (fc)
5432 case RPC_FC_BYTE:
5433 case RPC_FC_CHAR:
5434 case RPC_FC_SMALL:
5435 case RPC_FC_USMALL:
5436 return *pMemory;
5437 case RPC_FC_WCHAR:
5438 case RPC_FC_SHORT:
5439 case RPC_FC_USHORT:
5440 case RPC_FC_ENUM16:
5441 return *(const USHORT *)pMemory;
5442 case RPC_FC_LONG:
5443 case RPC_FC_ULONG:
5444 case RPC_FC_ENUM32:
5445 return *(const ULONG *)pMemory;
5446 default:
5447 FIXME("Unhandled base type: 0x%02x\n", fc);
5448 return 0;
5452 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
5453 ULONG discriminant,
5454 PFORMAT_STRING pFormat)
5456 unsigned short num_arms, arm, type;
5458 num_arms = *(const SHORT*)pFormat & 0x0fff;
5459 pFormat += 2;
5460 for(arm = 0; arm < num_arms; arm++)
5462 if(discriminant == *(const ULONG*)pFormat)
5464 pFormat += 4;
5465 break;
5467 pFormat += 6;
5470 type = *(const unsigned short*)pFormat;
5471 TRACE("type %04x\n", type);
5472 if(arm == num_arms) /* default arm extras */
5474 if(type == 0xffff)
5476 ERR("no arm for 0x%x and no default case\n", discriminant);
5477 RpcRaiseException(RPC_S_INVALID_TAG);
5478 return NULL;
5480 if(type == 0)
5482 TRACE("falling back to empty default case for 0x%x\n", discriminant);
5483 return NULL;
5486 return pFormat;
5489 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
5491 unsigned short type;
5493 pFormat += 2;
5495 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5496 if(!pFormat)
5497 return NULL;
5499 type = *(const unsigned short*)pFormat;
5500 if((type & 0xff00) == 0x8000)
5502 unsigned char basetype = LOBYTE(type);
5503 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
5505 else
5507 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5508 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
5509 if (m)
5511 unsigned char *saved_buffer = NULL;
5512 int pointer_buffer_mark_set = 0;
5513 switch(*desc)
5515 case RPC_FC_RP:
5516 case RPC_FC_UP:
5517 case RPC_FC_OP:
5518 case RPC_FC_FP:
5519 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
5520 saved_buffer = pStubMsg->Buffer;
5521 if (pStubMsg->PointerBufferMark)
5523 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5524 pStubMsg->PointerBufferMark = NULL;
5525 pointer_buffer_mark_set = 1;
5527 else
5528 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
5530 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
5531 if (pointer_buffer_mark_set)
5533 STD_OVERFLOW_CHECK(pStubMsg);
5534 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5535 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5537 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5538 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5539 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5541 pStubMsg->Buffer = saved_buffer + 4;
5543 break;
5544 default:
5545 m(pStubMsg, pMemory, desc);
5548 else FIXME("no marshaller for embedded type %02x\n", *desc);
5550 return NULL;
5553 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5554 unsigned char **ppMemory,
5555 ULONG discriminant,
5556 PFORMAT_STRING pFormat,
5557 unsigned char fMustAlloc)
5559 unsigned short type;
5561 pFormat += 2;
5563 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5564 if(!pFormat)
5565 return NULL;
5567 type = *(const unsigned short*)pFormat;
5568 if((type & 0xff00) == 0x8000)
5570 unsigned char basetype = LOBYTE(type);
5571 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
5573 else
5575 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5576 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
5577 if (m)
5579 unsigned char *saved_buffer = NULL;
5580 int pointer_buffer_mark_set = 0;
5581 switch(*desc)
5583 case RPC_FC_RP:
5584 case RPC_FC_UP:
5585 case RPC_FC_OP:
5586 case RPC_FC_FP:
5587 ALIGN_POINTER(pStubMsg->Buffer, 4);
5588 saved_buffer = pStubMsg->Buffer;
5589 if (pStubMsg->PointerBufferMark)
5591 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5592 pStubMsg->PointerBufferMark = NULL;
5593 pointer_buffer_mark_set = 1;
5595 else
5596 pStubMsg->Buffer += 4; /* for pointer ID */
5598 if (saved_buffer + 4 > pStubMsg->BufferEnd)
5600 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5601 saved_buffer, pStubMsg->BufferEnd);
5602 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5605 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
5606 if (pointer_buffer_mark_set)
5608 STD_OVERFLOW_CHECK(pStubMsg);
5609 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5610 pStubMsg->Buffer = saved_buffer + 4;
5612 break;
5613 default:
5614 m(pStubMsg, ppMemory, desc, fMustAlloc);
5617 else FIXME("no marshaller for embedded type %02x\n", *desc);
5619 return NULL;
5622 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
5623 unsigned char *pMemory,
5624 ULONG discriminant,
5625 PFORMAT_STRING pFormat)
5627 unsigned short type;
5629 pFormat += 2;
5631 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5632 if(!pFormat)
5633 return;
5635 type = *(const unsigned short*)pFormat;
5636 if((type & 0xff00) == 0x8000)
5638 unsigned char basetype = LOBYTE(type);
5639 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
5641 else
5643 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5644 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
5645 if (m)
5647 switch(*desc)
5649 case RPC_FC_RP:
5650 case RPC_FC_UP:
5651 case RPC_FC_OP:
5652 case RPC_FC_FP:
5653 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5654 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
5655 if (!pStubMsg->IgnoreEmbeddedPointers)
5657 int saved_buffer_length = pStubMsg->BufferLength;
5658 pStubMsg->BufferLength = pStubMsg->PointerLength;
5659 pStubMsg->PointerLength = 0;
5660 if(!pStubMsg->BufferLength)
5661 ERR("BufferLength == 0??\n");
5662 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
5663 pStubMsg->PointerLength = pStubMsg->BufferLength;
5664 pStubMsg->BufferLength = saved_buffer_length;
5666 break;
5667 default:
5668 m(pStubMsg, pMemory, desc);
5671 else FIXME("no buffersizer for embedded type %02x\n", *desc);
5675 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
5676 ULONG discriminant,
5677 PFORMAT_STRING pFormat)
5679 unsigned short type, size;
5681 size = *(const unsigned short*)pFormat;
5682 pStubMsg->Memory += size;
5683 pFormat += 2;
5685 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5686 if(!pFormat)
5687 return 0;
5689 type = *(const unsigned short*)pFormat;
5690 if((type & 0xff00) == 0x8000)
5692 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
5694 else
5696 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5697 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
5698 unsigned char *saved_buffer;
5699 if (m)
5701 switch(*desc)
5703 case RPC_FC_RP:
5704 case RPC_FC_UP:
5705 case RPC_FC_OP:
5706 case RPC_FC_FP:
5707 ALIGN_POINTER(pStubMsg->Buffer, 4);
5708 saved_buffer = pStubMsg->Buffer;
5709 safe_buffer_increment(pStubMsg, 4);
5710 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
5711 pStubMsg->MemorySize += sizeof(void *);
5712 if (!pStubMsg->IgnoreEmbeddedPointers)
5713 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
5714 break;
5715 default:
5716 return m(pStubMsg, desc);
5719 else FIXME("no marshaller for embedded type %02x\n", *desc);
5722 TRACE("size %d\n", size);
5723 return size;
5726 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
5727 unsigned char *pMemory,
5728 ULONG discriminant,
5729 PFORMAT_STRING pFormat)
5731 unsigned short type;
5733 pFormat += 2;
5735 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5736 if(!pFormat)
5737 return;
5739 type = *(const unsigned short*)pFormat;
5740 if((type & 0xff00) != 0x8000)
5742 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5743 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5744 if (m)
5746 switch(*desc)
5748 case RPC_FC_RP:
5749 case RPC_FC_UP:
5750 case RPC_FC_OP:
5751 case RPC_FC_FP:
5752 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5753 break;
5754 default:
5755 m(pStubMsg, pMemory, desc);
5761 /***********************************************************************
5762 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
5764 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5765 unsigned char *pMemory,
5766 PFORMAT_STRING pFormat)
5768 unsigned char switch_type;
5769 unsigned char increment;
5770 ULONG switch_value;
5772 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5773 pFormat++;
5775 switch_type = *pFormat & 0xf;
5776 increment = (*pFormat & 0xf0) >> 4;
5777 pFormat++;
5779 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment);
5781 switch_value = get_discriminant(switch_type, pMemory);
5782 TRACE("got switch value 0x%x\n", switch_value);
5784 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5785 pMemory += increment;
5787 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5790 /***********************************************************************
5791 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5793 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5794 unsigned char **ppMemory,
5795 PFORMAT_STRING pFormat,
5796 unsigned char fMustAlloc)
5798 unsigned char switch_type;
5799 unsigned char increment;
5800 ULONG switch_value;
5801 unsigned short size;
5802 unsigned char *pMemoryArm;
5804 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5805 pFormat++;
5807 switch_type = *pFormat & 0xf;
5808 increment = (*pFormat & 0xf0) >> 4;
5809 pFormat++;
5811 ALIGN_POINTER(pStubMsg->Buffer, increment);
5812 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5813 TRACE("got switch value 0x%x\n", switch_value);
5815 size = *(const unsigned short*)pFormat + increment;
5816 if (!fMustAlloc && !*ppMemory)
5817 fMustAlloc = TRUE;
5818 if (fMustAlloc)
5819 *ppMemory = NdrAllocate(pStubMsg, size);
5821 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
5822 * since the arm is part of the memory block that is encompassed by
5823 * the whole union. Memory is forced to allocate when pointers
5824 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
5825 * clearing the memory we pass in to the unmarshaller */
5826 if (fMustAlloc)
5827 memset(*ppMemory, 0, size);
5829 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5830 pMemoryArm = *ppMemory + increment;
5832 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE);
5835 /***********************************************************************
5836 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5838 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5839 unsigned char *pMemory,
5840 PFORMAT_STRING pFormat)
5842 unsigned char switch_type;
5843 unsigned char increment;
5844 ULONG switch_value;
5846 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5847 pFormat++;
5849 switch_type = *pFormat & 0xf;
5850 increment = (*pFormat & 0xf0) >> 4;
5851 pFormat++;
5853 ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5854 switch_value = get_discriminant(switch_type, pMemory);
5855 TRACE("got switch value 0x%x\n", switch_value);
5857 /* Add discriminant size */
5858 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5859 pMemory += increment;
5861 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5864 /***********************************************************************
5865 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5867 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5868 PFORMAT_STRING pFormat)
5870 unsigned char switch_type;
5871 unsigned char increment;
5872 ULONG switch_value;
5874 switch_type = *pFormat & 0xf;
5875 increment = (*pFormat & 0xf0) >> 4;
5876 pFormat++;
5878 ALIGN_POINTER(pStubMsg->Buffer, increment);
5879 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5880 TRACE("got switch value 0x%x\n", switch_value);
5882 pStubMsg->Memory += increment;
5884 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5887 /***********************************************************************
5888 * NdrEncapsulatedUnionFree [RPCRT4.@]
5890 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5891 unsigned char *pMemory,
5892 PFORMAT_STRING pFormat)
5894 unsigned char switch_type;
5895 unsigned char increment;
5896 ULONG switch_value;
5898 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5899 pFormat++;
5901 switch_type = *pFormat & 0xf;
5902 increment = (*pFormat & 0xf0) >> 4;
5903 pFormat++;
5905 switch_value = get_discriminant(switch_type, pMemory);
5906 TRACE("got switch value 0x%x\n", switch_value);
5908 pMemory += increment;
5910 union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5913 /***********************************************************************
5914 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5916 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5917 unsigned char *pMemory,
5918 PFORMAT_STRING pFormat)
5920 unsigned char switch_type;
5922 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5923 pFormat++;
5925 switch_type = *pFormat;
5926 pFormat++;
5928 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5929 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5930 /* Marshall discriminant */
5931 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5933 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5936 static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
5937 PFORMAT_STRING *ppFormat)
5939 LONG discriminant = 0;
5941 switch(**ppFormat)
5943 case RPC_FC_BYTE:
5944 case RPC_FC_CHAR:
5945 case RPC_FC_SMALL:
5946 case RPC_FC_USMALL:
5948 UCHAR d;
5949 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5950 discriminant = d;
5951 break;
5953 case RPC_FC_WCHAR:
5954 case RPC_FC_SHORT:
5955 case RPC_FC_USHORT:
5957 USHORT d;
5958 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5959 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5960 discriminant = d;
5961 break;
5963 case RPC_FC_LONG:
5964 case RPC_FC_ULONG:
5966 ULONG d;
5967 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5968 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5969 discriminant = d;
5970 break;
5972 default:
5973 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
5975 (*ppFormat)++;
5977 if (pStubMsg->fHasNewCorrDesc)
5978 *ppFormat += 6;
5979 else
5980 *ppFormat += 4;
5981 return discriminant;
5984 /**********************************************************************
5985 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
5987 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5988 unsigned char **ppMemory,
5989 PFORMAT_STRING pFormat,
5990 unsigned char fMustAlloc)
5992 LONG discriminant;
5993 unsigned short size;
5995 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5996 pFormat++;
5998 /* Unmarshall discriminant */
5999 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6000 TRACE("unmarshalled discriminant %x\n", discriminant);
6002 pFormat += *(const SHORT*)pFormat;
6004 size = *(const unsigned short*)pFormat;
6006 if (!fMustAlloc && !*ppMemory)
6007 fMustAlloc = TRUE;
6008 if (fMustAlloc)
6009 *ppMemory = NdrAllocate(pStubMsg, size);
6011 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6012 * since the arm is part of the memory block that is encompassed by
6013 * the whole union. Memory is forced to allocate when pointers
6014 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6015 * clearing the memory we pass in to the unmarshaller */
6016 if (fMustAlloc)
6017 memset(*ppMemory, 0, size);
6019 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
6022 /***********************************************************************
6023 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
6025 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6026 unsigned char *pMemory,
6027 PFORMAT_STRING pFormat)
6029 unsigned char switch_type;
6031 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6032 pFormat++;
6034 switch_type = *pFormat;
6035 pFormat++;
6037 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6038 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6039 /* Add discriminant size */
6040 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6042 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6045 /***********************************************************************
6046 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
6048 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6049 PFORMAT_STRING pFormat)
6051 ULONG discriminant;
6053 pFormat++;
6054 /* Unmarshall discriminant */
6055 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6056 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
6058 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
6061 /***********************************************************************
6062 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
6064 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6065 unsigned char *pMemory,
6066 PFORMAT_STRING pFormat)
6068 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6069 pFormat++;
6070 pFormat++;
6072 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6073 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6075 union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6078 /***********************************************************************
6079 * NdrByteCountPointerMarshall [RPCRT4.@]
6081 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6082 unsigned char *pMemory,
6083 PFORMAT_STRING pFormat)
6085 FIXME("stub\n");
6086 return NULL;
6089 /***********************************************************************
6090 * NdrByteCountPointerUnmarshall [RPCRT4.@]
6092 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6093 unsigned char **ppMemory,
6094 PFORMAT_STRING pFormat,
6095 unsigned char fMustAlloc)
6097 FIXME("stub\n");
6098 return NULL;
6101 /***********************************************************************
6102 * NdrByteCountPointerBufferSize [RPCRT4.@]
6104 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6105 unsigned char *pMemory,
6106 PFORMAT_STRING pFormat)
6108 FIXME("stub\n");
6111 /***********************************************************************
6112 * NdrByteCountPointerMemorySize [internal]
6114 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6115 PFORMAT_STRING pFormat)
6117 FIXME("stub\n");
6118 return 0;
6121 /***********************************************************************
6122 * NdrByteCountPointerFree [RPCRT4.@]
6124 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
6125 unsigned char *pMemory,
6126 PFORMAT_STRING pFormat)
6128 FIXME("stub\n");
6131 /***********************************************************************
6132 * NdrXmitOrRepAsMarshall [RPCRT4.@]
6134 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6135 unsigned char *pMemory,
6136 PFORMAT_STRING pFormat)
6138 FIXME("stub\n");
6139 return NULL;
6142 /***********************************************************************
6143 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
6145 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6146 unsigned char **ppMemory,
6147 PFORMAT_STRING pFormat,
6148 unsigned char fMustAlloc)
6150 FIXME("stub\n");
6151 return NULL;
6154 /***********************************************************************
6155 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
6157 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6158 unsigned char *pMemory,
6159 PFORMAT_STRING pFormat)
6161 FIXME("stub\n");
6164 /***********************************************************************
6165 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
6167 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6168 PFORMAT_STRING pFormat)
6170 FIXME("stub\n");
6171 return 0;
6174 /***********************************************************************
6175 * NdrXmitOrRepAsFree [RPCRT4.@]
6177 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
6178 unsigned char *pMemory,
6179 PFORMAT_STRING pFormat)
6181 FIXME("stub\n");
6184 /***********************************************************************
6185 * NdrRangeMarshall [internal]
6187 static unsigned char *WINAPI NdrRangeMarshall(
6188 PMIDL_STUB_MESSAGE pStubMsg,
6189 unsigned char *pMemory,
6190 PFORMAT_STRING pFormat)
6192 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6193 unsigned char base_type;
6195 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6197 if (pRange->type != RPC_FC_RANGE)
6199 ERR("invalid format type %x\n", pRange->type);
6200 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6201 return NULL;
6204 base_type = pRange->flags_type & 0xf;
6206 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
6209 /***********************************************************************
6210 * NdrRangeUnmarshall [RPCRT4.@]
6212 unsigned char *WINAPI NdrRangeUnmarshall(
6213 PMIDL_STUB_MESSAGE pStubMsg,
6214 unsigned char **ppMemory,
6215 PFORMAT_STRING pFormat,
6216 unsigned char fMustAlloc)
6218 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6219 unsigned char base_type;
6221 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6223 if (pRange->type != RPC_FC_RANGE)
6225 ERR("invalid format type %x\n", pRange->type);
6226 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6227 return NULL;
6229 base_type = pRange->flags_type & 0xf;
6231 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
6232 base_type, pRange->low_value, pRange->high_value);
6234 #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
6235 do \
6237 ALIGN_POINTER(pStubMsg->Buffer, sizeof(wire_type)); \
6238 if (!fMustAlloc && !*ppMemory) \
6239 fMustAlloc = TRUE; \
6240 if (fMustAlloc) \
6241 *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
6242 if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
6244 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
6245 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
6246 RpcRaiseException(RPC_X_BAD_STUB_DATA); \
6248 if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
6249 (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
6251 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
6252 *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
6253 (mem_type)pRange->high_value); \
6254 RpcRaiseException(RPC_S_INVALID_BOUND); \
6255 return NULL; \
6257 TRACE("*ppMemory: %p\n", *ppMemory); \
6258 **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
6259 pStubMsg->Buffer += sizeof(wire_type); \
6260 } while (0)
6262 switch(base_type)
6264 case RPC_FC_CHAR:
6265 case RPC_FC_SMALL:
6266 RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
6267 TRACE("value: 0x%02x\n", **ppMemory);
6268 break;
6269 case RPC_FC_BYTE:
6270 case RPC_FC_USMALL:
6271 RANGE_UNMARSHALL(CHAR, CHAR, "%u");
6272 TRACE("value: 0x%02x\n", **ppMemory);
6273 break;
6274 case RPC_FC_WCHAR: /* FIXME: valid? */
6275 case RPC_FC_USHORT:
6276 RANGE_UNMARSHALL(USHORT, USHORT, "%u");
6277 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6278 break;
6279 case RPC_FC_SHORT:
6280 RANGE_UNMARSHALL(SHORT, SHORT, "%d");
6281 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6282 break;
6283 case RPC_FC_LONG:
6284 case RPC_FC_ENUM32:
6285 RANGE_UNMARSHALL(LONG, LONG, "%d");
6286 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6287 break;
6288 case RPC_FC_ULONG:
6289 RANGE_UNMARSHALL(ULONG, ULONG, "%u");
6290 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6291 break;
6292 case RPC_FC_ENUM16:
6293 RANGE_UNMARSHALL(UINT, USHORT, "%u");
6294 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6295 break;
6296 case RPC_FC_FLOAT:
6297 case RPC_FC_DOUBLE:
6298 case RPC_FC_HYPER:
6299 default:
6300 ERR("invalid range base type: 0x%02x\n", base_type);
6301 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6304 return NULL;
6307 /***********************************************************************
6308 * NdrRangeBufferSize [internal]
6310 static void WINAPI NdrRangeBufferSize(
6311 PMIDL_STUB_MESSAGE pStubMsg,
6312 unsigned char *pMemory,
6313 PFORMAT_STRING pFormat)
6315 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6316 unsigned char base_type;
6318 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6320 if (pRange->type != RPC_FC_RANGE)
6322 ERR("invalid format type %x\n", pRange->type);
6323 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6325 base_type = pRange->flags_type & 0xf;
6327 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
6330 /***********************************************************************
6331 * NdrRangeMemorySize [internal]
6333 static ULONG WINAPI NdrRangeMemorySize(
6334 PMIDL_STUB_MESSAGE pStubMsg,
6335 PFORMAT_STRING pFormat)
6337 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6338 unsigned char base_type;
6340 if (pRange->type != RPC_FC_RANGE)
6342 ERR("invalid format type %x\n", pRange->type);
6343 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6344 return 0;
6346 base_type = pRange->flags_type & 0xf;
6348 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
6351 /***********************************************************************
6352 * NdrRangeFree [internal]
6354 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
6355 unsigned char *pMemory,
6356 PFORMAT_STRING pFormat)
6358 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6360 /* nothing to do */
6363 /***********************************************************************
6364 * NdrBaseTypeMarshall [internal]
6366 static unsigned char *WINAPI NdrBaseTypeMarshall(
6367 PMIDL_STUB_MESSAGE pStubMsg,
6368 unsigned char *pMemory,
6369 PFORMAT_STRING pFormat)
6371 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6373 switch(*pFormat)
6375 case RPC_FC_BYTE:
6376 case RPC_FC_CHAR:
6377 case RPC_FC_SMALL:
6378 case RPC_FC_USMALL:
6379 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
6380 TRACE("value: 0x%02x\n", *pMemory);
6381 break;
6382 case RPC_FC_WCHAR:
6383 case RPC_FC_SHORT:
6384 case RPC_FC_USHORT:
6385 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6386 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
6387 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
6388 break;
6389 case RPC_FC_LONG:
6390 case RPC_FC_ULONG:
6391 case RPC_FC_ERROR_STATUS_T:
6392 case RPC_FC_ENUM32:
6393 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG));
6394 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
6395 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
6396 break;
6397 case RPC_FC_FLOAT:
6398 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float));
6399 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
6400 break;
6401 case RPC_FC_DOUBLE:
6402 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double));
6403 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
6404 break;
6405 case RPC_FC_HYPER:
6406 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG));
6407 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
6408 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
6409 break;
6410 case RPC_FC_ENUM16:
6411 /* only 16-bits on the wire, so do a sanity check */
6412 if (*(UINT *)pMemory > SHRT_MAX)
6413 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
6414 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6415 if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6416 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6417 *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
6418 pStubMsg->Buffer += sizeof(USHORT);
6419 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
6420 break;
6421 case RPC_FC_IGNORE:
6422 break;
6423 default:
6424 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6427 /* FIXME: what is the correct return value? */
6428 return NULL;
6431 /***********************************************************************
6432 * NdrBaseTypeUnmarshall [internal]
6434 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
6435 PMIDL_STUB_MESSAGE pStubMsg,
6436 unsigned char **ppMemory,
6437 PFORMAT_STRING pFormat,
6438 unsigned char fMustAlloc)
6440 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6442 #define BASE_TYPE_UNMARSHALL(type) \
6443 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
6444 if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
6446 *ppMemory = pStubMsg->Buffer; \
6447 TRACE("*ppMemory: %p\n", *ppMemory); \
6448 safe_buffer_increment(pStubMsg, sizeof(type)); \
6450 else \
6452 if (fMustAlloc) \
6453 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
6454 TRACE("*ppMemory: %p\n", *ppMemory); \
6455 safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \
6458 switch(*pFormat)
6460 case RPC_FC_BYTE:
6461 case RPC_FC_CHAR:
6462 case RPC_FC_SMALL:
6463 case RPC_FC_USMALL:
6464 BASE_TYPE_UNMARSHALL(UCHAR);
6465 TRACE("value: 0x%02x\n", **ppMemory);
6466 break;
6467 case RPC_FC_WCHAR:
6468 case RPC_FC_SHORT:
6469 case RPC_FC_USHORT:
6470 BASE_TYPE_UNMARSHALL(USHORT);
6471 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6472 break;
6473 case RPC_FC_LONG:
6474 case RPC_FC_ULONG:
6475 case RPC_FC_ERROR_STATUS_T:
6476 case RPC_FC_ENUM32:
6477 BASE_TYPE_UNMARSHALL(ULONG);
6478 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6479 break;
6480 case RPC_FC_FLOAT:
6481 BASE_TYPE_UNMARSHALL(float);
6482 TRACE("value: %f\n", **(float **)ppMemory);
6483 break;
6484 case RPC_FC_DOUBLE:
6485 BASE_TYPE_UNMARSHALL(double);
6486 TRACE("value: %f\n", **(double **)ppMemory);
6487 break;
6488 case RPC_FC_HYPER:
6489 BASE_TYPE_UNMARSHALL(ULONGLONG);
6490 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
6491 break;
6492 case RPC_FC_ENUM16:
6493 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6494 if (!fMustAlloc && !*ppMemory)
6495 fMustAlloc = TRUE;
6496 if (fMustAlloc)
6497 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
6498 if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
6499 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6500 TRACE("*ppMemory: %p\n", *ppMemory);
6501 /* 16-bits on the wire, but int in memory */
6502 **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
6503 pStubMsg->Buffer += sizeof(USHORT);
6504 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6505 break;
6506 case RPC_FC_IGNORE:
6507 break;
6508 default:
6509 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6511 #undef BASE_TYPE_UNMARSHALL
6513 /* FIXME: what is the correct return value? */
6515 return NULL;
6518 /***********************************************************************
6519 * NdrBaseTypeBufferSize [internal]
6521 static void WINAPI NdrBaseTypeBufferSize(
6522 PMIDL_STUB_MESSAGE pStubMsg,
6523 unsigned char *pMemory,
6524 PFORMAT_STRING pFormat)
6526 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6528 switch(*pFormat)
6530 case RPC_FC_BYTE:
6531 case RPC_FC_CHAR:
6532 case RPC_FC_SMALL:
6533 case RPC_FC_USMALL:
6534 safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6535 break;
6536 case RPC_FC_WCHAR:
6537 case RPC_FC_SHORT:
6538 case RPC_FC_USHORT:
6539 case RPC_FC_ENUM16:
6540 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
6541 safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6542 break;
6543 case RPC_FC_LONG:
6544 case RPC_FC_ULONG:
6545 case RPC_FC_ENUM32:
6546 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
6547 safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6548 break;
6549 case RPC_FC_FLOAT:
6550 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
6551 safe_buffer_length_increment(pStubMsg, sizeof(float));
6552 break;
6553 case RPC_FC_DOUBLE:
6554 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
6555 safe_buffer_length_increment(pStubMsg, sizeof(double));
6556 break;
6557 case RPC_FC_HYPER:
6558 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
6559 safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6560 break;
6561 case RPC_FC_ERROR_STATUS_T:
6562 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
6563 safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6564 break;
6565 case RPC_FC_IGNORE:
6566 break;
6567 default:
6568 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6572 /***********************************************************************
6573 * NdrBaseTypeMemorySize [internal]
6575 static ULONG WINAPI NdrBaseTypeMemorySize(
6576 PMIDL_STUB_MESSAGE pStubMsg,
6577 PFORMAT_STRING pFormat)
6579 TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6581 switch(*pFormat)
6583 case RPC_FC_BYTE:
6584 case RPC_FC_CHAR:
6585 case RPC_FC_SMALL:
6586 case RPC_FC_USMALL:
6587 safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6588 pStubMsg->MemorySize += sizeof(UCHAR);
6589 return sizeof(UCHAR);
6590 case RPC_FC_WCHAR:
6591 case RPC_FC_SHORT:
6592 case RPC_FC_USHORT:
6593 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6594 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6595 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(USHORT));
6596 pStubMsg->MemorySize += sizeof(USHORT);
6597 return sizeof(USHORT);
6598 case RPC_FC_LONG:
6599 case RPC_FC_ULONG:
6600 case RPC_FC_ENUM32:
6601 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
6602 safe_buffer_increment(pStubMsg, sizeof(ULONG));
6603 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONG));
6604 pStubMsg->MemorySize += sizeof(ULONG);
6605 return sizeof(ULONG);
6606 case RPC_FC_FLOAT:
6607 ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
6608 safe_buffer_increment(pStubMsg, sizeof(float));
6609 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(float));
6610 pStubMsg->MemorySize += sizeof(float);
6611 return sizeof(float);
6612 case RPC_FC_DOUBLE:
6613 ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
6614 safe_buffer_increment(pStubMsg, sizeof(double));
6615 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(double));
6616 pStubMsg->MemorySize += sizeof(double);
6617 return sizeof(double);
6618 case RPC_FC_HYPER:
6619 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
6620 safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6621 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONGLONG));
6622 pStubMsg->MemorySize += sizeof(ULONGLONG);
6623 return sizeof(ULONGLONG);
6624 case RPC_FC_ERROR_STATUS_T:
6625 ALIGN_POINTER(pStubMsg->Buffer, sizeof(error_status_t));
6626 safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6627 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(error_status_t));
6628 pStubMsg->MemorySize += sizeof(error_status_t);
6629 return sizeof(error_status_t);
6630 case RPC_FC_ENUM16:
6631 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6632 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6633 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(UINT));
6634 pStubMsg->MemorySize += sizeof(UINT);
6635 return sizeof(UINT);
6636 case RPC_FC_IGNORE:
6637 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
6638 pStubMsg->MemorySize += sizeof(void *);
6639 return sizeof(void *);
6640 default:
6641 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6642 return 0;
6646 /***********************************************************************
6647 * NdrBaseTypeFree [internal]
6649 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6650 unsigned char *pMemory,
6651 PFORMAT_STRING pFormat)
6653 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6655 /* nothing to do */
6658 /***********************************************************************
6659 * NdrContextHandleBufferSize [internal]
6661 static void WINAPI NdrContextHandleBufferSize(
6662 PMIDL_STUB_MESSAGE pStubMsg,
6663 unsigned char *pMemory,
6664 PFORMAT_STRING pFormat)
6666 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6668 if (*pFormat != RPC_FC_BIND_CONTEXT)
6670 ERR("invalid format type %x\n", *pFormat);
6671 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6673 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
6674 safe_buffer_length_increment(pStubMsg, cbNDRContext);
6677 /***********************************************************************
6678 * NdrContextHandleMarshall [internal]
6680 static unsigned char *WINAPI NdrContextHandleMarshall(
6681 PMIDL_STUB_MESSAGE pStubMsg,
6682 unsigned char *pMemory,
6683 PFORMAT_STRING pFormat)
6685 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6687 if (*pFormat != RPC_FC_BIND_CONTEXT)
6689 ERR("invalid format type %x\n", *pFormat);
6690 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6692 TRACE("flags: 0x%02x\n", pFormat[1]);
6694 if (pStubMsg->IsClient)
6696 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6697 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6698 else
6699 NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
6701 else
6703 NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
6704 NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
6705 NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
6708 return NULL;
6711 /***********************************************************************
6712 * NdrContextHandleUnmarshall [internal]
6714 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6715 PMIDL_STUB_MESSAGE pStubMsg,
6716 unsigned char **ppMemory,
6717 PFORMAT_STRING pFormat,
6718 unsigned char fMustAlloc)
6720 TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg,
6721 ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE");
6723 if (*pFormat != RPC_FC_BIND_CONTEXT)
6725 ERR("invalid format type %x\n", *pFormat);
6726 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6728 TRACE("flags: 0x%02x\n", pFormat[1]);
6730 if (pStubMsg->IsClient)
6732 /* [out]-only or [ret] param */
6733 if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT)
6734 **(NDR_CCONTEXT **)ppMemory = NULL;
6735 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
6737 else
6739 NDR_SCONTEXT ctxt;
6740 ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat);
6741 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6742 *(void **)ppMemory = NDRSContextValue(ctxt);
6743 else
6744 *(void **)ppMemory = *NDRSContextValue(ctxt);
6747 return NULL;
6750 /***********************************************************************
6751 * NdrClientContextMarshall [RPCRT4.@]
6753 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6754 NDR_CCONTEXT ContextHandle,
6755 int fCheck)
6757 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
6759 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
6761 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6763 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6764 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6765 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6768 /* FIXME: what does fCheck do? */
6769 NDRCContextMarshall(ContextHandle,
6770 pStubMsg->Buffer);
6772 pStubMsg->Buffer += cbNDRContext;
6775 /***********************************************************************
6776 * NdrClientContextUnmarshall [RPCRT4.@]
6778 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6779 NDR_CCONTEXT * pContextHandle,
6780 RPC_BINDING_HANDLE BindHandle)
6782 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
6784 ALIGN_POINTER(pStubMsg->Buffer, 4);
6786 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
6787 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6789 NDRCContextUnmarshall(pContextHandle,
6790 BindHandle,
6791 pStubMsg->Buffer,
6792 pStubMsg->RpcMsg->DataRepresentation);
6794 pStubMsg->Buffer += cbNDRContext;
6797 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6798 NDR_SCONTEXT ContextHandle,
6799 NDR_RUNDOWN RundownRoutine )
6801 TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
6803 ALIGN_POINTER(pStubMsg->Buffer, 4);
6805 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6807 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6808 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6809 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6812 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6813 pStubMsg->Buffer, RundownRoutine, NULL,
6814 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6815 pStubMsg->Buffer += cbNDRContext;
6818 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
6820 NDR_SCONTEXT ContextHandle;
6822 TRACE("(%p)\n", pStubMsg);
6824 ALIGN_POINTER(pStubMsg->Buffer, 4);
6826 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6828 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6829 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6830 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6833 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6834 pStubMsg->Buffer,
6835 pStubMsg->RpcMsg->DataRepresentation,
6836 NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6837 pStubMsg->Buffer += cbNDRContext;
6839 return ContextHandle;
6842 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
6843 unsigned char* pMemory,
6844 PFORMAT_STRING pFormat)
6846 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
6849 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
6850 PFORMAT_STRING pFormat)
6852 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6853 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6855 TRACE("(%p, %p)\n", pStubMsg, pFormat);
6857 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6858 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6859 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6860 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6861 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6863 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6864 if_id = &sif->InterfaceId;
6867 return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
6868 pStubMsg->RpcMsg->DataRepresentation, if_id,
6869 flags);
6872 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6873 NDR_SCONTEXT ContextHandle,
6874 NDR_RUNDOWN RundownRoutine,
6875 PFORMAT_STRING pFormat)
6877 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6878 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6880 TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
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 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6892 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6893 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6894 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6895 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6897 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6898 if_id = &sif->InterfaceId;
6901 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6902 pStubMsg->Buffer, RundownRoutine, if_id, flags);
6903 pStubMsg->Buffer += cbNDRContext;
6906 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6907 PFORMAT_STRING pFormat)
6909 NDR_SCONTEXT ContextHandle;
6910 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6911 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6913 TRACE("(%p, %p)\n", pStubMsg, pFormat);
6915 ALIGN_POINTER(pStubMsg->Buffer, 4);
6917 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6919 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6920 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6921 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6924 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6925 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6926 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6927 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6928 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6930 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6931 if_id = &sif->InterfaceId;
6934 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6935 pStubMsg->Buffer,
6936 pStubMsg->RpcMsg->DataRepresentation,
6937 if_id, flags);
6938 pStubMsg->Buffer += cbNDRContext;
6940 return ContextHandle;
6943 /***********************************************************************
6944 * NdrCorrelationInitialize [RPCRT4.@]
6946 * Initializes correlation validity checking.
6948 * PARAMS
6949 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
6950 * pMemory [I] Pointer to memory to use as a cache.
6951 * CacheSize [I] Size of the memory pointed to by pMemory.
6952 * Flags [I] Reserved. Set to zero.
6954 * RETURNS
6955 * Nothing.
6957 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
6959 FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
6960 pStubMsg->fHasNewCorrDesc = TRUE;
6963 /***********************************************************************
6964 * NdrCorrelationPass [RPCRT4.@]
6966 * Performs correlation validity checking.
6968 * PARAMS
6969 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
6971 * RETURNS
6972 * Nothing.
6974 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
6976 FIXME("(%p): stub\n", pStubMsg);
6979 /***********************************************************************
6980 * NdrCorrelationFree [RPCRT4.@]
6982 * Frees any resources used while unmarshalling parameters that need
6983 * correlation validity checking.
6985 * PARAMS
6986 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
6988 * RETURNS
6989 * Nothing.
6991 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
6993 FIXME("(%p): stub\n", pStubMsg);