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