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