rpcrt4: Fix NdrConformantStringUnmarshall to always increment the buffer during unmar...
[wine/multimedia.git] / dlls / rpcrt4 / ndr_marshall.c
blob2322c78a79323a97d33cc1523ecda627e6ae2782
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 in base type and user marshall functions
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <assert.h>
35 #include <limits.h>
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winerror.h"
41 #include "ndr_misc.h"
42 #include "rpcndr.h"
44 #include "wine/unicode.h"
45 #include "wine/rpcfc.h"
47 #include "wine/debug.h"
48 #include "wine/list.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(ole);
52 #if defined(__i386__)
53 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
54 (*((UINT32 *)(pchar)) = (uint32))
56 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
57 (*((UINT32 *)(pchar)))
58 #else
59 /* these would work for i386 too, but less efficient */
60 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
61 (*(pchar) = LOBYTE(LOWORD(uint32)), \
62 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
63 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
64 *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
65 (uint32)) /* allow as r-value */
67 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
68 (MAKELONG( \
69 MAKEWORD(*(pchar), *((pchar)+1)), \
70 MAKEWORD(*((pchar)+2), *((pchar)+3))))
71 #endif
73 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
74 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
75 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
76 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
77 *(pchar) = HIBYTE(HIWORD(uint32)), \
78 (uint32)) /* allow as r-value */
80 #define BIG_ENDIAN_UINT32_READ(pchar) \
81 (MAKELONG( \
82 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
83 MAKEWORD(*((pchar)+1), *(pchar))))
85 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
86 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
87 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
88 # define NDR_LOCAL_UINT32_READ(pchar) \
89 BIG_ENDIAN_UINT32_READ(pchar)
90 #else
91 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
92 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
93 # define NDR_LOCAL_UINT32_READ(pchar) \
94 LITTLE_ENDIAN_UINT32_READ(pchar)
95 #endif
97 /* _Align must be the desired alignment,
98 * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
99 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
100 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
101 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
102 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
103 #define ALIGN_POINTER_CLEAR(_Ptr, _Align) \
104 do { \
105 memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \
106 ALIGN_POINTER(_Ptr, _Align); \
107 } while(0)
109 #define STD_OVERFLOW_CHECK(_Msg) do { \
110 TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
111 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
112 ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
113 } while (0)
115 #define NDR_TABLE_SIZE 128
116 #define NDR_TABLE_MASK 127
118 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
119 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
120 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
121 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
122 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
124 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
125 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
126 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
128 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
130 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
131 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
132 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
133 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
134 /* 0x10 */
135 NdrBaseTypeMarshall,
136 /* 0x11 */
137 NdrPointerMarshall, NdrPointerMarshall,
138 NdrPointerMarshall, NdrPointerMarshall,
139 /* 0x15 */
140 NdrSimpleStructMarshall, NdrSimpleStructMarshall,
141 NdrConformantStructMarshall, NdrConformantStructMarshall,
142 NdrConformantVaryingStructMarshall,
143 NdrComplexStructMarshall,
144 /* 0x1b */
145 NdrConformantArrayMarshall,
146 NdrConformantVaryingArrayMarshall,
147 NdrFixedArrayMarshall, NdrFixedArrayMarshall,
148 NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
149 NdrComplexArrayMarshall,
150 /* 0x22 */
151 NdrConformantStringMarshall, 0, 0,
152 NdrConformantStringMarshall,
153 NdrNonConformantStringMarshall, 0, 0, 0,
154 /* 0x2a */
155 NdrEncapsulatedUnionMarshall,
156 NdrNonEncapsulatedUnionMarshall,
157 NdrByteCountPointerMarshall,
158 NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
159 /* 0x2f */
160 NdrInterfacePointerMarshall,
161 /* 0x30 */
162 NdrContextHandleMarshall,
163 /* 0xb1 */
164 0, 0, 0,
165 NdrUserMarshalMarshall,
166 0, 0,
167 /* 0xb7 */
168 NdrRangeMarshall
170 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
172 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
173 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
174 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
175 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
176 /* 0x10 */
177 NdrBaseTypeUnmarshall,
178 /* 0x11 */
179 NdrPointerUnmarshall, NdrPointerUnmarshall,
180 NdrPointerUnmarshall, NdrPointerUnmarshall,
181 /* 0x15 */
182 NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
183 NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
184 NdrConformantVaryingStructUnmarshall,
185 NdrComplexStructUnmarshall,
186 /* 0x1b */
187 NdrConformantArrayUnmarshall,
188 NdrConformantVaryingArrayUnmarshall,
189 NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
190 NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
191 NdrComplexArrayUnmarshall,
192 /* 0x22 */
193 NdrConformantStringUnmarshall, 0, 0,
194 NdrConformantStringUnmarshall,
195 NdrNonConformantStringUnmarshall, 0, 0, 0,
196 /* 0x2a */
197 NdrEncapsulatedUnionUnmarshall,
198 NdrNonEncapsulatedUnionUnmarshall,
199 NdrByteCountPointerUnmarshall,
200 NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
201 /* 0x2f */
202 NdrInterfacePointerUnmarshall,
203 /* 0x30 */
204 NdrContextHandleUnmarshall,
205 /* 0xb1 */
206 0, 0, 0,
207 NdrUserMarshalUnmarshall,
208 0, 0,
209 /* 0xb7 */
210 NdrRangeUnmarshall
212 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
214 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
215 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
216 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
217 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
218 /* 0x10 */
219 NdrBaseTypeBufferSize,
220 /* 0x11 */
221 NdrPointerBufferSize, NdrPointerBufferSize,
222 NdrPointerBufferSize, NdrPointerBufferSize,
223 /* 0x15 */
224 NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
225 NdrConformantStructBufferSize, NdrConformantStructBufferSize,
226 NdrConformantVaryingStructBufferSize,
227 NdrComplexStructBufferSize,
228 /* 0x1b */
229 NdrConformantArrayBufferSize,
230 NdrConformantVaryingArrayBufferSize,
231 NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
232 NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
233 NdrComplexArrayBufferSize,
234 /* 0x22 */
235 NdrConformantStringBufferSize, 0, 0,
236 NdrConformantStringBufferSize,
237 NdrNonConformantStringBufferSize, 0, 0, 0,
238 /* 0x2a */
239 NdrEncapsulatedUnionBufferSize,
240 NdrNonEncapsulatedUnionBufferSize,
241 NdrByteCountPointerBufferSize,
242 NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
243 /* 0x2f */
244 NdrInterfacePointerBufferSize,
245 /* 0x30 */
246 NdrContextHandleBufferSize,
247 /* 0xb1 */
248 0, 0, 0,
249 NdrUserMarshalBufferSize,
250 0, 0,
251 /* 0xb7 */
252 NdrRangeBufferSize
254 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
256 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
257 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
258 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
259 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
260 /* 0x10 */
261 NdrBaseTypeMemorySize,
262 /* 0x11 */
263 NdrPointerMemorySize, NdrPointerMemorySize,
264 NdrPointerMemorySize, NdrPointerMemorySize,
265 /* 0x15 */
266 NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
267 NdrConformantStructMemorySize, NdrConformantStructMemorySize,
268 NdrConformantVaryingStructMemorySize,
269 NdrComplexStructMemorySize,
270 /* 0x1b */
271 NdrConformantArrayMemorySize,
272 NdrConformantVaryingArrayMemorySize,
273 NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
274 NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
275 NdrComplexArrayMemorySize,
276 /* 0x22 */
277 NdrConformantStringMemorySize, 0, 0,
278 NdrConformantStringMemorySize,
279 NdrNonConformantStringMemorySize, 0, 0, 0,
280 /* 0x2a */
281 NdrEncapsulatedUnionMemorySize,
282 NdrNonEncapsulatedUnionMemorySize,
283 NdrByteCountPointerMemorySize,
284 NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
285 /* 0x2f */
286 NdrInterfacePointerMemorySize,
287 /* 0x30 */
289 /* 0xb1 */
290 0, 0, 0,
291 NdrUserMarshalMemorySize,
292 0, 0,
293 /* 0xb7 */
294 NdrRangeMemorySize
296 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
298 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
299 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
300 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
301 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
302 /* 0x10 */
303 NdrBaseTypeFree,
304 /* 0x11 */
305 NdrPointerFree, NdrPointerFree,
306 NdrPointerFree, NdrPointerFree,
307 /* 0x15 */
308 NdrSimpleStructFree, NdrSimpleStructFree,
309 NdrConformantStructFree, NdrConformantStructFree,
310 NdrConformantVaryingStructFree,
311 NdrComplexStructFree,
312 /* 0x1b */
313 NdrConformantArrayFree,
314 NdrConformantVaryingArrayFree,
315 NdrFixedArrayFree, NdrFixedArrayFree,
316 NdrVaryingArrayFree, NdrVaryingArrayFree,
317 NdrComplexArrayFree,
318 /* 0x22 */
319 0, 0, 0,
320 0, 0, 0, 0, 0,
321 /* 0x2a */
322 NdrEncapsulatedUnionFree,
323 NdrNonEncapsulatedUnionFree,
325 NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
326 /* 0x2f */
327 NdrInterfacePointerFree,
328 /* 0x30 */
330 /* 0xb1 */
331 0, 0, 0,
332 NdrUserMarshalFree,
333 0, 0,
334 /* 0xb7 */
335 NdrRangeFree
338 typedef struct _NDR_MEMORY_LIST
340 ULONG magic;
341 ULONG size;
342 ULONG reserved;
343 struct _NDR_MEMORY_LIST *next;
344 } NDR_MEMORY_LIST;
346 #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
348 /***********************************************************************
349 * NdrAllocate [RPCRT4.@]
351 * Allocates a block of memory using pStubMsg->pfnAllocate.
353 * PARAMS
354 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
355 * len [I] Size of memory block to allocate.
357 * RETURNS
358 * The memory block of size len that was allocated.
360 * NOTES
361 * The memory block is always 8-byte aligned.
362 * If the function is unable to allocate memory an ERROR_OUTOFMEMORY
363 * exception is raised.
365 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
367 size_t aligned_len;
368 size_t adjusted_len;
369 void *p;
370 NDR_MEMORY_LIST *mem_list;
372 aligned_len = ALIGNED_LENGTH(len, 8);
373 adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
374 /* check for overflow */
375 if (adjusted_len < len)
377 ERR("overflow of adjusted_len %d, len %d\n", adjusted_len, len);
378 RpcRaiseException(RPC_X_BAD_STUB_DATA);
381 p = pStubMsg->pfnAllocate(adjusted_len);
382 if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
384 mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
385 mem_list->magic = MEML_MAGIC;
386 mem_list->size = aligned_len;
387 mem_list->reserved = 0;
388 mem_list->next = pStubMsg->pMemoryList;
389 pStubMsg->pMemoryList = mem_list;
391 TRACE("-- %p\n", p);
392 return p;
395 static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
397 TRACE("(%p, %p)\n", pStubMsg, Pointer);
399 pStubMsg->pfnFree(Pointer);
402 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
404 return (*(const ULONG *)pFormat != -1);
407 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
409 ALIGN_POINTER(pStubMsg->Buffer, 4);
410 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
411 RpcRaiseException(RPC_X_BAD_STUB_DATA);
412 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
413 pStubMsg->Buffer += 4;
414 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
415 if (pStubMsg->fHasNewCorrDesc)
416 return pFormat+6;
417 else
418 return pFormat+4;
421 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
423 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
425 pStubMsg->Offset = 0;
426 pStubMsg->ActualCount = pStubMsg->MaxCount;
427 goto done;
430 ALIGN_POINTER(pStubMsg->Buffer, 4);
431 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
432 RpcRaiseException(RPC_X_BAD_STUB_DATA);
433 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
434 pStubMsg->Buffer += 4;
435 TRACE("offset is %d\n", pStubMsg->Offset);
436 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
437 pStubMsg->Buffer += 4;
438 TRACE("variance is %d\n", pStubMsg->ActualCount);
440 if ((pStubMsg->ActualCount > MaxValue) ||
441 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
443 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
444 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
445 RpcRaiseException(RPC_S_INVALID_BOUND);
446 return NULL;
449 done:
450 if (pStubMsg->fHasNewCorrDesc)
451 return pFormat+6;
452 else
453 return pFormat+4;
456 /* writes the conformance value to the buffer */
457 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
459 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
460 if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
461 RpcRaiseException(RPC_X_BAD_STUB_DATA);
462 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
463 pStubMsg->Buffer += 4;
466 /* writes the variance values to the buffer */
467 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
469 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
470 if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
471 RpcRaiseException(RPC_X_BAD_STUB_DATA);
472 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
473 pStubMsg->Buffer += 4;
474 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
475 pStubMsg->Buffer += 4;
478 /* requests buffer space for the conformance value */
479 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
481 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
482 if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
483 RpcRaiseException(RPC_X_BAD_STUB_DATA);
484 pStubMsg->BufferLength += 4;
487 /* requests buffer space for the variance values */
488 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
490 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
491 if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
492 RpcRaiseException(RPC_X_BAD_STUB_DATA);
493 pStubMsg->BufferLength += 8;
496 PFORMAT_STRING ComputeConformanceOrVariance(
497 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
498 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
500 BYTE dtype = pFormat[0] & 0xf;
501 short ofs = *(const short *)&pFormat[2];
502 LPVOID ptr = NULL;
503 DWORD data = 0;
505 if (!IsConformanceOrVariancePresent(pFormat)) {
506 /* null descriptor */
507 *pCount = def;
508 goto finish_conf;
511 switch (pFormat[0] & 0xf0) {
512 case RPC_FC_NORMAL_CONFORMANCE:
513 TRACE("normal conformance, ofs=%d\n", ofs);
514 ptr = pMemory;
515 break;
516 case RPC_FC_POINTER_CONFORMANCE:
517 TRACE("pointer conformance, ofs=%d\n", ofs);
518 ptr = pStubMsg->Memory;
519 break;
520 case RPC_FC_TOP_LEVEL_CONFORMANCE:
521 TRACE("toplevel conformance, ofs=%d\n", ofs);
522 if (pStubMsg->StackTop) {
523 ptr = pStubMsg->StackTop;
525 else {
526 /* -Os mode, *pCount is already set */
527 goto finish_conf;
529 break;
530 case RPC_FC_CONSTANT_CONFORMANCE:
531 data = ofs | ((DWORD)pFormat[1] << 16);
532 TRACE("constant conformance, val=%d\n", data);
533 *pCount = data;
534 goto finish_conf;
535 case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
536 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
537 if (pStubMsg->StackTop) {
538 ptr = pStubMsg->StackTop;
540 else {
541 /* ? */
542 goto done_conf_grab;
544 break;
545 default:
546 FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
549 switch (pFormat[1]) {
550 case RPC_FC_DEREFERENCE:
551 ptr = *(LPVOID*)((char *)ptr + ofs);
552 break;
553 case RPC_FC_CALLBACK:
555 unsigned char *old_stack_top = pStubMsg->StackTop;
556 pStubMsg->StackTop = ptr;
558 /* ofs is index into StubDesc->apfnExprEval */
559 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
560 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
562 pStubMsg->StackTop = old_stack_top;
564 /* the callback function always stores the computed value in MaxCount */
565 *pCount = pStubMsg->MaxCount;
566 goto finish_conf;
568 default:
569 ptr = (char *)ptr + ofs;
570 break;
573 switch (dtype) {
574 case RPC_FC_LONG:
575 case RPC_FC_ULONG:
576 data = *(DWORD*)ptr;
577 break;
578 case RPC_FC_SHORT:
579 data = *(SHORT*)ptr;
580 break;
581 case RPC_FC_USHORT:
582 data = *(USHORT*)ptr;
583 break;
584 case RPC_FC_CHAR:
585 case RPC_FC_SMALL:
586 data = *(CHAR*)ptr;
587 break;
588 case RPC_FC_BYTE:
589 case RPC_FC_USMALL:
590 data = *(UCHAR*)ptr;
591 break;
592 default:
593 FIXME("unknown conformance data type %x\n", dtype);
594 goto done_conf_grab;
596 TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data);
598 done_conf_grab:
599 switch (pFormat[1]) {
600 case RPC_FC_DEREFERENCE: /* already handled */
601 case 0: /* no op */
602 *pCount = data;
603 break;
604 case RPC_FC_ADD_1:
605 *pCount = data + 1;
606 break;
607 case RPC_FC_SUB_1:
608 *pCount = data - 1;
609 break;
610 case RPC_FC_MULT_2:
611 *pCount = data * 2;
612 break;
613 case RPC_FC_DIV_2:
614 *pCount = data / 2;
615 break;
616 default:
617 FIXME("unknown conformance op %d\n", pFormat[1]);
618 goto finish_conf;
621 finish_conf:
622 TRACE("resulting conformance is %ld\n", *pCount);
623 if (pStubMsg->fHasNewCorrDesc)
624 return pFormat+6;
625 else
626 return pFormat+4;
629 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
630 * the result overflows 32-bits */
631 static inline ULONG safe_multiply(ULONG a, ULONG b)
633 ULONGLONG ret = (ULONGLONG)a * b;
634 if (ret > 0xffffffff)
636 RpcRaiseException(RPC_S_INVALID_BOUND);
637 return 0;
639 return ret;
642 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
644 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
645 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
646 RpcRaiseException(RPC_X_BAD_STUB_DATA);
647 pStubMsg->Buffer += size;
650 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
652 if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
654 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
655 pStubMsg->BufferLength, size);
656 RpcRaiseException(RPC_X_BAD_STUB_DATA);
658 pStubMsg->BufferLength += size;
661 /* copies data from the buffer, checking that there is enough data in the buffer
662 * to do so */
663 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
665 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
666 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
667 RpcRaiseException(RPC_X_BAD_STUB_DATA);
668 memcpy(p, pStubMsg->Buffer, size);
669 pStubMsg->Buffer += size;
672 /* copies data to the buffer, checking that there is enough space to do so */
673 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
675 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
676 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
678 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
679 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
680 size);
681 RpcRaiseException(RPC_X_BAD_STUB_DATA);
683 memcpy(pStubMsg->Buffer, p, size);
684 pStubMsg->Buffer += size;
688 * NdrConformantString:
690 * What MS calls a ConformantString is, in DCE terminology,
691 * a Varying-Conformant String.
693 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
694 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
695 * into unmarshalled string)
696 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
697 * [
698 * data: CHARTYPE[maxlen]
699 * ]
700 * ], where CHARTYPE is the appropriate character type (specified externally)
704 /***********************************************************************
705 * NdrConformantStringMarshall [RPCRT4.@]
707 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
708 unsigned char *pszMessage, PFORMAT_STRING pFormat)
710 ULONG esize, size;
712 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
714 if (*pFormat == RPC_FC_C_CSTRING) {
715 TRACE("string=%s\n", debugstr_a((char*)pszMessage));
716 pStubMsg->ActualCount = strlen((char*)pszMessage)+1;
717 esize = 1;
719 else if (*pFormat == RPC_FC_C_WSTRING) {
720 TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
721 pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1;
722 esize = 2;
724 else {
725 ERR("Unhandled string type: %#x\n", *pFormat);
726 /* FIXME: raise an exception. */
727 return NULL;
730 if (pFormat[1] == RPC_FC_STRING_SIZED)
731 pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0);
732 else
733 pStubMsg->MaxCount = pStubMsg->ActualCount;
734 pStubMsg->Offset = 0;
735 WriteConformance(pStubMsg);
736 WriteVariance(pStubMsg);
738 size = safe_multiply(esize, pStubMsg->ActualCount);
739 safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */
741 /* success */
742 return NULL; /* is this always right? */
745 /***********************************************************************
746 * NdrConformantStringBufferSize [RPCRT4.@]
748 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
749 unsigned char* pMemory, PFORMAT_STRING pFormat)
751 ULONG esize;
753 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
755 SizeConformance(pStubMsg);
756 SizeVariance(pStubMsg);
758 if (*pFormat == RPC_FC_C_CSTRING) {
759 TRACE("string=%s\n", debugstr_a((char*)pMemory));
760 pStubMsg->ActualCount = strlen((char*)pMemory)+1;
761 esize = 1;
763 else if (*pFormat == RPC_FC_C_WSTRING) {
764 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
765 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1;
766 esize = 2;
768 else {
769 ERR("Unhandled string type: %#x\n", *pFormat);
770 /* FIXME: raise an exception */
771 return;
774 if (pFormat[1] == RPC_FC_STRING_SIZED)
775 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
776 else
777 pStubMsg->MaxCount = pStubMsg->ActualCount;
779 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
782 /************************************************************************
783 * NdrConformantStringMemorySize [RPCRT4.@]
785 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
786 PFORMAT_STRING pFormat )
788 ULONG rslt = 0;
790 FIXME("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
792 assert(pStubMsg && pFormat);
794 if (*pFormat == RPC_FC_C_CSTRING) {
795 rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
797 else if (*pFormat == RPC_FC_C_WSTRING) {
798 rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */
800 else {
801 ERR("Unhandled string type: %#x\n", *pFormat);
802 /* FIXME: raise an exception */
805 if (pFormat[1] != RPC_FC_PAD) {
806 FIXME("sized string format=%d\n", pFormat[1]);
809 TRACE(" --> %u\n", rslt);
810 return rslt;
813 /************************************************************************
814 * NdrConformantStringUnmarshall [RPCRT4.@]
816 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
817 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
819 ULONG bufsize, memsize, esize, i;
821 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
822 pStubMsg, *ppMemory, pFormat, fMustAlloc);
824 assert(pFormat && ppMemory && pStubMsg);
826 ReadConformance(pStubMsg, NULL);
827 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
829 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
831 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
832 pStubMsg->ActualCount, pStubMsg->MaxCount);
833 RpcRaiseException(RPC_S_INVALID_BOUND);
834 return NULL;
836 if (pStubMsg->Offset)
838 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
839 RpcRaiseException(RPC_S_INVALID_BOUND);
840 return NULL;
843 if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
844 else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
845 else {
846 ERR("Unhandled string type: %#x\n", *pFormat);
847 /* FIXME: raise an exception */
848 esize = 0;
851 memsize = safe_multiply(esize, pStubMsg->MaxCount);
852 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
854 /* strings must always have null terminating bytes */
855 if (bufsize < esize)
857 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
858 RpcRaiseException(RPC_S_INVALID_BOUND);
859 return NULL;
862 /* verify the buffer is safe to access */
863 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
864 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
866 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
867 pStubMsg->BufferEnd, pStubMsg->Buffer);
868 RpcRaiseException(RPC_X_BAD_STUB_DATA);
869 return NULL;
872 for (i = bufsize - esize; i < bufsize; i++)
873 if (pStubMsg->Buffer[i] != 0)
875 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
876 i, pStubMsg->Buffer[i]);
877 RpcRaiseException(RPC_S_INVALID_BOUND);
878 return NULL;
881 if (fMustAlloc)
882 *ppMemory = NdrAllocate(pStubMsg, memsize);
883 else
885 if (!pStubMsg->IsClient && !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
886 /* if the data in the RPC buffer is big enough, we just point straight
887 * into it */
888 *ppMemory = pStubMsg->Buffer;
889 else if (!*ppMemory)
890 *ppMemory = NdrAllocate(pStubMsg, memsize);
893 if (*ppMemory == pStubMsg->Buffer)
894 safe_buffer_increment(pStubMsg, bufsize);
895 else
896 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
898 if (*pFormat == RPC_FC_C_CSTRING) {
899 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
901 else if (*pFormat == RPC_FC_C_WSTRING) {
902 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
905 return NULL; /* FIXME: is this always right? */
908 /***********************************************************************
909 * NdrNonConformantStringMarshall [RPCRT4.@]
911 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
912 unsigned char *pMemory,
913 PFORMAT_STRING pFormat)
915 FIXME("stub\n");
916 return NULL;
919 /***********************************************************************
920 * NdrNonConformantStringUnmarshall [RPCRT4.@]
922 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
923 unsigned char **ppMemory,
924 PFORMAT_STRING pFormat,
925 unsigned char fMustAlloc)
927 FIXME("stub\n");
928 return NULL;
931 /***********************************************************************
932 * NdrNonConformantStringBufferSize [RPCRT4.@]
934 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
935 unsigned char *pMemory,
936 PFORMAT_STRING pFormat)
938 FIXME("stub\n");
941 /***********************************************************************
942 * NdrNonConformantStringMemorySize [RPCRT4.@]
944 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
945 PFORMAT_STRING pFormat)
947 FIXME("stub\n");
948 return 0;
951 static inline void dump_pointer_attr(unsigned char attr)
953 if (attr & RPC_FC_P_ALLOCALLNODES)
954 TRACE(" RPC_FC_P_ALLOCALLNODES");
955 if (attr & RPC_FC_P_DONTFREE)
956 TRACE(" RPC_FC_P_DONTFREE");
957 if (attr & RPC_FC_P_ONSTACK)
958 TRACE(" RPC_FC_P_ONSTACK");
959 if (attr & RPC_FC_P_SIMPLEPOINTER)
960 TRACE(" RPC_FC_P_SIMPLEPOINTER");
961 if (attr & RPC_FC_P_DEREF)
962 TRACE(" RPC_FC_P_DEREF");
963 TRACE("\n");
966 /***********************************************************************
967 * PointerMarshall [internal]
969 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
970 unsigned char *Buffer,
971 unsigned char *Pointer,
972 PFORMAT_STRING pFormat)
974 unsigned type = pFormat[0], attr = pFormat[1];
975 PFORMAT_STRING desc;
976 NDR_MARSHALL m;
977 ULONG pointer_id;
978 int pointer_needs_marshaling;
980 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
981 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
982 pFormat += 2;
983 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
984 else desc = pFormat + *(const SHORT*)pFormat;
986 switch (type) {
987 case RPC_FC_RP: /* ref pointer (always non-null) */
988 if (!Pointer)
990 ERR("NULL ref pointer is not allowed\n");
991 RpcRaiseException(RPC_X_NULL_REF_POINTER);
993 pointer_needs_marshaling = 1;
994 break;
995 case RPC_FC_UP: /* unique pointer */
996 case RPC_FC_OP: /* object pointer - same as unique here */
997 if (Pointer)
998 pointer_needs_marshaling = 1;
999 else
1000 pointer_needs_marshaling = 0;
1001 pointer_id = (ULONG)Pointer;
1002 TRACE("writing 0x%08x to buffer\n", pointer_id);
1003 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
1004 break;
1005 case RPC_FC_FP:
1006 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
1007 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
1008 TRACE("writing 0x%08x to buffer\n", pointer_id);
1009 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
1010 break;
1011 default:
1012 FIXME("unhandled ptr type=%02x\n", type);
1013 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1014 return;
1017 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
1019 if (pointer_needs_marshaling) {
1020 if (attr & RPC_FC_P_DEREF) {
1021 Pointer = *(unsigned char**)Pointer;
1022 TRACE("deref => %p\n", Pointer);
1024 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1025 if (m) m(pStubMsg, Pointer, desc);
1026 else FIXME("no marshaller for data type=%02x\n", *desc);
1029 STD_OVERFLOW_CHECK(pStubMsg);
1032 /***********************************************************************
1033 * PointerUnmarshall [internal]
1035 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1036 unsigned char *Buffer,
1037 unsigned char **pPointer,
1038 unsigned char *pSrcPointer,
1039 PFORMAT_STRING pFormat,
1040 unsigned char fMustAlloc)
1042 unsigned type = pFormat[0], attr = pFormat[1];
1043 PFORMAT_STRING desc;
1044 NDR_UNMARSHALL m;
1045 DWORD pointer_id = 0;
1046 int pointer_needs_unmarshaling;
1048 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
1049 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1050 pFormat += 2;
1051 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1052 else desc = pFormat + *(const SHORT*)pFormat;
1054 switch (type) {
1055 case RPC_FC_RP: /* ref pointer (always non-null) */
1056 pointer_needs_unmarshaling = 1;
1057 break;
1058 case RPC_FC_UP: /* unique pointer */
1059 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1060 TRACE("pointer_id is 0x%08x\n", pointer_id);
1061 if (pointer_id)
1062 pointer_needs_unmarshaling = 1;
1063 else {
1064 *pPointer = NULL;
1065 pointer_needs_unmarshaling = 0;
1067 break;
1068 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1069 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1070 TRACE("pointer_id is 0x%08x\n", pointer_id);
1071 if (!fMustAlloc && pSrcPointer)
1073 FIXME("free object pointer %p\n", pSrcPointer);
1074 fMustAlloc = TRUE;
1076 if (pointer_id)
1077 pointer_needs_unmarshaling = 1;
1078 else
1079 pointer_needs_unmarshaling = 0;
1080 break;
1081 case RPC_FC_FP:
1082 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1083 TRACE("pointer_id is 0x%08x\n", pointer_id);
1084 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
1085 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
1086 break;
1087 default:
1088 FIXME("unhandled ptr type=%02x\n", type);
1089 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1090 return;
1093 if (pointer_needs_unmarshaling) {
1094 unsigned char *base_ptr_val = *pPointer;
1095 unsigned char **current_ptr = pPointer;
1096 if (pStubMsg->IsClient) {
1097 TRACE("client\n");
1098 /* if we aren't forcing allocation of memory then try to use the existing
1099 * (source) pointer to unmarshall the data into so that [in,out]
1100 * parameters behave correctly. it doesn't matter if the parameter is
1101 * [out] only since in that case the pointer will be NULL. we force
1102 * allocation when the source pointer is NULL here instead of in the type
1103 * unmarshalling routine for the benefit of the deref code below */
1104 if (!fMustAlloc) {
1105 if (pSrcPointer) {
1106 TRACE("setting *pPointer to %p\n", pSrcPointer);
1107 *pPointer = base_ptr_val = pSrcPointer;
1108 } else
1109 fMustAlloc = TRUE;
1111 } else {
1112 TRACE("server\n");
1113 /* the memory in a stub is never initialised, so we have to work out here
1114 * whether we have to initialise it so we can use the optimisation of
1115 * setting the pointer to the buffer, if possible, or set fMustAlloc to
1116 * TRUE. */
1117 if (attr & RPC_FC_P_DEREF) {
1118 fMustAlloc = TRUE;
1119 } else {
1120 base_ptr_val = NULL;
1121 *current_ptr = NULL;
1125 if (attr & RPC_FC_P_ALLOCALLNODES)
1126 FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
1128 if (attr & RPC_FC_P_DEREF) {
1129 if (fMustAlloc) {
1130 base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
1131 *pPointer = base_ptr_val;
1132 current_ptr = (unsigned char **)base_ptr_val;
1133 } else
1134 current_ptr = *(unsigned char***)current_ptr;
1135 TRACE("deref => %p\n", current_ptr);
1136 if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
1138 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1139 if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
1140 else FIXME("no unmarshaller for data type=%02x\n", *desc);
1142 if (type == RPC_FC_FP)
1143 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
1144 base_ptr_val);
1147 TRACE("pointer=%p\n", *pPointer);
1150 /***********************************************************************
1151 * PointerBufferSize [internal]
1153 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1154 unsigned char *Pointer,
1155 PFORMAT_STRING pFormat)
1157 unsigned type = pFormat[0], attr = pFormat[1];
1158 PFORMAT_STRING desc;
1159 NDR_BUFFERSIZE m;
1160 int pointer_needs_sizing;
1161 ULONG pointer_id;
1163 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1164 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1165 pFormat += 2;
1166 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1167 else desc = pFormat + *(const SHORT*)pFormat;
1169 switch (type) {
1170 case RPC_FC_RP: /* ref pointer (always non-null) */
1171 if (!Pointer)
1173 ERR("NULL ref pointer is not allowed\n");
1174 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1176 break;
1177 case RPC_FC_OP:
1178 case RPC_FC_UP:
1179 /* NULL pointer has no further representation */
1180 if (!Pointer)
1181 return;
1182 break;
1183 case RPC_FC_FP:
1184 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1185 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1186 if (!pointer_needs_sizing)
1187 return;
1188 break;
1189 default:
1190 FIXME("unhandled ptr type=%02x\n", type);
1191 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1192 return;
1195 if (attr & RPC_FC_P_DEREF) {
1196 Pointer = *(unsigned char**)Pointer;
1197 TRACE("deref => %p\n", Pointer);
1200 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1201 if (m) m(pStubMsg, Pointer, desc);
1202 else FIXME("no buffersizer for data type=%02x\n", *desc);
1205 /***********************************************************************
1206 * PointerMemorySize [internal]
1208 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1209 unsigned char *Buffer,
1210 PFORMAT_STRING pFormat)
1212 unsigned type = pFormat[0], attr = pFormat[1];
1213 PFORMAT_STRING desc;
1214 NDR_MEMORYSIZE m;
1215 DWORD pointer_id = 0;
1216 int pointer_needs_sizing;
1218 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1219 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1220 pFormat += 2;
1221 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1222 else desc = pFormat + *(const SHORT*)pFormat;
1224 switch (type) {
1225 case RPC_FC_RP: /* ref pointer (always non-null) */
1226 pointer_needs_sizing = 1;
1227 break;
1228 case RPC_FC_UP: /* unique pointer */
1229 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1230 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1231 TRACE("pointer_id is 0x%08x\n", pointer_id);
1232 if (pointer_id)
1233 pointer_needs_sizing = 1;
1234 else
1235 pointer_needs_sizing = 0;
1236 break;
1237 case RPC_FC_FP:
1239 void *pointer;
1240 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1241 TRACE("pointer_id is 0x%08x\n", pointer_id);
1242 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1243 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1244 break;
1246 default:
1247 FIXME("unhandled ptr type=%02x\n", type);
1248 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1249 return 0;
1252 if (attr & RPC_FC_P_DEREF) {
1253 TRACE("deref\n");
1256 if (pointer_needs_sizing) {
1257 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1258 if (m) m(pStubMsg, desc);
1259 else FIXME("no memorysizer for data type=%02x\n", *desc);
1262 return pStubMsg->MemorySize;
1265 /***********************************************************************
1266 * PointerFree [internal]
1268 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1269 unsigned char *Pointer,
1270 PFORMAT_STRING pFormat)
1272 unsigned type = pFormat[0], attr = pFormat[1];
1273 PFORMAT_STRING desc;
1274 NDR_FREE m;
1275 unsigned char *current_pointer = Pointer;
1277 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1278 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1279 if (attr & RPC_FC_P_DONTFREE) return;
1280 pFormat += 2;
1281 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1282 else desc = pFormat + *(const SHORT*)pFormat;
1284 if (!Pointer) return;
1286 if (type == RPC_FC_FP) {
1287 int pointer_needs_freeing = NdrFullPointerFree(
1288 pStubMsg->FullPtrXlatTables, Pointer);
1289 if (!pointer_needs_freeing)
1290 return;
1293 if (attr & RPC_FC_P_DEREF) {
1294 current_pointer = *(unsigned char**)Pointer;
1295 TRACE("deref => %p\n", current_pointer);
1298 m = NdrFreer[*desc & NDR_TABLE_MASK];
1299 if (m) m(pStubMsg, current_pointer, desc);
1301 /* this check stops us from trying to free buffer memory. we don't have to
1302 * worry about clients, since they won't call this function.
1303 * we don't have to check for the buffer being reallocated because
1304 * BufferStart and BufferEnd won't be reset when allocating memory for
1305 * sending the response. we don't have to check for the new buffer here as
1306 * it won't be used a type memory, only for buffer memory */
1307 if (Pointer >= (unsigned char *)pStubMsg->BufferStart &&
1308 Pointer < (unsigned char *)pStubMsg->BufferEnd)
1309 goto notfree;
1311 if (attr & RPC_FC_P_ONSTACK) {
1312 TRACE("not freeing stack ptr %p\n", Pointer);
1313 return;
1315 TRACE("freeing %p\n", Pointer);
1316 NdrFree(pStubMsg, Pointer);
1317 return;
1318 notfree:
1319 TRACE("not freeing %p\n", Pointer);
1322 /***********************************************************************
1323 * EmbeddedPointerMarshall
1325 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1326 unsigned char *pMemory,
1327 PFORMAT_STRING pFormat)
1329 unsigned char *Mark = pStubMsg->BufferMark;
1330 unsigned rep, count, stride;
1331 unsigned i;
1332 unsigned char *saved_buffer = NULL;
1334 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1336 if (*pFormat != RPC_FC_PP) return NULL;
1337 pFormat += 2;
1339 if (pStubMsg->PointerBufferMark)
1341 saved_buffer = pStubMsg->Buffer;
1342 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1343 pStubMsg->PointerBufferMark = NULL;
1346 while (pFormat[0] != RPC_FC_END) {
1347 switch (pFormat[0]) {
1348 default:
1349 FIXME("unknown repeat type %d\n", pFormat[0]);
1350 case RPC_FC_NO_REPEAT:
1351 rep = 1;
1352 stride = 0;
1353 count = 1;
1354 pFormat += 2;
1355 break;
1356 case RPC_FC_FIXED_REPEAT:
1357 rep = *(const WORD*)&pFormat[2];
1358 stride = *(const WORD*)&pFormat[4];
1359 count = *(const WORD*)&pFormat[8];
1360 pFormat += 10;
1361 break;
1362 case RPC_FC_VARIABLE_REPEAT:
1363 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1364 stride = *(const WORD*)&pFormat[2];
1365 count = *(const WORD*)&pFormat[6];
1366 pFormat += 8;
1367 break;
1369 for (i = 0; i < rep; i++) {
1370 PFORMAT_STRING info = pFormat;
1371 unsigned char *membase = pMemory + (i * stride);
1372 unsigned char *bufbase = Mark + (i * stride);
1373 unsigned u;
1375 for (u=0; u<count; u++,info+=8) {
1376 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1377 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1378 unsigned char *saved_memory = pStubMsg->Memory;
1380 pStubMsg->Memory = pMemory;
1381 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1382 pStubMsg->Memory = saved_memory;
1385 pFormat += 8 * count;
1388 if (saved_buffer)
1390 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1391 pStubMsg->Buffer = saved_buffer;
1394 STD_OVERFLOW_CHECK(pStubMsg);
1396 return NULL;
1399 /***********************************************************************
1400 * EmbeddedPointerUnmarshall
1402 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1403 unsigned char *pDstMemoryPtrs,
1404 unsigned char *pSrcMemoryPtrs,
1405 PFORMAT_STRING pFormat,
1406 unsigned char fMustAlloc)
1408 unsigned char *Mark = pStubMsg->BufferMark;
1409 unsigned rep, count, stride;
1410 unsigned i;
1411 unsigned char *saved_buffer = NULL;
1413 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstMemoryPtrs, pSrcMemoryPtrs, pFormat, fMustAlloc);
1415 if (*pFormat != RPC_FC_PP) return NULL;
1416 pFormat += 2;
1418 if (pStubMsg->PointerBufferMark)
1420 saved_buffer = pStubMsg->Buffer;
1421 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1422 pStubMsg->PointerBufferMark = NULL;
1425 while (pFormat[0] != RPC_FC_END) {
1426 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1427 switch (pFormat[0]) {
1428 default:
1429 FIXME("unknown repeat type %d\n", pFormat[0]);
1430 case RPC_FC_NO_REPEAT:
1431 rep = 1;
1432 stride = 0;
1433 count = 1;
1434 pFormat += 2;
1435 break;
1436 case RPC_FC_FIXED_REPEAT:
1437 rep = *(const WORD*)&pFormat[2];
1438 stride = *(const WORD*)&pFormat[4];
1439 count = *(const WORD*)&pFormat[8];
1440 pFormat += 10;
1441 break;
1442 case RPC_FC_VARIABLE_REPEAT:
1443 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1444 stride = *(const WORD*)&pFormat[2];
1445 count = *(const WORD*)&pFormat[6];
1446 pFormat += 8;
1447 break;
1449 for (i = 0; i < rep; i++) {
1450 PFORMAT_STRING info = pFormat;
1451 unsigned char *memdstbase = pDstMemoryPtrs + (i * stride);
1452 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1453 unsigned char *bufbase = Mark + (i * stride);
1454 unsigned u;
1456 for (u=0; u<count; u++,info+=8) {
1457 unsigned char **memdstptr = (unsigned char **)(memdstbase + *(const SHORT*)&info[0]);
1458 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1459 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1460 PointerUnmarshall(pStubMsg, bufptr, memdstptr, *memsrcptr, info+4, fMustAlloc);
1463 pFormat += 8 * count;
1466 if (saved_buffer)
1468 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1469 pStubMsg->Buffer = saved_buffer;
1472 return NULL;
1475 /***********************************************************************
1476 * EmbeddedPointerBufferSize
1478 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1479 unsigned char *pMemory,
1480 PFORMAT_STRING pFormat)
1482 unsigned rep, count, stride;
1483 unsigned i;
1484 ULONG saved_buffer_length = 0;
1486 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1488 if (pStubMsg->IgnoreEmbeddedPointers) return;
1490 if (*pFormat != RPC_FC_PP) return;
1491 pFormat += 2;
1493 if (pStubMsg->PointerLength)
1495 saved_buffer_length = pStubMsg->BufferLength;
1496 pStubMsg->BufferLength = pStubMsg->PointerLength;
1497 pStubMsg->PointerLength = 0;
1500 while (pFormat[0] != RPC_FC_END) {
1501 switch (pFormat[0]) {
1502 default:
1503 FIXME("unknown repeat type %d\n", pFormat[0]);
1504 case RPC_FC_NO_REPEAT:
1505 rep = 1;
1506 stride = 0;
1507 count = 1;
1508 pFormat += 2;
1509 break;
1510 case RPC_FC_FIXED_REPEAT:
1511 rep = *(const WORD*)&pFormat[2];
1512 stride = *(const WORD*)&pFormat[4];
1513 count = *(const WORD*)&pFormat[8];
1514 pFormat += 10;
1515 break;
1516 case RPC_FC_VARIABLE_REPEAT:
1517 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1518 stride = *(const WORD*)&pFormat[2];
1519 count = *(const WORD*)&pFormat[6];
1520 pFormat += 8;
1521 break;
1523 for (i = 0; i < rep; i++) {
1524 PFORMAT_STRING info = pFormat;
1525 unsigned char *membase = pMemory + (i * stride);
1526 unsigned u;
1528 for (u=0; u<count; u++,info+=8) {
1529 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1530 unsigned char *saved_memory = pStubMsg->Memory;
1532 pStubMsg->Memory = pMemory;
1533 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1534 pStubMsg->Memory = saved_memory;
1537 pFormat += 8 * count;
1540 if (saved_buffer_length)
1542 pStubMsg->PointerLength = pStubMsg->BufferLength;
1543 pStubMsg->BufferLength = saved_buffer_length;
1547 /***********************************************************************
1548 * EmbeddedPointerMemorySize [internal]
1550 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1551 PFORMAT_STRING pFormat)
1553 unsigned char *Mark = pStubMsg->BufferMark;
1554 unsigned rep, count, stride;
1555 unsigned i;
1556 unsigned char *saved_buffer = NULL;
1558 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1560 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1562 if (pStubMsg->PointerBufferMark)
1564 saved_buffer = pStubMsg->Buffer;
1565 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1566 pStubMsg->PointerBufferMark = NULL;
1569 if (*pFormat != RPC_FC_PP) return 0;
1570 pFormat += 2;
1572 while (pFormat[0] != RPC_FC_END) {
1573 switch (pFormat[0]) {
1574 default:
1575 FIXME("unknown repeat type %d\n", pFormat[0]);
1576 case RPC_FC_NO_REPEAT:
1577 rep = 1;
1578 stride = 0;
1579 count = 1;
1580 pFormat += 2;
1581 break;
1582 case RPC_FC_FIXED_REPEAT:
1583 rep = *(const WORD*)&pFormat[2];
1584 stride = *(const WORD*)&pFormat[4];
1585 count = *(const WORD*)&pFormat[8];
1586 pFormat += 10;
1587 break;
1588 case RPC_FC_VARIABLE_REPEAT:
1589 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1590 stride = *(const WORD*)&pFormat[2];
1591 count = *(const WORD*)&pFormat[6];
1592 pFormat += 8;
1593 break;
1595 for (i = 0; i < rep; i++) {
1596 PFORMAT_STRING info = pFormat;
1597 unsigned char *bufbase = Mark + (i * stride);
1598 unsigned u;
1599 for (u=0; u<count; u++,info+=8) {
1600 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1601 PointerMemorySize(pStubMsg, bufptr, info+4);
1604 pFormat += 8 * count;
1607 if (saved_buffer)
1609 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1610 pStubMsg->Buffer = saved_buffer;
1613 return 0;
1616 /***********************************************************************
1617 * EmbeddedPointerFree [internal]
1619 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1620 unsigned char *pMemory,
1621 PFORMAT_STRING pFormat)
1623 unsigned rep, count, stride;
1624 unsigned i;
1626 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1627 if (*pFormat != RPC_FC_PP) return;
1628 pFormat += 2;
1630 while (pFormat[0] != RPC_FC_END) {
1631 switch (pFormat[0]) {
1632 default:
1633 FIXME("unknown repeat type %d\n", pFormat[0]);
1634 case RPC_FC_NO_REPEAT:
1635 rep = 1;
1636 stride = 0;
1637 count = 1;
1638 pFormat += 2;
1639 break;
1640 case RPC_FC_FIXED_REPEAT:
1641 rep = *(const WORD*)&pFormat[2];
1642 stride = *(const WORD*)&pFormat[4];
1643 count = *(const WORD*)&pFormat[8];
1644 pFormat += 10;
1645 break;
1646 case RPC_FC_VARIABLE_REPEAT:
1647 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1648 stride = *(const WORD*)&pFormat[2];
1649 count = *(const WORD*)&pFormat[6];
1650 pFormat += 8;
1651 break;
1653 for (i = 0; i < rep; i++) {
1654 PFORMAT_STRING info = pFormat;
1655 unsigned char *membase = pMemory + (i * stride);
1656 unsigned u;
1658 for (u=0; u<count; u++,info+=8) {
1659 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1660 unsigned char *saved_memory = pStubMsg->Memory;
1662 pStubMsg->Memory = pMemory;
1663 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1664 pStubMsg->Memory = saved_memory;
1667 pFormat += 8 * count;
1671 /***********************************************************************
1672 * NdrPointerMarshall [RPCRT4.@]
1674 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1675 unsigned char *pMemory,
1676 PFORMAT_STRING pFormat)
1678 unsigned char *Buffer;
1680 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1682 /* incremement the buffer here instead of in PointerMarshall,
1683 * as that is used by embedded pointers which already handle the incrementing
1684 * the buffer, and shouldn't write any additional pointer data to the wire */
1685 if (*pFormat != RPC_FC_RP)
1687 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1688 Buffer = pStubMsg->Buffer;
1689 safe_buffer_increment(pStubMsg, 4);
1691 else
1692 Buffer = pStubMsg->Buffer;
1694 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1696 return NULL;
1699 /***********************************************************************
1700 * NdrPointerUnmarshall [RPCRT4.@]
1702 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1703 unsigned char **ppMemory,
1704 PFORMAT_STRING pFormat,
1705 unsigned char fMustAlloc)
1707 unsigned char *Buffer;
1709 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1711 /* incremement the buffer here instead of in PointerUnmarshall,
1712 * as that is used by embedded pointers which already handle the incrementing
1713 * the buffer, and shouldn't read any additional pointer data from the
1714 * buffer */
1715 if (*pFormat != RPC_FC_RP)
1717 ALIGN_POINTER(pStubMsg->Buffer, 4);
1718 Buffer = pStubMsg->Buffer;
1719 safe_buffer_increment(pStubMsg, 4);
1721 else
1722 Buffer = pStubMsg->Buffer;
1724 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1726 return NULL;
1729 /***********************************************************************
1730 * NdrPointerBufferSize [RPCRT4.@]
1732 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1733 unsigned char *pMemory,
1734 PFORMAT_STRING pFormat)
1736 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1738 /* incremement the buffer length here instead of in PointerBufferSize,
1739 * as that is used by embedded pointers which already handle the buffer
1740 * length, and shouldn't write anything more to the wire */
1741 if (*pFormat != RPC_FC_RP)
1743 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1744 safe_buffer_length_increment(pStubMsg, 4);
1747 PointerBufferSize(pStubMsg, pMemory, pFormat);
1750 /***********************************************************************
1751 * NdrPointerMemorySize [RPCRT4.@]
1753 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1754 PFORMAT_STRING pFormat)
1756 /* unsigned size = *(LPWORD)(pFormat+2); */
1757 FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1758 PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1759 return 0;
1762 /***********************************************************************
1763 * NdrPointerFree [RPCRT4.@]
1765 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1766 unsigned char *pMemory,
1767 PFORMAT_STRING pFormat)
1769 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1770 PointerFree(pStubMsg, pMemory, pFormat);
1773 /***********************************************************************
1774 * NdrSimpleTypeMarshall [RPCRT4.@]
1776 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1777 unsigned char FormatChar )
1779 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1782 /***********************************************************************
1783 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1785 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1786 unsigned char FormatChar )
1788 NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0);
1791 /***********************************************************************
1792 * NdrSimpleStructMarshall [RPCRT4.@]
1794 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1795 unsigned char *pMemory,
1796 PFORMAT_STRING pFormat)
1798 unsigned size = *(const WORD*)(pFormat+2);
1799 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1801 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
1803 pStubMsg->BufferMark = pStubMsg->Buffer;
1804 safe_copy_to_buffer(pStubMsg, pMemory, size);
1806 if (pFormat[0] != RPC_FC_STRUCT)
1807 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1809 return NULL;
1812 /***********************************************************************
1813 * NdrSimpleStructUnmarshall [RPCRT4.@]
1815 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1816 unsigned char **ppMemory,
1817 PFORMAT_STRING pFormat,
1818 unsigned char fMustAlloc)
1820 unsigned size = *(const WORD*)(pFormat+2);
1821 unsigned char *saved_buffer;
1822 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1824 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1826 if (fMustAlloc)
1827 *ppMemory = NdrAllocate(pStubMsg, size);
1828 else
1830 if (!pStubMsg->IsClient && !*ppMemory)
1831 /* for servers, we just point straight into the RPC buffer */
1832 *ppMemory = pStubMsg->Buffer;
1835 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1836 safe_buffer_increment(pStubMsg, size);
1837 if (pFormat[0] == RPC_FC_PSTRUCT)
1838 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1840 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1841 if (*ppMemory != saved_buffer)
1842 memcpy(*ppMemory, saved_buffer, size);
1844 return NULL;
1847 /***********************************************************************
1848 * NdrSimpleStructBufferSize [RPCRT4.@]
1850 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1851 unsigned char *pMemory,
1852 PFORMAT_STRING pFormat)
1854 unsigned size = *(const WORD*)(pFormat+2);
1855 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1857 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1859 safe_buffer_length_increment(pStubMsg, size);
1860 if (pFormat[0] != RPC_FC_STRUCT)
1861 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1864 /***********************************************************************
1865 * NdrSimpleStructMemorySize [RPCRT4.@]
1867 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1868 PFORMAT_STRING pFormat)
1870 unsigned short size = *(const WORD *)(pFormat+2);
1872 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1874 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1875 pStubMsg->MemorySize += size;
1876 safe_buffer_increment(pStubMsg, size);
1878 if (pFormat[0] != RPC_FC_STRUCT)
1879 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1880 return pStubMsg->MemorySize;
1883 /***********************************************************************
1884 * NdrSimpleStructFree [RPCRT4.@]
1886 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1887 unsigned char *pMemory,
1888 PFORMAT_STRING pFormat)
1890 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1891 if (pFormat[0] != RPC_FC_STRUCT)
1892 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1896 static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg,
1897 PFORMAT_STRING pFormat)
1899 switch (*pFormat) {
1900 case RPC_FC_STRUCT:
1901 case RPC_FC_PSTRUCT:
1902 case RPC_FC_CSTRUCT:
1903 case RPC_FC_BOGUS_STRUCT:
1904 case RPC_FC_SMFARRAY:
1905 case RPC_FC_SMVARRAY:
1906 return *(const WORD*)&pFormat[2];
1907 case RPC_FC_USER_MARSHAL:
1908 return *(const WORD*)&pFormat[4];
1909 case RPC_FC_NON_ENCAPSULATED_UNION:
1910 pFormat += 2;
1911 if (pStubMsg->fHasNewCorrDesc)
1912 pFormat += 6;
1913 else
1914 pFormat += 4;
1916 pFormat += *(const SHORT*)pFormat;
1917 return *(const SHORT*)pFormat;
1918 case RPC_FC_IP:
1919 return sizeof(void *);
1920 default:
1921 FIXME("unhandled embedded type %02x\n", *pFormat);
1923 return 0;
1927 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1928 PFORMAT_STRING pFormat)
1930 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1932 if (!m)
1934 FIXME("no memorysizer for data type=%02x\n", *pFormat);
1935 return 0;
1938 return m(pStubMsg, pFormat);
1942 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1943 unsigned char *pMemory,
1944 PFORMAT_STRING pFormat,
1945 PFORMAT_STRING pPointer)
1947 PFORMAT_STRING desc;
1948 NDR_MARSHALL m;
1949 unsigned long size;
1951 while (*pFormat != RPC_FC_END) {
1952 switch (*pFormat) {
1953 case RPC_FC_BYTE:
1954 case RPC_FC_CHAR:
1955 case RPC_FC_SMALL:
1956 case RPC_FC_USMALL:
1957 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
1958 safe_copy_to_buffer(pStubMsg, pMemory, 1);
1959 pMemory += 1;
1960 break;
1961 case RPC_FC_WCHAR:
1962 case RPC_FC_SHORT:
1963 case RPC_FC_USHORT:
1964 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1965 safe_copy_to_buffer(pStubMsg, pMemory, 2);
1966 pMemory += 2;
1967 break;
1968 case RPC_FC_LONG:
1969 case RPC_FC_ULONG:
1970 case RPC_FC_ENUM32:
1971 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
1972 safe_copy_to_buffer(pStubMsg, pMemory, 4);
1973 pMemory += 4;
1974 break;
1975 case RPC_FC_HYPER:
1976 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1977 safe_copy_to_buffer(pStubMsg, pMemory, 8);
1978 pMemory += 8;
1979 break;
1980 case RPC_FC_POINTER:
1982 unsigned char *saved_buffer;
1983 int pointer_buffer_mark_set = 0;
1984 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1985 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1986 saved_buffer = pStubMsg->Buffer;
1987 if (pStubMsg->PointerBufferMark)
1989 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1990 pStubMsg->PointerBufferMark = NULL;
1991 pointer_buffer_mark_set = 1;
1993 else
1994 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
1995 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
1996 if (pointer_buffer_mark_set)
1998 STD_OVERFLOW_CHECK(pStubMsg);
1999 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2000 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
2002 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
2003 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
2004 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2006 pStubMsg->Buffer = saved_buffer + 4;
2008 pPointer += 4;
2009 pMemory += 4;
2010 break;
2012 case RPC_FC_ALIGNM4:
2013 ALIGN_POINTER(pMemory, 4);
2014 break;
2015 case RPC_FC_ALIGNM8:
2016 ALIGN_POINTER(pMemory, 8);
2017 break;
2018 case RPC_FC_STRUCTPAD1:
2019 case RPC_FC_STRUCTPAD2:
2020 case RPC_FC_STRUCTPAD3:
2021 case RPC_FC_STRUCTPAD4:
2022 case RPC_FC_STRUCTPAD5:
2023 case RPC_FC_STRUCTPAD6:
2024 case RPC_FC_STRUCTPAD7:
2025 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2026 break;
2027 case RPC_FC_EMBEDDED_COMPLEX:
2028 pMemory += pFormat[1];
2029 pFormat += 2;
2030 desc = pFormat + *(const SHORT*)pFormat;
2031 size = EmbeddedComplexSize(pStubMsg, desc);
2032 TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
2033 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2034 if (m)
2036 /* for some reason interface pointers aren't generated as
2037 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2038 * they still need the derefencing treatment that pointers are
2039 * given */
2040 if (*desc == RPC_FC_IP)
2041 m(pStubMsg, *(unsigned char **)pMemory, desc);
2042 else
2043 m(pStubMsg, pMemory, desc);
2045 else FIXME("no marshaller for embedded type %02x\n", *desc);
2046 pMemory += size;
2047 pFormat += 2;
2048 continue;
2049 case RPC_FC_PAD:
2050 break;
2051 default:
2052 FIXME("unhandled format 0x%02x\n", *pFormat);
2054 pFormat++;
2057 return pMemory;
2060 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2061 unsigned char *pMemory,
2062 PFORMAT_STRING pFormat,
2063 PFORMAT_STRING pPointer)
2065 PFORMAT_STRING desc;
2066 NDR_UNMARSHALL m;
2067 unsigned long size;
2069 while (*pFormat != RPC_FC_END) {
2070 switch (*pFormat) {
2071 case RPC_FC_BYTE:
2072 case RPC_FC_CHAR:
2073 case RPC_FC_SMALL:
2074 case RPC_FC_USMALL:
2075 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2076 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2077 pMemory += 1;
2078 break;
2079 case RPC_FC_WCHAR:
2080 case RPC_FC_SHORT:
2081 case RPC_FC_USHORT:
2082 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2083 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2084 pMemory += 2;
2085 break;
2086 case RPC_FC_LONG:
2087 case RPC_FC_ULONG:
2088 case RPC_FC_ENUM32:
2089 safe_copy_from_buffer(pStubMsg, pMemory, 4);
2090 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2091 pMemory += 4;
2092 break;
2093 case RPC_FC_HYPER:
2094 safe_copy_from_buffer(pStubMsg, pMemory, 8);
2095 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2096 pMemory += 8;
2097 break;
2098 case RPC_FC_POINTER:
2100 unsigned char *saved_buffer;
2101 int pointer_buffer_mark_set = 0;
2102 TRACE("pointer => %p\n", pMemory);
2103 ALIGN_POINTER(pStubMsg->Buffer, 4);
2104 saved_buffer = pStubMsg->Buffer;
2105 if (pStubMsg->PointerBufferMark)
2107 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2108 pStubMsg->PointerBufferMark = NULL;
2109 pointer_buffer_mark_set = 1;
2111 else
2112 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2114 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, TRUE);
2115 if (pointer_buffer_mark_set)
2117 STD_OVERFLOW_CHECK(pStubMsg);
2118 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2119 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
2121 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
2122 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
2123 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2125 pStubMsg->Buffer = saved_buffer + 4;
2127 pPointer += 4;
2128 pMemory += 4;
2129 break;
2131 case RPC_FC_ALIGNM4:
2132 ALIGN_POINTER_CLEAR(pMemory, 4);
2133 break;
2134 case RPC_FC_ALIGNM8:
2135 ALIGN_POINTER_CLEAR(pMemory, 8);
2136 break;
2137 case RPC_FC_STRUCTPAD1:
2138 case RPC_FC_STRUCTPAD2:
2139 case RPC_FC_STRUCTPAD3:
2140 case RPC_FC_STRUCTPAD4:
2141 case RPC_FC_STRUCTPAD5:
2142 case RPC_FC_STRUCTPAD6:
2143 case RPC_FC_STRUCTPAD7:
2144 memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2145 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2146 break;
2147 case RPC_FC_EMBEDDED_COMPLEX:
2148 pMemory += pFormat[1];
2149 pFormat += 2;
2150 desc = pFormat + *(const SHORT*)pFormat;
2151 size = EmbeddedComplexSize(pStubMsg, desc);
2152 TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
2153 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2154 memset(pMemory, 0, size); /* just in case */
2155 if (m)
2157 /* for some reason interface pointers aren't generated as
2158 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2159 * they still need the derefencing treatment that pointers are
2160 * given */
2161 if (*desc == RPC_FC_IP)
2162 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2163 else
2164 m(pStubMsg, &pMemory, desc, FALSE);
2166 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2167 pMemory += size;
2168 pFormat += 2;
2169 continue;
2170 case RPC_FC_PAD:
2171 break;
2172 default:
2173 FIXME("unhandled format %d\n", *pFormat);
2175 pFormat++;
2178 return pMemory;
2181 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2182 unsigned char *pMemory,
2183 PFORMAT_STRING pFormat,
2184 PFORMAT_STRING pPointer)
2186 PFORMAT_STRING desc;
2187 NDR_BUFFERSIZE m;
2188 unsigned long size;
2190 while (*pFormat != RPC_FC_END) {
2191 switch (*pFormat) {
2192 case RPC_FC_BYTE:
2193 case RPC_FC_CHAR:
2194 case RPC_FC_SMALL:
2195 case RPC_FC_USMALL:
2196 safe_buffer_length_increment(pStubMsg, 1);
2197 pMemory += 1;
2198 break;
2199 case RPC_FC_WCHAR:
2200 case RPC_FC_SHORT:
2201 case RPC_FC_USHORT:
2202 safe_buffer_length_increment(pStubMsg, 2);
2203 pMemory += 2;
2204 break;
2205 case RPC_FC_LONG:
2206 case RPC_FC_ULONG:
2207 case RPC_FC_ENUM32:
2208 safe_buffer_length_increment(pStubMsg, 4);
2209 pMemory += 4;
2210 break;
2211 case RPC_FC_HYPER:
2212 safe_buffer_length_increment(pStubMsg, 8);
2213 pMemory += 8;
2214 break;
2215 case RPC_FC_POINTER:
2216 if (!pStubMsg->IgnoreEmbeddedPointers)
2218 int saved_buffer_length = pStubMsg->BufferLength;
2219 pStubMsg->BufferLength = pStubMsg->PointerLength;
2220 pStubMsg->PointerLength = 0;
2221 if(!pStubMsg->BufferLength)
2222 ERR("BufferLength == 0??\n");
2223 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2224 pStubMsg->PointerLength = pStubMsg->BufferLength;
2225 pStubMsg->BufferLength = saved_buffer_length;
2227 safe_buffer_length_increment(pStubMsg, 4);
2228 pPointer += 4;
2229 pMemory += 4;
2230 break;
2231 case RPC_FC_ALIGNM4:
2232 ALIGN_POINTER(pMemory, 4);
2233 break;
2234 case RPC_FC_ALIGNM8:
2235 ALIGN_POINTER(pMemory, 8);
2236 break;
2237 case RPC_FC_STRUCTPAD1:
2238 case RPC_FC_STRUCTPAD2:
2239 case RPC_FC_STRUCTPAD3:
2240 case RPC_FC_STRUCTPAD4:
2241 case RPC_FC_STRUCTPAD5:
2242 case RPC_FC_STRUCTPAD6:
2243 case RPC_FC_STRUCTPAD7:
2244 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2245 break;
2246 case RPC_FC_EMBEDDED_COMPLEX:
2247 pMemory += pFormat[1];
2248 pFormat += 2;
2249 desc = pFormat + *(const SHORT*)pFormat;
2250 size = EmbeddedComplexSize(pStubMsg, desc);
2251 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2252 if (m)
2254 /* for some reason interface pointers aren't generated as
2255 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2256 * they still need the derefencing treatment that pointers are
2257 * given */
2258 if (*desc == RPC_FC_IP)
2259 m(pStubMsg, *(unsigned char **)pMemory, desc);
2260 else
2261 m(pStubMsg, pMemory, desc);
2263 else FIXME("no buffersizer for embedded type %02x\n", *desc);
2264 pMemory += size;
2265 pFormat += 2;
2266 continue;
2267 case RPC_FC_PAD:
2268 break;
2269 default:
2270 FIXME("unhandled format 0x%02x\n", *pFormat);
2272 pFormat++;
2275 return pMemory;
2278 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2279 unsigned char *pMemory,
2280 PFORMAT_STRING pFormat,
2281 PFORMAT_STRING pPointer)
2283 PFORMAT_STRING desc;
2284 NDR_FREE m;
2285 unsigned long size;
2287 while (*pFormat != RPC_FC_END) {
2288 switch (*pFormat) {
2289 case RPC_FC_BYTE:
2290 case RPC_FC_CHAR:
2291 case RPC_FC_SMALL:
2292 case RPC_FC_USMALL:
2293 pMemory += 1;
2294 break;
2295 case RPC_FC_WCHAR:
2296 case RPC_FC_SHORT:
2297 case RPC_FC_USHORT:
2298 pMemory += 2;
2299 break;
2300 case RPC_FC_LONG:
2301 case RPC_FC_ULONG:
2302 case RPC_FC_ENUM32:
2303 pMemory += 4;
2304 break;
2305 case RPC_FC_HYPER:
2306 pMemory += 8;
2307 break;
2308 case RPC_FC_POINTER:
2309 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2310 pPointer += 4;
2311 pMemory += 4;
2312 break;
2313 case RPC_FC_ALIGNM4:
2314 ALIGN_POINTER(pMemory, 4);
2315 break;
2316 case RPC_FC_ALIGNM8:
2317 ALIGN_POINTER(pMemory, 8);
2318 break;
2319 case RPC_FC_STRUCTPAD1:
2320 case RPC_FC_STRUCTPAD2:
2321 case RPC_FC_STRUCTPAD3:
2322 case RPC_FC_STRUCTPAD4:
2323 case RPC_FC_STRUCTPAD5:
2324 case RPC_FC_STRUCTPAD6:
2325 case RPC_FC_STRUCTPAD7:
2326 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2327 break;
2328 case RPC_FC_EMBEDDED_COMPLEX:
2329 pMemory += pFormat[1];
2330 pFormat += 2;
2331 desc = pFormat + *(const SHORT*)pFormat;
2332 size = EmbeddedComplexSize(pStubMsg, desc);
2333 m = NdrFreer[*desc & NDR_TABLE_MASK];
2334 if (m)
2336 /* for some reason interface pointers aren't generated as
2337 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2338 * they still need the derefencing treatment that pointers are
2339 * given */
2340 if (*desc == RPC_FC_IP)
2341 m(pStubMsg, *(unsigned char **)pMemory, desc);
2342 else
2343 m(pStubMsg, pMemory, desc);
2345 else FIXME("no freer for embedded type %02x\n", *desc);
2346 pMemory += size;
2347 pFormat += 2;
2348 continue;
2349 case RPC_FC_PAD:
2350 break;
2351 default:
2352 FIXME("unhandled format 0x%02x\n", *pFormat);
2354 pFormat++;
2357 return pMemory;
2360 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2361 PFORMAT_STRING pFormat)
2363 PFORMAT_STRING desc;
2364 unsigned long size = 0;
2366 while (*pFormat != RPC_FC_END) {
2367 switch (*pFormat) {
2368 case RPC_FC_BYTE:
2369 case RPC_FC_CHAR:
2370 case RPC_FC_SMALL:
2371 case RPC_FC_USMALL:
2372 size += 1;
2373 safe_buffer_increment(pStubMsg, 1);
2374 break;
2375 case RPC_FC_WCHAR:
2376 case RPC_FC_SHORT:
2377 case RPC_FC_USHORT:
2378 size += 2;
2379 safe_buffer_increment(pStubMsg, 2);
2380 break;
2381 case RPC_FC_LONG:
2382 case RPC_FC_ULONG:
2383 case RPC_FC_ENUM32:
2384 size += 4;
2385 safe_buffer_increment(pStubMsg, 4);
2386 break;
2387 case RPC_FC_HYPER:
2388 size += 8;
2389 safe_buffer_increment(pStubMsg, 8);
2390 break;
2391 case RPC_FC_POINTER:
2392 size += 4;
2393 safe_buffer_increment(pStubMsg, 4);
2394 if (!pStubMsg->IgnoreEmbeddedPointers)
2395 FIXME("embedded pointers\n");
2396 break;
2397 case RPC_FC_ALIGNM4:
2398 ALIGN_LENGTH(size, 4);
2399 ALIGN_POINTER(pStubMsg->Buffer, 4);
2400 break;
2401 case RPC_FC_ALIGNM8:
2402 ALIGN_LENGTH(size, 8);
2403 ALIGN_POINTER(pStubMsg->Buffer, 8);
2404 break;
2405 case RPC_FC_STRUCTPAD1:
2406 case RPC_FC_STRUCTPAD2:
2407 case RPC_FC_STRUCTPAD3:
2408 case RPC_FC_STRUCTPAD4:
2409 case RPC_FC_STRUCTPAD5:
2410 case RPC_FC_STRUCTPAD6:
2411 case RPC_FC_STRUCTPAD7:
2412 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2413 break;
2414 case RPC_FC_EMBEDDED_COMPLEX:
2415 size += pFormat[1];
2416 pFormat += 2;
2417 desc = pFormat + *(const SHORT*)pFormat;
2418 size += EmbeddedComplexMemorySize(pStubMsg, desc);
2419 pFormat += 2;
2420 continue;
2421 case RPC_FC_PAD:
2422 break;
2423 default:
2424 FIXME("unhandled format 0x%02x\n", *pFormat);
2426 pFormat++;
2429 return size;
2432 /***********************************************************************
2433 * NdrComplexStructMarshall [RPCRT4.@]
2435 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2436 unsigned char *pMemory,
2437 PFORMAT_STRING pFormat)
2439 PFORMAT_STRING conf_array = NULL;
2440 PFORMAT_STRING pointer_desc = NULL;
2441 unsigned char *OldMemory = pStubMsg->Memory;
2442 int pointer_buffer_mark_set = 0;
2444 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2446 if (!pStubMsg->PointerBufferMark)
2448 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2449 /* save buffer length */
2450 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2452 /* get the buffer pointer after complex array data, but before
2453 * pointer data */
2454 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2455 pStubMsg->IgnoreEmbeddedPointers = 1;
2456 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2457 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2459 /* save it for use by embedded pointer code later */
2460 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2461 TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2462 pointer_buffer_mark_set = 1;
2464 /* restore the original buffer length */
2465 pStubMsg->BufferLength = saved_buffer_length;
2468 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
2470 pFormat += 4;
2471 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2472 pFormat += 2;
2473 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2474 pFormat += 2;
2476 pStubMsg->Memory = pMemory;
2478 ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2480 if (conf_array)
2481 NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2483 pStubMsg->Memory = OldMemory;
2485 if (pointer_buffer_mark_set)
2487 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2488 pStubMsg->PointerBufferMark = NULL;
2491 STD_OVERFLOW_CHECK(pStubMsg);
2493 return NULL;
2496 /***********************************************************************
2497 * NdrComplexStructUnmarshall [RPCRT4.@]
2499 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2500 unsigned char **ppMemory,
2501 PFORMAT_STRING pFormat,
2502 unsigned char fMustAlloc)
2504 unsigned size = *(const WORD*)(pFormat+2);
2505 PFORMAT_STRING conf_array = NULL;
2506 PFORMAT_STRING pointer_desc = NULL;
2507 unsigned char *pMemory;
2508 int pointer_buffer_mark_set = 0;
2510 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2512 if (!pStubMsg->PointerBufferMark)
2514 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2515 /* save buffer pointer */
2516 unsigned char *saved_buffer = pStubMsg->Buffer;
2518 /* get the buffer pointer after complex array data, but before
2519 * pointer data */
2520 pStubMsg->IgnoreEmbeddedPointers = 1;
2521 NdrComplexStructMemorySize(pStubMsg, pFormat);
2522 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2524 /* save it for use by embedded pointer code later */
2525 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2526 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2527 pointer_buffer_mark_set = 1;
2529 /* restore the original buffer */
2530 pStubMsg->Buffer = saved_buffer;
2533 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2535 if (fMustAlloc || !*ppMemory)
2537 *ppMemory = NdrAllocate(pStubMsg, size);
2538 memset(*ppMemory, 0, size);
2541 pFormat += 4;
2542 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2543 pFormat += 2;
2544 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2545 pFormat += 2;
2547 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2549 if (conf_array)
2550 NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2552 if (pointer_buffer_mark_set)
2554 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2555 pStubMsg->PointerBufferMark = NULL;
2558 return NULL;
2561 /***********************************************************************
2562 * NdrComplexStructBufferSize [RPCRT4.@]
2564 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2565 unsigned char *pMemory,
2566 PFORMAT_STRING pFormat)
2568 PFORMAT_STRING conf_array = NULL;
2569 PFORMAT_STRING pointer_desc = NULL;
2570 unsigned char *OldMemory = pStubMsg->Memory;
2571 int pointer_length_set = 0;
2573 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2575 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2577 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2579 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2580 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2582 /* get the buffer length after complex struct data, but before
2583 * pointer data */
2584 pStubMsg->IgnoreEmbeddedPointers = 1;
2585 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2586 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2588 /* save it for use by embedded pointer code later */
2589 pStubMsg->PointerLength = pStubMsg->BufferLength;
2590 pointer_length_set = 1;
2591 TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2593 /* restore the original buffer length */
2594 pStubMsg->BufferLength = saved_buffer_length;
2597 pFormat += 4;
2598 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2599 pFormat += 2;
2600 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2601 pFormat += 2;
2603 pStubMsg->Memory = pMemory;
2605 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2607 if (conf_array)
2608 NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2610 pStubMsg->Memory = OldMemory;
2612 if(pointer_length_set)
2614 pStubMsg->BufferLength = pStubMsg->PointerLength;
2615 pStubMsg->PointerLength = 0;
2620 /***********************************************************************
2621 * NdrComplexStructMemorySize [RPCRT4.@]
2623 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2624 PFORMAT_STRING pFormat)
2626 unsigned size = *(const WORD*)(pFormat+2);
2627 PFORMAT_STRING conf_array = NULL;
2628 PFORMAT_STRING pointer_desc = NULL;
2630 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2632 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2634 pFormat += 4;
2635 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2636 pFormat += 2;
2637 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2638 pFormat += 2;
2640 ComplexStructMemorySize(pStubMsg, pFormat);
2642 if (conf_array)
2643 NdrConformantArrayMemorySize(pStubMsg, conf_array);
2645 return size;
2648 /***********************************************************************
2649 * NdrComplexStructFree [RPCRT4.@]
2651 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2652 unsigned char *pMemory,
2653 PFORMAT_STRING pFormat)
2655 PFORMAT_STRING conf_array = NULL;
2656 PFORMAT_STRING pointer_desc = NULL;
2657 unsigned char *OldMemory = pStubMsg->Memory;
2659 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2661 pFormat += 4;
2662 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2663 pFormat += 2;
2664 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2665 pFormat += 2;
2667 pStubMsg->Memory = pMemory;
2669 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2671 if (conf_array)
2672 NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2674 pStubMsg->Memory = OldMemory;
2677 /***********************************************************************
2678 * NdrConformantArrayMarshall [RPCRT4.@]
2680 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2681 unsigned char *pMemory,
2682 PFORMAT_STRING pFormat)
2684 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2685 unsigned char alignment = pFormat[1] + 1;
2687 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2688 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2690 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2692 WriteConformance(pStubMsg);
2694 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
2696 size = safe_multiply(esize, pStubMsg->MaxCount);
2697 pStubMsg->BufferMark = pStubMsg->Buffer;
2698 safe_copy_to_buffer(pStubMsg, pMemory, size);
2700 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2702 return NULL;
2705 /***********************************************************************
2706 * NdrConformantArrayUnmarshall [RPCRT4.@]
2708 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2709 unsigned char **ppMemory,
2710 PFORMAT_STRING pFormat,
2711 unsigned char fMustAlloc)
2713 DWORD size, esize = *(const WORD*)(pFormat+2);
2714 unsigned char alignment = pFormat[1] + 1;
2715 unsigned char *saved_buffer;
2717 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2718 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2720 pFormat = ReadConformance(pStubMsg, pFormat+4);
2722 size = safe_multiply(esize, pStubMsg->MaxCount);
2723 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2725 if (fMustAlloc)
2726 *ppMemory = NdrAllocate(pStubMsg, size);
2727 else
2729 if (!pStubMsg->IsClient && !*ppMemory)
2730 /* for servers, we just point straight into the RPC buffer */
2731 *ppMemory = pStubMsg->Buffer;
2734 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
2735 safe_buffer_increment(pStubMsg, size);
2736 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2738 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2739 if (*ppMemory != saved_buffer)
2740 memcpy(*ppMemory, saved_buffer, size);
2742 return NULL;
2745 /***********************************************************************
2746 * NdrConformantArrayBufferSize [RPCRT4.@]
2748 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2749 unsigned char *pMemory,
2750 PFORMAT_STRING pFormat)
2752 DWORD size, esize = *(const WORD*)(pFormat+2);
2753 unsigned char alignment = pFormat[1] + 1;
2755 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2756 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2758 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2760 SizeConformance(pStubMsg);
2762 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2764 size = safe_multiply(esize, pStubMsg->MaxCount);
2765 /* conformance value plus array */
2766 safe_buffer_length_increment(pStubMsg, size);
2768 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2771 /***********************************************************************
2772 * NdrConformantArrayMemorySize [RPCRT4.@]
2774 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2775 PFORMAT_STRING pFormat)
2777 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2778 unsigned char alignment = pFormat[1] + 1;
2780 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2781 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2783 pFormat = ReadConformance(pStubMsg, pFormat+4);
2784 size = safe_multiply(esize, pStubMsg->MaxCount);
2785 pStubMsg->MemorySize += size;
2787 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2788 pStubMsg->BufferMark = pStubMsg->Buffer;
2789 safe_buffer_increment(pStubMsg, size);
2791 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2793 return pStubMsg->MemorySize;
2796 /***********************************************************************
2797 * NdrConformantArrayFree [RPCRT4.@]
2799 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2800 unsigned char *pMemory,
2801 PFORMAT_STRING pFormat)
2803 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2804 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2806 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2808 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2812 /***********************************************************************
2813 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
2815 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2816 unsigned char* pMemory,
2817 PFORMAT_STRING pFormat )
2819 ULONG bufsize;
2820 unsigned char alignment = pFormat[1] + 1;
2821 DWORD esize = *(const WORD*)(pFormat+2);
2823 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2825 if (pFormat[0] != RPC_FC_CVARRAY)
2827 ERR("invalid format type %x\n", pFormat[0]);
2828 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2829 return NULL;
2832 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2833 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2835 WriteConformance(pStubMsg);
2836 WriteVariance(pStubMsg);
2838 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
2840 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2842 pStubMsg->BufferMark = pStubMsg->Buffer;
2843 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
2845 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2847 return NULL;
2851 /***********************************************************************
2852 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
2854 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2855 unsigned char** ppMemory,
2856 PFORMAT_STRING pFormat,
2857 unsigned char fMustAlloc )
2859 ULONG bufsize, memsize;
2860 unsigned char alignment = pFormat[1] + 1;
2861 DWORD esize = *(const WORD*)(pFormat+2);
2863 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2865 if (pFormat[0] != RPC_FC_CVARRAY)
2867 ERR("invalid format type %x\n", pFormat[0]);
2868 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2869 return NULL;
2872 pFormat = ReadConformance(pStubMsg, pFormat+4);
2873 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2875 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2877 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2878 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2880 if (!*ppMemory || fMustAlloc)
2881 *ppMemory = NdrAllocate(pStubMsg, memsize);
2882 safe_copy_from_buffer(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
2884 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
2886 return NULL;
2890 /***********************************************************************
2891 * NdrConformantVaryingArrayFree [RPCRT4.@]
2893 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2894 unsigned char* pMemory,
2895 PFORMAT_STRING pFormat )
2897 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2899 if (pFormat[0] != RPC_FC_CVARRAY)
2901 ERR("invalid format type %x\n", pFormat[0]);
2902 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2903 return;
2906 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2907 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2909 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2913 /***********************************************************************
2914 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
2916 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2917 unsigned char* pMemory, PFORMAT_STRING pFormat )
2919 unsigned char alignment = pFormat[1] + 1;
2920 DWORD esize = *(const WORD*)(pFormat+2);
2922 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, 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;
2931 /* compute size */
2932 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2933 /* compute length */
2934 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2936 SizeConformance(pStubMsg);
2937 SizeVariance(pStubMsg);
2939 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2941 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2943 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2947 /***********************************************************************
2948 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
2950 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2951 PFORMAT_STRING pFormat )
2953 ULONG bufsize, memsize;
2954 unsigned char alignment = pFormat[1] + 1;
2955 DWORD esize = *(const WORD*)(pFormat+2);
2957 TRACE("(%p, %p)\n", pStubMsg, pFormat);
2959 if (pFormat[0] != RPC_FC_CVARRAY)
2961 ERR("invalid format type %x\n", pFormat[0]);
2962 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2963 return pStubMsg->MemorySize;
2966 pFormat = ReadConformance(pStubMsg, pFormat+4);
2967 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2969 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2971 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2972 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2974 safe_buffer_increment(pStubMsg, bufsize);
2975 pStubMsg->MemorySize += memsize;
2977 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2979 return pStubMsg->MemorySize;
2983 /***********************************************************************
2984 * NdrComplexArrayMarshall [RPCRT4.@]
2986 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2987 unsigned char *pMemory,
2988 PFORMAT_STRING pFormat)
2990 ULONG i, count, def;
2991 BOOL variance_present;
2992 unsigned char alignment;
2993 int pointer_buffer_mark_set = 0;
2995 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2997 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2999 ERR("invalid format type %x\n", pFormat[0]);
3000 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3001 return NULL;
3004 alignment = pFormat[1] + 1;
3006 if (!pStubMsg->PointerBufferMark)
3008 /* save buffer fields that may be changed by buffer sizer functions
3009 * and that may be needed later on */
3010 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3011 unsigned long saved_buffer_length = pStubMsg->BufferLength;
3012 unsigned long saved_max_count = pStubMsg->MaxCount;
3013 unsigned long saved_offset = pStubMsg->Offset;
3014 unsigned long saved_actual_count = pStubMsg->ActualCount;
3016 /* get the buffer pointer after complex array data, but before
3017 * pointer data */
3018 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
3019 pStubMsg->IgnoreEmbeddedPointers = 1;
3020 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3021 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3023 /* save it for use by embedded pointer code later */
3024 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
3025 TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
3026 pointer_buffer_mark_set = 1;
3028 /* restore fields */
3029 pStubMsg->ActualCount = saved_actual_count;
3030 pStubMsg->Offset = saved_offset;
3031 pStubMsg->MaxCount = saved_max_count;
3032 pStubMsg->BufferLength = saved_buffer_length;
3035 def = *(const WORD*)&pFormat[2];
3036 pFormat += 4;
3038 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3039 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3041 variance_present = IsConformanceOrVariancePresent(pFormat);
3042 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3043 TRACE("variance = %d\n", pStubMsg->ActualCount);
3045 WriteConformance(pStubMsg);
3046 if (variance_present)
3047 WriteVariance(pStubMsg);
3049 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3051 count = pStubMsg->ActualCount;
3052 for (i = 0; i < count; i++)
3053 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3055 STD_OVERFLOW_CHECK(pStubMsg);
3057 if (pointer_buffer_mark_set)
3059 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3060 pStubMsg->PointerBufferMark = NULL;
3063 return NULL;
3066 /***********************************************************************
3067 * NdrComplexArrayUnmarshall [RPCRT4.@]
3069 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3070 unsigned char **ppMemory,
3071 PFORMAT_STRING pFormat,
3072 unsigned char fMustAlloc)
3074 ULONG i, count, size;
3075 unsigned char alignment;
3076 unsigned char *pMemory;
3077 unsigned char *saved_buffer;
3078 int pointer_buffer_mark_set = 0;
3079 int saved_ignore_embedded;
3081 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3083 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3085 ERR("invalid format type %x\n", pFormat[0]);
3086 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3087 return NULL;
3090 alignment = pFormat[1] + 1;
3092 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3093 /* save buffer pointer */
3094 saved_buffer = pStubMsg->Buffer;
3095 /* get the buffer pointer after complex array data, but before
3096 * pointer data */
3097 pStubMsg->IgnoreEmbeddedPointers = 1;
3098 pStubMsg->MemorySize = 0;
3099 NdrComplexArrayMemorySize(pStubMsg, pFormat);
3100 size = pStubMsg->MemorySize;
3101 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3103 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
3104 if (!pStubMsg->PointerBufferMark)
3106 /* save it for use by embedded pointer code later */
3107 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3108 pointer_buffer_mark_set = 1;
3110 /* restore the original buffer */
3111 pStubMsg->Buffer = saved_buffer;
3113 pFormat += 4;
3115 pFormat = ReadConformance(pStubMsg, pFormat);
3116 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3118 if (fMustAlloc || !*ppMemory)
3120 *ppMemory = NdrAllocate(pStubMsg, size);
3121 memset(*ppMemory, 0, size);
3124 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3126 pMemory = *ppMemory;
3127 count = pStubMsg->ActualCount;
3128 for (i = 0; i < count; i++)
3129 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
3131 if (pointer_buffer_mark_set)
3133 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3134 pStubMsg->PointerBufferMark = NULL;
3137 return NULL;
3140 /***********************************************************************
3141 * NdrComplexArrayBufferSize [RPCRT4.@]
3143 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3144 unsigned char *pMemory,
3145 PFORMAT_STRING pFormat)
3147 ULONG i, count, def;
3148 unsigned char alignment;
3149 BOOL variance_present;
3150 int pointer_length_set = 0;
3152 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3154 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3156 ERR("invalid format type %x\n", pFormat[0]);
3157 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3158 return;
3161 alignment = pFormat[1] + 1;
3163 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3165 /* save buffer fields that may be changed by buffer sizer functions
3166 * and that may be needed later on */
3167 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3168 unsigned long saved_buffer_length = pStubMsg->BufferLength;
3169 unsigned long saved_max_count = pStubMsg->MaxCount;
3170 unsigned long saved_offset = pStubMsg->Offset;
3171 unsigned long saved_actual_count = pStubMsg->ActualCount;
3173 /* get the buffer pointer after complex array data, but before
3174 * pointer data */
3175 pStubMsg->IgnoreEmbeddedPointers = 1;
3176 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3177 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3179 /* save it for use by embedded pointer code later */
3180 pStubMsg->PointerLength = pStubMsg->BufferLength;
3181 pointer_length_set = 1;
3183 /* restore fields */
3184 pStubMsg->ActualCount = saved_actual_count;
3185 pStubMsg->Offset = saved_offset;
3186 pStubMsg->MaxCount = saved_max_count;
3187 pStubMsg->BufferLength = saved_buffer_length;
3189 def = *(const WORD*)&pFormat[2];
3190 pFormat += 4;
3192 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3193 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3194 SizeConformance(pStubMsg);
3196 variance_present = IsConformanceOrVariancePresent(pFormat);
3197 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3198 TRACE("variance = %d\n", pStubMsg->ActualCount);
3200 if (variance_present)
3201 SizeVariance(pStubMsg);
3203 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3205 count = pStubMsg->ActualCount;
3206 for (i = 0; i < count; i++)
3207 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
3209 if(pointer_length_set)
3211 pStubMsg->BufferLength = pStubMsg->PointerLength;
3212 pStubMsg->PointerLength = 0;
3216 /***********************************************************************
3217 * NdrComplexArrayMemorySize [RPCRT4.@]
3219 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3220 PFORMAT_STRING pFormat)
3222 ULONG i, count, esize, SavedMemorySize, MemorySize;
3223 unsigned char alignment;
3224 unsigned char *Buffer;
3226 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3228 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3230 ERR("invalid format type %x\n", pFormat[0]);
3231 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3232 return 0;
3235 alignment = pFormat[1] + 1;
3237 pFormat += 4;
3239 pFormat = ReadConformance(pStubMsg, pFormat);
3240 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3242 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3244 SavedMemorySize = pStubMsg->MemorySize;
3246 Buffer = pStubMsg->Buffer;
3247 pStubMsg->MemorySize = 0;
3248 esize = ComplexStructMemorySize(pStubMsg, pFormat);
3249 pStubMsg->Buffer = Buffer;
3251 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3253 count = pStubMsg->ActualCount;
3254 for (i = 0; i < count; i++)
3255 ComplexStructMemorySize(pStubMsg, pFormat);
3257 pStubMsg->MemorySize = SavedMemorySize;
3259 pStubMsg->MemorySize += MemorySize;
3260 return MemorySize;
3263 /***********************************************************************
3264 * NdrComplexArrayFree [RPCRT4.@]
3266 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3267 unsigned char *pMemory,
3268 PFORMAT_STRING pFormat)
3270 ULONG i, count, def;
3272 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3274 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3276 ERR("invalid format type %x\n", pFormat[0]);
3277 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3278 return;
3281 def = *(const WORD*)&pFormat[2];
3282 pFormat += 4;
3284 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3285 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3287 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3288 TRACE("variance = %d\n", pStubMsg->ActualCount);
3290 count = pStubMsg->ActualCount;
3291 for (i = 0; i < count; i++)
3292 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
3295 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
3296 USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
3297 USER_MARSHAL_CB *umcb)
3299 umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
3300 pStubMsg->RpcMsg->DataRepresentation);
3301 umcb->pStubMsg = pStubMsg;
3302 umcb->pReserve = NULL;
3303 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
3304 umcb->CBType = cbtype;
3305 umcb->pFormat = pFormat;
3306 umcb->pTypeFormat = NULL /* FIXME */;
3309 #define USER_MARSHAL_PTR_PREFIX \
3310 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
3311 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
3313 /***********************************************************************
3314 * NdrUserMarshalMarshall [RPCRT4.@]
3316 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3317 unsigned char *pMemory,
3318 PFORMAT_STRING pFormat)
3320 unsigned flags = pFormat[1];
3321 unsigned index = *(const WORD*)&pFormat[2];
3322 unsigned char *saved_buffer = NULL;
3323 USER_MARSHAL_CB umcb;
3325 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3326 TRACE("index=%d\n", index);
3328 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
3330 if (flags & USER_MARSHAL_POINTER)
3332 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
3333 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
3334 pStubMsg->Buffer += 4;
3335 if (pStubMsg->PointerBufferMark)
3337 saved_buffer = pStubMsg->Buffer;
3338 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3339 pStubMsg->PointerBufferMark = NULL;
3341 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8);
3343 else
3344 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1);
3346 pStubMsg->Buffer =
3347 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
3348 &umcb.Flags, pStubMsg->Buffer, pMemory);
3350 if (saved_buffer)
3352 STD_OVERFLOW_CHECK(pStubMsg);
3353 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3354 pStubMsg->Buffer = saved_buffer;
3357 STD_OVERFLOW_CHECK(pStubMsg);
3359 return NULL;
3362 /***********************************************************************
3363 * NdrUserMarshalUnmarshall [RPCRT4.@]
3365 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3366 unsigned char **ppMemory,
3367 PFORMAT_STRING pFormat,
3368 unsigned char fMustAlloc)
3370 unsigned flags = pFormat[1];
3371 unsigned index = *(const WORD*)&pFormat[2];
3372 DWORD memsize = *(const WORD*)&pFormat[4];
3373 unsigned char *saved_buffer = NULL;
3374 USER_MARSHAL_CB umcb;
3376 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3377 TRACE("index=%d\n", index);
3379 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
3381 if (flags & USER_MARSHAL_POINTER)
3383 ALIGN_POINTER(pStubMsg->Buffer, 4);
3384 /* skip pointer prefix */
3385 pStubMsg->Buffer += 4;
3386 if (pStubMsg->PointerBufferMark)
3388 saved_buffer = pStubMsg->Buffer;
3389 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3390 pStubMsg->PointerBufferMark = NULL;
3392 ALIGN_POINTER(pStubMsg->Buffer, 8);
3394 else
3395 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3397 if (fMustAlloc || !*ppMemory)
3398 *ppMemory = NdrAllocate(pStubMsg, memsize);
3400 pStubMsg->Buffer =
3401 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
3402 &umcb.Flags, pStubMsg->Buffer, *ppMemory);
3404 if (saved_buffer)
3406 STD_OVERFLOW_CHECK(pStubMsg);
3407 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3408 pStubMsg->Buffer = saved_buffer;
3411 return NULL;
3414 /***********************************************************************
3415 * NdrUserMarshalBufferSize [RPCRT4.@]
3417 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3418 unsigned char *pMemory,
3419 PFORMAT_STRING pFormat)
3421 unsigned flags = pFormat[1];
3422 unsigned index = *(const WORD*)&pFormat[2];
3423 DWORD bufsize = *(const WORD*)&pFormat[6];
3424 USER_MARSHAL_CB umcb;
3425 unsigned long saved_buffer_length = 0;
3427 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3428 TRACE("index=%d\n", index);
3430 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
3432 if (flags & USER_MARSHAL_POINTER)
3434 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3435 /* skip pointer prefix */
3436 safe_buffer_length_increment(pStubMsg, 4);
3437 if (pStubMsg->IgnoreEmbeddedPointers)
3438 return;
3439 if (pStubMsg->PointerLength)
3441 saved_buffer_length = pStubMsg->BufferLength;
3442 pStubMsg->BufferLength = pStubMsg->PointerLength;
3443 pStubMsg->PointerLength = 0;
3445 ALIGN_LENGTH(pStubMsg->BufferLength, 8);
3447 else
3448 ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
3450 if (bufsize) {
3451 TRACE("size=%d\n", bufsize);
3452 safe_buffer_length_increment(pStubMsg, bufsize);
3454 else
3455 pStubMsg->BufferLength =
3456 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
3457 &umcb.Flags, pStubMsg->BufferLength, pMemory);
3459 if (saved_buffer_length)
3461 pStubMsg->PointerLength = pStubMsg->BufferLength;
3462 pStubMsg->BufferLength = saved_buffer_length;
3467 /***********************************************************************
3468 * NdrUserMarshalMemorySize [RPCRT4.@]
3470 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3471 PFORMAT_STRING pFormat)
3473 unsigned flags = pFormat[1];
3474 unsigned index = *(const WORD*)&pFormat[2];
3475 DWORD memsize = *(const WORD*)&pFormat[4];
3476 DWORD bufsize = *(const WORD*)&pFormat[6];
3478 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3479 TRACE("index=%d\n", index);
3481 pStubMsg->MemorySize += memsize;
3483 if (flags & USER_MARSHAL_POINTER)
3485 ALIGN_POINTER(pStubMsg->Buffer, 4);
3486 /* skip pointer prefix */
3487 pStubMsg->Buffer += 4;
3488 if (pStubMsg->IgnoreEmbeddedPointers)
3489 return pStubMsg->MemorySize;
3490 ALIGN_POINTER(pStubMsg->Buffer, 8);
3492 else
3493 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3495 if (!bufsize)
3496 FIXME("not implemented for varying buffer size\n");
3498 pStubMsg->Buffer += bufsize;
3500 return pStubMsg->MemorySize;
3503 /***********************************************************************
3504 * NdrUserMarshalFree [RPCRT4.@]
3506 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
3507 unsigned char *pMemory,
3508 PFORMAT_STRING pFormat)
3510 /* unsigned flags = pFormat[1]; */
3511 unsigned index = *(const WORD*)&pFormat[2];
3512 USER_MARSHAL_CB umcb;
3514 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3515 TRACE("index=%d\n", index);
3517 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
3519 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
3520 &umcb.Flags, pMemory);
3523 /***********************************************************************
3524 * NdrClearOutParameters [RPCRT4.@]
3526 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
3527 PFORMAT_STRING pFormat,
3528 void *ArgAddr)
3530 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
3533 /***********************************************************************
3534 * NdrConvert [RPCRT4.@]
3536 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
3538 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
3539 /* FIXME: since this stub doesn't do any converting, the proper behavior
3540 is to raise an exception */
3543 /***********************************************************************
3544 * NdrConvert2 [RPCRT4.@]
3546 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
3548 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
3549 pStubMsg, pFormat, NumberParams);
3550 /* FIXME: since this stub doesn't do any converting, the proper behavior
3551 is to raise an exception */
3554 #include "pshpack1.h"
3555 typedef struct _NDR_CSTRUCT_FORMAT
3557 unsigned char type;
3558 unsigned char alignment;
3559 unsigned short memory_size;
3560 short offset_to_array_description;
3561 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
3562 #include "poppack.h"
3564 /***********************************************************************
3565 * NdrConformantStructMarshall [RPCRT4.@]
3567 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3568 unsigned char *pMemory,
3569 PFORMAT_STRING pFormat)
3571 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3572 PFORMAT_STRING pCArrayFormat;
3573 ULONG esize, bufsize;
3575 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3577 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3578 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3580 ERR("invalid format type %x\n", pCStructFormat->type);
3581 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3582 return NULL;
3585 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3586 pCStructFormat->offset_to_array_description;
3587 if (*pCArrayFormat != RPC_FC_CARRAY)
3589 ERR("invalid array format type %x\n", pCStructFormat->type);
3590 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3591 return NULL;
3593 esize = *(const WORD*)(pCArrayFormat+2);
3595 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3596 pCArrayFormat + 4, 0);
3598 WriteConformance(pStubMsg);
3600 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3602 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3604 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3605 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3607 ERR("integer overflow of memory_size %u with bufsize %u\n",
3608 pCStructFormat->memory_size, bufsize);
3609 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3611 /* copy constant sized part of struct */
3612 pStubMsg->BufferMark = pStubMsg->Buffer;
3613 safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
3615 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3616 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3618 return NULL;
3621 /***********************************************************************
3622 * NdrConformantStructUnmarshall [RPCRT4.@]
3624 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3625 unsigned char **ppMemory,
3626 PFORMAT_STRING pFormat,
3627 unsigned char fMustAlloc)
3629 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3630 PFORMAT_STRING pCArrayFormat;
3631 ULONG esize, bufsize;
3632 unsigned char *saved_buffer;
3634 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3636 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3637 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3639 ERR("invalid format type %x\n", pCStructFormat->type);
3640 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3641 return NULL;
3643 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3644 pCStructFormat->offset_to_array_description;
3645 if (*pCArrayFormat != RPC_FC_CARRAY)
3647 ERR("invalid array format type %x\n", pCStructFormat->type);
3648 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3649 return NULL;
3651 esize = *(const WORD*)(pCArrayFormat+2);
3653 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
3655 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3657 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3659 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3660 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3662 ERR("integer overflow of memory_size %u with bufsize %u\n",
3663 pCStructFormat->memory_size, bufsize);
3664 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3667 if (fMustAlloc)
3669 SIZE_T size = pCStructFormat->memory_size + bufsize;
3670 *ppMemory = NdrAllocate(pStubMsg, size);
3672 else
3674 if (!pStubMsg->IsClient && !*ppMemory)
3675 /* for servers, we just point straight into the RPC buffer */
3676 *ppMemory = pStubMsg->Buffer;
3679 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3680 safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
3681 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3682 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3684 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
3685 if (*ppMemory != saved_buffer)
3686 memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
3688 return NULL;
3691 /***********************************************************************
3692 * NdrConformantStructBufferSize [RPCRT4.@]
3694 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3695 unsigned char *pMemory,
3696 PFORMAT_STRING pFormat)
3698 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3699 PFORMAT_STRING pCArrayFormat;
3700 ULONG esize;
3702 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3704 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3705 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3707 ERR("invalid format type %x\n", pCStructFormat->type);
3708 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3709 return;
3711 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3712 pCStructFormat->offset_to_array_description;
3713 if (*pCArrayFormat != RPC_FC_CARRAY)
3715 ERR("invalid array format type %x\n", pCStructFormat->type);
3716 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3717 return;
3719 esize = *(const WORD*)(pCArrayFormat+2);
3721 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
3722 SizeConformance(pStubMsg);
3724 ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
3726 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3728 safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
3729 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
3731 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3732 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3735 /***********************************************************************
3736 * NdrConformantStructMemorySize [RPCRT4.@]
3738 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3739 PFORMAT_STRING pFormat)
3741 FIXME("stub\n");
3742 return 0;
3745 /***********************************************************************
3746 * NdrConformantStructFree [RPCRT4.@]
3748 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3749 unsigned char *pMemory,
3750 PFORMAT_STRING pFormat)
3752 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3753 PFORMAT_STRING pCArrayFormat;
3754 ULONG esize;
3756 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3758 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3759 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3761 ERR("invalid format type %x\n", pCStructFormat->type);
3762 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3763 return;
3766 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3767 pCStructFormat->offset_to_array_description;
3768 if (*pCArrayFormat != RPC_FC_CARRAY)
3770 ERR("invalid array format type %x\n", pCStructFormat->type);
3771 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3772 return;
3774 esize = *(const WORD*)(pCArrayFormat+2);
3776 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3777 pCArrayFormat + 4, 0);
3779 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3781 /* copy constant sized part of struct */
3782 pStubMsg->BufferMark = pStubMsg->Buffer;
3784 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3785 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3788 /***********************************************************************
3789 * NdrConformantVaryingStructMarshall [RPCRT4.@]
3791 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3792 unsigned char *pMemory,
3793 PFORMAT_STRING pFormat)
3795 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3796 PFORMAT_STRING pCVArrayFormat;
3797 ULONG esize, bufsize;
3799 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3801 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3802 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3804 ERR("invalid format type %x\n", pCVStructFormat->type);
3805 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3806 return NULL;
3809 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3810 pCVStructFormat->offset_to_array_description;
3811 switch (*pCVArrayFormat)
3813 case RPC_FC_CVARRAY:
3814 esize = *(const WORD*)(pCVArrayFormat+2);
3816 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3817 pCVArrayFormat + 4, 0);
3818 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3819 pCVArrayFormat, 0);
3820 break;
3821 case RPC_FC_C_CSTRING:
3822 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3823 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3824 esize = sizeof(char);
3825 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3826 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3827 pCVArrayFormat + 2, 0);
3828 else
3829 pStubMsg->MaxCount = pStubMsg->ActualCount;
3830 break;
3831 case RPC_FC_C_WSTRING:
3832 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3833 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3834 esize = sizeof(WCHAR);
3835 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3836 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3837 pCVArrayFormat + 2, 0);
3838 else
3839 pStubMsg->MaxCount = pStubMsg->ActualCount;
3840 break;
3841 default:
3842 ERR("invalid array format type %x\n", *pCVArrayFormat);
3843 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3844 return NULL;
3847 WriteConformance(pStubMsg);
3849 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3851 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3853 /* write constant sized part */
3854 pStubMsg->BufferMark = pStubMsg->Buffer;
3855 safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
3857 WriteVariance(pStubMsg);
3859 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3861 /* write array part */
3862 safe_copy_to_buffer(pStubMsg, pMemory + pCVStructFormat->memory_size, bufsize);
3864 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3866 return NULL;
3869 /***********************************************************************
3870 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
3872 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3873 unsigned char **ppMemory,
3874 PFORMAT_STRING pFormat,
3875 unsigned char fMustAlloc)
3877 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3878 PFORMAT_STRING pCVArrayFormat;
3879 ULONG esize, bufsize;
3880 unsigned char cvarray_type;
3882 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3884 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3885 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3887 ERR("invalid format type %x\n", pCVStructFormat->type);
3888 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3889 return NULL;
3892 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3893 pCVStructFormat->offset_to_array_description;
3894 cvarray_type = *pCVArrayFormat;
3895 switch (cvarray_type)
3897 case RPC_FC_CVARRAY:
3898 esize = *(const WORD*)(pCVArrayFormat+2);
3899 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3900 break;
3901 case RPC_FC_C_CSTRING:
3902 esize = sizeof(char);
3903 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3904 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3905 else
3906 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3907 break;
3908 case RPC_FC_C_WSTRING:
3909 esize = sizeof(WCHAR);
3910 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3911 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3912 else
3913 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3914 break;
3915 default:
3916 ERR("invalid array format type %x\n", *pCVArrayFormat);
3917 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3918 return NULL;
3921 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3923 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3925 /* work out how much memory to allocate if we need to do so */
3926 if (!*ppMemory || fMustAlloc)
3928 SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3929 *ppMemory = NdrAllocate(pStubMsg, size);
3932 /* copy the constant data */
3933 pStubMsg->BufferMark = pStubMsg->Buffer;
3934 safe_copy_from_buffer(pStubMsg, *ppMemory, pCVStructFormat->memory_size);
3936 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3938 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3940 if ((cvarray_type == RPC_FC_C_CSTRING) ||
3941 (cvarray_type == RPC_FC_C_WSTRING))
3943 ULONG i;
3944 /* strings must always have null terminating bytes */
3945 if (bufsize < esize)
3947 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
3948 RpcRaiseException(RPC_S_INVALID_BOUND);
3949 return NULL;
3951 for (i = bufsize - esize; i < bufsize; i++)
3952 if (pStubMsg->Buffer[i] != 0)
3954 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
3955 i, pStubMsg->Buffer[i]);
3956 RpcRaiseException(RPC_S_INVALID_BOUND);
3957 return NULL;
3961 /* copy the array data */
3962 safe_copy_from_buffer(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize);
3964 if (cvarray_type == RPC_FC_C_CSTRING)
3965 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3966 else if (cvarray_type == RPC_FC_C_WSTRING)
3967 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3969 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
3971 return NULL;
3974 /***********************************************************************
3975 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
3977 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3978 unsigned char *pMemory,
3979 PFORMAT_STRING pFormat)
3981 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3982 PFORMAT_STRING pCVArrayFormat;
3983 ULONG esize;
3985 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3987 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3988 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3990 ERR("invalid format type %x\n", pCVStructFormat->type);
3991 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3992 return;
3995 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3996 pCVStructFormat->offset_to_array_description;
3997 switch (*pCVArrayFormat)
3999 case RPC_FC_CVARRAY:
4000 esize = *(const WORD*)(pCVArrayFormat+2);
4002 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4003 pCVArrayFormat + 4, 0);
4004 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4005 pCVArrayFormat, 0);
4006 break;
4007 case RPC_FC_C_CSTRING:
4008 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4009 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4010 esize = sizeof(char);
4011 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4012 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4013 pCVArrayFormat + 2, 0);
4014 else
4015 pStubMsg->MaxCount = pStubMsg->ActualCount;
4016 break;
4017 case RPC_FC_C_WSTRING:
4018 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4019 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4020 esize = sizeof(WCHAR);
4021 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4022 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4023 pCVArrayFormat + 2, 0);
4024 else
4025 pStubMsg->MaxCount = pStubMsg->ActualCount;
4026 break;
4027 default:
4028 ERR("invalid array format type %x\n", *pCVArrayFormat);
4029 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4030 return;
4033 SizeConformance(pStubMsg);
4035 ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4037 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4039 safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4040 SizeVariance(pStubMsg);
4041 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4043 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4046 /***********************************************************************
4047 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
4049 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4050 PFORMAT_STRING pFormat)
4052 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4053 PFORMAT_STRING pCVArrayFormat;
4054 ULONG esize;
4055 unsigned char cvarray_type;
4057 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4059 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4060 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4062 ERR("invalid format type %x\n", pCVStructFormat->type);
4063 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4064 return 0;
4067 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4068 pCVStructFormat->offset_to_array_description;
4069 cvarray_type = *pCVArrayFormat;
4070 switch (cvarray_type)
4072 case RPC_FC_CVARRAY:
4073 esize = *(const WORD*)(pCVArrayFormat+2);
4074 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
4075 break;
4076 case RPC_FC_C_CSTRING:
4077 esize = sizeof(char);
4078 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4079 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4080 else
4081 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4082 break;
4083 case RPC_FC_C_WSTRING:
4084 esize = sizeof(WCHAR);
4085 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4086 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4087 else
4088 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4089 break;
4090 default:
4091 ERR("invalid array format type %x\n", *pCVArrayFormat);
4092 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4093 return 0;
4096 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4098 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4100 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4101 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
4102 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4104 pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
4106 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4108 return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
4111 /***********************************************************************
4112 * NdrConformantVaryingStructFree [RPCRT4.@]
4114 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4115 unsigned char *pMemory,
4116 PFORMAT_STRING pFormat)
4118 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4119 PFORMAT_STRING pCVArrayFormat;
4120 ULONG esize;
4122 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4124 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4125 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4127 ERR("invalid format type %x\n", pCVStructFormat->type);
4128 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4129 return;
4132 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4133 pCVStructFormat->offset_to_array_description;
4134 switch (*pCVArrayFormat)
4136 case RPC_FC_CVARRAY:
4137 esize = *(const WORD*)(pCVArrayFormat+2);
4139 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4140 pCVArrayFormat + 4, 0);
4141 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4142 pCVArrayFormat, 0);
4143 break;
4144 case RPC_FC_C_CSTRING:
4145 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4146 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4147 esize = sizeof(char);
4148 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4149 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4150 pCVArrayFormat + 2, 0);
4151 else
4152 pStubMsg->MaxCount = pStubMsg->ActualCount;
4153 break;
4154 case RPC_FC_C_WSTRING:
4155 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4156 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4157 esize = sizeof(WCHAR);
4158 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4159 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4160 pCVArrayFormat + 2, 0);
4161 else
4162 pStubMsg->MaxCount = pStubMsg->ActualCount;
4163 break;
4164 default:
4165 ERR("invalid array format type %x\n", *pCVArrayFormat);
4166 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4167 return;
4170 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4172 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4175 #include "pshpack1.h"
4176 typedef struct
4178 unsigned char type;
4179 unsigned char alignment;
4180 unsigned short total_size;
4181 } NDR_SMFARRAY_FORMAT;
4183 typedef struct
4185 unsigned char type;
4186 unsigned char alignment;
4187 unsigned long total_size;
4188 } NDR_LGFARRAY_FORMAT;
4189 #include "poppack.h"
4191 /***********************************************************************
4192 * NdrFixedArrayMarshall [RPCRT4.@]
4194 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4195 unsigned char *pMemory,
4196 PFORMAT_STRING pFormat)
4198 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4199 unsigned long total_size;
4201 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4203 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4204 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4206 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4207 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4208 return NULL;
4211 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4213 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4215 total_size = pSmFArrayFormat->total_size;
4216 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4218 else
4220 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4221 total_size = pLgFArrayFormat->total_size;
4222 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4225 pStubMsg->BufferMark = pStubMsg->Buffer;
4226 safe_copy_to_buffer(pStubMsg, pMemory, total_size);
4228 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4230 return NULL;
4233 /***********************************************************************
4234 * NdrFixedArrayUnmarshall [RPCRT4.@]
4236 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4237 unsigned char **ppMemory,
4238 PFORMAT_STRING pFormat,
4239 unsigned char fMustAlloc)
4241 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4242 unsigned long total_size;
4243 unsigned char *saved_buffer;
4245 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4247 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4248 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4250 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4251 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4252 return NULL;
4255 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4257 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4259 total_size = pSmFArrayFormat->total_size;
4260 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4262 else
4264 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4265 total_size = pLgFArrayFormat->total_size;
4266 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4269 if (fMustAlloc)
4270 *ppMemory = NdrAllocate(pStubMsg, total_size);
4271 else
4273 if (!pStubMsg->IsClient && !*ppMemory)
4274 /* for servers, we just point straight into the RPC buffer */
4275 *ppMemory = pStubMsg->Buffer;
4278 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4279 safe_buffer_increment(pStubMsg, total_size);
4280 pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4282 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4283 if (*ppMemory != saved_buffer)
4284 memcpy(*ppMemory, saved_buffer, total_size);
4286 return NULL;
4289 /***********************************************************************
4290 * NdrFixedArrayBufferSize [RPCRT4.@]
4292 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4293 unsigned char *pMemory,
4294 PFORMAT_STRING pFormat)
4296 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4297 unsigned long total_size;
4299 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4301 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4302 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4304 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4305 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4306 return;
4309 ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
4311 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4313 total_size = pSmFArrayFormat->total_size;
4314 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4316 else
4318 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4319 total_size = pLgFArrayFormat->total_size;
4320 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4322 safe_buffer_length_increment(pStubMsg, total_size);
4324 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4327 /***********************************************************************
4328 * NdrFixedArrayMemorySize [RPCRT4.@]
4330 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4331 PFORMAT_STRING pFormat)
4333 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4334 ULONG total_size;
4336 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4338 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4339 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4341 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4342 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4343 return 0;
4346 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4348 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4350 total_size = pSmFArrayFormat->total_size;
4351 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4353 else
4355 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4356 total_size = pLgFArrayFormat->total_size;
4357 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4359 pStubMsg->BufferMark = pStubMsg->Buffer;
4360 safe_buffer_increment(pStubMsg, total_size);
4361 pStubMsg->MemorySize += total_size;
4363 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4365 return total_size;
4368 /***********************************************************************
4369 * NdrFixedArrayFree [RPCRT4.@]
4371 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4372 unsigned char *pMemory,
4373 PFORMAT_STRING pFormat)
4375 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4377 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4379 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4380 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4382 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4383 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4384 return;
4387 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4388 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4389 else
4391 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4392 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4395 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4398 /***********************************************************************
4399 * NdrVaryingArrayMarshall [RPCRT4.@]
4401 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4402 unsigned char *pMemory,
4403 PFORMAT_STRING pFormat)
4405 unsigned char alignment;
4406 DWORD elements, esize;
4407 ULONG bufsize;
4409 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4411 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4412 (pFormat[0] != RPC_FC_LGVARRAY))
4414 ERR("invalid format type %x\n", pFormat[0]);
4415 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4416 return NULL;
4419 alignment = pFormat[1] + 1;
4421 if (pFormat[0] == RPC_FC_SMVARRAY)
4423 pFormat += 2;
4424 pFormat += sizeof(WORD);
4425 elements = *(const WORD*)pFormat;
4426 pFormat += sizeof(WORD);
4428 else
4430 pFormat += 2;
4431 pFormat += sizeof(DWORD);
4432 elements = *(const DWORD*)pFormat;
4433 pFormat += sizeof(DWORD);
4436 esize = *(const WORD*)pFormat;
4437 pFormat += sizeof(WORD);
4439 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4440 if ((pStubMsg->ActualCount > elements) ||
4441 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4443 RpcRaiseException(RPC_S_INVALID_BOUND);
4444 return NULL;
4447 WriteVariance(pStubMsg);
4449 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
4451 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4452 pStubMsg->BufferMark = pStubMsg->Buffer;
4453 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
4455 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4457 return NULL;
4460 /***********************************************************************
4461 * NdrVaryingArrayUnmarshall [RPCRT4.@]
4463 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4464 unsigned char **ppMemory,
4465 PFORMAT_STRING pFormat,
4466 unsigned char fMustAlloc)
4468 unsigned char alignment;
4469 DWORD size, elements, esize;
4470 ULONG bufsize;
4472 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4474 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4475 (pFormat[0] != RPC_FC_LGVARRAY))
4477 ERR("invalid format type %x\n", pFormat[0]);
4478 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4479 return NULL;
4482 alignment = pFormat[1] + 1;
4484 if (pFormat[0] == RPC_FC_SMVARRAY)
4486 pFormat += 2;
4487 size = *(const WORD*)pFormat;
4488 pFormat += sizeof(WORD);
4489 elements = *(const WORD*)pFormat;
4490 pFormat += sizeof(WORD);
4492 else
4494 pFormat += 2;
4495 size = *(const DWORD*)pFormat;
4496 pFormat += sizeof(DWORD);
4497 elements = *(const DWORD*)pFormat;
4498 pFormat += sizeof(DWORD);
4501 esize = *(const WORD*)pFormat;
4502 pFormat += sizeof(WORD);
4504 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4506 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4508 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4510 if (!*ppMemory || fMustAlloc)
4511 *ppMemory = NdrAllocate(pStubMsg, size);
4512 safe_copy_from_buffer(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
4514 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
4516 return NULL;
4519 /***********************************************************************
4520 * NdrVaryingArrayBufferSize [RPCRT4.@]
4522 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4523 unsigned char *pMemory,
4524 PFORMAT_STRING pFormat)
4526 unsigned char alignment;
4527 DWORD elements, esize;
4529 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4531 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4532 (pFormat[0] != RPC_FC_LGVARRAY))
4534 ERR("invalid format type %x\n", pFormat[0]);
4535 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4536 return;
4539 alignment = pFormat[1] + 1;
4541 if (pFormat[0] == RPC_FC_SMVARRAY)
4543 pFormat += 2;
4544 pFormat += sizeof(WORD);
4545 elements = *(const WORD*)pFormat;
4546 pFormat += sizeof(WORD);
4548 else
4550 pFormat += 2;
4551 pFormat += sizeof(DWORD);
4552 elements = *(const DWORD*)pFormat;
4553 pFormat += sizeof(DWORD);
4556 esize = *(const WORD*)pFormat;
4557 pFormat += sizeof(WORD);
4559 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4560 if ((pStubMsg->ActualCount > elements) ||
4561 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4563 RpcRaiseException(RPC_S_INVALID_BOUND);
4564 return;
4567 SizeVariance(pStubMsg);
4569 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4571 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4573 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4576 /***********************************************************************
4577 * NdrVaryingArrayMemorySize [RPCRT4.@]
4579 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4580 PFORMAT_STRING pFormat)
4582 unsigned char alignment;
4583 DWORD size, elements, esize;
4585 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4587 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4588 (pFormat[0] != RPC_FC_LGVARRAY))
4590 ERR("invalid format type %x\n", pFormat[0]);
4591 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4592 return 0;
4595 alignment = pFormat[1] + 1;
4597 if (pFormat[0] == RPC_FC_SMVARRAY)
4599 pFormat += 2;
4600 size = *(const WORD*)pFormat;
4601 pFormat += sizeof(WORD);
4602 elements = *(const WORD*)pFormat;
4603 pFormat += sizeof(WORD);
4605 else
4607 pFormat += 2;
4608 size = *(const DWORD*)pFormat;
4609 pFormat += sizeof(DWORD);
4610 elements = *(const DWORD*)pFormat;
4611 pFormat += sizeof(DWORD);
4614 esize = *(const WORD*)pFormat;
4615 pFormat += sizeof(WORD);
4617 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4619 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4621 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4622 pStubMsg->MemorySize += size;
4624 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4626 return pStubMsg->MemorySize;
4629 /***********************************************************************
4630 * NdrVaryingArrayFree [RPCRT4.@]
4632 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4633 unsigned char *pMemory,
4634 PFORMAT_STRING pFormat)
4636 unsigned char alignment;
4637 DWORD elements;
4639 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4641 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4642 (pFormat[0] != RPC_FC_LGVARRAY))
4644 ERR("invalid format type %x\n", pFormat[0]);
4645 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4646 return;
4649 alignment = pFormat[1] + 1;
4651 if (pFormat[0] == RPC_FC_SMVARRAY)
4653 pFormat += 2;
4654 pFormat += sizeof(WORD);
4655 elements = *(const WORD*)pFormat;
4656 pFormat += sizeof(WORD);
4658 else
4660 pFormat += 2;
4661 pFormat += sizeof(DWORD);
4662 elements = *(const DWORD*)pFormat;
4663 pFormat += sizeof(DWORD);
4666 pFormat += sizeof(WORD);
4668 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4669 if ((pStubMsg->ActualCount > elements) ||
4670 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4672 RpcRaiseException(RPC_S_INVALID_BOUND);
4673 return;
4676 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4679 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
4681 switch (fc)
4683 case RPC_FC_BYTE:
4684 case RPC_FC_CHAR:
4685 case RPC_FC_SMALL:
4686 case RPC_FC_USMALL:
4687 return *(const UCHAR *)pMemory;
4688 case RPC_FC_WCHAR:
4689 case RPC_FC_SHORT:
4690 case RPC_FC_USHORT:
4691 case RPC_FC_ENUM16:
4692 return *(const USHORT *)pMemory;
4693 case RPC_FC_LONG:
4694 case RPC_FC_ULONG:
4695 case RPC_FC_ENUM32:
4696 return *(const ULONG *)pMemory;
4697 default:
4698 FIXME("Unhandled base type: 0x%02x\n", fc);
4699 return 0;
4703 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
4704 unsigned long discriminant,
4705 PFORMAT_STRING pFormat)
4707 unsigned short num_arms, arm, type;
4709 num_arms = *(const SHORT*)pFormat & 0x0fff;
4710 pFormat += 2;
4711 for(arm = 0; arm < num_arms; arm++)
4713 if(discriminant == *(const ULONG*)pFormat)
4715 pFormat += 4;
4716 break;
4718 pFormat += 6;
4721 type = *(const unsigned short*)pFormat;
4722 TRACE("type %04x\n", type);
4723 if(arm == num_arms) /* default arm extras */
4725 if(type == 0xffff)
4727 ERR("no arm for 0x%lx and no default case\n", discriminant);
4728 RpcRaiseException(RPC_S_INVALID_TAG);
4729 return NULL;
4731 if(type == 0)
4733 TRACE("falling back to empty default case for 0x%lx\n", discriminant);
4734 return NULL;
4737 return pFormat;
4740 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
4742 unsigned short type;
4744 pFormat += 2;
4746 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4747 if(!pFormat)
4748 return NULL;
4750 type = *(const unsigned short*)pFormat;
4751 if((type & 0xff00) == 0x8000)
4753 unsigned char basetype = LOBYTE(type);
4754 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4756 else
4758 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4759 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4760 if (m)
4762 unsigned char *saved_buffer = NULL;
4763 int pointer_buffer_mark_set = 0;
4764 switch(*desc)
4766 case RPC_FC_RP:
4767 case RPC_FC_UP:
4768 case RPC_FC_OP:
4769 case RPC_FC_FP:
4770 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
4771 saved_buffer = pStubMsg->Buffer;
4772 if (pStubMsg->PointerBufferMark)
4774 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4775 pStubMsg->PointerBufferMark = NULL;
4776 pointer_buffer_mark_set = 1;
4778 else
4779 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
4781 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
4782 if (pointer_buffer_mark_set)
4784 STD_OVERFLOW_CHECK(pStubMsg);
4785 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4786 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
4788 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
4789 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
4790 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4792 pStubMsg->Buffer = saved_buffer + 4;
4794 break;
4795 default:
4796 m(pStubMsg, pMemory, desc);
4799 else FIXME("no marshaller for embedded type %02x\n", *desc);
4801 return NULL;
4804 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4805 unsigned char **ppMemory,
4806 ULONG discriminant,
4807 PFORMAT_STRING pFormat,
4808 unsigned char fMustAlloc)
4810 unsigned short type;
4812 pFormat += 2;
4814 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4815 if(!pFormat)
4816 return NULL;
4818 type = *(const unsigned short*)pFormat;
4819 if((type & 0xff00) == 0x8000)
4821 unsigned char basetype = LOBYTE(type);
4822 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
4824 else
4826 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4827 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
4828 if (m)
4830 unsigned char *saved_buffer = NULL;
4831 int pointer_buffer_mark_set = 0;
4832 switch(*desc)
4834 case RPC_FC_RP:
4835 case RPC_FC_UP:
4836 case RPC_FC_OP:
4837 case RPC_FC_FP:
4838 **(void***)ppMemory = NULL;
4839 ALIGN_POINTER(pStubMsg->Buffer, 4);
4840 saved_buffer = pStubMsg->Buffer;
4841 if (pStubMsg->PointerBufferMark)
4843 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4844 pStubMsg->PointerBufferMark = NULL;
4845 pointer_buffer_mark_set = 1;
4847 else
4848 pStubMsg->Buffer += 4; /* for pointer ID */
4850 if (saved_buffer + 4 > pStubMsg->BufferEnd)
4852 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
4853 saved_buffer, pStubMsg->BufferEnd);
4854 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4857 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
4858 if (pointer_buffer_mark_set)
4860 STD_OVERFLOW_CHECK(pStubMsg);
4861 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4862 pStubMsg->Buffer = saved_buffer + 4;
4864 break;
4865 default:
4866 m(pStubMsg, ppMemory, desc, fMustAlloc);
4869 else FIXME("no marshaller for embedded type %02x\n", *desc);
4871 return NULL;
4874 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
4875 unsigned char *pMemory,
4876 ULONG discriminant,
4877 PFORMAT_STRING pFormat)
4879 unsigned short type;
4881 pFormat += 2;
4883 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4884 if(!pFormat)
4885 return;
4887 type = *(const unsigned short*)pFormat;
4888 if((type & 0xff00) == 0x8000)
4890 unsigned char basetype = LOBYTE(type);
4891 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
4893 else
4895 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4896 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
4897 if (m)
4899 switch(*desc)
4901 case RPC_FC_RP:
4902 case RPC_FC_UP:
4903 case RPC_FC_OP:
4904 case RPC_FC_FP:
4905 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4906 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
4907 if (!pStubMsg->IgnoreEmbeddedPointers)
4909 int saved_buffer_length = pStubMsg->BufferLength;
4910 pStubMsg->BufferLength = pStubMsg->PointerLength;
4911 pStubMsg->PointerLength = 0;
4912 if(!pStubMsg->BufferLength)
4913 ERR("BufferLength == 0??\n");
4914 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
4915 pStubMsg->PointerLength = pStubMsg->BufferLength;
4916 pStubMsg->BufferLength = saved_buffer_length;
4918 break;
4919 default:
4920 m(pStubMsg, pMemory, desc);
4923 else FIXME("no buffersizer for embedded type %02x\n", *desc);
4927 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
4928 ULONG discriminant,
4929 PFORMAT_STRING pFormat)
4931 unsigned short type, size;
4933 size = *(const unsigned short*)pFormat;
4934 pStubMsg->Memory += size;
4935 pFormat += 2;
4937 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4938 if(!pFormat)
4939 return 0;
4941 type = *(const unsigned short*)pFormat;
4942 if((type & 0xff00) == 0x8000)
4944 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
4946 else
4948 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4949 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
4950 unsigned char *saved_buffer;
4951 if (m)
4953 switch(*desc)
4955 case RPC_FC_RP:
4956 case RPC_FC_UP:
4957 case RPC_FC_OP:
4958 case RPC_FC_FP:
4959 ALIGN_POINTER(pStubMsg->Buffer, 4);
4960 saved_buffer = pStubMsg->Buffer;
4961 safe_buffer_increment(pStubMsg, 4);
4962 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
4963 pStubMsg->MemorySize += 4;
4964 if (!pStubMsg->IgnoreEmbeddedPointers)
4965 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
4966 break;
4967 default:
4968 return m(pStubMsg, desc);
4971 else FIXME("no marshaller for embedded type %02x\n", *desc);
4974 TRACE("size %d\n", size);
4975 return size;
4978 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
4979 unsigned char *pMemory,
4980 ULONG discriminant,
4981 PFORMAT_STRING pFormat)
4983 unsigned short type;
4985 pFormat += 2;
4987 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4988 if(!pFormat)
4989 return;
4991 type = *(const unsigned short*)pFormat;
4992 if((type & 0xff00) != 0x8000)
4994 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4995 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
4996 if (m)
4998 switch(*desc)
5000 case RPC_FC_RP:
5001 case RPC_FC_UP:
5002 case RPC_FC_OP:
5003 case RPC_FC_FP:
5004 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5005 break;
5006 default:
5007 m(pStubMsg, pMemory, desc);
5010 else FIXME("no freer for embedded type %02x\n", *desc);
5014 /***********************************************************************
5015 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
5017 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5018 unsigned char *pMemory,
5019 PFORMAT_STRING pFormat)
5021 unsigned char switch_type;
5022 unsigned char increment;
5023 ULONG switch_value;
5025 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5026 pFormat++;
5028 switch_type = *pFormat & 0xf;
5029 increment = (*pFormat & 0xf0) >> 4;
5030 pFormat++;
5032 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment);
5034 switch_value = get_discriminant(switch_type, pMemory);
5035 TRACE("got switch value 0x%x\n", switch_value);
5037 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5038 pMemory += increment;
5040 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5043 /***********************************************************************
5044 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5046 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5047 unsigned char **ppMemory,
5048 PFORMAT_STRING pFormat,
5049 unsigned char fMustAlloc)
5051 unsigned char switch_type;
5052 unsigned char increment;
5053 ULONG switch_value;
5054 unsigned short size;
5055 unsigned char *pMemoryArm;
5057 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5058 pFormat++;
5060 switch_type = *pFormat & 0xf;
5061 increment = (*pFormat & 0xf0) >> 4;
5062 pFormat++;
5064 ALIGN_POINTER(pStubMsg->Buffer, increment);
5065 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5066 TRACE("got switch value 0x%x\n", switch_value);
5068 size = *(const unsigned short*)pFormat + increment;
5069 if(!*ppMemory || fMustAlloc)
5070 *ppMemory = NdrAllocate(pStubMsg, size);
5072 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5073 pMemoryArm = *ppMemory + increment;
5075 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
5078 /***********************************************************************
5079 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5081 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5082 unsigned char *pMemory,
5083 PFORMAT_STRING pFormat)
5085 unsigned char switch_type;
5086 unsigned char increment;
5087 ULONG switch_value;
5089 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5090 pFormat++;
5092 switch_type = *pFormat & 0xf;
5093 increment = (*pFormat & 0xf0) >> 4;
5094 pFormat++;
5096 ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5097 switch_value = get_discriminant(switch_type, pMemory);
5098 TRACE("got switch value 0x%x\n", switch_value);
5100 /* Add discriminant size */
5101 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5102 pMemory += increment;
5104 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5107 /***********************************************************************
5108 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5110 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5111 PFORMAT_STRING pFormat)
5113 unsigned char switch_type;
5114 unsigned char increment;
5115 ULONG switch_value;
5117 switch_type = *pFormat & 0xf;
5118 increment = (*pFormat & 0xf0) >> 4;
5119 pFormat++;
5121 ALIGN_POINTER(pStubMsg->Buffer, increment);
5122 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5123 TRACE("got switch value 0x%x\n", switch_value);
5125 pStubMsg->Memory += increment;
5127 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5130 /***********************************************************************
5131 * NdrEncapsulatedUnionFree [RPCRT4.@]
5133 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5134 unsigned char *pMemory,
5135 PFORMAT_STRING pFormat)
5137 unsigned char switch_type;
5138 unsigned char increment;
5139 ULONG switch_value;
5141 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5142 pFormat++;
5144 switch_type = *pFormat & 0xf;
5145 increment = (*pFormat & 0xf0) >> 4;
5146 pFormat++;
5148 switch_value = get_discriminant(switch_type, pMemory);
5149 TRACE("got switch value 0x%x\n", switch_value);
5151 pMemory += increment;
5153 return union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5156 /***********************************************************************
5157 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5159 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5160 unsigned char *pMemory,
5161 PFORMAT_STRING pFormat)
5163 unsigned char switch_type;
5165 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5166 pFormat++;
5168 switch_type = *pFormat;
5169 pFormat++;
5171 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5172 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5173 /* Marshall discriminant */
5174 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5176 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5179 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
5180 PFORMAT_STRING *ppFormat)
5182 long discriminant = 0;
5184 switch(**ppFormat)
5186 case RPC_FC_BYTE:
5187 case RPC_FC_CHAR:
5188 case RPC_FC_SMALL:
5189 case RPC_FC_USMALL:
5191 UCHAR d;
5192 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5193 discriminant = d;
5194 break;
5196 case RPC_FC_WCHAR:
5197 case RPC_FC_SHORT:
5198 case RPC_FC_USHORT:
5200 USHORT d;
5201 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5202 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5203 discriminant = d;
5204 break;
5206 case RPC_FC_LONG:
5207 case RPC_FC_ULONG:
5209 ULONG d;
5210 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5211 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5212 discriminant = d;
5213 break;
5215 default:
5216 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
5218 (*ppFormat)++;
5220 if (pStubMsg->fHasNewCorrDesc)
5221 *ppFormat += 6;
5222 else
5223 *ppFormat += 4;
5224 return discriminant;
5227 /**********************************************************************
5228 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
5230 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5231 unsigned char **ppMemory,
5232 PFORMAT_STRING pFormat,
5233 unsigned char fMustAlloc)
5235 long discriminant;
5236 unsigned short size;
5238 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5239 pFormat++;
5241 /* Unmarshall discriminant */
5242 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5243 TRACE("unmarshalled discriminant %lx\n", discriminant);
5245 pFormat += *(const SHORT*)pFormat;
5247 size = *(const unsigned short*)pFormat;
5249 if(!*ppMemory || fMustAlloc)
5250 *ppMemory = NdrAllocate(pStubMsg, size);
5252 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
5255 /***********************************************************************
5256 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
5258 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5259 unsigned char *pMemory,
5260 PFORMAT_STRING pFormat)
5262 unsigned char switch_type;
5264 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5265 pFormat++;
5267 switch_type = *pFormat;
5268 pFormat++;
5270 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5271 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5272 /* Add discriminant size */
5273 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5275 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5278 /***********************************************************************
5279 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
5281 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5282 PFORMAT_STRING pFormat)
5284 ULONG discriminant;
5286 pFormat++;
5287 /* Unmarshall discriminant */
5288 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5289 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
5291 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
5294 /***********************************************************************
5295 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
5297 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5298 unsigned char *pMemory,
5299 PFORMAT_STRING pFormat)
5301 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5302 pFormat++;
5303 pFormat++;
5305 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5306 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5308 return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5311 /***********************************************************************
5312 * NdrByteCountPointerMarshall [RPCRT4.@]
5314 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5315 unsigned char *pMemory,
5316 PFORMAT_STRING pFormat)
5318 FIXME("stub\n");
5319 return NULL;
5322 /***********************************************************************
5323 * NdrByteCountPointerUnmarshall [RPCRT4.@]
5325 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5326 unsigned char **ppMemory,
5327 PFORMAT_STRING pFormat,
5328 unsigned char fMustAlloc)
5330 FIXME("stub\n");
5331 return NULL;
5334 /***********************************************************************
5335 * NdrByteCountPointerBufferSize [RPCRT4.@]
5337 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5338 unsigned char *pMemory,
5339 PFORMAT_STRING pFormat)
5341 FIXME("stub\n");
5344 /***********************************************************************
5345 * NdrByteCountPointerMemorySize [RPCRT4.@]
5347 ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5348 PFORMAT_STRING pFormat)
5350 FIXME("stub\n");
5351 return 0;
5354 /***********************************************************************
5355 * NdrByteCountPointerFree [RPCRT4.@]
5357 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
5358 unsigned char *pMemory,
5359 PFORMAT_STRING pFormat)
5361 FIXME("stub\n");
5364 /***********************************************************************
5365 * NdrXmitOrRepAsMarshall [RPCRT4.@]
5367 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5368 unsigned char *pMemory,
5369 PFORMAT_STRING pFormat)
5371 FIXME("stub\n");
5372 return NULL;
5375 /***********************************************************************
5376 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
5378 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5379 unsigned char **ppMemory,
5380 PFORMAT_STRING pFormat,
5381 unsigned char fMustAlloc)
5383 FIXME("stub\n");
5384 return NULL;
5387 /***********************************************************************
5388 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
5390 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5391 unsigned char *pMemory,
5392 PFORMAT_STRING pFormat)
5394 FIXME("stub\n");
5397 /***********************************************************************
5398 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
5400 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5401 PFORMAT_STRING pFormat)
5403 FIXME("stub\n");
5404 return 0;
5407 /***********************************************************************
5408 * NdrXmitOrRepAsFree [RPCRT4.@]
5410 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
5411 unsigned char *pMemory,
5412 PFORMAT_STRING pFormat)
5414 FIXME("stub\n");
5417 #include "pshpack1.h"
5418 typedef struct
5420 unsigned char type;
5421 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
5422 ULONG low_value;
5423 ULONG high_value;
5424 } NDR_RANGE;
5425 #include "poppack.h"
5427 /***********************************************************************
5428 * NdrRangeMarshall [internal]
5430 unsigned char *WINAPI NdrRangeMarshall(
5431 PMIDL_STUB_MESSAGE pStubMsg,
5432 unsigned char *pMemory,
5433 PFORMAT_STRING pFormat)
5435 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5436 unsigned char base_type;
5438 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5440 if (pRange->type != RPC_FC_RANGE)
5442 ERR("invalid format type %x\n", pRange->type);
5443 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5444 return NULL;
5447 base_type = pRange->flags_type & 0xf;
5449 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
5452 /***********************************************************************
5453 * NdrRangeUnmarshall
5455 unsigned char *WINAPI NdrRangeUnmarshall(
5456 PMIDL_STUB_MESSAGE pStubMsg,
5457 unsigned char **ppMemory,
5458 PFORMAT_STRING pFormat,
5459 unsigned char fMustAlloc)
5461 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5462 unsigned char base_type;
5464 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5466 if (pRange->type != RPC_FC_RANGE)
5468 ERR("invalid format type %x\n", pRange->type);
5469 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5470 return NULL;
5472 base_type = pRange->flags_type & 0xf;
5474 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
5475 base_type, pRange->low_value, pRange->high_value);
5477 #define RANGE_UNMARSHALL(type, format_spec) \
5478 do \
5480 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5481 if (fMustAlloc || !*ppMemory) \
5482 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5483 if (pStubMsg->Buffer + sizeof(type) > pStubMsg->BufferEnd) \
5485 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
5486 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
5487 RpcRaiseException(RPC_X_BAD_STUB_DATA); \
5489 if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \
5490 (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \
5492 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
5493 *(type *)pStubMsg->Buffer, (type)pRange->low_value, \
5494 (type)pRange->high_value); \
5495 RpcRaiseException(RPC_S_INVALID_BOUND); \
5496 return NULL; \
5498 TRACE("*ppMemory: %p\n", *ppMemory); \
5499 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5500 pStubMsg->Buffer += sizeof(type); \
5501 } while (0)
5503 switch(base_type)
5505 case RPC_FC_CHAR:
5506 case RPC_FC_SMALL:
5507 RANGE_UNMARSHALL(UCHAR, "%d");
5508 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5509 break;
5510 case RPC_FC_BYTE:
5511 case RPC_FC_USMALL:
5512 RANGE_UNMARSHALL(CHAR, "%u");
5513 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5514 break;
5515 case RPC_FC_WCHAR: /* FIXME: valid? */
5516 case RPC_FC_USHORT:
5517 RANGE_UNMARSHALL(USHORT, "%u");
5518 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5519 break;
5520 case RPC_FC_SHORT:
5521 RANGE_UNMARSHALL(SHORT, "%d");
5522 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5523 break;
5524 case RPC_FC_LONG:
5525 RANGE_UNMARSHALL(LONG, "%d");
5526 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5527 break;
5528 case RPC_FC_ULONG:
5529 RANGE_UNMARSHALL(ULONG, "%u");
5530 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5531 break;
5532 case RPC_FC_ENUM16:
5533 case RPC_FC_ENUM32:
5534 FIXME("Unhandled enum type\n");
5535 break;
5536 case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */
5537 case RPC_FC_FLOAT:
5538 case RPC_FC_DOUBLE:
5539 case RPC_FC_HYPER:
5540 default:
5541 ERR("invalid range base type: 0x%02x\n", base_type);
5542 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5545 return NULL;
5548 /***********************************************************************
5549 * NdrRangeBufferSize [internal]
5551 void WINAPI NdrRangeBufferSize(
5552 PMIDL_STUB_MESSAGE pStubMsg,
5553 unsigned char *pMemory,
5554 PFORMAT_STRING pFormat)
5556 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5557 unsigned char base_type;
5559 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5561 if (pRange->type != RPC_FC_RANGE)
5563 ERR("invalid format type %x\n", pRange->type);
5564 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5566 base_type = pRange->flags_type & 0xf;
5568 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
5571 /***********************************************************************
5572 * NdrRangeMemorySize [internal]
5574 ULONG WINAPI NdrRangeMemorySize(
5575 PMIDL_STUB_MESSAGE pStubMsg,
5576 PFORMAT_STRING pFormat)
5578 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5579 unsigned char base_type;
5581 if (pRange->type != RPC_FC_RANGE)
5583 ERR("invalid format type %x\n", pRange->type);
5584 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5585 return 0;
5587 base_type = pRange->flags_type & 0xf;
5589 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
5592 /***********************************************************************
5593 * NdrRangeFree [internal]
5595 void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
5596 unsigned char *pMemory,
5597 PFORMAT_STRING pFormat)
5599 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5601 /* nothing to do */
5604 /***********************************************************************
5605 * NdrBaseTypeMarshall [internal]
5607 static unsigned char *WINAPI NdrBaseTypeMarshall(
5608 PMIDL_STUB_MESSAGE pStubMsg,
5609 unsigned char *pMemory,
5610 PFORMAT_STRING pFormat)
5612 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5614 switch(*pFormat)
5616 case RPC_FC_BYTE:
5617 case RPC_FC_CHAR:
5618 case RPC_FC_SMALL:
5619 case RPC_FC_USMALL:
5620 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
5621 TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
5622 break;
5623 case RPC_FC_WCHAR:
5624 case RPC_FC_SHORT:
5625 case RPC_FC_USHORT:
5626 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
5627 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
5628 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
5629 break;
5630 case RPC_FC_LONG:
5631 case RPC_FC_ULONG:
5632 case RPC_FC_ERROR_STATUS_T:
5633 case RPC_FC_ENUM32:
5634 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG));
5635 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
5636 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
5637 break;
5638 case RPC_FC_FLOAT:
5639 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float));
5640 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
5641 break;
5642 case RPC_FC_DOUBLE:
5643 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double));
5644 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
5645 break;
5646 case RPC_FC_HYPER:
5647 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG));
5648 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
5649 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
5650 break;
5651 case RPC_FC_ENUM16:
5652 /* only 16-bits on the wire, so do a sanity check */
5653 if (*(UINT *)pMemory > SHRT_MAX)
5654 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
5655 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
5656 if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5657 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5658 *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
5659 pStubMsg->Buffer += sizeof(USHORT);
5660 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
5661 break;
5662 case RPC_FC_IGNORE:
5663 break;
5664 default:
5665 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5668 /* FIXME: what is the correct return value? */
5669 return NULL;
5672 /***********************************************************************
5673 * NdrBaseTypeUnmarshall [internal]
5675 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
5676 PMIDL_STUB_MESSAGE pStubMsg,
5677 unsigned char **ppMemory,
5678 PFORMAT_STRING pFormat,
5679 unsigned char fMustAlloc)
5681 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5683 #define BASE_TYPE_UNMARSHALL(type) \
5684 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5685 if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
5687 *ppMemory = pStubMsg->Buffer; \
5688 TRACE("*ppMemory: %p\n", *ppMemory); \
5690 else \
5692 if (fMustAlloc) \
5693 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5694 TRACE("*ppMemory: %p\n", *ppMemory); \
5695 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5697 pStubMsg->Buffer += sizeof(type);
5699 switch(*pFormat)
5701 case RPC_FC_BYTE:
5702 case RPC_FC_CHAR:
5703 case RPC_FC_SMALL:
5704 case RPC_FC_USMALL:
5705 BASE_TYPE_UNMARSHALL(UCHAR);
5706 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5707 break;
5708 case RPC_FC_WCHAR:
5709 case RPC_FC_SHORT:
5710 case RPC_FC_USHORT:
5711 BASE_TYPE_UNMARSHALL(USHORT);
5712 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5713 break;
5714 case RPC_FC_LONG:
5715 case RPC_FC_ULONG:
5716 case RPC_FC_ERROR_STATUS_T:
5717 case RPC_FC_ENUM32:
5718 BASE_TYPE_UNMARSHALL(ULONG);
5719 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5720 break;
5721 case RPC_FC_FLOAT:
5722 BASE_TYPE_UNMARSHALL(float);
5723 TRACE("value: %f\n", **(float **)ppMemory);
5724 break;
5725 case RPC_FC_DOUBLE:
5726 BASE_TYPE_UNMARSHALL(double);
5727 TRACE("value: %f\n", **(double **)ppMemory);
5728 break;
5729 case RPC_FC_HYPER:
5730 BASE_TYPE_UNMARSHALL(ULONGLONG);
5731 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
5732 break;
5733 case RPC_FC_ENUM16:
5734 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5735 if (fMustAlloc || !*ppMemory)
5736 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
5737 if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
5738 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5739 TRACE("*ppMemory: %p\n", *ppMemory);
5740 /* 16-bits on the wire, but int in memory */
5741 **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
5742 pStubMsg->Buffer += sizeof(USHORT);
5743 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
5744 break;
5745 case RPC_FC_IGNORE:
5746 break;
5747 default:
5748 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5750 #undef BASE_TYPE_UNMARSHALL
5752 /* FIXME: what is the correct return value? */
5754 return NULL;
5757 /***********************************************************************
5758 * NdrBaseTypeBufferSize [internal]
5760 static void WINAPI NdrBaseTypeBufferSize(
5761 PMIDL_STUB_MESSAGE pStubMsg,
5762 unsigned char *pMemory,
5763 PFORMAT_STRING pFormat)
5765 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5767 switch(*pFormat)
5769 case RPC_FC_BYTE:
5770 case RPC_FC_CHAR:
5771 case RPC_FC_SMALL:
5772 case RPC_FC_USMALL:
5773 safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
5774 break;
5775 case RPC_FC_WCHAR:
5776 case RPC_FC_SHORT:
5777 case RPC_FC_USHORT:
5778 case RPC_FC_ENUM16:
5779 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
5780 safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
5781 break;
5782 case RPC_FC_LONG:
5783 case RPC_FC_ULONG:
5784 case RPC_FC_ENUM32:
5785 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
5786 safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
5787 break;
5788 case RPC_FC_FLOAT:
5789 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
5790 safe_buffer_length_increment(pStubMsg, sizeof(float));
5791 break;
5792 case RPC_FC_DOUBLE:
5793 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
5794 safe_buffer_length_increment(pStubMsg, sizeof(double));
5795 break;
5796 case RPC_FC_HYPER:
5797 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
5798 safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
5799 break;
5800 case RPC_FC_ERROR_STATUS_T:
5801 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
5802 safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
5803 break;
5804 case RPC_FC_IGNORE:
5805 break;
5806 default:
5807 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5811 /***********************************************************************
5812 * NdrBaseTypeMemorySize [internal]
5814 static ULONG WINAPI NdrBaseTypeMemorySize(
5815 PMIDL_STUB_MESSAGE pStubMsg,
5816 PFORMAT_STRING pFormat)
5818 TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
5820 switch(*pFormat)
5822 case RPC_FC_BYTE:
5823 case RPC_FC_CHAR:
5824 case RPC_FC_SMALL:
5825 case RPC_FC_USMALL:
5826 safe_buffer_increment(pStubMsg, sizeof(UCHAR));
5827 pStubMsg->MemorySize += sizeof(UCHAR);
5828 return sizeof(UCHAR);
5829 case RPC_FC_WCHAR:
5830 case RPC_FC_SHORT:
5831 case RPC_FC_USHORT:
5832 safe_buffer_increment(pStubMsg, sizeof(USHORT));
5833 pStubMsg->MemorySize += sizeof(USHORT);
5834 return sizeof(USHORT);
5835 case RPC_FC_LONG:
5836 case RPC_FC_ULONG:
5837 case RPC_FC_ENUM32:
5838 safe_buffer_increment(pStubMsg, sizeof(ULONG));
5839 pStubMsg->MemorySize += sizeof(ULONG);
5840 return sizeof(ULONG);
5841 case RPC_FC_FLOAT:
5842 safe_buffer_increment(pStubMsg, sizeof(float));
5843 pStubMsg->MemorySize += sizeof(float);
5844 return sizeof(float);
5845 case RPC_FC_DOUBLE:
5846 safe_buffer_increment(pStubMsg, sizeof(double));
5847 pStubMsg->MemorySize += sizeof(double);
5848 return sizeof(double);
5849 case RPC_FC_HYPER:
5850 safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
5851 pStubMsg->MemorySize += sizeof(ULONGLONG);
5852 return sizeof(ULONGLONG);
5853 case RPC_FC_ERROR_STATUS_T:
5854 safe_buffer_increment(pStubMsg, sizeof(error_status_t));
5855 pStubMsg->MemorySize += sizeof(error_status_t);
5856 return sizeof(error_status_t);
5857 case RPC_FC_ENUM16:
5858 safe_buffer_increment(pStubMsg, sizeof(USHORT));
5859 pStubMsg->MemorySize += sizeof(UINT);
5860 return sizeof(UINT);
5861 case RPC_FC_IGNORE:
5862 pStubMsg->MemorySize += sizeof(void *);
5863 return sizeof(void *);
5864 default:
5865 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5866 return 0;
5870 /***********************************************************************
5871 * NdrBaseTypeFree [internal]
5873 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
5874 unsigned char *pMemory,
5875 PFORMAT_STRING pFormat)
5877 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5879 /* nothing to do */
5882 /***********************************************************************
5883 * NdrContextHandleBufferSize [internal]
5885 static void WINAPI NdrContextHandleBufferSize(
5886 PMIDL_STUB_MESSAGE pStubMsg,
5887 unsigned char *pMemory,
5888 PFORMAT_STRING pFormat)
5890 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5892 if (*pFormat != RPC_FC_BIND_CONTEXT)
5894 ERR("invalid format type %x\n", *pFormat);
5895 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5897 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5898 safe_buffer_length_increment(pStubMsg, cbNDRContext);
5901 /***********************************************************************
5902 * NdrContextHandleMarshall [internal]
5904 static unsigned char *WINAPI NdrContextHandleMarshall(
5905 PMIDL_STUB_MESSAGE pStubMsg,
5906 unsigned char *pMemory,
5907 PFORMAT_STRING pFormat)
5909 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5911 if (*pFormat != RPC_FC_BIND_CONTEXT)
5913 ERR("invalid format type %x\n", *pFormat);
5914 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5917 if (pFormat[1] & 0x80)
5918 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
5919 else
5920 NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE);
5922 return NULL;
5925 /***********************************************************************
5926 * NdrContextHandleUnmarshall [internal]
5928 static unsigned char *WINAPI NdrContextHandleUnmarshall(
5929 PMIDL_STUB_MESSAGE pStubMsg,
5930 unsigned char **ppMemory,
5931 PFORMAT_STRING pFormat,
5932 unsigned char fMustAlloc)
5934 if (*pFormat != RPC_FC_BIND_CONTEXT)
5936 ERR("invalid format type %x\n", *pFormat);
5937 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5940 **(NDR_CCONTEXT **)ppMemory = NULL;
5941 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
5943 return NULL;
5946 /***********************************************************************
5947 * NdrClientContextMarshall [RPCRT4.@]
5949 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5950 NDR_CCONTEXT ContextHandle,
5951 int fCheck)
5953 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
5955 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
5957 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5959 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
5960 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5961 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5964 /* FIXME: what does fCheck do? */
5965 NDRCContextMarshall(ContextHandle,
5966 pStubMsg->Buffer);
5968 pStubMsg->Buffer += cbNDRContext;
5971 /***********************************************************************
5972 * NdrClientContextUnmarshall [RPCRT4.@]
5974 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5975 NDR_CCONTEXT * pContextHandle,
5976 RPC_BINDING_HANDLE BindHandle)
5978 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
5980 ALIGN_POINTER(pStubMsg->Buffer, 4);
5982 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
5983 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5985 NDRCContextUnmarshall(pContextHandle,
5986 BindHandle,
5987 pStubMsg->Buffer,
5988 pStubMsg->RpcMsg->DataRepresentation);
5990 pStubMsg->Buffer += cbNDRContext;
5993 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5994 NDR_SCONTEXT ContextHandle,
5995 NDR_RUNDOWN RundownRoutine )
5997 FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
6000 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
6002 FIXME("(%p): stub\n", pStubMsg);
6003 return NULL;
6006 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
6007 unsigned char* pMemory,
6008 PFORMAT_STRING pFormat)
6010 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
6013 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
6014 PFORMAT_STRING pFormat)
6016 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
6017 return NULL;
6020 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6021 NDR_SCONTEXT ContextHandle,
6022 NDR_RUNDOWN RundownRoutine,
6023 PFORMAT_STRING pFormat)
6025 FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
6028 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6029 PFORMAT_STRING pFormat)
6031 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
6032 return NULL;
6035 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e
6037 typedef struct ndr_context_handle
6039 DWORD attributes;
6040 GUID uuid;
6041 } ndr_context_handle;
6043 struct context_handle_entry
6045 struct list entry;
6046 DWORD magic;
6047 RPC_BINDING_HANDLE handle;
6048 ndr_context_handle wire_data;
6051 static struct list context_handle_list = LIST_INIT(context_handle_list);
6053 static CRITICAL_SECTION ndr_context_cs;
6054 static CRITICAL_SECTION_DEBUG ndr_context_debug =
6056 0, 0, &ndr_context_cs,
6057 { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList },
6058 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") }
6060 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 };
6062 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
6064 struct context_handle_entry *che = (struct context_handle_entry*) CContext;
6066 if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
6067 return NULL;
6068 return che;
6071 static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid)
6073 struct context_handle_entry *che;
6074 LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry)
6075 if (IsEqualGUID(&che->wire_data.uuid, uuid))
6076 return che;
6077 return NULL;
6080 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
6082 struct context_handle_entry *che;
6083 RPC_BINDING_HANDLE handle = NULL;
6085 TRACE("%p\n", CContext);
6087 EnterCriticalSection(&ndr_context_cs);
6088 che = get_context_entry(CContext);
6089 if (che)
6090 handle = che->handle;
6091 LeaveCriticalSection(&ndr_context_cs);
6093 if (!handle)
6094 RpcRaiseException(ERROR_INVALID_HANDLE);
6095 return handle;
6098 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
6100 struct context_handle_entry *che;
6102 TRACE("%p %p\n", CContext, pBuff);
6104 if (CContext)
6106 EnterCriticalSection(&ndr_context_cs);
6107 che = get_context_entry(CContext);
6108 memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle));
6109 LeaveCriticalSection(&ndr_context_cs);
6111 else
6113 ndr_context_handle *wire_data = (ndr_context_handle *)pBuff;
6114 wire_data->attributes = 0;
6115 wire_data->uuid = GUID_NULL;
6119 /***********************************************************************
6120 * RpcSmDestroyClientContext [RPCRT4.@]
6122 RPC_STATUS WINAPI RpcSmDestroyClientContext(void **ContextHandle)
6124 RPC_STATUS status = RPC_X_SS_CONTEXT_MISMATCH;
6125 struct context_handle_entry *che = NULL;
6127 TRACE("(%p)\n", ContextHandle);
6129 EnterCriticalSection(&ndr_context_cs);
6130 che = get_context_entry(*ContextHandle);
6131 *ContextHandle = NULL;
6132 if (che)
6134 status = RPC_S_OK;
6135 list_remove(&che->entry);
6138 LeaveCriticalSection(&ndr_context_cs);
6140 if (che)
6142 RpcBindingFree(&che->handle);
6143 HeapFree(GetProcessHeap(), 0, che);
6146 return status;
6149 /***********************************************************************
6150 * RpcSsDestroyClientContext [RPCRT4.@]
6152 void WINAPI RpcSsDestroyClientContext(void **ContextHandle)
6154 RPC_STATUS status = RpcSmDestroyClientContext(ContextHandle);
6155 if (status != RPC_S_OK)
6156 RpcRaiseException(status);
6159 static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext,
6160 RPC_BINDING_HANDLE hBinding,
6161 const ndr_context_handle *chi)
6163 struct context_handle_entry *che = NULL;
6165 /* a null UUID means we should free the context handle */
6166 if (IsEqualGUID(&chi->uuid, &GUID_NULL))
6168 if (*CContext)
6170 che = get_context_entry(*CContext);
6171 if (!che)
6172 return ERROR_INVALID_HANDLE;
6173 list_remove(&che->entry);
6174 RpcBindingFree(&che->handle);
6175 HeapFree(GetProcessHeap(), 0, che);
6176 che = NULL;
6179 /* if there's no existing entry matching the GUID, allocate one */
6180 else if (!(che = context_entry_from_guid(&chi->uuid)))
6182 che = HeapAlloc(GetProcessHeap(), 0, sizeof *che);
6183 if (!che)
6184 return ERROR_NOT_ENOUGH_MEMORY;
6185 che->magic = NDR_CONTEXT_HANDLE_MAGIC;
6186 RpcBindingCopy(hBinding, &che->handle);
6187 list_add_tail(&context_handle_list, &che->entry);
6188 memcpy(&che->wire_data, chi, sizeof *chi);
6191 *CContext = che;
6193 return ERROR_SUCCESS;
6196 /***********************************************************************
6197 * NDRCContextUnmarshall [RPCRT4.@]
6199 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext,
6200 RPC_BINDING_HANDLE hBinding,
6201 void *pBuff, ULONG DataRepresentation)
6203 UINT r;
6205 TRACE("*%p=(%p) %p %p %08x\n",
6206 CContext, *CContext, hBinding, pBuff, DataRepresentation);
6208 EnterCriticalSection(&ndr_context_cs);
6209 r = ndr_update_context_handle(CContext, hBinding, pBuff);
6210 LeaveCriticalSection(&ndr_context_cs);
6211 if (r)
6212 RpcRaiseException(r);
6215 /***********************************************************************
6216 * NDRSContextMarshall [RPCRT4.@]
6218 void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext,
6219 void *pBuff,
6220 NDR_RUNDOWN userRunDownIn)
6222 FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn);
6225 /***********************************************************************
6226 * NDRSContextMarshallEx [RPCRT4.@]
6228 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding,
6229 NDR_SCONTEXT CContext,
6230 void *pBuff,
6231 NDR_RUNDOWN userRunDownIn)
6233 FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn);
6236 /***********************************************************************
6237 * NDRSContextMarshall2 [RPCRT4.@]
6239 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
6240 NDR_SCONTEXT CContext,
6241 void *pBuff,
6242 NDR_RUNDOWN userRunDownIn,
6243 void *CtxGuard, ULONG Flags)
6245 FIXME("(%p %p %p %p %p %u): stub\n",
6246 hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags);
6249 /***********************************************************************
6250 * NDRSContextUnmarshall [RPCRT4.@]
6252 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff,
6253 ULONG DataRepresentation)
6255 FIXME("(%p %08x): stub\n", pBuff, DataRepresentation);
6256 return NULL;
6259 /***********************************************************************
6260 * NDRSContextUnmarshallEx [RPCRT4.@]
6262 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding,
6263 void *pBuff,
6264 ULONG DataRepresentation)
6266 FIXME("(%p %p %08x): stub\n", hBinding, pBuff, DataRepresentation);
6267 return NULL;
6270 /***********************************************************************
6271 * NDRSContextUnmarshall2 [RPCRT4.@]
6273 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
6274 void *pBuff,
6275 ULONG DataRepresentation,
6276 void *CtxGuard, ULONG Flags)
6278 FIXME("(%p %p %08x %p %u): stub\n",
6279 hBinding, pBuff, DataRepresentation, CtxGuard, Flags);
6280 return NULL;