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