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 #include "pshpack1.h"
2118 typedef struct
2119 {
2120 unsigned char type;
2121 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2122 ULONG low_value;
2123 ULONG high_value;
2124 } NDR_RANGE;
2125 #include "poppack.h"
2126
2127 static unsigned long EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
2128 PFORMAT_STRING pFormat)
2129 {
2130 switch (*pFormat) {
2131 case RPC_FC_STRUCT:
2132 case RPC_FC_PSTRUCT:
2133 case RPC_FC_CSTRUCT:
2134 case RPC_FC_BOGUS_STRUCT:
2135 case RPC_FC_SMFARRAY:
2136 case RPC_FC_SMVARRAY:
2137 case RPC_FC_CSTRING:
2138 return *(const WORD*)&pFormat[2];
2139 case RPC_FC_USER_MARSHAL:
2140 return *(const WORD*)&pFormat[4];
2141 case RPC_FC_RANGE: {
2142 switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2143 case RPC_FC_BYTE:
2144 case RPC_FC_CHAR:
2145 case RPC_FC_SMALL:
2146 case RPC_FC_USMALL:
2147 return sizeof(UCHAR);
2148 case RPC_FC_WCHAR:
2149 case RPC_FC_SHORT:
2150 case RPC_FC_USHORT:
2151 return sizeof(USHORT);
2152 case RPC_FC_LONG:
2153 case RPC_FC_ULONG:
2154 case RPC_FC_ENUM32:
2155 return sizeof(ULONG);
2156 case RPC_FC_FLOAT:
2157 return sizeof(float);
2158 case RPC_FC_DOUBLE:
2159 return sizeof(double);
2160 case RPC_FC_HYPER:
2161 return sizeof(ULONGLONG);
2162 case RPC_FC_ERROR_STATUS_T:
2163 return sizeof(error_status_t);
2164 case RPC_FC_ENUM16:
2165 return sizeof(UINT);
2166 default:
2167 ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2168 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2169 }
2170 }
2171 case RPC_FC_NON_ENCAPSULATED_UNION:
2172 pFormat += 2;
2173 if (pStubMsg->fHasNewCorrDesc)
2174 pFormat += 6;
2175 else
2176 pFormat += 4;
2177
2178 pFormat += *(const SHORT*)pFormat;
2179 return *(const SHORT*)pFormat;
2180 case RPC_FC_IP:
2181 return sizeof(void *);
2182 case RPC_FC_WSTRING:
2183 return *(const WORD*)&pFormat[2] * 2;
2184 default:
2185 FIXME("unhandled embedded type %02x\n", *pFormat);
2186 }
2187 return 0;
2188 }
2189
2190
2191 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2192 PFORMAT_STRING pFormat)
2193 {
2194 NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
2195
2196 if (!m)
2197 {
2198 FIXME("no memorysizer for data type=%02x\n", *pFormat);
2199 return 0;
2200 }
2201
2202 return m(pStubMsg, pFormat);
2203 }
2204
2205
2206 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2207 unsigned char *pMemory,
2208 PFORMAT_STRING pFormat,
2209 PFORMAT_STRING pPointer)
2210 {
2211 PFORMAT_STRING desc;
2212 NDR_MARSHALL m;
2213 unsigned long size;
2214
2215 while (*pFormat != RPC_FC_END) {
2216 switch (*pFormat) {
2217 case RPC_FC_BYTE:
2218 case RPC_FC_CHAR:
2219 case RPC_FC_SMALL:
2220 case RPC_FC_USMALL:
2221 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2222 safe_copy_to_buffer(pStubMsg, pMemory, 1);
2223 pMemory += 1;
2224 break;
2225 case RPC_FC_WCHAR:
2226 case RPC_FC_SHORT:
2227 case RPC_FC_USHORT:
2228 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2229 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2230 pMemory += 2;
2231 break;
2232 case RPC_FC_ENUM16:
2233 TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2234 if (32767 < *(DWORD*)pMemory)
2235 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2236 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2237 pMemory += 4;
2238 break;
2239 case RPC_FC_LONG:
2240 case RPC_FC_ULONG:
2241 case RPC_FC_ENUM32:
2242 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2243 safe_copy_to_buffer(pStubMsg, pMemory, 4);
2244 pMemory += 4;
2245 break;
2246 case RPC_FC_HYPER:
2247 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2248 safe_copy_to_buffer(pStubMsg, pMemory, 8);
2249 pMemory += 8;
2250 break;
2251 case RPC_FC_POINTER:
2252 {
2253 unsigned char *saved_buffer;
2254 int pointer_buffer_mark_set = 0;
2255 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2256 TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2257 if (*pPointer != RPC_FC_RP)
2258 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
2259 saved_buffer = pStubMsg->Buffer;
2260 if (pStubMsg->PointerBufferMark)
2261 {
2262 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2263 pStubMsg->PointerBufferMark = NULL;
2264 pointer_buffer_mark_set = 1;
2265 }
2266 else if (*pPointer != RPC_FC_RP)
2267 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2268 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2269 if (pointer_buffer_mark_set)
2270 {
2271 STD_OVERFLOW_CHECK(pStubMsg);
2272 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2273 pStubMsg->Buffer = saved_buffer;
2274 if (*pPointer != RPC_FC_RP)
2275 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2276 }
2277 TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2278 pPointer += 4;
2279 pMemory += 4;
2280 break;
2281 }
2282 case RPC_FC_ALIGNM4:
2283 ALIGN_POINTER(pMemory, 4);
2284 break;
2285 case RPC_FC_ALIGNM8:
2286 ALIGN_POINTER(pMemory, 8);
2287 break;
2288 case RPC_FC_STRUCTPAD1:
2289 case RPC_FC_STRUCTPAD2:
2290 case RPC_FC_STRUCTPAD3:
2291 case RPC_FC_STRUCTPAD4:
2292 case RPC_FC_STRUCTPAD5:
2293 case RPC_FC_STRUCTPAD6:
2294 case RPC_FC_STRUCTPAD7:
2295 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2296 break;
2297 case RPC_FC_EMBEDDED_COMPLEX:
2298 pMemory += pFormat[1];
2299 pFormat += 2;
2300 desc = pFormat + *(const SHORT*)pFormat;
2301 size = EmbeddedComplexSize(pStubMsg, desc);
2302 TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
2303 m = NdrMarshaller[*desc & NDR_TABLE_MASK];
2304 if (m)
2305 {
2306 /* for some reason interface pointers aren't generated as
2307 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2308 * they still need the derefencing treatment that pointers are
2309 * given */
2310 if (*desc == RPC_FC_IP)
2311 m(pStubMsg, *(unsigned char **)pMemory, desc);
2312 else
2313 m(pStubMsg, pMemory, desc);
2314 }
2315 else FIXME("no marshaller for embedded type %02x\n", *desc);
2316 pMemory += size;
2317 pFormat += 2;
2318 continue;
2319 case RPC_FC_PAD:
2320 break;
2321 default:
2322 FIXME("unhandled format 0x%02x\n", *pFormat);
2323 }
2324 pFormat++;
2325 }
2326
2327 return pMemory;
2328 }
2329
2330 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2331 unsigned char *pMemory,
2332 PFORMAT_STRING pFormat,
2333 PFORMAT_STRING pPointer,
2334 unsigned char fMustAlloc)
2335 {
2336 PFORMAT_STRING desc;
2337 NDR_UNMARSHALL m;
2338 unsigned long size;
2339
2340 while (*pFormat != RPC_FC_END) {
2341 switch (*pFormat) {
2342 case RPC_FC_BYTE:
2343 case RPC_FC_CHAR:
2344 case RPC_FC_SMALL:
2345 case RPC_FC_USMALL:
2346 safe_copy_from_buffer(pStubMsg, pMemory, 1);
2347 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
2348 pMemory += 1;
2349 break;
2350 case RPC_FC_WCHAR:
2351 case RPC_FC_SHORT:
2352 case RPC_FC_USHORT:
2353 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2354 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
2355 pMemory += 2;
2356 break;
2357 case RPC_FC_ENUM16:
2358 safe_copy_from_buffer(pStubMsg, pMemory, 2);
2359 *(DWORD*)pMemory &= 0xffff;
2360 TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
2361 if (32767 < *(DWORD*)pMemory)
2362 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
2363 pMemory += 4;
2364 break;
2365 case RPC_FC_LONG:
2366 case RPC_FC_ULONG:
2367 case RPC_FC_ENUM32:
2368 safe_copy_from_buffer(pStubMsg, pMemory, 4);
2369 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
2370 pMemory += 4;
2371 break;
2372 case RPC_FC_HYPER:
2373 safe_copy_from_buffer(pStubMsg, pMemory, 8);
2374 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2375 pMemory += 8;
2376 break;
2377 case RPC_FC_POINTER:
2378 {
2379 unsigned char *saved_buffer;
2380 int pointer_buffer_mark_set = 0;
2381 TRACE("pointer => %p\n", pMemory);
2382 if (*pPointer != RPC_FC_RP)
2383 ALIGN_POINTER(pStubMsg->Buffer, 4);
2384 saved_buffer = pStubMsg->Buffer;
2385 if (pStubMsg->PointerBufferMark)
2386 {
2387 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2388 pStubMsg->PointerBufferMark = NULL;
2389 pointer_buffer_mark_set = 1;
2390 }
2391 else if (*pPointer != RPC_FC_RP)
2392 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2393
2394 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
2395 if (pointer_buffer_mark_set)
2396 {
2397 STD_OVERFLOW_CHECK(pStubMsg);
2398 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2399 pStubMsg->Buffer = saved_buffer;
2400 if (*pPointer != RPC_FC_RP)
2401 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2402 }
2403 pPointer += 4;
2404 pMemory += 4;
2405 break;
2406 }
2407 case RPC_FC_ALIGNM4:
2408 ALIGN_POINTER_CLEAR(pMemory, 4);
2409 break;
2410 case RPC_FC_ALIGNM8:
2411 ALIGN_POINTER_CLEAR(pMemory, 8);
2412 break;
2413 case RPC_FC_STRUCTPAD1:
2414 case RPC_FC_STRUCTPAD2:
2415 case RPC_FC_STRUCTPAD3:
2416 case RPC_FC_STRUCTPAD4:
2417 case RPC_FC_STRUCTPAD5:
2418 case RPC_FC_STRUCTPAD6:
2419 case RPC_FC_STRUCTPAD7:
2420 memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
2421 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2422 break;
2423 case RPC_FC_EMBEDDED_COMPLEX:
2424 pMemory += pFormat[1];
2425 pFormat += 2;
2426 desc = pFormat + *(const SHORT*)pFormat;
2427 size = EmbeddedComplexSize(pStubMsg, desc);
2428 TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
2429 if (fMustAlloc)
2430 /* we can't pass fMustAlloc=TRUE into the marshaller for this type
2431 * since the type is part of the memory block that is encompassed by
2432 * the whole complex type. Memory is forced to allocate when pointers
2433 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
2434 * clearing the memory we pass in to the unmarshaller */
2435 memset(pMemory, 0, size);
2436 m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
2437 if (m)
2438 {
2439 /* for some reason interface pointers aren't generated as
2440 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2441 * they still need the derefencing treatment that pointers are
2442 * given */
2443 if (*desc == RPC_FC_IP)
2444 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
2445 else
2446 m(pStubMsg, &pMemory, desc, FALSE);
2447 }
2448 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
2449 pMemory += size;
2450 pFormat += 2;
2451 continue;
2452 case RPC_FC_PAD:
2453 break;
2454 default:
2455 FIXME("unhandled format %d\n", *pFormat);
2456 }
2457 pFormat++;
2458 }
2459
2460 return pMemory;
2461 }
2462
2463 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2464 unsigned char *pMemory,
2465 PFORMAT_STRING pFormat,
2466 PFORMAT_STRING pPointer)
2467 {
2468 PFORMAT_STRING desc;
2469 NDR_BUFFERSIZE m;
2470 unsigned long size;
2471
2472 while (*pFormat != RPC_FC_END) {
2473 switch (*pFormat) {
2474 case RPC_FC_BYTE:
2475 case RPC_FC_CHAR:
2476 case RPC_FC_SMALL:
2477 case RPC_FC_USMALL:
2478 safe_buffer_length_increment(pStubMsg, 1);
2479 pMemory += 1;
2480 break;
2481 case RPC_FC_WCHAR:
2482 case RPC_FC_SHORT:
2483 case RPC_FC_USHORT:
2484 safe_buffer_length_increment(pStubMsg, 2);
2485 pMemory += 2;
2486 break;
2487 case RPC_FC_ENUM16:
2488 safe_buffer_length_increment(pStubMsg, 2);
2489 pMemory += 4;
2490 break;
2491 case RPC_FC_LONG:
2492 case RPC_FC_ULONG:
2493 case RPC_FC_ENUM32:
2494 safe_buffer_length_increment(pStubMsg, 4);
2495 pMemory += 4;
2496 break;
2497 case RPC_FC_HYPER:
2498 safe_buffer_length_increment(pStubMsg, 8);
2499 pMemory += 8;
2500 break;
2501 case RPC_FC_POINTER:
2502 if (!pStubMsg->IgnoreEmbeddedPointers)
2503 {
2504 int saved_buffer_length = pStubMsg->BufferLength;
2505 pStubMsg->BufferLength = pStubMsg->PointerLength;
2506 pStubMsg->PointerLength = 0;
2507 if(!pStubMsg->BufferLength)
2508 ERR("BufferLength == 0??\n");
2509 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
2510 pStubMsg->PointerLength = pStubMsg->BufferLength;
2511 pStubMsg->BufferLength = saved_buffer_length;
2512 }
2513 if (*pPointer != RPC_FC_RP)
2514 {
2515 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2516 safe_buffer_length_increment(pStubMsg, 4);
2517 }
2518 pPointer += 4;
2519 pMemory += 4;
2520 break;
2521 case RPC_FC_ALIGNM4:
2522 ALIGN_POINTER(pMemory, 4);
2523 break;
2524 case RPC_FC_ALIGNM8:
2525 ALIGN_POINTER(pMemory, 8);
2526 break;
2527 case RPC_FC_STRUCTPAD1:
2528 case RPC_FC_STRUCTPAD2:
2529 case RPC_FC_STRUCTPAD3:
2530 case RPC_FC_STRUCTPAD4:
2531 case RPC_FC_STRUCTPAD5:
2532 case RPC_FC_STRUCTPAD6:
2533 case RPC_FC_STRUCTPAD7:
2534 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2535 break;
2536 case RPC_FC_EMBEDDED_COMPLEX:
2537 pMemory += pFormat[1];
2538 pFormat += 2;
2539 desc = pFormat + *(const SHORT*)pFormat;
2540 size = EmbeddedComplexSize(pStubMsg, desc);
2541 m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
2542 if (m)
2543 {
2544 /* for some reason interface pointers aren't generated as
2545 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2546 * they still need the derefencing treatment that pointers are
2547 * given */
2548 if (*desc == RPC_FC_IP)
2549 m(pStubMsg, *(unsigned char **)pMemory, desc);
2550 else
2551 m(pStubMsg, pMemory, desc);
2552 }
2553 else FIXME("no buffersizer for embedded type %02x\n", *desc);
2554 pMemory += size;
2555 pFormat += 2;
2556 continue;
2557 case RPC_FC_PAD:
2558 break;
2559 default:
2560 FIXME("unhandled format 0x%02x\n", *pFormat);
2561 }
2562 pFormat++;
2563 }
2564
2565 return pMemory;
2566 }
2567
2568 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
2569 unsigned char *pMemory,
2570 PFORMAT_STRING pFormat,
2571 PFORMAT_STRING pPointer)
2572 {
2573 PFORMAT_STRING desc;
2574 NDR_FREE m;
2575 unsigned long size;
2576
2577 while (*pFormat != RPC_FC_END) {
2578 switch (*pFormat) {
2579 case RPC_FC_BYTE:
2580 case RPC_FC_CHAR:
2581 case RPC_FC_SMALL:
2582 case RPC_FC_USMALL:
2583 pMemory += 1;
2584 break;
2585 case RPC_FC_WCHAR:
2586 case RPC_FC_SHORT:
2587 case RPC_FC_USHORT:
2588 pMemory += 2;
2589 break;
2590 case RPC_FC_LONG:
2591 case RPC_FC_ULONG:
2592 case RPC_FC_ENUM16:
2593 case RPC_FC_ENUM32:
2594 pMemory += 4;
2595 break;
2596 case RPC_FC_HYPER:
2597 pMemory += 8;
2598 break;
2599 case RPC_FC_POINTER:
2600 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
2601 pPointer += 4;
2602 pMemory += 4;
2603 break;
2604 case RPC_FC_ALIGNM4:
2605 ALIGN_POINTER(pMemory, 4);
2606 break;
2607 case RPC_FC_ALIGNM8:
2608 ALIGN_POINTER(pMemory, 8);
2609 break;
2610 case RPC_FC_STRUCTPAD1:
2611 case RPC_FC_STRUCTPAD2:
2612 case RPC_FC_STRUCTPAD3:
2613 case RPC_FC_STRUCTPAD4:
2614 case RPC_FC_STRUCTPAD5:
2615 case RPC_FC_STRUCTPAD6:
2616 case RPC_FC_STRUCTPAD7:
2617 pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2618 break;
2619 case RPC_FC_EMBEDDED_COMPLEX:
2620 pMemory += pFormat[1];
2621 pFormat += 2;
2622 desc = pFormat + *(const SHORT*)pFormat;
2623 size = EmbeddedComplexSize(pStubMsg, desc);
2624 m = NdrFreer[*desc & NDR_TABLE_MASK];
2625 if (m)
2626 {
2627 /* for some reason interface pointers aren't generated as
2628 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2629 * they still need the derefencing treatment that pointers are
2630 * given */
2631 if (*desc == RPC_FC_IP)
2632 m(pStubMsg, *(unsigned char **)pMemory, desc);
2633 else
2634 m(pStubMsg, pMemory, desc);
2635 }
2636 pMemory += size;
2637 pFormat += 2;
2638 continue;
2639 case RPC_FC_PAD:
2640 break;
2641 default:
2642 FIXME("unhandled format 0x%02x\n", *pFormat);
2643 }
2644 pFormat++;
2645 }
2646
2647 return pMemory;
2648 }
2649
2650 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2651 PFORMAT_STRING pFormat,
2652 PFORMAT_STRING pPointer)
2653 {
2654 PFORMAT_STRING desc;
2655 unsigned long size = 0;
2656
2657 while (*pFormat != RPC_FC_END) {
2658 switch (*pFormat) {
2659 case RPC_FC_BYTE:
2660 case RPC_FC_CHAR:
2661 case RPC_FC_SMALL:
2662 case RPC_FC_USMALL:
2663 size += 1;
2664 safe_buffer_increment(pStubMsg, 1);
2665 break;
2666 case RPC_FC_WCHAR:
2667 case RPC_FC_SHORT:
2668 case RPC_FC_USHORT:
2669 size += 2;
2670 safe_buffer_increment(pStubMsg, 2);
2671 break;
2672 case RPC_FC_ENUM16:
2673 size += 4;
2674 safe_buffer_increment(pStubMsg, 2);
2675 break;
2676 case RPC_FC_LONG:
2677 case RPC_FC_ULONG:
2678 case RPC_FC_ENUM32:
2679 size += 4;
2680 safe_buffer_increment(pStubMsg, 4);
2681 break;
2682 case RPC_FC_HYPER:
2683 size += 8;
2684 safe_buffer_increment(pStubMsg, 8);
2685 break;
2686 case RPC_FC_POINTER:
2687 {
2688 unsigned char *saved_buffer;
2689 int pointer_buffer_mark_set = 0;
2690 if (*pPointer != RPC_FC_RP)
2691 ALIGN_POINTER(pStubMsg->Buffer, 4);
2692 saved_buffer = pStubMsg->Buffer;
2693 if (pStubMsg->PointerBufferMark)
2694 {
2695 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2696 pStubMsg->PointerBufferMark = NULL;
2697 pointer_buffer_mark_set = 1;
2698 }
2699 else if (*pPointer != RPC_FC_RP)
2700 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2701
2702 if (!pStubMsg->IgnoreEmbeddedPointers)
2703 PointerMemorySize(pStubMsg, saved_buffer, pPointer);
2704 if (pointer_buffer_mark_set)
2705 {
2706 STD_OVERFLOW_CHECK(pStubMsg);
2707 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2708 pStubMsg->Buffer = saved_buffer;
2709 if (*pPointer != RPC_FC_RP)
2710 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2711 }
2712 pPointer += 4;
2713 size += 4;
2714 break;
2715 }
2716 case RPC_FC_ALIGNM4:
2717 ALIGN_LENGTH(size, 4);
2718 ALIGN_POINTER(pStubMsg->Buffer, 4);
2719 break;
2720 case RPC_FC_ALIGNM8:
2721 ALIGN_LENGTH(size, 8);
2722 ALIGN_POINTER(pStubMsg->Buffer, 8);
2723 break;
2724 case RPC_FC_STRUCTPAD1:
2725 case RPC_FC_STRUCTPAD2:
2726 case RPC_FC_STRUCTPAD3:
2727 case RPC_FC_STRUCTPAD4:
2728 case RPC_FC_STRUCTPAD5:
2729 case RPC_FC_STRUCTPAD6:
2730 case RPC_FC_STRUCTPAD7:
2731 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2732 break;
2733 case RPC_FC_EMBEDDED_COMPLEX:
2734 size += pFormat[1];
2735 pFormat += 2;
2736 desc = pFormat + *(const SHORT*)pFormat;
2737 size += EmbeddedComplexMemorySize(pStubMsg, desc);
2738 pFormat += 2;
2739 continue;
2740 case RPC_FC_PAD:
2741 break;
2742 default:
2743 FIXME("unhandled format 0x%02x\n", *pFormat);
2744 }
2745 pFormat++;
2746 }
2747
2748 return size;
2749 }
2750
2751 unsigned long ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,
2752 PFORMAT_STRING pFormat)
2753 {
2754 PFORMAT_STRING desc;
2755 unsigned long size = 0;
2756
2757 while (*pFormat != RPC_FC_END) {
2758 switch (*pFormat) {
2759 case RPC_FC_BYTE:
2760 case RPC_FC_CHAR:
2761 case RPC_FC_SMALL:
2762 case RPC_FC_USMALL:
2763 size += 1;
2764 break;
2765 case RPC_FC_WCHAR:
2766 case RPC_FC_SHORT:
2767 case RPC_FC_USHORT:
2768 size += 2;
2769 break;
2770 case RPC_FC_LONG:
2771 case RPC_FC_ULONG:
2772 case RPC_FC_ENUM16:
2773 case RPC_FC_ENUM32:
2774 size += 4;
2775 break;
2776 case RPC_FC_HYPER:
2777 size += 8;
2778 break;
2779 case RPC_FC_POINTER:
2780 size += sizeof(void *);
2781 break;
2782 case RPC_FC_ALIGNM4:
2783 ALIGN_LENGTH(size, 4);
2784 break;
2785 case RPC_FC_ALIGNM8:
2786 ALIGN_LENGTH(size, 8);
2787 break;
2788 case RPC_FC_STRUCTPAD1:
2789 case RPC_FC_STRUCTPAD2:
2790 case RPC_FC_STRUCTPAD3:
2791 case RPC_FC_STRUCTPAD4:
2792 case RPC_FC_STRUCTPAD5:
2793 case RPC_FC_STRUCTPAD6:
2794 case RPC_FC_STRUCTPAD7:
2795 size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
2796 break;
2797 case RPC_FC_EMBEDDED_COMPLEX:
2798 size += pFormat[1];
2799 pFormat += 2;
2800 desc = pFormat + *(const SHORT*)pFormat;
2801 size += EmbeddedComplexSize(pStubMsg, desc);
2802 pFormat += 2;
2803 continue;
2804 case RPC_FC_PAD:
2805 break;
2806 default:
2807 FIXME("unhandled format 0x%02x\n", *pFormat);
2808 }
2809 pFormat++;
2810 }
2811
2812 return size;
2813 }
2814
2815 /***********************************************************************
2816 * NdrComplexStructMarshall [RPCRT4.@]
2817 */
2818 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2819 unsigned char *pMemory,
2820 PFORMAT_STRING pFormat)
2821 {
2822 PFORMAT_STRING conf_array = NULL;
2823 PFORMAT_STRING pointer_desc = NULL;
2824 unsigned char *OldMemory = pStubMsg->Memory;
2825 int pointer_buffer_mark_set = 0;
2826
2827 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2828
2829 if (!pStubMsg->PointerBufferMark)
2830 {
2831 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2832 /* save buffer length */
2833 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2834
2835 /* get the buffer pointer after complex array data, but before
2836 * pointer data */
2837 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
2838 pStubMsg->IgnoreEmbeddedPointers = 1;
2839 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2840 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2841
2842 /* save it for use by embedded pointer code later */
2843 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
2844 TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
2845 pointer_buffer_mark_set = 1;
2846
2847 /* restore the original buffer length */
2848 pStubMsg->BufferLength = saved_buffer_length;
2849 }
2850
2851 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1);
2852
2853 pFormat += 4;
2854 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
2855 pFormat += 2;
2856 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2857 pFormat += 2;
2858
2859 pStubMsg->Memory = pMemory;
2860
2861 ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
2862
2863 if (conf_array)
2864 NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
2865
2866 pStubMsg->Memory = OldMemory;
2867
2868 if (pointer_buffer_mark_set)
2869 {
2870 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2871 pStubMsg->PointerBufferMark = NULL;
2872 }
2873
2874 STD_OVERFLOW_CHECK(pStubMsg);
2875
2876 return NULL;
2877 }
2878
2879 /***********************************************************************
2880 * NdrComplexStructUnmarshall [RPCRT4.@]
2881 */
2882 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2883 unsigned char **ppMemory,
2884 PFORMAT_STRING pFormat,
2885 unsigned char fMustAlloc)
2886 {
2887 unsigned size = *(const WORD*)(pFormat+2);
2888 PFORMAT_STRING conf_array = NULL;
2889 PFORMAT_STRING pointer_desc = NULL;
2890 unsigned char *pMemory;
2891 int pointer_buffer_mark_set = 0;
2892
2893 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2894
2895 if (!pStubMsg->PointerBufferMark)
2896 {
2897 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2898 /* save buffer pointer */
2899 unsigned char *saved_buffer = pStubMsg->Buffer;
2900
2901 /* get the buffer pointer after complex array data, but before
2902 * pointer data */
2903 pStubMsg->IgnoreEmbeddedPointers = 1;
2904 NdrComplexStructMemorySize(pStubMsg, pFormat);
2905 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2906
2907 /* save it for use by embedded pointer code later */
2908 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2909 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
2910 pointer_buffer_mark_set = 1;
2911
2912 /* restore the original buffer */
2913 pStubMsg->Buffer = saved_buffer;
2914 }
2915
2916 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
2917
2918 if (fMustAlloc || !*ppMemory)
2919 *ppMemory = NdrAllocate(pStubMsg, size);
2920
2921 pFormat += 4;
2922 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
2923 pFormat += 2;
2924 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2925 pFormat += 2;
2926
2927 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
2928
2929 if (conf_array)
2930 NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
2931
2932 if (pointer_buffer_mark_set)
2933 {
2934 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2935 pStubMsg->PointerBufferMark = NULL;
2936 }
2937
2938 return NULL;
2939 }
2940
2941 /***********************************************************************
2942 * NdrComplexStructBufferSize [RPCRT4.@]
2943 */
2944 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2945 unsigned char *pMemory,
2946 PFORMAT_STRING pFormat)
2947 {
2948 PFORMAT_STRING conf_array = NULL;
2949 PFORMAT_STRING pointer_desc = NULL;
2950 unsigned char *OldMemory = pStubMsg->Memory;
2951 int pointer_length_set = 0;
2952
2953 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2954
2955 ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
2956
2957 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
2958 {
2959 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
2960 unsigned long saved_buffer_length = pStubMsg->BufferLength;
2961
2962 /* get the buffer length after complex struct data, but before
2963 * pointer data */
2964 pStubMsg->IgnoreEmbeddedPointers = 1;
2965 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
2966 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
2967
2968 /* save it for use by embedded pointer code later */
2969 pStubMsg->PointerLength = pStubMsg->BufferLength;
2970 pointer_length_set = 1;
2971 TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
2972
2973 /* restore the original buffer length */
2974 pStubMsg->BufferLength = saved_buffer_length;
2975 }
2976
2977 pFormat += 4;
2978 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
2979 pFormat += 2;
2980 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2981 pFormat += 2;
2982
2983 pStubMsg->Memory = pMemory;
2984
2985 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
2986
2987 if (conf_array)
2988 NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
2989
2990 pStubMsg->Memory = OldMemory;
2991
2992 if(pointer_length_set)
2993 {
2994 pStubMsg->BufferLength = pStubMsg->PointerLength;
2995 pStubMsg->PointerLength = 0;
2996 }
2997
2998 }
2999
3000 /***********************************************************************
3001 * NdrComplexStructMemorySize [RPCRT4.@]
3002 */
3003 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3004 PFORMAT_STRING pFormat)
3005 {
3006 unsigned size = *(const WORD*)(pFormat+2);
3007 PFORMAT_STRING conf_array = NULL;
3008 PFORMAT_STRING pointer_desc = NULL;
3009
3010 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3011
3012 ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
3013
3014 pFormat += 4;
3015 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3016 pFormat += 2;
3017 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3018 pFormat += 2;
3019
3020 ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3021
3022 if (conf_array)
3023 NdrConformantArrayMemorySize(pStubMsg, conf_array);
3024
3025 return size;
3026 }
3027
3028 /***********************************************************************
3029 * NdrComplexStructFree [RPCRT4.@]
3030 */
3031 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3032 unsigned char *pMemory,
3033 PFORMAT_STRING pFormat)
3034 {
3035 PFORMAT_STRING conf_array = NULL;
3036 PFORMAT_STRING pointer_desc = NULL;
3037 unsigned char *OldMemory = pStubMsg->Memory;
3038
3039 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3040
3041 pFormat += 4;
3042 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3043 pFormat += 2;
3044 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3045 pFormat += 2;
3046
3047 pStubMsg->Memory = pMemory;
3048
3049 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3050
3051 if (conf_array)
3052 NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
3053
3054 pStubMsg->Memory = OldMemory;
3055 }
3056
3057 /***********************************************************************
3058 * NdrConformantArrayMarshall [RPCRT4.@]
3059 */
3060 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3061 unsigned char *pMemory,
3062 PFORMAT_STRING pFormat)
3063 {
3064 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
3065 unsigned char alignment = pFormat[1] + 1;
3066
3067 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3068 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3069
3070 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3071
3072 WriteConformance(pStubMsg);
3073
3074 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3075
3076 size = safe_multiply(esize, pStubMsg->MaxCount);
3077 pStubMsg->BufferMark = pStubMsg->Buffer;
3078 safe_copy_to_buffer(pStubMsg, pMemory, size);
3079
3080 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3081
3082 return NULL;
3083 }
3084
3085 /***********************************************************************
3086 * NdrConformantArrayUnmarshall [RPCRT4.@]
3087 */
3088 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3089 unsigned char **ppMemory,
3090 PFORMAT_STRING pFormat,
3091 unsigned char fMustAlloc)
3092 {
3093 DWORD size, esize = *(const WORD*)(pFormat+2);
3094 unsigned char alignment = pFormat[1] + 1;
3095 unsigned char *saved_buffer;
3096
3097 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3098 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3099
3100 pFormat = ReadConformance(pStubMsg, pFormat+4);
3101
3102 size = safe_multiply(esize, pStubMsg->MaxCount);
3103 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3104
3105 if (fMustAlloc)
3106 *ppMemory = NdrAllocate(pStubMsg, size);
3107 else
3108 {
3109 if (!pStubMsg->IsClient && !*ppMemory)
3110 /* for servers, we just point straight into the RPC buffer */
3111 *ppMemory = pStubMsg->Buffer;
3112 }
3113
3114 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3115 safe_buffer_increment(pStubMsg, size);
3116 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3117
3118 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
3119 if (*ppMemory != saved_buffer)
3120 memcpy(*ppMemory, saved_buffer, size);
3121
3122 return NULL;
3123 }
3124
3125 /***********************************************************************
3126 * NdrConformantArrayBufferSize [RPCRT4.@]
3127 */
3128 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3129 unsigned char *pMemory,
3130 PFORMAT_STRING pFormat)
3131 {
3132 DWORD size, esize = *(const WORD*)(pFormat+2);
3133 unsigned char alignment = pFormat[1] + 1;
3134
3135 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3136 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3137
3138 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3139
3140 SizeConformance(pStubMsg);
3141
3142 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3143
3144 size = safe_multiply(esize, pStubMsg->MaxCount);
3145 /* conformance value plus array */
3146 safe_buffer_length_increment(pStubMsg, size);
3147
3148 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3149 }
3150
3151 /***********************************************************************
3152 * NdrConformantArrayMemorySize [RPCRT4.@]
3153 */
3154 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3155 PFORMAT_STRING pFormat)
3156 {
3157 DWORD size = 0, esize = *(const WORD*)(pFormat+2);
3158 unsigned char alignment = pFormat[1] + 1;
3159
3160 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3161 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3162
3163 pFormat = ReadConformance(pStubMsg, pFormat+4);
3164 size = safe_multiply(esize, pStubMsg->MaxCount);
3165 pStubMsg->MemorySize += size;
3166
3167 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3168 pStubMsg->BufferMark = pStubMsg->Buffer;
3169 safe_buffer_increment(pStubMsg, size);
3170
3171 EmbeddedPointerMemorySize(pStubMsg, pFormat);
3172
3173 return pStubMsg->MemorySize;
3174 }
3175
3176 /***********************************************************************
3177 * NdrConformantArrayFree [RPCRT4.@]
3178 */
3179 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3180 unsigned char *pMemory,
3181 PFORMAT_STRING pFormat)
3182 {
3183 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3184 if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
3185
3186 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3187
3188 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3189 }
3190
3191
3192 /***********************************************************************
3193 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
3194 */
3195 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
3196 unsigned char* pMemory,
3197 PFORMAT_STRING pFormat )
3198 {
3199 ULONG bufsize;
3200 unsigned char alignment = pFormat[1] + 1;
3201 DWORD esize = *(const WORD*)(pFormat+2);
3202
3203 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3204
3205 if (pFormat[0] != RPC_FC_CVARRAY)
3206 {
3207 ERR("invalid format type %x\n", pFormat[0]);
3208 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3209 return NULL;
3210 }
3211
3212 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3213 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3214
3215 WriteConformance(pStubMsg);
3216 WriteVariance(pStubMsg);
3217
3218 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3219
3220 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3221
3222 pStubMsg->BufferMark = pStubMsg->Buffer;
3223 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
3224
3225 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3226
3227 return NULL;
3228 }
3229
3230
3231 /***********************************************************************
3232 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
3233 */
3234 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
3235 unsigned char** ppMemory,
3236 PFORMAT_STRING pFormat,
3237 unsigned char fMustAlloc )
3238 {
3239 ULONG bufsize, memsize;
3240 unsigned char alignment = pFormat[1] + 1;
3241 DWORD esize = *(const WORD*)(pFormat+2);
3242 unsigned char *saved_buffer;
3243 ULONG offset;
3244
3245 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3246
3247 if (pFormat[0] != RPC_FC_CVARRAY)
3248 {
3249 ERR("invalid format type %x\n", pFormat[0]);
3250 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3251 return NULL;
3252 }
3253
3254 pFormat = ReadConformance(pStubMsg, pFormat+4);
3255 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3256
3257 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3258
3259 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3260 memsize = safe_multiply(esize, pStubMsg->MaxCount);
3261 offset = pStubMsg->Offset;
3262
3263 if (!*ppMemory || fMustAlloc)
3264 *ppMemory = NdrAllocate(pStubMsg, memsize);
3265 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
3266 safe_buffer_increment(pStubMsg, bufsize);
3267
3268 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
3269
3270 memcpy(*ppMemory + offset, saved_buffer, bufsize);
3271
3272 return NULL;
3273 }
3274
3275
3276 /***********************************************************************
3277 * NdrConformantVaryingArrayFree [RPCRT4.@]
3278 */
3279 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
3280 unsigned char* pMemory,
3281 PFORMAT_STRING pFormat )
3282 {
3283 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3284
3285 if (pFormat[0] != RPC_FC_CVARRAY)
3286 {
3287 ERR("invalid format type %x\n", pFormat[0]);
3288 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3289 return;
3290 }
3291
3292 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3293 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3294
3295 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3296 }
3297
3298
3299 /***********************************************************************
3300 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
3301 */
3302 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
3303 unsigned char* pMemory, PFORMAT_STRING pFormat )
3304 {
3305 unsigned char alignment = pFormat[1] + 1;
3306 DWORD esize = *(const WORD*)(pFormat+2);
3307
3308 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3309
3310 if (pFormat[0] != RPC_FC_CVARRAY)
3311 {
3312 ERR("invalid format type %x\n", pFormat[0]);
3313 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3314 return;
3315 }
3316
3317 /* compute size */
3318 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
3319 /* compute length */
3320 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
3321
3322 SizeConformance(pStubMsg);
3323 SizeVariance(pStubMsg);
3324
3325 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3326
3327 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
3328
3329 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3330 }
3331
3332
3333 /***********************************************************************
3334 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
3335 */
3336 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
3337 PFORMAT_STRING pFormat )
3338 {
3339 ULONG bufsize, memsize;
3340 unsigned char alignment = pFormat[1] + 1;
3341 DWORD esize = *(const WORD*)(pFormat+2);
3342
3343 TRACE("(%p, %p)\n", pStubMsg, pFormat);
3344
3345 if (pFormat[0] != RPC_FC_CVARRAY)
3346 {
3347 ERR("invalid format type %x\n", pFormat[0]);
3348 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3349 return pStubMsg->MemorySize;
3350 }
3351
3352 pFormat = ReadConformance(pStubMsg, pFormat+4);
3353 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3354
3355 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3356
3357 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
3358 memsize = safe_multiply(esize, pStubMsg->MaxCount);
3359
3360 safe_buffer_increment(pStubMsg, bufsize);
3361 pStubMsg->MemorySize += memsize;
3362
3363 EmbeddedPointerMemorySize(pStubMsg, pFormat);
3364
3365 return pStubMsg->MemorySize;
3366 }
3367
3368
3369 /***********************************************************************
3370 * NdrComplexArrayMarshall [RPCRT4.@]
3371 */
3372 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3373 unsigned char *pMemory,
3374 PFORMAT_STRING pFormat)
3375 {
3376 ULONG i, count, def;
3377 BOOL variance_present;
3378 unsigned char alignment;
3379 int pointer_buffer_mark_set = 0;
3380
3381 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3382
3383 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3384 {
3385 ERR("invalid format type %x\n", pFormat[0]);
3386 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3387 return NULL;
3388 }
3389
3390 alignment = pFormat[1] + 1;
3391
3392 if (!pStubMsg->PointerBufferMark)
3393 {
3394 /* save buffer fields that may be changed by buffer sizer functions
3395 * and that may be needed later on */
3396 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3397 unsigned long saved_buffer_length = pStubMsg->BufferLength;
3398 unsigned long saved_max_count = pStubMsg->MaxCount;
3399 unsigned long saved_offset = pStubMsg->Offset;
3400 unsigned long saved_actual_count = pStubMsg->ActualCount;
3401
3402 /* get the buffer pointer after complex array data, but before
3403 * pointer data */
3404 pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
3405 pStubMsg->IgnoreEmbeddedPointers = 1;
3406 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3407 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3408
3409 /* save it for use by embedded pointer code later */
3410 pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
3411 TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
3412 pointer_buffer_mark_set = 1;
3413
3414 /* restore fields */
3415 pStubMsg->ActualCount = saved_actual_count;
3416 pStubMsg->Offset = saved_offset;
3417 pStubMsg->MaxCount = saved_max_count;
3418 pStubMsg->BufferLength = saved_buffer_length;
3419 }
3420
3421 def = *(const WORD*)&pFormat[2];
3422 pFormat += 4;
3423
3424 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3425 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3426
3427 variance_present = IsConformanceOrVariancePresent(pFormat);
3428 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3429 TRACE("variance = %d\n", pStubMsg->ActualCount);
3430
3431 WriteConformance(pStubMsg);
3432 if (variance_present)
3433 WriteVariance(pStubMsg);
3434
3435 ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment);
3436
3437 count = pStubMsg->ActualCount;
3438 for (i = 0; i < count; i++)
3439 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
3440
3441 STD_OVERFLOW_CHECK(pStubMsg);
3442
3443 if (pointer_buffer_mark_set)
3444 {
3445 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3446 pStubMsg->PointerBufferMark = NULL;
3447 }
3448
3449 return NULL;
3450 }
3451
3452 /***********************************************************************
3453 * NdrComplexArrayUnmarshall [RPCRT4.@]
3454 */
3455 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3456 unsigned char **ppMemory,
3457 PFORMAT_STRING pFormat,
3458 unsigned char fMustAlloc)
3459 {
3460 ULONG i, count, size;
3461 unsigned char alignment;
3462 unsigned char *pMemory;
3463 unsigned char *saved_buffer;
3464 int pointer_buffer_mark_set = 0;
3465 int saved_ignore_embedded;
3466
3467 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3468
3469 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3470 {
3471 ERR("invalid format type %x\n", pFormat[0]);
3472 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3473 return NULL;
3474 }
3475
3476 alignment = pFormat[1] + 1;
3477
3478 saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3479 /* save buffer pointer */
3480 saved_buffer = pStubMsg->Buffer;
3481 /* get the buffer pointer after complex array data, but before
3482 * pointer data */
3483 pStubMsg->IgnoreEmbeddedPointers = 1;
3484 pStubMsg->MemorySize = 0;
3485 NdrComplexArrayMemorySize(pStubMsg, pFormat);
3486 size = pStubMsg->MemorySize;
3487 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3488
3489 TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
3490 if (!pStubMsg->PointerBufferMark)
3491 {
3492 /* save it for use by embedded pointer code later */
3493 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3494 pointer_buffer_mark_set = 1;
3495 }
3496 /* restore the original buffer */
3497 pStubMsg->Buffer = saved_buffer;
3498
3499 pFormat += 4;
3500
3501 pFormat = ReadConformance(pStubMsg, pFormat);
3502 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3503
3504 if (fMustAlloc || !*ppMemory)
3505 *ppMemory = NdrAllocate(pStubMsg, size);
3506
3507 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3508
3509 pMemory = *ppMemory;
3510 count = pStubMsg->ActualCount;
3511 for (i = 0; i < count; i++)
3512 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
3513
3514 if (pointer_buffer_mark_set)
3515 {
3516 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3517 pStubMsg->PointerBufferMark = NULL;
3518 }
3519
3520 return NULL;
3521 }
3522
3523 /***********************************************************************
3524 * NdrComplexArrayBufferSize [RPCRT4.@]
3525 */
3526 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3527 unsigned char *pMemory,
3528 PFORMAT_STRING pFormat)
3529 {
3530 ULONG i, count, def;
3531 unsigned char alignment;
3532 BOOL variance_present;
3533 int pointer_length_set = 0;
3534
3535 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3536
3537 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3538 {
3539 ERR("invalid format type %x\n", pFormat[0]);
3540 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3541 return;
3542 }
3543
3544 alignment = pFormat[1] + 1;
3545
3546 if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3547 {
3548 /* save buffer fields that may be changed by buffer sizer functions
3549 * and that may be needed later on */
3550 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3551 unsigned long saved_buffer_length = pStubMsg->BufferLength;
3552 unsigned long saved_max_count = pStubMsg->MaxCount;
3553 unsigned long saved_offset = pStubMsg->Offset;
3554 unsigned long saved_actual_count = pStubMsg->ActualCount;
3555
3556 /* get the buffer pointer after complex array data, but before
3557 * pointer data */
3558 pStubMsg->IgnoreEmbeddedPointers = 1;
3559 NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
3560 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3561
3562 /* save it for use by embedded pointer code later */
3563 pStubMsg->PointerLength = pStubMsg->BufferLength;
3564 pointer_length_set = 1;
3565
3566 /* restore fields */
3567 pStubMsg->ActualCount = saved_actual_count;
3568 pStubMsg->Offset = saved_offset;
3569 pStubMsg->MaxCount = saved_max_count;
3570 pStubMsg->BufferLength = saved_buffer_length;
3571 }
3572 def = *(const WORD*)&pFormat[2];
3573 pFormat += 4;
3574
3575 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
3576 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
3577 SizeConformance(pStubMsg);
3578
3579 variance_present = IsConformanceOrVariancePresent(pFormat);
3580 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
3581 TRACE("variance = %d\n", pStubMsg->ActualCount);
3582
3583 if (variance_present)
3584 SizeVariance(pStubMsg);
3585
3586 ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
3587
3588 count = pStubMsg->ActualCount;
3589 for (i = 0; i < count; i++)
3590 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
3591
3592 if(pointer_length_set)
3593 {
3594 pStubMsg->BufferLength = pStubMsg->PointerLength;
3595 pStubMsg->PointerLength = 0;
3596 }
3597 }
3598
3599 /***********************************************************************
3600 * NdrComplexArrayMemorySize [RPCRT4.@]
3601 */
3602 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3603 PFORMAT_STRING pFormat)
3604 {
3605 ULONG i, count, esize, SavedMemorySize, MemorySize;
3606 unsigned char alignment;
3607
3608 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3609
3610 if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
3611 {
3612 ERR("invalid format type %x\n", pFormat[0]);
3613 RpcRaiseException(RPC_S_INTERNAL_ERROR);
3614 return 0;
3615 }
3616
3617 alignment = pFormat[1] + 1;
3618
3619 pFormat += 4;
3620
3621 pFormat = ReadConformance(pStubMsg, pFormat);
3622 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
3623
3624 ALIGN_POINTER(pStubMsg->Buffer, alignment);
3625
3626 SavedMemorySize = pStubMsg->MemorySize;
3627
3628 esize = ComplexStructSize(pStubMsg, pFormat);
3629
3630 MemorySize = safe_multiply(pStubMsg->MaxCount, esize);
3631
3632 count = pStubMsg->ActualCount;