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