rpcrt4: Document NdrAllocate.
[wine/testsucceed.git] / dlls / rpcrt4 / ndr_marshall.c
blob0efa4d2db7df4839e2adfdb604a8ae307d94b864
1 /*
2 * NDR data marshalling
4 * Copyright 2002 Greg Turner
5 * Copyright 2003-2006 CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * TODO:
22 * - Non-conformant strings
23 * - String structs
24 * - Byte count pointers
25 * - transmit_as/represent as
26 * - Multi-dimensional arrays
27 * - Conversion functions (NdrConvert)
28 * - Checks for integer addition overflow
29 * - Checks for out-of-memory conditions
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <limits.h>
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winerror.h"
42 #include "ndr_misc.h"
43 #include "rpcndr.h"
45 #include "wine/unicode.h"
46 #include "wine/rpcfc.h"
48 #include "wine/debug.h"
49 #include "wine/list.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(ole);
53 #if defined(__i386__)
54 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
55 (*((UINT32 *)(pchar)) = (uint32))
57 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
58 (*((UINT32 *)(pchar)))
59 #else
60 /* these would work for i386 too, but less efficient */
61 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
62 (*(pchar) = LOBYTE(LOWORD(uint32)), \
63 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
64 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
65 *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
66 (uint32)) /* allow as r-value */
68 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
69 (MAKELONG( \
70 MAKEWORD(*(pchar), *((pchar)+1)), \
71 MAKEWORD(*((pchar)+2), *((pchar)+3))))
72 #endif
74 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
75 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
76 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
77 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
78 *(pchar) = HIBYTE(HIWORD(uint32)), \
79 (uint32)) /* allow as r-value */
81 #define BIG_ENDIAN_UINT32_READ(pchar) \
82 (MAKELONG( \
83 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
84 MAKEWORD(*((pchar)+1), *(pchar))))
86 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
87 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
88 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
89 # define NDR_LOCAL_UINT32_READ(pchar) \
90 BIG_ENDIAN_UINT32_READ(pchar)
91 #else
92 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
93 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
94 # define NDR_LOCAL_UINT32_READ(pchar) \
95 LITTLE_ENDIAN_UINT32_READ(pchar)
96 #endif
98 /* _Align must be the desired alignment,
99 * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
100 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
101 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
102 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
103 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
105 #define STD_OVERFLOW_CHECK(_Msg) do { \
106 TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
107 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
108 ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
109 } while (0)
111 #define NDR_TABLE_SIZE 128
112 #define NDR_TABLE_MASK 127
114 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
115 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
116 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
117 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
118 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
120 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
121 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
122 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
124 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
126 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
127 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
128 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
129 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
130 /* 0x10 */
131 NdrBaseTypeMarshall,
132 /* 0x11 */
133 NdrPointerMarshall, NdrPointerMarshall,
134 NdrPointerMarshall, NdrPointerMarshall,
135 /* 0x15 */
136 NdrSimpleStructMarshall, NdrSimpleStructMarshall,
137 NdrConformantStructMarshall, NdrConformantStructMarshall,
138 NdrConformantVaryingStructMarshall,
139 NdrComplexStructMarshall,
140 /* 0x1b */
141 NdrConformantArrayMarshall,
142 NdrConformantVaryingArrayMarshall,
143 NdrFixedArrayMarshall, NdrFixedArrayMarshall,
144 NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
145 NdrComplexArrayMarshall,
146 /* 0x22 */
147 NdrConformantStringMarshall, 0, 0,
148 NdrConformantStringMarshall,
149 NdrNonConformantStringMarshall, 0, 0, 0,
150 /* 0x2a */
151 NdrEncapsulatedUnionMarshall,
152 NdrNonEncapsulatedUnionMarshall,
153 NdrByteCountPointerMarshall,
154 NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
155 /* 0x2f */
156 NdrInterfacePointerMarshall,
157 /* 0x30 */
158 NdrContextHandleMarshall,
159 /* 0xb1 */
160 0, 0, 0,
161 NdrUserMarshalMarshall,
162 0, 0,
163 /* 0xb7 */
164 NdrRangeMarshall
166 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
168 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
169 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
170 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
171 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
172 /* 0x10 */
173 NdrBaseTypeUnmarshall,
174 /* 0x11 */
175 NdrPointerUnmarshall, NdrPointerUnmarshall,
176 NdrPointerUnmarshall, NdrPointerUnmarshall,
177 /* 0x15 */
178 NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
179 NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
180 NdrConformantVaryingStructUnmarshall,
181 NdrComplexStructUnmarshall,
182 /* 0x1b */
183 NdrConformantArrayUnmarshall,
184 NdrConformantVaryingArrayUnmarshall,
185 NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
186 NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
187 NdrComplexArrayUnmarshall,
188 /* 0x22 */
189 NdrConformantStringUnmarshall, 0, 0,
190 NdrConformantStringUnmarshall,
191 NdrNonConformantStringUnmarshall, 0, 0, 0,
192 /* 0x2a */
193 NdrEncapsulatedUnionUnmarshall,
194 NdrNonEncapsulatedUnionUnmarshall,
195 NdrByteCountPointerUnmarshall,
196 NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
197 /* 0x2f */
198 NdrInterfacePointerUnmarshall,
199 /* 0x30 */
200 NdrContextHandleUnmarshall,
201 /* 0xb1 */
202 0, 0, 0,
203 NdrUserMarshalUnmarshall,
204 0, 0,
205 /* 0xb7 */
206 NdrRangeUnmarshall
208 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
210 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
211 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
212 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
213 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
214 /* 0x10 */
215 NdrBaseTypeBufferSize,
216 /* 0x11 */
217 NdrPointerBufferSize, NdrPointerBufferSize,
218 NdrPointerBufferSize, NdrPointerBufferSize,
219 /* 0x15 */
220 NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
221 NdrConformantStructBufferSize, NdrConformantStructBufferSize,
222 NdrConformantVaryingStructBufferSize,
223 NdrComplexStructBufferSize,
224 /* 0x1b */
225 NdrConformantArrayBufferSize,
226 NdrConformantVaryingArrayBufferSize,
227 NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
228 NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
229 NdrComplexArrayBufferSize,
230 /* 0x22 */
231 NdrConformantStringBufferSize, 0, 0,
232 NdrConformantStringBufferSize,
233 NdrNonConformantStringBufferSize, 0, 0, 0,
234 /* 0x2a */
235 NdrEncapsulatedUnionBufferSize,
236 NdrNonEncapsulatedUnionBufferSize,
237 NdrByteCountPointerBufferSize,
238 NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
239 /* 0x2f */
240 NdrInterfacePointerBufferSize,
241 /* 0x30 */
242 NdrContextHandleBufferSize,
243 /* 0xb1 */
244 0, 0, 0,
245 NdrUserMarshalBufferSize,
246 0, 0,
247 /* 0xb7 */
248 NdrRangeBufferSize
250 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
252 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
253 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
254 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
255 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
256 /* 0x10 */
257 NdrBaseTypeMemorySize,
258 /* 0x11 */
259 NdrPointerMemorySize, NdrPointerMemorySize,
260 NdrPointerMemorySize, NdrPointerMemorySize,
261 /* 0x15 */
262 NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
263 NdrConformantStructMemorySize, NdrConformantStructMemorySize,
264 NdrConformantVaryingStructMemorySize,
265 NdrComplexStructMemorySize,
266 /* 0x1b */
267 NdrConformantArrayMemorySize,
268 NdrConformantVaryingArrayMemorySize,
269 NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
270 NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
271 NdrComplexArrayMemorySize,
272 /* 0x22 */
273 NdrConformantStringMemorySize, 0, 0,
274 NdrConformantStringMemorySize,
275 NdrNonConformantStringMemorySize, 0, 0, 0,
276 /* 0x2a */
277 NdrEncapsulatedUnionMemorySize,
278 NdrNonEncapsulatedUnionMemorySize,
279 NdrByteCountPointerMemorySize,
280 NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
281 /* 0x2f */
282 NdrInterfacePointerMemorySize,
283 /* 0x30 */
285 /* 0xb1 */
286 0, 0, 0,
287 NdrUserMarshalMemorySize,
288 0, 0,
289 /* 0xb7 */
290 NdrRangeMemorySize
292 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
294 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
295 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
296 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
297 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
298 /* 0x10 */
299 NdrBaseTypeFree,
300 /* 0x11 */
301 NdrPointerFree, NdrPointerFree,
302 NdrPointerFree, NdrPointerFree,
303 /* 0x15 */
304 NdrSimpleStructFree, NdrSimpleStructFree,
305 NdrConformantStructFree, NdrConformantStructFree,
306 NdrConformantVaryingStructFree,
307 NdrComplexStructFree,
308 /* 0x1b */
309 NdrConformantArrayFree,
310 NdrConformantVaryingArrayFree,
311 NdrFixedArrayFree, NdrFixedArrayFree,
312 NdrVaryingArrayFree, NdrVaryingArrayFree,
313 NdrComplexArrayFree,
314 /* 0x22 */
315 0, 0, 0,
316 0, 0, 0, 0, 0,
317 /* 0x2a */
318 NdrEncapsulatedUnionFree,
319 NdrNonEncapsulatedUnionFree,
321 NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
322 /* 0x2f */
323 NdrInterfacePointerFree,
324 /* 0x30 */
326 /* 0xb1 */
327 0, 0, 0,
328 NdrUserMarshalFree,
329 0, 0,
330 /* 0xb7 */
331 NdrRangeFree
334 typedef struct _NDR_MEMORY_LIST
336 ULONG magic;
337 ULONG size;
338 ULONG reserved;
339 struct _NDR_MEMORY_LIST *next;
340 } NDR_MEMORY_LIST;
342 #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
344 /***********************************************************************
345 * NdrAllocate [RPCRT4.@]
347 * Allocates a block of memory using pStubMsg->pfnAllocate.
349 * PARAMS
350 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
351 * len [I] Size of memory block to allocate.
353 * RETURNS
354 * The memory block of size len that was allocated.
356 * NOTES
357 * The memory block is always 8-byte aligned.
358 * If the function is unable to allocate memory an ERROR_OUTOFMEMORY
359 * exception is raised.
361 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
363 size_t aligned_len;
364 size_t adjusted_len;
365 void *p;
366 NDR_MEMORY_LIST *mem_list;
368 aligned_len = ALIGNED_LENGTH(len, 8);
369 adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
370 /* check for overflow */
371 if (adjusted_len < len)
373 ERR("overflow of adjusted_len %d, len %d\n", adjusted_len, len);
374 RpcRaiseException(RPC_X_BAD_STUB_DATA);
377 p = pStubMsg->pfnAllocate(adjusted_len);
378 if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
380 mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
381 mem_list->magic = MEML_MAGIC;
382 mem_list->size = aligned_len;
383 mem_list->reserved = 0;
384 mem_list->next = pStubMsg->pMemoryList;
385 pStubMsg->pMemoryList = mem_list;
387 TRACE("-- %p\n", p);
388 return p;
391 static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
393 TRACE("(%p, %p)\n", pStubMsg, Pointer);
395 pStubMsg->pfnFree(Pointer);
398 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
400 return (*(const ULONG *)pFormat != -1);
403 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
405 ALIGN_POINTER(pStubMsg->Buffer, 4);
406 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
407 RpcRaiseException(RPC_X_BAD_STUB_DATA);
408 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
409 pStubMsg->Buffer += 4;
410 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
411 if (pStubMsg->fHasNewCorrDesc)
412 return pFormat+6;
413 else
414 return pFormat+4;
417 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
419 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
421 pStubMsg->Offset = 0;
422 pStubMsg->ActualCount = pStubMsg->MaxCount;
423 goto done;
426 ALIGN_POINTER(pStubMsg->Buffer, 4);
427 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
428 RpcRaiseException(RPC_X_BAD_STUB_DATA);
429 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
430 pStubMsg->Buffer += 4;
431 TRACE("offset is %d\n", pStubMsg->Offset);
432 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
433 pStubMsg->Buffer += 4;
434 TRACE("variance is %d\n", pStubMsg->ActualCount);
436 if ((pStubMsg->ActualCount > MaxValue) ||
437 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
439 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
440 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
441 RpcRaiseException(RPC_S_INVALID_BOUND);
442 return NULL;
445 done:
446 if (pStubMsg->fHasNewCorrDesc)
447 return pFormat+6;
448 else
449 return pFormat+4;
452 /* writes the conformance value to the buffer */
453 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
455 ALIGN_POINTER(pStubMsg->Buffer, 4);
456 if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
457 RpcRaiseException(RPC_X_BAD_STUB_DATA);
458 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
459 pStubMsg->Buffer += 4;
462 /* writes the variance values to the buffer */
463 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
465 ALIGN_POINTER(pStubMsg->Buffer, 4);
466 if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
467 RpcRaiseException(RPC_X_BAD_STUB_DATA);
468 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
469 pStubMsg->Buffer += 4;
470 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
471 pStubMsg->Buffer += 4;
474 /* requests buffer space for the conformance value */
475 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
477 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
478 if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
479 RpcRaiseException(RPC_X_BAD_STUB_DATA);
480 pStubMsg->BufferLength += 4;
483 /* requests buffer space for the variance values */
484 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
486 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
487 if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
488 RpcRaiseException(RPC_X_BAD_STUB_DATA);
489 pStubMsg->BufferLength += 8;
492 PFORMAT_STRING ComputeConformanceOrVariance(
493 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
494 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
496 BYTE dtype = pFormat[0] & 0xf;
497 short ofs = *(const short *)&pFormat[2];
498 LPVOID ptr = NULL;
499 DWORD data = 0;
501 if (!IsConformanceOrVariancePresent(pFormat)) {
502 /* null descriptor */
503 *pCount = def;
504 goto finish_conf;
507 switch (pFormat[0] & 0xf0) {
508 case RPC_FC_NORMAL_CONFORMANCE:
509 TRACE("normal conformance, ofs=%d\n", ofs);
510 ptr = pMemory;
511 break;
512 case RPC_FC_POINTER_CONFORMANCE:
513 TRACE("pointer conformance, ofs=%d\n", ofs);
514 ptr = pStubMsg->Memory;
515 break;
516 case RPC_FC_TOP_LEVEL_CONFORMANCE:
517 TRACE("toplevel conformance, ofs=%d\n", ofs);
518 if (pStubMsg->StackTop) {
519 ptr = pStubMsg->StackTop;
521 else {
522 /* -Os mode, *pCount is already set */
523 goto finish_conf;
525 break;
526 case RPC_FC_CONSTANT_CONFORMANCE:
527 data = ofs | ((DWORD)pFormat[1] << 16);
528 TRACE("constant conformance, val=%d\n", data);
529 *pCount = data;
530 goto finish_conf;
531 case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
532 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
533 if (pStubMsg->StackTop) {
534 ptr = pStubMsg->StackTop;
536 else {
537 /* ? */
538 goto done_conf_grab;
540 break;
541 default:
542 FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
545 switch (pFormat[1]) {
546 case RPC_FC_DEREFERENCE:
547 ptr = *(LPVOID*)((char *)ptr + ofs);
548 break;
549 case RPC_FC_CALLBACK:
551 unsigned char *old_stack_top = pStubMsg->StackTop;
552 pStubMsg->StackTop = ptr;
554 /* ofs is index into StubDesc->apfnExprEval */
555 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
556 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
558 pStubMsg->StackTop = old_stack_top;
560 /* the callback function always stores the computed value in MaxCount */
561 *pCount = pStubMsg->MaxCount;
562 goto finish_conf;
564 default:
565 ptr = (char *)ptr + ofs;
566 break;
569 switch (dtype) {
570 case RPC_FC_LONG:
571 case RPC_FC_ULONG:
572 data = *(DWORD*)ptr;
573 break;
574 case RPC_FC_SHORT:
575 data = *(SHORT*)ptr;
576 break;
577 case RPC_FC_USHORT:
578 data = *(USHORT*)ptr;
579 break;
580 case RPC_FC_CHAR:
581 case RPC_FC_SMALL:
582 data = *(CHAR*)ptr;
583 break;
584 case RPC_FC_BYTE:
585 case RPC_FC_USMALL:
586 data = *(UCHAR*)ptr;
587 break;
588 default:
589 FIXME("unknown conformance data type %x\n", dtype);
590 goto done_conf_grab;
592 TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
594 done_conf_grab:
595 switch (pFormat[1]) {
596 case RPC_FC_DEREFERENCE: /* already handled */
597 case 0: /* no op */
598 *pCount = data;
599 break;
600 case RPC_FC_ADD_1:
601 *pCount = data + 1;
602 break;
603 case RPC_FC_SUB_1:
604 *pCount = data - 1;
605 break;
606 case RPC_FC_MULT_2:
607 *pCount = data * 2;
608 break;
609 case RPC_FC_DIV_2:
610 *pCount = data / 2;
611 break;
612 default:
613 FIXME("unknown conformance op %d\n", pFormat[1]);
614 goto finish_conf;
617 finish_conf:
618 TRACE("resulting conformance is %ld\n", *pCount);
619 if (pStubMsg->fHasNewCorrDesc)
620 return pFormat+6;
621 else
622 return pFormat+4;
625 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
626 * the result overflows 32-bits */
627 static inline ULONG safe_multiply(ULONG a, ULONG b)
629 ULONGLONG ret = (ULONGLONG)a * b;
630 if (ret > 0xffffffff)
632 RpcRaiseException(RPC_S_INVALID_BOUND);
633 return 0;
635 return ret;
638 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
640 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
641 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
642 RpcRaiseException(RPC_X_BAD_STUB_DATA);
643 pStubMsg->Buffer += size;
646 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
648 if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
650 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
651 pStubMsg->BufferLength, size);
652 RpcRaiseException(RPC_X_BAD_STUB_DATA);
654 pStubMsg->BufferLength += size;
657 /* copies data from the buffer, checking that there is enough data in the buffer
658 * to do so */
659 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
661 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
662 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
663 RpcRaiseException(RPC_X_BAD_STUB_DATA);
664 memcpy(p, pStubMsg->Buffer, size);
665 pStubMsg->Buffer += size;
668 /* copies data to the buffer, checking that there is enough space to do so */
669 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
671 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
672 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
674 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
675 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
676 size);
677 RpcRaiseException(RPC_X_BAD_STUB_DATA);
679 memcpy(pStubMsg->Buffer, p, size);
680 pStubMsg->Buffer += size;
684 * NdrConformantString:
686 * What MS calls a ConformantString is, in DCE terminology,
687 * a Varying-Conformant String.
689 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
690 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
691 * into unmarshalled string)
692 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
693 * [
694 * data: CHARTYPE[maxlen]
695 * ]
696 * ], where CHARTYPE is the appropriate character type (specified externally)
700 /***********************************************************************
701 * NdrConformantStringMarshall [RPCRT4.@]
703 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
704 unsigned char *pszMessage, PFORMAT_STRING pFormat)
706 ULONG esize, size;
708 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
710 if (*pFormat == RPC_FC_C_CSTRING) {
711 TRACE("string=%s\n", debugstr_a((char*)pszMessage));
712 pStubMsg->ActualCount = strlen((char*)pszMessage)+1;
713 esize = 1;
715 else if (*pFormat == RPC_FC_C_WSTRING) {
716 TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
717 pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1;
718 esize = 2;
720 else {
721 ERR("Unhandled string type: %#x\n", *pFormat);
722 /* FIXME: raise an exception. */
723 return NULL;
726 if (pFormat[1] == RPC_FC_STRING_SIZED)
727 pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0);
728 else
729 pStubMsg->MaxCount = pStubMsg->ActualCount;
730 pStubMsg->Offset = 0;
731 WriteConformance(pStubMsg);
732 WriteVariance(pStubMsg);
734 size = safe_multiply(esize, pStubMsg->ActualCount);
735 safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */
737 /* success */
738 return NULL; /* is this always right? */
741 /***********************************************************************
742 * NdrConformantStringBufferSize [RPCRT4.@]
744 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
745 unsigned char* pMemory, PFORMAT_STRING pFormat)
747 ULONG esize;
749 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
751 SizeConformance(pStubMsg);
752 SizeVariance(pStubMsg);
754 if (*pFormat == RPC_FC_C_CSTRING) {
755 TRACE("string=%s\n", debugstr_a((char*)pMemory));
756 pStubMsg->ActualCount = strlen((char*)pMemory)+1;
757 esize = 1;
759 else if (*pFormat == RPC_FC_C_WSTRING) {
760 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
761 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1;
762 esize = 2;
764 else {
765 ERR("Unhandled string type: %#x\n", *pFormat);
766 /* FIXME: raise an exception */
767 return;
770 if (pFormat[1] == RPC_FC_STRING_SIZED)
771 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
772 else
773 pStubMsg->MaxCount = pStubMsg->ActualCount;
775 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
778 /************************************************************************
779 * NdrConformantStringMemorySize [RPCRT4.@]
781 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
782 PFORMAT_STRING pFormat )
784 ULONG rslt = 0;
786 FIXME("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
788 assert(pStubMsg && pFormat);
790 if (*pFormat == RPC_FC_C_CSTRING) {
791 rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
793 else if (*pFormat == RPC_FC_C_WSTRING) {
794 rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */
796 else {
797 ERR("Unhandled string type: %#x\n", *pFormat);
798 /* FIXME: raise an exception */
801 if (pFormat[1] != RPC_FC_PAD) {
802 FIXME("sized string format=%d\n", pFormat[1]);
805 TRACE(" --> %u\n", rslt);
806 return rslt;
809 /************************************************************************
810 * NdrConformantStringUnmarshall [RPCRT4.@]
812 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
813 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
815 ULONG bufsize, memsize, esize, i;
817 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
818 pStubMsg, *ppMemory, pFormat, fMustAlloc);
820 assert(pFormat && ppMemory && pStubMsg);
822 ReadConformance(pStubMsg, NULL);
823 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
825 if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
826 else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
827 else {
828 ERR("Unhandled string type: %#x\n", *pFormat);
829 /* FIXME: raise an exception */
830 esize = 0;
833 memsize = safe_multiply(esize, pStubMsg->MaxCount);
834 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
836 /* strings must always have null terminating bytes */
837 if (bufsize < esize)
839 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
840 RpcRaiseException(RPC_S_INVALID_BOUND);
841 return NULL;
844 /* verify the buffer is safe to access */
845 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
846 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
848 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
849 pStubMsg->BufferEnd, pStubMsg->Buffer);
850 RpcRaiseException(RPC_X_BAD_STUB_DATA);
851 return NULL;
854 for (i = bufsize - esize; i < bufsize; i++)
855 if (pStubMsg->Buffer[i] != 0)
857 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
858 i, pStubMsg->Buffer[i]);
859 RpcRaiseException(RPC_S_INVALID_BOUND);
860 return NULL;
863 if (fMustAlloc || !*ppMemory)
864 *ppMemory = NdrAllocate(pStubMsg, memsize);
866 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
868 if (*pFormat == RPC_FC_C_CSTRING) {
869 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
871 else if (*pFormat == RPC_FC_C_WSTRING) {
872 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
875 return NULL; /* FIXME: is this always right? */
878 /***********************************************************************
879 * NdrNonConformantStringMarshall [RPCRT4.@]
881 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
882 unsigned char *pMemory,
883 PFORMAT_STRING pFormat)
885 FIXME("stub\n");
886 return NULL;
889 /***********************************************************************
890 * NdrNonConformantStringUnmarshall [RPCRT4.@]
892 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
893 unsigned char **ppMemory,
894 PFORMAT_STRING pFormat,
895 unsigned char fMustAlloc)
897 FIXME("stub\n");
898 return NULL;
901 /***********************************************************************
902 * NdrNonConformantStringBufferSize [RPCRT4.@]
904 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
905 unsigned char *pMemory,
906 PFORMAT_STRING pFormat)
908 FIXME("stub\n");
911 /***********************************************************************
912 * NdrNonConformantStringMemorySize [RPCRT4.@]
914 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
915 PFORMAT_STRING pFormat)
917 FIXME("stub\n");
918 return 0;
921 static inline void dump_pointer_attr(unsigned char attr)
923 if (attr & RPC_FC_P_ALLOCALLNODES)
924 TRACE(" RPC_FC_P_ALLOCALLNODES");
925 if (attr & RPC_FC_P_DONTFREE)
926 TRACE(" RPC_FC_P_DONTFREE");
927 if (attr & RPC_FC_P_ONSTACK)
928 TRACE(" RPC_FC_P_ONSTACK");
929 if (attr & RPC_FC_P_SIMPLEPOINTER)
930 TRACE(" RPC_FC_P_SIMPLEPOINTER");
931 if (attr & RPC_FC_P_DEREF)
932 TRACE(" RPC_FC_P_DEREF");
933 TRACE("\n");
936 /***********************************************************************
937 * PointerMarshall [internal]
939 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
940 unsigned char *Buffer,
941 unsigned char *Pointer,
942 PFORMAT_STRING pFormat)
944 unsigned type = pFormat[0], attr = pFormat[1];
945 PFORMAT_STRING desc;
946 NDR_MARSHALL m;
947 ULONG pointer_id;
948 int pointer_needs_marshaling;
950 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
951 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
952 pFormat += 2;
953 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
954 else desc = pFormat + *(const SHORT*)pFormat;
956 switch (type) {
957 case RPC_FC_RP: /* ref pointer (always non-null) */
958 if (!Pointer)
960 ERR("NULL ref pointer is not allowed\n");
961 RpcRaiseException(RPC_X_NULL_REF_POINTER);
963 pointer_needs_marshaling = 1;
964 break;
965 case RPC_FC_UP: /* unique pointer */
966 case RPC_FC_OP: /* object pointer - same as unique here */
967 if (Pointer)
968 pointer_needs_marshaling = 1;
969 else
970 pointer_needs_marshaling = 0;
971 pointer_id = (ULONG)Pointer;
972 TRACE("writing 0x%08x to buffer\n", pointer_id);
973 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
974 break;
975 case RPC_FC_FP:
976 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
977 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
978 TRACE("writing 0x%08x to buffer\n", pointer_id);
979 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
980 break;
981 default:
982 FIXME("unhandled ptr type=%02x\n", type);
983 RpcRaiseException(RPC_X_BAD_STUB_DATA);
984 return;
987 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
989 if (pointer_needs_marshaling) {
990 if (attr & RPC_FC_P_DEREF) {
991 Pointer = *(unsigned char**)Pointer;
992 TRACE("deref => %p\n", Pointer);
994 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
995 if (m) m(pStubMsg, Pointer, desc);
996 else FIXME("no marshaller for data type=%02x\n", *desc);
999 STD_OVERFLOW_CHECK(pStubMsg);
1002 /***********************************************************************
1003 * PointerUnmarshall [internal]
1005 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1006 unsigned char *Buffer,
1007 unsigned char **pPointer,
1008 unsigned char *pSrcPointer,
1009 PFORMAT_STRING pFormat,
1010 unsigned char fMustAlloc)
1012 unsigned type = pFormat[0], attr = pFormat[1];
1013 PFORMAT_STRING desc;
1014 NDR_UNMARSHALL m;
1015 DWORD pointer_id = 0;
1016 int pointer_needs_unmarshaling;
1018 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
1019 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1020 pFormat += 2;
1021 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1022 else desc = pFormat + *(const SHORT*)pFormat;
1024 switch (type) {
1025 case RPC_FC_RP: /* ref pointer (always non-null) */
1026 pointer_needs_unmarshaling = 1;
1027 break;
1028 case RPC_FC_UP: /* unique pointer */
1029 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1030 TRACE("pointer_id is 0x%08x\n", pointer_id);
1031 if (pointer_id)
1032 pointer_needs_unmarshaling = 1;
1033 else {
1034 *pPointer = NULL;
1035 pointer_needs_unmarshaling = 0;
1037 break;
1038 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1039 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1040 TRACE("pointer_id is 0x%08x\n", pointer_id);
1041 if (!fMustAlloc && pSrcPointer)
1043 FIXME("free object pointer %p\n", pSrcPointer);
1044 fMustAlloc = TRUE;
1046 if (pointer_id)
1047 pointer_needs_unmarshaling = 1;
1048 else
1049 pointer_needs_unmarshaling = 0;
1050 break;
1051 case RPC_FC_FP:
1052 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1053 TRACE("pointer_id is 0x%08x\n", pointer_id);
1054 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
1055 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
1056 break;
1057 default:
1058 FIXME("unhandled ptr type=%02x\n", type);
1059 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1060 return;
1063 if (pointer_needs_unmarshaling) {
1064 unsigned char *base_ptr_val = *pPointer;
1065 unsigned char **current_ptr = pPointer;
1066 if (pStubMsg->IsClient) {
1067 TRACE("client\n");
1068 /* if we aren't forcing allocation of memory then try to use the existing
1069 * (source) pointer to unmarshall the data into so that [in,out]
1070 * parameters behave correctly. it doesn't matter if the parameter is
1071 * [out] only since in that case the pointer will be NULL. we force
1072 * allocation when the source pointer is NULL here instead of in the type
1073 * unmarshalling routine for the benefit of the deref code below */
1074 if (!fMustAlloc) {
1075 if (pSrcPointer) {
1076 TRACE("setting *pPointer to %p\n", pSrcPointer);
1077 *pPointer = base_ptr_val = pSrcPointer;
1078 } else
1079 fMustAlloc = TRUE;
1081 } else {
1082 TRACE("server\n");
1083 /* the memory in a stub is never initialised, so we have to work out here
1084 * whether we have to initialise it so we can use the optimisation of
1085 * setting the pointer to the buffer, if possible, or set fMustAlloc to
1086 * TRUE. */
1087 if (attr & RPC_FC_P_DEREF) {
1088 fMustAlloc = TRUE;
1089 } else {
1090 base_ptr_val = NULL;
1091 *current_ptr = NULL;
1095 if (attr & RPC_FC_P_DEREF) {
1096 if (fMustAlloc) {
1097 base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
1098 *pPointer = base_ptr_val;
1099 current_ptr = (unsigned char **)base_ptr_val;
1100 } else
1101 current_ptr = *(unsigned char***)current_ptr;
1102 TRACE("deref => %p\n", current_ptr);
1103 if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
1105 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1106 if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
1107 else FIXME("no unmarshaller for data type=%02x\n", *desc);
1109 if (type == RPC_FC_FP)
1110 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
1111 base_ptr_val);
1114 TRACE("pointer=%p\n", *pPointer);
1117 /***********************************************************************
1118 * PointerBufferSize [internal]
1120 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1121 unsigned char *Pointer,
1122 PFORMAT_STRING pFormat)
1124 unsigned type = pFormat[0], attr = pFormat[1];
1125 PFORMAT_STRING desc;
1126 NDR_BUFFERSIZE m;
1127 int pointer_needs_sizing;
1128 ULONG pointer_id;
1130 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1131 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1132 pFormat += 2;
1133 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1134 else desc = pFormat + *(const SHORT*)pFormat;
1136 switch (type) {
1137 case RPC_FC_RP: /* ref pointer (always non-null) */
1138 if (!Pointer)
1140 ERR("NULL ref pointer is not allowed\n");
1141 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1143 break;
1144 case RPC_FC_OP:
1145 case RPC_FC_UP:
1146 /* NULL pointer has no further representation */
1147 if (!Pointer)
1148 return;
1149 break;
1150 case RPC_FC_FP:
1151 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1152 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1153 if (!pointer_needs_sizing)
1154 return;
1155 break;
1156 default:
1157 FIXME("unhandled ptr type=%02x\n", type);
1158 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1159 return;
1162 if (attr & RPC_FC_P_DEREF) {
1163 Pointer = *(unsigned char**)Pointer;
1164 TRACE("deref => %p\n", Pointer);
1167 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1168 if (m) m(pStubMsg, Pointer, desc);
1169 else FIXME("no buffersizer for data type=%02x\n", *desc);
1172 /***********************************************************************
1173 * PointerMemorySize [internal]
1175 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1176 unsigned char *Buffer,
1177 PFORMAT_STRING pFormat)
1179 unsigned type = pFormat[0], attr = pFormat[1];
1180 PFORMAT_STRING desc;
1181 NDR_MEMORYSIZE m;
1182 DWORD pointer_id = 0;
1183 int pointer_needs_sizing;
1185 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1186 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1187 pFormat += 2;
1188 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1189 else desc = pFormat + *(const SHORT*)pFormat;
1191 switch (type) {
1192 case RPC_FC_RP: /* ref pointer (always non-null) */
1193 pointer_needs_sizing = 1;
1194 break;
1195 case RPC_FC_UP: /* unique pointer */
1196 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1197 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1198 TRACE("pointer_id is 0x%08x\n", pointer_id);
1199 if (pointer_id)
1200 pointer_needs_sizing = 1;
1201 else
1202 pointer_needs_sizing = 0;
1203 break;
1204 case RPC_FC_FP:
1206 void *pointer;
1207 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1208 TRACE("pointer_id is 0x%08x\n", pointer_id);
1209 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1210 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1211 break;
1213 default:
1214 FIXME("unhandled ptr type=%02x\n", type);
1215 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1216 return 0;
1219 if (attr & RPC_FC_P_DEREF) {
1220 TRACE("deref\n");
1223 if (pointer_needs_sizing) {
1224 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1225 if (m) m(pStubMsg, desc);
1226 else FIXME("no memorysizer for data type=%02x\n", *desc);
1229 return pStubMsg->MemorySize;
1232 /***********************************************************************
1233 * PointerFree [internal]
1235 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1236 unsigned char *Pointer,
1237 PFORMAT_STRING pFormat)
1239 unsigned type = pFormat[0], attr = pFormat[1];
1240 PFORMAT_STRING desc;
1241 NDR_FREE m;
1242 unsigned char *current_pointer = Pointer;
1244 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1245 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1246 if (attr & RPC_FC_P_DONTFREE) return;
1247 pFormat += 2;
1248 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1249 else desc = pFormat + *(const SHORT*)pFormat;
1251 if (!Pointer) return;
1253 if (type == RPC_FC_FP) {
1254 int pointer_needs_freeing = NdrFullPointerFree(
1255 pStubMsg->FullPtrXlatTables, Pointer);
1256 if (!pointer_needs_freeing)
1257 return;
1260 if (attr & RPC_FC_P_DEREF) {
1261 current_pointer = *(unsigned char**)Pointer;
1262 TRACE("deref => %p\n", current_pointer);
1265 m = NdrFreer[*desc & NDR_TABLE_MASK];
1266 if (m) m(pStubMsg, current_pointer, desc);
1268 /* this check stops us from trying to free buffer memory. we don't have to
1269 * worry about clients, since they won't call this function.
1270 * we don't have to check for the buffer being reallocated because
1271 * BufferStart and BufferEnd won't be reset when allocating memory for
1272 * sending the response. we don't have to check for the new buffer here as
1273 * it won't be used a type memory, only for buffer memory */
1274 if (Pointer >= (unsigned char *)pStubMsg->BufferStart &&
1275 Pointer < (unsigned char *)pStubMsg->BufferEnd)
1276 goto notfree;
1278 if (attr & RPC_FC_P_ONSTACK) {
1279 TRACE("not freeing stack ptr %p\n", Pointer);
1280 return;
1282 TRACE("freeing %p\n", Pointer);
1283 NdrFree(pStubMsg, Pointer);
1284 return;
1285 notfree:
1286 TRACE("not freeing %p\n", Pointer);
1289 /***********************************************************************
1290 * EmbeddedPointerMarshall
1292 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1293 unsigned char *pMemory,
1294 PFORMAT_STRING pFormat)
1296 unsigned char *Mark = pStubMsg->BufferMark;
1297 unsigned rep, count, stride;
1298 unsigned i;
1299 unsigned char *saved_buffer = NULL;
1301 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1303 if (*pFormat != RPC_FC_PP) return NULL;
1304 pFormat += 2;
1306 if (pStubMsg->PointerBufferMark)
1308 saved_buffer = pStubMsg->Buffer;
1309 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1310 pStubMsg->PointerBufferMark = NULL;
1313 while (pFormat[0] != RPC_FC_END) {
1314 switch (pFormat[0]) {
1315 default:
1316 FIXME("unknown repeat type %d\n", pFormat[0]);
1317 case RPC_FC_NO_REPEAT:
1318 rep = 1;
1319 stride = 0;
1320 count = 1;
1321 pFormat += 2;
1322 break;
1323 case RPC_FC_FIXED_REPEAT:
1324 rep = *(const WORD*)&pFormat[2];
1325 stride = *(const WORD*)&pFormat[4];
1326 count = *(const WORD*)&pFormat[8];
1327 pFormat += 10;
1328 break;
1329 case RPC_FC_VARIABLE_REPEAT:
1330 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1331 stride = *(const WORD*)&pFormat[2];
1332 count = *(const WORD*)&pFormat[6];
1333 pFormat += 8;
1334 break;
1336 for (i = 0; i < rep; i++) {
1337 PFORMAT_STRING info = pFormat;
1338 unsigned char *membase = pMemory + (i * stride);
1339 unsigned char *bufbase = Mark + (i * stride);
1340 unsigned u;
1342 for (u=0; u<count; u++,info+=8) {
1343 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1344 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1345 unsigned char *saved_memory = pStubMsg->Memory;
1347 pStubMsg->Memory = pMemory;
1348 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1349 pStubMsg->Memory = saved_memory;
1352 pFormat += 8 * count;
1355 if (saved_buffer)
1357 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1358 pStubMsg->Buffer = saved_buffer;
1361 STD_OVERFLOW_CHECK(pStubMsg);
1363 return NULL;
1366 /***********************************************************************
1367 * EmbeddedPointerUnmarshall
1369 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1370 unsigned char *pDstMemoryPtrs,
1371 unsigned char *pSrcMemoryPtrs,
1372 PFORMAT_STRING pFormat,
1373 unsigned char fMustAlloc)
1375 unsigned char *Mark = pStubMsg->BufferMark;
1376 unsigned rep, count, stride;
1377 unsigned i;
1378 unsigned char *saved_buffer = NULL;
1380 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstMemoryPtrs, pSrcMemoryPtrs, pFormat, fMustAlloc);
1382 if (*pFormat != RPC_FC_PP) return NULL;
1383 pFormat += 2;
1385 if (pStubMsg->PointerBufferMark)
1387 saved_buffer = pStubMsg->Buffer;
1388 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1389 pStubMsg->PointerBufferMark = NULL;
1392 while (pFormat[0] != RPC_FC_END) {
1393 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1394 switch (pFormat[0]) {
1395 default:
1396 FIXME("unknown repeat type %d\n", pFormat[0]);
1397 case RPC_FC_NO_REPEAT:
1398 rep = 1;
1399 stride = 0;
1400 count = 1;
1401 pFormat += 2;
1402 break;
1403 case RPC_FC_FIXED_REPEAT:
1404 rep = *(const WORD*)&pFormat[2];
1405 stride = *(const WORD*)&pFormat[4];
1406 count = *(const WORD*)&pFormat[8];
1407 pFormat += 10;
1408 break;
1409 case RPC_FC_VARIABLE_REPEAT:
1410 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1411 stride = *(const WORD*)&pFormat[2];
1412 count = *(const WORD*)&pFormat[6];
1413 pFormat += 8;
1414 break;
1416 for (i = 0; i < rep; i++) {
1417 PFORMAT_STRING info = pFormat;
1418 unsigned char *memdstbase = pDstMemoryPtrs + (i * stride);
1419 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1420 unsigned char *bufbase = Mark + (i * stride);
1421 unsigned u;
1423 for (u=0; u<count; u++,info+=8) {
1424 unsigned char **memdstptr = (unsigned char **)(memdstbase + *(const SHORT*)&info[0]);
1425 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1426 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1427 PointerUnmarshall(pStubMsg, bufptr, memdstptr, *memsrcptr, info+4, fMustAlloc);
1430 pFormat += 8 * count;
1433 if (saved_buffer)
1435 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1436 pStubMsg->Buffer = saved_buffer;
1439 return NULL;
1442 /***********************************************************************
1443 * EmbeddedPointerBufferSize
1445 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1446 unsigned char *pMemory,
1447 PFORMAT_STRING pFormat)
1449 unsigned rep, count, stride;
1450 unsigned i;
1451 ULONG saved_buffer_length = 0;
1453 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1455 if (pStubMsg->IgnoreEmbeddedPointers) return;
1457 if (*pFormat != RPC_FC_PP) return;
1458 pFormat += 2;
1460 if (pStubMsg->PointerLength)
1462 saved_buffer_length = pStubMsg->BufferLength;
1463 pStubMsg->BufferLength = pStubMsg->PointerLength;
1464 pStubMsg->PointerLength = 0;
1467 while (pFormat[0] != RPC_FC_END) {
1468 switch (pFormat[0]) {
1469 default:
1470 FIXME("unknown repeat type %d\n", pFormat[0]);
1471 case RPC_FC_NO_REPEAT:
1472 rep = 1;
1473 stride = 0;
1474 count = 1;
1475 pFormat += 2;
1476 break;
1477 case RPC_FC_FIXED_REPEAT:
1478 rep = *(const WORD*)&pFormat[2];
1479 stride = *(const WORD*)&pFormat[4];
1480 count = *(const WORD*)&pFormat[8];
1481 pFormat += 10;
1482 break;
1483 case RPC_FC_VARIABLE_REPEAT:
1484 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1485 stride = *(const WORD*)&pFormat[2];
1486 count = *(const WORD*)&pFormat[6];
1487 pFormat += 8;
1488 break;
1490 for (i = 0; i < rep; i++) {
1491 PFORMAT_STRING info = pFormat;
1492 unsigned char *membase = pMemory + (i * stride);
1493 unsigned u;
1495 for (u=0; u<count; u++,info+=8) {
1496 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1497 unsigned char *saved_memory = pStubMsg->Memory;
1499 pStubMsg->Memory = pMemory;
1500 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1501 pStubMsg->Memory = saved_memory;
1504 pFormat += 8 * count;
1507 if (saved_buffer_length)
1509 pStubMsg->PointerLength = pStubMsg->BufferLength;
1510 pStubMsg->BufferLength = saved_buffer_length;
1514 /***********************************************************************
1515 * EmbeddedPointerMemorySize [internal]
1517 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1518 PFORMAT_STRING pFormat)
1520 unsigned char *Mark = pStubMsg->BufferMark;
1521 unsigned rep, count, stride;
1522 unsigned i;
1523 unsigned char *saved_buffer = NULL;
1525 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1527 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1529 if (pStubMsg->PointerBufferMark)
1531 saved_buffer = pStubMsg->Buffer;
1532 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1533 pStubMsg->PointerBufferMark = NULL;
1536 if (*pFormat != RPC_FC_PP) return 0;
1537 pFormat += 2;
1539 while (pFormat[0] != RPC_FC_END) {
1540 switch (pFormat[0]) {
1541 default:
1542 FIXME("unknown repeat type %d\n", pFormat[0]);
1543 case RPC_FC_NO_REPEAT:
1544 rep = 1;
1545 stride = 0;
1546 count = 1;
1547 pFormat += 2;
1548 break;
1549 case RPC_FC_FIXED_REPEAT:
1550 rep = *(const WORD*)&pFormat[2];
1551 stride = *(const WORD*)&pFormat[4];
1552 count = *(const WORD*)&pFormat[8];
1553 pFormat += 10;
1554 break;
1555 case RPC_FC_VARIABLE_REPEAT:
1556 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1557 stride = *(const WORD*)&pFormat[2];
1558 count = *(const WORD*)&pFormat[6];
1559 pFormat += 8;
1560 break;
1562 for (i = 0; i < rep; i++) {
1563 PFORMAT_STRING info = pFormat;
1564 unsigned char *bufbase = Mark + (i * stride);
1565 unsigned u;
1566 for (u=0; u<count; u++,info+=8) {
1567 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1568 PointerMemorySize(pStubMsg, bufptr, info+4);
1571 pFormat += 8 * count;
1574 if (saved_buffer)
1576 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1577 pStubMsg->Buffer = saved_buffer;
1580 return 0;
1583 /***********************************************************************
1584 * EmbeddedPointerFree [internal]
1586 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1587 unsigned char *pMemory,
1588 PFORMAT_STRING pFormat)
1590 unsigned rep, count, stride;
1591 unsigned i;
1593 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1594 if (*pFormat != RPC_FC_PP) return;
1595 pFormat += 2;
1597 while (pFormat[0] != RPC_FC_END) {
1598 switch (pFormat[0]) {
1599 default:
1600 FIXME("unknown repeat type %d\n", pFormat[0]);
1601 case RPC_FC_NO_REPEAT:
1602 rep = 1;
1603 stride = 0;
1604 count = 1;
1605 pFormat += 2;
1606 break;
1607 case RPC_FC_FIXED_REPEAT:
1608 rep = *(const WORD*)&pFormat[2];
1609 stride = *(const WORD*)&pFormat[4];
1610 count = *(const WORD*)&pFormat[8];
1611 pFormat += 10;
1612 break;
1613 case RPC_FC_VARIABLE_REPEAT:
1614 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1615 stride = *(const WORD*)&pFormat[2];
1616 count = *(const WORD*)&pFormat[6];
1617 pFormat += 8;
1618 break;
1620 for (i = 0; i < rep; i++) {
1621 PFORMAT_STRING info = pFormat;
1622 unsigned char *membase = pMemory + (i * stride);
1623 unsigned u;
1625 for (u=0; u<count; u++,info+=8) {
1626 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1627 unsigned char *saved_memory = pStubMsg->Memory;
1629 pStubMsg->Memory = pMemory;
1630 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1631 pStubMsg->Memory = saved_memory;
1634 pFormat += 8 * count;
1638 /***********************************************************************
1639 * NdrPointerMarshall [RPCRT4.@]
1641 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1642 unsigned char *pMemory,
1643 PFORMAT_STRING pFormat)
1645 unsigned char *Buffer;
1647 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1649 /* incremement the buffer here instead of in PointerMarshall,
1650 * as that is used by embedded pointers which already handle the incrementing
1651 * the buffer, and shouldn't write any additional pointer data to the wire */
1652 if (*pFormat != RPC_FC_RP)
1654 ALIGN_POINTER(pStubMsg->Buffer, 4);
1655 Buffer = pStubMsg->Buffer;
1656 safe_buffer_increment(pStubMsg, 4);
1658 else
1659 Buffer = pStubMsg->Buffer;
1661 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1663 return NULL;
1666 /***********************************************************************
1667 * NdrPointerUnmarshall [RPCRT4.@]
1669 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1670 unsigned char **ppMemory,
1671 PFORMAT_STRING pFormat,
1672 unsigned char fMustAlloc)
1674 unsigned char *Buffer;
1676 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1678 /* incremement the buffer here instead of in PointerUnmarshall,
1679 * as that is used by embedded pointers which already handle the incrementing
1680 * the buffer, and shouldn't read any additional pointer data from the
1681 * buffer */
1682 if (*pFormat != RPC_FC_RP)
1684 ALIGN_POINTER(pStubMsg->Buffer, 4);
1685 Buffer = pStubMsg->Buffer;
1686 safe_buffer_increment(pStubMsg, 4);
1688 else
1689 Buffer = pStubMsg->Buffer;
1691 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1693 return NULL;
1696 /***********************************************************************
1697 * NdrPointerBufferSize [RPCRT4.@]
1699 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1700 unsigned char *pMemory,
1701 PFORMAT_STRING pFormat)
1703 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1705 /* incremement the buffer length here instead of in PointerBufferSize,
1706 * as that is used by embedded pointers which already handle the buffer
1707 * length, and shouldn't write anything more to the wire */
1708 if (*pFormat != RPC_FC_RP)
1710 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1711 safe_buffer_length_increment(pStubMsg, 4);
1714 PointerBufferSize(pStubMsg, pMemory, pFormat);
1717 /***********************************************************************
1718 * NdrPointerMemorySize [RPCRT4.@]
1720 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1721 PFORMAT_STRING pFormat)
1723 /* unsigned size = *(LPWORD)(pFormat+2); */
1724 FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1725 PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1726 return 0;
1729 /***********************************************************************
1730 * NdrPointerFree [RPCRT4.@]
1732 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1733 unsigned char *pMemory,
1734 PFORMAT_STRING pFormat)
1736 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1737 PointerFree(pStubMsg, pMemory, pFormat);
1740 /***********************************************************************
1741 * NdrSimpleTypeMarshall [RPCRT4.@]
1743 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1744 unsigned char FormatChar )
1746 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1749 /***********************************************************************
1750 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1752 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1753 unsigned char FormatChar )
1755 NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0);
1758 /***********************************************************************
1759 * NdrSimpleStructMarshall [RPCRT4.@]
1761 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1762 unsigned char *pMemory,
1763 PFORMAT_STRING pFormat)
1765 unsigned size = *(const WORD*)(pFormat+2);
1766 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1768 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1770 pStubMsg->BufferMark = pStubMsg->Buffer;
1771 safe_copy_to_buffer(pStubMsg, pMemory, size);
1773 if (pFormat[0] != RPC_FC_STRUCT)
1774 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1776 return NULL;
1779 /***********************************************************************
1780 * NdrSimpleStructUnmarshall [RPCRT4.@]
1782 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1783 unsigned char **ppMemory,
1784 PFORMAT_STRING pFormat,
1785 unsigned char fMustAlloc)
1787 unsigned size = *(const WORD*)(pFormat+2);
1788 unsigned char *saved_buffer;
1789 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1791 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1793 if (fMustAlloc)
1794 *ppMemory = NdrAllocate(pStubMsg, size);
1795 else
1797 if (!pStubMsg->IsClient && !*ppMemory)
1798 /* for servers, we just point straight into the RPC buffer */
1799 *ppMemory = pStubMsg->Buffer;
1802 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1803 safe_buffer_increment(pStubMsg, size);
1804 if (pFormat[0] == RPC_FC_PSTRUCT)
1805 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1807 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1808 if (*ppMemory != saved_buffer)
1809 memcpy(*ppMemory, saved_buffer, size);
1811 return NULL;
1814 /***********************************************************************
1815 * NdrSimpleStructBufferSize [RPCRT4.@]
1817 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1818 unsigned char *pMemory,
1819 PFORMAT_STRING pFormat)
1821 unsigned size = *(const WORD*)(pFormat+2);
1822 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1824 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1826 safe_buffer_length_increment(pStubMsg, size);
1827 if (pFormat[0] != RPC_FC_STRUCT)
1828 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1831 /***********************************************************************
1832 * NdrSimpleStructMemorySize [RPCRT4.@]
1834 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1835 PFORMAT_STRING pFormat)
1837 unsigned short size = *(const WORD *)(pFormat+2);
1839 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1841 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1842 pStubMsg->MemorySize += size;
1843 safe_buffer_increment(pStubMsg, size);
1845 if (pFormat[0] != RPC_FC_STRUCT)
1846 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1847 return pStubMsg->MemorySize;
1850 /***********************************************************************
1851 * NdrSimpleStructFree [RPCRT4.@]
1853 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1854 unsigned char *pMemory,
1855 PFORMAT_STRING pFormat)
1857 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1858 if (pFormat[0] != RPC_FC_STRUCT)
1859 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1863 static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg,
1864 PFORMAT_STRING pFormat)
1866 switch (*pFormat) {
1867 case RPC_FC_STRUCT:
1868 case RPC_FC_PSTRUCT:
1869 case RPC_FC_CSTRUCT:
1870 case RPC_FC_BOGUS_STRUCT:
1871 case RPC_FC_SMFARRAY:
1872 case RPC_FC_SMVARRAY:
1873 return *(const WORD*)&pFormat[2];
1874 case RPC_FC_USER_MARSHAL:
1875 return *(const WORD*)&pFormat[4];
1876 case RPC_FC_NON_ENCAPSULATED_UNION:
1877 pFormat += 2;
1878 if (pStubMsg->fHasNewCorrDesc)
1879 pFormat += 6;
1880 else
1881 pFormat += 4;
1883 pFormat += *(const SHORT*)pFormat;
1884 return *(const SHORT*)pFormat;
1885 case RPC_FC_IP:
1886 return sizeof(void *);
1887 default:
1888 FIXME("unhandled embedded type %02x\n", *pFormat);
1890 return 0;
1894 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1895 PFORMAT_STRING pFormat)
1897 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1899 if (!m)
1901 FIXME("no memorysizer for data type=%02x\n", *pFormat);
1902 return 0;
1905 return m(pStubMsg, pFormat);
1909 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1910 unsigned char *pMemory,
1911 PFORMAT_STRING pFormat,
1912 PFORMAT_STRING pPointer)
1914 PFORMAT_STRING desc;
1915 NDR_MARSHALL m;
1916 unsigned long size;
1918 while (*pFormat != RPC_FC_END) {
1919 switch (*pFormat) {
1920 case RPC_FC_BYTE:
1921 case RPC_FC_CHAR:
1922 case RPC_FC_SMALL:
1923 case RPC_FC_USMALL:
1924 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
1925 safe_copy_to_buffer(pStubMsg, pMemory, 1);
1926 pMemory += 1;
1927 break;
1928 case RPC_FC_WCHAR:
1929 case RPC_FC_SHORT:
1930 case RPC_FC_USHORT:
1931 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1932 safe_copy_to_buffer(pStubMsg, pMemory, 2);
1933 pMemory += 2;
1934 break;
1935 case RPC_FC_LONG:
1936 case RPC_FC_ULONG:
1937 case RPC_FC_ENUM32:
1938 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
1939 safe_copy_to_buffer(pStubMsg, pMemory, 4);
1940 pMemory += 4;
1941 break;
1942 case RPC_FC_HYPER:
1943 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1944 safe_copy_to_buffer(pStubMsg, pMemory, 8);
1945 pMemory += 8;
1946 break;
1947 case RPC_FC_POINTER:
1949 unsigned char *saved_buffer;
1950 int pointer_buffer_mark_set = 0;
1951 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1952 saved_buffer = pStubMsg->Buffer;
1953 if (pStubMsg->PointerBufferMark)
1955 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1956 pStubMsg->PointerBufferMark = NULL;
1957 pointer_buffer_mark_set = 1;
1959 else
1960 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
1961 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
1962 if (pointer_buffer_mark_set)
1964 STD_OVERFLOW_CHECK(pStubMsg);
1965 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1966 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
1968 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
1969 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
1970 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1972 pStubMsg->Buffer = saved_buffer + 4;
1974 pPointer += 4;
1975 pMemory += 4;
1976 break;
1978 case RPC_FC_ALIGNM4:
1979 ALIGN_POINTER(pMemory, 4);
1980 break;
1981 case RPC_FC_ALIGNM8:
1982 ALIGN_POINTER(pMemory, 8);
1983 break;
1984 case RPC_FC_STRUCTPAD1:
1985 case RPC_FC_STRUCTPAD2:
1986 case RPC_FC_STRUCTPAD3:
1987 case RPC_FC_STRUCTPAD4:
1988 case RPC_FC_STRUCTPAD5:
1989 case RPC_FC_STRUCTPAD6:
1990 case RPC_FC_STRUCTPAD7:
1991 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
1992 break;
1993 case RPC_FC_EMBEDDED_COMPLEX:
1994 pMemory += pFormat[1];
1995 pFormat += 2;
1996 desc = pFormat + *(const SHORT*)pFormat;
1997 size = EmbeddedComplexSize(pStubMsg, desc);
1998 TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1999 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2000 if (m)
2002 /* for some reason interface pointers aren't generated as
2003 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2004 * they still need the derefencing treatment that pointers are
2005 * given */
2006 if (*desc == RPC_FC_IP)
2007 m(pStubMsg, *(unsigned char **)pMemory, desc);
2008 else
2009 m(pStubMsg, pMemory, desc);
2011 else FIXME("no marshaller for embedded type %02x\n", *desc);
2012 pMemory += size;
2013 pFormat += 2;
2014 continue;
2015 case RPC_FC_PAD:
2016 break;
2017 default:
2018 FIXME("unhandled format 0x%02x\n", *pFormat);
2020 pFormat++;
2023 return pMemory;
2026 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2027 unsigned char *pMemory,
2028 PFORMAT_STRING pFormat,
2029 PFORMAT_STRING pPointer)
2031 PFORMAT_STRING desc;
2032 NDR_UNMARSHALL m;
2033 unsigned long size;
2035 while (*pFormat != RPC_FC_END) {
2036 switch (*pFormat) {
2037 case RPC_FC_BYTE:
2038 case RPC_FC_CHAR:
2039 case RPC_FC_SMALL:
2040 case RPC_FC_USMALL:
2041 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2042 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2043 pMemory += 1;
2044 break;
2045 case RPC_FC_WCHAR:
2046 case RPC_FC_SHORT:
2047 case RPC_FC_USHORT:
2048 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2049 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2050 pMemory += 2;
2051 break;
2052 case RPC_FC_LONG:
2053 case RPC_FC_ULONG:
2054 case RPC_FC_ENUM32:
2055 safe_copy_from_buffer(pStubMsg, pMemory, 4);
2056 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2057 pMemory += 4;
2058 break;
2059 case RPC_FC_HYPER:
2060 safe_copy_from_buffer(pStubMsg, pMemory, 8);
2061 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2062 pMemory += 8;
2063 break;
2064 case RPC_FC_POINTER:
2066 unsigned char *saved_buffer;
2067 int pointer_buffer_mark_set = 0;
2068 TRACE("pointer => %p\n", pMemory);
2069 ALIGN_POINTER(pStubMsg->Buffer, 4);
2070 saved_buffer = pStubMsg->Buffer;
2071 if (pStubMsg->PointerBufferMark)
2073 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2074 pStubMsg->PointerBufferMark = NULL;
2075 pointer_buffer_mark_set = 1;
2077 else
2078 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2080 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, TRUE);
2081 if (pointer_buffer_mark_set)
2083 STD_OVERFLOW_CHECK(pStubMsg);
2084 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2085 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
2087 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
2088 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
2089 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2091 pStubMsg->Buffer = saved_buffer + 4;
2093 pPointer += 4;
2094 pMemory += 4;
2095 break;
2097 case RPC_FC_ALIGNM4:
2098 ALIGN_POINTER(pMemory, 4);
2099 break;
2100 case RPC_FC_ALIGNM8:
2101 ALIGN_POINTER(pMemory, 8);
2102 break;
2103 case RPC_FC_STRUCTPAD1:
2104 case RPC_FC_STRUCTPAD2:
2105 case RPC_FC_STRUCTPAD3:
2106 case RPC_FC_STRUCTPAD4:
2107 case RPC_FC_STRUCTPAD5:
2108 case RPC_FC_STRUCTPAD6:
2109 case RPC_FC_STRUCTPAD7:
2110 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2111 break;
2112 case RPC_FC_EMBEDDED_COMPLEX:
2113 pMemory += pFormat[1];
2114 pFormat += 2;
2115 desc = pFormat + *(const SHORT*)pFormat;
2116 size = EmbeddedComplexSize(pStubMsg, desc);
2117 TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
2118 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2119 memset(pMemory, 0, size); /* just in case */
2120 if (m)
2122 /* for some reason interface pointers aren't generated as
2123 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2124 * they still need the derefencing treatment that pointers are
2125 * given */
2126 if (*desc == RPC_FC_IP)
2127 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2128 else
2129 m(pStubMsg, &pMemory, desc, FALSE);
2131 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2132 pMemory += size;
2133 pFormat += 2;
2134 continue;
2135 case RPC_FC_PAD:
2136 break;
2137 default:
2138 FIXME("unhandled format %d\n", *pFormat);
2140 pFormat++;
2143 return pMemory;
2146 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2147 unsigned char *pMemory,
2148 PFORMAT_STRING pFormat,
2149 PFORMAT_STRING pPointer)
2151 PFORMAT_STRING desc;
2152 NDR_BUFFERSIZE m;
2153 unsigned long size;
2155 while (*pFormat != RPC_FC_END) {
2156 switch (*pFormat) {
2157 case RPC_FC_BYTE:
2158 case RPC_FC_CHAR:
2159 case RPC_FC_SMALL:
2160 case RPC_FC_USMALL:
2161 safe_buffer_length_increment(pStubMsg, 1);
2162 pMemory += 1;
2163 break;
2164 case RPC_FC_WCHAR:
2165 case RPC_FC_SHORT:
2166 case RPC_FC_USHORT:
2167 safe_buffer_length_increment(pStubMsg, 2);
2168 pMemory += 2;
2169 break;
2170 case RPC_FC_LONG:
2171 case RPC_FC_ULONG:
2172 case RPC_FC_ENUM32:
2173 safe_buffer_length_increment(pStubMsg, 4);
2174 pMemory += 4;
2175 break;
2176 case RPC_FC_HYPER:
2177 safe_buffer_length_increment(pStubMsg, 8);
2178 pMemory += 8;
2179 break;
2180 case RPC_FC_POINTER:
2181 if (!pStubMsg->IgnoreEmbeddedPointers)
2183 int saved_buffer_length = pStubMsg->BufferLength;
2184 pStubMsg->BufferLength = pStubMsg->PointerLength;
2185 pStubMsg->PointerLength = 0;
2186 if(!pStubMsg->BufferLength)
2187 ERR("BufferLength == 0??\n");
2188 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2189 pStubMsg->PointerLength = pStubMsg->BufferLength;
2190 pStubMsg->BufferLength = saved_buffer_length;
2192 safe_buffer_length_increment(pStubMsg, 4);
2193 pPointer += 4;
2194 pMemory += 4;
2195 break;
2196 case RPC_FC_ALIGNM4:
2197 ALIGN_POINTER(pMemory, 4);
2198 break;
2199 case RPC_FC_ALIGNM8:
2200 ALIGN_POINTER(pMemory, 8);
2201 break;
2202 case RPC_FC_STRUCTPAD1:
2203 case RPC_FC_STRUCTPAD2:
2204 case RPC_FC_STRUCTPAD3:
2205 case RPC_FC_STRUCTPAD4:
2206 case RPC_FC_STRUCTPAD5:
2207 case RPC_FC_STRUCTPAD6:
2208 case RPC_FC_STRUCTPAD7:
2209 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2210 break;
2211 case RPC_FC_EMBEDDED_COMPLEX:
2212 pMemory += pFormat[1];
2213 pFormat += 2;
2214 desc = pFormat + *(const SHORT*)pFormat;
2215 size = EmbeddedComplexSize(pStubMsg, desc);
2216 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2217 if (m)
2219 /* for some reason interface pointers aren't generated as
2220 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2221 * they still need the derefencing treatment that pointers are
2222 * given */
2223 if (*desc == RPC_FC_IP)
2224 m(pStubMsg, *(unsigned char **)pMemory, desc);
2225 else
2226 m(pStubMsg, pMemory, desc);
2228 else FIXME("no buffersizer for embedded type %02x\n", *desc);
2229 pMemory += size;
2230 pFormat += 2;
2231 continue;
2232 case RPC_FC_PAD:
2233 break;
2234 default:
2235 FIXME("unhandled format 0x%02x\n", *pFormat);
2237 pFormat++;
2240 return pMemory;
2243 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2244 unsigned char *pMemory,
2245 PFORMAT_STRING pFormat,
2246 PFORMAT_STRING pPointer)
2248 PFORMAT_STRING desc;
2249 NDR_FREE m;
2250 unsigned long size;
2252 while (*pFormat != RPC_FC_END) {
2253 switch (*pFormat) {
2254 case RPC_FC_BYTE:
2255 case RPC_FC_CHAR:
2256 case RPC_FC_SMALL:
2257 case RPC_FC_USMALL:
2258 pMemory += 1;
2259 break;
2260 case RPC_FC_WCHAR:
2261 case RPC_FC_SHORT:
2262 case RPC_FC_USHORT:
2263 pMemory += 2;
2264 break;
2265 case RPC_FC_LONG:
2266 case RPC_FC_ULONG:
2267 case RPC_FC_ENUM32:
2268 pMemory += 4;
2269 break;
2270 case RPC_FC_HYPER:
2271 pMemory += 8;
2272 break;
2273 case RPC_FC_POINTER:
2274 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2275 pPointer += 4;
2276 pMemory += 4;
2277 break;
2278 case RPC_FC_ALIGNM4:
2279 ALIGN_POINTER(pMemory, 4);
2280 break;
2281 case RPC_FC_ALIGNM8:
2282 ALIGN_POINTER(pMemory, 8);
2283 break;
2284 case RPC_FC_STRUCTPAD1:
2285 case RPC_FC_STRUCTPAD2:
2286 case RPC_FC_STRUCTPAD3:
2287 case RPC_FC_STRUCTPAD4:
2288 case RPC_FC_STRUCTPAD5:
2289 case RPC_FC_STRUCTPAD6:
2290 case RPC_FC_STRUCTPAD7:
2291 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2292 break;
2293 case RPC_FC_EMBEDDED_COMPLEX:
2294 pMemory += pFormat[1];
2295 pFormat += 2;
2296 desc = pFormat + *(const SHORT*)pFormat;
2297 size = EmbeddedComplexSize(pStubMsg, desc);
2298 m = NdrFreer[*desc & NDR_TABLE_MASK];
2299 if (m)
2301 /* for some reason interface pointers aren't generated as
2302 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2303 * they still need the derefencing treatment that pointers are
2304 * given */
2305 if (*desc == RPC_FC_IP)
2306 m(pStubMsg, *(unsigned char **)pMemory, desc);
2307 else
2308 m(pStubMsg, pMemory, desc);
2310 else FIXME("no freer for embedded type %02x\n", *desc);
2311 pMemory += size;
2312 pFormat += 2;
2313 continue;
2314 case RPC_FC_PAD:
2315 break;
2316 default:
2317 FIXME("unhandled format 0x%02x\n", *pFormat);
2319 pFormat++;
2322 return pMemory;
2325 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2326 PFORMAT_STRING pFormat)
2328 PFORMAT_STRING desc;
2329 unsigned long size = 0;
2331 while (*pFormat != RPC_FC_END) {
2332 switch (*pFormat) {
2333 case RPC_FC_BYTE:
2334 case RPC_FC_CHAR:
2335 case RPC_FC_SMALL:
2336 case RPC_FC_USMALL:
2337 size += 1;
2338 safe_buffer_increment(pStubMsg, 1);
2339 break;
2340 case RPC_FC_WCHAR:
2341 case RPC_FC_SHORT:
2342 case RPC_FC_USHORT:
2343 size += 2;
2344 safe_buffer_increment(pStubMsg, 2);
2345 break;
2346 case RPC_FC_LONG:
2347 case RPC_FC_ULONG:
2348 case RPC_FC_ENUM32:
2349 size += 4;
2350 safe_buffer_increment(pStubMsg, 4);
2351 break;
2352 case RPC_FC_HYPER:
2353 size += 8;
2354 safe_buffer_increment(pStubMsg, 8);
2355 break;
2356 case RPC_FC_POINTER:
2357 size += 4;
2358 safe_buffer_increment(pStubMsg, 4);
2359 if (!pStubMsg->IgnoreEmbeddedPointers)
2360 FIXME("embedded pointers\n");
2361 break;
2362 case RPC_FC_ALIGNM4:
2363 ALIGN_LENGTH(size, 4);
2364 ALIGN_POINTER(pStubMsg->Buffer, 4);
2365 break;
2366 case RPC_FC_ALIGNM8:
2367 ALIGN_LENGTH(size, 8);
2368 ALIGN_POINTER(pStubMsg->Buffer, 8);
2369 break;
2370 case RPC_FC_STRUCTPAD1:
2371 case RPC_FC_STRUCTPAD2:
2372 case RPC_FC_STRUCTPAD3:
2373 case RPC_FC_STRUCTPAD4:
2374 case RPC_FC_STRUCTPAD5:
2375 case RPC_FC_STRUCTPAD6:
2376 case RPC_FC_STRUCTPAD7:
2377 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2378 break;
2379 case RPC_FC_EMBEDDED_COMPLEX:
2380 size += pFormat[1];
2381 pFormat += 2;
2382 desc = pFormat + *(const SHORT*)pFormat;
2383 size += EmbeddedComplexMemorySize(pStubMsg, desc);
2384 pFormat += 2;
2385 continue;
2386 case RPC_FC_PAD:
2387 break;
2388 default:
2389 FIXME("unhandled format 0x%02x\n", *pFormat);
2391 pFormat++;
2394 return size;
2397 /***********************************************************************
2398 * NdrComplexStructMarshall [RPCRT4.@]
2400 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2401 unsigned char *pMemory,
2402 PFORMAT_STRING pFormat)
2404 PFORMAT_STRING conf_array = NULL;
2405 PFORMAT_STRING pointer_desc = NULL;
2406 unsigned char *OldMemory = pStubMsg->Memory;
2407 int pointer_buffer_mark_set = 0;
2409 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2411 if (!pStubMsg->PointerBufferMark)
2413 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2414 /* save buffer length */
2415 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2417 /* get the buffer pointer after complex array data, but before
2418 * pointer data */
2419 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2420 pStubMsg->IgnoreEmbeddedPointers = 1;
2421 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2422 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2424 /* save it for use by embedded pointer code later */
2425 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2426 TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2427 pointer_buffer_mark_set = 1;
2429 /* restore the original buffer length */
2430 pStubMsg->BufferLength = saved_buffer_length;
2433 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2435 pFormat += 4;
2436 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2437 pFormat += 2;
2438 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2439 pFormat += 2;
2441 pStubMsg->Memory = pMemory;
2443 ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2445 if (conf_array)
2446 NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2448 pStubMsg->Memory = OldMemory;
2450 if (pointer_buffer_mark_set)
2452 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2453 pStubMsg->PointerBufferMark = NULL;
2456 STD_OVERFLOW_CHECK(pStubMsg);
2458 return NULL;
2461 /***********************************************************************
2462 * NdrComplexStructUnmarshall [RPCRT4.@]
2464 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2465 unsigned char **ppMemory,
2466 PFORMAT_STRING pFormat,
2467 unsigned char fMustAlloc)
2469 unsigned size = *(const WORD*)(pFormat+2);
2470 PFORMAT_STRING conf_array = NULL;
2471 PFORMAT_STRING pointer_desc = NULL;
2472 unsigned char *pMemory;
2473 int pointer_buffer_mark_set = 0;
2475 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2477 if (!pStubMsg->PointerBufferMark)
2479 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2480 /* save buffer pointer */
2481 unsigned char *saved_buffer = pStubMsg->Buffer;
2483 /* get the buffer pointer after complex array data, but before
2484 * pointer data */
2485 pStubMsg->IgnoreEmbeddedPointers = 1;
2486 NdrComplexStructMemorySize(pStubMsg, pFormat);
2487 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2489 /* save it for use by embedded pointer code later */
2490 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2491 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2492 pointer_buffer_mark_set = 1;
2494 /* restore the original buffer */
2495 pStubMsg->Buffer = saved_buffer;
2498 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2500 if (fMustAlloc || !*ppMemory)
2502 *ppMemory = NdrAllocate(pStubMsg, size);
2503 memset(*ppMemory, 0, size);
2506 pFormat += 4;
2507 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2508 pFormat += 2;
2509 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2510 pFormat += 2;
2512 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2514 if (conf_array)
2515 NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2517 if (pointer_buffer_mark_set)
2519 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2520 pStubMsg->PointerBufferMark = NULL;
2523 return NULL;
2526 /***********************************************************************
2527 * NdrComplexStructBufferSize [RPCRT4.@]
2529 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2530 unsigned char *pMemory,
2531 PFORMAT_STRING pFormat)
2533 PFORMAT_STRING conf_array = NULL;
2534 PFORMAT_STRING pointer_desc = NULL;
2535 unsigned char *OldMemory = pStubMsg->Memory;
2536 int pointer_length_set = 0;
2538 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2540 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2542 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2544 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2545 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2547 /* get the buffer length after complex struct data, but before
2548 * pointer data */
2549 pStubMsg->IgnoreEmbeddedPointers = 1;
2550 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2551 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2553 /* save it for use by embedded pointer code later */
2554 pStubMsg->PointerLength = pStubMsg->BufferLength;
2555 pointer_length_set = 1;
2556 TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2558 /* restore the original buffer length */
2559 pStubMsg->BufferLength = saved_buffer_length;
2562 pFormat += 4;
2563 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2564 pFormat += 2;
2565 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2566 pFormat += 2;
2568 pStubMsg->Memory = pMemory;
2570 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2572 if (conf_array)
2573 NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2575 pStubMsg->Memory = OldMemory;
2577 if(pointer_length_set)
2579 pStubMsg->BufferLength = pStubMsg->PointerLength;
2580 pStubMsg->PointerLength = 0;
2585 /***********************************************************************
2586 * NdrComplexStructMemorySize [RPCRT4.@]
2588 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2589 PFORMAT_STRING pFormat)
2591 unsigned size = *(const WORD*)(pFormat+2);
2592 PFORMAT_STRING conf_array = NULL;
2593 PFORMAT_STRING pointer_desc = NULL;
2595 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2597 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2599 pFormat += 4;
2600 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2601 pFormat += 2;
2602 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2603 pFormat += 2;
2605 ComplexStructMemorySize(pStubMsg, pFormat);
2607 if (conf_array)
2608 NdrConformantArrayMemorySize(pStubMsg, conf_array);
2610 return size;
2613 /***********************************************************************
2614 * NdrComplexStructFree [RPCRT4.@]
2616 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2617 unsigned char *pMemory,
2618 PFORMAT_STRING pFormat)
2620 PFORMAT_STRING conf_array = NULL;
2621 PFORMAT_STRING pointer_desc = NULL;
2622 unsigned char *OldMemory = pStubMsg->Memory;
2624 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2626 pFormat += 4;
2627 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2628 pFormat += 2;
2629 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2630 pFormat += 2;
2632 pStubMsg->Memory = pMemory;
2634 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2636 if (conf_array)
2637 NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2639 pStubMsg->Memory = OldMemory;
2642 /***********************************************************************
2643 * NdrConformantArrayMarshall [RPCRT4.@]
2645 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2646 unsigned char *pMemory,
2647 PFORMAT_STRING pFormat)
2649 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2650 unsigned char alignment = pFormat[1] + 1;
2652 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2653 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2655 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2657 WriteConformance(pStubMsg);
2659 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2661 size = safe_multiply(esize, pStubMsg->MaxCount);
2662 pStubMsg->BufferMark = pStubMsg->Buffer;
2663 safe_copy_to_buffer(pStubMsg, pMemory, size);
2665 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2667 return NULL;
2670 /***********************************************************************
2671 * NdrConformantArrayUnmarshall [RPCRT4.@]
2673 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2674 unsigned char **ppMemory,
2675 PFORMAT_STRING pFormat,
2676 unsigned char fMustAlloc)
2678 DWORD size, esize = *(const WORD*)(pFormat+2);
2679 unsigned char alignment = pFormat[1] + 1;
2680 unsigned char *saved_buffer;
2682 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2683 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2685 pFormat = ReadConformance(pStubMsg, pFormat+4);
2687 size = safe_multiply(esize, pStubMsg->MaxCount);
2688 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2690 if (fMustAlloc)
2691 *ppMemory = NdrAllocate(pStubMsg, size);
2692 else
2694 if (!pStubMsg->IsClient && !*ppMemory)
2695 /* for servers, we just point straight into the RPC buffer */
2696 *ppMemory = pStubMsg->Buffer;
2699 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
2700 safe_buffer_increment(pStubMsg, size);
2701 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2703 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2704 if (*ppMemory != saved_buffer)
2705 memcpy(*ppMemory, saved_buffer, size);
2707 return NULL;
2710 /***********************************************************************
2711 * NdrConformantArrayBufferSize [RPCRT4.@]
2713 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2714 unsigned char *pMemory,
2715 PFORMAT_STRING pFormat)
2717 DWORD size, esize = *(const WORD*)(pFormat+2);
2718 unsigned char alignment = pFormat[1] + 1;
2720 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2721 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2723 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2725 SizeConformance(pStubMsg);
2727 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2729 size = safe_multiply(esize, pStubMsg->MaxCount);
2730 /* conformance value plus array */
2731 safe_buffer_length_increment(pStubMsg, size);
2733 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2736 /***********************************************************************
2737 * NdrConformantArrayMemorySize [RPCRT4.@]
2739 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2740 PFORMAT_STRING pFormat)
2742 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2743 unsigned char alignment = pFormat[1] + 1;
2745 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2746 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2748 pFormat = ReadConformance(pStubMsg, pFormat+4);
2749 size = safe_multiply(esize, pStubMsg->MaxCount);
2750 pStubMsg->MemorySize += size;
2752 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2753 pStubMsg->BufferMark = pStubMsg->Buffer;
2754 safe_buffer_increment(pStubMsg, size);
2756 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2758 return pStubMsg->MemorySize;
2761 /***********************************************************************
2762 * NdrConformantArrayFree [RPCRT4.@]
2764 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2765 unsigned char *pMemory,
2766 PFORMAT_STRING pFormat)
2768 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2769 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2771 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2773 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2777 /***********************************************************************
2778 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
2780 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2781 unsigned char* pMemory,
2782 PFORMAT_STRING pFormat )
2784 ULONG bufsize;
2785 unsigned char alignment = pFormat[1] + 1;
2786 DWORD esize = *(const WORD*)(pFormat+2);
2788 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2790 if (pFormat[0] != RPC_FC_CVARRAY)
2792 ERR("invalid format type %x\n", pFormat[0]);
2793 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2794 return NULL;
2797 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2798 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2800 WriteConformance(pStubMsg);
2801 WriteVariance(pStubMsg);
2803 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2805 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2807 pStubMsg->BufferMark = pStubMsg->Buffer;
2808 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
2810 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2812 return NULL;
2816 /***********************************************************************
2817 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
2819 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2820 unsigned char** ppMemory,
2821 PFORMAT_STRING pFormat,
2822 unsigned char fMustAlloc )
2824 ULONG bufsize, memsize;
2825 unsigned char alignment = pFormat[1] + 1;
2826 DWORD esize = *(const WORD*)(pFormat+2);
2828 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2830 if (pFormat[0] != RPC_FC_CVARRAY)
2832 ERR("invalid format type %x\n", pFormat[0]);
2833 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2834 return NULL;
2837 pFormat = ReadConformance(pStubMsg, pFormat+4);
2838 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2840 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2842 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2843 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2845 if (!*ppMemory || fMustAlloc)
2846 *ppMemory = NdrAllocate(pStubMsg, memsize);
2847 safe_copy_from_buffer(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
2849 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
2851 return NULL;
2855 /***********************************************************************
2856 * NdrConformantVaryingArrayFree [RPCRT4.@]
2858 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2859 unsigned char* pMemory,
2860 PFORMAT_STRING pFormat )
2862 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2864 if (pFormat[0] != RPC_FC_CVARRAY)
2866 ERR("invalid format type %x\n", pFormat[0]);
2867 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2868 return;
2871 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2872 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2874 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2878 /***********************************************************************
2879 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
2881 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2882 unsigned char* pMemory, PFORMAT_STRING pFormat )
2884 unsigned char alignment = pFormat[1] + 1;
2885 DWORD esize = *(const WORD*)(pFormat+2);
2887 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2889 if (pFormat[0] != RPC_FC_CVARRAY)
2891 ERR("invalid format type %x\n", pFormat[0]);
2892 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2893 return;
2896 /* compute size */
2897 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2898 /* compute length */
2899 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2901 SizeConformance(pStubMsg);
2902 SizeVariance(pStubMsg);
2904 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2906 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2908 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2912 /***********************************************************************
2913 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
2915 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2916 PFORMAT_STRING pFormat )
2918 ULONG bufsize, memsize;
2919 unsigned char alignment = pFormat[1] + 1;
2920 DWORD esize = *(const WORD*)(pFormat+2);
2922 TRACE("(%p, %p)\n", pStubMsg, pFormat);
2924 if (pFormat[0] != RPC_FC_CVARRAY)
2926 ERR("invalid format type %x\n", pFormat[0]);
2927 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2928 return pStubMsg->MemorySize;
2931 pFormat = ReadConformance(pStubMsg, pFormat+4);
2932 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2934 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2936 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2937 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2939 safe_buffer_increment(pStubMsg, bufsize);
2940 pStubMsg->MemorySize += memsize;
2942 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2944 return pStubMsg->MemorySize;
2948 /***********************************************************************
2949 * NdrComplexArrayMarshall [RPCRT4.@]
2951 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2952 unsigned char *pMemory,
2953 PFORMAT_STRING pFormat)
2955 ULONG i, count, def;
2956 BOOL variance_present;
2957 unsigned char alignment;
2958 int pointer_buffer_mark_set = 0;
2960 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2962 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2964 ERR("invalid format type %x\n", pFormat[0]);
2965 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2966 return NULL;
2969 alignment = pFormat[1] + 1;
2971 if (!pStubMsg->PointerBufferMark)
2973 /* save buffer fields that may be changed by buffer sizer functions
2974 * and that may be needed later on */
2975 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2976 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2977 unsigned long saved_max_count = pStubMsg->MaxCount;
2978 unsigned long saved_offset = pStubMsg->Offset;
2979 unsigned long saved_actual_count = pStubMsg->ActualCount;
2981 /* get the buffer pointer after complex array data, but before
2982 * pointer data */
2983 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2984 pStubMsg->IgnoreEmbeddedPointers = 1;
2985 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
2986 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2988 /* save it for use by embedded pointer code later */
2989 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2990 TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
2991 pointer_buffer_mark_set = 1;
2993 /* restore fields */
2994 pStubMsg->ActualCount = saved_actual_count;
2995 pStubMsg->Offset = saved_offset;
2996 pStubMsg->MaxCount = saved_max_count;
2997 pStubMsg->BufferLength = saved_buffer_length;
3000 def = *(const WORD*)&pFormat[2];
3001 pFormat += 4;
3003 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3004 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3006 variance_present = IsConformanceOrVariancePresent(pFormat);
3007 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3008 TRACE("variance = %d\n", pStubMsg->ActualCount);
3010 WriteConformance(pStubMsg);
3011 if (variance_present)
3012 WriteVariance(pStubMsg);
3014 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3016 count = pStubMsg->ActualCount;
3017 for (i = 0; i < count; i++)
3018 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3020 STD_OVERFLOW_CHECK(pStubMsg);
3022 if (pointer_buffer_mark_set)
3024 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3025 pStubMsg->PointerBufferMark = NULL;
3028 return NULL;
3031 /***********************************************************************
3032 * NdrComplexArrayUnmarshall [RPCRT4.@]
3034 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3035 unsigned char **ppMemory,
3036 PFORMAT_STRING pFormat,
3037 unsigned char fMustAlloc)
3039 ULONG i, count, size;
3040 unsigned char alignment;
3041 unsigned char *pMemory;
3042 unsigned char *saved_buffer;
3043 int pointer_buffer_mark_set = 0;
3044 int saved_ignore_embedded;
3046 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3048 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3050 ERR("invalid format type %x\n", pFormat[0]);
3051 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3052 return NULL;
3055 alignment = pFormat[1] + 1;
3057 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3058 /* save buffer pointer */
3059 saved_buffer = pStubMsg->Buffer;
3060 /* get the buffer pointer after complex array data, but before
3061 * pointer data */
3062 pStubMsg->IgnoreEmbeddedPointers = 1;
3063 pStubMsg->MemorySize = 0;
3064 NdrComplexArrayMemorySize(pStubMsg, pFormat);
3065 size = pStubMsg->MemorySize;
3066 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3068 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
3069 if (!pStubMsg->PointerBufferMark)
3071 /* save it for use by embedded pointer code later */
3072 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3073 pointer_buffer_mark_set = 1;
3075 /* restore the original buffer */
3076 pStubMsg->Buffer = saved_buffer;
3078 pFormat += 4;
3080 pFormat = ReadConformance(pStubMsg, pFormat);
3081 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3083 if (fMustAlloc || !*ppMemory)
3085 *ppMemory = NdrAllocate(pStubMsg, size);
3086 memset(*ppMemory, 0, size);
3089 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3091 pMemory = *ppMemory;
3092 count = pStubMsg->ActualCount;
3093 for (i = 0; i < count; i++)
3094 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
3096 if (pointer_buffer_mark_set)
3098 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3099 pStubMsg->PointerBufferMark = NULL;
3102 return NULL;
3105 /***********************************************************************
3106 * NdrComplexArrayBufferSize [RPCRT4.@]
3108 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3109 unsigned char *pMemory,
3110 PFORMAT_STRING pFormat)
3112 ULONG i, count, def;
3113 unsigned char alignment;
3114 BOOL variance_present;
3115 int pointer_length_set = 0;
3117 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3119 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3121 ERR("invalid format type %x\n", pFormat[0]);
3122 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3123 return;
3126 alignment = pFormat[1] + 1;
3128 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3130 /* save buffer fields that may be changed by buffer sizer functions
3131 * and that may be needed later on */
3132 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3133 unsigned long saved_buffer_length = pStubMsg->BufferLength;
3134 unsigned long saved_max_count = pStubMsg->MaxCount;
3135 unsigned long saved_offset = pStubMsg->Offset;
3136 unsigned long saved_actual_count = pStubMsg->ActualCount;
3138 /* get the buffer pointer after complex array data, but before
3139 * pointer data */
3140 pStubMsg->IgnoreEmbeddedPointers = 1;
3141 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3142 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3144 /* save it for use by embedded pointer code later */
3145 pStubMsg->PointerLength = pStubMsg->BufferLength;
3146 pointer_length_set = 1;
3148 /* restore fields */
3149 pStubMsg->ActualCount = saved_actual_count;
3150 pStubMsg->Offset = saved_offset;
3151 pStubMsg->MaxCount = saved_max_count;
3152 pStubMsg->BufferLength = saved_buffer_length;
3154 def = *(const WORD*)&pFormat[2];
3155 pFormat += 4;
3157 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3158 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3159 SizeConformance(pStubMsg);
3161 variance_present = IsConformanceOrVariancePresent(pFormat);
3162 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3163 TRACE("variance = %d\n", pStubMsg->ActualCount);
3165 if (variance_present)
3166 SizeVariance(pStubMsg);
3168 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3170 count = pStubMsg->ActualCount;
3171 for (i = 0; i < count; i++)
3172 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
3174 if(pointer_length_set)
3176 pStubMsg->BufferLength = pStubMsg->PointerLength;
3177 pStubMsg->PointerLength = 0;
3181 /***********************************************************************
3182 * NdrComplexArrayMemorySize [RPCRT4.@]
3184 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3185 PFORMAT_STRING pFormat)
3187 ULONG i, count, esize, SavedMemorySize, MemorySize;
3188 unsigned char alignment;
3189 unsigned char *Buffer;
3191 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3193 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3195 ERR("invalid format type %x\n", pFormat[0]);
3196 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3197 return 0;
3200 alignment = pFormat[1] + 1;
3202 pFormat += 4;
3204 pFormat = ReadConformance(pStubMsg, pFormat);
3205 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3207 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3209 SavedMemorySize = pStubMsg->MemorySize;
3211 Buffer = pStubMsg->Buffer;
3212 pStubMsg->MemorySize = 0;
3213 esize = ComplexStructMemorySize(pStubMsg, pFormat);
3214 pStubMsg->Buffer = Buffer;
3216 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3218 count = pStubMsg->ActualCount;
3219 for (i = 0; i < count; i++)
3220 ComplexStructMemorySize(pStubMsg, pFormat);
3222 pStubMsg->MemorySize = SavedMemorySize;
3224 pStubMsg->MemorySize += MemorySize;
3225 return MemorySize;
3228 /***********************************************************************
3229 * NdrComplexArrayFree [RPCRT4.@]
3231 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3232 unsigned char *pMemory,
3233 PFORMAT_STRING pFormat)
3235 ULONG i, count, def;
3237 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3239 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3241 ERR("invalid format type %x\n", pFormat[0]);
3242 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3243 return;
3246 def = *(const WORD*)&pFormat[2];
3247 pFormat += 4;
3249 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3250 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3252 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3253 TRACE("variance = %d\n", pStubMsg->ActualCount);
3255 count = pStubMsg->ActualCount;
3256 for (i = 0; i < count; i++)
3257 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
3260 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
3261 USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
3262 USER_MARSHAL_CB *umcb)
3264 umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
3265 pStubMsg->RpcMsg->DataRepresentation);
3266 umcb->pStubMsg = pStubMsg;
3267 umcb->pReserve = NULL;
3268 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
3269 umcb->CBType = cbtype;
3270 umcb->pFormat = pFormat;
3271 umcb->pTypeFormat = NULL /* FIXME */;
3274 #define USER_MARSHAL_PTR_PREFIX \
3275 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
3276 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
3278 /***********************************************************************
3279 * NdrUserMarshalMarshall [RPCRT4.@]
3281 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3282 unsigned char *pMemory,
3283 PFORMAT_STRING pFormat)
3285 unsigned flags = pFormat[1];
3286 unsigned index = *(const WORD*)&pFormat[2];
3287 unsigned char *saved_buffer = NULL;
3288 USER_MARSHAL_CB umcb;
3290 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3291 TRACE("index=%d\n", index);
3293 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
3295 if (flags & USER_MARSHAL_POINTER)
3297 ALIGN_POINTER(pStubMsg->Buffer, 4);
3298 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
3299 pStubMsg->Buffer += 4;
3300 if (pStubMsg->PointerBufferMark)
3302 saved_buffer = pStubMsg->Buffer;
3303 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3304 pStubMsg->PointerBufferMark = NULL;
3306 ALIGN_POINTER(pStubMsg->Buffer, 8);
3308 else
3309 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3311 pStubMsg->Buffer =
3312 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
3313 &umcb.Flags, pStubMsg->Buffer, pMemory);
3315 if (saved_buffer)
3317 STD_OVERFLOW_CHECK(pStubMsg);
3318 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3319 pStubMsg->Buffer = saved_buffer;
3322 STD_OVERFLOW_CHECK(pStubMsg);
3324 return NULL;
3327 /***********************************************************************
3328 * NdrUserMarshalUnmarshall [RPCRT4.@]
3330 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3331 unsigned char **ppMemory,
3332 PFORMAT_STRING pFormat,
3333 unsigned char fMustAlloc)
3335 unsigned flags = pFormat[1];
3336 unsigned index = *(const WORD*)&pFormat[2];
3337 DWORD memsize = *(const WORD*)&pFormat[4];
3338 unsigned char *saved_buffer = NULL;
3339 USER_MARSHAL_CB umcb;
3341 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3342 TRACE("index=%d\n", index);
3344 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
3346 if (flags & USER_MARSHAL_POINTER)
3348 ALIGN_POINTER(pStubMsg->Buffer, 4);
3349 /* skip pointer prefix */
3350 pStubMsg->Buffer += 4;
3351 if (pStubMsg->PointerBufferMark)
3353 saved_buffer = pStubMsg->Buffer;
3354 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3355 pStubMsg->PointerBufferMark = NULL;
3357 ALIGN_POINTER(pStubMsg->Buffer, 8);
3359 else
3360 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3362 if (fMustAlloc || !*ppMemory)
3363 *ppMemory = NdrAllocate(pStubMsg, memsize);
3365 pStubMsg->Buffer =
3366 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
3367 &umcb.Flags, pStubMsg->Buffer, *ppMemory);
3369 if (saved_buffer)
3371 STD_OVERFLOW_CHECK(pStubMsg);
3372 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3373 pStubMsg->Buffer = saved_buffer;
3376 return NULL;
3379 /***********************************************************************
3380 * NdrUserMarshalBufferSize [RPCRT4.@]
3382 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3383 unsigned char *pMemory,
3384 PFORMAT_STRING pFormat)
3386 unsigned flags = pFormat[1];
3387 unsigned index = *(const WORD*)&pFormat[2];
3388 DWORD bufsize = *(const WORD*)&pFormat[6];
3389 USER_MARSHAL_CB umcb;
3390 unsigned long saved_buffer_length = 0;
3392 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3393 TRACE("index=%d\n", index);
3395 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
3397 if (flags & USER_MARSHAL_POINTER)
3399 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3400 /* skip pointer prefix */
3401 safe_buffer_length_increment(pStubMsg, 4);
3402 if (pStubMsg->IgnoreEmbeddedPointers)
3403 return;
3404 if (pStubMsg->PointerLength)
3406 saved_buffer_length = pStubMsg->BufferLength;
3407 pStubMsg->BufferLength = pStubMsg->PointerLength;
3408 pStubMsg->PointerLength = 0;
3410 ALIGN_LENGTH(pStubMsg->BufferLength, 8);
3412 else
3413 ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
3415 if (bufsize) {
3416 TRACE("size=%d\n", bufsize);
3417 safe_buffer_length_increment(pStubMsg, bufsize);
3419 else
3420 pStubMsg->BufferLength =
3421 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
3422 &umcb.Flags, pStubMsg->BufferLength, pMemory);
3424 if (saved_buffer_length)
3426 pStubMsg->PointerLength = pStubMsg->BufferLength;
3427 pStubMsg->BufferLength = saved_buffer_length;
3432 /***********************************************************************
3433 * NdrUserMarshalMemorySize [RPCRT4.@]
3435 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3436 PFORMAT_STRING pFormat)
3438 unsigned flags = pFormat[1];
3439 unsigned index = *(const WORD*)&pFormat[2];
3440 DWORD memsize = *(const WORD*)&pFormat[4];
3441 DWORD bufsize = *(const WORD*)&pFormat[6];
3443 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3444 TRACE("index=%d\n", index);
3446 pStubMsg->MemorySize += memsize;
3448 if (flags & USER_MARSHAL_POINTER)
3450 ALIGN_POINTER(pStubMsg->Buffer, 4);
3451 /* skip pointer prefix */
3452 pStubMsg->Buffer += 4;
3453 if (pStubMsg->IgnoreEmbeddedPointers)
3454 return pStubMsg->MemorySize;
3455 ALIGN_POINTER(pStubMsg->Buffer, 8);
3457 else
3458 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3460 if (!bufsize)
3461 FIXME("not implemented for varying buffer size\n");
3463 pStubMsg->Buffer += bufsize;
3465 return pStubMsg->MemorySize;
3468 /***********************************************************************
3469 * NdrUserMarshalFree [RPCRT4.@]
3471 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
3472 unsigned char *pMemory,
3473 PFORMAT_STRING pFormat)
3475 /* unsigned flags = pFormat[1]; */
3476 unsigned index = *(const WORD*)&pFormat[2];
3477 USER_MARSHAL_CB umcb;
3479 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3480 TRACE("index=%d\n", index);
3482 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
3484 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
3485 &umcb.Flags, pMemory);
3488 /***********************************************************************
3489 * NdrClearOutParameters [RPCRT4.@]
3491 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
3492 PFORMAT_STRING pFormat,
3493 void *ArgAddr)
3495 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
3498 /***********************************************************************
3499 * NdrConvert [RPCRT4.@]
3501 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
3503 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
3504 /* FIXME: since this stub doesn't do any converting, the proper behavior
3505 is to raise an exception */
3508 /***********************************************************************
3509 * NdrConvert2 [RPCRT4.@]
3511 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
3513 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
3514 pStubMsg, pFormat, NumberParams);
3515 /* FIXME: since this stub doesn't do any converting, the proper behavior
3516 is to raise an exception */
3519 #include "pshpack1.h"
3520 typedef struct _NDR_CSTRUCT_FORMAT
3522 unsigned char type;
3523 unsigned char alignment;
3524 unsigned short memory_size;
3525 short offset_to_array_description;
3526 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
3527 #include "poppack.h"
3529 /***********************************************************************
3530 * NdrConformantStructMarshall [RPCRT4.@]
3532 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3533 unsigned char *pMemory,
3534 PFORMAT_STRING pFormat)
3536 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3537 PFORMAT_STRING pCArrayFormat;
3538 ULONG esize, bufsize;
3540 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3542 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3543 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3545 ERR("invalid format type %x\n", pCStructFormat->type);
3546 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3547 return NULL;
3550 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3551 pCStructFormat->offset_to_array_description;
3552 if (*pCArrayFormat != RPC_FC_CARRAY)
3554 ERR("invalid array format type %x\n", pCStructFormat->type);
3555 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3556 return NULL;
3558 esize = *(const WORD*)(pCArrayFormat+2);
3560 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3561 pCArrayFormat + 4, 0);
3563 WriteConformance(pStubMsg);
3565 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3567 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3569 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3570 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3572 ERR("integer overflow of memory_size %u with bufsize %u\n",
3573 pCStructFormat->memory_size, bufsize);
3574 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3576 /* copy constant sized part of struct */
3577 pStubMsg->BufferMark = pStubMsg->Buffer;
3578 safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
3580 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3581 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3583 return NULL;
3586 /***********************************************************************
3587 * NdrConformantStructUnmarshall [RPCRT4.@]
3589 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3590 unsigned char **ppMemory,
3591 PFORMAT_STRING pFormat,
3592 unsigned char fMustAlloc)
3594 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3595 PFORMAT_STRING pCArrayFormat;
3596 ULONG esize, bufsize;
3597 unsigned char *saved_buffer;
3599 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3601 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3602 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3604 ERR("invalid format type %x\n", pCStructFormat->type);
3605 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3606 return NULL;
3608 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3609 pCStructFormat->offset_to_array_description;
3610 if (*pCArrayFormat != RPC_FC_CARRAY)
3612 ERR("invalid array format type %x\n", pCStructFormat->type);
3613 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3614 return NULL;
3616 esize = *(const WORD*)(pCArrayFormat+2);
3618 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
3620 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3622 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3624 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3625 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3627 ERR("integer overflow of memory_size %u with bufsize %u\n",
3628 pCStructFormat->memory_size, bufsize);
3629 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3632 if (fMustAlloc)
3634 SIZE_T size = pCStructFormat->memory_size + bufsize;
3635 *ppMemory = NdrAllocate(pStubMsg, size);
3637 else
3639 if (!pStubMsg->IsClient && !*ppMemory)
3640 /* for servers, we just point straight into the RPC buffer */
3641 *ppMemory = pStubMsg->Buffer;
3644 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3645 safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
3646 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3647 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3649 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
3650 if (*ppMemory != saved_buffer)
3651 memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
3653 return NULL;
3656 /***********************************************************************
3657 * NdrConformantStructBufferSize [RPCRT4.@]
3659 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3660 unsigned char *pMemory,
3661 PFORMAT_STRING pFormat)
3663 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3664 PFORMAT_STRING pCArrayFormat;
3665 ULONG esize;
3667 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3669 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3670 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3672 ERR("invalid format type %x\n", pCStructFormat->type);
3673 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3674 return;
3676 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3677 pCStructFormat->offset_to_array_description;
3678 if (*pCArrayFormat != RPC_FC_CARRAY)
3680 ERR("invalid array format type %x\n", pCStructFormat->type);
3681 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3682 return;
3684 esize = *(const WORD*)(pCArrayFormat+2);
3686 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
3687 SizeConformance(pStubMsg);
3689 ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
3691 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3693 safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
3694 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
3696 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3697 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3700 /***********************************************************************
3701 * NdrConformantStructMemorySize [RPCRT4.@]
3703 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3704 PFORMAT_STRING pFormat)
3706 FIXME("stub\n");
3707 return 0;
3710 /***********************************************************************
3711 * NdrConformantStructFree [RPCRT4.@]
3713 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3714 unsigned char *pMemory,
3715 PFORMAT_STRING pFormat)
3717 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3718 PFORMAT_STRING pCArrayFormat;
3719 ULONG esize;
3721 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3723 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3724 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3726 ERR("invalid format type %x\n", pCStructFormat->type);
3727 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3728 return;
3731 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3732 pCStructFormat->offset_to_array_description;
3733 if (*pCArrayFormat != RPC_FC_CARRAY)
3735 ERR("invalid array format type %x\n", pCStructFormat->type);
3736 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3737 return;
3739 esize = *(const WORD*)(pCArrayFormat+2);
3741 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3742 pCArrayFormat + 4, 0);
3744 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3746 /* copy constant sized part of struct */
3747 pStubMsg->BufferMark = pStubMsg->Buffer;
3749 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3750 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3753 /***********************************************************************
3754 * NdrConformantVaryingStructMarshall [RPCRT4.@]
3756 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3757 unsigned char *pMemory,
3758 PFORMAT_STRING pFormat)
3760 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3761 PFORMAT_STRING pCVArrayFormat;
3762 ULONG esize, bufsize;
3764 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3766 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3767 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3769 ERR("invalid format type %x\n", pCVStructFormat->type);
3770 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3771 return NULL;
3774 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3775 pCVStructFormat->offset_to_array_description;
3776 switch (*pCVArrayFormat)
3778 case RPC_FC_CVARRAY:
3779 esize = *(const WORD*)(pCVArrayFormat+2);
3781 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3782 pCVArrayFormat + 4, 0);
3783 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3784 pCVArrayFormat, 0);
3785 break;
3786 case RPC_FC_C_CSTRING:
3787 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3788 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3789 esize = sizeof(char);
3790 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3791 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3792 pCVArrayFormat + 2, 0);
3793 else
3794 pStubMsg->MaxCount = pStubMsg->ActualCount;
3795 break;
3796 case RPC_FC_C_WSTRING:
3797 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3798 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3799 esize = sizeof(WCHAR);
3800 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3801 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3802 pCVArrayFormat + 2, 0);
3803 else
3804 pStubMsg->MaxCount = pStubMsg->ActualCount;
3805 break;
3806 default:
3807 ERR("invalid array format type %x\n", *pCVArrayFormat);
3808 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3809 return NULL;
3812 WriteConformance(pStubMsg);
3814 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3816 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3818 /* write constant sized part */
3819 pStubMsg->BufferMark = pStubMsg->Buffer;
3820 safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
3822 WriteVariance(pStubMsg);
3824 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3826 /* write array part */
3827 safe_copy_to_buffer(pStubMsg, pMemory + pCVStructFormat->memory_size, bufsize);
3829 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3831 return NULL;
3834 /***********************************************************************
3835 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
3837 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3838 unsigned char **ppMemory,
3839 PFORMAT_STRING pFormat,
3840 unsigned char fMustAlloc)
3842 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3843 PFORMAT_STRING pCVArrayFormat;
3844 ULONG esize, bufsize;
3845 unsigned char cvarray_type;
3847 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3849 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3850 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3852 ERR("invalid format type %x\n", pCVStructFormat->type);
3853 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3854 return NULL;
3857 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3858 pCVStructFormat->offset_to_array_description;
3859 cvarray_type = *pCVArrayFormat;
3860 switch (cvarray_type)
3862 case RPC_FC_CVARRAY:
3863 esize = *(const WORD*)(pCVArrayFormat+2);
3864 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3865 break;
3866 case RPC_FC_C_CSTRING:
3867 esize = sizeof(char);
3868 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3869 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3870 else
3871 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3872 break;
3873 case RPC_FC_C_WSTRING:
3874 esize = sizeof(WCHAR);
3875 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3876 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3877 else
3878 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3879 break;
3880 default:
3881 ERR("invalid array format type %x\n", *pCVArrayFormat);
3882 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3883 return NULL;
3886 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3888 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3890 /* work out how much memory to allocate if we need to do so */
3891 if (!*ppMemory || fMustAlloc)
3893 SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3894 *ppMemory = NdrAllocate(pStubMsg, size);
3897 /* copy the constant data */
3898 pStubMsg->BufferMark = pStubMsg->Buffer;
3899 safe_copy_from_buffer(pStubMsg, *ppMemory, pCVStructFormat->memory_size);
3901 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3903 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3905 if ((cvarray_type == RPC_FC_C_CSTRING) ||
3906 (cvarray_type == RPC_FC_C_WSTRING))
3908 ULONG i;
3909 /* strings must always have null terminating bytes */
3910 if (bufsize < esize)
3912 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
3913 RpcRaiseException(RPC_S_INVALID_BOUND);
3914 return NULL;
3916 for (i = bufsize - esize; i < bufsize; i++)
3917 if (pStubMsg->Buffer[i] != 0)
3919 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
3920 i, pStubMsg->Buffer[i]);
3921 RpcRaiseException(RPC_S_INVALID_BOUND);
3922 return NULL;
3926 /* copy the array data */
3927 safe_copy_from_buffer(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize);
3929 if (cvarray_type == RPC_FC_C_CSTRING)
3930 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3931 else if (cvarray_type == RPC_FC_C_WSTRING)
3932 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3934 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
3936 return NULL;
3939 /***********************************************************************
3940 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
3942 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3943 unsigned char *pMemory,
3944 PFORMAT_STRING pFormat)
3946 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3947 PFORMAT_STRING pCVArrayFormat;
3948 ULONG esize;
3950 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3952 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3953 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3955 ERR("invalid format type %x\n", pCVStructFormat->type);
3956 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3957 return;
3960 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3961 pCVStructFormat->offset_to_array_description;
3962 switch (*pCVArrayFormat)
3964 case RPC_FC_CVARRAY:
3965 esize = *(const WORD*)(pCVArrayFormat+2);
3967 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3968 pCVArrayFormat + 4, 0);
3969 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3970 pCVArrayFormat, 0);
3971 break;
3972 case RPC_FC_C_CSTRING:
3973 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3974 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3975 esize = sizeof(char);
3976 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3977 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3978 pCVArrayFormat + 2, 0);
3979 else
3980 pStubMsg->MaxCount = pStubMsg->ActualCount;
3981 break;
3982 case RPC_FC_C_WSTRING:
3983 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3984 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3985 esize = sizeof(WCHAR);
3986 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3987 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3988 pCVArrayFormat + 2, 0);
3989 else
3990 pStubMsg->MaxCount = pStubMsg->ActualCount;
3991 break;
3992 default:
3993 ERR("invalid array format type %x\n", *pCVArrayFormat);
3994 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3995 return;
3998 SizeConformance(pStubMsg);
4000 ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4002 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4004 safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4005 SizeVariance(pStubMsg);
4006 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4008 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4011 /***********************************************************************
4012 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
4014 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4015 PFORMAT_STRING pFormat)
4017 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4018 PFORMAT_STRING pCVArrayFormat;
4019 ULONG esize;
4020 unsigned char cvarray_type;
4022 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4024 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4025 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4027 ERR("invalid format type %x\n", pCVStructFormat->type);
4028 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4029 return 0;
4032 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4033 pCVStructFormat->offset_to_array_description;
4034 cvarray_type = *pCVArrayFormat;
4035 switch (cvarray_type)
4037 case RPC_FC_CVARRAY:
4038 esize = *(const WORD*)(pCVArrayFormat+2);
4039 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
4040 break;
4041 case RPC_FC_C_CSTRING:
4042 esize = sizeof(char);
4043 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4044 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4045 else
4046 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4047 break;
4048 case RPC_FC_C_WSTRING:
4049 esize = sizeof(WCHAR);
4050 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4051 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4052 else
4053 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4054 break;
4055 default:
4056 ERR("invalid array format type %x\n", *pCVArrayFormat);
4057 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4058 return 0;
4061 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4063 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4065 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4066 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
4067 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4069 pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
4071 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4073 return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
4076 /***********************************************************************
4077 * NdrConformantVaryingStructFree [RPCRT4.@]
4079 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4080 unsigned char *pMemory,
4081 PFORMAT_STRING pFormat)
4083 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4084 PFORMAT_STRING pCVArrayFormat;
4085 ULONG esize;
4087 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4089 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4090 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4092 ERR("invalid format type %x\n", pCVStructFormat->type);
4093 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4094 return;
4097 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4098 pCVStructFormat->offset_to_array_description;
4099 switch (*pCVArrayFormat)
4101 case RPC_FC_CVARRAY:
4102 esize = *(const WORD*)(pCVArrayFormat+2);
4104 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4105 pCVArrayFormat + 4, 0);
4106 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4107 pCVArrayFormat, 0);
4108 break;
4109 case RPC_FC_C_CSTRING:
4110 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4111 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4112 esize = sizeof(char);
4113 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4114 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4115 pCVArrayFormat + 2, 0);
4116 else
4117 pStubMsg->MaxCount = pStubMsg->ActualCount;
4118 break;
4119 case RPC_FC_C_WSTRING:
4120 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4121 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4122 esize = sizeof(WCHAR);
4123 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4124 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4125 pCVArrayFormat + 2, 0);
4126 else
4127 pStubMsg->MaxCount = pStubMsg->ActualCount;
4128 break;
4129 default:
4130 ERR("invalid array format type %x\n", *pCVArrayFormat);
4131 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4132 return;
4135 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4137 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4140 #include "pshpack1.h"
4141 typedef struct
4143 unsigned char type;
4144 unsigned char alignment;
4145 unsigned short total_size;
4146 } NDR_SMFARRAY_FORMAT;
4148 typedef struct
4150 unsigned char type;
4151 unsigned char alignment;
4152 unsigned long total_size;
4153 } NDR_LGFARRAY_FORMAT;
4154 #include "poppack.h"
4156 /***********************************************************************
4157 * NdrFixedArrayMarshall [RPCRT4.@]
4159 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4160 unsigned char *pMemory,
4161 PFORMAT_STRING pFormat)
4163 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4164 unsigned long total_size;
4166 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4168 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4169 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4171 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4172 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4173 return NULL;
4176 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4178 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4180 total_size = pSmFArrayFormat->total_size;
4181 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4183 else
4185 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4186 total_size = pLgFArrayFormat->total_size;
4187 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4190 pStubMsg->BufferMark = pStubMsg->Buffer;
4191 safe_copy_to_buffer(pStubMsg, pMemory, total_size);
4193 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4195 return NULL;
4198 /***********************************************************************
4199 * NdrFixedArrayUnmarshall [RPCRT4.@]
4201 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4202 unsigned char **ppMemory,
4203 PFORMAT_STRING pFormat,
4204 unsigned char fMustAlloc)
4206 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4207 unsigned long total_size;
4208 unsigned char *saved_buffer;
4210 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4212 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4213 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4215 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4216 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4217 return NULL;
4220 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4222 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4224 total_size = pSmFArrayFormat->total_size;
4225 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4227 else
4229 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4230 total_size = pLgFArrayFormat->total_size;
4231 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4234 if (fMustAlloc)
4235 *ppMemory = NdrAllocate(pStubMsg, total_size);
4236 else
4238 if (!pStubMsg->IsClient && !*ppMemory)
4239 /* for servers, we just point straight into the RPC buffer */
4240 *ppMemory = pStubMsg->Buffer;
4243 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4244 safe_buffer_increment(pStubMsg, total_size);
4245 pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4247 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4248 if (*ppMemory != saved_buffer)
4249 memcpy(*ppMemory, saved_buffer, total_size);
4251 return NULL;
4254 /***********************************************************************
4255 * NdrFixedArrayBufferSize [RPCRT4.@]
4257 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4258 unsigned char *pMemory,
4259 PFORMAT_STRING pFormat)
4261 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4262 unsigned long total_size;
4264 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4266 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4267 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4269 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4270 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4271 return;
4274 ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
4276 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4278 total_size = pSmFArrayFormat->total_size;
4279 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4281 else
4283 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4284 total_size = pLgFArrayFormat->total_size;
4285 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4287 safe_buffer_length_increment(pStubMsg, total_size);
4289 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4292 /***********************************************************************
4293 * NdrFixedArrayMemorySize [RPCRT4.@]
4295 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4296 PFORMAT_STRING pFormat)
4298 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4299 ULONG total_size;
4301 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4303 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4304 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4306 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4307 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4308 return 0;
4311 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4313 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4315 total_size = pSmFArrayFormat->total_size;
4316 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4318 else
4320 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4321 total_size = pLgFArrayFormat->total_size;
4322 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4324 pStubMsg->BufferMark = pStubMsg->Buffer;
4325 safe_buffer_increment(pStubMsg, total_size);
4326 pStubMsg->MemorySize += total_size;
4328 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4330 return total_size;
4333 /***********************************************************************
4334 * NdrFixedArrayFree [RPCRT4.@]
4336 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4337 unsigned char *pMemory,
4338 PFORMAT_STRING pFormat)
4340 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4342 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4344 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4345 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4347 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4348 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4349 return;
4352 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4353 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4354 else
4356 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4357 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4360 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4363 /***********************************************************************
4364 * NdrVaryingArrayMarshall [RPCRT4.@]
4366 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4367 unsigned char *pMemory,
4368 PFORMAT_STRING pFormat)
4370 unsigned char alignment;
4371 DWORD elements, esize;
4372 ULONG bufsize;
4374 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4376 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4377 (pFormat[0] != RPC_FC_LGVARRAY))
4379 ERR("invalid format type %x\n", pFormat[0]);
4380 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4381 return NULL;
4384 alignment = pFormat[1] + 1;
4386 if (pFormat[0] == RPC_FC_SMVARRAY)
4388 pFormat += 2;
4389 pFormat += sizeof(WORD);
4390 elements = *(const WORD*)pFormat;
4391 pFormat += sizeof(WORD);
4393 else
4395 pFormat += 2;
4396 pFormat += sizeof(DWORD);
4397 elements = *(const DWORD*)pFormat;
4398 pFormat += sizeof(DWORD);
4401 esize = *(const WORD*)pFormat;
4402 pFormat += sizeof(WORD);
4404 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4405 if ((pStubMsg->ActualCount > elements) ||
4406 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4408 RpcRaiseException(RPC_S_INVALID_BOUND);
4409 return NULL;
4412 WriteVariance(pStubMsg);
4414 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4416 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4417 pStubMsg->BufferMark = pStubMsg->Buffer;
4418 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
4420 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4422 return NULL;
4425 /***********************************************************************
4426 * NdrVaryingArrayUnmarshall [RPCRT4.@]
4428 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4429 unsigned char **ppMemory,
4430 PFORMAT_STRING pFormat,
4431 unsigned char fMustAlloc)
4433 unsigned char alignment;
4434 DWORD size, elements, esize;
4435 ULONG bufsize;
4437 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4439 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4440 (pFormat[0] != RPC_FC_LGVARRAY))
4442 ERR("invalid format type %x\n", pFormat[0]);
4443 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4444 return NULL;
4447 alignment = pFormat[1] + 1;
4449 if (pFormat[0] == RPC_FC_SMVARRAY)
4451 pFormat += 2;
4452 size = *(const WORD*)pFormat;
4453 pFormat += sizeof(WORD);
4454 elements = *(const WORD*)pFormat;
4455 pFormat += sizeof(WORD);
4457 else
4459 pFormat += 2;
4460 size = *(const DWORD*)pFormat;
4461 pFormat += sizeof(DWORD);
4462 elements = *(const DWORD*)pFormat;
4463 pFormat += sizeof(DWORD);
4466 esize = *(const WORD*)pFormat;
4467 pFormat += sizeof(WORD);
4469 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4471 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4473 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4475 if (!*ppMemory || fMustAlloc)
4476 *ppMemory = NdrAllocate(pStubMsg, size);
4477 safe_copy_from_buffer(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
4479 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
4481 return NULL;
4484 /***********************************************************************
4485 * NdrVaryingArrayBufferSize [RPCRT4.@]
4487 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4488 unsigned char *pMemory,
4489 PFORMAT_STRING pFormat)
4491 unsigned char alignment;
4492 DWORD elements, esize;
4494 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4496 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4497 (pFormat[0] != RPC_FC_LGVARRAY))
4499 ERR("invalid format type %x\n", pFormat[0]);
4500 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4501 return;
4504 alignment = pFormat[1] + 1;
4506 if (pFormat[0] == RPC_FC_SMVARRAY)
4508 pFormat += 2;
4509 pFormat += sizeof(WORD);
4510 elements = *(const WORD*)pFormat;
4511 pFormat += sizeof(WORD);
4513 else
4515 pFormat += 2;
4516 pFormat += sizeof(DWORD);
4517 elements = *(const DWORD*)pFormat;
4518 pFormat += sizeof(DWORD);
4521 esize = *(const WORD*)pFormat;
4522 pFormat += sizeof(WORD);
4524 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4525 if ((pStubMsg->ActualCount > elements) ||
4526 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4528 RpcRaiseException(RPC_S_INVALID_BOUND);
4529 return;
4532 SizeVariance(pStubMsg);
4534 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4536 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4538 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4541 /***********************************************************************
4542 * NdrVaryingArrayMemorySize [RPCRT4.@]
4544 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4545 PFORMAT_STRING pFormat)
4547 unsigned char alignment;
4548 DWORD size, elements, esize;
4550 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4552 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4553 (pFormat[0] != RPC_FC_LGVARRAY))
4555 ERR("invalid format type %x\n", pFormat[0]);
4556 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4557 return 0;
4560 alignment = pFormat[1] + 1;
4562 if (pFormat[0] == RPC_FC_SMVARRAY)
4564 pFormat += 2;
4565 size = *(const WORD*)pFormat;
4566 pFormat += sizeof(WORD);
4567 elements = *(const WORD*)pFormat;
4568 pFormat += sizeof(WORD);
4570 else
4572 pFormat += 2;
4573 size = *(const DWORD*)pFormat;
4574 pFormat += sizeof(DWORD);
4575 elements = *(const DWORD*)pFormat;
4576 pFormat += sizeof(DWORD);
4579 esize = *(const WORD*)pFormat;
4580 pFormat += sizeof(WORD);
4582 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4584 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4586 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4587 pStubMsg->MemorySize += size;
4589 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4591 return pStubMsg->MemorySize;
4594 /***********************************************************************
4595 * NdrVaryingArrayFree [RPCRT4.@]
4597 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4598 unsigned char *pMemory,
4599 PFORMAT_STRING pFormat)
4601 unsigned char alignment;
4602 DWORD elements;
4604 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4606 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4607 (pFormat[0] != RPC_FC_LGVARRAY))
4609 ERR("invalid format type %x\n", pFormat[0]);
4610 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4611 return;
4614 alignment = pFormat[1] + 1;
4616 if (pFormat[0] == RPC_FC_SMVARRAY)
4618 pFormat += 2;
4619 pFormat += sizeof(WORD);
4620 elements = *(const WORD*)pFormat;
4621 pFormat += sizeof(WORD);
4623 else
4625 pFormat += 2;
4626 pFormat += sizeof(DWORD);
4627 elements = *(const DWORD*)pFormat;
4628 pFormat += sizeof(DWORD);
4631 pFormat += sizeof(WORD);
4633 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4634 if ((pStubMsg->ActualCount > elements) ||
4635 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4637 RpcRaiseException(RPC_S_INVALID_BOUND);
4638 return;
4641 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4644 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
4646 switch (fc)
4648 case RPC_FC_BYTE:
4649 case RPC_FC_CHAR:
4650 case RPC_FC_SMALL:
4651 case RPC_FC_USMALL:
4652 return *(const UCHAR *)pMemory;
4653 case RPC_FC_WCHAR:
4654 case RPC_FC_SHORT:
4655 case RPC_FC_USHORT:
4656 case RPC_FC_ENUM16:
4657 return *(const USHORT *)pMemory;
4658 case RPC_FC_LONG:
4659 case RPC_FC_ULONG:
4660 case RPC_FC_ENUM32:
4661 return *(const ULONG *)pMemory;
4662 default:
4663 FIXME("Unhandled base type: 0x%02x\n", fc);
4664 return 0;
4668 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
4669 unsigned long discriminant,
4670 PFORMAT_STRING pFormat)
4672 unsigned short num_arms, arm, type;
4674 num_arms = *(const SHORT*)pFormat & 0x0fff;
4675 pFormat += 2;
4676 for(arm = 0; arm < num_arms; arm++)
4678 if(discriminant == *(const ULONG*)pFormat)
4680 pFormat += 4;
4681 break;
4683 pFormat += 6;
4686 type = *(const unsigned short*)pFormat;
4687 TRACE("type %04x\n", type);
4688 if(arm == num_arms) /* default arm extras */
4690 if(type == 0xffff)
4692 ERR("no arm for 0x%lx and no default case\n", discriminant);
4693 RpcRaiseException(RPC_S_INVALID_TAG);
4694 return NULL;
4696 if(type == 0)
4698 TRACE("falling back to empty default case for 0x%lx\n", discriminant);
4699 return NULL;
4702 return pFormat;
4705 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
4707 unsigned short type;
4709 pFormat += 2;
4711 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4712 if(!pFormat)
4713 return NULL;
4715 type = *(const unsigned short*)pFormat;
4716 if((type & 0xff00) == 0x8000)
4718 unsigned char basetype = LOBYTE(type);
4719 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4721 else
4723 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4724 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4725 if (m)
4727 unsigned char *saved_buffer = NULL;
4728 int pointer_buffer_mark_set = 0;
4729 switch(*desc)
4731 case RPC_FC_RP:
4732 case RPC_FC_UP:
4733 case RPC_FC_OP:
4734 case RPC_FC_FP:
4735 ALIGN_POINTER(pStubMsg->Buffer, 4);
4736 saved_buffer = pStubMsg->Buffer;
4737 if (pStubMsg->PointerBufferMark)
4739 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4740 pStubMsg->PointerBufferMark = NULL;
4741 pointer_buffer_mark_set = 1;
4743 else
4744 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
4746 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
4747 if (pointer_buffer_mark_set)
4749 STD_OVERFLOW_CHECK(pStubMsg);
4750 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4751 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
4753 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
4754 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
4755 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4757 pStubMsg->Buffer = saved_buffer + 4;
4759 break;
4760 default:
4761 m(pStubMsg, pMemory, desc);
4764 else FIXME("no marshaller for embedded type %02x\n", *desc);
4766 return NULL;
4769 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4770 unsigned char **ppMemory,
4771 ULONG discriminant,
4772 PFORMAT_STRING pFormat,
4773 unsigned char fMustAlloc)
4775 unsigned short type;
4777 pFormat += 2;
4779 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4780 if(!pFormat)
4781 return NULL;
4783 type = *(const unsigned short*)pFormat;
4784 if((type & 0xff00) == 0x8000)
4786 unsigned char basetype = LOBYTE(type);
4787 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
4789 else
4791 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4792 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
4793 if (m)
4795 unsigned char *saved_buffer = NULL;
4796 int pointer_buffer_mark_set = 0;
4797 switch(*desc)
4799 case RPC_FC_RP:
4800 case RPC_FC_UP:
4801 case RPC_FC_OP:
4802 case RPC_FC_FP:
4803 **(void***)ppMemory = NULL;
4804 ALIGN_POINTER(pStubMsg->Buffer, 4);
4805 saved_buffer = pStubMsg->Buffer;
4806 if (pStubMsg->PointerBufferMark)
4808 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4809 pStubMsg->PointerBufferMark = NULL;
4810 pointer_buffer_mark_set = 1;
4812 else
4813 pStubMsg->Buffer += 4; /* for pointer ID */
4815 if (saved_buffer + 4 > pStubMsg->BufferEnd)
4817 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
4818 saved_buffer, pStubMsg->BufferEnd);
4819 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4822 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
4823 if (pointer_buffer_mark_set)
4825 STD_OVERFLOW_CHECK(pStubMsg);
4826 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4827 pStubMsg->Buffer = saved_buffer + 4;
4829 break;
4830 default:
4831 m(pStubMsg, ppMemory, desc, fMustAlloc);
4834 else FIXME("no marshaller for embedded type %02x\n", *desc);
4836 return NULL;
4839 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
4840 unsigned char *pMemory,
4841 ULONG discriminant,
4842 PFORMAT_STRING pFormat)
4844 unsigned short type;
4846 pFormat += 2;
4848 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4849 if(!pFormat)
4850 return;
4852 type = *(const unsigned short*)pFormat;
4853 if((type & 0xff00) == 0x8000)
4855 unsigned char basetype = LOBYTE(type);
4856 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
4858 else
4860 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4861 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
4862 if (m)
4864 switch(*desc)
4866 case RPC_FC_RP:
4867 case RPC_FC_UP:
4868 case RPC_FC_OP:
4869 case RPC_FC_FP:
4870 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4871 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
4872 if (!pStubMsg->IgnoreEmbeddedPointers)
4874 int saved_buffer_length = pStubMsg->BufferLength;
4875 pStubMsg->BufferLength = pStubMsg->PointerLength;
4876 pStubMsg->PointerLength = 0;
4877 if(!pStubMsg->BufferLength)
4878 ERR("BufferLength == 0??\n");
4879 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
4880 pStubMsg->PointerLength = pStubMsg->BufferLength;
4881 pStubMsg->BufferLength = saved_buffer_length;
4883 break;
4884 default:
4885 m(pStubMsg, pMemory, desc);
4888 else FIXME("no buffersizer for embedded type %02x\n", *desc);
4892 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
4893 ULONG discriminant,
4894 PFORMAT_STRING pFormat)
4896 unsigned short type, size;
4898 size = *(const unsigned short*)pFormat;
4899 pStubMsg->Memory += size;
4900 pFormat += 2;
4902 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4903 if(!pFormat)
4904 return 0;
4906 type = *(const unsigned short*)pFormat;
4907 if((type & 0xff00) == 0x8000)
4909 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
4911 else
4913 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4914 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
4915 unsigned char *saved_buffer;
4916 if (m)
4918 switch(*desc)
4920 case RPC_FC_RP:
4921 case RPC_FC_UP:
4922 case RPC_FC_OP:
4923 case RPC_FC_FP:
4924 ALIGN_POINTER(pStubMsg->Buffer, 4);
4925 saved_buffer = pStubMsg->Buffer;
4926 safe_buffer_increment(pStubMsg, 4);
4927 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
4928 pStubMsg->MemorySize += 4;
4929 if (!pStubMsg->IgnoreEmbeddedPointers)
4930 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
4931 break;
4932 default:
4933 return m(pStubMsg, desc);
4936 else FIXME("no marshaller for embedded type %02x\n", *desc);
4939 TRACE("size %d\n", size);
4940 return size;
4943 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
4944 unsigned char *pMemory,
4945 ULONG discriminant,
4946 PFORMAT_STRING pFormat)
4948 unsigned short type;
4950 pFormat += 2;
4952 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4953 if(!pFormat)
4954 return;
4956 type = *(const unsigned short*)pFormat;
4957 if((type & 0xff00) != 0x8000)
4959 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4960 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
4961 if (m)
4963 switch(*desc)
4965 case RPC_FC_RP:
4966 case RPC_FC_UP:
4967 case RPC_FC_OP:
4968 case RPC_FC_FP:
4969 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
4970 break;
4971 default:
4972 m(pStubMsg, pMemory, desc);
4975 else FIXME("no freer for embedded type %02x\n", *desc);
4979 /***********************************************************************
4980 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
4982 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4983 unsigned char *pMemory,
4984 PFORMAT_STRING pFormat)
4986 unsigned char switch_type;
4987 unsigned char increment;
4988 ULONG switch_value;
4990 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4991 pFormat++;
4993 switch_type = *pFormat & 0xf;
4994 increment = (*pFormat & 0xf0) >> 4;
4995 pFormat++;
4997 ALIGN_POINTER(pStubMsg->Buffer, increment);
4999 switch_value = get_discriminant(switch_type, pMemory);
5000 TRACE("got switch value 0x%x\n", switch_value);
5002 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5003 pMemory += increment;
5005 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5008 /***********************************************************************
5009 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5011 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5012 unsigned char **ppMemory,
5013 PFORMAT_STRING pFormat,
5014 unsigned char fMustAlloc)
5016 unsigned char switch_type;
5017 unsigned char increment;
5018 ULONG switch_value;
5019 unsigned short size;
5020 unsigned char *pMemoryArm;
5022 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5023 pFormat++;
5025 switch_type = *pFormat & 0xf;
5026 increment = (*pFormat & 0xf0) >> 4;
5027 pFormat++;
5029 ALIGN_POINTER(pStubMsg->Buffer, increment);
5030 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5031 TRACE("got switch value 0x%x\n", switch_value);
5033 size = *(const unsigned short*)pFormat + increment;
5034 if(!*ppMemory || fMustAlloc)
5035 *ppMemory = NdrAllocate(pStubMsg, size);
5037 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5038 pMemoryArm = *ppMemory + increment;
5040 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
5043 /***********************************************************************
5044 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5046 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5047 unsigned char *pMemory,
5048 PFORMAT_STRING pFormat)
5050 unsigned char switch_type;
5051 unsigned char increment;
5052 ULONG switch_value;
5054 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5055 pFormat++;
5057 switch_type = *pFormat & 0xf;
5058 increment = (*pFormat & 0xf0) >> 4;
5059 pFormat++;
5061 ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5062 switch_value = get_discriminant(switch_type, pMemory);
5063 TRACE("got switch value 0x%x\n", switch_value);
5065 /* Add discriminant size */
5066 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5067 pMemory += increment;
5069 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5072 /***********************************************************************
5073 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5075 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5076 PFORMAT_STRING pFormat)
5078 unsigned char switch_type;
5079 unsigned char increment;
5080 ULONG switch_value;
5082 switch_type = *pFormat & 0xf;
5083 increment = (*pFormat & 0xf0) >> 4;
5084 pFormat++;
5086 ALIGN_POINTER(pStubMsg->Buffer, increment);
5087 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5088 TRACE("got switch value 0x%x\n", switch_value);
5090 pStubMsg->Memory += increment;
5092 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5095 /***********************************************************************
5096 * NdrEncapsulatedUnionFree [RPCRT4.@]
5098 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5099 unsigned char *pMemory,
5100 PFORMAT_STRING pFormat)
5102 unsigned char switch_type;
5103 unsigned char increment;
5104 ULONG switch_value;
5106 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5107 pFormat++;
5109 switch_type = *pFormat & 0xf;
5110 increment = (*pFormat & 0xf0) >> 4;
5111 pFormat++;
5113 switch_value = get_discriminant(switch_type, pMemory);
5114 TRACE("got switch value 0x%x\n", switch_value);
5116 pMemory += increment;
5118 return union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5121 /***********************************************************************
5122 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5124 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5125 unsigned char *pMemory,
5126 PFORMAT_STRING pFormat)
5128 unsigned char switch_type;
5130 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5131 pFormat++;
5133 switch_type = *pFormat;
5134 pFormat++;
5136 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5137 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5138 /* Marshall discriminant */
5139 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5141 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5144 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
5145 PFORMAT_STRING *ppFormat)
5147 long discriminant = 0;
5149 switch(**ppFormat)
5151 case RPC_FC_BYTE:
5152 case RPC_FC_CHAR:
5153 case RPC_FC_SMALL:
5154 case RPC_FC_USMALL:
5156 UCHAR d;
5157 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5158 discriminant = d;
5159 break;
5161 case RPC_FC_WCHAR:
5162 case RPC_FC_SHORT:
5163 case RPC_FC_USHORT:
5165 USHORT d;
5166 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5167 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5168 discriminant = d;
5169 break;
5171 case RPC_FC_LONG:
5172 case RPC_FC_ULONG:
5174 ULONG d;
5175 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5176 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5177 discriminant = d;
5178 break;
5180 default:
5181 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
5183 (*ppFormat)++;
5185 if (pStubMsg->fHasNewCorrDesc)
5186 *ppFormat += 6;
5187 else
5188 *ppFormat += 4;
5189 return discriminant;
5192 /**********************************************************************
5193 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
5195 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5196 unsigned char **ppMemory,
5197 PFORMAT_STRING pFormat,
5198 unsigned char fMustAlloc)
5200 long discriminant;
5201 unsigned short size;
5203 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5204 pFormat++;
5206 /* Unmarshall discriminant */
5207 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5208 TRACE("unmarshalled discriminant %lx\n", discriminant);
5210 pFormat += *(const SHORT*)pFormat;
5212 size = *(const unsigned short*)pFormat;
5214 if(!*ppMemory || fMustAlloc)
5215 *ppMemory = NdrAllocate(pStubMsg, size);
5217 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
5220 /***********************************************************************
5221 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
5223 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5224 unsigned char *pMemory,
5225 PFORMAT_STRING pFormat)
5227 unsigned char switch_type;
5229 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5230 pFormat++;
5232 switch_type = *pFormat;
5233 pFormat++;
5235 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5236 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5237 /* Add discriminant size */
5238 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5240 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5243 /***********************************************************************
5244 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
5246 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5247 PFORMAT_STRING pFormat)
5249 ULONG discriminant;
5251 pFormat++;
5252 /* Unmarshall discriminant */
5253 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5254 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
5256 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
5259 /***********************************************************************
5260 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
5262 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5263 unsigned char *pMemory,
5264 PFORMAT_STRING pFormat)
5266 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5267 pFormat++;
5268 pFormat++;
5270 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5271 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5273 return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5276 /***********************************************************************
5277 * NdrByteCountPointerMarshall [RPCRT4.@]
5279 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5280 unsigned char *pMemory,
5281 PFORMAT_STRING pFormat)
5283 FIXME("stub\n");
5284 return NULL;
5287 /***********************************************************************
5288 * NdrByteCountPointerUnmarshall [RPCRT4.@]
5290 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5291 unsigned char **ppMemory,
5292 PFORMAT_STRING pFormat,
5293 unsigned char fMustAlloc)
5295 FIXME("stub\n");
5296 return NULL;
5299 /***********************************************************************
5300 * NdrByteCountPointerBufferSize [RPCRT4.@]
5302 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5303 unsigned char *pMemory,
5304 PFORMAT_STRING pFormat)
5306 FIXME("stub\n");
5309 /***********************************************************************
5310 * NdrByteCountPointerMemorySize [RPCRT4.@]
5312 ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5313 PFORMAT_STRING pFormat)
5315 FIXME("stub\n");
5316 return 0;
5319 /***********************************************************************
5320 * NdrByteCountPointerFree [RPCRT4.@]
5322 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
5323 unsigned char *pMemory,
5324 PFORMAT_STRING pFormat)
5326 FIXME("stub\n");
5329 /***********************************************************************
5330 * NdrXmitOrRepAsMarshall [RPCRT4.@]
5332 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5333 unsigned char *pMemory,
5334 PFORMAT_STRING pFormat)
5336 FIXME("stub\n");
5337 return NULL;
5340 /***********************************************************************
5341 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
5343 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5344 unsigned char **ppMemory,
5345 PFORMAT_STRING pFormat,
5346 unsigned char fMustAlloc)
5348 FIXME("stub\n");
5349 return NULL;
5352 /***********************************************************************
5353 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
5355 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5356 unsigned char *pMemory,
5357 PFORMAT_STRING pFormat)
5359 FIXME("stub\n");
5362 /***********************************************************************
5363 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
5365 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5366 PFORMAT_STRING pFormat)
5368 FIXME("stub\n");
5369 return 0;
5372 /***********************************************************************
5373 * NdrXmitOrRepAsFree [RPCRT4.@]
5375 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
5376 unsigned char *pMemory,
5377 PFORMAT_STRING pFormat)
5379 FIXME("stub\n");
5382 #include "pshpack1.h"
5383 typedef struct
5385 unsigned char type;
5386 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
5387 ULONG low_value;
5388 ULONG high_value;
5389 } NDR_RANGE;
5390 #include "poppack.h"
5392 /***********************************************************************
5393 * NdrRangeMarshall [internal]
5395 unsigned char *WINAPI NdrRangeMarshall(
5396 PMIDL_STUB_MESSAGE pStubMsg,
5397 unsigned char *pMemory,
5398 PFORMAT_STRING pFormat)
5400 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5401 unsigned char base_type;
5403 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5405 if (pRange->type != RPC_FC_RANGE)
5407 ERR("invalid format type %x\n", pRange->type);
5408 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5409 return NULL;
5412 base_type = pRange->flags_type & 0xf;
5414 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
5417 /***********************************************************************
5418 * NdrRangeUnmarshall
5420 unsigned char *WINAPI NdrRangeUnmarshall(
5421 PMIDL_STUB_MESSAGE pStubMsg,
5422 unsigned char **ppMemory,
5423 PFORMAT_STRING pFormat,
5424 unsigned char fMustAlloc)
5426 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5427 unsigned char base_type;
5429 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5431 if (pRange->type != RPC_FC_RANGE)
5433 ERR("invalid format type %x\n", pRange->type);
5434 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5435 return NULL;
5437 base_type = pRange->flags_type & 0xf;
5439 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
5440 base_type, pRange->low_value, pRange->high_value);
5442 #define RANGE_UNMARSHALL(type, format_spec) \
5443 do \
5445 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5446 if (fMustAlloc || !*ppMemory) \
5447 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5448 if (pStubMsg->Buffer + sizeof(type) > pStubMsg->BufferEnd) \
5450 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
5451 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
5452 RpcRaiseException(RPC_X_BAD_STUB_DATA); \
5454 if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \
5455 (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \
5457 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
5458 *(type *)pStubMsg->Buffer, (type)pRange->low_value, \
5459 (type)pRange->high_value); \
5460 RpcRaiseException(RPC_S_INVALID_BOUND); \
5461 return NULL; \
5463 TRACE("*ppMemory: %p\n", *ppMemory); \
5464 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5465 pStubMsg->Buffer += sizeof(type); \
5466 } while (0)
5468 switch(base_type)
5470 case RPC_FC_CHAR:
5471 case RPC_FC_SMALL:
5472 RANGE_UNMARSHALL(UCHAR, "%d");
5473 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5474 break;
5475 case RPC_FC_BYTE:
5476 case RPC_FC_USMALL:
5477 RANGE_UNMARSHALL(CHAR, "%u");
5478 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5479 break;
5480 case RPC_FC_WCHAR: /* FIXME: valid? */
5481 case RPC_FC_USHORT:
5482 RANGE_UNMARSHALL(USHORT, "%u");
5483 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5484 break;
5485 case RPC_FC_SHORT:
5486 RANGE_UNMARSHALL(SHORT, "%d");
5487 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5488 break;
5489 case RPC_FC_LONG:
5490 RANGE_UNMARSHALL(LONG, "%d");
5491 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5492 break;
5493 case RPC_FC_ULONG:
5494 RANGE_UNMARSHALL(ULONG, "%u");
5495 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5496 break;
5497 case RPC_FC_ENUM16:
5498 case RPC_FC_ENUM32:
5499 FIXME("Unhandled enum type\n");
5500 break;
5501 case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */
5502 case RPC_FC_FLOAT:
5503 case RPC_FC_DOUBLE:
5504 case RPC_FC_HYPER:
5505 default:
5506 ERR("invalid range base type: 0x%02x\n", base_type);
5507 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5510 return NULL;
5513 /***********************************************************************
5514 * NdrRangeBufferSize [internal]
5516 void WINAPI NdrRangeBufferSize(
5517 PMIDL_STUB_MESSAGE pStubMsg,
5518 unsigned char *pMemory,
5519 PFORMAT_STRING pFormat)
5521 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5522 unsigned char base_type;
5524 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5526 if (pRange->type != RPC_FC_RANGE)
5528 ERR("invalid format type %x\n", pRange->type);
5529 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5531 base_type = pRange->flags_type & 0xf;
5533 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
5536 /***********************************************************************
5537 * NdrRangeMemorySize [internal]
5539 ULONG WINAPI NdrRangeMemorySize(
5540 PMIDL_STUB_MESSAGE pStubMsg,
5541 PFORMAT_STRING pFormat)
5543 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5544 unsigned char base_type;
5546 if (pRange->type != RPC_FC_RANGE)
5548 ERR("invalid format type %x\n", pRange->type);
5549 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5550 return 0;
5552 base_type = pRange->flags_type & 0xf;
5554 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
5557 /***********************************************************************
5558 * NdrRangeFree [internal]
5560 void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
5561 unsigned char *pMemory,
5562 PFORMAT_STRING pFormat)
5564 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5566 /* nothing to do */
5569 /***********************************************************************
5570 * NdrBaseTypeMarshall [internal]
5572 static unsigned char *WINAPI NdrBaseTypeMarshall(
5573 PMIDL_STUB_MESSAGE pStubMsg,
5574 unsigned char *pMemory,
5575 PFORMAT_STRING pFormat)
5577 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5579 switch(*pFormat)
5581 case RPC_FC_BYTE:
5582 case RPC_FC_CHAR:
5583 case RPC_FC_SMALL:
5584 case RPC_FC_USMALL:
5585 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
5586 TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
5587 break;
5588 case RPC_FC_WCHAR:
5589 case RPC_FC_SHORT:
5590 case RPC_FC_USHORT:
5591 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5592 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
5593 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
5594 break;
5595 case RPC_FC_LONG:
5596 case RPC_FC_ULONG:
5597 case RPC_FC_ERROR_STATUS_T:
5598 case RPC_FC_ENUM32:
5599 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5600 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
5601 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
5602 break;
5603 case RPC_FC_FLOAT:
5604 ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
5605 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
5606 break;
5607 case RPC_FC_DOUBLE:
5608 ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
5609 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
5610 break;
5611 case RPC_FC_HYPER:
5612 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
5613 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
5614 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
5615 break;
5616 case RPC_FC_ENUM16:
5617 /* only 16-bits on the wire, so do a sanity check */
5618 if (*(UINT *)pMemory > SHRT_MAX)
5619 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
5620 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5621 if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5622 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5623 *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
5624 pStubMsg->Buffer += sizeof(USHORT);
5625 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
5626 break;
5627 case RPC_FC_IGNORE:
5628 break;
5629 default:
5630 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5633 /* FIXME: what is the correct return value? */
5634 return NULL;
5637 /***********************************************************************
5638 * NdrBaseTypeUnmarshall [internal]
5640 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
5641 PMIDL_STUB_MESSAGE pStubMsg,
5642 unsigned char **ppMemory,
5643 PFORMAT_STRING pFormat,
5644 unsigned char fMustAlloc)
5646 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5648 #define BASE_TYPE_UNMARSHALL(type) \
5649 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5650 if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
5652 *ppMemory = pStubMsg->Buffer; \
5653 TRACE("*ppMemory: %p\n", *ppMemory); \
5655 else \
5657 if (fMustAlloc) \
5658 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5659 TRACE("*ppMemory: %p\n", *ppMemory); \
5660 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5662 pStubMsg->Buffer += sizeof(type);
5664 switch(*pFormat)
5666 case RPC_FC_BYTE:
5667 case RPC_FC_CHAR:
5668 case RPC_FC_SMALL:
5669 case RPC_FC_USMALL:
5670 BASE_TYPE_UNMARSHALL(UCHAR);
5671 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5672 break;
5673 case RPC_FC_WCHAR:
5674 case RPC_FC_SHORT:
5675 case RPC_FC_USHORT:
5676 BASE_TYPE_UNMARSHALL(USHORT);
5677 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5678 break;
5679 case RPC_FC_LONG:
5680 case RPC_FC_ULONG:
5681 case RPC_FC_ERROR_STATUS_T:
5682 case RPC_FC_ENUM32:
5683 BASE_TYPE_UNMARSHALL(ULONG);
5684 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5685 break;
5686 case RPC_FC_FLOAT:
5687 BASE_TYPE_UNMARSHALL(float);
5688 TRACE("value: %f\n", **(float **)ppMemory);
5689 break;
5690 case RPC_FC_DOUBLE:
5691 BASE_TYPE_UNMARSHALL(double);
5692 TRACE("value: %f\n", **(double **)ppMemory);
5693 break;
5694 case RPC_FC_HYPER:
5695 BASE_TYPE_UNMARSHALL(ULONGLONG);
5696 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
5697 break;
5698 case RPC_FC_ENUM16:
5699 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5700 if (fMustAlloc || !*ppMemory)
5701 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
5702 if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
5703 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5704 TRACE("*ppMemory: %p\n", *ppMemory);
5705 /* 16-bits on the wire, but int in memory */
5706 **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
5707 pStubMsg->Buffer += sizeof(USHORT);
5708 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
5709 break;
5710 case RPC_FC_IGNORE:
5711 break;
5712 default:
5713 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5715 #undef BASE_TYPE_UNMARSHALL
5717 /* FIXME: what is the correct return value? */
5719 return NULL;
5722 /***********************************************************************
5723 * NdrBaseTypeBufferSize [internal]
5725 static void WINAPI NdrBaseTypeBufferSize(
5726 PMIDL_STUB_MESSAGE pStubMsg,
5727 unsigned char *pMemory,
5728 PFORMAT_STRING pFormat)
5730 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5732 switch(*pFormat)
5734 case RPC_FC_BYTE:
5735 case RPC_FC_CHAR:
5736 case RPC_FC_SMALL:
5737 case RPC_FC_USMALL:
5738 safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
5739 break;
5740 case RPC_FC_WCHAR:
5741 case RPC_FC_SHORT:
5742 case RPC_FC_USHORT:
5743 case RPC_FC_ENUM16:
5744 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
5745 safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
5746 break;
5747 case RPC_FC_LONG:
5748 case RPC_FC_ULONG:
5749 case RPC_FC_ENUM32:
5750 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
5751 safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
5752 break;
5753 case RPC_FC_FLOAT:
5754 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
5755 safe_buffer_length_increment(pStubMsg, sizeof(float));
5756 break;
5757 case RPC_FC_DOUBLE:
5758 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
5759 safe_buffer_length_increment(pStubMsg, sizeof(double));
5760 break;
5761 case RPC_FC_HYPER:
5762 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
5763 safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
5764 break;
5765 case RPC_FC_ERROR_STATUS_T:
5766 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
5767 safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
5768 break;
5769 case RPC_FC_IGNORE:
5770 break;
5771 default:
5772 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5776 /***********************************************************************
5777 * NdrBaseTypeMemorySize [internal]
5779 static ULONG WINAPI NdrBaseTypeMemorySize(
5780 PMIDL_STUB_MESSAGE pStubMsg,
5781 PFORMAT_STRING pFormat)
5783 TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
5785 switch(*pFormat)
5787 case RPC_FC_BYTE:
5788 case RPC_FC_CHAR:
5789 case RPC_FC_SMALL:
5790 case RPC_FC_USMALL:
5791 safe_buffer_increment(pStubMsg, sizeof(UCHAR));
5792 pStubMsg->MemorySize += sizeof(UCHAR);
5793 return sizeof(UCHAR);
5794 case RPC_FC_WCHAR:
5795 case RPC_FC_SHORT:
5796 case RPC_FC_USHORT:
5797 safe_buffer_increment(pStubMsg, sizeof(USHORT));
5798 pStubMsg->MemorySize += sizeof(USHORT);
5799 return sizeof(USHORT);
5800 case RPC_FC_LONG:
5801 case RPC_FC_ULONG:
5802 case RPC_FC_ENUM32:
5803 safe_buffer_increment(pStubMsg, sizeof(ULONG));
5804 pStubMsg->MemorySize += sizeof(ULONG);
5805 return sizeof(ULONG);
5806 case RPC_FC_FLOAT:
5807 safe_buffer_increment(pStubMsg, sizeof(float));
5808 pStubMsg->MemorySize += sizeof(float);
5809 return sizeof(float);
5810 case RPC_FC_DOUBLE:
5811 safe_buffer_increment(pStubMsg, sizeof(double));
5812 pStubMsg->MemorySize += sizeof(double);
5813 return sizeof(double);
5814 case RPC_FC_HYPER:
5815 safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
5816 pStubMsg->MemorySize += sizeof(ULONGLONG);
5817 return sizeof(ULONGLONG);
5818 case RPC_FC_ERROR_STATUS_T:
5819 safe_buffer_increment(pStubMsg, sizeof(error_status_t));
5820 pStubMsg->MemorySize += sizeof(error_status_t);
5821 return sizeof(error_status_t);
5822 case RPC_FC_ENUM16:
5823 safe_buffer_increment(pStubMsg, sizeof(USHORT));
5824 pStubMsg->MemorySize += sizeof(UINT);
5825 return sizeof(UINT);
5826 case RPC_FC_IGNORE:
5827 pStubMsg->MemorySize += sizeof(void *);
5828 return sizeof(void *);
5829 default:
5830 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5831 return 0;
5835 /***********************************************************************
5836 * NdrBaseTypeFree [internal]
5838 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
5839 unsigned char *pMemory,
5840 PFORMAT_STRING pFormat)
5842 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5844 /* nothing to do */
5847 /***********************************************************************
5848 * NdrContextHandleBufferSize [internal]
5850 static void WINAPI NdrContextHandleBufferSize(
5851 PMIDL_STUB_MESSAGE pStubMsg,
5852 unsigned char *pMemory,
5853 PFORMAT_STRING pFormat)
5855 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5857 if (*pFormat != RPC_FC_BIND_CONTEXT)
5859 ERR("invalid format type %x\n", *pFormat);
5860 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5862 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5863 safe_buffer_length_increment(pStubMsg, cbNDRContext);
5866 /***********************************************************************
5867 * NdrContextHandleMarshall [internal]
5869 static unsigned char *WINAPI NdrContextHandleMarshall(
5870 PMIDL_STUB_MESSAGE pStubMsg,
5871 unsigned char *pMemory,
5872 PFORMAT_STRING pFormat)
5874 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5876 if (*pFormat != RPC_FC_BIND_CONTEXT)
5878 ERR("invalid format type %x\n", *pFormat);
5879 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5882 if (pFormat[1] & 0x80)
5883 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
5884 else
5885 NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE);
5887 return NULL;
5890 /***********************************************************************
5891 * NdrContextHandleUnmarshall [internal]
5893 static unsigned char *WINAPI NdrContextHandleUnmarshall(
5894 PMIDL_STUB_MESSAGE pStubMsg,
5895 unsigned char **ppMemory,
5896 PFORMAT_STRING pFormat,
5897 unsigned char fMustAlloc)
5899 if (*pFormat != RPC_FC_BIND_CONTEXT)
5901 ERR("invalid format type %x\n", *pFormat);
5902 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5905 **(NDR_CCONTEXT **)ppMemory = NULL;
5906 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
5908 return NULL;
5911 /***********************************************************************
5912 * NdrClientContextMarshall [RPCRT4.@]
5914 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5915 NDR_CCONTEXT ContextHandle,
5916 int fCheck)
5918 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
5920 ALIGN_POINTER(pStubMsg->Buffer, 4);
5922 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5924 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
5925 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5926 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5929 /* FIXME: what does fCheck do? */
5930 NDRCContextMarshall(ContextHandle,
5931 pStubMsg->Buffer);
5933 pStubMsg->Buffer += cbNDRContext;
5936 /***********************************************************************
5937 * NdrClientContextUnmarshall [RPCRT4.@]
5939 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5940 NDR_CCONTEXT * pContextHandle,
5941 RPC_BINDING_HANDLE BindHandle)
5943 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
5945 ALIGN_POINTER(pStubMsg->Buffer, 4);
5947 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
5948 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5950 NDRCContextUnmarshall(pContextHandle,
5951 BindHandle,
5952 pStubMsg->Buffer,
5953 pStubMsg->RpcMsg->DataRepresentation);
5955 pStubMsg->Buffer += cbNDRContext;
5958 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5959 NDR_SCONTEXT ContextHandle,
5960 NDR_RUNDOWN RundownRoutine )
5962 FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
5965 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
5967 FIXME("(%p): stub\n", pStubMsg);
5968 return NULL;
5971 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
5972 unsigned char* pMemory,
5973 PFORMAT_STRING pFormat)
5975 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
5978 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
5979 PFORMAT_STRING pFormat)
5981 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5982 return NULL;
5985 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5986 NDR_SCONTEXT ContextHandle,
5987 NDR_RUNDOWN RundownRoutine,
5988 PFORMAT_STRING pFormat)
5990 FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
5993 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5994 PFORMAT_STRING pFormat)
5996 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
5997 return NULL;
6000 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e
6002 typedef struct ndr_context_handle
6004 DWORD attributes;
6005 GUID uuid;
6006 } ndr_context_handle;
6008 struct context_handle_entry
6010 struct list entry;
6011 DWORD magic;
6012 RPC_BINDING_HANDLE handle;
6013 ndr_context_handle wire_data;
6016 static struct list context_handle_list = LIST_INIT(context_handle_list);
6018 static CRITICAL_SECTION ndr_context_cs;
6019 static CRITICAL_SECTION_DEBUG ndr_context_debug =
6021 0, 0, &ndr_context_cs,
6022 { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList },
6023 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") }
6025 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 };
6027 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
6029 struct context_handle_entry *che = (struct context_handle_entry*) CContext;
6031 if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
6032 return NULL;
6033 return che;
6036 static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid)
6038 struct context_handle_entry *che;
6039 LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry)
6040 if (IsEqualGUID(&che->wire_data.uuid, uuid))
6041 return che;
6042 return NULL;
6045 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
6047 struct context_handle_entry *che;
6048 RPC_BINDING_HANDLE handle = NULL;
6050 TRACE("%p\n", CContext);
6052 EnterCriticalSection(&ndr_context_cs);
6053 che = get_context_entry(CContext);
6054 if (che)
6055 handle = che->handle;
6056 LeaveCriticalSection(&ndr_context_cs);
6058 if (!handle)
6059 RpcRaiseException(ERROR_INVALID_HANDLE);
6060 return handle;
6063 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
6065 struct context_handle_entry *che;
6067 TRACE("%p %p\n", CContext, pBuff);
6069 if (CContext)
6071 EnterCriticalSection(&ndr_context_cs);
6072 che = get_context_entry(CContext);
6073 memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle));
6074 LeaveCriticalSection(&ndr_context_cs);
6076 else
6078 ndr_context_handle *wire_data = (ndr_context_handle *)pBuff;
6079 wire_data->attributes = 0;
6080 wire_data->uuid = GUID_NULL;
6084 /***********************************************************************
6085 * RpcSmDestroyClientContext [RPCRT4.@]
6087 RPC_STATUS WINAPI RpcSmDestroyClientContext(void **ContextHandle)
6089 RPC_STATUS status = RPC_X_SS_CONTEXT_MISMATCH;
6090 struct context_handle_entry *che = NULL;
6092 TRACE("(%p)\n", ContextHandle);
6094 EnterCriticalSection(&ndr_context_cs);
6095 che = get_context_entry(*ContextHandle);
6096 *ContextHandle = NULL;
6097 if (che)
6099 status = RPC_S_OK;
6100 list_remove(&che->entry);
6103 LeaveCriticalSection(&ndr_context_cs);
6105 if (che)
6107 RpcBindingFree(&che->handle);
6108 HeapFree(GetProcessHeap(), 0, che);
6111 return status;
6114 /***********************************************************************
6115 * RpcSsDestroyClientContext [RPCRT4.@]
6117 void WINAPI RpcSsDestroyClientContext(void **ContextHandle)
6119 RPC_STATUS status = RpcSmDestroyClientContext(ContextHandle);
6120 if (status != RPC_S_OK)
6121 RpcRaiseException(status);
6124 static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext,
6125 RPC_BINDING_HANDLE hBinding,
6126 const ndr_context_handle *chi)
6128 struct context_handle_entry *che = NULL;
6130 /* a null UUID means we should free the context handle */
6131 if (IsEqualGUID(&chi->uuid, &GUID_NULL))
6133 if (*CContext)
6135 che = get_context_entry(*CContext);
6136 if (!che)
6137 return ERROR_INVALID_HANDLE;
6138 list_remove(&che->entry);
6139 RpcBindingFree(&che->handle);
6140 HeapFree(GetProcessHeap(), 0, che);
6141 che = NULL;
6144 /* if there's no existing entry matching the GUID, allocate one */
6145 else if (!(che = context_entry_from_guid(&chi->uuid)))
6147 che = HeapAlloc(GetProcessHeap(), 0, sizeof *che);
6148 if (!che)
6149 return ERROR_NOT_ENOUGH_MEMORY;
6150 che->magic = NDR_CONTEXT_HANDLE_MAGIC;
6151 RpcBindingCopy(hBinding, &che->handle);
6152 list_add_tail(&context_handle_list, &che->entry);
6153 memcpy(&che->wire_data, chi, sizeof *chi);
6156 *CContext = che;
6158 return ERROR_SUCCESS;
6161 /***********************************************************************
6162 * NDRCContextUnmarshall [RPCRT4.@]
6164 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext,
6165 RPC_BINDING_HANDLE hBinding,
6166 void *pBuff, ULONG DataRepresentation)
6168 UINT r;
6170 TRACE("*%p=(%p) %p %p %08x\n",
6171 CContext, *CContext, hBinding, pBuff, DataRepresentation);
6173 EnterCriticalSection(&ndr_context_cs);
6174 r = ndr_update_context_handle(CContext, hBinding, pBuff);
6175 LeaveCriticalSection(&ndr_context_cs);
6176 if (r)
6177 RpcRaiseException(r);
6180 /***********************************************************************
6181 * NDRSContextMarshall [RPCRT4.@]
6183 void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext,
6184 void *pBuff,
6185 NDR_RUNDOWN userRunDownIn)
6187 FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn);
6190 /***********************************************************************
6191 * NDRSContextMarshallEx [RPCRT4.@]
6193 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding,
6194 NDR_SCONTEXT CContext,
6195 void *pBuff,
6196 NDR_RUNDOWN userRunDownIn)
6198 FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn);
6201 /***********************************************************************
6202 * NDRSContextMarshall2 [RPCRT4.@]
6204 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
6205 NDR_SCONTEXT CContext,
6206 void *pBuff,
6207 NDR_RUNDOWN userRunDownIn,
6208 void *CtxGuard, ULONG Flags)
6210 FIXME("(%p %p %p %p %p %u): stub\n",
6211 hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags);
6214 /***********************************************************************
6215 * NDRSContextUnmarshall [RPCRT4.@]
6217 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff,
6218 ULONG DataRepresentation)
6220 FIXME("(%p %08x): stub\n", pBuff, DataRepresentation);
6221 return NULL;
6224 /***********************************************************************
6225 * NDRSContextUnmarshallEx [RPCRT4.@]
6227 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding,
6228 void *pBuff,
6229 ULONG DataRepresentation)
6231 FIXME("(%p %p %08x): stub\n", hBinding, pBuff, DataRepresentation);
6232 return NULL;
6235 /***********************************************************************
6236 * NDRSContextUnmarshall2 [RPCRT4.@]
6238 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
6239 void *pBuff,
6240 ULONG DataRepresentation,
6241 void *CtxGuard, ULONG Flags)
6243 FIXME("(%p %p %08x %p %u): stub\n",
6244 hBinding, pBuff, DataRepresentation, CtxGuard, Flags);
6245 return NULL;