push b5232b2081a0e20e4bf07d6ded424d0101e4a589
[wine/hacks.git] / dlls / rpcrt4 / ndr_marshall.c
blobe238daea2d9392b7e5d64096fa22479753395522
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 * - Non-conformant strings
23 * - String structs
24 * - Byte count pointers
25 * - transmit_as/represent as
26 * - Multi-dimensional arrays
27 * - Conversion functions (NdrConvert)
28 * - Checks for integer addition overflow
29 * - Checks for out-of-memory conditions
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <limits.h>
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winerror.h"
42 #include "ndr_misc.h"
43 #include "rpcndr.h"
45 #include "wine/unicode.h"
46 #include "wine/rpcfc.h"
48 #include "wine/debug.h"
49 #include "wine/list.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(ole);
53 #if defined(__i386__)
54 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
55 (*((UINT32 *)(pchar)) = (uint32))
57 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
58 (*((UINT32 *)(pchar)))
59 #else
60 /* these would work for i386 too, but less efficient */
61 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
62 (*(pchar) = LOBYTE(LOWORD(uint32)), \
63 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
64 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
65 *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
66 (uint32)) /* allow as r-value */
68 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
69 (MAKELONG( \
70 MAKEWORD(*(pchar), *((pchar)+1)), \
71 MAKEWORD(*((pchar)+2), *((pchar)+3))))
72 #endif
74 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
75 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
76 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
77 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
78 *(pchar) = HIBYTE(HIWORD(uint32)), \
79 (uint32)) /* allow as r-value */
81 #define BIG_ENDIAN_UINT32_READ(pchar) \
82 (MAKELONG( \
83 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
84 MAKEWORD(*((pchar)+1), *(pchar))))
86 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
87 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
88 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
89 # define NDR_LOCAL_UINT32_READ(pchar) \
90 BIG_ENDIAN_UINT32_READ(pchar)
91 #else
92 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
93 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
94 # define NDR_LOCAL_UINT32_READ(pchar) \
95 LITTLE_ENDIAN_UINT32_READ(pchar)
96 #endif
98 /* _Align must be the desired alignment,
99 * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
100 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
101 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
102 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
103 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
105 #define STD_OVERFLOW_CHECK(_Msg) do { \
106 TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
107 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
108 ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
109 } while (0)
111 #define NDR_TABLE_SIZE 128
112 #define NDR_TABLE_MASK 127
114 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
115 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
116 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
117 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
118 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
120 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
121 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
122 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
124 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
126 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
127 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
128 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
129 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
130 /* 0x10 */
131 NdrBaseTypeMarshall,
132 /* 0x11 */
133 NdrPointerMarshall, NdrPointerMarshall,
134 NdrPointerMarshall, NdrPointerMarshall,
135 /* 0x15 */
136 NdrSimpleStructMarshall, NdrSimpleStructMarshall,
137 NdrConformantStructMarshall, NdrConformantStructMarshall,
138 NdrConformantVaryingStructMarshall,
139 NdrComplexStructMarshall,
140 /* 0x1b */
141 NdrConformantArrayMarshall,
142 NdrConformantVaryingArrayMarshall,
143 NdrFixedArrayMarshall, NdrFixedArrayMarshall,
144 NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
145 NdrComplexArrayMarshall,
146 /* 0x22 */
147 NdrConformantStringMarshall, 0, 0,
148 NdrConformantStringMarshall,
149 NdrNonConformantStringMarshall, 0, 0, 0,
150 /* 0x2a */
151 NdrEncapsulatedUnionMarshall,
152 NdrNonEncapsulatedUnionMarshall,
153 NdrByteCountPointerMarshall,
154 NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
155 /* 0x2f */
156 NdrInterfacePointerMarshall,
157 /* 0x30 */
158 NdrContextHandleMarshall,
159 /* 0xb1 */
160 0, 0, 0,
161 NdrUserMarshalMarshall,
162 0, 0,
163 /* 0xb7 */
164 NdrRangeMarshall
166 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
168 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
169 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
170 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
171 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
172 /* 0x10 */
173 NdrBaseTypeUnmarshall,
174 /* 0x11 */
175 NdrPointerUnmarshall, NdrPointerUnmarshall,
176 NdrPointerUnmarshall, NdrPointerUnmarshall,
177 /* 0x15 */
178 NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
179 NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
180 NdrConformantVaryingStructUnmarshall,
181 NdrComplexStructUnmarshall,
182 /* 0x1b */
183 NdrConformantArrayUnmarshall,
184 NdrConformantVaryingArrayUnmarshall,
185 NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
186 NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
187 NdrComplexArrayUnmarshall,
188 /* 0x22 */
189 NdrConformantStringUnmarshall, 0, 0,
190 NdrConformantStringUnmarshall,
191 NdrNonConformantStringUnmarshall, 0, 0, 0,
192 /* 0x2a */
193 NdrEncapsulatedUnionUnmarshall,
194 NdrNonEncapsulatedUnionUnmarshall,
195 NdrByteCountPointerUnmarshall,
196 NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
197 /* 0x2f */
198 NdrInterfacePointerUnmarshall,
199 /* 0x30 */
200 NdrContextHandleUnmarshall,
201 /* 0xb1 */
202 0, 0, 0,
203 NdrUserMarshalUnmarshall,
204 0, 0,
205 /* 0xb7 */
206 NdrRangeUnmarshall
208 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
210 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
211 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
212 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
213 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
214 /* 0x10 */
215 NdrBaseTypeBufferSize,
216 /* 0x11 */
217 NdrPointerBufferSize, NdrPointerBufferSize,
218 NdrPointerBufferSize, NdrPointerBufferSize,
219 /* 0x15 */
220 NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
221 NdrConformantStructBufferSize, NdrConformantStructBufferSize,
222 NdrConformantVaryingStructBufferSize,
223 NdrComplexStructBufferSize,
224 /* 0x1b */
225 NdrConformantArrayBufferSize,
226 NdrConformantVaryingArrayBufferSize,
227 NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
228 NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
229 NdrComplexArrayBufferSize,
230 /* 0x22 */
231 NdrConformantStringBufferSize, 0, 0,
232 NdrConformantStringBufferSize,
233 NdrNonConformantStringBufferSize, 0, 0, 0,
234 /* 0x2a */
235 NdrEncapsulatedUnionBufferSize,
236 NdrNonEncapsulatedUnionBufferSize,
237 NdrByteCountPointerBufferSize,
238 NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
239 /* 0x2f */
240 NdrInterfacePointerBufferSize,
241 /* 0x30 */
242 NdrContextHandleBufferSize,
243 /* 0xb1 */
244 0, 0, 0,
245 NdrUserMarshalBufferSize,
246 0, 0,
247 /* 0xb7 */
248 NdrRangeBufferSize
250 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
252 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
253 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
254 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
255 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
256 /* 0x10 */
257 NdrBaseTypeMemorySize,
258 /* 0x11 */
259 NdrPointerMemorySize, NdrPointerMemorySize,
260 NdrPointerMemorySize, NdrPointerMemorySize,
261 /* 0x15 */
262 NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
263 NdrConformantStructMemorySize, NdrConformantStructMemorySize,
264 NdrConformantVaryingStructMemorySize,
265 NdrComplexStructMemorySize,
266 /* 0x1b */
267 NdrConformantArrayMemorySize,
268 NdrConformantVaryingArrayMemorySize,
269 NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
270 NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
271 NdrComplexArrayMemorySize,
272 /* 0x22 */
273 NdrConformantStringMemorySize, 0, 0,
274 NdrConformantStringMemorySize,
275 NdrNonConformantStringMemorySize, 0, 0, 0,
276 /* 0x2a */
277 NdrEncapsulatedUnionMemorySize,
278 NdrNonEncapsulatedUnionMemorySize,
279 NdrByteCountPointerMemorySize,
280 NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
281 /* 0x2f */
282 NdrInterfacePointerMemorySize,
283 /* 0x30 */
285 /* 0xb1 */
286 0, 0, 0,
287 NdrUserMarshalMemorySize,
288 0, 0,
289 /* 0xb7 */
290 NdrRangeMemorySize
292 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
294 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
295 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
296 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
297 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
298 /* 0x10 */
299 NdrBaseTypeFree,
300 /* 0x11 */
301 NdrPointerFree, NdrPointerFree,
302 NdrPointerFree, NdrPointerFree,
303 /* 0x15 */
304 NdrSimpleStructFree, NdrSimpleStructFree,
305 NdrConformantStructFree, NdrConformantStructFree,
306 NdrConformantVaryingStructFree,
307 NdrComplexStructFree,
308 /* 0x1b */
309 NdrConformantArrayFree,
310 NdrConformantVaryingArrayFree,
311 NdrFixedArrayFree, NdrFixedArrayFree,
312 NdrVaryingArrayFree, NdrVaryingArrayFree,
313 NdrComplexArrayFree,
314 /* 0x22 */
315 0, 0, 0,
316 0, 0, 0, 0, 0,
317 /* 0x2a */
318 NdrEncapsulatedUnionFree,
319 NdrNonEncapsulatedUnionFree,
321 NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
322 /* 0x2f */
323 NdrInterfacePointerFree,
324 /* 0x30 */
326 /* 0xb1 */
327 0, 0, 0,
328 NdrUserMarshalFree,
329 0, 0,
330 /* 0xb7 */
331 NdrRangeFree
334 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
336 /* hmm, this is probably supposed to do more? */
337 return pStubMsg->pfnAllocate(len);
340 static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
342 pStubMsg->pfnFree(Pointer);
345 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
347 return (*(const ULONG *)pFormat != -1);
350 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
352 ALIGN_POINTER(pStubMsg->Buffer, 4);
353 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
354 RpcRaiseException(RPC_X_BAD_STUB_DATA);
355 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
356 pStubMsg->Buffer += 4;
357 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
358 if (pStubMsg->fHasNewCorrDesc)
359 return pFormat+6;
360 else
361 return pFormat+4;
364 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
366 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
368 pStubMsg->Offset = 0;
369 pStubMsg->ActualCount = pStubMsg->MaxCount;
370 goto done;
373 ALIGN_POINTER(pStubMsg->Buffer, 4);
374 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
375 RpcRaiseException(RPC_X_BAD_STUB_DATA);
376 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
377 pStubMsg->Buffer += 4;
378 TRACE("offset is %d\n", pStubMsg->Offset);
379 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
380 pStubMsg->Buffer += 4;
381 TRACE("variance is %d\n", pStubMsg->ActualCount);
383 if ((pStubMsg->ActualCount > MaxValue) ||
384 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
386 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
387 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
388 RpcRaiseException(RPC_S_INVALID_BOUND);
389 return NULL;
392 done:
393 if (pStubMsg->fHasNewCorrDesc)
394 return pFormat+6;
395 else
396 return pFormat+4;
399 /* writes the conformance value to the buffer */
400 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
402 ALIGN_POINTER(pStubMsg->Buffer, 4);
403 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
404 pStubMsg->Buffer += 4;
407 /* writes the variance values to the buffer */
408 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
410 ALIGN_POINTER(pStubMsg->Buffer, 4);
411 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
412 pStubMsg->Buffer += 4;
413 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
414 pStubMsg->Buffer += 4;
417 /* requests buffer space for the conformance value */
418 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
420 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
421 pStubMsg->BufferLength += 4;
424 /* requests buffer space for the variance values */
425 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
427 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
428 pStubMsg->BufferLength += 8;
431 PFORMAT_STRING ComputeConformanceOrVariance(
432 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
433 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
435 BYTE dtype = pFormat[0] & 0xf;
436 short ofs = *(const short *)&pFormat[2];
437 LPVOID ptr = NULL;
438 DWORD data = 0;
440 if (!IsConformanceOrVariancePresent(pFormat)) {
441 /* null descriptor */
442 *pCount = def;
443 goto finish_conf;
446 switch (pFormat[0] & 0xf0) {
447 case RPC_FC_NORMAL_CONFORMANCE:
448 TRACE("normal conformance, ofs=%d\n", ofs);
449 ptr = pMemory;
450 break;
451 case RPC_FC_POINTER_CONFORMANCE:
452 TRACE("pointer conformance, ofs=%d\n", ofs);
453 ptr = pStubMsg->Memory;
454 break;
455 case RPC_FC_TOP_LEVEL_CONFORMANCE:
456 TRACE("toplevel conformance, ofs=%d\n", ofs);
457 if (pStubMsg->StackTop) {
458 ptr = pStubMsg->StackTop;
460 else {
461 /* -Os mode, *pCount is already set */
462 goto finish_conf;
464 break;
465 case RPC_FC_CONSTANT_CONFORMANCE:
466 data = ofs | ((DWORD)pFormat[1] << 16);
467 TRACE("constant conformance, val=%d\n", data);
468 *pCount = data;
469 goto finish_conf;
470 case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
471 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
472 if (pStubMsg->StackTop) {
473 ptr = pStubMsg->StackTop;
475 else {
476 /* ? */
477 goto done_conf_grab;
479 break;
480 default:
481 FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
484 switch (pFormat[1]) {
485 case RPC_FC_DEREFERENCE:
486 ptr = *(LPVOID*)((char *)ptr + ofs);
487 break;
488 case RPC_FC_CALLBACK:
490 unsigned char *old_stack_top = pStubMsg->StackTop;
491 pStubMsg->StackTop = ptr;
493 /* ofs is index into StubDesc->apfnExprEval */
494 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
495 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
497 pStubMsg->StackTop = old_stack_top;
499 /* the callback function always stores the computed value in MaxCount */
500 *pCount = pStubMsg->MaxCount;
501 goto finish_conf;
503 default:
504 ptr = (char *)ptr + ofs;
505 break;
508 switch (dtype) {
509 case RPC_FC_LONG:
510 case RPC_FC_ULONG:
511 data = *(DWORD*)ptr;
512 break;
513 case RPC_FC_SHORT:
514 data = *(SHORT*)ptr;
515 break;
516 case RPC_FC_USHORT:
517 data = *(USHORT*)ptr;
518 break;
519 case RPC_FC_CHAR:
520 case RPC_FC_SMALL:
521 data = *(CHAR*)ptr;
522 break;
523 case RPC_FC_BYTE:
524 case RPC_FC_USMALL:
525 data = *(UCHAR*)ptr;
526 break;
527 default:
528 FIXME("unknown conformance data type %x\n", dtype);
529 goto done_conf_grab;
531 TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
533 done_conf_grab:
534 switch (pFormat[1]) {
535 case RPC_FC_DEREFERENCE: /* already handled */
536 case 0: /* no op */
537 *pCount = data;
538 break;
539 case RPC_FC_ADD_1:
540 *pCount = data + 1;
541 break;
542 case RPC_FC_SUB_1:
543 *pCount = data - 1;
544 break;
545 case RPC_FC_MULT_2:
546 *pCount = data * 2;
547 break;
548 case RPC_FC_DIV_2:
549 *pCount = data / 2;
550 break;
551 default:
552 FIXME("unknown conformance op %d\n", pFormat[1]);
553 goto finish_conf;
556 finish_conf:
557 TRACE("resulting conformance is %ld\n", *pCount);
558 if (pStubMsg->fHasNewCorrDesc)
559 return pFormat+6;
560 else
561 return pFormat+4;
564 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
565 * the result overflows 32-bits */
566 static inline ULONG safe_multiply(ULONG a, ULONG b)
568 ULONGLONG ret = (ULONGLONG)a * b;
569 if (ret > 0xffffffff)
571 RpcRaiseException(RPC_S_INVALID_BOUND);
572 return 0;
574 return ret;
577 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
579 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
580 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
581 RpcRaiseException(RPC_X_BAD_STUB_DATA);
582 pStubMsg->Buffer += size;
585 /* copies data from the buffer, checking that there is enough data in the buffer
586 * to do so */
587 static inline void safe_buffer_copy(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
589 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
590 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
591 RpcRaiseException(RPC_X_BAD_STUB_DATA);
592 memcpy(p, pStubMsg->Buffer, size);
593 pStubMsg->Buffer += size;
597 * NdrConformantString:
599 * What MS calls a ConformantString is, in DCE terminology,
600 * a Varying-Conformant String.
602 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
603 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
604 * into unmarshalled string)
605 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
606 * [
607 * data: CHARTYPE[maxlen]
608 * ]
609 * ], where CHARTYPE is the appropriate character type (specified externally)
613 /***********************************************************************
614 * NdrConformantStringMarshall [RPCRT4.@]
616 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
617 unsigned char *pszMessage, PFORMAT_STRING pFormat)
619 ULONG esize, size;
621 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
623 if (*pFormat == RPC_FC_C_CSTRING) {
624 TRACE("string=%s\n", debugstr_a((char*)pszMessage));
625 pStubMsg->ActualCount = strlen((char*)pszMessage)+1;
626 esize = 1;
628 else if (*pFormat == RPC_FC_C_WSTRING) {
629 TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
630 pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1;
631 esize = 2;
633 else {
634 ERR("Unhandled string type: %#x\n", *pFormat);
635 /* FIXME: raise an exception. */
636 return NULL;
639 if (pFormat[1] == RPC_FC_STRING_SIZED)
640 pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0);
641 else
642 pStubMsg->MaxCount = pStubMsg->ActualCount;
643 pStubMsg->Offset = 0;
644 WriteConformance(pStubMsg);
645 WriteVariance(pStubMsg);
647 size = safe_multiply(esize, pStubMsg->ActualCount);
648 memcpy(pStubMsg->Buffer, pszMessage, size); /* the string itself */
649 pStubMsg->Buffer += size;
651 STD_OVERFLOW_CHECK(pStubMsg);
653 /* success */
654 return NULL; /* is this always right? */
657 /***********************************************************************
658 * NdrConformantStringBufferSize [RPCRT4.@]
660 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
661 unsigned char* pMemory, PFORMAT_STRING pFormat)
663 ULONG esize;
665 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
667 SizeConformance(pStubMsg);
668 SizeVariance(pStubMsg);
670 if (*pFormat == RPC_FC_C_CSTRING) {
671 TRACE("string=%s\n", debugstr_a((char*)pMemory));
672 pStubMsg->ActualCount = strlen((char*)pMemory)+1;
673 esize = 1;
675 else if (*pFormat == RPC_FC_C_WSTRING) {
676 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
677 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1;
678 esize = 2;
680 else {
681 ERR("Unhandled string type: %#x\n", *pFormat);
682 /* FIXME: raise an exception */
683 return;
686 if (pFormat[1] == RPC_FC_STRING_SIZED)
687 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
688 else
689 pStubMsg->MaxCount = pStubMsg->ActualCount;
691 pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
694 /************************************************************************
695 * NdrConformantStringMemorySize [RPCRT4.@]
697 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
698 PFORMAT_STRING pFormat )
700 ULONG rslt = 0;
702 FIXME("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
704 assert(pStubMsg && pFormat);
706 if (*pFormat == RPC_FC_C_CSTRING) {
707 rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
709 else if (*pFormat == RPC_FC_C_WSTRING) {
710 rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */
712 else {
713 ERR("Unhandled string type: %#x\n", *pFormat);
714 /* FIXME: raise an exception */
717 if (pFormat[1] != RPC_FC_PAD) {
718 FIXME("sized string format=%d\n", pFormat[1]);
721 TRACE(" --> %u\n", rslt);
722 return rslt;
725 /************************************************************************
726 * NdrConformantStringUnmarshall [RPCRT4.@]
728 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
729 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
731 ULONG bufsize, memsize, esize, i;
733 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
734 pStubMsg, *ppMemory, pFormat, fMustAlloc);
736 assert(pFormat && ppMemory && pStubMsg);
738 ReadConformance(pStubMsg, NULL);
739 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
741 if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
742 else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
743 else {
744 ERR("Unhandled string type: %#x\n", *pFormat);
745 /* FIXME: raise an exception */
746 esize = 0;
749 memsize = safe_multiply(esize, pStubMsg->MaxCount);
750 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
752 /* strings must always have null terminating bytes */
753 if (bufsize < esize)
755 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
756 RpcRaiseException(RPC_S_INVALID_BOUND);
757 return NULL;
760 /* verify the buffer is safe to access */
761 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
762 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
764 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
765 pStubMsg->BufferEnd, pStubMsg->Buffer);
766 RpcRaiseException(RPC_X_BAD_STUB_DATA);
767 return NULL;
770 for (i = bufsize - esize; i < bufsize; i++)
771 if (pStubMsg->Buffer[i] != 0)
773 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
774 i, pStubMsg->Buffer[i]);
775 RpcRaiseException(RPC_S_INVALID_BOUND);
776 return NULL;
779 if (fMustAlloc || !*ppMemory)
780 *ppMemory = NdrAllocate(pStubMsg, memsize);
782 safe_buffer_copy(pStubMsg, *ppMemory, bufsize);
784 if (*pFormat == RPC_FC_C_CSTRING) {
785 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
787 else if (*pFormat == RPC_FC_C_WSTRING) {
788 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
791 return NULL; /* FIXME: is this always right? */
794 /***********************************************************************
795 * NdrNonConformantStringMarshall [RPCRT4.@]
797 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
798 unsigned char *pMemory,
799 PFORMAT_STRING pFormat)
801 FIXME("stub\n");
802 return NULL;
805 /***********************************************************************
806 * NdrNonConformantStringUnmarshall [RPCRT4.@]
808 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
809 unsigned char **ppMemory,
810 PFORMAT_STRING pFormat,
811 unsigned char fMustAlloc)
813 FIXME("stub\n");
814 return NULL;
817 /***********************************************************************
818 * NdrNonConformantStringBufferSize [RPCRT4.@]
820 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
821 unsigned char *pMemory,
822 PFORMAT_STRING pFormat)
824 FIXME("stub\n");
827 /***********************************************************************
828 * NdrNonConformantStringMemorySize [RPCRT4.@]
830 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
831 PFORMAT_STRING pFormat)
833 FIXME("stub\n");
834 return 0;
837 static inline void dump_pointer_attr(unsigned char attr)
839 if (attr & RPC_FC_P_ALLOCALLNODES)
840 TRACE(" RPC_FC_P_ALLOCALLNODES");
841 if (attr & RPC_FC_P_DONTFREE)
842 TRACE(" RPC_FC_P_DONTFREE");
843 if (attr & RPC_FC_P_ONSTACK)
844 TRACE(" RPC_FC_P_ONSTACK");
845 if (attr & RPC_FC_P_SIMPLEPOINTER)
846 TRACE(" RPC_FC_P_SIMPLEPOINTER");
847 if (attr & RPC_FC_P_DEREF)
848 TRACE(" RPC_FC_P_DEREF");
849 TRACE("\n");
852 /***********************************************************************
853 * PointerMarshall [internal]
855 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
856 unsigned char *Buffer,
857 unsigned char *Pointer,
858 PFORMAT_STRING pFormat)
860 unsigned type = pFormat[0], attr = pFormat[1];
861 PFORMAT_STRING desc;
862 NDR_MARSHALL m;
863 ULONG pointer_id;
864 int pointer_needs_marshaling;
866 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
867 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
868 pFormat += 2;
869 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
870 else desc = pFormat + *(const SHORT*)pFormat;
872 switch (type) {
873 case RPC_FC_RP: /* ref pointer (always non-null) */
874 #if 0 /* this causes problems for InstallShield so is disabled - we need more tests */
875 if (!Pointer)
876 RpcRaiseException(RPC_X_NULL_REF_POINTER);
877 #endif
878 pointer_needs_marshaling = 1;
879 break;
880 case RPC_FC_UP: /* unique pointer */
881 case RPC_FC_OP: /* object pointer - same as unique here */
882 if (Pointer)
883 pointer_needs_marshaling = 1;
884 else
885 pointer_needs_marshaling = 0;
886 pointer_id = (ULONG)Pointer;
887 TRACE("writing 0x%08x to buffer\n", pointer_id);
888 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
889 break;
890 case RPC_FC_FP:
891 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
892 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
893 TRACE("writing 0x%08x to buffer\n", pointer_id);
894 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
895 break;
896 default:
897 FIXME("unhandled ptr type=%02x\n", type);
898 RpcRaiseException(RPC_X_BAD_STUB_DATA);
899 return;
902 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
904 if (pointer_needs_marshaling) {
905 if (attr & RPC_FC_P_DEREF) {
906 Pointer = *(unsigned char**)Pointer;
907 TRACE("deref => %p\n", Pointer);
909 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
910 if (m) m(pStubMsg, Pointer, desc);
911 else FIXME("no marshaller for data type=%02x\n", *desc);
914 STD_OVERFLOW_CHECK(pStubMsg);
917 /***********************************************************************
918 * PointerUnmarshall [internal]
920 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
921 unsigned char *Buffer,
922 unsigned char **pPointer,
923 PFORMAT_STRING pFormat,
924 unsigned char fMustAlloc)
926 unsigned type = pFormat[0], attr = pFormat[1];
927 PFORMAT_STRING desc;
928 NDR_UNMARSHALL m;
929 DWORD pointer_id = 0;
930 int pointer_needs_unmarshaling;
932 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc);
933 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
934 pFormat += 2;
935 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
936 else desc = pFormat + *(const SHORT*)pFormat;
938 switch (type) {
939 case RPC_FC_RP: /* ref pointer (always non-null) */
940 pointer_needs_unmarshaling = 1;
941 break;
942 case RPC_FC_UP: /* unique pointer */
943 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
944 TRACE("pointer_id is 0x%08x\n", pointer_id);
945 if (pointer_id)
946 pointer_needs_unmarshaling = 1;
947 else {
948 *pPointer = NULL;
949 pointer_needs_unmarshaling = 0;
951 break;
952 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
953 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
954 TRACE("pointer_id is 0x%08x\n", pointer_id);
955 if (!fMustAlloc && *pPointer)
957 FIXME("free object pointer %p\n", *pPointer);
958 *pPointer = NULL;
960 if (pointer_id)
961 pointer_needs_unmarshaling = 1;
962 else
963 pointer_needs_unmarshaling = 0;
964 break;
965 case RPC_FC_FP:
966 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
967 TRACE("pointer_id is 0x%08x\n", pointer_id);
968 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
969 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
970 break;
971 default:
972 FIXME("unhandled ptr type=%02x\n", type);
973 RpcRaiseException(RPC_X_BAD_STUB_DATA);
974 return;
977 if (pointer_needs_unmarshaling) {
978 if (attr & RPC_FC_P_DEREF) {
979 if (!*pPointer || fMustAlloc)
980 *pPointer = NdrAllocate(pStubMsg, sizeof(void *));
981 pPointer = *(unsigned char***)pPointer;
982 TRACE("deref => %p\n", pPointer);
984 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
985 if (m) m(pStubMsg, pPointer, desc, fMustAlloc);
986 else FIXME("no unmarshaller for data type=%02x\n", *desc);
988 if (type == RPC_FC_FP)
989 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
990 *pPointer);
993 TRACE("pointer=%p\n", *pPointer);
996 /***********************************************************************
997 * PointerBufferSize [internal]
999 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1000 unsigned char *Pointer,
1001 PFORMAT_STRING pFormat)
1003 unsigned type = pFormat[0], attr = pFormat[1];
1004 PFORMAT_STRING desc;
1005 NDR_BUFFERSIZE m;
1006 int pointer_needs_sizing;
1007 ULONG pointer_id;
1009 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1010 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1011 pFormat += 2;
1012 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1013 else desc = pFormat + *(const SHORT*)pFormat;
1015 switch (type) {
1016 case RPC_FC_RP: /* ref pointer (always non-null) */
1017 break;
1018 case RPC_FC_OP:
1019 case RPC_FC_UP:
1020 /* NULL pointer has no further representation */
1021 if (!Pointer)
1022 return;
1023 break;
1024 case RPC_FC_FP:
1025 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1026 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1027 if (!pointer_needs_sizing)
1028 return;
1029 break;
1030 default:
1031 FIXME("unhandled ptr type=%02x\n", type);
1032 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1033 return;
1036 if (attr & RPC_FC_P_DEREF) {
1037 Pointer = *(unsigned char**)Pointer;
1038 TRACE("deref => %p\n", Pointer);
1041 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1042 if (m) m(pStubMsg, Pointer, desc);
1043 else FIXME("no buffersizer for data type=%02x\n", *desc);
1046 /***********************************************************************
1047 * PointerMemorySize [internal]
1049 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1050 unsigned char *Buffer,
1051 PFORMAT_STRING pFormat)
1053 unsigned type = pFormat[0], attr = pFormat[1];
1054 PFORMAT_STRING desc;
1055 NDR_MEMORYSIZE m;
1057 FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat);
1058 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1059 pFormat += 2;
1060 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1061 else desc = pFormat + *(const SHORT*)pFormat;
1063 switch (type) {
1064 case RPC_FC_RP: /* ref pointer (always non-null) */
1065 break;
1066 default:
1067 FIXME("unhandled ptr type=%02x\n", type);
1068 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1071 if (attr & RPC_FC_P_DEREF) {
1072 TRACE("deref\n");
1075 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1076 if (m) m(pStubMsg, desc);
1077 else FIXME("no memorysizer for data type=%02x\n", *desc);
1079 return 0;
1082 /***********************************************************************
1083 * PointerFree [internal]
1085 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1086 unsigned char *Pointer,
1087 PFORMAT_STRING pFormat)
1089 unsigned type = pFormat[0], attr = pFormat[1];
1090 PFORMAT_STRING desc;
1091 NDR_FREE m;
1093 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1094 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1095 if (attr & RPC_FC_P_DONTFREE) return;
1096 pFormat += 2;
1097 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1098 else desc = pFormat + *(const SHORT*)pFormat;
1100 if (!Pointer) return;
1102 if (type == RPC_FC_FP) {
1103 int pointer_needs_freeing = NdrFullPointerFree(
1104 pStubMsg->FullPtrXlatTables, Pointer);
1105 if (!pointer_needs_freeing)
1106 return;
1109 if (attr & RPC_FC_P_DEREF) {
1110 Pointer = *(unsigned char**)Pointer;
1111 TRACE("deref => %p\n", Pointer);
1114 m = NdrFreer[*desc & NDR_TABLE_MASK];
1115 if (m) m(pStubMsg, Pointer, desc);
1117 /* hmm... is this sensible?
1118 * perhaps we should check if the memory comes from NdrAllocate,
1119 * and deallocate only if so - checking if the pointer is between
1120 * BufferStart and BufferEnd is probably no good since the buffer
1121 * may be reallocated when the server wants to marshal the reply */
1122 switch (*desc) {
1123 case RPC_FC_BOGUS_STRUCT:
1124 case RPC_FC_BOGUS_ARRAY:
1125 case RPC_FC_USER_MARSHAL:
1126 case RPC_FC_CARRAY:
1127 case RPC_FC_CVARRAY:
1128 break;
1129 default:
1130 FIXME("unhandled data type=%02x\n", *desc);
1131 break;
1132 case RPC_FC_C_CSTRING:
1133 case RPC_FC_C_WSTRING:
1134 if (pStubMsg->ReuseBuffer) goto notfree;
1135 break;
1136 case RPC_FC_IP:
1137 goto notfree;
1140 if (attr & RPC_FC_P_ONSTACK) {
1141 TRACE("not freeing stack ptr %p\n", Pointer);
1142 return;
1144 TRACE("freeing %p\n", Pointer);
1145 NdrFree(pStubMsg, Pointer);
1146 return;
1147 notfree:
1148 TRACE("not freeing %p\n", Pointer);
1151 /***********************************************************************
1152 * EmbeddedPointerMarshall
1154 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1155 unsigned char *pMemory,
1156 PFORMAT_STRING pFormat)
1158 unsigned char *Mark = pStubMsg->BufferMark;
1159 unsigned long Offset = pStubMsg->Offset;
1160 unsigned ofs, rep, count, stride, xofs;
1161 unsigned i;
1162 unsigned char *saved_buffer = NULL;
1164 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1166 if (*pFormat != RPC_FC_PP) return NULL;
1167 pFormat += 2;
1169 if (pStubMsg->PointerBufferMark)
1171 saved_buffer = pStubMsg->Buffer;
1172 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1173 pStubMsg->PointerBufferMark = NULL;
1176 while (pFormat[0] != RPC_FC_END) {
1177 switch (pFormat[0]) {
1178 default:
1179 FIXME("unknown repeat type %d\n", pFormat[0]);
1180 case RPC_FC_NO_REPEAT:
1181 rep = 1;
1182 stride = 0;
1183 ofs = 0;
1184 count = 1;
1185 xofs = 0;
1186 pFormat += 2;
1187 break;
1188 case RPC_FC_FIXED_REPEAT:
1189 rep = *(const WORD*)&pFormat[2];
1190 stride = *(const WORD*)&pFormat[4];
1191 ofs = *(const WORD*)&pFormat[6];
1192 count = *(const WORD*)&pFormat[8];
1193 xofs = 0;
1194 pFormat += 10;
1195 break;
1196 case RPC_FC_VARIABLE_REPEAT:
1197 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1198 stride = *(const WORD*)&pFormat[2];
1199 ofs = *(const WORD*)&pFormat[4];
1200 count = *(const WORD*)&pFormat[6];
1201 xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1202 pFormat += 8;
1203 break;
1205 for (i = 0; i < rep; i++) {
1206 PFORMAT_STRING info = pFormat;
1207 unsigned char *membase = pMemory + ofs + (i * stride);
1208 unsigned char *bufbase = Mark + ofs + (i * stride);
1209 unsigned u;
1211 for (u=0; u<count; u++,info+=8) {
1212 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1213 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1214 unsigned char *saved_memory = pStubMsg->Memory;
1216 pStubMsg->Memory = pMemory;
1217 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1218 pStubMsg->Memory = saved_memory;
1221 pFormat += 8 * count;
1224 if (saved_buffer)
1226 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1227 pStubMsg->Buffer = saved_buffer;
1230 STD_OVERFLOW_CHECK(pStubMsg);
1232 return NULL;
1235 /***********************************************************************
1236 * EmbeddedPointerUnmarshall
1238 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1239 unsigned char **ppMemory,
1240 PFORMAT_STRING pFormat,
1241 unsigned char fMustAlloc)
1243 unsigned char *Mark = pStubMsg->BufferMark;
1244 unsigned long Offset = pStubMsg->Offset;
1245 unsigned ofs, rep, count, stride, xofs;
1246 unsigned i;
1247 unsigned char *saved_buffer = NULL;
1249 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1251 if (*pFormat != RPC_FC_PP) return NULL;
1252 pFormat += 2;
1254 if (pStubMsg->PointerBufferMark)
1256 saved_buffer = pStubMsg->Buffer;
1257 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1258 pStubMsg->PointerBufferMark = NULL;
1261 while (pFormat[0] != RPC_FC_END) {
1262 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1263 switch (pFormat[0]) {
1264 default:
1265 FIXME("unknown repeat type %d\n", pFormat[0]);
1266 case RPC_FC_NO_REPEAT:
1267 rep = 1;
1268 stride = 0;
1269 ofs = 0;
1270 count = 1;
1271 xofs = 0;
1272 pFormat += 2;
1273 break;
1274 case RPC_FC_FIXED_REPEAT:
1275 rep = *(const WORD*)&pFormat[2];
1276 stride = *(const WORD*)&pFormat[4];
1277 ofs = *(const WORD*)&pFormat[6];
1278 count = *(const WORD*)&pFormat[8];
1279 xofs = 0;
1280 pFormat += 10;
1281 break;
1282 case RPC_FC_VARIABLE_REPEAT:
1283 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1284 stride = *(const WORD*)&pFormat[2];
1285 ofs = *(const WORD*)&pFormat[4];
1286 count = *(const WORD*)&pFormat[6];
1287 xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1288 pFormat += 8;
1289 break;
1291 /* ofs doesn't seem to matter in this context */
1292 for (i = 0; i < rep; i++) {
1293 PFORMAT_STRING info = pFormat;
1294 unsigned char *membase = *ppMemory + ofs + (i * stride);
1295 unsigned char *bufbase = Mark + ofs + (i * stride);
1296 unsigned u;
1298 for (u=0; u<count; u++,info+=8) {
1299 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1300 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1301 PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, TRUE);
1304 pFormat += 8 * count;
1307 if (saved_buffer)
1309 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1310 pStubMsg->Buffer = saved_buffer;
1313 return NULL;
1316 /***********************************************************************
1317 * EmbeddedPointerBufferSize
1319 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1320 unsigned char *pMemory,
1321 PFORMAT_STRING pFormat)
1323 unsigned long Offset = pStubMsg->Offset;
1324 unsigned ofs, rep, count, stride, xofs;
1325 unsigned i;
1326 ULONG saved_buffer_length = 0;
1328 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1330 if (pStubMsg->IgnoreEmbeddedPointers) return;
1332 if (*pFormat != RPC_FC_PP) return;
1333 pFormat += 2;
1335 if (pStubMsg->PointerLength)
1337 saved_buffer_length = pStubMsg->BufferLength;
1338 pStubMsg->BufferLength = pStubMsg->PointerLength;
1339 pStubMsg->PointerLength = 0;
1342 while (pFormat[0] != RPC_FC_END) {
1343 switch (pFormat[0]) {
1344 default:
1345 FIXME("unknown repeat type %d\n", pFormat[0]);
1346 case RPC_FC_NO_REPEAT:
1347 rep = 1;
1348 stride = 0;
1349 ofs = 0;
1350 count = 1;
1351 xofs = 0;
1352 pFormat += 2;
1353 break;
1354 case RPC_FC_FIXED_REPEAT:
1355 rep = *(const WORD*)&pFormat[2];
1356 stride = *(const WORD*)&pFormat[4];
1357 ofs = *(const WORD*)&pFormat[6];
1358 count = *(const WORD*)&pFormat[8];
1359 xofs = 0;
1360 pFormat += 10;
1361 break;
1362 case RPC_FC_VARIABLE_REPEAT:
1363 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1364 stride = *(const WORD*)&pFormat[2];
1365 ofs = *(const WORD*)&pFormat[4];
1366 count = *(const WORD*)&pFormat[6];
1367 xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1368 pFormat += 8;
1369 break;
1371 for (i = 0; i < rep; i++) {
1372 PFORMAT_STRING info = pFormat;
1373 unsigned char *membase = pMemory + ofs + (i * stride);
1374 unsigned u;
1376 for (u=0; u<count; u++,info+=8) {
1377 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1378 unsigned char *saved_memory = pStubMsg->Memory;
1380 pStubMsg->Memory = pMemory;
1381 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1382 pStubMsg->Memory = saved_memory;
1385 pFormat += 8 * count;
1388 if (saved_buffer_length)
1390 pStubMsg->PointerLength = pStubMsg->BufferLength;
1391 pStubMsg->BufferLength = saved_buffer_length;
1395 /***********************************************************************
1396 * EmbeddedPointerMemorySize [internal]
1398 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1399 PFORMAT_STRING pFormat)
1401 unsigned long Offset = pStubMsg->Offset;
1402 unsigned char *Mark = pStubMsg->BufferMark;
1403 unsigned ofs, rep, count, stride, xofs;
1404 unsigned i;
1406 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1408 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1410 FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1412 if (*pFormat != RPC_FC_PP) return 0;
1413 pFormat += 2;
1415 while (pFormat[0] != RPC_FC_END) {
1416 switch (pFormat[0]) {
1417 default:
1418 FIXME("unknown repeat type %d\n", pFormat[0]);
1419 case RPC_FC_NO_REPEAT:
1420 rep = 1;
1421 stride = 0;
1422 ofs = 0;
1423 count = 1;
1424 xofs = 0;
1425 pFormat += 2;
1426 break;
1427 case RPC_FC_FIXED_REPEAT:
1428 rep = *(const WORD*)&pFormat[2];
1429 stride = *(const WORD*)&pFormat[4];
1430 ofs = *(const WORD*)&pFormat[6];
1431 count = *(const WORD*)&pFormat[8];
1432 xofs = 0;
1433 pFormat += 10;
1434 break;
1435 case RPC_FC_VARIABLE_REPEAT:
1436 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1437 stride = *(const WORD*)&pFormat[2];
1438 ofs = *(const WORD*)&pFormat[4];
1439 count = *(const WORD*)&pFormat[6];
1440 xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1441 pFormat += 8;
1442 break;
1444 /* ofs doesn't seem to matter in this context */
1445 for (i = 0; i < rep; i++) {
1446 PFORMAT_STRING info = pFormat;
1447 unsigned char *bufbase = Mark + ofs + (i * stride);
1448 unsigned u;
1449 for (u=0; u<count; u++,info+=8) {
1450 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1451 PointerMemorySize(pStubMsg, bufptr, info+4);
1454 pFormat += 8 * count;
1457 return 0;
1460 /***********************************************************************
1461 * EmbeddedPointerFree [internal]
1463 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1464 unsigned char *pMemory,
1465 PFORMAT_STRING pFormat)
1467 unsigned long Offset = pStubMsg->Offset;
1468 unsigned ofs, rep, count, stride, xofs;
1469 unsigned i;
1471 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1472 if (*pFormat != RPC_FC_PP) return;
1473 pFormat += 2;
1475 while (pFormat[0] != RPC_FC_END) {
1476 switch (pFormat[0]) {
1477 default:
1478 FIXME("unknown repeat type %d\n", pFormat[0]);
1479 case RPC_FC_NO_REPEAT:
1480 rep = 1;
1481 stride = 0;
1482 ofs = 0;
1483 count = 1;
1484 xofs = 0;
1485 pFormat += 2;
1486 break;
1487 case RPC_FC_FIXED_REPEAT:
1488 rep = *(const WORD*)&pFormat[2];
1489 stride = *(const WORD*)&pFormat[4];
1490 ofs = *(const WORD*)&pFormat[6];
1491 count = *(const WORD*)&pFormat[8];
1492 xofs = 0;
1493 pFormat += 10;
1494 break;
1495 case RPC_FC_VARIABLE_REPEAT:
1496 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1497 stride = *(const WORD*)&pFormat[2];
1498 ofs = *(const WORD*)&pFormat[4];
1499 count = *(const WORD*)&pFormat[6];
1500 xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1501 pFormat += 8;
1502 break;
1504 for (i = 0; i < rep; i++) {
1505 PFORMAT_STRING info = pFormat;
1506 unsigned char *membase = pMemory + (i * stride);
1507 unsigned u;
1509 for (u=0; u<count; u++,info+=8) {
1510 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1511 unsigned char *saved_memory = pStubMsg->Memory;
1513 pStubMsg->Memory = pMemory;
1514 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1515 pStubMsg->Memory = saved_memory;
1518 pFormat += 8 * count;
1522 /***********************************************************************
1523 * NdrPointerMarshall [RPCRT4.@]
1525 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1526 unsigned char *pMemory,
1527 PFORMAT_STRING pFormat)
1529 unsigned char *Buffer;
1531 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1533 /* incremement the buffer here instead of in PointerMarshall,
1534 * as that is used by embedded pointers which already handle the incrementing
1535 * the buffer, and shouldn't write any additional pointer data to the wire */
1536 if (*pFormat != RPC_FC_RP)
1538 ALIGN_POINTER(pStubMsg->Buffer, 4);
1539 Buffer = pStubMsg->Buffer;
1540 pStubMsg->Buffer += 4;
1542 else
1543 Buffer = pStubMsg->Buffer;
1545 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1547 STD_OVERFLOW_CHECK(pStubMsg);
1549 return NULL;
1552 /***********************************************************************
1553 * NdrPointerUnmarshall [RPCRT4.@]
1555 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1556 unsigned char **ppMemory,
1557 PFORMAT_STRING pFormat,
1558 unsigned char fMustAlloc)
1560 unsigned char *Buffer;
1562 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1564 /* incremement the buffer here instead of in PointerUnmarshall,
1565 * as that is used by embedded pointers which already handle the incrementing
1566 * the buffer, and shouldn't read any additional pointer data from the
1567 * buffer */
1568 if (*pFormat != RPC_FC_RP)
1570 ALIGN_POINTER(pStubMsg->Buffer, 4);
1571 Buffer = pStubMsg->Buffer;
1572 safe_buffer_increment(pStubMsg, 4);
1574 else
1575 Buffer = pStubMsg->Buffer;
1577 PointerUnmarshall(pStubMsg, Buffer, ppMemory, pFormat, fMustAlloc);
1579 return NULL;
1582 /***********************************************************************
1583 * NdrPointerBufferSize [RPCRT4.@]
1585 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1586 unsigned char *pMemory,
1587 PFORMAT_STRING pFormat)
1589 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1591 /* incremement the buffer length here instead of in PointerBufferSize,
1592 * as that is used by embedded pointers which already handle the buffer
1593 * length, and shouldn't write anything more to the wire */
1594 if (*pFormat != RPC_FC_RP)
1596 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1597 pStubMsg->BufferLength += 4;
1600 PointerBufferSize(pStubMsg, pMemory, pFormat);
1603 /***********************************************************************
1604 * NdrPointerMemorySize [RPCRT4.@]
1606 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1607 PFORMAT_STRING pFormat)
1609 /* unsigned size = *(LPWORD)(pFormat+2); */
1610 FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1611 PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1612 return 0;
1615 /***********************************************************************
1616 * NdrPointerFree [RPCRT4.@]
1618 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1619 unsigned char *pMemory,
1620 PFORMAT_STRING pFormat)
1622 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1623 PointerFree(pStubMsg, pMemory, pFormat);
1626 /***********************************************************************
1627 * NdrSimpleTypeMarshall [RPCRT4.@]
1629 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1630 unsigned char FormatChar )
1632 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1635 /***********************************************************************
1636 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1638 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1639 unsigned char FormatChar )
1641 NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0);
1644 /***********************************************************************
1645 * NdrSimpleStructMarshall [RPCRT4.@]
1647 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1648 unsigned char *pMemory,
1649 PFORMAT_STRING pFormat)
1651 unsigned size = *(const WORD*)(pFormat+2);
1652 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1654 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1656 memcpy(pStubMsg->Buffer, pMemory, size);
1657 pStubMsg->BufferMark = pStubMsg->Buffer;
1658 pStubMsg->Buffer += size;
1660 if (pFormat[0] != RPC_FC_STRUCT)
1661 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1663 STD_OVERFLOW_CHECK(pStubMsg);
1665 return NULL;
1668 /***********************************************************************
1669 * NdrSimpleStructUnmarshall [RPCRT4.@]
1671 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1672 unsigned char **ppMemory,
1673 PFORMAT_STRING pFormat,
1674 unsigned char fMustAlloc)
1676 unsigned size = *(const WORD*)(pFormat+2);
1677 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1679 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1681 if (fMustAlloc) {
1682 *ppMemory = NdrAllocate(pStubMsg, size);
1683 memcpy(*ppMemory, pStubMsg->Buffer, size);
1684 } else {
1685 if (!pStubMsg->IsClient && !*ppMemory)
1686 /* for servers, we just point straight into the RPC buffer */
1687 *ppMemory = pStubMsg->Buffer;
1688 else
1689 /* for clients, memory should be provided by caller */
1690 memcpy(*ppMemory, pStubMsg->Buffer, size);
1693 pStubMsg->BufferMark = pStubMsg->Buffer;
1694 pStubMsg->Buffer += size;
1696 if (pFormat[0] != RPC_FC_STRUCT)
1697 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1699 return NULL;
1702 /***********************************************************************
1703 * NdrSimpleStructBufferSize [RPCRT4.@]
1705 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1706 unsigned char *pMemory,
1707 PFORMAT_STRING pFormat)
1709 unsigned size = *(const WORD*)(pFormat+2);
1710 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1712 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1714 pStubMsg->BufferLength += size;
1715 if (pFormat[0] != RPC_FC_STRUCT)
1716 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1719 /***********************************************************************
1720 * NdrSimpleStructMemorySize [RPCRT4.@]
1722 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1723 PFORMAT_STRING pFormat)
1725 unsigned short size = *(const WORD *)(pFormat+2);
1727 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1729 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1730 pStubMsg->MemorySize += size;
1731 pStubMsg->Buffer += size;
1733 if (pFormat[0] != RPC_FC_STRUCT)
1734 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1735 return size;
1738 /***********************************************************************
1739 * NdrSimpleStructFree [RPCRT4.@]
1741 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1742 unsigned char *pMemory,
1743 PFORMAT_STRING pFormat)
1745 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1746 if (pFormat[0] != RPC_FC_STRUCT)
1747 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1751 static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg,
1752 PFORMAT_STRING pFormat)
1754 switch (*pFormat) {
1755 case RPC_FC_STRUCT:
1756 case RPC_FC_PSTRUCT:
1757 case RPC_FC_CSTRUCT:
1758 case RPC_FC_BOGUS_STRUCT:
1759 case RPC_FC_SMFARRAY:
1760 case RPC_FC_SMVARRAY:
1761 return *(const WORD*)&pFormat[2];
1762 case RPC_FC_USER_MARSHAL:
1763 return *(const WORD*)&pFormat[4];
1764 case RPC_FC_NON_ENCAPSULATED_UNION:
1765 pFormat += 2;
1766 if (pStubMsg->fHasNewCorrDesc)
1767 pFormat += 6;
1768 else
1769 pFormat += 4;
1771 pFormat += *(const SHORT*)pFormat;
1772 return *(const SHORT*)pFormat;
1773 case RPC_FC_IP:
1774 return sizeof(void *);
1775 default:
1776 FIXME("unhandled embedded type %02x\n", *pFormat);
1778 return 0;
1782 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1783 PFORMAT_STRING pFormat)
1785 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1787 if (!m)
1789 FIXME("no memorysizer for data type=%02x\n", *pFormat);
1790 return 0;
1793 return m(pStubMsg, pFormat);
1797 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1798 unsigned char *pMemory,
1799 PFORMAT_STRING pFormat,
1800 PFORMAT_STRING pPointer)
1802 PFORMAT_STRING desc;
1803 NDR_MARSHALL m;
1804 unsigned long size;
1806 while (*pFormat != RPC_FC_END) {
1807 switch (*pFormat) {
1808 case RPC_FC_BYTE:
1809 case RPC_FC_CHAR:
1810 case RPC_FC_SMALL:
1811 case RPC_FC_USMALL:
1812 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
1813 memcpy(pStubMsg->Buffer, pMemory, 1);
1814 pStubMsg->Buffer += 1;
1815 pMemory += 1;
1816 break;
1817 case RPC_FC_WCHAR:
1818 case RPC_FC_SHORT:
1819 case RPC_FC_USHORT:
1820 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1821 memcpy(pStubMsg->Buffer, pMemory, 2);
1822 pStubMsg->Buffer += 2;
1823 pMemory += 2;
1824 break;
1825 case RPC_FC_LONG:
1826 case RPC_FC_ULONG:
1827 case RPC_FC_ENUM32:
1828 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
1829 memcpy(pStubMsg->Buffer, pMemory, 4);
1830 pStubMsg->Buffer += 4;
1831 pMemory += 4;
1832 break;
1833 case RPC_FC_HYPER:
1834 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1835 memcpy(pStubMsg->Buffer, pMemory, 8);
1836 pStubMsg->Buffer += 8;
1837 pMemory += 8;
1838 break;
1839 case RPC_FC_POINTER:
1841 unsigned char *saved_buffer;
1842 int pointer_buffer_mark_set = 0;
1843 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1844 saved_buffer = pStubMsg->Buffer;
1845 if (pStubMsg->PointerBufferMark)
1847 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1848 pStubMsg->PointerBufferMark = NULL;
1849 pointer_buffer_mark_set = 1;
1851 else
1852 pStubMsg->Buffer += 4; /* for pointer ID */
1853 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
1854 if (pointer_buffer_mark_set)
1856 STD_OVERFLOW_CHECK(pStubMsg);
1857 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1858 pStubMsg->Buffer = saved_buffer + 4;
1860 pPointer += 4;
1861 pMemory += 4;
1862 break;
1864 case RPC_FC_ALIGNM4:
1865 ALIGN_POINTER(pMemory, 4);
1866 break;
1867 case RPC_FC_ALIGNM8:
1868 ALIGN_POINTER(pMemory, 8);
1869 break;
1870 case RPC_FC_STRUCTPAD1:
1871 case RPC_FC_STRUCTPAD2:
1872 case RPC_FC_STRUCTPAD3:
1873 case RPC_FC_STRUCTPAD4:
1874 case RPC_FC_STRUCTPAD5:
1875 case RPC_FC_STRUCTPAD6:
1876 case RPC_FC_STRUCTPAD7:
1877 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1878 break;
1879 case RPC_FC_EMBEDDED_COMPLEX:
1880 pMemory += pFormat[1];
1881 pFormat += 2;
1882 desc = pFormat + *(const SHORT*)pFormat;
1883 size = EmbeddedComplexSize(pStubMsg, desc);
1884 TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1885 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1886 if (m)
1888 /* for some reason interface pointers aren't generated as
1889 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
1890 * they still need the derefencing treatment that pointers are
1891 * given */
1892 if (*desc == RPC_FC_IP)
1893 m(pStubMsg, *(unsigned char **)pMemory, desc);
1894 else
1895 m(pStubMsg, pMemory, desc);
1897 else FIXME("no marshaller for embedded type %02x\n", *desc);
1898 pMemory += size;
1899 pFormat += 2;
1900 continue;
1901 case RPC_FC_PAD:
1902 break;
1903 default:
1904 FIXME("unhandled format 0x%02x\n", *pFormat);
1906 pFormat++;
1909 return pMemory;
1912 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1913 unsigned char *pMemory,
1914 PFORMAT_STRING pFormat,
1915 PFORMAT_STRING pPointer)
1917 PFORMAT_STRING desc;
1918 NDR_UNMARSHALL m;
1919 unsigned long size;
1921 while (*pFormat != RPC_FC_END) {
1922 switch (*pFormat) {
1923 case RPC_FC_BYTE:
1924 case RPC_FC_CHAR:
1925 case RPC_FC_SMALL:
1926 case RPC_FC_USMALL:
1927 safe_buffer_copy(pStubMsg, pMemory, 1);
1928 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
1929 pMemory += 1;
1930 break;
1931 case RPC_FC_WCHAR:
1932 case RPC_FC_SHORT:
1933 case RPC_FC_USHORT:
1934 safe_buffer_copy(pStubMsg, pMemory, 2);
1935 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1936 pMemory += 2;
1937 break;
1938 case RPC_FC_LONG:
1939 case RPC_FC_ULONG:
1940 case RPC_FC_ENUM32:
1941 safe_buffer_copy(pStubMsg, pMemory, 4);
1942 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
1943 pMemory += 4;
1944 break;
1945 case RPC_FC_HYPER:
1946 safe_buffer_copy(pStubMsg, pMemory, 8);
1947 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1948 pMemory += 8;
1949 break;
1950 case RPC_FC_POINTER:
1952 unsigned char *saved_buffer;
1953 int pointer_buffer_mark_set = 0;
1954 TRACE("pointer => %p\n", pMemory);
1955 ALIGN_POINTER(pStubMsg->Buffer, 4);
1956 saved_buffer = pStubMsg->Buffer;
1957 if (pStubMsg->PointerBufferMark)
1959 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1960 pStubMsg->PointerBufferMark = NULL;
1961 pointer_buffer_mark_set = 1;
1963 else
1964 pStubMsg->Buffer += 4; /* for pointer ID */
1966 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, pPointer, TRUE);
1967 if (pointer_buffer_mark_set)
1969 STD_OVERFLOW_CHECK(pStubMsg);
1970 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1971 pStubMsg->Buffer = saved_buffer + 4;
1973 pPointer += 4;
1974 pMemory += 4;
1975 break;
1977 case RPC_FC_ALIGNM4:
1978 ALIGN_POINTER(pMemory, 4);
1979 break;
1980 case RPC_FC_ALIGNM8:
1981 ALIGN_POINTER(pMemory, 8);
1982 break;
1983 case RPC_FC_STRUCTPAD1:
1984 case RPC_FC_STRUCTPAD2:
1985 case RPC_FC_STRUCTPAD3:
1986 case RPC_FC_STRUCTPAD4:
1987 case RPC_FC_STRUCTPAD5:
1988 case RPC_FC_STRUCTPAD6:
1989 case RPC_FC_STRUCTPAD7:
1990 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1991 break;
1992 case RPC_FC_EMBEDDED_COMPLEX:
1993 pMemory += pFormat[1];
1994 pFormat += 2;
1995 desc = pFormat + *(const SHORT*)pFormat;
1996 size = EmbeddedComplexSize(pStubMsg, desc);
1997 TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1998 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1999 memset(pMemory, 0, size); /* just in case */
2000 if (m)
2002 /* for some reason interface pointers aren't generated as
2003 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2004 * they still need the derefencing treatment that pointers are
2005 * given */
2006 if (*desc == RPC_FC_IP)
2007 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2008 else
2009 m(pStubMsg, &pMemory, desc, FALSE);
2011 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2012 pMemory += size;
2013 pFormat += 2;
2014 continue;
2015 case RPC_FC_PAD:
2016 break;
2017 default:
2018 FIXME("unhandled format %d\n", *pFormat);
2020 pFormat++;
2023 return pMemory;
2026 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2027 unsigned char *pMemory,
2028 PFORMAT_STRING pFormat,
2029 PFORMAT_STRING pPointer)
2031 PFORMAT_STRING desc;
2032 NDR_BUFFERSIZE m;
2033 unsigned long size;
2035 while (*pFormat != RPC_FC_END) {
2036 switch (*pFormat) {
2037 case RPC_FC_BYTE:
2038 case RPC_FC_CHAR:
2039 case RPC_FC_SMALL:
2040 case RPC_FC_USMALL:
2041 pStubMsg->BufferLength += 1;
2042 pMemory += 1;
2043 break;
2044 case RPC_FC_WCHAR:
2045 case RPC_FC_SHORT:
2046 case RPC_FC_USHORT:
2047 pStubMsg->BufferLength += 2;
2048 pMemory += 2;
2049 break;
2050 case RPC_FC_LONG:
2051 case RPC_FC_ULONG:
2052 case RPC_FC_ENUM32:
2053 pStubMsg->BufferLength += 4;
2054 pMemory += 4;
2055 break;
2056 case RPC_FC_HYPER:
2057 pStubMsg->BufferLength += 8;
2058 pMemory += 8;
2059 break;
2060 case RPC_FC_POINTER:
2061 if (!pStubMsg->IgnoreEmbeddedPointers)
2063 int saved_buffer_length = pStubMsg->BufferLength;
2064 pStubMsg->BufferLength = pStubMsg->PointerLength;
2065 pStubMsg->PointerLength = 0;
2066 if(!pStubMsg->BufferLength)
2067 ERR("BufferLength == 0??\n");
2068 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2069 pStubMsg->PointerLength = pStubMsg->BufferLength;
2070 pStubMsg->BufferLength = saved_buffer_length;
2072 pStubMsg->BufferLength += 4;
2073 pPointer += 4;
2074 pMemory += 4;
2075 break;
2076 case RPC_FC_ALIGNM4:
2077 ALIGN_POINTER(pMemory, 4);
2078 break;
2079 case RPC_FC_ALIGNM8:
2080 ALIGN_POINTER(pMemory, 8);
2081 break;
2082 case RPC_FC_STRUCTPAD1:
2083 case RPC_FC_STRUCTPAD2:
2084 case RPC_FC_STRUCTPAD3:
2085 case RPC_FC_STRUCTPAD4:
2086 case RPC_FC_STRUCTPAD5:
2087 case RPC_FC_STRUCTPAD6:
2088 case RPC_FC_STRUCTPAD7:
2089 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2090 break;
2091 case RPC_FC_EMBEDDED_COMPLEX:
2092 pMemory += pFormat[1];
2093 pFormat += 2;
2094 desc = pFormat + *(const SHORT*)pFormat;
2095 size = EmbeddedComplexSize(pStubMsg, desc);
2096 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2097 if (m)
2099 /* for some reason interface pointers aren't generated as
2100 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2101 * they still need the derefencing treatment that pointers are
2102 * given */
2103 if (*desc == RPC_FC_IP)
2104 m(pStubMsg, *(unsigned char **)pMemory, desc);
2105 else
2106 m(pStubMsg, pMemory, desc);
2108 else FIXME("no buffersizer for embedded type %02x\n", *desc);
2109 pMemory += size;
2110 pFormat += 2;
2111 continue;
2112 case RPC_FC_PAD:
2113 break;
2114 default:
2115 FIXME("unhandled format 0x%02x\n", *pFormat);
2117 pFormat++;
2120 return pMemory;
2123 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2124 unsigned char *pMemory,
2125 PFORMAT_STRING pFormat,
2126 PFORMAT_STRING pPointer)
2128 PFORMAT_STRING desc;
2129 NDR_FREE m;
2130 unsigned long size;
2132 while (*pFormat != RPC_FC_END) {
2133 switch (*pFormat) {
2134 case RPC_FC_BYTE:
2135 case RPC_FC_CHAR:
2136 case RPC_FC_SMALL:
2137 case RPC_FC_USMALL:
2138 pMemory += 1;
2139 break;
2140 case RPC_FC_WCHAR:
2141 case RPC_FC_SHORT:
2142 case RPC_FC_USHORT:
2143 pMemory += 2;
2144 break;
2145 case RPC_FC_LONG:
2146 case RPC_FC_ULONG:
2147 case RPC_FC_ENUM32:
2148 pMemory += 4;
2149 break;
2150 case RPC_FC_HYPER:
2151 pMemory += 8;
2152 break;
2153 case RPC_FC_POINTER:
2154 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2155 pPointer += 4;
2156 pMemory += 4;
2157 break;
2158 case RPC_FC_ALIGNM4:
2159 ALIGN_POINTER(pMemory, 4);
2160 break;
2161 case RPC_FC_ALIGNM8:
2162 ALIGN_POINTER(pMemory, 8);
2163 break;
2164 case RPC_FC_STRUCTPAD1:
2165 case RPC_FC_STRUCTPAD2:
2166 case RPC_FC_STRUCTPAD3:
2167 case RPC_FC_STRUCTPAD4:
2168 case RPC_FC_STRUCTPAD5:
2169 case RPC_FC_STRUCTPAD6:
2170 case RPC_FC_STRUCTPAD7:
2171 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2172 break;
2173 case RPC_FC_EMBEDDED_COMPLEX:
2174 pMemory += pFormat[1];
2175 pFormat += 2;
2176 desc = pFormat + *(const SHORT*)pFormat;
2177 size = EmbeddedComplexSize(pStubMsg, desc);
2178 m = NdrFreer[*desc & NDR_TABLE_MASK];
2179 if (m)
2181 /* for some reason interface pointers aren't generated as
2182 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2183 * they still need the derefencing treatment that pointers are
2184 * given */
2185 if (*desc == RPC_FC_IP)
2186 m(pStubMsg, *(unsigned char **)pMemory, desc);
2187 else
2188 m(pStubMsg, pMemory, desc);
2190 else FIXME("no freer for embedded type %02x\n", *desc);
2191 pMemory += size;
2192 pFormat += 2;
2193 continue;
2194 case RPC_FC_PAD:
2195 break;
2196 default:
2197 FIXME("unhandled format 0x%02x\n", *pFormat);
2199 pFormat++;
2202 return pMemory;
2205 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2206 PFORMAT_STRING pFormat)
2208 PFORMAT_STRING desc;
2209 unsigned long size = 0;
2211 while (*pFormat != RPC_FC_END) {
2212 switch (*pFormat) {
2213 case RPC_FC_BYTE:
2214 case RPC_FC_CHAR:
2215 case RPC_FC_SMALL:
2216 case RPC_FC_USMALL:
2217 size += 1;
2218 pStubMsg->Buffer += 1;
2219 break;
2220 case RPC_FC_WCHAR:
2221 case RPC_FC_SHORT:
2222 case RPC_FC_USHORT:
2223 size += 2;
2224 pStubMsg->Buffer += 2;
2225 break;
2226 case RPC_FC_LONG:
2227 case RPC_FC_ULONG:
2228 case RPC_FC_ENUM32:
2229 size += 4;
2230 pStubMsg->Buffer += 4;
2231 break;
2232 case RPC_FC_HYPER:
2233 size += 8;
2234 pStubMsg->Buffer += 8;
2235 break;
2236 case RPC_FC_POINTER:
2237 size += 4;
2238 pStubMsg->Buffer += 4;
2239 if (!pStubMsg->IgnoreEmbeddedPointers)
2240 FIXME("embedded pointers\n");
2241 break;
2242 case RPC_FC_ALIGNM4:
2243 ALIGN_LENGTH(size, 4);
2244 ALIGN_POINTER(pStubMsg->Buffer, 4);
2245 break;
2246 case RPC_FC_ALIGNM8:
2247 ALIGN_LENGTH(size, 8);
2248 ALIGN_POINTER(pStubMsg->Buffer, 8);
2249 break;
2250 case RPC_FC_STRUCTPAD1:
2251 case RPC_FC_STRUCTPAD2:
2252 case RPC_FC_STRUCTPAD3:
2253 case RPC_FC_STRUCTPAD4:
2254 case RPC_FC_STRUCTPAD5:
2255 case RPC_FC_STRUCTPAD6:
2256 case RPC_FC_STRUCTPAD7:
2257 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2258 break;
2259 case RPC_FC_EMBEDDED_COMPLEX:
2260 size += pFormat[1];
2261 pFormat += 2;
2262 desc = pFormat + *(const SHORT*)pFormat;
2263 size += EmbeddedComplexMemorySize(pStubMsg, desc);
2264 pFormat += 2;
2265 continue;
2266 case RPC_FC_PAD:
2267 break;
2268 default:
2269 FIXME("unhandled format 0x%02x\n", *pFormat);
2271 pFormat++;
2274 return size;
2277 /***********************************************************************
2278 * NdrComplexStructMarshall [RPCRT4.@]
2280 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2281 unsigned char *pMemory,
2282 PFORMAT_STRING pFormat)
2284 PFORMAT_STRING conf_array = NULL;
2285 PFORMAT_STRING pointer_desc = NULL;
2286 unsigned char *OldMemory = pStubMsg->Memory;
2287 int pointer_buffer_mark_set = 0;
2289 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2291 if (!pStubMsg->PointerBufferMark)
2293 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2294 /* save buffer length */
2295 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2297 /* get the buffer pointer after complex array data, but before
2298 * pointer data */
2299 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2300 pStubMsg->IgnoreEmbeddedPointers = 1;
2301 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2302 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2304 /* save it for use by embedded pointer code later */
2305 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2306 TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2307 pointer_buffer_mark_set = 1;
2309 /* restore the original buffer length */
2310 pStubMsg->BufferLength = saved_buffer_length;
2313 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2315 pFormat += 4;
2316 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2317 pFormat += 2;
2318 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2319 pFormat += 2;
2321 pStubMsg->Memory = pMemory;
2323 ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2325 if (conf_array)
2326 NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2328 pStubMsg->Memory = OldMemory;
2330 if (pointer_buffer_mark_set)
2332 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2333 pStubMsg->PointerBufferMark = NULL;
2336 STD_OVERFLOW_CHECK(pStubMsg);
2338 return NULL;
2341 /***********************************************************************
2342 * NdrComplexStructUnmarshall [RPCRT4.@]
2344 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2345 unsigned char **ppMemory,
2346 PFORMAT_STRING pFormat,
2347 unsigned char fMustAlloc)
2349 unsigned size = *(const WORD*)(pFormat+2);
2350 PFORMAT_STRING conf_array = NULL;
2351 PFORMAT_STRING pointer_desc = NULL;
2352 unsigned char *pMemory;
2353 int pointer_buffer_mark_set = 0;
2355 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2357 if (!pStubMsg->PointerBufferMark)
2359 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2360 /* save buffer pointer */
2361 unsigned char *saved_buffer = pStubMsg->Buffer;
2363 /* get the buffer pointer after complex array data, but before
2364 * pointer data */
2365 pStubMsg->IgnoreEmbeddedPointers = 1;
2366 NdrComplexStructMemorySize(pStubMsg, pFormat);
2367 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2369 /* save it for use by embedded pointer code later */
2370 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2371 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2372 pointer_buffer_mark_set = 1;
2374 /* restore the original buffer */
2375 pStubMsg->Buffer = saved_buffer;
2378 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2380 if (fMustAlloc || !*ppMemory)
2382 *ppMemory = NdrAllocate(pStubMsg, size);
2383 memset(*ppMemory, 0, size);
2386 pFormat += 4;
2387 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2388 pFormat += 2;
2389 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2390 pFormat += 2;
2392 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2394 if (conf_array)
2395 NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2397 if (pointer_buffer_mark_set)
2399 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2400 pStubMsg->PointerBufferMark = NULL;
2403 return NULL;
2406 /***********************************************************************
2407 * NdrComplexStructBufferSize [RPCRT4.@]
2409 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2410 unsigned char *pMemory,
2411 PFORMAT_STRING pFormat)
2413 PFORMAT_STRING conf_array = NULL;
2414 PFORMAT_STRING pointer_desc = NULL;
2415 unsigned char *OldMemory = pStubMsg->Memory;
2416 int pointer_length_set = 0;
2418 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2420 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2422 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2424 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2425 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2427 /* get the buffer length after complex struct data, but before
2428 * pointer data */
2429 pStubMsg->IgnoreEmbeddedPointers = 1;
2430 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2431 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2433 /* save it for use by embedded pointer code later */
2434 pStubMsg->PointerLength = pStubMsg->BufferLength;
2435 pointer_length_set = 1;
2436 TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2438 /* restore the original buffer length */
2439 pStubMsg->BufferLength = saved_buffer_length;
2442 pFormat += 4;
2443 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2444 pFormat += 2;
2445 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2446 pFormat += 2;
2448 pStubMsg->Memory = pMemory;
2450 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2452 if (conf_array)
2453 NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2455 pStubMsg->Memory = OldMemory;
2457 if(pointer_length_set)
2459 pStubMsg->BufferLength = pStubMsg->PointerLength;
2460 pStubMsg->PointerLength = 0;
2465 /***********************************************************************
2466 * NdrComplexStructMemorySize [RPCRT4.@]
2468 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2469 PFORMAT_STRING pFormat)
2471 unsigned size = *(const WORD*)(pFormat+2);
2472 PFORMAT_STRING conf_array = NULL;
2473 PFORMAT_STRING pointer_desc = NULL;
2475 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2477 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2479 pFormat += 4;
2480 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2481 pFormat += 2;
2482 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2483 pFormat += 2;
2485 ComplexStructMemorySize(pStubMsg, pFormat);
2487 if (conf_array)
2488 NdrConformantArrayMemorySize(pStubMsg, conf_array);
2490 return size;
2493 /***********************************************************************
2494 * NdrComplexStructFree [RPCRT4.@]
2496 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2497 unsigned char *pMemory,
2498 PFORMAT_STRING pFormat)
2500 PFORMAT_STRING conf_array = NULL;
2501 PFORMAT_STRING pointer_desc = NULL;
2502 unsigned char *OldMemory = pStubMsg->Memory;
2504 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2506 pFormat += 4;
2507 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2508 pFormat += 2;
2509 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2510 pFormat += 2;
2512 pStubMsg->Memory = pMemory;
2514 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2516 if (conf_array)
2517 NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2519 pStubMsg->Memory = OldMemory;
2522 /***********************************************************************
2523 * NdrConformantArrayMarshall [RPCRT4.@]
2525 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2526 unsigned char *pMemory,
2527 PFORMAT_STRING pFormat)
2529 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2530 unsigned char alignment = pFormat[1] + 1;
2532 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2533 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2535 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2537 WriteConformance(pStubMsg);
2539 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2541 size = safe_multiply(esize, pStubMsg->MaxCount);
2542 memcpy(pStubMsg->Buffer, pMemory, size);
2543 pStubMsg->BufferMark = pStubMsg->Buffer;
2544 pStubMsg->Buffer += size;
2546 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2548 STD_OVERFLOW_CHECK(pStubMsg);
2550 return NULL;
2553 /***********************************************************************
2554 * NdrConformantArrayUnmarshall [RPCRT4.@]
2556 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2557 unsigned char **ppMemory,
2558 PFORMAT_STRING pFormat,
2559 unsigned char fMustAlloc)
2561 DWORD size, esize = *(const WORD*)(pFormat+2);
2562 unsigned char alignment = pFormat[1] + 1;
2564 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2565 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2567 pFormat = ReadConformance(pStubMsg, pFormat+4);
2569 size = safe_multiply(esize, pStubMsg->MaxCount);
2571 if (fMustAlloc || !*ppMemory)
2572 *ppMemory = NdrAllocate(pStubMsg, size);
2574 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2576 pStubMsg->BufferMark = pStubMsg->Buffer;
2577 safe_buffer_copy(pStubMsg, *ppMemory, size);
2579 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2581 return NULL;
2584 /***********************************************************************
2585 * NdrConformantArrayBufferSize [RPCRT4.@]
2587 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2588 unsigned char *pMemory,
2589 PFORMAT_STRING pFormat)
2591 DWORD size, esize = *(const WORD*)(pFormat+2);
2592 unsigned char alignment = pFormat[1] + 1;
2594 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2595 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2597 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2599 SizeConformance(pStubMsg);
2601 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2603 size = safe_multiply(esize, pStubMsg->MaxCount);
2604 /* conformance value plus array */
2605 pStubMsg->BufferLength += size;
2607 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2610 /***********************************************************************
2611 * NdrConformantArrayMemorySize [RPCRT4.@]
2613 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2614 PFORMAT_STRING pFormat)
2616 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2617 unsigned char alignment = pFormat[1] + 1;
2619 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2620 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2622 pFormat = ReadConformance(pStubMsg, pFormat+4);
2623 size = safe_multiply(esize, pStubMsg->MaxCount);
2624 pStubMsg->MemorySize += size;
2626 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2627 pStubMsg->BufferMark = pStubMsg->Buffer;
2628 pStubMsg->Buffer += size;
2630 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2632 return pStubMsg->MemorySize;
2635 /***********************************************************************
2636 * NdrConformantArrayFree [RPCRT4.@]
2638 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2639 unsigned char *pMemory,
2640 PFORMAT_STRING pFormat)
2642 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2643 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2645 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2647 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2651 /***********************************************************************
2652 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
2654 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2655 unsigned char* pMemory,
2656 PFORMAT_STRING pFormat )
2658 ULONG bufsize;
2659 unsigned char alignment = pFormat[1] + 1;
2660 DWORD esize = *(const WORD*)(pFormat+2);
2662 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2664 if (pFormat[0] != RPC_FC_CVARRAY)
2666 ERR("invalid format type %x\n", pFormat[0]);
2667 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2668 return NULL;
2671 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2672 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2674 WriteConformance(pStubMsg);
2675 WriteVariance(pStubMsg);
2677 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2679 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2681 memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize);
2682 pStubMsg->BufferMark = pStubMsg->Buffer;
2683 pStubMsg->Buffer += bufsize;
2685 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2687 STD_OVERFLOW_CHECK(pStubMsg);
2689 return NULL;
2693 /***********************************************************************
2694 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
2696 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2697 unsigned char** ppMemory,
2698 PFORMAT_STRING pFormat,
2699 unsigned char fMustAlloc )
2701 ULONG bufsize, memsize;
2702 unsigned char alignment = pFormat[1] + 1;
2703 DWORD esize = *(const WORD*)(pFormat+2);
2705 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2707 if (pFormat[0] != RPC_FC_CVARRAY)
2709 ERR("invalid format type %x\n", pFormat[0]);
2710 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2711 return NULL;
2714 pFormat = ReadConformance(pStubMsg, pFormat+4);
2715 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2717 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2719 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2720 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2722 if (!*ppMemory || fMustAlloc)
2723 *ppMemory = NdrAllocate(pStubMsg, memsize);
2724 safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
2726 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2728 return NULL;
2732 /***********************************************************************
2733 * NdrConformantVaryingArrayFree [RPCRT4.@]
2735 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2736 unsigned char* pMemory,
2737 PFORMAT_STRING pFormat )
2739 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2741 if (pFormat[0] != RPC_FC_CVARRAY)
2743 ERR("invalid format type %x\n", pFormat[0]);
2744 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2745 return;
2748 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2749 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2751 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2755 /***********************************************************************
2756 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
2758 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2759 unsigned char* pMemory, PFORMAT_STRING pFormat )
2761 unsigned char alignment = pFormat[1] + 1;
2762 DWORD esize = *(const WORD*)(pFormat+2);
2764 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2766 if (pFormat[0] != RPC_FC_CVARRAY)
2768 ERR("invalid format type %x\n", pFormat[0]);
2769 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2770 return;
2773 /* compute size */
2774 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2775 /* compute length */
2776 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2778 SizeConformance(pStubMsg);
2779 SizeVariance(pStubMsg);
2781 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2783 pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
2785 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2789 /***********************************************************************
2790 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
2792 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2793 PFORMAT_STRING pFormat )
2795 FIXME( "stub\n" );
2796 return 0;
2800 /***********************************************************************
2801 * NdrComplexArrayMarshall [RPCRT4.@]
2803 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2804 unsigned char *pMemory,
2805 PFORMAT_STRING pFormat)
2807 ULONG i, count, def;
2808 BOOL variance_present;
2809 unsigned char alignment;
2810 int pointer_buffer_mark_set = 0;
2812 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2814 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2816 ERR("invalid format type %x\n", pFormat[0]);
2817 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2818 return NULL;
2821 alignment = pFormat[1] + 1;
2823 if (!pStubMsg->PointerBufferMark)
2825 /* save buffer fields that may be changed by buffer sizer functions
2826 * and that may be needed later on */
2827 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2828 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2829 unsigned long saved_max_count = pStubMsg->MaxCount;
2830 unsigned long saved_offset = pStubMsg->Offset;
2831 unsigned long saved_actual_count = pStubMsg->ActualCount;
2833 /* get the buffer pointer after complex array data, but before
2834 * pointer data */
2835 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2836 pStubMsg->IgnoreEmbeddedPointers = 1;
2837 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
2838 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2840 /* save it for use by embedded pointer code later */
2841 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2842 TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
2843 pointer_buffer_mark_set = 1;
2845 /* restore fields */
2846 pStubMsg->ActualCount = saved_actual_count;
2847 pStubMsg->Offset = saved_offset;
2848 pStubMsg->MaxCount = saved_max_count;
2849 pStubMsg->BufferLength = saved_buffer_length;
2852 def = *(const WORD*)&pFormat[2];
2853 pFormat += 4;
2855 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2856 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2858 variance_present = IsConformanceOrVariancePresent(pFormat);
2859 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2860 TRACE("variance = %d\n", pStubMsg->ActualCount);
2862 WriteConformance(pStubMsg);
2863 if (variance_present)
2864 WriteVariance(pStubMsg);
2866 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2868 count = pStubMsg->ActualCount;
2869 for (i = 0; i < count; i++)
2870 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2872 STD_OVERFLOW_CHECK(pStubMsg);
2874 if (pointer_buffer_mark_set)
2876 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2877 pStubMsg->PointerBufferMark = NULL;
2880 return NULL;
2883 /***********************************************************************
2884 * NdrComplexArrayUnmarshall [RPCRT4.@]
2886 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2887 unsigned char **ppMemory,
2888 PFORMAT_STRING pFormat,
2889 unsigned char fMustAlloc)
2891 ULONG i, count, size;
2892 unsigned char alignment;
2893 unsigned char *pMemory;
2894 unsigned char *saved_buffer;
2895 int pointer_buffer_mark_set = 0;
2896 int saved_ignore_embedded;
2898 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2900 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2902 ERR("invalid format type %x\n", pFormat[0]);
2903 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2904 return NULL;
2907 alignment = pFormat[1] + 1;
2909 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2910 /* save buffer pointer */
2911 saved_buffer = pStubMsg->Buffer;
2912 /* get the buffer pointer after complex array data, but before
2913 * pointer data */
2914 pStubMsg->IgnoreEmbeddedPointers = 1;
2915 pStubMsg->MemorySize = 0;
2916 NdrComplexArrayMemorySize(pStubMsg, pFormat);
2917 size = pStubMsg->MemorySize;
2918 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2920 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
2921 if (!pStubMsg->PointerBufferMark)
2923 /* save it for use by embedded pointer code later */
2924 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2925 pointer_buffer_mark_set = 1;
2927 /* restore the original buffer */
2928 pStubMsg->Buffer = saved_buffer;
2930 pFormat += 4;
2932 pFormat = ReadConformance(pStubMsg, pFormat);
2933 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2935 if (fMustAlloc || !*ppMemory)
2937 *ppMemory = NdrAllocate(pStubMsg, size);
2938 memset(*ppMemory, 0, size);
2941 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2943 pMemory = *ppMemory;
2944 count = pStubMsg->ActualCount;
2945 for (i = 0; i < count; i++)
2946 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
2948 if (pointer_buffer_mark_set)
2950 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2951 pStubMsg->PointerBufferMark = NULL;
2954 return NULL;
2957 /***********************************************************************
2958 * NdrComplexArrayBufferSize [RPCRT4.@]
2960 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2961 unsigned char *pMemory,
2962 PFORMAT_STRING pFormat)
2964 ULONG i, count, def;
2965 unsigned char alignment;
2966 BOOL variance_present;
2967 int pointer_length_set = 0;
2969 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2971 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2973 ERR("invalid format type %x\n", pFormat[0]);
2974 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2975 return;
2978 alignment = pFormat[1] + 1;
2980 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2982 /* save buffer fields that may be changed by buffer sizer functions
2983 * and that may be needed later on */
2984 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2985 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2986 unsigned long saved_max_count = pStubMsg->MaxCount;
2987 unsigned long saved_offset = pStubMsg->Offset;
2988 unsigned long saved_actual_count = pStubMsg->ActualCount;
2990 /* get the buffer pointer after complex array data, but before
2991 * pointer data */
2992 pStubMsg->IgnoreEmbeddedPointers = 1;
2993 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
2994 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2996 /* save it for use by embedded pointer code later */
2997 pStubMsg->PointerLength = pStubMsg->BufferLength;
2998 pointer_length_set = 1;
3000 /* restore fields */
3001 pStubMsg->ActualCount = saved_actual_count;
3002 pStubMsg->Offset = saved_offset;
3003 pStubMsg->MaxCount = saved_max_count;
3004 pStubMsg->BufferLength = saved_buffer_length;
3006 def = *(const WORD*)&pFormat[2];
3007 pFormat += 4;
3009 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3010 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3011 SizeConformance(pStubMsg);
3013 variance_present = IsConformanceOrVariancePresent(pFormat);
3014 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3015 TRACE("variance = %d\n", pStubMsg->ActualCount);
3017 if (variance_present)
3018 SizeVariance(pStubMsg);
3020 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3022 count = pStubMsg->ActualCount;
3023 for (i = 0; i < count; i++)
3024 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
3026 if(pointer_length_set)
3028 pStubMsg->BufferLength = pStubMsg->PointerLength;
3029 pStubMsg->PointerLength = 0;
3033 /***********************************************************************
3034 * NdrComplexArrayMemorySize [RPCRT4.@]
3036 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3037 PFORMAT_STRING pFormat)
3039 ULONG i, count, esize, SavedMemorySize, MemorySize;
3040 unsigned char alignment;
3041 unsigned char *Buffer;
3043 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3045 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3047 ERR("invalid format type %x\n", pFormat[0]);
3048 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3049 return 0;
3052 alignment = pFormat[1] + 1;
3054 pFormat += 4;
3056 pFormat = ReadConformance(pStubMsg, pFormat);
3057 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3059 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3061 SavedMemorySize = pStubMsg->MemorySize;
3063 Buffer = pStubMsg->Buffer;
3064 pStubMsg->MemorySize = 0;
3065 esize = ComplexStructMemorySize(pStubMsg, pFormat);
3066 pStubMsg->Buffer = Buffer;
3068 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3070 count = pStubMsg->ActualCount;
3071 for (i = 0; i < count; i++)
3072 ComplexStructMemorySize(pStubMsg, pFormat);
3074 pStubMsg->MemorySize = SavedMemorySize;
3076 pStubMsg->MemorySize += MemorySize;
3077 return MemorySize;
3080 /***********************************************************************
3081 * NdrComplexArrayFree [RPCRT4.@]
3083 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3084 unsigned char *pMemory,
3085 PFORMAT_STRING pFormat)
3087 ULONG i, count, def;
3089 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3091 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3093 ERR("invalid format type %x\n", pFormat[0]);
3094 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3095 return;
3098 def = *(const WORD*)&pFormat[2];
3099 pFormat += 4;
3101 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3102 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3104 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3105 TRACE("variance = %d\n", pStubMsg->ActualCount);
3107 count = pStubMsg->ActualCount;
3108 for (i = 0; i < count; i++)
3109 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
3112 static ULONG UserMarshalFlags(const MIDL_STUB_MESSAGE *pStubMsg)
3114 return MAKELONG(pStubMsg->dwDestContext,
3115 pStubMsg->RpcMsg->DataRepresentation);
3118 #define USER_MARSHAL_PTR_PREFIX \
3119 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
3120 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
3122 /***********************************************************************
3123 * NdrUserMarshalMarshall [RPCRT4.@]
3125 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3126 unsigned char *pMemory,
3127 PFORMAT_STRING pFormat)
3129 unsigned flags = pFormat[1];
3130 unsigned index = *(const WORD*)&pFormat[2];
3131 unsigned char *saved_buffer = NULL;
3132 ULONG uflag = UserMarshalFlags(pStubMsg);
3133 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3134 TRACE("index=%d\n", index);
3136 if (flags & USER_MARSHAL_POINTER)
3138 ALIGN_POINTER(pStubMsg->Buffer, 4);
3139 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
3140 pStubMsg->Buffer += 4;
3141 if (pStubMsg->PointerBufferMark)
3143 saved_buffer = pStubMsg->Buffer;
3144 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3145 pStubMsg->PointerBufferMark = NULL;
3147 ALIGN_POINTER(pStubMsg->Buffer, 8);
3149 else
3150 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3152 pStubMsg->Buffer =
3153 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
3154 &uflag, pStubMsg->Buffer, pMemory);
3156 if (saved_buffer)
3158 STD_OVERFLOW_CHECK(pStubMsg);
3159 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3160 pStubMsg->Buffer = saved_buffer;
3163 STD_OVERFLOW_CHECK(pStubMsg);
3165 return NULL;
3168 /***********************************************************************
3169 * NdrUserMarshalUnmarshall [RPCRT4.@]
3171 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3172 unsigned char **ppMemory,
3173 PFORMAT_STRING pFormat,
3174 unsigned char fMustAlloc)
3176 unsigned flags = pFormat[1];
3177 unsigned index = *(const WORD*)&pFormat[2];
3178 DWORD memsize = *(const WORD*)&pFormat[4];
3179 unsigned char *saved_buffer = NULL;
3180 ULONG uflag = UserMarshalFlags(pStubMsg);
3181 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3182 TRACE("index=%d\n", index);
3184 if (flags & USER_MARSHAL_POINTER)
3186 ALIGN_POINTER(pStubMsg->Buffer, 4);
3187 /* skip pointer prefix */
3188 pStubMsg->Buffer += 4;
3189 if (pStubMsg->PointerBufferMark)
3191 saved_buffer = pStubMsg->Buffer;
3192 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3193 pStubMsg->PointerBufferMark = NULL;
3195 ALIGN_POINTER(pStubMsg->Buffer, 8);
3197 else
3198 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3200 if (fMustAlloc || !*ppMemory)
3201 *ppMemory = NdrAllocate(pStubMsg, memsize);
3203 pStubMsg->Buffer =
3204 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
3205 &uflag, pStubMsg->Buffer, *ppMemory);
3207 if (saved_buffer)
3209 STD_OVERFLOW_CHECK(pStubMsg);
3210 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3211 pStubMsg->Buffer = saved_buffer;
3214 return NULL;
3217 /***********************************************************************
3218 * NdrUserMarshalBufferSize [RPCRT4.@]
3220 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3221 unsigned char *pMemory,
3222 PFORMAT_STRING pFormat)
3224 unsigned flags = pFormat[1];
3225 unsigned index = *(const WORD*)&pFormat[2];
3226 DWORD bufsize = *(const WORD*)&pFormat[6];
3227 ULONG uflag = UserMarshalFlags(pStubMsg);
3228 unsigned long saved_buffer_length = 0;
3229 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3230 TRACE("index=%d\n", index);
3232 if (flags & USER_MARSHAL_POINTER)
3234 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3235 /* skip pointer prefix */
3236 pStubMsg->BufferLength += 4;
3237 if (pStubMsg->IgnoreEmbeddedPointers)
3238 return;
3239 if (pStubMsg->PointerLength)
3241 saved_buffer_length = pStubMsg->BufferLength;
3242 pStubMsg->BufferLength = pStubMsg->PointerLength;
3243 pStubMsg->PointerLength = 0;
3245 ALIGN_LENGTH(pStubMsg->BufferLength, 8);
3247 else
3248 ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
3250 if (bufsize) {
3251 TRACE("size=%d\n", bufsize);
3252 pStubMsg->BufferLength += bufsize;
3254 else
3255 pStubMsg->BufferLength =
3256 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
3257 &uflag, pStubMsg->BufferLength, pMemory);
3259 if (saved_buffer_length)
3261 pStubMsg->PointerLength = pStubMsg->BufferLength;
3262 pStubMsg->BufferLength = saved_buffer_length;
3267 /***********************************************************************
3268 * NdrUserMarshalMemorySize [RPCRT4.@]
3270 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3271 PFORMAT_STRING pFormat)
3273 unsigned flags = pFormat[1];
3274 unsigned index = *(const WORD*)&pFormat[2];
3275 DWORD memsize = *(const WORD*)&pFormat[4];
3276 DWORD bufsize = *(const WORD*)&pFormat[6];
3278 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3279 TRACE("index=%d\n", index);
3281 pStubMsg->MemorySize += memsize;
3283 if (flags & USER_MARSHAL_POINTER)
3285 ALIGN_POINTER(pStubMsg->Buffer, 4);
3286 /* skip pointer prefix */
3287 pStubMsg->Buffer += 4;
3288 if (pStubMsg->IgnoreEmbeddedPointers)
3289 return pStubMsg->MemorySize;
3290 ALIGN_POINTER(pStubMsg->Buffer, 8);
3292 else
3293 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3295 if (!bufsize)
3296 FIXME("not implemented for varying buffer size\n");
3298 pStubMsg->Buffer += bufsize;
3300 return pStubMsg->MemorySize;
3303 /***********************************************************************
3304 * NdrUserMarshalFree [RPCRT4.@]
3306 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
3307 unsigned char *pMemory,
3308 PFORMAT_STRING pFormat)
3310 /* unsigned flags = pFormat[1]; */
3311 unsigned index = *(const WORD*)&pFormat[2];
3312 ULONG uflag = UserMarshalFlags(pStubMsg);
3313 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3314 TRACE("index=%d\n", index);
3316 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
3317 &uflag, pMemory);
3320 /***********************************************************************
3321 * NdrClearOutParameters [RPCRT4.@]
3323 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
3324 PFORMAT_STRING pFormat,
3325 void *ArgAddr)
3327 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
3330 /***********************************************************************
3331 * NdrConvert [RPCRT4.@]
3333 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
3335 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
3336 /* FIXME: since this stub doesn't do any converting, the proper behavior
3337 is to raise an exception */
3340 /***********************************************************************
3341 * NdrConvert2 [RPCRT4.@]
3343 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
3345 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
3346 pStubMsg, pFormat, NumberParams);
3347 /* FIXME: since this stub doesn't do any converting, the proper behavior
3348 is to raise an exception */
3351 #include "pshpack1.h"
3352 typedef struct _NDR_CSTRUCT_FORMAT
3354 unsigned char type;
3355 unsigned char alignment;
3356 unsigned short memory_size;
3357 short offset_to_array_description;
3358 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
3359 #include "poppack.h"
3361 /***********************************************************************
3362 * NdrConformantStructMarshall [RPCRT4.@]
3364 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3365 unsigned char *pMemory,
3366 PFORMAT_STRING pFormat)
3368 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3369 PFORMAT_STRING pCArrayFormat;
3370 ULONG esize, bufsize;
3372 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3374 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3375 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3377 ERR("invalid format type %x\n", pCStructFormat->type);
3378 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3379 return NULL;
3382 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3383 pCStructFormat->offset_to_array_description;
3384 if (*pCArrayFormat != RPC_FC_CARRAY)
3386 ERR("invalid array format type %x\n", pCStructFormat->type);
3387 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3388 return NULL;
3390 esize = *(const WORD*)(pCArrayFormat+2);
3392 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3393 pCArrayFormat + 4, 0);
3395 WriteConformance(pStubMsg);
3397 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3399 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3401 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3402 /* copy constant sized part of struct */
3403 pStubMsg->BufferMark = pStubMsg->Buffer;
3404 memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size + bufsize);
3405 pStubMsg->Buffer += pCStructFormat->memory_size + bufsize;
3407 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3408 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3410 STD_OVERFLOW_CHECK(pStubMsg);
3412 return NULL;
3415 /***********************************************************************
3416 * NdrConformantStructUnmarshall [RPCRT4.@]
3418 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3419 unsigned char **ppMemory,
3420 PFORMAT_STRING pFormat,
3421 unsigned char fMustAlloc)
3423 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3424 PFORMAT_STRING pCArrayFormat;
3425 ULONG esize, bufsize;
3427 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3429 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3430 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3432 ERR("invalid format type %x\n", pCStructFormat->type);
3433 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3434 return NULL;
3436 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3437 pCStructFormat->offset_to_array_description;
3438 if (*pCArrayFormat != RPC_FC_CARRAY)
3440 ERR("invalid array format type %x\n", pCStructFormat->type);
3441 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3442 return NULL;
3444 esize = *(const WORD*)(pCArrayFormat+2);
3446 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
3448 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3450 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3452 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3453 /* work out how much memory to allocate if we need to do so */
3454 if (!*ppMemory || fMustAlloc)
3456 SIZE_T size = pCStructFormat->memory_size + bufsize;
3457 *ppMemory = NdrAllocate(pStubMsg, size);
3460 /* now copy the data */
3461 pStubMsg->BufferMark = pStubMsg->Buffer;
3462 safe_buffer_copy(pStubMsg, *ppMemory, pCStructFormat->memory_size + bufsize);
3464 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3465 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3467 return NULL;
3470 /***********************************************************************
3471 * NdrConformantStructBufferSize [RPCRT4.@]
3473 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3474 unsigned char *pMemory,
3475 PFORMAT_STRING pFormat)
3477 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3478 PFORMAT_STRING pCArrayFormat;
3479 ULONG esize;
3481 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3483 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3484 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3486 ERR("invalid format type %x\n", pCStructFormat->type);
3487 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3488 return;
3490 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3491 pCStructFormat->offset_to_array_description;
3492 if (*pCArrayFormat != RPC_FC_CARRAY)
3494 ERR("invalid array format type %x\n", pCStructFormat->type);
3495 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3496 return;
3498 esize = *(const WORD*)(pCArrayFormat+2);
3500 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
3501 SizeConformance(pStubMsg);
3503 ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
3505 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3507 pStubMsg->BufferLength += pCStructFormat->memory_size +
3508 safe_multiply(pStubMsg->MaxCount, esize);
3510 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3511 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3514 /***********************************************************************
3515 * NdrConformantStructMemorySize [RPCRT4.@]
3517 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3518 PFORMAT_STRING pFormat)
3520 FIXME("stub\n");
3521 return 0;
3524 /***********************************************************************
3525 * NdrConformantStructFree [RPCRT4.@]
3527 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3528 unsigned char *pMemory,
3529 PFORMAT_STRING pFormat)
3531 FIXME("stub\n");
3534 /***********************************************************************
3535 * NdrConformantVaryingStructMarshall [RPCRT4.@]
3537 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3538 unsigned char *pMemory,
3539 PFORMAT_STRING pFormat)
3541 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3542 PFORMAT_STRING pCVArrayFormat;
3543 ULONG esize, bufsize;
3545 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3547 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3548 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3550 ERR("invalid format type %x\n", pCVStructFormat->type);
3551 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3552 return NULL;
3555 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3556 pCVStructFormat->offset_to_array_description;
3557 switch (*pCVArrayFormat)
3559 case RPC_FC_CVARRAY:
3560 esize = *(const WORD*)(pCVArrayFormat+2);
3562 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3563 pCVArrayFormat + 4, 0);
3564 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3565 pCVArrayFormat, 0);
3566 break;
3567 case RPC_FC_C_CSTRING:
3568 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3569 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3570 esize = sizeof(char);
3571 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3572 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3573 pCVArrayFormat + 2, 0);
3574 else
3575 pStubMsg->MaxCount = pStubMsg->ActualCount;
3576 break;
3577 case RPC_FC_C_WSTRING:
3578 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3579 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3580 esize = sizeof(WCHAR);
3581 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3582 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3583 pCVArrayFormat + 2, 0);
3584 else
3585 pStubMsg->MaxCount = pStubMsg->ActualCount;
3586 break;
3587 default:
3588 ERR("invalid array format type %x\n", *pCVArrayFormat);
3589 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3590 return NULL;
3593 WriteConformance(pStubMsg);
3595 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3597 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3599 /* write constant sized part */
3600 pStubMsg->BufferMark = pStubMsg->Buffer;
3601 memcpy(pStubMsg->Buffer, pMemory, pCVStructFormat->memory_size);
3602 pStubMsg->Buffer += pCVStructFormat->memory_size;
3604 WriteVariance(pStubMsg);
3606 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3608 /* write array part */
3609 memcpy(pStubMsg->Buffer, pMemory + pCVStructFormat->memory_size, bufsize);
3610 pStubMsg->Buffer += bufsize;
3612 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3614 STD_OVERFLOW_CHECK(pStubMsg);
3616 return NULL;
3619 /***********************************************************************
3620 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
3622 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3623 unsigned char **ppMemory,
3624 PFORMAT_STRING pFormat,
3625 unsigned char fMustAlloc)
3627 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3628 PFORMAT_STRING pCVArrayFormat;
3629 ULONG esize, bufsize;
3630 unsigned char cvarray_type;
3632 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3634 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3635 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3637 ERR("invalid format type %x\n", pCVStructFormat->type);
3638 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3639 return NULL;
3642 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3643 pCVStructFormat->offset_to_array_description;
3644 cvarray_type = *pCVArrayFormat;
3645 switch (cvarray_type)
3647 case RPC_FC_CVARRAY:
3648 esize = *(const WORD*)(pCVArrayFormat+2);
3649 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3650 break;
3651 case RPC_FC_C_CSTRING:
3652 esize = sizeof(char);
3653 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3654 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3655 else
3656 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3657 break;
3658 case RPC_FC_C_WSTRING:
3659 esize = sizeof(WCHAR);
3660 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3661 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3662 else
3663 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3664 break;
3665 default:
3666 ERR("invalid array format type %x\n", *pCVArrayFormat);
3667 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3668 return NULL;
3671 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3673 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3675 /* work out how much memory to allocate if we need to do so */
3676 if (!*ppMemory || fMustAlloc)
3678 SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3679 *ppMemory = NdrAllocate(pStubMsg, size);
3682 /* copy the constant data */
3683 pStubMsg->BufferMark = pStubMsg->Buffer;
3684 safe_buffer_copy(pStubMsg, *ppMemory, pCVStructFormat->memory_size);
3686 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3688 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3690 if ((cvarray_type == RPC_FC_C_CSTRING) ||
3691 (cvarray_type == RPC_FC_C_WSTRING))
3693 ULONG i;
3694 /* strings must always have null terminating bytes */
3695 if (bufsize < esize)
3697 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
3698 RpcRaiseException(RPC_S_INVALID_BOUND);
3699 return NULL;
3701 for (i = bufsize - esize; i < bufsize; i++)
3702 if (pStubMsg->Buffer[i] != 0)
3704 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
3705 i, pStubMsg->Buffer[i]);
3706 RpcRaiseException(RPC_S_INVALID_BOUND);
3707 return NULL;
3711 /* copy the array data */
3712 safe_buffer_copy(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize);
3714 if (cvarray_type == RPC_FC_C_CSTRING)
3715 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3716 else if (cvarray_type == RPC_FC_C_WSTRING)
3717 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3719 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3721 return NULL;
3724 /***********************************************************************
3725 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
3727 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3728 unsigned char *pMemory,
3729 PFORMAT_STRING pFormat)
3731 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3732 PFORMAT_STRING pCVArrayFormat;
3733 ULONG esize;
3735 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3737 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3738 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3740 ERR("invalid format type %x\n", pCVStructFormat->type);
3741 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3742 return;
3745 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3746 pCVStructFormat->offset_to_array_description;
3747 switch (*pCVArrayFormat)
3749 case RPC_FC_CVARRAY:
3750 esize = *(const WORD*)(pCVArrayFormat+2);
3752 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3753 pCVArrayFormat + 4, 0);
3754 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3755 pCVArrayFormat, 0);
3756 break;
3757 case RPC_FC_C_CSTRING:
3758 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3759 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3760 esize = sizeof(char);
3761 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3762 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3763 pCVArrayFormat + 2, 0);
3764 else
3765 pStubMsg->MaxCount = pStubMsg->ActualCount;
3766 break;
3767 case RPC_FC_C_WSTRING:
3768 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3769 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3770 esize = sizeof(WCHAR);
3771 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3772 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3773 pCVArrayFormat + 2, 0);
3774 else
3775 pStubMsg->MaxCount = pStubMsg->ActualCount;
3776 break;
3777 default:
3778 ERR("invalid array format type %x\n", *pCVArrayFormat);
3779 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3780 return;
3783 SizeConformance(pStubMsg);
3785 ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
3787 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3789 pStubMsg->BufferLength += pCVStructFormat->memory_size;
3790 SizeVariance(pStubMsg);
3791 pStubMsg->BufferLength += safe_multiply(pStubMsg->MaxCount, esize);
3793 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3796 /***********************************************************************
3797 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
3799 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3800 PFORMAT_STRING pFormat)
3802 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3803 PFORMAT_STRING pCVArrayFormat;
3804 ULONG esize;
3805 unsigned char cvarray_type;
3807 TRACE("(%p, %p)\n", pStubMsg, pFormat);
3809 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3810 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3812 ERR("invalid format type %x\n", pCVStructFormat->type);
3813 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3814 return 0;
3817 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3818 pCVStructFormat->offset_to_array_description;
3819 cvarray_type = *pCVArrayFormat;
3820 switch (cvarray_type)
3822 case RPC_FC_CVARRAY:
3823 esize = *(const WORD*)(pCVArrayFormat+2);
3824 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3825 break;
3826 case RPC_FC_C_CSTRING:
3827 esize = sizeof(char);
3828 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3829 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3830 else
3831 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3832 break;
3833 case RPC_FC_C_WSTRING:
3834 esize = sizeof(WCHAR);
3835 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3836 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3837 else
3838 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3839 break;
3840 default:
3841 ERR("invalid array format type %x\n", *pCVArrayFormat);
3842 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3843 return 0;
3846 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3848 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3850 pStubMsg->Buffer += pCVStructFormat->memory_size;
3851 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3852 pStubMsg->Buffer += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->ActualCount);
3854 pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3856 EmbeddedPointerMemorySize(pStubMsg, pFormat);
3858 return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3861 /***********************************************************************
3862 * NdrConformantVaryingStructFree [RPCRT4.@]
3864 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3865 unsigned char *pMemory,
3866 PFORMAT_STRING pFormat)
3868 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3869 PFORMAT_STRING pCVArrayFormat;
3870 ULONG esize;
3872 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3874 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3875 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3877 ERR("invalid format type %x\n", pCVStructFormat->type);
3878 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3879 return;
3882 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3883 pCVStructFormat->offset_to_array_description;
3884 switch (*pCVArrayFormat)
3886 case RPC_FC_CVARRAY:
3887 esize = *(const WORD*)(pCVArrayFormat+2);
3889 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3890 pCVArrayFormat + 4, 0);
3891 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3892 pCVArrayFormat, 0);
3893 break;
3894 case RPC_FC_C_CSTRING:
3895 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3896 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3897 esize = sizeof(char);
3898 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3899 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3900 pCVArrayFormat + 2, 0);
3901 else
3902 pStubMsg->MaxCount = pStubMsg->ActualCount;
3903 break;
3904 case RPC_FC_C_WSTRING:
3905 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3906 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3907 esize = sizeof(WCHAR);
3908 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3909 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3910 pCVArrayFormat + 2, 0);
3911 else
3912 pStubMsg->MaxCount = pStubMsg->ActualCount;
3913 break;
3914 default:
3915 ERR("invalid array format type %x\n", *pCVArrayFormat);
3916 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3917 return;
3920 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3922 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3925 #include "pshpack1.h"
3926 typedef struct
3928 unsigned char type;
3929 unsigned char alignment;
3930 unsigned short total_size;
3931 } NDR_SMFARRAY_FORMAT;
3933 typedef struct
3935 unsigned char type;
3936 unsigned char alignment;
3937 unsigned long total_size;
3938 } NDR_LGFARRAY_FORMAT;
3939 #include "poppack.h"
3941 /***********************************************************************
3942 * NdrFixedArrayMarshall [RPCRT4.@]
3944 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3945 unsigned char *pMemory,
3946 PFORMAT_STRING pFormat)
3948 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3949 unsigned long total_size;
3951 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3953 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3954 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3956 ERR("invalid format type %x\n", pSmFArrayFormat->type);
3957 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3958 return NULL;
3961 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3963 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3965 total_size = pSmFArrayFormat->total_size;
3966 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3968 else
3970 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3971 total_size = pLgFArrayFormat->total_size;
3972 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3975 memcpy(pStubMsg->Buffer, pMemory, total_size);
3976 pStubMsg->BufferMark = pStubMsg->Buffer;
3977 pStubMsg->Buffer += total_size;
3979 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3981 return NULL;
3984 /***********************************************************************
3985 * NdrFixedArrayUnmarshall [RPCRT4.@]
3987 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3988 unsigned char **ppMemory,
3989 PFORMAT_STRING pFormat,
3990 unsigned char fMustAlloc)
3992 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3993 unsigned long total_size;
3995 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3997 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3998 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4000 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4001 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4002 return NULL;
4005 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4007 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4009 total_size = pSmFArrayFormat->total_size;
4010 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4012 else
4014 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4015 total_size = pLgFArrayFormat->total_size;
4016 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4019 if (fMustAlloc || !*ppMemory)
4020 *ppMemory = NdrAllocate(pStubMsg, total_size);
4021 pStubMsg->BufferMark = pStubMsg->Buffer;
4022 safe_buffer_copy(pStubMsg, *ppMemory, total_size);
4024 pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
4026 return NULL;
4029 /***********************************************************************
4030 * NdrFixedArrayBufferSize [RPCRT4.@]
4032 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4033 unsigned char *pMemory,
4034 PFORMAT_STRING pFormat)
4036 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4037 unsigned long total_size;
4039 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4041 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4042 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4044 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4045 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4046 return;
4049 ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
4051 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4053 total_size = pSmFArrayFormat->total_size;
4054 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4056 else
4058 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4059 total_size = pLgFArrayFormat->total_size;
4060 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4062 pStubMsg->BufferLength += total_size;
4064 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4067 /***********************************************************************
4068 * NdrFixedArrayMemorySize [RPCRT4.@]
4070 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4071 PFORMAT_STRING pFormat)
4073 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4074 ULONG total_size;
4076 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4078 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4079 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4081 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4082 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4083 return 0;
4086 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4088 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4090 total_size = pSmFArrayFormat->total_size;
4091 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4093 else
4095 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4096 total_size = pLgFArrayFormat->total_size;
4097 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4099 pStubMsg->BufferMark = pStubMsg->Buffer;
4100 pStubMsg->Buffer += total_size;
4101 pStubMsg->MemorySize += total_size;
4103 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4105 return total_size;
4108 /***********************************************************************
4109 * NdrFixedArrayFree [RPCRT4.@]
4111 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4112 unsigned char *pMemory,
4113 PFORMAT_STRING pFormat)
4115 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4117 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4119 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4120 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4122 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4123 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4124 return;
4127 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4128 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4129 else
4131 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4132 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4135 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4138 /***********************************************************************
4139 * NdrVaryingArrayMarshall [RPCRT4.@]
4141 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4142 unsigned char *pMemory,
4143 PFORMAT_STRING pFormat)
4145 unsigned char alignment;
4146 DWORD elements, esize;
4147 ULONG bufsize;
4149 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4151 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4152 (pFormat[0] != RPC_FC_LGVARRAY))
4154 ERR("invalid format type %x\n", pFormat[0]);
4155 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4156 return NULL;
4159 alignment = pFormat[1] + 1;
4161 if (pFormat[0] == RPC_FC_SMVARRAY)
4163 pFormat += 2;
4164 pFormat += sizeof(WORD);
4165 elements = *(const WORD*)pFormat;
4166 pFormat += sizeof(WORD);
4168 else
4170 pFormat += 2;
4171 pFormat += sizeof(DWORD);
4172 elements = *(const DWORD*)pFormat;
4173 pFormat += sizeof(DWORD);
4176 esize = *(const WORD*)pFormat;
4177 pFormat += sizeof(WORD);
4179 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4180 if ((pStubMsg->ActualCount > elements) ||
4181 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4183 RpcRaiseException(RPC_S_INVALID_BOUND);
4184 return NULL;
4187 WriteVariance(pStubMsg);
4189 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4191 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4192 memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize);
4193 pStubMsg->BufferMark = pStubMsg->Buffer;
4194 pStubMsg->Buffer += bufsize;
4196 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4198 STD_OVERFLOW_CHECK(pStubMsg);
4200 return NULL;
4203 /***********************************************************************
4204 * NdrVaryingArrayUnmarshall [RPCRT4.@]
4206 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4207 unsigned char **ppMemory,
4208 PFORMAT_STRING pFormat,
4209 unsigned char fMustAlloc)
4211 unsigned char alignment;
4212 DWORD size, elements, esize;
4213 ULONG bufsize;
4215 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4217 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4218 (pFormat[0] != RPC_FC_LGVARRAY))
4220 ERR("invalid format type %x\n", pFormat[0]);
4221 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4222 return NULL;
4225 alignment = pFormat[1] + 1;
4227 if (pFormat[0] == RPC_FC_SMVARRAY)
4229 pFormat += 2;
4230 size = *(const WORD*)pFormat;
4231 pFormat += sizeof(WORD);
4232 elements = *(const WORD*)pFormat;
4233 pFormat += sizeof(WORD);
4235 else
4237 pFormat += 2;
4238 size = *(const DWORD*)pFormat;
4239 pFormat += sizeof(DWORD);
4240 elements = *(const DWORD*)pFormat;
4241 pFormat += sizeof(DWORD);
4244 esize = *(const WORD*)pFormat;
4245 pFormat += sizeof(WORD);
4247 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4249 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4251 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4253 if (!*ppMemory || fMustAlloc)
4254 *ppMemory = NdrAllocate(pStubMsg, size);
4255 safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
4257 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
4259 return NULL;
4262 /***********************************************************************
4263 * NdrVaryingArrayBufferSize [RPCRT4.@]
4265 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4266 unsigned char *pMemory,
4267 PFORMAT_STRING pFormat)
4269 unsigned char alignment;
4270 DWORD elements, esize;
4272 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4274 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4275 (pFormat[0] != RPC_FC_LGVARRAY))
4277 ERR("invalid format type %x\n", pFormat[0]);
4278 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4279 return;
4282 alignment = pFormat[1] + 1;
4284 if (pFormat[0] == RPC_FC_SMVARRAY)
4286 pFormat += 2;
4287 pFormat += sizeof(WORD);
4288 elements = *(const WORD*)pFormat;
4289 pFormat += sizeof(WORD);
4291 else
4293 pFormat += 2;
4294 pFormat += sizeof(DWORD);
4295 elements = *(const DWORD*)pFormat;
4296 pFormat += sizeof(DWORD);
4299 esize = *(const WORD*)pFormat;
4300 pFormat += sizeof(WORD);
4302 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4303 if ((pStubMsg->ActualCount > elements) ||
4304 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4306 RpcRaiseException(RPC_S_INVALID_BOUND);
4307 return;
4310 SizeVariance(pStubMsg);
4312 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4314 pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
4316 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4319 /***********************************************************************
4320 * NdrVaryingArrayMemorySize [RPCRT4.@]
4322 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4323 PFORMAT_STRING pFormat)
4325 unsigned char alignment;
4326 DWORD size, elements, esize;
4328 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4330 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4331 (pFormat[0] != RPC_FC_LGVARRAY))
4333 ERR("invalid format type %x\n", pFormat[0]);
4334 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4335 return 0;
4338 alignment = pFormat[1] + 1;
4340 if (pFormat[0] == RPC_FC_SMVARRAY)
4342 pFormat += 2;
4343 size = *(const WORD*)pFormat;
4344 pFormat += sizeof(WORD);
4345 elements = *(const WORD*)pFormat;
4346 pFormat += sizeof(WORD);
4348 else
4350 pFormat += 2;
4351 size = *(const DWORD*)pFormat;
4352 pFormat += sizeof(DWORD);
4353 elements = *(const DWORD*)pFormat;
4354 pFormat += sizeof(DWORD);
4357 esize = *(const WORD*)pFormat;
4358 pFormat += sizeof(WORD);
4360 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4362 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4364 pStubMsg->Buffer += safe_multiply(esize, pStubMsg->ActualCount);
4365 pStubMsg->MemorySize += size;
4367 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4369 return pStubMsg->MemorySize;
4372 /***********************************************************************
4373 * NdrVaryingArrayFree [RPCRT4.@]
4375 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4376 unsigned char *pMemory,
4377 PFORMAT_STRING pFormat)
4379 unsigned char alignment;
4380 DWORD elements;
4382 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4384 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4385 (pFormat[0] != RPC_FC_LGVARRAY))
4387 ERR("invalid format type %x\n", pFormat[0]);
4388 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4389 return;
4392 alignment = pFormat[1] + 1;
4394 if (pFormat[0] == RPC_FC_SMVARRAY)
4396 pFormat += 2;
4397 pFormat += sizeof(WORD);
4398 elements = *(const WORD*)pFormat;
4399 pFormat += sizeof(WORD);
4401 else
4403 pFormat += 2;
4404 pFormat += sizeof(DWORD);
4405 elements = *(const DWORD*)pFormat;
4406 pFormat += sizeof(DWORD);
4409 pFormat += sizeof(WORD);
4411 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4412 if ((pStubMsg->ActualCount > elements) ||
4413 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4415 RpcRaiseException(RPC_S_INVALID_BOUND);
4416 return;
4419 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4422 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
4424 switch (fc)
4426 case RPC_FC_BYTE:
4427 case RPC_FC_CHAR:
4428 case RPC_FC_SMALL:
4429 case RPC_FC_USMALL:
4430 return *(const UCHAR *)pMemory;
4431 case RPC_FC_WCHAR:
4432 case RPC_FC_SHORT:
4433 case RPC_FC_USHORT:
4434 case RPC_FC_ENUM16:
4435 return *(const USHORT *)pMemory;
4436 case RPC_FC_LONG:
4437 case RPC_FC_ULONG:
4438 case RPC_FC_ENUM32:
4439 return *(const ULONG *)pMemory;
4440 default:
4441 FIXME("Unhandled base type: 0x%02x\n", fc);
4442 return 0;
4446 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
4447 unsigned long discriminant,
4448 PFORMAT_STRING pFormat)
4450 unsigned short num_arms, arm, type;
4452 num_arms = *(const SHORT*)pFormat & 0x0fff;
4453 pFormat += 2;
4454 for(arm = 0; arm < num_arms; arm++)
4456 if(discriminant == *(const ULONG*)pFormat)
4458 pFormat += 4;
4459 break;
4461 pFormat += 6;
4464 type = *(const unsigned short*)pFormat;
4465 TRACE("type %04x\n", type);
4466 if(arm == num_arms) /* default arm extras */
4468 if(type == 0xffff)
4470 ERR("no arm for 0x%lx and no default case\n", discriminant);
4471 RpcRaiseException(RPC_S_INVALID_TAG);
4472 return NULL;
4474 if(type == 0)
4476 TRACE("falling back to empty default case for 0x%lx\n", discriminant);
4477 return NULL;
4480 return pFormat;
4483 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
4485 unsigned short type;
4487 pFormat += 2;
4489 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4490 if(!pFormat)
4491 return NULL;
4493 type = *(const unsigned short*)pFormat;
4494 if((type & 0xff00) == 0x8000)
4496 unsigned char basetype = LOBYTE(type);
4497 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4499 else
4501 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4502 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4503 if (m)
4505 unsigned char *saved_buffer = NULL;
4506 int pointer_buffer_mark_set = 0;
4507 switch(*desc)
4509 case RPC_FC_RP:
4510 case RPC_FC_UP:
4511 case RPC_FC_OP:
4512 case RPC_FC_FP:
4513 ALIGN_POINTER(pStubMsg->Buffer, 4);
4514 saved_buffer = pStubMsg->Buffer;
4515 if (pStubMsg->PointerBufferMark)
4517 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4518 pStubMsg->PointerBufferMark = NULL;
4519 pointer_buffer_mark_set = 1;
4521 else
4522 pStubMsg->Buffer += 4; /* for pointer ID */
4524 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
4525 if (pointer_buffer_mark_set)
4527 STD_OVERFLOW_CHECK(pStubMsg);
4528 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4529 pStubMsg->Buffer = saved_buffer + 4;
4531 break;
4532 default:
4533 m(pStubMsg, pMemory, desc);
4536 else FIXME("no marshaller for embedded type %02x\n", *desc);
4538 return NULL;
4541 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4542 unsigned char **ppMemory,
4543 ULONG discriminant,
4544 PFORMAT_STRING pFormat,
4545 unsigned char fMustAlloc)
4547 unsigned short type;
4549 pFormat += 2;
4551 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4552 if(!pFormat)
4553 return NULL;
4555 type = *(const unsigned short*)pFormat;
4556 if((type & 0xff00) == 0x8000)
4558 unsigned char basetype = LOBYTE(type);
4559 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
4561 else
4563 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4564 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
4565 if (m)
4567 unsigned char *saved_buffer = NULL;
4568 int pointer_buffer_mark_set = 0;
4569 switch(*desc)
4571 case RPC_FC_RP:
4572 case RPC_FC_UP:
4573 case RPC_FC_OP:
4574 case RPC_FC_FP:
4575 **(void***)ppMemory = NULL;
4576 ALIGN_POINTER(pStubMsg->Buffer, 4);
4577 saved_buffer = pStubMsg->Buffer;
4578 if (pStubMsg->PointerBufferMark)
4580 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4581 pStubMsg->PointerBufferMark = NULL;
4582 pointer_buffer_mark_set = 1;
4584 else
4585 pStubMsg->Buffer += 4; /* for pointer ID */
4587 if (saved_buffer + 4 > pStubMsg->BufferEnd)
4588 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4590 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, fMustAlloc);
4591 if (pointer_buffer_mark_set)
4593 STD_OVERFLOW_CHECK(pStubMsg);
4594 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4595 pStubMsg->Buffer = saved_buffer + 4;
4597 break;
4598 default:
4599 m(pStubMsg, ppMemory, desc, fMustAlloc);
4602 else FIXME("no marshaller for embedded type %02x\n", *desc);
4604 return NULL;
4607 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
4608 unsigned char *pMemory,
4609 ULONG discriminant,
4610 PFORMAT_STRING pFormat)
4612 unsigned short type;
4614 pFormat += 2;
4616 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4617 if(!pFormat)
4618 return;
4620 type = *(const unsigned short*)pFormat;
4621 if((type & 0xff00) == 0x8000)
4623 unsigned char basetype = LOBYTE(type);
4624 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
4626 else
4628 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4629 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
4630 if (m)
4632 switch(*desc)
4634 case RPC_FC_RP:
4635 case RPC_FC_UP:
4636 case RPC_FC_OP:
4637 case RPC_FC_FP:
4638 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4639 pStubMsg->BufferLength += 4; /* for pointer ID */
4640 if (!pStubMsg->IgnoreEmbeddedPointers)
4642 int saved_buffer_length = pStubMsg->BufferLength;
4643 pStubMsg->BufferLength = pStubMsg->PointerLength;
4644 pStubMsg->PointerLength = 0;
4645 if(!pStubMsg->BufferLength)
4646 ERR("BufferLength == 0??\n");
4647 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
4648 pStubMsg->PointerLength = pStubMsg->BufferLength;
4649 pStubMsg->BufferLength = saved_buffer_length;
4651 break;
4652 default:
4653 m(pStubMsg, pMemory, desc);
4656 else FIXME("no buffersizer for embedded type %02x\n", *desc);
4660 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
4661 ULONG discriminant,
4662 PFORMAT_STRING pFormat)
4664 unsigned short type, size;
4666 size = *(const unsigned short*)pFormat;
4667 pStubMsg->Memory += size;
4668 pFormat += 2;
4670 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4671 if(!pFormat)
4672 return 0;
4674 type = *(const unsigned short*)pFormat;
4675 if((type & 0xff00) == 0x8000)
4677 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
4679 else
4681 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4682 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
4683 unsigned char *saved_buffer;
4684 if (m)
4686 switch(*desc)
4688 case RPC_FC_RP:
4689 case RPC_FC_UP:
4690 case RPC_FC_OP:
4691 case RPC_FC_FP:
4692 ALIGN_POINTER(pStubMsg->Buffer, 4);
4693 saved_buffer = pStubMsg->Buffer;
4694 pStubMsg->Buffer += 4;
4695 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
4696 pStubMsg->MemorySize += 4;
4697 if (!pStubMsg->IgnoreEmbeddedPointers)
4698 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
4699 break;
4700 default:
4701 return m(pStubMsg, desc);
4704 else FIXME("no marshaller for embedded type %02x\n", *desc);
4707 TRACE("size %d\n", size);
4708 return size;
4711 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
4712 unsigned char *pMemory,
4713 ULONG discriminant,
4714 PFORMAT_STRING pFormat)
4716 unsigned short type;
4718 pFormat += 2;
4720 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4721 if(!pFormat)
4722 return;
4724 type = *(const unsigned short*)pFormat;
4725 if((type & 0xff00) != 0x8000)
4727 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4728 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
4729 if (m)
4731 switch(*desc)
4733 case RPC_FC_RP:
4734 case RPC_FC_UP:
4735 case RPC_FC_OP:
4736 case RPC_FC_FP:
4737 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
4738 break;
4739 default:
4740 m(pStubMsg, pMemory, desc);
4743 else FIXME("no freer for embedded type %02x\n", *desc);
4747 /***********************************************************************
4748 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
4750 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4751 unsigned char *pMemory,
4752 PFORMAT_STRING pFormat)
4754 unsigned char switch_type;
4755 unsigned char increment;
4756 ULONG switch_value;
4758 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4759 pFormat++;
4761 switch_type = *pFormat & 0xf;
4762 increment = (*pFormat & 0xf0) >> 4;
4763 pFormat++;
4765 ALIGN_POINTER(pStubMsg->Buffer, increment);
4767 switch_value = get_discriminant(switch_type, pMemory);
4768 TRACE("got switch value 0x%x\n", switch_value);
4770 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
4771 pMemory += increment;
4773 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
4776 /***********************************************************************
4777 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
4779 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4780 unsigned char **ppMemory,
4781 PFORMAT_STRING pFormat,
4782 unsigned char fMustAlloc)
4784 unsigned char switch_type;
4785 unsigned char increment;
4786 ULONG switch_value;
4787 unsigned short size;
4788 unsigned char *pMemoryArm;
4790 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4791 pFormat++;
4793 switch_type = *pFormat & 0xf;
4794 increment = (*pFormat & 0xf0) >> 4;
4795 pFormat++;
4797 ALIGN_POINTER(pStubMsg->Buffer, increment);
4798 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
4799 TRACE("got switch value 0x%x\n", switch_value);
4801 size = *(const unsigned short*)pFormat + increment;
4802 if(!*ppMemory || fMustAlloc)
4803 *ppMemory = NdrAllocate(pStubMsg, size);
4805 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
4806 pMemoryArm = *ppMemory + increment;
4808 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
4811 /***********************************************************************
4812 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
4814 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4815 unsigned char *pMemory,
4816 PFORMAT_STRING pFormat)
4818 unsigned char switch_type;
4819 unsigned char increment;
4820 ULONG switch_value;
4822 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4823 pFormat++;
4825 switch_type = *pFormat & 0xf;
4826 increment = (*pFormat & 0xf0) >> 4;
4827 pFormat++;
4829 ALIGN_LENGTH(pStubMsg->BufferLength, increment);
4830 switch_value = get_discriminant(switch_type, pMemory);
4831 TRACE("got switch value 0x%x\n", switch_value);
4833 /* Add discriminant size */
4834 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
4835 pMemory += increment;
4837 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
4840 /***********************************************************************
4841 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
4843 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4844 PFORMAT_STRING pFormat)
4846 unsigned char switch_type;
4847 unsigned char increment;
4848 ULONG switch_value;
4850 switch_type = *pFormat & 0xf;
4851 increment = (*pFormat & 0xf0) >> 4;
4852 pFormat++;
4854 ALIGN_POINTER(pStubMsg->Buffer, increment);
4855 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
4856 TRACE("got switch value 0x%x\n", switch_value);
4858 pStubMsg->Memory += increment;
4860 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
4863 /***********************************************************************
4864 * NdrEncapsulatedUnionFree [RPCRT4.@]
4866 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
4867 unsigned char *pMemory,
4868 PFORMAT_STRING pFormat)
4870 unsigned char switch_type;
4871 unsigned char increment;
4872 ULONG switch_value;
4874 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4875 pFormat++;
4877 switch_type = *pFormat & 0xf;
4878 increment = (*pFormat & 0xf0) >> 4;
4879 pFormat++;
4881 switch_value = get_discriminant(switch_type, pMemory);
4882 TRACE("got switch value 0x%x\n", switch_value);
4884 pMemory += increment;
4886 return union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
4889 /***********************************************************************
4890 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
4892 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4893 unsigned char *pMemory,
4894 PFORMAT_STRING pFormat)
4896 unsigned char switch_type;
4898 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4899 pFormat++;
4901 switch_type = *pFormat;
4902 pFormat++;
4904 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4905 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4906 /* Marshall discriminant */
4907 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
4909 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
4912 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
4913 PFORMAT_STRING *ppFormat)
4915 long discriminant = 0;
4917 switch(**ppFormat)
4919 case RPC_FC_BYTE:
4920 case RPC_FC_CHAR:
4921 case RPC_FC_SMALL:
4922 case RPC_FC_USMALL:
4924 UCHAR d;
4925 safe_buffer_copy(pStubMsg, &d, sizeof(d));
4926 discriminant = d;
4927 break;
4929 case RPC_FC_WCHAR:
4930 case RPC_FC_SHORT:
4931 case RPC_FC_USHORT:
4933 USHORT d;
4934 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4935 safe_buffer_copy(pStubMsg, &d, sizeof(d));
4936 discriminant = d;
4937 break;
4939 case RPC_FC_LONG:
4940 case RPC_FC_ULONG:
4942 ULONG d;
4943 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4944 safe_buffer_copy(pStubMsg, &d, sizeof(d));
4945 discriminant = d;
4946 break;
4948 default:
4949 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
4951 (*ppFormat)++;
4953 if (pStubMsg->fHasNewCorrDesc)
4954 *ppFormat += 6;
4955 else
4956 *ppFormat += 4;
4957 return discriminant;
4960 /**********************************************************************
4961 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
4963 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4964 unsigned char **ppMemory,
4965 PFORMAT_STRING pFormat,
4966 unsigned char fMustAlloc)
4968 long discriminant;
4969 unsigned short size;
4971 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4972 pFormat++;
4974 /* Unmarshall discriminant */
4975 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
4976 TRACE("unmarshalled discriminant %lx\n", discriminant);
4978 pFormat += *(const SHORT*)pFormat;
4980 size = *(const unsigned short*)pFormat;
4982 if(!*ppMemory || fMustAlloc)
4983 *ppMemory = NdrAllocate(pStubMsg, size);
4985 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
4988 /***********************************************************************
4989 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
4991 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4992 unsigned char *pMemory,
4993 PFORMAT_STRING pFormat)
4995 unsigned char switch_type;
4997 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4998 pFormat++;
5000 switch_type = *pFormat;
5001 pFormat++;
5003 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5004 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5005 /* Add discriminant size */
5006 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5008 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5011 /***********************************************************************
5012 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
5014 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5015 PFORMAT_STRING pFormat)
5017 ULONG discriminant;
5019 pFormat++;
5020 /* Unmarshall discriminant */
5021 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5022 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
5024 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
5027 /***********************************************************************
5028 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
5030 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5031 unsigned char *pMemory,
5032 PFORMAT_STRING pFormat)
5034 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5035 pFormat++;
5036 pFormat++;
5038 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5039 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5041 return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5044 /***********************************************************************
5045 * NdrByteCountPointerMarshall [RPCRT4.@]
5047 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5048 unsigned char *pMemory,
5049 PFORMAT_STRING pFormat)
5051 FIXME("stub\n");
5052 return NULL;
5055 /***********************************************************************
5056 * NdrByteCountPointerUnmarshall [RPCRT4.@]
5058 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5059 unsigned char **ppMemory,
5060 PFORMAT_STRING pFormat,
5061 unsigned char fMustAlloc)
5063 FIXME("stub\n");
5064 return NULL;
5067 /***********************************************************************
5068 * NdrByteCountPointerBufferSize [RPCRT4.@]
5070 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5071 unsigned char *pMemory,
5072 PFORMAT_STRING pFormat)
5074 FIXME("stub\n");
5077 /***********************************************************************
5078 * NdrByteCountPointerMemorySize [RPCRT4.@]
5080 ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5081 PFORMAT_STRING pFormat)
5083 FIXME("stub\n");
5084 return 0;
5087 /***********************************************************************
5088 * NdrByteCountPointerFree [RPCRT4.@]
5090 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
5091 unsigned char *pMemory,
5092 PFORMAT_STRING pFormat)
5094 FIXME("stub\n");
5097 /***********************************************************************
5098 * NdrXmitOrRepAsMarshall [RPCRT4.@]
5100 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5101 unsigned char *pMemory,
5102 PFORMAT_STRING pFormat)
5104 FIXME("stub\n");
5105 return NULL;
5108 /***********************************************************************
5109 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
5111 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5112 unsigned char **ppMemory,
5113 PFORMAT_STRING pFormat,
5114 unsigned char fMustAlloc)
5116 FIXME("stub\n");
5117 return NULL;
5120 /***********************************************************************
5121 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
5123 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5124 unsigned char *pMemory,
5125 PFORMAT_STRING pFormat)
5127 FIXME("stub\n");
5130 /***********************************************************************
5131 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
5133 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5134 PFORMAT_STRING pFormat)
5136 FIXME("stub\n");
5137 return 0;
5140 /***********************************************************************
5141 * NdrXmitOrRepAsFree [RPCRT4.@]
5143 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
5144 unsigned char *pMemory,
5145 PFORMAT_STRING pFormat)
5147 FIXME("stub\n");
5150 #include "pshpack1.h"
5151 typedef struct
5153 unsigned char type;
5154 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
5155 ULONG low_value;
5156 ULONG high_value;
5157 } NDR_RANGE;
5158 #include "poppack.h"
5160 /***********************************************************************
5161 * NdrRangeMarshall [internal]
5163 unsigned char *WINAPI NdrRangeMarshall(
5164 PMIDL_STUB_MESSAGE pStubMsg,
5165 unsigned char *pMemory,
5166 PFORMAT_STRING pFormat)
5168 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5169 unsigned char base_type;
5171 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5173 if (pRange->type != RPC_FC_RANGE)
5175 ERR("invalid format type %x\n", pRange->type);
5176 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5177 return NULL;
5180 base_type = pRange->flags_type & 0xf;
5182 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
5185 /***********************************************************************
5186 * NdrRangeUnmarshall
5188 unsigned char *WINAPI NdrRangeUnmarshall(
5189 PMIDL_STUB_MESSAGE pStubMsg,
5190 unsigned char **ppMemory,
5191 PFORMAT_STRING pFormat,
5192 unsigned char fMustAlloc)
5194 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5195 unsigned char base_type;
5197 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5199 if (pRange->type != RPC_FC_RANGE)
5201 ERR("invalid format type %x\n", pRange->type);
5202 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5203 return NULL;
5205 base_type = pRange->flags_type & 0xf;
5207 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
5208 base_type, pRange->low_value, pRange->high_value);
5210 #define RANGE_UNMARSHALL(type, format_spec) \
5211 do \
5213 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5214 if (fMustAlloc || !*ppMemory) \
5215 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5216 if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \
5217 (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \
5219 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
5220 *(type *)pStubMsg->Buffer, (type)pRange->low_value, \
5221 (type)pRange->high_value); \
5222 RpcRaiseException(RPC_S_INVALID_BOUND); \
5223 return NULL; \
5225 TRACE("*ppMemory: %p\n", *ppMemory); \
5226 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5227 pStubMsg->Buffer += sizeof(type); \
5228 } while (0)
5230 switch(base_type)
5232 case RPC_FC_CHAR:
5233 case RPC_FC_SMALL:
5234 RANGE_UNMARSHALL(UCHAR, "%d");
5235 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5236 break;
5237 case RPC_FC_BYTE:
5238 case RPC_FC_USMALL:
5239 RANGE_UNMARSHALL(CHAR, "%u");
5240 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5241 break;
5242 case RPC_FC_WCHAR: /* FIXME: valid? */
5243 case RPC_FC_USHORT:
5244 RANGE_UNMARSHALL(USHORT, "%u");
5245 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5246 break;
5247 case RPC_FC_SHORT:
5248 RANGE_UNMARSHALL(SHORT, "%d");
5249 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5250 break;
5251 case RPC_FC_LONG:
5252 RANGE_UNMARSHALL(LONG, "%d");
5253 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5254 break;
5255 case RPC_FC_ULONG:
5256 RANGE_UNMARSHALL(ULONG, "%u");
5257 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5258 break;
5259 case RPC_FC_ENUM16:
5260 case RPC_FC_ENUM32:
5261 FIXME("Unhandled enum type\n");
5262 break;
5263 case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */
5264 case RPC_FC_FLOAT:
5265 case RPC_FC_DOUBLE:
5266 case RPC_FC_HYPER:
5267 default:
5268 ERR("invalid range base type: 0x%02x\n", base_type);
5269 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5272 return NULL;
5275 /***********************************************************************
5276 * NdrRangeBufferSize [internal]
5278 void WINAPI NdrRangeBufferSize(
5279 PMIDL_STUB_MESSAGE pStubMsg,
5280 unsigned char *pMemory,
5281 PFORMAT_STRING pFormat)
5283 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5284 unsigned char base_type;
5286 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5288 if (pRange->type != RPC_FC_RANGE)
5290 ERR("invalid format type %x\n", pRange->type);
5291 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5293 base_type = pRange->flags_type & 0xf;
5295 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
5298 /***********************************************************************
5299 * NdrRangeMemorySize [internal]
5301 ULONG WINAPI NdrRangeMemorySize(
5302 PMIDL_STUB_MESSAGE pStubMsg,
5303 PFORMAT_STRING pFormat)
5305 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5306 unsigned char base_type;
5308 if (pRange->type != RPC_FC_RANGE)
5310 ERR("invalid format type %x\n", pRange->type);
5311 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5312 return 0;
5314 base_type = pRange->flags_type & 0xf;
5316 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
5319 /***********************************************************************
5320 * NdrRangeFree [internal]
5322 void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
5323 unsigned char *pMemory,
5324 PFORMAT_STRING pFormat)
5326 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5328 /* nothing to do */
5331 /***********************************************************************
5332 * NdrBaseTypeMarshall [internal]
5334 static unsigned char *WINAPI NdrBaseTypeMarshall(
5335 PMIDL_STUB_MESSAGE pStubMsg,
5336 unsigned char *pMemory,
5337 PFORMAT_STRING pFormat)
5339 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5341 switch(*pFormat)
5343 case RPC_FC_BYTE:
5344 case RPC_FC_CHAR:
5345 case RPC_FC_SMALL:
5346 case RPC_FC_USMALL:
5347 *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory;
5348 pStubMsg->Buffer += sizeof(UCHAR);
5349 TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
5350 break;
5351 case RPC_FC_WCHAR:
5352 case RPC_FC_SHORT:
5353 case RPC_FC_USHORT:
5354 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5355 *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory;
5356 pStubMsg->Buffer += sizeof(USHORT);
5357 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
5358 break;
5359 case RPC_FC_LONG:
5360 case RPC_FC_ULONG:
5361 case RPC_FC_ERROR_STATUS_T:
5362 case RPC_FC_ENUM32:
5363 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5364 *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory;
5365 pStubMsg->Buffer += sizeof(ULONG);
5366 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
5367 break;
5368 case RPC_FC_FLOAT:
5369 ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
5370 *(float *)pStubMsg->Buffer = *(float *)pMemory;
5371 pStubMsg->Buffer += sizeof(float);
5372 break;
5373 case RPC_FC_DOUBLE:
5374 ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
5375 *(double *)pStubMsg->Buffer = *(double *)pMemory;
5376 pStubMsg->Buffer += sizeof(double);
5377 break;
5378 case RPC_FC_HYPER:
5379 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
5380 *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory;
5381 pStubMsg->Buffer += sizeof(ULONGLONG);
5382 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
5383 break;
5384 case RPC_FC_ENUM16:
5385 /* only 16-bits on the wire, so do a sanity check */
5386 if (*(UINT *)pMemory > SHRT_MAX)
5387 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
5388 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5389 *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
5390 pStubMsg->Buffer += sizeof(USHORT);
5391 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
5392 break;
5393 default:
5394 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5397 STD_OVERFLOW_CHECK(pStubMsg);
5399 /* FIXME: what is the correct return value? */
5400 return NULL;
5403 /***********************************************************************
5404 * NdrBaseTypeUnmarshall [internal]
5406 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
5407 PMIDL_STUB_MESSAGE pStubMsg,
5408 unsigned char **ppMemory,
5409 PFORMAT_STRING pFormat,
5410 unsigned char fMustAlloc)
5412 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5414 #define BASE_TYPE_UNMARSHALL(type) \
5415 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5416 if (fMustAlloc || !*ppMemory) \
5417 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5418 TRACE("*ppMemory: %p\n", *ppMemory); \
5419 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5420 pStubMsg->Buffer += sizeof(type);
5422 switch(*pFormat)
5424 case RPC_FC_BYTE:
5425 case RPC_FC_CHAR:
5426 case RPC_FC_SMALL:
5427 case RPC_FC_USMALL:
5428 BASE_TYPE_UNMARSHALL(UCHAR);
5429 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5430 break;
5431 case RPC_FC_WCHAR:
5432 case RPC_FC_SHORT:
5433 case RPC_FC_USHORT:
5434 BASE_TYPE_UNMARSHALL(USHORT);
5435 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5436 break;
5437 case RPC_FC_LONG:
5438 case RPC_FC_ULONG:
5439 case RPC_FC_ERROR_STATUS_T:
5440 case RPC_FC_ENUM32:
5441 BASE_TYPE_UNMARSHALL(ULONG);
5442 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5443 break;
5444 case RPC_FC_FLOAT:
5445 BASE_TYPE_UNMARSHALL(float);
5446 TRACE("value: %f\n", **(float **)ppMemory);
5447 break;
5448 case RPC_FC_DOUBLE:
5449 BASE_TYPE_UNMARSHALL(double);
5450 TRACE("value: %f\n", **(double **)ppMemory);
5451 break;
5452 case RPC_FC_HYPER:
5453 BASE_TYPE_UNMARSHALL(ULONGLONG);
5454 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
5455 break;
5456 case RPC_FC_ENUM16:
5457 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5458 if (fMustAlloc || !*ppMemory)
5459 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
5460 TRACE("*ppMemory: %p\n", *ppMemory);
5461 /* 16-bits on the wire, but int in memory */
5462 **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
5463 pStubMsg->Buffer += sizeof(USHORT);
5464 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
5465 break;
5466 default:
5467 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5469 #undef BASE_TYPE_UNMARSHALL
5471 /* FIXME: what is the correct return value? */
5473 return NULL;
5476 /***********************************************************************
5477 * NdrBaseTypeBufferSize [internal]
5479 static void WINAPI NdrBaseTypeBufferSize(
5480 PMIDL_STUB_MESSAGE pStubMsg,
5481 unsigned char *pMemory,
5482 PFORMAT_STRING pFormat)
5484 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5486 switch(*pFormat)
5488 case RPC_FC_BYTE:
5489 case RPC_FC_CHAR:
5490 case RPC_FC_SMALL:
5491 case RPC_FC_USMALL:
5492 pStubMsg->BufferLength += sizeof(UCHAR);
5493 break;
5494 case RPC_FC_WCHAR:
5495 case RPC_FC_SHORT:
5496 case RPC_FC_USHORT:
5497 case RPC_FC_ENUM16:
5498 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
5499 pStubMsg->BufferLength += sizeof(USHORT);
5500 break;
5501 case RPC_FC_LONG:
5502 case RPC_FC_ULONG:
5503 case RPC_FC_ENUM32:
5504 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
5505 pStubMsg->BufferLength += sizeof(ULONG);
5506 break;
5507 case RPC_FC_FLOAT:
5508 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
5509 pStubMsg->BufferLength += sizeof(float);
5510 break;
5511 case RPC_FC_DOUBLE:
5512 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
5513 pStubMsg->BufferLength += sizeof(double);
5514 break;
5515 case RPC_FC_HYPER:
5516 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
5517 pStubMsg->BufferLength += sizeof(ULONGLONG);
5518 break;
5519 case RPC_FC_ERROR_STATUS_T:
5520 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
5521 pStubMsg->BufferLength += sizeof(error_status_t);
5522 break;
5523 default:
5524 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5528 /***********************************************************************
5529 * NdrBaseTypeMemorySize [internal]
5531 static ULONG WINAPI NdrBaseTypeMemorySize(
5532 PMIDL_STUB_MESSAGE pStubMsg,
5533 PFORMAT_STRING pFormat)
5535 switch(*pFormat)
5537 case RPC_FC_BYTE:
5538 case RPC_FC_CHAR:
5539 case RPC_FC_SMALL:
5540 case RPC_FC_USMALL:
5541 pStubMsg->Buffer += sizeof(UCHAR);
5542 pStubMsg->MemorySize += sizeof(UCHAR);
5543 return sizeof(UCHAR);
5544 case RPC_FC_WCHAR:
5545 case RPC_FC_SHORT:
5546 case RPC_FC_USHORT:
5547 pStubMsg->Buffer += sizeof(USHORT);
5548 pStubMsg->MemorySize += sizeof(USHORT);
5549 return sizeof(USHORT);
5550 case RPC_FC_LONG:
5551 case RPC_FC_ULONG:
5552 pStubMsg->Buffer += sizeof(ULONG);
5553 pStubMsg->MemorySize += sizeof(ULONG);
5554 return sizeof(ULONG);
5555 case RPC_FC_FLOAT:
5556 pStubMsg->Buffer += sizeof(float);
5557 pStubMsg->MemorySize += sizeof(float);
5558 return sizeof(float);
5559 case RPC_FC_DOUBLE:
5560 pStubMsg->Buffer += sizeof(double);
5561 pStubMsg->MemorySize += sizeof(double);
5562 return sizeof(double);
5563 case RPC_FC_HYPER:
5564 pStubMsg->Buffer += sizeof(ULONGLONG);
5565 pStubMsg->MemorySize += sizeof(ULONGLONG);
5566 return sizeof(ULONGLONG);
5567 case RPC_FC_ERROR_STATUS_T:
5568 pStubMsg->Buffer += sizeof(error_status_t);
5569 pStubMsg->MemorySize += sizeof(error_status_t);
5570 return sizeof(error_status_t);
5571 case RPC_FC_ENUM16:
5572 case RPC_FC_ENUM32:
5573 pStubMsg->Buffer += sizeof(INT);
5574 pStubMsg->MemorySize += sizeof(INT);
5575 return sizeof(INT);
5576 default:
5577 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5578 return 0;
5582 /***********************************************************************
5583 * NdrBaseTypeFree [internal]
5585 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
5586 unsigned char *pMemory,
5587 PFORMAT_STRING pFormat)
5589 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5591 /* nothing to do */
5594 /***********************************************************************
5595 * NdrContextHandleBufferSize [internal]
5597 static void WINAPI NdrContextHandleBufferSize(
5598 PMIDL_STUB_MESSAGE pStubMsg,
5599 unsigned char *pMemory,
5600 PFORMAT_STRING pFormat)
5602 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5604 if (*pFormat != RPC_FC_BIND_CONTEXT)
5606 ERR("invalid format type %x\n", *pFormat);
5607 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5609 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5610 pStubMsg->BufferLength += cbNDRContext;
5613 /***********************************************************************
5614 * NdrContextHandleMarshall [internal]
5616 static unsigned char *WINAPI NdrContextHandleMarshall(
5617 PMIDL_STUB_MESSAGE pStubMsg,
5618 unsigned char *pMemory,
5619 PFORMAT_STRING pFormat)
5621 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5623 if (*pFormat != RPC_FC_BIND_CONTEXT)
5625 ERR("invalid format type %x\n", *pFormat);
5626 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5629 if (pFormat[1] & 0x80)
5630 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
5631 else
5632 NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE);
5634 return NULL;
5637 /***********************************************************************
5638 * NdrContextHandleUnmarshall [internal]
5640 static unsigned char *WINAPI NdrContextHandleUnmarshall(
5641 PMIDL_STUB_MESSAGE pStubMsg,
5642 unsigned char **ppMemory,
5643 PFORMAT_STRING pFormat,
5644 unsigned char fMustAlloc)
5646 if (*pFormat != RPC_FC_BIND_CONTEXT)
5648 ERR("invalid format type %x\n", *pFormat);
5649 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5652 **(NDR_CCONTEXT **)ppMemory = NULL;
5653 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
5655 return NULL;
5658 /***********************************************************************
5659 * NdrClientContextMarshall [RPCRT4.@]
5661 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5662 NDR_CCONTEXT ContextHandle,
5663 int fCheck)
5665 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
5667 ALIGN_POINTER(pStubMsg->Buffer, 4);
5669 /* FIXME: what does fCheck do? */
5670 NDRCContextMarshall(ContextHandle,
5671 pStubMsg->Buffer);
5673 pStubMsg->Buffer += cbNDRContext;
5676 /***********************************************************************
5677 * NdrClientContextUnmarshall [RPCRT4.@]
5679 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5680 NDR_CCONTEXT * pContextHandle,
5681 RPC_BINDING_HANDLE BindHandle)
5683 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
5685 ALIGN_POINTER(pStubMsg->Buffer, 4);
5687 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
5688 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5690 NDRCContextUnmarshall(pContextHandle,
5691 BindHandle,
5692 pStubMsg->Buffer,
5693 pStubMsg->RpcMsg->DataRepresentation);
5695 pStubMsg->Buffer += cbNDRContext;
5698 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5699 NDR_SCONTEXT ContextHandle,
5700 NDR_RUNDOWN RundownRoutine )
5702 FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
5705 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
5707 FIXME("(%p): stub\n", pStubMsg);
5708 return NULL;
5711 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
5712 unsigned char* pMemory,
5713 PFORMAT_STRING pFormat)
5715 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
5718 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
5719 PFORMAT_STRING pFormat)
5721 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5722 return NULL;
5725 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5726 NDR_SCONTEXT ContextHandle,
5727 NDR_RUNDOWN RundownRoutine,
5728 PFORMAT_STRING pFormat)
5730 FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
5733 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5734 PFORMAT_STRING pFormat)
5736 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5737 return NULL;
5740 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e
5742 typedef struct ndr_context_handle
5744 DWORD attributes;
5745 GUID uuid;
5746 } ndr_context_handle;
5748 struct context_handle_entry
5750 struct list entry;
5751 DWORD magic;
5752 RPC_BINDING_HANDLE handle;
5753 ndr_context_handle wire_data;
5756 static struct list context_handle_list = LIST_INIT(context_handle_list);
5758 static CRITICAL_SECTION ndr_context_cs;
5759 static CRITICAL_SECTION_DEBUG ndr_context_debug =
5761 0, 0, &ndr_context_cs,
5762 { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList },
5763 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") }
5765 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 };
5767 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
5769 struct context_handle_entry *che = (struct context_handle_entry*) CContext;
5771 if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
5772 return NULL;
5773 return che;
5776 static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid)
5778 struct context_handle_entry *che;
5779 LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry)
5780 if (IsEqualGUID(&che->wire_data.uuid, uuid))
5781 return che;
5782 return NULL;
5785 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
5787 struct context_handle_entry *che;
5788 RPC_BINDING_HANDLE handle = NULL;
5790 TRACE("%p\n", CContext);
5792 EnterCriticalSection(&ndr_context_cs);
5793 che = get_context_entry(CContext);
5794 if (che)
5795 handle = che->handle;
5796 LeaveCriticalSection(&ndr_context_cs);
5798 if (!handle)
5799 RpcRaiseException(ERROR_INVALID_HANDLE);
5800 return handle;
5803 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
5805 struct context_handle_entry *che;
5807 TRACE("%p %p\n", CContext, pBuff);
5809 if (CContext)
5811 EnterCriticalSection(&ndr_context_cs);
5812 che = get_context_entry(CContext);
5813 memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle));
5814 LeaveCriticalSection(&ndr_context_cs);
5816 else
5818 ndr_context_handle *wire_data = (ndr_context_handle *)pBuff;
5819 wire_data->attributes = 0;
5820 wire_data->uuid = GUID_NULL;
5824 /***********************************************************************
5825 * RpcSmDestroyClientContext [RPCRT4.@]
5827 RPC_STATUS WINAPI RpcSmDestroyClientContext(void **ContextHandle)
5829 RPC_STATUS status = RPC_X_SS_CONTEXT_MISMATCH;
5830 struct context_handle_entry *che = NULL;
5832 TRACE("(%p)\n", ContextHandle);
5834 EnterCriticalSection(&ndr_context_cs);
5835 che = get_context_entry(*ContextHandle);
5836 *ContextHandle = NULL;
5837 if (che)
5839 status = RPC_S_OK;
5840 list_remove(&che->entry);
5843 LeaveCriticalSection(&ndr_context_cs);
5845 if (che)
5847 RpcBindingFree(&che->handle);
5848 HeapFree(GetProcessHeap(), 0, che);
5851 return status;
5854 /***********************************************************************
5855 * RpcSsDestroyClientContext [RPCRT4.@]
5857 void WINAPI RpcSsDestroyClientContext(void **ContextHandle)
5859 RPC_STATUS status = RpcSmDestroyClientContext(ContextHandle);
5860 if (status != RPC_S_OK)
5861 RpcRaiseException(status);
5864 static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext,
5865 RPC_BINDING_HANDLE hBinding,
5866 const ndr_context_handle *chi)
5868 struct context_handle_entry *che = NULL;
5870 /* a null UUID means we should free the context handle */
5871 if (IsEqualGUID(&chi->uuid, &GUID_NULL))
5873 if (*CContext)
5875 che = get_context_entry(*CContext);
5876 if (!che)
5877 return ERROR_INVALID_HANDLE;
5878 list_remove(&che->entry);
5879 RpcBindingFree(&che->handle);
5880 HeapFree(GetProcessHeap(), 0, che);
5881 che = NULL;
5884 /* if there's no existing entry matching the GUID, allocate one */
5885 else if (!(che = context_entry_from_guid(&chi->uuid)))
5887 che = HeapAlloc(GetProcessHeap(), 0, sizeof *che);
5888 if (!che)
5889 return ERROR_NOT_ENOUGH_MEMORY;
5890 che->magic = NDR_CONTEXT_HANDLE_MAGIC;
5891 RpcBindingCopy(hBinding, &che->handle);
5892 list_add_tail(&context_handle_list, &che->entry);
5893 memcpy(&che->wire_data, chi, sizeof *chi);
5896 *CContext = che;
5898 return ERROR_SUCCESS;
5901 /***********************************************************************
5902 * NDRCContextUnmarshall [RPCRT4.@]
5904 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext,
5905 RPC_BINDING_HANDLE hBinding,
5906 void *pBuff, ULONG DataRepresentation)
5908 UINT r;
5910 TRACE("*%p=(%p) %p %p %08x\n",
5911 CContext, *CContext, hBinding, pBuff, DataRepresentation);
5913 EnterCriticalSection(&ndr_context_cs);
5914 r = ndr_update_context_handle(CContext, hBinding, pBuff);
5915 LeaveCriticalSection(&ndr_context_cs);
5916 if (r)
5917 RpcRaiseException(r);
5920 /***********************************************************************
5921 * NDRSContextMarshall [RPCRT4.@]
5923 void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext,
5924 void *pBuff,
5925 NDR_RUNDOWN userRunDownIn)
5927 FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn);
5930 /***********************************************************************
5931 * NDRSContextMarshallEx [RPCRT4.@]
5933 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding,
5934 NDR_SCONTEXT CContext,
5935 void *pBuff,
5936 NDR_RUNDOWN userRunDownIn)
5938 FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn);
5941 /***********************************************************************
5942 * NDRSContextMarshall2 [RPCRT4.@]
5944 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
5945 NDR_SCONTEXT CContext,
5946 void *pBuff,
5947 NDR_RUNDOWN userRunDownIn,
5948 void *CtxGuard, ULONG Flags)
5950 FIXME("(%p %p %p %p %p %u): stub\n",
5951 hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags);
5954 /***********************************************************************
5955 * NDRSContextUnmarshall [RPCRT4.@]
5957 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff,
5958 ULONG DataRepresentation)
5960 FIXME("(%p %08x): stub\n", pBuff, DataRepresentation);
5961 return NULL;
5964 /***********************************************************************
5965 * NDRSContextUnmarshallEx [RPCRT4.@]
5967 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding,
5968 void *pBuff,
5969 ULONG DataRepresentation)
5971 FIXME("(%p %p %08x): stub\n", hBinding, pBuff, DataRepresentation);
5972 return NULL;
5975 /***********************************************************************
5976 * NDRSContextUnmarshall2 [RPCRT4.@]
5978 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
5979 void *pBuff,
5980 ULONG DataRepresentation,
5981 void *CtxGuard, ULONG Flags)
5983 FIXME("(%p %p %08x %p %u): stub\n",
5984 hBinding, pBuff, DataRepresentation, CtxGuard, Flags);
5985 return NULL;