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