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