rpcrt4: Add support for FC_FLOAT and FC_DOUBLE in complex structures.
[wine.git] / dlls / rpcrt4 / ndr_marshall.c
blobe594c9537744f2eb9670a41d1f067b9c86bcd1ac
1 /*
2 * NDR data marshalling
4 * Copyright 2002 Greg Turner
5 * Copyright 2003-2006 CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * TODO:
22 * - String structs
23 * - Byte count pointers
24 * - transmit_as/represent as
25 * - Multi-dimensional arrays
26 * - Conversion functions (NdrConvert)
27 * - Checks for integer addition overflow in user marshall functions
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <limits.h>
35 #define NONAMELESSUNION
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winerror.h"
40 #include "ndr_misc.h"
41 #include "rpcndr.h"
42 #include "ndrtypes.h"
44 #include "wine/unicode.h"
45 #include "wine/rpcfc.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(ole);
51 #if defined(__i386__)
52 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
53 (*((UINT32 *)(pchar)) = (uint32))
55 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
56 (*((UINT32 *)(pchar)))
57 #else
58 /* these would work for i386 too, but less efficient */
59 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
60 (*(pchar) = LOBYTE(LOWORD(uint32)), \
61 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
62 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
63 *((pchar)+3) = HIBYTE(HIWORD(uint32)))
65 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
66 (MAKELONG( \
67 MAKEWORD(*(pchar), *((pchar)+1)), \
68 MAKEWORD(*((pchar)+2), *((pchar)+3))))
69 #endif
71 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
72 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
73 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
74 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
75 *(pchar) = HIBYTE(HIWORD(uint32)))
77 #define BIG_ENDIAN_UINT32_READ(pchar) \
78 (MAKELONG( \
79 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
80 MAKEWORD(*((pchar)+1), *(pchar))))
82 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
83 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
84 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
85 # define NDR_LOCAL_UINT32_READ(pchar) \
86 BIG_ENDIAN_UINT32_READ(pchar)
87 #else
88 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
89 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
90 # define NDR_LOCAL_UINT32_READ(pchar) \
91 LITTLE_ENDIAN_UINT32_READ(pchar)
92 #endif
94 /* _Align must be the desired alignment,
95 * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
96 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
97 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
98 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
99 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
100 #define ALIGN_POINTER_CLEAR(_Ptr, _Align) \
101 do { \
102 memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \
103 ALIGN_POINTER(_Ptr, _Align); \
104 } while(0)
106 #define STD_OVERFLOW_CHECK(_Msg) do { \
107 TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
108 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
109 ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
110 } while (0)
112 #define NDR_POINTER_ID_BASE 0x20000
113 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
114 #define NDR_TABLE_SIZE 128
115 #define NDR_TABLE_MASK 127
117 #define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL))
119 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
120 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
121 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
122 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
123 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
125 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
126 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
127 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
129 static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
130 static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
131 static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
132 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
134 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
136 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
138 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
139 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
140 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
141 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
142 /* 0x10 */
143 NdrBaseTypeMarshall,
144 /* 0x11 */
145 NdrPointerMarshall, NdrPointerMarshall,
146 NdrPointerMarshall, NdrPointerMarshall,
147 /* 0x15 */
148 NdrSimpleStructMarshall, NdrSimpleStructMarshall,
149 NdrConformantStructMarshall, NdrConformantStructMarshall,
150 NdrConformantVaryingStructMarshall,
151 NdrComplexStructMarshall,
152 /* 0x1b */
153 NdrConformantArrayMarshall,
154 NdrConformantVaryingArrayMarshall,
155 NdrFixedArrayMarshall, NdrFixedArrayMarshall,
156 NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
157 NdrComplexArrayMarshall,
158 /* 0x22 */
159 NdrConformantStringMarshall, 0, 0,
160 NdrConformantStringMarshall,
161 NdrNonConformantStringMarshall, 0, 0, 0,
162 /* 0x2a */
163 NdrEncapsulatedUnionMarshall,
164 NdrNonEncapsulatedUnionMarshall,
165 NdrByteCountPointerMarshall,
166 NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
167 /* 0x2f */
168 NdrInterfacePointerMarshall,
169 /* 0x30 */
170 NdrContextHandleMarshall,
171 /* 0xb1 */
172 0, 0, 0,
173 NdrUserMarshalMarshall,
174 0, 0,
175 /* 0xb7 */
176 NdrRangeMarshall
178 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
180 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
181 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
182 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
183 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
184 /* 0x10 */
185 NdrBaseTypeUnmarshall,
186 /* 0x11 */
187 NdrPointerUnmarshall, NdrPointerUnmarshall,
188 NdrPointerUnmarshall, NdrPointerUnmarshall,
189 /* 0x15 */
190 NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
191 NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
192 NdrConformantVaryingStructUnmarshall,
193 NdrComplexStructUnmarshall,
194 /* 0x1b */
195 NdrConformantArrayUnmarshall,
196 NdrConformantVaryingArrayUnmarshall,
197 NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
198 NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
199 NdrComplexArrayUnmarshall,
200 /* 0x22 */
201 NdrConformantStringUnmarshall, 0, 0,
202 NdrConformantStringUnmarshall,
203 NdrNonConformantStringUnmarshall, 0, 0, 0,
204 /* 0x2a */
205 NdrEncapsulatedUnionUnmarshall,
206 NdrNonEncapsulatedUnionUnmarshall,
207 NdrByteCountPointerUnmarshall,
208 NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
209 /* 0x2f */
210 NdrInterfacePointerUnmarshall,
211 /* 0x30 */
212 NdrContextHandleUnmarshall,
213 /* 0xb1 */
214 0, 0, 0,
215 NdrUserMarshalUnmarshall,
216 0, 0,
217 /* 0xb7 */
218 NdrRangeUnmarshall
220 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
222 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
223 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
224 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
225 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
226 /* 0x10 */
227 NdrBaseTypeBufferSize,
228 /* 0x11 */
229 NdrPointerBufferSize, NdrPointerBufferSize,
230 NdrPointerBufferSize, NdrPointerBufferSize,
231 /* 0x15 */
232 NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
233 NdrConformantStructBufferSize, NdrConformantStructBufferSize,
234 NdrConformantVaryingStructBufferSize,
235 NdrComplexStructBufferSize,
236 /* 0x1b */
237 NdrConformantArrayBufferSize,
238 NdrConformantVaryingArrayBufferSize,
239 NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
240 NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
241 NdrComplexArrayBufferSize,
242 /* 0x22 */
243 NdrConformantStringBufferSize, 0, 0,
244 NdrConformantStringBufferSize,
245 NdrNonConformantStringBufferSize, 0, 0, 0,
246 /* 0x2a */
247 NdrEncapsulatedUnionBufferSize,
248 NdrNonEncapsulatedUnionBufferSize,
249 NdrByteCountPointerBufferSize,
250 NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
251 /* 0x2f */
252 NdrInterfacePointerBufferSize,
253 /* 0x30 */
254 NdrContextHandleBufferSize,
255 /* 0xb1 */
256 0, 0, 0,
257 NdrUserMarshalBufferSize,
258 0, 0,
259 /* 0xb7 */
260 NdrRangeBufferSize
262 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
264 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
265 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
266 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
267 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
268 /* 0x10 */
269 NdrBaseTypeMemorySize,
270 /* 0x11 */
271 NdrPointerMemorySize, NdrPointerMemorySize,
272 NdrPointerMemorySize, NdrPointerMemorySize,
273 /* 0x15 */
274 NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
275 NdrConformantStructMemorySize, NdrConformantStructMemorySize,
276 NdrConformantVaryingStructMemorySize,
277 NdrComplexStructMemorySize,
278 /* 0x1b */
279 NdrConformantArrayMemorySize,
280 NdrConformantVaryingArrayMemorySize,
281 NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
282 NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
283 NdrComplexArrayMemorySize,
284 /* 0x22 */
285 NdrConformantStringMemorySize, 0, 0,
286 NdrConformantStringMemorySize,
287 NdrNonConformantStringMemorySize, 0, 0, 0,
288 /* 0x2a */
289 NdrEncapsulatedUnionMemorySize,
290 NdrNonEncapsulatedUnionMemorySize,
291 NdrByteCountPointerMemorySize,
292 NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
293 /* 0x2f */
294 NdrInterfacePointerMemorySize,
295 /* 0x30 */
297 /* 0xb1 */
298 0, 0, 0,
299 NdrUserMarshalMemorySize,
300 0, 0,
301 /* 0xb7 */
302 NdrRangeMemorySize
304 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
306 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
307 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
308 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
309 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
310 /* 0x10 */
311 NdrBaseTypeFree,
312 /* 0x11 */
313 NdrPointerFree, NdrPointerFree,
314 NdrPointerFree, NdrPointerFree,
315 /* 0x15 */
316 NdrSimpleStructFree, NdrSimpleStructFree,
317 NdrConformantStructFree, NdrConformantStructFree,
318 NdrConformantVaryingStructFree,
319 NdrComplexStructFree,
320 /* 0x1b */
321 NdrConformantArrayFree,
322 NdrConformantVaryingArrayFree,
323 NdrFixedArrayFree, NdrFixedArrayFree,
324 NdrVaryingArrayFree, NdrVaryingArrayFree,
325 NdrComplexArrayFree,
326 /* 0x22 */
327 0, 0, 0,
328 0, 0, 0, 0, 0,
329 /* 0x2a */
330 NdrEncapsulatedUnionFree,
331 NdrNonEncapsulatedUnionFree,
333 NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
334 /* 0x2f */
335 NdrInterfacePointerFree,
336 /* 0x30 */
338 /* 0xb1 */
339 0, 0, 0,
340 NdrUserMarshalFree,
341 0, 0,
342 /* 0xb7 */
343 NdrRangeFree
346 typedef struct _NDR_MEMORY_LIST
348 ULONG magic;
349 ULONG size;
350 ULONG reserved;
351 struct _NDR_MEMORY_LIST *next;
352 } NDR_MEMORY_LIST;
354 #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
356 /***********************************************************************
357 * NdrAllocate [RPCRT4.@]
359 * Allocates a block of memory using pStubMsg->pfnAllocate.
361 * PARAMS
362 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
363 * len [I] Size of memory block to allocate.
365 * RETURNS
366 * The memory block of size len that was allocated.
368 * NOTES
369 * The memory block is always 8-byte aligned.
370 * If the function is unable to allocate memory an ERROR_OUTOFMEMORY
371 * exception is raised.
373 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len)
375 SIZE_T aligned_len;
376 SIZE_T adjusted_len;
377 void *p;
378 NDR_MEMORY_LIST *mem_list;
380 aligned_len = ALIGNED_LENGTH(len, 8);
381 adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
382 /* check for overflow */
383 if (adjusted_len < len)
385 ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len);
386 RpcRaiseException(RPC_X_BAD_STUB_DATA);
389 p = pStubMsg->pfnAllocate(adjusted_len);
390 if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
392 mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
393 mem_list->magic = MEML_MAGIC;
394 mem_list->size = aligned_len;
395 mem_list->reserved = 0;
396 mem_list->next = pStubMsg->pMemoryList;
397 pStubMsg->pMemoryList = mem_list;
399 TRACE("-- %p\n", p);
400 return p;
403 static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
405 TRACE("(%p, %p)\n", pStubMsg, Pointer);
407 pStubMsg->pfnFree(Pointer);
410 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
412 return (*(const ULONG *)pFormat != -1);
415 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
417 ALIGN_POINTER(pStubMsg->Buffer, 4);
418 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
419 RpcRaiseException(RPC_X_BAD_STUB_DATA);
420 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
421 pStubMsg->Buffer += 4;
422 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
423 if (pStubMsg->fHasNewCorrDesc)
424 return pFormat+6;
425 else
426 return pFormat+4;
429 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
431 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
433 pStubMsg->Offset = 0;
434 pStubMsg->ActualCount = pStubMsg->MaxCount;
435 goto done;
438 ALIGN_POINTER(pStubMsg->Buffer, 4);
439 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
440 RpcRaiseException(RPC_X_BAD_STUB_DATA);
441 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
442 pStubMsg->Buffer += 4;
443 TRACE("offset is %d\n", pStubMsg->Offset);
444 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
445 pStubMsg->Buffer += 4;
446 TRACE("variance is %d\n", pStubMsg->ActualCount);
448 if ((pStubMsg->ActualCount > MaxValue) ||
449 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
451 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
452 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
453 RpcRaiseException(RPC_S_INVALID_BOUND);
454 return NULL;
457 done:
458 if (pStubMsg->fHasNewCorrDesc)
459 return pFormat+6;
460 else
461 return pFormat+4;
464 /* writes the conformance value to the buffer */
465 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
467 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
468 if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
469 RpcRaiseException(RPC_X_BAD_STUB_DATA);
470 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
471 pStubMsg->Buffer += 4;
474 /* writes the variance values to the buffer */
475 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
477 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
478 if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
479 RpcRaiseException(RPC_X_BAD_STUB_DATA);
480 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
481 pStubMsg->Buffer += 4;
482 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
483 pStubMsg->Buffer += 4;
486 /* requests buffer space for the conformance value */
487 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
489 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
490 if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
491 RpcRaiseException(RPC_X_BAD_STUB_DATA);
492 pStubMsg->BufferLength += 4;
495 /* requests buffer space for the variance values */
496 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
498 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
499 if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
500 RpcRaiseException(RPC_X_BAD_STUB_DATA);
501 pStubMsg->BufferLength += 8;
504 PFORMAT_STRING ComputeConformanceOrVariance(
505 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
506 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
508 BYTE dtype = pFormat[0] & 0xf;
509 short ofs = *(const short *)&pFormat[2];
510 LPVOID ptr = NULL;
511 DWORD data = 0;
513 if (!IsConformanceOrVariancePresent(pFormat)) {
514 /* null descriptor */
515 *pCount = def;
516 goto finish_conf;
519 switch (pFormat[0] & 0xf0) {
520 case RPC_FC_NORMAL_CONFORMANCE:
521 TRACE("normal conformance, ofs=%d\n", ofs);
522 ptr = pMemory;
523 break;
524 case RPC_FC_POINTER_CONFORMANCE:
525 TRACE("pointer conformance, ofs=%d\n", ofs);
526 ptr = pStubMsg->Memory;
527 break;
528 case RPC_FC_TOP_LEVEL_CONFORMANCE:
529 TRACE("toplevel conformance, ofs=%d\n", ofs);
530 if (pStubMsg->StackTop) {
531 ptr = pStubMsg->StackTop;
533 else {
534 /* -Os mode, *pCount is already set */
535 goto finish_conf;
537 break;
538 case RPC_FC_CONSTANT_CONFORMANCE:
539 data = ofs | ((DWORD)pFormat[1] << 16);
540 TRACE("constant conformance, val=%d\n", data);
541 *pCount = data;
542 goto finish_conf;
543 case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
544 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
545 if (pStubMsg->StackTop) {
546 ptr = pStubMsg->StackTop;
548 else {
549 /* ? */
550 goto done_conf_grab;
552 break;
553 default:
554 FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0);
555 goto finish_conf;
558 switch (pFormat[1]) {
559 case RPC_FC_DEREFERENCE:
560 ptr = *(LPVOID*)((char *)ptr + ofs);
561 break;
562 case RPC_FC_CALLBACK:
564 unsigned char *old_stack_top = pStubMsg->StackTop;
565 pStubMsg->StackTop = ptr;
567 /* ofs is index into StubDesc->apfnExprEval */
568 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
569 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
571 pStubMsg->StackTop = old_stack_top;
573 /* the callback function always stores the computed value in MaxCount */
574 *pCount = pStubMsg->MaxCount;
575 goto finish_conf;
577 default:
578 ptr = (char *)ptr + ofs;
579 break;
582 switch (dtype) {
583 case RPC_FC_LONG:
584 case RPC_FC_ULONG:
585 data = *(DWORD*)ptr;
586 break;
587 case RPC_FC_SHORT:
588 data = *(SHORT*)ptr;
589 break;
590 case RPC_FC_USHORT:
591 data = *(USHORT*)ptr;
592 break;
593 case RPC_FC_CHAR:
594 case RPC_FC_SMALL:
595 data = *(CHAR*)ptr;
596 break;
597 case RPC_FC_BYTE:
598 case RPC_FC_USMALL:
599 data = *(UCHAR*)ptr;
600 break;
601 default:
602 FIXME("unknown conformance data type %x\n", dtype);
603 goto done_conf_grab;
605 TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
607 done_conf_grab:
608 switch (pFormat[1]) {
609 case RPC_FC_DEREFERENCE: /* already handled */
610 case 0: /* no op */
611 *pCount = data;
612 break;
613 case RPC_FC_ADD_1:
614 *pCount = data + 1;
615 break;
616 case RPC_FC_SUB_1:
617 *pCount = data - 1;
618 break;
619 case RPC_FC_MULT_2:
620 *pCount = data * 2;
621 break;
622 case RPC_FC_DIV_2:
623 *pCount = data / 2;
624 break;
625 default:
626 FIXME("unknown conformance op %d\n", pFormat[1]);
627 goto finish_conf;
630 finish_conf:
631 TRACE("resulting conformance is %ld\n", *pCount);
632 if (pStubMsg->fHasNewCorrDesc)
633 return pFormat+6;
634 else
635 return pFormat+4;
638 static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg,
639 PFORMAT_STRING pFormat)
641 if (IsConformanceOrVariancePresent(pFormat))
643 if (pStubMsg->fHasNewCorrDesc)
644 pFormat += 6;
645 else
646 pFormat += 4;
648 return pFormat;
651 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
652 * the result overflows 32-bits */
653 static inline ULONG safe_multiply(ULONG a, ULONG b)
655 ULONGLONG ret = (ULONGLONG)a * b;
656 if (ret > 0xffffffff)
658 RpcRaiseException(RPC_S_INVALID_BOUND);
659 return 0;
661 return ret;
664 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
666 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
667 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
668 RpcRaiseException(RPC_X_BAD_STUB_DATA);
669 pStubMsg->Buffer += size;
672 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
674 if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
676 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
677 pStubMsg->BufferLength, size);
678 RpcRaiseException(RPC_X_BAD_STUB_DATA);
680 pStubMsg->BufferLength += size;
683 /* copies data from the buffer, checking that there is enough data in the buffer
684 * to do so */
685 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
687 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
688 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
690 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
691 pStubMsg->Buffer, pStubMsg->BufferEnd, size);
692 RpcRaiseException(RPC_X_BAD_STUB_DATA);
694 if (p == pStubMsg->Buffer)
695 ERR("pointer is the same as the buffer\n");
696 memcpy(p, pStubMsg->Buffer, size);
697 pStubMsg->Buffer += size;
700 /* copies data to the buffer, checking that there is enough space to do so */
701 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
703 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
704 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
706 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
707 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
708 size);
709 RpcRaiseException(RPC_X_BAD_STUB_DATA);
711 memcpy(pStubMsg->Buffer, p, size);
712 pStubMsg->Buffer += size;
715 /* verify that string data sitting in the buffer is valid and safe to
716 * unmarshall */
717 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
719 ULONG i;
721 /* verify the buffer is safe to access */
722 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
723 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
725 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
726 pStubMsg->BufferEnd, pStubMsg->Buffer);
727 RpcRaiseException(RPC_X_BAD_STUB_DATA);
730 /* strings must always have null terminating bytes */
731 if (bufsize < esize)
733 ERR("invalid string length of %d\n", bufsize / esize);
734 RpcRaiseException(RPC_S_INVALID_BOUND);
737 for (i = bufsize - esize; i < bufsize; i++)
738 if (pStubMsg->Buffer[i] != 0)
740 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
741 i, pStubMsg->Buffer[i]);
742 RpcRaiseException(RPC_S_INVALID_BOUND);
746 static inline void dump_pointer_attr(unsigned char attr)
748 if (attr & RPC_FC_P_ALLOCALLNODES)
749 TRACE(" RPC_FC_P_ALLOCALLNODES");
750 if (attr & RPC_FC_P_DONTFREE)
751 TRACE(" RPC_FC_P_DONTFREE");
752 if (attr & RPC_FC_P_ONSTACK)
753 TRACE(" RPC_FC_P_ONSTACK");
754 if (attr & RPC_FC_P_SIMPLEPOINTER)
755 TRACE(" RPC_FC_P_SIMPLEPOINTER");
756 if (attr & RPC_FC_P_DEREF)
757 TRACE(" RPC_FC_P_DEREF");
758 TRACE("\n");
761 /***********************************************************************
762 * PointerMarshall [internal]
764 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
765 unsigned char *Buffer,
766 unsigned char *Pointer,
767 PFORMAT_STRING pFormat)
769 unsigned type = pFormat[0], attr = pFormat[1];
770 PFORMAT_STRING desc;
771 NDR_MARSHALL m;
772 ULONG pointer_id;
773 int pointer_needs_marshaling;
775 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
776 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
777 pFormat += 2;
778 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
779 else desc = pFormat + *(const SHORT*)pFormat;
781 switch (type) {
782 case RPC_FC_RP: /* ref pointer (always non-null) */
783 if (!Pointer)
785 ERR("NULL ref pointer is not allowed\n");
786 RpcRaiseException(RPC_X_NULL_REF_POINTER);
788 pointer_needs_marshaling = 1;
789 break;
790 case RPC_FC_UP: /* unique pointer */
791 case RPC_FC_OP: /* object pointer - same as unique here */
792 if (Pointer)
793 pointer_needs_marshaling = 1;
794 else
795 pointer_needs_marshaling = 0;
796 pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
797 TRACE("writing 0x%08x to buffer\n", pointer_id);
798 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
799 break;
800 case RPC_FC_FP:
801 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
802 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
803 TRACE("writing 0x%08x to buffer\n", pointer_id);
804 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
805 break;
806 default:
807 FIXME("unhandled ptr type=%02x\n", type);
808 RpcRaiseException(RPC_X_BAD_STUB_DATA);
809 return;
812 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
814 if (pointer_needs_marshaling) {
815 if (attr & RPC_FC_P_DEREF) {
816 Pointer = *(unsigned char**)Pointer;
817 TRACE("deref => %p\n", Pointer);
819 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
820 if (m) m(pStubMsg, Pointer, desc);
821 else FIXME("no marshaller for data type=%02x\n", *desc);
824 STD_OVERFLOW_CHECK(pStubMsg);
827 /***********************************************************************
828 * PointerUnmarshall [internal]
830 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
831 unsigned char *Buffer,
832 unsigned char **pPointer,
833 unsigned char *pSrcPointer,
834 PFORMAT_STRING pFormat,
835 unsigned char fMustAlloc)
837 unsigned type = pFormat[0], attr = pFormat[1];
838 PFORMAT_STRING desc;
839 NDR_UNMARSHALL m;
840 DWORD pointer_id = 0;
841 int pointer_needs_unmarshaling;
843 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
844 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
845 pFormat += 2;
846 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
847 else desc = pFormat + *(const SHORT*)pFormat;
849 switch (type) {
850 case RPC_FC_RP: /* ref pointer (always non-null) */
851 pointer_needs_unmarshaling = 1;
852 break;
853 case RPC_FC_UP: /* unique pointer */
854 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
855 TRACE("pointer_id is 0x%08x\n", pointer_id);
856 if (pointer_id)
857 pointer_needs_unmarshaling = 1;
858 else {
859 *pPointer = NULL;
860 pointer_needs_unmarshaling = 0;
862 break;
863 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
864 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
865 TRACE("pointer_id is 0x%08x\n", pointer_id);
866 if (!fMustAlloc && pSrcPointer)
868 FIXME("free object pointer %p\n", pSrcPointer);
869 fMustAlloc = TRUE;
871 if (pointer_id)
872 pointer_needs_unmarshaling = 1;
873 else
875 *pPointer = NULL;
876 pointer_needs_unmarshaling = 0;
878 break;
879 case RPC_FC_FP:
880 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
881 TRACE("pointer_id is 0x%08x\n", pointer_id);
882 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
883 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
884 break;
885 default:
886 FIXME("unhandled ptr type=%02x\n", type);
887 RpcRaiseException(RPC_X_BAD_STUB_DATA);
888 return;
891 if (pointer_needs_unmarshaling) {
892 unsigned char *base_ptr_val = *pPointer;
893 unsigned char **current_ptr = pPointer;
894 if (pStubMsg->IsClient) {
895 TRACE("client\n");
896 /* if we aren't forcing allocation of memory then try to use the existing
897 * (source) pointer to unmarshall the data into so that [in,out]
898 * parameters behave correctly. it doesn't matter if the parameter is
899 * [out] only since in that case the pointer will be NULL. we force
900 * allocation when the source pointer is NULL here instead of in the type
901 * unmarshalling routine for the benefit of the deref code below */
902 if (!fMustAlloc) {
903 if (pSrcPointer) {
904 TRACE("setting *pPointer to %p\n", pSrcPointer);
905 *pPointer = base_ptr_val = pSrcPointer;
906 } else
907 fMustAlloc = TRUE;
909 } else {
910 TRACE("server\n");
911 /* the memory in a stub is never initialised, so we have to work out here
912 * whether we have to initialise it so we can use the optimisation of
913 * setting the pointer to the buffer, if possible, or set fMustAlloc to
914 * TRUE. */
915 if (attr & RPC_FC_P_DEREF) {
916 fMustAlloc = TRUE;
917 } else {
918 base_ptr_val = NULL;
919 *current_ptr = NULL;
923 if (attr & RPC_FC_P_ALLOCALLNODES)
924 FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
926 if (attr & RPC_FC_P_DEREF) {
927 if (fMustAlloc) {
928 base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
929 *pPointer = base_ptr_val;
930 current_ptr = (unsigned char **)base_ptr_val;
931 } else
932 current_ptr = *(unsigned char***)current_ptr;
933 TRACE("deref => %p\n", current_ptr);
934 if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
936 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
937 if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
938 else FIXME("no unmarshaller for data type=%02x\n", *desc);
940 if (type == RPC_FC_FP)
941 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
942 *pPointer);
945 TRACE("pointer=%p\n", *pPointer);
948 /***********************************************************************
949 * PointerBufferSize [internal]
951 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
952 unsigned char *Pointer,
953 PFORMAT_STRING pFormat)
955 unsigned type = pFormat[0], attr = pFormat[1];
956 PFORMAT_STRING desc;
957 NDR_BUFFERSIZE m;
958 int pointer_needs_sizing;
959 ULONG pointer_id;
961 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
962 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
963 pFormat += 2;
964 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
965 else desc = pFormat + *(const SHORT*)pFormat;
967 switch (type) {
968 case RPC_FC_RP: /* ref pointer (always non-null) */
969 if (!Pointer)
971 ERR("NULL ref pointer is not allowed\n");
972 RpcRaiseException(RPC_X_NULL_REF_POINTER);
974 break;
975 case RPC_FC_OP:
976 case RPC_FC_UP:
977 /* NULL pointer has no further representation */
978 if (!Pointer)
979 return;
980 break;
981 case RPC_FC_FP:
982 pointer_needs_sizing = !NdrFullPointerQueryPointer(
983 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
984 if (!pointer_needs_sizing)
985 return;
986 break;
987 default:
988 FIXME("unhandled ptr type=%02x\n", type);
989 RpcRaiseException(RPC_X_BAD_STUB_DATA);
990 return;
993 if (attr & RPC_FC_P_DEREF) {
994 Pointer = *(unsigned char**)Pointer;
995 TRACE("deref => %p\n", Pointer);
998 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
999 if (m) m(pStubMsg, Pointer, desc);
1000 else FIXME("no buffersizer for data type=%02x\n", *desc);
1003 /***********************************************************************
1004 * PointerMemorySize [internal]
1006 static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1007 unsigned char *Buffer, PFORMAT_STRING pFormat)
1009 unsigned type = pFormat[0], attr = pFormat[1];
1010 PFORMAT_STRING desc;
1011 NDR_MEMORYSIZE m;
1012 DWORD pointer_id = 0;
1013 int pointer_needs_sizing;
1015 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1016 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1017 pFormat += 2;
1018 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1019 else desc = pFormat + *(const SHORT*)pFormat;
1021 switch (type) {
1022 case RPC_FC_RP: /* ref pointer (always non-null) */
1023 pointer_needs_sizing = 1;
1024 break;
1025 case RPC_FC_UP: /* unique pointer */
1026 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1027 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1028 TRACE("pointer_id is 0x%08x\n", pointer_id);
1029 if (pointer_id)
1030 pointer_needs_sizing = 1;
1031 else
1032 pointer_needs_sizing = 0;
1033 break;
1034 case RPC_FC_FP:
1036 void *pointer;
1037 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1038 TRACE("pointer_id is 0x%08x\n", pointer_id);
1039 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1040 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1041 break;
1043 default:
1044 FIXME("unhandled ptr type=%02x\n", type);
1045 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1046 return 0;
1049 if (attr & RPC_FC_P_DEREF) {
1050 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void*));
1051 pStubMsg->MemorySize += sizeof(void*);
1052 TRACE("deref\n");
1055 if (pointer_needs_sizing) {
1056 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1057 if (m) m(pStubMsg, desc);
1058 else FIXME("no memorysizer for data type=%02x\n", *desc);
1061 return pStubMsg->MemorySize;
1064 /***********************************************************************
1065 * PointerFree [internal]
1067 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1068 unsigned char *Pointer,
1069 PFORMAT_STRING pFormat)
1071 unsigned type = pFormat[0], attr = pFormat[1];
1072 PFORMAT_STRING desc;
1073 NDR_FREE m;
1074 unsigned char *current_pointer = Pointer;
1076 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1077 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1078 if (attr & RPC_FC_P_DONTFREE) return;
1079 pFormat += 2;
1080 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1081 else desc = pFormat + *(const SHORT*)pFormat;
1083 if (!Pointer) return;
1085 if (type == RPC_FC_FP) {
1086 int pointer_needs_freeing = NdrFullPointerFree(
1087 pStubMsg->FullPtrXlatTables, Pointer);
1088 if (!pointer_needs_freeing)
1089 return;
1092 if (attr & RPC_FC_P_DEREF) {
1093 current_pointer = *(unsigned char**)Pointer;
1094 TRACE("deref => %p\n", current_pointer);
1097 m = NdrFreer[*desc & NDR_TABLE_MASK];
1098 if (m) m(pStubMsg, current_pointer, desc);
1100 /* this check stops us from trying to free buffer memory. we don't have to
1101 * worry about clients, since they won't call this function.
1102 * we don't have to check for the buffer being reallocated because
1103 * BufferStart and BufferEnd won't be reset when allocating memory for
1104 * sending the response. we don't have to check for the new buffer here as
1105 * it won't be used a type memory, only for buffer memory */
1106 if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd)
1107 goto notfree;
1109 if (attr & RPC_FC_P_ONSTACK) {
1110 TRACE("not freeing stack ptr %p\n", Pointer);
1111 return;
1113 TRACE("freeing %p\n", Pointer);
1114 NdrFree(pStubMsg, Pointer);
1115 return;
1116 notfree:
1117 TRACE("not freeing %p\n", Pointer);
1120 /***********************************************************************
1121 * EmbeddedPointerMarshall
1123 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1124 unsigned char *pMemory,
1125 PFORMAT_STRING pFormat)
1127 unsigned char *Mark = pStubMsg->BufferMark;
1128 unsigned rep, count, stride;
1129 unsigned i;
1130 unsigned char *saved_buffer = NULL;
1132 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1134 if (*pFormat != RPC_FC_PP) return NULL;
1135 pFormat += 2;
1137 if (pStubMsg->PointerBufferMark)
1139 saved_buffer = pStubMsg->Buffer;
1140 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1141 pStubMsg->PointerBufferMark = NULL;
1144 while (pFormat[0] != RPC_FC_END) {
1145 switch (pFormat[0]) {
1146 default:
1147 FIXME("unknown repeat type %d\n", pFormat[0]);
1148 case RPC_FC_NO_REPEAT:
1149 rep = 1;
1150 stride = 0;
1151 count = 1;
1152 pFormat += 2;
1153 break;
1154 case RPC_FC_FIXED_REPEAT:
1155 rep = *(const WORD*)&pFormat[2];
1156 stride = *(const WORD*)&pFormat[4];
1157 count = *(const WORD*)&pFormat[8];
1158 pFormat += 10;
1159 break;
1160 case RPC_FC_VARIABLE_REPEAT:
1161 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1162 stride = *(const WORD*)&pFormat[2];
1163 count = *(const WORD*)&pFormat[6];
1164 pFormat += 8;
1165 break;
1167 for (i = 0; i < rep; i++) {
1168 PFORMAT_STRING info = pFormat;
1169 unsigned char *membase = pMemory + (i * stride);
1170 unsigned char *bufbase = Mark + (i * stride);
1171 unsigned u;
1173 for (u=0; u<count; u++,info+=8) {
1174 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1175 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1176 unsigned char *saved_memory = pStubMsg->Memory;
1178 pStubMsg->Memory = pMemory;
1179 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1180 pStubMsg->Memory = saved_memory;
1183 pFormat += 8 * count;
1186 if (saved_buffer)
1188 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1189 pStubMsg->Buffer = saved_buffer;
1192 STD_OVERFLOW_CHECK(pStubMsg);
1194 return NULL;
1197 /***********************************************************************
1198 * EmbeddedPointerUnmarshall
1200 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1201 unsigned char *pDstBuffer,
1202 unsigned char *pSrcMemoryPtrs,
1203 PFORMAT_STRING pFormat,
1204 unsigned char fMustAlloc)
1206 unsigned char *Mark = pStubMsg->BufferMark;
1207 unsigned rep, count, stride;
1208 unsigned i;
1209 unsigned char *saved_buffer = NULL;
1211 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1213 if (*pFormat != RPC_FC_PP) return NULL;
1214 pFormat += 2;
1216 if (pStubMsg->PointerBufferMark)
1218 saved_buffer = pStubMsg->Buffer;
1219 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1220 pStubMsg->PointerBufferMark = NULL;
1223 while (pFormat[0] != RPC_FC_END) {
1224 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1225 switch (pFormat[0]) {
1226 default:
1227 FIXME("unknown repeat type %d\n", pFormat[0]);
1228 case RPC_FC_NO_REPEAT:
1229 rep = 1;
1230 stride = 0;
1231 count = 1;
1232 pFormat += 2;
1233 break;
1234 case RPC_FC_FIXED_REPEAT:
1235 rep = *(const WORD*)&pFormat[2];
1236 stride = *(const WORD*)&pFormat[4];
1237 count = *(const WORD*)&pFormat[8];
1238 pFormat += 10;
1239 break;
1240 case RPC_FC_VARIABLE_REPEAT:
1241 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1242 stride = *(const WORD*)&pFormat[2];
1243 count = *(const WORD*)&pFormat[6];
1244 pFormat += 8;
1245 break;
1247 for (i = 0; i < rep; i++) {
1248 PFORMAT_STRING info = pFormat;
1249 unsigned char *bufdstbase = pDstBuffer + (i * stride);
1250 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1251 unsigned char *bufbase = Mark + (i * stride);
1252 unsigned u;
1254 for (u=0; u<count; u++,info+=8) {
1255 unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1256 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1257 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1258 PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1261 pFormat += 8 * count;
1264 if (saved_buffer)
1266 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1267 pStubMsg->Buffer = saved_buffer;
1270 return NULL;
1273 /***********************************************************************
1274 * EmbeddedPointerBufferSize
1276 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1277 unsigned char *pMemory,
1278 PFORMAT_STRING pFormat)
1280 unsigned rep, count, stride;
1281 unsigned i;
1282 ULONG saved_buffer_length = 0;
1284 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1286 if (pStubMsg->IgnoreEmbeddedPointers) return;
1288 if (*pFormat != RPC_FC_PP) return;
1289 pFormat += 2;
1291 if (pStubMsg->PointerLength)
1293 saved_buffer_length = pStubMsg->BufferLength;
1294 pStubMsg->BufferLength = pStubMsg->PointerLength;
1295 pStubMsg->PointerLength = 0;
1298 while (pFormat[0] != RPC_FC_END) {
1299 switch (pFormat[0]) {
1300 default:
1301 FIXME("unknown repeat type %d\n", pFormat[0]);
1302 case RPC_FC_NO_REPEAT:
1303 rep = 1;
1304 stride = 0;
1305 count = 1;
1306 pFormat += 2;
1307 break;
1308 case RPC_FC_FIXED_REPEAT:
1309 rep = *(const WORD*)&pFormat[2];
1310 stride = *(const WORD*)&pFormat[4];
1311 count = *(const WORD*)&pFormat[8];
1312 pFormat += 10;
1313 break;
1314 case RPC_FC_VARIABLE_REPEAT:
1315 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1316 stride = *(const WORD*)&pFormat[2];
1317 count = *(const WORD*)&pFormat[6];
1318 pFormat += 8;
1319 break;
1321 for (i = 0; i < rep; i++) {
1322 PFORMAT_STRING info = pFormat;
1323 unsigned char *membase = pMemory + (i * stride);
1324 unsigned u;
1326 for (u=0; u<count; u++,info+=8) {
1327 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1328 unsigned char *saved_memory = pStubMsg->Memory;
1330 pStubMsg->Memory = pMemory;
1331 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1332 pStubMsg->Memory = saved_memory;
1335 pFormat += 8 * count;
1338 if (saved_buffer_length)
1340 pStubMsg->PointerLength = pStubMsg->BufferLength;
1341 pStubMsg->BufferLength = saved_buffer_length;
1345 /***********************************************************************
1346 * EmbeddedPointerMemorySize [internal]
1348 static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1349 PFORMAT_STRING pFormat)
1351 unsigned char *Mark = pStubMsg->BufferMark;
1352 unsigned rep, count, stride;
1353 unsigned i;
1354 unsigned char *saved_buffer = NULL;
1356 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1358 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1360 if (pStubMsg->PointerBufferMark)
1362 saved_buffer = pStubMsg->Buffer;
1363 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1364 pStubMsg->PointerBufferMark = NULL;
1367 if (*pFormat != RPC_FC_PP) return 0;
1368 pFormat += 2;
1370 while (pFormat[0] != RPC_FC_END) {
1371 switch (pFormat[0]) {
1372 default:
1373 FIXME("unknown repeat type %d\n", pFormat[0]);
1374 case RPC_FC_NO_REPEAT:
1375 rep = 1;
1376 stride = 0;
1377 count = 1;
1378 pFormat += 2;
1379 break;
1380 case RPC_FC_FIXED_REPEAT:
1381 rep = *(const WORD*)&pFormat[2];
1382 stride = *(const WORD*)&pFormat[4];
1383 count = *(const WORD*)&pFormat[8];
1384 pFormat += 10;
1385 break;
1386 case RPC_FC_VARIABLE_REPEAT:
1387 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1388 stride = *(const WORD*)&pFormat[2];
1389 count = *(const WORD*)&pFormat[6];
1390 pFormat += 8;
1391 break;
1393 for (i = 0; i < rep; i++) {
1394 PFORMAT_STRING info = pFormat;
1395 unsigned char *bufbase = Mark + (i * stride);
1396 unsigned u;
1397 for (u=0; u<count; u++,info+=8) {
1398 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1399 PointerMemorySize(pStubMsg, bufptr, info+4);
1402 pFormat += 8 * count;
1405 if (saved_buffer)
1407 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1408 pStubMsg->Buffer = saved_buffer;
1411 return 0;
1414 /***********************************************************************
1415 * EmbeddedPointerFree [internal]
1417 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1418 unsigned char *pMemory,
1419 PFORMAT_STRING pFormat)
1421 unsigned rep, count, stride;
1422 unsigned i;
1424 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1425 if (*pFormat != RPC_FC_PP) return;
1426 pFormat += 2;
1428 while (pFormat[0] != RPC_FC_END) {
1429 switch (pFormat[0]) {
1430 default:
1431 FIXME("unknown repeat type %d\n", pFormat[0]);
1432 case RPC_FC_NO_REPEAT:
1433 rep = 1;
1434 stride = 0;
1435 count = 1;
1436 pFormat += 2;
1437 break;
1438 case RPC_FC_FIXED_REPEAT:
1439 rep = *(const WORD*)&pFormat[2];
1440 stride = *(const WORD*)&pFormat[4];
1441 count = *(const WORD*)&pFormat[8];
1442 pFormat += 10;
1443 break;
1444 case RPC_FC_VARIABLE_REPEAT:
1445 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1446 stride = *(const WORD*)&pFormat[2];
1447 count = *(const WORD*)&pFormat[6];
1448 pFormat += 8;
1449 break;
1451 for (i = 0; i < rep; i++) {
1452 PFORMAT_STRING info = pFormat;
1453 unsigned char *membase = pMemory + (i * stride);
1454 unsigned u;
1456 for (u=0; u<count; u++,info+=8) {
1457 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1458 unsigned char *saved_memory = pStubMsg->Memory;
1460 pStubMsg->Memory = pMemory;
1461 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1462 pStubMsg->Memory = saved_memory;
1465 pFormat += 8 * count;
1469 /***********************************************************************
1470 * NdrPointerMarshall [RPCRT4.@]
1472 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1473 unsigned char *pMemory,
1474 PFORMAT_STRING pFormat)
1476 unsigned char *Buffer;
1478 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1480 /* Increment the buffer here instead of in PointerMarshall,
1481 * as that is used by embedded pointers which already handle the incrementing
1482 * the buffer, and shouldn't write any additional pointer data to the wire */
1483 if (*pFormat != RPC_FC_RP)
1485 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1486 Buffer = pStubMsg->Buffer;
1487 safe_buffer_increment(pStubMsg, 4);
1489 else
1490 Buffer = pStubMsg->Buffer;
1492 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1494 return NULL;
1497 /***********************************************************************
1498 * NdrPointerUnmarshall [RPCRT4.@]
1500 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1501 unsigned char **ppMemory,
1502 PFORMAT_STRING pFormat,
1503 unsigned char fMustAlloc)
1505 unsigned char *Buffer;
1507 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1509 if (*pFormat == RPC_FC_RP)
1511 Buffer = pStubMsg->Buffer;
1512 /* Do the NULL ref pointer check here because embedded pointers can be
1513 * NULL if the type the pointer is embedded in was allocated rather than
1514 * being passed in by the client */
1515 if (pStubMsg->IsClient && !*ppMemory)
1517 ERR("NULL ref pointer is not allowed\n");
1518 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1521 else
1523 /* Increment the buffer here instead of in PointerUnmarshall,
1524 * as that is used by embedded pointers which already handle the incrementing
1525 * the buffer, and shouldn't read any additional pointer data from the
1526 * buffer */
1527 ALIGN_POINTER(pStubMsg->Buffer, 4);
1528 Buffer = pStubMsg->Buffer;
1529 safe_buffer_increment(pStubMsg, 4);
1532 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1534 return NULL;
1537 /***********************************************************************
1538 * NdrPointerBufferSize [RPCRT4.@]
1540 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1541 unsigned char *pMemory,
1542 PFORMAT_STRING pFormat)
1544 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1546 /* Increment the buffer length here instead of in PointerBufferSize,
1547 * as that is used by embedded pointers which already handle the buffer
1548 * length, and shouldn't write anything more to the wire */
1549 if (*pFormat != RPC_FC_RP)
1551 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1552 safe_buffer_length_increment(pStubMsg, 4);
1555 PointerBufferSize(pStubMsg, pMemory, pFormat);
1558 /***********************************************************************
1559 * NdrPointerMemorySize [RPCRT4.@]
1561 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1562 PFORMAT_STRING pFormat)
1564 unsigned char *Buffer = pStubMsg->Buffer;
1565 if (*pFormat != RPC_FC_RP)
1567 ALIGN_POINTER(pStubMsg->Buffer, 4);
1568 safe_buffer_increment(pStubMsg, 4);
1570 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
1571 return PointerMemorySize(pStubMsg, Buffer, pFormat);
1574 /***********************************************************************
1575 * NdrPointerFree [RPCRT4.@]
1577 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1578 unsigned char *pMemory,
1579 PFORMAT_STRING pFormat)
1581 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1582 PointerFree(pStubMsg, pMemory, pFormat);
1585 /***********************************************************************
1586 * NdrSimpleTypeMarshall [RPCRT4.@]
1588 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1589 unsigned char FormatChar )
1591 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1594 /***********************************************************************
1595 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1597 * Unmarshall a base type.
1599 * NOTES
1600 * Doesn't check that the buffer is long enough before copying, so the caller
1601 * should do this.
1603 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1604 unsigned char FormatChar )
1606 #define BASE_TYPE_UNMARSHALL(type) \
1607 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
1608 TRACE("pMemory: %p\n", pMemory); \
1609 *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1610 pStubMsg->Buffer += sizeof(type);
1612 switch(FormatChar)
1614 case RPC_FC_BYTE:
1615 case RPC_FC_CHAR:
1616 case RPC_FC_SMALL:
1617 case RPC_FC_USMALL:
1618 BASE_TYPE_UNMARSHALL(UCHAR);
1619 TRACE("value: 0x%02x\n", *pMemory);
1620 break;
1621 case RPC_FC_WCHAR:
1622 case RPC_FC_SHORT:
1623 case RPC_FC_USHORT:
1624 BASE_TYPE_UNMARSHALL(USHORT);
1625 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1626 break;
1627 case RPC_FC_LONG:
1628 case RPC_FC_ULONG:
1629 case RPC_FC_ERROR_STATUS_T:
1630 case RPC_FC_ENUM32:
1631 BASE_TYPE_UNMARSHALL(ULONG);
1632 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1633 break;
1634 case RPC_FC_FLOAT:
1635 BASE_TYPE_UNMARSHALL(float);
1636 TRACE("value: %f\n", *(float *)pMemory);
1637 break;
1638 case RPC_FC_DOUBLE:
1639 BASE_TYPE_UNMARSHALL(double);
1640 TRACE("value: %f\n", *(double *)pMemory);
1641 break;
1642 case RPC_FC_HYPER:
1643 BASE_TYPE_UNMARSHALL(ULONGLONG);
1644 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1645 break;
1646 case RPC_FC_ENUM16:
1647 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
1648 TRACE("pMemory: %p\n", pMemory);
1649 /* 16-bits on the wire, but int in memory */
1650 *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1651 pStubMsg->Buffer += sizeof(USHORT);
1652 TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1653 break;
1654 case RPC_FC_IGNORE:
1655 break;
1656 default:
1657 FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1659 #undef BASE_TYPE_UNMARSHALL
1662 /***********************************************************************
1663 * NdrSimpleStructMarshall [RPCRT4.@]
1665 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1666 unsigned char *pMemory,
1667 PFORMAT_STRING pFormat)
1669 unsigned size = *(const WORD*)(pFormat+2);
1670 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1672 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
1674 pStubMsg->BufferMark = pStubMsg->Buffer;
1675 safe_copy_to_buffer(pStubMsg, pMemory, size);
1677 if (pFormat[0] != RPC_FC_STRUCT)
1678 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1680 return NULL;
1683 /***********************************************************************
1684 * NdrSimpleStructUnmarshall [RPCRT4.@]
1686 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1687 unsigned char **ppMemory,
1688 PFORMAT_STRING pFormat,
1689 unsigned char fMustAlloc)
1691 unsigned size = *(const WORD*)(pFormat+2);
1692 unsigned char *saved_buffer;
1693 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1695 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1697 if (fMustAlloc)
1698 *ppMemory = NdrAllocate(pStubMsg, size);
1699 else
1701 if (!pStubMsg->IsClient && !*ppMemory)
1702 /* for servers, we just point straight into the RPC buffer */
1703 *ppMemory = pStubMsg->Buffer;
1706 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1707 safe_buffer_increment(pStubMsg, size);
1708 if (pFormat[0] == RPC_FC_PSTRUCT)
1709 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1711 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1712 if (*ppMemory != saved_buffer)
1713 memcpy(*ppMemory, saved_buffer, size);
1715 return NULL;
1718 /***********************************************************************
1719 * NdrSimpleStructBufferSize [RPCRT4.@]
1721 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1722 unsigned char *pMemory,
1723 PFORMAT_STRING pFormat)
1725 unsigned size = *(const WORD*)(pFormat+2);
1726 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1728 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1730 safe_buffer_length_increment(pStubMsg, size);
1731 if (pFormat[0] != RPC_FC_STRUCT)
1732 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1735 /***********************************************************************
1736 * NdrSimpleStructMemorySize [RPCRT4.@]
1738 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1739 PFORMAT_STRING pFormat)
1741 unsigned short size = *(const WORD *)(pFormat+2);
1743 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1745 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1746 pStubMsg->MemorySize += size;
1747 safe_buffer_increment(pStubMsg, size);
1749 if (pFormat[0] != RPC_FC_STRUCT)
1750 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1751 return pStubMsg->MemorySize;
1754 /***********************************************************************
1755 * NdrSimpleStructFree [RPCRT4.@]
1757 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1758 unsigned char *pMemory,
1759 PFORMAT_STRING pFormat)
1761 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1762 if (pFormat[0] != RPC_FC_STRUCT)
1763 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1766 /* Array helpers */
1768 static inline void array_compute_and_size_conformance(
1769 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1770 PFORMAT_STRING pFormat)
1772 switch (fc)
1774 case RPC_FC_CARRAY:
1775 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1776 SizeConformance(pStubMsg);
1777 break;
1778 case RPC_FC_CVARRAY:
1779 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1780 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1781 SizeConformance(pStubMsg);
1782 break;
1783 case RPC_FC_C_CSTRING:
1784 case RPC_FC_C_WSTRING:
1785 if (fc == RPC_FC_C_CSTRING)
1787 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1788 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1790 else
1792 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1793 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1796 if (pFormat[1] == RPC_FC_STRING_SIZED)
1797 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1798 else
1799 pStubMsg->MaxCount = pStubMsg->ActualCount;
1801 SizeConformance(pStubMsg);
1802 break;
1803 default:
1804 ERR("unknown array format 0x%x\n", fc);
1805 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1809 static inline void array_buffer_size(
1810 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1811 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1813 DWORD size;
1814 DWORD esize;
1815 unsigned char alignment;
1817 switch (fc)
1819 case RPC_FC_CARRAY:
1820 esize = *(const WORD*)(pFormat+2);
1821 alignment = pFormat[1] + 1;
1823 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1825 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1827 size = safe_multiply(esize, pStubMsg->MaxCount);
1828 /* conformance value plus array */
1829 safe_buffer_length_increment(pStubMsg, size);
1831 if (fHasPointers)
1832 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1833 break;
1834 case RPC_FC_CVARRAY:
1835 esize = *(const WORD*)(pFormat+2);
1836 alignment = pFormat[1] + 1;
1838 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1839 pFormat = SkipConformance(pStubMsg, pFormat);
1841 SizeVariance(pStubMsg);
1843 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
1845 size = safe_multiply(esize, pStubMsg->ActualCount);
1846 safe_buffer_length_increment(pStubMsg, size);
1848 if (fHasPointers)
1849 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1850 break;
1851 case RPC_FC_C_CSTRING:
1852 case RPC_FC_C_WSTRING:
1853 if (fc == RPC_FC_C_CSTRING)
1854 esize = 1;
1855 else
1856 esize = 2;
1858 SizeVariance(pStubMsg);
1860 size = safe_multiply(esize, pStubMsg->ActualCount);
1861 safe_buffer_length_increment(pStubMsg, size);
1862 break;
1863 default:
1864 ERR("unknown array format 0x%x\n", fc);
1865 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1869 static inline void array_compute_and_write_conformance(
1870 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1871 PFORMAT_STRING pFormat)
1873 switch (fc)
1875 case RPC_FC_CARRAY:
1876 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1877 WriteConformance(pStubMsg);
1878 break;
1879 case RPC_FC_CVARRAY:
1880 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1881 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1882 WriteConformance(pStubMsg);
1883 break;
1884 case RPC_FC_C_CSTRING:
1885 case RPC_FC_C_WSTRING:
1886 if (fc == RPC_FC_C_CSTRING)
1888 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1889 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1891 else
1893 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1894 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1896 if (pFormat[1] == RPC_FC_STRING_SIZED)
1897 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1898 else
1899 pStubMsg->MaxCount = pStubMsg->ActualCount;
1900 pStubMsg->Offset = 0;
1901 WriteConformance(pStubMsg);
1902 break;
1903 default:
1904 ERR("unknown array format 0x%x\n", fc);
1905 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1909 static inline void array_write_variance_and_marshall(
1910 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1911 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1913 DWORD size;
1914 DWORD esize;
1915 unsigned char alignment;
1917 switch (fc)
1919 case RPC_FC_CARRAY:
1920 esize = *(const WORD*)(pFormat+2);
1921 alignment = pFormat[1] + 1;
1923 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1925 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1927 size = safe_multiply(esize, pStubMsg->MaxCount);
1928 if (fHasPointers)
1929 pStubMsg->BufferMark = pStubMsg->Buffer;
1930 safe_copy_to_buffer(pStubMsg, pMemory, size);
1932 if (fHasPointers)
1933 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1934 break;
1935 case RPC_FC_CVARRAY:
1936 esize = *(const WORD*)(pFormat+2);
1937 alignment = pFormat[1] + 1;
1939 /* conformance */
1940 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1941 /* variance */
1942 pFormat = SkipConformance(pStubMsg, pFormat);
1944 WriteVariance(pStubMsg);
1946 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
1948 size = safe_multiply(esize, pStubMsg->ActualCount);
1950 if (fHasPointers)
1951 pStubMsg->BufferMark = pStubMsg->Buffer;
1952 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
1954 if (fHasPointers)
1955 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1956 break;
1957 case RPC_FC_C_CSTRING:
1958 case RPC_FC_C_WSTRING:
1959 if (fc == RPC_FC_C_CSTRING)
1960 esize = 1;
1961 else
1962 esize = 2;
1964 WriteVariance(pStubMsg);
1966 size = safe_multiply(esize, pStubMsg->ActualCount);
1967 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
1968 break;
1969 default:
1970 ERR("unknown array format 0x%x\n", fc);
1971 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1975 static inline ULONG array_read_conformance(
1976 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
1978 DWORD esize;
1980 switch (fc)
1982 case RPC_FC_CARRAY:
1983 esize = *(const WORD*)(pFormat+2);
1984 pFormat = ReadConformance(pStubMsg, pFormat+4);
1985 return safe_multiply(esize, pStubMsg->MaxCount);
1986 case RPC_FC_CVARRAY:
1987 esize = *(const WORD*)(pFormat+2);
1988 pFormat = ReadConformance(pStubMsg, pFormat+4);
1989 return safe_multiply(esize, pStubMsg->MaxCount);
1990 case RPC_FC_C_CSTRING:
1991 case RPC_FC_C_WSTRING:
1992 if (fc == RPC_FC_C_CSTRING)
1993 esize = 1;
1994 else
1995 esize = 2;
1997 if (pFormat[1] == RPC_FC_STRING_SIZED)
1998 ReadConformance(pStubMsg, pFormat + 2);
1999 else
2000 ReadConformance(pStubMsg, NULL);
2001 return safe_multiply(esize, pStubMsg->MaxCount);
2002 default:
2003 ERR("unknown array format 0x%x\n", fc);
2004 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2008 static inline ULONG array_read_variance_and_unmarshall(
2009 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
2010 PFORMAT_STRING pFormat, unsigned char fMustAlloc,
2011 unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
2013 ULONG bufsize, memsize;
2014 WORD esize;
2015 unsigned char alignment;
2016 unsigned char *saved_buffer;
2017 ULONG offset;
2019 switch (fc)
2021 case RPC_FC_CARRAY:
2022 esize = *(const WORD*)(pFormat+2);
2023 alignment = pFormat[1] + 1;
2025 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2027 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2029 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2031 if (fUnmarshall)
2033 if (fMustAlloc)
2034 *ppMemory = NdrAllocate(pStubMsg, memsize);
2035 else
2037 if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2038 /* for servers, we just point straight into the RPC buffer */
2039 *ppMemory = pStubMsg->Buffer;
2042 saved_buffer = pStubMsg->Buffer;
2043 safe_buffer_increment(pStubMsg, bufsize);
2045 pStubMsg->BufferMark = saved_buffer;
2046 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2048 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2049 if (*ppMemory != saved_buffer)
2050 memcpy(*ppMemory, saved_buffer, bufsize);
2052 return bufsize;
2053 case RPC_FC_CVARRAY:
2054 esize = *(const WORD*)(pFormat+2);
2055 alignment = pFormat[1] + 1;
2057 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2059 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2061 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2063 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2064 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2066 if (fUnmarshall)
2068 offset = pStubMsg->Offset;
2070 if (!fMustAlloc && !*ppMemory)
2071 fMustAlloc = TRUE;
2072 if (fMustAlloc)
2073 *ppMemory = NdrAllocate(pStubMsg, memsize);
2074 saved_buffer = pStubMsg->Buffer;
2075 safe_buffer_increment(pStubMsg, bufsize);
2077 pStubMsg->BufferMark = saved_buffer;
2078 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2079 fMustAlloc);
2081 memcpy(*ppMemory + offset, saved_buffer, bufsize);
2083 return bufsize;
2084 case RPC_FC_C_CSTRING:
2085 case RPC_FC_C_WSTRING:
2086 if (fc == RPC_FC_C_CSTRING)
2087 esize = 1;
2088 else
2089 esize = 2;
2091 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2093 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2095 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2096 pStubMsg->ActualCount, pStubMsg->MaxCount);
2097 RpcRaiseException(RPC_S_INVALID_BOUND);
2099 if (pStubMsg->Offset)
2101 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2102 RpcRaiseException(RPC_S_INVALID_BOUND);
2105 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2106 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2108 validate_string_data(pStubMsg, bufsize, esize);
2110 if (fUnmarshall)
2112 if (fMustAlloc)
2113 *ppMemory = NdrAllocate(pStubMsg, memsize);
2114 else
2116 if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2117 !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2118 /* if the data in the RPC buffer is big enough, we just point
2119 * straight into it */
2120 *ppMemory = pStubMsg->Buffer;
2121 else if (!*ppMemory)
2122 *ppMemory = NdrAllocate(pStubMsg, memsize);
2125 if (*ppMemory == pStubMsg->Buffer)
2126 safe_buffer_increment(pStubMsg, bufsize);
2127 else
2128 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2130 if (*pFormat == RPC_FC_C_CSTRING)
2131 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2132 else
2133 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2135 return bufsize;
2136 default:
2137 ERR("unknown array format 0x%x\n", fc);
2138 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2142 static inline void array_memory_size(
2143 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2144 unsigned char fHasPointers)
2146 ULONG bufsize, memsize;
2147 DWORD esize;
2148 unsigned char alignment;
2150 switch (fc)
2152 case RPC_FC_CARRAY:
2153 esize = *(const WORD*)(pFormat+2);
2154 alignment = pFormat[1] + 1;
2156 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2158 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2159 pStubMsg->MemorySize += memsize;
2161 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2162 if (fHasPointers)
2163 pStubMsg->BufferMark = pStubMsg->Buffer;
2164 safe_buffer_increment(pStubMsg, bufsize);
2166 if (fHasPointers)
2167 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2168 break;
2169 case RPC_FC_CVARRAY:
2170 esize = *(const WORD*)(pFormat+2);
2171 alignment = pFormat[1] + 1;
2173 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2175 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2177 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2178 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2179 pStubMsg->MemorySize += memsize;
2181 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2182 if (fHasPointers)
2183 pStubMsg->BufferMark = pStubMsg->Buffer;
2184 safe_buffer_increment(pStubMsg, bufsize);
2186 if (fHasPointers)
2187 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2188 break;
2189 case RPC_FC_C_CSTRING:
2190 case RPC_FC_C_WSTRING:
2191 if (fc == RPC_FC_C_CSTRING)
2192 esize = 1;
2193 else
2194 esize = 2;
2196 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2198 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2200 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2201 pStubMsg->ActualCount, pStubMsg->MaxCount);
2202 RpcRaiseException(RPC_S_INVALID_BOUND);
2204 if (pStubMsg->Offset)
2206 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2207 RpcRaiseException(RPC_S_INVALID_BOUND);
2210 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2211 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2213 validate_string_data(pStubMsg, bufsize, esize);
2215 safe_buffer_increment(pStubMsg, bufsize);
2216 pStubMsg->MemorySize += memsize;
2217 break;
2218 default:
2219 ERR("unknown array format 0x%x\n", fc);
2220 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2224 static inline void array_free(
2225 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2226 unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2228 switch (fc)
2230 case RPC_FC_CARRAY:
2231 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2232 if (fHasPointers)
2233 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2234 break;
2235 case RPC_FC_CVARRAY:
2236 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2237 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2238 if (fHasPointers)
2239 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2240 break;
2241 case RPC_FC_C_CSTRING:
2242 case RPC_FC_C_WSTRING:
2243 /* No embedded pointers so nothing to do */
2244 break;
2245 default:
2246 ERR("unknown array format 0x%x\n", fc);
2247 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2252 * NdrConformantString:
2254 * What MS calls a ConformantString is, in DCE terminology,
2255 * a Varying-Conformant String.
2257 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2258 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
2259 * into unmarshalled string)
2260 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2262 * data: CHARTYPE[maxlen]
2264 * ], where CHARTYPE is the appropriate character type (specified externally)
2268 /***********************************************************************
2269 * NdrConformantStringMarshall [RPCRT4.@]
2271 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
2272 unsigned char *pszMessage, PFORMAT_STRING pFormat)
2274 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2276 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2277 ERR("Unhandled string type: %#x\n", pFormat[0]);
2278 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2281 /* allow compiler to optimise inline function by passing constant into
2282 * these functions */
2283 if (pFormat[0] == RPC_FC_C_CSTRING) {
2284 array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2285 pFormat);
2286 array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2287 pFormat, TRUE /* fHasPointers */);
2288 } else {
2289 array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2290 pFormat);
2291 array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2292 pFormat, TRUE /* fHasPointers */);
2295 return NULL;
2298 /***********************************************************************
2299 * NdrConformantStringBufferSize [RPCRT4.@]
2301 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2302 unsigned char* pMemory, PFORMAT_STRING pFormat)
2304 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2306 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2307 ERR("Unhandled string type: %#x\n", pFormat[0]);
2308 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2311 /* allow compiler to optimise inline function by passing constant into
2312 * these functions */
2313 if (pFormat[0] == RPC_FC_C_CSTRING) {
2314 array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory,
2315 pFormat);
2316 array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2317 TRUE /* fHasPointers */);
2318 } else {
2319 array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory,
2320 pFormat);
2321 array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2322 TRUE /* fHasPointers */);
2326 /************************************************************************
2327 * NdrConformantStringMemorySize [RPCRT4.@]
2329 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2330 PFORMAT_STRING pFormat )
2332 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2334 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2335 ERR("Unhandled string type: %#x\n", pFormat[0]);
2336 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2339 /* allow compiler to optimise inline function by passing constant into
2340 * these functions */
2341 if (pFormat[0] == RPC_FC_C_CSTRING) {
2342 array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2343 array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat,
2344 TRUE /* fHasPointers */);
2345 } else {
2346 array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2347 array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat,
2348 TRUE /* fHasPointers */);
2351 return pStubMsg->MemorySize;
2354 /************************************************************************
2355 * NdrConformantStringUnmarshall [RPCRT4.@]
2357 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2358 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2360 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2361 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2363 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2364 ERR("Unhandled string type: %#x\n", *pFormat);
2365 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2368 /* allow compiler to optimise inline function by passing constant into
2369 * these functions */
2370 if (pFormat[0] == RPC_FC_C_CSTRING) {
2371 array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2372 array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory,
2373 pFormat, fMustAlloc,
2374 TRUE /* fUseBufferMemoryServer */,
2375 TRUE /* fUnmarshall */);
2376 } else {
2377 array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2378 array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory,
2379 pFormat, fMustAlloc,
2380 TRUE /* fUseBufferMemoryServer */,
2381 TRUE /* fUnmarshall */);
2384 return NULL;
2387 /***********************************************************************
2388 * NdrNonConformantStringMarshall [RPCRT4.@]
2390 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2391 unsigned char *pMemory,
2392 PFORMAT_STRING pFormat)
2394 ULONG esize, size, maxsize;
2396 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2398 maxsize = *(USHORT *)&pFormat[2];
2400 if (*pFormat == RPC_FC_CSTRING)
2402 ULONG i;
2403 const char *str = (const char *)pMemory;
2404 for (i = 0; i < maxsize && *str; i++, str++)
2406 TRACE("string=%s\n", debugstr_an(str, i));
2407 pStubMsg->ActualCount = i + 1;
2408 esize = 1;
2410 else if (*pFormat == RPC_FC_WSTRING)
2412 ULONG i;
2413 const WCHAR *str = (const WCHAR *)pMemory;
2414 for (i = 0; i < maxsize && *str; i++, str++)
2416 TRACE("string=%s\n", debugstr_wn(str, i));
2417 pStubMsg->ActualCount = i + 1;
2418 esize = 2;
2420 else
2422 ERR("Unhandled string type: %#x\n", *pFormat);
2423 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2426 pStubMsg->Offset = 0;
2427 WriteVariance(pStubMsg);
2429 size = safe_multiply(esize, pStubMsg->ActualCount);
2430 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2432 return NULL;
2435 /***********************************************************************
2436 * NdrNonConformantStringUnmarshall [RPCRT4.@]
2438 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2439 unsigned char **ppMemory,
2440 PFORMAT_STRING pFormat,
2441 unsigned char fMustAlloc)
2443 ULONG bufsize, memsize, esize, maxsize;
2445 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2446 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2448 maxsize = *(USHORT *)&pFormat[2];
2450 ReadVariance(pStubMsg, NULL, maxsize);
2451 if (pStubMsg->Offset)
2453 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2454 RpcRaiseException(RPC_S_INVALID_BOUND);
2457 if (*pFormat == RPC_FC_CSTRING) esize = 1;
2458 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2459 else
2461 ERR("Unhandled string type: %#x\n", *pFormat);
2462 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2465 memsize = esize * maxsize;
2466 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2468 validate_string_data(pStubMsg, bufsize, esize);
2470 if (!fMustAlloc && !*ppMemory)
2471 fMustAlloc = TRUE;
2472 if (fMustAlloc)
2473 *ppMemory = NdrAllocate(pStubMsg, memsize);
2475 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2477 if (*pFormat == RPC_FC_CSTRING) {
2478 TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2480 else if (*pFormat == RPC_FC_WSTRING) {
2481 TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2484 return NULL;
2487 /***********************************************************************
2488 * NdrNonConformantStringBufferSize [RPCRT4.@]
2490 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2491 unsigned char *pMemory,
2492 PFORMAT_STRING pFormat)
2494 ULONG esize, maxsize;
2496 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2498 maxsize = *(USHORT *)&pFormat[2];
2500 SizeVariance(pStubMsg);
2502 if (*pFormat == RPC_FC_CSTRING)
2504 ULONG i;
2505 const char *str = (const char *)pMemory;
2506 for (i = 0; i < maxsize && *str; i++, str++)
2508 TRACE("string=%s\n", debugstr_an(str, i));
2509 pStubMsg->ActualCount = i + 1;
2510 esize = 1;
2512 else if (*pFormat == RPC_FC_WSTRING)
2514 ULONG i;
2515 const WCHAR *str = (const WCHAR *)pMemory;
2516 for (i = 0; i < maxsize && *str; i++, str++)
2518 TRACE("string=%s\n", debugstr_wn(str, i));
2519 pStubMsg->ActualCount = i + 1;
2520 esize = 2;
2522 else
2524 ERR("Unhandled string type: %#x\n", *pFormat);
2525 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2528 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2531 /***********************************************************************
2532 * NdrNonConformantStringMemorySize [RPCRT4.@]
2534 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2535 PFORMAT_STRING pFormat)
2537 ULONG bufsize, memsize, esize, maxsize;
2539 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2541 maxsize = *(USHORT *)&pFormat[2];
2543 ReadVariance(pStubMsg, NULL, maxsize);
2545 if (pStubMsg->Offset)
2547 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2548 RpcRaiseException(RPC_S_INVALID_BOUND);
2551 if (*pFormat == RPC_FC_CSTRING) esize = 1;
2552 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2553 else
2555 ERR("Unhandled string type: %#x\n", *pFormat);
2556 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2559 memsize = esize * maxsize;
2560 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2562 validate_string_data(pStubMsg, bufsize, esize);
2564 safe_buffer_increment(pStubMsg, bufsize);
2565 pStubMsg->MemorySize += memsize;
2567 return pStubMsg->MemorySize;
2570 /* Complex types */
2572 #include "pshpack1.h"
2573 typedef struct
2575 unsigned char type;
2576 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2577 ULONG low_value;
2578 ULONG high_value;
2579 } NDR_RANGE;
2580 #include "poppack.h"
2582 static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2583 PFORMAT_STRING pFormat)
2585 switch (*pFormat) {
2586 case RPC_FC_STRUCT:
2587 case RPC_FC_PSTRUCT:
2588 case RPC_FC_CSTRUCT:
2589 case RPC_FC_BOGUS_STRUCT:
2590 case RPC_FC_SMFARRAY:
2591 case RPC_FC_SMVARRAY:
2592 case RPC_FC_CSTRING:
2593 return *(const WORD*)&pFormat[2];
2594 case RPC_FC_USER_MARSHAL:
2595 return *(const WORD*)&pFormat[4];
2596 case RPC_FC_RANGE: {
2597 switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2598 case RPC_FC_BYTE:
2599 case RPC_FC_CHAR:
2600 case RPC_FC_SMALL:
2601 case RPC_FC_USMALL:
2602 return sizeof(UCHAR);
2603 case RPC_FC_WCHAR:
2604 case RPC_FC_SHORT:
2605 case RPC_FC_USHORT:
2606 return sizeof(USHORT);
2607 case RPC_FC_LONG:
2608 case RPC_FC_ULONG:
2609 case RPC_FC_ENUM32:
2610 return sizeof(ULONG);
2611 case RPC_FC_FLOAT:
2612 return sizeof(float);
2613 case RPC_FC_DOUBLE:
2614 return sizeof(double);
2615 case RPC_FC_HYPER:
2616 return sizeof(ULONGLONG);
2617 case RPC_FC_ENUM16:
2618 return sizeof(UINT);
2619 default:
2620 ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2621 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2624 case RPC_FC_NON_ENCAPSULATED_UNION:
2625 pFormat += 2;
2626 if (pStubMsg->fHasNewCorrDesc)
2627 pFormat += 6;
2628 else
2629 pFormat += 4;
2631 pFormat += *(const SHORT*)pFormat;
2632 return *(const SHORT*)pFormat;
2633 case RPC_FC_IP:
2634 return sizeof(void *);
2635 case RPC_FC_WSTRING:
2636 return *(const WORD*)&pFormat[2] * 2;
2637 default:
2638 FIXME("unhandled embedded type %02x\n", *pFormat);
2640 return 0;
2644 static ULONG EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2645 PFORMAT_STRING pFormat)
2647 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2649 if (!m)
2651 FIXME("no memorysizer for data type=%02x\n", *pFormat);
2652 return 0;
2655 return m(pStubMsg, pFormat);
2659 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2660 unsigned char *pMemory,
2661 PFORMAT_STRING pFormat,
2662 PFORMAT_STRING pPointer)
2664 PFORMAT_STRING desc;
2665 NDR_MARSHALL m;
2666 ULONG size;
2668 while (*pFormat != RPC_FC_END) {
2669 switch (*pFormat) {
2670 case RPC_FC_BYTE:
2671 case RPC_FC_CHAR:
2672 case RPC_FC_SMALL:
2673 case RPC_FC_USMALL:
2674 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2675 safe_copy_to_buffer(pStubMsg, pMemory, 1);
2676 pMemory += 1;
2677 break;
2678 case RPC_FC_WCHAR:
2679 case RPC_FC_SHORT:
2680 case RPC_FC_USHORT:
2681 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2682 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2683 pMemory += 2;
2684 break;
2685 case RPC_FC_ENUM16:
2686 TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2687 if (32767 < *(DWORD*)pMemory)
2688 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2689 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2690 pMemory += 4;
2691 break;
2692 case RPC_FC_LONG:
2693 case RPC_FC_ULONG:
2694 case RPC_FC_ENUM32:
2695 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2696 safe_copy_to_buffer(pStubMsg, pMemory, 4);
2697 pMemory += 4;
2698 break;
2699 case RPC_FC_FLOAT:
2700 TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
2701 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
2702 pMemory += sizeof(float);
2703 break;
2704 case RPC_FC_HYPER:
2705 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2706 safe_copy_to_buffer(pStubMsg, pMemory, 8);
2707 pMemory += 8;
2708 break;
2709 case RPC_FC_DOUBLE:
2710 TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
2711 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
2712 pMemory += sizeof(double);
2713 break;
2714 case RPC_FC_POINTER:
2716 unsigned char *saved_buffer;
2717 int pointer_buffer_mark_set = 0;
2718 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2719 TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2720 if (*pPointer != RPC_FC_RP)
2721 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2722 saved_buffer = pStubMsg->Buffer;
2723 if (pStubMsg->PointerBufferMark)
2725 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2726 pStubMsg->PointerBufferMark = NULL;
2727 pointer_buffer_mark_set = 1;
2729 else if (*pPointer != RPC_FC_RP)
2730 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2731 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2732 if (pointer_buffer_mark_set)
2734 STD_OVERFLOW_CHECK(pStubMsg);
2735 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2736 pStubMsg->Buffer = saved_buffer;
2737 if (*pPointer != RPC_FC_RP)
2738 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2740 TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2741 pPointer += 4;
2742 pMemory += sizeof(void *);
2743 break;
2745 case RPC_FC_ALIGNM2:
2746 ALIGN_POINTER(pMemory, 2);
2747 break;
2748 case RPC_FC_ALIGNM4:
2749 ALIGN_POINTER(pMemory, 4);
2750 break;
2751 case RPC_FC_ALIGNM8:
2752 ALIGN_POINTER(pMemory, 8);
2753 break;
2754 case RPC_FC_STRUCTPAD1:
2755 case RPC_FC_STRUCTPAD2:
2756 case RPC_FC_STRUCTPAD3:
2757 case RPC_FC_STRUCTPAD4:
2758 case RPC_FC_STRUCTPAD5:
2759 case RPC_FC_STRUCTPAD6:
2760 case RPC_FC_STRUCTPAD7:
2761 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2762 break;
2763 case RPC_FC_EMBEDDED_COMPLEX:
2764 pMemory += pFormat[1];
2765 pFormat += 2;
2766 desc = pFormat + *(const SHORT*)pFormat;
2767 size = EmbeddedComplexSize(pStubMsg, desc);
2768 TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2769 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2770 if (m)
2772 /* for some reason interface pointers aren't generated as
2773 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2774 * they still need the derefencing treatment that pointers are
2775 * given */
2776 if (*desc == RPC_FC_IP)
2777 m(pStubMsg, *(unsigned char **)pMemory, desc);
2778 else
2779 m(pStubMsg, pMemory, desc);
2781 else FIXME("no marshaller for embedded type %02x\n", *desc);
2782 pMemory += size;
2783 pFormat += 2;
2784 continue;
2785 case RPC_FC_PAD:
2786 break;
2787 default:
2788 FIXME("unhandled format 0x%02x\n", *pFormat);
2790 pFormat++;
2793 return pMemory;
2796 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2797 unsigned char *pMemory,
2798 PFORMAT_STRING pFormat,
2799 PFORMAT_STRING pPointer,
2800 unsigned char fMustAlloc)
2802 PFORMAT_STRING desc;
2803 NDR_UNMARSHALL m;
2804 ULONG size;
2806 while (*pFormat != RPC_FC_END) {
2807 switch (*pFormat) {
2808 case RPC_FC_BYTE:
2809 case RPC_FC_CHAR:
2810 case RPC_FC_SMALL:
2811 case RPC_FC_USMALL:
2812 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2813 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2814 pMemory += 1;
2815 break;
2816 case RPC_FC_WCHAR:
2817 case RPC_FC_SHORT:
2818 case RPC_FC_USHORT:
2819 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2820 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2821 pMemory += 2;
2822 break;
2823 case RPC_FC_ENUM16:
2824 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2825 *(DWORD*)pMemory &= 0xffff;
2826 TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2827 if (32767 < *(DWORD*)pMemory)
2828 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2829 pMemory += 4;
2830 break;
2831 case RPC_FC_LONG:
2832 case RPC_FC_ULONG:
2833 case RPC_FC_ENUM32:
2834 safe_copy_from_buffer(pStubMsg, pMemory, 4);
2835 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2836 pMemory += 4;
2837 break;
2838 case RPC_FC_FLOAT:
2839 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
2840 TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
2841 pMemory += sizeof(float);
2842 break;
2843 case RPC_FC_HYPER:
2844 safe_copy_from_buffer(pStubMsg, pMemory, 8);
2845 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2846 pMemory += 8;
2847 break;
2848 case RPC_FC_DOUBLE:
2849 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
2850 TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
2851 pMemory += sizeof(double);
2852 break;
2853 case RPC_FC_POINTER:
2855 unsigned char *saved_buffer;
2856 int pointer_buffer_mark_set = 0;
2857 TRACE("pointer => %p\n", pMemory);
2858 if (*pPointer != RPC_FC_RP)
2859 ALIGN_POINTER(pStubMsg->Buffer, 4);
2860 saved_buffer = pStubMsg->Buffer;
2861 if (pStubMsg->PointerBufferMark)
2863 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2864 pStubMsg->PointerBufferMark = NULL;
2865 pointer_buffer_mark_set = 1;
2867 else if (*pPointer != RPC_FC_RP)
2868 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2870 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
2871 if (pointer_buffer_mark_set)
2873 STD_OVERFLOW_CHECK(pStubMsg);
2874 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2875 pStubMsg->Buffer = saved_buffer;
2876 if (*pPointer != RPC_FC_RP)
2877 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2879 pPointer += 4;
2880 pMemory += sizeof(void *);
2881 break;
2883 case RPC_FC_ALIGNM2:
2884 ALIGN_POINTER_CLEAR(pMemory, 2);
2885 break;
2886 case RPC_FC_ALIGNM4:
2887 ALIGN_POINTER_CLEAR(pMemory, 4);
2888 break;
2889 case RPC_FC_ALIGNM8:
2890 ALIGN_POINTER_CLEAR(pMemory, 8);
2891 break;
2892 case RPC_FC_STRUCTPAD1:
2893 case RPC_FC_STRUCTPAD2:
2894 case RPC_FC_STRUCTPAD3:
2895 case RPC_FC_STRUCTPAD4:
2896 case RPC_FC_STRUCTPAD5:
2897 case RPC_FC_STRUCTPAD6:
2898 case RPC_FC_STRUCTPAD7:
2899 memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2900 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2901 break;
2902 case RPC_FC_EMBEDDED_COMPLEX:
2903 pMemory += pFormat[1];
2904 pFormat += 2;
2905 desc = pFormat + *(const SHORT*)pFormat;
2906 size = EmbeddedComplexSize(pStubMsg, desc);
2907 TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
2908 if (fMustAlloc)
2909 /* we can't pass fMustAlloc=TRUE into the marshaller for this type
2910 * since the type is part of the memory block that is encompassed by
2911 * the whole complex type. Memory is forced to allocate when pointers
2912 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
2913 * clearing the memory we pass in to the unmarshaller */
2914 memset(pMemory, 0, size);
2915 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2916 if (m)
2918 /* for some reason interface pointers aren't generated as
2919 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2920 * they still need the derefencing treatment that pointers are
2921 * given */
2922 if (*desc == RPC_FC_IP)
2923 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2924 else
2925 m(pStubMsg, &pMemory, desc, FALSE);
2927 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2928 pMemory += size;
2929 pFormat += 2;
2930 continue;
2931 case RPC_FC_PAD:
2932 break;
2933 default:
2934 FIXME("unhandled format %d\n", *pFormat);
2936 pFormat++;
2939 return pMemory;
2942 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2943 unsigned char *pMemory,
2944 PFORMAT_STRING pFormat,
2945 PFORMAT_STRING pPointer)
2947 PFORMAT_STRING desc;
2948 NDR_BUFFERSIZE m;
2949 ULONG size;
2951 while (*pFormat != RPC_FC_END) {
2952 switch (*pFormat) {
2953 case RPC_FC_BYTE:
2954 case RPC_FC_CHAR:
2955 case RPC_FC_SMALL:
2956 case RPC_FC_USMALL:
2957 safe_buffer_length_increment(pStubMsg, 1);
2958 pMemory += 1;
2959 break;
2960 case RPC_FC_WCHAR:
2961 case RPC_FC_SHORT:
2962 case RPC_FC_USHORT:
2963 safe_buffer_length_increment(pStubMsg, 2);
2964 pMemory += 2;
2965 break;
2966 case RPC_FC_ENUM16:
2967 safe_buffer_length_increment(pStubMsg, 2);
2968 pMemory += 4;
2969 break;
2970 case RPC_FC_LONG:
2971 case RPC_FC_ULONG:
2972 case RPC_FC_ENUM32:
2973 case RPC_FC_FLOAT:
2974 safe_buffer_length_increment(pStubMsg, 4);
2975 pMemory += 4;
2976 break;
2977 case RPC_FC_HYPER:
2978 case RPC_FC_DOUBLE:
2979 safe_buffer_length_increment(pStubMsg, 8);
2980 pMemory += 8;
2981 break;
2982 case RPC_FC_POINTER:
2983 if (!pStubMsg->IgnoreEmbeddedPointers)
2985 int saved_buffer_length = pStubMsg->BufferLength;
2986 pStubMsg->BufferLength = pStubMsg->PointerLength;
2987 pStubMsg->PointerLength = 0;
2988 if(!pStubMsg->BufferLength)
2989 ERR("BufferLength == 0??\n");
2990 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2991 pStubMsg->PointerLength = pStubMsg->BufferLength;
2992 pStubMsg->BufferLength = saved_buffer_length;
2994 if (*pPointer != RPC_FC_RP)
2996 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2997 safe_buffer_length_increment(pStubMsg, 4);
2999 pPointer += 4;
3000 pMemory += sizeof(void*);
3001 break;
3002 case RPC_FC_ALIGNM2:
3003 ALIGN_POINTER(pMemory, 2);
3004 break;
3005 case RPC_FC_ALIGNM4:
3006 ALIGN_POINTER(pMemory, 4);
3007 break;
3008 case RPC_FC_ALIGNM8:
3009 ALIGN_POINTER(pMemory, 8);
3010 break;
3011 case RPC_FC_STRUCTPAD1:
3012 case RPC_FC_STRUCTPAD2:
3013 case RPC_FC_STRUCTPAD3:
3014 case RPC_FC_STRUCTPAD4:
3015 case RPC_FC_STRUCTPAD5:
3016 case RPC_FC_STRUCTPAD6:
3017 case RPC_FC_STRUCTPAD7:
3018 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3019 break;
3020 case RPC_FC_EMBEDDED_COMPLEX:
3021 pMemory += pFormat[1];
3022 pFormat += 2;
3023 desc = pFormat + *(const SHORT*)pFormat;
3024 size = EmbeddedComplexSize(pStubMsg, desc);
3025 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3026 if (m)
3028 /* for some reason interface pointers aren't generated as
3029 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3030 * they still need the derefencing treatment that pointers are
3031 * given */
3032 if (*desc == RPC_FC_IP)
3033 m(pStubMsg, *(unsigned char **)pMemory, desc);
3034 else
3035 m(pStubMsg, pMemory, desc);
3037 else FIXME("no buffersizer for embedded type %02x\n", *desc);
3038 pMemory += size;
3039 pFormat += 2;
3040 continue;
3041 case RPC_FC_PAD:
3042 break;
3043 default:
3044 FIXME("unhandled format 0x%02x\n", *pFormat);
3046 pFormat++;
3049 return pMemory;
3052 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
3053 unsigned char *pMemory,
3054 PFORMAT_STRING pFormat,
3055 PFORMAT_STRING pPointer)
3057 PFORMAT_STRING desc;
3058 NDR_FREE m;
3059 ULONG size;
3061 while (*pFormat != RPC_FC_END) {
3062 switch (*pFormat) {
3063 case RPC_FC_BYTE:
3064 case RPC_FC_CHAR:
3065 case RPC_FC_SMALL:
3066 case RPC_FC_USMALL:
3067 pMemory += 1;
3068 break;
3069 case RPC_FC_WCHAR:
3070 case RPC_FC_SHORT:
3071 case RPC_FC_USHORT:
3072 pMemory += 2;
3073 break;
3074 case RPC_FC_LONG:
3075 case RPC_FC_ULONG:
3076 case RPC_FC_ENUM16:
3077 case RPC_FC_ENUM32:
3078 case RPC_FC_FLOAT:
3079 pMemory += 4;
3080 break;
3081 case RPC_FC_HYPER:
3082 case RPC_FC_DOUBLE:
3083 pMemory += 8;
3084 break;
3085 case RPC_FC_POINTER:
3086 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3087 pPointer += 4;
3088 pMemory += sizeof(void *);
3089 break;
3090 case RPC_FC_ALIGNM2:
3091 ALIGN_POINTER(pMemory, 2);
3092 break;
3093 case RPC_FC_ALIGNM4:
3094 ALIGN_POINTER(pMemory, 4);
3095 break;
3096 case RPC_FC_ALIGNM8:
3097 ALIGN_POINTER(pMemory, 8);
3098 break;
3099 case RPC_FC_STRUCTPAD1:
3100 case RPC_FC_STRUCTPAD2:
3101 case RPC_FC_STRUCTPAD3:
3102 case RPC_FC_STRUCTPAD4:
3103 case RPC_FC_STRUCTPAD5:
3104 case RPC_FC_STRUCTPAD6:
3105 case RPC_FC_STRUCTPAD7:
3106 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3107 break;
3108 case RPC_FC_EMBEDDED_COMPLEX:
3109 pMemory += pFormat[1];
3110 pFormat += 2;
3111 desc = pFormat + *(const SHORT*)pFormat;
3112 size = EmbeddedComplexSize(pStubMsg, desc);
3113 m = NdrFreer[*desc & NDR_TABLE_MASK];
3114 if (m)
3116 /* for some reason interface pointers aren't generated as
3117 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3118 * they still need the derefencing treatment that pointers are
3119 * given */
3120 if (*desc == RPC_FC_IP)
3121 m(pStubMsg, *(unsigned char **)pMemory, desc);
3122 else
3123 m(pStubMsg, pMemory, desc);
3125 pMemory += size;
3126 pFormat += 2;
3127 continue;
3128 case RPC_FC_PAD:
3129 break;
3130 default:
3131 FIXME("unhandled format 0x%02x\n", *pFormat);
3133 pFormat++;
3136 return pMemory;
3139 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3140 PFORMAT_STRING pFormat,
3141 PFORMAT_STRING pPointer)
3143 PFORMAT_STRING desc;
3144 ULONG size = 0;
3146 while (*pFormat != RPC_FC_END) {
3147 switch (*pFormat) {
3148 case RPC_FC_BYTE:
3149 case RPC_FC_CHAR:
3150 case RPC_FC_SMALL:
3151 case RPC_FC_USMALL:
3152 size += 1;
3153 safe_buffer_increment(pStubMsg, 1);
3154 break;
3155 case RPC_FC_WCHAR:
3156 case RPC_FC_SHORT:
3157 case RPC_FC_USHORT:
3158 size += 2;
3159 safe_buffer_increment(pStubMsg, 2);
3160 break;
3161 case RPC_FC_ENUM16:
3162 size += 4;
3163 safe_buffer_increment(pStubMsg, 2);
3164 break;
3165 case RPC_FC_LONG:
3166 case RPC_FC_ULONG:
3167 case RPC_FC_ENUM32:
3168 case RPC_FC_FLOAT:
3169 size += 4;
3170 safe_buffer_increment(pStubMsg, 4);
3171 break;
3172 case RPC_FC_HYPER:
3173 case RPC_FC_DOUBLE:
3174 size += 8;
3175 safe_buffer_increment(pStubMsg, 8);
3176 break;
3177 case RPC_FC_POINTER:
3179 unsigned char *saved_buffer;
3180 int pointer_buffer_mark_set = 0;
3181 if (*pPointer != RPC_FC_RP)
3182 ALIGN_POINTER(pStubMsg->Buffer, 4);
3183 saved_buffer = pStubMsg->Buffer;
3184 if (pStubMsg->PointerBufferMark)
3186 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3187 pStubMsg->PointerBufferMark = NULL;
3188 pointer_buffer_mark_set = 1;
3190 else if (*pPointer != RPC_FC_RP)
3191 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3193 if (!pStubMsg->IgnoreEmbeddedPointers)
3194 PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3195 if (pointer_buffer_mark_set)
3197 STD_OVERFLOW_CHECK(pStubMsg);
3198 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3199 pStubMsg->Buffer = saved_buffer;
3200 if (*pPointer != RPC_FC_RP)
3201 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3203 pPointer += 4;
3204 size += sizeof(void *);
3205 break;
3207 case RPC_FC_ALIGNM2:
3208 ALIGN_LENGTH(size, 2);
3209 break;
3210 case RPC_FC_ALIGNM4:
3211 ALIGN_LENGTH(size, 4);
3212 break;
3213 case RPC_FC_ALIGNM8:
3214 ALIGN_LENGTH(size, 8);
3215 break;
3216 case RPC_FC_STRUCTPAD1:
3217 case RPC_FC_STRUCTPAD2:
3218 case RPC_FC_STRUCTPAD3:
3219 case RPC_FC_STRUCTPAD4:
3220 case RPC_FC_STRUCTPAD5:
3221 case RPC_FC_STRUCTPAD6:
3222 case RPC_FC_STRUCTPAD7:
3223 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3224 break;
3225 case RPC_FC_EMBEDDED_COMPLEX:
3226 size += pFormat[1];
3227 pFormat += 2;
3228 desc = pFormat + *(const SHORT*)pFormat;
3229 size += EmbeddedComplexMemorySize(pStubMsg, desc);
3230 pFormat += 2;
3231 continue;
3232 case RPC_FC_PAD:
3233 break;
3234 default:
3235 FIXME("unhandled format 0x%02x\n", *pFormat);
3237 pFormat++;
3240 return size;
3243 ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
3245 PFORMAT_STRING desc;
3246 ULONG size = 0;
3248 while (*pFormat != RPC_FC_END) {
3249 switch (*pFormat) {
3250 case RPC_FC_BYTE:
3251 case RPC_FC_CHAR:
3252 case RPC_FC_SMALL:
3253 case RPC_FC_USMALL:
3254 size += 1;
3255 break;
3256 case RPC_FC_WCHAR:
3257 case RPC_FC_SHORT:
3258 case RPC_FC_USHORT:
3259 size += 2;
3260 break;
3261 case RPC_FC_LONG:
3262 case RPC_FC_ULONG:
3263 case RPC_FC_ENUM16:
3264 case RPC_FC_ENUM32:
3265 case RPC_FC_FLOAT:
3266 size += 4;
3267 break;
3268 case RPC_FC_HYPER:
3269 case RPC_FC_DOUBLE:
3270 size += 8;
3271 break;
3272 case RPC_FC_POINTER:
3273 size += sizeof(void *);
3274 break;
3275 case RPC_FC_ALIGNM2:
3276 ALIGN_LENGTH(size, 2);
3277 break;
3278 case RPC_FC_ALIGNM4:
3279 ALIGN_LENGTH(size, 4);
3280 break;
3281 case RPC_FC_ALIGNM8:
3282 ALIGN_LENGTH(size, 8);
3283 break;
3284 case RPC_FC_STRUCTPAD1:
3285 case RPC_FC_STRUCTPAD2:
3286 case RPC_FC_STRUCTPAD3:
3287 case RPC_FC_STRUCTPAD4:
3288 case RPC_FC_STRUCTPAD5:
3289 case RPC_FC_STRUCTPAD6:
3290 case RPC_FC_STRUCTPAD7:
3291 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3292 break;
3293 case RPC_FC_EMBEDDED_COMPLEX:
3294 size += pFormat[1];
3295 pFormat += 2;
3296 desc = pFormat + *(const SHORT*)pFormat;
3297 size += EmbeddedComplexSize(pStubMsg, desc);
3298 pFormat += 2;
3299 continue;
3300 case RPC_FC_PAD:
3301 break;
3302 default:
3303 FIXME("unhandled format 0x%02x\n", *pFormat);
3305 pFormat++;
3308 return size;
3311 /***********************************************************************
3312 * NdrComplexStructMarshall [RPCRT4.@]
3314 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3315 unsigned char *pMemory,
3316 PFORMAT_STRING pFormat)
3318 PFORMAT_STRING conf_array = NULL;
3319 PFORMAT_STRING pointer_desc = NULL;
3320 unsigned char *OldMemory = pStubMsg->Memory;
3321 int pointer_buffer_mark_set = 0;
3322 ULONG count = 0;
3323 ULONG max_count = 0;
3324 ULONG offset = 0;
3326 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3328 if (!pStubMsg->PointerBufferMark)
3330 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3331 /* save buffer length */
3332 ULONG saved_buffer_length = pStubMsg->BufferLength;
3334 /* get the buffer pointer after complex array data, but before
3335 * pointer data */
3336 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3337 pStubMsg->IgnoreEmbeddedPointers = 1;
3338 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3339 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3341 /* save it for use by embedded pointer code later */
3342 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3343 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
3344 pointer_buffer_mark_set = 1;
3346 /* restore the original buffer length */
3347 pStubMsg->BufferLength = saved_buffer_length;
3350 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
3352 pFormat += 4;
3353 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3354 pFormat += 2;
3355 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3356 pFormat += 2;
3358 pStubMsg->Memory = pMemory;
3360 if (conf_array)
3362 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3363 array_compute_and_write_conformance(conf_array[0], pStubMsg,
3364 pMemory + struct_size, conf_array);
3365 /* these could be changed in ComplexMarshall so save them for later */
3366 max_count = pStubMsg->MaxCount;
3367 count = pStubMsg->ActualCount;
3368 offset = pStubMsg->Offset;
3371 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3373 if (conf_array)
3375 pStubMsg->MaxCount = max_count;
3376 pStubMsg->ActualCount = count;
3377 pStubMsg->Offset = offset;
3378 array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3379 conf_array, TRUE /* fHasPointers */);
3382 pStubMsg->Memory = OldMemory;
3384 if (pointer_buffer_mark_set)
3386 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3387 pStubMsg->PointerBufferMark = NULL;
3390 STD_OVERFLOW_CHECK(pStubMsg);
3392 return NULL;
3395 /***********************************************************************
3396 * NdrComplexStructUnmarshall [RPCRT4.@]
3398 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3399 unsigned char **ppMemory,
3400 PFORMAT_STRING pFormat,
3401 unsigned char fMustAlloc)
3403 unsigned size = *(const WORD*)(pFormat+2);
3404 PFORMAT_STRING conf_array = NULL;
3405 PFORMAT_STRING pointer_desc = NULL;
3406 unsigned char *pMemory;
3407 int pointer_buffer_mark_set = 0;
3408 ULONG count = 0;
3409 ULONG max_count = 0;
3410 ULONG offset = 0;
3411 ULONG array_size = 0;
3413 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3415 if (!pStubMsg->PointerBufferMark)
3417 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3418 /* save buffer pointer */
3419 unsigned char *saved_buffer = pStubMsg->Buffer;
3421 /* get the buffer pointer after complex array data, but before
3422 * pointer data */
3423 pStubMsg->IgnoreEmbeddedPointers = 1;
3424 NdrComplexStructMemorySize(pStubMsg, pFormat);
3425 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3427 /* save it for use by embedded pointer code later */
3428 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3429 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
3430 pointer_buffer_mark_set = 1;
3432 /* restore the original buffer */
3433 pStubMsg->Buffer = saved_buffer;
3436 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3438 pFormat += 4;
3439 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3440 pFormat += 2;
3441 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3442 pFormat += 2;
3444 if (conf_array)
3446 array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3447 size += array_size;
3449 /* these could be changed in ComplexMarshall so save them for later */
3450 max_count = pStubMsg->MaxCount;
3451 count = pStubMsg->ActualCount;
3452 offset = pStubMsg->Offset;
3455 if (!fMustAlloc && !*ppMemory)
3456 fMustAlloc = TRUE;
3457 if (fMustAlloc)
3458 *ppMemory = NdrAllocate(pStubMsg, size);
3460 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3462 if (conf_array)
3464 pStubMsg->MaxCount = max_count;
3465 pStubMsg->ActualCount = count;
3466 pStubMsg->Offset = offset;
3467 if (fMustAlloc)
3468 memset(pMemory, 0, array_size);
3469 array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3470 conf_array, FALSE,
3471 FALSE /* fUseBufferMemoryServer */,
3472 TRUE /* fUnmarshall */);
3475 if (pointer_buffer_mark_set)
3477 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3478 pStubMsg->PointerBufferMark = NULL;
3481 return NULL;
3484 /***********************************************************************
3485 * NdrComplexStructBufferSize [RPCRT4.@]
3487 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3488 unsigned char *pMemory,
3489 PFORMAT_STRING pFormat)
3491 PFORMAT_STRING conf_array = NULL;
3492 PFORMAT_STRING pointer_desc = NULL;
3493 unsigned char *OldMemory = pStubMsg->Memory;
3494 int pointer_length_set = 0;
3495 ULONG count = 0;
3496 ULONG max_count = 0;
3497 ULONG offset = 0;
3499 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3501 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
3503 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3505 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3506 ULONG saved_buffer_length = pStubMsg->BufferLength;
3508 /* get the buffer length after complex struct data, but before
3509 * pointer data */
3510 pStubMsg->IgnoreEmbeddedPointers = 1;
3511 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3512 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3514 /* save it for use by embedded pointer code later */
3515 pStubMsg->PointerLength = pStubMsg->BufferLength;
3516 pointer_length_set = 1;
3517 TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
3519 /* restore the original buffer length */
3520 pStubMsg->BufferLength = saved_buffer_length;
3523 pFormat += 4;
3524 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3525 pFormat += 2;
3526 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3527 pFormat += 2;
3529 pStubMsg->Memory = pMemory;
3531 if (conf_array)
3533 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3534 array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3535 conf_array);
3537 /* these could be changed in ComplexMarshall so save them for later */
3538 max_count = pStubMsg->MaxCount;
3539 count = pStubMsg->ActualCount;
3540 offset = pStubMsg->Offset;
3543 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3545 if (conf_array)
3547 pStubMsg->MaxCount = max_count;
3548 pStubMsg->ActualCount = count;
3549 pStubMsg->Offset = offset;
3550 array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3551 TRUE /* fHasPointers */);
3554 pStubMsg->Memory = OldMemory;
3556 if(pointer_length_set)
3558 pStubMsg->BufferLength = pStubMsg->PointerLength;
3559 pStubMsg->PointerLength = 0;
3564 /***********************************************************************
3565 * NdrComplexStructMemorySize [RPCRT4.@]
3567 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3568 PFORMAT_STRING pFormat)
3570 unsigned size = *(const WORD*)(pFormat+2);
3571 PFORMAT_STRING conf_array = NULL;
3572 PFORMAT_STRING pointer_desc = NULL;
3573 ULONG count = 0;
3574 ULONG max_count = 0;
3575 ULONG offset = 0;
3577 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3579 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3581 pFormat += 4;
3582 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3583 pFormat += 2;
3584 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3585 pFormat += 2;
3587 if (conf_array)
3589 array_read_conformance(conf_array[0], pStubMsg, conf_array);
3591 /* these could be changed in ComplexStructMemorySize so save them for
3592 * later */
3593 max_count = pStubMsg->MaxCount;
3594 count = pStubMsg->ActualCount;
3595 offset = pStubMsg->Offset;
3598 ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3600 if (conf_array)
3602 pStubMsg->MaxCount = max_count;
3603 pStubMsg->ActualCount = count;
3604 pStubMsg->Offset = offset;
3605 array_memory_size(conf_array[0], pStubMsg, conf_array,
3606 TRUE /* fHasPointers */);
3609 return size;
3612 /***********************************************************************
3613 * NdrComplexStructFree [RPCRT4.@]
3615 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3616 unsigned char *pMemory,
3617 PFORMAT_STRING pFormat)
3619 PFORMAT_STRING conf_array = NULL;
3620 PFORMAT_STRING pointer_desc = NULL;
3621 unsigned char *OldMemory = pStubMsg->Memory;
3623 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3625 pFormat += 4;
3626 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3627 pFormat += 2;
3628 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3629 pFormat += 2;
3631 pStubMsg->Memory = pMemory;
3633 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3635 if (conf_array)
3636 array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3637 TRUE /* fHasPointers */);
3639 pStubMsg->Memory = OldMemory;
3642 /***********************************************************************
3643 * NdrConformantArrayMarshall [RPCRT4.@]
3645 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3646 unsigned char *pMemory,
3647 PFORMAT_STRING pFormat)
3649 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3650 if (pFormat[0] != RPC_FC_CARRAY)
3652 ERR("invalid format = 0x%x\n", pFormat[0]);
3653 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3656 array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
3657 pFormat);
3658 array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3659 TRUE /* fHasPointers */);
3661 return NULL;
3664 /***********************************************************************
3665 * NdrConformantArrayUnmarshall [RPCRT4.@]
3667 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3668 unsigned char **ppMemory,
3669 PFORMAT_STRING pFormat,
3670 unsigned char fMustAlloc)
3672 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3673 if (pFormat[0] != RPC_FC_CARRAY)
3675 ERR("invalid format = 0x%x\n", pFormat[0]);
3676 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3679 array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3680 array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
3681 fMustAlloc,
3682 TRUE /* fUseBufferMemoryServer */,
3683 TRUE /* fUnmarshall */);
3685 return NULL;
3688 /***********************************************************************
3689 * NdrConformantArrayBufferSize [RPCRT4.@]
3691 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3692 unsigned char *pMemory,
3693 PFORMAT_STRING pFormat)
3695 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3696 if (pFormat[0] != RPC_FC_CARRAY)
3698 ERR("invalid format = 0x%x\n", pFormat[0]);
3699 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3702 array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat);
3703 array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3704 TRUE /* fHasPointers */);
3707 /***********************************************************************
3708 * NdrConformantArrayMemorySize [RPCRT4.@]
3710 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3711 PFORMAT_STRING pFormat)
3713 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3714 if (pFormat[0] != RPC_FC_CARRAY)
3716 ERR("invalid format = 0x%x\n", pFormat[0]);
3717 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3720 array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3721 array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
3723 return pStubMsg->MemorySize;
3726 /***********************************************************************
3727 * NdrConformantArrayFree [RPCRT4.@]
3729 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3730 unsigned char *pMemory,
3731 PFORMAT_STRING pFormat)
3733 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3734 if (pFormat[0] != RPC_FC_CARRAY)
3736 ERR("invalid format = 0x%x\n", pFormat[0]);
3737 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3740 array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3741 TRUE /* fHasPointers */);
3745 /***********************************************************************
3746 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
3748 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
3749 unsigned char* pMemory,
3750 PFORMAT_STRING pFormat )
3752 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3754 if (pFormat[0] != RPC_FC_CVARRAY)
3756 ERR("invalid format type %x\n", pFormat[0]);
3757 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3758 return NULL;
3761 array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3762 pFormat);
3763 array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory,
3764 pFormat, TRUE /* fHasPointers */);
3766 return NULL;
3770 /***********************************************************************
3771 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
3773 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
3774 unsigned char** ppMemory,
3775 PFORMAT_STRING pFormat,
3776 unsigned char fMustAlloc )
3778 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3780 if (pFormat[0] != RPC_FC_CVARRAY)
3782 ERR("invalid format type %x\n", pFormat[0]);
3783 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3784 return NULL;
3787 array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3788 array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory,
3789 pFormat, fMustAlloc,
3790 TRUE /* fUseBufferMemoryServer */,
3791 TRUE /* fUnmarshall */);
3793 return NULL;
3797 /***********************************************************************
3798 * NdrConformantVaryingArrayFree [RPCRT4.@]
3800 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
3801 unsigned char* pMemory,
3802 PFORMAT_STRING pFormat )
3804 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3806 if (pFormat[0] != RPC_FC_CVARRAY)
3808 ERR("invalid format type %x\n", pFormat[0]);
3809 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3810 return;
3813 array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3814 TRUE /* fHasPointers */);
3818 /***********************************************************************
3819 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
3821 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
3822 unsigned char* pMemory, PFORMAT_STRING pFormat )
3824 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3826 if (pFormat[0] != RPC_FC_CVARRAY)
3828 ERR("invalid format type %x\n", pFormat[0]);
3829 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3830 return;
3833 array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
3834 pFormat);
3835 array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
3836 TRUE /* fHasPointers */);
3840 /***********************************************************************
3841 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
3843 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
3844 PFORMAT_STRING pFormat )
3846 TRACE("(%p, %p)\n", pStubMsg, pFormat);
3848 if (pFormat[0] != RPC_FC_CVARRAY)
3850 ERR("invalid format type %x\n", pFormat[0]);
3851 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3852 return pStubMsg->MemorySize;
3855 array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
3856 array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat,
3857 TRUE /* fHasPointers */);
3859 return pStubMsg->MemorySize;
3863 /***********************************************************************
3864 * NdrComplexArrayMarshall [RPCRT4.@]
3866 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3867 unsigned char *pMemory,
3868 PFORMAT_STRING pFormat)
3870 ULONG i, count, def;
3871 BOOL variance_present;
3872 unsigned char alignment;
3873 int pointer_buffer_mark_set = 0;
3875 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3877 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3879 ERR("invalid format type %x\n", pFormat[0]);
3880 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3881 return NULL;
3884 alignment = pFormat[1] + 1;
3886 if (!pStubMsg->PointerBufferMark)
3888 /* save buffer fields that may be changed by buffer sizer functions
3889 * and that may be needed later on */
3890 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3891 ULONG saved_buffer_length = pStubMsg->BufferLength;
3892 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
3893 ULONG saved_offset = pStubMsg->Offset;
3894 ULONG saved_actual_count = pStubMsg->ActualCount;
3896 /* get the buffer pointer after complex array data, but before
3897 * pointer data */
3898 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3899 pStubMsg->IgnoreEmbeddedPointers = 1;
3900 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3901 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3903 /* save it for use by embedded pointer code later */
3904 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3905 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
3906 pointer_buffer_mark_set = 1;
3908 /* restore fields */
3909 pStubMsg->ActualCount = saved_actual_count;
3910 pStubMsg->Offset = saved_offset;
3911 pStubMsg->MaxCount = saved_max_count;
3912 pStubMsg->BufferLength = saved_buffer_length;
3915 def = *(const WORD*)&pFormat[2];
3916 pFormat += 4;
3918 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3919 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3921 variance_present = IsConformanceOrVariancePresent(pFormat);
3922 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3923 TRACE("variance = %d\n", pStubMsg->ActualCount);
3925 WriteConformance(pStubMsg);
3926 if (variance_present)
3927 WriteVariance(pStubMsg);
3929 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3931 count = pStubMsg->ActualCount;
3932 for (i = 0; i < count; i++)
3933 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3935 STD_OVERFLOW_CHECK(pStubMsg);
3937 if (pointer_buffer_mark_set)
3939 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3940 pStubMsg->PointerBufferMark = NULL;
3943 return NULL;
3946 /***********************************************************************
3947 * NdrComplexArrayUnmarshall [RPCRT4.@]
3949 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3950 unsigned char **ppMemory,
3951 PFORMAT_STRING pFormat,
3952 unsigned char fMustAlloc)
3954 ULONG i, count, size;
3955 unsigned char alignment;
3956 unsigned char *pMemory;
3957 unsigned char *saved_buffer;
3958 int pointer_buffer_mark_set = 0;
3959 int saved_ignore_embedded;
3961 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3963 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3965 ERR("invalid format type %x\n", pFormat[0]);
3966 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3967 return NULL;
3970 alignment = pFormat[1] + 1;
3972 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3973 /* save buffer pointer */
3974 saved_buffer = pStubMsg->Buffer;
3975 /* get the buffer pointer after complex array data, but before
3976 * pointer data */
3977 pStubMsg->IgnoreEmbeddedPointers = 1;
3978 pStubMsg->MemorySize = 0;
3979 NdrComplexArrayMemorySize(pStubMsg, pFormat);
3980 size = pStubMsg->MemorySize;
3981 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3983 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer));
3984 if (!pStubMsg->PointerBufferMark)
3986 /* save it for use by embedded pointer code later */
3987 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3988 pointer_buffer_mark_set = 1;
3990 /* restore the original buffer */
3991 pStubMsg->Buffer = saved_buffer;
3993 pFormat += 4;
3995 pFormat = ReadConformance(pStubMsg, pFormat);
3996 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3998 if (!fMustAlloc && !*ppMemory)
3999 fMustAlloc = TRUE;
4000 if (fMustAlloc)
4001 *ppMemory = NdrAllocate(pStubMsg, size);
4003 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4005 pMemory = *ppMemory;
4006 count = pStubMsg->ActualCount;
4007 for (i = 0; i < count; i++)
4008 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
4010 if (pointer_buffer_mark_set)
4012 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4013 pStubMsg->PointerBufferMark = NULL;
4016 return NULL;
4019 /***********************************************************************
4020 * NdrComplexArrayBufferSize [RPCRT4.@]
4022 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4023 unsigned char *pMemory,
4024 PFORMAT_STRING pFormat)
4026 ULONG i, count, def;
4027 unsigned char alignment;
4028 BOOL variance_present;
4029 int pointer_length_set = 0;
4031 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4033 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4035 ERR("invalid format type %x\n", pFormat[0]);
4036 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4037 return;
4040 alignment = pFormat[1] + 1;
4042 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
4044 /* save buffer fields that may be changed by buffer sizer functions
4045 * and that may be needed later on */
4046 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4047 ULONG saved_buffer_length = pStubMsg->BufferLength;
4048 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4049 ULONG saved_offset = pStubMsg->Offset;
4050 ULONG saved_actual_count = pStubMsg->ActualCount;
4052 /* get the buffer pointer after complex array data, but before
4053 * pointer data */
4054 pStubMsg->IgnoreEmbeddedPointers = 1;
4055 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4056 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4058 /* save it for use by embedded pointer code later */
4059 pStubMsg->PointerLength = pStubMsg->BufferLength;
4060 pointer_length_set = 1;
4062 /* restore fields */
4063 pStubMsg->ActualCount = saved_actual_count;
4064 pStubMsg->Offset = saved_offset;
4065 pStubMsg->MaxCount = saved_max_count;
4066 pStubMsg->BufferLength = saved_buffer_length;
4068 def = *(const WORD*)&pFormat[2];
4069 pFormat += 4;
4071 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4072 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4073 SizeConformance(pStubMsg);
4075 variance_present = IsConformanceOrVariancePresent(pFormat);
4076 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4077 TRACE("variance = %d\n", pStubMsg->ActualCount);
4079 if (variance_present)
4080 SizeVariance(pStubMsg);
4082 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4084 count = pStubMsg->ActualCount;
4085 for (i = 0; i < count; i++)
4086 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
4088 if(pointer_length_set)
4090 pStubMsg->BufferLength = pStubMsg->PointerLength;
4091 pStubMsg->PointerLength = 0;
4095 /***********************************************************************
4096 * NdrComplexArrayMemorySize [RPCRT4.@]
4098 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4099 PFORMAT_STRING pFormat)
4101 ULONG i, count, esize, SavedMemorySize, MemorySize;
4102 unsigned char alignment;
4104 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4106 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4108 ERR("invalid format type %x\n", pFormat[0]);
4109 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4110 return 0;
4113 alignment = pFormat[1] + 1;
4115 pFormat += 4;
4117 pFormat = ReadConformance(pStubMsg, pFormat);
4118 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
4120 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4122 SavedMemorySize = pStubMsg->MemorySize;
4124 esize = ComplexStructSize(pStubMsg, pFormat);
4126 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
4128 count = pStubMsg->ActualCount;
4129 for (i = 0; i < count; i++)
4130 ComplexStructMemorySize(pStubMsg, pFormat, NULL);
4132 pStubMsg->MemorySize = SavedMemorySize;
4134 pStubMsg->MemorySize += MemorySize;
4135 return MemorySize;
4138 /***********************************************************************
4139 * NdrComplexArrayFree [RPCRT4.@]
4141 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4142 unsigned char *pMemory,
4143 PFORMAT_STRING pFormat)
4145 ULONG i, count, def;
4147 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4149 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4151 ERR("invalid format type %x\n", pFormat[0]);
4152 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4153 return;
4156 def = *(const WORD*)&pFormat[2];
4157 pFormat += 4;
4159 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4160 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4162 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4163 TRACE("variance = %d\n", pStubMsg->ActualCount);
4165 count = pStubMsg->ActualCount;
4166 for (i = 0; i < count; i++)
4167 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
4170 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
4171 USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
4172 USER_MARSHAL_CB *umcb)
4174 umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
4175 pStubMsg->RpcMsg->DataRepresentation);
4176 umcb->pStubMsg = pStubMsg;
4177 umcb->pReserve = NULL;
4178 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
4179 umcb->CBType = cbtype;
4180 umcb->pFormat = pFormat;
4181 umcb->pTypeFormat = NULL /* FIXME */;
4184 #define USER_MARSHAL_PTR_PREFIX \
4185 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
4186 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
4188 /***********************************************************************
4189 * NdrUserMarshalMarshall [RPCRT4.@]
4191 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4192 unsigned char *pMemory,
4193 PFORMAT_STRING pFormat)
4195 unsigned flags = pFormat[1];
4196 unsigned index = *(const WORD*)&pFormat[2];
4197 unsigned char *saved_buffer = NULL;
4198 USER_MARSHAL_CB umcb;
4200 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4201 TRACE("index=%d\n", index);
4203 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
4205 if (flags & USER_MARSHAL_POINTER)
4207 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
4208 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
4209 pStubMsg->Buffer += 4;
4210 if (pStubMsg->PointerBufferMark)
4212 saved_buffer = pStubMsg->Buffer;
4213 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4214 pStubMsg->PointerBufferMark = NULL;
4216 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8);
4218 else
4219 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1);
4221 pStubMsg->Buffer =
4222 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
4223 &umcb.Flags, pStubMsg->Buffer, pMemory);
4225 if (saved_buffer)
4227 STD_OVERFLOW_CHECK(pStubMsg);
4228 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4229 pStubMsg->Buffer = saved_buffer;
4232 STD_OVERFLOW_CHECK(pStubMsg);
4234 return NULL;
4237 /***********************************************************************
4238 * NdrUserMarshalUnmarshall [RPCRT4.@]
4240 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4241 unsigned char **ppMemory,
4242 PFORMAT_STRING pFormat,
4243 unsigned char fMustAlloc)
4245 unsigned flags = pFormat[1];
4246 unsigned index = *(const WORD*)&pFormat[2];
4247 DWORD memsize = *(const WORD*)&pFormat[4];
4248 unsigned char *saved_buffer = NULL;
4249 USER_MARSHAL_CB umcb;
4251 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4252 TRACE("index=%d\n", index);
4254 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
4256 if (flags & USER_MARSHAL_POINTER)
4258 ALIGN_POINTER(pStubMsg->Buffer, 4);
4259 /* skip pointer prefix */
4260 pStubMsg->Buffer += 4;
4261 if (pStubMsg->PointerBufferMark)
4263 saved_buffer = pStubMsg->Buffer;
4264 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4265 pStubMsg->PointerBufferMark = NULL;
4267 ALIGN_POINTER(pStubMsg->Buffer, 8);
4269 else
4270 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4272 if (!fMustAlloc && !*ppMemory)
4273 fMustAlloc = TRUE;
4274 if (fMustAlloc)
4276 *ppMemory = NdrAllocate(pStubMsg, memsize);
4277 memset(*ppMemory, 0, memsize);
4280 pStubMsg->Buffer =
4281 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
4282 &umcb.Flags, pStubMsg->Buffer, *ppMemory);
4284 if (saved_buffer)
4286 STD_OVERFLOW_CHECK(pStubMsg);
4287 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4288 pStubMsg->Buffer = saved_buffer;
4291 return NULL;
4294 /***********************************************************************
4295 * NdrUserMarshalBufferSize [RPCRT4.@]
4297 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4298 unsigned char *pMemory,
4299 PFORMAT_STRING pFormat)
4301 unsigned flags = pFormat[1];
4302 unsigned index = *(const WORD*)&pFormat[2];
4303 DWORD bufsize = *(const WORD*)&pFormat[6];
4304 USER_MARSHAL_CB umcb;
4305 ULONG saved_buffer_length = 0;
4307 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4308 TRACE("index=%d\n", index);
4310 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
4312 if (flags & USER_MARSHAL_POINTER)
4314 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4315 /* skip pointer prefix */
4316 safe_buffer_length_increment(pStubMsg, 4);
4317 if (pStubMsg->IgnoreEmbeddedPointers)
4318 return;
4319 if (pStubMsg->PointerLength)
4321 saved_buffer_length = pStubMsg->BufferLength;
4322 pStubMsg->BufferLength = pStubMsg->PointerLength;
4323 pStubMsg->PointerLength = 0;
4325 ALIGN_LENGTH(pStubMsg->BufferLength, 8);
4327 else
4328 ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
4330 if (bufsize) {
4331 TRACE("size=%d\n", bufsize);
4332 safe_buffer_length_increment(pStubMsg, bufsize);
4334 else
4335 pStubMsg->BufferLength =
4336 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
4337 &umcb.Flags, pStubMsg->BufferLength, pMemory);
4339 if (saved_buffer_length)
4341 pStubMsg->PointerLength = pStubMsg->BufferLength;
4342 pStubMsg->BufferLength = saved_buffer_length;
4347 /***********************************************************************
4348 * NdrUserMarshalMemorySize [RPCRT4.@]
4350 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4351 PFORMAT_STRING pFormat)
4353 unsigned flags = pFormat[1];
4354 unsigned index = *(const WORD*)&pFormat[2];
4355 DWORD memsize = *(const WORD*)&pFormat[4];
4356 DWORD bufsize = *(const WORD*)&pFormat[6];
4358 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4359 TRACE("index=%d\n", index);
4361 pStubMsg->MemorySize += memsize;
4363 if (flags & USER_MARSHAL_POINTER)
4365 ALIGN_POINTER(pStubMsg->Buffer, 4);
4366 /* skip pointer prefix */
4367 pStubMsg->Buffer += 4;
4368 if (pStubMsg->IgnoreEmbeddedPointers)
4369 return pStubMsg->MemorySize;
4370 ALIGN_POINTER(pStubMsg->Buffer, 8);
4372 else
4373 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
4375 if (!bufsize)
4376 FIXME("not implemented for varying buffer size\n");
4378 pStubMsg->Buffer += bufsize;
4380 return pStubMsg->MemorySize;
4383 /***********************************************************************
4384 * NdrUserMarshalFree [RPCRT4.@]
4386 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
4387 unsigned char *pMemory,
4388 PFORMAT_STRING pFormat)
4390 /* unsigned flags = pFormat[1]; */
4391 unsigned index = *(const WORD*)&pFormat[2];
4392 USER_MARSHAL_CB umcb;
4394 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4395 TRACE("index=%d\n", index);
4397 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
4399 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
4400 &umcb.Flags, pMemory);
4403 /***********************************************************************
4404 * NdrGetUserMarshalInfo [RPCRT4.@]
4406 RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi)
4408 USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags);
4410 TRACE("(%p,%u,%p)\n", flags, level, umi);
4412 if (level != 1)
4413 return RPC_S_INVALID_ARG;
4415 memset(&umi->u1.Level1, 0, sizeof(umi->u1.Level1));
4416 umi->InformationLevel = level;
4418 if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE)
4419 return RPC_S_INVALID_ARG;
4421 umi->u1.Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate;
4422 umi->u1.Level1.pfnFree = umcb->pStubMsg->pfnFree;
4423 umi->u1.Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer;
4425 switch (umcb->CBType)
4427 case USER_MARSHAL_CB_MARSHALL:
4428 case USER_MARSHAL_CB_UNMARSHALL:
4430 RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg;
4431 unsigned char *buffer_start = msg->Buffer;
4432 unsigned char *buffer_end =
4433 (unsigned char *)msg->Buffer + msg->BufferLength;
4435 if (umcb->pStubMsg->Buffer < buffer_start ||
4436 umcb->pStubMsg->Buffer > buffer_end)
4437 return ERROR_INVALID_USER_BUFFER;
4439 umi->u1.Level1.Buffer = umcb->pStubMsg->Buffer;
4440 umi->u1.Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer;
4441 break;
4443 case USER_MARSHAL_CB_BUFFER_SIZE:
4444 case USER_MARSHAL_CB_FREE:
4445 break;
4446 default:
4447 WARN("unrecognised CBType %d\n", umcb->CBType);
4450 return RPC_S_OK;
4453 /***********************************************************************
4454 * NdrClearOutParameters [RPCRT4.@]
4456 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
4457 PFORMAT_STRING pFormat,
4458 void *ArgAddr)
4460 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
4463 /***********************************************************************
4464 * NdrConvert [RPCRT4.@]
4466 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
4468 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
4469 /* FIXME: since this stub doesn't do any converting, the proper behavior
4470 is to raise an exception */
4473 /***********************************************************************
4474 * NdrConvert2 [RPCRT4.@]
4476 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
4478 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
4479 pStubMsg, pFormat, NumberParams);
4480 /* FIXME: since this stub doesn't do any converting, the proper behavior
4481 is to raise an exception */
4484 #include "pshpack1.h"
4485 typedef struct _NDR_CSTRUCT_FORMAT
4487 unsigned char type;
4488 unsigned char alignment;
4489 unsigned short memory_size;
4490 short offset_to_array_description;
4491 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
4492 #include "poppack.h"
4494 /***********************************************************************
4495 * NdrConformantStructMarshall [RPCRT4.@]
4497 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4498 unsigned char *pMemory,
4499 PFORMAT_STRING pFormat)
4501 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4502 PFORMAT_STRING pCArrayFormat;
4503 ULONG esize, bufsize;
4505 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4507 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4508 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4510 ERR("invalid format type %x\n", pCStructFormat->type);
4511 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4512 return NULL;
4515 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4516 pCStructFormat->offset_to_array_description;
4517 if (*pCArrayFormat != RPC_FC_CARRAY)
4519 ERR("invalid array format type %x\n", pCStructFormat->type);
4520 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4521 return NULL;
4523 esize = *(const WORD*)(pCArrayFormat+2);
4525 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4526 pCArrayFormat + 4, 0);
4528 WriteConformance(pStubMsg);
4530 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4532 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4534 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4535 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4537 ERR("integer overflow of memory_size %u with bufsize %u\n",
4538 pCStructFormat->memory_size, bufsize);
4539 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4541 /* copy constant sized part of struct */
4542 pStubMsg->BufferMark = pStubMsg->Buffer;
4543 safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
4545 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4546 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4548 return NULL;
4551 /***********************************************************************
4552 * NdrConformantStructUnmarshall [RPCRT4.@]
4554 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4555 unsigned char **ppMemory,
4556 PFORMAT_STRING pFormat,
4557 unsigned char fMustAlloc)
4559 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4560 PFORMAT_STRING pCArrayFormat;
4561 ULONG esize, bufsize;
4562 unsigned char *saved_buffer;
4564 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4566 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4567 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4569 ERR("invalid format type %x\n", pCStructFormat->type);
4570 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4571 return NULL;
4573 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4574 pCStructFormat->offset_to_array_description;
4575 if (*pCArrayFormat != RPC_FC_CARRAY)
4577 ERR("invalid array format type %x\n", pCStructFormat->type);
4578 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4579 return NULL;
4581 esize = *(const WORD*)(pCArrayFormat+2);
4583 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
4585 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
4587 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4589 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4590 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4592 ERR("integer overflow of memory_size %u with bufsize %u\n",
4593 pCStructFormat->memory_size, bufsize);
4594 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4597 if (fMustAlloc)
4599 SIZE_T size = pCStructFormat->memory_size + bufsize;
4600 *ppMemory = NdrAllocate(pStubMsg, size);
4602 else
4604 if (!pStubMsg->IsClient && !*ppMemory)
4605 /* for servers, we just point straight into the RPC buffer */
4606 *ppMemory = pStubMsg->Buffer;
4609 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4610 safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
4611 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4612 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4614 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4615 if (*ppMemory != saved_buffer)
4616 memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
4618 return NULL;
4621 /***********************************************************************
4622 * NdrConformantStructBufferSize [RPCRT4.@]
4624 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4625 unsigned char *pMemory,
4626 PFORMAT_STRING pFormat)
4628 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4629 PFORMAT_STRING pCArrayFormat;
4630 ULONG esize;
4632 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4634 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4635 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4637 ERR("invalid format type %x\n", pCStructFormat->type);
4638 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4639 return;
4641 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4642 pCStructFormat->offset_to_array_description;
4643 if (*pCArrayFormat != RPC_FC_CARRAY)
4645 ERR("invalid array format type %x\n", pCStructFormat->type);
4646 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4647 return;
4649 esize = *(const WORD*)(pCArrayFormat+2);
4651 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
4652 SizeConformance(pStubMsg);
4654 ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
4656 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4658 safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
4659 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4661 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4662 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4665 /***********************************************************************
4666 * NdrConformantStructMemorySize [RPCRT4.@]
4668 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4669 PFORMAT_STRING pFormat)
4671 FIXME("stub\n");
4672 return 0;
4675 /***********************************************************************
4676 * NdrConformantStructFree [RPCRT4.@]
4678 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4679 unsigned char *pMemory,
4680 PFORMAT_STRING pFormat)
4682 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4683 PFORMAT_STRING pCArrayFormat;
4685 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4687 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4688 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4690 ERR("invalid format type %x\n", pCStructFormat->type);
4691 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4692 return;
4695 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4696 pCStructFormat->offset_to_array_description;
4697 if (*pCArrayFormat != RPC_FC_CARRAY)
4699 ERR("invalid array format type %x\n", pCStructFormat->type);
4700 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4701 return;
4704 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4705 pCArrayFormat + 4, 0);
4707 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4709 /* copy constant sized part of struct */
4710 pStubMsg->BufferMark = pStubMsg->Buffer;
4712 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4713 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4716 /***********************************************************************
4717 * NdrConformantVaryingStructMarshall [RPCRT4.@]
4719 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4720 unsigned char *pMemory,
4721 PFORMAT_STRING pFormat)
4723 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4724 PFORMAT_STRING pCVArrayFormat;
4726 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4728 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4729 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4731 ERR("invalid format type %x\n", pCVStructFormat->type);
4732 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4733 return NULL;
4736 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4737 pCVStructFormat->offset_to_array_description;
4739 array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg,
4740 pMemory + pCVStructFormat->memory_size,
4741 pCVArrayFormat);
4743 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4745 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4747 /* write constant sized part */
4748 pStubMsg->BufferMark = pStubMsg->Buffer;
4749 safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
4751 array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg,
4752 pMemory + pCVStructFormat->memory_size,
4753 pCVArrayFormat, FALSE /* fHasPointers */);
4755 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4757 return NULL;
4760 /***********************************************************************
4761 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
4763 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4764 unsigned char **ppMemory,
4765 PFORMAT_STRING pFormat,
4766 unsigned char fMustAlloc)
4768 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4769 PFORMAT_STRING pCVArrayFormat;
4770 ULONG memsize, bufsize;
4771 unsigned char *saved_buffer, *saved_array_buffer;
4772 ULONG offset;
4773 unsigned char *array_memory;
4775 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4777 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4778 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4780 ERR("invalid format type %x\n", pCVStructFormat->type);
4781 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4782 return NULL;
4785 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4786 pCVStructFormat->offset_to_array_description;
4788 memsize = array_read_conformance(*pCVArrayFormat, pStubMsg,
4789 pCVArrayFormat);
4791 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4793 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4795 /* work out how much memory to allocate if we need to do so */
4796 if (!fMustAlloc && !*ppMemory)
4797 fMustAlloc = TRUE;
4798 if (fMustAlloc)
4800 SIZE_T size = pCVStructFormat->memory_size + memsize;
4801 *ppMemory = NdrAllocate(pStubMsg, size);
4804 /* mark the start of the constant data */
4805 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4806 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4808 array_memory = *ppMemory + pCVStructFormat->memory_size;
4809 bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg,
4810 &array_memory, pCVArrayFormat,
4811 FALSE /* fMustAlloc */,
4812 FALSE /* fUseServerBufferMemory */,
4813 FALSE /* fUnmarshall */);
4815 /* save offset in case unmarshalling pointers changes it */
4816 offset = pStubMsg->Offset;
4818 /* mark the start of the array data */
4819 saved_array_buffer = pStubMsg->Buffer;
4820 safe_buffer_increment(pStubMsg, bufsize);
4822 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4824 /* copy the constant data */
4825 memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size);
4826 /* copy the array data */
4827 TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size);
4828 memcpy(*ppMemory + pCVStructFormat->memory_size + offset,
4829 saved_array_buffer, bufsize);
4831 if (*pCVArrayFormat == RPC_FC_C_CSTRING)
4832 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
4833 else if (*pCVArrayFormat == RPC_FC_C_WSTRING)
4834 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
4836 return NULL;
4839 /***********************************************************************
4840 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
4842 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4843 unsigned char *pMemory,
4844 PFORMAT_STRING pFormat)
4846 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4847 PFORMAT_STRING pCVArrayFormat;
4849 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4851 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4852 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4854 ERR("invalid format type %x\n", pCVStructFormat->type);
4855 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4856 return;
4859 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4860 pCVStructFormat->offset_to_array_description;
4861 array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg,
4862 pMemory + pCVStructFormat->memory_size,
4863 pCVArrayFormat);
4865 ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4867 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4869 safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4871 array_buffer_size(*pCVArrayFormat, pStubMsg,
4872 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4873 FALSE /* fHasPointers */);
4875 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4878 /***********************************************************************
4879 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
4881 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4882 PFORMAT_STRING pFormat)
4884 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4885 PFORMAT_STRING pCVArrayFormat;
4887 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4889 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4890 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4892 ERR("invalid format type %x\n", pCVStructFormat->type);
4893 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4894 return 0;
4897 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4898 pCVStructFormat->offset_to_array_description;
4899 array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat);
4901 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4903 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4905 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4906 array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat,
4907 FALSE /* fHasPointers */);
4909 pStubMsg->MemorySize += pCVStructFormat->memory_size;
4911 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4913 return pStubMsg->MemorySize;
4916 /***********************************************************************
4917 * NdrConformantVaryingStructFree [RPCRT4.@]
4919 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4920 unsigned char *pMemory,
4921 PFORMAT_STRING pFormat)
4923 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4924 PFORMAT_STRING pCVArrayFormat;
4926 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4928 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4929 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4931 ERR("invalid format type %x\n", pCVStructFormat->type);
4932 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4933 return;
4936 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4937 pCVStructFormat->offset_to_array_description;
4938 array_free(*pCVArrayFormat, pStubMsg,
4939 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
4940 FALSE /* fHasPointers */);
4942 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4944 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4947 #include "pshpack1.h"
4948 typedef struct
4950 unsigned char type;
4951 unsigned char alignment;
4952 unsigned short total_size;
4953 } NDR_SMFARRAY_FORMAT;
4955 typedef struct
4957 unsigned char type;
4958 unsigned char alignment;
4959 ULONG total_size;
4960 } NDR_LGFARRAY_FORMAT;
4961 #include "poppack.h"
4963 /***********************************************************************
4964 * NdrFixedArrayMarshall [RPCRT4.@]
4966 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4967 unsigned char *pMemory,
4968 PFORMAT_STRING pFormat)
4970 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4971 ULONG total_size;
4973 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4975 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4976 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4978 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4979 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4980 return NULL;
4983 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4985 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4987 total_size = pSmFArrayFormat->total_size;
4988 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4990 else
4992 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4993 total_size = pLgFArrayFormat->total_size;
4994 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4997 pStubMsg->BufferMark = pStubMsg->Buffer;
4998 safe_copy_to_buffer(pStubMsg, pMemory, total_size);
5000 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5002 return NULL;
5005 /***********************************************************************
5006 * NdrFixedArrayUnmarshall [RPCRT4.@]
5008 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5009 unsigned char **ppMemory,
5010 PFORMAT_STRING pFormat,
5011 unsigned char fMustAlloc)
5013 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5014 ULONG total_size;
5015 unsigned char *saved_buffer;
5017 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5019 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5020 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5022 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5023 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5024 return NULL;
5027 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5029 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5031 total_size = pSmFArrayFormat->total_size;
5032 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5034 else
5036 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5037 total_size = pLgFArrayFormat->total_size;
5038 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5041 if (fMustAlloc)
5042 *ppMemory = NdrAllocate(pStubMsg, total_size);
5043 else
5045 if (!pStubMsg->IsClient && !*ppMemory)
5046 /* for servers, we just point straight into the RPC buffer */
5047 *ppMemory = pStubMsg->Buffer;
5050 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5051 safe_buffer_increment(pStubMsg, total_size);
5052 pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5054 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
5055 if (*ppMemory != saved_buffer)
5056 memcpy(*ppMemory, saved_buffer, total_size);
5058 return NULL;
5061 /***********************************************************************
5062 * NdrFixedArrayBufferSize [RPCRT4.@]
5064 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5065 unsigned char *pMemory,
5066 PFORMAT_STRING pFormat)
5068 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5069 ULONG total_size;
5071 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5073 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5074 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5076 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5077 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5078 return;
5081 ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
5083 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5085 total_size = pSmFArrayFormat->total_size;
5086 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5088 else
5090 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5091 total_size = pLgFArrayFormat->total_size;
5092 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5094 safe_buffer_length_increment(pStubMsg, total_size);
5096 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5099 /***********************************************************************
5100 * NdrFixedArrayMemorySize [RPCRT4.@]
5102 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5103 PFORMAT_STRING pFormat)
5105 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5106 ULONG total_size;
5108 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5110 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5111 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5113 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5114 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5115 return 0;
5118 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5120 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5122 total_size = pSmFArrayFormat->total_size;
5123 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5125 else
5127 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5128 total_size = pLgFArrayFormat->total_size;
5129 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5131 pStubMsg->BufferMark = pStubMsg->Buffer;
5132 safe_buffer_increment(pStubMsg, total_size);
5133 pStubMsg->MemorySize += total_size;
5135 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5137 return total_size;
5140 /***********************************************************************
5141 * NdrFixedArrayFree [RPCRT4.@]
5143 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5144 unsigned char *pMemory,
5145 PFORMAT_STRING pFormat)
5147 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5149 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5151 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5152 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5154 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5155 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5156 return;
5159 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5160 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5161 else
5163 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5164 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5167 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5170 /***********************************************************************
5171 * NdrVaryingArrayMarshall [RPCRT4.@]
5173 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5174 unsigned char *pMemory,
5175 PFORMAT_STRING pFormat)
5177 unsigned char alignment;
5178 DWORD elements, esize;
5179 ULONG bufsize;
5181 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5183 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5184 (pFormat[0] != RPC_FC_LGVARRAY))
5186 ERR("invalid format type %x\n", pFormat[0]);
5187 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5188 return NULL;
5191 alignment = pFormat[1] + 1;
5193 if (pFormat[0] == RPC_FC_SMVARRAY)
5195 pFormat += 2;
5196 pFormat += sizeof(WORD);
5197 elements = *(const WORD*)pFormat;
5198 pFormat += sizeof(WORD);
5200 else
5202 pFormat += 2;
5203 pFormat += sizeof(DWORD);
5204 elements = *(const DWORD*)pFormat;
5205 pFormat += sizeof(DWORD);
5208 esize = *(const WORD*)pFormat;
5209 pFormat += sizeof(WORD);
5211 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5212 if ((pStubMsg->ActualCount > elements) ||
5213 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5215 RpcRaiseException(RPC_S_INVALID_BOUND);
5216 return NULL;
5219 WriteVariance(pStubMsg);
5221 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
5223 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5224 pStubMsg->BufferMark = pStubMsg->Buffer;
5225 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
5227 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5229 return NULL;
5232 /***********************************************************************
5233 * NdrVaryingArrayUnmarshall [RPCRT4.@]
5235 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5236 unsigned char **ppMemory,
5237 PFORMAT_STRING pFormat,
5238 unsigned char fMustAlloc)
5240 unsigned char alignment;
5241 DWORD size, elements, esize;
5242 ULONG bufsize;
5243 unsigned char *saved_buffer;
5244 ULONG offset;
5246 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5248 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5249 (pFormat[0] != RPC_FC_LGVARRAY))
5251 ERR("invalid format type %x\n", pFormat[0]);
5252 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5253 return NULL;
5256 alignment = pFormat[1] + 1;
5258 if (pFormat[0] == RPC_FC_SMVARRAY)
5260 pFormat += 2;
5261 size = *(const WORD*)pFormat;
5262 pFormat += sizeof(WORD);
5263 elements = *(const WORD*)pFormat;
5264 pFormat += sizeof(WORD);
5266 else
5268 pFormat += 2;
5269 size = *(const DWORD*)pFormat;
5270 pFormat += sizeof(DWORD);
5271 elements = *(const DWORD*)pFormat;
5272 pFormat += sizeof(DWORD);
5275 esize = *(const WORD*)pFormat;
5276 pFormat += sizeof(WORD);
5278 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5280 ALIGN_POINTER(pStubMsg->Buffer, alignment);
5282 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5283 offset = pStubMsg->Offset;
5285 if (!fMustAlloc && !*ppMemory)
5286 fMustAlloc = TRUE;
5287 if (fMustAlloc)
5288 *ppMemory = NdrAllocate(pStubMsg, size);
5289 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5290 safe_buffer_increment(pStubMsg, bufsize);
5292 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5294 memcpy(*ppMemory + offset, saved_buffer, bufsize);
5296 return NULL;
5299 /***********************************************************************
5300 * NdrVaryingArrayBufferSize [RPCRT4.@]
5302 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5303 unsigned char *pMemory,
5304 PFORMAT_STRING pFormat)
5306 unsigned char alignment;
5307 DWORD elements, esize;
5309 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5311 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5312 (pFormat[0] != RPC_FC_LGVARRAY))
5314 ERR("invalid format type %x\n", pFormat[0]);
5315 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5316 return;
5319 alignment = pFormat[1] + 1;
5321 if (pFormat[0] == RPC_FC_SMVARRAY)
5323 pFormat += 2;
5324 pFormat += sizeof(WORD);
5325 elements = *(const WORD*)pFormat;
5326 pFormat += sizeof(WORD);
5328 else
5330 pFormat += 2;
5331 pFormat += sizeof(DWORD);
5332 elements = *(const DWORD*)pFormat;
5333 pFormat += sizeof(DWORD);
5336 esize = *(const WORD*)pFormat;
5337 pFormat += sizeof(WORD);
5339 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5340 if ((pStubMsg->ActualCount > elements) ||
5341 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5343 RpcRaiseException(RPC_S_INVALID_BOUND);
5344 return;
5347 SizeVariance(pStubMsg);
5349 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
5351 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5353 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5356 /***********************************************************************
5357 * NdrVaryingArrayMemorySize [RPCRT4.@]
5359 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5360 PFORMAT_STRING pFormat)
5362 unsigned char alignment;
5363 DWORD size, elements, esize;
5365 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5367 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5368 (pFormat[0] != RPC_FC_LGVARRAY))
5370 ERR("invalid format type %x\n", pFormat[0]);
5371 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5372 return 0;
5375 alignment = pFormat[1] + 1;
5377 if (pFormat[0] == RPC_FC_SMVARRAY)
5379 pFormat += 2;
5380 size = *(const WORD*)pFormat;
5381 pFormat += sizeof(WORD);
5382 elements = *(const WORD*)pFormat;
5383 pFormat += sizeof(WORD);
5385 else
5387 pFormat += 2;
5388 size = *(const DWORD*)pFormat;
5389 pFormat += sizeof(DWORD);
5390 elements = *(const DWORD*)pFormat;
5391 pFormat += sizeof(DWORD);
5394 esize = *(const WORD*)pFormat;
5395 pFormat += sizeof(WORD);
5397 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5399 ALIGN_POINTER(pStubMsg->Buffer, alignment);
5401 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5402 pStubMsg->MemorySize += size;
5404 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5406 return pStubMsg->MemorySize;
5409 /***********************************************************************
5410 * NdrVaryingArrayFree [RPCRT4.@]
5412 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5413 unsigned char *pMemory,
5414 PFORMAT_STRING pFormat)
5416 DWORD elements;
5418 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5420 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5421 (pFormat[0] != RPC_FC_LGVARRAY))
5423 ERR("invalid format type %x\n", pFormat[0]);
5424 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5425 return;
5428 if (pFormat[0] == RPC_FC_SMVARRAY)
5430 pFormat += 2;
5431 pFormat += sizeof(WORD);
5432 elements = *(const WORD*)pFormat;
5433 pFormat += sizeof(WORD);
5435 else
5437 pFormat += 2;
5438 pFormat += sizeof(DWORD);
5439 elements = *(const DWORD*)pFormat;
5440 pFormat += sizeof(DWORD);
5443 pFormat += sizeof(WORD);
5445 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5446 if ((pStubMsg->ActualCount > elements) ||
5447 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5449 RpcRaiseException(RPC_S_INVALID_BOUND);
5450 return;
5453 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5456 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
5458 switch (fc)
5460 case RPC_FC_BYTE:
5461 case RPC_FC_CHAR:
5462 case RPC_FC_SMALL:
5463 case RPC_FC_USMALL:
5464 return *pMemory;
5465 case RPC_FC_WCHAR:
5466 case RPC_FC_SHORT:
5467 case RPC_FC_USHORT:
5468 case RPC_FC_ENUM16:
5469 return *(const USHORT *)pMemory;
5470 case RPC_FC_LONG:
5471 case RPC_FC_ULONG:
5472 case RPC_FC_ENUM32:
5473 return *(const ULONG *)pMemory;
5474 default:
5475 FIXME("Unhandled base type: 0x%02x\n", fc);
5476 return 0;
5480 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
5481 ULONG discriminant,
5482 PFORMAT_STRING pFormat)
5484 unsigned short num_arms, arm, type;
5486 num_arms = *(const SHORT*)pFormat & 0x0fff;
5487 pFormat += 2;
5488 for(arm = 0; arm < num_arms; arm++)
5490 if(discriminant == *(const ULONG*)pFormat)
5492 pFormat += 4;
5493 break;
5495 pFormat += 6;
5498 type = *(const unsigned short*)pFormat;
5499 TRACE("type %04x\n", type);
5500 if(arm == num_arms) /* default arm extras */
5502 if(type == 0xffff)
5504 ERR("no arm for 0x%x and no default case\n", discriminant);
5505 RpcRaiseException(RPC_S_INVALID_TAG);
5506 return NULL;
5508 if(type == 0)
5510 TRACE("falling back to empty default case for 0x%x\n", discriminant);
5511 return NULL;
5514 return pFormat;
5517 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
5519 unsigned short type;
5521 pFormat += 2;
5523 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5524 if(!pFormat)
5525 return NULL;
5527 type = *(const unsigned short*)pFormat;
5528 if((type & 0xff00) == 0x8000)
5530 unsigned char basetype = LOBYTE(type);
5531 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
5533 else
5535 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5536 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
5537 if (m)
5539 unsigned char *saved_buffer = NULL;
5540 int pointer_buffer_mark_set = 0;
5541 switch(*desc)
5543 case RPC_FC_RP:
5544 case RPC_FC_UP:
5545 case RPC_FC_OP:
5546 case RPC_FC_FP:
5547 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
5548 saved_buffer = pStubMsg->Buffer;
5549 if (pStubMsg->PointerBufferMark)
5551 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5552 pStubMsg->PointerBufferMark = NULL;
5553 pointer_buffer_mark_set = 1;
5555 else
5556 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
5558 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
5559 if (pointer_buffer_mark_set)
5561 STD_OVERFLOW_CHECK(pStubMsg);
5562 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5563 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5565 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5566 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5567 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5569 pStubMsg->Buffer = saved_buffer + 4;
5571 break;
5572 default:
5573 m(pStubMsg, pMemory, desc);
5576 else FIXME("no marshaller for embedded type %02x\n", *desc);
5578 return NULL;
5581 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5582 unsigned char **ppMemory,
5583 ULONG discriminant,
5584 PFORMAT_STRING pFormat,
5585 unsigned char fMustAlloc)
5587 unsigned short type;
5589 pFormat += 2;
5591 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5592 if(!pFormat)
5593 return NULL;
5595 type = *(const unsigned short*)pFormat;
5596 if((type & 0xff00) == 0x8000)
5598 unsigned char basetype = LOBYTE(type);
5599 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
5601 else
5603 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5604 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
5605 if (m)
5607 unsigned char *saved_buffer = NULL;
5608 int pointer_buffer_mark_set = 0;
5609 switch(*desc)
5611 case RPC_FC_RP:
5612 case RPC_FC_UP:
5613 case RPC_FC_OP:
5614 case RPC_FC_FP:
5615 ALIGN_POINTER(pStubMsg->Buffer, 4);
5616 saved_buffer = pStubMsg->Buffer;
5617 if (pStubMsg->PointerBufferMark)
5619 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5620 pStubMsg->PointerBufferMark = NULL;
5621 pointer_buffer_mark_set = 1;
5623 else
5624 pStubMsg->Buffer += 4; /* for pointer ID */
5626 if (saved_buffer + 4 > pStubMsg->BufferEnd)
5628 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5629 saved_buffer, pStubMsg->BufferEnd);
5630 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5633 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
5634 if (pointer_buffer_mark_set)
5636 STD_OVERFLOW_CHECK(pStubMsg);
5637 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5638 pStubMsg->Buffer = saved_buffer + 4;
5640 break;
5641 default:
5642 m(pStubMsg, ppMemory, desc, fMustAlloc);
5645 else FIXME("no marshaller for embedded type %02x\n", *desc);
5647 return NULL;
5650 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
5651 unsigned char *pMemory,
5652 ULONG discriminant,
5653 PFORMAT_STRING pFormat)
5655 unsigned short type;
5657 pFormat += 2;
5659 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5660 if(!pFormat)
5661 return;
5663 type = *(const unsigned short*)pFormat;
5664 if((type & 0xff00) == 0x8000)
5666 unsigned char basetype = LOBYTE(type);
5667 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
5669 else
5671 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5672 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
5673 if (m)
5675 switch(*desc)
5677 case RPC_FC_RP:
5678 case RPC_FC_UP:
5679 case RPC_FC_OP:
5680 case RPC_FC_FP:
5681 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5682 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
5683 if (!pStubMsg->IgnoreEmbeddedPointers)
5685 int saved_buffer_length = pStubMsg->BufferLength;
5686 pStubMsg->BufferLength = pStubMsg->PointerLength;
5687 pStubMsg->PointerLength = 0;
5688 if(!pStubMsg->BufferLength)
5689 ERR("BufferLength == 0??\n");
5690 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
5691 pStubMsg->PointerLength = pStubMsg->BufferLength;
5692 pStubMsg->BufferLength = saved_buffer_length;
5694 break;
5695 default:
5696 m(pStubMsg, pMemory, desc);
5699 else FIXME("no buffersizer for embedded type %02x\n", *desc);
5703 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
5704 ULONG discriminant,
5705 PFORMAT_STRING pFormat)
5707 unsigned short type, size;
5709 size = *(const unsigned short*)pFormat;
5710 pStubMsg->Memory += size;
5711 pFormat += 2;
5713 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5714 if(!pFormat)
5715 return 0;
5717 type = *(const unsigned short*)pFormat;
5718 if((type & 0xff00) == 0x8000)
5720 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
5722 else
5724 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5725 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
5726 unsigned char *saved_buffer;
5727 if (m)
5729 switch(*desc)
5731 case RPC_FC_RP:
5732 case RPC_FC_UP:
5733 case RPC_FC_OP:
5734 case RPC_FC_FP:
5735 ALIGN_POINTER(pStubMsg->Buffer, 4);
5736 saved_buffer = pStubMsg->Buffer;
5737 safe_buffer_increment(pStubMsg, 4);
5738 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
5739 pStubMsg->MemorySize += sizeof(void *);
5740 if (!pStubMsg->IgnoreEmbeddedPointers)
5741 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
5742 break;
5743 default:
5744 return m(pStubMsg, desc);
5747 else FIXME("no marshaller for embedded type %02x\n", *desc);
5750 TRACE("size %d\n", size);
5751 return size;
5754 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
5755 unsigned char *pMemory,
5756 ULONG discriminant,
5757 PFORMAT_STRING pFormat)
5759 unsigned short type;
5761 pFormat += 2;
5763 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5764 if(!pFormat)
5765 return;
5767 type = *(const unsigned short*)pFormat;
5768 if((type & 0xff00) != 0x8000)
5770 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5771 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5772 if (m)
5774 switch(*desc)
5776 case RPC_FC_RP:
5777 case RPC_FC_UP:
5778 case RPC_FC_OP:
5779 case RPC_FC_FP:
5780 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5781 break;
5782 default:
5783 m(pStubMsg, pMemory, desc);
5789 /***********************************************************************
5790 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
5792 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5793 unsigned char *pMemory,
5794 PFORMAT_STRING pFormat)
5796 unsigned char switch_type;
5797 unsigned char increment;
5798 ULONG switch_value;
5800 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5801 pFormat++;
5803 switch_type = *pFormat & 0xf;
5804 increment = (*pFormat & 0xf0) >> 4;
5805 pFormat++;
5807 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment);
5809 switch_value = get_discriminant(switch_type, pMemory);
5810 TRACE("got switch value 0x%x\n", switch_value);
5812 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5813 pMemory += increment;
5815 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5818 /***********************************************************************
5819 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5821 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5822 unsigned char **ppMemory,
5823 PFORMAT_STRING pFormat,
5824 unsigned char fMustAlloc)
5826 unsigned char switch_type;
5827 unsigned char increment;
5828 ULONG switch_value;
5829 unsigned short size;
5830 unsigned char *pMemoryArm;
5832 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5833 pFormat++;
5835 switch_type = *pFormat & 0xf;
5836 increment = (*pFormat & 0xf0) >> 4;
5837 pFormat++;
5839 ALIGN_POINTER(pStubMsg->Buffer, increment);
5840 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5841 TRACE("got switch value 0x%x\n", switch_value);
5843 size = *(const unsigned short*)pFormat + increment;
5844 if (!fMustAlloc && !*ppMemory)
5845 fMustAlloc = TRUE;
5846 if (fMustAlloc)
5847 *ppMemory = NdrAllocate(pStubMsg, size);
5849 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
5850 * since the arm is part of the memory block that is encompassed by
5851 * the whole union. Memory is forced to allocate when pointers
5852 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
5853 * clearing the memory we pass in to the unmarshaller */
5854 if (fMustAlloc)
5855 memset(*ppMemory, 0, size);
5857 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5858 pMemoryArm = *ppMemory + increment;
5860 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE);
5863 /***********************************************************************
5864 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5866 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5867 unsigned char *pMemory,
5868 PFORMAT_STRING pFormat)
5870 unsigned char switch_type;
5871 unsigned char increment;
5872 ULONG switch_value;
5874 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5875 pFormat++;
5877 switch_type = *pFormat & 0xf;
5878 increment = (*pFormat & 0xf0) >> 4;
5879 pFormat++;
5881 ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5882 switch_value = get_discriminant(switch_type, pMemory);
5883 TRACE("got switch value 0x%x\n", switch_value);
5885 /* Add discriminant size */
5886 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5887 pMemory += increment;
5889 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5892 /***********************************************************************
5893 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5895 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5896 PFORMAT_STRING pFormat)
5898 unsigned char switch_type;
5899 unsigned char increment;
5900 ULONG switch_value;
5902 switch_type = *pFormat & 0xf;
5903 increment = (*pFormat & 0xf0) >> 4;
5904 pFormat++;
5906 ALIGN_POINTER(pStubMsg->Buffer, increment);
5907 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5908 TRACE("got switch value 0x%x\n", switch_value);
5910 pStubMsg->Memory += increment;
5912 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5915 /***********************************************************************
5916 * NdrEncapsulatedUnionFree [RPCRT4.@]
5918 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5919 unsigned char *pMemory,
5920 PFORMAT_STRING pFormat)
5922 unsigned char switch_type;
5923 unsigned char increment;
5924 ULONG switch_value;
5926 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5927 pFormat++;
5929 switch_type = *pFormat & 0xf;
5930 increment = (*pFormat & 0xf0) >> 4;
5931 pFormat++;
5933 switch_value = get_discriminant(switch_type, pMemory);
5934 TRACE("got switch value 0x%x\n", switch_value);
5936 pMemory += increment;
5938 union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5941 /***********************************************************************
5942 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5944 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5945 unsigned char *pMemory,
5946 PFORMAT_STRING pFormat)
5948 unsigned char switch_type;
5950 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5951 pFormat++;
5953 switch_type = *pFormat;
5954 pFormat++;
5956 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5957 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5958 /* Marshall discriminant */
5959 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5961 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5964 static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
5965 PFORMAT_STRING *ppFormat)
5967 LONG discriminant = 0;
5969 switch(**ppFormat)
5971 case RPC_FC_BYTE:
5972 case RPC_FC_CHAR:
5973 case RPC_FC_SMALL:
5974 case RPC_FC_USMALL:
5976 UCHAR d;
5977 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5978 discriminant = d;
5979 break;
5981 case RPC_FC_WCHAR:
5982 case RPC_FC_SHORT:
5983 case RPC_FC_USHORT:
5985 USHORT d;
5986 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5987 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5988 discriminant = d;
5989 break;
5991 case RPC_FC_LONG:
5992 case RPC_FC_ULONG:
5994 ULONG d;
5995 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5996 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5997 discriminant = d;
5998 break;
6000 default:
6001 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
6003 (*ppFormat)++;
6005 if (pStubMsg->fHasNewCorrDesc)
6006 *ppFormat += 6;
6007 else
6008 *ppFormat += 4;
6009 return discriminant;
6012 /**********************************************************************
6013 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
6015 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6016 unsigned char **ppMemory,
6017 PFORMAT_STRING pFormat,
6018 unsigned char fMustAlloc)
6020 LONG discriminant;
6021 unsigned short size;
6023 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
6024 pFormat++;
6026 /* Unmarshall discriminant */
6027 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6028 TRACE("unmarshalled discriminant %x\n", discriminant);
6030 pFormat += *(const SHORT*)pFormat;
6032 size = *(const unsigned short*)pFormat;
6034 if (!fMustAlloc && !*ppMemory)
6035 fMustAlloc = TRUE;
6036 if (fMustAlloc)
6037 *ppMemory = NdrAllocate(pStubMsg, size);
6039 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6040 * since the arm is part of the memory block that is encompassed by
6041 * the whole union. Memory is forced to allocate when pointers
6042 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6043 * clearing the memory we pass in to the unmarshaller */
6044 if (fMustAlloc)
6045 memset(*ppMemory, 0, size);
6047 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
6050 /***********************************************************************
6051 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
6053 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6054 unsigned char *pMemory,
6055 PFORMAT_STRING pFormat)
6057 unsigned char switch_type;
6059 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6060 pFormat++;
6062 switch_type = *pFormat;
6063 pFormat++;
6065 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6066 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6067 /* Add discriminant size */
6068 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6070 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6073 /***********************************************************************
6074 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
6076 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6077 PFORMAT_STRING pFormat)
6079 ULONG discriminant;
6081 pFormat++;
6082 /* Unmarshall discriminant */
6083 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6084 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
6086 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
6089 /***********************************************************************
6090 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
6092 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6093 unsigned char *pMemory,
6094 PFORMAT_STRING pFormat)
6096 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6097 pFormat++;
6098 pFormat++;
6100 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6101 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6103 union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6106 /***********************************************************************
6107 * NdrByteCountPointerMarshall [RPCRT4.@]
6109 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6110 unsigned char *pMemory,
6111 PFORMAT_STRING pFormat)
6113 FIXME("stub\n");
6114 return NULL;
6117 /***********************************************************************
6118 * NdrByteCountPointerUnmarshall [RPCRT4.@]
6120 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6121 unsigned char **ppMemory,
6122 PFORMAT_STRING pFormat,
6123 unsigned char fMustAlloc)
6125 FIXME("stub\n");
6126 return NULL;
6129 /***********************************************************************
6130 * NdrByteCountPointerBufferSize [RPCRT4.@]
6132 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6133 unsigned char *pMemory,
6134 PFORMAT_STRING pFormat)
6136 FIXME("stub\n");
6139 /***********************************************************************
6140 * NdrByteCountPointerMemorySize [internal]
6142 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6143 PFORMAT_STRING pFormat)
6145 FIXME("stub\n");
6146 return 0;
6149 /***********************************************************************
6150 * NdrByteCountPointerFree [RPCRT4.@]
6152 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
6153 unsigned char *pMemory,
6154 PFORMAT_STRING pFormat)
6156 FIXME("stub\n");
6159 /***********************************************************************
6160 * NdrXmitOrRepAsMarshall [RPCRT4.@]
6162 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6163 unsigned char *pMemory,
6164 PFORMAT_STRING pFormat)
6166 FIXME("stub\n");
6167 return NULL;
6170 /***********************************************************************
6171 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
6173 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6174 unsigned char **ppMemory,
6175 PFORMAT_STRING pFormat,
6176 unsigned char fMustAlloc)
6178 FIXME("stub\n");
6179 return NULL;
6182 /***********************************************************************
6183 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
6185 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6186 unsigned char *pMemory,
6187 PFORMAT_STRING pFormat)
6189 FIXME("stub\n");
6192 /***********************************************************************
6193 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
6195 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6196 PFORMAT_STRING pFormat)
6198 FIXME("stub\n");
6199 return 0;
6202 /***********************************************************************
6203 * NdrXmitOrRepAsFree [RPCRT4.@]
6205 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
6206 unsigned char *pMemory,
6207 PFORMAT_STRING pFormat)
6209 FIXME("stub\n");
6212 /***********************************************************************
6213 * NdrRangeMarshall [internal]
6215 static unsigned char *WINAPI NdrRangeMarshall(
6216 PMIDL_STUB_MESSAGE pStubMsg,
6217 unsigned char *pMemory,
6218 PFORMAT_STRING pFormat)
6220 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6221 unsigned char base_type;
6223 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6225 if (pRange->type != RPC_FC_RANGE)
6227 ERR("invalid format type %x\n", pRange->type);
6228 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6229 return NULL;
6232 base_type = pRange->flags_type & 0xf;
6234 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
6237 /***********************************************************************
6238 * NdrRangeUnmarshall [RPCRT4.@]
6240 unsigned char *WINAPI NdrRangeUnmarshall(
6241 PMIDL_STUB_MESSAGE pStubMsg,
6242 unsigned char **ppMemory,
6243 PFORMAT_STRING pFormat,
6244 unsigned char fMustAlloc)
6246 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6247 unsigned char base_type;
6249 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6251 if (pRange->type != RPC_FC_RANGE)
6253 ERR("invalid format type %x\n", pRange->type);
6254 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6255 return NULL;
6257 base_type = pRange->flags_type & 0xf;
6259 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
6260 base_type, pRange->low_value, pRange->high_value);
6262 #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
6263 do \
6265 ALIGN_POINTER(pStubMsg->Buffer, sizeof(wire_type)); \
6266 if (!fMustAlloc && !*ppMemory) \
6267 fMustAlloc = TRUE; \
6268 if (fMustAlloc) \
6269 *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
6270 if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
6272 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
6273 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
6274 RpcRaiseException(RPC_X_BAD_STUB_DATA); \
6276 if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
6277 (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
6279 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
6280 *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
6281 (mem_type)pRange->high_value); \
6282 RpcRaiseException(RPC_S_INVALID_BOUND); \
6283 return NULL; \
6285 TRACE("*ppMemory: %p\n", *ppMemory); \
6286 **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
6287 pStubMsg->Buffer += sizeof(wire_type); \
6288 } while (0)
6290 switch(base_type)
6292 case RPC_FC_CHAR:
6293 case RPC_FC_SMALL:
6294 RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
6295 TRACE("value: 0x%02x\n", **ppMemory);
6296 break;
6297 case RPC_FC_BYTE:
6298 case RPC_FC_USMALL:
6299 RANGE_UNMARSHALL(CHAR, CHAR, "%u");
6300 TRACE("value: 0x%02x\n", **ppMemory);
6301 break;
6302 case RPC_FC_WCHAR: /* FIXME: valid? */
6303 case RPC_FC_USHORT:
6304 RANGE_UNMARSHALL(USHORT, USHORT, "%u");
6305 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6306 break;
6307 case RPC_FC_SHORT:
6308 RANGE_UNMARSHALL(SHORT, SHORT, "%d");
6309 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6310 break;
6311 case RPC_FC_LONG:
6312 case RPC_FC_ENUM32:
6313 RANGE_UNMARSHALL(LONG, LONG, "%d");
6314 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6315 break;
6316 case RPC_FC_ULONG:
6317 RANGE_UNMARSHALL(ULONG, ULONG, "%u");
6318 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6319 break;
6320 case RPC_FC_ENUM16:
6321 RANGE_UNMARSHALL(UINT, USHORT, "%u");
6322 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6323 break;
6324 case RPC_FC_FLOAT:
6325 case RPC_FC_DOUBLE:
6326 case RPC_FC_HYPER:
6327 default:
6328 ERR("invalid range base type: 0x%02x\n", base_type);
6329 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6332 return NULL;
6335 /***********************************************************************
6336 * NdrRangeBufferSize [internal]
6338 static void WINAPI NdrRangeBufferSize(
6339 PMIDL_STUB_MESSAGE pStubMsg,
6340 unsigned char *pMemory,
6341 PFORMAT_STRING pFormat)
6343 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6344 unsigned char base_type;
6346 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6348 if (pRange->type != RPC_FC_RANGE)
6350 ERR("invalid format type %x\n", pRange->type);
6351 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6353 base_type = pRange->flags_type & 0xf;
6355 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
6358 /***********************************************************************
6359 * NdrRangeMemorySize [internal]
6361 static ULONG WINAPI NdrRangeMemorySize(
6362 PMIDL_STUB_MESSAGE pStubMsg,
6363 PFORMAT_STRING pFormat)
6365 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
6366 unsigned char base_type;
6368 if (pRange->type != RPC_FC_RANGE)
6370 ERR("invalid format type %x\n", pRange->type);
6371 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6372 return 0;
6374 base_type = pRange->flags_type & 0xf;
6376 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
6379 /***********************************************************************
6380 * NdrRangeFree [internal]
6382 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
6383 unsigned char *pMemory,
6384 PFORMAT_STRING pFormat)
6386 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6388 /* nothing to do */
6391 /***********************************************************************
6392 * NdrBaseTypeMarshall [internal]
6394 static unsigned char *WINAPI NdrBaseTypeMarshall(
6395 PMIDL_STUB_MESSAGE pStubMsg,
6396 unsigned char *pMemory,
6397 PFORMAT_STRING pFormat)
6399 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6401 switch(*pFormat)
6403 case RPC_FC_BYTE:
6404 case RPC_FC_CHAR:
6405 case RPC_FC_SMALL:
6406 case RPC_FC_USMALL:
6407 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
6408 TRACE("value: 0x%02x\n", *pMemory);
6409 break;
6410 case RPC_FC_WCHAR:
6411 case RPC_FC_SHORT:
6412 case RPC_FC_USHORT:
6413 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6414 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
6415 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
6416 break;
6417 case RPC_FC_LONG:
6418 case RPC_FC_ULONG:
6419 case RPC_FC_ERROR_STATUS_T:
6420 case RPC_FC_ENUM32:
6421 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG));
6422 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
6423 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
6424 break;
6425 case RPC_FC_FLOAT:
6426 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float));
6427 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
6428 break;
6429 case RPC_FC_DOUBLE:
6430 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double));
6431 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
6432 break;
6433 case RPC_FC_HYPER:
6434 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG));
6435 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
6436 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
6437 break;
6438 case RPC_FC_ENUM16:
6439 /* only 16-bits on the wire, so do a sanity check */
6440 if (*(UINT *)pMemory > SHRT_MAX)
6441 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
6442 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
6443 if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6444 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6445 *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
6446 pStubMsg->Buffer += sizeof(USHORT);
6447 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
6448 break;
6449 case RPC_FC_IGNORE:
6450 break;
6451 default:
6452 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6455 /* FIXME: what is the correct return value? */
6456 return NULL;
6459 /***********************************************************************
6460 * NdrBaseTypeUnmarshall [internal]
6462 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
6463 PMIDL_STUB_MESSAGE pStubMsg,
6464 unsigned char **ppMemory,
6465 PFORMAT_STRING pFormat,
6466 unsigned char fMustAlloc)
6468 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6470 #define BASE_TYPE_UNMARSHALL(type) \
6471 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
6472 if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
6474 *ppMemory = pStubMsg->Buffer; \
6475 TRACE("*ppMemory: %p\n", *ppMemory); \
6476 safe_buffer_increment(pStubMsg, sizeof(type)); \
6478 else \
6480 if (fMustAlloc) \
6481 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
6482 TRACE("*ppMemory: %p\n", *ppMemory); \
6483 safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \
6486 switch(*pFormat)
6488 case RPC_FC_BYTE:
6489 case RPC_FC_CHAR:
6490 case RPC_FC_SMALL:
6491 case RPC_FC_USMALL:
6492 BASE_TYPE_UNMARSHALL(UCHAR);
6493 TRACE("value: 0x%02x\n", **ppMemory);
6494 break;
6495 case RPC_FC_WCHAR:
6496 case RPC_FC_SHORT:
6497 case RPC_FC_USHORT:
6498 BASE_TYPE_UNMARSHALL(USHORT);
6499 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6500 break;
6501 case RPC_FC_LONG:
6502 case RPC_FC_ULONG:
6503 case RPC_FC_ERROR_STATUS_T:
6504 case RPC_FC_ENUM32:
6505 BASE_TYPE_UNMARSHALL(ULONG);
6506 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6507 break;
6508 case RPC_FC_FLOAT:
6509 BASE_TYPE_UNMARSHALL(float);
6510 TRACE("value: %f\n", **(float **)ppMemory);
6511 break;
6512 case RPC_FC_DOUBLE:
6513 BASE_TYPE_UNMARSHALL(double);
6514 TRACE("value: %f\n", **(double **)ppMemory);
6515 break;
6516 case RPC_FC_HYPER:
6517 BASE_TYPE_UNMARSHALL(ULONGLONG);
6518 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
6519 break;
6520 case RPC_FC_ENUM16:
6521 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6522 if (!fMustAlloc && !*ppMemory)
6523 fMustAlloc = TRUE;
6524 if (fMustAlloc)
6525 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
6526 if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
6527 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6528 TRACE("*ppMemory: %p\n", *ppMemory);
6529 /* 16-bits on the wire, but int in memory */
6530 **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
6531 pStubMsg->Buffer += sizeof(USHORT);
6532 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6533 break;
6534 case RPC_FC_IGNORE:
6535 break;
6536 default:
6537 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6539 #undef BASE_TYPE_UNMARSHALL
6541 /* FIXME: what is the correct return value? */
6543 return NULL;
6546 /***********************************************************************
6547 * NdrBaseTypeBufferSize [internal]
6549 static void WINAPI NdrBaseTypeBufferSize(
6550 PMIDL_STUB_MESSAGE pStubMsg,
6551 unsigned char *pMemory,
6552 PFORMAT_STRING pFormat)
6554 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6556 switch(*pFormat)
6558 case RPC_FC_BYTE:
6559 case RPC_FC_CHAR:
6560 case RPC_FC_SMALL:
6561 case RPC_FC_USMALL:
6562 safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6563 break;
6564 case RPC_FC_WCHAR:
6565 case RPC_FC_SHORT:
6566 case RPC_FC_USHORT:
6567 case RPC_FC_ENUM16:
6568 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
6569 safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6570 break;
6571 case RPC_FC_LONG:
6572 case RPC_FC_ULONG:
6573 case RPC_FC_ENUM32:
6574 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
6575 safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6576 break;
6577 case RPC_FC_FLOAT:
6578 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
6579 safe_buffer_length_increment(pStubMsg, sizeof(float));
6580 break;
6581 case RPC_FC_DOUBLE:
6582 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
6583 safe_buffer_length_increment(pStubMsg, sizeof(double));
6584 break;
6585 case RPC_FC_HYPER:
6586 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
6587 safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6588 break;
6589 case RPC_FC_ERROR_STATUS_T:
6590 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
6591 safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6592 break;
6593 case RPC_FC_IGNORE:
6594 break;
6595 default:
6596 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6600 /***********************************************************************
6601 * NdrBaseTypeMemorySize [internal]
6603 static ULONG WINAPI NdrBaseTypeMemorySize(
6604 PMIDL_STUB_MESSAGE pStubMsg,
6605 PFORMAT_STRING pFormat)
6607 TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6609 switch(*pFormat)
6611 case RPC_FC_BYTE:
6612 case RPC_FC_CHAR:
6613 case RPC_FC_SMALL:
6614 case RPC_FC_USMALL:
6615 safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6616 pStubMsg->MemorySize += sizeof(UCHAR);
6617 return sizeof(UCHAR);
6618 case RPC_FC_WCHAR:
6619 case RPC_FC_SHORT:
6620 case RPC_FC_USHORT:
6621 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6622 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6623 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(USHORT));
6624 pStubMsg->MemorySize += sizeof(USHORT);
6625 return sizeof(USHORT);
6626 case RPC_FC_LONG:
6627 case RPC_FC_ULONG:
6628 case RPC_FC_ENUM32:
6629 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
6630 safe_buffer_increment(pStubMsg, sizeof(ULONG));
6631 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONG));
6632 pStubMsg->MemorySize += sizeof(ULONG);
6633 return sizeof(ULONG);
6634 case RPC_FC_FLOAT:
6635 ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
6636 safe_buffer_increment(pStubMsg, sizeof(float));
6637 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(float));
6638 pStubMsg->MemorySize += sizeof(float);
6639 return sizeof(float);
6640 case RPC_FC_DOUBLE:
6641 ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
6642 safe_buffer_increment(pStubMsg, sizeof(double));
6643 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(double));
6644 pStubMsg->MemorySize += sizeof(double);
6645 return sizeof(double);
6646 case RPC_FC_HYPER:
6647 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
6648 safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6649 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONGLONG));
6650 pStubMsg->MemorySize += sizeof(ULONGLONG);
6651 return sizeof(ULONGLONG);
6652 case RPC_FC_ERROR_STATUS_T:
6653 ALIGN_POINTER(pStubMsg->Buffer, sizeof(error_status_t));
6654 safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6655 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(error_status_t));
6656 pStubMsg->MemorySize += sizeof(error_status_t);
6657 return sizeof(error_status_t);
6658 case RPC_FC_ENUM16:
6659 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
6660 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6661 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(UINT));
6662 pStubMsg->MemorySize += sizeof(UINT);
6663 return sizeof(UINT);
6664 case RPC_FC_IGNORE:
6665 ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
6666 pStubMsg->MemorySize += sizeof(void *);
6667 return sizeof(void *);
6668 default:
6669 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6670 return 0;
6674 /***********************************************************************
6675 * NdrBaseTypeFree [internal]
6677 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6678 unsigned char *pMemory,
6679 PFORMAT_STRING pFormat)
6681 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6683 /* nothing to do */
6686 /***********************************************************************
6687 * NdrContextHandleBufferSize [internal]
6689 static void WINAPI NdrContextHandleBufferSize(
6690 PMIDL_STUB_MESSAGE pStubMsg,
6691 unsigned char *pMemory,
6692 PFORMAT_STRING pFormat)
6694 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6696 if (*pFormat != RPC_FC_BIND_CONTEXT)
6698 ERR("invalid format type %x\n", *pFormat);
6699 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6701 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
6702 safe_buffer_length_increment(pStubMsg, cbNDRContext);
6705 /***********************************************************************
6706 * NdrContextHandleMarshall [internal]
6708 static unsigned char *WINAPI NdrContextHandleMarshall(
6709 PMIDL_STUB_MESSAGE pStubMsg,
6710 unsigned char *pMemory,
6711 PFORMAT_STRING pFormat)
6713 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6715 if (*pFormat != RPC_FC_BIND_CONTEXT)
6717 ERR("invalid format type %x\n", *pFormat);
6718 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6720 TRACE("flags: 0x%02x\n", pFormat[1]);
6722 if (pStubMsg->IsClient)
6724 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6725 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6726 else
6727 NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
6729 else
6731 NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
6732 NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
6733 NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
6736 return NULL;
6739 /***********************************************************************
6740 * NdrContextHandleUnmarshall [internal]
6742 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6743 PMIDL_STUB_MESSAGE pStubMsg,
6744 unsigned char **ppMemory,
6745 PFORMAT_STRING pFormat,
6746 unsigned char fMustAlloc)
6748 TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg,
6749 ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE");
6751 if (*pFormat != RPC_FC_BIND_CONTEXT)
6753 ERR("invalid format type %x\n", *pFormat);
6754 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6756 TRACE("flags: 0x%02x\n", pFormat[1]);
6758 if (pStubMsg->IsClient)
6760 /* [out]-only or [ret] param */
6761 if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT)
6762 **(NDR_CCONTEXT **)ppMemory = NULL;
6763 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
6765 else
6767 NDR_SCONTEXT ctxt;
6768 ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat);
6769 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6770 *(void **)ppMemory = NDRSContextValue(ctxt);
6771 else
6772 *(void **)ppMemory = *NDRSContextValue(ctxt);
6775 return NULL;
6778 /***********************************************************************
6779 * NdrClientContextMarshall [RPCRT4.@]
6781 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6782 NDR_CCONTEXT ContextHandle,
6783 int fCheck)
6785 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
6787 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
6789 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6791 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6792 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6793 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6796 /* FIXME: what does fCheck do? */
6797 NDRCContextMarshall(ContextHandle,
6798 pStubMsg->Buffer);
6800 pStubMsg->Buffer += cbNDRContext;
6803 /***********************************************************************
6804 * NdrClientContextUnmarshall [RPCRT4.@]
6806 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6807 NDR_CCONTEXT * pContextHandle,
6808 RPC_BINDING_HANDLE BindHandle)
6810 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
6812 ALIGN_POINTER(pStubMsg->Buffer, 4);
6814 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
6815 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6817 NDRCContextUnmarshall(pContextHandle,
6818 BindHandle,
6819 pStubMsg->Buffer,
6820 pStubMsg->RpcMsg->DataRepresentation);
6822 pStubMsg->Buffer += cbNDRContext;
6825 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6826 NDR_SCONTEXT ContextHandle,
6827 NDR_RUNDOWN RundownRoutine )
6829 TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
6831 ALIGN_POINTER(pStubMsg->Buffer, 4);
6833 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6835 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6836 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6837 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6840 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6841 pStubMsg->Buffer, RundownRoutine, NULL,
6842 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6843 pStubMsg->Buffer += cbNDRContext;
6846 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
6848 NDR_SCONTEXT ContextHandle;
6850 TRACE("(%p)\n", pStubMsg);
6852 ALIGN_POINTER(pStubMsg->Buffer, 4);
6854 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6856 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6857 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6858 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6861 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6862 pStubMsg->Buffer,
6863 pStubMsg->RpcMsg->DataRepresentation,
6864 NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6865 pStubMsg->Buffer += cbNDRContext;
6867 return ContextHandle;
6870 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
6871 unsigned char* pMemory,
6872 PFORMAT_STRING pFormat)
6874 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
6877 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
6878 PFORMAT_STRING pFormat)
6880 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6881 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6883 TRACE("(%p, %p)\n", pStubMsg, pFormat);
6885 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6886 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6887 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6888 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6889 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6891 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6892 if_id = &sif->InterfaceId;
6895 return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
6896 pStubMsg->RpcMsg->DataRepresentation, if_id,
6897 flags);
6900 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6901 NDR_SCONTEXT ContextHandle,
6902 NDR_RUNDOWN RundownRoutine,
6903 PFORMAT_STRING pFormat)
6905 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6906 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6908 TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
6910 ALIGN_POINTER(pStubMsg->Buffer, 4);
6912 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6914 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6915 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6916 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6919 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6920 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6921 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6922 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6923 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6925 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6926 if_id = &sif->InterfaceId;
6929 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6930 pStubMsg->Buffer, RundownRoutine, if_id, flags);
6931 pStubMsg->Buffer += cbNDRContext;
6934 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6935 PFORMAT_STRING pFormat)
6937 NDR_SCONTEXT ContextHandle;
6938 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6939 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6941 TRACE("(%p, %p)\n", pStubMsg, pFormat);
6943 ALIGN_POINTER(pStubMsg->Buffer, 4);
6945 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6947 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6948 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6949 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6952 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6953 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6954 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6955 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6956 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6958 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6959 if_id = &sif->InterfaceId;
6962 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6963 pStubMsg->Buffer,
6964 pStubMsg->RpcMsg->DataRepresentation,
6965 if_id, flags);
6966 pStubMsg->Buffer += cbNDRContext;
6968 return ContextHandle;
6971 /***********************************************************************
6972 * NdrCorrelationInitialize [RPCRT4.@]
6974 * Initializes correlation validity checking.
6976 * PARAMS
6977 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
6978 * pMemory [I] Pointer to memory to use as a cache.
6979 * CacheSize [I] Size of the memory pointed to by pMemory.
6980 * Flags [I] Reserved. Set to zero.
6982 * RETURNS
6983 * Nothing.
6985 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
6987 FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
6988 pStubMsg->fHasNewCorrDesc = TRUE;
6991 /***********************************************************************
6992 * NdrCorrelationPass [RPCRT4.@]
6994 * Performs correlation validity checking.
6996 * PARAMS
6997 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
6999 * RETURNS
7000 * Nothing.
7002 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
7004 FIXME("(%p): stub\n", pStubMsg);
7007 /***********************************************************************
7008 * NdrCorrelationFree [RPCRT4.@]
7010 * Frees any resources used while unmarshalling parameters that need
7011 * correlation validity checking.
7013 * PARAMS
7014 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7016 * RETURNS
7017 * Nothing.
7019 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
7021 FIXME("(%p): stub\n", pStubMsg);