[LT2013]
[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