[RPCRT4]
[reactos.git] / reactos / 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 "precomp.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(ole);
33
34 #if defined(__i386__)
35 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
36 (*((UINT32 *)(pchar)) = (uint32))
37
38 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
39 (*((UINT32 *)(pchar)))
40 #else
41 /* these would work for i386 too, but less efficient */
42 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
43 (*(pchar) = LOBYTE(LOWORD(uint32)), \
44 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
45 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
46 *((pchar)+3) = HIBYTE(HIWORD(uint32)))
47
48 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
49 (MAKELONG( \
50 MAKEWORD(*(pchar), *((pchar)+1)), \
51 MAKEWORD(*((pchar)+2), *((pchar)+3))))
52 #endif
53
54 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
55 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
56 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
57 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
58 *(pchar) = HIBYTE(HIWORD(uint32)))
59
60 #define BIG_ENDIAN_UINT32_READ(pchar) \
61 (MAKELONG( \
62 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
63 MAKEWORD(*((pchar)+1), *(pchar))))
64
65 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
66 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
67 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
68 # define NDR_LOCAL_UINT32_READ(pchar) \
69 BIG_ENDIAN_UINT32_READ(pchar)
70 #else
71 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
72 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
73 # define NDR_LOCAL_UINT32_READ(pchar) \
74 LITTLE_ENDIAN_UINT32_READ(pchar)
75 #endif
76
77 static inline void align_length( ULONG *len, unsigned int align )
78 {
79 *len = (*len + align - 1) & ~(align - 1);
80 }
81
82 static inline void align_pointer( unsigned char **ptr, unsigned int align )
83 {
84 ULONG_PTR mask = align - 1;
85 *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
86 }
87
88 static inline void align_pointer_clear( unsigned char **ptr, unsigned int align )
89 {
90 ULONG_PTR mask = align - 1;
91 memset( *ptr, 0, (align - (ULONG_PTR)*ptr) & mask );
92 *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
93 }
94
95 #define STD_OVERFLOW_CHECK(_Msg) do { \
96 TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
97 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
98 ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
99 } while (0)
100
101 #define NDR_POINTER_ID_BASE 0x20000
102 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
103 #define NDR_TABLE_SIZE 128
104 #define NDR_TABLE_MASK 127
105
106 #define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL))
107
108 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
109 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
110 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
111 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
112 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
113
114 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
115 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
116 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
117
118 static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
119 static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
120 static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
121 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
122
123 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
124
125 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
126 unsigned char *pMemory,
127 PFORMAT_STRING pFormat,
128 PFORMAT_STRING pPointer);
129 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
130 unsigned char *pMemory,
131 PFORMAT_STRING pFormat,
132 PFORMAT_STRING pPointer);
133 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
134 unsigned char *pMemory,
135 PFORMAT_STRING pFormat,
136 PFORMAT_STRING pPointer,
137 unsigned char fMustAlloc);
138 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
139 PFORMAT_STRING pFormat,
140 PFORMAT_STRING pPointer);
141 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
142 unsigned char *pMemory,
143 PFORMAT_STRING pFormat,
144 PFORMAT_STRING pPointer);
145
146 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
147 0,
148 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
149 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
150 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
151 NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
152 /* 0x10 */
153 NdrBaseTypeMarshall,
154 /* 0x11 */
155 NdrPointerMarshall, NdrPointerMarshall,
156 NdrPointerMarshall, NdrPointerMarshall,
157 /* 0x15 */
158 NdrSimpleStructMarshall, NdrSimpleStructMarshall,
159 NdrConformantStructMarshall, NdrConformantStructMarshall,
160 NdrConformantVaryingStructMarshall,
161 NdrComplexStructMarshall,
162 /* 0x1b */
163 NdrConformantArrayMarshall,
164 NdrConformantVaryingArrayMarshall,
165 NdrFixedArrayMarshall, NdrFixedArrayMarshall,
166 NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
167 NdrComplexArrayMarshall,
168 /* 0x22 */
169 NdrConformantStringMarshall, 0, 0,
170 NdrConformantStringMarshall,
171 NdrNonConformantStringMarshall, 0, 0, 0,
172 /* 0x2a */
173 NdrEncapsulatedUnionMarshall,
174 NdrNonEncapsulatedUnionMarshall,
175 NdrByteCountPointerMarshall,
176 NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
177 /* 0x2f */
178 NdrInterfacePointerMarshall,
179 /* 0x30 */
180 NdrContextHandleMarshall,
181 /* 0xb1 */
182 0, 0, 0,
183 NdrUserMarshalMarshall,
184 0, 0,
185 /* 0xb7 */
186 NdrRangeMarshall
187 };
188 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
189 0,
190 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
191 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
192 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
193 NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
194 /* 0x10 */
195 NdrBaseTypeUnmarshall,
196 /* 0x11 */
197 NdrPointerUnmarshall, NdrPointerUnmarshall,
198 NdrPointerUnmarshall, NdrPointerUnmarshall,
199 /* 0x15 */
200 NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
201 NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
202 NdrConformantVaryingStructUnmarshall,
203 NdrComplexStructUnmarshall,
204 /* 0x1b */
205 NdrConformantArrayUnmarshall,
206 NdrConformantVaryingArrayUnmarshall,
207 NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
208 NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
209 NdrComplexArrayUnmarshall,
210 /* 0x22 */
211 NdrConformantStringUnmarshall, 0, 0,
212 NdrConformantStringUnmarshall,
213 NdrNonConformantStringUnmarshall, 0, 0, 0,
214 /* 0x2a */
215 NdrEncapsulatedUnionUnmarshall,
216 NdrNonEncapsulatedUnionUnmarshall,
217 NdrByteCountPointerUnmarshall,
218 NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
219 /* 0x2f */
220 NdrInterfacePointerUnmarshall,
221 /* 0x30 */
222 NdrContextHandleUnmarshall,
223 /* 0xb1 */
224 0, 0, 0,
225 NdrUserMarshalUnmarshall,
226 0, 0,
227 /* 0xb7 */
228 NdrRangeUnmarshall
229 };
230 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
231 0,
232 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
233 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
234 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
235 NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
236 /* 0x10 */
237 NdrBaseTypeBufferSize,
238 /* 0x11 */
239 NdrPointerBufferSize, NdrPointerBufferSize,
240 NdrPointerBufferSize, NdrPointerBufferSize,
241 /* 0x15 */
242 NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
243 NdrConformantStructBufferSize, NdrConformantStructBufferSize,
244 NdrConformantVaryingStructBufferSize,
245 NdrComplexStructBufferSize,
246 /* 0x1b */
247 NdrConformantArrayBufferSize,
248 NdrConformantVaryingArrayBufferSize,
249 NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
250 NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
251 NdrComplexArrayBufferSize,
252 /* 0x22 */
253 NdrConformantStringBufferSize, 0, 0,
254 NdrConformantStringBufferSize,
255 NdrNonConformantStringBufferSize, 0, 0, 0,
256 /* 0x2a */
257 NdrEncapsulatedUnionBufferSize,
258 NdrNonEncapsulatedUnionBufferSize,
259 NdrByteCountPointerBufferSize,
260 NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
261 /* 0x2f */
262 NdrInterfacePointerBufferSize,
263 /* 0x30 */
264 NdrContextHandleBufferSize,
265 /* 0xb1 */
266 0, 0, 0,
267 NdrUserMarshalBufferSize,
268 0, 0,
269 /* 0xb7 */
270 NdrRangeBufferSize
271 };
272 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
273 0,
274 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
275 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
276 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
277 NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
278 /* 0x10 */
279 NdrBaseTypeMemorySize,
280 /* 0x11 */
281 NdrPointerMemorySize, NdrPointerMemorySize,
282 NdrPointerMemorySize, NdrPointerMemorySize,
283 /* 0x15 */
284 NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
285 NdrConformantStructMemorySize, NdrConformantStructMemorySize,
286 NdrConformantVaryingStructMemorySize,
287 NdrComplexStructMemorySize,
288 /* 0x1b */
289 NdrConformantArrayMemorySize,
290 NdrConformantVaryingArrayMemorySize,
291 NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
292 NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
293 NdrComplexArrayMemorySize,
294 /* 0x22 */
295 NdrConformantStringMemorySize, 0, 0,
296 NdrConformantStringMemorySize,
297 NdrNonConformantStringMemorySize, 0, 0, 0,
298 /* 0x2a */
299 NdrEncapsulatedUnionMemorySize,
300 NdrNonEncapsulatedUnionMemorySize,
301 NdrByteCountPointerMemorySize,
302 NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
303 /* 0x2f */
304 NdrInterfacePointerMemorySize,
305 /* 0x30 */
306 0,
307 /* 0xb1 */
308 0, 0, 0,
309 NdrUserMarshalMemorySize,
310 0, 0,
311 /* 0xb7 */
312 NdrRangeMemorySize
313 };
314 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
315 0,
316 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
317 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
318 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
319 NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
320 /* 0x10 */
321 NdrBaseTypeFree,
322 /* 0x11 */
323 NdrPointerFree, NdrPointerFree,
324 NdrPointerFree, NdrPointerFree,
325 /* 0x15 */
326 NdrSimpleStructFree, NdrSimpleStructFree,
327 NdrConformantStructFree, NdrConformantStructFree,
328 NdrConformantVaryingStructFree,
329 NdrComplexStructFree,
330 /* 0x1b */
331 NdrConformantArrayFree,
332 NdrConformantVaryingArrayFree,
333 NdrFixedArrayFree, NdrFixedArrayFree,
334 NdrVaryingArrayFree, NdrVaryingArrayFree,
335 NdrComplexArrayFree,
336 /* 0x22 */
337 0, 0, 0,
338 0, 0, 0, 0, 0,
339 /* 0x2a */
340 NdrEncapsulatedUnionFree,
341 NdrNonEncapsulatedUnionFree,
342 0,
343 NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
344 /* 0x2f */
345 NdrInterfacePointerFree,
346 /* 0x30 */
347 0,
348 /* 0xb1 */
349 0, 0, 0,
350 NdrUserMarshalFree,
351 0, 0,
352 /* 0xb7 */
353 NdrRangeFree
354 };
355
356 typedef struct _NDR_MEMORY_LIST
357 {
358 ULONG magic;
359 ULONG size;
360 ULONG reserved;
361 struct _NDR_MEMORY_LIST *next;
362 } NDR_MEMORY_LIST;
363
364 #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
365
366 /***********************************************************************
367 * NdrAllocate [RPCRT4.@]
368 *
369 * Allocates a block of memory using pStubMsg->pfnAllocate.
370 *
371 * PARAMS
372 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
373 * len [I] Size of memory block to allocate.
374 *
375 * RETURNS
376 * The memory block of size len that was allocated.
377 *
378 * NOTES
379 * The memory block is always 8-byte aligned.
380 * If the function is unable to allocate memory an ERROR_OUTOFMEMORY
381 * exception is raised.
382 */
383 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len)
384 {
385 SIZE_T aligned_len;
386 SIZE_T adjusted_len;
387 void *p;
388 NDR_MEMORY_LIST *mem_list;
389
390 aligned_len = (len + 7) & ~7;
391 adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
392 /* check for overflow */
393 if (adjusted_len < len)
394 {
395 ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len);
396 RpcRaiseException(RPC_X_BAD_STUB_DATA);
397 }
398
399 p = pStubMsg->pfnAllocate(adjusted_len);
400 if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
401
402 mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
403 mem_list->magic = MEML_MAGIC;
404 mem_list->size = aligned_len;
405 mem_list->reserved = 0;
406 mem_list->next = pStubMsg->pMemoryList;
407 pStubMsg->pMemoryList = mem_list;
408
409 TRACE("-- %p\n", p);
410 return p;
411 }
412
413 static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
414 {
415 TRACE("(%p, %p)\n", pStubMsg, Pointer);
416
417 pStubMsg->pfnFree(Pointer);
418 }
419
420 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
421 {
422 return (*(const ULONG *)pFormat != -1);
423 }
424
425 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
426 {
427 align_pointer(&pStubMsg->Buffer, 4);
428 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
429 RpcRaiseException(RPC_X_BAD_STUB_DATA);
430 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
431 pStubMsg->Buffer += 4;
432 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
433 if (pStubMsg->fHasNewCorrDesc)
434 return pFormat+6;
435 else
436 return pFormat+4;
437 }
438
439 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
440 {
441 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
442 {
443 pStubMsg->Offset = 0;
444 pStubMsg->ActualCount = pStubMsg->MaxCount;
445 goto done;
446 }
447
448 align_pointer(&pStubMsg->Buffer, 4);
449 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
450 RpcRaiseException(RPC_X_BAD_STUB_DATA);
451 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
452 pStubMsg->Buffer += 4;
453 TRACE("offset is %d\n", pStubMsg->Offset);
454 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
455 pStubMsg->Buffer += 4;
456 TRACE("variance is %d\n", pStubMsg->ActualCount);
457
458 if ((pStubMsg->ActualCount > MaxValue) ||
459 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
460 {
461 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
462 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
463 RpcRaiseException(RPC_S_INVALID_BOUND);
464 return NULL;
465 }
466
467 done:
468 if (pStubMsg->fHasNewCorrDesc)
469 return pFormat+6;
470 else
471 return pFormat+4;
472 }
473
474 /* writes the conformance value to the buffer */
475 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
476 {
477 align_pointer_clear(&pStubMsg->Buffer, 4);
478 if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
479 RpcRaiseException(RPC_X_BAD_STUB_DATA);
480 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
481 pStubMsg->Buffer += 4;
482 }
483
484 /* writes the variance values to the buffer */
485 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
486 {
487 align_pointer_clear(&pStubMsg->Buffer, 4);
488 if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
489 RpcRaiseException(RPC_X_BAD_STUB_DATA);
490 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
491 pStubMsg->Buffer += 4;
492 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
493 pStubMsg->Buffer += 4;
494 }
495
496 /* requests buffer space for the conformance value */
497 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
498 {
499 align_length(&pStubMsg->BufferLength, 4);
500 if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
501 RpcRaiseException(RPC_X_BAD_STUB_DATA);
502 pStubMsg->BufferLength += 4;
503 }
504
505 /* requests buffer space for the variance values */
506 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
507 {
508 align_length(&pStubMsg->BufferLength, 4);
509 if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
510 RpcRaiseException(RPC_X_BAD_STUB_DATA);
511 pStubMsg->BufferLength += 8;
512 }
513
514 PFORMAT_STRING ComputeConformanceOrVariance(
515 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
516 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
517 {
518 BYTE dtype = pFormat[0] & 0xf;
519 short ofs = *(const short *)&pFormat[2];
520 LPVOID ptr = NULL;
521 ULONG_PTR data = 0;
522
523 if (!IsConformanceOrVariancePresent(pFormat)) {
524 /* null descriptor */
525 *pCount = def;
526 goto finish_conf;
527 }
528
529 switch (pFormat[0] & 0xf0) {
530 case RPC_FC_NORMAL_CONFORMANCE:
531 TRACE("normal conformance, ofs=%d\n", ofs);
532 ptr = pMemory;
533 break;
534 case RPC_FC_POINTER_CONFORMANCE:
535 TRACE("pointer conformance, ofs=%d\n", ofs);
536 ptr = pStubMsg->Memory;
537 break;
538 case RPC_FC_TOP_LEVEL_CONFORMANCE:
539 TRACE("toplevel conformance, ofs=%d\n", ofs);
540 if (pStubMsg->StackTop) {
541 ptr = pStubMsg->StackTop;
542 }
543 else {
544 /* -Os mode, *pCount is already set */
545 goto finish_conf;
546 }
547 break;
548 case RPC_FC_CONSTANT_CONFORMANCE:
549 data = ofs | ((DWORD)pFormat[1] << 16);
550 TRACE("constant conformance, val=%ld\n", data);
551 *pCount = data;
552 goto finish_conf;
553 case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
554 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
555 if (pStubMsg->StackTop) {
556 ptr = pStubMsg->StackTop;
557 }
558 else {
559 /* ? */
560 goto done_conf_grab;
561 }
562 break;
563 default:
564 FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0);
565 goto finish_conf;
566 }
567
568 switch (pFormat[1]) {
569 case RPC_FC_DEREFERENCE:
570 ptr = *(LPVOID*)((char *)ptr + ofs);
571 break;
572 case RPC_FC_CALLBACK:
573 {
574 unsigned char *old_stack_top = pStubMsg->StackTop;
575 ULONG_PTR max_count, old_max_count = pStubMsg->MaxCount;
576
577 pStubMsg->StackTop = ptr;
578
579 /* ofs is index into StubDesc->apfnExprEval */
580 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
581 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
582
583 pStubMsg->StackTop = old_stack_top;
584
585 /* the callback function always stores the computed value in MaxCount */
586 max_count = pStubMsg->MaxCount;
587 pStubMsg->MaxCount = old_max_count;
588 *pCount = max_count;
589 goto finish_conf;
590 }
591 default:
592 ptr = (char *)ptr + ofs;
593 break;
594 }
595
596 switch (dtype) {
597 case RPC_FC_LONG:
598 case RPC_FC_ULONG:
599 data = *(DWORD*)ptr;
600 break;
601 case RPC_FC_SHORT:
602 data = *(SHORT*)ptr;
603 break;
604 case RPC_FC_USHORT:
605 data = *(USHORT*)ptr;
606 break;
607 case RPC_FC_CHAR:
608 case RPC_FC_SMALL:
609 data = *(CHAR*)ptr;
610 break;
611 case RPC_FC_BYTE:
612 case RPC_FC_USMALL:
613 data = *(UCHAR*)ptr;
614 break;
615 case RPC_FC_HYPER:
616 data = *(ULONGLONG *)ptr;
617 break;
618 default:
619 FIXME("unknown conformance data type %x\n", dtype);
620 goto done_conf_grab;
621 }
622 TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);
623
624 done_conf_grab:
625 switch (pFormat[1]) {
626 case RPC_FC_DEREFERENCE: /* already handled */
627 case 0: /* no op */
628 *pCount = data;
629 break;
630 case RPC_FC_ADD_1:
631 *pCount = data + 1;
632 break;
633 case RPC_FC_SUB_1:
634 *pCount = data - 1;
635 break;
636 case RPC_FC_MULT_2:
637 *pCount = data * 2;
638 break;
639 case RPC_FC_DIV_2:
640 *pCount = data / 2;
641 break;
642 default:
643 FIXME("unknown conformance op %d\n", pFormat[1]);
644 goto finish_conf;
645 }
646
647 finish_conf:
648 TRACE("resulting conformance is %ld\n", *pCount);
649 if (pStubMsg->fHasNewCorrDesc)
650 return pFormat+6;
651 else
652 return pFormat+4;
653 }
654
655 static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg,
656 PFORMAT_STRING pFormat)
657 {
658 if (pStubMsg->fHasNewCorrDesc)
659 pFormat += 6;
660 else
661 pFormat += 4;
662 return pFormat;
663 }
664
665 static inline PFORMAT_STRING SkipVariance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
666 {
667 return SkipConformance( pStubMsg, pFormat );
668 }
669
670 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
671 * the result overflows 32-bits */
672 static inline ULONG safe_multiply(ULONG a, ULONG b)
673 {
674 ULONGLONG ret = (ULONGLONG)a * b;
675 if (ret > 0xffffffff)
676 {
677 RpcRaiseException(RPC_S_INVALID_BOUND);
678 return 0;
679 }
680 return ret;
681 }
682
683 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
684 {
685 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
686 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
687 RpcRaiseException(RPC_X_BAD_STUB_DATA);
688 pStubMsg->Buffer += size;
689 }
690
691 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
692 {
693 if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
694 {
695 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
696 pStubMsg->BufferLength, size);
697 RpcRaiseException(RPC_X_BAD_STUB_DATA);
698 }
699 pStubMsg->BufferLength += size;
700 }
701
702 /* copies data from the buffer, checking that there is enough data in the buffer
703 * to do so */
704 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
705 {
706 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
707 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
708 {
709 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
710 pStubMsg->Buffer, pStubMsg->BufferEnd, size);
711 RpcRaiseException(RPC_X_BAD_STUB_DATA);
712 }
713 if (p == pStubMsg->Buffer)
714 ERR("pointer is the same as the buffer\n");
715 memcpy(p, pStubMsg->Buffer, size);
716 pStubMsg->Buffer += size;
717 }
718
719 /* copies data to the buffer, checking that there is enough space to do so */
720 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
721 {
722 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
723 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
724 {
725 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
726 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
727 size);
728 RpcRaiseException(RPC_X_BAD_STUB_DATA);
729 }
730 memcpy(pStubMsg->Buffer, p, size);
731 pStubMsg->Buffer += size;
732 }
733
734 /* verify that string data sitting in the buffer is valid and safe to
735 * unmarshall */
736 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
737 {
738 ULONG i;
739
740 /* verify the buffer is safe to access */
741 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
742 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
743 {
744 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
745 pStubMsg->BufferEnd, pStubMsg->Buffer);
746 RpcRaiseException(RPC_X_BAD_STUB_DATA);
747 }
748
749 /* strings must always have null terminating bytes */
750 if (bufsize < esize)
751 {
752 ERR("invalid string length of %d\n", bufsize / esize);
753 RpcRaiseException(RPC_S_INVALID_BOUND);
754 }
755
756 for (i = bufsize - esize; i < bufsize; i++)
757 if (pStubMsg->Buffer[i] != 0)
758 {
759 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
760 i, pStubMsg->Buffer[i]);
761 RpcRaiseException(RPC_S_INVALID_BOUND);
762 }
763 }
764
765 static inline void dump_pointer_attr(unsigned char attr)
766 {
767 if (attr & RPC_FC_P_ALLOCALLNODES)
768 TRACE(" RPC_FC_P_ALLOCALLNODES");
769 if (attr & RPC_FC_P_DONTFREE)
770 TRACE(" RPC_FC_P_DONTFREE");
771 if (attr & RPC_FC_P_ONSTACK)
772 TRACE(" RPC_FC_P_ONSTACK");
773 if (attr & RPC_FC_P_SIMPLEPOINTER)
774 TRACE(" RPC_FC_P_SIMPLEPOINTER");
775 if (attr & RPC_FC_P_DEREF)
776 TRACE(" RPC_FC_P_DEREF");
777 TRACE("\n");
778 }
779
780 /***********************************************************************
781 * PointerMarshall [internal]
782 */
783 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
784 unsigned char *Buffer,
785 unsigned char *Pointer,
786 PFORMAT_STRING pFormat)
787 {
788 unsigned type = pFormat[0], attr = pFormat[1];
789 PFORMAT_STRING desc;
790 NDR_MARSHALL m;
791 ULONG pointer_id;
792 BOOL pointer_needs_marshaling;
793
794 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
795 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
796 pFormat += 2;
797 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
798 else desc = pFormat + *(const SHORT*)pFormat;
799
800 switch (type) {
801 case RPC_FC_RP: /* ref pointer (always non-null) */
802 if (!Pointer)
803 {
804 ERR("NULL ref pointer is not allowed\n");
805 RpcRaiseException(RPC_X_NULL_REF_POINTER);
806 }
807 pointer_needs_marshaling = TRUE;
808 break;
809 case RPC_FC_UP: /* unique pointer */
810 case RPC_FC_OP: /* object pointer - same as unique here */
811 if (Pointer)
812 pointer_needs_marshaling = TRUE;
813 else
814 pointer_needs_marshaling = FALSE;
815 pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
816 TRACE("writing 0x%08x to buffer\n", pointer_id);
817 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
818 break;
819 case RPC_FC_FP:
820 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
821 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
822 TRACE("writing 0x%08x to buffer\n", pointer_id);
823 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
824 break;
825 default:
826 FIXME("unhandled ptr type=%02x\n", type);
827 RpcRaiseException(RPC_X_BAD_STUB_DATA);
828 return;
829 }
830
831 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
832
833 if (pointer_needs_marshaling) {
834 if (attr & RPC_FC_P_DEREF) {
835 Pointer = *(unsigned char**)Pointer;
836 TRACE("deref => %p\n", Pointer);
837 }
838 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
839 if (m) m(pStubMsg, Pointer, desc);
840 else FIXME("no marshaller for data type=%02x\n", *desc);
841 }
842
843 STD_OVERFLOW_CHECK(pStubMsg);
844 }
845
846 /***********************************************************************
847 * PointerUnmarshall [internal]
848 */
849 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
850 unsigned char *Buffer,
851 unsigned char **pPointer,
852 unsigned char *pSrcPointer,
853 PFORMAT_STRING pFormat,
854 unsigned char fMustAlloc)
855 {
856 unsigned type = pFormat[0], attr = pFormat[1];
857 PFORMAT_STRING desc;
858 NDR_UNMARSHALL m;
859 DWORD pointer_id = 0;
860 BOOL pointer_needs_unmarshaling;
861
862 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
863 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
864 pFormat += 2;
865 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
866 else desc = pFormat + *(const SHORT*)pFormat;
867
868 switch (type) {
869 case RPC_FC_RP: /* ref pointer (always non-null) */
870 pointer_needs_unmarshaling = TRUE;
871 break;
872 case RPC_FC_UP: /* unique pointer */
873 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
874 TRACE("pointer_id is 0x%08x\n", pointer_id);
875 if (pointer_id)
876 pointer_needs_unmarshaling = TRUE;
877 else {
878 *pPointer = NULL;
879 pointer_needs_unmarshaling = FALSE;
880 }
881 break;
882 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
883 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
884 TRACE("pointer_id is 0x%08x\n", pointer_id);
885 if (!fMustAlloc && pSrcPointer)
886 {
887 FIXME("free object pointer %p\n", pSrcPointer);
888 fMustAlloc = TRUE;
889 }
890 if (pointer_id)
891 pointer_needs_unmarshaling = TRUE;
892 else
893 {
894 *pPointer = NULL;
895 pointer_needs_unmarshaling = FALSE;
896 }
897 break;
898 case RPC_FC_FP:
899 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
900 TRACE("pointer_id is 0x%08x\n", pointer_id);
901 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
902 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
903 break;
904 default:
905 FIXME("unhandled ptr type=%02x\n", type);
906 RpcRaiseException(RPC_X_BAD_STUB_DATA);
907 return;
908 }
909
910 if (pointer_needs_unmarshaling) {
911 unsigned char **current_ptr = pPointer;
912 if (pStubMsg->IsClient) {
913 TRACE("client\n");
914 /* if we aren't forcing allocation of memory then try to use the existing
915 * (source) pointer to unmarshall the data into so that [in,out]
916 * parameters behave correctly. it doesn't matter if the parameter is
917 * [out] only since in that case the pointer will be NULL. we force
918 * allocation when the source pointer is NULL here instead of in the type
919 * unmarshalling routine for the benefit of the deref code below */
920 if (!fMustAlloc) {
921 if (pSrcPointer) {
922 TRACE("setting *pPointer to %p\n", pSrcPointer);
923 *pPointer = pSrcPointer;
924 } else
925 fMustAlloc = TRUE;
926 }
927 } else {
928 TRACE("server\n");
929 /* the memory in a stub is never initialised, so we have to work out here
930 * whether we have to initialise it so we can use the optimisation of
931 * setting the pointer to the buffer, if possible, or set fMustAlloc to
932 * TRUE. */
933 if (attr & RPC_FC_P_DEREF) {
934 fMustAlloc = TRUE;
935 } else {
936 *current_ptr = NULL;
937 }
938 }
939
940 if (attr & RPC_FC_P_ALLOCALLNODES)
941 FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
942
943 if (attr & RPC_FC_P_DEREF) {
944 if (fMustAlloc) {
945 unsigned char *base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
946 *pPointer = base_ptr_val;
947 current_ptr = (unsigned char **)base_ptr_val;
948 } else
949 current_ptr = *(unsigned char***)current_ptr;
950 TRACE("deref => %p\n", current_ptr);
951 if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
952 }
953 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
954 if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
955 else FIXME("no unmarshaller for data type=%02x\n", *desc);
956
957 if (type == RPC_FC_FP)
958 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
959 *pPointer);
960 }
961
962 TRACE("pointer=%p\n", *pPointer);
963 }
964
965 /***********************************************************************
966 * PointerBufferSize [internal]
967 */
968 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
969 unsigned char *Pointer,
970 PFORMAT_STRING pFormat)
971 {
972 unsigned type = pFormat[0], attr = pFormat[1];
973 PFORMAT_STRING desc;
974 NDR_BUFFERSIZE m;
975 BOOL pointer_needs_sizing;
976 ULONG pointer_id;
977
978 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
979 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
980 pFormat += 2;
981 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
982 else desc = pFormat + *(const SHORT*)pFormat;
983
984 switch (type) {
985 case RPC_FC_RP: /* ref pointer (always non-null) */
986 if (!Pointer)
987 {
988 ERR("NULL ref pointer is not allowed\n");
989 RpcRaiseException(RPC_X_NULL_REF_POINTER);
990 }
991 break;
992 case RPC_FC_OP:
993 case RPC_FC_UP:
994 /* NULL pointer has no further representation */
995 if (!Pointer)
996 return;
997 break;
998 case RPC_FC_FP:
999 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1000 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1001 if (!pointer_needs_sizing)
1002 return;
1003 break;
1004 default:
1005 FIXME("unhandled ptr type=%02x\n", type);
1006 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1007 return;
1008 }
1009
1010 if (attr & RPC_FC_P_DEREF) {
1011 Pointer = *(unsigned char**)Pointer;
1012 TRACE("deref => %p\n", Pointer);
1013 }
1014
1015 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1016 if (m) m(pStubMsg, Pointer, desc);
1017 else FIXME("no buffersizer for data type=%02x\n", *desc);
1018 }
1019
1020 /***********************************************************************
1021 * PointerMemorySize [internal]
1022 */
1023 static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1024 unsigned char *Buffer, PFORMAT_STRING pFormat)
1025 {
1026 unsigned type = pFormat[0], attr = pFormat[1];
1027 PFORMAT_STRING desc;
1028 NDR_MEMORYSIZE m;
1029 DWORD pointer_id = 0;
1030 BOOL pointer_needs_sizing;
1031
1032 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1033 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1034 pFormat += 2;
1035 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1036 else desc = pFormat + *(const SHORT*)pFormat;
1037
1038 switch (type) {
1039 case RPC_FC_RP: /* ref pointer (always non-null) */
1040 pointer_needs_sizing = TRUE;
1041 break;
1042 case RPC_FC_UP: /* unique pointer */
1043 case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
1044 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1045 TRACE("pointer_id is 0x%08x\n", pointer_id);
1046 if (pointer_id)
1047 pointer_needs_sizing = TRUE;
1048 else
1049 pointer_needs_sizing = FALSE;
1050 break;
1051 case RPC_FC_FP:
1052 {
1053 void *pointer;
1054 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1055 TRACE("pointer_id is 0x%08x\n", pointer_id);
1056 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1057 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1058 break;
1059 }
1060 default:
1061 FIXME("unhandled ptr type=%02x\n", type);
1062 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1063 return 0;
1064 }
1065
1066 if (attr & RPC_FC_P_DEREF) {
1067 align_length(&pStubMsg->MemorySize, sizeof(void*));
1068 pStubMsg->MemorySize += sizeof(void*);
1069 TRACE("deref\n");
1070 }
1071
1072 if (pointer_needs_sizing) {
1073 m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
1074 if (m) m(pStubMsg, desc);
1075 else FIXME("no memorysizer for data type=%02x\n", *desc);
1076 }
1077
1078 return pStubMsg->MemorySize;
1079 }
1080
1081 /***********************************************************************
1082 * PointerFree [internal]
1083 */
1084 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1085 unsigned char *Pointer,
1086 PFORMAT_STRING pFormat)
1087 {
1088 unsigned type = pFormat[0], attr = pFormat[1];
1089 PFORMAT_STRING desc;
1090 NDR_FREE m;
1091 unsigned char *current_pointer = Pointer;
1092
1093 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1094 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1095 if (attr & RPC_FC_P_DONTFREE) return;
1096 pFormat += 2;
1097 if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
1098 else desc = pFormat + *(const SHORT*)pFormat;
1099
1100 if (!Pointer) return;
1101
1102 if (type == RPC_FC_FP) {
1103 int pointer_needs_freeing = NdrFullPointerFree(
1104 pStubMsg->FullPtrXlatTables, Pointer);
1105 if (!pointer_needs_freeing)
1106 return;
1107 }
1108
1109 if (attr & RPC_FC_P_DEREF) {
1110 current_pointer = *(unsigned char**)Pointer;
1111 TRACE("deref => %p\n", current_pointer);
1112 }
1113
1114 m = NdrFreer[*desc & NDR_TABLE_MASK];
1115 if (m) m(pStubMsg, current_pointer, desc);
1116
1117 /* this check stops us from trying to free buffer memory. we don't have to
1118 * worry about clients, since they won't call this function.
1119 * we don't have to check for the buffer being reallocated because
1120 * BufferStart and BufferEnd won't be reset when allocating memory for
1121 * sending the response. we don't have to check for the new buffer here as
1122 * it won't be used a type memory, only for buffer memory */
1123 if (Pointer >= pStubMsg->BufferStart && Pointer <= pStubMsg->BufferEnd)
1124 goto notfree;
1125
1126 if (attr & RPC_FC_P_ONSTACK) {
1127 TRACE("not freeing stack ptr %p\n", Pointer);
1128 return;
1129 }
1130 TRACE("freeing %p\n", Pointer);
1131 NdrFree(pStubMsg, Pointer);
1132 return;
1133 notfree:
1134 TRACE("not freeing %p\n", Pointer);
1135 }
1136
1137 /***********************************************************************
1138 * EmbeddedPointerMarshall
1139 */
1140 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1141 unsigned char *pMemory,
1142 PFORMAT_STRING pFormat)
1143 {
1144 unsigned char *Mark = pStubMsg->BufferMark;
1145 unsigned rep, count, stride;
1146 unsigned i;
1147 unsigned char *saved_buffer = NULL;
1148
1149 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1150
1151 if (*pFormat != RPC_FC_PP) return NULL;
1152 pFormat += 2;
1153
1154 if (pStubMsg->PointerBufferMark)
1155 {
1156 saved_buffer = pStubMsg->Buffer;
1157 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1158 pStubMsg->PointerBufferMark = NULL;
1159 }
1160
1161 while (pFormat[0] != RPC_FC_END) {
1162 switch (pFormat[0]) {
1163 default:
1164 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1165 /* fallthrough */
1166 case RPC_FC_NO_REPEAT:
1167 rep = 1;
1168 stride = 0;
1169 count = 1;
1170 pFormat += 2;
1171 break;
1172 case RPC_FC_FIXED_REPEAT:
1173 rep = *(const WORD*)&pFormat[2];
1174 stride = *(const WORD*)&pFormat[4];
1175 count = *(const WORD*)&pFormat[8];
1176 pFormat += 10;
1177 break;
1178 case RPC_FC_VARIABLE_REPEAT:
1179 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1180 stride = *(const WORD*)&pFormat[2];
1181 count = *(const WORD*)&pFormat[6];
1182 pFormat += 8;
1183 break;
1184 }
1185 for (i = 0; i < rep; i++) {
1186 PFORMAT_STRING info = pFormat;
1187 unsigned char *membase = pMemory + (i * stride);
1188 unsigned char *bufbase = Mark + (i * stride);
1189 unsigned u;
1190
1191 for (u=0; u<count; u++,info+=8) {
1192 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1193 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1194 unsigned char *saved_memory = pStubMsg->Memory;
1195
1196 pStubMsg->Memory = membase;
1197 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1198 pStubMsg->Memory = saved_memory;
1199 }
1200 }
1201 pFormat += 8 * count;
1202 }
1203
1204 if (saved_buffer)
1205 {
1206 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1207 pStubMsg->Buffer = saved_buffer;
1208 }
1209
1210 STD_OVERFLOW_CHECK(pStubMsg);
1211
1212 return NULL;
1213 }
1214
1215 /***********************************************************************
1216 * EmbeddedPointerUnmarshall
1217 */
1218 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1219 unsigned char *pDstBuffer,
1220 unsigned char *pSrcMemoryPtrs,
1221 PFORMAT_STRING pFormat,
1222 unsigned char fMustAlloc)
1223 {
1224 unsigned char *Mark = pStubMsg->BufferMark;
1225 unsigned rep, count, stride;
1226 unsigned i;
1227 unsigned char *saved_buffer = NULL;
1228
1229 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1230
1231 if (*pFormat != RPC_FC_PP) return NULL;
1232 pFormat += 2;
1233
1234 if (pStubMsg->PointerBufferMark)
1235 {
1236 saved_buffer = pStubMsg->Buffer;
1237 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1238 pStubMsg->PointerBufferMark = NULL;
1239 }
1240
1241 while (pFormat[0] != RPC_FC_END) {
1242 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1243 switch (pFormat[0]) {
1244 default:
1245 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1246 /* fallthrough */
1247 case RPC_FC_NO_REPEAT:
1248 rep = 1;
1249 stride = 0;
1250 count = 1;
1251 pFormat += 2;
1252 break;
1253 case RPC_FC_FIXED_REPEAT:
1254 rep = *(const WORD*)&pFormat[2];
1255 stride = *(const WORD*)&pFormat[4];
1256 count = *(const WORD*)&pFormat[8];
1257 pFormat += 10;
1258 break;
1259 case RPC_FC_VARIABLE_REPEAT:
1260 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1261 stride = *(const WORD*)&pFormat[2];
1262 count = *(const WORD*)&pFormat[6];
1263 pFormat += 8;
1264 break;
1265 }
1266 for (i = 0; i < rep; i++) {
1267 PFORMAT_STRING info = pFormat;
1268 unsigned char *bufdstbase = pDstBuffer + (i * stride);
1269 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1270 unsigned char *bufbase = Mark + (i * stride);
1271 unsigned u;
1272
1273 for (u=0; u<count; u++,info+=8) {
1274 unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1275 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1276 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1277 PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1278 }
1279 }
1280 pFormat += 8 * count;
1281 }
1282
1283 if (saved_buffer)
1284 {
1285 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1286 pStubMsg->Buffer = saved_buffer;
1287 }
1288
1289 return NULL;
1290 }
1291
1292 /***********************************************************************
1293 * EmbeddedPointerBufferSize
1294 */
1295 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1296 unsigned char *pMemory,
1297 PFORMAT_STRING pFormat)
1298 {
1299 unsigned rep, count, stride;
1300 unsigned i;
1301 ULONG saved_buffer_length = 0;
1302
1303 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1304
1305 if (pStubMsg->IgnoreEmbeddedPointers) return;
1306
1307 if (*pFormat != RPC_FC_PP) return;
1308 pFormat += 2;
1309
1310 if (pStubMsg->PointerLength)
1311 {
1312 saved_buffer_length = pStubMsg->BufferLength;
1313 pStubMsg->BufferLength = pStubMsg->PointerLength;
1314 pStubMsg->PointerLength = 0;
1315 }
1316
1317 while (pFormat[0] != RPC_FC_END) {
1318 switch (pFormat[0]) {
1319 default:
1320 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1321 /* fallthrough */
1322 case RPC_FC_NO_REPEAT:
1323 rep = 1;
1324 stride = 0;
1325 count = 1;
1326 pFormat += 2;
1327 break;
1328 case RPC_FC_FIXED_REPEAT:
1329 rep = *(const WORD*)&pFormat[2];
1330 stride = *(const WORD*)&pFormat[4];
1331 count = *(const WORD*)&pFormat[8];
1332 pFormat += 10;
1333 break;
1334 case RPC_FC_VARIABLE_REPEAT:
1335 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1336 stride = *(const WORD*)&pFormat[2];
1337 count = *(const WORD*)&pFormat[6];
1338 pFormat += 8;
1339 break;
1340 }
1341 for (i = 0; i < rep; i++) {
1342 PFORMAT_STRING info = pFormat;
1343 unsigned char *membase = pMemory + (i * stride);
1344 unsigned u;
1345
1346 for (u=0; u<count; u++,info+=8) {
1347 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1348 unsigned char *saved_memory = pStubMsg->Memory;
1349
1350 pStubMsg->Memory = membase;
1351 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1352 pStubMsg->Memory = saved_memory;
1353 }
1354 }
1355 pFormat += 8 * count;
1356 }
1357
1358 if (saved_buffer_length)
1359 {
1360 pStubMsg->PointerLength = pStubMsg->BufferLength;
1361 pStubMsg->BufferLength = saved_buffer_length;
1362 }
1363 }
1364
1365 /***********************************************************************
1366 * EmbeddedPointerMemorySize [internal]
1367 */
1368 static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1369 PFORMAT_STRING pFormat)
1370 {
1371 unsigned char *Mark = pStubMsg->BufferMark;
1372 unsigned rep, count, stride;
1373 unsigned i;
1374 unsigned char *saved_buffer = NULL;
1375
1376 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1377
1378 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1379
1380 if (pStubMsg->PointerBufferMark)
1381 {
1382 saved_buffer = pStubMsg->Buffer;
1383 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1384 pStubMsg->PointerBufferMark = NULL;
1385 }
1386
1387 if (*pFormat != RPC_FC_PP) return 0;
1388 pFormat += 2;
1389
1390 while (pFormat[0] != RPC_FC_END) {
1391 switch (pFormat[0]) {
1392 default:
1393 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1394 /* fallthrough */
1395 case RPC_FC_NO_REPEAT:
1396 rep = 1;
1397 stride = 0;
1398 count = 1;
1399 pFormat += 2;
1400 break;
1401 case RPC_FC_FIXED_REPEAT:
1402 rep = *(const WORD*)&pFormat[2];
1403 stride = *(const WORD*)&pFormat[4];
1404 count = *(const WORD*)&pFormat[8];
1405 pFormat += 10;
1406 break;
1407 case RPC_FC_VARIABLE_REPEAT:
1408 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1409 stride = *(const WORD*)&pFormat[2];
1410 count = *(const WORD*)&pFormat[6];
1411 pFormat += 8;
1412 break;
1413 }
1414 for (i = 0; i < rep; i++) {
1415 PFORMAT_STRING info = pFormat;
1416 unsigned char *bufbase = Mark + (i * stride);
1417 unsigned u;
1418 for (u=0; u<count; u++,info+=8) {
1419 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1420 PointerMemorySize(pStubMsg, bufptr, info+4);
1421 }
1422 }
1423 pFormat += 8 * count;
1424 }
1425
1426 if (saved_buffer)
1427 {
1428 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1429 pStubMsg->Buffer = saved_buffer;
1430 }
1431
1432 return 0;
1433 }
1434
1435 /***********************************************************************
1436 * EmbeddedPointerFree [internal]
1437 */
1438 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1439 unsigned char *pMemory,
1440 PFORMAT_STRING pFormat)
1441 {
1442 unsigned rep, count, stride;
1443 unsigned i;
1444
1445 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1446 if (*pFormat != RPC_FC_PP) return;
1447 pFormat += 2;
1448
1449 while (pFormat[0] != RPC_FC_END) {
1450 switch (pFormat[0]) {
1451 default:
1452 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1453 /* fallthrough */
1454 case RPC_FC_NO_REPEAT:
1455 rep = 1;
1456 stride = 0;
1457 count = 1;
1458 pFormat += 2;
1459 break;
1460 case RPC_FC_FIXED_REPEAT:
1461 rep = *(const WORD*)&pFormat[2];
1462 stride = *(const WORD*)&pFormat[4];
1463 count = *(const WORD*)&pFormat[8];
1464 pFormat += 10;
1465 break;
1466 case RPC_FC_VARIABLE_REPEAT:
1467 rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1468 stride = *(const WORD*)&pFormat[2];
1469 count = *(const WORD*)&pFormat[6];
1470 pFormat += 8;
1471 break;
1472 }
1473 for (i = 0; i < rep; i++) {
1474 PFORMAT_STRING info = pFormat;
1475 unsigned char *membase = pMemory + (i * stride);
1476 unsigned u;
1477
1478 for (u=0; u<count; u++,info+=8) {
1479 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1480 unsigned char *saved_memory = pStubMsg->Memory;
1481
1482 pStubMsg->Memory = pMemory;
1483 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1484 pStubMsg->Memory = saved_memory;
1485 }
1486 }
1487 pFormat += 8 * count;
1488 }
1489 }
1490
1491 /***********************************************************************
1492 * NdrPointerMarshall [RPCRT4.@]
1493 */
1494 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1495 unsigned char *pMemory,
1496 PFORMAT_STRING pFormat)
1497 {
1498 unsigned char *Buffer;
1499
1500 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1501
1502 /* Increment the buffer here instead of in PointerMarshall,
1503 * as that is used by embedded pointers which already handle the incrementing
1504 * the buffer, and shouldn't write any additional pointer data to the wire */
1505 if (*pFormat != RPC_FC_RP)
1506 {
1507 align_pointer_clear(&pStubMsg->Buffer, 4);
1508 Buffer = pStubMsg->Buffer;
1509 safe_buffer_increment(pStubMsg, 4);
1510 }
1511 else
1512 Buffer = pStubMsg->Buffer;
1513
1514 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1515
1516 return NULL;
1517 }
1518
1519 /***********************************************************************
1520 * NdrPointerUnmarshall [RPCRT4.@]
1521 */
1522 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1523 unsigned char **ppMemory,
1524 PFORMAT_STRING pFormat,
1525 unsigned char fMustAlloc)
1526 {
1527 unsigned char *Buffer;
1528
1529 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1530
1531 if (*pFormat == RPC_FC_RP)
1532 {
1533 Buffer = pStubMsg->Buffer;
1534 /* Do the NULL ref pointer check here because embedded pointers can be
1535 * NULL if the type the pointer is embedded in was allocated rather than
1536 * being passed in by the client */
1537 if (pStubMsg->IsClient && !*ppMemory)
1538 {
1539 ERR("NULL ref pointer is not allowed\n");
1540 RpcRaiseException(RPC_X_NULL_REF_POINTER);
1541 }
1542 }
1543 else
1544 {
1545 /* Increment the buffer here instead of in PointerUnmarshall,
1546 * as that is used by embedded pointers which already handle the incrementing
1547 * the buffer, and shouldn't read any additional pointer data from the
1548 * buffer */
1549 align_pointer(&pStubMsg->Buffer, 4);
1550 Buffer = pStubMsg->Buffer;
1551 safe_buffer_increment(pStubMsg, 4);
1552 }
1553
1554 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1555
1556 return NULL;
1557 }
1558
1559 /***********************************************************************
1560 * NdrPointerBufferSize [RPCRT4.@]
1561 */
1562 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1563 unsigned char *pMemory,
1564 PFORMAT_STRING pFormat)
1565 {
1566 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1567
1568 /* Increment the buffer length here instead of in PointerBufferSize,
1569 * as that is used by embedded pointers which already handle the buffer
1570 * length, and shouldn't write anything more to the wire */
1571 if (*pFormat != RPC_FC_RP)
1572 {
1573 align_length(&pStubMsg->BufferLength, 4);
1574 safe_buffer_length_increment(pStubMsg, 4);
1575 }
1576
1577 PointerBufferSize(pStubMsg, pMemory, pFormat);
1578 }
1579
1580 /***********************************************************************
1581 * NdrPointerMemorySize [RPCRT4.@]
1582 */
1583 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1584 PFORMAT_STRING pFormat)
1585 {
1586 unsigned char *Buffer = pStubMsg->Buffer;
1587 if (*pFormat != RPC_FC_RP)
1588 {
1589 align_pointer(&pStubMsg->Buffer, 4);
1590 safe_buffer_increment(pStubMsg, 4);
1591 }
1592 align_length(&pStubMsg->MemorySize, sizeof(void *));
1593 return PointerMemorySize(pStubMsg, Buffer, pFormat);
1594 }
1595
1596 /***********************************************************************
1597 * NdrPointerFree [RPCRT4.@]
1598 */
1599 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1600 unsigned char *pMemory,
1601 PFORMAT_STRING pFormat)
1602 {
1603 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1604 PointerFree(pStubMsg, pMemory, pFormat);
1605 }
1606
1607 /***********************************************************************
1608 * NdrSimpleTypeMarshall [RPCRT4.@]
1609 */
1610 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1611 unsigned char FormatChar )
1612 {
1613 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1614 }
1615
1616 /***********************************************************************
1617 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1618 *
1619 * Unmarshall a base type.
1620 *
1621 * NOTES
1622 * Doesn't check that the buffer is long enough before copying, so the caller
1623 * should do this.
1624 */
1625 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1626 unsigned char FormatChar )
1627 {
1628 #define BASE_TYPE_UNMARSHALL(type) \
1629 align_pointer(&pStubMsg->Buffer, sizeof(type)); \
1630 TRACE("pMemory: %p\n", pMemory); \
1631 *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1632 pStubMsg->Buffer += sizeof(type);
1633
1634 switch(FormatChar)
1635 {
1636 case RPC_FC_BYTE:
1637 case RPC_FC_CHAR:
1638 case RPC_FC_SMALL:
1639 case RPC_FC_USMALL:
1640 BASE_TYPE_UNMARSHALL(UCHAR);
1641 TRACE("value: 0x%02x\n", *pMemory);
1642 break;
1643 case RPC_FC_WCHAR:
1644 case RPC_FC_SHORT:
1645 case RPC_FC_USHORT:
1646 BASE_TYPE_UNMARSHALL(USHORT);
1647 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1648 break;
1649 case RPC_FC_LONG:
1650 case RPC_FC_ULONG:
1651 case RPC_FC_ERROR_STATUS_T:
1652 case RPC_FC_ENUM32:
1653 BASE_TYPE_UNMARSHALL(ULONG);
1654 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1655 break;
1656 case RPC_FC_FLOAT:
1657 BASE_TYPE_UNMARSHALL(float);
1658 TRACE("value: %f\n", *(float *)pMemory);
1659 break;
1660 case RPC_FC_DOUBLE:
1661 BASE_TYPE_UNMARSHALL(double);
1662 TRACE("value: %f\n", *(double *)pMemory);
1663 break;
1664 case RPC_FC_HYPER:
1665 BASE_TYPE_UNMARSHALL(ULONGLONG);
1666 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1667 break;
1668 case RPC_FC_ENUM16:
1669 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
1670 TRACE("pMemory: %p\n", pMemory);
1671 /* 16-bits on the wire, but int in memory */
1672 *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1673 pStubMsg->Buffer += sizeof(USHORT);
1674 TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1675 break;
1676 case RPC_FC_INT3264:
1677 align_pointer(&pStubMsg->Buffer, sizeof(INT));
1678 /* 32-bits on the wire, but int_ptr in memory */
1679 *(INT_PTR *)pMemory = *(INT *)pStubMsg->Buffer;
1680 pStubMsg->Buffer += sizeof(INT);
1681 TRACE("value: 0x%08lx\n", *(INT_PTR *)pMemory);
1682 break;
1683 case RPC_FC_UINT3264:
1684 align_pointer(&pStubMsg->Buffer, sizeof(UINT));
1685 /* 32-bits on the wire, but int_ptr in memory */
1686 *(UINT_PTR *)pMemory = *(UINT *)pStubMsg->Buffer;
1687 pStubMsg->Buffer += sizeof(UINT);
1688 TRACE("value: 0x%08lx\n", *(UINT_PTR *)pMemory);
1689 break;
1690 case RPC_FC_IGNORE:
1691 break;
1692 default:
1693 FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1694 }
1695 #undef BASE_TYPE_UNMARSHALL
1696 }
1697
1698 /***********************************************************************
1699 * NdrSimpleStructMarshall [RPCRT4.@]
1700 */
1701 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1702 unsigned char *pMemory,
1703 PFORMAT_STRING pFormat)
1704 {
1705 unsigned size = *(const WORD*)(pFormat+2);
1706 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1707
1708 align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
1709
1710 pStubMsg->BufferMark = pStubMsg->Buffer;
1711 safe_copy_to_buffer(pStubMsg, pMemory, size);
1712
1713 if (pFormat[0] != RPC_FC_STRUCT)
1714 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1715
1716 return NULL;
1717 }
1718
1719 /***********************************************************************
1720 * NdrSimpleStructUnmarshall [RPCRT4.@]
1721 */
1722 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1723 unsigned char **ppMemory,
1724 PFORMAT_STRING pFormat,
1725 unsigned char fMustAlloc)
1726 {
1727 unsigned size = *(const WORD*)(pFormat+2);
1728 unsigned char *saved_buffer;
1729 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1730
1731 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1732
1733 if (fMustAlloc)
1734 *ppMemory = NdrAllocate(pStubMsg, size);
1735 else
1736 {
1737 if (!pStubMsg->IsClient && !*ppMemory)
1738 /* for servers, we just point straight into the RPC buffer */
1739 *ppMemory = pStubMsg->Buffer;
1740 }
1741
1742 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1743 safe_buffer_increment(pStubMsg, size);
1744 if (pFormat[0] == RPC_FC_PSTRUCT)
1745 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1746
1747 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1748 if (*ppMemory != saved_buffer)
1749 memcpy(*ppMemory, saved_buffer, size);
1750
1751 return NULL;
1752 }
1753
1754 /***********************************************************************
1755 * NdrSimpleStructBufferSize [RPCRT4.@]
1756 */
1757 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1758 unsigned char *pMemory,
1759 PFORMAT_STRING pFormat)
1760 {
1761 unsigned size = *(const WORD*)(pFormat+2);
1762 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1763
1764 align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
1765
1766 safe_buffer_length_increment(pStubMsg, size);
1767 if (pFormat[0] != RPC_FC_STRUCT)
1768 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1769 }
1770
1771 /***********************************************************************
1772 * NdrSimpleStructMemorySize [RPCRT4.@]
1773 */
1774 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1775 PFORMAT_STRING pFormat)
1776 {
1777 unsigned short size = *(const WORD *)(pFormat+2);
1778
1779 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1780
1781 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1782 pStubMsg->MemorySize += size;
1783 safe_buffer_increment(pStubMsg, size);
1784
1785 if (pFormat[0] != RPC_FC_STRUCT)
1786 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1787 return pStubMsg->MemorySize;
1788 }
1789
1790 /***********************************************************************
1791 * NdrSimpleStructFree [RPCRT4.@]
1792 */
1793 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1794 unsigned char *pMemory,
1795 PFORMAT_STRING pFormat)
1796 {
1797 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1798 if (pFormat[0] != RPC_FC_STRUCT)
1799 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1800 }
1801
1802 /* Array helpers */
1803
1804 static inline void array_compute_and_size_conformance(
1805 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1806 PFORMAT_STRING pFormat)
1807 {
1808 DWORD count;
1809
1810 switch (fc)
1811 {
1812 case RPC_FC_CARRAY:
1813 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1814 SizeConformance(pStubMsg);
1815 break;
1816 case RPC_FC_CVARRAY:
1817 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1818 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1819 SizeConformance(pStubMsg);
1820 break;
1821 case RPC_FC_C_CSTRING:
1822 case RPC_FC_C_WSTRING:
1823 if (fc == RPC_FC_C_CSTRING)
1824 {
1825 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1826 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1827 }
1828 else
1829 {
1830 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1831 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1832 }
1833
1834 if (pFormat[1] == RPC_FC_STRING_SIZED)
1835 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1836 else
1837 pStubMsg->MaxCount = pStubMsg->ActualCount;
1838
1839 SizeConformance(pStubMsg);
1840 break;
1841 case RPC_FC_BOGUS_ARRAY:
1842 count = *(const WORD *)(pFormat + 2);
1843 pFormat += 4;
1844 if (IsConformanceOrVariancePresent(pFormat)) SizeConformance(pStubMsg);
1845 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, count);
1846 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
1847 break;
1848 default:
1849 ERR("unknown array format 0x%x\n", fc);
1850 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1851 }
1852 }
1853
1854 static inline void array_buffer_size(
1855 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1856 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1857 {
1858 DWORD i, size;
1859 DWORD esize;
1860 unsigned char alignment;
1861
1862 switch (fc)
1863 {
1864 case RPC_FC_CARRAY:
1865 esize = *(const WORD*)(pFormat+2);
1866 alignment = pFormat[1] + 1;
1867
1868 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1869
1870 align_length(&pStubMsg->BufferLength, alignment);
1871
1872 size = safe_multiply(esize, pStubMsg->MaxCount);
1873 /* conformance value plus array */
1874 safe_buffer_length_increment(pStubMsg, size);
1875
1876 if (fHasPointers)
1877 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1878 break;
1879 case RPC_FC_CVARRAY:
1880 esize = *(const WORD*)(pFormat+2);
1881 alignment = pFormat[1] + 1;
1882
1883 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1884 pFormat = SkipVariance(pStubMsg, pFormat);
1885
1886 SizeVariance(pStubMsg);
1887
1888 align_length(&pStubMsg->BufferLength, alignment);
1889
1890 size = safe_multiply(esize, pStubMsg->ActualCount);
1891 safe_buffer_length_increment(pStubMsg, size);
1892
1893 if (fHasPointers)
1894 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1895 break;
1896 case RPC_FC_C_CSTRING:
1897 case RPC_FC_C_WSTRING:
1898 if (fc == RPC_FC_C_CSTRING)
1899 esize = 1;
1900 else
1901 esize = 2;
1902
1903 SizeVariance(pStubMsg);
1904
1905 size = safe_multiply(esize, pStubMsg->ActualCount);
1906 safe_buffer_length_increment(pStubMsg, size);
1907 break;
1908 case RPC_FC_BOGUS_ARRAY:
1909 alignment = pFormat[1] + 1;
1910 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1911 if (IsConformanceOrVariancePresent(pFormat)) SizeVariance(pStubMsg);
1912 pFormat = SkipVariance(pStubMsg, pFormat);
1913
1914 align_length(&pStubMsg->BufferLength, alignment);
1915
1916 size = pStubMsg->ActualCount;
1917 for (i = 0; i < size; i++)
1918 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
1919 break;
1920 default:
1921 ERR("unknown array format 0x%x\n", fc);
1922 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1923 }
1924 }
1925
1926 static inline void array_compute_and_write_conformance(
1927 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1928 PFORMAT_STRING pFormat)
1929 {
1930 ULONG def;
1931 BOOL conformance_present;
1932
1933 switch (fc)
1934 {
1935 case RPC_FC_CARRAY:
1936 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1937 WriteConformance(pStubMsg);
1938 break;
1939 case RPC_FC_CVARRAY:
1940 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1941 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1942 WriteConformance(pStubMsg);
1943 break;
1944 case RPC_FC_C_CSTRING:
1945 case RPC_FC_C_WSTRING:
1946 if (fc == RPC_FC_C_CSTRING)
1947 {
1948 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1949 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1950 }
1951 else
1952 {
1953 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1954 pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
1955 }
1956 if (pFormat[1] == RPC_FC_STRING_SIZED)
1957 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1958 else
1959 pStubMsg->MaxCount = pStubMsg->ActualCount;
1960 pStubMsg->Offset = 0;
1961 WriteConformance(pStubMsg);
1962 break;
1963 case RPC_FC_BOGUS_ARRAY:
1964 def = *(const WORD *)(pFormat + 2);
1965 pFormat += 4;
1966 conformance_present = IsConformanceOrVariancePresent(pFormat);
1967 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
1968 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
1969 if (conformance_present) WriteConformance(pStubMsg);
1970 break;
1971 default:
1972 ERR("unknown array format 0x%x\n", fc);
1973 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1974 }
1975 }
1976
1977 static inline void array_write_variance_and_marshall(
1978 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1979 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1980 {
1981 DWORD i, size;
1982 DWORD esize;
1983 unsigned char alignment;
1984
1985 switch (fc)
1986 {
1987 case RPC_FC_CARRAY:
1988 esize = *(const WORD*)(pFormat+2);
1989 alignment = pFormat[1] + 1;
1990
1991 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1992
1993 align_pointer_clear(&pStubMsg->Buffer, alignment);
1994
1995 size = safe_multiply(esize, pStubMsg->MaxCount);
1996 if (fHasPointers)
1997 pStubMsg->BufferMark = pStubMsg->Buffer;
1998 safe_copy_to_buffer(pStubMsg, pMemory, size);
1999
2000 if (fHasPointers)
2001 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2002 break;
2003 case RPC_FC_CVARRAY:
2004 esize = *(const WORD*)(pFormat+2);
2005 alignment = pFormat[1] + 1;
2006
2007 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2008 pFormat = SkipVariance(pStubMsg, pFormat);
2009
2010 WriteVariance(pStubMsg);
2011
2012 align_pointer_clear(&pStubMsg->Buffer, alignment);
2013
2014 size = safe_multiply(esize, pStubMsg->ActualCount);
2015
2016 if (fHasPointers)
2017 pStubMsg->BufferMark = pStubMsg->Buffer;
2018 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
2019
2020 if (fHasPointers)
2021 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2022 break;
2023 case RPC_FC_C_CSTRING:
2024 case RPC_FC_C_WSTRING:
2025 if (fc == RPC_FC_C_CSTRING)
2026 esize = 1;
2027 else
2028 esize = 2;
2029
2030 WriteVariance(pStubMsg);
2031
2032 size = safe_multiply(esize, pStubMsg->ActualCount);
2033 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2034 break;
2035 case RPC_FC_BOGUS_ARRAY:
2036 alignment = pFormat[1] + 1;
2037 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2038 if (IsConformanceOrVariancePresent(pFormat)) WriteVariance(pStubMsg);
2039 pFormat = SkipVariance(pStubMsg, pFormat);
2040
2041 align_pointer_clear(&pStubMsg->Buffer, alignment);
2042
2043 size = pStubMsg->ActualCount;
2044 for (i = 0; i < size; i++)
2045 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2046 break;
2047 default:
2048 ERR("unknown array format 0x%x\n", fc);
2049 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2050 }
2051 }
2052
2053 static inline ULONG array_read_conformance(
2054 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
2055 {
2056 DWORD def, esize;
2057
2058 switch (fc)
2059 {
2060 case RPC_FC_CARRAY:
2061 esize = *(const WORD*)(pFormat+2);
2062 pFormat = ReadConformance(pStubMsg, pFormat+4);
2063 return safe_multiply(esize, pStubMsg->MaxCount);
2064 case RPC_FC_CVARRAY:
2065 esize = *(const WORD*)(pFormat+2);
2066 pFormat = ReadConformance(pStubMsg, pFormat+4);
2067 return safe_multiply(esize, pStubMsg->MaxCount);
2068 case RPC_FC_C_CSTRING:
2069 case RPC_FC_C_WSTRING:
2070 if (fc == RPC_FC_C_CSTRING)
2071 esize = 1;
2072 else
2073 esize = 2;
2074
2075 if (pFormat[1] == RPC_FC_STRING_SIZED)
2076 ReadConformance(pStubMsg, pFormat + 2);
2077 else
2078 ReadConformance(pStubMsg, NULL);
2079 return safe_multiply(esize, pStubMsg->MaxCount);
2080 case RPC_FC_BOGUS_ARRAY:
2081 def = *(const WORD *)(pFormat + 2);
2082 pFormat += 4;
2083 if (IsConformanceOrVariancePresent(pFormat)) pFormat = ReadConformance(pStubMsg, pFormat);
2084 else
2085 {
2086 pStubMsg->MaxCount = def;
2087 pFormat = SkipConformance( pStubMsg, pFormat );
2088 }
2089 pFormat = SkipVariance( pStubMsg, pFormat );
2090
2091 esize = ComplexStructSize(pStubMsg, pFormat);
2092 return safe_multiply(pStubMsg->MaxCount, esize);
2093 default:
2094 ERR("unknown array format 0x%x\n", fc);
2095 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2096 }
2097 }
2098
2099 static inline ULONG array_read_variance_and_unmarshall(
2100 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
2101 PFORMAT_STRING pFormat, unsigned char fMustAlloc,
2102 unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
2103 {
2104 ULONG bufsize, memsize;
2105 WORD esize;
2106 unsigned char alignment;
2107 unsigned char *saved_buffer, *pMemory;
2108 ULONG i, offset, count;
2109
2110 switch (fc)
2111 {
2112 case RPC_FC_CARRAY:
2113 esize = *(const WORD*)(pFormat+2);
2114 alignment = pFormat[1] + 1;
2115
2116 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2117
2118 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2119
2120 align_pointer(&pStubMsg->Buffer, alignment);
2121
2122 if (fUnmarshall)
2123 {
2124 if (fMustAlloc)
2125 *ppMemory = NdrAllocate(pStubMsg, memsize);
2126 else
2127 {
2128 if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2129 /* for servers, we just point straight into the RPC buffer */
2130 *ppMemory = pStubMsg->Buffer;
2131 }
2132
2133 saved_buffer = pStubMsg->Buffer;
2134 safe_buffer_increment(pStubMsg, bufsize);
2135
2136 pStubMsg->BufferMark = saved_buffer;
2137 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2138
2139 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2140 if (*ppMemory != saved_buffer)
2141 memcpy(*ppMemory, saved_buffer, bufsize);
2142 }
2143 return bufsize;
2144 case RPC_FC_CVARRAY:
2145 esize = *(const WORD*)(pFormat+2);
2146 alignment = pFormat[1] + 1;
2147
2148 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2149
2150 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2151
2152 align_pointer(&pStubMsg->Buffer, alignment);
2153
2154 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2155 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2156
2157 if (fUnmarshall)
2158 {
2159 offset = pStubMsg->Offset;
2160
2161 if (!fMustAlloc && !*ppMemory)
2162 fMustAlloc = TRUE;
2163 if (fMustAlloc)
2164 *ppMemory = NdrAllocate(pStubMsg, memsize);
2165 saved_buffer = pStubMsg->Buffer;
2166 safe_buffer_increment(pStubMsg, bufsize);
2167
2168 pStubMsg->BufferMark = saved_buffer;
2169 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2170 fMustAlloc);
2171
2172 memcpy(*ppMemory + offset, saved_buffer, bufsize);
2173 }
2174 return bufsize;
2175 case RPC_FC_C_CSTRING:
2176 case RPC_FC_C_WSTRING:
2177 if (fc == RPC_FC_C_CSTRING)
2178 esize = 1;
2179 else
2180 esize = 2;
2181
2182 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2183
2184 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2185 {
2186 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2187 pStubMsg->ActualCount, pStubMsg->MaxCount);
2188 RpcRaiseException(RPC_S_INVALID_BOUND);
2189 }
2190 if (pStubMsg->Offset)
2191 {
2192 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2193 RpcRaiseException(RPC_S_INVALID_BOUND);
2194 }
2195
2196 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2197 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2198
2199 validate_string_data(pStubMsg, bufsize, esize);
2200
2201 if (fUnmarshall)
2202 {
2203 if (fMustAlloc)
2204 *ppMemory = NdrAllocate(pStubMsg, memsize);
2205 else
2206 {
2207 if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2208 !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2209 /* if the data in the RPC buffer is big enough, we just point
2210 * straight into it */
2211 *ppMemory = pStubMsg->Buffer;
2212 else if (!*ppMemory)
2213 *ppMemory = NdrAllocate(pStubMsg, memsize);
2214 }
2215
2216 if (*ppMemory == pStubMsg->Buffer)
2217 safe_buffer_increment(pStubMsg, bufsize);
2218 else
2219 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2220
2221 if (*pFormat == RPC_FC_C_CSTRING)
2222 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2223 else
2224 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2225 }
2226 return bufsize;
2227
2228 case RPC_FC_BOGUS_ARRAY:
2229 alignment = pFormat[1] + 1;
2230 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2231 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2232
2233 esize = ComplexStructSize(pStubMsg, pFormat);
2234 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2235
2236 assert( fUnmarshall );
2237
2238 if (!fMustAlloc && !*ppMemory)
2239 fMustAlloc = TRUE;
2240 if (fMustAlloc)
2241 *ppMemory = NdrAllocate(pStubMsg, memsize);
2242
2243 align_pointer(&pStubMsg->Buffer, alignment);
2244 saved_buffer = pStubMsg->Buffer;
2245
2246 pMemory = *ppMemory;
2247 count = pStubMsg->ActualCount;
2248 for (i = 0; i < count; i++)
2249 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
2250 return pStubMsg->Buffer - saved_buffer;
2251
2252 default:
2253 ERR("unknown array format 0x%x\n", fc);
2254 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2255 }
2256 }
2257
2258 static inline void array_memory_size(
2259 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2260 unsigned char fHasPointers)
2261 {
2262 ULONG i, count, SavedMemorySize;
2263 ULONG bufsize, memsize;
2264 DWORD esize;
2265 unsigned char alignment;
2266
2267 switch (fc)
2268 {
2269 case RPC_FC_CARRAY:
2270 esize = *(const WORD*)(pFormat+2);
2271 alignment = pFormat[1] + 1;
2272
2273 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2274
2275 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2276 pStubMsg->MemorySize += memsize;
2277
2278 align_pointer(&pStubMsg->Buffer, alignment);
2279 if (fHasPointers)
2280 pStubMsg->BufferMark = pStubMsg->Buffer;
2281 safe_buffer_increment(pStubMsg, bufsize);
2282
2283 if (fHasPointers)
2284 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2285 break;
2286 case RPC_FC_CVARRAY:
2287 esize = *(const WORD*)(pFormat+2);
2288 alignment = pFormat[1] + 1;
2289
2290 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2291
2292 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2293
2294 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2295 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2296 pStubMsg->MemorySize += memsize;
2297
2298 align_pointer(&pStubMsg->Buffer, alignment);
2299 if (fHasPointers)
2300 pStubMsg->BufferMark = pStubMsg->Buffer;
2301 safe_buffer_increment(pStubMsg, bufsize);
2302
2303 if (fHasPointers)
2304 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2305 break;
2306 case RPC_FC_C_CSTRING:
2307 case RPC_FC_C_WSTRING:
2308 if (fc == RPC_FC_C_CSTRING)
2309 esize = 1;
2310 else
2311 esize = 2;
2312
2313 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2314
2315 if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2316 {
2317 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2318 pStubMsg->ActualCount, pStubMsg->MaxCount);
2319 RpcRaiseException(RPC_S_INVALID_BOUND);
2320 }
2321 if (pStubMsg->Offset)
2322 {
2323 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2324 RpcRaiseException(RPC_S_INVALID_BOUND);
2325 }
2326
2327 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2328 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2329
2330 validate_string_data(pStubMsg, bufsize, esize);
2331
2332 safe_buffer_increment(pStubMsg, bufsize);
2333 pStubMsg->MemorySize += memsize;
2334 break;
2335 case RPC_FC_BOGUS_ARRAY:
2336 alignment = pFormat[1] + 1;
2337 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2338 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2339
2340 align_pointer(&pStubMsg->Buffer, alignment);
2341
2342 SavedMemorySize = pStubMsg->MemorySize;
2343
2344 esize = ComplexStructSize(pStubMsg, pFormat);
2345 memsize = safe_multiply(pStubMsg->MaxCount, esize);
2346
2347 count = pStubMsg->ActualCount;
2348 for (i = 0; i < count; i++)
2349 ComplexStructMemorySize(pStubMsg, pFormat, NULL);
2350
2351 pStubMsg->MemorySize = SavedMemorySize + memsize;
2352 break;
2353 default:
2354 ERR("unknown array format 0x%x\n", fc);
2355 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2356 }
2357 }
2358
2359 static inline void array_free(
2360 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2361 unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2362 {
2363 DWORD i, count;
2364
2365 switch (fc)
2366 {
2367 case RPC_FC_CARRAY:
2368 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2369 if (fHasPointers)
2370 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2371 break;
2372 case RPC_FC_CVARRAY:
2373 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2374 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2375 if (fHasPointers)
2376 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2377 break;
2378 case RPC_FC_C_CSTRING:
2379 case RPC_FC_C_WSTRING:
2380 /* No embedded pointers so nothing to do */
2381 break;
2382 case RPC_FC_BOGUS_ARRAY:
2383 count = *(const WORD *)(pFormat + 2);
2384 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, count);
2385 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2386
2387 count = pStubMsg->ActualCount;
2388 for (i = 0; i < count; i++)
2389 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2390 break;
2391 default:
2392 ERR("unknown array format 0x%x\n", fc);
2393 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2394 }
2395 }
2396
2397 /*
2398 * NdrConformantString:
2399 *
2400 * What MS calls a ConformantString is, in DCE terminology,
2401 * a Varying-Conformant String.
2402 * [
2403 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2404 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
2405 * into unmarshalled string)
2406 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2407 * [
2408 * data: CHARTYPE[maxlen]
2409 * ]
2410 * ], where CHARTYPE is the appropriate character type (specified externally)
2411 *
2412 */
2413
2414 /***********************************************************************
2415 * NdrConformantStringMarshall [RPCRT4.@]
2416 */
2417 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
2418 unsigned char *pszMessage, PFORMAT_STRING pFormat)
2419 {
2420 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2421
2422 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2423 ERR("Unhandled string type: %#x\n", pFormat[0]);
2424 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2425 }
2426
2427 /* allow compiler to optimise inline function by passing constant into
2428 * these functions */
2429 if (pFormat[0] == RPC_FC_C_CSTRING) {
2430 array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2431 pFormat);
2432 array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
2433 pFormat, TRUE /* fHasPointers */);
2434 } else {
2435 array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2436 pFormat);
2437 array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
2438 pFormat, TRUE /* fHasPointers */);
2439 }
2440
2441 return NULL;
2442 }
2443
2444 /***********************************************************************
2445 * NdrConformantStringBufferSize [RPCRT4.@]
2446 */
2447 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2448 unsigned char* pMemory, PFORMAT_STRING pFormat)
2449 {
2450 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2451
2452 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2453 ERR("Unhandled string type: %#x\n", pFormat[0]);
2454 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2455 }
2456
2457 /* allow compiler to optimise inline function by passing constant into
2458 * these functions */
2459 if (pFormat[0] == RPC_FC_C_CSTRING) {
2460 array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory,
2461 pFormat);
2462 array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2463 TRUE /* fHasPointers */);
2464 } else {
2465 array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory,
2466 pFormat);
2467 array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2468 TRUE /* fHasPointers */);
2469 }
2470 }
2471
2472 /************************************************************************
2473 * NdrConformantStringMemorySize [RPCRT4.@]
2474 */
2475 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2476 PFORMAT_STRING pFormat )
2477 {
2478 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2479
2480 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2481 ERR("Unhandled string type: %#x\n", pFormat[0]);
2482 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2483 }
2484
2485 /* allow compiler to optimise inline function by passing constant into
2486 * these functions */
2487 if (pFormat[0] == RPC_FC_C_CSTRING) {
2488 array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2489 array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat,
2490 TRUE /* fHasPointers */);
2491 } else {
2492 array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2493 array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat,
2494 TRUE /* fHasPointers */);
2495 }
2496
2497 return pStubMsg->MemorySize;
2498 }
2499
2500 /************************************************************************
2501 * NdrConformantStringUnmarshall [RPCRT4.@]
2502 */
2503 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2504 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2505 {
2506 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2507 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2508
2509 if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
2510 ERR("Unhandled string type: %#x\n", *pFormat);
2511 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2512 }
2513
2514 /* allow compiler to optimise inline function by passing constant into
2515 * these functions */
2516 if (pFormat[0] == RPC_FC_C_CSTRING) {
2517 array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
2518 array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory,
2519 pFormat, fMustAlloc,
2520 TRUE /* fUseBufferMemoryServer */,
2521 TRUE /* fUnmarshall */);
2522 } else {
2523 array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
2524 array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory,
2525 pFormat, fMustAlloc,
2526 TRUE /* fUseBufferMemoryServer */,
2527 TRUE /* fUnmarshall */);
2528 }
2529
2530 return NULL;
2531 }
2532
2533 /***********************************************************************
2534 * NdrNonConformantStringMarshall [RPCRT4.@]
2535 */
2536 unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2537 unsigned char *pMemory,
2538 PFORMAT_STRING pFormat)
2539 {
2540 ULONG esize, size, maxsize;
2541
2542 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2543
2544 maxsize = *(const USHORT *)&pFormat[2];
2545
2546 if (*pFormat == RPC_FC_CSTRING)
2547 {
2548 ULONG i = 0;
2549 const char *str = (const char *)pMemory;
2550 while (i < maxsize && str[i]) i++;
2551 TRACE("string=%s\n", debugstr_an(str, i));
2552 pStubMsg->ActualCount = i + 1;
2553 esize = 1;
2554 }
2555 else if (*pFormat == RPC_FC_WSTRING)
2556 {
2557 ULONG i = 0;
2558 const WCHAR *str = (const WCHAR *)pMemory;
2559 while (i < maxsize && str[i]) i++;
2560 TRACE("string=%s\n", debugstr_wn(str, i));
2561 pStubMsg->ActualCount = i + 1;
2562 esize = 2;
2563 }
2564 else
2565 {
2566 ERR("Unhandled string type: %#x\n", *pFormat);
2567 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2568 }
2569
2570 pStubMsg->Offset = 0;
2571 WriteVariance(pStubMsg);
2572
2573 size = safe_multiply(esize, pStubMsg->ActualCount);
2574 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2575
2576 return NULL;
2577 }
2578
2579 /***********************************************************************
2580 * NdrNonConformantStringUnmarshall [RPCRT4.@]
2581 */
2582 unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2583 unsigned char **ppMemory,
2584 PFORMAT_STRING pFormat,
2585 unsigned char fMustAlloc)
2586 {
2587 ULONG bufsize, memsize, esize, maxsize;
2588
2589 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2590 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2591
2592 maxsize = *(const USHORT *)&pFormat[2];
2593
2594 ReadVariance(pStubMsg, NULL, maxsize);
2595 if (pStubMsg->Offset)
2596 {
2597 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2598 RpcRaiseException(RPC_S_INVALID_BOUND);
2599 }
2600
2601 if (*pFormat == RPC_FC_CSTRING) esize = 1;
2602 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2603 else
2604 {
2605 ERR("Unhandled string type: %#x\n", *pFormat);
2606 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2607 }
2608
2609 memsize = esize * maxsize;
2610 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2611
2612 validate_string_data(pStubMsg, bufsize, esize);
2613
2614 if (!fMustAlloc && !*ppMemory)
2615 fMustAlloc = TRUE;
2616 if (fMustAlloc)
2617 *ppMemory = NdrAllocate(pStubMsg, memsize);
2618
2619 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2620
2621 if (*pFormat == RPC_FC_CSTRING) {
2622 TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2623 }
2624 else if (*pFormat == RPC_FC_WSTRING) {
2625 TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2626 }
2627
2628 return NULL;
2629 }
2630
2631 /***********************************************************************
2632 * NdrNonConformantStringBufferSize [RPCRT4.@]
2633 */
2634 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2635 unsigned char *pMemory,
2636 PFORMAT_STRING pFormat)
2637 {
2638 ULONG esize, maxsize;
2639
2640 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2641
2642 maxsize = *(const USHORT *)&pFormat[2];
2643
2644 SizeVariance(pStubMsg);
2645
2646 if (*pFormat == RPC_FC_CSTRING)
2647 {
2648 ULONG i = 0;
2649 const char *str = (const char *)pMemory;
2650 while (i < maxsize && str[i]) i++;
2651 TRACE("string=%s\n", debugstr_an(str, i));
2652 pStubMsg->ActualCount = i + 1;
2653 esize = 1;
2654 }
2655 else if (*pFormat == RPC_FC_WSTRING)
2656 {
2657 ULONG i = 0;
2658 const WCHAR *str = (const WCHAR *)pMemory;
2659 while (i < maxsize && str[i]) i++;
2660 TRACE("string=%s\n", debugstr_wn(str, i));
2661 pStubMsg->ActualCount = i + 1;
2662 esize = 2;
2663 }
2664 else
2665 {
2666 ERR("Unhandled string type: %#x\n", *pFormat);
2667 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2668 }
2669
2670 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2671 }
2672
2673 /***********************************************************************
2674 * NdrNonConformantStringMemorySize [RPCRT4.@]
2675 */
2676 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2677 PFORMAT_STRING pFormat)
2678 {
2679 ULONG bufsize, memsize, esize, maxsize;
2680
2681 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2682
2683 maxsize = *(const USHORT *)&pFormat[2];
2684
2685 ReadVariance(pStubMsg, NULL, maxsize);
2686
2687 if (pStubMsg->Offset)
2688 {
2689 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2690 RpcRaiseException(RPC_S_INVALID_BOUND);
2691 }
2692
2693 if (*pFormat == RPC_FC_CSTRING) esize = 1;
2694 else if (*pFormat == RPC_FC_WSTRING) esize = 2;
2695 else
2696 {
2697 ERR("Unhandled string type: %#x\n", *pFormat);
2698 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2699 }
2700
2701 memsize = esize * maxsize;
2702 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2703
2704 validate_string_data(pStubMsg, bufsize, esize);
2705
2706 safe_buffer_increment(pStubMsg, bufsize);
2707 pStubMsg->MemorySize += memsize;
2708
2709 return pStubMsg->MemorySize;
2710 }
2711
2712 /* Complex types */
2713
2714 #include "pshpack1.h"
2715 typedef struct
2716 {
2717 unsigned char type;
2718 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2719 ULONG low_value;
2720 ULONG high_value;
2721 } NDR_RANGE;
2722 #include "poppack.h"
2723
2724 static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2725 PFORMAT_STRING pFormat)
2726 {
2727 switch (*pFormat) {
2728 case RPC_FC_STRUCT:
2729 case RPC_FC_PSTRUCT:
2730 case RPC_FC_CSTRUCT:
2731 case RPC_FC_BOGUS_STRUCT:
2732 case RPC_FC_SMFARRAY:
2733 case RPC_FC_SMVARRAY:
2734 case RPC_FC_CSTRING:
2735 return *(const WORD*)&pFormat[2];
2736 case RPC_FC_USER_MARSHAL:
2737 return *(const WORD*)&pFormat[4];
2738 case RPC_FC_RANGE: {
2739 switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2740 case RPC_FC_BYTE:
2741 case RPC_FC_CHAR:
2742 case RPC_FC_SMALL:
2743 case RPC_FC_USMALL:
2744 return sizeof(UCHAR);
2745 case RPC_FC_WCHAR:
2746 case RPC_FC_SHORT:
2747 case RPC_FC_USHORT:
2748 return sizeof(USHORT);
2749 case RPC_FC_LONG:
2750 case RPC_FC_ULONG:
2751 case RPC_FC_ENUM32:
2752 case RPC_FC_INT3264:
2753 case RPC_FC_UINT3264:
2754 return sizeof(ULONG);
2755 case RPC_FC_FLOAT:
2756 return sizeof(float);
2757 case RPC_FC_DOUBLE:
2758 return sizeof(double);
2759 case RPC_FC_HYPER:
2760 return sizeof(ULONGLONG);
2761 case RPC_FC_ENUM16:
2762 return sizeof(UINT);
2763 default:
2764 ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2765 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2766 }
2767 }
2768 case RPC_FC_NON_ENCAPSULATED_UNION:
2769 pFormat += 2;
2770 if (pStubMsg->fHasNewCorrDesc)
2771 pFormat += 6;
2772 else
2773 pFormat += 4;
2774
2775 pFormat += *(const SHORT*)pFormat;
2776 return *(const SHORT*)pFormat;
2777 case RPC_FC_IP:
2778 return sizeof(void *);
2779 case RPC_FC_WSTRING:
2780 return *(const WORD*)&pFormat[2] * 2;
2781 default:
2782 FIXME("unhandled embedded type %02x\n", *pFormat);
2783 }
2784 return 0;
2785 }
2786
2787
2788 static ULONG EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2789 PFORMAT_STRING pFormat)
2790 {
2791 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2792
2793 if (!m)
2794 {
2795 FIXME("no memorysizer for data type=%02x\n", *pFormat);
2796 return 0;
2797 }
2798
2799 return m(pStubMsg, pFormat);
2800 }
2801
2802
2803 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2804 unsigned char *pMemory,
2805 PFORMAT_STRING pFormat,
2806 PFORMAT_STRING pPointer)
2807 {
2808 PFORMAT_STRING desc;
2809 NDR_MARSHALL m;
2810 ULONG size;
2811
2812 while (*pFormat != RPC_FC_END) {
2813 switch (*pFormat) {
2814 case RPC_FC_BYTE:
2815 case RPC_FC_CHAR:
2816 case RPC_FC_SMALL:
2817 case RPC_FC_USMALL:
2818 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2819 safe_copy_to_buffer(pStubMsg, pMemory, 1);
2820 pMemory += 1;
2821 break;
2822 case RPC_FC_WCHAR:
2823 case RPC_FC_SHORT:
2824 case RPC_FC_USHORT:
2825 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2826 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2827 pMemory += 2;
2828 break;
2829 case RPC_FC_ENUM16:
2830 {
2831 USHORT val = *(DWORD *)pMemory;
2832 TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2833 if (32767 < *(DWORD*)pMemory)
2834 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2835 safe_copy_to_buffer(pStubMsg, &val, 2);
2836 pMemory += 4;
2837 break;
2838 }
2839 case RPC_FC_LONG:
2840 case RPC_FC_ULONG:
2841 case RPC_FC_ENUM32:
2842 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2843 safe_copy_to_buffer(pStubMsg, pMemory, 4);
2844 pMemory += 4;
2845 break;
2846 case RPC_FC_INT3264:
2847 case RPC_FC_UINT3264:
2848 {
2849 UINT val = *(UINT_PTR *)pMemory;
2850 TRACE("int3264=%ld <= %p\n", *(UINT_PTR *)pMemory, pMemory);
2851 safe_copy_to_buffer(pStubMsg, &val, sizeof(UINT));
2852 pMemory += sizeof(UINT_PTR);
2853 break;
2854 }
2855 case RPC_FC_FLOAT:
2856 TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
2857 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
2858 pMemory += sizeof(float);
2859 break;
2860 case RPC_FC_HYPER:
2861 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2862 safe_copy_to_buffer(pStubMsg, pMemory, 8);
2863 pMemory += 8;
2864 break;
2865 case RPC_FC_DOUBLE:
2866 TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
2867 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
2868 pMemory += sizeof(double);
2869 break;
2870 case RPC_FC_RP:
2871 case RPC_FC_UP:
2872 case RPC_FC_OP:
2873 case RPC_FC_FP:
2874 case RPC_FC_POINTER:
2875 {
2876 unsigned char *saved_buffer;
2877 BOOL pointer_buffer_mark_set = FALSE;
2878 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2879 TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2880 if (*pFormat != RPC_FC_POINTER)
2881 pPointer = pFormat;
2882 if (*pPointer != RPC_FC_RP)
2883 align_pointer_clear(&pStubMsg->Buffer, 4);
2884 saved_buffer = pStubMsg->Buffer;
2885 if (pStubMsg->PointerBufferMark)
2886 {
2887 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2888 pStubMsg->PointerBufferMark = NULL;
2889 pointer_buffer_mark_set = TRUE;
2890 }
2891 else if (*pPointer != RPC_FC_RP)
2892 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2893 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2894 if (pointer_buffer_mark_set)
2895 {
2896 STD_OVERFLOW_CHECK(pStubMsg);
2897 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2898 pStubMsg->Buffer = saved_buffer;
2899 if (*pPointer != RPC_FC_RP)
2900 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2901 }
2902 TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2903 if (*pFormat == RPC_FC_POINTER)
2904 pPointer += 4;
2905 else
2906 pFormat += 4;
2907 pMemory += sizeof(void *);
2908 break;
2909 }
2910 case RPC_FC_ALIGNM2:
2911 align_pointer(&pMemory, 2);
2912 break;
2913 case RPC_FC_ALIGNM4:
2914 align_pointer(&pMemory, 4);
2915 break;
2916 case RPC_FC_ALIGNM8:
2917 align_pointer(&pMemory, 8);
2918 break;
2919 case RPC_FC_STRUCTPAD1:
2920 case RPC_FC_STRUCTPAD2:
2921 case RPC_FC_STRUCTPAD3:
2922 case RPC_FC_STRUCTPAD4:
2923 case RPC_FC_STRUCTPAD5:
2924 case RPC_FC_STRUCTPAD6:
2925 case RPC_FC_STRUCTPAD7:
2926 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2927 break;
2928 case RPC_FC_EMBEDDED_COMPLEX:
2929 pMemory += pFormat[1];
2930 pFormat += 2;
2931 desc = pFormat + *(const SHORT*)pFormat;
2932 size = EmbeddedComplexSize(pStubMsg, desc);
2933 TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2934 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2935 if (m)
2936 {
2937 /* for some reason interface pointers aren't generated as
2938 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2939 * they still need the derefencing treatment that pointers are
2940 * given */
2941 if (*desc == RPC_FC_IP)
2942 m(pStubMsg, *(unsigned char **)pMemory, desc);
2943 else
2944 m(pStubMsg, pMemory, desc);
2945 }
2946 else FIXME("no marshaller for embedded type %02x\n", *desc);
2947 pMemory += size;
2948 pFormat += 2;
2949 continue;
2950 case RPC_FC_PAD:
2951 break;
2952 default:
2953 FIXME("unhandled format 0x%02x\n", *pFormat);
2954 }
2955 pFormat++;
2956 }
2957
2958 return pMemory;
2959 }
2960
2961 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2962 unsigned char *pMemory,
2963 PFORMAT_STRING pFormat,
2964 PFORMAT_STRING pPointer,
2965 unsigned char fMustAlloc)
2966 {
2967 PFORMAT_STRING desc;
2968 NDR_UNMARSHALL m;
2969 ULONG size;
2970
2971 while (*pFormat != RPC_FC_END) {
2972 switch (*pFormat) {
2973 case RPC_FC_BYTE:
2974 case RPC_FC_CHAR:
2975 case RPC_FC_SMALL:
2976 case RPC_FC_USMALL:
2977 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2978 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2979 pMemory += 1;
2980 break;
2981 case RPC_FC_WCHAR:
2982 case RPC_FC_SHORT:
2983 case RPC_FC_USHORT:
2984 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2985 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2986 pMemory += 2;
2987 break;
2988 case RPC_FC_ENUM16:
2989 {
2990 WORD val;
2991 safe_copy_from_buffer(pStubMsg, &val, 2);
2992 *(DWORD*)pMemory = val;
2993 TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2994 if (32767 < *(DWORD*)pMemory)
2995 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2996 pMemory += 4;
2997 break;
2998 }
2999 case RPC_FC_LONG:
3000 case RPC_FC_ULONG:
3001 case RPC_FC_ENUM32:
3002 safe_copy_from_buffer(pStubMsg, pMemory, 4);
3003 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
3004 pMemory += 4;
3005 break;
3006 case RPC_FC_INT3264:
3007 {
3008 INT val;
3009 safe_copy_from_buffer(pStubMsg, &val, 4);
3010 *(INT_PTR *)pMemory = val;
3011 TRACE("int3264=%ld => %p\n", *(INT_PTR*)pMemory, pMemory);
3012 pMemory += sizeof(INT_PTR);
3013 break;
3014 }
3015 case RPC_FC_UINT3264:
3016 {
3017 UINT val;
3018 safe_copy_from_buffer(pStubMsg, &val, 4);
3019 *(UINT_PTR *)pMemory = val;
3020 TRACE("uint3264=%ld => %p\n", *(UINT_PTR*)pMemory, pMemory);
3021 pMemory += sizeof(UINT_PTR);
3022 break;
3023 }
3024 case RPC_FC_FLOAT:
3025 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
3026 TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
3027 pMemory += sizeof(float);
3028 break;
3029 case RPC_FC_HYPER:
3030 safe_copy_from_buffer(pStubMsg, pMemory, 8);
3031 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
3032 pMemory += 8;
3033 break;
3034 case RPC_FC_DOUBLE:
3035 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
3036 TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
3037 pMemory += sizeof(double);
3038 break;
3039 case RPC_FC_RP:
3040 case RPC_FC_UP:
3041 case RPC_FC_OP:
3042 case RPC_FC_FP:
3043 case RPC_FC_POINTER:
3044 {
3045 unsigned char *saved_buffer;
3046 BOOL pointer_buffer_mark_set = FALSE;
3047 TRACE("pointer => %p\n", pMemory);
3048 if (*pFormat != RPC_FC_POINTER)
3049 pPointer = pFormat;
3050 if (*pPointer != RPC_FC_RP)
3051 align_pointer(&pStubMsg->Buffer, 4);
3052 saved_buffer = pStubMsg->Buffer;
3053 if (pStubMsg->PointerBufferMark)
3054 {
3055 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3056 pStubMsg->PointerBufferMark = NULL;