Sync with trunk r58033.
[reactos.git] / dll / win32 / rpcrt4 / ndr_marshall.c
1 /*
2 * NDR data marshalling
3 *
4 * Copyright 2002 Greg Turner
5 * Copyright 2003-2006 CodeWeavers
6 *
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.
11 *
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.
16 *
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
20 *
21 * TODO:
22 * - String structs
23 * - Byte count pointers
24 * - transmit_as/represent as
25 * - Multi-dimensional arrays
26 * - Conversion functions (NdrConvert)
27 * - Checks for integer addition overflow in user marshall functions
28 */
29
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <limits.h>
35
36 #define NONAMELESSUNION
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winerror.h"
40
41 #include "ndr_misc.h"
42 #include "rpcndr.h"
43 #include "ndrtypes.h"
44
45 #include "wine/unicode.h"
46 #include "wine/rpcfc.h"
47
48 #include "wine/debug.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(ole);
51
52 #if defined(__i386__)
53 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
54 (*((UINT32 *)(pchar)) = (uint32))
55
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
66 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
67 (MAKELONG( \
68 MAKEWORD(*(pchar), *((pchar)+1)), \
69 MAKEWORD(*((pchar)+2), *((pchar)+3))))
70 #endif
71
72 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
73 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
74 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
75 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
76 *(pchar) = HIBYTE(HIWORD(uint32)))
77
78 #define BIG_ENDIAN_UINT32_READ(pchar) \
79 (MAKELONG( \
80 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
81 MAKEWORD(*((pchar)+1), *(pchar))))
82
83 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
84 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
85 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
86 # define NDR_LOCAL_UINT32_READ(pchar) \
87 BIG_ENDIAN_UINT32_READ(pchar)
88 #else
89 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
90 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
91 # define NDR_LOCAL_UINT32_READ(pchar) \
92 LITTLE_ENDIAN_UINT32_READ(pchar)
93 #endif
94
95 static inline void align_length( ULONG *len, unsigned int align )
96 {
97 *len = (*len + align - 1) & ~(align - 1);
98 }
99
100 static inline void align_pointer( unsigned char **ptr, unsigned int align )
101 {
102 ULONG_PTR mask = align - 1;
103 *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
104 }
105
106 static inline void align_pointer_clear( unsigned char **ptr, unsigned int align )
107 {
108 ULONG_PTR mask = align - 1;
109 memset( *ptr, 0, (align - (ULONG_PTR)*ptr) & mask );
110 *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
111 }
112
113 #define STD_OVERFLOW_CHECK(_Msg) do { \
114 TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
115 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
116 ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
117 } while (0)
118
119 #define NDR_POINTER_ID_BASE 0x20000
120 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
121 #define NDR_TABLE_SIZE 128
122 #define NDR_TABLE_MASK 127
123
124 #define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL))
125
126 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
127 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
128 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
129 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
130 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
131
132 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
133 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
134 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
135
136 static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
137 static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
138 static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
139 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
140
141 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
142
143 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
144 unsigned char *pMemory,
145 PFORMAT_STRING pFormat,
146 PFORMAT_STRING pPointer);
147 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
148 unsigned char *pMemory,
149 PFORMAT_STRING pFormat,
150 PFORMAT_STRING pPointer);
151 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
152 unsigned char *pMemory,
153 PFORMAT_STRING pFormat,
154 PFORMAT_STRING pPointer,
155 unsigned char fMustAlloc);
156 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
157 PFORMAT_STRING pFormat,
158 PFORMAT_STRING pPointer);
159 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
160 unsigned char *pMemory,
161 PFORMAT_STRING pFormat,
162 PFORMAT_STRING pPointer);
163
164 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
165 0,
166 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
167 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
168 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
169 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
170 /* 0x10 */
171 NdrBaseTypeMarshall,
172 /* 0x11 */
173 NdrPointerMarshall, NdrPointerMarshall,
174 NdrPointerMarshall, NdrPointerMarshall,
175 /* 0x15 */
176 NdrSimpleStructMarshall, NdrSimpleStructMarshall,
177 NdrConformantStructMarshall, NdrConformantStructMarshall,
178 NdrConformantVaryingStructMarshall,
179 NdrComplexStructMarshall,
180 /* 0x1b */
181 NdrConformantArrayMarshall,
182 NdrConformantVaryingArrayMarshall,
183 NdrFixedArrayMarshall, NdrFixedArrayMarshall,
184 NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
185 NdrComplexArrayMarshall,
186 /* 0x22 */
187 NdrConformantStringMarshall, 0, 0,
188 NdrConformantStringMarshall,
189 NdrNonConformantStringMarshall, 0, 0, 0,
190 /* 0x2a */
191 NdrEncapsulatedUnionMarshall,
192 NdrNonEncapsulatedUnionMarshall,
193 NdrByteCountPointerMarshall,
194 NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
195 /* 0x2f */
196 NdrInterfacePointerMarshall,
197 /* 0x30 */
198 NdrContextHandleMarshall,
199 /* 0xb1 */
200 0, 0, 0,
201 NdrUserMarshalMarshall,
202 0, 0,
203 /* 0xb7 */
204 NdrRangeMarshall
205 };
206 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
207 0,
208 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
209 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
210 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
211 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
212 /* 0x10 */
213 NdrBaseTypeUnmarshall,
214 /* 0x11 */
215 NdrPointerUnmarshall, NdrPointerUnmarshall,
216 NdrPointerUnmarshall, NdrPointerUnmarshall,
217 /* 0x15 */
218 NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
219 NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
220 NdrConformantVaryingStructUnmarshall,
221 NdrComplexStructUnmarshall,
222 /* 0x1b */
223 NdrConformantArrayUnmarshall,
224 NdrConformantVaryingArrayUnmarshall,
225 NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
226 NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
227 NdrComplexArrayUnmarshall,
228 /* 0x22 */
229 NdrConformantStringUnmarshall, 0, 0,
230 NdrConformantStringUnmarshall,
231 NdrNonConformantStringUnmarshall, 0, 0, 0,
232 /* 0x2a */
233 NdrEncapsulatedUnionUnmarshall,
234 NdrNonEncapsulatedUnionUnmarshall,
235 NdrByteCountPointerUnmarshall,
236 NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
237 /* 0x2f */
238 NdrInterfacePointerUnmarshall,
239 /* 0x30 */
240 NdrContextHandleUnmarshall,
241 /* 0xb1 */
242 0, 0, 0,
243 NdrUserMarshalUnmarshall,
244 0, 0,
245 /* 0xb7 */
246 NdrRangeUnmarshall
247 };
248 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
249 0,
250 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
251 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
252 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
253 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
254 /* 0x10 */
255 NdrBaseTypeBufferSize,
256 /* 0x11 */
257 NdrPointerBufferSize, NdrPointerBufferSize,
258 NdrPointerBufferSize, NdrPointerBufferSize,
259 /* 0x15 */
260 NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
261 NdrConformantStructBufferSize, NdrConformantStructBufferSize,
262 NdrConformantVaryingStructBufferSize,
263 NdrComplexStructBufferSize,
264 /* 0x1b */
265 NdrConformantArrayBufferSize,
266 NdrConformantVaryingArrayBufferSize,
267 NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
268 NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
269 NdrComplexArrayBufferSize,
270 /* 0x22 */
271 NdrConformantStringBufferSize, 0, 0,
272 NdrConformantStringBufferSize,
273 NdrNonConformantStringBufferSize, 0, 0, 0,
274 /* 0x2a */
275 NdrEncapsulatedUnionBufferSize,
276 NdrNonEncapsulatedUnionBufferSize,
277 NdrByteCountPointerBufferSize,
278 NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
279 /* 0x2f */
280 NdrInterfacePointerBufferSize,
281 /* 0x30 */
282 NdrContextHandleBufferSize,
283 /* 0xb1 */
284 0, 0, 0,
285 NdrUserMarshalBufferSize,
286 0, 0,
287 /* 0xb7 */
288 NdrRangeBufferSize
289 };
290 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
291 0,
292 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
293 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
294 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
295 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
296 /* 0x10 */
297 NdrBaseTypeMemorySize,
298 /* 0x11 */
299 NdrPointerMemorySize, NdrPointerMemorySize,
300 NdrPointerMemorySize, NdrPointerMemorySize,
301 /* 0x15 */
302 NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
303 NdrConformantStructMemorySize, NdrConformantStructMemorySize,
304 NdrConformantVaryingStructMemorySize,
305 NdrComplexStructMemorySize,
306 /* 0x1b */
307 NdrConformantArrayMemorySize,
308 NdrConformantVaryingArrayMemorySize,
309 NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
310 NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
311 NdrComplexArrayMemorySize,
312 /* 0x22 */
313 NdrConformantStringMemorySize, 0, 0,
314 NdrConformantStringMemorySize,
315 NdrNonConformantStringMemorySize, 0, 0, 0,
316 /* 0x2a */
317 NdrEncapsulatedUnionMemorySize,
318 NdrNonEncapsulatedUnionMemorySize,
319 NdrByteCountPointerMemorySize,
320 NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
321 /* 0x2f */
322 NdrInterfacePointerMemorySize,
323 /* 0x30 */
324 0,
325 /* 0xb1 */
326 0, 0, 0,
327 NdrUserMarshalMemorySize,
328 0, 0,
329 /* 0xb7 */
330 NdrRangeMemorySize
331 };
332 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
333 0,
334 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
335 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
336 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
337 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
338 /* 0x10 */
339 NdrBaseTypeFree,
340 /* 0x11 */
341 NdrPointerFree, NdrPointerFree,
342 NdrPointerFree, NdrPointerFree,
343 /* 0x15 */
344 NdrSimpleStructFree, NdrSimpleStructFree,
345 NdrConformantStructFree, NdrConformantStructFree,
346 NdrConformantVaryingStructFree,
347 NdrComplexStructFree,
348 /* 0x1b */
349 NdrConformantArrayFree,
350 NdrConformantVaryingArrayFree,
351 NdrFixedArrayFree, NdrFixedArrayFree,
352 NdrVaryingArrayFree, NdrVaryingArrayFree,
353 NdrComplexArrayFree,
354 /* 0x22 */
355 0, 0, 0,
356 0, 0, 0, 0, 0,
357 /* 0x2a */
358 NdrEncapsulatedUnionFree,
359 NdrNonEncapsulatedUnionFree,
360 0,
361 NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
362 /* 0x2f */
363 NdrInterfacePointerFree,
364 /* 0x30 */
365 0,
366 /* 0xb1 */
367 0, 0, 0,
368 NdrUserMarshalFree,
369 0, 0,
370 /* 0xb7 */
371 NdrRangeFree
372 };
373
374 typedef struct _NDR_MEMORY_LIST
375 {
376 ULONG magic;
377 ULONG size;
378 ULONG reserved;
379 struct _NDR_MEMORY_LIST *next;
380 } NDR_MEMORY_LIST;
381
382 #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
383
384 /***********************************************************************
385 * NdrAllocate [RPCRT4.@]
386 *
387 * Allocates a block of memory using pStubMsg->pfnAllocate.
388 *
389 * PARAMS
390 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
391 * len [I] Size of memory block to allocate.
392 *
393 * RETURNS
394 * The memory block of size len that was allocated.
395 *
396 * NOTES
397 * The memory block is always 8-byte aligned.
398 * If the function is unable to allocate memory an ERROR_OUTOFMEMORY
399 * exception is raised.
400 */
401 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len)
402 {
403 SIZE_T aligned_len;
404 SIZE_T adjusted_len;
405 void *p;
406 NDR_MEMORY_LIST *mem_list;
407
408 aligned_len = (len + 7) & ~7;
409 adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
410 /* check for overflow */
411 if (adjusted_len < len)
412 {
413 ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len);
414 RpcRaiseException(RPC_X_BAD_STUB_DATA);
415 }
416
417 p = pStubMsg->pfnAllocate(adjusted_len);
418 if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
419
420 mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
421 mem_list->magic = MEML_MAGIC;
422 mem_list->size = aligned_len;
423 mem_list->reserved = 0;
424 mem_list->next = pStubMsg->pMemoryList;
425 pStubMsg->pMemoryList = mem_list;
426
427 TRACE("-- %p\n", p);
428 return p;
429 }
430
431 static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
432 {
433 TRACE("(%p, %p)\n", pStubMsg, Pointer);
434
435 pStubMsg->pfnFree(Pointer);
436 }
437
438 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
439 {
440 return (*(const ULONG *)pFormat != -1);
441 }
442
443 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
444 {
445 align_pointer(&pStubMsg->Buffer, 4);
446 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
447 RpcRaiseException(RPC_X_BAD_STUB_DATA);
448 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
449 pStubMsg->Buffer += 4;
450 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
451 if (pStubMsg->fHasNewCorrDesc)
452 return pFormat+6;
453 else
454 return pFormat+4;
455 }
456
457 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
458 {
459 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
460 {
461 pStubMsg->Offset = 0;
462 pStubMsg->ActualCount = pStubMsg->MaxCount;
463 goto done;
464 }
465
466 align_pointer(&pStubMsg->Buffer, 4);
467 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
468 RpcRaiseException(RPC_X_BAD_STUB_DATA);
469 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
470 pStubMsg->Buffer += 4;
471 TRACE("offset is %d\n", pStubMsg->Offset);
472 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
473 pStubMsg->Buffer += 4;
474 TRACE("variance is %d\n", pStubMsg->ActualCount);
475
476 if ((pStubMsg->ActualCount > MaxValue) ||
477 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
478 {
479 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
480 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
481 RpcRaiseException(RPC_S_INVALID_BOUND);
482 return NULL;
483 }
484
485 done:
486 if (pStubMsg->fHasNewCorrDesc)
487 return pFormat+6;
488 else
489 return pFormat+4;
490 }
491
492 /* writes the conformance value to the buffer */
493 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
494 {
495 align_pointer_clear(&pStubMsg->Buffer, 4);
496 if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
497 RpcRaiseException(RPC_X_BAD_STUB_DATA);
498 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
499 pStubMsg->Buffer += 4;
500 }
501
502 /* writes the variance values to the buffer */
503 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
504 {
505 align_pointer_clear(&pStubMsg->Buffer, 4);
506 if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
507 RpcRaiseException(RPC_X_BAD_STUB_DATA);
508 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
509 pStubMsg->Buffer += 4;
510 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
511 pStubMsg->Buffer += 4;
512 }
513
514 /* requests buffer space for the conformance value */
515 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
516 {
517 align_length(&pStubMsg->BufferLength, 4);
518 if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
519 RpcRaiseException(RPC_X_BAD_STUB_DATA);
520 pStubMsg->BufferLength += 4;
521 }
522
523 /* requests buffer space for the variance values */
524 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
525 {
526 align_length(&pStubMsg->BufferLength, 4);
527 if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
528 RpcRaiseException(RPC_X_BAD_STUB_DATA);
529 pStubMsg->BufferLength += 8;
530 }
531
532 PFORMAT_STRING ComputeConformanceOrVariance(
533 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
534 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
535 {
536 BYTE dtype = pFormat[0] & 0xf;
537 short ofs = *(const short *)&pFormat[2];
538 LPVOID ptr = NULL;
539 ULONG_PTR data = 0;
540
541 if (!IsConformanceOrVariancePresent(pFormat)) {
542 /* null descriptor */
543 *pCount = def;
544 goto finish_conf;
545 }
546
547 switch (pFormat[0] & 0xf0) {
548 case RPC_FC_NORMAL_CONFORMANCE:
549 TRACE("normal conformance, ofs=%d\n", ofs);
550 ptr = pMemory;
551 break;
552 case RPC_FC_POINTER_CONFORMANCE:
553 TRACE("pointer conformance, ofs=%d\n", ofs);
554 ptr = pStubMsg->Memory;
555 break;
556 case RPC_FC_TOP_LEVEL_CONFORMANCE:
557 TRACE("toplevel conformance, ofs=%d\n", ofs);
558 if (pStubMsg->StackTop) {
559 ptr = pStubMsg->StackTop;
560 }
561 else {
562 /* -Os mode, *pCount is already set */
563 goto finish_conf;
564 }
565 break;
566 case RPC_FC_CONSTANT_CONFORMANCE:
567 data = ofs | ((DWORD)pFormat[1] << 16);
568 TRACE("constant conformance, val=%ld\n", data);
569 *pCount = data;
570 goto finish_conf;
571 case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
572 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
573 if (pStubMsg->StackTop) {
574 ptr = pStubMsg->StackTop;
575 }
576 else {
577 /* ? */
578 goto done_conf_grab;
579 }
580 break;
581 default:
582 FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0);
583 goto finish_conf;
584 }
585
586 switch (pFormat[1]) {
587 case RPC_FC_DEREFERENCE:
588 ptr = *(LPVOID*)((char *)ptr + ofs);
589 break;
590 case RPC_FC_CALLBACK:
591 {
592 unsigned char *old_stack_top = pStubMsg->StackTop;
593 ULONG_PTR max_count, old_max_count = pStubMsg->MaxCount;
594
595 pStubMsg->StackTop = ptr;
596
597 /* ofs is index into StubDesc->apfnExprEval */
598 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
599 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
600
601 pStubMsg->StackTop = old_stack_top;
602
603 /* the callback function always stores the computed value in MaxCount */
604 max_count = pStubMsg->MaxCount;
605 pStubMsg->MaxCount = old_max_count;
606 *pCount = max_count;
607 goto finish_conf;
608 }
609 default:
610 ptr = (char *)ptr + ofs;
611 break;
612 }
613
614 switch (dtype) {
615 case RPC_FC_LONG:
616 case RPC_FC_ULONG:
617 data = *(DWORD*)ptr;
618 break;
619 case RPC_FC_SHORT:
620 data = *(SHORT*)ptr;
621 break;
622 case RPC_FC_USHORT:
623 data = *(USHORT*)ptr;
624 break;
625 case RPC_FC_CHAR:
626 case RPC_FC_SMALL:
627 data = *(CHAR*)ptr;
628 break;
629 case RPC_FC_BYTE:
630 case RPC_FC_USMALL:
631 data = *(UCHAR*)ptr;
632 break;
633 case RPC_FC_HYPER:
634 data = *(ULONGLONG *)ptr;
635 break;
636 default:
637 FIXME("unknown conformance data type %x\n", dtype);
638 goto done_conf_grab;
639 }
640 TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);
641
642 done_conf_grab:
643 switch (pFormat[1]) {
644 case RPC_FC_DEREFERENCE: /* already handled */
645 case 0: /* no op */
646 *pCount = data;
647 break;
648 case RPC_FC_ADD_1:
649 *pCount = data + 1;
650 break;
651 case RPC_FC_SUB_1:
652 *pCount = data - 1;
653 break;
654 case RPC_FC_MULT_2:
655 *pCount = data * 2;
656 break;
657 case RPC_FC_DIV_2:
658 *pCount = data / 2;
659 break;
660 default:
661 FIXME("unknown conformance op %d\n", pFormat[1]);
662 goto finish_conf;
663 }
664
665 finish_conf:
666 TRACE("resulting conformance is %ld\n", *pCount);
667 if (pStubMsg->fHasNewCorrDesc)
668 return pFormat+6;
669 else
670 return pFormat+4;
671 }
672
673 static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg,
674 PFORMAT_STRING pFormat)
675 {
676 if (pStubMsg->fHasNewCorrDesc)
677 pFormat += 6;
678 else
679 pFormat += 4;
680 return pFormat;
681 }
682
683 static inline PFORMAT_STRING SkipVariance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
684 {
685 return SkipConformance( pStubMsg, pFormat );
686 }
687
688 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
689 * the result overflows 32-bits */
690 static inline ULONG safe_multiply(ULONG a, ULONG b)
691 {
692 ULONGLONG ret = (ULONGLONG)a * b;
693 if (ret > 0xffffffff)
694 {
695 RpcRaiseException(RPC_S_INVALID_BOUND);
696 return 0;
697 }
698 return ret;
699 }
700
701 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
702 {
703 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
704 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
705 RpcRaiseException(RPC_X_BAD_STUB_DATA);
706 pStubMsg->Buffer += size;
707 }
708
709 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
710 {
711 if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
712 {
713 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
714 pStubMsg->BufferLength, size);
715 RpcRaiseException(RPC_X_BAD_STUB_DATA);
716 }
717 pStubMsg->BufferLength += size;
718 }
719
720 /* copies data from the buffer, checking that there is enough data in the buffer
721 * to do so */
722 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
723 {
724 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
725 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
726 {
727 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
728 pStubMsg->Buffer, pStubMsg->BufferEnd, size);
729 RpcRaiseException(RPC_X_BAD_STUB_DATA);
730 }
731 if (p == pStubMsg->Buffer)
732 ERR("pointer is the same as the buffer\n");
733 memcpy(p, pStubMsg->Buffer, size);
734 pStubMsg->Buffer += size;
735 }
736
737 /* copies data to the buffer, checking that there is enough space to do so */
738 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
739 {
740 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
741 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
742 {
743 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
744 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
745 size);
746 RpcRaiseException(RPC_X_BAD_STUB_DATA);
747 }
748 memcpy(pStubMsg->Buffer, p, size);
749 pStubMsg->Buffer += size;
750 }
751
752 /* verify that string data sitting in the buffer is valid and safe to
753 * unmarshall */
754 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
755 {
756 ULONG i;
757
758 /* verify the buffer is safe to access */
759 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
760 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
761 {
762 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
763 pStubMsg->BufferEnd, pStubMsg->Buffer);
764 RpcRaiseException(RPC_X_BAD_STUB_DATA);
765 }
766
767 /* strings must always have null terminating bytes */
768 if (bufsize < esize)
769 {
770 ERR("invalid string length of %d\n", bufsize / esize);
771 RpcRaiseException(RPC_S_INVALID_BOUND);
772 }
773
774 for (i = bufsize - esize; i < bufsize; i++)
775 if (pStubMsg->Buffer[i] != 0)
776 {
777 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
778 i, pStubMsg->Buffer[i]);
779 RpcRaiseException(RPC_S_INVALID_BOUND);
780 }
781 }
782
783 static inline void dump_pointer_attr(unsigned char attr)
784 {
785 if (attr & RPC_FC_P_ALLOCALLNODES)
786 TRACE(" RPC_FC_P_ALLOCALLNODES");
787 if (attr & RPC_FC_P_DONTFREE)
788 TRACE(" RPC_FC_P_DONTFREE");
789 if (attr & RPC_FC_P_ONSTACK)
790 TRACE(" RPC_FC_P_ONSTACK");
791 if (attr & RPC_FC_P_SIMPLEPOINTER)
792 TRACE(" RPC_FC_P_SIMPLEPOINTER");
793 if (attr & RPC_FC_P_DEREF)
794 TRACE(" RPC_FC_P_DEREF");
795 TRACE("\n");
796 }
797
798 /***********************************************************************
799 * PointerMarshall [internal]
800 */
801 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
802 unsigned char *Buffer,
803 unsigned char *Pointer,
804 PFORMAT_STRING pFormat)
805 {
806 unsigned type = pFormat[0], attr = pFormat[1];
807 PFORMAT_STRING desc;
808 NDR_MARSHALL m;
809 ULONG pointer_id;
810 int pointer_needs_marshaling;
811
812 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
813 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
814 pFormat += 2;
815 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
816 else desc = pFormat + *(const SHORT*)pFormat;
817
818 switch (type) {
819 case RPC_FC_RP: /* ref pointer (always non-null) */
820 if (!Pointer)
821 {
822 ERR("NULL ref pointer is not allowed\n");
823 RpcRaiseException(RPC_X_NULL_REF_POINTER);
824 }
825 pointer_needs_marshaling = 1;
826 break;
827 case RPC_FC_UP: /* unique pointer */
828 case RPC_FC_OP: /* object pointer - same as unique here */
829 if (Pointer)
830 pointer_needs_marshaling = 1;
831 else
832 pointer_needs_marshaling = 0;
833 pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
834 TRACE("writing 0x%08x to buffer\n", pointer_id);
835 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
836 break;
837 case RPC_FC_FP:
838 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
839 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
840 TRACE("writing 0x%08x to buffer\n", pointer_id);
841 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
842 break;
843 default:
844 FIXME("unhandled ptr type=%02x\n", type);
845 RpcRaiseException(RPC_X_BAD_STUB_DATA);
846 return;
847 }
848
849 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
850
851 if (pointer_needs_marshaling) {
852 if (attr & RPC_FC_P_DEREF) {
853 Pointer = *(unsigned char**)Pointer;
854 TRACE("deref => %p\n", Pointer);
855 }
856 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
857 if (m) m(pStubMsg, Pointer, desc);
858 else FIXME("no marshaller for data type=%02x\n", *desc);
859 }
860
861 STD_OVERFLOW_CHECK(pStubMsg);
862 }
863
864 /***********************************************************************
865 * PointerUnmarshall [internal]
866 */
867 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
868 unsigned char *Buffer,
869 unsigned char **pPointer,
870 unsigned char *pSrcPointer,
871 PFORMAT_STRING pFormat,
872 unsigned char fMustAlloc)
873 {
874 unsigned type = pFormat[0], attr = pFormat[1];
875 PFORMAT_STRING desc;
876 NDR_UNMARSHALL m;
877 DWORD pointer_id = 0;
878 int pointer_needs_unmarshaling;
879
880 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
881 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
882 pFormat += 2;
883 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
884 else desc = pFormat + *(const SHORT*)pFormat;
885
886 switch (type) {
887 case RPC_FC_RP: /* ref pointer (always non-null) */
888 pointer_needs_unmarshaling = 1;
889 break;
890 case RPC_FC_UP: /* unique pointer */
891 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
892 TRACE("pointer_id is 0x%08x\n", pointer_id);
893 if (pointer_id)
894 pointer_needs_unmarshaling = 1;
895 else {
896 *pPointer = NULL;
897 pointer_needs_unmarshaling = 0;
898 }
899 break;
900 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
901 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
902 TRACE("pointer_id is 0x%08x\n", pointer_id);
903 if (!fMustAlloc && pSrcPointer)
904 {
905 FIXME("free object pointer %p\n", pSrcPointer);
906 fMustAlloc = TRUE;
907 }
908 if (pointer_id)
909 pointer_needs_unmarshaling = 1;
910 else
911 {
912 *pPointer = NULL;
913 pointer_needs_unmarshaling = 0;
914 }
915 break;
916 case RPC_FC_FP:
917 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
918 TRACE("pointer_id is 0x%08x\n", pointer_id);
919 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
920 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
921 break;
922 default:
923 FIXME("unhandled ptr type=%02x\n", type);
924 RpcRaiseException(RPC_X_BAD_STUB_DATA);
925 return;
926 }
927
928 if (pointer_needs_unmarshaling) {
929 unsigned char **current_ptr = pPointer;
930 if (pStubMsg->IsClient) {
931 TRACE("client\n");
932 /* if we aren't forcing allocation of memory then try to use the existing
933 * (source) pointer to unmarshall the data into so that [in,out]
934 * parameters behave correctly. it doesn't matter if the parameter is
935 * [out] only since in that case the pointer will be NULL. we force
936 * allocation when the source pointer is NULL here instead of in the type
937 * unmarshalling routine for the benefit of the deref code below */
938 if (!fMustAlloc) {
939 if (pSrcPointer) {
940 TRACE("setting *pPointer to %p\n", pSrcPointer);
941 *pPointer = pSrcPointer;
942 } else
943 fMustAlloc = TRUE;
944 }
945 } else {
946 TRACE("server\n");
947 /* the memory in a stub is never initialised, so we have to work out here
948 * whether we have to initialise it so we can use the optimisation of
949 * setting the pointer to the buffer, if possible, or set fMustAlloc to
950 * TRUE. */
951 if (attr & RPC_FC_P_DEREF) {
952 fMustAlloc = TRUE;
953 } else {
954 *current_ptr = NULL;
955 }
956 }
957
958 if (attr & RPC_FC_P_ALLOCALLNODES)
959 FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
960
961 if (attr & RPC_FC_P_DEREF) {
962 if (fMustAlloc) {
963 unsigned char *base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
964 *pPointer = base_ptr_val;
965 current_ptr = (unsigned char **)base_ptr_val;
966 } else
967 current_ptr = *(unsigned char***)current_ptr;
968 TRACE("deref => %p\n", current_ptr);
969 if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
970 }
971 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
972 if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
973 else FIXME("no unmarshaller for data type=%02x\n", *desc);
974
975 if (type == RPC_FC_FP)
976 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
977 *pPointer);
978 }
979
980 TRACE("pointer=%p\n", *pPointer);
981 }
982
983 /***********************************************************************
984 * PointerBufferSize [internal]
985 */
986 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
987 unsigned char *Pointer,
988 PFORMAT_STRING pFormat)
989 {
990 unsigned type = pFormat[0], attr = pFormat[1];
991 PFORMAT_STRING desc;
992 NDR_BUFFERSIZE m;
993 int pointer_needs_sizing;
994 ULONG pointer_id;
995
996 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
997 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
998 pFormat += 2;
999 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1000 else desc = pFormat + *(const SHORT*)pFormat;
1001
1002 switch (type) {
1003 case RPC_FC_RP: /* ref pointer (always non-null) */
1004 if (!Pointer)
1005 {
1006 ERR("NULL ref pointer is not allowed\n");
1007 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1008 }
1009 break;
1010 case RPC_FC_OP:
1011 case RPC_FC_UP:
1012 /* NULL pointer has no further representation */
1013 if (!Pointer)
1014 return;
1015 break;
1016 case RPC_FC_FP:
1017 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1018 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1019 if (!pointer_needs_sizing)
1020 return;
1021 break;
1022 default:
1023 FIXME("unhandled ptr type=%02x\n", type);
1024 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1025 return;
1026 }
1027
1028 if (attr & RPC_FC_P_DEREF) {
1029 Pointer = *(unsigned char**)Pointer;
1030 TRACE("deref => %p\n", Pointer);
1031 }
1032
1033 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1034 if (m) m(pStubMsg, Pointer, desc);
1035 else FIXME("no buffersizer for data type=%02x\n", *desc);
1036 }
1037
1038 /***********************************************************************
1039 * PointerMemorySize [internal]
1040 */
1041 static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1042 unsigned char *Buffer, PFORMAT_STRING pFormat)
1043 {
1044 unsigned type = pFormat[0], attr = pFormat[1];
1045 PFORMAT_STRING desc;
1046 NDR_MEMORYSIZE m;
1047 DWORD pointer_id = 0;
1048 int pointer_needs_sizing;
1049
1050 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1051 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1052 pFormat += 2;
1053 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1054 else desc = pFormat + *(const SHORT*)pFormat;
1055
1056 switch (type) {
1057 case RPC_FC_RP: /* ref pointer (always non-null) */
1058 pointer_needs_sizing = 1;
1059 break;
1060 case RPC_FC_UP: /* unique pointer */
1061 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1062 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1063 TRACE("pointer_id is 0x%08x\n", pointer_id);
1064 if (pointer_id)
1065 pointer_needs_sizing = 1;
1066 else
1067 pointer_needs_sizing = 0;
1068 break;
1069 case RPC_FC_FP:
1070 {
1071 void *pointer;
1072 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1073 TRACE("pointer_id is 0x%08x\n", pointer_id);
1074 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1075 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1076 break;
1077 }
1078 default:
1079 FIXME("unhandled ptr type=%02x\n", type);
1080 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1081 return 0;
1082 }
1083
1084 if (attr & RPC_FC_P_DEREF) {
1085 align_length(&pStubMsg->MemorySize, sizeof(void*));
1086 pStubMsg->MemorySize += sizeof(void*);
1087 TRACE("deref\n");
1088 }
1089
1090 if (pointer_needs_sizing) {
1091 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1092 if (m) m(pStubMsg, desc);
1093 else FIXME("no memorysizer for data type=%02x\n", *desc);
1094 }
1095
1096 return pStubMsg->MemorySize;
1097 }
1098
1099 /***********************************************************************
1100 * PointerFree [internal]
1101 */
1102 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1103 unsigned char *Pointer,
1104 PFORMAT_STRING pFormat)
1105 {
1106 unsigned type = pFormat[0], attr = pFormat[1];
1107 PFORMAT_STRING desc;
1108 NDR_FREE m;
1109 unsigned char *current_pointer = Pointer;
1110
1111 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1112 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1113 if (attr & RPC_FC_P_DONTFREE) return;
1114 pFormat += 2;
1115 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1116 else desc = pFormat + *(const SHORT*)pFormat;
1117
1118 if (!Pointer) return;
1119
1120 if (type == RPC_FC_FP) {
1121 int pointer_needs_freeing = NdrFullPointerFree(
1122 pStubMsg->FullPtrXlatTables, Pointer);
1123 if (!pointer_needs_freeing)
1124 return;
1125 }
1126
1127 if (attr & RPC_FC_P_DEREF) {
1128 current_pointer = *(unsigned char**)Pointer;
1129 TRACE("deref => %p\n", current_pointer);
1130 }
1131
1132 m = NdrFreer[*desc & NDR_TABLE_MASK];
1133 if (m) m(pStubMsg, current_pointer, desc);
1134
1135 /* this check stops us from trying to free buffer memory. we don't have to
1136 * worry about clients, since they won't call this function.
1137 * we don't have to check for the buffer being reallocated because
1138 * BufferStart and BufferEnd won't be reset when allocating memory for
1139 * sending the response. we don't have to check for the new buffer here as
1140 * it won't be used a type memory, only for buffer memory */
1141 if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd)
1142 goto notfree;
1143
1144 if (attr & RPC_FC_P_ONSTACK) {
1145 TRACE("not freeing stack ptr %p\n", Pointer);
1146 return;
1147 }
1148 TRACE("freeing %p\n", Pointer);
1149 NdrFree(pStubMsg, Pointer);
1150 return;
1151 notfree:
1152 TRACE("not freeing %p\n", Pointer);
1153 }
1154
1155 /***********************************************************************
1156 * EmbeddedPointerMarshall
1157 */
1158 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1159 unsigned char *pMemory,
1160 PFORMAT_STRING pFormat)
1161 {
1162 unsigned char *Mark = pStubMsg->BufferMark;
1163 unsigned rep, count, stride;
1164 unsigned i;
1165 unsigned char *saved_buffer = NULL;
1166
1167 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1168
1169 if (*pFormat != RPC_FC_PP) return NULL;
1170 pFormat += 2;
1171
1172 if (pStubMsg->PointerBufferMark)
1173 {
1174 saved_buffer = pStubMsg->Buffer;
1175 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1176 pStubMsg->PointerBufferMark = NULL;
1177 }
1178
1179 while (pFormat[0] != RPC_FC_END) {
1180 switch (pFormat[0]) {
1181 default:
1182 FIXME("unknown repeat type %d\n", pFormat[0]);
1183 case RPC_FC_NO_REPEAT:
1184 rep = 1;
1185 stride = 0;
1186 count = 1;
1187 pFormat += 2;
1188 break;
1189 case RPC_FC_FIXED_REPEAT:
1190 rep = *(const WORD*)&pFormat[2];
1191 stride = *(const WORD*)&pFormat[4];
1192 count = *(const WORD*)&pFormat[8];
1193 pFormat += 10;
1194 break;
1195 case RPC_FC_VARIABLE_REPEAT:
1196 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1197 stride = *(const WORD*)&pFormat[2];
1198 count = *(const WORD*)&pFormat[6];
1199 pFormat += 8;
1200 break;
1201 }
1202 for (i = 0; i < rep; i++) {
1203 PFORMAT_STRING info = pFormat;
1204 unsigned char *membase = pMemory + (i * stride);
1205 unsigned char *bufbase = Mark + (i * stride);
1206 unsigned u;
1207
1208 for (u=0; u<count; u++,info+=8) {
1209 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1210 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1211 unsigned char *saved_memory = pStubMsg->Memory;
1212
1213 pStubMsg->Memory = pMemory;
1214 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1215 pStubMsg->Memory = saved_memory;
1216 }
1217 }
1218 pFormat += 8 * count;
1219 }
1220
1221 if (saved_buffer)
1222 {
1223 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1224 pStubMsg->Buffer = saved_buffer;
1225 }
1226
1227 STD_OVERFLOW_CHECK(pStubMsg);
1228
1229 return NULL;
1230 }
1231
1232 /***********************************************************************
1233 * EmbeddedPointerUnmarshall
1234 */
1235 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1236 unsigned char *pDstBuffer,
1237 unsigned char *pSrcMemoryPtrs,
1238 PFORMAT_STRING pFormat,
1239 unsigned char fMustAlloc)
1240 {
1241 unsigned char *Mark = pStubMsg->BufferMark;
1242 unsigned rep, count, stride;
1243 unsigned i;
1244 unsigned char *saved_buffer = NULL;
1245
1246 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1247
1248 if (*pFormat != RPC_FC_PP) return NULL;
1249 pFormat += 2;
1250
1251 if (pStubMsg->PointerBufferMark)
1252 {
1253 saved_buffer = pStubMsg->Buffer;
1254 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1255 pStubMsg->PointerBufferMark = NULL;
1256 }
1257
1258 while (pFormat[0] != RPC_FC_END) {
1259 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1260 switch (pFormat[0]) {
1261 default:
1262 FIXME("unknown repeat type %d\n", pFormat[0]);
1263 case RPC_FC_NO_REPEAT:
1264 rep = 1;
1265 stride = 0;
1266 count = 1;
1267 pFormat += 2;
1268 break;
1269 case RPC_FC_FIXED_REPEAT:
1270 rep = *(const WORD*)&pFormat[2];
1271 stride = *(const WORD*)&pFormat[4];
1272 count = *(const WORD*)&pFormat[8];
1273 pFormat += 10;
1274 break;
1275 case RPC_FC_VARIABLE_REPEAT:
1276 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1277 stride = *(const WORD*)&pFormat[2];
1278 count = *(const WORD*)&pFormat[6];
1279 pFormat += 8;
1280 break;
1281 }
1282 for (i = 0; i < rep; i++) {
1283 PFORMAT_STRING info = pFormat;
1284 unsigned char *bufdstbase = pDstBuffer + (i * stride);
1285 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1286 unsigned char *bufbase = Mark + (i * stride);
1287 unsigned u;
1288
1289 for (u=0; u<count; u++,info+=8) {
1290 unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1291 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1292 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1293 PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1294 }
1295 }
1296 pFormat += 8 * count;
1297 }
1298
1299 if (saved_buffer)
1300 {
1301 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1302 pStubMsg->Buffer = saved_buffer;
1303 }
1304
1305 return NULL;
1306 }
1307
1308 /***********************************************************************
1309 * EmbeddedPointerBufferSize
1310 */
1311 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1312 unsigned char *pMemory,
1313 PFORMAT_STRING pFormat)
1314 {
1315 unsigned rep, count, stride;
1316 unsigned i;
1317 ULONG saved_buffer_length = 0;
1318
1319 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1320
1321 if (pStubMsg->IgnoreEmbeddedPointers) return;
1322
1323 if (*pFormat != RPC_FC_PP) return;
1324 pFormat += 2;
1325
1326 if (pStubMsg->PointerLength)
1327 {
1328 saved_buffer_length = pStubMsg->BufferLength;
1329 pStubMsg->BufferLength = pStubMsg->PointerLength;
1330 pStubMsg->PointerLength = 0;
1331 }
1332
1333 while (pFormat[0] != RPC_FC_END) {
1334 switch (pFormat[0]) {
1335 default:
1336 FIXME("unknown repeat type %d\n", pFormat[0]);
1337 case RPC_FC_NO_REPEAT:
1338 rep = 1;
1339 stride = 0;
1340 count = 1;
1341 pFormat += 2;
1342 break;
1343 case RPC_FC_FIXED_REPEAT:
1344 rep = *(const WORD*)&pFormat[2];
1345 stride = *(const WORD*)&pFormat[4];
1346 count = *(const WORD*)&pFormat[8];
1347 pFormat += 10;
1348 break;
1349 case RPC_FC_VARIABLE_REPEAT:
1350 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1351 stride = *(const WORD*)&pFormat[2];
1352 count = *(const WORD*)&pFormat[6];
1353 pFormat += 8;
1354 break;
1355 }
1356 for (i = 0; i < rep; i++) {
1357 PFORMAT_STRING info = pFormat;
1358 unsigned char *membase = pMemory + (i * stride);
1359 unsigned u;
1360
1361 for (u=0; u<count; u++,info+=8) {
1362 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1363 unsigned char *saved_memory = pStubMsg->Memory;
1364
1365 pStubMsg->Memory = pMemory;
1366 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1367 pStubMsg->Memory = saved_memory;
1368 }
1369 }
1370 pFormat += 8 * count;
1371 }
1372
1373 if (saved_buffer_length)
1374 {
1375 pStubMsg->PointerLength = pStubMsg->BufferLength;
1376 pStubMsg->BufferLength = saved_buffer_length;
1377 }
1378 }
1379
1380 /***********************************************************************
1381 * EmbeddedPointerMemorySize [internal]
1382 */
1383 static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1384 PFORMAT_STRING pFormat)
1385 {
1386 unsigned char *Mark = pStubMsg->BufferMark;
1387 unsigned rep, count, stride;
1388 unsigned i;
1389 unsigned char *saved_buffer = NULL;
1390
1391 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1392
1393 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1394
1395 if (pStubMsg->PointerBufferMark)
1396 {
1397 saved_buffer = pStubMsg->Buffer;
1398 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1399 pStubMsg->PointerBufferMark = NULL;
1400 }
1401
1402 if (*pFormat != RPC_FC_PP) return 0;
1403 pFormat += 2;
1404
1405 while (pFormat[0] != RPC_FC_END) {
1406 switch (pFormat[0]) {
1407 default:
1408 FIXME("unknown repeat type %d\n", pFormat[0]);
1409 case RPC_FC_NO_REPEAT:
1410 rep = 1;
1411 stride = 0;
1412 count = 1;
1413 pFormat += 2;
1414 break;
1415 case RPC_FC_FIXED_REPEAT:
1416 rep = *(const WORD*)&pFormat[2];
1417 stride = *(const WORD*)&pFormat[4];
1418 count = *(const WORD*)&pFormat[8];
1419 pFormat += 10;
1420 break;
1421 case RPC_FC_VARIABLE_REPEAT:
1422 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1423 stride = *(const WORD*)&pFormat[2];
1424 count = *(const WORD*)&pFormat[6];
1425 pFormat += 8;
1426 break;
1427 }
1428 for (i = 0; i < rep; i++) {
1429 PFORMAT_STRING info = pFormat;
1430 unsigned char *bufbase = Mark + (i * stride);
1431 unsigned u;
1432 for (u=0; u<count; u++,info+=8) {
1433 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1434 PointerMemorySize(pStubMsg, bufptr, info+4);
1435 }
1436 }
1437 pFormat += 8 * count;
1438 }
1439
1440 if (saved_buffer)
1441 {
1442 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1443 pStubMsg->Buffer = saved_buffer;
1444 }
1445
1446 return 0;
1447 }
1448
1449 /***********************************************************************
1450 * EmbeddedPointerFree [internal]
1451 */
1452 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1453 unsigned char *pMemory,
1454 PFORMAT_STRING pFormat)
1455 {
1456 unsigned rep, count, stride;
1457 unsigned i;
1458
1459 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1460 if (*pFormat != RPC_FC_PP) return;
1461 pFormat += 2;
1462
1463 while (pFormat[0] != RPC_FC_END) {
1464 switch (pFormat[0]) {
1465 default:
1466 FIXME("unknown repeat type %d\n", pFormat[0]);
1467 case RPC_FC_NO_REPEAT:
1468 rep = 1;
1469 stride = 0;
1470 count = 1;
1471 pFormat += 2;
1472 break;
1473 case RPC_FC_FIXED_REPEAT:
1474 rep = *(const WORD*)&pFormat[2];
1475 stride = *(const WORD*)&pFormat[4];
1476 count = *(const WORD*)&pFormat[8];
1477 pFormat += 10;
1478 break;
1479 case RPC_FC_VARIABLE_REPEAT:
1480 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1481 stride = *(const WORD*)&pFormat[2];
1482 count = *(const WORD*)&pFormat[6];
1483 pFormat += 8;
1484 break;
1485 }
1486 for (i = 0; i < rep; i++) {
1487 PFORMAT_STRING info = pFormat;
1488 unsigned char *membase = pMemory + (i * stride);
1489 unsigned u;
1490
1491 for (u=0; u<count; u++,info+=8) {
1492 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1493 unsigned char *saved_memory = pStubMsg->Memory;
1494
1495 pStubMsg->Memory = pMemory;
1496 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1497 pStubMsg->Memory = saved_memory;
1498 }
1499 }
1500 pFormat += 8 * count;
1501 }
1502 }
1503
1504 /***********************************************************************
1505 * NdrPointerMarshall [RPCRT4.@]
1506 */
1507 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1508 unsigned char *pMemory,
1509 PFORMAT_STRING pFormat)
1510 {
1511 unsigned char *Buffer;
1512
1513 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1514
1515 /* Increment the buffer here instead of in PointerMarshall,
1516 * as that is used by embedded pointers which already handle the incrementing
1517 * the buffer, and shouldn't write any additional pointer data to the wire */
1518 if (*pFormat != RPC_FC_RP)
1519 {
1520 align_pointer_clear(&pStubMsg->Buffer, 4);
1521 Buffer = pStubMsg->Buffer;
1522 safe_buffer_increment(pStubMsg, 4);
1523 }
1524 else
1525 Buffer = pStubMsg->Buffer;
1526
1527 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1528
1529 return NULL;
1530 }
1531
1532 /***********************************************************************
1533 * NdrPointerUnmarshall [RPCRT4.@]
1534 */
1535 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1536 unsigned char **ppMemory,
1537 PFORMAT_STRING pFormat,
1538 unsigned char fMustAlloc)
1539 {
1540 unsigned char *Buffer;
1541
1542 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1543
1544 if (*pFormat == RPC_FC_RP)
1545 {
1546 Buffer = pStubMsg->Buffer;
1547 /* Do the NULL ref pointer check here because embedded pointers can be
1548 * NULL if the type the pointer is embedded in was allocated rather than
1549 * being passed in by the client */
1550 if (pStubMsg->IsClient && !*ppMemory)
1551 {
1552 ERR("NULL ref pointer is not allowed\n");
1553 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1554 }
1555 }
1556 else
1557 {
1558 /* Increment the buffer here instead of in PointerUnmarshall,
1559 * as that is used by embedded pointers which already handle the incrementing
1560 * the buffer, and shouldn't read any additional pointer data from the
1561 * buffer */
1562 align_pointer(&pStubMsg->Buffer, 4);
1563 Buffer = pStubMsg->Buffer;
1564 safe_buffer_increment(pStubMsg, 4);
1565 }
1566
1567 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1568
1569 return NULL;
1570 }
1571
1572 /***********************************************************************
1573 * NdrPointerBufferSize [RPCRT4.@]
1574 */
1575 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1576 unsigned char *pMemory,
1577 PFORMAT_STRING pFormat)
1578 {
1579 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1580
1581 /* Increment the buffer length here instead of in PointerBufferSize,
1582 * as that is used by embedded pointers which already handle the buffer
1583 * length, and shouldn't write anything more to the wire */
1584 if (*pFormat != RPC_FC_RP)
1585 {
1586 align_length(&pStubMsg->BufferLength, 4);
1587 safe_buffer_length_increment(pStubMsg, 4);
1588 }
1589
1590 PointerBufferSize(pStubMsg, pMemory, pFormat);
1591 }
1592
1593 /***********************************************************************
1594 * NdrPointerMemorySize [RPCRT4.@]
1595 */
1596 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1597 PFORMAT_STRING pFormat)
1598 {
1599 unsigned char *Buffer = pStubMsg->Buffer;
1600 if (*pFormat != RPC_FC_RP)
1601 {
1602 align_pointer(&pStubMsg->Buffer, 4);
1603 safe_buffer_increment(pStubMsg, 4);
1604 }
1605 align_length(&pStubMsg->MemorySize, sizeof(void *));
1606 return PointerMemorySize(pStubMsg, Buffer, pFormat);
1607 }
1608
1609 /***********************************************************************
1610 * NdrPointerFree [RPCRT4.@]
1611 */
1612 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1613 unsigned char *pMemory,
1614 PFORMAT_STRING pFormat)
1615 {
1616 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1617 PointerFree(pStubMsg, pMemory, pFormat);
1618 }
1619
1620 /***********************************************************************
1621 * NdrSimpleTypeMarshall [RPCRT4.@]
1622 */
1623 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1624 unsigned char FormatChar )
1625 {
1626 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1627 }
1628
1629 /***********************************************************************
1630 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1631 *
1632 * Unmarshall a base type.
1633 *
1634 * NOTES
1635 * Doesn't check that the buffer is long enough before copying, so the caller
1636 * should do this.
1637 */
1638 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1639 unsigned char FormatChar )
1640 {
1641 #define BASE_TYPE_UNMARSHALL(type) \
1642 align_pointer(&pStubMsg->Buffer, sizeof(type)); \
1643 TRACE("pMemory: %p\n", pMemory); \
1644 *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1645 pStubMsg->Buffer += sizeof(type);
1646
1647 switch(FormatChar)
1648 {
1649 case RPC_FC_BYTE:
1650 case RPC_FC_CHAR:
1651 case RPC_FC_SMALL:
1652 case RPC_FC_USMALL:
1653 BASE_TYPE_UNMARSHALL(UCHAR);
1654 TRACE("value: 0x%02x\n", *pMemory);
1655 break;
1656 case RPC_FC_WCHAR:
1657 case RPC_FC_SHORT:
1658 case RPC_FC_USHORT:
1659 BASE_TYPE_UNMARSHALL(USHORT);
1660 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1661 break;
1662 case RPC_FC_LONG:
1663 case RPC_FC_ULONG:
1664 case RPC_FC_ERROR_STATUS_T:
1665 case RPC_FC_ENUM32:
1666 BASE_TYPE_UNMARSHALL(ULONG);
1667 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1668 break;
1669 case RPC_FC_FLOAT:
1670 BASE_TYPE_UNMARSHALL(float);
1671 TRACE("value: %f\n", *(float *)pMemory);
1672 break;
1673 case RPC_FC_DOUBLE:
1674 BASE_TYPE_UNMARSHALL(double);
1675 TRACE("value: %f\n", *(double *)pMemory);
1676 break;
1677 case RPC_FC_HYPER:
1678 BASE_TYPE_UNMARSHALL(ULONGLONG);
1679 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1680 break;
1681 case RPC_FC_ENUM16:
1682 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
1683 TRACE("pMemory: %p\n", pMemory);
1684 /* 16-bits on the wire, but int in memory */
1685 *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1686 pStubMsg->Buffer += sizeof(USHORT);
1687 TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1688 break;
1689 case RPC_FC_INT3264:
1690 align_pointer(&pStubMsg->Buffer, sizeof(INT));
1691 /* 32-bits on the wire, but int_ptr in memory */
1692 *(INT_PTR *)pMemory = *(INT *)pStubMsg->Buffer;
1693 pStubMsg->Buffer += sizeof(INT);
1694 TRACE("value: 0x%08lx\n", *(INT_PTR *)pMemory);
1695 break;
1696 case RPC_FC_UINT3264:
1697 align_pointer(&pStubMsg->Buffer, sizeof(UINT));
1698 /* 32-bits on the wire, but int_ptr in memory */
1699 *(UINT_PTR *)pMemory = *(UINT *)pStubMsg->Buffer;
1700 pStubMsg->Buffer += sizeof(UINT);
1701 TRACE("value: 0x%08lx\n", *(UINT_PTR *)pMemory);
1702 break;
1703 case RPC_FC_IGNORE:
1704 break;
1705 default:
1706 FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1707 }
1708 #undef BASE_TYPE_UNMARSHALL
1709 }
1710
1711 /***********************************************************************
1712 * NdrSimpleStructMarshall [RPCRT4.@]
1713 */
1714 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1715 unsigned char *pMemory,
1716 PFORMAT_STRING pFormat)
1717 {
1718 unsigned size = *(const WORD*)(pFormat+2);
1719 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1720
1721 align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
1722
1723 pStubMsg->BufferMark = pStubMsg->Buffer;
1724 safe_copy_to_buffer(pStubMsg, pMemory, size);
1725
1726 if (pFormat[0] != RPC_FC_STRUCT)
1727 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1728
1729 return NULL;
1730 }
1731
1732 /***********************************************************************
1733 * NdrSimpleStructUnmarshall [RPCRT4.@]
1734 */
1735 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1736 unsigned char **ppMemory,
1737 PFORMAT_STRING pFormat,
1738 unsigned char fMustAlloc)
1739 {
1740 unsigned size = *(const WORD*)(pFormat+2);
1741 unsigned char *saved_buffer;
1742 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1743
1744 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1745
1746 if (fMustAlloc)
1747 *ppMemory = NdrAllocate(pStubMsg, size);
1748 else
1749 {
1750 if (!pStubMsg->IsClient && !*ppMemory)
1751 /* for servers, we just point straight into the RPC buffer */
1752 *ppMemory = pStubMsg->Buffer;
1753 }
1754
1755 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1756 safe_buffer_increment(pStubMsg, size);
1757 if (pFormat[0] == RPC_FC_PSTRUCT)
1758 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1759
1760 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1761 if (*ppMemory != saved_buffer)
1762 memcpy(*ppMemory, saved_buffer, size);
1763
1764 return NULL;
1765 }
1766
1767 /***********************************************************************
1768 * NdrSimpleStructBufferSize [RPCRT4.@]
1769 */
1770 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1771 unsigned char *pMemory,
1772 PFORMAT_STRING pFormat)
1773 {
1774 unsigned size = *(const WORD*)(pFormat+2);
1775 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1776
1777 align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
1778
1779 safe_buffer_length_increment(pStubMsg, size);
1780 if (pFormat[0] != RPC_FC_STRUCT)
1781 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1782 }
1783
1784 /***********************************************************************
1785 * NdrSimpleStructMemorySize [RPCRT4.@]
1786 */
1787 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1788 PFORMAT_STRING pFormat)
1789 {
1790 unsigned short size = *(const WORD *)(pFormat+2);
1791
1792 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1793
1794 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1795 pStubMsg->MemorySize += size;
1796 safe_buffer_increment(pStubMsg, size);
1797
1798 if (pFormat[0] != RPC_FC_STRUCT)
1799 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1800 return pStubMsg->MemorySize;
1801 }
1802
1803 /***********************************************************************
1804 * NdrSimpleStructFree [RPCRT4.@]
1805 */
1806 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1807 unsigned char *pMemory,
1808 PFORMAT_STRING pFormat)
1809 {
1810 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1811 if (pFormat[0] != RPC_FC_STRUCT)
1812 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1813 }
1814
1815 /* Array helpers */
1816
1817 static inline void array_compute_and_size_conformance(
1818 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1819 PFORMAT_STRING pFormat)
1820 {
1821 DWORD count;
1822
1823 switch (fc)
1824 {
1825 case RPC_FC_CARRAY:
1826 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1827 SizeConformance(pStubMsg);
1828 break;
1829 case RPC_FC_CVARRAY:
1830 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1831 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1832 SizeConformance(pStubMsg);
1833 break;
1834 case RPC_FC_C_CSTRING:
1835 case RPC_FC_C_WSTRING:
1836 if (fc == RPC_FC_C_CSTRING)
1837 {
1838 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1839 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1840 }
1841 else
1842 {
1843 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1844 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1845 }
1846
1847 if (pFormat[1] == RPC_FC_STRING_SIZED)
1848 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1849 else
1850 pStubMsg->MaxCount = pStubMsg->ActualCount;
1851
1852 SizeConformance(pStubMsg);
1853 break;
1854 case RPC_FC_BOGUS_ARRAY:
1855 count = *(const WORD *)(pFormat + 2);
1856 pFormat += 4;
1857 if (IsConformanceOrVariancePresent(pFormat)) SizeConformance(pStubMsg);
1858 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, count);
1859 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
1860 break;
1861 default:
1862 ERR("unknown array format 0x%x\n", fc);
1863 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1864 }
1865 }
1866
1867 static inline void array_buffer_size(
1868 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1869 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1870 {
1871 DWORD i, size;
1872 DWORD esize;
1873 unsigned char alignment;
1874
1875 switch (fc)
1876 {
1877 case RPC_FC_CARRAY:
1878 esize = *(const WORD*)(pFormat+2);
1879 alignment = pFormat[1] + 1;
1880
1881 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1882
1883 align_length(&pStubMsg->BufferLength, alignment);
1884
1885 size = safe_multiply(esize, pStubMsg->MaxCount);
1886 /* conformance value plus array */
1887 safe_buffer_length_increment(pStubMsg, size);
1888
1889 if (fHasPointers)
1890 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1891 break;
1892 case RPC_FC_CVARRAY:
1893 esize = *(const WORD*)(pFormat+2);
1894 alignment = pFormat[1] + 1;
1895
1896 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1897 pFormat = SkipVariance(pStubMsg, pFormat);
1898
1899 SizeVariance(pStubMsg);
1900
1901 align_length(&pStubMsg->BufferLength, alignment);
1902
1903 size = safe_multiply(esize, pStubMsg->ActualCount);
1904 safe_buffer_length_increment(pStubMsg, size);
1905
1906 if (fHasPointers)
1907 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1908 break;
1909 case RPC_FC_C_CSTRING:
1910 case RPC_FC_C_WSTRING:
1911 if (fc == RPC_FC_C_CSTRING)
1912 esize = 1;
1913 else
1914 esize = 2;
1915
1916 SizeVariance(pStubMsg);
1917
1918 size = safe_multiply(esize, pStubMsg->ActualCount);
1919 safe_buffer_length_increment(pStubMsg, size);
1920 break;
1921 case RPC_FC_BOGUS_ARRAY:
1922 alignment = pFormat[1] + 1;
1923 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1924 if (IsConformanceOrVariancePresent(pFormat)) SizeVariance(pStubMsg);
1925 pFormat = SkipVariance(pStubMsg, pFormat);
1926
1927 align_length(&pStubMsg->BufferLength, alignment);
1928
1929 size = pStubMsg->ActualCount;
1930 for (i = 0; i < size; i++)
1931 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
1932 break;
1933 default:
1934 ERR("unknown array format 0x%x\n", fc);
1935 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1936 }
1937 }
1938
1939 static inline void array_compute_and_write_conformance(
1940 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1941 PFORMAT_STRING pFormat)
1942 {
1943 ULONG def;
1944 BOOL conformance_present;
1945
1946 switch (fc)
1947 {
1948 case RPC_FC_CARRAY:
1949 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1950 WriteConformance(pStubMsg);
1951 break;
1952 case RPC_FC_CVARRAY:
1953 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1954 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1955 WriteConformance(pStubMsg);
1956 break;
1957 case RPC_FC_C_CSTRING:
1958 case RPC_FC_C_WSTRING:
1959 if (fc == RPC_FC_C_CSTRING)
1960 {
1961 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1962 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1963 }
1964 else
1965 {
1966 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1967 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1968 }
1969 if (pFormat[1] == RPC_FC_STRING_SIZED)
1970 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1971 else
1972 pStubMsg->MaxCount = pStubMsg->ActualCount;
1973 pStubMsg->Offset = 0;
1974 WriteConformance(pStubMsg);
1975 break;
1976 case RPC_FC_BOGUS_ARRAY:
1977 def = *(const WORD *)(pFormat + 2);
1978 pFormat += 4;
1979 conformance_present = IsConformanceOrVariancePresent(pFormat);
1980 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
1981 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
1982 if (conformance_present) WriteConformance(pStubMsg);
1983 break;
1984 default:
1985 ERR("unknown array format 0x%x\n", fc);
1986 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1987 }
1988 }
1989
1990 static inline void array_write_variance_and_marshall(
1991 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1992 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1993 {
1994 DWORD i, size;
1995 DWORD esize;
1996 unsigned char alignment;
1997
1998 switch (fc)
1999 {
2000 case RPC_FC_CARRAY:
2001 esize = *(const WORD*)(pFormat+2);
2002 alignment = pFormat[1] + 1;
2003
2004 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2005
2006 align_pointer_clear(&pStubMsg->Buffer, alignment);
2007
2008 size = safe_multiply(esize, pStubMsg->MaxCount);
2009 if (fHasPointers)
2010 pStubMsg->BufferMark = pStubMsg->Buffer;
2011 safe_copy_to_buffer(pStubMsg, pMemory, size);
2012
2013 if (fHasPointers)
2014 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2015 break;
2016 case RPC_FC_CVARRAY:
2017 esize = *(const WORD*)(pFormat+2);
2018 alignment = pFormat[1] + 1;
2019
2020 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2021 pFormat = SkipVariance(pStubMsg, pFormat);
2022
2023 WriteVariance(pStubMsg);
2024
2025 align_pointer_clear(&pStubMsg->Buffer, alignment);
2026
2027 size = safe_multiply(esize, pStubMsg->ActualCount);
2028
2029 if (fHasPointers)
2030 pStubMsg->BufferMark = pStubMsg->Buffer;
2031 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
2032
2033 if (fHasPointers)
2034 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2035 break;
2036 case RPC_FC_C_CSTRING:
2037 case RPC_FC_C_WSTRING:
2038 if (fc == RPC_FC_C_CSTRING)
2039 esize = 1;
2040 else
2041 esize = 2;
2042
2043 WriteVariance(pStubMsg);
2044
2045 size = safe_multiply(esize, pStubMsg->ActualCount);
2046 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2047 break;
2048 case RPC_FC_BOGUS_ARRAY:
2049 alignment = pFormat[1] + 1;
2050 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2051 if (IsConformanceOrVariancePresent(pFormat)) WriteVariance(pStubMsg);
2052 pFormat = SkipVariance(pStubMsg, pFormat);
2053
2054 align_pointer_clear(&pStubMsg->Buffer, alignment);
2055
2056 size = pStubMsg->ActualCount;
2057 for (i = 0; i < size; i++)
2058 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2059 break;
2060 default:
2061 ERR("unknown array format 0x%x\n", fc);
2062 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2063 }
2064 }
2065
2066 static inline ULONG array_read_conformance(
2067 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
2068 {
2069 DWORD def, esize;
2070
2071 switch (fc)
2072 {
2073 case RPC_FC_CARRAY:
2074 esize = *(const WORD*)(pFormat+2);
2075 pFormat = ReadConformance(pStubMsg, pFormat+4);
2076 return safe_multiply(esize, pStubMsg->MaxCount);
2077 case RPC_FC_CVARRAY:
2078 esize = *(const WORD*)(pFormat+2);
2079 pFormat = ReadConformance(pStubMsg, pFormat+4);
2080 return safe_multiply(esize, pStubMsg->MaxCount);
2081 case RPC_FC_C_CSTRING:
2082 case RPC_FC_C_WSTRING:
2083 if (fc == RPC_FC_C_CSTRING)
2084 esize = 1;
2085 else
2086 esize = 2;
2087
2088 if (pFormat[1] == RPC_FC_STRING_SIZED)
2089 ReadConformance(pStubMsg, pFormat + 2);
2090 else
2091 ReadConformance(pStubMsg, NULL);
2092 return safe_multiply(esize, pStubMsg->MaxCount);
2093 case RPC_FC_BOGUS_ARRAY:
2094 def = *(const WORD *)(pFormat + 2);
2095 pFormat += 4;
2096 if (IsConformanceOrVariancePresent(pFormat)) pFormat = ReadConformance(pStubMsg, pFormat);
2097 else
2098 {
2099 pStubMsg->MaxCount = def;
2100 pFormat = SkipConformance( pStubMsg, pFormat );
2101 }
2102 pFormat = SkipVariance( pStubMsg, pFormat );
2103
2104 esize = ComplexStructSize(pStubMsg, pFormat);
2105 return safe_multiply(pStubMsg->MaxCount, esize);
2106 default:
2107 ERR("unknown array format 0x%x\n", fc);
2108 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2109 }
2110 }
2111
2112 static inline ULONG array_read_variance_and_unmarshall(
2113 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
2114 PFORMAT_STRING pFormat, unsigned char fMustAlloc,
2115 unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
2116 {
2117 ULONG bufsize, memsize;
2118 WORD esize;
2119 unsigned char alignment;
2120 unsigned char *saved_buffer, *pMemory;
2121 ULONG i, offset, count;
2122
2123 switch (fc)
2124 {
2125 case RPC_FC_CARRAY:
2126 esize = *(const WORD*)(pFormat+2);
2127 alignment = pFormat[1] + 1;
2128
2129 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2130
2131 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2132
2133 align_pointer(&pStubMsg->Buffer, alignment);
2134
2135 if (fUnmarshall)
2136 {
2137 if (fMustAlloc)
2138 *ppMemory = NdrAllocate(pStubMsg, memsize);
2139 else
2140 {
2141 if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2142 /* for servers, we just point straight into the RPC buffer */
2143 *ppMemory = pStubMsg->Buffer;
2144 }
2145
2146 saved_buffer = pStubMsg->Buffer;
2147 safe_buffer_increment(pStubMsg, bufsize);
2148
2149 pStubMsg->BufferMark = saved_buffer;
2150 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2151
2152 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2153 if (*ppMemory != saved_buffer)
2154 memcpy(*ppMemory, saved_buffer, bufsize);
2155 }
2156 return bufsize;
2157 case RPC_FC_CVARRAY:
2158 esize = *(const WORD*)(pFormat+2);
2159 alignment = pFormat[1] + 1;
2160
2161 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2162
2163 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2164
2165 align_pointer(&pStubMsg->Buffer, alignment);
2166
2167 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2168 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2169
2170 if (fUnmarshall)
2171 {
2172 offset = pStubMsg->Offset;
2173
2174 if (!fMustAlloc && !*ppMemory)
2175 fMustAlloc = TRUE;
2176 if (fMustAlloc)
2177 *ppMemory = NdrAllocate(pStubMsg, memsize);
2178 saved_buffer = pStubMsg->Buffer;
2179 safe_buffer_increment(pStubMsg, bufsize);
2180
2181 pStubMsg->BufferMark = saved_buffer;
2182 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2183 fMustAlloc);
2184
2185 memcpy(*ppMemory + offset, saved_buffer, bufsize);
2186 }
2187 return bufsize;
2188 case RPC_FC_C_CSTRING:
2189 case RPC_FC_C_WSTRING:
2190 if (fc == RPC_FC_C_CSTRING)
2191 esize = 1;
2192 else
2193 esize = 2;
2194
2195 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2196
2197 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2198 {
2199 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2200 pStubMsg->ActualCount, pStubMsg->MaxCount);
2201 RpcRaiseException(RPC_S_INVALID_BOUND);
2202 }
2203 if (pStubMsg->Offset)
2204 {
2205 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2206 RpcRaiseException(RPC_S_INVALID_BOUND);
2207 }
2208
2209 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2210 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2211
2212 validate_string_data(pStubMsg, bufsize, esize);
2213
2214 if (fUnmarshall)
2215 {
2216 if (fMustAlloc)
2217 *ppMemory = NdrAllocate(pStubMsg, memsize);
2218 else
2219 {
2220 if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2221 !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2222 /* if the data in the RPC buffer is big enough, we just point
2223 * straight into it */
2224 *ppMemory = pStubMsg->Buffer;
2225 else if (!*ppMemory)
2226 *ppMemory = NdrAllocate(pStubMsg, memsize);
2227 }
2228
2229 if (*ppMemory == pStubMsg->Buffer)
2230 safe_buffer_increment(pStubMsg, bufsize);
2231 else
2232 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2233
2234 if (*pFormat == RPC_FC_C_CSTRING)
2235 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2236 else
2237 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2238 }
2239 return bufsize;
2240
2241 case RPC_FC_BOGUS_ARRAY:
2242 alignment = pFormat[1] + 1;
2243 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2244 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2245
2246 esize = ComplexStructSize(pStubMsg, pFormat);
2247 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2248
2249 assert( fUnmarshall );
2250
2251 if (!fMustAlloc && !*ppMemory)
2252 fMustAlloc = TRUE;
2253 if (fMustAlloc)
2254 *ppMemory = NdrAllocate(pStubMsg, memsize);
2255
2256 align_pointer(&pStubMsg->Buffer, alignment);
2257 saved_buffer = pStubMsg->Buffer;
2258
2259 pMemory = *ppMemory;
2260 count = pStubMsg->ActualCount;
2261 for (i = 0; i < count; i++)
2262 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
2263 return pStubMsg->Buffer - saved_buffer;
2264
2265 default:
2266 ERR("unknown array format 0x%x\n", fc);
2267 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2268 }
2269 }
2270
2271 static inline void array_memory_size(
2272 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2273 unsigned char fHasPointers)
2274 {
2275 ULONG i, count, SavedMemorySize;
2276 ULONG bufsize, memsize;
2277 DWORD esize;
2278 unsigned char alignment;
2279
2280 switch (fc)
2281 {
2282 case RPC_FC_CARRAY:
2283 esize = *(const WORD*)(pFormat+2);
2284 alignment = pFormat[1] + 1;
2285
2286 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2287
2288 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2289 pStubMsg->MemorySize += memsize;
2290
2291 align_pointer(&pStubMsg->Buffer, alignment);
2292 if (fHasPointers)
2293 pStubMsg->BufferMark = pStubMsg->Buffer;
2294 safe_buffer_increment(pStubMsg, bufsize);
2295
2296 if (fHasPointers)
2297 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2298 break;
2299 case RPC_FC_CVARRAY:
2300 esize = *(const WORD*)(pFormat+2);
2301 alignment = pFormat[1] + 1;
2302
2303 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2304
2305 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2306
2307 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2308 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2309 pStubMsg->MemorySize += memsize;
2310
2311 align_pointer(&pStubMsg->Buffer, alignment);
2312 if (fHasPointers)
2313 pStubMsg->BufferMark = pStubMsg->Buffer;
2314 safe_buffer_increment(pStubMsg, bufsize);
2315
2316 if (fHasPointers)
2317 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2318 break;
2319 case RPC_FC_C_CSTRING:
2320 case RPC_FC_C_WSTRING:
2321 if (fc == RPC_FC_C_CSTRING)
2322 esize = 1;
2323 else
2324 esize = 2;
2325
2326 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2327
2328 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2329 {
2330 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2331 pStubMsg->ActualCount, pStubMsg->MaxCount);
2332 RpcRaiseException(RPC_S_INVALID_BOUND);
2333 }
2334 if (pStubMsg->Offset)
2335 {
2336 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2337 RpcRaiseException(RPC_S_INVALID_BOUND);
2338 }
2339
2340 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2341 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2342
2343 validate_string_data(pStubMsg, bufsize, esize);
2344
2345 safe_buffer_increment(pStubMsg, bufsize);
2346 pStubMsg->MemorySize += memsize;
2347 break;
2348 case RPC_FC_BOGUS_ARRAY:
2349 alignment = pFormat[1] + 1;
2350 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2351 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2352
2353 align_pointer(&pStubMsg->Buffer, alignment);
2354
2355 SavedMemorySize = pStubMsg->MemorySize;
2356
2357 esize = ComplexStructSize(pStubMsg, pFormat);
2358 memsize = safe_multiply(pStubMsg->MaxCount, esize);
2359
2360 count = pStubMsg->ActualCount;
2361 for (i = 0; i < count; i++)
2362 ComplexStructMemorySize(pStubMsg, pFormat, NULL);
2363
2364 pStubMsg->MemorySize = SavedMemorySize + memsize;
2365 break;
2366 default:
2367 ERR("unknown array format 0x%x\n", fc);
2368 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2369 }
2370 }
2371
2372 static inline void array_free(
2373 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2374 unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2375 {
2376 DWORD i, count;
2377
2378 switch (fc)
2379 {
2380 case RPC_FC_CARRAY:
2381 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2382 if (fHasPointers)
2383 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2384 break;
2385 case RPC_FC_CVARRAY:
2386 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2387 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2388 if (fHasPointers)
2389 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2390 break;
2391 case RPC_FC_C_CSTRING:
2392 case RPC_FC_C_WSTRING:
2393 /* No embedded pointers so nothing to do */
2394 break;
2395 case RPC_FC_BOGUS_ARRAY:
2396 count = *(const WORD *)(pFormat + 2);
2397 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, count);
2398 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2399
2400 count = pStubMsg->ActualCount;
2401 for (i = 0; i < count; i++)
2402 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2403 break;
2404 default:
2405 ERR("unknown array format 0x%x\n", fc);
2406 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2407 }
2408 }
2409
2410 /*
2411 * NdrConformantString:
2412 *
2413 * What MS calls a ConformantString is, in DCE terminology,
2414 * a Varying-Conformant String.
2415 * [
2416 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2417 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
2418 * into unmarshalled string)
2419 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2420 * [
2421 * data: CHARTYPE[maxlen]
2422 * ]
2423 * ], where CHARTYPE is the appropriate character type (specified externally)
2424 *
2425 */
2426
2427 /***********************************************************************
2428 * NdrConformantStringMarshall [RPCRT4.@]
2429 */
2430 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
2431 unsigned char *pszMessage, PFORMAT_STRING pFormat)
2432 {
2433 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2434
2435 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2436 ERR("Unhandled string type: %#x\n", pFormat[0]);
2437 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2438 }
2439
2440 /* allow compiler to optimise inline function by passing constant into
2441 * these functions */
2442 if (pFormat[0] == RPC_FC_C_CSTRING) {
2443 array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2444 pFormat);
2445 array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2446 pFormat, TRUE /* fHasPointers */);
2447 } else {
2448 array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2449 pFormat);
2450 array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2451 pFormat, TRUE /* fHasPointers */);
2452 }
2453
2454 return NULL;
2455 }
2456
2457 /***********************************************************************
2458 * NdrConformantStringBufferSize [RPCRT4.@]
2459 */
2460 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2461 unsigned char* pMemory, PFORMAT_STRING pFormat)
2462 {
2463 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2464
2465 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2466 ERR("Unhandled string type: %#x\n", pFormat[0]);
2467 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2468 }
2469
2470 /* allow compiler to optimise inline function by passing constant into
2471 * these functions */
2472 if (pFormat[0] == RPC_FC_C_CSTRING) {
2473 array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory,
2474 pFormat);
2475 array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2476 TRUE /* fHasPointers */);
2477 } else {
2478 array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory,
2479 pFormat);
2480 array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2481 TRUE /* fHasPointers */);
2482 }
2483 }
2484
2485 /************************************************************************
2486 * NdrConformantStringMemorySize [RPCRT4.@]
2487 */
2488 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2489 PFORMAT_STRING pFormat )
2490 {
2491 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2492
2493 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2494 ERR("Unhandled string type: %#x\n", pFormat[0]);
2495 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2496 }
2497
2498 /* allow compiler to optimise inline function by passing constant into
2499 * these functions */
2500 if (pFormat[0] == RPC_FC_C_CSTRING) {
2501 array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2502 array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat,
2503 TRUE /* fHasPointers */);
2504 } else {
2505 array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2506 array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat,
2507 TRUE /* fHasPointers */);
2508 }
2509
2510 return pStubMsg->MemorySize;
2511 }
2512
2513 /************************************************************************
2514 * NdrConformantStringUnmarshall [RPCRT4.@]
2515 */
2516 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2517 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2518 {
2519 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2520 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2521
2522 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2523 ERR("Unhandled string type: %#x\n", *pFormat);
2524 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2525 }
2526
2527 /* allow compiler to optimise inline function by passing constant into
2528 * these functions */
2529 if (pFormat[0] == RPC_FC_C_CSTRING) {
2530 array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2531 array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory,
2532 pFormat, fMustAlloc,
2533 TRUE /* fUseBufferMemoryServer */,
2534 TRUE /* fUnmarshall */);
2535 } else {
2536 array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2537 array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory,
2538 pFormat, fMustAlloc,
2539 TRUE /* fUseBufferMemoryServer */,
2540 TRUE /* fUnmarshall */);
2541 }
2542
2543 return NULL;
2544 }
2545
2546 /***********************************************************************
2547 * NdrNonConformantStringMarshall [RPCRT4.@]
2548 */
2549 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2550 unsigned char *pMemory,
2551 PFORMAT_STRING pFormat)
2552 {
2553 ULONG esize, size, maxsize;
2554
2555 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2556
2557 maxsize = *(const USHORT *)&pFormat[2];
2558
2559 if (*pFormat == RPC_FC_CSTRING)
2560 {
2561 ULONG i = 0;
2562 const char *str = (const char *)pMemory;
2563 while (i < maxsize && str[i]) i++;
2564 TRACE("string=%s\n", debugstr_an(str, i));
2565 pStubMsg->ActualCount = i + 1;
2566 esize = 1;
2567 }
2568 else if (*pFormat == RPC_FC_WSTRING)
2569 {
2570 ULONG i = 0;
2571 const WCHAR *str = (const WCHAR *)pMemory;
2572 while (i < maxsize && str[i]) i++;
2573 TRACE("string=%s\n", debugstr_wn(str, i));
2574 pStubMsg->ActualCount = i + 1;
2575 esize = 2;
2576 }
2577 else
2578 {
2579 ERR("Unhandled string type: %#x\n", *pFormat);
2580 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2581 }
2582
2583 pStubMsg->Offset = 0;
2584 WriteVariance(pStubMsg);
2585
2586 size = safe_multiply(esize, pStubMsg->ActualCount);
2587 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2588
2589 return NULL;
2590 }
2591
2592 /***********************************************************************
2593 * NdrNonConformantStringUnmarshall [RPCRT4.@]
2594 */
2595 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2596 unsigned char **ppMemory,
2597 PFORMAT_STRING pFormat,
2598 unsigned char fMustAlloc)
2599 {
2600 ULONG bufsize, memsize, esize, maxsize;
2601
2602 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2603 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2604
2605 maxsize = *(const USHORT *)&pFormat[2];
2606
2607 ReadVariance(pStubMsg, NULL, maxsize);
2608 if (pStubMsg->Offset)
2609 {
2610 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2611 RpcRaiseException(RPC_S_INVALID_BOUND);
2612 }
2613
2614 if (*pFormat == RPC_FC_CSTRING) esize = 1;
2615 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2616 else
2617 {
2618 ERR("Unhandled string type: %#x\n", *pFormat);
2619 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2620 }
2621
2622 memsize = esize * maxsize;
2623 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2624
2625 validate_string_data(pStubMsg, bufsize, esize);
2626
2627 if (!fMustAlloc && !*ppMemory)
2628 fMustAlloc = TRUE;
2629 if (fMustAlloc)
2630 *ppMemory = NdrAllocate(pStubMsg, memsize);
2631
2632 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2633
2634 if (*pFormat == RPC_FC_CSTRING) {
2635 TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2636 }
2637 else if (*pFormat == RPC_FC_WSTRING) {
2638 TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2639 }
2640
2641 return NULL;
2642 }
2643
2644 /***********************************************************************
2645 * NdrNonConformantStringBufferSize [RPCRT4.@]
2646 */
2647 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2648 unsigned char *pMemory,
2649 PFORMAT_STRING pFormat)
2650 {
2651 ULONG esize, maxsize;
2652
2653 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2654
2655 maxsize = *(const USHORT *)&pFormat[2];
2656
2657 SizeVariance(pStubMsg);
2658
2659 if (*pFormat == RPC_FC_CSTRING)
2660 {
2661 ULONG i = 0;
2662 const char *str = (const char *)pMemory;
2663 while (i < maxsize && str[i]) i++;
2664 TRACE("string=%s\n", debugstr_an(str, i));
2665 pStubMsg->ActualCount = i + 1;
2666 esize = 1;
2667 }
2668 else if (*pFormat == RPC_FC_WSTRING)
2669 {
2670 ULONG i = 0;
2671 const WCHAR *str = (const WCHAR *)pMemory;
2672 while (i < maxsize && str[i]) i++;
2673 TRACE("string=%s\n", debugstr_wn(str, i));
2674 pStubMsg->ActualCount = i + 1;
2675 esize = 2;
2676 }
2677 else
2678 {
2679 ERR("Unhandled string type: %#x\n", *pFormat);
2680 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2681 }
2682
2683 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2684 }
2685
2686 /***********************************************************************
2687 * NdrNonConformantStringMemorySize [RPCRT4.@]
2688 */
2689 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2690 PFORMAT_STRING pFormat)
2691 {
2692 ULONG bufsize, memsize, esize, maxsize;
2693
2694 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2695
2696 maxsize = *(const USHORT *)&pFormat[2];
2697
2698 ReadVariance(pStubMsg, NULL, maxsize);
2699
2700 if (pStubMsg->Offset)
2701 {
2702 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2703 RpcRaiseException(RPC_S_INVALID_BOUND);
2704 }
2705
2706 if (*pFormat == RPC_FC_CSTRING) esize = 1;
2707 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2708 else
2709 {
2710 ERR("Unhandled string type: %#x\n", *pFormat);
2711 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2712 }
2713
2714 memsize = esize * maxsize;
2715 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2716
2717 validate_string_data(pStubMsg, bufsize, esize);
2718
2719 safe_buffer_increment(pStubMsg, bufsize);
2720 pStubMsg->MemorySize += memsize;
2721
2722 return pStubMsg->MemorySize;
2723 }
2724
2725 /* Complex types */
2726
2727 #include "pshpack1.h"
2728 typedef struct
2729 {
2730 unsigned char type;
2731 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2732 ULONG low_value;
2733 ULONG high_value;
2734 } NDR_RANGE;
2735 #include "poppack.h"
2736
2737 static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2738 PFORMAT_STRING pFormat)
2739 {
2740 switch (*pFormat) {
2741 case RPC_FC_STRUCT:
2742 case RPC_FC_PSTRUCT:
2743 case RPC_FC_CSTRUCT:
2744 case RPC_FC_BOGUS_STRUCT:
2745 case RPC_FC_SMFARRAY:
2746 case RPC_FC_SMVARRAY:
2747 case RPC_FC_CSTRING:
2748 return *(const WORD*)&pFormat[2];
2749 case RPC_FC_USER_MARSHAL:
2750 return *(const WORD*)&pFormat[4];
2751 case RPC_FC_RANGE: {
2752 switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2753 case RPC_FC_BYTE:
2754 case RPC_FC_CHAR:
2755 case RPC_FC_SMALL:
2756 case RPC_FC_USMALL:
2757 return sizeof(UCHAR);
2758 case RPC_FC_WCHAR:
2759 case RPC_FC_SHORT:
2760 case RPC_FC_USHORT:
2761 return sizeof(USHORT);
2762 case RPC_FC_LONG:
2763 case RPC_FC_ULONG:
2764 case RPC_FC_ENUM32:
2765 case RPC_FC_INT3264:
2766 case RPC_FC_UINT3264:
2767 return sizeof(ULONG);
2768 case RPC_FC_FLOAT:
2769 return sizeof(float);
2770 case RPC_FC_DOUBLE:
2771 return sizeof(double);
2772 case RPC_FC_HYPER:
2773 return sizeof(ULONGLONG);
2774 case RPC_FC_ENUM16:
2775 return sizeof(UINT);
2776 default:
2777 ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2778 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2779 }
2780 }
2781 case RPC_FC_NON_ENCAPSULATED_UNION:
2782 pFormat += 2;
2783 if (pStubMsg->fHasNewCorrDesc)
2784 pFormat += 6;
2785 else
2786 pFormat += 4;
2787
2788 pFormat += *(const SHORT*)pFormat;
2789 return *(const SHORT*)pFormat;
2790 case RPC_FC_IP:
2791 return sizeof(void *);
2792 case RPC_FC_WSTRING:
2793 return *(const WORD*)&pFormat[2] * 2;
2794 default:
2795 FIXME("unhandled embedded type %02x\n", *pFormat);
2796 }
2797 return 0;
2798 }
2799
2800
2801 static ULONG EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2802 PFORMAT_STRING pFormat)
2803 {
2804 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2805
2806 if (!m)
2807 {
2808 FIXME("no memorysizer for data type=%02x\n", *pFormat);
2809 return 0;
2810 }
2811
2812 return m(pStubMsg, pFormat);
2813 }
2814
2815
2816 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2817 unsigned char *pMemory,
2818 PFORMAT_STRING pFormat,
2819 PFORMAT_STRING pPointer)
2820 {
2821 PFORMAT_STRING desc;
2822 NDR_MARSHALL m;
2823 ULONG size;
2824
2825 while (*pFormat != RPC_FC_END) {
2826 switch (*pFormat) {
2827 case RPC_FC_BYTE:
2828 case RPC_FC_CHAR:
2829 case RPC_FC_SMALL:
2830 case RPC_FC_USMALL:
2831 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2832 safe_copy_to_buffer(pStubMsg, pMemory, 1);
2833 pMemory += 1;
2834 break;
2835 case RPC_FC_WCHAR:
2836 case RPC_FC_SHORT:
2837 case RPC_FC_USHORT:
2838 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2839 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2840 pMemory += 2;
2841 break;
2842 case RPC_FC_ENUM16:
2843 {
2844 USHORT val = *(DWORD *)pMemory;
2845 TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2846 if (32767 < *(DWORD*)pMemory)
2847 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2848 safe_copy_to_buffer(pStubMsg, &val, 2);
2849 pMemory += 4;
2850 break;
2851 }
2852 case RPC_FC_LONG:
2853 case RPC_FC_ULONG:
2854 case RPC_FC_ENUM32:
2855 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2856 safe_copy_to_buffer(pStubMsg, pMemory, 4);
2857 pMemory += 4;
2858 break;
2859 case RPC_FC_INT3264:
2860 case RPC_FC_UINT3264:
2861 {
2862 UINT val = *(UINT_PTR *)pMemory;
2863 TRACE("int3264=%ld <= %p\n", *(UINT_PTR *)pMemory, pMemory);
2864 safe_copy_to_buffer(pStubMsg, &val, sizeof(UINT));
2865 pMemory += sizeof(UINT_PTR);
2866 break;
2867 }
2868 case RPC_FC_FLOAT:
2869 TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
2870 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
2871 pMemory += sizeof(float);
2872 break;
2873 case RPC_FC_HYPER:
2874 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2875 safe_copy_to_buffer(pStubMsg, pMemory, 8);
2876 pMemory += 8;
2877 break;
2878 case RPC_FC_DOUBLE:
2879 TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
2880 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
2881 pMemory += sizeof(double);
2882 break;
2883 case RPC_FC_RP:
2884 case RPC_FC_UP:
2885 case RPC_FC_OP:
2886 case RPC_FC_FP:
2887 case RPC_FC_POINTER:
2888 {
2889 unsigned char *saved_buffer;
2890 int pointer_buffer_mark_set = 0;
2891 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2892 TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2893 if (*pFormat != RPC_FC_POINTER)
2894 pPointer = pFormat;
2895 if (*pPointer != RPC_FC_RP)
2896 align_pointer_clear(&pStubMsg->Buffer, 4);
2897 saved_buffer = pStubMsg->Buffer;
2898 if (pStubMsg->PointerBufferMark)
2899 {
2900 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2901 pStubMsg->PointerBufferMark = NULL;
2902 pointer_buffer_mark_set = 1;
2903 }
2904 else if (*pPointer != RPC_FC_RP)
2905 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2906 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2907 if (pointer_buffer_mark_set)
2908 {
2909 STD_OVERFLOW_CHECK(pStubMsg);
2910 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2911 pStubMsg->Buffer = saved_buffer;
2912 if (*pPointer != RPC_FC_RP)
2913 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2914 }
2915 TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2916 if (*pFormat == RPC_FC_POINTER)
2917 pPointer += 4;
2918 else
2919 pFormat += 4;
2920 pMemory += sizeof(void *);
2921 break;
2922 }
2923 case RPC_FC_ALIGNM2:
2924 align_pointer(&pMemory, 2);
2925 break;
2926 case RPC_FC_ALIGNM4:
2927 align_pointer(&pMemory, 4);
2928 break;
2929 case RPC_FC_ALIGNM8:
2930 align_pointer(&pMemory, 8);
2931 break;
2932 case RPC_FC_STRUCTPAD1:
2933 case RPC_FC_STRUCTPAD2:
2934 case RPC_FC_STRUCTPAD3:
2935 case RPC_FC_STRUCTPAD4:
2936 case RPC_FC_STRUCTPAD5:
2937 case RPC_FC_STRUCTPAD6:
2938 case RPC_FC_STRUCTPAD7:
2939 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2940 break;
2941 case RPC_FC_EMBEDDED_COMPLEX:
2942 pMemory += pFormat[1];
2943 pFormat += 2;
2944 desc = pFormat + *(const SHORT*)pFormat;
2945 size = EmbeddedComplexSize(pStubMsg, desc);
2946 TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2947 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2948 if (m)
2949 {
2950 /* for some reason interface pointers aren't generated as
2951 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2952 * they still need the derefencing treatment that pointers are
2953 * given */
2954 if (*desc == RPC_FC_IP)
2955 m(pStubMsg, *(unsigned char **)pMemory, desc);
2956 else
2957 m(pStubMsg, pMemory, desc);
2958 }
2959 else FIXME("no marshaller for embedded type %02x\n", *desc);
2960 pMemory += size;
2961 pFormat += 2;
2962 continue;
2963 case RPC_FC_PAD:
2964 break;
2965 default:
2966 FIXME("unhandled format 0x%02x\n", *pFormat);
2967 }
2968 pFormat++;
2969 }
2970
2971 return pMemory;
2972 }
2973
2974 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2975 unsigned char *pMemory,
2976 PFORMAT_STRING pFormat,
2977 PFORMAT_STRING pPointer,
2978 unsigned char fMustAlloc)
2979 {
2980 PFORMAT_STRING desc;
2981 NDR_UNMARSHALL m;
2982 ULONG size;
2983
2984 while (*pFormat != RPC_FC_END) {
2985 switch (*pFormat) {
2986 case RPC_FC_BYTE:
2987 case RPC_FC_CHAR:
2988 case RPC_FC_SMALL:
2989 case RPC_FC_USMALL:
2990 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2991 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2992 pMemory += 1;
2993 break;
2994 case RPC_FC_WCHAR:
2995 case RPC_FC_SHORT:
2996 case RPC_FC_USHORT:
2997 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2998 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2999 pMemory += 2;
3000 break;
3001 case RPC_FC_ENUM16:
3002 {
3003 WORD val;
3004 safe_copy_from_buffer(pStubMsg, &val, 2);
3005 *(DWORD*)pMemory = val;
3006 TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
3007 if (32767 < *(DWORD*)pMemory)
3008 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
3009 pMemory += 4;
3010 break;
3011 }
3012 case RPC_FC_LONG:
3013 case RPC_FC_ULONG:
3014 case RPC_FC_ENUM32:
3015 safe_copy_from_buffer(pStubMsg, pMemory, 4);
3016 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
3017 pMemory += 4;
3018 break;
3019 case RPC_FC_INT3264:
3020 {
3021 INT val;
3022 safe_copy_from_buffer(pStubMsg, &val, 4);
3023 *(INT_PTR *)pMemory = val;
3024 TRACE("int3264=%ld => %p\n", *(INT_PTR*)pMemory, pMemory);
3025 pMemory += sizeof(INT_PTR);
3026 break;
3027 }
3028 case RPC_FC_UINT3264:
3029 {
3030 UINT val;
3031 safe_copy_from_buffer(pStubMsg, &val, 4);
3032 *(UINT_PTR *)pMemory = val;
3033 TRACE("uint3264=%ld => %p\n", *(UINT_PTR*)pMemory, pMemory);
3034 pMemory += sizeof(UINT_PTR);
3035 break;
3036 }
3037 case RPC_FC_FLOAT:
3038 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
3039 TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
3040 pMemory += sizeof(float);
3041 break;
3042 case RPC_FC_HYPER:
3043 safe_copy_from_buffer(pStubMsg, pMemory, 8);
3044 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
3045 pMemory += 8;
3046 break;
3047 case RPC_FC_DOUBLE:
3048 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
3049 TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
3050 pMemory += sizeof(double);
3051 break;
3052 case RPC_FC_RP:
3053 case RPC_FC_UP:
3054 case RPC_FC_OP:
3055 case RPC_FC_FP:
3056 case RPC_FC_POINTER:
3057 {
3058 unsigned char *saved_buffer;
3059 int pointer_buffer_mark_set = 0;
3060 TRACE("pointer => %p\n", pMemory);
3061 if (*pFormat != RPC_FC_POINTER)
3062 pPointer = pFormat;
3063 if (*pPointer != RPC_FC_RP)
3064 align_pointer(&pStubMsg->Buffer, 4);
3065 saved_buffer = pStubMsg->Buffer;
3066 if (pStubMsg->PointerBufferMark)
3067 {
3068 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3069 pStubMsg->PointerBufferMark = NULL;
3070 pointer_buffer_mark_set = 1;
3071 }
3072 else if (*pPointer != RPC_FC_RP)
3073 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3074
3075 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
3076 if (pointer_buffer_mark_set)
3077 {
3078 STD_OVERFLOW_CHECK(pStubMsg);
3079 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3080 pStubMsg->Buffer = saved_buffer;
3081 if (*pPointer != RPC_FC_RP)
3082 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3083 }
3084 if (*pFormat == RPC_FC_POINTER)
3085 pPointer += 4;
3086 else
3087 pFormat += 4;
3088 pMemory += sizeof(void *);
3089 break;
3090 }
3091 case RPC_FC_ALIGNM2:
3092 align_pointer_clear(&pMemory, 2);
3093 break;
3094 case RPC_FC_ALIGNM4:
3095 align_pointer_clear(&pMemory, 4);
3096 break;
3097 case RPC_FC_ALIGNM8:
3098 align_pointer_clear(&pMemory, 8);
3099 break;
3100 case RPC_FC_STRUCTPAD1:
3101 case RPC_FC_STRUCTPAD2:
3102 case RPC_FC_STRUCTPAD3:
3103 case RPC_FC_STRUCTPAD4:
3104 case RPC_FC_STRUCTPAD5:
3105 case RPC_FC_STRUCTPAD6:
3106 case RPC_FC_STRUCTPAD7:
3107 memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
3108 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3109 break;
3110 case RPC_FC_EMBEDDED_COMPLEX:
3111 pMemory += pFormat[1];
3112 pFormat += 2;
3113 desc = pFormat + *(const SHORT*)pFormat;
3114 size = EmbeddedComplexSize(pStubMsg, desc);
3115 TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
3116 if (fMustAlloc)
3117 /* we can't pass fMustAlloc=TRUE into the marshaller for this type
3118 * since the type is part of the memory block that is encompassed by
3119 * the whole complex type. Memory is forced to allocate when pointers
3120 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
3121 * clearing the memory we pass in to the unmarshaller */
3122 memset(pMemory, 0, size);
3123 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
3124 if (m)
3125 {
3126 /* for some reason interface pointers aren't generated as
3127 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3128 * they still need the derefencing treatment that pointers are
3129 * given */
3130 if (*desc == RPC_FC_IP)
3131 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
3132 else
3133 m(pStubMsg, &pMemory, desc, FALSE);
3134 }
3135 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
3136 pMemory += size;
3137 pFormat += 2;
3138 continue;
3139 case RPC_FC_PAD:
3140 break;
3141 default:
3142 FIXME("unhandled format %d\n", *pFormat);
3143 }
3144 pFormat++;
3145 }
3146
3147 return pMemory;
3148 }
3149
3150 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3151 unsigned char *pMemory,
3152 PFORMAT_STRING pFormat,
3153 PFORMAT_STRING pPointer)
3154 {
3155 PFORMAT_STRING desc;
3156 NDR_BUFFERSIZE m;
3157 ULONG size;
3158
3159 while (*pFormat != RPC_FC_END) {
3160 switch (*pFormat) {
3161 case RPC_FC_BYTE:
3162 case RPC_FC_CHAR:
3163 case RPC_FC_SMALL:
3164 case RPC_FC_USMALL:
3165 safe_buffer_length_increment(pStubMsg, 1);
3166 pMemory += 1;
3167 break;
3168 case RPC_FC_WCHAR:
3169 case RPC_FC_SHORT:
3170 case RPC_FC_USHORT:
3171 safe_buffer_length_increment(pStubMsg, 2);
3172 pMemory += 2;
3173 break;
3174 case RPC_FC_ENUM16:
3175 safe_buffer_length_increment(pStubMsg, 2);
3176 pMemory += 4;
3177 break;
3178 case RPC_FC_LONG:
3179 case RPC_FC_ULONG:
3180 case RPC_FC_ENUM32:
3181 case RPC_FC_FLOAT:
3182 safe_buffer_length_increment(pStubMsg, 4);
3183 pMemory += 4;
3184 break;
3185 case RPC_FC_INT3264:
3186 case RPC_FC_UINT3264:
3187 safe_buffer_length_increment(pStubMsg, 4);
3188 pMemory += sizeof(INT_PTR);
3189 break;
3190 case RPC_FC_HYPER:
3191 case RPC_FC_DOUBLE:
3192 safe_buffer_length_increment(pStubMsg, 8);
3193 pMemory += 8;
3194 break;
3195 case RPC_FC_RP:
3196 case RPC_FC_UP:
3197 case RPC_FC_OP:
3198 case RPC_FC_FP:
3199 case RPC_FC_POINTER:
3200 if (*pFormat != RPC_FC_POINTER)
3201 pPointer = pFormat;
3202 if (!pStubMsg->IgnoreEmbeddedPointers)
3203 {
3204 int saved_buffer_length = pStubMsg->BufferLength;
3205 pStubMsg->BufferLength = pStubMsg->PointerLength;
3206 pStubMsg->PointerLength = 0;
3207 if(!pStubMsg->BufferLength)
3208 ERR("BufferLength == 0??\n");
3209 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
3210 pStubMsg->PointerLength = pStubMsg->BufferLength;
3211 pStubMsg->BufferLength = saved_buffer_length;
3212 }
3213 if (*pPointer != RPC_FC_RP)
3214 {
3215 align_length(&pStubMsg->BufferLength, 4);
3216 safe_buffer_length_increment(pStubMsg, 4);
3217 }
3218 if (*pFormat == RPC_FC_POINTER)
3219 pPointer += 4;
3220 else
3221 pFormat += 4;
3222 pMemory += sizeof(void*);
3223 break;
3224 case RPC_FC_ALIGNM2:
3225 align_pointer(&pMemory, 2);
3226 break;
3227 case RPC_FC_ALIGNM4:
3228 align_pointer(&pMemory, 4);
3229 break;
3230 case RPC_FC_ALIGNM8:
3231 align_pointer(&pMemory, 8);
3232 break;
3233 case RPC_FC_STRUCTPAD1:
3234 case RPC_FC_STRUCTPAD2:
3235 case RPC_FC_STRUCTPAD3:
3236 case RPC_FC_STRUCTPAD4:
3237 case RPC_FC_STRUCTPAD5:
3238 case RPC_FC_STRUCTPAD6:
3239 case RPC_FC_STRUCTPAD7:
3240 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3241 break;
3242 case RPC_FC_EMBEDDED_COMPLEX:
3243 pMemory += pFormat[1];
3244 pFormat += 2;
3245 desc = pFormat + *(const SHORT*)pFormat;
3246 size = EmbeddedComplexSize(pStubMsg, desc);
3247 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3248 if (m)
3249 {
3250 /* for some reason interface pointers aren't generated as
3251 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3252 * they still need the derefencing treatment that pointers are
3253 * given */
3254 if (*desc == RPC_FC_IP)
3255 m(pStubMsg, *(unsigned char **)pMemory, desc);
3256 else
3257 m(pStubMsg, pMemory, desc);
3258 }
3259 else FIXME("no buffersizer for embedded type %02x\n", *desc);
3260 pMemory += size;
3261 pFormat += 2;
3262 continue;
3263 case RPC_FC_PAD:
3264 break;
3265 default:
3266 FIXME("unhandled format 0x%02x\n", *pFormat);
3267 }
3268 pFormat++;
3269 }
3270
3271 return pMemory;
3272 }
3273
3274 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
3275 unsigned char *pMemory,
3276 PFORMAT_STRING pFormat,
3277 PFORMAT_STRING pPointer)
3278 {
3279 PFORMAT_STRING desc;
3280 NDR_FREE m;
3281 ULONG size;
3282
3283 while (*pFormat != RPC_FC_END) {
3284 switch (*pFormat) {
3285 case RPC_FC_BYTE:
3286 case RPC_FC_CHAR:
3287 case RPC_FC_SMALL:
3288 case RPC_FC_USMALL:
3289 pMemory += 1;
3290 break;
3291 case RPC_FC_WCHAR:
3292 case RPC_FC_SHORT:
3293 case RPC_FC_USHORT:
3294 pMemory += 2;
3295 break;
3296 case RPC_FC_LONG:
3297 case RPC_FC_ULONG:
3298 case RPC_FC_ENUM16:
3299 case RPC_FC_ENUM32:
3300 case RPC_FC_FLOAT:
3301 pMemory += 4;
3302 break;
3303 case RPC_FC_INT3264:
3304 case RPC_FC_UINT3264:
3305 pMemory += sizeof(INT_PTR);
3306 break;
3307 case RPC_FC_HYPER:
3308 case RPC_FC_DOUBLE:
3309 pMemory += 8;
3310 break;
3311 case RPC_FC_RP:
3312 case RPC_FC_UP:
3313 case RPC_FC_OP:
3314 case RPC_FC_FP:
3315 case RPC_FC_POINTER:
3316 if (*pFormat != RPC_FC_POINTER)
3317 pPointer = pFormat;
3318 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3319 if (*pFormat == RPC_FC_POINTER)
3320 pPointer += 4;
3321 else
3322 pFormat += 4;
3323 pMemory += sizeof(void *);
3324 break;
3325 case RPC_FC_ALIGNM2:
3326 align_pointer(&pMemory, 2);
3327 break;
3328 case RPC_FC_ALIGNM4:
3329 align_pointer(&pMemory, 4);
3330 break;
3331 case RPC_FC_ALIGNM8:
3332 align_pointer(&pMemory, 8);
3333 break;
3334 case RPC_FC_STRUCTPAD1:
3335 case RPC_FC_STRUCTPAD2:
3336 case RPC_FC_STRUCTPAD3:
3337 case RPC_FC_STRUCTPAD4:
3338 case RPC_FC_STRUCTPAD5:
3339 case RPC_FC_STRUCTPAD6:
3340 case RPC_FC_STRUCTPAD7:
3341 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3342 break;
3343 case RPC_FC_EMBEDDED_COMPLEX:
3344 pMemory += pFormat[1];
3345 pFormat += 2;
3346 desc = pFormat + *(const SHORT*)pFormat;
3347 size = EmbeddedComplexSize(pStubMsg, desc);
3348 m = NdrFreer[*desc & NDR_TABLE_MASK];
3349 if (m)
3350 {
3351 /* for some reason interface pointers aren't generated as
3352 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
3353 * they still need the derefencing treatment that pointers are
3354 * given */
3355 if (*desc == RPC_FC_IP)
3356 m(pStubMsg, *(unsigned char **)pMemory, desc);
3357 else
3358 m(pStubMsg, pMemory, desc);
3359 }
3360 pMemory += size;
3361 pFormat += 2;
3362 continue;
3363 case RPC_FC_PAD:
3364 break;
3365 default:
3366 FIXME("unhandled format 0x%02x\n", *pFormat);
3367 }
3368 pFormat++;
3369 }
3370
3371 return pMemory;
3372 }
3373
3374 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3375 PFORMAT_STRING pFormat,
3376 PFORMAT_STRING pPointer)
3377 {
3378 PFORMAT_STRING desc;
3379 ULONG size = 0;
3380
3381 while (*pFormat != RPC_FC_END) {
3382 switch (*pFormat) {
3383 case RPC_FC_BYTE:
3384 case RPC_FC_CHAR:
3385 case RPC_FC_SMALL:
3386 case RPC_FC_USMALL:
3387 size += 1;
3388 safe_buffer_increment(pStubMsg, 1);
3389 break;
3390 case RPC_FC_WCHAR:
3391 case RPC_FC_SHORT:
3392 case RPC_FC_USHORT:
3393 size += 2;
3394 safe_buffer_increment(pStubMsg, 2);
3395 break;
3396 case RPC_FC_ENUM16:
3397 size += 4;
3398 safe_buffer_increment(pStubMsg, 2);
3399 break;
3400 case RPC_FC_LONG:
3401 case RPC_FC_ULONG:
3402 case RPC_FC_ENUM32:
3403 case RPC_FC_FLOAT:
3404 size += 4;
3405 safe_buffer_increment(pStubMsg, 4);
3406 break;
3407 case RPC_FC_INT3264:
3408 case RPC_FC_UINT3264:
3409 size += sizeof(INT_PTR);
3410 safe_buffer_increment(pStubMsg, 4);
3411 break;
3412 case RPC_FC_HYPER:
3413 case RPC_FC_DOUBLE:
3414 size += 8;
3415 safe_buffer_increment(pStubMsg, 8);
3416 break;
3417 case RPC_FC_RP:
3418 case RPC_FC_UP:
3419 case RPC_FC_OP:
3420 case RPC_FC_FP:
3421 case RPC_FC_POINTER:
3422 {
3423 unsigned char *saved_buffer;
3424 int pointer_buffer_mark_set = 0;
3425 if (*pFormat != RPC_FC_POINTER)
3426 pPointer = pFormat;
3427 if (*pPointer != RPC_FC_RP)
3428 align_pointer(&pStubMsg->Buffer, 4);
3429 saved_buffer = pStubMsg->Buffer;
3430 if (pStubMsg->PointerBufferMark)
3431 {
3432 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3433 pStubMsg->PointerBufferMark = NULL;
3434 pointer_buffer_mark_set = 1;
3435 }
3436 else if (*pPointer != RPC_FC_RP)
3437 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3438
3439 if (!pStubMsg->IgnoreEmbeddedPointers)
3440 PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3441 if (pointer_buffer_mark_set)
3442 {
3443 STD_OVERFLOW_CHECK(pStubMsg);
3444 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3445 pStubMsg->Buffer = saved_buffer;
3446 if (*pPointer != RPC_FC_RP)
3447 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3448 }
3449 if (*pFormat == RPC_FC_POINTER)
3450 pPointer += 4;
3451 else
3452 pFormat += 4;
3453 size += sizeof(void *);
3454 break;
3455 }
3456 case RPC_FC_ALIGNM2:
3457 align_length(&size, 2);
3458 break;
3459 case RPC_FC_ALIGNM4:
3460 align_length(&size, 4);
3461 break;
3462 case RPC_FC_ALIGNM8:
3463 align_length(&size, 8);
3464 break;
3465 case RPC_FC_STRUCTPAD1:
3466 case RPC_FC_STRUCTPAD2:
3467 case RPC_FC_STRUCTPAD3:
3468 case RPC_FC_STRUCTPAD4:
3469 case RPC_FC_STRUCTPAD5:
3470 case RPC_FC_STRUCTPAD6:
3471 case RPC_FC_STRUCTPAD7:
3472 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3473 break;
3474 case RPC_FC_EMBEDDED_COMPLEX:
3475 size += pFormat[1];
3476 pFormat += 2;
3477 desc = pFormat + *(const SHORT*)pFormat;
3478 size += EmbeddedComplexMemorySize(pStubMsg, desc);
3479 pFormat += 2;
3480 continue;
3481 case RPC_FC_PAD:
3482 break;
3483 default:
3484 FIXME("unhandled format 0x%02x\n", *pFormat);
3485 }
3486 pFormat++;
3487 }
3488
3489 return size;
3490 }
3491
3492 ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
3493 {
3494 PFORMAT_STRING desc;
3495 ULONG size = 0;
3496
3497 while (*pFormat != RPC_FC_END) {
3498 switch (*pFormat) {
3499 case RPC_FC_BYTE:
3500 case RPC_FC_CHAR:
3501 case RPC_FC_SMALL:
3502 case RPC_FC_USMALL:
3503 size += 1;
3504 break;
3505 case RPC_FC_WCHAR:
3506 case RPC_FC_SHORT:
3507 case RPC_FC_USHORT:
3508 size += 2;
3509 break;
3510 case RPC_FC_LONG:
3511 case RPC_FC_ULONG:
3512 case RPC_FC_ENUM16:
3513 case RPC_FC_ENUM32:
3514 case RPC_FC_FLOAT:
3515 size += 4;
3516 break;
3517 case RPC_FC_INT3264:
3518 case RPC_FC_UINT3264:
3519 size += sizeof(INT_PTR);
3520 break;
3521 case RPC_FC_HYPER:
3522 case RPC_FC_DOUBLE:
3523 size += 8;
3524 break;
3525 case RPC_FC_RP:
3526 case RPC_FC_UP:
3527 case RPC_FC_OP:
3528 case RPC_FC_FP:
3529 case RPC_FC_POINTER:
3530 size += sizeof(void *);
3531 if (*pFormat != RPC_FC_POINTER)
3532 pFormat += 4;
3533 break;
3534 case RPC_FC_ALIGNM2:
3535 align_length(&size, 2);
3536 break;
3537 case RPC_FC_ALIGNM4:
3538 align_length(&size, 4);
3539 break;
3540 case RPC_FC_ALIGNM8:
3541 align_length(&size, 8);
3542 break;
3543 case RPC_FC_STRUCTPAD1:
3544 case RPC_FC_STRUCTPAD2:
3545 case RPC_FC_STRUCTPAD3:
3546 case RPC_FC_STRUCTPAD4:
3547 case RPC_FC_STRUCTPAD5:
3548 case RPC_FC_STRUCTPAD6:
3549 case RPC_FC_STRUCTPAD7:
3550 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
3551 break;
3552 case RPC_FC_EMBEDDED_COMPLEX:
3553 size += pFormat[1];
3554 pFormat += 2;
3555 desc = pFormat + *(const SHORT*)pFormat;
3556 size += EmbeddedComplexSize(pStubMsg, desc);
3557 pFormat += 2;
3558 continue;
3559 case RPC_FC_PAD:
3560 break;
3561 default:
3562 FIXME("unhandled format 0x%02x\n", *pFormat);
3563 }
3564 pFormat++;
3565 }
3566
3567 return size;
3568 }
3569
3570 /***********************************************************************
3571 * NdrComplexStructMarshall [RPCRT4.@]
3572 */
3573 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3574 unsigned char *pMemory,
3575 PFORMAT_STRING pFormat)
3576 {
3577 PFORMAT_STRING conf_array = NULL;
3578 PFORMAT_STRING pointer_desc = NULL;
3579 unsigned char *OldMemory = pStubMsg->Memory;
3580 int pointer_buffer_mark_set = 0;
3581 ULONG count = 0;
3582 ULONG max_count = 0;
3583 ULONG offset = 0;
3584
3585 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3586
3587 if (!pStubMsg->PointerBufferMark)
3588 {
3589 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3590 /* save buffer length */
3591 ULONG saved_buffer_length = pStubMsg->BufferLength;
3592
3593 /* get the buffer pointer after complex array data, but before
3594 * pointer data */
3595 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3596 pStubMsg->IgnoreEmbeddedPointers = 1;
3597 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3598 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3599
3600 /* save it for use by embedded pointer code later */
3601 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3602 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
3603 pointer_buffer_mark_set = 1;
3604
3605 /* restore the original buffer length */
3606 pStubMsg->BufferLength = saved_buffer_length;
3607 }
3608
3609 align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
3610
3611 pFormat += 4;
3612 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3613 pFormat += 2;
3614 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3615 pFormat += 2;
3616
3617 pStubMsg->Memory = pMemory;
3618
3619 if (conf_array)
3620 {
3621 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3622 array_compute_and_write_conformance(conf_array[0], pStubMsg,
3623 pMemory + struct_size, conf_array);
3624 /* these could be changed in ComplexMarshall so save them for later */
3625 max_count = pStubMsg->MaxCount;
3626 count = pStubMsg->ActualCount;
3627 offset = pStubMsg->Offset;
3628 }
3629
3630 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3631
3632 if (conf_array)
3633 {
3634 pStubMsg->MaxCount = max_count;
3635 pStubMsg->ActualCount = count;
3636 pStubMsg->Offset = offset;
3637 array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3638 conf_array, TRUE /* fHasPointers */);
3639 }
3640
3641 pStubMsg->Memory = OldMemory;
3642
3643 if (pointer_buffer_mark_set)
3644 {
3645 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3646 pStubMsg->PointerBufferMark = NULL;
3647 }
3648
3649 STD_OVERFLOW_CHECK(pStubMsg);
3650
3651 return NULL;
3652 }
3653
3654 /***********************************************************************
3655 * NdrComplexStructUnmarshall [RPCRT4.@]
3656 */
3657 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3658 unsigned char **ppMemory,
3659 PFORMAT_STRING pFormat,
3660 unsigned char fMustAlloc)
3661 {
3662 unsigned size = *(const WORD*)(pFormat+2);
3663 PFORMAT_STRING conf_array = NULL;
3664 PFORMAT_STRING pointer_desc = NULL;
3665 unsigned char *pMemory;
3666 int pointer_buffer_mark_set = 0;
3667 ULONG count = 0;
3668 ULONG max_count = 0;
3669 ULONG offset = 0;
3670 ULONG array_size = 0;
3671
3672 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3673
3674 if (!pStubMsg->PointerBufferMark)
3675 {
3676 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3677 /* save buffer pointer */
3678 unsigned char *saved_buffer = pStubMsg->Buffer;
3679
3680 /* get the buffer pointer after complex array data, but before
3681 * pointer data */
3682 pStubMsg->IgnoreEmbeddedPointers = 1;
3683 NdrComplexStructMemorySize(pStubMsg, pFormat);
3684 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3685
3686 /* save it for use by embedded pointer code later */
3687 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3688 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
3689 pointer_buffer_mark_set = 1;
3690
3691 /* restore the original buffer */
3692 pStubMsg->Buffer = saved_buffer;
3693 }
3694
3695 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
3696
3697 pFormat += 4;
3698 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3699 pFormat += 2;
3700 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3701 pFormat += 2;
3702
3703 if (conf_array)
3704 {
3705 array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3706 size += array_size;
3707
3708 /* these could be changed in ComplexMarshall so save them for later */
3709 max_count = pStubMsg->MaxCount;
3710 count = pStubMsg->ActualCount;
3711 offset = pStubMsg->Offset;
3712 }
3713
3714 if (!fMustAlloc && !*ppMemory)
3715 fMustAlloc = TRUE;
3716 if (fMustAlloc)
3717 *ppMemory = NdrAllocate(pStubMsg, size);
3718
3719 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3720
3721 if (conf_array)
3722 {
3723 pStubMsg->MaxCount = max_count;
3724 pStubMsg->ActualCount = count;
3725 pStubMsg->Offset = offset;
3726 if (fMustAlloc)
3727 memset(pMemory, 0, array_size);
3728 array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3729 conf_array, FALSE,
3730 FALSE /* fUseBufferMemoryServer */,
3731 TRUE /* fUnmarshall */);
3732 }
3733
3734 if (pointer_buffer_mark_set)
3735 {
3736 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3737 pStubMsg->PointerBufferMark = NULL;
3738 }
3739
3740 return NULL;
3741 }
3742
3743 /***********************************************************************
3744 * NdrComplexStructBufferSize [RPCRT4.@]
3745 */
3746 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3747 unsigned char *pMemory,
3748 PFORMAT_STRING pFormat)
3749 {
3750 PFORMAT_STRING conf_array = NULL;
3751 PFORMAT_STRING pointer_desc = NULL;
3752 unsigned char *OldMemory = pStubMsg->Memory;
3753 int pointer_length_set = 0;
3754 ULONG count = 0;
3755 ULONG max_count = 0;
3756 ULONG offset = 0;
3757
3758 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3759
3760 align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
3761
3762 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3763 {
3764 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3765 ULONG saved_buffer_length = pStubMsg->BufferLength;
3766
3767 /* get the buffer length after complex struct data, but before
3768 * pointer data */
3769 pStubMsg->IgnoreEmbeddedPointers = 1;
3770 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3771 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3772
3773 /* save it for use by embedded pointer code later */
3774 pStubMsg->PointerLength = pStubMsg->BufferLength;
3775 pointer_length_set = 1;
3776 TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
3777
3778 /* restore the original buffer length */
3779 pStubMsg->BufferLength = saved_buffer_length;
3780 }
3781
3782 pFormat += 4;
3783 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3784 pFormat += 2;
3785 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3786 pFormat += 2;
3787
3788 pStubMsg->Memory = pMemory;
3789
3790 if (conf_array)
3791 {
3792 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3793 array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3794 conf_array);
3795
3796 /* these could be changed in ComplexMarshall so save them for later */
3797 max_count = pStubMsg->MaxCount;
3798 count = pStubMsg->ActualCount;
3799 offset = pStubMsg->Offset;
3800 }
3801
3802 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3803
3804 if (conf_array)
3805 {
3806 pStubMsg->MaxCount = max_count;
3807 pStubMsg->ActualCount = count;
3808 pStubMsg->Offset = offset;
3809 array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3810 TRUE /* fHasPointers */);
3811 }
3812
3813 pStubMsg->Memory = OldMemory;
3814
3815 if(pointer_length_set)
3816 {
3817 pStubMsg->BufferLength = pStubMsg->PointerLength;
3818 pStubMsg->PointerLength = 0;
3819 }
3820
3821 }
3822
3823 /***********************************************************************
3824 * NdrComplexStructMemorySize [RPCRT4.@]
3825 */
3826 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3827 PFORMAT_STRING pFormat)
3828 {
3829 unsigned size = *(const WORD*)(pFormat+2);
3830 PFORMAT_STRING conf_array = NULL;
3831 PFORMAT_STRING pointer_desc = NULL;
3832 ULONG count = 0;
3833 ULONG max_count = 0;
3834 ULONG offset = 0;
3835
3836 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3837
3838 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
3839
3840 pFormat += 4;
3841 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3842 pFormat += 2;
3843 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3844 pFormat += 2;
3845
3846 if (conf_array)
3847 {
3848 array_read_conformance(conf_array[0], pStubMsg, conf_array);
3849
3850 /* these could be changed in ComplexStructMemorySize so save them for
3851 * later */
3852 max_count = pStubMsg->MaxCount;
3853 count = pStubMsg->ActualCount;
3854 offset = pStubMsg->Offset;
3855 }
3856
3857 ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3858
3859 if (conf_array)
3860 {
3861 pStubMsg->MaxCount = max_count;
3862 pStubMsg->ActualCount = count;
3863 pStubMsg->Offset = offset;
3864 array_memory_size(conf_array[0], pStubMsg, conf_array,
3865 TRUE /* fHasPointers */);
3866 }
3867
3868 return size;
3869 }
3870
3871 /***********************************************************************
3872 * NdrComplexStructFree [RPCRT4.@]
3873 */
3874 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3875 unsigned char *pMemory,
3876 PFORMAT_STRING pFormat)
3877 {
3878 PFORMAT_STRING conf_array = NULL;
3879 PFORMAT_STRING pointer_desc = NULL;
3880 unsigned char *OldMemory = pStubMsg->Memory;
3881
3882 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3883
3884 pFormat += 4;
3885 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3886 pFormat += 2;
3887 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3888 pFormat += 2;
3889
3890 pStubMsg->Memory = pMemory;
3891
3892 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3893
3894 if (conf_array)
3895 array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3896 TRUE /* fHasPointers */);
3897
3898 pStubMsg->Memory = OldMemory;
3899 }
3900
3901 /***********************************************************************
3902 * NdrConformantArrayMarshall [RPCRT4.@]
3903 */
3904 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3905 unsigned char *pMemory,
3906 PFORMAT_STRING pFormat)
3907 {
3908 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3909 if (pFormat[0] != RPC_FC_CARRAY)
3910 {
3911 ERR("invalid format = 0x%x\n", pFormat[0]);
3912 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3913 }
3914
3915 array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
3916 pFormat);
3917 array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3918 TRUE /* fHasPointers */);
3919
3920 return NULL;
3921 }
3922
3923 /***********************************************************************
3924 * NdrConformantArrayUnmarshall [RPCRT4.@]
3925 */
3926 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3927 unsigned char **ppMemory,
3928 PFORMAT_STRING pFormat,
3929 unsigned char fMustAlloc)
3930 {
3931 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3932 if (pFormat[0] != RPC_FC_CARRAY)
3933 {
3934 ERR("invalid format = 0x%x\n", pFormat[0]);
3935 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3936 }
3937
3938 array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3939 array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
3940 fMustAlloc,
3941 TRUE /* fUseBufferMemoryServer */,
3942 TRUE /* fUnmarshall */);
3943
3944 return NULL;
3945 }
3946
3947 /***********************************************************************
3948 * NdrConformantArrayBufferSize [RPCRT4.@]
3949 */
3950 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3951 unsigned char *pMemory,
3952 PFORMAT_STRING pFormat)
3953 {
3954 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3955 if (pFormat[0] != RPC_FC_CARRAY)
3956 {
3957 ERR("invalid format = 0x%x\n", pFormat[0]);
3958 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3959 }
3960
3961 array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat);
3962 array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
3963 TRUE /* fHasPointers */);
3964 }
3965
3966 /***********************************************************************
3967 * NdrConformantArrayMemorySize [RPCRT4.@]
3968 */
3969 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3970 PFORMAT_STRING pFormat)
3971 {
3972 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3973 if (pFormat[0] != RPC_FC_CARRAY)
3974 {
3975 ERR("invalid format = 0x%x\n", pFormat[0]);
3976 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3977 }
3978
3979 array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
3980 array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
3981
3982 return pStubMsg->MemorySize;
3983 }
3984
3985 /***********************************************************************
3986 * NdrConformantArrayFree [RPCRT4.@]
3987 */
3988 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3989 unsigned char *pMemory,
3990 PFORMAT_STRING pFormat)
3991 {
3992 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3993 if (pFormat[0] != RPC_FC_CARRAY)
3994 {
3995 ERR("invalid format = 0x%x\n", pFormat[0]);
3996 RpcRaiseException(RPC_X_BAD_STUB_DATA);
3997 }
3998
3999 array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
4000 TRUE /* fHasPointers */);
4001 }
4002
4003
4004 /***********************************************************************
4005 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
4006 */
4007 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
4008 unsigned char* pMemory,
4009 PFORMAT_STRING pFormat )
4010 {
4011 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4012
4013 if (pFormat[0] != RPC_FC_CVARRAY)
4014 {
4015 ERR("invalid format type %x\n", pFormat[0]);
4016 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4017 return NULL;
4018 }
4019
4020 array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
4021 pFormat);
4022 array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory,
4023 pFormat, TRUE /* fHasPointers */);
4024
4025 return NULL;
4026 }
4027
4028
4029 /***********************************************************************
4030 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
4031 */
4032 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
4033 unsigned char** ppMemory,
4034 PFORMAT_STRING pFormat,
4035 unsigned char fMustAlloc )
4036 {
4037 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4038
4039 if (pFormat[0] != RPC_FC_CVARRAY)
4040 {
4041 ERR("invalid format type %x\n", pFormat[0]);
4042 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4043 return NULL;
4044 }
4045
4046 array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
4047 array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory,
4048 pFormat, fMustAlloc,
4049 TRUE /* fUseBufferMemoryServer */,
4050 TRUE /* fUnmarshall */);
4051
4052 return NULL;
4053 }
4054
4055
4056 /***********************************************************************
4057 * NdrConformantVaryingArrayFree [RPCRT4.@]
4058 */
4059 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
4060 unsigned char* pMemory,
4061 PFORMAT_STRING pFormat )
4062 {
4063 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4064
4065 if (pFormat[0] != RPC_FC_CVARRAY)
4066 {
4067 ERR("invalid format type %x\n", pFormat[0]);
4068 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4069 return;
4070 }
4071
4072 array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
4073 TRUE /* fHasPointers */);
4074 }
4075
4076
4077 /***********************************************************************
4078 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
4079 */
4080 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
4081 unsigned char* pMemory, PFORMAT_STRING pFormat )
4082 {
4083 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4084
4085 if (pFormat[0] != RPC_FC_CVARRAY)
4086 {
4087 ERR("invalid format type %x\n", pFormat[0]);
4088 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4089 return;
4090 }
4091
4092 array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
4093 pFormat);
4094 array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
4095 TRUE /* fHasPointers */);
4096 }
4097
4098
4099 /***********************************************************************
4100 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
4101 */
4102 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
4103 PFORMAT_STRING pFormat )
4104 {
4105 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4106
4107 if (pFormat[0] != RPC_FC_CVARRAY)
4108 {
4109 ERR("invalid format type %x\n", pFormat[0]);
4110 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4111 return pStubMsg->MemorySize;
4112 }
4113
4114 array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
4115 array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat,
4116 TRUE /* fHasPointers */);
4117
4118 return pStubMsg->MemorySize;
4119 }
4120
4121
4122 /***********************************************************************
4123 * NdrComplexArrayMarshall [RPCRT4.@]
4124 */
4125 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4126 unsigned char *pMemory,
4127 PFORMAT_STRING pFormat)
4128 {
4129 int pointer_buffer_mark_set = 0;
4130
4131 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4132
4133 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4134 {
4135 ERR("invalid format type %x\n", pFormat[0]);
4136 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4137 return NULL;
4138 }
4139
4140 if (!pStubMsg->PointerBufferMark)
4141 {
4142 /* save buffer fields that may be changed by buffer sizer functions
4143 * and that may be needed later on */
4144 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4145 ULONG saved_buffer_length = pStubMsg->BufferLength;
4146 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4147 ULONG saved_offset = pStubMsg->Offset;
4148 ULONG saved_actual_count = pStubMsg->ActualCount;
4149
4150 /* get the buffer pointer after complex array data, but before
4151 * pointer data */
4152 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
4153 pStubMsg->IgnoreEmbeddedPointers = 1;
4154 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4155 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4156
4157 /* save it for use by embedded pointer code later */
4158 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
4159 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
4160 pointer_buffer_mark_set = 1;
4161
4162 /* restore fields */
4163 pStubMsg->ActualCount = saved_actual_count;
4164 pStubMsg->Offset = saved_offset;
4165 pStubMsg->MaxCount = saved_max_count;
4166 pStubMsg->BufferLength = saved_buffer_length;
4167 }
4168
4169 array_compute_and_write_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat);
4170 array_write_variance_and_marshall(RPC_FC_BOGUS_ARRAY, pStubMsg,
4171 pMemory, pFormat, TRUE /* fHasPointers */);
4172
4173 STD_OVERFLOW_CHECK(pStubMsg);
4174
4175 if (pointer_buffer_mark_set)
4176 {
4177 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4178 pStubMsg->PointerBufferMark = NULL;
4179 }
4180
4181 return NULL;
4182 }
4183
4184 /***********************************************************************
4185 * NdrComplexArrayUnmarshall [RPCRT4.@]
4186 */
4187 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4188 unsigned char **ppMemory,
4189 PFORMAT_STRING pFormat,
4190 unsigned char fMustAlloc)
4191 {
4192 unsigned char *saved_buffer;
4193 int pointer_buffer_mark_set = 0;
4194 int saved_ignore_embedded;
4195
4196 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4197
4198 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4199 {
4200 ERR("invalid format type %x\n", pFormat[0]);
4201 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4202 return NULL;
4203 }
4204
4205 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4206 /* save buffer pointer */
4207 saved_buffer = pStubMsg->Buffer;
4208 /* get the buffer pointer after complex array data, but before
4209 * pointer data */
4210 pStubMsg->IgnoreEmbeddedPointers = 1;
4211 pStubMsg->MemorySize = 0;
4212 NdrComplexArrayMemorySize(pStubMsg, pFormat);
4213 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4214
4215 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer));
4216 if (!pStubMsg->PointerBufferMark)
4217 {
4218 /* save it for use by embedded pointer code later */
4219 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4220 pointer_buffer_mark_set = 1;
4221 }
4222 /* restore the original buffer */
4223 pStubMsg->Buffer = saved_buffer;
4224
4225 array_read_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat);
4226 array_read_variance_and_unmarshall(RPC_FC_BOGUS_ARRAY, pStubMsg, ppMemory, pFormat, fMustAlloc,
4227 TRUE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */);
4228
4229 if (pointer_buffer_mark_set)
4230 {
4231 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4232 pStubMsg->PointerBufferMark = NULL;
4233 }
4234
4235 return NULL;
4236 }
4237
4238 /***********************************************************************
4239 * NdrComplexArrayBufferSize [RPCRT4.@]
4240 */
4241 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4242 unsigned char *pMemory,
4243 PFORMAT_STRING pFormat)
4244 {
4245 int pointer_length_set = 0;
4246
4247 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4248
4249 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4250 {
4251 ERR("invalid format type %x\n", pFormat[0]);
4252 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4253 return;
4254 }
4255
4256 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
4257 {
4258 /* save buffer fields that may be changed by buffer sizer functions
4259 * and that may be needed later on */
4260 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
4261 ULONG saved_buffer_length = pStubMsg->BufferLength;
4262 ULONG_PTR saved_max_count = pStubMsg->MaxCount;
4263 ULONG saved_offset = pStubMsg->Offset;
4264 ULONG saved_actual_count = pStubMsg->ActualCount;
4265
4266 /* get the buffer pointer after complex array data, but before
4267 * pointer data */
4268 pStubMsg->IgnoreEmbeddedPointers = 1;
4269 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
4270 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
4271
4272 /* save it for use by embedded pointer code later */
4273 pStubMsg->PointerLength = pStubMsg->BufferLength;
4274 pointer_length_set = 1;
4275
4276 /* restore fields */
4277 pStubMsg->ActualCount = saved_actual_count;
4278 pStubMsg->Offset = saved_offset;
4279 pStubMsg->MaxCount = saved_max_count;
4280 pStubMsg->BufferLength = saved_buffer_length;
4281 }
4282
4283 array_compute_and_size_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat);
4284 array_buffer_size(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */);
4285
4286 if(pointer_length_set)
4287 {
4288 pStubMsg->BufferLength = pStubMsg->PointerLength;
4289 pStubMsg->PointerLength = 0;
4290 }
4291 }
4292
4293 /***********************************************************************
4294 * NdrComplexArrayMemorySize [RPCRT4.@]
4295 */
4296 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4297 PFORMAT_STRING pFormat)
4298 {
4299 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4300
4301 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4302 {
4303 ERR("invalid format type %x\n", pFormat[0]);
4304 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4305 return 0;
4306 }
4307
4308 array_read_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat);
4309 array_memory_size(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
4310 return pStubMsg->MemorySize;
4311 }
4312
4313 /***********************************************************************
4314 * NdrComplexArrayFree [RPCRT4.@]
4315 */
4316 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
4317 unsigned char *pMemory,
4318 PFORMAT_STRING pFormat)
4319 {
4320 ULONG i, count, def;
4321
4322 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4323
4324 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
4325 {
4326 ERR("invalid format type %x\n", pFormat[0]);
4327 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4328 return;
4329 }
4330
4331 def = *(const WORD*)&pFormat[2];
4332 pFormat += 4;
4333
4334 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
4335 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
4336
4337 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
4338 TRACE("variance = %d\n", pStubMsg->ActualCount);
4339
4340 count = pStubMsg->ActualCount;
4341 for (i = 0; i < count; i++)
4342 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
4343 }
4344
4345 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
4346 USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
4347 USER_MARSHAL_CB *umcb)
4348 {
4349 umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
4350 pStubMsg->RpcMsg->DataRepresentation);
4351 umcb->pStubMsg = pStubMsg;
4352 umcb->pReserve = NULL;
4353 umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
4354 umcb->CBType = cbtype;
4355 umcb->pFormat = pFormat;
4356 umcb->pTypeFormat = NULL /* FIXME */;
4357 }
4358
4359 #define USER_MARSHAL_PTR_PREFIX \
4360 ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
4361 ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
4362
4363 /***********************************************************************
4364 * NdrUserMarshalMarshall [RPCRT4.@]
4365 */
4366 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4367 unsigned char *pMemory,
4368 PFORMAT_STRING pFormat)
4369 {
4370 unsigned flags = pFormat[1];
4371 unsigned index = *(const WORD*)&pFormat[2];
4372 unsigned char *saved_buffer = NULL;
4373 USER_MARSHAL_CB umcb;
4374
4375 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4376 TRACE("index=%d\n", index);
4377
4378 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
4379
4380 if (flags & USER_MARSHAL_POINTER)
4381 {
4382 align_pointer_clear(&pStubMsg->Buffer, 4);
4383 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
4384 pStubMsg->Buffer += 4;
4385 if (pStubMsg->PointerBufferMark)
4386 {
4387 saved_buffer = pStubMsg->Buffer;
4388 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4389 pStubMsg->PointerBufferMark = NULL;
4390 }
4391 align_pointer_clear(&pStubMsg->Buffer, 8);
4392 }
4393 else
4394 align_pointer_clear(&pStubMsg->Buffer, (flags & 0xf) + 1);
4395
4396 pStubMsg->Buffer =
4397 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
4398 &umcb.Flags, pStubMsg->Buffer, pMemory);
4399
4400 if (saved_buffer)
4401 {
4402 STD_OVERFLOW_CHECK(pStubMsg);
4403 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4404 pStubMsg->Buffer = saved_buffer;
4405 }
4406
4407 STD_OVERFLOW_CHECK(pStubMsg);
4408
4409 return NULL;
4410 }
4411
4412 /***********************************************************************
4413 * NdrUserMarshalUnmarshall [RPCRT4.@]
4414 */
4415 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4416 unsigned char **ppMemory,
4417 PFORMAT_STRING pFormat,
4418 unsigned char fMustAlloc)
4419 {
4420 unsigned flags = pFormat[1];
4421 unsigned index = *(const WORD*)&pFormat[2];
4422 DWORD memsize = *(const WORD*)&pFormat[4];
4423 unsigned char *saved_buffer = NULL;
4424 USER_MARSHAL_CB umcb;
4425
4426 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4427 TRACE("index=%d\n", index);
4428
4429 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
4430
4431 if (flags & USER_MARSHAL_POINTER)
4432 {
4433 align_pointer(&pStubMsg->Buffer, 4);
4434 /* skip pointer prefix */
4435 pStubMsg->Buffer += 4;
4436 if (pStubMsg->PointerBufferMark)
4437 {
4438 saved_buffer = pStubMsg->Buffer;
4439 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
4440 pStubMsg->PointerBufferMark = NULL;
4441 }
4442 align_pointer(&pStubMsg->Buffer, 8);
4443 }
4444 else
4445 align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1);
4446
4447 if (!fMustAlloc && !*ppMemory)
4448 fMustAlloc = TRUE;
4449 if (fMustAlloc)
4450 {
4451 *ppMemory = NdrAllocate(pStubMsg, memsize);
4452 memset(*ppMemory, 0, memsize);
4453 }
4454
4455 pStubMsg->Buffer =
4456 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
4457 &umcb.Flags, pStubMsg->Buffer, *ppMemory);
4458
4459 if (saved_buffer)
4460 {
4461 STD_OVERFLOW_CHECK(pStubMsg);
4462 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
4463 pStubMsg->Buffer = saved_buffer;
4464 }
4465
4466 return NULL;
4467 }
4468
4469 /***********************************************************************
4470 * NdrUserMarshalBufferSize [RPCRT4.@]
4471 */
4472 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4473 unsigned char *pMemory,
4474 PFORMAT_STRING pFormat)
4475 {
4476 unsigned flags = pFormat[1];
4477 unsigned index = *(const WORD*)&pFormat[2];
4478 DWORD bufsize = *(const WORD*)&pFormat[6];
4479 USER_MARSHAL_CB umcb;
4480 ULONG saved_buffer_length = 0;
4481
4482 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4483 TRACE("index=%d\n", index);
4484
4485 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
4486
4487 if (flags & USER_MARSHAL_POINTER)
4488 {
4489 align_length(&pStubMsg->BufferLength, 4);
4490 /* skip pointer prefix */
4491 safe_buffer_length_increment(pStubMsg, 4);
4492 if (pStubMsg->IgnoreEmbeddedPointers)
4493 return;
4494 if (pStubMsg->PointerLength)
4495 {
4496 saved_buffer_length = pStubMsg->BufferLength;
4497 pStubMsg->BufferLength = pStubMsg->PointerLength;
4498 pStubMsg->PointerLength = 0;
4499 }
4500 align_length(&pStubMsg->BufferLength, 8);
4501 }
4502 else
4503 align_length(&pStubMsg->BufferLength, (flags & 0xf) + 1);
4504
4505 if (bufsize) {
4506 TRACE("size=%d\n", bufsize);
4507 safe_buffer_length_increment(pStubMsg, bufsize);
4508 }
4509 else
4510 pStubMsg->BufferLength =
4511 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
4512 &umcb.Flags, pStubMsg->BufferLength, pMemory);
4513
4514 if (saved_buffer_length)
4515 {
4516 pStubMsg->PointerLength = pStubMsg->BufferLength;
4517 pStubMsg->BufferLength = saved_buffer_length;
4518 }
4519
4520 }
4521
4522 /***********************************************************************
4523 * NdrUserMarshalMemorySize [RPCRT4.@]
4524 */
4525 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4526 PFORMAT_STRING pFormat)
4527 {
4528 unsigned flags = pFormat[1];
4529 unsigned index = *(const WORD*)&pFormat[2];
4530 DWORD memsize = *(const WORD*)&pFormat[4];
4531 DWORD bufsize = *(const WORD*)&pFormat[6];
4532
4533 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4534 TRACE("index=%d\n", index);
4535
4536 pStubMsg->MemorySize += memsize;
4537
4538 if (flags & USER_MARSHAL_POINTER)
4539 {
4540 align_pointer(&pStubMsg->Buffer, 4);
4541 /* skip pointer prefix */
4542 pStubMsg->Buffer += 4;
4543 if (pStubMsg->IgnoreEmbeddedPointers)
4544 return pStubMsg->MemorySize;
4545 align_pointer(&pStubMsg->Buffer, 8);
4546 }
4547 else
4548 align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1);
4549
4550 if (!bufsize)
4551 FIXME("not implemented for varying buffer size\n");
4552
4553 pStubMsg->Buffer += bufsize;
4554
4555 return pStubMsg->MemorySize;
4556 }
4557
4558 /***********************************************************************
4559 * NdrUserMarshalFree [RPCRT4.@]
4560 */
4561 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
4562 unsigned char *pMemory,
4563 PFORMAT_STRING pFormat)
4564 {
4565 /* unsigned flags = pFormat[1]; */
4566 unsigned index = *(const WORD*)&pFormat[2];
4567 USER_MARSHAL_CB umcb;
4568
4569 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4570 TRACE("index=%d\n", index);
4571
4572 UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
4573
4574 pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
4575 &umcb.Flags, pMemory);
4576 }
4577
4578 /***********************************************************************
4579 * NdrGetUserMarshalInfo [RPCRT4.@]
4580 */
4581 RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi)
4582 {
4583 USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags);
4584
4585 TRACE("(%p,%u,%p)\n", flags, level, umi);
4586
4587 if (level != 1)
4588 return RPC_S_INVALID_ARG;
4589
4590 memset(&umi->u1.Level1, 0, sizeof(umi->u1.Level1));
4591 umi->InformationLevel = level;
4592
4593 if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE)
4594 return RPC_S_INVALID_ARG;
4595
4596 umi->u1.Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate;
4597 umi->u1.Level1.pfnFree = umcb->pStubMsg->pfnFree;
4598 umi->u1.Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer;
4599
4600 switch (umcb->CBType)
4601 {
4602 case USER_MARSHAL_CB_MARSHALL:
4603 case USER_MARSHAL_CB_UNMARSHALL:
4604 {
4605 RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg;
4606 unsigned char *buffer_start = msg->Buffer;
4607 unsigned char *buffer_end =
4608 (unsigned char *)msg->Buffer + msg->BufferLength;
4609
4610 if (umcb->pStubMsg->Buffer < buffer_start ||
4611 umcb->pStubMsg->Buffer > buffer_end)
4612 return ERROR_INVALID_USER_BUFFER;
4613
4614 umi->u1.Level1.Buffer = umcb->pStubMsg->Buffer;
4615 umi->u1.Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer;
4616 break;
4617 }
4618 case USER_MARSHAL_CB_BUFFER_SIZE:
4619 case USER_MARSHAL_CB_FREE:
4620 break;
4621 default:
4622 WARN("unrecognised CBType %d\n", umcb->CBType);
4623 }
4624
4625 return RPC_S_OK;
4626 }
4627
4628 /***********************************************************************
4629 * NdrClearOutParameters [RPCRT4.@]
4630 */
4631 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
4632 PFORMAT_STRING pFormat,
4633 void *ArgAddr)
4634 {
4635 FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
4636 }
4637
4638 /***********************************************************************
4639 * NdrConvert [RPCRT4.@]
4640 */
4641 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
4642 {
4643 FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
4644 /* FIXME: since this stub doesn't do any converting, the proper behavior
4645 is to raise an exception */
4646 }
4647
4648 /***********************************************************************
4649 * NdrConvert2 [RPCRT4.@]
4650 */
4651 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
4652 {
4653 FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
4654 pStubMsg, pFormat, NumberParams);
4655 /* FIXME: since this stub doesn't do any converting, the proper behavior
4656 is to raise an exception */
4657 }
4658
4659 #include "pshpack1.h"
4660 typedef struct _NDR_CSTRUCT_FORMAT
4661 {
4662 unsigned char type;
4663 unsigned char alignment;
4664 unsigned short memory_size;
4665 short offset_to_array_description;
4666 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
4667 #include "poppack.h"
4668
4669 /***********************************************************************
4670 * NdrConformantStructMarshall [RPCRT4.@]
4671 */
4672 unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4673 unsigned char *pMemory,
4674 PFORMAT_STRING pFormat)
4675 {
4676 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4677 PFORMAT_STRING pCArrayFormat;
4678 ULONG esize, bufsize;
4679
4680 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4681
4682 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4683 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4684 {
4685 ERR("invalid format type %x\n", pCStructFormat->type);
4686 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4687 return NULL;
4688 }
4689
4690 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4691 pCStructFormat->offset_to_array_description;
4692 if (*pCArrayFormat != RPC_FC_CARRAY)
4693 {
4694 ERR("invalid array format type %x\n", pCStructFormat->type);
4695 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4696 return NULL;
4697 }
4698 esize = *(const WORD*)(pCArrayFormat+2);
4699
4700 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4701 pCArrayFormat + 4, 0);
4702
4703 WriteConformance(pStubMsg);
4704
4705 align_pointer_clear(&pStubMsg->Buffer, pCStructFormat->alignment + 1);
4706
4707 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4708
4709 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4710 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4711 {
4712 ERR("integer overflow of memory_size %u with bufsize %u\n",
4713 pCStructFormat->memory_size, bufsize);
4714 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4715 }
4716 /* copy constant sized part of struct */
4717 pStubMsg->BufferMark = pStubMsg->Buffer;
4718 safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
4719
4720 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4721 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4722
4723 return NULL;
4724 }
4725
4726 /***********************************************************************
4727 * NdrConformantStructUnmarshall [RPCRT4.@]
4728 */
4729 unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4730 unsigned char **ppMemory,
4731 PFORMAT_STRING pFormat,
4732 unsigned char fMustAlloc)
4733 {
4734 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4735 PFORMAT_STRING pCArrayFormat;
4736 ULONG esize, bufsize;
4737 unsigned char *saved_buffer;
4738
4739 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4740
4741 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4742 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4743 {
4744 ERR("invalid format type %x\n", pCStructFormat->type);
4745 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4746 return NULL;
4747 }
4748 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4749 pCStructFormat->offset_to_array_description;
4750 if (*pCArrayFormat != RPC_FC_CARRAY)
4751 {
4752 ERR("invalid array format type %x\n", pCStructFormat->type);
4753 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4754 return NULL;
4755 }
4756 esize = *(const WORD*)(pCArrayFormat+2);
4757
4758 pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
4759
4760 align_pointer(&pStubMsg->Buffer, pCStructFormat->alignment + 1);
4761
4762 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4763
4764 bufsize = safe_multiply(esize, pStubMsg->MaxCount);
4765 if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
4766 {
4767 ERR("integer overflow of memory_size %u with bufsize %u\n",
4768 pCStructFormat->memory_size, bufsize);
4769 RpcRaiseException(RPC_X_BAD_STUB_DATA);
4770 }
4771
4772 if (fMustAlloc)
4773 {
4774 SIZE_T size = pCStructFormat->memory_size + bufsize;
4775 *ppMemory = NdrAllocate(pStubMsg, size);
4776 }
4777 else
4778 {
4779 if (!pStubMsg->IsClient && !*ppMemory)
4780 /* for servers, we just point straight into the RPC buffer */
4781 *ppMemory = pStubMsg->Buffer;
4782 }
4783
4784 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4785 safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
4786 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4787 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4788
4789 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
4790 if (*ppMemory != saved_buffer)
4791 memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
4792
4793 return NULL;
4794 }
4795
4796 /***********************************************************************
4797 * NdrConformantStructBufferSize [RPCRT4.@]
4798 */
4799 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
4800 unsigned char *pMemory,
4801 PFORMAT_STRING pFormat)
4802 {
4803 const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4804 PFORMAT_STRING pCArrayFormat;
4805 ULONG esize;
4806
4807 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4808
4809 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4810 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4811 {
4812 ERR("invalid format type %x\n", pCStructFormat->type);
4813 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4814 return;
4815 }
4816 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4817 pCStructFormat->offset_to_array_description;
4818 if (*pCArrayFormat != RPC_FC_CARRAY)
4819 {
4820 ERR("invalid array format type %x\n", pCStructFormat->type);
4821 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4822 return;
4823 }
4824 esize = *(const WORD*)(pCArrayFormat+2);
4825
4826 pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
4827 SizeConformance(pStubMsg);
4828
4829 align_length(&pStubMsg->BufferLength, pCStructFormat->alignment + 1);
4830
4831 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4832
4833 safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
4834 safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
4835
4836 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4837 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
4838 }
4839
4840 /***********************************************************************
4841 * NdrConformantStructMemorySize [RPCRT4.@]
4842 */
4843 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
4844 PFORMAT_STRING pFormat)
4845 {
4846 FIXME("stub\n");
4847 return 0;
4848 }
4849
4850 /***********************************************************************
4851 * NdrConformantStructFree [RPCRT4.@]
4852 */
4853 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
4854 unsigned char *pMemory,
4855 PFORMAT_STRING pFormat)
4856 {
4857 const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
4858 PFORMAT_STRING pCArrayFormat;
4859
4860 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4861
4862 pFormat += sizeof(NDR_CSTRUCT_FORMAT);
4863 if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
4864 {
4865 ERR("invalid format type %x\n", pCStructFormat->type);
4866 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4867 return;
4868 }
4869
4870 pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
4871 pCStructFormat->offset_to_array_description;
4872 if (*pCArrayFormat != RPC_FC_CARRAY)
4873 {
4874 ERR("invalid array format type %x\n", pCStructFormat->type);
4875 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4876 return;
4877 }
4878
4879 ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
4880 pCArrayFormat + 4, 0);
4881
4882 TRACE("memory_size = %d\n", pCStructFormat->memory_size);
4883
4884 /* copy constant sized part of struct */
4885 pStubMsg->BufferMark = pStubMsg->Buffer;
4886
4887 if (pCStructFormat->type == RPC_FC_CPSTRUCT)
4888 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
4889 }
4890
4891 /***********************************************************************
4892 * NdrConformantVaryingStructMarshall [RPCRT4.@]
4893 */
4894 unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4895 unsigned char *pMemory,
4896 PFORMAT_STRING pFormat)
4897 {
4898 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4899 PFORMAT_STRING pCVArrayFormat;
4900
4901 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4902
4903 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4904 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4905 {
4906 ERR("invalid format type %x\n", pCVStructFormat->type);
4907 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4908 return NULL;
4909 }
4910
4911 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4912 pCVStructFormat->offset_to_array_description;
4913
4914 array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg,
4915 pMemory + pCVStructFormat->memory_size,
4916 pCVArrayFormat);
4917
4918 align_pointer_clear(&pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4919
4920 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4921
4922 /* write constant sized part */
4923 pStubMsg->BufferMark = pStubMsg->Buffer;
4924 safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
4925
4926 array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg,
4927 pMemory + pCVStructFormat->memory_size,
4928 pCVArrayFormat, FALSE /* fHasPointers */);
4929
4930 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
4931
4932 return NULL;
4933 }
4934
4935 /***********************************************************************
4936 * NdrConformantVaryingStructUnmarshall [RPCRT4.@]
4937 */
4938 unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4939 unsigned char **ppMemory,
4940 PFORMAT_STRING pFormat,
4941 unsigned char fMustAlloc)
4942 {
4943 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
4944 PFORMAT_STRING pCVArrayFormat;
4945 ULONG memsize, bufsize;
4946 unsigned char *saved_buffer, *saved_array_buffer;
4947 ULONG offset;
4948 unsigned char *array_memory;
4949
4950 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4951
4952 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
4953 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
4954 {
4955 ERR("invalid format type %x\n", pCVStructFormat->type);
4956 RpcRaiseException(RPC_S_INTERNAL_ERROR);
4957 return NULL;
4958 }
4959
4960 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
4961 pCVStructFormat->offset_to_array_description;
4962
4963 memsize = array_read_conformance(*pCVArrayFormat, pStubMsg,
4964 pCVArrayFormat);
4965
4966 align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1);
4967
4968 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
4969
4970 /* work out how much memory to allocate if we need to do so */
4971 if (!fMustAlloc && !*ppMemory)
4972 fMustAlloc = TRUE;
4973 if (fMustAlloc)
4974 {
4975 SIZE_T size = pCVStructFormat->memory_size + memsize;
4976 *ppMemory = NdrAllocate(pStubMsg, size);
4977 }
4978
4979 /* mark the start of the constant data */
4980 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
4981 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
4982
4983 array_memory = *ppMemory + pCVStructFormat->memory_size;
4984 bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg,
4985 &array_memory, pCVArrayFormat,
4986 FALSE /* fMustAlloc */,
4987 FALSE /* fUseServerBufferMemory */,
4988 FALSE /* fUnmarshall */);
4989
4990 /* save offset in case unmarshalling pointers changes it */
4991 offset = pStubMsg->Offset;
4992
4993 /* mark the start of the array data */
4994 saved_array_buffer = pStubMsg->Buffer;
4995 safe_buffer_increment(pStubMsg, bufsize);
4996
4997 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
4998
4999 /* copy the constant data */
5000 memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size);
5001 /* copy the array data */
5002 TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size);
5003 memcpy(*ppMemory + pCVStructFormat->memory_size + offset,
5004 saved_array_buffer, bufsize);
5005
5006 if (*pCVArrayFormat == RPC_FC_C_CSTRING)
5007 TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
5008 else if (*pCVArrayFormat == RPC_FC_C_WSTRING)
5009 TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
5010
5011 return NULL;
5012 }
5013
5014 /***********************************************************************
5015 * NdrConformantVaryingStructBufferSize [RPCRT4.@]
5016 */
5017 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5018 unsigned char *pMemory,
5019 PFORMAT_STRING pFormat)
5020 {
5021 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
5022 PFORMAT_STRING pCVArrayFormat;
5023
5024 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5025
5026 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
5027 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
5028 {
5029 ERR("invalid format type %x\n", pCVStructFormat->type);
5030 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5031 return;
5032 }
5033
5034 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
5035 pCVStructFormat->offset_to_array_description;
5036 array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg,
5037 pMemory + pCVStructFormat->memory_size,
5038 pCVArrayFormat);
5039
5040 align_length(&pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
5041
5042 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
5043
5044 safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
5045
5046 array_buffer_size(*pCVArrayFormat, pStubMsg,
5047 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
5048 FALSE /* fHasPointers */);
5049
5050 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5051 }
5052
5053 /***********************************************************************
5054 * NdrConformantVaryingStructMemorySize [RPCRT4.@]
5055 */
5056 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5057 PFORMAT_STRING pFormat)
5058 {
5059 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
5060 PFORMAT_STRING pCVArrayFormat;
5061
5062 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5063
5064 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
5065 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
5066 {
5067 ERR("invalid format type %x\n", pCVStructFormat->type);
5068 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5069 return 0;
5070 }
5071
5072 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
5073 pCVStructFormat->offset_to_array_description;
5074 array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat);
5075
5076 align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1);
5077
5078 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
5079
5080 safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
5081 array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat,
5082 FALSE /* fHasPointers */);
5083
5084 pStubMsg->MemorySize += pCVStructFormat->memory_size;
5085
5086 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5087
5088 return pStubMsg->MemorySize;
5089 }
5090
5091 /***********************************************************************
5092 * NdrConformantVaryingStructFree [RPCRT4.@]
5093 */
5094 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
5095 unsigned char *pMemory,
5096 PFORMAT_STRING pFormat)
5097 {
5098 const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
5099 PFORMAT_STRING pCVArrayFormat;
5100
5101 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5102
5103 pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
5104 if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
5105 {
5106 ERR("invalid format type %x\n", pCVStructFormat->type);
5107 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5108 return;
5109 }
5110
5111 pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
5112 pCVStructFormat->offset_to_array_description;
5113 array_free(*pCVArrayFormat, pStubMsg,
5114 pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
5115 FALSE /* fHasPointers */);
5116
5117 TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
5118
5119 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5120 }
5121
5122 #include "pshpack1.h"
5123 typedef struct
5124 {
5125 unsigned char type;
5126 unsigned char alignment;
5127 unsigned short total_size;
5128 } NDR_SMFARRAY_FORMAT;
5129
5130 typedef struct
5131 {
5132 unsigned char type;
5133 unsigned char alignment;
5134 ULONG total_size;
5135 } NDR_LGFARRAY_FORMAT;
5136 #include "poppack.h"
5137
5138 /***********************************************************************
5139 * NdrFixedArrayMarshall [RPCRT4.@]
5140 */
5141 unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5142 unsigned char *pMemory,
5143 PFORMAT_STRING pFormat)
5144 {
5145 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5146 ULONG total_size;
5147
5148 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5149
5150 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5151 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5152 {
5153 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5154 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5155 return NULL;
5156 }
5157
5158 align_pointer_clear(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5159
5160 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5161 {
5162 total_size = pSmFArrayFormat->total_size;
5163 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5164 }
5165 else
5166 {
5167 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5168 total_size = pLgFArrayFormat->total_size;
5169 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5170 }
5171
5172 pStubMsg->BufferMark = pStubMsg->Buffer;
5173 safe_copy_to_buffer(pStubMsg, pMemory, total_size);
5174
5175 pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5176
5177 return NULL;
5178 }
5179
5180 /***********************************************************************
5181 * NdrFixedArrayUnmarshall [RPCRT4.@]
5182 */
5183 unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5184 unsigned char **ppMemory,
5185 PFORMAT_STRING pFormat,
5186 unsigned char fMustAlloc)
5187 {
5188 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5189 ULONG total_size;
5190 unsigned char *saved_buffer;
5191
5192 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5193
5194 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5195 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5196 {
5197 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5198 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5199 return NULL;
5200 }
5201
5202 align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5203
5204 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5205 {
5206 total_size = pSmFArrayFormat->total_size;
5207 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5208 }
5209 else
5210 {
5211 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5212 total_size = pLgFArrayFormat->total_size;
5213 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5214 }
5215
5216 if (fMustAlloc)
5217 *ppMemory = NdrAllocate(pStubMsg, total_size);
5218 else
5219 {
5220 if (!pStubMsg->IsClient && !*ppMemory)
5221 /* for servers, we just point straight into the RPC buffer */
5222 *ppMemory = pStubMsg->Buffer;
5223 }
5224
5225 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5226 safe_buffer_increment(pStubMsg, total_size);
5227 pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5228
5229 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
5230 if (*ppMemory != saved_buffer)
5231 memcpy(*ppMemory, saved_buffer, total_size);
5232
5233 return NULL;
5234 }
5235
5236 /***********************************************************************
5237 * NdrFixedArrayBufferSize [RPCRT4.@]
5238 */
5239 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5240 unsigned char *pMemory,
5241 PFORMAT_STRING pFormat)
5242 {
5243 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5244 ULONG total_size;
5245
5246 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5247
5248 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5249 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5250 {
5251 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5252 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5253 return;
5254 }
5255
5256 align_length(&pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
5257
5258 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5259 {
5260 total_size = pSmFArrayFormat->total_size;
5261 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5262 }
5263 else
5264 {
5265 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5266 total_size = pLgFArrayFormat->total_size;
5267 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5268 }
5269 safe_buffer_length_increment(pStubMsg, total_size);
5270
5271 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5272 }
5273
5274 /***********************************************************************
5275 * NdrFixedArrayMemorySize [RPCRT4.@]
5276 */
5277 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5278 PFORMAT_STRING pFormat)
5279 {
5280 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5281 ULONG total_size;
5282
5283 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5284
5285 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5286 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5287 {
5288 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5289 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5290 return 0;
5291 }
5292
5293 align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
5294
5295 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5296 {
5297 total_size = pSmFArrayFormat->total_size;
5298 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5299 }
5300 else
5301 {
5302 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5303 total_size = pLgFArrayFormat->total_size;
5304 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5305 }
5306 pStubMsg->BufferMark = pStubMsg->Buffer;
5307 safe_buffer_increment(pStubMsg, total_size);
5308 pStubMsg->MemorySize += total_size;
5309
5310 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5311
5312 return total_size;
5313 }
5314
5315 /***********************************************************************
5316 * NdrFixedArrayFree [RPCRT4.@]
5317 */
5318 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5319 unsigned char *pMemory,
5320 PFORMAT_STRING pFormat)
5321 {
5322 const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
5323
5324 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5325
5326 if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
5327 (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
5328 {
5329 ERR("invalid format type %x\n", pSmFArrayFormat->type);
5330 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5331 return;
5332 }
5333
5334 if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
5335 pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
5336 else
5337 {
5338 const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
5339 pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
5340 }
5341
5342 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5343 }
5344
5345 /***********************************************************************
5346 * NdrVaryingArrayMarshall [RPCRT4.@]
5347 */
5348 unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5349 unsigned char *pMemory,
5350 PFORMAT_STRING pFormat)
5351 {
5352 unsigned char alignment;
5353 DWORD elements, esize;
5354 ULONG bufsize;
5355
5356 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5357
5358 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5359 (pFormat[0] != RPC_FC_LGVARRAY))
5360 {
5361 ERR("invalid format type %x\n", pFormat[0]);
5362 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5363 return NULL;
5364 }
5365
5366 alignment = pFormat[1] + 1;
5367
5368 if (pFormat[0] == RPC_FC_SMVARRAY)
5369 {
5370 pFormat += 2;
5371 pFormat += sizeof(WORD);
5372 elements = *(const WORD*)pFormat;
5373 pFormat += sizeof(WORD);
5374 }
5375 else
5376 {
5377 pFormat += 2;
5378 pFormat += sizeof(DWORD);
5379 elements = *(const DWORD*)pFormat;
5380 pFormat += sizeof(DWORD);
5381 }
5382
5383 esize = *(const WORD*)pFormat;
5384 pFormat += sizeof(WORD);
5385
5386 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5387 if ((pStubMsg->ActualCount > elements) ||
5388 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5389 {
5390 RpcRaiseException(RPC_S_INVALID_BOUND);
5391 return NULL;
5392 }
5393
5394 WriteVariance(pStubMsg);
5395
5396 align_pointer_clear(&pStubMsg->Buffer, alignment);
5397
5398 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5399 pStubMsg->BufferMark = pStubMsg->Buffer;
5400 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
5401
5402 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
5403
5404 return NULL;
5405 }
5406
5407 /***********************************************************************
5408 * NdrVaryingArrayUnmarshall [RPCRT4.@]
5409 */
5410 unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5411 unsigned char **ppMemory,
5412 PFORMAT_STRING pFormat,
5413 unsigned char fMustAlloc)
5414 {
5415 unsigned char alignment;
5416 DWORD size, elements, esize;
5417 ULONG bufsize;
5418 unsigned char *saved_buffer;
5419 ULONG offset;
5420
5421 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
5422
5423 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5424 (pFormat[0] != RPC_FC_LGVARRAY))
5425 {
5426 ERR("invalid format type %x\n", pFormat[0]);
5427 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5428 return NULL;
5429 }
5430
5431 alignment = pFormat[1] + 1;
5432
5433 if (pFormat[0] == RPC_FC_SMVARRAY)
5434 {
5435 pFormat += 2;
5436 size = *(const WORD*)pFormat;
5437 pFormat += sizeof(WORD);
5438 elements = *(const WORD*)pFormat;
5439 pFormat += sizeof(WORD);
5440 }
5441 else
5442 {
5443 pFormat += 2;
5444 size = *(const DWORD*)pFormat;
5445 pFormat += sizeof(DWORD);
5446 elements = *(const DWORD*)pFormat;
5447 pFormat += sizeof(DWORD);
5448 }
5449
5450 esize = *(const WORD*)pFormat;
5451 pFormat += sizeof(WORD);
5452
5453 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5454
5455 align_pointer(&pStubMsg->Buffer, alignment);
5456
5457 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
5458 offset = pStubMsg->Offset;
5459
5460 if (!fMustAlloc && !*ppMemory)
5461 fMustAlloc = TRUE;
5462 if (fMustAlloc)
5463 *ppMemory = NdrAllocate(pStubMsg, size);
5464 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
5465 safe_buffer_increment(pStubMsg, bufsize);
5466
5467 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
5468
5469 memcpy(*ppMemory + offset, saved_buffer, bufsize);
5470
5471 return NULL;
5472 }
5473
5474 /***********************************************************************
5475 * NdrVaryingArrayBufferSize [RPCRT4.@]
5476 */
5477 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
5478 unsigned char *pMemory,
5479 PFORMAT_STRING pFormat)
5480 {
5481 unsigned char alignment;
5482 DWORD elements, esize;
5483
5484 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5485
5486 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5487 (pFormat[0] != RPC_FC_LGVARRAY))
5488 {
5489 ERR("invalid format type %x\n", pFormat[0]);
5490 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5491 return;
5492 }
5493
5494 alignment = pFormat[1] + 1;
5495
5496 if (pFormat[0] == RPC_FC_SMVARRAY)
5497 {
5498 pFormat += 2;
5499 pFormat += sizeof(WORD);
5500 elements = *(const WORD*)pFormat;
5501 pFormat += sizeof(WORD);
5502 }
5503 else
5504 {
5505 pFormat += 2;
5506 pFormat += sizeof(DWORD);
5507 elements = *(const DWORD*)pFormat;
5508 pFormat += sizeof(DWORD);
5509 }
5510
5511 esize = *(const WORD*)pFormat;
5512 pFormat += sizeof(WORD);
5513
5514 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5515 if ((pStubMsg->ActualCount > elements) ||
5516 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5517 {
5518 RpcRaiseException(RPC_S_INVALID_BOUND);
5519 return;
5520 }
5521
5522 SizeVariance(pStubMsg);
5523
5524 align_length(&pStubMsg->BufferLength, alignment);
5525
5526 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5527
5528 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
5529 }
5530
5531 /***********************************************************************
5532 * NdrVaryingArrayMemorySize [RPCRT4.@]
5533 */
5534 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
5535 PFORMAT_STRING pFormat)
5536 {
5537 unsigned char alignment;
5538 DWORD size, elements, esize;
5539
5540 TRACE("(%p, %p)\n", pStubMsg, pFormat);
5541
5542 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5543 (pFormat[0] != RPC_FC_LGVARRAY))
5544 {
5545 ERR("invalid format type %x\n", pFormat[0]);
5546 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5547 return 0;
5548 }
5549
5550 alignment = pFormat[1] + 1;
5551
5552 if (pFormat[0] == RPC_FC_SMVARRAY)
5553 {
5554 pFormat += 2;
5555 size = *(const WORD*)pFormat;
5556 pFormat += sizeof(WORD);
5557 elements = *(const WORD*)pFormat;
5558 pFormat += sizeof(WORD);
5559 }
5560 else
5561 {
5562 pFormat += 2;
5563 size = *(const DWORD*)pFormat;
5564 pFormat += sizeof(DWORD);
5565 elements = *(const DWORD*)pFormat;
5566 pFormat += sizeof(DWORD);
5567 }
5568
5569 esize = *(const WORD*)pFormat;
5570 pFormat += sizeof(WORD);
5571
5572 pFormat = ReadVariance(pStubMsg, pFormat, elements);
5573
5574 align_pointer(&pStubMsg->Buffer, alignment);
5575
5576 safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
5577 pStubMsg->MemorySize += size;
5578
5579 EmbeddedPointerMemorySize(pStubMsg, pFormat);
5580
5581 return pStubMsg->MemorySize;
5582 }
5583
5584 /***********************************************************************
5585 * NdrVaryingArrayFree [RPCRT4.@]
5586 */
5587 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
5588 unsigned char *pMemory,
5589 PFORMAT_STRING pFormat)
5590 {
5591 DWORD elements;
5592
5593 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5594
5595 if ((pFormat[0] != RPC_FC_SMVARRAY) &&
5596 (pFormat[0] != RPC_FC_LGVARRAY))
5597 {
5598 ERR("invalid format type %x\n", pFormat[0]);
5599 RpcRaiseException(RPC_S_INTERNAL_ERROR);
5600 return;
5601 }
5602
5603 if (pFormat[0] == RPC_FC_SMVARRAY)
5604 {
5605 pFormat += 2;
5606 pFormat += sizeof(WORD);
5607 elements = *(const WORD*)pFormat;
5608 pFormat += sizeof(WORD);
5609 }
5610 else
5611 {
5612 pFormat += 2;
5613 pFormat += sizeof(DWORD);
5614 elements = *(const DWORD*)pFormat;
5615 pFormat += sizeof(DWORD);
5616 }
5617
5618 pFormat += sizeof(WORD);
5619
5620 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
5621 if ((pStubMsg->ActualCount > elements) ||
5622 (pStubMsg->ActualCount + pStubMsg->Offset > elements))
5623 {
5624 RpcRaiseException(RPC_S_INVALID_BOUND);
5625 return;
5626 }
5627
5628 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
5629 }
5630
5631 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
5632 {
5633 switch (fc)
5634 {
5635 case RPC_FC_BYTE:
5636 case RPC_FC_CHAR:
5637 case RPC_FC_SMALL:
5638 case RPC_FC_USMALL:
5639 return *pMemory;
5640 case RPC_FC_WCHAR:
5641 case RPC_FC_SHORT:
5642 case RPC_FC_USHORT:
5643 case RPC_FC_ENUM16:
5644 return *(const USHORT *)pMemory;
5645 case RPC_FC_LONG:
5646 case RPC_FC_ULONG:
5647 case RPC_FC_ENUM32:
5648 return *(const ULONG *)pMemory;
5649 case RPC_FC_INT3264:
5650 case RPC_FC_UINT3264:
5651 return *(const ULONG_PTR *)pMemory;
5652 default:
5653 FIXME("Unhandled base type: 0x%02x\n", fc);
5654 return 0;
5655 }
5656 }
5657
5658 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
5659 ULONG discriminant,
5660 PFORMAT_STRING pFormat)
5661 {
5662 unsigned short num_arms, arm, type;
5663
5664 num_arms = *(const SHORT*)pFormat & 0x0fff;
5665 pFormat += 2;
5666 for(arm = 0; arm < num_arms; arm++)
5667 {
5668 if(discriminant == *(const ULONG*)pFormat)
5669 {
5670 pFormat += 4;
5671 break;
5672 }
5673 pFormat += 6;
5674 }
5675
5676 type = *(const unsigned short*)pFormat;
5677 TRACE("type %04x\n", type);
5678 if(arm == num_arms) /* default arm extras */
5679 {
5680 if(type == 0xffff)
5681 {
5682 ERR("no arm for 0x%x and no default case\n", discriminant);
5683 RpcRaiseException(RPC_S_INVALID_TAG);
5684 return NULL;
5685 }
5686 if(type == 0)
5687 {
5688 TRACE("falling back to empty default case for 0x%x\n", discriminant);
5689 return NULL;
5690 }
5691 }
5692 return pFormat;
5693 }
5694
5695 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
5696 {
5697 unsigned short type;
5698
5699 pFormat += 2;
5700
5701 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5702 if(!pFormat)
5703 return NULL;
5704
5705 type = *(const unsigned short*)pFormat;
5706 if((type & 0xff00) == 0x8000)
5707 {
5708 unsigned char basetype = LOBYTE(type);
5709 return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
5710 }
5711 else
5712 {
5713 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5714 NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
5715 if (m)
5716 {
5717 unsigned char *saved_buffer = NULL;
5718 int pointer_buffer_mark_set = 0;
5719 switch(*desc)
5720 {
5721 case RPC_FC_RP:
5722 case RPC_FC_UP:
5723 case RPC_FC_OP:
5724 case RPC_FC_FP:
5725 align_pointer_clear(&pStubMsg->Buffer, 4);
5726 saved_buffer = pStubMsg->Buffer;
5727 if (pStubMsg->PointerBufferMark)
5728 {
5729 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5730 pStubMsg->PointerBufferMark = NULL;
5731 pointer_buffer_mark_set = 1;
5732 }
5733 else
5734 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
5735
5736 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
5737 if (pointer_buffer_mark_set)
5738 {
5739 STD_OVERFLOW_CHECK(pStubMsg);
5740 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5741 if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
5742 {
5743 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5744 saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
5745 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5746 }
5747 pStubMsg->Buffer = saved_buffer + 4;
5748 }
5749 break;
5750 default:
5751 m(pStubMsg, pMemory, desc);
5752 }
5753 }
5754 else FIXME("no marshaller for embedded type %02x\n", *desc);
5755 }
5756 return NULL;
5757 }
5758
5759 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
5760 unsigned char **ppMemory,
5761 ULONG discriminant,
5762 PFORMAT_STRING pFormat,
5763 unsigned char fMustAlloc)
5764 {
5765 unsigned short type;
5766
5767 pFormat += 2;
5768
5769 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5770 if(!pFormat)
5771 return NULL;
5772
5773 type = *(const unsigned short*)pFormat;
5774 if((type & 0xff00) == 0x8000)
5775 {
5776 unsigned char basetype = LOBYTE(type);
5777 return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
5778 }
5779 else
5780 {
5781 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5782 NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
5783 if (m)
5784 {
5785 unsigned char *saved_buffer = NULL;
5786 int pointer_buffer_mark_set = 0;
5787 switch(*desc)
5788 {
5789 case RPC_FC_RP:
5790 case RPC_FC_UP:
5791 case RPC_FC_OP:
5792 case RPC_FC_FP:
5793 align_pointer(&pStubMsg->Buffer, 4);
5794 saved_buffer = pStubMsg->Buffer;
5795 if (pStubMsg->PointerBufferMark)
5796 {
5797 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
5798 pStubMsg->PointerBufferMark = NULL;
5799 pointer_buffer_mark_set = 1;
5800 }
5801 else
5802 pStubMsg->Buffer += 4; /* for pointer ID */
5803
5804 if (saved_buffer + 4 > pStubMsg->BufferEnd)
5805 {
5806 ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
5807 saved_buffer, pStubMsg->BufferEnd);
5808 RpcRaiseException(RPC_X_BAD_STUB_DATA);
5809 }
5810
5811 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
5812 if (pointer_buffer_mark_set)
5813 {
5814 STD_OVERFLOW_CHECK(pStubMsg);
5815 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
5816 pStubMsg->Buffer = saved_buffer + 4;
5817 }
5818 break;
5819 default:
5820 m(pStubMsg, ppMemory, desc, fMustAlloc);
5821 }
5822 }
5823 else FIXME("no marshaller for embedded type %02x\n", *desc);
5824 }
5825 return NULL;
5826 }
5827
5828 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
5829 unsigned char *pMemory,
5830 ULONG discriminant,
5831 PFORMAT_STRING pFormat)
5832 {
5833 unsigned short type;
5834
5835 pFormat += 2;
5836
5837 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5838 if(!pFormat)
5839 return;
5840
5841 type = *(const unsigned short*)pFormat;
5842 if((type & 0xff00) == 0x8000)
5843 {
5844 unsigned char basetype = LOBYTE(type);
5845 NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
5846 }
5847 else
5848 {
5849 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5850 NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
5851 if (m)
5852 {
5853 switch(*desc)
5854 {
5855 case RPC_FC_RP:
5856 case RPC_FC_UP:
5857 case RPC_FC_OP:
5858 case RPC_FC_FP:
5859 align_length(&pStubMsg->BufferLength, 4);
5860 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
5861 if (!pStubMsg->IgnoreEmbeddedPointers)
5862 {
5863 int saved_buffer_length = pStubMsg->BufferLength;
5864 pStubMsg->BufferLength = pStubMsg->PointerLength;
5865 pStubMsg->PointerLength = 0;
5866 if(!pStubMsg->BufferLength)
5867 ERR("BufferLength == 0??\n");
5868 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
5869 pStubMsg->PointerLength = pStubMsg->BufferLength;
5870 pStubMsg->BufferLength = saved_buffer_length;
5871 }
5872 break;
5873 default:
5874 m(pStubMsg, pMemory, desc);
5875 }
5876 }
5877 else FIXME("no buffersizer for embedded type %02x\n", *desc);
5878 }
5879 }
5880
5881 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
5882 ULONG discriminant,
5883 PFORMAT_STRING pFormat)
5884 {
5885 unsigned short type, size;
5886
5887 size = *(const unsigned short*)pFormat;
5888 pStubMsg->Memory += size;
5889 pFormat += 2;
5890
5891 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5892 if(!pFormat)
5893 return 0;
5894
5895 type = *(const unsigned short*)pFormat;
5896 if((type & 0xff00) == 0x8000)
5897 {
5898 return NdrBaseTypeMemorySize(pStubMsg, pFormat);
5899 }
5900 else
5901 {
5902 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5903 NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
5904 unsigned char *saved_buffer;
5905 if (m)
5906 {
5907 switch(*desc)
5908 {
5909 case RPC_FC_RP:
5910 case RPC_FC_UP:
5911 case RPC_FC_OP:
5912 case RPC_FC_FP:
5913 align_pointer(&pStubMsg->Buffer, 4);
5914 saved_buffer = pStubMsg->Buffer;
5915 safe_buffer_increment(pStubMsg, 4);
5916 align_length(&pStubMsg->MemorySize, sizeof(void *));
5917 pStubMsg->MemorySize += sizeof(void *);
5918 if (!pStubMsg->IgnoreEmbeddedPointers)
5919 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
5920 break;
5921 default:
5922 return m(pStubMsg, desc);
5923 }
5924 }
5925 else FIXME("no marshaller for embedded type %02x\n", *desc);
5926 }
5927
5928 TRACE("size %d\n", size);
5929 return size;
5930 }
5931
5932 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
5933 unsigned char *pMemory,
5934 ULONG discriminant,
5935 PFORMAT_STRING pFormat)
5936 {
5937 unsigned short type;
5938
5939 pFormat += 2;
5940
5941 pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
5942 if(!pFormat)
5943 return;
5944
5945 type = *(const unsigned short*)pFormat;
5946 if((type & 0xff00) != 0x8000)
5947 {
5948 PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
5949 NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
5950 if (m)
5951 {
5952 switch(*desc)
5953 {
5954 case RPC_FC_RP:
5955 case RPC_FC_UP:
5956 case RPC_FC_OP:
5957 case RPC_FC_FP:
5958 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
5959 break;
5960 default:
5961 m(pStubMsg, pMemory, desc);
5962 }
5963 }
5964 }
5965 }
5966
5967 /***********************************************************************
5968 * NdrEncapsulatedUnionMarshall [RPCRT4.@]
5969 */
5970 unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
5971 unsigned char *pMemory,
5972 PFORMAT_STRING pFormat)
5973 {
5974 unsigned char switch_type;
5975 unsigned char increment;
5976 ULONG switch_value;
5977
5978 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
5979 pFormat++;
5980
5981 switch_type = *pFormat & 0xf;
5982 increment = (*pFormat & 0xf0) >> 4;
5983 pFormat++;
5984
5985 align_pointer_clear(&pStubMsg->Buffer, increment);
5986
5987 switch_value = get_discriminant(switch_type, pMemory);
5988 TRACE("got switch value 0x%x\n", switch_value);
5989
5990 NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
5991 pMemory += increment;
5992
5993 return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
5994 }
5995
5996 /***********************************************************************
5997 * NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
5998 */
5999 unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6000 unsigned char **ppMemory,
6001 PFORMAT_STRING pFormat,
6002 unsigned char fMustAlloc)
6003 {
6004 unsigned char switch_type;
6005 unsigned char increment;
6006 ULONG switch_value;
6007 unsigned short size;
6008 unsigned char *pMemoryArm;
6009
6010 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
6011 pFormat++;
6012
6013 switch_type = *pFormat & 0xf;
6014 increment = (*pFormat & 0xf0) >> 4;
6015 pFormat++;
6016
6017 align_pointer(&pStubMsg->Buffer, increment);
6018 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
6019 TRACE("got switch value 0x%x\n", switch_value);
6020
6021 size = *(const unsigned short*)pFormat + increment;
6022 if (!fMustAlloc && !*ppMemory)
6023 fMustAlloc = TRUE;
6024 if (fMustAlloc)
6025 *ppMemory = NdrAllocate(pStubMsg, size);
6026
6027 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6028 * since the arm is part of the memory block that is encompassed by
6029 * the whole union. Memory is forced to allocate when pointers
6030 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6031 * clearing the memory we pass in to the unmarshaller */
6032 if (fMustAlloc)
6033 memset(*ppMemory, 0, size);
6034
6035 NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
6036 pMemoryArm = *ppMemory + increment;
6037
6038 return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE);
6039 }
6040
6041 /***********************************************************************
6042 * NdrEncapsulatedUnionBufferSize [RPCRT4.@]
6043 */
6044 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6045 unsigned char *pMemory,
6046 PFORMAT_STRING pFormat)
6047 {
6048 unsigned char switch_type;
6049 unsigned char increment;
6050 ULONG switch_value;
6051
6052 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6053 pFormat++;
6054
6055 switch_type = *pFormat & 0xf;
6056 increment = (*pFormat & 0xf0) >> 4;
6057 pFormat++;
6058
6059 align_length(&pStubMsg->BufferLength, increment);
6060 switch_value = get_discriminant(switch_type, pMemory);
6061 TRACE("got switch value 0x%x\n", switch_value);
6062
6063 /* Add discriminant size */
6064 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
6065 pMemory += increment;
6066
6067 union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
6068 }
6069
6070 /***********************************************************************
6071 * NdrEncapsulatedUnionMemorySize [RPCRT4.@]
6072 */
6073 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6074 PFORMAT_STRING pFormat)
6075 {
6076 unsigned char switch_type;
6077 unsigned char increment;
6078 ULONG switch_value;
6079
6080 switch_type = *pFormat & 0xf;
6081 increment = (*pFormat & 0xf0) >> 4;
6082 pFormat++;
6083
6084 align_pointer(&pStubMsg->Buffer, increment);
6085 switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
6086 TRACE("got switch value 0x%x\n", switch_value);
6087
6088 pStubMsg->Memory += increment;
6089
6090 return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
6091 }
6092
6093 /***********************************************************************
6094 * NdrEncapsulatedUnionFree [RPCRT4.@]
6095 */
6096 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6097 unsigned char *pMemory,
6098 PFORMAT_STRING pFormat)
6099 {
6100 unsigned char switch_type;
6101 unsigned char increment;
6102 ULONG switch_value;
6103
6104 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6105 pFormat++;
6106
6107 switch_type = *pFormat & 0xf;
6108 increment = (*pFormat & 0xf0) >> 4;
6109 pFormat++;
6110
6111 switch_value = get_discriminant(switch_type, pMemory);
6112 TRACE("got switch value 0x%x\n", switch_value);
6113
6114 pMemory += increment;
6115
6116 union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
6117 }
6118
6119 /***********************************************************************
6120 * NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
6121 */
6122 unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6123 unsigned char *pMemory,
6124 PFORMAT_STRING pFormat)
6125 {
6126 unsigned char switch_type;
6127
6128 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6129 pFormat++;
6130
6131 switch_type = *pFormat;
6132 pFormat++;
6133
6134 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6135 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6136 /* Marshall discriminant */
6137 NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6138
6139 return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6140 }
6141
6142 static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
6143 PFORMAT_STRING *ppFormat)
6144 {
6145 LONG discriminant = 0;
6146
6147 switch(**ppFormat)
6148 {
6149 case RPC_FC_BYTE:
6150 case RPC_FC_CHAR:
6151 case RPC_FC_SMALL:
6152 case RPC_FC_USMALL:
6153 {
6154 UCHAR d;
6155 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6156 discriminant = d;
6157 break;
6158 }
6159 case RPC_FC_WCHAR:
6160 case RPC_FC_SHORT:
6161 case RPC_FC_USHORT:
6162 case RPC_FC_ENUM16:
6163 {
6164 USHORT d;
6165 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6166 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6167 discriminant = d;
6168 break;
6169 }
6170 case RPC_FC_LONG:
6171 case RPC_FC_ULONG:
6172 {
6173 ULONG d;
6174 align_pointer(&pStubMsg->Buffer, sizeof(ULONG));
6175 safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
6176 discriminant = d;
6177 break;
6178 }
6179 default:
6180 FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
6181 }
6182 (*ppFormat)++;
6183
6184 if (pStubMsg->fHasNewCorrDesc)
6185 *ppFormat += 6;
6186 else
6187 *ppFormat += 4;
6188 return discriminant;
6189 }
6190
6191 /**********************************************************************
6192 * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
6193 */
6194 unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6195 unsigned char **ppMemory,
6196 PFORMAT_STRING pFormat,
6197 unsigned char fMustAlloc)
6198 {
6199 LONG discriminant;
6200 unsigned short size;
6201
6202 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
6203 pFormat++;
6204
6205 /* Unmarshall discriminant */
6206 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6207 TRACE("unmarshalled discriminant %x\n", discriminant);
6208
6209 pFormat += *(const SHORT*)pFormat;
6210
6211 size = *(const unsigned short*)pFormat;
6212
6213 if (!fMustAlloc && !*ppMemory)
6214 fMustAlloc = TRUE;
6215 if (fMustAlloc)
6216 *ppMemory = NdrAllocate(pStubMsg, size);
6217
6218 /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
6219 * since the arm is part of the memory block that is encompassed by
6220 * the whole union. Memory is forced to allocate when pointers
6221 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
6222 * clearing the memory we pass in to the unmarshaller */
6223 if (fMustAlloc)
6224 memset(*ppMemory, 0, size);
6225
6226 return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
6227 }
6228
6229 /***********************************************************************
6230 * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
6231 */
6232 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6233 unsigned char *pMemory,
6234 PFORMAT_STRING pFormat)
6235 {
6236 unsigned char switch_type;
6237
6238 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6239 pFormat++;
6240
6241 switch_type = *pFormat;
6242 pFormat++;
6243
6244 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6245 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6246 /* Add discriminant size */
6247 NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
6248
6249 union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6250 }
6251
6252 /***********************************************************************
6253 * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
6254 */
6255 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6256 PFORMAT_STRING pFormat)
6257 {
6258 ULONG discriminant;
6259
6260 pFormat++;
6261 /* Unmarshall discriminant */
6262 discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
6263 TRACE("unmarshalled discriminant 0x%x\n", discriminant);
6264
6265 return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
6266 }
6267
6268 /***********************************************************************
6269 * NdrNonEncapsulatedUnionFree [RPCRT4.@]
6270 */
6271 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
6272 unsigned char *pMemory,
6273 PFORMAT_STRING pFormat)
6274 {
6275 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
6276 pFormat++;
6277 pFormat++;
6278
6279 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
6280 TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
6281
6282 union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
6283 }
6284
6285 /***********************************************************************
6286 * NdrByteCountPointerMarshall [RPCRT4.@]
6287 */
6288 unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6289 unsigned char *pMemory,
6290 PFORMAT_STRING pFormat)
6291 {
6292 FIXME("stub\n");
6293 return NULL;
6294 }
6295
6296 /***********************************************************************
6297 * NdrByteCountPointerUnmarshall [RPCRT4.@]
6298 */
6299 unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6300 unsigned char **ppMemory,
6301 PFORMAT_STRING pFormat,
6302 unsigned char fMustAlloc)
6303 {
6304 FIXME("stub\n");
6305 return NULL;
6306 }
6307
6308 /***********************************************************************
6309 * NdrByteCountPointerBufferSize [RPCRT4.@]
6310 */
6311 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6312 unsigned char *pMemory,
6313 PFORMAT_STRING pFormat)
6314 {
6315 FIXME("stub\n");
6316 }
6317
6318 /***********************************************************************
6319 * NdrByteCountPointerMemorySize [internal]
6320 */
6321 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6322 PFORMAT_STRING pFormat)
6323 {
6324 FIXME("stub\n");
6325 return 0;
6326 }
6327
6328 /***********************************************************************
6329 * NdrByteCountPointerFree [RPCRT4.@]
6330 */
6331 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
6332 unsigned char *pMemory,
6333 PFORMAT_STRING pFormat)
6334 {
6335 FIXME("stub\n");
6336 }
6337
6338 /***********************************************************************
6339 * NdrXmitOrRepAsMarshall [RPCRT4.@]
6340 */
6341 unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
6342 unsigned char *pMemory,
6343 PFORMAT_STRING pFormat)
6344 {
6345 FIXME("stub\n");
6346 return NULL;
6347 }
6348
6349 /***********************************************************************
6350 * NdrXmitOrRepAsUnmarshall [RPCRT4.@]
6351 */
6352 unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
6353 unsigned char **ppMemory,
6354 PFORMAT_STRING pFormat,
6355 unsigned char fMustAlloc)
6356 {
6357 FIXME("stub\n");
6358 return NULL;
6359 }
6360
6361 /***********************************************************************
6362 * NdrXmitOrRepAsBufferSize [RPCRT4.@]
6363 */
6364 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
6365 unsigned char *pMemory,
6366 PFORMAT_STRING pFormat)
6367 {
6368 FIXME("stub\n");
6369 }
6370
6371 /***********************************************************************
6372 * NdrXmitOrRepAsMemorySize [RPCRT4.@]
6373 */
6374 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
6375 PFORMAT_STRING pFormat)
6376 {
6377 FIXME("stub\n");
6378 return 0;
6379 }
6380
6381 /***********************************************************************
6382 * NdrXmitOrRepAsFree [RPCRT4.@]
6383 */
6384 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
6385 unsigned char *pMemory,
6386 PFORMAT_STRING pFormat)
6387 {
6388 FIXME("stub\n");
6389 }
6390
6391 /***********************************************************************
6392 * NdrRangeMarshall [internal]
6393 */
6394 static unsigned char *WINAPI NdrRangeMarshall(
6395 PMIDL_STUB_MESSAGE pStubMsg,
6396 unsigned char *pMemory,
6397 PFORMAT_STRING pFormat)
6398 {
6399 const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6400 unsigned char base_type;
6401
6402 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6403
6404 if (pRange->type != RPC_FC_RANGE)
6405 {
6406 ERR("invalid format type %x\n", pRange->type);
6407 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6408 return NULL;
6409 }
6410
6411 base_type = pRange->flags_type & 0xf;
6412
6413 return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
6414 }
6415
6416 /***********************************************************************
6417 * NdrRangeUnmarshall [RPCRT4.@]
6418 */
6419 unsigned char *WINAPI NdrRangeUnmarshall(
6420 PMIDL_STUB_MESSAGE pStubMsg,
6421 unsigned char **ppMemory,
6422 PFORMAT_STRING pFormat,
6423 unsigned char fMustAlloc)
6424 {
6425 const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6426 unsigned char base_type;
6427
6428 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6429
6430 if (pRange->type != RPC_FC_RANGE)
6431 {
6432 ERR("invalid format type %x\n", pRange->type);
6433 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6434 return NULL;
6435 }
6436 base_type = pRange->flags_type & 0xf;
6437
6438 TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
6439 base_type, pRange->low_value, pRange->high_value);
6440
6441 #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
6442 do \
6443 { \
6444 align_pointer(&pStubMsg->Buffer, sizeof(wire_type)); \
6445 if (!fMustAlloc && !*ppMemory) \
6446 fMustAlloc = TRUE; \
6447 if (fMustAlloc) \
6448 *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
6449 if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
6450 { \
6451 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
6452 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
6453 RpcRaiseException(RPC_X_BAD_STUB_DATA); \
6454 } \
6455 if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
6456 (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
6457 { \
6458 ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
6459 *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
6460 (mem_type)pRange->high_value); \
6461 RpcRaiseException(RPC_S_INVALID_BOUND); \
6462 return NULL; \
6463 } \
6464 TRACE("*ppMemory: %p\n", *ppMemory); \
6465 **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
6466 pStubMsg->Buffer += sizeof(wire_type); \
6467 } while (0)
6468
6469 switch(base_type)
6470 {
6471 case RPC_FC_CHAR:
6472 case RPC_FC_SMALL:
6473 RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
6474 TRACE("value: 0x%02x\n", **ppMemory);
6475 break;
6476 case RPC_FC_BYTE:
6477 case RPC_FC_USMALL:
6478 RANGE_UNMARSHALL(CHAR, CHAR, "%u");
6479 TRACE("value: 0x%02x\n", **ppMemory);
6480 break;
6481 case RPC_FC_WCHAR: /* FIXME: valid? */
6482 case RPC_FC_USHORT:
6483 RANGE_UNMARSHALL(USHORT, USHORT, "%u");
6484 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6485 break;
6486 case RPC_FC_SHORT:
6487 RANGE_UNMARSHALL(SHORT, SHORT, "%d");
6488 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6489 break;
6490 case RPC_FC_LONG:
6491 case RPC_FC_ENUM32:
6492 RANGE_UNMARSHALL(LONG, LONG, "%d");
6493 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6494 break;
6495 case RPC_FC_ULONG:
6496 RANGE_UNMARSHALL(ULONG, ULONG, "%u");
6497 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6498 break;
6499 case RPC_FC_ENUM16:
6500 RANGE_UNMARSHALL(UINT, USHORT, "%u");
6501 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6502 break;
6503 case RPC_FC_FLOAT:
6504 case RPC_FC_DOUBLE:
6505 case RPC_FC_HYPER:
6506 default:
6507 ERR("invalid range base type: 0x%02x\n", base_type);
6508 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6509 }
6510
6511 return NULL;
6512 }
6513
6514 /***********************************************************************
6515 * NdrRangeBufferSize [internal]
6516 */
6517 static void WINAPI NdrRangeBufferSize(
6518 PMIDL_STUB_MESSAGE pStubMsg,
6519 unsigned char *pMemory,
6520 PFORMAT_STRING pFormat)
6521 {
6522 const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6523 unsigned char base_type;
6524
6525 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6526
6527 if (pRange->type != RPC_FC_RANGE)
6528 {
6529 ERR("invalid format type %x\n", pRange->type);
6530 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6531 }
6532 base_type = pRange->flags_type & 0xf;
6533
6534 NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
6535 }
6536
6537 /***********************************************************************
6538 * NdrRangeMemorySize [internal]
6539 */
6540 static ULONG WINAPI NdrRangeMemorySize(
6541 PMIDL_STUB_MESSAGE pStubMsg,
6542 PFORMAT_STRING pFormat)
6543 {
6544 const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
6545 unsigned char base_type;
6546
6547 if (pRange->type != RPC_FC_RANGE)
6548 {
6549 ERR("invalid format type %x\n", pRange->type);
6550 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6551 return 0;
6552 }
6553 base_type = pRange->flags_type & 0xf;
6554
6555 return NdrBaseTypeMemorySize(pStubMsg, &base_type);
6556 }
6557
6558 /***********************************************************************
6559 * NdrRangeFree [internal]
6560 */
6561 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
6562 unsigned char *pMemory,
6563 PFORMAT_STRING pFormat)
6564 {
6565 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6566
6567 /* nothing to do */
6568 }
6569
6570 /***********************************************************************
6571 * NdrBaseTypeMarshall [internal]
6572 */
6573 static unsigned char *WINAPI NdrBaseTypeMarshall(
6574 PMIDL_STUB_MESSAGE pStubMsg,
6575 unsigned char *pMemory,
6576 PFORMAT_STRING pFormat)
6577 {
6578 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6579
6580 switch(*pFormat)
6581 {
6582 case RPC_FC_BYTE:
6583 case RPC_FC_CHAR:
6584 case RPC_FC_SMALL:
6585 case RPC_FC_USMALL:
6586 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
6587 TRACE("value: 0x%02x\n", *pMemory);
6588 break;
6589 case RPC_FC_WCHAR:
6590 case RPC_FC_SHORT:
6591 case RPC_FC_USHORT:
6592 align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT));
6593 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
6594 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
6595 break;
6596 case RPC_FC_LONG:
6597 case RPC_FC_ULONG:
6598 case RPC_FC_ERROR_STATUS_T:
6599 case RPC_FC_ENUM32:
6600 align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONG));
6601 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
6602 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
6603 break;
6604 case RPC_FC_FLOAT:
6605 align_pointer_clear(&pStubMsg->Buffer, sizeof(float));
6606 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
6607 break;
6608 case RPC_FC_DOUBLE:
6609 align_pointer_clear(&pStubMsg->Buffer, sizeof(double));
6610 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
6611 break;
6612 case RPC_FC_HYPER:
6613 align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONGLONG));
6614 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
6615 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
6616 break;
6617 case RPC_FC_ENUM16:
6618 {
6619 USHORT val = *(UINT *)pMemory;
6620 /* only 16-bits on the wire, so do a sanity check */
6621 if (*(UINT *)pMemory > SHRT_MAX)
6622 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
6623 align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT));
6624 safe_copy_to_buffer(pStubMsg, &val, sizeof(val));
6625 TRACE("value: 0x%04x\n", *(UINT *)pMemory);
6626 break;
6627 }
6628 case RPC_FC_INT3264:
6629 case RPC_FC_UINT3264:
6630 {
6631 UINT val = *(UINT_PTR *)pMemory;
6632 align_pointer_clear(&pStubMsg->Buffer, sizeof(UINT));
6633 safe_copy_to_buffer(pStubMsg, &val, sizeof(val));
6634 break;
6635 }
6636 case RPC_FC_IGNORE:
6637 break;
6638 default:
6639 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6640 }
6641
6642 /* FIXME: what is the correct return value? */
6643 return NULL;
6644 }
6645
6646 /***********************************************************************
6647 * NdrBaseTypeUnmarshall [internal]
6648 */
6649 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
6650 PMIDL_STUB_MESSAGE pStubMsg,
6651 unsigned char **ppMemory,
6652 PFORMAT_STRING pFormat,
6653 unsigned char fMustAlloc)
6654 {
6655 TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
6656
6657 #define BASE_TYPE_UNMARSHALL(type) do { \
6658 align_pointer(&pStubMsg->Buffer, sizeof(type)); \
6659 if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
6660 { \
6661 *ppMemory = pStubMsg->Buffer; \
6662 TRACE("*ppMemory: %p\n", *ppMemory); \
6663 safe_buffer_increment(pStubMsg, sizeof(type)); \
6664 } \
6665 else \
6666 { \
6667 if (fMustAlloc) \
6668 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
6669 TRACE("*ppMemory: %p\n", *ppMemory); \
6670 safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \
6671 } \
6672 } while (0)
6673
6674 switch(*pFormat)
6675 {
6676 case RPC_FC_BYTE:
6677 case RPC_FC_CHAR:
6678 case RPC_FC_SMALL:
6679 case RPC_FC_USMALL:
6680 BASE_TYPE_UNMARSHALL(UCHAR);
6681 TRACE("value: 0x%02x\n", **ppMemory);
6682 break;
6683 case RPC_FC_WCHAR:
6684 case RPC_FC_SHORT:
6685 case RPC_FC_USHORT:
6686 BASE_TYPE_UNMARSHALL(USHORT);
6687 TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
6688 break;
6689 case RPC_FC_LONG:
6690 case RPC_FC_ULONG:
6691 case RPC_FC_ERROR_STATUS_T:
6692 case RPC_FC_ENUM32:
6693 BASE_TYPE_UNMARSHALL(ULONG);
6694 TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
6695 break;
6696 case RPC_FC_FLOAT:
6697 BASE_TYPE_UNMARSHALL(float);
6698 TRACE("value: %f\n", **(float **)ppMemory);
6699 break;
6700 case RPC_FC_DOUBLE:
6701 BASE_TYPE_UNMARSHALL(double);
6702 TRACE("value: %f\n", **(double **)ppMemory);
6703 break;
6704 case RPC_FC_HYPER:
6705 BASE_TYPE_UNMARSHALL(ULONGLONG);
6706 TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
6707 break;
6708 case RPC_FC_ENUM16:
6709 {
6710 USHORT val;
6711 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6712 if (!fMustAlloc && !*ppMemory)
6713 fMustAlloc = TRUE;
6714 if (fMustAlloc)
6715 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
6716 safe_copy_from_buffer(pStubMsg, &val, sizeof(USHORT));
6717 /* 16-bits on the wire, but int in memory */
6718 **(UINT **)ppMemory = val;
6719 TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
6720 break;
6721 }
6722 case RPC_FC_INT3264:
6723 if (sizeof(INT_PTR) == sizeof(INT)) BASE_TYPE_UNMARSHALL(INT);
6724 else
6725 {
6726 INT val;
6727 align_pointer(&pStubMsg->Buffer, sizeof(INT));
6728 if (!fMustAlloc && !*ppMemory)
6729 fMustAlloc = TRUE;
6730 if (fMustAlloc)
6731 *ppMemory = NdrAllocate(pStubMsg, sizeof(INT_PTR));
6732 safe_copy_from_buffer(pStubMsg, &val, sizeof(INT));
6733 **(INT_PTR **)ppMemory = val;
6734 TRACE("value: 0x%08lx\n", **(INT_PTR **)ppMemory);
6735 }
6736 break;
6737 case RPC_FC_UINT3264:
6738 if (sizeof(UINT_PTR) == sizeof(UINT)) BASE_TYPE_UNMARSHALL(UINT);
6739 else
6740 {
6741 UINT val;
6742 align_pointer(&pStubMsg->Buffer, sizeof(UINT));
6743 if (!fMustAlloc && !*ppMemory)
6744 fMustAlloc = TRUE;
6745 if (fMustAlloc)
6746 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT_PTR));
6747 safe_copy_from_buffer(pStubMsg, &val, sizeof(UINT));
6748 **(UINT_PTR **)ppMemory = val;
6749 TRACE("value: 0x%08lx\n", **(UINT_PTR **)ppMemory);
6750 }
6751 break;
6752 case RPC_FC_IGNORE:
6753 break;
6754 default:
6755 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6756 }
6757 #undef BASE_TYPE_UNMARSHALL
6758
6759 /* FIXME: what is the correct return value? */
6760
6761 return NULL;
6762 }
6763
6764 /***********************************************************************
6765 * NdrBaseTypeBufferSize [internal]
6766 */
6767 static void WINAPI NdrBaseTypeBufferSize(
6768 PMIDL_STUB_MESSAGE pStubMsg,
6769 unsigned char *pMemory,
6770 PFORMAT_STRING pFormat)
6771 {
6772 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6773
6774 switch(*pFormat)
6775 {
6776 case RPC_FC_BYTE:
6777 case RPC_FC_CHAR:
6778 case RPC_FC_SMALL:
6779 case RPC_FC_USMALL:
6780 safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
6781 break;
6782 case RPC_FC_WCHAR:
6783 case RPC_FC_SHORT:
6784 case RPC_FC_USHORT:
6785 case RPC_FC_ENUM16:
6786 align_length(&pStubMsg->BufferLength, sizeof(USHORT));
6787 safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
6788 break;
6789 case RPC_FC_LONG:
6790 case RPC_FC_ULONG:
6791 case RPC_FC_ENUM32:
6792 case RPC_FC_INT3264:
6793 case RPC_FC_UINT3264:
6794 align_length(&pStubMsg->BufferLength, sizeof(ULONG));
6795 safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
6796 break;
6797 case RPC_FC_FLOAT:
6798 align_length(&pStubMsg->BufferLength, sizeof(float));
6799 safe_buffer_length_increment(pStubMsg, sizeof(float));
6800 break;
6801 case RPC_FC_DOUBLE:
6802 align_length(&pStubMsg->BufferLength, sizeof(double));
6803 safe_buffer_length_increment(pStubMsg, sizeof(double));
6804 break;
6805 case RPC_FC_HYPER:
6806 align_length(&pStubMsg->BufferLength, sizeof(ULONGLONG));
6807 safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
6808 break;
6809 case RPC_FC_ERROR_STATUS_T:
6810 align_length(&pStubMsg->BufferLength, sizeof(error_status_t));
6811 safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
6812 break;
6813 case RPC_FC_IGNORE:
6814 break;
6815 default:
6816 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6817 }
6818 }
6819
6820 /***********************************************************************
6821 * NdrBaseTypeMemorySize [internal]
6822 */
6823 static ULONG WINAPI NdrBaseTypeMemorySize(
6824 PMIDL_STUB_MESSAGE pStubMsg,
6825 PFORMAT_STRING pFormat)
6826 {
6827 TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
6828
6829 switch(*pFormat)
6830 {
6831 case RPC_FC_BYTE:
6832 case RPC_FC_CHAR:
6833 case RPC_FC_SMALL:
6834 case RPC_FC_USMALL:
6835 safe_buffer_increment(pStubMsg, sizeof(UCHAR));
6836 pStubMsg->MemorySize += sizeof(UCHAR);
6837 return sizeof(UCHAR);
6838 case RPC_FC_WCHAR:
6839 case RPC_FC_SHORT:
6840 case RPC_FC_USHORT:
6841 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6842 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6843 align_length(&pStubMsg->MemorySize, sizeof(USHORT));
6844 pStubMsg->MemorySize += sizeof(USHORT);
6845 return sizeof(USHORT);
6846 case RPC_FC_LONG:
6847 case RPC_FC_ULONG:
6848 case RPC_FC_ENUM32:
6849 align_pointer(&pStubMsg->Buffer, sizeof(ULONG));
6850 safe_buffer_increment(pStubMsg, sizeof(ULONG));
6851 align_length(&pStubMsg->MemorySize, sizeof(ULONG));
6852 pStubMsg->MemorySize += sizeof(ULONG);
6853 return sizeof(ULONG);
6854 case RPC_FC_FLOAT:
6855 align_pointer(&pStubMsg->Buffer, sizeof(float));
6856 safe_buffer_increment(pStubMsg, sizeof(float));
6857 align_length(&pStubMsg->MemorySize, sizeof(float));
6858 pStubMsg->MemorySize += sizeof(float);
6859 return sizeof(float);
6860 case RPC_FC_DOUBLE:
6861 align_pointer(&pStubMsg->Buffer, sizeof(double));
6862 safe_buffer_increment(pStubMsg, sizeof(double));
6863 align_length(&pStubMsg->MemorySize, sizeof(double));
6864 pStubMsg->MemorySize += sizeof(double);
6865 return sizeof(double);
6866 case RPC_FC_HYPER:
6867 align_pointer(&pStubMsg->Buffer, sizeof(ULONGLONG));
6868 safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
6869 align_length(&pStubMsg->MemorySize, sizeof(ULONGLONG));
6870 pStubMsg->MemorySize += sizeof(ULONGLONG);
6871 return sizeof(ULONGLONG);
6872 case RPC_FC_ERROR_STATUS_T:
6873 align_pointer(&pStubMsg->Buffer, sizeof(error_status_t));
6874 safe_buffer_increment(pStubMsg, sizeof(error_status_t));
6875 align_length(&pStubMsg->MemorySize, sizeof(error_status_t));
6876 pStubMsg->MemorySize += sizeof(error_status_t);
6877 return sizeof(error_status_t);
6878 case RPC_FC_ENUM16:
6879 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
6880 safe_buffer_increment(pStubMsg, sizeof(USHORT));
6881 align_length(&pStubMsg->MemorySize, sizeof(UINT));
6882 pStubMsg->MemorySize += sizeof(UINT);
6883 return sizeof(UINT);
6884 case RPC_FC_INT3264:
6885 case RPC_FC_UINT3264:
6886 align_pointer(&pStubMsg->Buffer, sizeof(UINT));
6887 safe_buffer_increment(pStubMsg, sizeof(UINT));
6888 align_length(&pStubMsg->MemorySize, sizeof(UINT_PTR));
6889 pStubMsg->MemorySize += sizeof(UINT_PTR);
6890 return sizeof(UINT_PTR);
6891 case RPC_FC_IGNORE:
6892 align_length(&pStubMsg->MemorySize, sizeof(void *));
6893 pStubMsg->MemorySize += sizeof(void *);
6894 return sizeof(void *);
6895 default:
6896 FIXME("Unhandled base type: 0x%02x\n", *pFormat);
6897 return 0;
6898 }
6899 }
6900
6901 /***********************************************************************
6902 * NdrBaseTypeFree [internal]
6903 */
6904 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
6905 unsigned char *pMemory,
6906 PFORMAT_STRING pFormat)
6907 {
6908 TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6909
6910 /* nothing to do */
6911 }
6912
6913 /***********************************************************************
6914 * NdrContextHandleBufferSize [internal]
6915 */
6916 static void WINAPI NdrContextHandleBufferSize(
6917 PMIDL_STUB_MESSAGE pStubMsg,
6918 unsigned char *pMemory,
6919 PFORMAT_STRING pFormat)
6920 {
6921 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6922
6923 if (*pFormat != RPC_FC_BIND_CONTEXT)
6924 {
6925 ERR("invalid format type %x\n", *pFormat);
6926 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6927 }
6928 align_length(&pStubMsg->BufferLength, 4);
6929 safe_buffer_length_increment(pStubMsg, cbNDRContext);
6930 }
6931
6932 /***********************************************************************
6933 * NdrContextHandleMarshall [internal]
6934 */
6935 static unsigned char *WINAPI NdrContextHandleMarshall(
6936 PMIDL_STUB_MESSAGE pStubMsg,
6937 unsigned char *pMemory,
6938 PFORMAT_STRING pFormat)
6939 {
6940 TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
6941
6942 if (*pFormat != RPC_FC_BIND_CONTEXT)
6943 {
6944 ERR("invalid format type %x\n", *pFormat);
6945 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6946 }
6947 TRACE("flags: 0x%02x\n", pFormat[1]);
6948
6949 if (pStubMsg->IsClient)
6950 {
6951 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6952 NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
6953 else
6954 NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
6955 }
6956 else
6957 {
6958 NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
6959 NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
6960 NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
6961 }
6962
6963 return NULL;
6964 }
6965
6966 /***********************************************************************
6967 * NdrContextHandleUnmarshall [internal]
6968 */
6969 static unsigned char *WINAPI NdrContextHandleUnmarshall(
6970 PMIDL_STUB_MESSAGE pStubMsg,
6971 unsigned char **ppMemory,
6972 PFORMAT_STRING pFormat,
6973 unsigned char fMustAlloc)
6974 {
6975 TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg,
6976 ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE");
6977
6978 if (*pFormat != RPC_FC_BIND_CONTEXT)
6979 {
6980 ERR("invalid format type %x\n", *pFormat);
6981 RpcRaiseException(RPC_S_INTERNAL_ERROR);
6982 }
6983 TRACE("flags: 0x%02x\n", pFormat[1]);
6984
6985 if (pStubMsg->IsClient)
6986 {
6987 /* [out]-only or [ret] param */
6988 if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT)
6989 **(NDR_CCONTEXT **)ppMemory = NULL;
6990 NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
6991 }
6992 else
6993 {
6994 NDR_SCONTEXT ctxt;
6995 ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat);
6996 if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
6997 *(void **)ppMemory = NDRSContextValue(ctxt);
6998 else
6999 *(void **)ppMemory = *NDRSContextValue(ctxt);
7000 }
7001
7002 return NULL;
7003 }
7004
7005 /***********************************************************************
7006 * NdrClientContextMarshall [RPCRT4.@]
7007 */
7008 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
7009 NDR_CCONTEXT ContextHandle,
7010 int fCheck)
7011 {
7012 TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
7013
7014 align_pointer_clear(&pStubMsg->Buffer, 4);
7015
7016 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7017 {
7018 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7019 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7020 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7021 }
7022
7023 /* FIXME: what does fCheck do? */
7024 NDRCContextMarshall(ContextHandle,
7025 pStubMsg->Buffer);
7026
7027 pStubMsg->Buffer += cbNDRContext;
7028 }
7029
7030 /***********************************************************************
7031 * NdrClientContextUnmarshall [RPCRT4.@]
7032 */
7033 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
7034 NDR_CCONTEXT * pContextHandle,
7035 RPC_BINDING_HANDLE BindHandle)
7036 {
7037 TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
7038
7039 align_pointer(&pStubMsg->Buffer, 4);
7040
7041 if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
7042 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7043
7044 NDRCContextUnmarshall(pContextHandle,
7045 BindHandle,
7046 pStubMsg->Buffer,
7047 pStubMsg->RpcMsg->DataRepresentation);
7048
7049 pStubMsg->Buffer += cbNDRContext;
7050 }
7051
7052 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
7053 NDR_SCONTEXT ContextHandle,
7054 NDR_RUNDOWN RundownRoutine )
7055 {
7056 TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
7057
7058 align_pointer(&pStubMsg->Buffer, 4);
7059
7060 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7061 {
7062 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7063 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7064 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7065 }
7066
7067 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
7068 pStubMsg->Buffer, RundownRoutine, NULL,
7069 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
7070 pStubMsg->Buffer += cbNDRContext;
7071 }
7072
7073 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
7074 {
7075 NDR_SCONTEXT ContextHandle;
7076
7077 TRACE("(%p)\n", pStubMsg);
7078
7079 align_pointer(&pStubMsg->Buffer, 4);
7080
7081 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7082 {
7083 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7084 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7085 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7086 }
7087
7088 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
7089 pStubMsg->Buffer,
7090 pStubMsg->RpcMsg->DataRepresentation,
7091 NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
7092 pStubMsg->Buffer += cbNDRContext;
7093
7094 return ContextHandle;
7095 }
7096
7097 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
7098 unsigned char* pMemory,
7099 PFORMAT_STRING pFormat)
7100 {
7101 FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
7102 }
7103
7104 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
7105 PFORMAT_STRING pFormat)
7106 {
7107 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
7108 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
7109
7110 TRACE("(%p, %p)\n", pStubMsg, pFormat);
7111
7112 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7113 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7114 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
7115 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7116 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7117 {
7118 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7119 if_id = &sif->InterfaceId;
7120 }
7121
7122 return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
7123 pStubMsg->RpcMsg->DataRepresentation, if_id,
7124 flags);
7125 }
7126
7127 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
7128 NDR_SCONTEXT ContextHandle,
7129 NDR_RUNDOWN RundownRoutine,
7130 PFORMAT_STRING pFormat)
7131 {
7132 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
7133 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
7134
7135 TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
7136
7137 align_pointer(&pStubMsg->Buffer, 4);
7138
7139 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7140 {
7141 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7142 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7143 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7144 }
7145
7146 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7147 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7148 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
7149 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7150 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7151 {
7152 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7153 if_id = &sif->InterfaceId;
7154 }
7155
7156 NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
7157 pStubMsg->Buffer, RundownRoutine, if_id, flags);
7158 pStubMsg->Buffer += cbNDRContext;
7159 }
7160
7161 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
7162 PFORMAT_STRING pFormat)
7163 {
7164 NDR_SCONTEXT ContextHandle;
7165 RPC_SYNTAX_IDENTIFIER *if_id = NULL;
7166 ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
7167
7168 TRACE("(%p, %p)\n", pStubMsg, pFormat);
7169
7170 align_pointer(&pStubMsg->Buffer, 4);
7171
7172 if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
7173 {
7174 ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
7175 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
7176 RpcRaiseException(RPC_X_BAD_STUB_DATA);
7177 }
7178
7179 if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
7180 flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
7181 if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
7182 flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
7183 if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
7184 {
7185 RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
7186 if_id = &sif->InterfaceId;
7187 }
7188
7189 ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
7190 pStubMsg->Buffer,
7191 pStubMsg->RpcMsg->DataRepresentation,
7192 if_id, flags);
7193 pStubMsg->Buffer += cbNDRContext;
7194
7195 return ContextHandle;
7196 }
7197
7198 /***********************************************************************
7199 * NdrCorrelationInitialize [RPCRT4.@]
7200 *
7201 * Initializes correlation validity checking.
7202 *
7203 * PARAMS
7204 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7205 * pMemory [I] Pointer to memory to use as a cache.
7206 * CacheSize [I] Size of the memory pointed to by pMemory.
7207 * Flags [I] Reserved. Set to zero.
7208 *
7209 * RETURNS
7210 * Nothing.
7211 */
7212 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
7213 {
7214 FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
7215 pStubMsg->fHasNewCorrDesc = TRUE;
7216 }
7217
7218 /***********************************************************************
7219 * NdrCorrelationPass [RPCRT4.@]
7220 *
7221 * Performs correlation validity checking.
7222 *
7223 * PARAMS
7224 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7225 *
7226 * RETURNS
7227 * Nothing.
7228 */
7229 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
7230 {
7231 FIXME("(%p): stub\n", pStubMsg);
7232 }
7233
7234 /***********************************************************************
7235 * NdrCorrelationFree [RPCRT4.@]
7236 *
7237 * Frees any resources used while unmarshalling parameters that need
7238 * correlation validity checking.
7239 *
7240 * PARAMS
7241 * pStubMsg [I] MIDL_STUB_MESSAGE used during unmarshalling.
7242 *
7243 * RETURNS
7244 * Nothing.
7245 */
7246 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
7247 {
7248 FIXME("(%p): stub\n", pStubMsg);
7249 }