msvcrt: Remove strange condition which might lead to crash.
[wine/wine64.git] / dlls / rpcrt4 / ndr_marshall.c
blob8d358cfdc81aa4ac4ea2f5f6f333b214efc6beed
1 /*
2 * NDR data marshalling
4 * Copyright 2002 Greg Turner
5 * Copyright 2003-2006 CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * TODO:
22 * - String structs
23 * - Byte count pointers
24 * - transmit_as/represent as
25 * - Multi-dimensional arrays
26 * - Conversion functions (NdrConvert)
27 * - Checks for integer addition overflow in base type and user marshall functions
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <limits.h>
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winerror.h"
40 #include "ndr_misc.h"
41 #include "rpcndr.h"
43 #include "wine/unicode.h"
44 #include "wine/rpcfc.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(ole);
50 #if defined(__i386__)
51 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
52 (*((UINT32 *)(pchar)) = (uint32))
54 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
55 (*((UINT32 *)(pchar)))
56 #else
57 /* these would work for i386 too, but less efficient */
58 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
59 (*(pchar) = LOBYTE(LOWORD(uint32)), \
60 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
61 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
62 *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
63 (uint32)) /* allow as r-value */
65 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
66 (MAKELONG( \
67 MAKEWORD(*(pchar), *((pchar)+1)), \
68 MAKEWORD(*((pchar)+2), *((pchar)+3))))
69 #endif
71 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
72 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
73 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
74 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
75 *(pchar) = HIBYTE(HIWORD(uint32)), \
76 (uint32)) /* allow as r-value */
78 #define BIG_ENDIAN_UINT32_READ(pchar) \
79 (MAKELONG( \
80 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
81 MAKEWORD(*((pchar)+1), *(pchar))))
83 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
84 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
85 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
86 # define NDR_LOCAL_UINT32_READ(pchar) \
87 BIG_ENDIAN_UINT32_READ(pchar)
88 #else
89 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
90 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
91 # define NDR_LOCAL_UINT32_READ(pchar) \
92 LITTLE_ENDIAN_UINT32_READ(pchar)
93 #endif
95 /* _Align must be the desired alignment,
96 * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
97 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
98 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
99 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
100 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
101 #define ALIGN_POINTER_CLEAR(_Ptr, _Align) \
102 do { \
103 memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \
104 ALIGN_POINTER(_Ptr, _Align); \
105 } while(0)
107 #define STD_OVERFLOW_CHECK(_Msg) do { \
108 TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
109 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
110 ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
111 } while (0)
113 #define NDR_TABLE_SIZE 128
114 #define NDR_TABLE_MASK 127
116 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
117 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
118 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
119 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
120 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
122 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
123 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
124 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
126 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
128 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
129 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
130 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
131 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
132 /* 0x10 */
133 NdrBaseTypeMarshall,
134 /* 0x11 */
135 NdrPointerMarshall, NdrPointerMarshall,
136 NdrPointerMarshall, NdrPointerMarshall,
137 /* 0x15 */
138 NdrSimpleStructMarshall, NdrSimpleStructMarshall,
139 NdrConformantStructMarshall, NdrConformantStructMarshall,
140 NdrConformantVaryingStructMarshall,
141 NdrComplexStructMarshall,
142 /* 0x1b */
143 NdrConformantArrayMarshall,
144 NdrConformantVaryingArrayMarshall,
145 NdrFixedArrayMarshall, NdrFixedArrayMarshall,
146 NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
147 NdrComplexArrayMarshall,
148 /* 0x22 */
149 NdrConformantStringMarshall, 0, 0,
150 NdrConformantStringMarshall,
151 NdrNonConformantStringMarshall, 0, 0, 0,
152 /* 0x2a */
153 NdrEncapsulatedUnionMarshall,
154 NdrNonEncapsulatedUnionMarshall,
155 NdrByteCountPointerMarshall,
156 NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
157 /* 0x2f */
158 NdrInterfacePointerMarshall,
159 /* 0x30 */
160 NdrContextHandleMarshall,
161 /* 0xb1 */
162 0, 0, 0,
163 NdrUserMarshalMarshall,
164 0, 0,
165 /* 0xb7 */
166 NdrRangeMarshall
168 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
170 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
171 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
172 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
173 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
174 /* 0x10 */
175 NdrBaseTypeUnmarshall,
176 /* 0x11 */
177 NdrPointerUnmarshall, NdrPointerUnmarshall,
178 NdrPointerUnmarshall, NdrPointerUnmarshall,
179 /* 0x15 */
180 NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
181 NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
182 NdrConformantVaryingStructUnmarshall,
183 NdrComplexStructUnmarshall,
184 /* 0x1b */
185 NdrConformantArrayUnmarshall,
186 NdrConformantVaryingArrayUnmarshall,
187 NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
188 NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
189 NdrComplexArrayUnmarshall,
190 /* 0x22 */
191 NdrConformantStringUnmarshall, 0, 0,
192 NdrConformantStringUnmarshall,
193 NdrNonConformantStringUnmarshall, 0, 0, 0,
194 /* 0x2a */
195 NdrEncapsulatedUnionUnmarshall,
196 NdrNonEncapsulatedUnionUnmarshall,
197 NdrByteCountPointerUnmarshall,
198 NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
199 /* 0x2f */
200 NdrInterfacePointerUnmarshall,
201 /* 0x30 */
202 NdrContextHandleUnmarshall,
203 /* 0xb1 */
204 0, 0, 0,
205 NdrUserMarshalUnmarshall,
206 0, 0,
207 /* 0xb7 */
208 NdrRangeUnmarshall
210 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
212 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
213 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
214 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
215 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
216 /* 0x10 */
217 NdrBaseTypeBufferSize,
218 /* 0x11 */
219 NdrPointerBufferSize, NdrPointerBufferSize,
220 NdrPointerBufferSize, NdrPointerBufferSize,
221 /* 0x15 */
222 NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
223 NdrConformantStructBufferSize, NdrConformantStructBufferSize,
224 NdrConformantVaryingStructBufferSize,
225 NdrComplexStructBufferSize,
226 /* 0x1b */
227 NdrConformantArrayBufferSize,
228 NdrConformantVaryingArrayBufferSize,
229 NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
230 NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
231 NdrComplexArrayBufferSize,
232 /* 0x22 */
233 NdrConformantStringBufferSize, 0, 0,
234 NdrConformantStringBufferSize,
235 NdrNonConformantStringBufferSize, 0, 0, 0,
236 /* 0x2a */
237 NdrEncapsulatedUnionBufferSize,
238 NdrNonEncapsulatedUnionBufferSize,
239 NdrByteCountPointerBufferSize,
240 NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
241 /* 0x2f */
242 NdrInterfacePointerBufferSize,
243 /* 0x30 */
244 NdrContextHandleBufferSize,
245 /* 0xb1 */
246 0, 0, 0,
247 NdrUserMarshalBufferSize,
248 0, 0,
249 /* 0xb7 */
250 NdrRangeBufferSize
252 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
254 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
255 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
256 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
257 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
258 /* 0x10 */
259 NdrBaseTypeMemorySize,
260 /* 0x11 */
261 NdrPointerMemorySize, NdrPointerMemorySize,
262 NdrPointerMemorySize, NdrPointerMemorySize,
263 /* 0x15 */
264 NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
265 NdrConformantStructMemorySize, NdrConformantStructMemorySize,
266 NdrConformantVaryingStructMemorySize,
267 NdrComplexStructMemorySize,
268 /* 0x1b */
269 NdrConformantArrayMemorySize,
270 NdrConformantVaryingArrayMemorySize,
271 NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
272 NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
273 NdrComplexArrayMemorySize,
274 /* 0x22 */
275 NdrConformantStringMemorySize, 0, 0,
276 NdrConformantStringMemorySize,
277 NdrNonConformantStringMemorySize, 0, 0, 0,
278 /* 0x2a */
279 NdrEncapsulatedUnionMemorySize,
280 NdrNonEncapsulatedUnionMemorySize,
281 NdrByteCountPointerMemorySize,
282 NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
283 /* 0x2f */
284 NdrInterfacePointerMemorySize,
285 /* 0x30 */
287 /* 0xb1 */
288 0, 0, 0,
289 NdrUserMarshalMemorySize,
290 0, 0,
291 /* 0xb7 */
292 NdrRangeMemorySize
294 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
296 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
297 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
298 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
299 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
300 /* 0x10 */
301 NdrBaseTypeFree,
302 /* 0x11 */
303 NdrPointerFree, NdrPointerFree,
304 NdrPointerFree, NdrPointerFree,
305 /* 0x15 */
306 NdrSimpleStructFree, NdrSimpleStructFree,
307 NdrConformantStructFree, NdrConformantStructFree,
308 NdrConformantVaryingStructFree,
309 NdrComplexStructFree,
310 /* 0x1b */
311 NdrConformantArrayFree,
312 NdrConformantVaryingArrayFree,
313 NdrFixedArrayFree, NdrFixedArrayFree,
314 NdrVaryingArrayFree, NdrVaryingArrayFree,
315 NdrComplexArrayFree,
316 /* 0x22 */
317 0, 0, 0,
318 0, 0, 0, 0, 0,
319 /* 0x2a */
320 NdrEncapsulatedUnionFree,
321 NdrNonEncapsulatedUnionFree,
323 NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
324 /* 0x2f */
325 NdrInterfacePointerFree,
326 /* 0x30 */
328 /* 0xb1 */
329 0, 0, 0,
330 NdrUserMarshalFree,
331 0, 0,
332 /* 0xb7 */
333 NdrRangeFree
336 typedef struct _NDR_MEMORY_LIST
338 ULONG magic;
339 ULONG size;
340 ULONG reserved;
341 struct _NDR_MEMORY_LIST *next;
342 } NDR_MEMORY_LIST;
344 #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
346 /***********************************************************************
347 * NdrAllocate [RPCRT4.@]
349 * Allocates a block of memory using pStubMsg->pfnAllocate.
351 * PARAMS
352 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
353 * len [I] Size of memory block to allocate.
355 * RETURNS
356 * The memory block of size len that was allocated.
358 * NOTES
359 * The memory block is always 8-byte aligned.
360 * If the function is unable to allocate memory an ERROR_OUTOFMEMORY
361 * exception is raised.
363 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
365 size_t aligned_len;
366 size_t adjusted_len;
367 void *p;
368 NDR_MEMORY_LIST *mem_list;
370 aligned_len = ALIGNED_LENGTH(len, 8);
371 adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
372 /* check for overflow */
373 if (adjusted_len < len)
375 ERR("overflow of adjusted_len %d, len %d\n", adjusted_len, len);
376 RpcRaiseException(RPC_X_BAD_STUB_DATA);
379 p = pStubMsg->pfnAllocate(adjusted_len);
380 if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
382 mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
383 mem_list->magic = MEML_MAGIC;
384 mem_list->size = aligned_len;
385 mem_list->reserved = 0;
386 mem_list->next = pStubMsg->pMemoryList;
387 pStubMsg->pMemoryList = mem_list;
389 TRACE("-- %p\n", p);
390 return p;
393 static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
395 TRACE("(%p, %p)\n", pStubMsg, Pointer);
397 pStubMsg->pfnFree(Pointer);
400 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
402 return (*(const ULONG *)pFormat != -1);
405 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
407 ALIGN_POINTER(pStubMsg->Buffer, 4);
408 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
409 RpcRaiseException(RPC_X_BAD_STUB_DATA);
410 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
411 pStubMsg->Buffer += 4;
412 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
413 if (pStubMsg->fHasNewCorrDesc)
414 return pFormat+6;
415 else
416 return pFormat+4;
419 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
421 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
423 pStubMsg->Offset = 0;
424 pStubMsg->ActualCount = pStubMsg->MaxCount;
425 goto done;
428 ALIGN_POINTER(pStubMsg->Buffer, 4);
429 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
430 RpcRaiseException(RPC_X_BAD_STUB_DATA);
431 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
432 pStubMsg->Buffer += 4;
433 TRACE("offset is %d\n", pStubMsg->Offset);
434 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
435 pStubMsg->Buffer += 4;
436 TRACE("variance is %d\n", pStubMsg->ActualCount);
438 if ((pStubMsg->ActualCount > MaxValue) ||
439 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
441 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
442 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
443 RpcRaiseException(RPC_S_INVALID_BOUND);
444 return NULL;
447 done:
448 if (pStubMsg->fHasNewCorrDesc)
449 return pFormat+6;
450 else
451 return pFormat+4;
454 /* writes the conformance value to the buffer */
455 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
457 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
458 if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
459 RpcRaiseException(RPC_X_BAD_STUB_DATA);
460 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
461 pStubMsg->Buffer += 4;
464 /* writes the variance values to the buffer */
465 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
467 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
468 if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
469 RpcRaiseException(RPC_X_BAD_STUB_DATA);
470 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
471 pStubMsg->Buffer += 4;
472 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
473 pStubMsg->Buffer += 4;
476 /* requests buffer space for the conformance value */
477 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
479 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
480 if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
481 RpcRaiseException(RPC_X_BAD_STUB_DATA);
482 pStubMsg->BufferLength += 4;
485 /* requests buffer space for the variance values */
486 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
488 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
489 if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
490 RpcRaiseException(RPC_X_BAD_STUB_DATA);
491 pStubMsg->BufferLength += 8;
494 PFORMAT_STRING ComputeConformanceOrVariance(
495 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
496 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
498 BYTE dtype = pFormat[0] & 0xf;
499 short ofs = *(const short *)&pFormat[2];
500 LPVOID ptr = NULL;
501 DWORD data = 0;
503 if (!IsConformanceOrVariancePresent(pFormat)) {
504 /* null descriptor */
505 *pCount = def;
506 goto finish_conf;
509 switch (pFormat[0] & 0xf0) {
510 case RPC_FC_NORMAL_CONFORMANCE:
511 TRACE("normal conformance, ofs=%d\n", ofs);
512 ptr = pMemory;
513 break;
514 case RPC_FC_POINTER_CONFORMANCE:
515 TRACE("pointer conformance, ofs=%d\n", ofs);
516 ptr = pStubMsg->Memory;
517 break;
518 case RPC_FC_TOP_LEVEL_CONFORMANCE:
519 TRACE("toplevel conformance, ofs=%d\n", ofs);
520 if (pStubMsg->StackTop) {
521 ptr = pStubMsg->StackTop;
523 else {
524 /* -Os mode, *pCount is already set */
525 goto finish_conf;
527 break;
528 case RPC_FC_CONSTANT_CONFORMANCE:
529 data = ofs | ((DWORD)pFormat[1] << 16);
530 TRACE("constant conformance, val=%d\n", data);
531 *pCount = data;
532 goto finish_conf;
533 case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
534 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
535 if (pStubMsg->StackTop) {
536 ptr = pStubMsg->StackTop;
538 else {
539 /* ? */
540 goto done_conf_grab;
542 break;
543 default:
544 FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
547 switch (pFormat[1]) {
548 case RPC_FC_DEREFERENCE:
549 ptr = *(LPVOID*)((char *)ptr + ofs);
550 break;
551 case RPC_FC_CALLBACK:
553 unsigned char *old_stack_top = pStubMsg->StackTop;
554 pStubMsg->StackTop = ptr;
556 /* ofs is index into StubDesc->apfnExprEval */
557 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
558 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
560 pStubMsg->StackTop = old_stack_top;
562 /* the callback function always stores the computed value in MaxCount */
563 *pCount = pStubMsg->MaxCount;
564 goto finish_conf;
566 default:
567 ptr = (char *)ptr + ofs;
568 break;
571 switch (dtype) {
572 case RPC_FC_LONG:
573 case RPC_FC_ULONG:
574 data = *(DWORD*)ptr;
575 break;
576 case RPC_FC_SHORT:
577 data = *(SHORT*)ptr;
578 break;
579 case RPC_FC_USHORT:
580 data = *(USHORT*)ptr;
581 break;
582 case RPC_FC_CHAR:
583 case RPC_FC_SMALL:
584 data = *(CHAR*)ptr;
585 break;
586 case RPC_FC_BYTE:
587 case RPC_FC_USMALL:
588 data = *(UCHAR*)ptr;
589 break;
590 default:
591 FIXME("unknown conformance data type %x\n", dtype);
592 goto done_conf_grab;
594 TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
596 done_conf_grab:
597 switch (pFormat[1]) {
598 case RPC_FC_DEREFERENCE: /* already handled */
599 case 0: /* no op */
600 *pCount = data;
601 break;
602 case RPC_FC_ADD_1:
603 *pCount = data + 1;
604 break;
605 case RPC_FC_SUB_1:
606 *pCount = data - 1;
607 break;
608 case RPC_FC_MULT_2:
609 *pCount = data * 2;
610 break;
611 case RPC_FC_DIV_2:
612 *pCount = data / 2;
613 break;
614 default:
615 FIXME("unknown conformance op %d\n", pFormat[1]);
616 goto finish_conf;
619 finish_conf:
620 TRACE("resulting conformance is %ld\n", *pCount);
621 if (pStubMsg->fHasNewCorrDesc)
622 return pFormat+6;
623 else
624 return pFormat+4;
627 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
628 * the result overflows 32-bits */
629 static inline ULONG safe_multiply(ULONG a, ULONG b)
631 ULONGLONG ret = (ULONGLONG)a * b;
632 if (ret > 0xffffffff)
634 RpcRaiseException(RPC_S_INVALID_BOUND);
635 return 0;
637 return ret;
640 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
642 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
643 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
644 RpcRaiseException(RPC_X_BAD_STUB_DATA);
645 pStubMsg->Buffer += size;
648 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
650 if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
652 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
653 pStubMsg->BufferLength, size);
654 RpcRaiseException(RPC_X_BAD_STUB_DATA);
656 pStubMsg->BufferLength += size;
659 /* copies data from the buffer, checking that there is enough data in the buffer
660 * to do so */
661 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
663 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
664 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
666 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
667 pStubMsg->Buffer, pStubMsg->BufferEnd, size);
668 RpcRaiseException(RPC_X_BAD_STUB_DATA);
670 if (p == pStubMsg->Buffer)
671 ERR("pointer is the same as the buffer\n");
672 memcpy(p, pStubMsg->Buffer, size);
673 pStubMsg->Buffer += size;
676 /* copies data to the buffer, checking that there is enough space to do so */
677 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
679 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
680 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
682 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
683 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
684 size);
685 RpcRaiseException(RPC_X_BAD_STUB_DATA);
687 memcpy(pStubMsg->Buffer, p, size);
688 pStubMsg->Buffer += size;
692 * NdrConformantString:
694 * What MS calls a ConformantString is, in DCE terminology,
695 * a Varying-Conformant String.
697 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
698 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
699 * into unmarshalled string)
700 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
701 * [
702 * data: CHARTYPE[maxlen]
703 * ]
704 * ], where CHARTYPE is the appropriate character type (specified externally)
708 /***********************************************************************
709 * NdrConformantStringMarshall [RPCRT4.@]
711 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
712 unsigned char *pszMessage, PFORMAT_STRING pFormat)
714 ULONG esize, size;
716 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
718 if (*pFormat == RPC_FC_C_CSTRING) {
719 TRACE("string=%s\n", debugstr_a((char*)pszMessage));
720 pStubMsg->ActualCount = strlen((char*)pszMessage)+1;
721 esize = 1;
723 else if (*pFormat == RPC_FC_C_WSTRING) {
724 TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
725 pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1;
726 esize = 2;
728 else {
729 ERR("Unhandled string type: %#x\n", *pFormat);
730 /* FIXME: raise an exception. */
731 return NULL;
734 if (pFormat[1] == RPC_FC_STRING_SIZED)
735 pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0);
736 else
737 pStubMsg->MaxCount = pStubMsg->ActualCount;
738 pStubMsg->Offset = 0;
739 WriteConformance(pStubMsg);
740 WriteVariance(pStubMsg);
742 size = safe_multiply(esize, pStubMsg->ActualCount);
743 safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */
745 /* success */
746 return NULL; /* is this always right? */
749 /***********************************************************************
750 * NdrConformantStringBufferSize [RPCRT4.@]
752 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
753 unsigned char* pMemory, PFORMAT_STRING pFormat)
755 ULONG esize;
757 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
759 SizeConformance(pStubMsg);
760 SizeVariance(pStubMsg);
762 if (*pFormat == RPC_FC_C_CSTRING) {
763 TRACE("string=%s\n", debugstr_a((char*)pMemory));
764 pStubMsg->ActualCount = strlen((char*)pMemory)+1;
765 esize = 1;
767 else if (*pFormat == RPC_FC_C_WSTRING) {
768 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
769 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1;
770 esize = 2;
772 else {
773 ERR("Unhandled string type: %#x\n", *pFormat);
774 /* FIXME: raise an exception */
775 return;
778 if (pFormat[1] == RPC_FC_STRING_SIZED)
779 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
780 else
781 pStubMsg->MaxCount = pStubMsg->ActualCount;
783 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
786 /************************************************************************
787 * NdrConformantStringMemorySize [RPCRT4.@]
789 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
790 PFORMAT_STRING pFormat )
792 ULONG bufsize, memsize, esize, i;
794 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
796 ReadConformance(pStubMsg, NULL);
797 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
799 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
801 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
802 pStubMsg->ActualCount, pStubMsg->MaxCount);
803 RpcRaiseException(RPC_S_INVALID_BOUND);
805 if (pStubMsg->Offset)
807 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
808 RpcRaiseException(RPC_S_INVALID_BOUND);
811 if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
812 else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
813 else {
814 ERR("Unhandled string type: %#x\n", *pFormat);
815 /* FIXME: raise an exception */
816 esize = 0;
819 memsize = safe_multiply(esize, pStubMsg->MaxCount);
820 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
822 /* strings must always have null terminating bytes */
823 if (bufsize < esize)
825 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
826 RpcRaiseException(RPC_S_INVALID_BOUND);
829 /* verify the buffer is safe to access */
830 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
831 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
833 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
834 pStubMsg->BufferEnd, pStubMsg->Buffer);
835 RpcRaiseException(RPC_X_BAD_STUB_DATA);
838 for (i = bufsize - esize; i < bufsize; i++)
839 if (pStubMsg->Buffer[i] != 0)
841 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
842 i, pStubMsg->Buffer[i]);
843 RpcRaiseException(RPC_S_INVALID_BOUND);
846 safe_buffer_increment(pStubMsg, bufsize);
847 pStubMsg->MemorySize += memsize;
849 return pStubMsg->MemorySize;
852 /************************************************************************
853 * NdrConformantStringUnmarshall [RPCRT4.@]
855 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
856 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
858 ULONG bufsize, memsize, esize, i;
860 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
861 pStubMsg, *ppMemory, pFormat, fMustAlloc);
863 assert(pFormat && ppMemory && pStubMsg);
865 ReadConformance(pStubMsg, NULL);
866 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
868 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
870 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
871 pStubMsg->ActualCount, pStubMsg->MaxCount);
872 RpcRaiseException(RPC_S_INVALID_BOUND);
873 return NULL;
875 if (pStubMsg->Offset)
877 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
878 RpcRaiseException(RPC_S_INVALID_BOUND);
879 return NULL;
882 if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
883 else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
884 else {
885 ERR("Unhandled string type: %#x\n", *pFormat);
886 /* FIXME: raise an exception */
887 esize = 0;
890 memsize = safe_multiply(esize, pStubMsg->MaxCount);
891 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
893 /* strings must always have null terminating bytes */
894 if (bufsize < esize)
896 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
897 RpcRaiseException(RPC_S_INVALID_BOUND);
898 return NULL;
901 /* verify the buffer is safe to access */
902 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
903 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
905 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
906 pStubMsg->BufferEnd, pStubMsg->Buffer);
907 RpcRaiseException(RPC_X_BAD_STUB_DATA);
908 return NULL;
911 for (i = bufsize - esize; i < bufsize; i++)
912 if (pStubMsg->Buffer[i] != 0)
914 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
915 i, pStubMsg->Buffer[i]);
916 RpcRaiseException(RPC_S_INVALID_BOUND);
917 return NULL;
920 if (fMustAlloc)
921 *ppMemory = NdrAllocate(pStubMsg, memsize);
922 else
924 if (!pStubMsg->IsClient && !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
925 /* if the data in the RPC buffer is big enough, we just point straight
926 * into it */
927 *ppMemory = pStubMsg->Buffer;
928 else if (!*ppMemory)
929 *ppMemory = NdrAllocate(pStubMsg, memsize);
932 if (*ppMemory == pStubMsg->Buffer)
933 safe_buffer_increment(pStubMsg, bufsize);
934 else
935 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
937 if (*pFormat == RPC_FC_C_CSTRING) {
938 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
940 else if (*pFormat == RPC_FC_C_WSTRING) {
941 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
944 return NULL; /* FIXME: is this always right? */
947 /***********************************************************************
948 * NdrNonConformantStringMarshall [RPCRT4.@]
950 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
951 unsigned char *pMemory,
952 PFORMAT_STRING pFormat)
954 ULONG esize, size, maxsize;
956 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
958 maxsize = *(USHORT *)&pFormat[2];
960 if (*pFormat == RPC_FC_CSTRING)
962 ULONG i;
963 const char *str = (const char *)pMemory;
964 for (i = 0; i < maxsize && *str; i++, str++)
966 TRACE("string=%s\n", debugstr_an(str, i));
967 pStubMsg->ActualCount = i + 1;
968 esize = 1;
970 else if (*pFormat == RPC_FC_WSTRING)
972 ULONG i;
973 const WCHAR *str = (const WCHAR *)pMemory;
974 for (i = 0; i < maxsize && *str; i++, str++)
976 TRACE("string=%s\n", debugstr_wn(str, i));
977 pStubMsg->ActualCount = i + 1;
978 esize = 2;
980 else
982 ERR("Unhandled string type: %#x\n", *pFormat);
983 RpcRaiseException(RPC_X_BAD_STUB_DATA);
986 pStubMsg->Offset = 0;
987 WriteVariance(pStubMsg);
989 size = safe_multiply(esize, pStubMsg->ActualCount);
990 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
992 return NULL;
995 /***********************************************************************
996 * NdrNonConformantStringUnmarshall [RPCRT4.@]
998 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
999 unsigned char **ppMemory,
1000 PFORMAT_STRING pFormat,
1001 unsigned char fMustAlloc)
1003 ULONG bufsize, memsize, esize, i, maxsize;
1005 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
1006 pStubMsg, *ppMemory, pFormat, fMustAlloc);
1008 maxsize = *(USHORT *)&pFormat[2];
1010 ReadVariance(pStubMsg, NULL, maxsize);
1011 if (pStubMsg->Offset)
1013 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
1014 RpcRaiseException(RPC_S_INVALID_BOUND);
1017 if (*pFormat == RPC_FC_CSTRING) esize = 1;
1018 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
1019 else
1021 ERR("Unhandled string type: %#x\n", *pFormat);
1022 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1025 memsize = esize * maxsize;
1026 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
1028 if (bufsize < esize)
1030 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
1031 RpcRaiseException(RPC_S_INVALID_BOUND);
1032 return NULL;
1035 /* verify the buffer is safe to access */
1036 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
1037 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
1039 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
1040 pStubMsg->BufferEnd, pStubMsg->Buffer);
1041 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1042 return NULL;
1045 /* strings must always have null terminating bytes */
1046 for (i = bufsize - esize; i < bufsize; i++)
1047 if (pStubMsg->Buffer[i] != 0)
1049 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
1050 i, pStubMsg->Buffer[i]);
1051 RpcRaiseException(RPC_S_INVALID_BOUND);
1054 if (fMustAlloc || !*ppMemory)
1055 *ppMemory = NdrAllocate(pStubMsg, memsize);
1057 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
1059 if (*pFormat == RPC_FC_CSTRING) {
1060 TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
1062 else if (*pFormat == RPC_FC_WSTRING) {
1063 TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
1066 return NULL;
1069 /***********************************************************************
1070 * NdrNonConformantStringBufferSize [RPCRT4.@]
1072 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1073 unsigned char *pMemory,
1074 PFORMAT_STRING pFormat)
1076 ULONG esize, maxsize;
1078 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
1080 maxsize = *(USHORT *)&pFormat[2];
1082 SizeVariance(pStubMsg);
1084 if (*pFormat == RPC_FC_CSTRING)
1086 ULONG i;
1087 const char *str = (const char *)pMemory;
1088 for (i = 0; i < maxsize && *str; i++, str++)
1090 TRACE("string=%s\n", debugstr_an(str, i));
1091 pStubMsg->ActualCount = i + 1;
1092 esize = 1;
1094 else if (*pFormat == RPC_FC_WSTRING)
1096 ULONG i;
1097 const WCHAR *str = (const WCHAR *)pMemory;
1098 for (i = 0; i < maxsize && *str; i++, str++)
1100 TRACE("string=%s\n", debugstr_wn(str, i));
1101 pStubMsg->ActualCount = i + 1;
1102 esize = 2;
1104 else
1106 ERR("Unhandled string type: %#x\n", *pFormat);
1107 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1110 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
1113 /***********************************************************************
1114 * NdrNonConformantStringMemorySize [RPCRT4.@]
1116 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1117 PFORMAT_STRING pFormat)
1119 ULONG bufsize, memsize, esize, i, maxsize;
1121 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
1123 maxsize = *(USHORT *)&pFormat[2];
1125 ReadVariance(pStubMsg, NULL, maxsize);
1127 if (pStubMsg->Offset)
1129 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
1130 RpcRaiseException(RPC_S_INVALID_BOUND);
1133 if (*pFormat == RPC_FC_CSTRING) esize = 1;
1134 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
1135 else
1137 ERR("Unhandled string type: %#x\n", *pFormat);
1138 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1141 memsize = esize * maxsize;
1142 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
1144 /* strings must always have null terminating bytes */
1145 if (bufsize < esize)
1147 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
1148 RpcRaiseException(RPC_S_INVALID_BOUND);
1151 /* verify the buffer is safe to access */
1152 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
1153 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
1155 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
1156 pStubMsg->BufferEnd, pStubMsg->Buffer);
1157 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1160 for (i = bufsize - esize; i < bufsize; i++)
1161 if (pStubMsg->Buffer[i] != 0)
1163 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
1164 i, pStubMsg->Buffer[i]);
1165 RpcRaiseException(RPC_S_INVALID_BOUND);
1168 safe_buffer_increment(pStubMsg, bufsize);
1169 pStubMsg->MemorySize += memsize;
1171 return pStubMsg->MemorySize;
1174 static inline void dump_pointer_attr(unsigned char attr)
1176 if (attr & RPC_FC_P_ALLOCALLNODES)
1177 TRACE(" RPC_FC_P_ALLOCALLNODES");
1178 if (attr & RPC_FC_P_DONTFREE)
1179 TRACE(" RPC_FC_P_DONTFREE");
1180 if (attr & RPC_FC_P_ONSTACK)
1181 TRACE(" RPC_FC_P_ONSTACK");
1182 if (attr & RPC_FC_P_SIMPLEPOINTER)
1183 TRACE(" RPC_FC_P_SIMPLEPOINTER");
1184 if (attr & RPC_FC_P_DEREF)
1185 TRACE(" RPC_FC_P_DEREF");
1186 TRACE("\n");
1189 /***********************************************************************
1190 * PointerMarshall [internal]
1192 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1193 unsigned char *Buffer,
1194 unsigned char *Pointer,
1195 PFORMAT_STRING pFormat)
1197 unsigned type = pFormat[0], attr = pFormat[1];
1198 PFORMAT_STRING desc;
1199 NDR_MARSHALL m;
1200 ULONG pointer_id;
1201 int pointer_needs_marshaling;
1203 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
1204 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1205 pFormat += 2;
1206 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1207 else desc = pFormat + *(const SHORT*)pFormat;
1209 switch (type) {
1210 case RPC_FC_RP: /* ref pointer (always non-null) */
1211 if (!Pointer)
1213 ERR("NULL ref pointer is not allowed\n");
1214 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1216 pointer_needs_marshaling = 1;
1217 break;
1218 case RPC_FC_UP: /* unique pointer */
1219 case RPC_FC_OP: /* object pointer - same as unique here */
1220 if (Pointer)
1221 pointer_needs_marshaling = 1;
1222 else
1223 pointer_needs_marshaling = 0;
1224 pointer_id = (ULONG)Pointer;
1225 TRACE("writing 0x%08x to buffer\n", pointer_id);
1226 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
1227 break;
1228 case RPC_FC_FP:
1229 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
1230 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
1231 TRACE("writing 0x%08x to buffer\n", pointer_id);
1232 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
1233 break;
1234 default:
1235 FIXME("unhandled ptr type=%02x\n", type);
1236 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1237 return;
1240 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
1242 if (pointer_needs_marshaling) {
1243 if (attr & RPC_FC_P_DEREF) {
1244 Pointer = *(unsigned char**)Pointer;
1245 TRACE("deref => %p\n", Pointer);
1247 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1248 if (m) m(pStubMsg, Pointer, desc);
1249 else FIXME("no marshaller for data type=%02x\n", *desc);
1252 STD_OVERFLOW_CHECK(pStubMsg);
1255 /***********************************************************************
1256 * PointerUnmarshall [internal]
1258 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1259 unsigned char *Buffer,
1260 unsigned char **pPointer,
1261 unsigned char *pSrcPointer,
1262 PFORMAT_STRING pFormat,
1263 unsigned char fMustAlloc)
1265 unsigned type = pFormat[0], attr = pFormat[1];
1266 PFORMAT_STRING desc;
1267 NDR_UNMARSHALL m;
1268 DWORD pointer_id = 0;
1269 int pointer_needs_unmarshaling;
1271 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
1272 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1273 pFormat += 2;
1274 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1275 else desc = pFormat + *(const SHORT*)pFormat;
1277 switch (type) {
1278 case RPC_FC_RP: /* ref pointer (always non-null) */
1279 pointer_needs_unmarshaling = 1;
1280 break;
1281 case RPC_FC_UP: /* unique pointer */
1282 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1283 TRACE("pointer_id is 0x%08x\n", pointer_id);
1284 if (pointer_id)
1285 pointer_needs_unmarshaling = 1;
1286 else {
1287 *pPointer = NULL;
1288 pointer_needs_unmarshaling = 0;
1290 break;
1291 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1292 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1293 TRACE("pointer_id is 0x%08x\n", pointer_id);
1294 if (!fMustAlloc && pSrcPointer)
1296 FIXME("free object pointer %p\n", pSrcPointer);
1297 fMustAlloc = TRUE;
1299 if (pointer_id)
1300 pointer_needs_unmarshaling = 1;
1301 else
1302 pointer_needs_unmarshaling = 0;
1303 break;
1304 case RPC_FC_FP:
1305 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1306 TRACE("pointer_id is 0x%08x\n", pointer_id);
1307 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
1308 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
1309 break;
1310 default:
1311 FIXME("unhandled ptr type=%02x\n", type);
1312 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1313 return;
1316 if (pointer_needs_unmarshaling) {
1317 unsigned char *base_ptr_val = *pPointer;
1318 unsigned char **current_ptr = pPointer;
1319 if (pStubMsg->IsClient) {
1320 TRACE("client\n");
1321 /* if we aren't forcing allocation of memory then try to use the existing
1322 * (source) pointer to unmarshall the data into so that [in,out]
1323 * parameters behave correctly. it doesn't matter if the parameter is
1324 * [out] only since in that case the pointer will be NULL. we force
1325 * allocation when the source pointer is NULL here instead of in the type
1326 * unmarshalling routine for the benefit of the deref code below */
1327 if (!fMustAlloc) {
1328 if (pSrcPointer) {
1329 TRACE("setting *pPointer to %p\n", pSrcPointer);
1330 *pPointer = base_ptr_val = pSrcPointer;
1331 } else
1332 fMustAlloc = TRUE;
1334 } else {
1335 TRACE("server\n");
1336 /* the memory in a stub is never initialised, so we have to work out here
1337 * whether we have to initialise it so we can use the optimisation of
1338 * setting the pointer to the buffer, if possible, or set fMustAlloc to
1339 * TRUE. */
1340 if (attr & RPC_FC_P_DEREF) {
1341 fMustAlloc = TRUE;
1342 } else {
1343 base_ptr_val = NULL;
1344 *current_ptr = NULL;
1348 if (attr & RPC_FC_P_ALLOCALLNODES)
1349 FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
1351 if (attr & RPC_FC_P_DEREF) {
1352 if (fMustAlloc) {
1353 base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
1354 *pPointer = base_ptr_val;
1355 current_ptr = (unsigned char **)base_ptr_val;
1356 } else
1357 current_ptr = *(unsigned char***)current_ptr;
1358 TRACE("deref => %p\n", current_ptr);
1359 if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
1361 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1362 if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
1363 else FIXME("no unmarshaller for data type=%02x\n", *desc);
1365 if (type == RPC_FC_FP)
1366 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
1367 base_ptr_val);
1370 TRACE("pointer=%p\n", *pPointer);
1373 /***********************************************************************
1374 * PointerBufferSize [internal]
1376 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1377 unsigned char *Pointer,
1378 PFORMAT_STRING pFormat)
1380 unsigned type = pFormat[0], attr = pFormat[1];
1381 PFORMAT_STRING desc;
1382 NDR_BUFFERSIZE m;
1383 int pointer_needs_sizing;
1384 ULONG pointer_id;
1386 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1387 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1388 pFormat += 2;
1389 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1390 else desc = pFormat + *(const SHORT*)pFormat;
1392 switch (type) {
1393 case RPC_FC_RP: /* ref pointer (always non-null) */
1394 if (!Pointer)
1396 ERR("NULL ref pointer is not allowed\n");
1397 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1399 break;
1400 case RPC_FC_OP:
1401 case RPC_FC_UP:
1402 /* NULL pointer has no further representation */
1403 if (!Pointer)
1404 return;
1405 break;
1406 case RPC_FC_FP:
1407 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1408 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1409 if (!pointer_needs_sizing)
1410 return;
1411 break;
1412 default:
1413 FIXME("unhandled ptr type=%02x\n", type);
1414 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1415 return;
1418 if (attr & RPC_FC_P_DEREF) {
1419 Pointer = *(unsigned char**)Pointer;
1420 TRACE("deref => %p\n", Pointer);
1423 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1424 if (m) m(pStubMsg, Pointer, desc);
1425 else FIXME("no buffersizer for data type=%02x\n", *desc);
1428 /***********************************************************************
1429 * PointerMemorySize [internal]
1431 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1432 unsigned char *Buffer,
1433 PFORMAT_STRING pFormat)
1435 unsigned type = pFormat[0], attr = pFormat[1];
1436 PFORMAT_STRING desc;
1437 NDR_MEMORYSIZE m;
1438 DWORD pointer_id = 0;
1439 int pointer_needs_sizing;
1441 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1442 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1443 pFormat += 2;
1444 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1445 else desc = pFormat + *(const SHORT*)pFormat;
1447 switch (type) {
1448 case RPC_FC_RP: /* ref pointer (always non-null) */
1449 pointer_needs_sizing = 1;
1450 break;
1451 case RPC_FC_UP: /* unique pointer */
1452 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1453 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1454 TRACE("pointer_id is 0x%08x\n", pointer_id);
1455 if (pointer_id)
1456 pointer_needs_sizing = 1;
1457 else
1458 pointer_needs_sizing = 0;
1459 break;
1460 case RPC_FC_FP:
1462 void *pointer;
1463 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1464 TRACE("pointer_id is 0x%08x\n", pointer_id);
1465 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1466 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1467 break;
1469 default:
1470 FIXME("unhandled ptr type=%02x\n", type);
1471 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1472 return 0;
1475 if (attr & RPC_FC_P_DEREF) {
1476 TRACE("deref\n");
1479 if (pointer_needs_sizing) {
1480 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1481 if (m) m(pStubMsg, desc);
1482 else FIXME("no memorysizer for data type=%02x\n", *desc);
1485 return pStubMsg->MemorySize;
1488 /***********************************************************************
1489 * PointerFree [internal]
1491 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1492 unsigned char *Pointer,
1493 PFORMAT_STRING pFormat)
1495 unsigned type = pFormat[0], attr = pFormat[1];
1496 PFORMAT_STRING desc;
1497 NDR_FREE m;
1498 unsigned char *current_pointer = Pointer;
1500 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1501 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1502 if (attr & RPC_FC_P_DONTFREE) return;
1503 pFormat += 2;
1504 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1505 else desc = pFormat + *(const SHORT*)pFormat;
1507 if (!Pointer) return;
1509 if (type == RPC_FC_FP) {
1510 int pointer_needs_freeing = NdrFullPointerFree(
1511 pStubMsg->FullPtrXlatTables, Pointer);
1512 if (!pointer_needs_freeing)
1513 return;
1516 if (attr & RPC_FC_P_DEREF) {
1517 current_pointer = *(unsigned char**)Pointer;
1518 TRACE("deref => %p\n", current_pointer);
1521 m = NdrFreer[*desc & NDR_TABLE_MASK];
1522 if (m) m(pStubMsg, current_pointer, desc);
1524 /* this check stops us from trying to free buffer memory. we don't have to
1525 * worry about clients, since they won't call this function.
1526 * we don't have to check for the buffer being reallocated because
1527 * BufferStart and BufferEnd won't be reset when allocating memory for
1528 * sending the response. we don't have to check for the new buffer here as
1529 * it won't be used a type memory, only for buffer memory */
1530 if (Pointer >= (unsigned char *)pStubMsg->BufferStart &&
1531 Pointer < (unsigned char *)pStubMsg->BufferEnd)
1532 goto notfree;
1534 if (attr & RPC_FC_P_ONSTACK) {
1535 TRACE("not freeing stack ptr %p\n", Pointer);
1536 return;
1538 TRACE("freeing %p\n", Pointer);
1539 NdrFree(pStubMsg, Pointer);
1540 return;
1541 notfree:
1542 TRACE("not freeing %p\n", Pointer);
1545 /***********************************************************************
1546 * EmbeddedPointerMarshall
1548 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1549 unsigned char *pMemory,
1550 PFORMAT_STRING pFormat)
1552 unsigned char *Mark = pStubMsg->BufferMark;
1553 unsigned rep, count, stride;
1554 unsigned i;
1555 unsigned char *saved_buffer = NULL;
1557 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1559 if (*pFormat != RPC_FC_PP) return NULL;
1560 pFormat += 2;
1562 if (pStubMsg->PointerBufferMark)
1564 saved_buffer = pStubMsg->Buffer;
1565 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1566 pStubMsg->PointerBufferMark = NULL;
1569 while (pFormat[0] != RPC_FC_END) {
1570 switch (pFormat[0]) {
1571 default:
1572 FIXME("unknown repeat type %d\n", pFormat[0]);
1573 case RPC_FC_NO_REPEAT:
1574 rep = 1;
1575 stride = 0;
1576 count = 1;
1577 pFormat += 2;
1578 break;
1579 case RPC_FC_FIXED_REPEAT:
1580 rep = *(const WORD*)&pFormat[2];
1581 stride = *(const WORD*)&pFormat[4];
1582 count = *(const WORD*)&pFormat[8];
1583 pFormat += 10;
1584 break;
1585 case RPC_FC_VARIABLE_REPEAT:
1586 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1587 stride = *(const WORD*)&pFormat[2];
1588 count = *(const WORD*)&pFormat[6];
1589 pFormat += 8;
1590 break;
1592 for (i = 0; i < rep; i++) {
1593 PFORMAT_STRING info = pFormat;
1594 unsigned char *membase = pMemory + (i * stride);
1595 unsigned char *bufbase = Mark + (i * stride);
1596 unsigned u;
1598 for (u=0; u<count; u++,info+=8) {
1599 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1600 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1601 unsigned char *saved_memory = pStubMsg->Memory;
1603 pStubMsg->Memory = pMemory;
1604 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1605 pStubMsg->Memory = saved_memory;
1608 pFormat += 8 * count;
1611 if (saved_buffer)
1613 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1614 pStubMsg->Buffer = saved_buffer;
1617 STD_OVERFLOW_CHECK(pStubMsg);
1619 return NULL;
1622 /***********************************************************************
1623 * EmbeddedPointerUnmarshall
1625 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1626 unsigned char *pDstMemoryPtrs,
1627 unsigned char *pSrcMemoryPtrs,
1628 PFORMAT_STRING pFormat,
1629 unsigned char fMustAlloc)
1631 unsigned char *Mark = pStubMsg->BufferMark;
1632 unsigned rep, count, stride;
1633 unsigned i;
1634 unsigned char *saved_buffer = NULL;
1636 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstMemoryPtrs, pSrcMemoryPtrs, pFormat, fMustAlloc);
1638 if (*pFormat != RPC_FC_PP) return NULL;
1639 pFormat += 2;
1641 if (pStubMsg->PointerBufferMark)
1643 saved_buffer = pStubMsg->Buffer;
1644 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1645 pStubMsg->PointerBufferMark = NULL;
1648 while (pFormat[0] != RPC_FC_END) {
1649 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1650 switch (pFormat[0]) {
1651 default:
1652 FIXME("unknown repeat type %d\n", pFormat[0]);
1653 case RPC_FC_NO_REPEAT:
1654 rep = 1;
1655 stride = 0;
1656 count = 1;
1657 pFormat += 2;
1658 break;
1659 case RPC_FC_FIXED_REPEAT:
1660 rep = *(const WORD*)&pFormat[2];
1661 stride = *(const WORD*)&pFormat[4];
1662 count = *(const WORD*)&pFormat[8];
1663 pFormat += 10;
1664 break;
1665 case RPC_FC_VARIABLE_REPEAT:
1666 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1667 stride = *(const WORD*)&pFormat[2];
1668 count = *(const WORD*)&pFormat[6];
1669 pFormat += 8;
1670 break;
1672 for (i = 0; i < rep; i++) {
1673 PFORMAT_STRING info = pFormat;
1674 unsigned char *memdstbase = pDstMemoryPtrs + (i * stride);
1675 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1676 unsigned char *bufbase = Mark + (i * stride);
1677 unsigned u;
1679 for (u=0; u<count; u++,info+=8) {
1680 unsigned char **memdstptr = (unsigned char **)(memdstbase + *(const SHORT*)&info[0]);
1681 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1682 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1683 PointerUnmarshall(pStubMsg, bufptr, memdstptr, *memsrcptr, info+4, fMustAlloc);
1686 pFormat += 8 * count;
1689 if (saved_buffer)
1691 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1692 pStubMsg->Buffer = saved_buffer;
1695 return NULL;
1698 /***********************************************************************
1699 * EmbeddedPointerBufferSize
1701 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1702 unsigned char *pMemory,
1703 PFORMAT_STRING pFormat)
1705 unsigned rep, count, stride;
1706 unsigned i;
1707 ULONG saved_buffer_length = 0;
1709 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1711 if (pStubMsg->IgnoreEmbeddedPointers) return;
1713 if (*pFormat != RPC_FC_PP) return;
1714 pFormat += 2;
1716 if (pStubMsg->PointerLength)
1718 saved_buffer_length = pStubMsg->BufferLength;
1719 pStubMsg->BufferLength = pStubMsg->PointerLength;
1720 pStubMsg->PointerLength = 0;
1723 while (pFormat[0] != RPC_FC_END) {
1724 switch (pFormat[0]) {
1725 default:
1726 FIXME("unknown repeat type %d\n", pFormat[0]);
1727 case RPC_FC_NO_REPEAT:
1728 rep = 1;
1729 stride = 0;
1730 count = 1;
1731 pFormat += 2;
1732 break;
1733 case RPC_FC_FIXED_REPEAT:
1734 rep = *(const WORD*)&pFormat[2];
1735 stride = *(const WORD*)&pFormat[4];
1736 count = *(const WORD*)&pFormat[8];
1737 pFormat += 10;
1738 break;
1739 case RPC_FC_VARIABLE_REPEAT:
1740 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1741 stride = *(const WORD*)&pFormat[2];
1742 count = *(const WORD*)&pFormat[6];
1743 pFormat += 8;
1744 break;
1746 for (i = 0; i < rep; i++) {
1747 PFORMAT_STRING info = pFormat;
1748 unsigned char *membase = pMemory + (i * stride);
1749 unsigned u;
1751 for (u=0; u<count; u++,info+=8) {
1752 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1753 unsigned char *saved_memory = pStubMsg->Memory;
1755 pStubMsg->Memory = pMemory;
1756 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1757 pStubMsg->Memory = saved_memory;
1760 pFormat += 8 * count;
1763 if (saved_buffer_length)
1765 pStubMsg->PointerLength = pStubMsg->BufferLength;
1766 pStubMsg->BufferLength = saved_buffer_length;
1770 /***********************************************************************
1771 * EmbeddedPointerMemorySize [internal]
1773 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1774 PFORMAT_STRING pFormat)
1776 unsigned char *Mark = pStubMsg->BufferMark;
1777 unsigned rep, count, stride;
1778 unsigned i;
1779 unsigned char *saved_buffer = NULL;
1781 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1783 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1785 if (pStubMsg->PointerBufferMark)
1787 saved_buffer = pStubMsg->Buffer;
1788 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1789 pStubMsg->PointerBufferMark = NULL;
1792 if (*pFormat != RPC_FC_PP) return 0;
1793 pFormat += 2;
1795 while (pFormat[0] != RPC_FC_END) {
1796 switch (pFormat[0]) {
1797 default:
1798 FIXME("unknown repeat type %d\n", pFormat[0]);
1799 case RPC_FC_NO_REPEAT:
1800 rep = 1;
1801 stride = 0;
1802 count = 1;
1803 pFormat += 2;
1804 break;
1805 case RPC_FC_FIXED_REPEAT:
1806 rep = *(const WORD*)&pFormat[2];
1807 stride = *(const WORD*)&pFormat[4];
1808 count = *(const WORD*)&pFormat[8];
1809 pFormat += 10;
1810 break;
1811 case RPC_FC_VARIABLE_REPEAT:
1812 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1813 stride = *(const WORD*)&pFormat[2];
1814 count = *(const WORD*)&pFormat[6];
1815 pFormat += 8;
1816 break;
1818 for (i = 0; i < rep; i++) {
1819 PFORMAT_STRING info = pFormat;
1820 unsigned char *bufbase = Mark + (i * stride);
1821 unsigned u;
1822 for (u=0; u<count; u++,info+=8) {
1823 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1824 PointerMemorySize(pStubMsg, bufptr, info+4);
1827 pFormat += 8 * count;
1830 if (saved_buffer)
1832 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1833 pStubMsg->Buffer = saved_buffer;
1836 return 0;
1839 /***********************************************************************
1840 * EmbeddedPointerFree [internal]
1842 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1843 unsigned char *pMemory,
1844 PFORMAT_STRING pFormat)
1846 unsigned rep, count, stride;
1847 unsigned i;
1849 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1850 if (*pFormat != RPC_FC_PP) return;
1851 pFormat += 2;
1853 while (pFormat[0] != RPC_FC_END) {
1854 switch (pFormat[0]) {
1855 default:
1856 FIXME("unknown repeat type %d\n", pFormat[0]);
1857 case RPC_FC_NO_REPEAT:
1858 rep = 1;
1859 stride = 0;
1860 count = 1;
1861 pFormat += 2;
1862 break;
1863 case RPC_FC_FIXED_REPEAT:
1864 rep = *(const WORD*)&pFormat[2];
1865 stride = *(const WORD*)&pFormat[4];
1866 count = *(const WORD*)&pFormat[8];
1867 pFormat += 10;
1868 break;
1869 case RPC_FC_VARIABLE_REPEAT:
1870 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1871 stride = *(const WORD*)&pFormat[2];
1872 count = *(const WORD*)&pFormat[6];
1873 pFormat += 8;
1874 break;
1876 for (i = 0; i < rep; i++) {
1877 PFORMAT_STRING info = pFormat;
1878 unsigned char *membase = pMemory + (i * stride);
1879 unsigned u;
1881 for (u=0; u<count; u++,info+=8) {
1882 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1883 unsigned char *saved_memory = pStubMsg->Memory;
1885 pStubMsg->Memory = pMemory;
1886 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1887 pStubMsg->Memory = saved_memory;
1890 pFormat += 8 * count;
1894 /***********************************************************************
1895 * NdrPointerMarshall [RPCRT4.@]
1897 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1898 unsigned char *pMemory,
1899 PFORMAT_STRING pFormat)
1901 unsigned char *Buffer;
1903 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1905 /* incremement the buffer here instead of in PointerMarshall,
1906 * as that is used by embedded pointers which already handle the incrementing
1907 * the buffer, and shouldn't write any additional pointer data to the wire */
1908 if (*pFormat != RPC_FC_RP)
1910 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1911 Buffer = pStubMsg->Buffer;
1912 safe_buffer_increment(pStubMsg, 4);
1914 else
1915 Buffer = pStubMsg->Buffer;
1917 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1919 return NULL;
1922 /***********************************************************************
1923 * NdrPointerUnmarshall [RPCRT4.@]
1925 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1926 unsigned char **ppMemory,
1927 PFORMAT_STRING pFormat,
1928 unsigned char fMustAlloc)
1930 unsigned char *Buffer;
1932 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1934 /* incremement the buffer here instead of in PointerUnmarshall,
1935 * as that is used by embedded pointers which already handle the incrementing
1936 * the buffer, and shouldn't read any additional pointer data from the
1937 * buffer */
1938 if (*pFormat != RPC_FC_RP)
1940 ALIGN_POINTER(pStubMsg->Buffer, 4);
1941 Buffer = pStubMsg->Buffer;
1942 safe_buffer_increment(pStubMsg, 4);
1944 else
1945 Buffer = pStubMsg->Buffer;
1947 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1949 return NULL;
1952 /***********************************************************************
1953 * NdrPointerBufferSize [RPCRT4.@]
1955 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1956 unsigned char *pMemory,
1957 PFORMAT_STRING pFormat)
1959 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1961 /* incremement the buffer length here instead of in PointerBufferSize,
1962 * as that is used by embedded pointers which already handle the buffer
1963 * length, and shouldn't write anything more to the wire */
1964 if (*pFormat != RPC_FC_RP)
1966 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1967 safe_buffer_length_increment(pStubMsg, 4);
1970 PointerBufferSize(pStubMsg, pMemory, pFormat);
1973 /***********************************************************************
1974 * NdrPointerMemorySize [RPCRT4.@]
1976 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1977 PFORMAT_STRING pFormat)
1979 /* unsigned size = *(LPWORD)(pFormat+2); */
1980 FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1981 PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1982 return 0;
1985 /***********************************************************************
1986 * NdrPointerFree [RPCRT4.@]
1988 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1989 unsigned char *pMemory,
1990 PFORMAT_STRING pFormat)
1992 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1993 PointerFree(pStubMsg, pMemory, pFormat);
1996 /***********************************************************************
1997 * NdrSimpleTypeMarshall [RPCRT4.@]
1999 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
2000 unsigned char FormatChar )
2002 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
2005 /***********************************************************************
2006 * NdrSimpleTypeUnmarshall [RPCRT4.@]
2008 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
2009 unsigned char FormatChar )
2011 NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0);
2014 /***********************************************************************
2015 * NdrSimpleStructMarshall [RPCRT4.@]
2017 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2018 unsigned char *pMemory,
2019 PFORMAT_STRING pFormat)
2021 unsigned size = *(const WORD*)(pFormat+2);
2022 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2024 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
2026 pStubMsg->BufferMark = pStubMsg->Buffer;
2027 safe_copy_to_buffer(pStubMsg, pMemory, size);
2029 if (pFormat[0] != RPC_FC_STRUCT)
2030 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
2032 return NULL;
2035 /***********************************************************************
2036 * NdrSimpleStructUnmarshall [RPCRT4.@]
2038 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2039 unsigned char **ppMemory,
2040 PFORMAT_STRING pFormat,
2041 unsigned char fMustAlloc)
2043 unsigned size = *(const WORD*)(pFormat+2);
2044 unsigned char *saved_buffer;
2045 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2047 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2049 if (fMustAlloc)
2050 *ppMemory = NdrAllocate(pStubMsg, size);
2051 else
2053 if (!pStubMsg->IsClient && !*ppMemory)
2054 /* for servers, we just point straight into the RPC buffer */
2055 *ppMemory = pStubMsg->Buffer;
2058 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
2059 safe_buffer_increment(pStubMsg, size);
2060 if (pFormat[0] == RPC_FC_PSTRUCT)
2061 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
2063 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2064 if (*ppMemory != saved_buffer)
2065 memcpy(*ppMemory, saved_buffer, size);
2067 return NULL;
2070 /***********************************************************************
2071 * NdrSimpleStructBufferSize [RPCRT4.@]
2073 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2074 unsigned char *pMemory,
2075 PFORMAT_STRING pFormat)
2077 unsigned size = *(const WORD*)(pFormat+2);
2078 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2080 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2082 safe_buffer_length_increment(pStubMsg, size);
2083 if (pFormat[0] != RPC_FC_STRUCT)
2084 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
2087 /***********************************************************************
2088 * NdrSimpleStructMemorySize [RPCRT4.@]
2090 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2091 PFORMAT_STRING pFormat)
2093 unsigned short size = *(const WORD *)(pFormat+2);
2095 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2097 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2098 pStubMsg->MemorySize += size;
2099 safe_buffer_increment(pStubMsg, size);
2101 if (pFormat[0] != RPC_FC_STRUCT)
2102 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
2103 return pStubMsg->MemorySize;
2106 /***********************************************************************
2107 * NdrSimpleStructFree [RPCRT4.@]
2109 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2110 unsigned char *pMemory,
2111 PFORMAT_STRING pFormat)
2113 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2114 if (pFormat[0] != RPC_FC_STRUCT)
2115 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
2119 static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg,
2120 PFORMAT_STRING pFormat)
2122 switch (*pFormat) {
2123 case RPC_FC_STRUCT:
2124 case RPC_FC_PSTRUCT:
2125 case RPC_FC_CSTRUCT:
2126 case RPC_FC_BOGUS_STRUCT:
2127 case RPC_FC_SMFARRAY:
2128 case RPC_FC_SMVARRAY:
2129 return *(const WORD*)&pFormat[2];
2130 case RPC_FC_USER_MARSHAL:
2131 return *(const WORD*)&pFormat[4];
2132 case RPC_FC_NON_ENCAPSULATED_UNION:
2133 pFormat += 2;
2134 if (pStubMsg->fHasNewCorrDesc)
2135 pFormat += 6;
2136 else
2137 pFormat += 4;
2139 pFormat += *(const SHORT*)pFormat;
2140 return *(const SHORT*)pFormat;
2141 case RPC_FC_IP:
2142 return sizeof(void *);
2143 default:
2144 FIXME("unhandled embedded type %02x\n", *pFormat);
2146 return 0;
2150 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2151 PFORMAT_STRING pFormat)
2153 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2155 if (!m)
2157 FIXME("no memorysizer for data type=%02x\n", *pFormat);
2158 return 0;
2161 return m(pStubMsg, pFormat);
2165 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2166 unsigned char *pMemory,
2167 PFORMAT_STRING pFormat,
2168 PFORMAT_STRING pPointer)
2170 PFORMAT_STRING desc;
2171 NDR_MARSHALL m;
2172 unsigned long size;
2174 while (*pFormat != RPC_FC_END) {
2175 switch (*pFormat) {
2176 case RPC_FC_BYTE:
2177 case RPC_FC_CHAR:
2178 case RPC_FC_SMALL:
2179 case RPC_FC_USMALL:
2180 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2181 safe_copy_to_buffer(pStubMsg, pMemory, 1);
2182 pMemory += 1;
2183 break;
2184 case RPC_FC_WCHAR:
2185 case RPC_FC_SHORT:
2186 case RPC_FC_USHORT:
2187 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2188 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2189 pMemory += 2;
2190 break;
2191 case RPC_FC_LONG:
2192 case RPC_FC_ULONG:
2193 case RPC_FC_ENUM32:
2194 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2195 safe_copy_to_buffer(pStubMsg, pMemory, 4);
2196 pMemory += 4;
2197 break;
2198 case RPC_FC_HYPER:
2199 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2200 safe_copy_to_buffer(pStubMsg, pMemory, 8);
2201 pMemory += 8;
2202 break;
2203 case RPC_FC_POINTER:
2205 unsigned char *saved_buffer;
2206 int pointer_buffer_mark_set = 0;
2207 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2208 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2209 saved_buffer = pStubMsg->Buffer;
2210 if (pStubMsg->PointerBufferMark)
2212 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2213 pStubMsg->PointerBufferMark = NULL;
2214 pointer_buffer_mark_set = 1;
2216 else
2217 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2218 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2219 if (pointer_buffer_mark_set)
2221 STD_OVERFLOW_CHECK(pStubMsg);
2222 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2223 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
2225 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
2226 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
2227 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2229 pStubMsg->Buffer = saved_buffer + 4;
2231 pPointer += 4;
2232 pMemory += 4;
2233 break;
2235 case RPC_FC_ALIGNM4:
2236 ALIGN_POINTER(pMemory, 4);
2237 break;
2238 case RPC_FC_ALIGNM8:
2239 ALIGN_POINTER(pMemory, 8);
2240 break;
2241 case RPC_FC_STRUCTPAD1:
2242 case RPC_FC_STRUCTPAD2:
2243 case RPC_FC_STRUCTPAD3:
2244 case RPC_FC_STRUCTPAD4:
2245 case RPC_FC_STRUCTPAD5:
2246 case RPC_FC_STRUCTPAD6:
2247 case RPC_FC_STRUCTPAD7:
2248 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2249 break;
2250 case RPC_FC_EMBEDDED_COMPLEX:
2251 pMemory += pFormat[1];
2252 pFormat += 2;
2253 desc = pFormat + *(const SHORT*)pFormat;
2254 size = EmbeddedComplexSize(pStubMsg, desc);
2255 TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
2256 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2257 if (m)
2259 /* for some reason interface pointers aren't generated as
2260 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2261 * they still need the derefencing treatment that pointers are
2262 * given */
2263 if (*desc == RPC_FC_IP)
2264 m(pStubMsg, *(unsigned char **)pMemory, desc);
2265 else
2266 m(pStubMsg, pMemory, desc);
2268 else FIXME("no marshaller for embedded type %02x\n", *desc);
2269 pMemory += size;
2270 pFormat += 2;
2271 continue;
2272 case RPC_FC_PAD:
2273 break;
2274 default:
2275 FIXME("unhandled format 0x%02x\n", *pFormat);
2277 pFormat++;
2280 return pMemory;
2283 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2284 unsigned char *pMemory,
2285 PFORMAT_STRING pFormat,
2286 PFORMAT_STRING pPointer)
2288 PFORMAT_STRING desc;
2289 NDR_UNMARSHALL m;
2290 unsigned long size;
2292 while (*pFormat != RPC_FC_END) {
2293 switch (*pFormat) {
2294 case RPC_FC_BYTE:
2295 case RPC_FC_CHAR:
2296 case RPC_FC_SMALL:
2297 case RPC_FC_USMALL:
2298 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2299 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2300 pMemory += 1;
2301 break;
2302 case RPC_FC_WCHAR:
2303 case RPC_FC_SHORT:
2304 case RPC_FC_USHORT:
2305 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2306 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2307 pMemory += 2;
2308 break;
2309 case RPC_FC_LONG:
2310 case RPC_FC_ULONG:
2311 case RPC_FC_ENUM32:
2312 safe_copy_from_buffer(pStubMsg, pMemory, 4);
2313 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2314 pMemory += 4;
2315 break;
2316 case RPC_FC_HYPER:
2317 safe_copy_from_buffer(pStubMsg, pMemory, 8);
2318 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2319 pMemory += 8;
2320 break;
2321 case RPC_FC_POINTER:
2323 unsigned char *saved_buffer;
2324 int pointer_buffer_mark_set = 0;
2325 TRACE("pointer => %p\n", pMemory);
2326 ALIGN_POINTER(pStubMsg->Buffer, 4);
2327 saved_buffer = pStubMsg->Buffer;
2328 if (pStubMsg->PointerBufferMark)
2330 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2331 pStubMsg->PointerBufferMark = NULL;
2332 pointer_buffer_mark_set = 1;
2334 else
2335 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2337 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, TRUE);
2338 if (pointer_buffer_mark_set)
2340 STD_OVERFLOW_CHECK(pStubMsg);
2341 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2342 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
2344 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
2345 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
2346 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2348 pStubMsg->Buffer = saved_buffer + 4;
2350 pPointer += 4;
2351 pMemory += 4;
2352 break;
2354 case RPC_FC_ALIGNM4:
2355 ALIGN_POINTER_CLEAR(pMemory, 4);
2356 break;
2357 case RPC_FC_ALIGNM8:
2358 ALIGN_POINTER_CLEAR(pMemory, 8);
2359 break;
2360 case RPC_FC_STRUCTPAD1:
2361 case RPC_FC_STRUCTPAD2:
2362 case RPC_FC_STRUCTPAD3:
2363 case RPC_FC_STRUCTPAD4:
2364 case RPC_FC_STRUCTPAD5:
2365 case RPC_FC_STRUCTPAD6:
2366 case RPC_FC_STRUCTPAD7:
2367 memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2368 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2369 break;
2370 case RPC_FC_EMBEDDED_COMPLEX:
2371 pMemory += pFormat[1];
2372 pFormat += 2;
2373 desc = pFormat + *(const SHORT*)pFormat;
2374 size = EmbeddedComplexSize(pStubMsg, desc);
2375 TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
2376 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2377 memset(pMemory, 0, size); /* just in case */
2378 if (m)
2380 /* for some reason interface pointers aren't generated as
2381 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2382 * they still need the derefencing treatment that pointers are
2383 * given */
2384 if (*desc == RPC_FC_IP)
2385 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2386 else
2387 m(pStubMsg, &pMemory, desc, FALSE);
2389 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2390 pMemory += size;
2391 pFormat += 2;
2392 continue;
2393 case RPC_FC_PAD:
2394 break;
2395 default:
2396 FIXME("unhandled format %d\n", *pFormat);
2398 pFormat++;
2401 return pMemory;
2404 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2405 unsigned char *pMemory,
2406 PFORMAT_STRING pFormat,
2407 PFORMAT_STRING pPointer)
2409 PFORMAT_STRING desc;
2410 NDR_BUFFERSIZE m;
2411 unsigned long size;
2413 while (*pFormat != RPC_FC_END) {
2414 switch (*pFormat) {
2415 case RPC_FC_BYTE:
2416 case RPC_FC_CHAR:
2417 case RPC_FC_SMALL:
2418 case RPC_FC_USMALL:
2419 safe_buffer_length_increment(pStubMsg, 1);
2420 pMemory += 1;
2421 break;
2422 case RPC_FC_WCHAR:
2423 case RPC_FC_SHORT:
2424 case RPC_FC_USHORT:
2425 safe_buffer_length_increment(pStubMsg, 2);
2426 pMemory += 2;
2427 break;
2428 case RPC_FC_LONG:
2429 case RPC_FC_ULONG:
2430 case RPC_FC_ENUM32:
2431 safe_buffer_length_increment(pStubMsg, 4);
2432 pMemory += 4;
2433 break;
2434 case RPC_FC_HYPER:
2435 safe_buffer_length_increment(pStubMsg, 8);
2436 pMemory += 8;
2437 break;
2438 case RPC_FC_POINTER:
2439 if (!pStubMsg->IgnoreEmbeddedPointers)
2441 int saved_buffer_length = pStubMsg->BufferLength;
2442 pStubMsg->BufferLength = pStubMsg->PointerLength;
2443 pStubMsg->PointerLength = 0;
2444 if(!pStubMsg->BufferLength)
2445 ERR("BufferLength == 0??\n");
2446 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2447 pStubMsg->PointerLength = pStubMsg->BufferLength;
2448 pStubMsg->BufferLength = saved_buffer_length;
2450 safe_buffer_length_increment(pStubMsg, 4);
2451 pPointer += 4;
2452 pMemory += 4;
2453 break;
2454 case RPC_FC_ALIGNM4:
2455 ALIGN_POINTER(pMemory, 4);
2456 break;
2457 case RPC_FC_ALIGNM8:
2458 ALIGN_POINTER(pMemory, 8);
2459 break;
2460 case RPC_FC_STRUCTPAD1:
2461 case RPC_FC_STRUCTPAD2:
2462 case RPC_FC_STRUCTPAD3:
2463 case RPC_FC_STRUCTPAD4:
2464 case RPC_FC_STRUCTPAD5:
2465 case RPC_FC_STRUCTPAD6:
2466 case RPC_FC_STRUCTPAD7:
2467 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2468 break;
2469 case RPC_FC_EMBEDDED_COMPLEX:
2470 pMemory += pFormat[1];
2471 pFormat += 2;
2472 desc = pFormat + *(const SHORT*)pFormat;
2473 size = EmbeddedComplexSize(pStubMsg, desc);
2474 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2475 if (m)
2477 /* for some reason interface pointers aren't generated as
2478 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2479 * they still need the derefencing treatment that pointers are
2480 * given */
2481 if (*desc == RPC_FC_IP)
2482 m(pStubMsg, *(unsigned char **)pMemory, desc);
2483 else
2484 m(pStubMsg, pMemory, desc);
2486 else FIXME("no buffersizer for embedded type %02x\n", *desc);
2487 pMemory += size;
2488 pFormat += 2;
2489 continue;
2490 case RPC_FC_PAD:
2491 break;
2492 default:
2493 FIXME("unhandled format 0x%02x\n", *pFormat);
2495 pFormat++;
2498 return pMemory;
2501 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2502 unsigned char *pMemory,
2503 PFORMAT_STRING pFormat,
2504 PFORMAT_STRING pPointer)
2506 PFORMAT_STRING desc;
2507 NDR_FREE m;
2508 unsigned long size;
2510 while (*pFormat != RPC_FC_END) {
2511 switch (*pFormat) {
2512 case RPC_FC_BYTE:
2513 case RPC_FC_CHAR:
2514 case RPC_FC_SMALL:
2515 case RPC_FC_USMALL:
2516 pMemory += 1;
2517 break;
2518 case RPC_FC_WCHAR:
2519 case RPC_FC_SHORT:
2520 case RPC_FC_USHORT:
2521 pMemory += 2;
2522 break;
2523 case RPC_FC_LONG:
2524 case RPC_FC_ULONG:
2525 case RPC_FC_ENUM32:
2526 pMemory += 4;
2527 break;
2528 case RPC_FC_HYPER:
2529 pMemory += 8;
2530 break;
2531 case RPC_FC_POINTER:
2532 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2533 pPointer += 4;
2534 pMemory += 4;
2535 break;
2536 case RPC_FC_ALIGNM4:
2537 ALIGN_POINTER(pMemory, 4);
2538 break;
2539 case RPC_FC_ALIGNM8:
2540 ALIGN_POINTER(pMemory, 8);
2541 break;
2542 case RPC_FC_STRUCTPAD1:
2543 case RPC_FC_STRUCTPAD2:
2544 case RPC_FC_STRUCTPAD3:
2545 case RPC_FC_STRUCTPAD4:
2546 case RPC_FC_STRUCTPAD5:
2547 case RPC_FC_STRUCTPAD6:
2548 case RPC_FC_STRUCTPAD7:
2549 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2550 break;
2551 case RPC_FC_EMBEDDED_COMPLEX:
2552 pMemory += pFormat[1];
2553 pFormat += 2;
2554 desc = pFormat + *(const SHORT*)pFormat;
2555 size = EmbeddedComplexSize(pStubMsg, desc);
2556 m = NdrFreer[*desc & NDR_TABLE_MASK];
2557 if (m)
2559 /* for some reason interface pointers aren't generated as
2560 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2561 * they still need the derefencing treatment that pointers are
2562 * given */
2563 if (*desc == RPC_FC_IP)
2564 m(pStubMsg, *(unsigned char **)pMemory, desc);
2565 else
2566 m(pStubMsg, pMemory, desc);
2568 else FIXME("no freer for embedded type %02x\n", *desc);
2569 pMemory += size;
2570 pFormat += 2;
2571 continue;
2572 case RPC_FC_PAD:
2573 break;
2574 default:
2575 FIXME("unhandled format 0x%02x\n", *pFormat);
2577 pFormat++;
2580 return pMemory;
2583 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2584 PFORMAT_STRING pFormat)
2586 PFORMAT_STRING desc;
2587 unsigned long size = 0;
2589 while (*pFormat != RPC_FC_END) {
2590 switch (*pFormat) {
2591 case RPC_FC_BYTE:
2592 case RPC_FC_CHAR:
2593 case RPC_FC_SMALL:
2594 case RPC_FC_USMALL:
2595 size += 1;
2596 safe_buffer_increment(pStubMsg, 1);
2597 break;
2598 case RPC_FC_WCHAR:
2599 case RPC_FC_SHORT:
2600 case RPC_FC_USHORT:
2601 size += 2;
2602 safe_buffer_increment(pStubMsg, 2);
2603 break;
2604 case RPC_FC_LONG:
2605 case RPC_FC_ULONG:
2606 case RPC_FC_ENUM32:
2607 size += 4;
2608 safe_buffer_increment(pStubMsg, 4);
2609 break;
2610 case RPC_FC_HYPER:
2611 size += 8;
2612 safe_buffer_increment(pStubMsg, 8);
2613 break;
2614 case RPC_FC_POINTER:
2615 size += 4;
2616 safe_buffer_increment(pStubMsg, 4);
2617 if (!pStubMsg->IgnoreEmbeddedPointers)
2618 FIXME("embedded pointers\n");
2619 break;
2620 case RPC_FC_ALIGNM4:
2621 ALIGN_LENGTH(size, 4);
2622 ALIGN_POINTER(pStubMsg->Buffer, 4);
2623 break;
2624 case RPC_FC_ALIGNM8:
2625 ALIGN_LENGTH(size, 8);
2626 ALIGN_POINTER(pStubMsg->Buffer, 8);
2627 break;
2628 case RPC_FC_STRUCTPAD1:
2629 case RPC_FC_STRUCTPAD2:
2630 case RPC_FC_STRUCTPAD3:
2631 case RPC_FC_STRUCTPAD4:
2632 case RPC_FC_STRUCTPAD5:
2633 case RPC_FC_STRUCTPAD6:
2634 case RPC_FC_STRUCTPAD7:
2635 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2636 break;
2637 case RPC_FC_EMBEDDED_COMPLEX:
2638 size += pFormat[1];
2639 pFormat += 2;
2640 desc = pFormat + *(const SHORT*)pFormat;
2641 size += EmbeddedComplexMemorySize(pStubMsg, desc);
2642 pFormat += 2;
2643 continue;
2644 case RPC_FC_PAD:
2645 break;
2646 default:
2647 FIXME("unhandled format 0x%02x\n", *pFormat);
2649 pFormat++;
2652 return size;
2655 /***********************************************************************
2656 * NdrComplexStructMarshall [RPCRT4.@]
2658 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2659 unsigned char *pMemory,
2660 PFORMAT_STRING pFormat)
2662 PFORMAT_STRING conf_array = NULL;
2663 PFORMAT_STRING pointer_desc = NULL;
2664 unsigned char *OldMemory = pStubMsg->Memory;
2665 int pointer_buffer_mark_set = 0;
2667 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2669 if (!pStubMsg->PointerBufferMark)
2671 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2672 /* save buffer length */
2673 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2675 /* get the buffer pointer after complex array data, but before
2676 * pointer data */
2677 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2678 pStubMsg->IgnoreEmbeddedPointers = 1;
2679 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2680 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2682 /* save it for use by embedded pointer code later */
2683 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2684 TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2685 pointer_buffer_mark_set = 1;
2687 /* restore the original buffer length */
2688 pStubMsg->BufferLength = saved_buffer_length;
2691 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
2693 pFormat += 4;
2694 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2695 pFormat += 2;
2696 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2697 pFormat += 2;
2699 pStubMsg->Memory = pMemory;
2701 ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2703 if (conf_array)
2704 NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2706 pStubMsg->Memory = OldMemory;
2708 if (pointer_buffer_mark_set)
2710 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2711 pStubMsg->PointerBufferMark = NULL;
2714 STD_OVERFLOW_CHECK(pStubMsg);
2716 return NULL;
2719 /***********************************************************************
2720 * NdrComplexStructUnmarshall [RPCRT4.@]
2722 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2723 unsigned char **ppMemory,
2724 PFORMAT_STRING pFormat,
2725 unsigned char fMustAlloc)
2727 unsigned size = *(const WORD*)(pFormat+2);
2728 PFORMAT_STRING conf_array = NULL;
2729 PFORMAT_STRING pointer_desc = NULL;
2730 unsigned char *pMemory;
2731 int pointer_buffer_mark_set = 0;
2733 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2735 if (!pStubMsg->PointerBufferMark)
2737 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2738 /* save buffer pointer */
2739 unsigned char *saved_buffer = pStubMsg->Buffer;
2741 /* get the buffer pointer after complex array data, but before
2742 * pointer data */
2743 pStubMsg->IgnoreEmbeddedPointers = 1;
2744 NdrComplexStructMemorySize(pStubMsg, pFormat);
2745 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2747 /* save it for use by embedded pointer code later */
2748 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2749 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2750 pointer_buffer_mark_set = 1;
2752 /* restore the original buffer */
2753 pStubMsg->Buffer = saved_buffer;
2756 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2758 if (fMustAlloc || !*ppMemory)
2760 *ppMemory = NdrAllocate(pStubMsg, size);
2761 memset(*ppMemory, 0, size);
2764 pFormat += 4;
2765 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2766 pFormat += 2;
2767 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2768 pFormat += 2;
2770 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2772 if (conf_array)
2773 NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2775 if (pointer_buffer_mark_set)
2777 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2778 pStubMsg->PointerBufferMark = NULL;
2781 return NULL;
2784 /***********************************************************************
2785 * NdrComplexStructBufferSize [RPCRT4.@]
2787 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2788 unsigned char *pMemory,
2789 PFORMAT_STRING pFormat)
2791 PFORMAT_STRING conf_array = NULL;
2792 PFORMAT_STRING pointer_desc = NULL;
2793 unsigned char *OldMemory = pStubMsg->Memory;
2794 int pointer_length_set = 0;
2796 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2798 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2800 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2802 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2803 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2805 /* get the buffer length after complex struct data, but before
2806 * pointer data */
2807 pStubMsg->IgnoreEmbeddedPointers = 1;
2808 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2809 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2811 /* save it for use by embedded pointer code later */
2812 pStubMsg->PointerLength = pStubMsg->BufferLength;
2813 pointer_length_set = 1;
2814 TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2816 /* restore the original buffer length */
2817 pStubMsg->BufferLength = saved_buffer_length;
2820 pFormat += 4;
2821 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2822 pFormat += 2;
2823 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2824 pFormat += 2;
2826 pStubMsg->Memory = pMemory;
2828 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2830 if (conf_array)
2831 NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2833 pStubMsg->Memory = OldMemory;
2835 if(pointer_length_set)
2837 pStubMsg->BufferLength = pStubMsg->PointerLength;
2838 pStubMsg->PointerLength = 0;
2843 /***********************************************************************
2844 * NdrComplexStructMemorySize [RPCRT4.@]
2846 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2847 PFORMAT_STRING pFormat)
2849 unsigned size = *(const WORD*)(pFormat+2);
2850 PFORMAT_STRING conf_array = NULL;
2851 PFORMAT_STRING pointer_desc = NULL;
2853 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2855 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2857 pFormat += 4;
2858 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2859 pFormat += 2;
2860 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2861 pFormat += 2;
2863 ComplexStructMemorySize(pStubMsg, pFormat);
2865 if (conf_array)
2866 NdrConformantArrayMemorySize(pStubMsg, conf_array);
2868 return size;
2871 /***********************************************************************
2872 * NdrComplexStructFree [RPCRT4.@]
2874 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2875 unsigned char *pMemory,
2876 PFORMAT_STRING pFormat)
2878 PFORMAT_STRING conf_array = NULL;
2879 PFORMAT_STRING pointer_desc = NULL;
2880 unsigned char *OldMemory = pStubMsg->Memory;
2882 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2884 pFormat += 4;
2885 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2886 pFormat += 2;
2887 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2888 pFormat += 2;
2890 pStubMsg->Memory = pMemory;
2892 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2894 if (conf_array)
2895 NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2897 pStubMsg->Memory = OldMemory;
2900 /***********************************************************************
2901 * NdrConformantArrayMarshall [RPCRT4.@]
2903 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2904 unsigned char *pMemory,
2905 PFORMAT_STRING pFormat)
2907 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2908 unsigned char alignment = pFormat[1] + 1;
2910 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2911 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2913 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2915 WriteConformance(pStubMsg);
2917 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
2919 size = safe_multiply(esize, pStubMsg->MaxCount);
2920 pStubMsg->BufferMark = pStubMsg->Buffer;
2921 safe_copy_to_buffer(pStubMsg, pMemory, size);
2923 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2925 return NULL;
2928 /***********************************************************************
2929 * NdrConformantArrayUnmarshall [RPCRT4.@]
2931 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2932 unsigned char **ppMemory,
2933 PFORMAT_STRING pFormat,
2934 unsigned char fMustAlloc)
2936 DWORD size, esize = *(const WORD*)(pFormat+2);
2937 unsigned char alignment = pFormat[1] + 1;
2938 unsigned char *saved_buffer;
2940 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2941 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2943 pFormat = ReadConformance(pStubMsg, pFormat+4);
2945 size = safe_multiply(esize, pStubMsg->MaxCount);
2946 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2948 if (fMustAlloc)
2949 *ppMemory = NdrAllocate(pStubMsg, size);
2950 else
2952 if (!pStubMsg->IsClient && !*ppMemory)
2953 /* for servers, we just point straight into the RPC buffer */
2954 *ppMemory = pStubMsg->Buffer;
2957 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
2958 safe_buffer_increment(pStubMsg, size);
2959 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2961 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2962 if (*ppMemory != saved_buffer)
2963 memcpy(*ppMemory, saved_buffer, size);
2965 return NULL;
2968 /***********************************************************************
2969 * NdrConformantArrayBufferSize [RPCRT4.@]
2971 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2972 unsigned char *pMemory,
2973 PFORMAT_STRING pFormat)
2975 DWORD size, esize = *(const WORD*)(pFormat+2);
2976 unsigned char alignment = pFormat[1] + 1;
2978 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2979 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2981 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2983 SizeConformance(pStubMsg);
2985 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2987 size = safe_multiply(esize, pStubMsg->MaxCount);
2988 /* conformance value plus array */
2989 safe_buffer_length_increment(pStubMsg, size);
2991 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2994 /***********************************************************************
2995 * NdrConformantArrayMemorySize [RPCRT4.@]
2997 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2998 PFORMAT_STRING pFormat)
3000 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
3001 unsigned char alignment = pFormat[1] + 1;
3003 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3004 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3006 pFormat = ReadConformance(pStubMsg, pFormat+4);
3007 size = safe_multiply(esize, pStubMsg->MaxCount);
3008 pStubMsg->MemorySize += size;
3010 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3011 pStubMsg->BufferMark = pStubMsg->Buffer;
3012 safe_buffer_increment(pStubMsg, size);
3014 EmbeddedPointerMemorySize(pStubMsg, pFormat);
3016 return pStubMsg->MemorySize;
3019 /***********************************************************************
3020 * NdrConformantArrayFree [RPCRT4.@]
3022 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3023 unsigned char *pMemory,
3024 PFORMAT_STRING pFormat)
3026 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3027 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3029 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3031 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3035 /***********************************************************************
3036 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
3038 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
3039 unsigned char* pMemory,
3040 PFORMAT_STRING pFormat )
3042 ULONG bufsize;
3043 unsigned char alignment = pFormat[1] + 1;
3044 DWORD esize = *(const WORD*)(pFormat+2);
3046 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3048 if (pFormat[0] != RPC_FC_CVARRAY)
3050 ERR("invalid format type %x\n", pFormat[0]);
3051 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3052 return NULL;
3055 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3056 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3058 WriteConformance(pStubMsg);
3059 WriteVariance(pStubMsg);
3061 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3063 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3065 pStubMsg->BufferMark = pStubMsg->Buffer;
3066 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
3068 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3070 return NULL;
3074 /***********************************************************************
3075 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
3077 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
3078 unsigned char** ppMemory,
3079 PFORMAT_STRING pFormat,
3080 unsigned char fMustAlloc )
3082 ULONG bufsize, memsize;
3083 unsigned char alignment = pFormat[1] + 1;
3084 DWORD esize = *(const WORD*)(pFormat+2);
3085 unsigned char *saved_buffer;
3086 ULONG offset;
3088 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3090 if (pFormat[0] != RPC_FC_CVARRAY)
3092 ERR("invalid format type %x\n", pFormat[0]);
3093 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3094 return NULL;
3097 pFormat = ReadConformance(pStubMsg, pFormat+4);
3098 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3100 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3102 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3103 memsize = safe_multiply(esize, pStubMsg->MaxCount);
3104 offset = pStubMsg->Offset;
3106 if (!*ppMemory || fMustAlloc)
3107 *ppMemory = NdrAllocate(pStubMsg, memsize);
3108 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3109 safe_buffer_increment(pStubMsg, bufsize);
3111 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3113 memcpy(*ppMemory + offset, saved_buffer, bufsize);
3115 return NULL;
3119 /***********************************************************************
3120 * NdrConformantVaryingArrayFree [RPCRT4.@]
3122 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
3123 unsigned char* pMemory,
3124 PFORMAT_STRING pFormat )
3126 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3128 if (pFormat[0] != RPC_FC_CVARRAY)
3130 ERR("invalid format type %x\n", pFormat[0]);
3131 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3132 return;
3135 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3136 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3138 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3142 /***********************************************************************
3143 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
3145 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
3146 unsigned char* pMemory, PFORMAT_STRING pFormat )
3148 unsigned char alignment = pFormat[1] + 1;
3149 DWORD esize = *(const WORD*)(pFormat+2);
3151 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3153 if (pFormat[0] != RPC_FC_CVARRAY)
3155 ERR("invalid format type %x\n", pFormat[0]);
3156 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3157 return;
3160 /* compute size */
3161 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3162 /* compute length */
3163 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3165 SizeConformance(pStubMsg);
3166 SizeVariance(pStubMsg);
3168 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3170 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
3172 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3176 /***********************************************************************
3177 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
3179 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
3180 PFORMAT_STRING pFormat )
3182 ULONG bufsize, memsize;
3183 unsigned char alignment = pFormat[1] + 1;
3184 DWORD esize = *(const WORD*)(pFormat+2);
3186 TRACE("(%p, %p)\n", pStubMsg, pFormat);
3188 if (pFormat[0] != RPC_FC_CVARRAY)
3190 ERR("invalid format type %x\n", pFormat[0]);
3191 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3192 return pStubMsg->MemorySize;
3195 pFormat = ReadConformance(pStubMsg, pFormat+4);
3196 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3198 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3200 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3201 memsize = safe_multiply(esize, pStubMsg->MaxCount);
3203 safe_buffer_increment(pStubMsg, bufsize);
3204 pStubMsg->MemorySize += memsize;
3206 EmbeddedPointerMemorySize(pStubMsg, pFormat);
3208 return pStubMsg->MemorySize;
3212 /***********************************************************************
3213 * NdrComplexArrayMarshall [RPCRT4.@]
3215 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3216 unsigned char *pMemory,
3217 PFORMAT_STRING pFormat)
3219 ULONG i, count, def;
3220 BOOL variance_present;
3221 unsigned char alignment;
3222 int pointer_buffer_mark_set = 0;
3224 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3226 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3228 ERR("invalid format type %x\n", pFormat[0]);
3229 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3230 return NULL;
3233 alignment = pFormat[1] + 1;
3235 if (!pStubMsg->PointerBufferMark)
3237 /* save buffer fields that may be changed by buffer sizer functions
3238 * and that may be needed later on */
3239 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3240 unsigned long saved_buffer_length = pStubMsg->BufferLength;
3241 unsigned long saved_max_count = pStubMsg->MaxCount;
3242 unsigned long saved_offset = pStubMsg->Offset;
3243 unsigned long saved_actual_count = pStubMsg->ActualCount;
3245 /* get the buffer pointer after complex array data, but before
3246 * pointer data */
3247 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
3248 pStubMsg->IgnoreEmbeddedPointers = 1;
3249 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3250 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3252 /* save it for use by embedded pointer code later */
3253 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
3254 TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
3255 pointer_buffer_mark_set = 1;
3257 /* restore fields */
3258 pStubMsg->ActualCount = saved_actual_count;
3259 pStubMsg->Offset = saved_offset;
3260 pStubMsg->MaxCount = saved_max_count;
3261 pStubMsg->BufferLength = saved_buffer_length;
3264 def = *(const WORD*)&pFormat[2];
3265 pFormat += 4;
3267 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3268 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3270 variance_present = IsConformanceOrVariancePresent(pFormat);
3271 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3272 TRACE("variance = %d\n", pStubMsg->ActualCount);
3274 WriteConformance(pStubMsg);
3275 if (variance_present)
3276 WriteVariance(pStubMsg);
3278 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3280 count = pStubMsg->ActualCount;
3281 for (i = 0; i < count; i++)
3282 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3284 STD_OVERFLOW_CHECK(pStubMsg);
3286 if (pointer_buffer_mark_set)
3288 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3289 pStubMsg->PointerBufferMark = NULL;
3292 return NULL;
3295 /***********************************************************************
3296 * NdrComplexArrayUnmarshall [RPCRT4.@]
3298 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3299 unsigned char **ppMemory,
3300 PFORMAT_STRING pFormat,
3301 unsigned char fMustAlloc)
3303 ULONG i, count, size;
3304 unsigned char alignment;
3305 unsigned char *pMemory;
3306 unsigned char *saved_buffer;
3307 int pointer_buffer_mark_set = 0;
3308 int saved_ignore_embedded;
3310 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3312 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3314 ERR("invalid format type %x\n", pFormat[0]);
3315 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3316 return NULL;
3319 alignment = pFormat[1] + 1;
3321 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3322 /* save buffer pointer */
3323 saved_buffer = pStubMsg->Buffer;
3324 /* get the buffer pointer after complex array data, but before
3325 * pointer data */
3326 pStubMsg->IgnoreEmbeddedPointers = 1;
3327 pStubMsg->MemorySize = 0;
3328 NdrComplexArrayMemorySize(pStubMsg, pFormat);
3329 size = pStubMsg->MemorySize;
3330 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3332 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
3333 if (!pStubMsg->PointerBufferMark)
3335 /* save it for use by embedded pointer code later */
3336 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3337 pointer_buffer_mark_set = 1;
3339 /* restore the original buffer */
3340 pStubMsg->Buffer = saved_buffer;
3342 pFormat += 4;
3344 pFormat = ReadConformance(pStubMsg, pFormat);
3345 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3347 if (fMustAlloc || !*ppMemory)
3349 *ppMemory = NdrAllocate(pStubMsg, size);
3350 memset(*ppMemory, 0, size);
3353 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3355 pMemory = *ppMemory;
3356 count = pStubMsg->ActualCount;
3357 for (i = 0; i < count; i++)
3358 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
3360 if (pointer_buffer_mark_set)
3362 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3363 pStubMsg->PointerBufferMark = NULL;
3366 return NULL;
3369 /***********************************************************************
3370 * NdrComplexArrayBufferSize [RPCRT4.@]
3372 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3373 unsigned char *pMemory,
3374 PFORMAT_STRING pFormat)
3376 ULONG i, count, def;
3377 unsigned char alignment;
3378 BOOL variance_present;
3379 int pointer_length_set = 0;
3381 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3383 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3385 ERR("invalid format type %x\n", pFormat[0]);
3386 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3387 return;
3390 alignment = pFormat[1] + 1;
3392 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3394 /* save buffer fields that may be changed by buffer sizer functions
3395 * and that may be needed later on */
3396 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3397 unsigned long saved_buffer_length = pStubMsg->BufferLength;
3398 unsigned long saved_max_count = pStubMsg->MaxCount;
3399 unsigned long saved_offset = pStubMsg->Offset;
3400 unsigned long saved_actual_count = pStubMsg->ActualCount;
3402 /* get the buffer pointer after complex array data, but before
3403 * pointer data */
3404 pStubMsg->IgnoreEmbeddedPointers = 1;
3405 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3406 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3408 /* save it for use by embedded pointer code later */
3409 pStubMsg->PointerLength = pStubMsg->BufferLength;
3410 pointer_length_set = 1;
3412 /* restore fields */
3413 pStubMsg->ActualCount = saved_actual_count;
3414 pStubMsg->Offset = saved_offset;
3415 pStubMsg->MaxCount = saved_max_count;
3416 pStubMsg->BufferLength = saved_buffer_length;
3418 def = *(const WORD*)&pFormat[2];
3419 pFormat += 4;
3421 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3422 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3423 SizeConformance(pStubMsg);
3425 variance_present = IsConformanceOrVariancePresent(pFormat);
3426 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3427 TRACE("variance = %d\n", pStubMsg->ActualCount);
3429 if (variance_present)
3430 SizeVariance(pStubMsg);
3432 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3434 count = pStubMsg->ActualCount;
3435 for (i = 0; i < count; i++)
3436 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
3438 if(pointer_length_set)
3440 pStubMsg->BufferLength = pStubMsg->PointerLength;
3441 pStubMsg->PointerLength = 0;
3445 /***********************************************************************
3446 * NdrComplexArrayMemorySize [RPCRT4.@]
3448 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3449 PFORMAT_STRING pFormat)
3451 ULONG i, count, esize, SavedMemorySize, MemorySize;
3452 unsigned char alignment;
3453 unsigned char *Buffer;
3455 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3457 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3459 ERR("invalid format type %x\n", pFormat[0]);
3460 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3461 return 0;
3464 alignment = pFormat[1] + 1;
3466 pFormat += 4;
3468 pFormat = ReadConformance(pStubMsg, pFormat);
3469 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3471 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3473 SavedMemorySize = pStubMsg->MemorySize;
3475 Buffer = pStubMsg->Buffer;
3476 pStubMsg->MemorySize = 0;
3477 esize = ComplexStructMemorySize(pStubMsg, pFormat);
3478 pStubMsg->Buffer = Buffer;
3480 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3482 count = pStubMsg->ActualCount;
3483 for (i = 0; i < count; i++)
3484 ComplexStructMemorySize(pStubMsg, pFormat);
3486 pStubMsg->MemorySize = SavedMemorySize;
3488 pStubMsg->MemorySize += MemorySize;
3489 return MemorySize;
3492 /***********************************************************************
3493 * NdrComplexArrayFree [RPCRT4.@]
3495 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3496 unsigned char *pMemory,
3497 PFORMAT_STRING pFormat)
3499 ULONG i, count, def;
3501 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3503 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3505 ERR("invalid format type %x\n", pFormat[0]);
3506 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3507 return;
3510 def = *(const WORD*)&pFormat[2];
3511 pFormat += 4;
3513 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3514 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3516 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3517 TRACE("variance = %d\n", pStubMsg->ActualCount);
3519 count = pStubMsg->ActualCount;
3520 for (i = 0; i < count; i++)
3521 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
3524 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
3525 USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
3526 USER_MARSHAL_CB *umcb)
3528 umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
3529 pStubMsg->RpcMsg->DataRepresentation);
3530 umcb->pStubMsg = pStubMsg;
3531 umcb->pReserve = NULL;
3532 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
3533 umcb->CBType = cbtype;
3534 umcb->pFormat = pFormat;
3535 umcb->pTypeFormat = NULL /* FIXME */;
3538 #define USER_MARSHAL_PTR_PREFIX \
3539 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
3540 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
3542 /***********************************************************************
3543 * NdrUserMarshalMarshall [RPCRT4.@]
3545 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3546 unsigned char *pMemory,
3547 PFORMAT_STRING pFormat)
3549 unsigned flags = pFormat[1];
3550 unsigned index = *(const WORD*)&pFormat[2];
3551 unsigned char *saved_buffer = NULL;
3552 USER_MARSHAL_CB umcb;
3554 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3555 TRACE("index=%d\n", index);
3557 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
3559 if (flags & USER_MARSHAL_POINTER)
3561 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
3562 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
3563 pStubMsg->Buffer += 4;
3564 if (pStubMsg->PointerBufferMark)
3566 saved_buffer = pStubMsg->Buffer;
3567 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3568 pStubMsg->PointerBufferMark = NULL;
3570 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8);
3572 else
3573 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1);
3575 pStubMsg->Buffer =
3576 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
3577 &umcb.Flags, pStubMsg->Buffer, pMemory);
3579 if (saved_buffer)
3581 STD_OVERFLOW_CHECK(pStubMsg);
3582 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3583 pStubMsg->Buffer = saved_buffer;
3586 STD_OVERFLOW_CHECK(pStubMsg);
3588 return NULL;
3591 /***********************************************************************
3592 * NdrUserMarshalUnmarshall [RPCRT4.@]
3594 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3595 unsigned char **ppMemory,
3596 PFORMAT_STRING pFormat,
3597 unsigned char fMustAlloc)
3599 unsigned flags = pFormat[1];
3600 unsigned index = *(const WORD*)&pFormat[2];
3601 DWORD memsize = *(const WORD*)&pFormat[4];
3602 unsigned char *saved_buffer = NULL;
3603 USER_MARSHAL_CB umcb;
3605 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3606 TRACE("index=%d\n", index);
3608 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
3610 if (flags & USER_MARSHAL_POINTER)
3612 ALIGN_POINTER(pStubMsg->Buffer, 4);
3613 /* skip pointer prefix */
3614 pStubMsg->Buffer += 4;
3615 if (pStubMsg->PointerBufferMark)
3617 saved_buffer = pStubMsg->Buffer;
3618 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3619 pStubMsg->PointerBufferMark = NULL;
3621 ALIGN_POINTER(pStubMsg->Buffer, 8);
3623 else
3624 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3626 if (fMustAlloc || !*ppMemory)
3627 *ppMemory = NdrAllocate(pStubMsg, memsize);
3629 pStubMsg->Buffer =
3630 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
3631 &umcb.Flags, pStubMsg->Buffer, *ppMemory);
3633 if (saved_buffer)
3635 STD_OVERFLOW_CHECK(pStubMsg);
3636 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3637 pStubMsg->Buffer = saved_buffer;
3640 return NULL;
3643 /***********************************************************************
3644 * NdrUserMarshalBufferSize [RPCRT4.@]
3646 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3647 unsigned char *pMemory,
3648 PFORMAT_STRING pFormat)
3650 unsigned flags = pFormat[1];
3651 unsigned index = *(const WORD*)&pFormat[2];
3652 DWORD bufsize = *(const WORD*)&pFormat[6];
3653 USER_MARSHAL_CB umcb;
3654 unsigned long saved_buffer_length = 0;
3656 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3657 TRACE("index=%d\n", index);
3659 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
3661 if (flags & USER_MARSHAL_POINTER)
3663 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3664 /* skip pointer prefix */
3665 safe_buffer_length_increment(pStubMsg, 4);
3666 if (pStubMsg->IgnoreEmbeddedPointers)
3667 return;
3668 if (pStubMsg->PointerLength)
3670 saved_buffer_length = pStubMsg->BufferLength;
3671 pStubMsg->BufferLength = pStubMsg->PointerLength;
3672 pStubMsg->PointerLength = 0;
3674 ALIGN_LENGTH(pStubMsg->BufferLength, 8);
3676 else
3677 ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
3679 if (bufsize) {
3680 TRACE("size=%d\n", bufsize);
3681 safe_buffer_length_increment(pStubMsg, bufsize);
3683 else
3684 pStubMsg->BufferLength =
3685 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
3686 &umcb.Flags, pStubMsg->BufferLength, pMemory);
3688 if (saved_buffer_length)
3690 pStubMsg->PointerLength = pStubMsg->BufferLength;
3691 pStubMsg->BufferLength = saved_buffer_length;
3696 /***********************************************************************
3697 * NdrUserMarshalMemorySize [RPCRT4.@]
3699 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3700 PFORMAT_STRING pFormat)
3702 unsigned flags = pFormat[1];
3703 unsigned index = *(const WORD*)&pFormat[2];
3704 DWORD memsize = *(const WORD*)&pFormat[4];
3705 DWORD bufsize = *(const WORD*)&pFormat[6];
3707 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3708 TRACE("index=%d\n", index);
3710 pStubMsg->MemorySize += memsize;
3712 if (flags & USER_MARSHAL_POINTER)
3714 ALIGN_POINTER(pStubMsg->Buffer, 4);
3715 /* skip pointer prefix */
3716 pStubMsg->Buffer += 4;
3717 if (pStubMsg->IgnoreEmbeddedPointers)
3718 return pStubMsg->MemorySize;
3719 ALIGN_POINTER(pStubMsg->Buffer, 8);
3721 else
3722 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3724 if (!bufsize)
3725 FIXME("not implemented for varying buffer size\n");
3727 pStubMsg->Buffer += bufsize;
3729 return pStubMsg->MemorySize;
3732 /***********************************************************************
3733 * NdrUserMarshalFree [RPCRT4.@]
3735 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
3736 unsigned char *pMemory,
3737 PFORMAT_STRING pFormat)
3739 /* unsigned flags = pFormat[1]; */
3740 unsigned index = *(const WORD*)&pFormat[2];
3741 USER_MARSHAL_CB umcb;
3743 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3744 TRACE("index=%d\n", index);
3746 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
3748 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
3749 &umcb.Flags, pMemory);
3752 /***********************************************************************
3753 * NdrClearOutParameters [RPCRT4.@]
3755 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
3756 PFORMAT_STRING pFormat,
3757 void *ArgAddr)
3759 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
3762 /***********************************************************************
3763 * NdrConvert [RPCRT4.@]
3765 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
3767 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
3768 /* FIXME: since this stub doesn't do any converting, the proper behavior
3769 is to raise an exception */
3772 /***********************************************************************
3773 * NdrConvert2 [RPCRT4.@]
3775 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
3777 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
3778 pStubMsg, pFormat, NumberParams);
3779 /* FIXME: since this stub doesn't do any converting, the proper behavior
3780 is to raise an exception */
3783 #include "pshpack1.h"
3784 typedef struct _NDR_CSTRUCT_FORMAT
3786 unsigned char type;
3787 unsigned char alignment;
3788 unsigned short memory_size;
3789 short offset_to_array_description;
3790 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
3791 #include "poppack.h"
3793 /***********************************************************************
3794 * NdrConformantStructMarshall [RPCRT4.@]
3796 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3797 unsigned char *pMemory,
3798 PFORMAT_STRING pFormat)
3800 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3801 PFORMAT_STRING pCArrayFormat;
3802 ULONG esize, bufsize;
3804 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3806 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3807 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3809 ERR("invalid format type %x\n", pCStructFormat->type);
3810 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3811 return NULL;
3814 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3815 pCStructFormat->offset_to_array_description;
3816 if (*pCArrayFormat != RPC_FC_CARRAY)
3818 ERR("invalid array format type %x\n", pCStructFormat->type);
3819 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3820 return NULL;
3822 esize = *(const WORD*)(pCArrayFormat+2);
3824 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3825 pCArrayFormat + 4, 0);
3827 WriteConformance(pStubMsg);
3829 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3831 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3833 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3834 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3836 ERR("integer overflow of memory_size %u with bufsize %u\n",
3837 pCStructFormat->memory_size, bufsize);
3838 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3840 /* copy constant sized part of struct */
3841 pStubMsg->BufferMark = pStubMsg->Buffer;
3842 safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
3844 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3845 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3847 return NULL;
3850 /***********************************************************************
3851 * NdrConformantStructUnmarshall [RPCRT4.@]
3853 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3854 unsigned char **ppMemory,
3855 PFORMAT_STRING pFormat,
3856 unsigned char fMustAlloc)
3858 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3859 PFORMAT_STRING pCArrayFormat;
3860 ULONG esize, bufsize;
3861 unsigned char *saved_buffer;
3863 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3865 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3866 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3868 ERR("invalid format type %x\n", pCStructFormat->type);
3869 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3870 return NULL;
3872 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3873 pCStructFormat->offset_to_array_description;
3874 if (*pCArrayFormat != RPC_FC_CARRAY)
3876 ERR("invalid array format type %x\n", pCStructFormat->type);
3877 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3878 return NULL;
3880 esize = *(const WORD*)(pCArrayFormat+2);
3882 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
3884 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3886 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3888 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3889 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3891 ERR("integer overflow of memory_size %u with bufsize %u\n",
3892 pCStructFormat->memory_size, bufsize);
3893 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3896 if (fMustAlloc)
3898 SIZE_T size = pCStructFormat->memory_size + bufsize;
3899 *ppMemory = NdrAllocate(pStubMsg, size);
3901 else
3903 if (!pStubMsg->IsClient && !*ppMemory)
3904 /* for servers, we just point straight into the RPC buffer */
3905 *ppMemory = pStubMsg->Buffer;
3908 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3909 safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
3910 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3911 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3913 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
3914 if (*ppMemory != saved_buffer)
3915 memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
3917 return NULL;
3920 /***********************************************************************
3921 * NdrConformantStructBufferSize [RPCRT4.@]
3923 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3924 unsigned char *pMemory,
3925 PFORMAT_STRING pFormat)
3927 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3928 PFORMAT_STRING pCArrayFormat;
3929 ULONG esize;
3931 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3933 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3934 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3936 ERR("invalid format type %x\n", pCStructFormat->type);
3937 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3938 return;
3940 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3941 pCStructFormat->offset_to_array_description;
3942 if (*pCArrayFormat != RPC_FC_CARRAY)
3944 ERR("invalid array format type %x\n", pCStructFormat->type);
3945 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3946 return;
3948 esize = *(const WORD*)(pCArrayFormat+2);
3950 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
3951 SizeConformance(pStubMsg);
3953 ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
3955 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3957 safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
3958 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
3960 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3961 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3964 /***********************************************************************
3965 * NdrConformantStructMemorySize [RPCRT4.@]
3967 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3968 PFORMAT_STRING pFormat)
3970 FIXME("stub\n");
3971 return 0;
3974 /***********************************************************************
3975 * NdrConformantStructFree [RPCRT4.@]
3977 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3978 unsigned char *pMemory,
3979 PFORMAT_STRING pFormat)
3981 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3982 PFORMAT_STRING pCArrayFormat;
3983 ULONG esize;
3985 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3987 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3988 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3990 ERR("invalid format type %x\n", pCStructFormat->type);
3991 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3992 return;
3995 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3996 pCStructFormat->offset_to_array_description;
3997 if (*pCArrayFormat != RPC_FC_CARRAY)
3999 ERR("invalid array format type %x\n", pCStructFormat->type);
4000 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4001 return;
4003 esize = *(const WORD*)(pCArrayFormat+2);
4005 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4006 pCArrayFormat + 4, 0);
4008 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4010 /* copy constant sized part of struct */
4011 pStubMsg->BufferMark = pStubMsg->Buffer;
4013 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4014 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4017 /***********************************************************************
4018 * NdrConformantVaryingStructMarshall [RPCRT4.@]
4020 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4021 unsigned char *pMemory,
4022 PFORMAT_STRING pFormat)
4024 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4025 PFORMAT_STRING pCVArrayFormat;
4026 ULONG esize, bufsize;
4028 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4030 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4031 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4033 ERR("invalid format type %x\n", pCVStructFormat->type);
4034 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4035 return NULL;
4038 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4039 pCVStructFormat->offset_to_array_description;
4040 switch (*pCVArrayFormat)
4042 case RPC_FC_CVARRAY:
4043 esize = *(const WORD*)(pCVArrayFormat+2);
4045 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4046 pCVArrayFormat + 4, 0);
4047 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4048 pCVArrayFormat, 0);
4049 break;
4050 case RPC_FC_C_CSTRING:
4051 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4052 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4053 esize = sizeof(char);
4054 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4055 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4056 pCVArrayFormat + 2, 0);
4057 else
4058 pStubMsg->MaxCount = pStubMsg->ActualCount;
4059 break;
4060 case RPC_FC_C_WSTRING:
4061 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4062 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4063 esize = sizeof(WCHAR);
4064 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4065 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4066 pCVArrayFormat + 2, 0);
4067 else
4068 pStubMsg->MaxCount = pStubMsg->ActualCount;
4069 break;
4070 default:
4071 ERR("invalid array format type %x\n", *pCVArrayFormat);
4072 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4073 return NULL;
4076 WriteConformance(pStubMsg);
4078 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4080 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4082 /* write constant sized part */
4083 pStubMsg->BufferMark = pStubMsg->Buffer;
4084 safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
4086 WriteVariance(pStubMsg);
4088 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4090 /* write array part */
4091 safe_copy_to_buffer(pStubMsg, pMemory + pCVStructFormat->memory_size, bufsize);
4093 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4095 return NULL;
4098 /***********************************************************************
4099 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
4101 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4102 unsigned char **ppMemory,
4103 PFORMAT_STRING pFormat,
4104 unsigned char fMustAlloc)
4106 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4107 PFORMAT_STRING pCVArrayFormat;
4108 ULONG esize, bufsize;
4109 unsigned char cvarray_type;
4111 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4113 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4114 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4116 ERR("invalid format type %x\n", pCVStructFormat->type);
4117 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4118 return NULL;
4121 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4122 pCVStructFormat->offset_to_array_description;
4123 cvarray_type = *pCVArrayFormat;
4124 switch (cvarray_type)
4126 case RPC_FC_CVARRAY:
4127 esize = *(const WORD*)(pCVArrayFormat+2);
4128 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
4129 break;
4130 case RPC_FC_C_CSTRING:
4131 esize = sizeof(char);
4132 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4133 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4134 else
4135 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4136 break;
4137 case RPC_FC_C_WSTRING:
4138 esize = sizeof(WCHAR);
4139 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4140 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4141 else
4142 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4143 break;
4144 default:
4145 ERR("invalid array format type %x\n", *pCVArrayFormat);
4146 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4147 return NULL;
4150 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4152 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4154 /* work out how much memory to allocate if we need to do so */
4155 if (!*ppMemory || fMustAlloc)
4157 SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
4158 *ppMemory = NdrAllocate(pStubMsg, size);
4161 /* copy the constant data */
4162 pStubMsg->BufferMark = pStubMsg->Buffer;
4163 safe_copy_from_buffer(pStubMsg, *ppMemory, pCVStructFormat->memory_size);
4165 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
4167 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4169 if ((cvarray_type == RPC_FC_C_CSTRING) ||
4170 (cvarray_type == RPC_FC_C_WSTRING))
4172 ULONG i;
4173 /* strings must always have null terminating bytes */
4174 if (bufsize < esize)
4176 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
4177 RpcRaiseException(RPC_S_INVALID_BOUND);
4178 return NULL;
4180 for (i = bufsize - esize; i < bufsize; i++)
4181 if (pStubMsg->Buffer[i] != 0)
4183 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
4184 i, pStubMsg->Buffer[i]);
4185 RpcRaiseException(RPC_S_INVALID_BOUND);
4186 return NULL;
4190 /* copy the array data */
4191 safe_copy_from_buffer(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize);
4193 if (cvarray_type == RPC_FC_C_CSTRING)
4194 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
4195 else if (cvarray_type == RPC_FC_C_WSTRING)
4196 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
4198 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
4200 return NULL;
4203 /***********************************************************************
4204 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
4206 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4207 unsigned char *pMemory,
4208 PFORMAT_STRING pFormat)
4210 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4211 PFORMAT_STRING pCVArrayFormat;
4212 ULONG esize;
4214 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4216 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4217 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4219 ERR("invalid format type %x\n", pCVStructFormat->type);
4220 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4221 return;
4224 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4225 pCVStructFormat->offset_to_array_description;
4226 switch (*pCVArrayFormat)
4228 case RPC_FC_CVARRAY:
4229 esize = *(const WORD*)(pCVArrayFormat+2);
4231 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4232 pCVArrayFormat + 4, 0);
4233 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4234 pCVArrayFormat, 0);
4235 break;
4236 case RPC_FC_C_CSTRING:
4237 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4238 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4239 esize = sizeof(char);
4240 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4241 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4242 pCVArrayFormat + 2, 0);
4243 else
4244 pStubMsg->MaxCount = pStubMsg->ActualCount;
4245 break;
4246 case RPC_FC_C_WSTRING:
4247 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4248 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4249 esize = sizeof(WCHAR);
4250 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4251 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4252 pCVArrayFormat + 2, 0);
4253 else
4254 pStubMsg->MaxCount = pStubMsg->ActualCount;
4255 break;
4256 default:
4257 ERR("invalid array format type %x\n", *pCVArrayFormat);
4258 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4259 return;
4262 SizeConformance(pStubMsg);
4264 ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4266 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4268 safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4269 SizeVariance(pStubMsg);
4270 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4272 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4275 /***********************************************************************
4276 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
4278 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4279 PFORMAT_STRING pFormat)
4281 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4282 PFORMAT_STRING pCVArrayFormat;
4283 ULONG esize;
4284 unsigned char cvarray_type;
4286 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4288 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4289 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4291 ERR("invalid format type %x\n", pCVStructFormat->type);
4292 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4293 return 0;
4296 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4297 pCVStructFormat->offset_to_array_description;
4298 cvarray_type = *pCVArrayFormat;
4299 switch (cvarray_type)
4301 case RPC_FC_CVARRAY:
4302 esize = *(const WORD*)(pCVArrayFormat+2);
4303 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
4304 break;
4305 case RPC_FC_C_CSTRING:
4306 esize = sizeof(char);
4307 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4308 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4309 else
4310 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4311 break;
4312 case RPC_FC_C_WSTRING:
4313 esize = sizeof(WCHAR);
4314 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4315 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4316 else
4317 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4318 break;
4319 default:
4320 ERR("invalid array format type %x\n", *pCVArrayFormat);
4321 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4322 return 0;
4325 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4327 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4329 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4330 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
4331 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4333 pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
4335 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4337 return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
4340 /***********************************************************************
4341 * NdrConformantVaryingStructFree [RPCRT4.@]
4343 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4344 unsigned char *pMemory,
4345 PFORMAT_STRING pFormat)
4347 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4348 PFORMAT_STRING pCVArrayFormat;
4349 ULONG esize;
4351 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4353 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4354 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4356 ERR("invalid format type %x\n", pCVStructFormat->type);
4357 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4358 return;
4361 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4362 pCVStructFormat->offset_to_array_description;
4363 switch (*pCVArrayFormat)
4365 case RPC_FC_CVARRAY:
4366 esize = *(const WORD*)(pCVArrayFormat+2);
4368 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4369 pCVArrayFormat + 4, 0);
4370 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4371 pCVArrayFormat, 0);
4372 break;
4373 case RPC_FC_C_CSTRING:
4374 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4375 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4376 esize = sizeof(char);
4377 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4378 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4379 pCVArrayFormat + 2, 0);
4380 else
4381 pStubMsg->MaxCount = pStubMsg->ActualCount;
4382 break;
4383 case RPC_FC_C_WSTRING:
4384 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4385 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4386 esize = sizeof(WCHAR);
4387 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4388 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4389 pCVArrayFormat + 2, 0);
4390 else
4391 pStubMsg->MaxCount = pStubMsg->ActualCount;
4392 break;
4393 default:
4394 ERR("invalid array format type %x\n", *pCVArrayFormat);
4395 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4396 return;
4399 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4401 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4404 #include "pshpack1.h"
4405 typedef struct
4407 unsigned char type;
4408 unsigned char alignment;
4409 unsigned short total_size;
4410 } NDR_SMFARRAY_FORMAT;
4412 typedef struct
4414 unsigned char type;
4415 unsigned char alignment;
4416 unsigned long total_size;
4417 } NDR_LGFARRAY_FORMAT;
4418 #include "poppack.h"
4420 /***********************************************************************
4421 * NdrFixedArrayMarshall [RPCRT4.@]
4423 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4424 unsigned char *pMemory,
4425 PFORMAT_STRING pFormat)
4427 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4428 unsigned long total_size;
4430 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4432 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4433 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4435 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4436 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4437 return NULL;
4440 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4442 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4444 total_size = pSmFArrayFormat->total_size;
4445 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4447 else
4449 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4450 total_size = pLgFArrayFormat->total_size;
4451 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4454 pStubMsg->BufferMark = pStubMsg->Buffer;
4455 safe_copy_to_buffer(pStubMsg, pMemory, total_size);
4457 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4459 return NULL;
4462 /***********************************************************************
4463 * NdrFixedArrayUnmarshall [RPCRT4.@]
4465 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4466 unsigned char **ppMemory,
4467 PFORMAT_STRING pFormat,
4468 unsigned char fMustAlloc)
4470 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4471 unsigned long total_size;
4472 unsigned char *saved_buffer;
4474 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4476 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4477 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4479 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4480 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4481 return NULL;
4484 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4486 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4488 total_size = pSmFArrayFormat->total_size;
4489 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4491 else
4493 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4494 total_size = pLgFArrayFormat->total_size;
4495 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4498 if (fMustAlloc)
4499 *ppMemory = NdrAllocate(pStubMsg, total_size);
4500 else
4502 if (!pStubMsg->IsClient && !*ppMemory)
4503 /* for servers, we just point straight into the RPC buffer */
4504 *ppMemory = pStubMsg->Buffer;
4507 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4508 safe_buffer_increment(pStubMsg, total_size);
4509 pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4511 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4512 if (*ppMemory != saved_buffer)
4513 memcpy(*ppMemory, saved_buffer, total_size);
4515 return NULL;
4518 /***********************************************************************
4519 * NdrFixedArrayBufferSize [RPCRT4.@]
4521 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4522 unsigned char *pMemory,
4523 PFORMAT_STRING pFormat)
4525 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4526 unsigned long total_size;
4528 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4530 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4531 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4533 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4534 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4535 return;
4538 ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
4540 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4542 total_size = pSmFArrayFormat->total_size;
4543 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4545 else
4547 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4548 total_size = pLgFArrayFormat->total_size;
4549 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4551 safe_buffer_length_increment(pStubMsg, total_size);
4553 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4556 /***********************************************************************
4557 * NdrFixedArrayMemorySize [RPCRT4.@]
4559 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4560 PFORMAT_STRING pFormat)
4562 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4563 ULONG total_size;
4565 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4567 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4568 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4570 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4571 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4572 return 0;
4575 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4577 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4579 total_size = pSmFArrayFormat->total_size;
4580 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4582 else
4584 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4585 total_size = pLgFArrayFormat->total_size;
4586 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4588 pStubMsg->BufferMark = pStubMsg->Buffer;
4589 safe_buffer_increment(pStubMsg, total_size);
4590 pStubMsg->MemorySize += total_size;
4592 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4594 return total_size;
4597 /***********************************************************************
4598 * NdrFixedArrayFree [RPCRT4.@]
4600 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4601 unsigned char *pMemory,
4602 PFORMAT_STRING pFormat)
4604 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4606 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4608 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4609 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4611 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4612 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4613 return;
4616 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4617 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4618 else
4620 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4621 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4624 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4627 /***********************************************************************
4628 * NdrVaryingArrayMarshall [RPCRT4.@]
4630 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4631 unsigned char *pMemory,
4632 PFORMAT_STRING pFormat)
4634 unsigned char alignment;
4635 DWORD elements, esize;
4636 ULONG bufsize;
4638 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4640 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4641 (pFormat[0] != RPC_FC_LGVARRAY))
4643 ERR("invalid format type %x\n", pFormat[0]);
4644 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4645 return NULL;
4648 alignment = pFormat[1] + 1;
4650 if (pFormat[0] == RPC_FC_SMVARRAY)
4652 pFormat += 2;
4653 pFormat += sizeof(WORD);
4654 elements = *(const WORD*)pFormat;
4655 pFormat += sizeof(WORD);
4657 else
4659 pFormat += 2;
4660 pFormat += sizeof(DWORD);
4661 elements = *(const DWORD*)pFormat;
4662 pFormat += sizeof(DWORD);
4665 esize = *(const WORD*)pFormat;
4666 pFormat += sizeof(WORD);
4668 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4669 if ((pStubMsg->ActualCount > elements) ||
4670 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4672 RpcRaiseException(RPC_S_INVALID_BOUND);
4673 return NULL;
4676 WriteVariance(pStubMsg);
4678 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
4680 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4681 pStubMsg->BufferMark = pStubMsg->Buffer;
4682 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
4684 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4686 return NULL;
4689 /***********************************************************************
4690 * NdrVaryingArrayUnmarshall [RPCRT4.@]
4692 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4693 unsigned char **ppMemory,
4694 PFORMAT_STRING pFormat,
4695 unsigned char fMustAlloc)
4697 unsigned char alignment;
4698 DWORD size, elements, esize;
4699 ULONG bufsize;
4700 unsigned char *saved_buffer;
4701 ULONG offset;
4703 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4705 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4706 (pFormat[0] != RPC_FC_LGVARRAY))
4708 ERR("invalid format type %x\n", pFormat[0]);
4709 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4710 return NULL;
4713 alignment = pFormat[1] + 1;
4715 if (pFormat[0] == RPC_FC_SMVARRAY)
4717 pFormat += 2;
4718 size = *(const WORD*)pFormat;
4719 pFormat += sizeof(WORD);
4720 elements = *(const WORD*)pFormat;
4721 pFormat += sizeof(WORD);
4723 else
4725 pFormat += 2;
4726 size = *(const DWORD*)pFormat;
4727 pFormat += sizeof(DWORD);
4728 elements = *(const DWORD*)pFormat;
4729 pFormat += sizeof(DWORD);
4732 esize = *(const WORD*)pFormat;
4733 pFormat += sizeof(WORD);
4735 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4737 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4739 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4740 offset = pStubMsg->Offset;
4742 if (!*ppMemory || fMustAlloc)
4743 *ppMemory = NdrAllocate(pStubMsg, size);
4744 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4745 safe_buffer_increment(pStubMsg, bufsize);
4747 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4749 memcpy(*ppMemory + offset, saved_buffer, bufsize);
4751 return NULL;
4754 /***********************************************************************
4755 * NdrVaryingArrayBufferSize [RPCRT4.@]
4757 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4758 unsigned char *pMemory,
4759 PFORMAT_STRING pFormat)
4761 unsigned char alignment;
4762 DWORD elements, esize;
4764 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4766 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4767 (pFormat[0] != RPC_FC_LGVARRAY))
4769 ERR("invalid format type %x\n", pFormat[0]);
4770 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4771 return;
4774 alignment = pFormat[1] + 1;
4776 if (pFormat[0] == RPC_FC_SMVARRAY)
4778 pFormat += 2;
4779 pFormat += sizeof(WORD);
4780 elements = *(const WORD*)pFormat;
4781 pFormat += sizeof(WORD);
4783 else
4785 pFormat += 2;
4786 pFormat += sizeof(DWORD);
4787 elements = *(const DWORD*)pFormat;
4788 pFormat += sizeof(DWORD);
4791 esize = *(const WORD*)pFormat;
4792 pFormat += sizeof(WORD);
4794 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4795 if ((pStubMsg->ActualCount > elements) ||
4796 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4798 RpcRaiseException(RPC_S_INVALID_BOUND);
4799 return;
4802 SizeVariance(pStubMsg);
4804 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4806 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4808 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4811 /***********************************************************************
4812 * NdrVaryingArrayMemorySize [RPCRT4.@]
4814 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4815 PFORMAT_STRING pFormat)
4817 unsigned char alignment;
4818 DWORD size, elements, esize;
4820 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4822 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4823 (pFormat[0] != RPC_FC_LGVARRAY))
4825 ERR("invalid format type %x\n", pFormat[0]);
4826 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4827 return 0;
4830 alignment = pFormat[1] + 1;
4832 if (pFormat[0] == RPC_FC_SMVARRAY)
4834 pFormat += 2;
4835 size = *(const WORD*)pFormat;
4836 pFormat += sizeof(WORD);
4837 elements = *(const WORD*)pFormat;
4838 pFormat += sizeof(WORD);
4840 else
4842 pFormat += 2;
4843 size = *(const DWORD*)pFormat;
4844 pFormat += sizeof(DWORD);
4845 elements = *(const DWORD*)pFormat;
4846 pFormat += sizeof(DWORD);
4849 esize = *(const WORD*)pFormat;
4850 pFormat += sizeof(WORD);
4852 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4854 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4856 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4857 pStubMsg->MemorySize += size;
4859 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4861 return pStubMsg->MemorySize;
4864 /***********************************************************************
4865 * NdrVaryingArrayFree [RPCRT4.@]
4867 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4868 unsigned char *pMemory,
4869 PFORMAT_STRING pFormat)
4871 unsigned char alignment;
4872 DWORD elements;
4874 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4876 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4877 (pFormat[0] != RPC_FC_LGVARRAY))
4879 ERR("invalid format type %x\n", pFormat[0]);
4880 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4881 return;
4884 alignment = pFormat[1] + 1;
4886 if (pFormat[0] == RPC_FC_SMVARRAY)
4888 pFormat += 2;
4889 pFormat += sizeof(WORD);
4890 elements = *(const WORD*)pFormat;
4891 pFormat += sizeof(WORD);
4893 else
4895 pFormat += 2;
4896 pFormat += sizeof(DWORD);
4897 elements = *(const DWORD*)pFormat;
4898 pFormat += sizeof(DWORD);
4901 pFormat += sizeof(WORD);
4903 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4904 if ((pStubMsg->ActualCount > elements) ||
4905 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4907 RpcRaiseException(RPC_S_INVALID_BOUND);
4908 return;
4911 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4914 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
4916 switch (fc)
4918 case RPC_FC_BYTE:
4919 case RPC_FC_CHAR:
4920 case RPC_FC_SMALL:
4921 case RPC_FC_USMALL:
4922 return *(const UCHAR *)pMemory;
4923 case RPC_FC_WCHAR:
4924 case RPC_FC_SHORT:
4925 case RPC_FC_USHORT:
4926 case RPC_FC_ENUM16:
4927 return *(const USHORT *)pMemory;
4928 case RPC_FC_LONG:
4929 case RPC_FC_ULONG:
4930 case RPC_FC_ENUM32:
4931 return *(const ULONG *)pMemory;
4932 default:
4933 FIXME("Unhandled base type: 0x%02x\n", fc);
4934 return 0;
4938 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
4939 unsigned long discriminant,
4940 PFORMAT_STRING pFormat)
4942 unsigned short num_arms, arm, type;
4944 num_arms = *(const SHORT*)pFormat & 0x0fff;
4945 pFormat += 2;
4946 for(arm = 0; arm < num_arms; arm++)
4948 if(discriminant == *(const ULONG*)pFormat)
4950 pFormat += 4;
4951 break;
4953 pFormat += 6;
4956 type = *(const unsigned short*)pFormat;
4957 TRACE("type %04x\n", type);
4958 if(arm == num_arms) /* default arm extras */
4960 if(type == 0xffff)
4962 ERR("no arm for 0x%lx and no default case\n", discriminant);
4963 RpcRaiseException(RPC_S_INVALID_TAG);
4964 return NULL;
4966 if(type == 0)
4968 TRACE("falling back to empty default case for 0x%lx\n", discriminant);
4969 return NULL;
4972 return pFormat;
4975 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
4977 unsigned short type;
4979 pFormat += 2;
4981 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4982 if(!pFormat)
4983 return NULL;
4985 type = *(const unsigned short*)pFormat;
4986 if((type & 0xff00) == 0x8000)
4988 unsigned char basetype = LOBYTE(type);
4989 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4991 else
4993 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4994 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4995 if (m)
4997 unsigned char *saved_buffer = NULL;
4998 int pointer_buffer_mark_set = 0;
4999 switch(*desc)
5001 case RPC_FC_RP:
5002 case RPC_FC_UP:
5003 case RPC_FC_OP:
5004 case RPC_FC_FP:
5005 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
5006 saved_buffer = pStubMsg->Buffer;
5007 if (pStubMsg->PointerBufferMark)
5009 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5010 pStubMsg->PointerBufferMark = NULL;
5011 pointer_buffer_mark_set = 1;
5013 else
5014 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
5016 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
5017 if (pointer_buffer_mark_set)
5019 STD_OVERFLOW_CHECK(pStubMsg);
5020 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5021 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5023 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5024 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5025 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5027 pStubMsg->Buffer = saved_buffer + 4;
5029 break;
5030 default:
5031 m(pStubMsg, pMemory, desc);
5034 else FIXME("no marshaller for embedded type %02x\n", *desc);
5036 return NULL;
5039 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5040 unsigned char **ppMemory,
5041 ULONG discriminant,
5042 PFORMAT_STRING pFormat,
5043 unsigned char fMustAlloc)
5045 unsigned short type;
5047 pFormat += 2;
5049 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5050 if(!pFormat)
5051 return NULL;
5053 type = *(const unsigned short*)pFormat;
5054 if((type & 0xff00) == 0x8000)
5056 unsigned char basetype = LOBYTE(type);
5057 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
5059 else
5061 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5062 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
5063 if (m)
5065 unsigned char *saved_buffer = NULL;
5066 int pointer_buffer_mark_set = 0;
5067 switch(*desc)
5069 case RPC_FC_RP:
5070 case RPC_FC_UP:
5071 case RPC_FC_OP:
5072 case RPC_FC_FP:
5073 **(void***)ppMemory = NULL;
5074 ALIGN_POINTER(pStubMsg->Buffer, 4);
5075 saved_buffer = pStubMsg->Buffer;
5076 if (pStubMsg->PointerBufferMark)
5078 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5079 pStubMsg->PointerBufferMark = NULL;
5080 pointer_buffer_mark_set = 1;
5082 else
5083 pStubMsg->Buffer += 4; /* for pointer ID */
5085 if (saved_buffer + 4 > pStubMsg->BufferEnd)
5087 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5088 saved_buffer, pStubMsg->BufferEnd);
5089 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5092 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
5093 if (pointer_buffer_mark_set)
5095 STD_OVERFLOW_CHECK(pStubMsg);
5096 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5097 pStubMsg->Buffer = saved_buffer + 4;
5099 break;
5100 default:
5101 m(pStubMsg, ppMemory, desc, fMustAlloc);
5104 else FIXME("no marshaller for embedded type %02x\n", *desc);
5106 return NULL;
5109 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
5110 unsigned char *pMemory,
5111 ULONG discriminant,
5112 PFORMAT_STRING pFormat)
5114 unsigned short type;
5116 pFormat += 2;
5118 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5119 if(!pFormat)
5120 return;
5122 type = *(const unsigned short*)pFormat;
5123 if((type & 0xff00) == 0x8000)
5125 unsigned char basetype = LOBYTE(type);
5126 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
5128 else
5130 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5131 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
5132 if (m)
5134 switch(*desc)
5136 case RPC_FC_RP:
5137 case RPC_FC_UP:
5138 case RPC_FC_OP:
5139 case RPC_FC_FP:
5140 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5141 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
5142 if (!pStubMsg->IgnoreEmbeddedPointers)
5144 int saved_buffer_length = pStubMsg->BufferLength;
5145 pStubMsg->BufferLength = pStubMsg->PointerLength;
5146 pStubMsg->PointerLength = 0;
5147 if(!pStubMsg->BufferLength)
5148 ERR("BufferLength == 0??\n");
5149 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
5150 pStubMsg->PointerLength = pStubMsg->BufferLength;
5151 pStubMsg->BufferLength = saved_buffer_length;
5153 break;
5154 default:
5155 m(pStubMsg, pMemory, desc);
5158 else FIXME("no buffersizer for embedded type %02x\n", *desc);
5162 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
5163 ULONG discriminant,
5164 PFORMAT_STRING pFormat)
5166 unsigned short type, size;
5168 size = *(const unsigned short*)pFormat;
5169 pStubMsg->Memory += size;
5170 pFormat += 2;
5172 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5173 if(!pFormat)
5174 return 0;
5176 type = *(const unsigned short*)pFormat;
5177 if((type & 0xff00) == 0x8000)
5179 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
5181 else
5183 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5184 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
5185 unsigned char *saved_buffer;
5186 if (m)
5188 switch(*desc)
5190 case RPC_FC_RP:
5191 case RPC_FC_UP:
5192 case RPC_FC_OP:
5193 case RPC_FC_FP:
5194 ALIGN_POINTER(pStubMsg->Buffer, 4);
5195 saved_buffer = pStubMsg->Buffer;
5196 safe_buffer_increment(pStubMsg, 4);
5197 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
5198 pStubMsg->MemorySize += 4;
5199 if (!pStubMsg->IgnoreEmbeddedPointers)
5200 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
5201 break;
5202 default:
5203 return m(pStubMsg, desc);
5206 else FIXME("no marshaller for embedded type %02x\n", *desc);
5209 TRACE("size %d\n", size);
5210 return size;
5213 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
5214 unsigned char *pMemory,
5215 ULONG discriminant,
5216 PFORMAT_STRING pFormat)
5218 unsigned short type;
5220 pFormat += 2;
5222 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5223 if(!pFormat)
5224 return;
5226 type = *(const unsigned short*)pFormat;
5227 if((type & 0xff00) != 0x8000)
5229 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5230 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5231 if (m)
5233 switch(*desc)
5235 case RPC_FC_RP:
5236 case RPC_FC_UP:
5237 case RPC_FC_OP:
5238 case RPC_FC_FP:
5239 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5240 break;
5241 default:
5242 m(pStubMsg, pMemory, desc);
5245 else FIXME("no freer for embedded type %02x\n", *desc);
5249 /***********************************************************************
5250 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
5252 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5253 unsigned char *pMemory,
5254 PFORMAT_STRING pFormat)
5256 unsigned char switch_type;
5257 unsigned char increment;
5258 ULONG switch_value;
5260 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5261 pFormat++;
5263 switch_type = *pFormat & 0xf;
5264 increment = (*pFormat & 0xf0) >> 4;
5265 pFormat++;
5267 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment);
5269 switch_value = get_discriminant(switch_type, pMemory);
5270 TRACE("got switch value 0x%x\n", switch_value);
5272 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5273 pMemory += increment;
5275 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5278 /***********************************************************************
5279 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5281 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5282 unsigned char **ppMemory,
5283 PFORMAT_STRING pFormat,
5284 unsigned char fMustAlloc)
5286 unsigned char switch_type;
5287 unsigned char increment;
5288 ULONG switch_value;
5289 unsigned short size;
5290 unsigned char *pMemoryArm;
5292 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5293 pFormat++;
5295 switch_type = *pFormat & 0xf;
5296 increment = (*pFormat & 0xf0) >> 4;
5297 pFormat++;
5299 ALIGN_POINTER(pStubMsg->Buffer, increment);
5300 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5301 TRACE("got switch value 0x%x\n", switch_value);
5303 size = *(const unsigned short*)pFormat + increment;
5304 if(!*ppMemory || fMustAlloc)
5305 *ppMemory = NdrAllocate(pStubMsg, size);
5307 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5308 pMemoryArm = *ppMemory + increment;
5310 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
5313 /***********************************************************************
5314 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5316 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5317 unsigned char *pMemory,
5318 PFORMAT_STRING pFormat)
5320 unsigned char switch_type;
5321 unsigned char increment;
5322 ULONG switch_value;
5324 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5325 pFormat++;
5327 switch_type = *pFormat & 0xf;
5328 increment = (*pFormat & 0xf0) >> 4;
5329 pFormat++;
5331 ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5332 switch_value = get_discriminant(switch_type, pMemory);
5333 TRACE("got switch value 0x%x\n", switch_value);
5335 /* Add discriminant size */
5336 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5337 pMemory += increment;
5339 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5342 /***********************************************************************
5343 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5345 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5346 PFORMAT_STRING pFormat)
5348 unsigned char switch_type;
5349 unsigned char increment;
5350 ULONG switch_value;
5352 switch_type = *pFormat & 0xf;
5353 increment = (*pFormat & 0xf0) >> 4;
5354 pFormat++;
5356 ALIGN_POINTER(pStubMsg->Buffer, increment);
5357 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5358 TRACE("got switch value 0x%x\n", switch_value);
5360 pStubMsg->Memory += increment;
5362 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5365 /***********************************************************************
5366 * NdrEncapsulatedUnionFree [RPCRT4.@]
5368 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5369 unsigned char *pMemory,
5370 PFORMAT_STRING pFormat)
5372 unsigned char switch_type;
5373 unsigned char increment;
5374 ULONG switch_value;
5376 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5377 pFormat++;
5379 switch_type = *pFormat & 0xf;
5380 increment = (*pFormat & 0xf0) >> 4;
5381 pFormat++;
5383 switch_value = get_discriminant(switch_type, pMemory);
5384 TRACE("got switch value 0x%x\n", switch_value);
5386 pMemory += increment;
5388 return union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5391 /***********************************************************************
5392 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5394 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5395 unsigned char *pMemory,
5396 PFORMAT_STRING pFormat)
5398 unsigned char switch_type;
5400 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5401 pFormat++;
5403 switch_type = *pFormat;
5404 pFormat++;
5406 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5407 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5408 /* Marshall discriminant */
5409 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5411 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5414 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
5415 PFORMAT_STRING *ppFormat)
5417 long discriminant = 0;
5419 switch(**ppFormat)
5421 case RPC_FC_BYTE:
5422 case RPC_FC_CHAR:
5423 case RPC_FC_SMALL:
5424 case RPC_FC_USMALL:
5426 UCHAR d;
5427 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5428 discriminant = d;
5429 break;
5431 case RPC_FC_WCHAR:
5432 case RPC_FC_SHORT:
5433 case RPC_FC_USHORT:
5435 USHORT d;
5436 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5437 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5438 discriminant = d;
5439 break;
5441 case RPC_FC_LONG:
5442 case RPC_FC_ULONG:
5444 ULONG d;
5445 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5446 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5447 discriminant = d;
5448 break;
5450 default:
5451 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
5453 (*ppFormat)++;
5455 if (pStubMsg->fHasNewCorrDesc)
5456 *ppFormat += 6;
5457 else
5458 *ppFormat += 4;
5459 return discriminant;
5462 /**********************************************************************
5463 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
5465 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5466 unsigned char **ppMemory,
5467 PFORMAT_STRING pFormat,
5468 unsigned char fMustAlloc)
5470 long discriminant;
5471 unsigned short size;
5473 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5474 pFormat++;
5476 /* Unmarshall discriminant */
5477 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5478 TRACE("unmarshalled discriminant %lx\n", discriminant);
5480 pFormat += *(const SHORT*)pFormat;
5482 size = *(const unsigned short*)pFormat;
5484 if(!*ppMemory || fMustAlloc)
5485 *ppMemory = NdrAllocate(pStubMsg, size);
5487 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
5490 /***********************************************************************
5491 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
5493 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5494 unsigned char *pMemory,
5495 PFORMAT_STRING pFormat)
5497 unsigned char switch_type;
5499 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5500 pFormat++;
5502 switch_type = *pFormat;
5503 pFormat++;
5505 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5506 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5507 /* Add discriminant size */
5508 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5510 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5513 /***********************************************************************
5514 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
5516 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5517 PFORMAT_STRING pFormat)
5519 ULONG discriminant;
5521 pFormat++;
5522 /* Unmarshall discriminant */
5523 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5524 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
5526 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
5529 /***********************************************************************
5530 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
5532 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5533 unsigned char *pMemory,
5534 PFORMAT_STRING pFormat)
5536 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5537 pFormat++;
5538 pFormat++;
5540 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5541 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5543 return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5546 /***********************************************************************
5547 * NdrByteCountPointerMarshall [RPCRT4.@]
5549 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5550 unsigned char *pMemory,
5551 PFORMAT_STRING pFormat)
5553 FIXME("stub\n");
5554 return NULL;
5557 /***********************************************************************
5558 * NdrByteCountPointerUnmarshall [RPCRT4.@]
5560 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5561 unsigned char **ppMemory,
5562 PFORMAT_STRING pFormat,
5563 unsigned char fMustAlloc)
5565 FIXME("stub\n");
5566 return NULL;
5569 /***********************************************************************
5570 * NdrByteCountPointerBufferSize [RPCRT4.@]
5572 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5573 unsigned char *pMemory,
5574 PFORMAT_STRING pFormat)
5576 FIXME("stub\n");
5579 /***********************************************************************
5580 * NdrByteCountPointerMemorySize [RPCRT4.@]
5582 ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5583 PFORMAT_STRING pFormat)
5585 FIXME("stub\n");
5586 return 0;
5589 /***********************************************************************
5590 * NdrByteCountPointerFree [RPCRT4.@]
5592 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
5593 unsigned char *pMemory,
5594 PFORMAT_STRING pFormat)
5596 FIXME("stub\n");
5599 /***********************************************************************
5600 * NdrXmitOrRepAsMarshall [RPCRT4.@]
5602 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5603 unsigned char *pMemory,
5604 PFORMAT_STRING pFormat)
5606 FIXME("stub\n");
5607 return NULL;
5610 /***********************************************************************
5611 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
5613 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5614 unsigned char **ppMemory,
5615 PFORMAT_STRING pFormat,
5616 unsigned char fMustAlloc)
5618 FIXME("stub\n");
5619 return NULL;
5622 /***********************************************************************
5623 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
5625 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5626 unsigned char *pMemory,
5627 PFORMAT_STRING pFormat)
5629 FIXME("stub\n");
5632 /***********************************************************************
5633 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
5635 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5636 PFORMAT_STRING pFormat)
5638 FIXME("stub\n");
5639 return 0;
5642 /***********************************************************************
5643 * NdrXmitOrRepAsFree [RPCRT4.@]
5645 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
5646 unsigned char *pMemory,
5647 PFORMAT_STRING pFormat)
5649 FIXME("stub\n");
5652 #include "pshpack1.h"
5653 typedef struct
5655 unsigned char type;
5656 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
5657 ULONG low_value;
5658 ULONG high_value;
5659 } NDR_RANGE;
5660 #include "poppack.h"
5662 /***********************************************************************
5663 * NdrRangeMarshall [internal]
5665 unsigned char *WINAPI NdrRangeMarshall(
5666 PMIDL_STUB_MESSAGE pStubMsg,
5667 unsigned char *pMemory,
5668 PFORMAT_STRING pFormat)
5670 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5671 unsigned char base_type;
5673 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5675 if (pRange->type != RPC_FC_RANGE)
5677 ERR("invalid format type %x\n", pRange->type);
5678 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5679 return NULL;
5682 base_type = pRange->flags_type & 0xf;
5684 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
5687 /***********************************************************************
5688 * NdrRangeUnmarshall
5690 unsigned char *WINAPI NdrRangeUnmarshall(
5691 PMIDL_STUB_MESSAGE pStubMsg,
5692 unsigned char **ppMemory,
5693 PFORMAT_STRING pFormat,
5694 unsigned char fMustAlloc)
5696 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5697 unsigned char base_type;
5699 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5701 if (pRange->type != RPC_FC_RANGE)
5703 ERR("invalid format type %x\n", pRange->type);
5704 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5705 return NULL;
5707 base_type = pRange->flags_type & 0xf;
5709 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
5710 base_type, pRange->low_value, pRange->high_value);
5712 #define RANGE_UNMARSHALL(type, format_spec) \
5713 do \
5715 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5716 if (fMustAlloc || !*ppMemory) \
5717 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5718 if (pStubMsg->Buffer + sizeof(type) > pStubMsg->BufferEnd) \
5720 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
5721 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
5722 RpcRaiseException(RPC_X_BAD_STUB_DATA); \
5724 if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \
5725 (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \
5727 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
5728 *(type *)pStubMsg->Buffer, (type)pRange->low_value, \
5729 (type)pRange->high_value); \
5730 RpcRaiseException(RPC_S_INVALID_BOUND); \
5731 return NULL; \
5733 TRACE("*ppMemory: %p\n", *ppMemory); \
5734 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5735 pStubMsg->Buffer += sizeof(type); \
5736 } while (0)
5738 switch(base_type)
5740 case RPC_FC_CHAR:
5741 case RPC_FC_SMALL:
5742 RANGE_UNMARSHALL(UCHAR, "%d");
5743 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5744 break;
5745 case RPC_FC_BYTE:
5746 case RPC_FC_USMALL:
5747 RANGE_UNMARSHALL(CHAR, "%u");
5748 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5749 break;
5750 case RPC_FC_WCHAR: /* FIXME: valid? */
5751 case RPC_FC_USHORT:
5752 RANGE_UNMARSHALL(USHORT, "%u");
5753 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5754 break;
5755 case RPC_FC_SHORT:
5756 RANGE_UNMARSHALL(SHORT, "%d");
5757 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5758 break;
5759 case RPC_FC_LONG:
5760 RANGE_UNMARSHALL(LONG, "%d");
5761 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5762 break;
5763 case RPC_FC_ULONG:
5764 RANGE_UNMARSHALL(ULONG, "%u");
5765 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5766 break;
5767 case RPC_FC_ENUM16:
5768 case RPC_FC_ENUM32:
5769 FIXME("Unhandled enum type\n");
5770 break;
5771 case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */
5772 case RPC_FC_FLOAT:
5773 case RPC_FC_DOUBLE:
5774 case RPC_FC_HYPER:
5775 default:
5776 ERR("invalid range base type: 0x%02x\n", base_type);
5777 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5780 return NULL;
5783 /***********************************************************************
5784 * NdrRangeBufferSize [internal]
5786 void WINAPI NdrRangeBufferSize(
5787 PMIDL_STUB_MESSAGE pStubMsg,
5788 unsigned char *pMemory,
5789 PFORMAT_STRING pFormat)
5791 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5792 unsigned char base_type;
5794 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5796 if (pRange->type != RPC_FC_RANGE)
5798 ERR("invalid format type %x\n", pRange->type);
5799 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5801 base_type = pRange->flags_type & 0xf;
5803 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
5806 /***********************************************************************
5807 * NdrRangeMemorySize [internal]
5809 ULONG WINAPI NdrRangeMemorySize(
5810 PMIDL_STUB_MESSAGE pStubMsg,
5811 PFORMAT_STRING pFormat)
5813 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5814 unsigned char base_type;
5816 if (pRange->type != RPC_FC_RANGE)
5818 ERR("invalid format type %x\n", pRange->type);
5819 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5820 return 0;
5822 base_type = pRange->flags_type & 0xf;
5824 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
5827 /***********************************************************************
5828 * NdrRangeFree [internal]
5830 void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
5831 unsigned char *pMemory,
5832 PFORMAT_STRING pFormat)
5834 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5836 /* nothing to do */
5839 /***********************************************************************
5840 * NdrBaseTypeMarshall [internal]
5842 static unsigned char *WINAPI NdrBaseTypeMarshall(
5843 PMIDL_STUB_MESSAGE pStubMsg,
5844 unsigned char *pMemory,
5845 PFORMAT_STRING pFormat)
5847 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5849 switch(*pFormat)
5851 case RPC_FC_BYTE:
5852 case RPC_FC_CHAR:
5853 case RPC_FC_SMALL:
5854 case RPC_FC_USMALL:
5855 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
5856 TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
5857 break;
5858 case RPC_FC_WCHAR:
5859 case RPC_FC_SHORT:
5860 case RPC_FC_USHORT:
5861 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
5862 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
5863 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
5864 break;
5865 case RPC_FC_LONG:
5866 case RPC_FC_ULONG:
5867 case RPC_FC_ERROR_STATUS_T:
5868 case RPC_FC_ENUM32:
5869 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG));
5870 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
5871 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
5872 break;
5873 case RPC_FC_FLOAT:
5874 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float));
5875 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
5876 break;
5877 case RPC_FC_DOUBLE:
5878 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double));
5879 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
5880 break;
5881 case RPC_FC_HYPER:
5882 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG));
5883 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
5884 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
5885 break;
5886 case RPC_FC_ENUM16:
5887 /* only 16-bits on the wire, so do a sanity check */
5888 if (*(UINT *)pMemory > SHRT_MAX)
5889 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
5890 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
5891 if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5892 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5893 *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
5894 pStubMsg->Buffer += sizeof(USHORT);
5895 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
5896 break;
5897 case RPC_FC_IGNORE:
5898 break;
5899 default:
5900 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5903 /* FIXME: what is the correct return value? */
5904 return NULL;
5907 /***********************************************************************
5908 * NdrBaseTypeUnmarshall [internal]
5910 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
5911 PMIDL_STUB_MESSAGE pStubMsg,
5912 unsigned char **ppMemory,
5913 PFORMAT_STRING pFormat,
5914 unsigned char fMustAlloc)
5916 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5918 #define BASE_TYPE_UNMARSHALL(type) \
5919 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5920 if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
5922 *ppMemory = pStubMsg->Buffer; \
5923 TRACE("*ppMemory: %p\n", *ppMemory); \
5925 else \
5927 if (fMustAlloc) \
5928 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5929 TRACE("*ppMemory: %p\n", *ppMemory); \
5930 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5932 pStubMsg->Buffer += sizeof(type);
5934 switch(*pFormat)
5936 case RPC_FC_BYTE:
5937 case RPC_FC_CHAR:
5938 case RPC_FC_SMALL:
5939 case RPC_FC_USMALL:
5940 BASE_TYPE_UNMARSHALL(UCHAR);
5941 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5942 break;
5943 case RPC_FC_WCHAR:
5944 case RPC_FC_SHORT:
5945 case RPC_FC_USHORT:
5946 BASE_TYPE_UNMARSHALL(USHORT);
5947 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5948 break;
5949 case RPC_FC_LONG:
5950 case RPC_FC_ULONG:
5951 case RPC_FC_ERROR_STATUS_T:
5952 case RPC_FC_ENUM32:
5953 BASE_TYPE_UNMARSHALL(ULONG);
5954 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5955 break;
5956 case RPC_FC_FLOAT:
5957 BASE_TYPE_UNMARSHALL(float);
5958 TRACE("value: %f\n", **(float **)ppMemory);
5959 break;
5960 case RPC_FC_DOUBLE:
5961 BASE_TYPE_UNMARSHALL(double);
5962 TRACE("value: %f\n", **(double **)ppMemory);
5963 break;
5964 case RPC_FC_HYPER:
5965 BASE_TYPE_UNMARSHALL(ULONGLONG);
5966 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
5967 break;
5968 case RPC_FC_ENUM16:
5969 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5970 if (fMustAlloc || !*ppMemory)
5971 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
5972 if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
5973 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5974 TRACE("*ppMemory: %p\n", *ppMemory);
5975 /* 16-bits on the wire, but int in memory */
5976 **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
5977 pStubMsg->Buffer += sizeof(USHORT);
5978 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
5979 break;
5980 case RPC_FC_IGNORE:
5981 break;
5982 default:
5983 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5985 #undef BASE_TYPE_UNMARSHALL
5987 /* FIXME: what is the correct return value? */
5989 return NULL;
5992 /***********************************************************************
5993 * NdrBaseTypeBufferSize [internal]
5995 static void WINAPI NdrBaseTypeBufferSize(
5996 PMIDL_STUB_MESSAGE pStubMsg,
5997 unsigned char *pMemory,
5998 PFORMAT_STRING pFormat)
6000 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6002 switch(*pFormat)
6004 case RPC_FC_BYTE:
6005 case RPC_FC_CHAR:
6006 case RPC_FC_SMALL:
6007 case RPC_FC_USMALL:
6008 safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6009 break;
6010 case RPC_FC_WCHAR:
6011 case RPC_FC_SHORT:
6012 case RPC_FC_USHORT:
6013 case RPC_FC_ENUM16:
6014 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
6015 safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6016 break;
6017 case RPC_FC_LONG:
6018 case RPC_FC_ULONG:
6019 case RPC_FC_ENUM32:
6020 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
6021 safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6022 break;
6023 case RPC_FC_FLOAT:
6024 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
6025 safe_buffer_length_increment(pStubMsg, sizeof(float));
6026 break;
6027 case RPC_FC_DOUBLE:
6028 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
6029 safe_buffer_length_increment(pStubMsg, sizeof(double));
6030 break;
6031 case RPC_FC_HYPER:
6032 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
6033 safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6034 break;
6035 case RPC_FC_ERROR_STATUS_T:
6036 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
6037 safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6038 break;
6039 case RPC_FC_IGNORE:
6040 break;
6041 default:
6042 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6046 /***********************************************************************
6047 * NdrBaseTypeMemorySize [internal]
6049 static ULONG WINAPI NdrBaseTypeMemorySize(
6050 PMIDL_STUB_MESSAGE pStubMsg,
6051 PFORMAT_STRING pFormat)
6053 TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6055 switch(*pFormat)
6057 case RPC_FC_BYTE:
6058 case RPC_FC_CHAR:
6059 case RPC_FC_SMALL:
6060 case RPC_FC_USMALL:
6061 safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6062 pStubMsg->MemorySize += sizeof(UCHAR);
6063 return sizeof(UCHAR);
6064 case RPC_FC_WCHAR:
6065 case RPC_FC_SHORT:
6066 case RPC_FC_USHORT:
6067 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6068 pStubMsg->MemorySize += sizeof(USHORT);
6069 return sizeof(USHORT);
6070 case RPC_FC_LONG:
6071 case RPC_FC_ULONG:
6072 case RPC_FC_ENUM32:
6073 safe_buffer_increment(pStubMsg, sizeof(ULONG));
6074 pStubMsg->MemorySize += sizeof(ULONG);
6075 return sizeof(ULONG);
6076 case RPC_FC_FLOAT:
6077 safe_buffer_increment(pStubMsg, sizeof(float));
6078 pStubMsg->MemorySize += sizeof(float);
6079 return sizeof(float);
6080 case RPC_FC_DOUBLE:
6081 safe_buffer_increment(pStubMsg, sizeof(double));
6082 pStubMsg->MemorySize += sizeof(double);
6083 return sizeof(double);
6084 case RPC_FC_HYPER:
6085 safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6086 pStubMsg->MemorySize += sizeof(ULONGLONG);
6087 return sizeof(ULONGLONG);
6088 case RPC_FC_ERROR_STATUS_T:
6089 safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6090 pStubMsg->MemorySize += sizeof(error_status_t);
6091 return sizeof(error_status_t);
6092 case RPC_FC_ENUM16:
6093 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6094 pStubMsg->MemorySize += sizeof(UINT);
6095 return sizeof(UINT);
6096 case RPC_FC_IGNORE:
6097 pStubMsg->MemorySize += sizeof(void *);
6098 return sizeof(void *);
6099 default:
6100 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6101 return 0;
6105 /***********************************************************************
6106 * NdrBaseTypeFree [internal]
6108 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6109 unsigned char *pMemory,
6110 PFORMAT_STRING pFormat)
6112 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6114 /* nothing to do */
6117 /***********************************************************************
6118 * NdrContextHandleBufferSize [internal]
6120 static void WINAPI NdrContextHandleBufferSize(
6121 PMIDL_STUB_MESSAGE pStubMsg,
6122 unsigned char *pMemory,
6123 PFORMAT_STRING pFormat)
6125 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6127 if (*pFormat != RPC_FC_BIND_CONTEXT)
6129 ERR("invalid format type %x\n", *pFormat);
6130 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6132 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
6133 safe_buffer_length_increment(pStubMsg, cbNDRContext);
6136 /***********************************************************************
6137 * NdrContextHandleMarshall [internal]
6139 static unsigned char *WINAPI NdrContextHandleMarshall(
6140 PMIDL_STUB_MESSAGE pStubMsg,
6141 unsigned char *pMemory,
6142 PFORMAT_STRING pFormat)
6144 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6146 if (*pFormat != RPC_FC_BIND_CONTEXT)
6148 ERR("invalid format type %x\n", *pFormat);
6149 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6152 if (pFormat[1] & 0x80)
6153 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6154 else
6155 NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE);
6157 return NULL;
6160 /***********************************************************************
6161 * NdrContextHandleUnmarshall [internal]
6163 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6164 PMIDL_STUB_MESSAGE pStubMsg,
6165 unsigned char **ppMemory,
6166 PFORMAT_STRING pFormat,
6167 unsigned char fMustAlloc)
6169 if (*pFormat != RPC_FC_BIND_CONTEXT)
6171 ERR("invalid format type %x\n", *pFormat);
6172 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6175 **(NDR_CCONTEXT **)ppMemory = NULL;
6176 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
6178 return NULL;
6181 /***********************************************************************
6182 * NdrClientContextMarshall [RPCRT4.@]
6184 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6185 NDR_CCONTEXT ContextHandle,
6186 int fCheck)
6188 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
6190 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
6192 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6194 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6195 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6196 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6199 /* FIXME: what does fCheck do? */
6200 NDRCContextMarshall(ContextHandle,
6201 pStubMsg->Buffer);
6203 pStubMsg->Buffer += cbNDRContext;
6206 /***********************************************************************
6207 * NdrClientContextUnmarshall [RPCRT4.@]
6209 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6210 NDR_CCONTEXT * pContextHandle,
6211 RPC_BINDING_HANDLE BindHandle)
6213 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
6215 ALIGN_POINTER(pStubMsg->Buffer, 4);
6217 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
6218 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6220 NDRCContextUnmarshall(pContextHandle,
6221 BindHandle,
6222 pStubMsg->Buffer,
6223 pStubMsg->RpcMsg->DataRepresentation);
6225 pStubMsg->Buffer += cbNDRContext;
6228 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6229 NDR_SCONTEXT ContextHandle,
6230 NDR_RUNDOWN RundownRoutine )
6232 TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
6234 ALIGN_POINTER(pStubMsg->Buffer, 4);
6236 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6238 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6239 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6240 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6243 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6244 pStubMsg->Buffer, RundownRoutine, NULL,
6245 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6246 pStubMsg->Buffer += cbNDRContext;
6249 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
6251 NDR_SCONTEXT ContextHandle;
6253 TRACE("(%p)\n", pStubMsg);
6255 ALIGN_POINTER(pStubMsg->Buffer, 4);
6257 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6259 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6260 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6261 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6264 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6265 pStubMsg->Buffer,
6266 pStubMsg->RpcMsg->DataRepresentation,
6267 NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
6268 pStubMsg->Buffer += cbNDRContext;
6270 return ContextHandle;
6273 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
6274 unsigned char* pMemory,
6275 PFORMAT_STRING pFormat)
6277 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
6280 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
6281 PFORMAT_STRING pFormat)
6283 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6284 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6286 TRACE("(%p, %p)\n", pStubMsg, pFormat);
6288 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6289 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6290 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6291 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6292 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6294 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6295 if_id = &sif->InterfaceId;
6298 return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
6299 pStubMsg->RpcMsg->DataRepresentation, if_id,
6300 flags);
6303 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6304 NDR_SCONTEXT ContextHandle,
6305 NDR_RUNDOWN RundownRoutine,
6306 PFORMAT_STRING pFormat)
6308 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6309 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6311 TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
6313 ALIGN_POINTER(pStubMsg->Buffer, 4);
6315 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6317 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6318 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6319 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6322 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6323 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6324 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6325 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6326 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6328 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6329 if_id = &sif->InterfaceId;
6332 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
6333 pStubMsg->Buffer, RundownRoutine, if_id, flags);
6334 pStubMsg->Buffer += cbNDRContext;
6337 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6338 PFORMAT_STRING pFormat)
6340 NDR_SCONTEXT ContextHandle;
6341 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
6342 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
6344 TRACE("(%p, %p)\n", pStubMsg, pFormat);
6346 ALIGN_POINTER(pStubMsg->Buffer, 4);
6348 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
6350 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
6351 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
6352 RpcRaiseException(RPC_X_BAD_STUB_DATA);
6355 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
6356 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
6357 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
6358 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
6359 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
6361 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
6362 if_id = &sif->InterfaceId;
6365 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
6366 pStubMsg->Buffer,
6367 pStubMsg->RpcMsg->DataRepresentation,
6368 if_id, flags);
6369 pStubMsg->Buffer += cbNDRContext;
6371 return ContextHandle;
6374 /***********************************************************************
6375 * NdrCorrelationInitialize [RPCRT4.@]
6377 * Initializes correlation validity checking.
6379 * PARAMS
6380 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
6381 * pMemory [I] Pointer to memory to use as a cache.
6382 * CacheSize [I] Size of the memory pointed to by pMemory.
6383 * Flags [I] Reserved. Set to zero.
6385 * RETURNS
6386 * Nothing.
6388 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
6390 FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
6391 pStubMsg->fHasNewCorrDesc = TRUE;
6394 /***********************************************************************
6395 * NdrCorrelationPass [RPCRT4.@]
6397 * Performs correlation validity checking.
6399 * PARAMS
6400 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
6402 * RETURNS
6403 * Nothing.
6405 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
6407 FIXME("(%p): stub\n", pStubMsg);
6410 /***********************************************************************
6411 * NdrCorrelationFree [RPCRT4.@]
6413 * Frees any resources used while unmarshalling parameters that need
6414 * correlation validity checking.
6416 * PARAMS
6417 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
6419 * RETURNS
6420 * Nothing.
6422 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
6424 FIXME("(%p): stub\n", pStubMsg);