push bd0608bf727e2241b2885edad5c5c753477ffd22
[wine/hacks.git] / dlls / rpcrt4 / ndr_marshall.c
blob05902033b3df73116b2bcd9df640337b95efadad
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 *(unsigned char**) *pPointer = NULL;
983 pPointer = *(unsigned char***)pPointer;
984 TRACE("deref => %p\n", pPointer);
986 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
987 if (m) m(pStubMsg, pPointer, desc, fMustAlloc);
988 else FIXME("no unmarshaller for data type=%02x\n", *desc);
990 if (type == RPC_FC_FP)
991 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
992 *pPointer);
995 TRACE("pointer=%p\n", *pPointer);
998 /***********************************************************************
999 * PointerBufferSize [internal]
1001 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1002 unsigned char *Pointer,
1003 PFORMAT_STRING pFormat)
1005 unsigned type = pFormat[0], attr = pFormat[1];
1006 PFORMAT_STRING desc;
1007 NDR_BUFFERSIZE m;
1008 int pointer_needs_sizing;
1009 ULONG pointer_id;
1011 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1012 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1013 pFormat += 2;
1014 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1015 else desc = pFormat + *(const SHORT*)pFormat;
1017 switch (type) {
1018 case RPC_FC_RP: /* ref pointer (always non-null) */
1019 break;
1020 case RPC_FC_OP:
1021 case RPC_FC_UP:
1022 /* NULL pointer has no further representation */
1023 if (!Pointer)
1024 return;
1025 break;
1026 case RPC_FC_FP:
1027 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1028 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1029 if (!pointer_needs_sizing)
1030 return;
1031 break;
1032 default:
1033 FIXME("unhandled ptr type=%02x\n", type);
1034 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1035 return;
1038 if (attr & RPC_FC_P_DEREF) {
1039 Pointer = *(unsigned char**)Pointer;
1040 TRACE("deref => %p\n", Pointer);
1043 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1044 if (m) m(pStubMsg, Pointer, desc);
1045 else FIXME("no buffersizer for data type=%02x\n", *desc);
1048 /***********************************************************************
1049 * PointerMemorySize [internal]
1051 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1052 unsigned char *Buffer,
1053 PFORMAT_STRING pFormat)
1055 unsigned type = pFormat[0], attr = pFormat[1];
1056 PFORMAT_STRING desc;
1057 NDR_MEMORYSIZE m;
1059 FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat);
1060 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1061 pFormat += 2;
1062 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1063 else desc = pFormat + *(const SHORT*)pFormat;
1065 switch (type) {
1066 case RPC_FC_RP: /* ref pointer (always non-null) */
1067 break;
1068 default:
1069 FIXME("unhandled ptr type=%02x\n", type);
1070 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1073 if (attr & RPC_FC_P_DEREF) {
1074 TRACE("deref\n");
1077 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1078 if (m) m(pStubMsg, desc);
1079 else FIXME("no memorysizer for data type=%02x\n", *desc);
1081 return 0;
1084 /***********************************************************************
1085 * PointerFree [internal]
1087 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1088 unsigned char *Pointer,
1089 PFORMAT_STRING pFormat)
1091 unsigned type = pFormat[0], attr = pFormat[1];
1092 PFORMAT_STRING desc;
1093 NDR_FREE m;
1095 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1096 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1097 if (attr & RPC_FC_P_DONTFREE) return;
1098 pFormat += 2;
1099 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1100 else desc = pFormat + *(const SHORT*)pFormat;
1102 if (!Pointer) return;
1104 if (type == RPC_FC_FP) {
1105 int pointer_needs_freeing = NdrFullPointerFree(
1106 pStubMsg->FullPtrXlatTables, Pointer);
1107 if (!pointer_needs_freeing)
1108 return;
1111 if (attr & RPC_FC_P_DEREF) {
1112 Pointer = *(unsigned char**)Pointer;
1113 TRACE("deref => %p\n", Pointer);
1116 m = NdrFreer[*desc & NDR_TABLE_MASK];
1117 if (m) m(pStubMsg, Pointer, desc);
1119 /* hmm... is this sensible?
1120 * perhaps we should check if the memory comes from NdrAllocate,
1121 * and deallocate only if so - checking if the pointer is between
1122 * BufferStart and BufferEnd is probably no good since the buffer
1123 * may be reallocated when the server wants to marshal the reply */
1124 switch (*desc) {
1125 case RPC_FC_BOGUS_STRUCT:
1126 case RPC_FC_BOGUS_ARRAY:
1127 case RPC_FC_USER_MARSHAL:
1128 case RPC_FC_CARRAY:
1129 case RPC_FC_CVARRAY:
1130 break;
1131 default:
1132 FIXME("unhandled data type=%02x\n", *desc);
1133 break;
1134 case RPC_FC_C_CSTRING:
1135 case RPC_FC_C_WSTRING:
1136 if (pStubMsg->ReuseBuffer) goto notfree;
1137 break;
1138 case RPC_FC_IP:
1139 goto notfree;
1142 if (attr & RPC_FC_P_ONSTACK) {
1143 TRACE("not freeing stack ptr %p\n", Pointer);
1144 return;
1146 TRACE("freeing %p\n", Pointer);
1147 NdrFree(pStubMsg, Pointer);
1148 return;
1149 notfree:
1150 TRACE("not freeing %p\n", Pointer);
1153 /***********************************************************************
1154 * EmbeddedPointerMarshall
1156 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1157 unsigned char *pMemory,
1158 PFORMAT_STRING pFormat)
1160 unsigned char *Mark = pStubMsg->BufferMark;
1161 unsigned rep, count, stride;
1162 unsigned i;
1163 unsigned char *saved_buffer = NULL;
1165 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1167 if (*pFormat != RPC_FC_PP) return NULL;
1168 pFormat += 2;
1170 if (pStubMsg->PointerBufferMark)
1172 saved_buffer = pStubMsg->Buffer;
1173 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1174 pStubMsg->PointerBufferMark = NULL;
1177 while (pFormat[0] != RPC_FC_END) {
1178 switch (pFormat[0]) {
1179 default:
1180 FIXME("unknown repeat type %d\n", pFormat[0]);
1181 case RPC_FC_NO_REPEAT:
1182 rep = 1;
1183 stride = 0;
1184 count = 1;
1185 pFormat += 2;
1186 break;
1187 case RPC_FC_FIXED_REPEAT:
1188 rep = *(const WORD*)&pFormat[2];
1189 stride = *(const WORD*)&pFormat[4];
1190 count = *(const WORD*)&pFormat[8];
1191 pFormat += 10;
1192 break;
1193 case RPC_FC_VARIABLE_REPEAT:
1194 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1195 stride = *(const WORD*)&pFormat[2];
1196 count = *(const WORD*)&pFormat[6];
1197 pFormat += 8;
1198 break;
1200 for (i = 0; i < rep; i++) {
1201 PFORMAT_STRING info = pFormat;
1202 unsigned char *membase = pMemory + (i * stride);
1203 unsigned char *bufbase = Mark + (i * stride);
1204 unsigned u;
1206 for (u=0; u<count; u++,info+=8) {
1207 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1208 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1209 unsigned char *saved_memory = pStubMsg->Memory;
1211 pStubMsg->Memory = pMemory;
1212 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1213 pStubMsg->Memory = saved_memory;
1216 pFormat += 8 * count;
1219 if (saved_buffer)
1221 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1222 pStubMsg->Buffer = saved_buffer;
1225 STD_OVERFLOW_CHECK(pStubMsg);
1227 return NULL;
1230 /***********************************************************************
1231 * EmbeddedPointerUnmarshall
1233 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1234 unsigned char **ppMemory,
1235 PFORMAT_STRING pFormat,
1236 unsigned char fMustAlloc)
1238 unsigned char *Mark = pStubMsg->BufferMark;
1239 unsigned rep, count, stride;
1240 unsigned i;
1241 unsigned char *saved_buffer = NULL;
1243 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1245 if (*pFormat != RPC_FC_PP) return NULL;
1246 pFormat += 2;
1248 if (pStubMsg->PointerBufferMark)
1250 saved_buffer = pStubMsg->Buffer;
1251 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1252 pStubMsg->PointerBufferMark = NULL;
1255 while (pFormat[0] != RPC_FC_END) {
1256 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1257 switch (pFormat[0]) {
1258 default:
1259 FIXME("unknown repeat type %d\n", pFormat[0]);
1260 case RPC_FC_NO_REPEAT:
1261 rep = 1;
1262 stride = 0;
1263 count = 1;
1264 pFormat += 2;
1265 break;
1266 case RPC_FC_FIXED_REPEAT:
1267 rep = *(const WORD*)&pFormat[2];
1268 stride = *(const WORD*)&pFormat[4];
1269 count = *(const WORD*)&pFormat[8];
1270 pFormat += 10;
1271 break;
1272 case RPC_FC_VARIABLE_REPEAT:
1273 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1274 stride = *(const WORD*)&pFormat[2];
1275 count = *(const WORD*)&pFormat[6];
1276 pFormat += 8;
1277 break;
1279 for (i = 0; i < rep; i++) {
1280 PFORMAT_STRING info = pFormat;
1281 unsigned char *membase = *ppMemory + (i * stride);
1282 unsigned char *bufbase = Mark + (i * stride);
1283 unsigned u;
1285 for (u=0; u<count; u++,info+=8) {
1286 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1287 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1288 PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, TRUE);
1291 pFormat += 8 * count;
1294 if (saved_buffer)
1296 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1297 pStubMsg->Buffer = saved_buffer;
1300 return NULL;
1303 /***********************************************************************
1304 * EmbeddedPointerBufferSize
1306 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1307 unsigned char *pMemory,
1308 PFORMAT_STRING pFormat)
1310 unsigned rep, count, stride;
1311 unsigned i;
1312 ULONG saved_buffer_length = 0;
1314 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1316 if (pStubMsg->IgnoreEmbeddedPointers) return;
1318 if (*pFormat != RPC_FC_PP) return;
1319 pFormat += 2;
1321 if (pStubMsg->PointerLength)
1323 saved_buffer_length = pStubMsg->BufferLength;
1324 pStubMsg->BufferLength = pStubMsg->PointerLength;
1325 pStubMsg->PointerLength = 0;
1328 while (pFormat[0] != RPC_FC_END) {
1329 switch (pFormat[0]) {
1330 default:
1331 FIXME("unknown repeat type %d\n", pFormat[0]);
1332 case RPC_FC_NO_REPEAT:
1333 rep = 1;
1334 stride = 0;
1335 count = 1;
1336 pFormat += 2;
1337 break;
1338 case RPC_FC_FIXED_REPEAT:
1339 rep = *(const WORD*)&pFormat[2];
1340 stride = *(const WORD*)&pFormat[4];
1341 count = *(const WORD*)&pFormat[8];
1342 pFormat += 10;
1343 break;
1344 case RPC_FC_VARIABLE_REPEAT:
1345 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1346 stride = *(const WORD*)&pFormat[2];
1347 count = *(const WORD*)&pFormat[6];
1348 pFormat += 8;
1349 break;
1351 for (i = 0; i < rep; i++) {
1352 PFORMAT_STRING info = pFormat;
1353 unsigned char *membase = pMemory + (i * stride);
1354 unsigned u;
1356 for (u=0; u<count; u++,info+=8) {
1357 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1358 unsigned char *saved_memory = pStubMsg->Memory;
1360 pStubMsg->Memory = pMemory;
1361 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1362 pStubMsg->Memory = saved_memory;
1365 pFormat += 8 * count;
1368 if (saved_buffer_length)
1370 pStubMsg->PointerLength = pStubMsg->BufferLength;
1371 pStubMsg->BufferLength = saved_buffer_length;
1375 /***********************************************************************
1376 * EmbeddedPointerMemorySize [internal]
1378 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1379 PFORMAT_STRING pFormat)
1381 unsigned char *Mark = pStubMsg->BufferMark;
1382 unsigned rep, count, stride;
1383 unsigned i;
1385 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1387 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1389 FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1391 if (*pFormat != RPC_FC_PP) return 0;
1392 pFormat += 2;
1394 while (pFormat[0] != RPC_FC_END) {
1395 switch (pFormat[0]) {
1396 default:
1397 FIXME("unknown repeat type %d\n", pFormat[0]);
1398 case RPC_FC_NO_REPEAT:
1399 rep = 1;
1400 stride = 0;
1401 count = 1;
1402 pFormat += 2;
1403 break;
1404 case RPC_FC_FIXED_REPEAT:
1405 rep = *(const WORD*)&pFormat[2];
1406 stride = *(const WORD*)&pFormat[4];
1407 count = *(const WORD*)&pFormat[8];
1408 pFormat += 10;
1409 break;
1410 case RPC_FC_VARIABLE_REPEAT:
1411 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1412 stride = *(const WORD*)&pFormat[2];
1413 count = *(const WORD*)&pFormat[6];
1414 pFormat += 8;
1415 break;
1417 for (i = 0; i < rep; i++) {
1418 PFORMAT_STRING info = pFormat;
1419 unsigned char *bufbase = Mark + (i * stride);
1420 unsigned u;
1421 for (u=0; u<count; u++,info+=8) {
1422 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1423 PointerMemorySize(pStubMsg, bufptr, info+4);
1426 pFormat += 8 * count;
1429 return 0;
1432 /***********************************************************************
1433 * EmbeddedPointerFree [internal]
1435 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1436 unsigned char *pMemory,
1437 PFORMAT_STRING pFormat)
1439 unsigned rep, count, stride;
1440 unsigned i;
1442 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1443 if (*pFormat != RPC_FC_PP) return;
1444 pFormat += 2;
1446 while (pFormat[0] != RPC_FC_END) {
1447 switch (pFormat[0]) {
1448 default:
1449 FIXME("unknown repeat type %d\n", pFormat[0]);
1450 case RPC_FC_NO_REPEAT:
1451 rep = 1;
1452 stride = 0;
1453 count = 1;
1454 pFormat += 2;
1455 break;
1456 case RPC_FC_FIXED_REPEAT:
1457 rep = *(const WORD*)&pFormat[2];
1458 stride = *(const WORD*)&pFormat[4];
1459 count = *(const WORD*)&pFormat[8];
1460 pFormat += 10;
1461 break;
1462 case RPC_FC_VARIABLE_REPEAT:
1463 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1464 stride = *(const WORD*)&pFormat[2];
1465 count = *(const WORD*)&pFormat[6];
1466 pFormat += 8;
1467 break;
1469 for (i = 0; i < rep; i++) {
1470 PFORMAT_STRING info = pFormat;
1471 unsigned char *membase = pMemory + (i * stride);
1472 unsigned u;
1474 for (u=0; u<count; u++,info+=8) {
1475 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1476 unsigned char *saved_memory = pStubMsg->Memory;
1478 pStubMsg->Memory = pMemory;
1479 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1480 pStubMsg->Memory = saved_memory;
1483 pFormat += 8 * count;
1487 /***********************************************************************
1488 * NdrPointerMarshall [RPCRT4.@]
1490 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1491 unsigned char *pMemory,
1492 PFORMAT_STRING pFormat)
1494 unsigned char *Buffer;
1496 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1498 /* incremement the buffer here instead of in PointerMarshall,
1499 * as that is used by embedded pointers which already handle the incrementing
1500 * the buffer, and shouldn't write any additional pointer data to the wire */
1501 if (*pFormat != RPC_FC_RP)
1503 ALIGN_POINTER(pStubMsg->Buffer, 4);
1504 Buffer = pStubMsg->Buffer;
1505 pStubMsg->Buffer += 4;
1507 else
1508 Buffer = pStubMsg->Buffer;
1510 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1512 STD_OVERFLOW_CHECK(pStubMsg);
1514 return NULL;
1517 /***********************************************************************
1518 * NdrPointerUnmarshall [RPCRT4.@]
1520 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1521 unsigned char **ppMemory,
1522 PFORMAT_STRING pFormat,
1523 unsigned char fMustAlloc)
1525 unsigned char *Buffer;
1527 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1529 /* incremement the buffer here instead of in PointerUnmarshall,
1530 * as that is used by embedded pointers which already handle the incrementing
1531 * the buffer, and shouldn't read any additional pointer data from the
1532 * buffer */
1533 if (*pFormat != RPC_FC_RP)
1535 ALIGN_POINTER(pStubMsg->Buffer, 4);
1536 Buffer = pStubMsg->Buffer;
1537 safe_buffer_increment(pStubMsg, 4);
1539 else
1540 Buffer = pStubMsg->Buffer;
1542 PointerUnmarshall(pStubMsg, Buffer, ppMemory, pFormat, fMustAlloc);
1544 return NULL;
1547 /***********************************************************************
1548 * NdrPointerBufferSize [RPCRT4.@]
1550 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1551 unsigned char *pMemory,
1552 PFORMAT_STRING pFormat)
1554 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1556 /* incremement the buffer length here instead of in PointerBufferSize,
1557 * as that is used by embedded pointers which already handle the buffer
1558 * length, and shouldn't write anything more to the wire */
1559 if (*pFormat != RPC_FC_RP)
1561 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1562 pStubMsg->BufferLength += 4;
1565 PointerBufferSize(pStubMsg, pMemory, pFormat);
1568 /***********************************************************************
1569 * NdrPointerMemorySize [RPCRT4.@]
1571 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1572 PFORMAT_STRING pFormat)
1574 /* unsigned size = *(LPWORD)(pFormat+2); */
1575 FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1576 PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1577 return 0;
1580 /***********************************************************************
1581 * NdrPointerFree [RPCRT4.@]
1583 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1584 unsigned char *pMemory,
1585 PFORMAT_STRING pFormat)
1587 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1588 PointerFree(pStubMsg, pMemory, pFormat);
1591 /***********************************************************************
1592 * NdrSimpleTypeMarshall [RPCRT4.@]
1594 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1595 unsigned char FormatChar )
1597 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1600 /***********************************************************************
1601 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1603 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1604 unsigned char FormatChar )
1606 NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0);
1609 /***********************************************************************
1610 * NdrSimpleStructMarshall [RPCRT4.@]
1612 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1613 unsigned char *pMemory,
1614 PFORMAT_STRING pFormat)
1616 unsigned size = *(const WORD*)(pFormat+2);
1617 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1619 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1621 memcpy(pStubMsg->Buffer, pMemory, size);
1622 pStubMsg->BufferMark = pStubMsg->Buffer;
1623 pStubMsg->Buffer += size;
1625 if (pFormat[0] != RPC_FC_STRUCT)
1626 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1628 STD_OVERFLOW_CHECK(pStubMsg);
1630 return NULL;
1633 /***********************************************************************
1634 * NdrSimpleStructUnmarshall [RPCRT4.@]
1636 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1637 unsigned char **ppMemory,
1638 PFORMAT_STRING pFormat,
1639 unsigned char fMustAlloc)
1641 unsigned size = *(const WORD*)(pFormat+2);
1642 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1644 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1646 if (fMustAlloc) {
1647 *ppMemory = NdrAllocate(pStubMsg, size);
1648 memcpy(*ppMemory, pStubMsg->Buffer, size);
1649 } else {
1650 if (!pStubMsg->IsClient && !*ppMemory)
1651 /* for servers, we just point straight into the RPC buffer */
1652 *ppMemory = pStubMsg->Buffer;
1653 else
1654 /* for clients, memory should be provided by caller */
1655 memcpy(*ppMemory, pStubMsg->Buffer, size);
1658 pStubMsg->BufferMark = pStubMsg->Buffer;
1659 pStubMsg->Buffer += size;
1661 if (pFormat[0] != RPC_FC_STRUCT)
1662 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1664 return NULL;
1667 /***********************************************************************
1668 * NdrSimpleStructBufferSize [RPCRT4.@]
1670 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1671 unsigned char *pMemory,
1672 PFORMAT_STRING pFormat)
1674 unsigned size = *(const WORD*)(pFormat+2);
1675 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1677 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1679 pStubMsg->BufferLength += size;
1680 if (pFormat[0] != RPC_FC_STRUCT)
1681 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1684 /***********************************************************************
1685 * NdrSimpleStructMemorySize [RPCRT4.@]
1687 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1688 PFORMAT_STRING pFormat)
1690 unsigned short size = *(const WORD *)(pFormat+2);
1692 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1694 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1695 pStubMsg->MemorySize += size;
1696 pStubMsg->Buffer += size;
1698 if (pFormat[0] != RPC_FC_STRUCT)
1699 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1700 return size;
1703 /***********************************************************************
1704 * NdrSimpleStructFree [RPCRT4.@]
1706 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1707 unsigned char *pMemory,
1708 PFORMAT_STRING pFormat)
1710 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1711 if (pFormat[0] != RPC_FC_STRUCT)
1712 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1716 static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg,
1717 PFORMAT_STRING pFormat)
1719 switch (*pFormat) {
1720 case RPC_FC_STRUCT:
1721 case RPC_FC_PSTRUCT:
1722 case RPC_FC_CSTRUCT:
1723 case RPC_FC_BOGUS_STRUCT:
1724 case RPC_FC_SMFARRAY:
1725 case RPC_FC_SMVARRAY:
1726 return *(const WORD*)&pFormat[2];
1727 case RPC_FC_USER_MARSHAL:
1728 return *(const WORD*)&pFormat[4];
1729 case RPC_FC_NON_ENCAPSULATED_UNION:
1730 pFormat += 2;
1731 if (pStubMsg->fHasNewCorrDesc)
1732 pFormat += 6;
1733 else
1734 pFormat += 4;
1736 pFormat += *(const SHORT*)pFormat;
1737 return *(const SHORT*)pFormat;
1738 case RPC_FC_IP:
1739 return sizeof(void *);
1740 default:
1741 FIXME("unhandled embedded type %02x\n", *pFormat);
1743 return 0;
1747 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1748 PFORMAT_STRING pFormat)
1750 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1752 if (!m)
1754 FIXME("no memorysizer for data type=%02x\n", *pFormat);
1755 return 0;
1758 return m(pStubMsg, pFormat);
1762 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1763 unsigned char *pMemory,
1764 PFORMAT_STRING pFormat,
1765 PFORMAT_STRING pPointer)
1767 PFORMAT_STRING desc;
1768 NDR_MARSHALL m;
1769 unsigned long size;
1771 while (*pFormat != RPC_FC_END) {
1772 switch (*pFormat) {
1773 case RPC_FC_BYTE:
1774 case RPC_FC_CHAR:
1775 case RPC_FC_SMALL:
1776 case RPC_FC_USMALL:
1777 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
1778 memcpy(pStubMsg->Buffer, pMemory, 1);
1779 pStubMsg->Buffer += 1;
1780 pMemory += 1;
1781 break;
1782 case RPC_FC_WCHAR:
1783 case RPC_FC_SHORT:
1784 case RPC_FC_USHORT:
1785 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1786 memcpy(pStubMsg->Buffer, pMemory, 2);
1787 pStubMsg->Buffer += 2;
1788 pMemory += 2;
1789 break;
1790 case RPC_FC_LONG:
1791 case RPC_FC_ULONG:
1792 case RPC_FC_ENUM32:
1793 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
1794 memcpy(pStubMsg->Buffer, pMemory, 4);
1795 pStubMsg->Buffer += 4;
1796 pMemory += 4;
1797 break;
1798 case RPC_FC_HYPER:
1799 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1800 memcpy(pStubMsg->Buffer, pMemory, 8);
1801 pStubMsg->Buffer += 8;
1802 pMemory += 8;
1803 break;
1804 case RPC_FC_POINTER:
1806 unsigned char *saved_buffer;
1807 int pointer_buffer_mark_set = 0;
1808 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1809 saved_buffer = pStubMsg->Buffer;
1810 if (pStubMsg->PointerBufferMark)
1812 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1813 pStubMsg->PointerBufferMark = NULL;
1814 pointer_buffer_mark_set = 1;
1816 else
1817 pStubMsg->Buffer += 4; /* for pointer ID */
1818 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
1819 if (pointer_buffer_mark_set)
1821 STD_OVERFLOW_CHECK(pStubMsg);
1822 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1823 pStubMsg->Buffer = saved_buffer + 4;
1825 pPointer += 4;
1826 pMemory += 4;
1827 break;
1829 case RPC_FC_ALIGNM4:
1830 ALIGN_POINTER(pMemory, 4);
1831 break;
1832 case RPC_FC_ALIGNM8:
1833 ALIGN_POINTER(pMemory, 8);
1834 break;
1835 case RPC_FC_STRUCTPAD1:
1836 case RPC_FC_STRUCTPAD2:
1837 case RPC_FC_STRUCTPAD3:
1838 case RPC_FC_STRUCTPAD4:
1839 case RPC_FC_STRUCTPAD5:
1840 case RPC_FC_STRUCTPAD6:
1841 case RPC_FC_STRUCTPAD7:
1842 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1843 break;
1844 case RPC_FC_EMBEDDED_COMPLEX:
1845 pMemory += pFormat[1];
1846 pFormat += 2;
1847 desc = pFormat + *(const SHORT*)pFormat;
1848 size = EmbeddedComplexSize(pStubMsg, desc);
1849 TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1850 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1851 if (m)
1853 /* for some reason interface pointers aren't generated as
1854 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
1855 * they still need the derefencing treatment that pointers are
1856 * given */
1857 if (*desc == RPC_FC_IP)
1858 m(pStubMsg, *(unsigned char **)pMemory, desc);
1859 else
1860 m(pStubMsg, pMemory, desc);
1862 else FIXME("no marshaller for embedded type %02x\n", *desc);
1863 pMemory += size;
1864 pFormat += 2;
1865 continue;
1866 case RPC_FC_PAD:
1867 break;
1868 default:
1869 FIXME("unhandled format 0x%02x\n", *pFormat);
1871 pFormat++;
1874 return pMemory;
1877 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1878 unsigned char *pMemory,
1879 PFORMAT_STRING pFormat,
1880 PFORMAT_STRING pPointer)
1882 PFORMAT_STRING desc;
1883 NDR_UNMARSHALL m;
1884 unsigned long size;
1886 while (*pFormat != RPC_FC_END) {
1887 switch (*pFormat) {
1888 case RPC_FC_BYTE:
1889 case RPC_FC_CHAR:
1890 case RPC_FC_SMALL:
1891 case RPC_FC_USMALL:
1892 safe_buffer_copy(pStubMsg, pMemory, 1);
1893 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
1894 pMemory += 1;
1895 break;
1896 case RPC_FC_WCHAR:
1897 case RPC_FC_SHORT:
1898 case RPC_FC_USHORT:
1899 safe_buffer_copy(pStubMsg, pMemory, 2);
1900 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1901 pMemory += 2;
1902 break;
1903 case RPC_FC_LONG:
1904 case RPC_FC_ULONG:
1905 case RPC_FC_ENUM32:
1906 safe_buffer_copy(pStubMsg, pMemory, 4);
1907 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
1908 pMemory += 4;
1909 break;
1910 case RPC_FC_HYPER:
1911 safe_buffer_copy(pStubMsg, pMemory, 8);
1912 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1913 pMemory += 8;
1914 break;
1915 case RPC_FC_POINTER:
1917 unsigned char *saved_buffer;
1918 int pointer_buffer_mark_set = 0;
1919 TRACE("pointer => %p\n", pMemory);
1920 ALIGN_POINTER(pStubMsg->Buffer, 4);
1921 saved_buffer = pStubMsg->Buffer;
1922 if (pStubMsg->PointerBufferMark)
1924 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1925 pStubMsg->PointerBufferMark = NULL;
1926 pointer_buffer_mark_set = 1;
1928 else
1929 pStubMsg->Buffer += 4; /* for pointer ID */
1931 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, pPointer, TRUE);
1932 if (pointer_buffer_mark_set)
1934 STD_OVERFLOW_CHECK(pStubMsg);
1935 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1936 pStubMsg->Buffer = saved_buffer + 4;
1938 pPointer += 4;
1939 pMemory += 4;
1940 break;
1942 case RPC_FC_ALIGNM4:
1943 ALIGN_POINTER(pMemory, 4);
1944 break;
1945 case RPC_FC_ALIGNM8:
1946 ALIGN_POINTER(pMemory, 8);
1947 break;
1948 case RPC_FC_STRUCTPAD1:
1949 case RPC_FC_STRUCTPAD2:
1950 case RPC_FC_STRUCTPAD3:
1951 case RPC_FC_STRUCTPAD4:
1952 case RPC_FC_STRUCTPAD5:
1953 case RPC_FC_STRUCTPAD6:
1954 case RPC_FC_STRUCTPAD7:
1955 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1956 break;
1957 case RPC_FC_EMBEDDED_COMPLEX:
1958 pMemory += pFormat[1];
1959 pFormat += 2;
1960 desc = pFormat + *(const SHORT*)pFormat;
1961 size = EmbeddedComplexSize(pStubMsg, desc);
1962 TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1963 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1964 memset(pMemory, 0, size); /* just in case */
1965 if (m)
1967 /* for some reason interface pointers aren't generated as
1968 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
1969 * they still need the derefencing treatment that pointers are
1970 * given */
1971 if (*desc == RPC_FC_IP)
1972 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
1973 else
1974 m(pStubMsg, &pMemory, desc, FALSE);
1976 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
1977 pMemory += size;
1978 pFormat += 2;
1979 continue;
1980 case RPC_FC_PAD:
1981 break;
1982 default:
1983 FIXME("unhandled format %d\n", *pFormat);
1985 pFormat++;
1988 return pMemory;
1991 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1992 unsigned char *pMemory,
1993 PFORMAT_STRING pFormat,
1994 PFORMAT_STRING pPointer)
1996 PFORMAT_STRING desc;
1997 NDR_BUFFERSIZE m;
1998 unsigned long size;
2000 while (*pFormat != RPC_FC_END) {
2001 switch (*pFormat) {
2002 case RPC_FC_BYTE:
2003 case RPC_FC_CHAR:
2004 case RPC_FC_SMALL:
2005 case RPC_FC_USMALL:
2006 pStubMsg->BufferLength += 1;
2007 pMemory += 1;
2008 break;
2009 case RPC_FC_WCHAR:
2010 case RPC_FC_SHORT:
2011 case RPC_FC_USHORT:
2012 pStubMsg->BufferLength += 2;
2013 pMemory += 2;
2014 break;
2015 case RPC_FC_LONG:
2016 case RPC_FC_ULONG:
2017 case RPC_FC_ENUM32:
2018 pStubMsg->BufferLength += 4;
2019 pMemory += 4;
2020 break;
2021 case RPC_FC_HYPER:
2022 pStubMsg->BufferLength += 8;
2023 pMemory += 8;
2024 break;
2025 case RPC_FC_POINTER:
2026 if (!pStubMsg->IgnoreEmbeddedPointers)
2028 int saved_buffer_length = pStubMsg->BufferLength;
2029 pStubMsg->BufferLength = pStubMsg->PointerLength;
2030 pStubMsg->PointerLength = 0;
2031 if(!pStubMsg->BufferLength)
2032 ERR("BufferLength == 0??\n");
2033 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2034 pStubMsg->PointerLength = pStubMsg->BufferLength;
2035 pStubMsg->BufferLength = saved_buffer_length;
2037 pStubMsg->BufferLength += 4;
2038 pPointer += 4;
2039 pMemory += 4;
2040 break;
2041 case RPC_FC_ALIGNM4:
2042 ALIGN_POINTER(pMemory, 4);
2043 break;
2044 case RPC_FC_ALIGNM8:
2045 ALIGN_POINTER(pMemory, 8);
2046 break;
2047 case RPC_FC_STRUCTPAD1:
2048 case RPC_FC_STRUCTPAD2:
2049 case RPC_FC_STRUCTPAD3:
2050 case RPC_FC_STRUCTPAD4:
2051 case RPC_FC_STRUCTPAD5:
2052 case RPC_FC_STRUCTPAD6:
2053 case RPC_FC_STRUCTPAD7:
2054 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2055 break;
2056 case RPC_FC_EMBEDDED_COMPLEX:
2057 pMemory += pFormat[1];
2058 pFormat += 2;
2059 desc = pFormat + *(const SHORT*)pFormat;
2060 size = EmbeddedComplexSize(pStubMsg, desc);
2061 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2062 if (m)
2064 /* for some reason interface pointers aren't generated as
2065 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2066 * they still need the derefencing treatment that pointers are
2067 * given */
2068 if (*desc == RPC_FC_IP)
2069 m(pStubMsg, *(unsigned char **)pMemory, desc);
2070 else
2071 m(pStubMsg, pMemory, desc);
2073 else FIXME("no buffersizer for embedded type %02x\n", *desc);
2074 pMemory += size;
2075 pFormat += 2;
2076 continue;
2077 case RPC_FC_PAD:
2078 break;
2079 default:
2080 FIXME("unhandled format 0x%02x\n", *pFormat);
2082 pFormat++;
2085 return pMemory;
2088 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2089 unsigned char *pMemory,
2090 PFORMAT_STRING pFormat,
2091 PFORMAT_STRING pPointer)
2093 PFORMAT_STRING desc;
2094 NDR_FREE m;
2095 unsigned long size;
2097 while (*pFormat != RPC_FC_END) {
2098 switch (*pFormat) {
2099 case RPC_FC_BYTE:
2100 case RPC_FC_CHAR:
2101 case RPC_FC_SMALL:
2102 case RPC_FC_USMALL:
2103 pMemory += 1;
2104 break;
2105 case RPC_FC_WCHAR:
2106 case RPC_FC_SHORT:
2107 case RPC_FC_USHORT:
2108 pMemory += 2;
2109 break;
2110 case RPC_FC_LONG:
2111 case RPC_FC_ULONG:
2112 case RPC_FC_ENUM32:
2113 pMemory += 4;
2114 break;
2115 case RPC_FC_HYPER:
2116 pMemory += 8;
2117 break;
2118 case RPC_FC_POINTER:
2119 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2120 pPointer += 4;
2121 pMemory += 4;
2122 break;
2123 case RPC_FC_ALIGNM4:
2124 ALIGN_POINTER(pMemory, 4);
2125 break;
2126 case RPC_FC_ALIGNM8:
2127 ALIGN_POINTER(pMemory, 8);
2128 break;
2129 case RPC_FC_STRUCTPAD1:
2130 case RPC_FC_STRUCTPAD2:
2131 case RPC_FC_STRUCTPAD3:
2132 case RPC_FC_STRUCTPAD4:
2133 case RPC_FC_STRUCTPAD5:
2134 case RPC_FC_STRUCTPAD6:
2135 case RPC_FC_STRUCTPAD7:
2136 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2137 break;
2138 case RPC_FC_EMBEDDED_COMPLEX:
2139 pMemory += pFormat[1];
2140 pFormat += 2;
2141 desc = pFormat + *(const SHORT*)pFormat;
2142 size = EmbeddedComplexSize(pStubMsg, desc);
2143 m = NdrFreer[*desc & NDR_TABLE_MASK];
2144 if (m)
2146 /* for some reason interface pointers aren't generated as
2147 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2148 * they still need the derefencing treatment that pointers are
2149 * given */
2150 if (*desc == RPC_FC_IP)
2151 m(pStubMsg, *(unsigned char **)pMemory, desc);
2152 else
2153 m(pStubMsg, pMemory, desc);
2155 else FIXME("no freer for embedded type %02x\n", *desc);
2156 pMemory += size;
2157 pFormat += 2;
2158 continue;
2159 case RPC_FC_PAD:
2160 break;
2161 default:
2162 FIXME("unhandled format 0x%02x\n", *pFormat);
2164 pFormat++;
2167 return pMemory;
2170 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2171 PFORMAT_STRING pFormat)
2173 PFORMAT_STRING desc;
2174 unsigned long size = 0;
2176 while (*pFormat != RPC_FC_END) {
2177 switch (*pFormat) {
2178 case RPC_FC_BYTE:
2179 case RPC_FC_CHAR:
2180 case RPC_FC_SMALL:
2181 case RPC_FC_USMALL:
2182 size += 1;
2183 pStubMsg->Buffer += 1;
2184 break;
2185 case RPC_FC_WCHAR:
2186 case RPC_FC_SHORT:
2187 case RPC_FC_USHORT:
2188 size += 2;
2189 pStubMsg->Buffer += 2;
2190 break;
2191 case RPC_FC_LONG:
2192 case RPC_FC_ULONG:
2193 case RPC_FC_ENUM32:
2194 size += 4;
2195 pStubMsg->Buffer += 4;
2196 break;
2197 case RPC_FC_HYPER:
2198 size += 8;
2199 pStubMsg->Buffer += 8;
2200 break;
2201 case RPC_FC_POINTER:
2202 size += 4;
2203 pStubMsg->Buffer += 4;
2204 if (!pStubMsg->IgnoreEmbeddedPointers)
2205 FIXME("embedded pointers\n");
2206 break;
2207 case RPC_FC_ALIGNM4:
2208 ALIGN_LENGTH(size, 4);
2209 ALIGN_POINTER(pStubMsg->Buffer, 4);
2210 break;
2211 case RPC_FC_ALIGNM8:
2212 ALIGN_LENGTH(size, 8);
2213 ALIGN_POINTER(pStubMsg->Buffer, 8);
2214 break;
2215 case RPC_FC_STRUCTPAD1:
2216 case RPC_FC_STRUCTPAD2:
2217 case RPC_FC_STRUCTPAD3:
2218 case RPC_FC_STRUCTPAD4:
2219 case RPC_FC_STRUCTPAD5:
2220 case RPC_FC_STRUCTPAD6:
2221 case RPC_FC_STRUCTPAD7:
2222 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2223 break;
2224 case RPC_FC_EMBEDDED_COMPLEX:
2225 size += pFormat[1];
2226 pFormat += 2;
2227 desc = pFormat + *(const SHORT*)pFormat;
2228 size += EmbeddedComplexMemorySize(pStubMsg, desc);
2229 pFormat += 2;
2230 continue;
2231 case RPC_FC_PAD:
2232 break;
2233 default:
2234 FIXME("unhandled format 0x%02x\n", *pFormat);
2236 pFormat++;
2239 return size;
2242 /***********************************************************************
2243 * NdrComplexStructMarshall [RPCRT4.@]
2245 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2246 unsigned char *pMemory,
2247 PFORMAT_STRING pFormat)
2249 PFORMAT_STRING conf_array = NULL;
2250 PFORMAT_STRING pointer_desc = NULL;
2251 unsigned char *OldMemory = pStubMsg->Memory;
2252 int pointer_buffer_mark_set = 0;
2254 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2256 if (!pStubMsg->PointerBufferMark)
2258 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2259 /* save buffer length */
2260 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2262 /* get the buffer pointer after complex array data, but before
2263 * pointer data */
2264 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2265 pStubMsg->IgnoreEmbeddedPointers = 1;
2266 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2267 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2269 /* save it for use by embedded pointer code later */
2270 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2271 TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2272 pointer_buffer_mark_set = 1;
2274 /* restore the original buffer length */
2275 pStubMsg->BufferLength = saved_buffer_length;
2278 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2280 pFormat += 4;
2281 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2282 pFormat += 2;
2283 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2284 pFormat += 2;
2286 pStubMsg->Memory = pMemory;
2288 ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2290 if (conf_array)
2291 NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2293 pStubMsg->Memory = OldMemory;
2295 if (pointer_buffer_mark_set)
2297 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2298 pStubMsg->PointerBufferMark = NULL;
2301 STD_OVERFLOW_CHECK(pStubMsg);
2303 return NULL;
2306 /***********************************************************************
2307 * NdrComplexStructUnmarshall [RPCRT4.@]
2309 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2310 unsigned char **ppMemory,
2311 PFORMAT_STRING pFormat,
2312 unsigned char fMustAlloc)
2314 unsigned size = *(const WORD*)(pFormat+2);
2315 PFORMAT_STRING conf_array = NULL;
2316 PFORMAT_STRING pointer_desc = NULL;
2317 unsigned char *pMemory;
2318 int pointer_buffer_mark_set = 0;
2320 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2322 if (!pStubMsg->PointerBufferMark)
2324 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2325 /* save buffer pointer */
2326 unsigned char *saved_buffer = pStubMsg->Buffer;
2328 /* get the buffer pointer after complex array data, but before
2329 * pointer data */
2330 pStubMsg->IgnoreEmbeddedPointers = 1;
2331 NdrComplexStructMemorySize(pStubMsg, pFormat);
2332 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2334 /* save it for use by embedded pointer code later */
2335 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2336 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2337 pointer_buffer_mark_set = 1;
2339 /* restore the original buffer */
2340 pStubMsg->Buffer = saved_buffer;
2343 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2345 if (fMustAlloc || !*ppMemory)
2347 *ppMemory = NdrAllocate(pStubMsg, size);
2348 memset(*ppMemory, 0, size);
2351 pFormat += 4;
2352 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2353 pFormat += 2;
2354 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2355 pFormat += 2;
2357 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2359 if (conf_array)
2360 NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2362 if (pointer_buffer_mark_set)
2364 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2365 pStubMsg->PointerBufferMark = NULL;
2368 return NULL;
2371 /***********************************************************************
2372 * NdrComplexStructBufferSize [RPCRT4.@]
2374 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2375 unsigned char *pMemory,
2376 PFORMAT_STRING pFormat)
2378 PFORMAT_STRING conf_array = NULL;
2379 PFORMAT_STRING pointer_desc = NULL;
2380 unsigned char *OldMemory = pStubMsg->Memory;
2381 int pointer_length_set = 0;
2383 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2385 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2387 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2389 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2390 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2392 /* get the buffer length after complex struct data, but before
2393 * pointer data */
2394 pStubMsg->IgnoreEmbeddedPointers = 1;
2395 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2396 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2398 /* save it for use by embedded pointer code later */
2399 pStubMsg->PointerLength = pStubMsg->BufferLength;
2400 pointer_length_set = 1;
2401 TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2403 /* restore the original buffer length */
2404 pStubMsg->BufferLength = saved_buffer_length;
2407 pFormat += 4;
2408 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2409 pFormat += 2;
2410 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2411 pFormat += 2;
2413 pStubMsg->Memory = pMemory;
2415 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2417 if (conf_array)
2418 NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2420 pStubMsg->Memory = OldMemory;
2422 if(pointer_length_set)
2424 pStubMsg->BufferLength = pStubMsg->PointerLength;
2425 pStubMsg->PointerLength = 0;
2430 /***********************************************************************
2431 * NdrComplexStructMemorySize [RPCRT4.@]
2433 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2434 PFORMAT_STRING pFormat)
2436 unsigned size = *(const WORD*)(pFormat+2);
2437 PFORMAT_STRING conf_array = NULL;
2438 PFORMAT_STRING pointer_desc = NULL;
2440 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2442 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2444 pFormat += 4;
2445 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2446 pFormat += 2;
2447 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2448 pFormat += 2;
2450 ComplexStructMemorySize(pStubMsg, pFormat);
2452 if (conf_array)
2453 NdrConformantArrayMemorySize(pStubMsg, conf_array);
2455 return size;
2458 /***********************************************************************
2459 * NdrComplexStructFree [RPCRT4.@]
2461 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2462 unsigned char *pMemory,
2463 PFORMAT_STRING pFormat)
2465 PFORMAT_STRING conf_array = NULL;
2466 PFORMAT_STRING pointer_desc = NULL;
2467 unsigned char *OldMemory = pStubMsg->Memory;
2469 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2471 pFormat += 4;
2472 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2473 pFormat += 2;
2474 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2475 pFormat += 2;
2477 pStubMsg->Memory = pMemory;
2479 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2481 if (conf_array)
2482 NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2484 pStubMsg->Memory = OldMemory;
2487 /***********************************************************************
2488 * NdrConformantArrayMarshall [RPCRT4.@]
2490 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2491 unsigned char *pMemory,
2492 PFORMAT_STRING pFormat)
2494 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2495 unsigned char alignment = pFormat[1] + 1;
2497 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2498 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2500 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2502 WriteConformance(pStubMsg);
2504 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2506 size = safe_multiply(esize, pStubMsg->MaxCount);
2507 memcpy(pStubMsg->Buffer, pMemory, size);
2508 pStubMsg->BufferMark = pStubMsg->Buffer;
2509 pStubMsg->Buffer += size;
2511 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2513 STD_OVERFLOW_CHECK(pStubMsg);
2515 return NULL;
2518 /***********************************************************************
2519 * NdrConformantArrayUnmarshall [RPCRT4.@]
2521 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2522 unsigned char **ppMemory,
2523 PFORMAT_STRING pFormat,
2524 unsigned char fMustAlloc)
2526 DWORD size, esize = *(const WORD*)(pFormat+2);
2527 unsigned char alignment = pFormat[1] + 1;
2529 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2530 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2532 pFormat = ReadConformance(pStubMsg, pFormat+4);
2534 size = safe_multiply(esize, pStubMsg->MaxCount);
2536 if (fMustAlloc || !*ppMemory)
2537 *ppMemory = NdrAllocate(pStubMsg, size);
2539 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2541 pStubMsg->BufferMark = pStubMsg->Buffer;
2542 safe_buffer_copy(pStubMsg, *ppMemory, size);
2544 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2546 return NULL;
2549 /***********************************************************************
2550 * NdrConformantArrayBufferSize [RPCRT4.@]
2552 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2553 unsigned char *pMemory,
2554 PFORMAT_STRING pFormat)
2556 DWORD size, esize = *(const WORD*)(pFormat+2);
2557 unsigned char alignment = pFormat[1] + 1;
2559 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2560 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2562 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2564 SizeConformance(pStubMsg);
2566 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2568 size = safe_multiply(esize, pStubMsg->MaxCount);
2569 /* conformance value plus array */
2570 pStubMsg->BufferLength += size;
2572 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2575 /***********************************************************************
2576 * NdrConformantArrayMemorySize [RPCRT4.@]
2578 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2579 PFORMAT_STRING pFormat)
2581 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2582 unsigned char alignment = pFormat[1] + 1;
2584 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2585 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2587 pFormat = ReadConformance(pStubMsg, pFormat+4);
2588 size = safe_multiply(esize, pStubMsg->MaxCount);
2589 pStubMsg->MemorySize += size;
2591 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2592 pStubMsg->BufferMark = pStubMsg->Buffer;
2593 pStubMsg->Buffer += size;
2595 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2597 return pStubMsg->MemorySize;
2600 /***********************************************************************
2601 * NdrConformantArrayFree [RPCRT4.@]
2603 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2604 unsigned char *pMemory,
2605 PFORMAT_STRING pFormat)
2607 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2608 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2610 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2612 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2616 /***********************************************************************
2617 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
2619 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2620 unsigned char* pMemory,
2621 PFORMAT_STRING pFormat )
2623 ULONG bufsize;
2624 unsigned char alignment = pFormat[1] + 1;
2625 DWORD esize = *(const WORD*)(pFormat+2);
2627 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2629 if (pFormat[0] != RPC_FC_CVARRAY)
2631 ERR("invalid format type %x\n", pFormat[0]);
2632 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2633 return NULL;
2636 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2637 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2639 WriteConformance(pStubMsg);
2640 WriteVariance(pStubMsg);
2642 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2644 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2646 memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize);
2647 pStubMsg->BufferMark = pStubMsg->Buffer;
2648 pStubMsg->Buffer += bufsize;
2650 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2652 STD_OVERFLOW_CHECK(pStubMsg);
2654 return NULL;
2658 /***********************************************************************
2659 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
2661 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2662 unsigned char** ppMemory,
2663 PFORMAT_STRING pFormat,
2664 unsigned char fMustAlloc )
2666 ULONG bufsize, memsize;
2667 unsigned char alignment = pFormat[1] + 1;
2668 DWORD esize = *(const WORD*)(pFormat+2);
2670 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2672 if (pFormat[0] != RPC_FC_CVARRAY)
2674 ERR("invalid format type %x\n", pFormat[0]);
2675 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2676 return NULL;
2679 pFormat = ReadConformance(pStubMsg, pFormat+4);
2680 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2682 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2684 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2685 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2687 if (!*ppMemory || fMustAlloc)
2688 *ppMemory = NdrAllocate(pStubMsg, memsize);
2689 safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
2691 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2693 return NULL;
2697 /***********************************************************************
2698 * NdrConformantVaryingArrayFree [RPCRT4.@]
2700 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2701 unsigned char* pMemory,
2702 PFORMAT_STRING pFormat )
2704 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2706 if (pFormat[0] != RPC_FC_CVARRAY)
2708 ERR("invalid format type %x\n", pFormat[0]);
2709 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2710 return;
2713 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2714 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2716 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2720 /***********************************************************************
2721 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
2723 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2724 unsigned char* pMemory, PFORMAT_STRING pFormat )
2726 unsigned char alignment = pFormat[1] + 1;
2727 DWORD esize = *(const WORD*)(pFormat+2);
2729 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2731 if (pFormat[0] != RPC_FC_CVARRAY)
2733 ERR("invalid format type %x\n", pFormat[0]);
2734 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2735 return;
2738 /* compute size */
2739 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2740 /* compute length */
2741 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2743 SizeConformance(pStubMsg);
2744 SizeVariance(pStubMsg);
2746 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2748 pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
2750 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2754 /***********************************************************************
2755 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
2757 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2758 PFORMAT_STRING pFormat )
2760 FIXME( "stub\n" );
2761 return 0;
2765 /***********************************************************************
2766 * NdrComplexArrayMarshall [RPCRT4.@]
2768 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2769 unsigned char *pMemory,
2770 PFORMAT_STRING pFormat)
2772 ULONG i, count, def;
2773 BOOL variance_present;
2774 unsigned char alignment;
2775 int pointer_buffer_mark_set = 0;
2777 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2779 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2781 ERR("invalid format type %x\n", pFormat[0]);
2782 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2783 return NULL;
2786 alignment = pFormat[1] + 1;
2788 if (!pStubMsg->PointerBufferMark)
2790 /* save buffer fields that may be changed by buffer sizer functions
2791 * and that may be needed later on */
2792 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2793 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2794 unsigned long saved_max_count = pStubMsg->MaxCount;
2795 unsigned long saved_offset = pStubMsg->Offset;
2796 unsigned long saved_actual_count = pStubMsg->ActualCount;
2798 /* get the buffer pointer after complex array data, but before
2799 * pointer data */
2800 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2801 pStubMsg->IgnoreEmbeddedPointers = 1;
2802 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
2803 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2805 /* save it for use by embedded pointer code later */
2806 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2807 TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
2808 pointer_buffer_mark_set = 1;
2810 /* restore fields */
2811 pStubMsg->ActualCount = saved_actual_count;
2812 pStubMsg->Offset = saved_offset;
2813 pStubMsg->MaxCount = saved_max_count;
2814 pStubMsg->BufferLength = saved_buffer_length;
2817 def = *(const WORD*)&pFormat[2];
2818 pFormat += 4;
2820 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2821 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2823 variance_present = IsConformanceOrVariancePresent(pFormat);
2824 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2825 TRACE("variance = %d\n", pStubMsg->ActualCount);
2827 WriteConformance(pStubMsg);
2828 if (variance_present)
2829 WriteVariance(pStubMsg);
2831 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2833 count = pStubMsg->ActualCount;
2834 for (i = 0; i < count; i++)
2835 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2837 STD_OVERFLOW_CHECK(pStubMsg);
2839 if (pointer_buffer_mark_set)
2841 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2842 pStubMsg->PointerBufferMark = NULL;
2845 return NULL;
2848 /***********************************************************************
2849 * NdrComplexArrayUnmarshall [RPCRT4.@]
2851 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2852 unsigned char **ppMemory,
2853 PFORMAT_STRING pFormat,
2854 unsigned char fMustAlloc)
2856 ULONG i, count, size;
2857 unsigned char alignment;
2858 unsigned char *pMemory;
2859 unsigned char *saved_buffer;
2860 int pointer_buffer_mark_set = 0;
2861 int saved_ignore_embedded;
2863 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2865 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2867 ERR("invalid format type %x\n", pFormat[0]);
2868 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2869 return NULL;
2872 alignment = pFormat[1] + 1;
2874 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2875 /* save buffer pointer */
2876 saved_buffer = pStubMsg->Buffer;
2877 /* get the buffer pointer after complex array data, but before
2878 * pointer data */
2879 pStubMsg->IgnoreEmbeddedPointers = 1;
2880 pStubMsg->MemorySize = 0;
2881 NdrComplexArrayMemorySize(pStubMsg, pFormat);
2882 size = pStubMsg->MemorySize;
2883 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2885 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
2886 if (!pStubMsg->PointerBufferMark)
2888 /* save it for use by embedded pointer code later */
2889 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2890 pointer_buffer_mark_set = 1;
2892 /* restore the original buffer */
2893 pStubMsg->Buffer = saved_buffer;
2895 pFormat += 4;
2897 pFormat = ReadConformance(pStubMsg, pFormat);
2898 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2900 if (fMustAlloc || !*ppMemory)
2902 *ppMemory = NdrAllocate(pStubMsg, size);
2903 memset(*ppMemory, 0, size);
2906 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2908 pMemory = *ppMemory;
2909 count = pStubMsg->ActualCount;
2910 for (i = 0; i < count; i++)
2911 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
2913 if (pointer_buffer_mark_set)
2915 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2916 pStubMsg->PointerBufferMark = NULL;
2919 return NULL;
2922 /***********************************************************************
2923 * NdrComplexArrayBufferSize [RPCRT4.@]
2925 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2926 unsigned char *pMemory,
2927 PFORMAT_STRING pFormat)
2929 ULONG i, count, def;
2930 unsigned char alignment;
2931 BOOL variance_present;
2932 int pointer_length_set = 0;
2934 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2936 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2938 ERR("invalid format type %x\n", pFormat[0]);
2939 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2940 return;
2943 alignment = pFormat[1] + 1;
2945 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2947 /* save buffer fields that may be changed by buffer sizer functions
2948 * and that may be needed later on */
2949 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2950 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2951 unsigned long saved_max_count = pStubMsg->MaxCount;
2952 unsigned long saved_offset = pStubMsg->Offset;
2953 unsigned long saved_actual_count = pStubMsg->ActualCount;
2955 /* get the buffer pointer after complex array data, but before
2956 * pointer data */
2957 pStubMsg->IgnoreEmbeddedPointers = 1;
2958 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
2959 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2961 /* save it for use by embedded pointer code later */
2962 pStubMsg->PointerLength = pStubMsg->BufferLength;
2963 pointer_length_set = 1;
2965 /* restore fields */
2966 pStubMsg->ActualCount = saved_actual_count;
2967 pStubMsg->Offset = saved_offset;
2968 pStubMsg->MaxCount = saved_max_count;
2969 pStubMsg->BufferLength = saved_buffer_length;
2971 def = *(const WORD*)&pFormat[2];
2972 pFormat += 4;
2974 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2975 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2976 SizeConformance(pStubMsg);
2978 variance_present = IsConformanceOrVariancePresent(pFormat);
2979 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2980 TRACE("variance = %d\n", pStubMsg->ActualCount);
2982 if (variance_present)
2983 SizeVariance(pStubMsg);
2985 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2987 count = pStubMsg->ActualCount;
2988 for (i = 0; i < count; i++)
2989 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
2991 if(pointer_length_set)
2993 pStubMsg->BufferLength = pStubMsg->PointerLength;
2994 pStubMsg->PointerLength = 0;
2998 /***********************************************************************
2999 * NdrComplexArrayMemorySize [RPCRT4.@]
3001 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3002 PFORMAT_STRING pFormat)
3004 ULONG i, count, esize, SavedMemorySize, MemorySize;
3005 unsigned char alignment;
3006 unsigned char *Buffer;
3008 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3010 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3012 ERR("invalid format type %x\n", pFormat[0]);
3013 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3014 return 0;
3017 alignment = pFormat[1] + 1;
3019 pFormat += 4;
3021 pFormat = ReadConformance(pStubMsg, pFormat);
3022 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3024 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3026 SavedMemorySize = pStubMsg->MemorySize;
3028 Buffer = pStubMsg->Buffer;
3029 pStubMsg->MemorySize = 0;
3030 esize = ComplexStructMemorySize(pStubMsg, pFormat);
3031 pStubMsg->Buffer = Buffer;
3033 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3035 count = pStubMsg->ActualCount;
3036 for (i = 0; i < count; i++)
3037 ComplexStructMemorySize(pStubMsg, pFormat);
3039 pStubMsg->MemorySize = SavedMemorySize;
3041 pStubMsg->MemorySize += MemorySize;
3042 return MemorySize;
3045 /***********************************************************************
3046 * NdrComplexArrayFree [RPCRT4.@]
3048 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3049 unsigned char *pMemory,
3050 PFORMAT_STRING pFormat)
3052 ULONG i, count, def;
3054 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3056 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3058 ERR("invalid format type %x\n", pFormat[0]);
3059 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3060 return;
3063 def = *(const WORD*)&pFormat[2];
3064 pFormat += 4;
3066 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3067 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3069 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3070 TRACE("variance = %d\n", pStubMsg->ActualCount);
3072 count = pStubMsg->ActualCount;
3073 for (i = 0; i < count; i++)
3074 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
3077 static ULONG UserMarshalFlags(const MIDL_STUB_MESSAGE *pStubMsg)
3079 return MAKELONG(pStubMsg->dwDestContext,
3080 pStubMsg->RpcMsg->DataRepresentation);
3083 #define USER_MARSHAL_PTR_PREFIX \
3084 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
3085 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
3087 /***********************************************************************
3088 * NdrUserMarshalMarshall [RPCRT4.@]
3090 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3091 unsigned char *pMemory,
3092 PFORMAT_STRING pFormat)
3094 unsigned flags = pFormat[1];
3095 unsigned index = *(const WORD*)&pFormat[2];
3096 unsigned char *saved_buffer = NULL;
3097 ULONG uflag = UserMarshalFlags(pStubMsg);
3098 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3099 TRACE("index=%d\n", index);
3101 if (flags & USER_MARSHAL_POINTER)
3103 ALIGN_POINTER(pStubMsg->Buffer, 4);
3104 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
3105 pStubMsg->Buffer += 4;
3106 if (pStubMsg->PointerBufferMark)
3108 saved_buffer = pStubMsg->Buffer;
3109 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3110 pStubMsg->PointerBufferMark = NULL;
3112 ALIGN_POINTER(pStubMsg->Buffer, 8);
3114 else
3115 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3117 pStubMsg->Buffer =
3118 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
3119 &uflag, pStubMsg->Buffer, pMemory);
3121 if (saved_buffer)
3123 STD_OVERFLOW_CHECK(pStubMsg);
3124 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3125 pStubMsg->Buffer = saved_buffer;
3128 STD_OVERFLOW_CHECK(pStubMsg);
3130 return NULL;
3133 /***********************************************************************
3134 * NdrUserMarshalUnmarshall [RPCRT4.@]
3136 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3137 unsigned char **ppMemory,
3138 PFORMAT_STRING pFormat,
3139 unsigned char fMustAlloc)
3141 unsigned flags = pFormat[1];
3142 unsigned index = *(const WORD*)&pFormat[2];
3143 DWORD memsize = *(const WORD*)&pFormat[4];
3144 unsigned char *saved_buffer = NULL;
3145 ULONG uflag = UserMarshalFlags(pStubMsg);
3146 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3147 TRACE("index=%d\n", index);
3149 if (flags & USER_MARSHAL_POINTER)
3151 ALIGN_POINTER(pStubMsg->Buffer, 4);
3152 /* skip pointer prefix */
3153 pStubMsg->Buffer += 4;
3154 if (pStubMsg->PointerBufferMark)
3156 saved_buffer = pStubMsg->Buffer;
3157 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3158 pStubMsg->PointerBufferMark = NULL;
3160 ALIGN_POINTER(pStubMsg->Buffer, 8);
3162 else
3163 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3165 if (fMustAlloc || !*ppMemory)
3166 *ppMemory = NdrAllocate(pStubMsg, memsize);
3168 pStubMsg->Buffer =
3169 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
3170 &uflag, pStubMsg->Buffer, *ppMemory);
3172 if (saved_buffer)
3174 STD_OVERFLOW_CHECK(pStubMsg);
3175 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3176 pStubMsg->Buffer = saved_buffer;
3179 return NULL;
3182 /***********************************************************************
3183 * NdrUserMarshalBufferSize [RPCRT4.@]
3185 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3186 unsigned char *pMemory,
3187 PFORMAT_STRING pFormat)
3189 unsigned flags = pFormat[1];
3190 unsigned index = *(const WORD*)&pFormat[2];
3191 DWORD bufsize = *(const WORD*)&pFormat[6];
3192 ULONG uflag = UserMarshalFlags(pStubMsg);
3193 unsigned long saved_buffer_length = 0;
3194 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3195 TRACE("index=%d\n", index);
3197 if (flags & USER_MARSHAL_POINTER)
3199 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3200 /* skip pointer prefix */
3201 pStubMsg->BufferLength += 4;
3202 if (pStubMsg->IgnoreEmbeddedPointers)
3203 return;
3204 if (pStubMsg->PointerLength)
3206 saved_buffer_length = pStubMsg->BufferLength;
3207 pStubMsg->BufferLength = pStubMsg->PointerLength;
3208 pStubMsg->PointerLength = 0;
3210 ALIGN_LENGTH(pStubMsg->BufferLength, 8);
3212 else
3213 ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
3215 if (bufsize) {
3216 TRACE("size=%d\n", bufsize);
3217 pStubMsg->BufferLength += bufsize;
3219 else
3220 pStubMsg->BufferLength =
3221 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
3222 &uflag, pStubMsg->BufferLength, pMemory);
3224 if (saved_buffer_length)
3226 pStubMsg->PointerLength = pStubMsg->BufferLength;
3227 pStubMsg->BufferLength = saved_buffer_length;
3232 /***********************************************************************
3233 * NdrUserMarshalMemorySize [RPCRT4.@]
3235 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3236 PFORMAT_STRING pFormat)
3238 unsigned flags = pFormat[1];
3239 unsigned index = *(const WORD*)&pFormat[2];
3240 DWORD memsize = *(const WORD*)&pFormat[4];
3241 DWORD bufsize = *(const WORD*)&pFormat[6];
3243 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3244 TRACE("index=%d\n", index);
3246 pStubMsg->MemorySize += memsize;
3248 if (flags & USER_MARSHAL_POINTER)
3250 ALIGN_POINTER(pStubMsg->Buffer, 4);
3251 /* skip pointer prefix */
3252 pStubMsg->Buffer += 4;
3253 if (pStubMsg->IgnoreEmbeddedPointers)
3254 return pStubMsg->MemorySize;
3255 ALIGN_POINTER(pStubMsg->Buffer, 8);
3257 else
3258 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3260 if (!bufsize)
3261 FIXME("not implemented for varying buffer size\n");
3263 pStubMsg->Buffer += bufsize;
3265 return pStubMsg->MemorySize;
3268 /***********************************************************************
3269 * NdrUserMarshalFree [RPCRT4.@]
3271 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
3272 unsigned char *pMemory,
3273 PFORMAT_STRING pFormat)
3275 /* unsigned flags = pFormat[1]; */
3276 unsigned index = *(const WORD*)&pFormat[2];
3277 ULONG uflag = UserMarshalFlags(pStubMsg);
3278 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3279 TRACE("index=%d\n", index);
3281 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
3282 &uflag, pMemory);
3285 /***********************************************************************
3286 * NdrClearOutParameters [RPCRT4.@]
3288 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
3289 PFORMAT_STRING pFormat,
3290 void *ArgAddr)
3292 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
3295 /***********************************************************************
3296 * NdrConvert [RPCRT4.@]
3298 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
3300 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
3301 /* FIXME: since this stub doesn't do any converting, the proper behavior
3302 is to raise an exception */
3305 /***********************************************************************
3306 * NdrConvert2 [RPCRT4.@]
3308 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
3310 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
3311 pStubMsg, pFormat, NumberParams);
3312 /* FIXME: since this stub doesn't do any converting, the proper behavior
3313 is to raise an exception */
3316 #include "pshpack1.h"
3317 typedef struct _NDR_CSTRUCT_FORMAT
3319 unsigned char type;
3320 unsigned char alignment;
3321 unsigned short memory_size;
3322 short offset_to_array_description;
3323 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
3324 #include "poppack.h"
3326 /***********************************************************************
3327 * NdrConformantStructMarshall [RPCRT4.@]
3329 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3330 unsigned char *pMemory,
3331 PFORMAT_STRING pFormat)
3333 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3334 PFORMAT_STRING pCArrayFormat;
3335 ULONG esize, bufsize;
3337 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3339 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3340 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3342 ERR("invalid format type %x\n", pCStructFormat->type);
3343 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3344 return NULL;
3347 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3348 pCStructFormat->offset_to_array_description;
3349 if (*pCArrayFormat != RPC_FC_CARRAY)
3351 ERR("invalid array format type %x\n", pCStructFormat->type);
3352 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3353 return NULL;
3355 esize = *(const WORD*)(pCArrayFormat+2);
3357 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3358 pCArrayFormat + 4, 0);
3360 WriteConformance(pStubMsg);
3362 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3364 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3366 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3367 /* copy constant sized part of struct */
3368 pStubMsg->BufferMark = pStubMsg->Buffer;
3369 memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size + bufsize);
3370 pStubMsg->Buffer += pCStructFormat->memory_size + bufsize;
3372 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3373 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3375 STD_OVERFLOW_CHECK(pStubMsg);
3377 return NULL;
3380 /***********************************************************************
3381 * NdrConformantStructUnmarshall [RPCRT4.@]
3383 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3384 unsigned char **ppMemory,
3385 PFORMAT_STRING pFormat,
3386 unsigned char fMustAlloc)
3388 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3389 PFORMAT_STRING pCArrayFormat;
3390 ULONG esize, bufsize;
3392 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3394 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3395 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3397 ERR("invalid format type %x\n", pCStructFormat->type);
3398 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3399 return NULL;
3401 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3402 pCStructFormat->offset_to_array_description;
3403 if (*pCArrayFormat != RPC_FC_CARRAY)
3405 ERR("invalid array format type %x\n", pCStructFormat->type);
3406 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3407 return NULL;
3409 esize = *(const WORD*)(pCArrayFormat+2);
3411 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
3413 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3415 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3417 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3418 /* work out how much memory to allocate if we need to do so */
3419 if (!*ppMemory || fMustAlloc)
3421 SIZE_T size = pCStructFormat->memory_size + bufsize;
3422 *ppMemory = NdrAllocate(pStubMsg, size);
3425 /* now copy the data */
3426 pStubMsg->BufferMark = pStubMsg->Buffer;
3427 safe_buffer_copy(pStubMsg, *ppMemory, pCStructFormat->memory_size + bufsize);
3429 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3430 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3432 return NULL;
3435 /***********************************************************************
3436 * NdrConformantStructBufferSize [RPCRT4.@]
3438 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3439 unsigned char *pMemory,
3440 PFORMAT_STRING pFormat)
3442 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3443 PFORMAT_STRING pCArrayFormat;
3444 ULONG esize;
3446 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3448 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3449 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3451 ERR("invalid format type %x\n", pCStructFormat->type);
3452 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3453 return;
3455 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3456 pCStructFormat->offset_to_array_description;
3457 if (*pCArrayFormat != RPC_FC_CARRAY)
3459 ERR("invalid array format type %x\n", pCStructFormat->type);
3460 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3461 return;
3463 esize = *(const WORD*)(pCArrayFormat+2);
3465 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
3466 SizeConformance(pStubMsg);
3468 ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
3470 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3472 pStubMsg->BufferLength += pCStructFormat->memory_size +
3473 safe_multiply(pStubMsg->MaxCount, esize);
3475 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3476 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3479 /***********************************************************************
3480 * NdrConformantStructMemorySize [RPCRT4.@]
3482 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3483 PFORMAT_STRING pFormat)
3485 FIXME("stub\n");
3486 return 0;
3489 /***********************************************************************
3490 * NdrConformantStructFree [RPCRT4.@]
3492 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3493 unsigned char *pMemory,
3494 PFORMAT_STRING pFormat)
3496 FIXME("stub\n");
3499 /***********************************************************************
3500 * NdrConformantVaryingStructMarshall [RPCRT4.@]
3502 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3503 unsigned char *pMemory,
3504 PFORMAT_STRING pFormat)
3506 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3507 PFORMAT_STRING pCVArrayFormat;
3508 ULONG esize, bufsize;
3510 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3512 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3513 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3515 ERR("invalid format type %x\n", pCVStructFormat->type);
3516 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3517 return NULL;
3520 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3521 pCVStructFormat->offset_to_array_description;
3522 switch (*pCVArrayFormat)
3524 case RPC_FC_CVARRAY:
3525 esize = *(const WORD*)(pCVArrayFormat+2);
3527 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3528 pCVArrayFormat + 4, 0);
3529 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3530 pCVArrayFormat, 0);
3531 break;
3532 case RPC_FC_C_CSTRING:
3533 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3534 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3535 esize = sizeof(char);
3536 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3537 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3538 pCVArrayFormat + 2, 0);
3539 else
3540 pStubMsg->MaxCount = pStubMsg->ActualCount;
3541 break;
3542 case RPC_FC_C_WSTRING:
3543 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3544 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3545 esize = sizeof(WCHAR);
3546 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3547 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3548 pCVArrayFormat + 2, 0);
3549 else
3550 pStubMsg->MaxCount = pStubMsg->ActualCount;
3551 break;
3552 default:
3553 ERR("invalid array format type %x\n", *pCVArrayFormat);
3554 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3555 return NULL;
3558 WriteConformance(pStubMsg);
3560 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3562 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3564 /* write constant sized part */
3565 pStubMsg->BufferMark = pStubMsg->Buffer;
3566 memcpy(pStubMsg->Buffer, pMemory, pCVStructFormat->memory_size);
3567 pStubMsg->Buffer += pCVStructFormat->memory_size;
3569 WriteVariance(pStubMsg);
3571 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3573 /* write array part */
3574 memcpy(pStubMsg->Buffer, pMemory + pCVStructFormat->memory_size, bufsize);
3575 pStubMsg->Buffer += bufsize;
3577 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3579 STD_OVERFLOW_CHECK(pStubMsg);
3581 return NULL;
3584 /***********************************************************************
3585 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
3587 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3588 unsigned char **ppMemory,
3589 PFORMAT_STRING pFormat,
3590 unsigned char fMustAlloc)
3592 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3593 PFORMAT_STRING pCVArrayFormat;
3594 ULONG esize, bufsize;
3595 unsigned char cvarray_type;
3597 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3599 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3600 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3602 ERR("invalid format type %x\n", pCVStructFormat->type);
3603 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3604 return NULL;
3607 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3608 pCVStructFormat->offset_to_array_description;
3609 cvarray_type = *pCVArrayFormat;
3610 switch (cvarray_type)
3612 case RPC_FC_CVARRAY:
3613 esize = *(const WORD*)(pCVArrayFormat+2);
3614 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3615 break;
3616 case RPC_FC_C_CSTRING:
3617 esize = sizeof(char);
3618 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3619 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3620 else
3621 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3622 break;
3623 case RPC_FC_C_WSTRING:
3624 esize = sizeof(WCHAR);
3625 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3626 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3627 else
3628 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3629 break;
3630 default:
3631 ERR("invalid array format type %x\n", *pCVArrayFormat);
3632 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3633 return NULL;
3636 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3638 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3640 /* work out how much memory to allocate if we need to do so */
3641 if (!*ppMemory || fMustAlloc)
3643 SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3644 *ppMemory = NdrAllocate(pStubMsg, size);
3647 /* copy the constant data */
3648 pStubMsg->BufferMark = pStubMsg->Buffer;
3649 safe_buffer_copy(pStubMsg, *ppMemory, pCVStructFormat->memory_size);
3651 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3653 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3655 if ((cvarray_type == RPC_FC_C_CSTRING) ||
3656 (cvarray_type == RPC_FC_C_WSTRING))
3658 ULONG i;
3659 /* strings must always have null terminating bytes */
3660 if (bufsize < esize)
3662 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
3663 RpcRaiseException(RPC_S_INVALID_BOUND);
3664 return NULL;
3666 for (i = bufsize - esize; i < bufsize; i++)
3667 if (pStubMsg->Buffer[i] != 0)
3669 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
3670 i, pStubMsg->Buffer[i]);
3671 RpcRaiseException(RPC_S_INVALID_BOUND);
3672 return NULL;
3676 /* copy the array data */
3677 safe_buffer_copy(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize);
3679 if (cvarray_type == RPC_FC_C_CSTRING)
3680 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3681 else if (cvarray_type == RPC_FC_C_WSTRING)
3682 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3684 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3686 return NULL;
3689 /***********************************************************************
3690 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
3692 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3693 unsigned char *pMemory,
3694 PFORMAT_STRING pFormat)
3696 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3697 PFORMAT_STRING pCVArrayFormat;
3698 ULONG esize;
3700 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3702 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3703 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3705 ERR("invalid format type %x\n", pCVStructFormat->type);
3706 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3707 return;
3710 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3711 pCVStructFormat->offset_to_array_description;
3712 switch (*pCVArrayFormat)
3714 case RPC_FC_CVARRAY:
3715 esize = *(const WORD*)(pCVArrayFormat+2);
3717 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3718 pCVArrayFormat + 4, 0);
3719 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3720 pCVArrayFormat, 0);
3721 break;
3722 case RPC_FC_C_CSTRING:
3723 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3724 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3725 esize = sizeof(char);
3726 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3727 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3728 pCVArrayFormat + 2, 0);
3729 else
3730 pStubMsg->MaxCount = pStubMsg->ActualCount;
3731 break;
3732 case RPC_FC_C_WSTRING:
3733 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3734 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3735 esize = sizeof(WCHAR);
3736 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3737 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3738 pCVArrayFormat + 2, 0);
3739 else
3740 pStubMsg->MaxCount = pStubMsg->ActualCount;
3741 break;
3742 default:
3743 ERR("invalid array format type %x\n", *pCVArrayFormat);
3744 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3745 return;
3748 SizeConformance(pStubMsg);
3750 ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
3752 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3754 pStubMsg->BufferLength += pCVStructFormat->memory_size;
3755 SizeVariance(pStubMsg);
3756 pStubMsg->BufferLength += safe_multiply(pStubMsg->MaxCount, esize);
3758 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3761 /***********************************************************************
3762 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
3764 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3765 PFORMAT_STRING pFormat)
3767 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3768 PFORMAT_STRING pCVArrayFormat;
3769 ULONG esize;
3770 unsigned char cvarray_type;
3772 TRACE("(%p, %p)\n", pStubMsg, pFormat);
3774 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3775 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3777 ERR("invalid format type %x\n", pCVStructFormat->type);
3778 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3779 return 0;
3782 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3783 pCVStructFormat->offset_to_array_description;
3784 cvarray_type = *pCVArrayFormat;
3785 switch (cvarray_type)
3787 case RPC_FC_CVARRAY:
3788 esize = *(const WORD*)(pCVArrayFormat+2);
3789 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3790 break;
3791 case RPC_FC_C_CSTRING:
3792 esize = sizeof(char);
3793 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3794 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3795 else
3796 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3797 break;
3798 case RPC_FC_C_WSTRING:
3799 esize = sizeof(WCHAR);
3800 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3801 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3802 else
3803 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3804 break;
3805 default:
3806 ERR("invalid array format type %x\n", *pCVArrayFormat);
3807 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3808 return 0;
3811 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3813 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3815 pStubMsg->Buffer += pCVStructFormat->memory_size;
3816 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3817 pStubMsg->Buffer += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->ActualCount);
3819 pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3821 EmbeddedPointerMemorySize(pStubMsg, pFormat);
3823 return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3826 /***********************************************************************
3827 * NdrConformantVaryingStructFree [RPCRT4.@]
3829 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3830 unsigned char *pMemory,
3831 PFORMAT_STRING pFormat)
3833 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3834 PFORMAT_STRING pCVArrayFormat;
3835 ULONG esize;
3837 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3839 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3840 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3842 ERR("invalid format type %x\n", pCVStructFormat->type);
3843 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3844 return;
3847 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3848 pCVStructFormat->offset_to_array_description;
3849 switch (*pCVArrayFormat)
3851 case RPC_FC_CVARRAY:
3852 esize = *(const WORD*)(pCVArrayFormat+2);
3854 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3855 pCVArrayFormat + 4, 0);
3856 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3857 pCVArrayFormat, 0);
3858 break;
3859 case RPC_FC_C_CSTRING:
3860 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3861 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3862 esize = sizeof(char);
3863 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3864 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3865 pCVArrayFormat + 2, 0);
3866 else
3867 pStubMsg->MaxCount = pStubMsg->ActualCount;
3868 break;
3869 case RPC_FC_C_WSTRING:
3870 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3871 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3872 esize = sizeof(WCHAR);
3873 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3874 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3875 pCVArrayFormat + 2, 0);
3876 else
3877 pStubMsg->MaxCount = pStubMsg->ActualCount;
3878 break;
3879 default:
3880 ERR("invalid array format type %x\n", *pCVArrayFormat);
3881 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3882 return;
3885 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3887 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3890 #include "pshpack1.h"
3891 typedef struct
3893 unsigned char type;
3894 unsigned char alignment;
3895 unsigned short total_size;
3896 } NDR_SMFARRAY_FORMAT;
3898 typedef struct
3900 unsigned char type;
3901 unsigned char alignment;
3902 unsigned long total_size;
3903 } NDR_LGFARRAY_FORMAT;
3904 #include "poppack.h"
3906 /***********************************************************************
3907 * NdrFixedArrayMarshall [RPCRT4.@]
3909 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3910 unsigned char *pMemory,
3911 PFORMAT_STRING pFormat)
3913 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3914 unsigned long total_size;
3916 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3918 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3919 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3921 ERR("invalid format type %x\n", pSmFArrayFormat->type);
3922 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3923 return NULL;
3926 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3928 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3930 total_size = pSmFArrayFormat->total_size;
3931 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3933 else
3935 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3936 total_size = pLgFArrayFormat->total_size;
3937 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3940 memcpy(pStubMsg->Buffer, pMemory, total_size);
3941 pStubMsg->BufferMark = pStubMsg->Buffer;
3942 pStubMsg->Buffer += total_size;
3944 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3946 return NULL;
3949 /***********************************************************************
3950 * NdrFixedArrayUnmarshall [RPCRT4.@]
3952 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3953 unsigned char **ppMemory,
3954 PFORMAT_STRING pFormat,
3955 unsigned char fMustAlloc)
3957 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3958 unsigned long total_size;
3960 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3962 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3963 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3965 ERR("invalid format type %x\n", pSmFArrayFormat->type);
3966 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3967 return NULL;
3970 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3972 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3974 total_size = pSmFArrayFormat->total_size;
3975 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
3977 else
3979 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3980 total_size = pLgFArrayFormat->total_size;
3981 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
3984 if (fMustAlloc || !*ppMemory)
3985 *ppMemory = NdrAllocate(pStubMsg, total_size);
3986 pStubMsg->BufferMark = pStubMsg->Buffer;
3987 safe_buffer_copy(pStubMsg, *ppMemory, total_size);
3989 pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3991 return NULL;
3994 /***********************************************************************
3995 * NdrFixedArrayBufferSize [RPCRT4.@]
3997 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3998 unsigned char *pMemory,
3999 PFORMAT_STRING pFormat)
4001 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4002 unsigned long total_size;
4004 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4006 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4007 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4009 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4010 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4011 return;
4014 ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
4016 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4018 total_size = pSmFArrayFormat->total_size;
4019 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4021 else
4023 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4024 total_size = pLgFArrayFormat->total_size;
4025 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4027 pStubMsg->BufferLength += total_size;
4029 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4032 /***********************************************************************
4033 * NdrFixedArrayMemorySize [RPCRT4.@]
4035 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4036 PFORMAT_STRING pFormat)
4038 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4039 ULONG total_size;
4041 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4043 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4044 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4046 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4047 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4048 return 0;
4051 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4053 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4055 total_size = pSmFArrayFormat->total_size;
4056 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4058 else
4060 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4061 total_size = pLgFArrayFormat->total_size;
4062 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4064 pStubMsg->BufferMark = pStubMsg->Buffer;
4065 pStubMsg->Buffer += total_size;
4066 pStubMsg->MemorySize += total_size;
4068 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4070 return total_size;
4073 /***********************************************************************
4074 * NdrFixedArrayFree [RPCRT4.@]
4076 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4077 unsigned char *pMemory,
4078 PFORMAT_STRING pFormat)
4080 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4082 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4084 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4085 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4087 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4088 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4089 return;
4092 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4093 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4094 else
4096 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4097 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4100 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4103 /***********************************************************************
4104 * NdrVaryingArrayMarshall [RPCRT4.@]
4106 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4107 unsigned char *pMemory,
4108 PFORMAT_STRING pFormat)
4110 unsigned char alignment;
4111 DWORD elements, esize;
4112 ULONG bufsize;
4114 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4116 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4117 (pFormat[0] != RPC_FC_LGVARRAY))
4119 ERR("invalid format type %x\n", pFormat[0]);
4120 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4121 return NULL;
4124 alignment = pFormat[1] + 1;
4126 if (pFormat[0] == RPC_FC_SMVARRAY)
4128 pFormat += 2;
4129 pFormat += sizeof(WORD);
4130 elements = *(const WORD*)pFormat;
4131 pFormat += sizeof(WORD);
4133 else
4135 pFormat += 2;
4136 pFormat += sizeof(DWORD);
4137 elements = *(const DWORD*)pFormat;
4138 pFormat += sizeof(DWORD);
4141 esize = *(const WORD*)pFormat;
4142 pFormat += sizeof(WORD);
4144 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4145 if ((pStubMsg->ActualCount > elements) ||
4146 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4148 RpcRaiseException(RPC_S_INVALID_BOUND);
4149 return NULL;
4152 WriteVariance(pStubMsg);
4154 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4156 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4157 memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize);
4158 pStubMsg->BufferMark = pStubMsg->Buffer;
4159 pStubMsg->Buffer += bufsize;
4161 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4163 STD_OVERFLOW_CHECK(pStubMsg);
4165 return NULL;
4168 /***********************************************************************
4169 * NdrVaryingArrayUnmarshall [RPCRT4.@]
4171 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4172 unsigned char **ppMemory,
4173 PFORMAT_STRING pFormat,
4174 unsigned char fMustAlloc)
4176 unsigned char alignment;
4177 DWORD size, elements, esize;
4178 ULONG bufsize;
4180 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4182 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4183 (pFormat[0] != RPC_FC_LGVARRAY))
4185 ERR("invalid format type %x\n", pFormat[0]);
4186 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4187 return NULL;
4190 alignment = pFormat[1] + 1;
4192 if (pFormat[0] == RPC_FC_SMVARRAY)
4194 pFormat += 2;
4195 size = *(const WORD*)pFormat;
4196 pFormat += sizeof(WORD);
4197 elements = *(const WORD*)pFormat;
4198 pFormat += sizeof(WORD);
4200 else
4202 pFormat += 2;
4203 size = *(const DWORD*)pFormat;
4204 pFormat += sizeof(DWORD);
4205 elements = *(const DWORD*)pFormat;
4206 pFormat += sizeof(DWORD);
4209 esize = *(const WORD*)pFormat;
4210 pFormat += sizeof(WORD);
4212 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4214 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4216 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4218 if (!*ppMemory || fMustAlloc)
4219 *ppMemory = NdrAllocate(pStubMsg, size);
4220 safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
4222 EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
4224 return NULL;
4227 /***********************************************************************
4228 * NdrVaryingArrayBufferSize [RPCRT4.@]
4230 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4231 unsigned char *pMemory,
4232 PFORMAT_STRING pFormat)
4234 unsigned char alignment;
4235 DWORD elements, esize;
4237 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4239 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4240 (pFormat[0] != RPC_FC_LGVARRAY))
4242 ERR("invalid format type %x\n", pFormat[0]);
4243 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4244 return;
4247 alignment = pFormat[1] + 1;
4249 if (pFormat[0] == RPC_FC_SMVARRAY)
4251 pFormat += 2;
4252 pFormat += sizeof(WORD);
4253 elements = *(const WORD*)pFormat;
4254 pFormat += sizeof(WORD);
4256 else
4258 pFormat += 2;
4259 pFormat += sizeof(DWORD);
4260 elements = *(const DWORD*)pFormat;
4261 pFormat += sizeof(DWORD);
4264 esize = *(const WORD*)pFormat;
4265 pFormat += sizeof(WORD);
4267 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4268 if ((pStubMsg->ActualCount > elements) ||
4269 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4271 RpcRaiseException(RPC_S_INVALID_BOUND);
4272 return;
4275 SizeVariance(pStubMsg);
4277 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4279 pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount);
4281 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4284 /***********************************************************************
4285 * NdrVaryingArrayMemorySize [RPCRT4.@]
4287 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4288 PFORMAT_STRING pFormat)
4290 unsigned char alignment;
4291 DWORD size, elements, esize;
4293 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4295 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4296 (pFormat[0] != RPC_FC_LGVARRAY))
4298 ERR("invalid format type %x\n", pFormat[0]);
4299 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4300 return 0;
4303 alignment = pFormat[1] + 1;
4305 if (pFormat[0] == RPC_FC_SMVARRAY)
4307 pFormat += 2;
4308 size = *(const WORD*)pFormat;
4309 pFormat += sizeof(WORD);
4310 elements = *(const WORD*)pFormat;
4311 pFormat += sizeof(WORD);
4313 else
4315 pFormat += 2;
4316 size = *(const DWORD*)pFormat;
4317 pFormat += sizeof(DWORD);
4318 elements = *(const DWORD*)pFormat;
4319 pFormat += sizeof(DWORD);
4322 esize = *(const WORD*)pFormat;
4323 pFormat += sizeof(WORD);
4325 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4327 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4329 pStubMsg->Buffer += safe_multiply(esize, pStubMsg->ActualCount);
4330 pStubMsg->MemorySize += size;
4332 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4334 return pStubMsg->MemorySize;
4337 /***********************************************************************
4338 * NdrVaryingArrayFree [RPCRT4.@]
4340 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4341 unsigned char *pMemory,
4342 PFORMAT_STRING pFormat)
4344 unsigned char alignment;
4345 DWORD elements;
4347 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4349 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4350 (pFormat[0] != RPC_FC_LGVARRAY))
4352 ERR("invalid format type %x\n", pFormat[0]);
4353 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4354 return;
4357 alignment = pFormat[1] + 1;
4359 if (pFormat[0] == RPC_FC_SMVARRAY)
4361 pFormat += 2;
4362 pFormat += sizeof(WORD);
4363 elements = *(const WORD*)pFormat;
4364 pFormat += sizeof(WORD);
4366 else
4368 pFormat += 2;
4369 pFormat += sizeof(DWORD);
4370 elements = *(const DWORD*)pFormat;
4371 pFormat += sizeof(DWORD);
4374 pFormat += sizeof(WORD);
4376 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4377 if ((pStubMsg->ActualCount > elements) ||
4378 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4380 RpcRaiseException(RPC_S_INVALID_BOUND);
4381 return;
4384 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4387 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
4389 switch (fc)
4391 case RPC_FC_BYTE:
4392 case RPC_FC_CHAR:
4393 case RPC_FC_SMALL:
4394 case RPC_FC_USMALL:
4395 return *(const UCHAR *)pMemory;
4396 case RPC_FC_WCHAR:
4397 case RPC_FC_SHORT:
4398 case RPC_FC_USHORT:
4399 case RPC_FC_ENUM16:
4400 return *(const USHORT *)pMemory;
4401 case RPC_FC_LONG:
4402 case RPC_FC_ULONG:
4403 case RPC_FC_ENUM32:
4404 return *(const ULONG *)pMemory;
4405 default:
4406 FIXME("Unhandled base type: 0x%02x\n", fc);
4407 return 0;
4411 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
4412 unsigned long discriminant,
4413 PFORMAT_STRING pFormat)
4415 unsigned short num_arms, arm, type;
4417 num_arms = *(const SHORT*)pFormat & 0x0fff;
4418 pFormat += 2;
4419 for(arm = 0; arm < num_arms; arm++)
4421 if(discriminant == *(const ULONG*)pFormat)
4423 pFormat += 4;
4424 break;
4426 pFormat += 6;
4429 type = *(const unsigned short*)pFormat;
4430 TRACE("type %04x\n", type);
4431 if(arm == num_arms) /* default arm extras */
4433 if(type == 0xffff)
4435 ERR("no arm for 0x%lx and no default case\n", discriminant);
4436 RpcRaiseException(RPC_S_INVALID_TAG);
4437 return NULL;
4439 if(type == 0)
4441 TRACE("falling back to empty default case for 0x%lx\n", discriminant);
4442 return NULL;
4445 return pFormat;
4448 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
4450 unsigned short type;
4452 pFormat += 2;
4454 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4455 if(!pFormat)
4456 return NULL;
4458 type = *(const unsigned short*)pFormat;
4459 if((type & 0xff00) == 0x8000)
4461 unsigned char basetype = LOBYTE(type);
4462 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4464 else
4466 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4467 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4468 if (m)
4470 unsigned char *saved_buffer = NULL;
4471 int pointer_buffer_mark_set = 0;
4472 switch(*desc)
4474 case RPC_FC_RP:
4475 case RPC_FC_UP:
4476 case RPC_FC_OP:
4477 case RPC_FC_FP:
4478 ALIGN_POINTER(pStubMsg->Buffer, 4);
4479 saved_buffer = pStubMsg->Buffer;
4480 if (pStubMsg->PointerBufferMark)
4482 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4483 pStubMsg->PointerBufferMark = NULL;
4484 pointer_buffer_mark_set = 1;
4486 else
4487 pStubMsg->Buffer += 4; /* for pointer ID */
4489 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
4490 if (pointer_buffer_mark_set)
4492 STD_OVERFLOW_CHECK(pStubMsg);
4493 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4494 pStubMsg->Buffer = saved_buffer + 4;
4496 break;
4497 default:
4498 m(pStubMsg, pMemory, desc);
4501 else FIXME("no marshaller for embedded type %02x\n", *desc);
4503 return NULL;
4506 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4507 unsigned char **ppMemory,
4508 ULONG discriminant,
4509 PFORMAT_STRING pFormat,
4510 unsigned char fMustAlloc)
4512 unsigned short type;
4514 pFormat += 2;
4516 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4517 if(!pFormat)
4518 return NULL;
4520 type = *(const unsigned short*)pFormat;
4521 if((type & 0xff00) == 0x8000)
4523 unsigned char basetype = LOBYTE(type);
4524 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
4526 else
4528 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4529 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
4530 if (m)
4532 unsigned char *saved_buffer = NULL;
4533 int pointer_buffer_mark_set = 0;
4534 switch(*desc)
4536 case RPC_FC_RP:
4537 case RPC_FC_UP:
4538 case RPC_FC_OP:
4539 case RPC_FC_FP:
4540 **(void***)ppMemory = NULL;
4541 ALIGN_POINTER(pStubMsg->Buffer, 4);
4542 saved_buffer = pStubMsg->Buffer;
4543 if (pStubMsg->PointerBufferMark)
4545 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4546 pStubMsg->PointerBufferMark = NULL;
4547 pointer_buffer_mark_set = 1;
4549 else
4550 pStubMsg->Buffer += 4; /* for pointer ID */
4552 if (saved_buffer + 4 > pStubMsg->BufferEnd)
4553 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4555 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, fMustAlloc);
4556 if (pointer_buffer_mark_set)
4558 STD_OVERFLOW_CHECK(pStubMsg);
4559 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4560 pStubMsg->Buffer = saved_buffer + 4;
4562 break;
4563 default:
4564 m(pStubMsg, ppMemory, desc, fMustAlloc);
4567 else FIXME("no marshaller for embedded type %02x\n", *desc);
4569 return NULL;
4572 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
4573 unsigned char *pMemory,
4574 ULONG discriminant,
4575 PFORMAT_STRING pFormat)
4577 unsigned short type;
4579 pFormat += 2;
4581 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4582 if(!pFormat)
4583 return;
4585 type = *(const unsigned short*)pFormat;
4586 if((type & 0xff00) == 0x8000)
4588 unsigned char basetype = LOBYTE(type);
4589 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
4591 else
4593 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4594 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
4595 if (m)
4597 switch(*desc)
4599 case RPC_FC_RP:
4600 case RPC_FC_UP:
4601 case RPC_FC_OP:
4602 case RPC_FC_FP:
4603 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4604 pStubMsg->BufferLength += 4; /* for pointer ID */
4605 if (!pStubMsg->IgnoreEmbeddedPointers)
4607 int saved_buffer_length = pStubMsg->BufferLength;
4608 pStubMsg->BufferLength = pStubMsg->PointerLength;
4609 pStubMsg->PointerLength = 0;
4610 if(!pStubMsg->BufferLength)
4611 ERR("BufferLength == 0??\n");
4612 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
4613 pStubMsg->PointerLength = pStubMsg->BufferLength;
4614 pStubMsg->BufferLength = saved_buffer_length;
4616 break;
4617 default:
4618 m(pStubMsg, pMemory, desc);
4621 else FIXME("no buffersizer for embedded type %02x\n", *desc);
4625 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
4626 ULONG discriminant,
4627 PFORMAT_STRING pFormat)
4629 unsigned short type, size;
4631 size = *(const unsigned short*)pFormat;
4632 pStubMsg->Memory += size;
4633 pFormat += 2;
4635 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4636 if(!pFormat)
4637 return 0;
4639 type = *(const unsigned short*)pFormat;
4640 if((type & 0xff00) == 0x8000)
4642 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
4644 else
4646 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4647 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
4648 unsigned char *saved_buffer;
4649 if (m)
4651 switch(*desc)
4653 case RPC_FC_RP:
4654 case RPC_FC_UP:
4655 case RPC_FC_OP:
4656 case RPC_FC_FP:
4657 ALIGN_POINTER(pStubMsg->Buffer, 4);
4658 saved_buffer = pStubMsg->Buffer;
4659 pStubMsg->Buffer += 4;
4660 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
4661 pStubMsg->MemorySize += 4;
4662 if (!pStubMsg->IgnoreEmbeddedPointers)
4663 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
4664 break;
4665 default:
4666 return m(pStubMsg, desc);
4669 else FIXME("no marshaller for embedded type %02x\n", *desc);
4672 TRACE("size %d\n", size);
4673 return size;
4676 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
4677 unsigned char *pMemory,
4678 ULONG discriminant,
4679 PFORMAT_STRING pFormat)
4681 unsigned short type;
4683 pFormat += 2;
4685 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4686 if(!pFormat)
4687 return;
4689 type = *(const unsigned short*)pFormat;
4690 if((type & 0xff00) != 0x8000)
4692 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4693 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
4694 if (m)
4696 switch(*desc)
4698 case RPC_FC_RP:
4699 case RPC_FC_UP:
4700 case RPC_FC_OP:
4701 case RPC_FC_FP:
4702 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
4703 break;
4704 default:
4705 m(pStubMsg, pMemory, desc);
4708 else FIXME("no freer for embedded type %02x\n", *desc);
4712 /***********************************************************************
4713 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
4715 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4716 unsigned char *pMemory,
4717 PFORMAT_STRING pFormat)
4719 unsigned char switch_type;
4720 unsigned char increment;
4721 ULONG switch_value;
4723 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4724 pFormat++;
4726 switch_type = *pFormat & 0xf;
4727 increment = (*pFormat & 0xf0) >> 4;
4728 pFormat++;
4730 ALIGN_POINTER(pStubMsg->Buffer, increment);
4732 switch_value = get_discriminant(switch_type, pMemory);
4733 TRACE("got switch value 0x%x\n", switch_value);
4735 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
4736 pMemory += increment;
4738 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
4741 /***********************************************************************
4742 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
4744 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4745 unsigned char **ppMemory,
4746 PFORMAT_STRING pFormat,
4747 unsigned char fMustAlloc)
4749 unsigned char switch_type;
4750 unsigned char increment;
4751 ULONG switch_value;
4752 unsigned short size;
4753 unsigned char *pMemoryArm;
4755 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4756 pFormat++;
4758 switch_type = *pFormat & 0xf;
4759 increment = (*pFormat & 0xf0) >> 4;
4760 pFormat++;
4762 ALIGN_POINTER(pStubMsg->Buffer, increment);
4763 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
4764 TRACE("got switch value 0x%x\n", switch_value);
4766 size = *(const unsigned short*)pFormat + increment;
4767 if(!*ppMemory || fMustAlloc)
4768 *ppMemory = NdrAllocate(pStubMsg, size);
4770 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
4771 pMemoryArm = *ppMemory + increment;
4773 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
4776 /***********************************************************************
4777 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
4779 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4780 unsigned char *pMemory,
4781 PFORMAT_STRING pFormat)
4783 unsigned char switch_type;
4784 unsigned char increment;
4785 ULONG switch_value;
4787 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4788 pFormat++;
4790 switch_type = *pFormat & 0xf;
4791 increment = (*pFormat & 0xf0) >> 4;
4792 pFormat++;
4794 ALIGN_LENGTH(pStubMsg->BufferLength, increment);
4795 switch_value = get_discriminant(switch_type, pMemory);
4796 TRACE("got switch value 0x%x\n", switch_value);
4798 /* Add discriminant size */
4799 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
4800 pMemory += increment;
4802 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
4805 /***********************************************************************
4806 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
4808 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4809 PFORMAT_STRING pFormat)
4811 unsigned char switch_type;
4812 unsigned char increment;
4813 ULONG switch_value;
4815 switch_type = *pFormat & 0xf;
4816 increment = (*pFormat & 0xf0) >> 4;
4817 pFormat++;
4819 ALIGN_POINTER(pStubMsg->Buffer, increment);
4820 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
4821 TRACE("got switch value 0x%x\n", switch_value);
4823 pStubMsg->Memory += increment;
4825 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
4828 /***********************************************************************
4829 * NdrEncapsulatedUnionFree [RPCRT4.@]
4831 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
4832 unsigned char *pMemory,
4833 PFORMAT_STRING pFormat)
4835 unsigned char switch_type;
4836 unsigned char increment;
4837 ULONG switch_value;
4839 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4840 pFormat++;
4842 switch_type = *pFormat & 0xf;
4843 increment = (*pFormat & 0xf0) >> 4;
4844 pFormat++;
4846 switch_value = get_discriminant(switch_type, pMemory);
4847 TRACE("got switch value 0x%x\n", switch_value);
4849 pMemory += increment;
4851 return union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
4854 /***********************************************************************
4855 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
4857 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4858 unsigned char *pMemory,
4859 PFORMAT_STRING pFormat)
4861 unsigned char switch_type;
4863 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4864 pFormat++;
4866 switch_type = *pFormat;
4867 pFormat++;
4869 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4870 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4871 /* Marshall discriminant */
4872 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
4874 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
4877 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
4878 PFORMAT_STRING *ppFormat)
4880 long discriminant = 0;
4882 switch(**ppFormat)
4884 case RPC_FC_BYTE:
4885 case RPC_FC_CHAR:
4886 case RPC_FC_SMALL:
4887 case RPC_FC_USMALL:
4889 UCHAR d;
4890 safe_buffer_copy(pStubMsg, &d, sizeof(d));
4891 discriminant = d;
4892 break;
4894 case RPC_FC_WCHAR:
4895 case RPC_FC_SHORT:
4896 case RPC_FC_USHORT:
4898 USHORT d;
4899 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4900 safe_buffer_copy(pStubMsg, &d, sizeof(d));
4901 discriminant = d;
4902 break;
4904 case RPC_FC_LONG:
4905 case RPC_FC_ULONG:
4907 ULONG d;
4908 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4909 safe_buffer_copy(pStubMsg, &d, sizeof(d));
4910 discriminant = d;
4911 break;
4913 default:
4914 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
4916 (*ppFormat)++;
4918 if (pStubMsg->fHasNewCorrDesc)
4919 *ppFormat += 6;
4920 else
4921 *ppFormat += 4;
4922 return discriminant;
4925 /**********************************************************************
4926 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
4928 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4929 unsigned char **ppMemory,
4930 PFORMAT_STRING pFormat,
4931 unsigned char fMustAlloc)
4933 long discriminant;
4934 unsigned short size;
4936 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4937 pFormat++;
4939 /* Unmarshall discriminant */
4940 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
4941 TRACE("unmarshalled discriminant %lx\n", discriminant);
4943 pFormat += *(const SHORT*)pFormat;
4945 size = *(const unsigned short*)pFormat;
4947 if(!*ppMemory || fMustAlloc)
4948 *ppMemory = NdrAllocate(pStubMsg, size);
4950 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
4953 /***********************************************************************
4954 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
4956 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4957 unsigned char *pMemory,
4958 PFORMAT_STRING pFormat)
4960 unsigned char switch_type;
4962 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4963 pFormat++;
4965 switch_type = *pFormat;
4966 pFormat++;
4968 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
4969 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
4970 /* Add discriminant size */
4971 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
4973 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
4976 /***********************************************************************
4977 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
4979 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4980 PFORMAT_STRING pFormat)
4982 ULONG discriminant;
4984 pFormat++;
4985 /* Unmarshall discriminant */
4986 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
4987 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
4989 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
4992 /***********************************************************************
4993 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
4995 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
4996 unsigned char *pMemory,
4997 PFORMAT_STRING pFormat)
4999 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5000 pFormat++;
5001 pFormat++;
5003 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5004 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5006 return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5009 /***********************************************************************
5010 * NdrByteCountPointerMarshall [RPCRT4.@]
5012 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5013 unsigned char *pMemory,
5014 PFORMAT_STRING pFormat)
5016 FIXME("stub\n");
5017 return NULL;
5020 /***********************************************************************
5021 * NdrByteCountPointerUnmarshall [RPCRT4.@]
5023 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5024 unsigned char **ppMemory,
5025 PFORMAT_STRING pFormat,
5026 unsigned char fMustAlloc)
5028 FIXME("stub\n");
5029 return NULL;
5032 /***********************************************************************
5033 * NdrByteCountPointerBufferSize [RPCRT4.@]
5035 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5036 unsigned char *pMemory,
5037 PFORMAT_STRING pFormat)
5039 FIXME("stub\n");
5042 /***********************************************************************
5043 * NdrByteCountPointerMemorySize [RPCRT4.@]
5045 ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5046 PFORMAT_STRING pFormat)
5048 FIXME("stub\n");
5049 return 0;
5052 /***********************************************************************
5053 * NdrByteCountPointerFree [RPCRT4.@]
5055 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
5056 unsigned char *pMemory,
5057 PFORMAT_STRING pFormat)
5059 FIXME("stub\n");
5062 /***********************************************************************
5063 * NdrXmitOrRepAsMarshall [RPCRT4.@]
5065 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5066 unsigned char *pMemory,
5067 PFORMAT_STRING pFormat)
5069 FIXME("stub\n");
5070 return NULL;
5073 /***********************************************************************
5074 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
5076 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5077 unsigned char **ppMemory,
5078 PFORMAT_STRING pFormat,
5079 unsigned char fMustAlloc)
5081 FIXME("stub\n");
5082 return NULL;
5085 /***********************************************************************
5086 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
5088 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5089 unsigned char *pMemory,
5090 PFORMAT_STRING pFormat)
5092 FIXME("stub\n");
5095 /***********************************************************************
5096 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
5098 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5099 PFORMAT_STRING pFormat)
5101 FIXME("stub\n");
5102 return 0;
5105 /***********************************************************************
5106 * NdrXmitOrRepAsFree [RPCRT4.@]
5108 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
5109 unsigned char *pMemory,
5110 PFORMAT_STRING pFormat)
5112 FIXME("stub\n");
5115 #include "pshpack1.h"
5116 typedef struct
5118 unsigned char type;
5119 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
5120 ULONG low_value;
5121 ULONG high_value;
5122 } NDR_RANGE;
5123 #include "poppack.h"
5125 /***********************************************************************
5126 * NdrRangeMarshall [internal]
5128 unsigned char *WINAPI NdrRangeMarshall(
5129 PMIDL_STUB_MESSAGE pStubMsg,
5130 unsigned char *pMemory,
5131 PFORMAT_STRING pFormat)
5133 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5134 unsigned char base_type;
5136 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5138 if (pRange->type != RPC_FC_RANGE)
5140 ERR("invalid format type %x\n", pRange->type);
5141 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5142 return NULL;
5145 base_type = pRange->flags_type & 0xf;
5147 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
5150 /***********************************************************************
5151 * NdrRangeUnmarshall
5153 unsigned char *WINAPI NdrRangeUnmarshall(
5154 PMIDL_STUB_MESSAGE pStubMsg,
5155 unsigned char **ppMemory,
5156 PFORMAT_STRING pFormat,
5157 unsigned char fMustAlloc)
5159 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5160 unsigned char base_type;
5162 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5164 if (pRange->type != RPC_FC_RANGE)
5166 ERR("invalid format type %x\n", pRange->type);
5167 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5168 return NULL;
5170 base_type = pRange->flags_type & 0xf;
5172 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
5173 base_type, pRange->low_value, pRange->high_value);
5175 #define RANGE_UNMARSHALL(type, format_spec) \
5176 do \
5178 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5179 if (fMustAlloc || !*ppMemory) \
5180 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5181 if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \
5182 (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \
5184 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
5185 *(type *)pStubMsg->Buffer, (type)pRange->low_value, \
5186 (type)pRange->high_value); \
5187 RpcRaiseException(RPC_S_INVALID_BOUND); \
5188 return NULL; \
5190 TRACE("*ppMemory: %p\n", *ppMemory); \
5191 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5192 pStubMsg->Buffer += sizeof(type); \
5193 } while (0)
5195 switch(base_type)
5197 case RPC_FC_CHAR:
5198 case RPC_FC_SMALL:
5199 RANGE_UNMARSHALL(UCHAR, "%d");
5200 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5201 break;
5202 case RPC_FC_BYTE:
5203 case RPC_FC_USMALL:
5204 RANGE_UNMARSHALL(CHAR, "%u");
5205 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5206 break;
5207 case RPC_FC_WCHAR: /* FIXME: valid? */
5208 case RPC_FC_USHORT:
5209 RANGE_UNMARSHALL(USHORT, "%u");
5210 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5211 break;
5212 case RPC_FC_SHORT:
5213 RANGE_UNMARSHALL(SHORT, "%d");
5214 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5215 break;
5216 case RPC_FC_LONG:
5217 RANGE_UNMARSHALL(LONG, "%d");
5218 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5219 break;
5220 case RPC_FC_ULONG:
5221 RANGE_UNMARSHALL(ULONG, "%u");
5222 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5223 break;
5224 case RPC_FC_ENUM16:
5225 case RPC_FC_ENUM32:
5226 FIXME("Unhandled enum type\n");
5227 break;
5228 case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */
5229 case RPC_FC_FLOAT:
5230 case RPC_FC_DOUBLE:
5231 case RPC_FC_HYPER:
5232 default:
5233 ERR("invalid range base type: 0x%02x\n", base_type);
5234 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5237 return NULL;
5240 /***********************************************************************
5241 * NdrRangeBufferSize [internal]
5243 void WINAPI NdrRangeBufferSize(
5244 PMIDL_STUB_MESSAGE pStubMsg,
5245 unsigned char *pMemory,
5246 PFORMAT_STRING pFormat)
5248 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5249 unsigned char base_type;
5251 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5253 if (pRange->type != RPC_FC_RANGE)
5255 ERR("invalid format type %x\n", pRange->type);
5256 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5258 base_type = pRange->flags_type & 0xf;
5260 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
5263 /***********************************************************************
5264 * NdrRangeMemorySize [internal]
5266 ULONG WINAPI NdrRangeMemorySize(
5267 PMIDL_STUB_MESSAGE pStubMsg,
5268 PFORMAT_STRING pFormat)
5270 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5271 unsigned char base_type;
5273 if (pRange->type != RPC_FC_RANGE)
5275 ERR("invalid format type %x\n", pRange->type);
5276 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5277 return 0;
5279 base_type = pRange->flags_type & 0xf;
5281 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
5284 /***********************************************************************
5285 * NdrRangeFree [internal]
5287 void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
5288 unsigned char *pMemory,
5289 PFORMAT_STRING pFormat)
5291 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5293 /* nothing to do */
5296 /***********************************************************************
5297 * NdrBaseTypeMarshall [internal]
5299 static unsigned char *WINAPI NdrBaseTypeMarshall(
5300 PMIDL_STUB_MESSAGE pStubMsg,
5301 unsigned char *pMemory,
5302 PFORMAT_STRING pFormat)
5304 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5306 switch(*pFormat)
5308 case RPC_FC_BYTE:
5309 case RPC_FC_CHAR:
5310 case RPC_FC_SMALL:
5311 case RPC_FC_USMALL:
5312 *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory;
5313 pStubMsg->Buffer += sizeof(UCHAR);
5314 TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
5315 break;
5316 case RPC_FC_WCHAR:
5317 case RPC_FC_SHORT:
5318 case RPC_FC_USHORT:
5319 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5320 *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory;
5321 pStubMsg->Buffer += sizeof(USHORT);
5322 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
5323 break;
5324 case RPC_FC_LONG:
5325 case RPC_FC_ULONG:
5326 case RPC_FC_ERROR_STATUS_T:
5327 case RPC_FC_ENUM32:
5328 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5329 *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory;
5330 pStubMsg->Buffer += sizeof(ULONG);
5331 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
5332 break;
5333 case RPC_FC_FLOAT:
5334 ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
5335 *(float *)pStubMsg->Buffer = *(float *)pMemory;
5336 pStubMsg->Buffer += sizeof(float);
5337 break;
5338 case RPC_FC_DOUBLE:
5339 ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
5340 *(double *)pStubMsg->Buffer = *(double *)pMemory;
5341 pStubMsg->Buffer += sizeof(double);
5342 break;
5343 case RPC_FC_HYPER:
5344 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
5345 *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory;
5346 pStubMsg->Buffer += sizeof(ULONGLONG);
5347 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
5348 break;
5349 case RPC_FC_ENUM16:
5350 /* only 16-bits on the wire, so do a sanity check */
5351 if (*(UINT *)pMemory > SHRT_MAX)
5352 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
5353 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5354 *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
5355 pStubMsg->Buffer += sizeof(USHORT);
5356 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
5357 break;
5358 case RPC_FC_IGNORE:
5359 break;
5360 default:
5361 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5364 STD_OVERFLOW_CHECK(pStubMsg);
5366 /* FIXME: what is the correct return value? */
5367 return NULL;
5370 /***********************************************************************
5371 * NdrBaseTypeUnmarshall [internal]
5373 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
5374 PMIDL_STUB_MESSAGE pStubMsg,
5375 unsigned char **ppMemory,
5376 PFORMAT_STRING pFormat,
5377 unsigned char fMustAlloc)
5379 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5381 #define BASE_TYPE_UNMARSHALL(type) \
5382 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5383 if (fMustAlloc || !*ppMemory) \
5384 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5385 TRACE("*ppMemory: %p\n", *ppMemory); \
5386 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5387 pStubMsg->Buffer += sizeof(type);
5389 switch(*pFormat)
5391 case RPC_FC_BYTE:
5392 case RPC_FC_CHAR:
5393 case RPC_FC_SMALL:
5394 case RPC_FC_USMALL:
5395 BASE_TYPE_UNMARSHALL(UCHAR);
5396 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5397 break;
5398 case RPC_FC_WCHAR:
5399 case RPC_FC_SHORT:
5400 case RPC_FC_USHORT:
5401 BASE_TYPE_UNMARSHALL(USHORT);
5402 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5403 break;
5404 case RPC_FC_LONG:
5405 case RPC_FC_ULONG:
5406 case RPC_FC_ERROR_STATUS_T:
5407 case RPC_FC_ENUM32:
5408 BASE_TYPE_UNMARSHALL(ULONG);
5409 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5410 break;
5411 case RPC_FC_FLOAT:
5412 BASE_TYPE_UNMARSHALL(float);
5413 TRACE("value: %f\n", **(float **)ppMemory);
5414 break;
5415 case RPC_FC_DOUBLE:
5416 BASE_TYPE_UNMARSHALL(double);
5417 TRACE("value: %f\n", **(double **)ppMemory);
5418 break;
5419 case RPC_FC_HYPER:
5420 BASE_TYPE_UNMARSHALL(ULONGLONG);
5421 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
5422 break;
5423 case RPC_FC_ENUM16:
5424 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5425 if (fMustAlloc || !*ppMemory)
5426 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
5427 TRACE("*ppMemory: %p\n", *ppMemory);
5428 /* 16-bits on the wire, but int in memory */
5429 **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
5430 pStubMsg->Buffer += sizeof(USHORT);
5431 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
5432 break;
5433 case RPC_FC_IGNORE:
5434 break;
5435 default:
5436 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5438 #undef BASE_TYPE_UNMARSHALL
5440 /* FIXME: what is the correct return value? */
5442 return NULL;
5445 /***********************************************************************
5446 * NdrBaseTypeBufferSize [internal]
5448 static void WINAPI NdrBaseTypeBufferSize(
5449 PMIDL_STUB_MESSAGE pStubMsg,
5450 unsigned char *pMemory,
5451 PFORMAT_STRING pFormat)
5453 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5455 switch(*pFormat)
5457 case RPC_FC_BYTE:
5458 case RPC_FC_CHAR:
5459 case RPC_FC_SMALL:
5460 case RPC_FC_USMALL:
5461 pStubMsg->BufferLength += sizeof(UCHAR);
5462 break;
5463 case RPC_FC_WCHAR:
5464 case RPC_FC_SHORT:
5465 case RPC_FC_USHORT:
5466 case RPC_FC_ENUM16:
5467 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
5468 pStubMsg->BufferLength += sizeof(USHORT);
5469 break;
5470 case RPC_FC_LONG:
5471 case RPC_FC_ULONG:
5472 case RPC_FC_ENUM32:
5473 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
5474 pStubMsg->BufferLength += sizeof(ULONG);
5475 break;
5476 case RPC_FC_FLOAT:
5477 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
5478 pStubMsg->BufferLength += sizeof(float);
5479 break;
5480 case RPC_FC_DOUBLE:
5481 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
5482 pStubMsg->BufferLength += sizeof(double);
5483 break;
5484 case RPC_FC_HYPER:
5485 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
5486 pStubMsg->BufferLength += sizeof(ULONGLONG);
5487 break;
5488 case RPC_FC_ERROR_STATUS_T:
5489 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
5490 pStubMsg->BufferLength += sizeof(error_status_t);
5491 break;
5492 case RPC_FC_IGNORE:
5493 break;
5494 default:
5495 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5499 /***********************************************************************
5500 * NdrBaseTypeMemorySize [internal]
5502 static ULONG WINAPI NdrBaseTypeMemorySize(
5503 PMIDL_STUB_MESSAGE pStubMsg,
5504 PFORMAT_STRING pFormat)
5506 switch(*pFormat)
5508 case RPC_FC_BYTE:
5509 case RPC_FC_CHAR:
5510 case RPC_FC_SMALL:
5511 case RPC_FC_USMALL:
5512 pStubMsg->Buffer += sizeof(UCHAR);
5513 pStubMsg->MemorySize += sizeof(UCHAR);
5514 return sizeof(UCHAR);
5515 case RPC_FC_WCHAR:
5516 case RPC_FC_SHORT:
5517 case RPC_FC_USHORT:
5518 pStubMsg->Buffer += sizeof(USHORT);
5519 pStubMsg->MemorySize += sizeof(USHORT);
5520 return sizeof(USHORT);
5521 case RPC_FC_LONG:
5522 case RPC_FC_ULONG:
5523 pStubMsg->Buffer += sizeof(ULONG);
5524 pStubMsg->MemorySize += sizeof(ULONG);
5525 return sizeof(ULONG);
5526 case RPC_FC_FLOAT:
5527 pStubMsg->Buffer += sizeof(float);
5528 pStubMsg->MemorySize += sizeof(float);
5529 return sizeof(float);
5530 case RPC_FC_DOUBLE:
5531 pStubMsg->Buffer += sizeof(double);
5532 pStubMsg->MemorySize += sizeof(double);
5533 return sizeof(double);
5534 case RPC_FC_HYPER:
5535 pStubMsg->Buffer += sizeof(ULONGLONG);
5536 pStubMsg->MemorySize += sizeof(ULONGLONG);
5537 return sizeof(ULONGLONG);
5538 case RPC_FC_ERROR_STATUS_T:
5539 pStubMsg->Buffer += sizeof(error_status_t);
5540 pStubMsg->MemorySize += sizeof(error_status_t);
5541 return sizeof(error_status_t);
5542 case RPC_FC_ENUM16:
5543 case RPC_FC_ENUM32:
5544 pStubMsg->Buffer += sizeof(INT);
5545 pStubMsg->MemorySize += sizeof(INT);
5546 return sizeof(INT);
5547 case RPC_FC_IGNORE:
5548 pStubMsg->MemorySize += sizeof(void *);
5549 return sizeof(void *);
5550 default:
5551 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5552 return 0;
5556 /***********************************************************************
5557 * NdrBaseTypeFree [internal]
5559 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
5560 unsigned char *pMemory,
5561 PFORMAT_STRING pFormat)
5563 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5565 /* nothing to do */
5568 /***********************************************************************
5569 * NdrContextHandleBufferSize [internal]
5571 static void WINAPI NdrContextHandleBufferSize(
5572 PMIDL_STUB_MESSAGE pStubMsg,
5573 unsigned char *pMemory,
5574 PFORMAT_STRING pFormat)
5576 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5578 if (*pFormat != RPC_FC_BIND_CONTEXT)
5580 ERR("invalid format type %x\n", *pFormat);
5581 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5583 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5584 pStubMsg->BufferLength += cbNDRContext;
5587 /***********************************************************************
5588 * NdrContextHandleMarshall [internal]
5590 static unsigned char *WINAPI NdrContextHandleMarshall(
5591 PMIDL_STUB_MESSAGE pStubMsg,
5592 unsigned char *pMemory,
5593 PFORMAT_STRING pFormat)
5595 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5597 if (*pFormat != RPC_FC_BIND_CONTEXT)
5599 ERR("invalid format type %x\n", *pFormat);
5600 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5603 if (pFormat[1] & 0x80)
5604 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
5605 else
5606 NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE);
5608 return NULL;
5611 /***********************************************************************
5612 * NdrContextHandleUnmarshall [internal]
5614 static unsigned char *WINAPI NdrContextHandleUnmarshall(
5615 PMIDL_STUB_MESSAGE pStubMsg,
5616 unsigned char **ppMemory,
5617 PFORMAT_STRING pFormat,
5618 unsigned char fMustAlloc)
5620 if (*pFormat != RPC_FC_BIND_CONTEXT)
5622 ERR("invalid format type %x\n", *pFormat);
5623 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5626 **(NDR_CCONTEXT **)ppMemory = NULL;
5627 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
5629 return NULL;
5632 /***********************************************************************
5633 * NdrClientContextMarshall [RPCRT4.@]
5635 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5636 NDR_CCONTEXT ContextHandle,
5637 int fCheck)
5639 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
5641 ALIGN_POINTER(pStubMsg->Buffer, 4);
5643 /* FIXME: what does fCheck do? */
5644 NDRCContextMarshall(ContextHandle,
5645 pStubMsg->Buffer);
5647 pStubMsg->Buffer += cbNDRContext;
5650 /***********************************************************************
5651 * NdrClientContextUnmarshall [RPCRT4.@]
5653 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5654 NDR_CCONTEXT * pContextHandle,
5655 RPC_BINDING_HANDLE BindHandle)
5657 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
5659 ALIGN_POINTER(pStubMsg->Buffer, 4);
5661 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
5662 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5664 NDRCContextUnmarshall(pContextHandle,
5665 BindHandle,
5666 pStubMsg->Buffer,
5667 pStubMsg->RpcMsg->DataRepresentation);
5669 pStubMsg->Buffer += cbNDRContext;
5672 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5673 NDR_SCONTEXT ContextHandle,
5674 NDR_RUNDOWN RundownRoutine )
5676 FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
5679 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
5681 FIXME("(%p): stub\n", pStubMsg);
5682 return NULL;
5685 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
5686 unsigned char* pMemory,
5687 PFORMAT_STRING pFormat)
5689 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
5692 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
5693 PFORMAT_STRING pFormat)
5695 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5696 return NULL;
5699 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5700 NDR_SCONTEXT ContextHandle,
5701 NDR_RUNDOWN RundownRoutine,
5702 PFORMAT_STRING pFormat)
5704 FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
5707 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5708 PFORMAT_STRING pFormat)
5710 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5711 return NULL;
5714 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e
5716 typedef struct ndr_context_handle
5718 DWORD attributes;
5719 GUID uuid;
5720 } ndr_context_handle;
5722 struct context_handle_entry
5724 struct list entry;
5725 DWORD magic;
5726 RPC_BINDING_HANDLE handle;
5727 ndr_context_handle wire_data;
5730 static struct list context_handle_list = LIST_INIT(context_handle_list);
5732 static CRITICAL_SECTION ndr_context_cs;
5733 static CRITICAL_SECTION_DEBUG ndr_context_debug =
5735 0, 0, &ndr_context_cs,
5736 { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList },
5737 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") }
5739 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 };
5741 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
5743 struct context_handle_entry *che = (struct context_handle_entry*) CContext;
5745 if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
5746 return NULL;
5747 return che;
5750 static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid)
5752 struct context_handle_entry *che;
5753 LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry)
5754 if (IsEqualGUID(&che->wire_data.uuid, uuid))
5755 return che;
5756 return NULL;
5759 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
5761 struct context_handle_entry *che;
5762 RPC_BINDING_HANDLE handle = NULL;
5764 TRACE("%p\n", CContext);
5766 EnterCriticalSection(&ndr_context_cs);
5767 che = get_context_entry(CContext);
5768 if (che)
5769 handle = che->handle;
5770 LeaveCriticalSection(&ndr_context_cs);
5772 if (!handle)
5773 RpcRaiseException(ERROR_INVALID_HANDLE);
5774 return handle;
5777 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
5779 struct context_handle_entry *che;
5781 TRACE("%p %p\n", CContext, pBuff);
5783 if (CContext)
5785 EnterCriticalSection(&ndr_context_cs);
5786 che = get_context_entry(CContext);
5787 memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle));
5788 LeaveCriticalSection(&ndr_context_cs);
5790 else
5792 ndr_context_handle *wire_data = (ndr_context_handle *)pBuff;
5793 wire_data->attributes = 0;
5794 wire_data->uuid = GUID_NULL;
5798 /***********************************************************************
5799 * RpcSmDestroyClientContext [RPCRT4.@]
5801 RPC_STATUS WINAPI RpcSmDestroyClientContext(void **ContextHandle)
5803 RPC_STATUS status = RPC_X_SS_CONTEXT_MISMATCH;
5804 struct context_handle_entry *che = NULL;
5806 TRACE("(%p)\n", ContextHandle);
5808 EnterCriticalSection(&ndr_context_cs);
5809 che = get_context_entry(*ContextHandle);
5810 *ContextHandle = NULL;
5811 if (che)
5813 status = RPC_S_OK;
5814 list_remove(&che->entry);
5817 LeaveCriticalSection(&ndr_context_cs);
5819 if (che)
5821 RpcBindingFree(&che->handle);
5822 HeapFree(GetProcessHeap(), 0, che);
5825 return status;
5828 /***********************************************************************
5829 * RpcSsDestroyClientContext [RPCRT4.@]
5831 void WINAPI RpcSsDestroyClientContext(void **ContextHandle)
5833 RPC_STATUS status = RpcSmDestroyClientContext(ContextHandle);
5834 if (status != RPC_S_OK)
5835 RpcRaiseException(status);
5838 static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext,
5839 RPC_BINDING_HANDLE hBinding,
5840 const ndr_context_handle *chi)
5842 struct context_handle_entry *che = NULL;
5844 /* a null UUID means we should free the context handle */
5845 if (IsEqualGUID(&chi->uuid, &GUID_NULL))
5847 if (*CContext)
5849 che = get_context_entry(*CContext);
5850 if (!che)
5851 return ERROR_INVALID_HANDLE;
5852 list_remove(&che->entry);
5853 RpcBindingFree(&che->handle);
5854 HeapFree(GetProcessHeap(), 0, che);
5855 che = NULL;
5858 /* if there's no existing entry matching the GUID, allocate one */
5859 else if (!(che = context_entry_from_guid(&chi->uuid)))
5861 che = HeapAlloc(GetProcessHeap(), 0, sizeof *che);
5862 if (!che)
5863 return ERROR_NOT_ENOUGH_MEMORY;
5864 che->magic = NDR_CONTEXT_HANDLE_MAGIC;
5865 RpcBindingCopy(hBinding, &che->handle);
5866 list_add_tail(&context_handle_list, &che->entry);
5867 memcpy(&che->wire_data, chi, sizeof *chi);
5870 *CContext = che;
5872 return ERROR_SUCCESS;
5875 /***********************************************************************
5876 * NDRCContextUnmarshall [RPCRT4.@]
5878 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext,
5879 RPC_BINDING_HANDLE hBinding,
5880 void *pBuff, ULONG DataRepresentation)
5882 UINT r;
5884 TRACE("*%p=(%p) %p %p %08x\n",
5885 CContext, *CContext, hBinding, pBuff, DataRepresentation);
5887 EnterCriticalSection(&ndr_context_cs);
5888 r = ndr_update_context_handle(CContext, hBinding, pBuff);
5889 LeaveCriticalSection(&ndr_context_cs);
5890 if (r)
5891 RpcRaiseException(r);
5894 /***********************************************************************
5895 * NDRSContextMarshall [RPCRT4.@]
5897 void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext,
5898 void *pBuff,
5899 NDR_RUNDOWN userRunDownIn)
5901 FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn);
5904 /***********************************************************************
5905 * NDRSContextMarshallEx [RPCRT4.@]
5907 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding,
5908 NDR_SCONTEXT CContext,
5909 void *pBuff,
5910 NDR_RUNDOWN userRunDownIn)
5912 FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn);
5915 /***********************************************************************
5916 * NDRSContextMarshall2 [RPCRT4.@]
5918 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
5919 NDR_SCONTEXT CContext,
5920 void *pBuff,
5921 NDR_RUNDOWN userRunDownIn,
5922 void *CtxGuard, ULONG Flags)
5924 FIXME("(%p %p %p %p %p %u): stub\n",
5925 hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags);
5928 /***********************************************************************
5929 * NDRSContextUnmarshall [RPCRT4.@]
5931 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff,
5932 ULONG DataRepresentation)
5934 FIXME("(%p %08x): stub\n", pBuff, DataRepresentation);
5935 return NULL;
5938 /***********************************************************************
5939 * NDRSContextUnmarshallEx [RPCRT4.@]
5941 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding,
5942 void *pBuff,
5943 ULONG DataRepresentation)
5945 FIXME("(%p %p %08x): stub\n", hBinding, pBuff, DataRepresentation);
5946 return NULL;
5949 /***********************************************************************
5950 * NDRSContextUnmarshall2 [RPCRT4.@]
5952 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
5953 void *pBuff,
5954 ULONG DataRepresentation,
5955 void *CtxGuard, ULONG Flags)
5957 FIXME("(%p %p %08x %p %u): stub\n",
5958 hBinding, pBuff, DataRepresentation, CtxGuard, Flags);
5959 return NULL;