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