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