push(c) a4382c9fdde1e1539eee98911c9b80c4ea5af108
[wine/hacks.git] / dlls / rpcrt4 / ndr_marshall.c
blob2db0212f9f0b4649b93b348784ffe40bc7a3313f
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))
668 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
669 pStubMsg->Buffer, pStubMsg->BufferEnd, size);
670 RpcRaiseException(RPC_X_BAD_STUB_DATA);
672 if (p == pStubMsg->Buffer)
673 ERR("pointer is the same as the buffer\n");
674 memcpy(p, pStubMsg->Buffer, size);
675 pStubMsg->Buffer += size;
678 /* copies data to the buffer, checking that there is enough space to do so */
679 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
681 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
682 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
684 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
685 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
686 size);
687 RpcRaiseException(RPC_X_BAD_STUB_DATA);
689 memcpy(pStubMsg->Buffer, p, size);
690 pStubMsg->Buffer += size;
694 * NdrConformantString:
696 * What MS calls a ConformantString is, in DCE terminology,
697 * a Varying-Conformant String.
699 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
700 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
701 * into unmarshalled string)
702 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
703 * [
704 * data: CHARTYPE[maxlen]
705 * ]
706 * ], where CHARTYPE is the appropriate character type (specified externally)
710 /***********************************************************************
711 * NdrConformantStringMarshall [RPCRT4.@]
713 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
714 unsigned char *pszMessage, PFORMAT_STRING pFormat)
716 ULONG esize, size;
718 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
720 if (*pFormat == RPC_FC_C_CSTRING) {
721 TRACE("string=%s\n", debugstr_a((char*)pszMessage));
722 pStubMsg->ActualCount = strlen((char*)pszMessage)+1;
723 esize = 1;
725 else if (*pFormat == RPC_FC_C_WSTRING) {
726 TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
727 pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1;
728 esize = 2;
730 else {
731 ERR("Unhandled string type: %#x\n", *pFormat);
732 /* FIXME: raise an exception. */
733 return NULL;
736 if (pFormat[1] == RPC_FC_STRING_SIZED)
737 pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0);
738 else
739 pStubMsg->MaxCount = pStubMsg->ActualCount;
740 pStubMsg->Offset = 0;
741 WriteConformance(pStubMsg);
742 WriteVariance(pStubMsg);
744 size = safe_multiply(esize, pStubMsg->ActualCount);
745 safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */
747 /* success */
748 return NULL; /* is this always right? */
751 /***********************************************************************
752 * NdrConformantStringBufferSize [RPCRT4.@]
754 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
755 unsigned char* pMemory, PFORMAT_STRING pFormat)
757 ULONG esize;
759 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
761 SizeConformance(pStubMsg);
762 SizeVariance(pStubMsg);
764 if (*pFormat == RPC_FC_C_CSTRING) {
765 TRACE("string=%s\n", debugstr_a((char*)pMemory));
766 pStubMsg->ActualCount = strlen((char*)pMemory)+1;
767 esize = 1;
769 else if (*pFormat == RPC_FC_C_WSTRING) {
770 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
771 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1;
772 esize = 2;
774 else {
775 ERR("Unhandled string type: %#x\n", *pFormat);
776 /* FIXME: raise an exception */
777 return;
780 if (pFormat[1] == RPC_FC_STRING_SIZED)
781 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
782 else
783 pStubMsg->MaxCount = pStubMsg->ActualCount;
785 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
788 /************************************************************************
789 * NdrConformantStringMemorySize [RPCRT4.@]
791 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
792 PFORMAT_STRING pFormat )
794 ULONG rslt = 0;
796 FIXME("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
798 assert(pStubMsg && pFormat);
800 if (*pFormat == RPC_FC_C_CSTRING) {
801 rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
803 else if (*pFormat == RPC_FC_C_WSTRING) {
804 rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */
806 else {
807 ERR("Unhandled string type: %#x\n", *pFormat);
808 /* FIXME: raise an exception */
811 if (pFormat[1] != RPC_FC_PAD) {
812 FIXME("sized string format=%d\n", pFormat[1]);
815 TRACE(" --> %u\n", rslt);
816 return rslt;
819 /************************************************************************
820 * NdrConformantStringUnmarshall [RPCRT4.@]
822 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
823 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
825 ULONG bufsize, memsize, esize, i;
827 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
828 pStubMsg, *ppMemory, pFormat, fMustAlloc);
830 assert(pFormat && ppMemory && pStubMsg);
832 ReadConformance(pStubMsg, NULL);
833 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
835 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
837 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
838 pStubMsg->ActualCount, pStubMsg->MaxCount);
839 RpcRaiseException(RPC_S_INVALID_BOUND);
840 return NULL;
842 if (pStubMsg->Offset)
844 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
845 RpcRaiseException(RPC_S_INVALID_BOUND);
846 return NULL;
849 if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
850 else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
851 else {
852 ERR("Unhandled string type: %#x\n", *pFormat);
853 /* FIXME: raise an exception */
854 esize = 0;
857 memsize = safe_multiply(esize, pStubMsg->MaxCount);
858 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
860 /* strings must always have null terminating bytes */
861 if (bufsize < esize)
863 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
864 RpcRaiseException(RPC_S_INVALID_BOUND);
865 return NULL;
868 /* verify the buffer is safe to access */
869 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
870 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
872 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
873 pStubMsg->BufferEnd, pStubMsg->Buffer);
874 RpcRaiseException(RPC_X_BAD_STUB_DATA);
875 return NULL;
878 for (i = bufsize - esize; i < bufsize; i++)
879 if (pStubMsg->Buffer[i] != 0)
881 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
882 i, pStubMsg->Buffer[i]);
883 RpcRaiseException(RPC_S_INVALID_BOUND);
884 return NULL;
887 if (fMustAlloc)
888 *ppMemory = NdrAllocate(pStubMsg, memsize);
889 else
891 if (!pStubMsg->IsClient && !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
892 /* if the data in the RPC buffer is big enough, we just point straight
893 * into it */
894 *ppMemory = pStubMsg->Buffer;
895 else if (!*ppMemory)
896 *ppMemory = NdrAllocate(pStubMsg, memsize);
899 if (*ppMemory == pStubMsg->Buffer)
900 safe_buffer_increment(pStubMsg, bufsize);
901 else
902 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
904 if (*pFormat == RPC_FC_C_CSTRING) {
905 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
907 else if (*pFormat == RPC_FC_C_WSTRING) {
908 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
911 return NULL; /* FIXME: is this always right? */
914 /***********************************************************************
915 * NdrNonConformantStringMarshall [RPCRT4.@]
917 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
918 unsigned char *pMemory,
919 PFORMAT_STRING pFormat)
921 FIXME("stub\n");
922 return NULL;
925 /***********************************************************************
926 * NdrNonConformantStringUnmarshall [RPCRT4.@]
928 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
929 unsigned char **ppMemory,
930 PFORMAT_STRING pFormat,
931 unsigned char fMustAlloc)
933 FIXME("stub\n");
934 return NULL;
937 /***********************************************************************
938 * NdrNonConformantStringBufferSize [RPCRT4.@]
940 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
941 unsigned char *pMemory,
942 PFORMAT_STRING pFormat)
944 FIXME("stub\n");
947 /***********************************************************************
948 * NdrNonConformantStringMemorySize [RPCRT4.@]
950 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
951 PFORMAT_STRING pFormat)
953 FIXME("stub\n");
954 return 0;
957 static inline void dump_pointer_attr(unsigned char attr)
959 if (attr & RPC_FC_P_ALLOCALLNODES)
960 TRACE(" RPC_FC_P_ALLOCALLNODES");
961 if (attr & RPC_FC_P_DONTFREE)
962 TRACE(" RPC_FC_P_DONTFREE");
963 if (attr & RPC_FC_P_ONSTACK)
964 TRACE(" RPC_FC_P_ONSTACK");
965 if (attr & RPC_FC_P_SIMPLEPOINTER)
966 TRACE(" RPC_FC_P_SIMPLEPOINTER");
967 if (attr & RPC_FC_P_DEREF)
968 TRACE(" RPC_FC_P_DEREF");
969 TRACE("\n");
972 /***********************************************************************
973 * PointerMarshall [internal]
975 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
976 unsigned char *Buffer,
977 unsigned char *Pointer,
978 PFORMAT_STRING pFormat)
980 unsigned type = pFormat[0], attr = pFormat[1];
981 PFORMAT_STRING desc;
982 NDR_MARSHALL m;
983 ULONG pointer_id;
984 int pointer_needs_marshaling;
986 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
987 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
988 pFormat += 2;
989 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
990 else desc = pFormat + *(const SHORT*)pFormat;
992 switch (type) {
993 case RPC_FC_RP: /* ref pointer (always non-null) */
994 if (!Pointer)
996 ERR("NULL ref pointer is not allowed\n");
997 RpcRaiseException(RPC_X_NULL_REF_POINTER);
999 pointer_needs_marshaling = 1;
1000 break;
1001 case RPC_FC_UP: /* unique pointer */
1002 case RPC_FC_OP: /* object pointer - same as unique here */
1003 if (Pointer)
1004 pointer_needs_marshaling = 1;
1005 else
1006 pointer_needs_marshaling = 0;
1007 pointer_id = (ULONG)Pointer;
1008 TRACE("writing 0x%08x to buffer\n", pointer_id);
1009 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
1010 break;
1011 case RPC_FC_FP:
1012 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
1013 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
1014 TRACE("writing 0x%08x to buffer\n", pointer_id);
1015 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
1016 break;
1017 default:
1018 FIXME("unhandled ptr type=%02x\n", type);
1019 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1020 return;
1023 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
1025 if (pointer_needs_marshaling) {
1026 if (attr & RPC_FC_P_DEREF) {
1027 Pointer = *(unsigned char**)Pointer;
1028 TRACE("deref => %p\n", Pointer);
1030 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1031 if (m) m(pStubMsg, Pointer, desc);
1032 else FIXME("no marshaller for data type=%02x\n", *desc);
1035 STD_OVERFLOW_CHECK(pStubMsg);
1038 /***********************************************************************
1039 * PointerUnmarshall [internal]
1041 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1042 unsigned char *Buffer,
1043 unsigned char **pPointer,
1044 unsigned char *pSrcPointer,
1045 PFORMAT_STRING pFormat,
1046 unsigned char fMustAlloc)
1048 unsigned type = pFormat[0], attr = pFormat[1];
1049 PFORMAT_STRING desc;
1050 NDR_UNMARSHALL m;
1051 DWORD pointer_id = 0;
1052 int pointer_needs_unmarshaling;
1054 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
1055 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1056 pFormat += 2;
1057 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1058 else desc = pFormat + *(const SHORT*)pFormat;
1060 switch (type) {
1061 case RPC_FC_RP: /* ref pointer (always non-null) */
1062 pointer_needs_unmarshaling = 1;
1063 break;
1064 case RPC_FC_UP: /* unique pointer */
1065 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1066 TRACE("pointer_id is 0x%08x\n", pointer_id);
1067 if (pointer_id)
1068 pointer_needs_unmarshaling = 1;
1069 else {
1070 *pPointer = NULL;
1071 pointer_needs_unmarshaling = 0;
1073 break;
1074 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1075 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1076 TRACE("pointer_id is 0x%08x\n", pointer_id);
1077 if (!fMustAlloc && pSrcPointer)
1079 FIXME("free object pointer %p\n", pSrcPointer);
1080 fMustAlloc = TRUE;
1082 if (pointer_id)
1083 pointer_needs_unmarshaling = 1;
1084 else
1085 pointer_needs_unmarshaling = 0;
1086 break;
1087 case RPC_FC_FP:
1088 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1089 TRACE("pointer_id is 0x%08x\n", pointer_id);
1090 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
1091 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
1092 break;
1093 default:
1094 FIXME("unhandled ptr type=%02x\n", type);
1095 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1096 return;
1099 if (pointer_needs_unmarshaling) {
1100 unsigned char *base_ptr_val = *pPointer;
1101 unsigned char **current_ptr = pPointer;
1102 if (pStubMsg->IsClient) {
1103 TRACE("client\n");
1104 /* if we aren't forcing allocation of memory then try to use the existing
1105 * (source) pointer to unmarshall the data into so that [in,out]
1106 * parameters behave correctly. it doesn't matter if the parameter is
1107 * [out] only since in that case the pointer will be NULL. we force
1108 * allocation when the source pointer is NULL here instead of in the type
1109 * unmarshalling routine for the benefit of the deref code below */
1110 if (!fMustAlloc) {
1111 if (pSrcPointer) {
1112 TRACE("setting *pPointer to %p\n", pSrcPointer);
1113 *pPointer = base_ptr_val = pSrcPointer;
1114 } else
1115 fMustAlloc = TRUE;
1117 } else {
1118 TRACE("server\n");
1119 /* the memory in a stub is never initialised, so we have to work out here
1120 * whether we have to initialise it so we can use the optimisation of
1121 * setting the pointer to the buffer, if possible, or set fMustAlloc to
1122 * TRUE. */
1123 if (attr & RPC_FC_P_DEREF) {
1124 fMustAlloc = TRUE;
1125 } else {
1126 base_ptr_val = NULL;
1127 *current_ptr = NULL;
1131 if (attr & RPC_FC_P_ALLOCALLNODES)
1132 FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
1134 if (attr & RPC_FC_P_DEREF) {
1135 if (fMustAlloc) {
1136 base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
1137 *pPointer = base_ptr_val;
1138 current_ptr = (unsigned char **)base_ptr_val;
1139 } else
1140 current_ptr = *(unsigned char***)current_ptr;
1141 TRACE("deref => %p\n", current_ptr);
1142 if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
1144 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1145 if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
1146 else FIXME("no unmarshaller for data type=%02x\n", *desc);
1148 if (type == RPC_FC_FP)
1149 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
1150 base_ptr_val);
1153 TRACE("pointer=%p\n", *pPointer);
1156 /***********************************************************************
1157 * PointerBufferSize [internal]
1159 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1160 unsigned char *Pointer,
1161 PFORMAT_STRING pFormat)
1163 unsigned type = pFormat[0], attr = pFormat[1];
1164 PFORMAT_STRING desc;
1165 NDR_BUFFERSIZE m;
1166 int pointer_needs_sizing;
1167 ULONG pointer_id;
1169 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1170 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1171 pFormat += 2;
1172 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1173 else desc = pFormat + *(const SHORT*)pFormat;
1175 switch (type) {
1176 case RPC_FC_RP: /* ref pointer (always non-null) */
1177 if (!Pointer)
1179 ERR("NULL ref pointer is not allowed\n");
1180 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1182 break;
1183 case RPC_FC_OP:
1184 case RPC_FC_UP:
1185 /* NULL pointer has no further representation */
1186 if (!Pointer)
1187 return;
1188 break;
1189 case RPC_FC_FP:
1190 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1191 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1192 if (!pointer_needs_sizing)
1193 return;
1194 break;
1195 default:
1196 FIXME("unhandled ptr type=%02x\n", type);
1197 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1198 return;
1201 if (attr & RPC_FC_P_DEREF) {
1202 Pointer = *(unsigned char**)Pointer;
1203 TRACE("deref => %p\n", Pointer);
1206 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1207 if (m) m(pStubMsg, Pointer, desc);
1208 else FIXME("no buffersizer for data type=%02x\n", *desc);
1211 /***********************************************************************
1212 * PointerMemorySize [internal]
1214 static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1215 unsigned char *Buffer,
1216 PFORMAT_STRING pFormat)
1218 unsigned type = pFormat[0], attr = pFormat[1];
1219 PFORMAT_STRING desc;
1220 NDR_MEMORYSIZE m;
1221 DWORD pointer_id = 0;
1222 int pointer_needs_sizing;
1224 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1225 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1226 pFormat += 2;
1227 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1228 else desc = pFormat + *(const SHORT*)pFormat;
1230 switch (type) {
1231 case RPC_FC_RP: /* ref pointer (always non-null) */
1232 pointer_needs_sizing = 1;
1233 break;
1234 case RPC_FC_UP: /* unique pointer */
1235 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1236 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1237 TRACE("pointer_id is 0x%08x\n", pointer_id);
1238 if (pointer_id)
1239 pointer_needs_sizing = 1;
1240 else
1241 pointer_needs_sizing = 0;
1242 break;
1243 case RPC_FC_FP:
1245 void *pointer;
1246 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1247 TRACE("pointer_id is 0x%08x\n", pointer_id);
1248 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1249 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1250 break;
1252 default:
1253 FIXME("unhandled ptr type=%02x\n", type);
1254 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1255 return 0;
1258 if (attr & RPC_FC_P_DEREF) {
1259 TRACE("deref\n");
1262 if (pointer_needs_sizing) {
1263 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1264 if (m) m(pStubMsg, desc);
1265 else FIXME("no memorysizer for data type=%02x\n", *desc);
1268 return pStubMsg->MemorySize;
1271 /***********************************************************************
1272 * PointerFree [internal]
1274 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1275 unsigned char *Pointer,
1276 PFORMAT_STRING pFormat)
1278 unsigned type = pFormat[0], attr = pFormat[1];
1279 PFORMAT_STRING desc;
1280 NDR_FREE m;
1281 unsigned char *current_pointer = Pointer;
1283 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1284 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1285 if (attr & RPC_FC_P_DONTFREE) return;
1286 pFormat += 2;
1287 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1288 else desc = pFormat + *(const SHORT*)pFormat;
1290 if (!Pointer) return;
1292 if (type == RPC_FC_FP) {
1293 int pointer_needs_freeing = NdrFullPointerFree(
1294 pStubMsg->FullPtrXlatTables, Pointer);
1295 if (!pointer_needs_freeing)
1296 return;
1299 if (attr & RPC_FC_P_DEREF) {
1300 current_pointer = *(unsigned char**)Pointer;
1301 TRACE("deref => %p\n", current_pointer);
1304 m = NdrFreer[*desc & NDR_TABLE_MASK];
1305 if (m) m(pStubMsg, current_pointer, desc);
1307 /* this check stops us from trying to free buffer memory. we don't have to
1308 * worry about clients, since they won't call this function.
1309 * we don't have to check for the buffer being reallocated because
1310 * BufferStart and BufferEnd won't be reset when allocating memory for
1311 * sending the response. we don't have to check for the new buffer here as
1312 * it won't be used a type memory, only for buffer memory */
1313 if (Pointer >= (unsigned char *)pStubMsg->BufferStart &&
1314 Pointer < (unsigned char *)pStubMsg->BufferEnd)
1315 goto notfree;
1317 if (attr & RPC_FC_P_ONSTACK) {
1318 TRACE("not freeing stack ptr %p\n", Pointer);
1319 return;
1321 TRACE("freeing %p\n", Pointer);
1322 NdrFree(pStubMsg, Pointer);
1323 return;
1324 notfree:
1325 TRACE("not freeing %p\n", Pointer);
1328 /***********************************************************************
1329 * EmbeddedPointerMarshall
1331 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1332 unsigned char *pMemory,
1333 PFORMAT_STRING pFormat)
1335 unsigned char *Mark = pStubMsg->BufferMark;
1336 unsigned rep, count, stride;
1337 unsigned i;
1338 unsigned char *saved_buffer = NULL;
1340 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1342 if (*pFormat != RPC_FC_PP) return NULL;
1343 pFormat += 2;
1345 if (pStubMsg->PointerBufferMark)
1347 saved_buffer = pStubMsg->Buffer;
1348 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1349 pStubMsg->PointerBufferMark = NULL;
1352 while (pFormat[0] != RPC_FC_END) {
1353 switch (pFormat[0]) {
1354 default:
1355 FIXME("unknown repeat type %d\n", pFormat[0]);
1356 case RPC_FC_NO_REPEAT:
1357 rep = 1;
1358 stride = 0;
1359 count = 1;
1360 pFormat += 2;
1361 break;
1362 case RPC_FC_FIXED_REPEAT:
1363 rep = *(const WORD*)&pFormat[2];
1364 stride = *(const WORD*)&pFormat[4];
1365 count = *(const WORD*)&pFormat[8];
1366 pFormat += 10;
1367 break;
1368 case RPC_FC_VARIABLE_REPEAT:
1369 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1370 stride = *(const WORD*)&pFormat[2];
1371 count = *(const WORD*)&pFormat[6];
1372 pFormat += 8;
1373 break;
1375 for (i = 0; i < rep; i++) {
1376 PFORMAT_STRING info = pFormat;
1377 unsigned char *membase = pMemory + (i * stride);
1378 unsigned char *bufbase = Mark + (i * stride);
1379 unsigned u;
1381 for (u=0; u<count; u++,info+=8) {
1382 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1383 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1384 unsigned char *saved_memory = pStubMsg->Memory;
1386 pStubMsg->Memory = pMemory;
1387 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1388 pStubMsg->Memory = saved_memory;
1391 pFormat += 8 * count;
1394 if (saved_buffer)
1396 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1397 pStubMsg->Buffer = saved_buffer;
1400 STD_OVERFLOW_CHECK(pStubMsg);
1402 return NULL;
1405 /***********************************************************************
1406 * EmbeddedPointerUnmarshall
1408 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1409 unsigned char *pDstMemoryPtrs,
1410 unsigned char *pSrcMemoryPtrs,
1411 PFORMAT_STRING pFormat,
1412 unsigned char fMustAlloc)
1414 unsigned char *Mark = pStubMsg->BufferMark;
1415 unsigned rep, count, stride;
1416 unsigned i;
1417 unsigned char *saved_buffer = NULL;
1419 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstMemoryPtrs, pSrcMemoryPtrs, pFormat, fMustAlloc);
1421 if (*pFormat != RPC_FC_PP) return NULL;
1422 pFormat += 2;
1424 if (pStubMsg->PointerBufferMark)
1426 saved_buffer = pStubMsg->Buffer;
1427 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1428 pStubMsg->PointerBufferMark = NULL;
1431 while (pFormat[0] != RPC_FC_END) {
1432 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1433 switch (pFormat[0]) {
1434 default:
1435 FIXME("unknown repeat type %d\n", pFormat[0]);
1436 case RPC_FC_NO_REPEAT:
1437 rep = 1;
1438 stride = 0;
1439 count = 1;
1440 pFormat += 2;
1441 break;
1442 case RPC_FC_FIXED_REPEAT:
1443 rep = *(const WORD*)&pFormat[2];
1444 stride = *(const WORD*)&pFormat[4];
1445 count = *(const WORD*)&pFormat[8];
1446 pFormat += 10;
1447 break;
1448 case RPC_FC_VARIABLE_REPEAT:
1449 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1450 stride = *(const WORD*)&pFormat[2];
1451 count = *(const WORD*)&pFormat[6];
1452 pFormat += 8;
1453 break;
1455 for (i = 0; i < rep; i++) {
1456 PFORMAT_STRING info = pFormat;
1457 unsigned char *memdstbase = pDstMemoryPtrs + (i * stride);
1458 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1459 unsigned char *bufbase = Mark + (i * stride);
1460 unsigned u;
1462 for (u=0; u<count; u++,info+=8) {
1463 unsigned char **memdstptr = (unsigned char **)(memdstbase + *(const SHORT*)&info[0]);
1464 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1465 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1466 PointerUnmarshall(pStubMsg, bufptr, memdstptr, *memsrcptr, info+4, fMustAlloc);
1469 pFormat += 8 * count;
1472 if (saved_buffer)
1474 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1475 pStubMsg->Buffer = saved_buffer;
1478 return NULL;
1481 /***********************************************************************
1482 * EmbeddedPointerBufferSize
1484 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1485 unsigned char *pMemory,
1486 PFORMAT_STRING pFormat)
1488 unsigned rep, count, stride;
1489 unsigned i;
1490 ULONG saved_buffer_length = 0;
1492 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1494 if (pStubMsg->IgnoreEmbeddedPointers) return;
1496 if (*pFormat != RPC_FC_PP) return;
1497 pFormat += 2;
1499 if (pStubMsg->PointerLength)
1501 saved_buffer_length = pStubMsg->BufferLength;
1502 pStubMsg->BufferLength = pStubMsg->PointerLength;
1503 pStubMsg->PointerLength = 0;
1506 while (pFormat[0] != RPC_FC_END) {
1507 switch (pFormat[0]) {
1508 default:
1509 FIXME("unknown repeat type %d\n", pFormat[0]);
1510 case RPC_FC_NO_REPEAT:
1511 rep = 1;
1512 stride = 0;
1513 count = 1;
1514 pFormat += 2;
1515 break;
1516 case RPC_FC_FIXED_REPEAT:
1517 rep = *(const WORD*)&pFormat[2];
1518 stride = *(const WORD*)&pFormat[4];
1519 count = *(const WORD*)&pFormat[8];
1520 pFormat += 10;
1521 break;
1522 case RPC_FC_VARIABLE_REPEAT:
1523 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1524 stride = *(const WORD*)&pFormat[2];
1525 count = *(const WORD*)&pFormat[6];
1526 pFormat += 8;
1527 break;
1529 for (i = 0; i < rep; i++) {
1530 PFORMAT_STRING info = pFormat;
1531 unsigned char *membase = pMemory + (i * stride);
1532 unsigned u;
1534 for (u=0; u<count; u++,info+=8) {
1535 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1536 unsigned char *saved_memory = pStubMsg->Memory;
1538 pStubMsg->Memory = pMemory;
1539 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1540 pStubMsg->Memory = saved_memory;
1543 pFormat += 8 * count;
1546 if (saved_buffer_length)
1548 pStubMsg->PointerLength = pStubMsg->BufferLength;
1549 pStubMsg->BufferLength = saved_buffer_length;
1553 /***********************************************************************
1554 * EmbeddedPointerMemorySize [internal]
1556 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1557 PFORMAT_STRING pFormat)
1559 unsigned char *Mark = pStubMsg->BufferMark;
1560 unsigned rep, count, stride;
1561 unsigned i;
1562 unsigned char *saved_buffer = NULL;
1564 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1566 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1568 if (pStubMsg->PointerBufferMark)
1570 saved_buffer = pStubMsg->Buffer;
1571 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1572 pStubMsg->PointerBufferMark = NULL;
1575 if (*pFormat != RPC_FC_PP) return 0;
1576 pFormat += 2;
1578 while (pFormat[0] != RPC_FC_END) {
1579 switch (pFormat[0]) {
1580 default:
1581 FIXME("unknown repeat type %d\n", pFormat[0]);
1582 case RPC_FC_NO_REPEAT:
1583 rep = 1;
1584 stride = 0;
1585 count = 1;
1586 pFormat += 2;
1587 break;
1588 case RPC_FC_FIXED_REPEAT:
1589 rep = *(const WORD*)&pFormat[2];
1590 stride = *(const WORD*)&pFormat[4];
1591 count = *(const WORD*)&pFormat[8];
1592 pFormat += 10;
1593 break;
1594 case RPC_FC_VARIABLE_REPEAT:
1595 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1596 stride = *(const WORD*)&pFormat[2];
1597 count = *(const WORD*)&pFormat[6];
1598 pFormat += 8;
1599 break;
1601 for (i = 0; i < rep; i++) {
1602 PFORMAT_STRING info = pFormat;
1603 unsigned char *bufbase = Mark + (i * stride);
1604 unsigned u;
1605 for (u=0; u<count; u++,info+=8) {
1606 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1607 PointerMemorySize(pStubMsg, bufptr, info+4);
1610 pFormat += 8 * count;
1613 if (saved_buffer)
1615 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1616 pStubMsg->Buffer = saved_buffer;
1619 return 0;
1622 /***********************************************************************
1623 * EmbeddedPointerFree [internal]
1625 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1626 unsigned char *pMemory,
1627 PFORMAT_STRING pFormat)
1629 unsigned rep, count, stride;
1630 unsigned i;
1632 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1633 if (*pFormat != RPC_FC_PP) return;
1634 pFormat += 2;
1636 while (pFormat[0] != RPC_FC_END) {
1637 switch (pFormat[0]) {
1638 default:
1639 FIXME("unknown repeat type %d\n", pFormat[0]);
1640 case RPC_FC_NO_REPEAT:
1641 rep = 1;
1642 stride = 0;
1643 count = 1;
1644 pFormat += 2;
1645 break;
1646 case RPC_FC_FIXED_REPEAT:
1647 rep = *(const WORD*)&pFormat[2];
1648 stride = *(const WORD*)&pFormat[4];
1649 count = *(const WORD*)&pFormat[8];
1650 pFormat += 10;
1651 break;
1652 case RPC_FC_VARIABLE_REPEAT:
1653 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1654 stride = *(const WORD*)&pFormat[2];
1655 count = *(const WORD*)&pFormat[6];
1656 pFormat += 8;
1657 break;
1659 for (i = 0; i < rep; i++) {
1660 PFORMAT_STRING info = pFormat;
1661 unsigned char *membase = pMemory + (i * stride);
1662 unsigned u;
1664 for (u=0; u<count; u++,info+=8) {
1665 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1666 unsigned char *saved_memory = pStubMsg->Memory;
1668 pStubMsg->Memory = pMemory;
1669 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1670 pStubMsg->Memory = saved_memory;
1673 pFormat += 8 * count;
1677 /***********************************************************************
1678 * NdrPointerMarshall [RPCRT4.@]
1680 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1681 unsigned char *pMemory,
1682 PFORMAT_STRING pFormat)
1684 unsigned char *Buffer;
1686 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1688 /* incremement the buffer here instead of in PointerMarshall,
1689 * as that is used by embedded pointers which already handle the incrementing
1690 * the buffer, and shouldn't write any additional pointer data to the wire */
1691 if (*pFormat != RPC_FC_RP)
1693 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1694 Buffer = pStubMsg->Buffer;
1695 safe_buffer_increment(pStubMsg, 4);
1697 else
1698 Buffer = pStubMsg->Buffer;
1700 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1702 return NULL;
1705 /***********************************************************************
1706 * NdrPointerUnmarshall [RPCRT4.@]
1708 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1709 unsigned char **ppMemory,
1710 PFORMAT_STRING pFormat,
1711 unsigned char fMustAlloc)
1713 unsigned char *Buffer;
1715 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1717 /* incremement the buffer here instead of in PointerUnmarshall,
1718 * as that is used by embedded pointers which already handle the incrementing
1719 * the buffer, and shouldn't read any additional pointer data from the
1720 * buffer */
1721 if (*pFormat != RPC_FC_RP)
1723 ALIGN_POINTER(pStubMsg->Buffer, 4);
1724 Buffer = pStubMsg->Buffer;
1725 safe_buffer_increment(pStubMsg, 4);
1727 else
1728 Buffer = pStubMsg->Buffer;
1730 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1732 return NULL;
1735 /***********************************************************************
1736 * NdrPointerBufferSize [RPCRT4.@]
1738 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1739 unsigned char *pMemory,
1740 PFORMAT_STRING pFormat)
1742 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1744 /* incremement the buffer length here instead of in PointerBufferSize,
1745 * as that is used by embedded pointers which already handle the buffer
1746 * length, and shouldn't write anything more to the wire */
1747 if (*pFormat != RPC_FC_RP)
1749 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1750 safe_buffer_length_increment(pStubMsg, 4);
1753 PointerBufferSize(pStubMsg, pMemory, pFormat);
1756 /***********************************************************************
1757 * NdrPointerMemorySize [RPCRT4.@]
1759 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1760 PFORMAT_STRING pFormat)
1762 /* unsigned size = *(LPWORD)(pFormat+2); */
1763 FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1764 PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1765 return 0;
1768 /***********************************************************************
1769 * NdrPointerFree [RPCRT4.@]
1771 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1772 unsigned char *pMemory,
1773 PFORMAT_STRING pFormat)
1775 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1776 PointerFree(pStubMsg, pMemory, pFormat);
1779 /***********************************************************************
1780 * NdrSimpleTypeMarshall [RPCRT4.@]
1782 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1783 unsigned char FormatChar )
1785 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1788 /***********************************************************************
1789 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1791 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1792 unsigned char FormatChar )
1794 NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0);
1797 /***********************************************************************
1798 * NdrSimpleStructMarshall [RPCRT4.@]
1800 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1801 unsigned char *pMemory,
1802 PFORMAT_STRING pFormat)
1804 unsigned size = *(const WORD*)(pFormat+2);
1805 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1807 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
1809 pStubMsg->BufferMark = pStubMsg->Buffer;
1810 safe_copy_to_buffer(pStubMsg, pMemory, size);
1812 if (pFormat[0] != RPC_FC_STRUCT)
1813 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1815 return NULL;
1818 /***********************************************************************
1819 * NdrSimpleStructUnmarshall [RPCRT4.@]
1821 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1822 unsigned char **ppMemory,
1823 PFORMAT_STRING pFormat,
1824 unsigned char fMustAlloc)
1826 unsigned size = *(const WORD*)(pFormat+2);
1827 unsigned char *saved_buffer;
1828 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1830 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1832 if (fMustAlloc)
1833 *ppMemory = NdrAllocate(pStubMsg, size);
1834 else
1836 if (!pStubMsg->IsClient && !*ppMemory)
1837 /* for servers, we just point straight into the RPC buffer */
1838 *ppMemory = pStubMsg->Buffer;
1841 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1842 safe_buffer_increment(pStubMsg, size);
1843 if (pFormat[0] == RPC_FC_PSTRUCT)
1844 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1846 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1847 if (*ppMemory != saved_buffer)
1848 memcpy(*ppMemory, saved_buffer, size);
1850 return NULL;
1853 /***********************************************************************
1854 * NdrSimpleStructBufferSize [RPCRT4.@]
1856 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1857 unsigned char *pMemory,
1858 PFORMAT_STRING pFormat)
1860 unsigned size = *(const WORD*)(pFormat+2);
1861 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1863 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1865 safe_buffer_length_increment(pStubMsg, size);
1866 if (pFormat[0] != RPC_FC_STRUCT)
1867 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1870 /***********************************************************************
1871 * NdrSimpleStructMemorySize [RPCRT4.@]
1873 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1874 PFORMAT_STRING pFormat)
1876 unsigned short size = *(const WORD *)(pFormat+2);
1878 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1880 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1881 pStubMsg->MemorySize += size;
1882 safe_buffer_increment(pStubMsg, size);
1884 if (pFormat[0] != RPC_FC_STRUCT)
1885 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1886 return pStubMsg->MemorySize;
1889 /***********************************************************************
1890 * NdrSimpleStructFree [RPCRT4.@]
1892 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1893 unsigned char *pMemory,
1894 PFORMAT_STRING pFormat)
1896 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1897 if (pFormat[0] != RPC_FC_STRUCT)
1898 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1902 static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg,
1903 PFORMAT_STRING pFormat)
1905 switch (*pFormat) {
1906 case RPC_FC_STRUCT:
1907 case RPC_FC_PSTRUCT:
1908 case RPC_FC_CSTRUCT:
1909 case RPC_FC_BOGUS_STRUCT:
1910 case RPC_FC_SMFARRAY:
1911 case RPC_FC_SMVARRAY:
1912 return *(const WORD*)&pFormat[2];
1913 case RPC_FC_USER_MARSHAL:
1914 return *(const WORD*)&pFormat[4];
1915 case RPC_FC_NON_ENCAPSULATED_UNION:
1916 pFormat += 2;
1917 if (pStubMsg->fHasNewCorrDesc)
1918 pFormat += 6;
1919 else
1920 pFormat += 4;
1922 pFormat += *(const SHORT*)pFormat;
1923 return *(const SHORT*)pFormat;
1924 case RPC_FC_IP:
1925 return sizeof(void *);
1926 default:
1927 FIXME("unhandled embedded type %02x\n", *pFormat);
1929 return 0;
1933 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1934 PFORMAT_STRING pFormat)
1936 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1938 if (!m)
1940 FIXME("no memorysizer for data type=%02x\n", *pFormat);
1941 return 0;
1944 return m(pStubMsg, pFormat);
1948 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1949 unsigned char *pMemory,
1950 PFORMAT_STRING pFormat,
1951 PFORMAT_STRING pPointer)
1953 PFORMAT_STRING desc;
1954 NDR_MARSHALL m;
1955 unsigned long size;
1957 while (*pFormat != RPC_FC_END) {
1958 switch (*pFormat) {
1959 case RPC_FC_BYTE:
1960 case RPC_FC_CHAR:
1961 case RPC_FC_SMALL:
1962 case RPC_FC_USMALL:
1963 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
1964 safe_copy_to_buffer(pStubMsg, pMemory, 1);
1965 pMemory += 1;
1966 break;
1967 case RPC_FC_WCHAR:
1968 case RPC_FC_SHORT:
1969 case RPC_FC_USHORT:
1970 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1971 safe_copy_to_buffer(pStubMsg, pMemory, 2);
1972 pMemory += 2;
1973 break;
1974 case RPC_FC_LONG:
1975 case RPC_FC_ULONG:
1976 case RPC_FC_ENUM32:
1977 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
1978 safe_copy_to_buffer(pStubMsg, pMemory, 4);
1979 pMemory += 4;
1980 break;
1981 case RPC_FC_HYPER:
1982 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
1983 safe_copy_to_buffer(pStubMsg, pMemory, 8);
1984 pMemory += 8;
1985 break;
1986 case RPC_FC_POINTER:
1988 unsigned char *saved_buffer;
1989 int pointer_buffer_mark_set = 0;
1990 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1991 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
1992 saved_buffer = pStubMsg->Buffer;
1993 if (pStubMsg->PointerBufferMark)
1995 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1996 pStubMsg->PointerBufferMark = NULL;
1997 pointer_buffer_mark_set = 1;
1999 else
2000 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2001 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2002 if (pointer_buffer_mark_set)
2004 STD_OVERFLOW_CHECK(pStubMsg);
2005 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2006 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
2008 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
2009 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
2010 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2012 pStubMsg->Buffer = saved_buffer + 4;
2014 pPointer += 4;
2015 pMemory += 4;
2016 break;
2018 case RPC_FC_ALIGNM4:
2019 ALIGN_POINTER(pMemory, 4);
2020 break;
2021 case RPC_FC_ALIGNM8:
2022 ALIGN_POINTER(pMemory, 8);
2023 break;
2024 case RPC_FC_STRUCTPAD1:
2025 case RPC_FC_STRUCTPAD2:
2026 case RPC_FC_STRUCTPAD3:
2027 case RPC_FC_STRUCTPAD4:
2028 case RPC_FC_STRUCTPAD5:
2029 case RPC_FC_STRUCTPAD6:
2030 case RPC_FC_STRUCTPAD7:
2031 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2032 break;
2033 case RPC_FC_EMBEDDED_COMPLEX:
2034 pMemory += pFormat[1];
2035 pFormat += 2;
2036 desc = pFormat + *(const SHORT*)pFormat;
2037 size = EmbeddedComplexSize(pStubMsg, desc);
2038 TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
2039 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2040 if (m)
2042 /* for some reason interface pointers aren't generated as
2043 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2044 * they still need the derefencing treatment that pointers are
2045 * given */
2046 if (*desc == RPC_FC_IP)
2047 m(pStubMsg, *(unsigned char **)pMemory, desc);
2048 else
2049 m(pStubMsg, pMemory, desc);
2051 else FIXME("no marshaller for embedded type %02x\n", *desc);
2052 pMemory += size;
2053 pFormat += 2;
2054 continue;
2055 case RPC_FC_PAD:
2056 break;
2057 default:
2058 FIXME("unhandled format 0x%02x\n", *pFormat);
2060 pFormat++;
2063 return pMemory;
2066 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2067 unsigned char *pMemory,
2068 PFORMAT_STRING pFormat,
2069 PFORMAT_STRING pPointer)
2071 PFORMAT_STRING desc;
2072 NDR_UNMARSHALL m;
2073 unsigned long size;
2075 while (*pFormat != RPC_FC_END) {
2076 switch (*pFormat) {
2077 case RPC_FC_BYTE:
2078 case RPC_FC_CHAR:
2079 case RPC_FC_SMALL:
2080 case RPC_FC_USMALL:
2081 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2082 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2083 pMemory += 1;
2084 break;
2085 case RPC_FC_WCHAR:
2086 case RPC_FC_SHORT:
2087 case RPC_FC_USHORT:
2088 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2089 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2090 pMemory += 2;
2091 break;
2092 case RPC_FC_LONG:
2093 case RPC_FC_ULONG:
2094 case RPC_FC_ENUM32:
2095 safe_copy_from_buffer(pStubMsg, pMemory, 4);
2096 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2097 pMemory += 4;
2098 break;
2099 case RPC_FC_HYPER:
2100 safe_copy_from_buffer(pStubMsg, pMemory, 8);
2101 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2102 pMemory += 8;
2103 break;
2104 case RPC_FC_POINTER:
2106 unsigned char *saved_buffer;
2107 int pointer_buffer_mark_set = 0;
2108 TRACE("pointer => %p\n", pMemory);
2109 ALIGN_POINTER(pStubMsg->Buffer, 4);
2110 saved_buffer = pStubMsg->Buffer;
2111 if (pStubMsg->PointerBufferMark)
2113 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2114 pStubMsg->PointerBufferMark = NULL;
2115 pointer_buffer_mark_set = 1;
2117 else
2118 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2120 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, TRUE);
2121 if (pointer_buffer_mark_set)
2123 STD_OVERFLOW_CHECK(pStubMsg);
2124 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2125 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
2127 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
2128 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
2129 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2131 pStubMsg->Buffer = saved_buffer + 4;
2133 pPointer += 4;
2134 pMemory += 4;
2135 break;
2137 case RPC_FC_ALIGNM4:
2138 ALIGN_POINTER_CLEAR(pMemory, 4);
2139 break;
2140 case RPC_FC_ALIGNM8:
2141 ALIGN_POINTER_CLEAR(pMemory, 8);
2142 break;
2143 case RPC_FC_STRUCTPAD1:
2144 case RPC_FC_STRUCTPAD2:
2145 case RPC_FC_STRUCTPAD3:
2146 case RPC_FC_STRUCTPAD4:
2147 case RPC_FC_STRUCTPAD5:
2148 case RPC_FC_STRUCTPAD6:
2149 case RPC_FC_STRUCTPAD7:
2150 memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2151 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2152 break;
2153 case RPC_FC_EMBEDDED_COMPLEX:
2154 pMemory += pFormat[1];
2155 pFormat += 2;
2156 desc = pFormat + *(const SHORT*)pFormat;
2157 size = EmbeddedComplexSize(pStubMsg, desc);
2158 TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
2159 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2160 memset(pMemory, 0, size); /* just in case */
2161 if (m)
2163 /* for some reason interface pointers aren't generated as
2164 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2165 * they still need the derefencing treatment that pointers are
2166 * given */
2167 if (*desc == RPC_FC_IP)
2168 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2169 else
2170 m(pStubMsg, &pMemory, desc, FALSE);
2172 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2173 pMemory += size;
2174 pFormat += 2;
2175 continue;
2176 case RPC_FC_PAD:
2177 break;
2178 default:
2179 FIXME("unhandled format %d\n", *pFormat);
2181 pFormat++;
2184 return pMemory;
2187 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2188 unsigned char *pMemory,
2189 PFORMAT_STRING pFormat,
2190 PFORMAT_STRING pPointer)
2192 PFORMAT_STRING desc;
2193 NDR_BUFFERSIZE m;
2194 unsigned long size;
2196 while (*pFormat != RPC_FC_END) {
2197 switch (*pFormat) {
2198 case RPC_FC_BYTE:
2199 case RPC_FC_CHAR:
2200 case RPC_FC_SMALL:
2201 case RPC_FC_USMALL:
2202 safe_buffer_length_increment(pStubMsg, 1);
2203 pMemory += 1;
2204 break;
2205 case RPC_FC_WCHAR:
2206 case RPC_FC_SHORT:
2207 case RPC_FC_USHORT:
2208 safe_buffer_length_increment(pStubMsg, 2);
2209 pMemory += 2;
2210 break;
2211 case RPC_FC_LONG:
2212 case RPC_FC_ULONG:
2213 case RPC_FC_ENUM32:
2214 safe_buffer_length_increment(pStubMsg, 4);
2215 pMemory += 4;
2216 break;
2217 case RPC_FC_HYPER:
2218 safe_buffer_length_increment(pStubMsg, 8);
2219 pMemory += 8;
2220 break;
2221 case RPC_FC_POINTER:
2222 if (!pStubMsg->IgnoreEmbeddedPointers)
2224 int saved_buffer_length = pStubMsg->BufferLength;
2225 pStubMsg->BufferLength = pStubMsg->PointerLength;
2226 pStubMsg->PointerLength = 0;
2227 if(!pStubMsg->BufferLength)
2228 ERR("BufferLength == 0??\n");
2229 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2230 pStubMsg->PointerLength = pStubMsg->BufferLength;
2231 pStubMsg->BufferLength = saved_buffer_length;
2233 safe_buffer_length_increment(pStubMsg, 4);
2234 pPointer += 4;
2235 pMemory += 4;
2236 break;
2237 case RPC_FC_ALIGNM4:
2238 ALIGN_POINTER(pMemory, 4);
2239 break;
2240 case RPC_FC_ALIGNM8:
2241 ALIGN_POINTER(pMemory, 8);
2242 break;
2243 case RPC_FC_STRUCTPAD1:
2244 case RPC_FC_STRUCTPAD2:
2245 case RPC_FC_STRUCTPAD3:
2246 case RPC_FC_STRUCTPAD4:
2247 case RPC_FC_STRUCTPAD5:
2248 case RPC_FC_STRUCTPAD6:
2249 case RPC_FC_STRUCTPAD7:
2250 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2251 break;
2252 case RPC_FC_EMBEDDED_COMPLEX:
2253 pMemory += pFormat[1];
2254 pFormat += 2;
2255 desc = pFormat + *(const SHORT*)pFormat;
2256 size = EmbeddedComplexSize(pStubMsg, desc);
2257 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2258 if (m)
2260 /* for some reason interface pointers aren't generated as
2261 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2262 * they still need the derefencing treatment that pointers are
2263 * given */
2264 if (*desc == RPC_FC_IP)
2265 m(pStubMsg, *(unsigned char **)pMemory, desc);
2266 else
2267 m(pStubMsg, pMemory, desc);
2269 else FIXME("no buffersizer for embedded type %02x\n", *desc);
2270 pMemory += size;
2271 pFormat += 2;
2272 continue;
2273 case RPC_FC_PAD:
2274 break;
2275 default:
2276 FIXME("unhandled format 0x%02x\n", *pFormat);
2278 pFormat++;
2281 return pMemory;
2284 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2285 unsigned char *pMemory,
2286 PFORMAT_STRING pFormat,
2287 PFORMAT_STRING pPointer)
2289 PFORMAT_STRING desc;
2290 NDR_FREE m;
2291 unsigned long size;
2293 while (*pFormat != RPC_FC_END) {
2294 switch (*pFormat) {
2295 case RPC_FC_BYTE:
2296 case RPC_FC_CHAR:
2297 case RPC_FC_SMALL:
2298 case RPC_FC_USMALL:
2299 pMemory += 1;
2300 break;
2301 case RPC_FC_WCHAR:
2302 case RPC_FC_SHORT:
2303 case RPC_FC_USHORT:
2304 pMemory += 2;
2305 break;
2306 case RPC_FC_LONG:
2307 case RPC_FC_ULONG:
2308 case RPC_FC_ENUM32:
2309 pMemory += 4;
2310 break;
2311 case RPC_FC_HYPER:
2312 pMemory += 8;
2313 break;
2314 case RPC_FC_POINTER:
2315 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2316 pPointer += 4;
2317 pMemory += 4;
2318 break;
2319 case RPC_FC_ALIGNM4:
2320 ALIGN_POINTER(pMemory, 4);
2321 break;
2322 case RPC_FC_ALIGNM8:
2323 ALIGN_POINTER(pMemory, 8);
2324 break;
2325 case RPC_FC_STRUCTPAD1:
2326 case RPC_FC_STRUCTPAD2:
2327 case RPC_FC_STRUCTPAD3:
2328 case RPC_FC_STRUCTPAD4:
2329 case RPC_FC_STRUCTPAD5:
2330 case RPC_FC_STRUCTPAD6:
2331 case RPC_FC_STRUCTPAD7:
2332 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2333 break;
2334 case RPC_FC_EMBEDDED_COMPLEX:
2335 pMemory += pFormat[1];
2336 pFormat += 2;
2337 desc = pFormat + *(const SHORT*)pFormat;
2338 size = EmbeddedComplexSize(pStubMsg, desc);
2339 m = NdrFreer[*desc & NDR_TABLE_MASK];
2340 if (m)
2342 /* for some reason interface pointers aren't generated as
2343 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2344 * they still need the derefencing treatment that pointers are
2345 * given */
2346 if (*desc == RPC_FC_IP)
2347 m(pStubMsg, *(unsigned char **)pMemory, desc);
2348 else
2349 m(pStubMsg, pMemory, desc);
2351 else FIXME("no freer for embedded type %02x\n", *desc);
2352 pMemory += size;
2353 pFormat += 2;
2354 continue;
2355 case RPC_FC_PAD:
2356 break;
2357 default:
2358 FIXME("unhandled format 0x%02x\n", *pFormat);
2360 pFormat++;
2363 return pMemory;
2366 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2367 PFORMAT_STRING pFormat)
2369 PFORMAT_STRING desc;
2370 unsigned long size = 0;
2372 while (*pFormat != RPC_FC_END) {
2373 switch (*pFormat) {
2374 case RPC_FC_BYTE:
2375 case RPC_FC_CHAR:
2376 case RPC_FC_SMALL:
2377 case RPC_FC_USMALL:
2378 size += 1;
2379 safe_buffer_increment(pStubMsg, 1);
2380 break;
2381 case RPC_FC_WCHAR:
2382 case RPC_FC_SHORT:
2383 case RPC_FC_USHORT:
2384 size += 2;
2385 safe_buffer_increment(pStubMsg, 2);
2386 break;
2387 case RPC_FC_LONG:
2388 case RPC_FC_ULONG:
2389 case RPC_FC_ENUM32:
2390 size += 4;
2391 safe_buffer_increment(pStubMsg, 4);
2392 break;
2393 case RPC_FC_HYPER:
2394 size += 8;
2395 safe_buffer_increment(pStubMsg, 8);
2396 break;
2397 case RPC_FC_POINTER:
2398 size += 4;
2399 safe_buffer_increment(pStubMsg, 4);
2400 if (!pStubMsg->IgnoreEmbeddedPointers)
2401 FIXME("embedded pointers\n");
2402 break;
2403 case RPC_FC_ALIGNM4:
2404 ALIGN_LENGTH(size, 4);
2405 ALIGN_POINTER(pStubMsg->Buffer, 4);
2406 break;
2407 case RPC_FC_ALIGNM8:
2408 ALIGN_LENGTH(size, 8);
2409 ALIGN_POINTER(pStubMsg->Buffer, 8);
2410 break;
2411 case RPC_FC_STRUCTPAD1:
2412 case RPC_FC_STRUCTPAD2:
2413 case RPC_FC_STRUCTPAD3:
2414 case RPC_FC_STRUCTPAD4:
2415 case RPC_FC_STRUCTPAD5:
2416 case RPC_FC_STRUCTPAD6:
2417 case RPC_FC_STRUCTPAD7:
2418 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2419 break;
2420 case RPC_FC_EMBEDDED_COMPLEX:
2421 size += pFormat[1];
2422 pFormat += 2;
2423 desc = pFormat + *(const SHORT*)pFormat;
2424 size += EmbeddedComplexMemorySize(pStubMsg, desc);
2425 pFormat += 2;
2426 continue;
2427 case RPC_FC_PAD:
2428 break;
2429 default:
2430 FIXME("unhandled format 0x%02x\n", *pFormat);
2432 pFormat++;
2435 return size;
2438 /***********************************************************************
2439 * NdrComplexStructMarshall [RPCRT4.@]
2441 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2442 unsigned char *pMemory,
2443 PFORMAT_STRING pFormat)
2445 PFORMAT_STRING conf_array = NULL;
2446 PFORMAT_STRING pointer_desc = NULL;
2447 unsigned char *OldMemory = pStubMsg->Memory;
2448 int pointer_buffer_mark_set = 0;
2450 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2452 if (!pStubMsg->PointerBufferMark)
2454 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2455 /* save buffer length */
2456 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2458 /* get the buffer pointer after complex array data, but before
2459 * pointer data */
2460 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2461 pStubMsg->IgnoreEmbeddedPointers = 1;
2462 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2463 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2465 /* save it for use by embedded pointer code later */
2466 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2467 TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2468 pointer_buffer_mark_set = 1;
2470 /* restore the original buffer length */
2471 pStubMsg->BufferLength = saved_buffer_length;
2474 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
2476 pFormat += 4;
2477 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2478 pFormat += 2;
2479 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2480 pFormat += 2;
2482 pStubMsg->Memory = pMemory;
2484 ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2486 if (conf_array)
2487 NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2489 pStubMsg->Memory = OldMemory;
2491 if (pointer_buffer_mark_set)
2493 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2494 pStubMsg->PointerBufferMark = NULL;
2497 STD_OVERFLOW_CHECK(pStubMsg);
2499 return NULL;
2502 /***********************************************************************
2503 * NdrComplexStructUnmarshall [RPCRT4.@]
2505 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2506 unsigned char **ppMemory,
2507 PFORMAT_STRING pFormat,
2508 unsigned char fMustAlloc)
2510 unsigned size = *(const WORD*)(pFormat+2);
2511 PFORMAT_STRING conf_array = NULL;
2512 PFORMAT_STRING pointer_desc = NULL;
2513 unsigned char *pMemory;
2514 int pointer_buffer_mark_set = 0;
2516 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2518 if (!pStubMsg->PointerBufferMark)
2520 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2521 /* save buffer pointer */
2522 unsigned char *saved_buffer = pStubMsg->Buffer;
2524 /* get the buffer pointer after complex array data, but before
2525 * pointer data */
2526 pStubMsg->IgnoreEmbeddedPointers = 1;
2527 NdrComplexStructMemorySize(pStubMsg, pFormat);
2528 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2530 /* save it for use by embedded pointer code later */
2531 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2532 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2533 pointer_buffer_mark_set = 1;
2535 /* restore the original buffer */
2536 pStubMsg->Buffer = saved_buffer;
2539 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2541 if (fMustAlloc || !*ppMemory)
2543 *ppMemory = NdrAllocate(pStubMsg, size);
2544 memset(*ppMemory, 0, size);
2547 pFormat += 4;
2548 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2549 pFormat += 2;
2550 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2551 pFormat += 2;
2553 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc);
2555 if (conf_array)
2556 NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2558 if (pointer_buffer_mark_set)
2560 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2561 pStubMsg->PointerBufferMark = NULL;
2564 return NULL;
2567 /***********************************************************************
2568 * NdrComplexStructBufferSize [RPCRT4.@]
2570 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2571 unsigned char *pMemory,
2572 PFORMAT_STRING pFormat)
2574 PFORMAT_STRING conf_array = NULL;
2575 PFORMAT_STRING pointer_desc = NULL;
2576 unsigned char *OldMemory = pStubMsg->Memory;
2577 int pointer_length_set = 0;
2579 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2581 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2583 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2585 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2586 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2588 /* get the buffer length after complex struct data, but before
2589 * pointer data */
2590 pStubMsg->IgnoreEmbeddedPointers = 1;
2591 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2592 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2594 /* save it for use by embedded pointer code later */
2595 pStubMsg->PointerLength = pStubMsg->BufferLength;
2596 pointer_length_set = 1;
2597 TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2599 /* restore the original buffer length */
2600 pStubMsg->BufferLength = saved_buffer_length;
2603 pFormat += 4;
2604 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2605 pFormat += 2;
2606 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2607 pFormat += 2;
2609 pStubMsg->Memory = pMemory;
2611 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2613 if (conf_array)
2614 NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2616 pStubMsg->Memory = OldMemory;
2618 if(pointer_length_set)
2620 pStubMsg->BufferLength = pStubMsg->PointerLength;
2621 pStubMsg->PointerLength = 0;
2626 /***********************************************************************
2627 * NdrComplexStructMemorySize [RPCRT4.@]
2629 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2630 PFORMAT_STRING pFormat)
2632 unsigned size = *(const WORD*)(pFormat+2);
2633 PFORMAT_STRING conf_array = NULL;
2634 PFORMAT_STRING pointer_desc = NULL;
2636 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2638 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2640 pFormat += 4;
2641 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2642 pFormat += 2;
2643 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2644 pFormat += 2;
2646 ComplexStructMemorySize(pStubMsg, pFormat);
2648 if (conf_array)
2649 NdrConformantArrayMemorySize(pStubMsg, conf_array);
2651 return size;
2654 /***********************************************************************
2655 * NdrComplexStructFree [RPCRT4.@]
2657 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2658 unsigned char *pMemory,
2659 PFORMAT_STRING pFormat)
2661 PFORMAT_STRING conf_array = NULL;
2662 PFORMAT_STRING pointer_desc = NULL;
2663 unsigned char *OldMemory = pStubMsg->Memory;
2665 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2667 pFormat += 4;
2668 if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2669 pFormat += 2;
2670 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2671 pFormat += 2;
2673 pStubMsg->Memory = pMemory;
2675 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2677 if (conf_array)
2678 NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2680 pStubMsg->Memory = OldMemory;
2683 /***********************************************************************
2684 * NdrConformantArrayMarshall [RPCRT4.@]
2686 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2687 unsigned char *pMemory,
2688 PFORMAT_STRING pFormat)
2690 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2691 unsigned char alignment = pFormat[1] + 1;
2693 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2694 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2696 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2698 WriteConformance(pStubMsg);
2700 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
2702 size = safe_multiply(esize, pStubMsg->MaxCount);
2703 pStubMsg->BufferMark = pStubMsg->Buffer;
2704 safe_copy_to_buffer(pStubMsg, pMemory, size);
2706 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2708 return NULL;
2711 /***********************************************************************
2712 * NdrConformantArrayUnmarshall [RPCRT4.@]
2714 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2715 unsigned char **ppMemory,
2716 PFORMAT_STRING pFormat,
2717 unsigned char fMustAlloc)
2719 DWORD size, esize = *(const WORD*)(pFormat+2);
2720 unsigned char alignment = pFormat[1] + 1;
2721 unsigned char *saved_buffer;
2723 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2724 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2726 pFormat = ReadConformance(pStubMsg, pFormat+4);
2728 size = safe_multiply(esize, pStubMsg->MaxCount);
2729 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2731 if (fMustAlloc)
2732 *ppMemory = NdrAllocate(pStubMsg, size);
2733 else
2735 if (!pStubMsg->IsClient && !*ppMemory)
2736 /* for servers, we just point straight into the RPC buffer */
2737 *ppMemory = pStubMsg->Buffer;
2740 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
2741 safe_buffer_increment(pStubMsg, size);
2742 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2744 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2745 if (*ppMemory != saved_buffer)
2746 memcpy(*ppMemory, saved_buffer, size);
2748 return NULL;
2751 /***********************************************************************
2752 * NdrConformantArrayBufferSize [RPCRT4.@]
2754 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2755 unsigned char *pMemory,
2756 PFORMAT_STRING pFormat)
2758 DWORD size, esize = *(const WORD*)(pFormat+2);
2759 unsigned char alignment = pFormat[1] + 1;
2761 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2762 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2764 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2766 SizeConformance(pStubMsg);
2768 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2770 size = safe_multiply(esize, pStubMsg->MaxCount);
2771 /* conformance value plus array */
2772 safe_buffer_length_increment(pStubMsg, size);
2774 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2777 /***********************************************************************
2778 * NdrConformantArrayMemorySize [RPCRT4.@]
2780 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2781 PFORMAT_STRING pFormat)
2783 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2784 unsigned char alignment = pFormat[1] + 1;
2786 TRACE("(%p,%p)\n", pStubMsg, pFormat);
2787 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2789 pFormat = ReadConformance(pStubMsg, pFormat+4);
2790 size = safe_multiply(esize, pStubMsg->MaxCount);
2791 pStubMsg->MemorySize += size;
2793 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2794 pStubMsg->BufferMark = pStubMsg->Buffer;
2795 safe_buffer_increment(pStubMsg, size);
2797 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2799 return pStubMsg->MemorySize;
2802 /***********************************************************************
2803 * NdrConformantArrayFree [RPCRT4.@]
2805 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2806 unsigned char *pMemory,
2807 PFORMAT_STRING pFormat)
2809 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2810 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2812 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2814 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2818 /***********************************************************************
2819 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
2821 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2822 unsigned char* pMemory,
2823 PFORMAT_STRING pFormat )
2825 ULONG bufsize;
2826 unsigned char alignment = pFormat[1] + 1;
2827 DWORD esize = *(const WORD*)(pFormat+2);
2829 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2831 if (pFormat[0] != RPC_FC_CVARRAY)
2833 ERR("invalid format type %x\n", pFormat[0]);
2834 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2835 return NULL;
2838 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2839 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2841 WriteConformance(pStubMsg);
2842 WriteVariance(pStubMsg);
2844 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
2846 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2848 pStubMsg->BufferMark = pStubMsg->Buffer;
2849 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
2851 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2853 return NULL;
2857 /***********************************************************************
2858 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
2860 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2861 unsigned char** ppMemory,
2862 PFORMAT_STRING pFormat,
2863 unsigned char fMustAlloc )
2865 ULONG bufsize, memsize;
2866 unsigned char alignment = pFormat[1] + 1;
2867 DWORD esize = *(const WORD*)(pFormat+2);
2869 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2871 if (pFormat[0] != RPC_FC_CVARRAY)
2873 ERR("invalid format type %x\n", pFormat[0]);
2874 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2875 return NULL;
2878 pFormat = ReadConformance(pStubMsg, pFormat+4);
2879 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2881 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2883 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2884 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2886 if (!*ppMemory || fMustAlloc)
2887 *ppMemory = NdrAllocate(pStubMsg, memsize);
2888 pStubMsg->BufferMark = pStubMsg->Buffer;
2889 safe_copy_from_buffer(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
2891 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
2893 return NULL;
2897 /***********************************************************************
2898 * NdrConformantVaryingArrayFree [RPCRT4.@]
2900 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2901 unsigned char* pMemory,
2902 PFORMAT_STRING pFormat )
2904 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2906 if (pFormat[0] != RPC_FC_CVARRAY)
2908 ERR("invalid format type %x\n", pFormat[0]);
2909 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2910 return;
2913 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2914 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2916 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2920 /***********************************************************************
2921 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
2923 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2924 unsigned char* pMemory, PFORMAT_STRING pFormat )
2926 unsigned char alignment = pFormat[1] + 1;
2927 DWORD esize = *(const WORD*)(pFormat+2);
2929 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2931 if (pFormat[0] != RPC_FC_CVARRAY)
2933 ERR("invalid format type %x\n", pFormat[0]);
2934 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2935 return;
2938 /* compute size */
2939 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2940 /* compute length */
2941 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2943 SizeConformance(pStubMsg);
2944 SizeVariance(pStubMsg);
2946 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2948 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2950 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2954 /***********************************************************************
2955 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
2957 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2958 PFORMAT_STRING pFormat )
2960 ULONG bufsize, memsize;
2961 unsigned char alignment = pFormat[1] + 1;
2962 DWORD esize = *(const WORD*)(pFormat+2);
2964 TRACE("(%p, %p)\n", pStubMsg, pFormat);
2966 if (pFormat[0] != RPC_FC_CVARRAY)
2968 ERR("invalid format type %x\n", pFormat[0]);
2969 RpcRaiseException(RPC_S_INTERNAL_ERROR);
2970 return pStubMsg->MemorySize;
2973 pFormat = ReadConformance(pStubMsg, pFormat+4);
2974 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2976 ALIGN_POINTER(pStubMsg->Buffer, alignment);
2978 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2979 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2981 safe_buffer_increment(pStubMsg, bufsize);
2982 pStubMsg->MemorySize += memsize;
2984 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2986 return pStubMsg->MemorySize;
2990 /***********************************************************************
2991 * NdrComplexArrayMarshall [RPCRT4.@]
2993 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2994 unsigned char *pMemory,
2995 PFORMAT_STRING pFormat)
2997 ULONG i, count, def;
2998 BOOL variance_present;
2999 unsigned char alignment;
3000 int pointer_buffer_mark_set = 0;
3002 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3004 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3006 ERR("invalid format type %x\n", pFormat[0]);
3007 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3008 return NULL;
3011 alignment = pFormat[1] + 1;
3013 if (!pStubMsg->PointerBufferMark)
3015 /* save buffer fields that may be changed by buffer sizer functions
3016 * and that may be needed later on */
3017 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3018 unsigned long saved_buffer_length = pStubMsg->BufferLength;
3019 unsigned long saved_max_count = pStubMsg->MaxCount;
3020 unsigned long saved_offset = pStubMsg->Offset;
3021 unsigned long saved_actual_count = pStubMsg->ActualCount;
3023 /* get the buffer pointer after complex array data, but before
3024 * pointer data */
3025 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
3026 pStubMsg->IgnoreEmbeddedPointers = 1;
3027 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3028 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3030 /* save it for use by embedded pointer code later */
3031 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
3032 TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
3033 pointer_buffer_mark_set = 1;
3035 /* restore fields */
3036 pStubMsg->ActualCount = saved_actual_count;
3037 pStubMsg->Offset = saved_offset;
3038 pStubMsg->MaxCount = saved_max_count;
3039 pStubMsg->BufferLength = saved_buffer_length;
3042 def = *(const WORD*)&pFormat[2];
3043 pFormat += 4;
3045 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3046 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3048 variance_present = IsConformanceOrVariancePresent(pFormat);
3049 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3050 TRACE("variance = %d\n", pStubMsg->ActualCount);
3052 WriteConformance(pStubMsg);
3053 if (variance_present)
3054 WriteVariance(pStubMsg);
3056 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3058 count = pStubMsg->ActualCount;
3059 for (i = 0; i < count; i++)
3060 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3062 STD_OVERFLOW_CHECK(pStubMsg);
3064 if (pointer_buffer_mark_set)
3066 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3067 pStubMsg->PointerBufferMark = NULL;
3070 return NULL;
3073 /***********************************************************************
3074 * NdrComplexArrayUnmarshall [RPCRT4.@]
3076 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3077 unsigned char **ppMemory,
3078 PFORMAT_STRING pFormat,
3079 unsigned char fMustAlloc)
3081 ULONG i, count, size;
3082 unsigned char alignment;
3083 unsigned char *pMemory;
3084 unsigned char *saved_buffer;
3085 int pointer_buffer_mark_set = 0;
3086 int saved_ignore_embedded;
3088 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3090 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3092 ERR("invalid format type %x\n", pFormat[0]);
3093 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3094 return NULL;
3097 alignment = pFormat[1] + 1;
3099 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3100 /* save buffer pointer */
3101 saved_buffer = pStubMsg->Buffer;
3102 /* get the buffer pointer after complex array data, but before
3103 * pointer data */
3104 pStubMsg->IgnoreEmbeddedPointers = 1;
3105 pStubMsg->MemorySize = 0;
3106 NdrComplexArrayMemorySize(pStubMsg, pFormat);
3107 size = pStubMsg->MemorySize;
3108 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3110 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
3111 if (!pStubMsg->PointerBufferMark)
3113 /* save it for use by embedded pointer code later */
3114 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3115 pointer_buffer_mark_set = 1;
3117 /* restore the original buffer */
3118 pStubMsg->Buffer = saved_buffer;
3120 pFormat += 4;
3122 pFormat = ReadConformance(pStubMsg, pFormat);
3123 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3125 if (fMustAlloc || !*ppMemory)
3127 *ppMemory = NdrAllocate(pStubMsg, size);
3128 memset(*ppMemory, 0, size);
3131 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3133 pMemory = *ppMemory;
3134 count = pStubMsg->ActualCount;
3135 for (i = 0; i < count; i++)
3136 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL);
3138 if (pointer_buffer_mark_set)
3140 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3141 pStubMsg->PointerBufferMark = NULL;
3144 return NULL;
3147 /***********************************************************************
3148 * NdrComplexArrayBufferSize [RPCRT4.@]
3150 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3151 unsigned char *pMemory,
3152 PFORMAT_STRING pFormat)
3154 ULONG i, count, def;
3155 unsigned char alignment;
3156 BOOL variance_present;
3157 int pointer_length_set = 0;
3159 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3161 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3163 ERR("invalid format type %x\n", pFormat[0]);
3164 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3165 return;
3168 alignment = pFormat[1] + 1;
3170 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3172 /* save buffer fields that may be changed by buffer sizer functions
3173 * and that may be needed later on */
3174 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3175 unsigned long saved_buffer_length = pStubMsg->BufferLength;
3176 unsigned long saved_max_count = pStubMsg->MaxCount;
3177 unsigned long saved_offset = pStubMsg->Offset;
3178 unsigned long saved_actual_count = pStubMsg->ActualCount;
3180 /* get the buffer pointer after complex array data, but before
3181 * pointer data */
3182 pStubMsg->IgnoreEmbeddedPointers = 1;
3183 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3184 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3186 /* save it for use by embedded pointer code later */
3187 pStubMsg->PointerLength = pStubMsg->BufferLength;
3188 pointer_length_set = 1;
3190 /* restore fields */
3191 pStubMsg->ActualCount = saved_actual_count;
3192 pStubMsg->Offset = saved_offset;
3193 pStubMsg->MaxCount = saved_max_count;
3194 pStubMsg->BufferLength = saved_buffer_length;
3196 def = *(const WORD*)&pFormat[2];
3197 pFormat += 4;
3199 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3200 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3201 SizeConformance(pStubMsg);
3203 variance_present = IsConformanceOrVariancePresent(pFormat);
3204 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3205 TRACE("variance = %d\n", pStubMsg->ActualCount);
3207 if (variance_present)
3208 SizeVariance(pStubMsg);
3210 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3212 count = pStubMsg->ActualCount;
3213 for (i = 0; i < count; i++)
3214 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
3216 if(pointer_length_set)
3218 pStubMsg->BufferLength = pStubMsg->PointerLength;
3219 pStubMsg->PointerLength = 0;
3223 /***********************************************************************
3224 * NdrComplexArrayMemorySize [RPCRT4.@]
3226 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3227 PFORMAT_STRING pFormat)
3229 ULONG i, count, esize, SavedMemorySize, MemorySize;
3230 unsigned char alignment;
3231 unsigned char *Buffer;
3233 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3235 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3237 ERR("invalid format type %x\n", pFormat[0]);
3238 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3239 return 0;
3242 alignment = pFormat[1] + 1;
3244 pFormat += 4;
3246 pFormat = ReadConformance(pStubMsg, pFormat);
3247 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3249 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3251 SavedMemorySize = pStubMsg->MemorySize;
3253 Buffer = pStubMsg->Buffer;
3254 pStubMsg->MemorySize = 0;
3255 esize = ComplexStructMemorySize(pStubMsg, pFormat);
3256 pStubMsg->Buffer = Buffer;
3258 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3260 count = pStubMsg->ActualCount;
3261 for (i = 0; i < count; i++)
3262 ComplexStructMemorySize(pStubMsg, pFormat);
3264 pStubMsg->MemorySize = SavedMemorySize;
3266 pStubMsg->MemorySize += MemorySize;
3267 return MemorySize;
3270 /***********************************************************************
3271 * NdrComplexArrayFree [RPCRT4.@]
3273 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3274 unsigned char *pMemory,
3275 PFORMAT_STRING pFormat)
3277 ULONG i, count, def;
3279 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3281 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3283 ERR("invalid format type %x\n", pFormat[0]);
3284 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3285 return;
3288 def = *(const WORD*)&pFormat[2];
3289 pFormat += 4;
3291 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3292 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3294 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3295 TRACE("variance = %d\n", pStubMsg->ActualCount);
3297 count = pStubMsg->ActualCount;
3298 for (i = 0; i < count; i++)
3299 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
3302 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
3303 USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
3304 USER_MARSHAL_CB *umcb)
3306 umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
3307 pStubMsg->RpcMsg->DataRepresentation);
3308 umcb->pStubMsg = pStubMsg;
3309 umcb->pReserve = NULL;
3310 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
3311 umcb->CBType = cbtype;
3312 umcb->pFormat = pFormat;
3313 umcb->pTypeFormat = NULL /* FIXME */;
3316 #define USER_MARSHAL_PTR_PREFIX \
3317 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
3318 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
3320 /***********************************************************************
3321 * NdrUserMarshalMarshall [RPCRT4.@]
3323 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3324 unsigned char *pMemory,
3325 PFORMAT_STRING pFormat)
3327 unsigned flags = pFormat[1];
3328 unsigned index = *(const WORD*)&pFormat[2];
3329 unsigned char *saved_buffer = NULL;
3330 USER_MARSHAL_CB umcb;
3332 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3333 TRACE("index=%d\n", index);
3335 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
3337 if (flags & USER_MARSHAL_POINTER)
3339 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
3340 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
3341 pStubMsg->Buffer += 4;
3342 if (pStubMsg->PointerBufferMark)
3344 saved_buffer = pStubMsg->Buffer;
3345 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3346 pStubMsg->PointerBufferMark = NULL;
3348 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8);
3350 else
3351 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1);
3353 pStubMsg->Buffer =
3354 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
3355 &umcb.Flags, pStubMsg->Buffer, pMemory);
3357 if (saved_buffer)
3359 STD_OVERFLOW_CHECK(pStubMsg);
3360 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3361 pStubMsg->Buffer = saved_buffer;
3364 STD_OVERFLOW_CHECK(pStubMsg);
3366 return NULL;
3369 /***********************************************************************
3370 * NdrUserMarshalUnmarshall [RPCRT4.@]
3372 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3373 unsigned char **ppMemory,
3374 PFORMAT_STRING pFormat,
3375 unsigned char fMustAlloc)
3377 unsigned flags = pFormat[1];
3378 unsigned index = *(const WORD*)&pFormat[2];
3379 DWORD memsize = *(const WORD*)&pFormat[4];
3380 unsigned char *saved_buffer = NULL;
3381 USER_MARSHAL_CB umcb;
3383 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3384 TRACE("index=%d\n", index);
3386 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
3388 if (flags & USER_MARSHAL_POINTER)
3390 ALIGN_POINTER(pStubMsg->Buffer, 4);
3391 /* skip pointer prefix */
3392 pStubMsg->Buffer += 4;
3393 if (pStubMsg->PointerBufferMark)
3395 saved_buffer = pStubMsg->Buffer;
3396 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3397 pStubMsg->PointerBufferMark = NULL;
3399 ALIGN_POINTER(pStubMsg->Buffer, 8);
3401 else
3402 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3404 if (fMustAlloc || !*ppMemory)
3405 *ppMemory = NdrAllocate(pStubMsg, memsize);
3407 pStubMsg->Buffer =
3408 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
3409 &umcb.Flags, pStubMsg->Buffer, *ppMemory);
3411 if (saved_buffer)
3413 STD_OVERFLOW_CHECK(pStubMsg);
3414 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3415 pStubMsg->Buffer = saved_buffer;
3418 return NULL;
3421 /***********************************************************************
3422 * NdrUserMarshalBufferSize [RPCRT4.@]
3424 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3425 unsigned char *pMemory,
3426 PFORMAT_STRING pFormat)
3428 unsigned flags = pFormat[1];
3429 unsigned index = *(const WORD*)&pFormat[2];
3430 DWORD bufsize = *(const WORD*)&pFormat[6];
3431 USER_MARSHAL_CB umcb;
3432 unsigned long saved_buffer_length = 0;
3434 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3435 TRACE("index=%d\n", index);
3437 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
3439 if (flags & USER_MARSHAL_POINTER)
3441 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3442 /* skip pointer prefix */
3443 safe_buffer_length_increment(pStubMsg, 4);
3444 if (pStubMsg->IgnoreEmbeddedPointers)
3445 return;
3446 if (pStubMsg->PointerLength)
3448 saved_buffer_length = pStubMsg->BufferLength;
3449 pStubMsg->BufferLength = pStubMsg->PointerLength;
3450 pStubMsg->PointerLength = 0;
3452 ALIGN_LENGTH(pStubMsg->BufferLength, 8);
3454 else
3455 ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
3457 if (bufsize) {
3458 TRACE("size=%d\n", bufsize);
3459 safe_buffer_length_increment(pStubMsg, bufsize);
3461 else
3462 pStubMsg->BufferLength =
3463 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
3464 &umcb.Flags, pStubMsg->BufferLength, pMemory);
3466 if (saved_buffer_length)
3468 pStubMsg->PointerLength = pStubMsg->BufferLength;
3469 pStubMsg->BufferLength = saved_buffer_length;
3474 /***********************************************************************
3475 * NdrUserMarshalMemorySize [RPCRT4.@]
3477 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3478 PFORMAT_STRING pFormat)
3480 unsigned flags = pFormat[1];
3481 unsigned index = *(const WORD*)&pFormat[2];
3482 DWORD memsize = *(const WORD*)&pFormat[4];
3483 DWORD bufsize = *(const WORD*)&pFormat[6];
3485 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3486 TRACE("index=%d\n", index);
3488 pStubMsg->MemorySize += memsize;
3490 if (flags & USER_MARSHAL_POINTER)
3492 ALIGN_POINTER(pStubMsg->Buffer, 4);
3493 /* skip pointer prefix */
3494 pStubMsg->Buffer += 4;
3495 if (pStubMsg->IgnoreEmbeddedPointers)
3496 return pStubMsg->MemorySize;
3497 ALIGN_POINTER(pStubMsg->Buffer, 8);
3499 else
3500 ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
3502 if (!bufsize)
3503 FIXME("not implemented for varying buffer size\n");
3505 pStubMsg->Buffer += bufsize;
3507 return pStubMsg->MemorySize;
3510 /***********************************************************************
3511 * NdrUserMarshalFree [RPCRT4.@]
3513 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
3514 unsigned char *pMemory,
3515 PFORMAT_STRING pFormat)
3517 /* unsigned flags = pFormat[1]; */
3518 unsigned index = *(const WORD*)&pFormat[2];
3519 USER_MARSHAL_CB umcb;
3521 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3522 TRACE("index=%d\n", index);
3524 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
3526 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
3527 &umcb.Flags, pMemory);
3530 /***********************************************************************
3531 * NdrClearOutParameters [RPCRT4.@]
3533 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
3534 PFORMAT_STRING pFormat,
3535 void *ArgAddr)
3537 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
3540 /***********************************************************************
3541 * NdrConvert [RPCRT4.@]
3543 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
3545 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
3546 /* FIXME: since this stub doesn't do any converting, the proper behavior
3547 is to raise an exception */
3550 /***********************************************************************
3551 * NdrConvert2 [RPCRT4.@]
3553 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
3555 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
3556 pStubMsg, pFormat, NumberParams);
3557 /* FIXME: since this stub doesn't do any converting, the proper behavior
3558 is to raise an exception */
3561 #include "pshpack1.h"
3562 typedef struct _NDR_CSTRUCT_FORMAT
3564 unsigned char type;
3565 unsigned char alignment;
3566 unsigned short memory_size;
3567 short offset_to_array_description;
3568 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
3569 #include "poppack.h"
3571 /***********************************************************************
3572 * NdrConformantStructMarshall [RPCRT4.@]
3574 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3575 unsigned char *pMemory,
3576 PFORMAT_STRING pFormat)
3578 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3579 PFORMAT_STRING pCArrayFormat;
3580 ULONG esize, bufsize;
3582 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3584 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3585 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3587 ERR("invalid format type %x\n", pCStructFormat->type);
3588 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3589 return NULL;
3592 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3593 pCStructFormat->offset_to_array_description;
3594 if (*pCArrayFormat != RPC_FC_CARRAY)
3596 ERR("invalid array format type %x\n", pCStructFormat->type);
3597 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3598 return NULL;
3600 esize = *(const WORD*)(pCArrayFormat+2);
3602 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3603 pCArrayFormat + 4, 0);
3605 WriteConformance(pStubMsg);
3607 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3609 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3611 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3612 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3614 ERR("integer overflow of memory_size %u with bufsize %u\n",
3615 pCStructFormat->memory_size, bufsize);
3616 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3618 /* copy constant sized part of struct */
3619 pStubMsg->BufferMark = pStubMsg->Buffer;
3620 safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
3622 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3623 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3625 return NULL;
3628 /***********************************************************************
3629 * NdrConformantStructUnmarshall [RPCRT4.@]
3631 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3632 unsigned char **ppMemory,
3633 PFORMAT_STRING pFormat,
3634 unsigned char fMustAlloc)
3636 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3637 PFORMAT_STRING pCArrayFormat;
3638 ULONG esize, bufsize;
3639 unsigned char *saved_buffer;
3641 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3643 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3644 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3646 ERR("invalid format type %x\n", pCStructFormat->type);
3647 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3648 return NULL;
3650 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3651 pCStructFormat->offset_to_array_description;
3652 if (*pCArrayFormat != RPC_FC_CARRAY)
3654 ERR("invalid array format type %x\n", pCStructFormat->type);
3655 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3656 return NULL;
3658 esize = *(const WORD*)(pCArrayFormat+2);
3660 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
3662 ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
3664 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3666 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
3667 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
3669 ERR("integer overflow of memory_size %u with bufsize %u\n",
3670 pCStructFormat->memory_size, bufsize);
3671 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3674 if (fMustAlloc)
3676 SIZE_T size = pCStructFormat->memory_size + bufsize;
3677 *ppMemory = NdrAllocate(pStubMsg, size);
3679 else
3681 if (!pStubMsg->IsClient && !*ppMemory)
3682 /* for servers, we just point straight into the RPC buffer */
3683 *ppMemory = pStubMsg->Buffer;
3686 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3687 safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
3688 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3689 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3691 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
3692 if (*ppMemory != saved_buffer)
3693 memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
3695 return NULL;
3698 /***********************************************************************
3699 * NdrConformantStructBufferSize [RPCRT4.@]
3701 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3702 unsigned char *pMemory,
3703 PFORMAT_STRING pFormat)
3705 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3706 PFORMAT_STRING pCArrayFormat;
3707 ULONG esize;
3709 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3711 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3712 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3714 ERR("invalid format type %x\n", pCStructFormat->type);
3715 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3716 return;
3718 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3719 pCStructFormat->offset_to_array_description;
3720 if (*pCArrayFormat != RPC_FC_CARRAY)
3722 ERR("invalid array format type %x\n", pCStructFormat->type);
3723 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3724 return;
3726 esize = *(const WORD*)(pCArrayFormat+2);
3728 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
3729 SizeConformance(pStubMsg);
3731 ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
3733 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3735 safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
3736 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
3738 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3739 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3742 /***********************************************************************
3743 * NdrConformantStructMemorySize [RPCRT4.@]
3745 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3746 PFORMAT_STRING pFormat)
3748 FIXME("stub\n");
3749 return 0;
3752 /***********************************************************************
3753 * NdrConformantStructFree [RPCRT4.@]
3755 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3756 unsigned char *pMemory,
3757 PFORMAT_STRING pFormat)
3759 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
3760 PFORMAT_STRING pCArrayFormat;
3761 ULONG esize;
3763 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3765 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
3766 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
3768 ERR("invalid format type %x\n", pCStructFormat->type);
3769 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3770 return;
3773 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
3774 pCStructFormat->offset_to_array_description;
3775 if (*pCArrayFormat != RPC_FC_CARRAY)
3777 ERR("invalid array format type %x\n", pCStructFormat->type);
3778 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3779 return;
3781 esize = *(const WORD*)(pCArrayFormat+2);
3783 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
3784 pCArrayFormat + 4, 0);
3786 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
3788 /* copy constant sized part of struct */
3789 pStubMsg->BufferMark = pStubMsg->Buffer;
3791 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
3792 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3795 /***********************************************************************
3796 * NdrConformantVaryingStructMarshall [RPCRT4.@]
3798 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3799 unsigned char *pMemory,
3800 PFORMAT_STRING pFormat)
3802 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3803 PFORMAT_STRING pCVArrayFormat;
3804 ULONG esize, bufsize;
3806 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3808 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3809 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3811 ERR("invalid format type %x\n", pCVStructFormat->type);
3812 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3813 return NULL;
3816 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3817 pCVStructFormat->offset_to_array_description;
3818 switch (*pCVArrayFormat)
3820 case RPC_FC_CVARRAY:
3821 esize = *(const WORD*)(pCVArrayFormat+2);
3823 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3824 pCVArrayFormat + 4, 0);
3825 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3826 pCVArrayFormat, 0);
3827 break;
3828 case RPC_FC_C_CSTRING:
3829 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3830 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3831 esize = sizeof(char);
3832 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3833 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3834 pCVArrayFormat + 2, 0);
3835 else
3836 pStubMsg->MaxCount = pStubMsg->ActualCount;
3837 break;
3838 case RPC_FC_C_WSTRING:
3839 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3840 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3841 esize = sizeof(WCHAR);
3842 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3843 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3844 pCVArrayFormat + 2, 0);
3845 else
3846 pStubMsg->MaxCount = pStubMsg->ActualCount;
3847 break;
3848 default:
3849 ERR("invalid array format type %x\n", *pCVArrayFormat);
3850 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3851 return NULL;
3854 WriteConformance(pStubMsg);
3856 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3858 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3860 /* write constant sized part */
3861 pStubMsg->BufferMark = pStubMsg->Buffer;
3862 safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
3864 WriteVariance(pStubMsg);
3866 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3868 /* write array part */
3869 safe_copy_to_buffer(pStubMsg, pMemory + pCVStructFormat->memory_size, bufsize);
3871 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3873 return NULL;
3876 /***********************************************************************
3877 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
3879 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3880 unsigned char **ppMemory,
3881 PFORMAT_STRING pFormat,
3882 unsigned char fMustAlloc)
3884 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3885 PFORMAT_STRING pCVArrayFormat;
3886 ULONG esize, bufsize;
3887 unsigned char cvarray_type;
3889 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3891 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3892 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3894 ERR("invalid format type %x\n", pCVStructFormat->type);
3895 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3896 return NULL;
3899 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
3900 pCVStructFormat->offset_to_array_description;
3901 cvarray_type = *pCVArrayFormat;
3902 switch (cvarray_type)
3904 case RPC_FC_CVARRAY:
3905 esize = *(const WORD*)(pCVArrayFormat+2);
3906 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3907 break;
3908 case RPC_FC_C_CSTRING:
3909 esize = sizeof(char);
3910 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3911 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3912 else
3913 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3914 break;
3915 case RPC_FC_C_WSTRING:
3916 esize = sizeof(WCHAR);
3917 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3918 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3919 else
3920 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3921 break;
3922 default:
3923 ERR("invalid array format type %x\n", *pCVArrayFormat);
3924 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3925 return NULL;
3928 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3930 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3932 /* work out how much memory to allocate if we need to do so */
3933 if (!*ppMemory || fMustAlloc)
3935 SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
3936 *ppMemory = NdrAllocate(pStubMsg, size);
3939 /* copy the constant data */
3940 pStubMsg->BufferMark = pStubMsg->Buffer;
3941 safe_copy_from_buffer(pStubMsg, *ppMemory, pCVStructFormat->memory_size);
3943 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
3945 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3947 if ((cvarray_type == RPC_FC_C_CSTRING) ||
3948 (cvarray_type == RPC_FC_C_WSTRING))
3950 ULONG i;
3951 /* strings must always have null terminating bytes */
3952 if (bufsize < esize)
3954 ERR("invalid string length of %d\n", pStubMsg->ActualCount);
3955 RpcRaiseException(RPC_S_INVALID_BOUND);
3956 return NULL;
3958 for (i = bufsize - esize; i < bufsize; i++)
3959 if (pStubMsg->Buffer[i] != 0)
3961 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
3962 i, pStubMsg->Buffer[i]);
3963 RpcRaiseException(RPC_S_INVALID_BOUND);
3964 return NULL;
3968 /* copy the array data */
3969 safe_copy_from_buffer(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize);
3971 if (cvarray_type == RPC_FC_C_CSTRING)
3972 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3973 else if (cvarray_type == RPC_FC_C_WSTRING)
3974 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3976 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
3978 return NULL;
3981 /***********************************************************************
3982 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
3984 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3985 unsigned char *pMemory,
3986 PFORMAT_STRING pFormat)
3988 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
3989 PFORMAT_STRING pCVArrayFormat;
3990 ULONG esize;
3992 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3994 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3995 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3997 ERR("invalid format type %x\n", pCVStructFormat->type);
3998 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3999 return;
4002 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4003 pCVStructFormat->offset_to_array_description;
4004 switch (*pCVArrayFormat)
4006 case RPC_FC_CVARRAY:
4007 esize = *(const WORD*)(pCVArrayFormat+2);
4009 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4010 pCVArrayFormat + 4, 0);
4011 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4012 pCVArrayFormat, 0);
4013 break;
4014 case RPC_FC_C_CSTRING:
4015 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4016 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4017 esize = sizeof(char);
4018 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4019 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4020 pCVArrayFormat + 2, 0);
4021 else
4022 pStubMsg->MaxCount = pStubMsg->ActualCount;
4023 break;
4024 case RPC_FC_C_WSTRING:
4025 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4026 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4027 esize = sizeof(WCHAR);
4028 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4029 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4030 pCVArrayFormat + 2, 0);
4031 else
4032 pStubMsg->MaxCount = pStubMsg->ActualCount;
4033 break;
4034 default:
4035 ERR("invalid array format type %x\n", *pCVArrayFormat);
4036 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4037 return;
4040 SizeConformance(pStubMsg);
4042 ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
4044 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4046 safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
4047 SizeVariance(pStubMsg);
4048 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4050 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4053 /***********************************************************************
4054 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
4056 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4057 PFORMAT_STRING pFormat)
4059 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4060 PFORMAT_STRING pCVArrayFormat;
4061 ULONG esize;
4062 unsigned char cvarray_type;
4064 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4066 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4067 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4069 ERR("invalid format type %x\n", pCVStructFormat->type);
4070 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4071 return 0;
4074 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4075 pCVStructFormat->offset_to_array_description;
4076 cvarray_type = *pCVArrayFormat;
4077 switch (cvarray_type)
4079 case RPC_FC_CVARRAY:
4080 esize = *(const WORD*)(pCVArrayFormat+2);
4081 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
4082 break;
4083 case RPC_FC_C_CSTRING:
4084 esize = sizeof(char);
4085 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4086 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4087 else
4088 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4089 break;
4090 case RPC_FC_C_WSTRING:
4091 esize = sizeof(WCHAR);
4092 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4093 pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
4094 else
4095 pCVArrayFormat = ReadConformance(pStubMsg, NULL);
4096 break;
4097 default:
4098 ERR("invalid array format type %x\n", *pCVArrayFormat);
4099 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4100 return 0;
4103 ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4105 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4107 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4108 pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount);
4109 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4111 pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount);
4113 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4115 return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
4118 /***********************************************************************
4119 * NdrConformantVaryingStructFree [RPCRT4.@]
4121 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4122 unsigned char *pMemory,
4123 PFORMAT_STRING pFormat)
4125 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4126 PFORMAT_STRING pCVArrayFormat;
4127 ULONG esize;
4129 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4131 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4132 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4134 ERR("invalid format type %x\n", pCVStructFormat->type);
4135 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4136 return;
4139 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4140 pCVStructFormat->offset_to_array_description;
4141 switch (*pCVArrayFormat)
4143 case RPC_FC_CVARRAY:
4144 esize = *(const WORD*)(pCVArrayFormat+2);
4146 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4147 pCVArrayFormat + 4, 0);
4148 pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4149 pCVArrayFormat, 0);
4150 break;
4151 case RPC_FC_C_CSTRING:
4152 TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
4153 pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
4154 esize = sizeof(char);
4155 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4156 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4157 pCVArrayFormat + 2, 0);
4158 else
4159 pStubMsg->MaxCount = pStubMsg->ActualCount;
4160 break;
4161 case RPC_FC_C_WSTRING:
4162 TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
4163 pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
4164 esize = sizeof(WCHAR);
4165 if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
4166 pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
4167 pCVArrayFormat + 2, 0);
4168 else
4169 pStubMsg->MaxCount = pStubMsg->ActualCount;
4170 break;
4171 default:
4172 ERR("invalid array format type %x\n", *pCVArrayFormat);
4173 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4174 return;
4177 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4179 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4182 #include "pshpack1.h"
4183 typedef struct
4185 unsigned char type;
4186 unsigned char alignment;
4187 unsigned short total_size;
4188 } NDR_SMFARRAY_FORMAT;
4190 typedef struct
4192 unsigned char type;
4193 unsigned char alignment;
4194 unsigned long total_size;
4195 } NDR_LGFARRAY_FORMAT;
4196 #include "poppack.h"
4198 /***********************************************************************
4199 * NdrFixedArrayMarshall [RPCRT4.@]
4201 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4202 unsigned char *pMemory,
4203 PFORMAT_STRING pFormat)
4205 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4206 unsigned long total_size;
4208 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4210 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4211 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4213 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4214 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4215 return NULL;
4218 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4220 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4222 total_size = pSmFArrayFormat->total_size;
4223 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4225 else
4227 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4228 total_size = pLgFArrayFormat->total_size;
4229 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4232 pStubMsg->BufferMark = pStubMsg->Buffer;
4233 safe_copy_to_buffer(pStubMsg, pMemory, total_size);
4235 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4237 return NULL;
4240 /***********************************************************************
4241 * NdrFixedArrayUnmarshall [RPCRT4.@]
4243 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4244 unsigned char **ppMemory,
4245 PFORMAT_STRING pFormat,
4246 unsigned char fMustAlloc)
4248 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4249 unsigned long total_size;
4250 unsigned char *saved_buffer;
4252 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4254 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4255 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4257 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4258 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4259 return NULL;
4262 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4264 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4266 total_size = pSmFArrayFormat->total_size;
4267 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4269 else
4271 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4272 total_size = pLgFArrayFormat->total_size;
4273 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4276 if (fMustAlloc)
4277 *ppMemory = NdrAllocate(pStubMsg, total_size);
4278 else
4280 if (!pStubMsg->IsClient && !*ppMemory)
4281 /* for servers, we just point straight into the RPC buffer */
4282 *ppMemory = pStubMsg->Buffer;
4285 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4286 safe_buffer_increment(pStubMsg, total_size);
4287 pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4289 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4290 if (*ppMemory != saved_buffer)
4291 memcpy(*ppMemory, saved_buffer, total_size);
4293 return NULL;
4296 /***********************************************************************
4297 * NdrFixedArrayBufferSize [RPCRT4.@]
4299 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4300 unsigned char *pMemory,
4301 PFORMAT_STRING pFormat)
4303 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4304 unsigned long total_size;
4306 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4308 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4309 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4311 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4312 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4313 return;
4316 ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
4318 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4320 total_size = pSmFArrayFormat->total_size;
4321 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4323 else
4325 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4326 total_size = pLgFArrayFormat->total_size;
4327 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4329 safe_buffer_length_increment(pStubMsg, total_size);
4331 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4334 /***********************************************************************
4335 * NdrFixedArrayMemorySize [RPCRT4.@]
4337 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4338 PFORMAT_STRING pFormat)
4340 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4341 ULONG total_size;
4343 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4345 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4346 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4348 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4349 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4350 return 0;
4353 ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
4355 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4357 total_size = pSmFArrayFormat->total_size;
4358 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4360 else
4362 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4363 total_size = pLgFArrayFormat->total_size;
4364 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4366 pStubMsg->BufferMark = pStubMsg->Buffer;
4367 safe_buffer_increment(pStubMsg, total_size);
4368 pStubMsg->MemorySize += total_size;
4370 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4372 return total_size;
4375 /***********************************************************************
4376 * NdrFixedArrayFree [RPCRT4.@]
4378 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4379 unsigned char *pMemory,
4380 PFORMAT_STRING pFormat)
4382 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
4384 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4386 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
4387 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
4389 ERR("invalid format type %x\n", pSmFArrayFormat->type);
4390 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4391 return;
4394 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
4395 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
4396 else
4398 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
4399 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
4402 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4405 /***********************************************************************
4406 * NdrVaryingArrayMarshall [RPCRT4.@]
4408 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4409 unsigned char *pMemory,
4410 PFORMAT_STRING pFormat)
4412 unsigned char alignment;
4413 DWORD elements, esize;
4414 ULONG bufsize;
4416 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4418 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4419 (pFormat[0] != RPC_FC_LGVARRAY))
4421 ERR("invalid format type %x\n", pFormat[0]);
4422 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4423 return NULL;
4426 alignment = pFormat[1] + 1;
4428 if (pFormat[0] == RPC_FC_SMVARRAY)
4430 pFormat += 2;
4431 pFormat += sizeof(WORD);
4432 elements = *(const WORD*)pFormat;
4433 pFormat += sizeof(WORD);
4435 else
4437 pFormat += 2;
4438 pFormat += sizeof(DWORD);
4439 elements = *(const DWORD*)pFormat;
4440 pFormat += sizeof(DWORD);
4443 esize = *(const WORD*)pFormat;
4444 pFormat += sizeof(WORD);
4446 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4447 if ((pStubMsg->ActualCount > elements) ||
4448 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4450 RpcRaiseException(RPC_S_INVALID_BOUND);
4451 return NULL;
4454 WriteVariance(pStubMsg);
4456 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
4458 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4459 pStubMsg->BufferMark = pStubMsg->Buffer;
4460 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
4462 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4464 return NULL;
4467 /***********************************************************************
4468 * NdrVaryingArrayUnmarshall [RPCRT4.@]
4470 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4471 unsigned char **ppMemory,
4472 PFORMAT_STRING pFormat,
4473 unsigned char fMustAlloc)
4475 unsigned char alignment;
4476 DWORD size, elements, esize;
4477 ULONG bufsize;
4479 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4481 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4482 (pFormat[0] != RPC_FC_LGVARRAY))
4484 ERR("invalid format type %x\n", pFormat[0]);
4485 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4486 return NULL;
4489 alignment = pFormat[1] + 1;
4491 if (pFormat[0] == RPC_FC_SMVARRAY)
4493 pFormat += 2;
4494 size = *(const WORD*)pFormat;
4495 pFormat += sizeof(WORD);
4496 elements = *(const WORD*)pFormat;
4497 pFormat += sizeof(WORD);
4499 else
4501 pFormat += 2;
4502 size = *(const DWORD*)pFormat;
4503 pFormat += sizeof(DWORD);
4504 elements = *(const DWORD*)pFormat;
4505 pFormat += sizeof(DWORD);
4508 esize = *(const WORD*)pFormat;
4509 pFormat += sizeof(WORD);
4511 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4513 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4515 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
4517 if (!*ppMemory || fMustAlloc)
4518 *ppMemory = NdrAllocate(pStubMsg, size);
4519 pStubMsg->BufferMark = pStubMsg->Buffer;
4520 safe_copy_from_buffer(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize);
4522 EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */);
4524 return NULL;
4527 /***********************************************************************
4528 * NdrVaryingArrayBufferSize [RPCRT4.@]
4530 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4531 unsigned char *pMemory,
4532 PFORMAT_STRING pFormat)
4534 unsigned char alignment;
4535 DWORD elements, esize;
4537 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4539 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4540 (pFormat[0] != RPC_FC_LGVARRAY))
4542 ERR("invalid format type %x\n", pFormat[0]);
4543 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4544 return;
4547 alignment = pFormat[1] + 1;
4549 if (pFormat[0] == RPC_FC_SMVARRAY)
4551 pFormat += 2;
4552 pFormat += sizeof(WORD);
4553 elements = *(const WORD*)pFormat;
4554 pFormat += sizeof(WORD);
4556 else
4558 pFormat += 2;
4559 pFormat += sizeof(DWORD);
4560 elements = *(const DWORD*)pFormat;
4561 pFormat += sizeof(DWORD);
4564 esize = *(const WORD*)pFormat;
4565 pFormat += sizeof(WORD);
4567 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4568 if ((pStubMsg->ActualCount > elements) ||
4569 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4571 RpcRaiseException(RPC_S_INVALID_BOUND);
4572 return;
4575 SizeVariance(pStubMsg);
4577 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
4579 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4581 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4584 /***********************************************************************
4585 * NdrVaryingArrayMemorySize [RPCRT4.@]
4587 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4588 PFORMAT_STRING pFormat)
4590 unsigned char alignment;
4591 DWORD size, elements, esize;
4593 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4595 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4596 (pFormat[0] != RPC_FC_LGVARRAY))
4598 ERR("invalid format type %x\n", pFormat[0]);
4599 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4600 return 0;
4603 alignment = pFormat[1] + 1;
4605 if (pFormat[0] == RPC_FC_SMVARRAY)
4607 pFormat += 2;
4608 size = *(const WORD*)pFormat;
4609 pFormat += sizeof(WORD);
4610 elements = *(const WORD*)pFormat;
4611 pFormat += sizeof(WORD);
4613 else
4615 pFormat += 2;
4616 size = *(const DWORD*)pFormat;
4617 pFormat += sizeof(DWORD);
4618 elements = *(const DWORD*)pFormat;
4619 pFormat += sizeof(DWORD);
4622 esize = *(const WORD*)pFormat;
4623 pFormat += sizeof(WORD);
4625 pFormat = ReadVariance(pStubMsg, pFormat, elements);
4627 ALIGN_POINTER(pStubMsg->Buffer, alignment);
4629 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
4630 pStubMsg->MemorySize += size;
4632 EmbeddedPointerMemorySize(pStubMsg, pFormat);
4634 return pStubMsg->MemorySize;
4637 /***********************************************************************
4638 * NdrVaryingArrayFree [RPCRT4.@]
4640 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4641 unsigned char *pMemory,
4642 PFORMAT_STRING pFormat)
4644 unsigned char alignment;
4645 DWORD elements;
4647 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4649 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
4650 (pFormat[0] != RPC_FC_LGVARRAY))
4652 ERR("invalid format type %x\n", pFormat[0]);
4653 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4654 return;
4657 alignment = pFormat[1] + 1;
4659 if (pFormat[0] == RPC_FC_SMVARRAY)
4661 pFormat += 2;
4662 pFormat += sizeof(WORD);
4663 elements = *(const WORD*)pFormat;
4664 pFormat += sizeof(WORD);
4666 else
4668 pFormat += 2;
4669 pFormat += sizeof(DWORD);
4670 elements = *(const DWORD*)pFormat;
4671 pFormat += sizeof(DWORD);
4674 pFormat += sizeof(WORD);
4676 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
4677 if ((pStubMsg->ActualCount > elements) ||
4678 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
4680 RpcRaiseException(RPC_S_INVALID_BOUND);
4681 return;
4684 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4687 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
4689 switch (fc)
4691 case RPC_FC_BYTE:
4692 case RPC_FC_CHAR:
4693 case RPC_FC_SMALL:
4694 case RPC_FC_USMALL:
4695 return *(const UCHAR *)pMemory;
4696 case RPC_FC_WCHAR:
4697 case RPC_FC_SHORT:
4698 case RPC_FC_USHORT:
4699 case RPC_FC_ENUM16:
4700 return *(const USHORT *)pMemory;
4701 case RPC_FC_LONG:
4702 case RPC_FC_ULONG:
4703 case RPC_FC_ENUM32:
4704 return *(const ULONG *)pMemory;
4705 default:
4706 FIXME("Unhandled base type: 0x%02x\n", fc);
4707 return 0;
4711 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
4712 unsigned long discriminant,
4713 PFORMAT_STRING pFormat)
4715 unsigned short num_arms, arm, type;
4717 num_arms = *(const SHORT*)pFormat & 0x0fff;
4718 pFormat += 2;
4719 for(arm = 0; arm < num_arms; arm++)
4721 if(discriminant == *(const ULONG*)pFormat)
4723 pFormat += 4;
4724 break;
4726 pFormat += 6;
4729 type = *(const unsigned short*)pFormat;
4730 TRACE("type %04x\n", type);
4731 if(arm == num_arms) /* default arm extras */
4733 if(type == 0xffff)
4735 ERR("no arm for 0x%lx and no default case\n", discriminant);
4736 RpcRaiseException(RPC_S_INVALID_TAG);
4737 return NULL;
4739 if(type == 0)
4741 TRACE("falling back to empty default case for 0x%lx\n", discriminant);
4742 return NULL;
4745 return pFormat;
4748 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
4750 unsigned short type;
4752 pFormat += 2;
4754 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4755 if(!pFormat)
4756 return NULL;
4758 type = *(const unsigned short*)pFormat;
4759 if((type & 0xff00) == 0x8000)
4761 unsigned char basetype = LOBYTE(type);
4762 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
4764 else
4766 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4767 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
4768 if (m)
4770 unsigned char *saved_buffer = NULL;
4771 int pointer_buffer_mark_set = 0;
4772 switch(*desc)
4774 case RPC_FC_RP:
4775 case RPC_FC_UP:
4776 case RPC_FC_OP:
4777 case RPC_FC_FP:
4778 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
4779 saved_buffer = pStubMsg->Buffer;
4780 if (pStubMsg->PointerBufferMark)
4782 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4783 pStubMsg->PointerBufferMark = NULL;
4784 pointer_buffer_mark_set = 1;
4786 else
4787 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
4789 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
4790 if (pointer_buffer_mark_set)
4792 STD_OVERFLOW_CHECK(pStubMsg);
4793 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4794 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
4796 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
4797 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
4798 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4800 pStubMsg->Buffer = saved_buffer + 4;
4802 break;
4803 default:
4804 m(pStubMsg, pMemory, desc);
4807 else FIXME("no marshaller for embedded type %02x\n", *desc);
4809 return NULL;
4812 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4813 unsigned char **ppMemory,
4814 ULONG discriminant,
4815 PFORMAT_STRING pFormat,
4816 unsigned char fMustAlloc)
4818 unsigned short type;
4820 pFormat += 2;
4822 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4823 if(!pFormat)
4824 return NULL;
4826 type = *(const unsigned short*)pFormat;
4827 if((type & 0xff00) == 0x8000)
4829 unsigned char basetype = LOBYTE(type);
4830 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
4832 else
4834 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4835 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
4836 if (m)
4838 unsigned char *saved_buffer = NULL;
4839 int pointer_buffer_mark_set = 0;
4840 switch(*desc)
4842 case RPC_FC_RP:
4843 case RPC_FC_UP:
4844 case RPC_FC_OP:
4845 case RPC_FC_FP:
4846 **(void***)ppMemory = NULL;
4847 ALIGN_POINTER(pStubMsg->Buffer, 4);
4848 saved_buffer = pStubMsg->Buffer;
4849 if (pStubMsg->PointerBufferMark)
4851 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4852 pStubMsg->PointerBufferMark = NULL;
4853 pointer_buffer_mark_set = 1;
4855 else
4856 pStubMsg->Buffer += 4; /* for pointer ID */
4858 if (saved_buffer + 4 > pStubMsg->BufferEnd)
4860 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
4861 saved_buffer, pStubMsg->BufferEnd);
4862 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4865 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
4866 if (pointer_buffer_mark_set)
4868 STD_OVERFLOW_CHECK(pStubMsg);
4869 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4870 pStubMsg->Buffer = saved_buffer + 4;
4872 break;
4873 default:
4874 m(pStubMsg, ppMemory, desc, fMustAlloc);
4877 else FIXME("no marshaller for embedded type %02x\n", *desc);
4879 return NULL;
4882 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
4883 unsigned char *pMemory,
4884 ULONG discriminant,
4885 PFORMAT_STRING pFormat)
4887 unsigned short type;
4889 pFormat += 2;
4891 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4892 if(!pFormat)
4893 return;
4895 type = *(const unsigned short*)pFormat;
4896 if((type & 0xff00) == 0x8000)
4898 unsigned char basetype = LOBYTE(type);
4899 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
4901 else
4903 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4904 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
4905 if (m)
4907 switch(*desc)
4909 case RPC_FC_RP:
4910 case RPC_FC_UP:
4911 case RPC_FC_OP:
4912 case RPC_FC_FP:
4913 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
4914 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
4915 if (!pStubMsg->IgnoreEmbeddedPointers)
4917 int saved_buffer_length = pStubMsg->BufferLength;
4918 pStubMsg->BufferLength = pStubMsg->PointerLength;
4919 pStubMsg->PointerLength = 0;
4920 if(!pStubMsg->BufferLength)
4921 ERR("BufferLength == 0??\n");
4922 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
4923 pStubMsg->PointerLength = pStubMsg->BufferLength;
4924 pStubMsg->BufferLength = saved_buffer_length;
4926 break;
4927 default:
4928 m(pStubMsg, pMemory, desc);
4931 else FIXME("no buffersizer for embedded type %02x\n", *desc);
4935 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
4936 ULONG discriminant,
4937 PFORMAT_STRING pFormat)
4939 unsigned short type, size;
4941 size = *(const unsigned short*)pFormat;
4942 pStubMsg->Memory += size;
4943 pFormat += 2;
4945 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4946 if(!pFormat)
4947 return 0;
4949 type = *(const unsigned short*)pFormat;
4950 if((type & 0xff00) == 0x8000)
4952 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
4954 else
4956 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
4957 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
4958 unsigned char *saved_buffer;
4959 if (m)
4961 switch(*desc)
4963 case RPC_FC_RP:
4964 case RPC_FC_UP:
4965 case RPC_FC_OP:
4966 case RPC_FC_FP:
4967 ALIGN_POINTER(pStubMsg->Buffer, 4);
4968 saved_buffer = pStubMsg->Buffer;
4969 safe_buffer_increment(pStubMsg, 4);
4970 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
4971 pStubMsg->MemorySize += 4;
4972 if (!pStubMsg->IgnoreEmbeddedPointers)
4973 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
4974 break;
4975 default:
4976 return m(pStubMsg, desc);
4979 else FIXME("no marshaller for embedded type %02x\n", *desc);
4982 TRACE("size %d\n", size);
4983 return size;
4986 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
4987 unsigned char *pMemory,
4988 ULONG discriminant,
4989 PFORMAT_STRING pFormat)
4991 unsigned short type;
4993 pFormat += 2;
4995 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
4996 if(!pFormat)
4997 return;
4999 type = *(const unsigned short*)pFormat;
5000 if((type & 0xff00) != 0x8000)
5002 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5003 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5004 if (m)
5006 switch(*desc)
5008 case RPC_FC_RP:
5009 case RPC_FC_UP:
5010 case RPC_FC_OP:
5011 case RPC_FC_FP:
5012 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5013 break;
5014 default:
5015 m(pStubMsg, pMemory, desc);
5018 else FIXME("no freer for embedded type %02x\n", *desc);
5022 /***********************************************************************
5023 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
5025 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5026 unsigned char *pMemory,
5027 PFORMAT_STRING pFormat)
5029 unsigned char switch_type;
5030 unsigned char increment;
5031 ULONG switch_value;
5033 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5034 pFormat++;
5036 switch_type = *pFormat & 0xf;
5037 increment = (*pFormat & 0xf0) >> 4;
5038 pFormat++;
5040 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment);
5042 switch_value = get_discriminant(switch_type, pMemory);
5043 TRACE("got switch value 0x%x\n", switch_value);
5045 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5046 pMemory += increment;
5048 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5051 /***********************************************************************
5052 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5054 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5055 unsigned char **ppMemory,
5056 PFORMAT_STRING pFormat,
5057 unsigned char fMustAlloc)
5059 unsigned char switch_type;
5060 unsigned char increment;
5061 ULONG switch_value;
5062 unsigned short size;
5063 unsigned char *pMemoryArm;
5065 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5066 pFormat++;
5068 switch_type = *pFormat & 0xf;
5069 increment = (*pFormat & 0xf0) >> 4;
5070 pFormat++;
5072 ALIGN_POINTER(pStubMsg->Buffer, increment);
5073 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5074 TRACE("got switch value 0x%x\n", switch_value);
5076 size = *(const unsigned short*)pFormat + increment;
5077 if(!*ppMemory || fMustAlloc)
5078 *ppMemory = NdrAllocate(pStubMsg, size);
5080 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
5081 pMemoryArm = *ppMemory + increment;
5083 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
5086 /***********************************************************************
5087 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
5089 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5090 unsigned char *pMemory,
5091 PFORMAT_STRING pFormat)
5093 unsigned char switch_type;
5094 unsigned char increment;
5095 ULONG switch_value;
5097 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5098 pFormat++;
5100 switch_type = *pFormat & 0xf;
5101 increment = (*pFormat & 0xf0) >> 4;
5102 pFormat++;
5104 ALIGN_LENGTH(pStubMsg->BufferLength, increment);
5105 switch_value = get_discriminant(switch_type, pMemory);
5106 TRACE("got switch value 0x%x\n", switch_value);
5108 /* Add discriminant size */
5109 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
5110 pMemory += increment;
5112 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
5115 /***********************************************************************
5116 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
5118 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5119 PFORMAT_STRING pFormat)
5121 unsigned char switch_type;
5122 unsigned char increment;
5123 ULONG switch_value;
5125 switch_type = *pFormat & 0xf;
5126 increment = (*pFormat & 0xf0) >> 4;
5127 pFormat++;
5129 ALIGN_POINTER(pStubMsg->Buffer, increment);
5130 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
5131 TRACE("got switch value 0x%x\n", switch_value);
5133 pStubMsg->Memory += increment;
5135 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
5138 /***********************************************************************
5139 * NdrEncapsulatedUnionFree [RPCRT4.@]
5141 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5142 unsigned char *pMemory,
5143 PFORMAT_STRING pFormat)
5145 unsigned char switch_type;
5146 unsigned char increment;
5147 ULONG switch_value;
5149 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5150 pFormat++;
5152 switch_type = *pFormat & 0xf;
5153 increment = (*pFormat & 0xf0) >> 4;
5154 pFormat++;
5156 switch_value = get_discriminant(switch_type, pMemory);
5157 TRACE("got switch value 0x%x\n", switch_value);
5159 pMemory += increment;
5161 return union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
5164 /***********************************************************************
5165 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
5167 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5168 unsigned char *pMemory,
5169 PFORMAT_STRING pFormat)
5171 unsigned char switch_type;
5173 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5174 pFormat++;
5176 switch_type = *pFormat;
5177 pFormat++;
5179 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5180 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5181 /* Marshall discriminant */
5182 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5184 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5187 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
5188 PFORMAT_STRING *ppFormat)
5190 long discriminant = 0;
5192 switch(**ppFormat)
5194 case RPC_FC_BYTE:
5195 case RPC_FC_CHAR:
5196 case RPC_FC_SMALL:
5197 case RPC_FC_USMALL:
5199 UCHAR d;
5200 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5201 discriminant = d;
5202 break;
5204 case RPC_FC_WCHAR:
5205 case RPC_FC_SHORT:
5206 case RPC_FC_USHORT:
5208 USHORT d;
5209 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5210 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5211 discriminant = d;
5212 break;
5214 case RPC_FC_LONG:
5215 case RPC_FC_ULONG:
5217 ULONG d;
5218 ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
5219 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
5220 discriminant = d;
5221 break;
5223 default:
5224 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
5226 (*ppFormat)++;
5228 if (pStubMsg->fHasNewCorrDesc)
5229 *ppFormat += 6;
5230 else
5231 *ppFormat += 4;
5232 return discriminant;
5235 /**********************************************************************
5236 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
5238 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5239 unsigned char **ppMemory,
5240 PFORMAT_STRING pFormat,
5241 unsigned char fMustAlloc)
5243 long discriminant;
5244 unsigned short size;
5246 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5247 pFormat++;
5249 /* Unmarshall discriminant */
5250 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5251 TRACE("unmarshalled discriminant %lx\n", discriminant);
5253 pFormat += *(const SHORT*)pFormat;
5255 size = *(const unsigned short*)pFormat;
5257 if(!*ppMemory || fMustAlloc)
5258 *ppMemory = NdrAllocate(pStubMsg, size);
5260 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
5263 /***********************************************************************
5264 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
5266 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5267 unsigned char *pMemory,
5268 PFORMAT_STRING pFormat)
5270 unsigned char switch_type;
5272 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5273 pFormat++;
5275 switch_type = *pFormat;
5276 pFormat++;
5278 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5279 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5280 /* Add discriminant size */
5281 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
5283 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5286 /***********************************************************************
5287 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
5289 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5290 PFORMAT_STRING pFormat)
5292 ULONG discriminant;
5294 pFormat++;
5295 /* Unmarshall discriminant */
5296 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
5297 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
5299 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
5302 /***********************************************************************
5303 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
5305 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
5306 unsigned char *pMemory,
5307 PFORMAT_STRING pFormat)
5309 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5310 pFormat++;
5311 pFormat++;
5313 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
5314 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
5316 return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
5319 /***********************************************************************
5320 * NdrByteCountPointerMarshall [RPCRT4.@]
5322 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5323 unsigned char *pMemory,
5324 PFORMAT_STRING pFormat)
5326 FIXME("stub\n");
5327 return NULL;
5330 /***********************************************************************
5331 * NdrByteCountPointerUnmarshall [RPCRT4.@]
5333 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5334 unsigned char **ppMemory,
5335 PFORMAT_STRING pFormat,
5336 unsigned char fMustAlloc)
5338 FIXME("stub\n");
5339 return NULL;
5342 /***********************************************************************
5343 * NdrByteCountPointerBufferSize [RPCRT4.@]
5345 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5346 unsigned char *pMemory,
5347 PFORMAT_STRING pFormat)
5349 FIXME("stub\n");
5352 /***********************************************************************
5353 * NdrByteCountPointerMemorySize [RPCRT4.@]
5355 ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5356 PFORMAT_STRING pFormat)
5358 FIXME("stub\n");
5359 return 0;
5362 /***********************************************************************
5363 * NdrByteCountPointerFree [RPCRT4.@]
5365 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
5366 unsigned char *pMemory,
5367 PFORMAT_STRING pFormat)
5369 FIXME("stub\n");
5372 /***********************************************************************
5373 * NdrXmitOrRepAsMarshall [RPCRT4.@]
5375 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5376 unsigned char *pMemory,
5377 PFORMAT_STRING pFormat)
5379 FIXME("stub\n");
5380 return NULL;
5383 /***********************************************************************
5384 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
5386 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5387 unsigned char **ppMemory,
5388 PFORMAT_STRING pFormat,
5389 unsigned char fMustAlloc)
5391 FIXME("stub\n");
5392 return NULL;
5395 /***********************************************************************
5396 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
5398 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5399 unsigned char *pMemory,
5400 PFORMAT_STRING pFormat)
5402 FIXME("stub\n");
5405 /***********************************************************************
5406 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
5408 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5409 PFORMAT_STRING pFormat)
5411 FIXME("stub\n");
5412 return 0;
5415 /***********************************************************************
5416 * NdrXmitOrRepAsFree [RPCRT4.@]
5418 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
5419 unsigned char *pMemory,
5420 PFORMAT_STRING pFormat)
5422 FIXME("stub\n");
5425 #include "pshpack1.h"
5426 typedef struct
5428 unsigned char type;
5429 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
5430 ULONG low_value;
5431 ULONG high_value;
5432 } NDR_RANGE;
5433 #include "poppack.h"
5435 /***********************************************************************
5436 * NdrRangeMarshall [internal]
5438 unsigned char *WINAPI NdrRangeMarshall(
5439 PMIDL_STUB_MESSAGE pStubMsg,
5440 unsigned char *pMemory,
5441 PFORMAT_STRING pFormat)
5443 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5444 unsigned char base_type;
5446 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5448 if (pRange->type != RPC_FC_RANGE)
5450 ERR("invalid format type %x\n", pRange->type);
5451 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5452 return NULL;
5455 base_type = pRange->flags_type & 0xf;
5457 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
5460 /***********************************************************************
5461 * NdrRangeUnmarshall
5463 unsigned char *WINAPI NdrRangeUnmarshall(
5464 PMIDL_STUB_MESSAGE pStubMsg,
5465 unsigned char **ppMemory,
5466 PFORMAT_STRING pFormat,
5467 unsigned char fMustAlloc)
5469 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5470 unsigned char base_type;
5472 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5474 if (pRange->type != RPC_FC_RANGE)
5476 ERR("invalid format type %x\n", pRange->type);
5477 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5478 return NULL;
5480 base_type = pRange->flags_type & 0xf;
5482 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
5483 base_type, pRange->low_value, pRange->high_value);
5485 #define RANGE_UNMARSHALL(type, format_spec) \
5486 do \
5488 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5489 if (fMustAlloc || !*ppMemory) \
5490 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5491 if (pStubMsg->Buffer + sizeof(type) > pStubMsg->BufferEnd) \
5493 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
5494 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
5495 RpcRaiseException(RPC_X_BAD_STUB_DATA); \
5497 if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \
5498 (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \
5500 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
5501 *(type *)pStubMsg->Buffer, (type)pRange->low_value, \
5502 (type)pRange->high_value); \
5503 RpcRaiseException(RPC_S_INVALID_BOUND); \
5504 return NULL; \
5506 TRACE("*ppMemory: %p\n", *ppMemory); \
5507 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5508 pStubMsg->Buffer += sizeof(type); \
5509 } while (0)
5511 switch(base_type)
5513 case RPC_FC_CHAR:
5514 case RPC_FC_SMALL:
5515 RANGE_UNMARSHALL(UCHAR, "%d");
5516 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5517 break;
5518 case RPC_FC_BYTE:
5519 case RPC_FC_USMALL:
5520 RANGE_UNMARSHALL(CHAR, "%u");
5521 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5522 break;
5523 case RPC_FC_WCHAR: /* FIXME: valid? */
5524 case RPC_FC_USHORT:
5525 RANGE_UNMARSHALL(USHORT, "%u");
5526 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5527 break;
5528 case RPC_FC_SHORT:
5529 RANGE_UNMARSHALL(SHORT, "%d");
5530 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5531 break;
5532 case RPC_FC_LONG:
5533 RANGE_UNMARSHALL(LONG, "%d");
5534 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5535 break;
5536 case RPC_FC_ULONG:
5537 RANGE_UNMARSHALL(ULONG, "%u");
5538 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5539 break;
5540 case RPC_FC_ENUM16:
5541 case RPC_FC_ENUM32:
5542 FIXME("Unhandled enum type\n");
5543 break;
5544 case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */
5545 case RPC_FC_FLOAT:
5546 case RPC_FC_DOUBLE:
5547 case RPC_FC_HYPER:
5548 default:
5549 ERR("invalid range base type: 0x%02x\n", base_type);
5550 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5553 return NULL;
5556 /***********************************************************************
5557 * NdrRangeBufferSize [internal]
5559 void WINAPI NdrRangeBufferSize(
5560 PMIDL_STUB_MESSAGE pStubMsg,
5561 unsigned char *pMemory,
5562 PFORMAT_STRING pFormat)
5564 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5565 unsigned char base_type;
5567 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5569 if (pRange->type != RPC_FC_RANGE)
5571 ERR("invalid format type %x\n", pRange->type);
5572 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5574 base_type = pRange->flags_type & 0xf;
5576 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
5579 /***********************************************************************
5580 * NdrRangeMemorySize [internal]
5582 ULONG WINAPI NdrRangeMemorySize(
5583 PMIDL_STUB_MESSAGE pStubMsg,
5584 PFORMAT_STRING pFormat)
5586 NDR_RANGE *pRange = (NDR_RANGE *)pFormat;
5587 unsigned char base_type;
5589 if (pRange->type != RPC_FC_RANGE)
5591 ERR("invalid format type %x\n", pRange->type);
5592 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5593 return 0;
5595 base_type = pRange->flags_type & 0xf;
5597 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
5600 /***********************************************************************
5601 * NdrRangeFree [internal]
5603 void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
5604 unsigned char *pMemory,
5605 PFORMAT_STRING pFormat)
5607 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5609 /* nothing to do */
5612 /***********************************************************************
5613 * NdrBaseTypeMarshall [internal]
5615 static unsigned char *WINAPI NdrBaseTypeMarshall(
5616 PMIDL_STUB_MESSAGE pStubMsg,
5617 unsigned char *pMemory,
5618 PFORMAT_STRING pFormat)
5620 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5622 switch(*pFormat)
5624 case RPC_FC_BYTE:
5625 case RPC_FC_CHAR:
5626 case RPC_FC_SMALL:
5627 case RPC_FC_USMALL:
5628 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
5629 TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
5630 break;
5631 case RPC_FC_WCHAR:
5632 case RPC_FC_SHORT:
5633 case RPC_FC_USHORT:
5634 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
5635 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
5636 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
5637 break;
5638 case RPC_FC_LONG:
5639 case RPC_FC_ULONG:
5640 case RPC_FC_ERROR_STATUS_T:
5641 case RPC_FC_ENUM32:
5642 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG));
5643 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
5644 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
5645 break;
5646 case RPC_FC_FLOAT:
5647 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float));
5648 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
5649 break;
5650 case RPC_FC_DOUBLE:
5651 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double));
5652 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
5653 break;
5654 case RPC_FC_HYPER:
5655 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG));
5656 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
5657 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
5658 break;
5659 case RPC_FC_ENUM16:
5660 /* only 16-bits on the wire, so do a sanity check */
5661 if (*(UINT *)pMemory > SHRT_MAX)
5662 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
5663 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT));
5664 if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5665 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5666 *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
5667 pStubMsg->Buffer += sizeof(USHORT);
5668 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
5669 break;
5670 case RPC_FC_IGNORE:
5671 break;
5672 default:
5673 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5676 /* FIXME: what is the correct return value? */
5677 return NULL;
5680 /***********************************************************************
5681 * NdrBaseTypeUnmarshall [internal]
5683 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
5684 PMIDL_STUB_MESSAGE pStubMsg,
5685 unsigned char **ppMemory,
5686 PFORMAT_STRING pFormat,
5687 unsigned char fMustAlloc)
5689 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
5691 #define BASE_TYPE_UNMARSHALL(type) \
5692 ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
5693 if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
5695 *ppMemory = pStubMsg->Buffer; \
5696 TRACE("*ppMemory: %p\n", *ppMemory); \
5698 else \
5700 if (fMustAlloc) \
5701 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
5702 TRACE("*ppMemory: %p\n", *ppMemory); \
5703 **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
5705 pStubMsg->Buffer += sizeof(type);
5707 switch(*pFormat)
5709 case RPC_FC_BYTE:
5710 case RPC_FC_CHAR:
5711 case RPC_FC_SMALL:
5712 case RPC_FC_USMALL:
5713 BASE_TYPE_UNMARSHALL(UCHAR);
5714 TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
5715 break;
5716 case RPC_FC_WCHAR:
5717 case RPC_FC_SHORT:
5718 case RPC_FC_USHORT:
5719 BASE_TYPE_UNMARSHALL(USHORT);
5720 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
5721 break;
5722 case RPC_FC_LONG:
5723 case RPC_FC_ULONG:
5724 case RPC_FC_ERROR_STATUS_T:
5725 case RPC_FC_ENUM32:
5726 BASE_TYPE_UNMARSHALL(ULONG);
5727 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
5728 break;
5729 case RPC_FC_FLOAT:
5730 BASE_TYPE_UNMARSHALL(float);
5731 TRACE("value: %f\n", **(float **)ppMemory);
5732 break;
5733 case RPC_FC_DOUBLE:
5734 BASE_TYPE_UNMARSHALL(double);
5735 TRACE("value: %f\n", **(double **)ppMemory);
5736 break;
5737 case RPC_FC_HYPER:
5738 BASE_TYPE_UNMARSHALL(ULONGLONG);
5739 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
5740 break;
5741 case RPC_FC_ENUM16:
5742 ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
5743 if (fMustAlloc || !*ppMemory)
5744 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
5745 if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd)
5746 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5747 TRACE("*ppMemory: %p\n", *ppMemory);
5748 /* 16-bits on the wire, but int in memory */
5749 **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
5750 pStubMsg->Buffer += sizeof(USHORT);
5751 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
5752 break;
5753 case RPC_FC_IGNORE:
5754 break;
5755 default:
5756 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5758 #undef BASE_TYPE_UNMARSHALL
5760 /* FIXME: what is the correct return value? */
5762 return NULL;
5765 /***********************************************************************
5766 * NdrBaseTypeBufferSize [internal]
5768 static void WINAPI NdrBaseTypeBufferSize(
5769 PMIDL_STUB_MESSAGE pStubMsg,
5770 unsigned char *pMemory,
5771 PFORMAT_STRING pFormat)
5773 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5775 switch(*pFormat)
5777 case RPC_FC_BYTE:
5778 case RPC_FC_CHAR:
5779 case RPC_FC_SMALL:
5780 case RPC_FC_USMALL:
5781 safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
5782 break;
5783 case RPC_FC_WCHAR:
5784 case RPC_FC_SHORT:
5785 case RPC_FC_USHORT:
5786 case RPC_FC_ENUM16:
5787 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
5788 safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
5789 break;
5790 case RPC_FC_LONG:
5791 case RPC_FC_ULONG:
5792 case RPC_FC_ENUM32:
5793 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
5794 safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
5795 break;
5796 case RPC_FC_FLOAT:
5797 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
5798 safe_buffer_length_increment(pStubMsg, sizeof(float));
5799 break;
5800 case RPC_FC_DOUBLE:
5801 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
5802 safe_buffer_length_increment(pStubMsg, sizeof(double));
5803 break;
5804 case RPC_FC_HYPER:
5805 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
5806 safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
5807 break;
5808 case RPC_FC_ERROR_STATUS_T:
5809 ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
5810 safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
5811 break;
5812 case RPC_FC_IGNORE:
5813 break;
5814 default:
5815 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5819 /***********************************************************************
5820 * NdrBaseTypeMemorySize [internal]
5822 static ULONG WINAPI NdrBaseTypeMemorySize(
5823 PMIDL_STUB_MESSAGE pStubMsg,
5824 PFORMAT_STRING pFormat)
5826 TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
5828 switch(*pFormat)
5830 case RPC_FC_BYTE:
5831 case RPC_FC_CHAR:
5832 case RPC_FC_SMALL:
5833 case RPC_FC_USMALL:
5834 safe_buffer_increment(pStubMsg, sizeof(UCHAR));
5835 pStubMsg->MemorySize += sizeof(UCHAR);
5836 return sizeof(UCHAR);
5837 case RPC_FC_WCHAR:
5838 case RPC_FC_SHORT:
5839 case RPC_FC_USHORT:
5840 safe_buffer_increment(pStubMsg, sizeof(USHORT));
5841 pStubMsg->MemorySize += sizeof(USHORT);
5842 return sizeof(USHORT);
5843 case RPC_FC_LONG:
5844 case RPC_FC_ULONG:
5845 case RPC_FC_ENUM32:
5846 safe_buffer_increment(pStubMsg, sizeof(ULONG));
5847 pStubMsg->MemorySize += sizeof(ULONG);
5848 return sizeof(ULONG);
5849 case RPC_FC_FLOAT:
5850 safe_buffer_increment(pStubMsg, sizeof(float));
5851 pStubMsg->MemorySize += sizeof(float);
5852 return sizeof(float);
5853 case RPC_FC_DOUBLE:
5854 safe_buffer_increment(pStubMsg, sizeof(double));
5855 pStubMsg->MemorySize += sizeof(double);
5856 return sizeof(double);
5857 case RPC_FC_HYPER:
5858 safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
5859 pStubMsg->MemorySize += sizeof(ULONGLONG);
5860 return sizeof(ULONGLONG);
5861 case RPC_FC_ERROR_STATUS_T:
5862 safe_buffer_increment(pStubMsg, sizeof(error_status_t));
5863 pStubMsg->MemorySize += sizeof(error_status_t);
5864 return sizeof(error_status_t);
5865 case RPC_FC_ENUM16:
5866 safe_buffer_increment(pStubMsg, sizeof(USHORT));
5867 pStubMsg->MemorySize += sizeof(UINT);
5868 return sizeof(UINT);
5869 case RPC_FC_IGNORE:
5870 pStubMsg->MemorySize += sizeof(void *);
5871 return sizeof(void *);
5872 default:
5873 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
5874 return 0;
5878 /***********************************************************************
5879 * NdrBaseTypeFree [internal]
5881 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
5882 unsigned char *pMemory,
5883 PFORMAT_STRING pFormat)
5885 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5887 /* nothing to do */
5890 /***********************************************************************
5891 * NdrContextHandleBufferSize [internal]
5893 static void WINAPI NdrContextHandleBufferSize(
5894 PMIDL_STUB_MESSAGE pStubMsg,
5895 unsigned char *pMemory,
5896 PFORMAT_STRING pFormat)
5898 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5900 if (*pFormat != RPC_FC_BIND_CONTEXT)
5902 ERR("invalid format type %x\n", *pFormat);
5903 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5905 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
5906 safe_buffer_length_increment(pStubMsg, cbNDRContext);
5909 /***********************************************************************
5910 * NdrContextHandleMarshall [internal]
5912 static unsigned char *WINAPI NdrContextHandleMarshall(
5913 PMIDL_STUB_MESSAGE pStubMsg,
5914 unsigned char *pMemory,
5915 PFORMAT_STRING pFormat)
5917 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
5919 if (*pFormat != RPC_FC_BIND_CONTEXT)
5921 ERR("invalid format type %x\n", *pFormat);
5922 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5925 if (pFormat[1] & 0x80)
5926 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
5927 else
5928 NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE);
5930 return NULL;
5933 /***********************************************************************
5934 * NdrContextHandleUnmarshall [internal]
5936 static unsigned char *WINAPI NdrContextHandleUnmarshall(
5937 PMIDL_STUB_MESSAGE pStubMsg,
5938 unsigned char **ppMemory,
5939 PFORMAT_STRING pFormat,
5940 unsigned char fMustAlloc)
5942 if (*pFormat != RPC_FC_BIND_CONTEXT)
5944 ERR("invalid format type %x\n", *pFormat);
5945 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5948 **(NDR_CCONTEXT **)ppMemory = NULL;
5949 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
5951 return NULL;
5954 /***********************************************************************
5955 * NdrClientContextMarshall [RPCRT4.@]
5957 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5958 NDR_CCONTEXT ContextHandle,
5959 int fCheck)
5961 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
5963 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
5965 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5967 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
5968 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5969 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5972 /* FIXME: what does fCheck do? */
5973 NDRCContextMarshall(ContextHandle,
5974 pStubMsg->Buffer);
5976 pStubMsg->Buffer += cbNDRContext;
5979 /***********************************************************************
5980 * NdrClientContextUnmarshall [RPCRT4.@]
5982 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5983 NDR_CCONTEXT * pContextHandle,
5984 RPC_BINDING_HANDLE BindHandle)
5986 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
5988 ALIGN_POINTER(pStubMsg->Buffer, 4);
5990 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
5991 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5993 NDRCContextUnmarshall(pContextHandle,
5994 BindHandle,
5995 pStubMsg->Buffer,
5996 pStubMsg->RpcMsg->DataRepresentation);
5998 pStubMsg->Buffer += cbNDRContext;
6001 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6002 NDR_SCONTEXT ContextHandle,
6003 NDR_RUNDOWN RundownRoutine )
6005 FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
6008 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
6010 FIXME("(%p): stub\n", pStubMsg);
6011 return NULL;
6014 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
6015 unsigned char* pMemory,
6016 PFORMAT_STRING pFormat)
6018 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
6021 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
6022 PFORMAT_STRING pFormat)
6024 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
6025 return NULL;
6028 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6029 NDR_SCONTEXT ContextHandle,
6030 NDR_RUNDOWN RundownRoutine,
6031 PFORMAT_STRING pFormat)
6033 FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
6036 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6037 PFORMAT_STRING pFormat)
6039 FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
6040 return NULL;
6043 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e
6045 typedef struct ndr_context_handle
6047 DWORD attributes;
6048 GUID uuid;
6049 } ndr_context_handle;
6051 struct context_handle_entry
6053 struct list entry;
6054 DWORD magic;
6055 RPC_BINDING_HANDLE handle;
6056 ndr_context_handle wire_data;
6059 static struct list context_handle_list = LIST_INIT(context_handle_list);
6061 static CRITICAL_SECTION ndr_context_cs;
6062 static CRITICAL_SECTION_DEBUG ndr_context_debug =
6064 0, 0, &ndr_context_cs,
6065 { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList },
6066 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") }
6068 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 };
6070 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
6072 struct context_handle_entry *che = (struct context_handle_entry*) CContext;
6074 if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
6075 return NULL;
6076 return che;
6079 static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid)
6081 struct context_handle_entry *che;
6082 LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry)
6083 if (IsEqualGUID(&che->wire_data.uuid, uuid))
6084 return che;
6085 return NULL;
6088 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
6090 struct context_handle_entry *che;
6091 RPC_BINDING_HANDLE handle = NULL;
6093 TRACE("%p\n", CContext);
6095 EnterCriticalSection(&ndr_context_cs);
6096 che = get_context_entry(CContext);
6097 if (che)
6098 handle = che->handle;
6099 LeaveCriticalSection(&ndr_context_cs);
6101 if (!handle)
6102 RpcRaiseException(ERROR_INVALID_HANDLE);
6103 return handle;
6106 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
6108 struct context_handle_entry *che;
6110 TRACE("%p %p\n", CContext, pBuff);
6112 if (CContext)
6114 EnterCriticalSection(&ndr_context_cs);
6115 che = get_context_entry(CContext);
6116 memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle));
6117 LeaveCriticalSection(&ndr_context_cs);
6119 else
6121 ndr_context_handle *wire_data = (ndr_context_handle *)pBuff;
6122 wire_data->attributes = 0;
6123 wire_data->uuid = GUID_NULL;
6127 /***********************************************************************
6128 * RpcSmDestroyClientContext [RPCRT4.@]
6130 RPC_STATUS WINAPI RpcSmDestroyClientContext(void **ContextHandle)
6132 RPC_STATUS status = RPC_X_SS_CONTEXT_MISMATCH;
6133 struct context_handle_entry *che = NULL;
6135 TRACE("(%p)\n", ContextHandle);
6137 EnterCriticalSection(&ndr_context_cs);
6138 che = get_context_entry(*ContextHandle);
6139 *ContextHandle = NULL;
6140 if (che)
6142 status = RPC_S_OK;
6143 list_remove(&che->entry);
6146 LeaveCriticalSection(&ndr_context_cs);
6148 if (che)
6150 RpcBindingFree(&che->handle);
6151 HeapFree(GetProcessHeap(), 0, che);
6154 return status;
6157 /***********************************************************************
6158 * RpcSsDestroyClientContext [RPCRT4.@]
6160 void WINAPI RpcSsDestroyClientContext(void **ContextHandle)
6162 RPC_STATUS status = RpcSmDestroyClientContext(ContextHandle);
6163 if (status != RPC_S_OK)
6164 RpcRaiseException(status);
6167 static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext,
6168 RPC_BINDING_HANDLE hBinding,
6169 const ndr_context_handle *chi)
6171 struct context_handle_entry *che = NULL;
6173 /* a null UUID means we should free the context handle */
6174 if (IsEqualGUID(&chi->uuid, &GUID_NULL))
6176 if (*CContext)
6178 che = get_context_entry(*CContext);
6179 if (!che)
6180 return ERROR_INVALID_HANDLE;
6181 list_remove(&che->entry);
6182 RpcBindingFree(&che->handle);
6183 HeapFree(GetProcessHeap(), 0, che);
6184 che = NULL;
6187 /* if there's no existing entry matching the GUID, allocate one */
6188 else if (!(che = context_entry_from_guid(&chi->uuid)))
6190 che = HeapAlloc(GetProcessHeap(), 0, sizeof *che);
6191 if (!che)
6192 return ERROR_NOT_ENOUGH_MEMORY;
6193 che->magic = NDR_CONTEXT_HANDLE_MAGIC;
6194 RpcBindingCopy(hBinding, &che->handle);
6195 list_add_tail(&context_handle_list, &che->entry);
6196 memcpy(&che->wire_data, chi, sizeof *chi);
6199 *CContext = che;
6201 return ERROR_SUCCESS;
6204 /***********************************************************************
6205 * NDRCContextUnmarshall [RPCRT4.@]
6207 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext,
6208 RPC_BINDING_HANDLE hBinding,
6209 void *pBuff, ULONG DataRepresentation)
6211 UINT r;
6213 TRACE("*%p=(%p) %p %p %08x\n",
6214 CContext, *CContext, hBinding, pBuff, DataRepresentation);
6216 EnterCriticalSection(&ndr_context_cs);
6217 r = ndr_update_context_handle(CContext, hBinding, pBuff);
6218 LeaveCriticalSection(&ndr_context_cs);
6219 if (r)
6220 RpcRaiseException(r);
6223 /***********************************************************************
6224 * NDRSContextMarshall [RPCRT4.@]
6226 void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext,
6227 void *pBuff,
6228 NDR_RUNDOWN userRunDownIn)
6230 FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn);
6233 /***********************************************************************
6234 * NDRSContextMarshallEx [RPCRT4.@]
6236 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding,
6237 NDR_SCONTEXT CContext,
6238 void *pBuff,
6239 NDR_RUNDOWN userRunDownIn)
6241 FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn);
6244 /***********************************************************************
6245 * NDRSContextMarshall2 [RPCRT4.@]
6247 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
6248 NDR_SCONTEXT CContext,
6249 void *pBuff,
6250 NDR_RUNDOWN userRunDownIn,
6251 void *CtxGuard, ULONG Flags)
6253 FIXME("(%p %p %p %p %p %u): stub\n",
6254 hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags);
6257 /***********************************************************************
6258 * NDRSContextUnmarshall [RPCRT4.@]
6260 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff,
6261 ULONG DataRepresentation)
6263 FIXME("(%p %08x): stub\n", pBuff, DataRepresentation);
6264 return NULL;
6267 /***********************************************************************
6268 * NDRSContextUnmarshallEx [RPCRT4.@]
6270 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding,
6271 void *pBuff,
6272 ULONG DataRepresentation)
6274 FIXME("(%p %p %08x): stub\n", hBinding, pBuff, DataRepresentation);
6275 return NULL;
6278 /***********************************************************************
6279 * NDRSContextUnmarshall2 [RPCRT4.@]
6281 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
6282 void *pBuff,
6283 ULONG DataRepresentation,
6284 void *CtxGuard, ULONG Flags)
6286 FIXME("(%p %p %08x %p %u): stub\n",
6287 hBinding, pBuff, DataRepresentation, CtxGuard, Flags);
6288 return NULL;