4 * Copyright 2002 Greg Turner
5 * Copyright 2003-2006 CodeWeavers
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.
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.
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
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
32 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
35 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
36 (*((UINT32 *)(pchar)) = (uint32))
38 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
39 (*((UINT32 *)(pchar)))
41 /* these would work for i386 too, but less efficient */
42 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
43 (*(pchar) = LOBYTE(LOWORD(uint32)), \
44 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
45 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
46 *((pchar)+3) = HIBYTE(HIWORD(uint32)))
48 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
50 MAKEWORD(*(pchar), *((pchar)+1)), \
51 MAKEWORD(*((pchar)+2), *((pchar)+3))))
54 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
55 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
56 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
57 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
58 *(pchar) = HIBYTE(HIWORD(uint32)))
60 #define BIG_ENDIAN_UINT32_READ(pchar) \
62 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
63 MAKEWORD(*((pchar)+1), *(pchar))))
65 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
66 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
67 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
68 # define NDR_LOCAL_UINT32_READ(pchar) \
69 BIG_ENDIAN_UINT32_READ(pchar)
71 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
72 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
73 # define NDR_LOCAL_UINT32_READ(pchar) \
74 LITTLE_ENDIAN_UINT32_READ(pchar)
77 static inline void align_length( ULONG
*len
, unsigned int align
)
79 *len
= (*len
+ align
- 1) & ~(align
- 1);
82 static inline void align_pointer( unsigned char **ptr
, unsigned int align
)
84 ULONG_PTR mask
= align
- 1;
85 *ptr
= (unsigned char *)(((ULONG_PTR
)*ptr
+ mask
) & ~mask
);
88 static inline void align_pointer_clear( unsigned char **ptr
, unsigned int align
)
90 ULONG_PTR mask
= align
- 1;
91 memset( *ptr
, 0, (align
- (ULONG_PTR
)*ptr
) & mask
);
92 *ptr
= (unsigned char *)(((ULONG_PTR
)*ptr
+ mask
) & ~mask
);
95 #define STD_OVERFLOW_CHECK(_Msg) do { \
96 TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
97 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
98 ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
101 #define NDR_POINTER_ID_BASE 0x20000
102 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
103 #define NDR_TABLE_SIZE 128
104 #define NDR_TABLE_MASK 127
106 #define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL))
108 static unsigned char *WINAPI
NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE
, unsigned char *, PFORMAT_STRING
);
109 static unsigned char *WINAPI
NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE
, unsigned char **, PFORMAT_STRING
, unsigned char);
110 static void WINAPI
NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE
, unsigned char *, PFORMAT_STRING
);
111 static void WINAPI
NdrBaseTypeFree(PMIDL_STUB_MESSAGE
, unsigned char *, PFORMAT_STRING
);
112 static ULONG WINAPI
NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE
, PFORMAT_STRING
);
114 static unsigned char *WINAPI
NdrContextHandleMarshall(PMIDL_STUB_MESSAGE
, unsigned char *, PFORMAT_STRING
);
115 static void WINAPI
NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE
, unsigned char *, PFORMAT_STRING
);
116 static unsigned char *WINAPI
NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE
, unsigned char **, PFORMAT_STRING
, unsigned char);
118 static unsigned char *WINAPI
NdrRangeMarshall(PMIDL_STUB_MESSAGE
,unsigned char *, PFORMAT_STRING
);
119 static void WINAPI
NdrRangeBufferSize(PMIDL_STUB_MESSAGE
, unsigned char *, PFORMAT_STRING
);
120 static ULONG WINAPI
NdrRangeMemorySize(PMIDL_STUB_MESSAGE
, PFORMAT_STRING
);
121 static void WINAPI
NdrRangeFree(PMIDL_STUB_MESSAGE
, unsigned char *, PFORMAT_STRING
);
123 static ULONG WINAPI
NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE
, PFORMAT_STRING
);
125 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg
,
126 unsigned char *pMemory
,
127 PFORMAT_STRING pFormat
,
128 PFORMAT_STRING pPointer
);
129 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg
,
130 unsigned char *pMemory
,
131 PFORMAT_STRING pFormat
,
132 PFORMAT_STRING pPointer
);
133 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg
,
134 unsigned char *pMemory
,
135 PFORMAT_STRING pFormat
,
136 PFORMAT_STRING pPointer
,
137 unsigned char fMustAlloc
);
138 static ULONG
ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg
,
139 PFORMAT_STRING pFormat
,
140 PFORMAT_STRING pPointer
);
141 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg
,
142 unsigned char *pMemory
,
143 PFORMAT_STRING pFormat
,
144 PFORMAT_STRING pPointer
);
146 const NDR_MARSHALL NdrMarshaller
[NDR_TABLE_SIZE
] = {
148 NdrBaseTypeMarshall
, NdrBaseTypeMarshall
, NdrBaseTypeMarshall
,
149 NdrBaseTypeMarshall
, NdrBaseTypeMarshall
, NdrBaseTypeMarshall
, NdrBaseTypeMarshall
,
150 NdrBaseTypeMarshall
, NdrBaseTypeMarshall
, NdrBaseTypeMarshall
, NdrBaseTypeMarshall
,
151 NdrBaseTypeMarshall
, NdrBaseTypeMarshall
, NdrBaseTypeMarshall
, NdrBaseTypeMarshall
,
155 NdrPointerMarshall
, NdrPointerMarshall
,
156 NdrPointerMarshall
, NdrPointerMarshall
,
158 NdrSimpleStructMarshall
, NdrSimpleStructMarshall
,
159 NdrConformantStructMarshall
, NdrConformantStructMarshall
,
160 NdrConformantVaryingStructMarshall
,
161 NdrComplexStructMarshall
,
163 NdrConformantArrayMarshall
,
164 NdrConformantVaryingArrayMarshall
,
165 NdrFixedArrayMarshall
, NdrFixedArrayMarshall
,
166 NdrVaryingArrayMarshall
, NdrVaryingArrayMarshall
,
167 NdrComplexArrayMarshall
,
169 NdrConformantStringMarshall
, 0, 0,
170 NdrConformantStringMarshall
,
171 NdrNonConformantStringMarshall
, 0, 0, 0,
173 NdrEncapsulatedUnionMarshall
,
174 NdrNonEncapsulatedUnionMarshall
,
175 NdrByteCountPointerMarshall
,
176 NdrXmitOrRepAsMarshall
, NdrXmitOrRepAsMarshall
,
178 NdrInterfacePointerMarshall
,
180 NdrContextHandleMarshall
,
183 NdrUserMarshalMarshall
,
188 const NDR_UNMARSHALL NdrUnmarshaller
[NDR_TABLE_SIZE
] = {
190 NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
,
191 NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
,
192 NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
,
193 NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
, NdrBaseTypeUnmarshall
,
195 NdrBaseTypeUnmarshall
,
197 NdrPointerUnmarshall
, NdrPointerUnmarshall
,
198 NdrPointerUnmarshall
, NdrPointerUnmarshall
,
200 NdrSimpleStructUnmarshall
, NdrSimpleStructUnmarshall
,
201 NdrConformantStructUnmarshall
, NdrConformantStructUnmarshall
,
202 NdrConformantVaryingStructUnmarshall
,
203 NdrComplexStructUnmarshall
,
205 NdrConformantArrayUnmarshall
,
206 NdrConformantVaryingArrayUnmarshall
,
207 NdrFixedArrayUnmarshall
, NdrFixedArrayUnmarshall
,
208 NdrVaryingArrayUnmarshall
, NdrVaryingArrayUnmarshall
,
209 NdrComplexArrayUnmarshall
,
211 NdrConformantStringUnmarshall
, 0, 0,
212 NdrConformantStringUnmarshall
,
213 NdrNonConformantStringUnmarshall
, 0, 0, 0,
215 NdrEncapsulatedUnionUnmarshall
,
216 NdrNonEncapsulatedUnionUnmarshall
,
217 NdrByteCountPointerUnmarshall
,
218 NdrXmitOrRepAsUnmarshall
, NdrXmitOrRepAsUnmarshall
,
220 NdrInterfacePointerUnmarshall
,
222 NdrContextHandleUnmarshall
,
225 NdrUserMarshalUnmarshall
,
230 const NDR_BUFFERSIZE NdrBufferSizer
[NDR_TABLE_SIZE
] = {
232 NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
,
233 NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
,
234 NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
,
235 NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
, NdrBaseTypeBufferSize
,
237 NdrBaseTypeBufferSize
,
239 NdrPointerBufferSize
, NdrPointerBufferSize
,
240 NdrPointerBufferSize
, NdrPointerBufferSize
,
242 NdrSimpleStructBufferSize
, NdrSimpleStructBufferSize
,
243 NdrConformantStructBufferSize
, NdrConformantStructBufferSize
,
244 NdrConformantVaryingStructBufferSize
,
245 NdrComplexStructBufferSize
,
247 NdrConformantArrayBufferSize
,
248 NdrConformantVaryingArrayBufferSize
,
249 NdrFixedArrayBufferSize
, NdrFixedArrayBufferSize
,
250 NdrVaryingArrayBufferSize
, NdrVaryingArrayBufferSize
,
251 NdrComplexArrayBufferSize
,
253 NdrConformantStringBufferSize
, 0, 0,
254 NdrConformantStringBufferSize
,
255 NdrNonConformantStringBufferSize
, 0, 0, 0,
257 NdrEncapsulatedUnionBufferSize
,
258 NdrNonEncapsulatedUnionBufferSize
,
259 NdrByteCountPointerBufferSize
,
260 NdrXmitOrRepAsBufferSize
, NdrXmitOrRepAsBufferSize
,
262 NdrInterfacePointerBufferSize
,
264 NdrContextHandleBufferSize
,
267 NdrUserMarshalBufferSize
,
272 const NDR_MEMORYSIZE NdrMemorySizer
[NDR_TABLE_SIZE
] = {
274 NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
,
275 NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
,
276 NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
,
277 NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
, NdrBaseTypeMemorySize
,
279 NdrBaseTypeMemorySize
,
281 NdrPointerMemorySize
, NdrPointerMemorySize
,
282 NdrPointerMemorySize
, NdrPointerMemorySize
,
284 NdrSimpleStructMemorySize
, NdrSimpleStructMemorySize
,
285 NdrConformantStructMemorySize
, NdrConformantStructMemorySize
,
286 NdrConformantVaryingStructMemorySize
,
287 NdrComplexStructMemorySize
,
289 NdrConformantArrayMemorySize
,
290 NdrConformantVaryingArrayMemorySize
,
291 NdrFixedArrayMemorySize
, NdrFixedArrayMemorySize
,
292 NdrVaryingArrayMemorySize
, NdrVaryingArrayMemorySize
,
293 NdrComplexArrayMemorySize
,
295 NdrConformantStringMemorySize
, 0, 0,
296 NdrConformantStringMemorySize
,
297 NdrNonConformantStringMemorySize
, 0, 0, 0,
299 NdrEncapsulatedUnionMemorySize
,
300 NdrNonEncapsulatedUnionMemorySize
,
301 NdrByteCountPointerMemorySize
,
302 NdrXmitOrRepAsMemorySize
, NdrXmitOrRepAsMemorySize
,
304 NdrInterfacePointerMemorySize
,
309 NdrUserMarshalMemorySize
,
314 const NDR_FREE NdrFreer
[NDR_TABLE_SIZE
] = {
316 NdrBaseTypeFree
, NdrBaseTypeFree
, NdrBaseTypeFree
,
317 NdrBaseTypeFree
, NdrBaseTypeFree
, NdrBaseTypeFree
, NdrBaseTypeFree
,
318 NdrBaseTypeFree
, NdrBaseTypeFree
, NdrBaseTypeFree
, NdrBaseTypeFree
,
319 NdrBaseTypeFree
, NdrBaseTypeFree
, NdrBaseTypeFree
, NdrBaseTypeFree
,
323 NdrPointerFree
, NdrPointerFree
,
324 NdrPointerFree
, NdrPointerFree
,
326 NdrSimpleStructFree
, NdrSimpleStructFree
,
327 NdrConformantStructFree
, NdrConformantStructFree
,
328 NdrConformantVaryingStructFree
,
329 NdrComplexStructFree
,
331 NdrConformantArrayFree
,
332 NdrConformantVaryingArrayFree
,
333 NdrFixedArrayFree
, NdrFixedArrayFree
,
334 NdrVaryingArrayFree
, NdrVaryingArrayFree
,
340 NdrEncapsulatedUnionFree
,
341 NdrNonEncapsulatedUnionFree
,
343 NdrXmitOrRepAsFree
, NdrXmitOrRepAsFree
,
345 NdrInterfacePointerFree
,
356 typedef struct _NDR_MEMORY_LIST
361 struct _NDR_MEMORY_LIST
*next
;
364 #define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
366 /***********************************************************************
367 * NdrAllocate [RPCRT4.@]
369 * Allocates a block of memory using pStubMsg->pfnAllocate.
372 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
373 * len [I] Size of memory block to allocate.
376 * The memory block of size len that was allocated.
379 * The memory block is always 8-byte aligned.
380 * If the function is unable to allocate memory an ERROR_OUTOFMEMORY
381 * exception is raised.
383 void * WINAPI
NdrAllocate(MIDL_STUB_MESSAGE
*pStubMsg
, SIZE_T len
)
388 NDR_MEMORY_LIST
*mem_list
;
390 aligned_len
= (len
+ 7) & ~7;
391 adjusted_len
= aligned_len
+ sizeof(NDR_MEMORY_LIST
);
392 /* check for overflow */
393 if (adjusted_len
< len
)
395 ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len
, len
);
396 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
399 p
= pStubMsg
->pfnAllocate(adjusted_len
);
400 if (!p
) RpcRaiseException(ERROR_OUTOFMEMORY
);
402 mem_list
= (NDR_MEMORY_LIST
*)((char *)p
+ aligned_len
);
403 mem_list
->magic
= MEML_MAGIC
;
404 mem_list
->size
= aligned_len
;
405 mem_list
->reserved
= 0;
406 mem_list
->next
= pStubMsg
->pMemoryList
;
407 pStubMsg
->pMemoryList
= mem_list
;
413 static void NdrFree(MIDL_STUB_MESSAGE
*pStubMsg
, unsigned char *Pointer
)
415 TRACE("(%p, %p)\n", pStubMsg
, Pointer
);
417 pStubMsg
->pfnFree(Pointer
);
420 static inline BOOL
IsConformanceOrVariancePresent(PFORMAT_STRING pFormat
)
422 return (*(const ULONG
*)pFormat
!= -1);
425 static PFORMAT_STRING
ReadConformance(MIDL_STUB_MESSAGE
*pStubMsg
, PFORMAT_STRING pFormat
)
427 align_pointer(&pStubMsg
->Buffer
, 4);
428 if (pStubMsg
->Buffer
+ 4 > pStubMsg
->BufferEnd
)
429 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
430 pStubMsg
->MaxCount
= NDR_LOCAL_UINT32_READ(pStubMsg
->Buffer
);
431 pStubMsg
->Buffer
+= 4;
432 TRACE("unmarshalled conformance is %ld\n", pStubMsg
->MaxCount
);
433 if (pStubMsg
->fHasNewCorrDesc
)
439 static inline PFORMAT_STRING
ReadVariance(MIDL_STUB_MESSAGE
*pStubMsg
, PFORMAT_STRING pFormat
, ULONG MaxValue
)
441 if (pFormat
&& !IsConformanceOrVariancePresent(pFormat
))
443 pStubMsg
->Offset
= 0;
444 pStubMsg
->ActualCount
= pStubMsg
->MaxCount
;
448 align_pointer(&pStubMsg
->Buffer
, 4);
449 if (pStubMsg
->Buffer
+ 8 > pStubMsg
->BufferEnd
)
450 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
451 pStubMsg
->Offset
= NDR_LOCAL_UINT32_READ(pStubMsg
->Buffer
);
452 pStubMsg
->Buffer
+= 4;
453 TRACE("offset is %d\n", pStubMsg
->Offset
);
454 pStubMsg
->ActualCount
= NDR_LOCAL_UINT32_READ(pStubMsg
->Buffer
);
455 pStubMsg
->Buffer
+= 4;
456 TRACE("variance is %d\n", pStubMsg
->ActualCount
);
458 if ((pStubMsg
->ActualCount
> MaxValue
) ||
459 (pStubMsg
->ActualCount
+ pStubMsg
->Offset
> MaxValue
))
461 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
462 pStubMsg
->ActualCount
, pStubMsg
->Offset
, MaxValue
);
463 RpcRaiseException(RPC_S_INVALID_BOUND
);
468 if (pStubMsg
->fHasNewCorrDesc
)
474 /* writes the conformance value to the buffer */
475 static inline void WriteConformance(MIDL_STUB_MESSAGE
*pStubMsg
)
477 align_pointer_clear(&pStubMsg
->Buffer
, 4);
478 if (pStubMsg
->Buffer
+ 4 > (unsigned char *)pStubMsg
->RpcMsg
->Buffer
+ pStubMsg
->BufferLength
)
479 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
480 NDR_LOCAL_UINT32_WRITE(pStubMsg
->Buffer
, pStubMsg
->MaxCount
);
481 pStubMsg
->Buffer
+= 4;
484 /* writes the variance values to the buffer */
485 static inline void WriteVariance(MIDL_STUB_MESSAGE
*pStubMsg
)
487 align_pointer_clear(&pStubMsg
->Buffer
, 4);
488 if (pStubMsg
->Buffer
+ 8 > (unsigned char *)pStubMsg
->RpcMsg
->Buffer
+ pStubMsg
->BufferLength
)
489 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
490 NDR_LOCAL_UINT32_WRITE(pStubMsg
->Buffer
, pStubMsg
->Offset
);
491 pStubMsg
->Buffer
+= 4;
492 NDR_LOCAL_UINT32_WRITE(pStubMsg
->Buffer
, pStubMsg
->ActualCount
);
493 pStubMsg
->Buffer
+= 4;
496 /* requests buffer space for the conformance value */
497 static inline void SizeConformance(MIDL_STUB_MESSAGE
*pStubMsg
)
499 align_length(&pStubMsg
->BufferLength
, 4);
500 if (pStubMsg
->BufferLength
+ 4 < pStubMsg
->BufferLength
)
501 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
502 pStubMsg
->BufferLength
+= 4;
505 /* requests buffer space for the variance values */
506 static inline void SizeVariance(MIDL_STUB_MESSAGE
*pStubMsg
)
508 align_length(&pStubMsg
->BufferLength
, 4);
509 if (pStubMsg
->BufferLength
+ 8 < pStubMsg
->BufferLength
)
510 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
511 pStubMsg
->BufferLength
+= 8;
514 PFORMAT_STRING
ComputeConformanceOrVariance(
515 MIDL_STUB_MESSAGE
*pStubMsg
, unsigned char *pMemory
,
516 PFORMAT_STRING pFormat
, ULONG_PTR def
, ULONG_PTR
*pCount
)
518 BYTE dtype
= pFormat
[0] & 0xf;
519 short ofs
= *(const short *)&pFormat
[2];
523 if (!IsConformanceOrVariancePresent(pFormat
)) {
524 /* null descriptor */
529 switch (pFormat
[0] & 0xf0) {
530 case RPC_FC_NORMAL_CONFORMANCE
:
531 TRACE("normal conformance, ofs=%d\n", ofs
);
534 case RPC_FC_POINTER_CONFORMANCE
:
535 TRACE("pointer conformance, ofs=%d\n", ofs
);
536 ptr
= pStubMsg
->Memory
;
538 case RPC_FC_TOP_LEVEL_CONFORMANCE
:
539 TRACE("toplevel conformance, ofs=%d\n", ofs
);
540 if (pStubMsg
->StackTop
) {
541 ptr
= pStubMsg
->StackTop
;
544 /* -Os mode, *pCount is already set */
548 case RPC_FC_CONSTANT_CONFORMANCE
:
549 data
= ofs
| ((DWORD
)pFormat
[1] << 16);
550 TRACE("constant conformance, val=%ld\n", data
);
553 case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE
:
554 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs
);
555 if (pStubMsg
->StackTop
) {
556 ptr
= pStubMsg
->StackTop
;
564 FIXME("unknown conformance type %x, expect crash.\n", pFormat
[0] & 0xf0);
568 switch (pFormat
[1]) {
569 case RPC_FC_DEREFERENCE
:
570 ptr
= *(LPVOID
*)((char *)ptr
+ ofs
);
572 case RPC_FC_CALLBACK
:
574 unsigned char *old_stack_top
= pStubMsg
->StackTop
;
575 ULONG_PTR max_count
, old_max_count
= pStubMsg
->MaxCount
;
577 pStubMsg
->StackTop
= ptr
;
579 /* ofs is index into StubDesc->apfnExprEval */
580 TRACE("callback conformance into apfnExprEval[%d]\n", ofs
);
581 pStubMsg
->StubDesc
->apfnExprEval
[ofs
](pStubMsg
);
583 pStubMsg
->StackTop
= old_stack_top
;
585 /* the callback function always stores the computed value in MaxCount */
586 max_count
= pStubMsg
->MaxCount
;
587 pStubMsg
->MaxCount
= old_max_count
;
592 ptr
= (char *)ptr
+ ofs
;
605 data
= *(USHORT
*)ptr
;
616 data
= *(ULONGLONG
*)ptr
;
619 FIXME("unknown conformance data type %x\n", dtype
);
622 TRACE("dereferenced data type %x at %p, got %ld\n", dtype
, ptr
, data
);
625 switch (pFormat
[1]) {
626 case RPC_FC_DEREFERENCE
: /* already handled */
643 FIXME("unknown conformance op %d\n", pFormat
[1]);
648 TRACE("resulting conformance is %ld\n", *pCount
);
649 if (pStubMsg
->fHasNewCorrDesc
)
655 static inline PFORMAT_STRING
SkipConformance(PMIDL_STUB_MESSAGE pStubMsg
,
656 PFORMAT_STRING pFormat
)
658 if (pStubMsg
->fHasNewCorrDesc
)
665 static inline PFORMAT_STRING
SkipVariance(PMIDL_STUB_MESSAGE pStubMsg
, PFORMAT_STRING pFormat
)
667 return SkipConformance( pStubMsg
, pFormat
);
670 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
671 * the result overflows 32-bits */
672 static inline ULONG
safe_multiply(ULONG a
, ULONG b
)
674 ULONGLONG ret
= (ULONGLONG
)a
* b
;
675 if (ret
> 0xffffffff)
677 RpcRaiseException(RPC_S_INVALID_BOUND
);
683 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE
*pStubMsg
, ULONG size
)
685 if ((pStubMsg
->Buffer
+ size
< pStubMsg
->Buffer
) || /* integer overflow of pStubMsg->Buffer */
686 (pStubMsg
->Buffer
+ size
> (unsigned char *)pStubMsg
->RpcMsg
->Buffer
+ pStubMsg
->BufferLength
))
687 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
688 pStubMsg
->Buffer
+= size
;
691 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE
*pStubMsg
, ULONG size
)
693 if (pStubMsg
->BufferLength
+ size
< pStubMsg
->BufferLength
) /* integer overflow of pStubMsg->BufferSize */
695 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
696 pStubMsg
->BufferLength
, size
);
697 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
699 pStubMsg
->BufferLength
+= size
;
702 /* copies data from the buffer, checking that there is enough data in the buffer
704 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE
*pStubMsg
, void *p
, ULONG size
)
706 if ((pStubMsg
->Buffer
+ size
< pStubMsg
->Buffer
) || /* integer overflow of pStubMsg->Buffer */
707 (pStubMsg
->Buffer
+ size
> pStubMsg
->BufferEnd
))
709 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
710 pStubMsg
->Buffer
, pStubMsg
->BufferEnd
, size
);
711 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
713 if (p
== pStubMsg
->Buffer
)
714 ERR("pointer is the same as the buffer\n");
715 memcpy(p
, pStubMsg
->Buffer
, size
);
716 pStubMsg
->Buffer
+= size
;
719 /* copies data to the buffer, checking that there is enough space to do so */
720 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE
*pStubMsg
, const void *p
, ULONG size
)
722 if ((pStubMsg
->Buffer
+ size
< pStubMsg
->Buffer
) || /* integer overflow of pStubMsg->Buffer */
723 (pStubMsg
->Buffer
+ size
> (unsigned char *)pStubMsg
->RpcMsg
->Buffer
+ pStubMsg
->BufferLength
))
725 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
726 pStubMsg
->Buffer
, (unsigned char *)pStubMsg
->RpcMsg
->Buffer
+ pStubMsg
->BufferLength
,
728 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
730 memcpy(pStubMsg
->Buffer
, p
, size
);
731 pStubMsg
->Buffer
+= size
;
734 /* verify that string data sitting in the buffer is valid and safe to
736 static void validate_string_data(MIDL_STUB_MESSAGE
*pStubMsg
, ULONG bufsize
, ULONG esize
)
740 /* verify the buffer is safe to access */
741 if ((pStubMsg
->Buffer
+ bufsize
< pStubMsg
->Buffer
) ||
742 (pStubMsg
->Buffer
+ bufsize
> pStubMsg
->BufferEnd
))
744 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize
,
745 pStubMsg
->BufferEnd
, pStubMsg
->Buffer
);
746 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
749 /* strings must always have null terminating bytes */
752 ERR("invalid string length of %d\n", bufsize
/ esize
);
753 RpcRaiseException(RPC_S_INVALID_BOUND
);
756 for (i
= bufsize
- esize
; i
< bufsize
; i
++)
757 if (pStubMsg
->Buffer
[i
] != 0)
759 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
760 i
, pStubMsg
->Buffer
[i
]);
761 RpcRaiseException(RPC_S_INVALID_BOUND
);
765 static inline void dump_pointer_attr(unsigned char attr
)
767 if (attr
& RPC_FC_P_ALLOCALLNODES
)
768 TRACE(" RPC_FC_P_ALLOCALLNODES");
769 if (attr
& RPC_FC_P_DONTFREE
)
770 TRACE(" RPC_FC_P_DONTFREE");
771 if (attr
& RPC_FC_P_ONSTACK
)
772 TRACE(" RPC_FC_P_ONSTACK");
773 if (attr
& RPC_FC_P_SIMPLEPOINTER
)
774 TRACE(" RPC_FC_P_SIMPLEPOINTER");
775 if (attr
& RPC_FC_P_DEREF
)
776 TRACE(" RPC_FC_P_DEREF");
780 /***********************************************************************
781 * PointerMarshall [internal]
783 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg
,
784 unsigned char *Buffer
,
785 unsigned char *Pointer
,
786 PFORMAT_STRING pFormat
)
788 unsigned type
= pFormat
[0], attr
= pFormat
[1];
792 BOOL pointer_needs_marshaling
;
794 TRACE("(%p,%p,%p,%p)\n", pStubMsg
, Buffer
, Pointer
, pFormat
);
795 TRACE("type=0x%x, attr=", type
); dump_pointer_attr(attr
);
797 if (attr
& RPC_FC_P_SIMPLEPOINTER
) desc
= pFormat
;
798 else desc
= pFormat
+ *(const SHORT
*)pFormat
;
801 case RPC_FC_RP
: /* ref pointer (always non-null) */
804 ERR("NULL ref pointer is not allowed\n");
805 RpcRaiseException(RPC_X_NULL_REF_POINTER
);
807 pointer_needs_marshaling
= TRUE
;
809 case RPC_FC_UP
: /* unique pointer */
810 case RPC_FC_OP
: /* object pointer - same as unique here */
812 pointer_needs_marshaling
= TRUE
;
814 pointer_needs_marshaling
= FALSE
;
815 pointer_id
= Pointer
? NDR_POINTER_ID(pStubMsg
) : 0;
816 TRACE("writing 0x%08x to buffer\n", pointer_id
);
817 NDR_LOCAL_UINT32_WRITE(Buffer
, pointer_id
);
820 pointer_needs_marshaling
= !NdrFullPointerQueryPointer(
821 pStubMsg
->FullPtrXlatTables
, Pointer
, 1, &pointer_id
);
822 TRACE("writing 0x%08x to buffer\n", pointer_id
);
823 NDR_LOCAL_UINT32_WRITE(Buffer
, pointer_id
);
826 FIXME("unhandled ptr type=%02x\n", type
);
827 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
831 TRACE("calling marshaller for type 0x%x\n", (int)*desc
);
833 if (pointer_needs_marshaling
) {
834 if (attr
& RPC_FC_P_DEREF
) {
835 Pointer
= *(unsigned char**)Pointer
;
836 TRACE("deref => %p\n", Pointer
);
838 m
= NdrMarshaller
[*desc
& NDR_TABLE_MASK
];
839 if (m
) m(pStubMsg
, Pointer
, desc
);
840 else FIXME("no marshaller for data type=%02x\n", *desc
);
843 STD_OVERFLOW_CHECK(pStubMsg
);
846 /***********************************************************************
847 * PointerUnmarshall [internal]
849 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg
,
850 unsigned char *Buffer
,
851 unsigned char **pPointer
,
852 unsigned char *pSrcPointer
,
853 PFORMAT_STRING pFormat
,
854 unsigned char fMustAlloc
)
856 unsigned type
= pFormat
[0], attr
= pFormat
[1];
859 DWORD pointer_id
= 0;
860 BOOL pointer_needs_unmarshaling
;
862 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg
, Buffer
, pPointer
, pSrcPointer
, pFormat
, fMustAlloc
);
863 TRACE("type=0x%x, attr=", type
); dump_pointer_attr(attr
);
865 if (attr
& RPC_FC_P_SIMPLEPOINTER
) desc
= pFormat
;
866 else desc
= pFormat
+ *(const SHORT
*)pFormat
;
869 case RPC_FC_RP
: /* ref pointer (always non-null) */
870 pointer_needs_unmarshaling
= TRUE
;
872 case RPC_FC_UP
: /* unique pointer */
873 pointer_id
= NDR_LOCAL_UINT32_READ(Buffer
);
874 TRACE("pointer_id is 0x%08x\n", pointer_id
);
876 pointer_needs_unmarshaling
= TRUE
;
879 pointer_needs_unmarshaling
= FALSE
;
882 case RPC_FC_OP
: /* object pointer - we must free data before overwriting it */
883 pointer_id
= NDR_LOCAL_UINT32_READ(Buffer
);
884 TRACE("pointer_id is 0x%08x\n", pointer_id
);
885 if (!fMustAlloc
&& pSrcPointer
)
887 FIXME("free object pointer %p\n", pSrcPointer
);
891 pointer_needs_unmarshaling
= TRUE
;
895 pointer_needs_unmarshaling
= FALSE
;
899 pointer_id
= NDR_LOCAL_UINT32_READ(Buffer
);
900 TRACE("pointer_id is 0x%08x\n", pointer_id
);
901 pointer_needs_unmarshaling
= !NdrFullPointerQueryRefId(
902 pStubMsg
->FullPtrXlatTables
, pointer_id
, 1, (void **)pPointer
);
905 FIXME("unhandled ptr type=%02x\n", type
);
906 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
910 if (pointer_needs_unmarshaling
) {
911 unsigned char **current_ptr
= pPointer
;
912 if (pStubMsg
->IsClient
) {
914 /* if we aren't forcing allocation of memory then try to use the existing
915 * (source) pointer to unmarshall the data into so that [in,out]
916 * parameters behave correctly. it doesn't matter if the parameter is
917 * [out] only since in that case the pointer will be NULL. we force
918 * allocation when the source pointer is NULL here instead of in the type
919 * unmarshalling routine for the benefit of the deref code below */
922 TRACE("setting *pPointer to %p\n", pSrcPointer
);
923 *pPointer
= pSrcPointer
;
929 /* the memory in a stub is never initialised, so we have to work out here
930 * whether we have to initialise it so we can use the optimisation of
931 * setting the pointer to the buffer, if possible, or set fMustAlloc to
933 if (attr
& RPC_FC_P_DEREF
) {
940 if (attr
& RPC_FC_P_ALLOCALLNODES
)
941 FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
943 if (attr
& RPC_FC_P_DEREF
) {
945 unsigned char *base_ptr_val
= NdrAllocate(pStubMsg
, sizeof(void *));
946 *pPointer
= base_ptr_val
;
947 current_ptr
= (unsigned char **)base_ptr_val
;
949 current_ptr
= *(unsigned char***)current_ptr
;
950 TRACE("deref => %p\n", current_ptr
);
951 if (!fMustAlloc
&& !*current_ptr
) fMustAlloc
= TRUE
;
953 m
= NdrUnmarshaller
[*desc
& NDR_TABLE_MASK
];
954 if (m
) m(pStubMsg
, current_ptr
, desc
, fMustAlloc
);
955 else FIXME("no unmarshaller for data type=%02x\n", *desc
);
957 if (type
== RPC_FC_FP
)
958 NdrFullPointerInsertRefId(pStubMsg
->FullPtrXlatTables
, pointer_id
,
962 TRACE("pointer=%p\n", *pPointer
);
965 /***********************************************************************
966 * PointerBufferSize [internal]
968 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg
,
969 unsigned char *Pointer
,
970 PFORMAT_STRING pFormat
)
972 unsigned type
= pFormat
[0], attr
= pFormat
[1];
975 BOOL pointer_needs_sizing
;
978 TRACE("(%p,%p,%p)\n", pStubMsg
, Pointer
, pFormat
);
979 TRACE("type=0x%x, attr=", type
); dump_pointer_attr(attr
);
981 if (attr
& RPC_FC_P_SIMPLEPOINTER
) desc
= pFormat
;
982 else desc
= pFormat
+ *(const SHORT
*)pFormat
;
985 case RPC_FC_RP
: /* ref pointer (always non-null) */
988 ERR("NULL ref pointer is not allowed\n");
989 RpcRaiseException(RPC_X_NULL_REF_POINTER
);
994 /* NULL pointer has no further representation */
999 pointer_needs_sizing
= !NdrFullPointerQueryPointer(
1000 pStubMsg
->FullPtrXlatTables
, Pointer
, 0, &pointer_id
);
1001 if (!pointer_needs_sizing
)
1005 FIXME("unhandled ptr type=%02x\n", type
);
1006 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
1010 if (attr
& RPC_FC_P_DEREF
) {
1011 Pointer
= *(unsigned char**)Pointer
;
1012 TRACE("deref => %p\n", Pointer
);
1015 m
= NdrBufferSizer
[*desc
& NDR_TABLE_MASK
];
1016 if (m
) m(pStubMsg
, Pointer
, desc
);
1017 else FIXME("no buffersizer for data type=%02x\n", *desc
);
1020 /***********************************************************************
1021 * PointerMemorySize [internal]
1023 static ULONG
PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg
,
1024 unsigned char *Buffer
, PFORMAT_STRING pFormat
)
1026 unsigned type
= pFormat
[0], attr
= pFormat
[1];
1027 PFORMAT_STRING desc
;
1029 DWORD pointer_id
= 0;
1030 BOOL pointer_needs_sizing
;
1032 TRACE("(%p,%p,%p)\n", pStubMsg
, Buffer
, pFormat
);
1033 TRACE("type=0x%x, attr=", type
); dump_pointer_attr(attr
);
1035 if (attr
& RPC_FC_P_SIMPLEPOINTER
) desc
= pFormat
;
1036 else desc
= pFormat
+ *(const SHORT
*)pFormat
;
1039 case RPC_FC_RP
: /* ref pointer (always non-null) */
1040 pointer_needs_sizing
= TRUE
;
1042 case RPC_FC_UP
: /* unique pointer */
1043 case RPC_FC_OP
: /* object pointer - we must free data before overwriting it */
1044 pointer_id
= NDR_LOCAL_UINT32_READ(Buffer
);
1045 TRACE("pointer_id is 0x%08x\n", pointer_id
);
1047 pointer_needs_sizing
= TRUE
;
1049 pointer_needs_sizing
= FALSE
;
1054 pointer_id
= NDR_LOCAL_UINT32_READ(Buffer
);
1055 TRACE("pointer_id is 0x%08x\n", pointer_id
);
1056 pointer_needs_sizing
= !NdrFullPointerQueryRefId(
1057 pStubMsg
->FullPtrXlatTables
, pointer_id
, 1, &pointer
);
1061 FIXME("unhandled ptr type=%02x\n", type
);
1062 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
1066 if (attr
& RPC_FC_P_DEREF
) {
1067 align_length(&pStubMsg
->MemorySize
, sizeof(void*));
1068 pStubMsg
->MemorySize
+= sizeof(void*);
1072 if (pointer_needs_sizing
) {
1073 m
= NdrMemorySizer
[*desc
& NDR_TABLE_MASK
];
1074 if (m
) m(pStubMsg
, desc
);
1075 else FIXME("no memorysizer for data type=%02x\n", *desc
);
1078 return pStubMsg
->MemorySize
;
1081 /***********************************************************************
1082 * PointerFree [internal]
1084 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg
,
1085 unsigned char *Pointer
,
1086 PFORMAT_STRING pFormat
)
1088 unsigned type
= pFormat
[0], attr
= pFormat
[1];
1089 PFORMAT_STRING desc
;
1091 unsigned char *current_pointer
= Pointer
;
1093 TRACE("(%p,%p,%p)\n", pStubMsg
, Pointer
, pFormat
);
1094 TRACE("type=0x%x, attr=", type
); dump_pointer_attr(attr
);
1095 if (attr
& RPC_FC_P_DONTFREE
) return;
1097 if (attr
& RPC_FC_P_SIMPLEPOINTER
) desc
= pFormat
;
1098 else desc
= pFormat
+ *(const SHORT
*)pFormat
;
1100 if (!Pointer
) return;
1102 if (type
== RPC_FC_FP
) {
1103 int pointer_needs_freeing
= NdrFullPointerFree(
1104 pStubMsg
->FullPtrXlatTables
, Pointer
);
1105 if (!pointer_needs_freeing
)
1109 if (attr
& RPC_FC_P_DEREF
) {
1110 current_pointer
= *(unsigned char**)Pointer
;
1111 TRACE("deref => %p\n", current_pointer
);
1114 m
= NdrFreer
[*desc
& NDR_TABLE_MASK
];
1115 if (m
) m(pStubMsg
, current_pointer
, desc
);
1117 /* this check stops us from trying to free buffer memory. we don't have to
1118 * worry about clients, since they won't call this function.
1119 * we don't have to check for the buffer being reallocated because
1120 * BufferStart and BufferEnd won't be reset when allocating memory for
1121 * sending the response. we don't have to check for the new buffer here as
1122 * it won't be used a type memory, only for buffer memory */
1123 if (Pointer
>= pStubMsg
->BufferStart
&& Pointer
< pStubMsg
->BufferEnd
)
1126 if (attr
& RPC_FC_P_ONSTACK
) {
1127 TRACE("not freeing stack ptr %p\n", Pointer
);
1130 TRACE("freeing %p\n", Pointer
);
1131 NdrFree(pStubMsg
, Pointer
);
1134 TRACE("not freeing %p\n", Pointer
);
1137 /***********************************************************************
1138 * EmbeddedPointerMarshall
1140 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg
,
1141 unsigned char *pMemory
,
1142 PFORMAT_STRING pFormat
)
1144 unsigned char *Mark
= pStubMsg
->BufferMark
;
1145 unsigned rep
, count
, stride
;
1147 unsigned char *saved_buffer
= NULL
;
1149 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
1151 if (*pFormat
!= RPC_FC_PP
) return NULL
;
1154 if (pStubMsg
->PointerBufferMark
)
1156 saved_buffer
= pStubMsg
->Buffer
;
1157 pStubMsg
->Buffer
= pStubMsg
->PointerBufferMark
;
1158 pStubMsg
->PointerBufferMark
= NULL
;
1161 while (pFormat
[0] != RPC_FC_END
) {
1162 switch (pFormat
[0]) {
1164 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat
[0]);
1166 case RPC_FC_NO_REPEAT
:
1172 case RPC_FC_FIXED_REPEAT
:
1173 rep
= *(const WORD
*)&pFormat
[2];
1174 stride
= *(const WORD
*)&pFormat
[4];
1175 count
= *(const WORD
*)&pFormat
[8];
1178 case RPC_FC_VARIABLE_REPEAT
:
1179 rep
= (pFormat
[1] == RPC_FC_VARIABLE_OFFSET
) ? pStubMsg
->ActualCount
: pStubMsg
->MaxCount
;
1180 stride
= *(const WORD
*)&pFormat
[2];
1181 count
= *(const WORD
*)&pFormat
[6];
1185 for (i
= 0; i
< rep
; i
++) {
1186 PFORMAT_STRING info
= pFormat
;
1187 unsigned char *membase
= pMemory
+ (i
* stride
);
1188 unsigned char *bufbase
= Mark
+ (i
* stride
);
1191 for (u
=0; u
<count
; u
++,info
+=8) {
1192 unsigned char *memptr
= membase
+ *(const SHORT
*)&info
[0];
1193 unsigned char *bufptr
= bufbase
+ *(const SHORT
*)&info
[2];
1194 unsigned char *saved_memory
= pStubMsg
->Memory
;
1196 pStubMsg
->Memory
= pMemory
;
1197 PointerMarshall(pStubMsg
, bufptr
, *(unsigned char**)memptr
, info
+4);
1198 pStubMsg
->Memory
= saved_memory
;
1201 pFormat
+= 8 * count
;
1206 pStubMsg
->PointerBufferMark
= pStubMsg
->Buffer
;
1207 pStubMsg
->Buffer
= saved_buffer
;
1210 STD_OVERFLOW_CHECK(pStubMsg
);
1215 /***********************************************************************
1216 * EmbeddedPointerUnmarshall
1218 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg
,
1219 unsigned char *pDstBuffer
,
1220 unsigned char *pSrcMemoryPtrs
,
1221 PFORMAT_STRING pFormat
,
1222 unsigned char fMustAlloc
)
1224 unsigned char *Mark
= pStubMsg
->BufferMark
;
1225 unsigned rep
, count
, stride
;
1227 unsigned char *saved_buffer
= NULL
;
1229 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg
, pDstBuffer
, pSrcMemoryPtrs
, pFormat
, fMustAlloc
);
1231 if (*pFormat
!= RPC_FC_PP
) return NULL
;
1234 if (pStubMsg
->PointerBufferMark
)
1236 saved_buffer
= pStubMsg
->Buffer
;
1237 pStubMsg
->Buffer
= pStubMsg
->PointerBufferMark
;
1238 pStubMsg
->PointerBufferMark
= NULL
;
1241 while (pFormat
[0] != RPC_FC_END
) {
1242 TRACE("pFormat[0] = 0x%x\n", pFormat
[0]);
1243 switch (pFormat
[0]) {
1245 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat
[0]);
1247 case RPC_FC_NO_REPEAT
:
1253 case RPC_FC_FIXED_REPEAT
:
1254 rep
= *(const WORD
*)&pFormat
[2];
1255 stride
= *(const WORD
*)&pFormat
[4];
1256 count
= *(const WORD
*)&pFormat
[8];
1259 case RPC_FC_VARIABLE_REPEAT
:
1260 rep
= (pFormat
[1] == RPC_FC_VARIABLE_OFFSET
) ? pStubMsg
->ActualCount
: pStubMsg
->MaxCount
;
1261 stride
= *(const WORD
*)&pFormat
[2];
1262 count
= *(const WORD
*)&pFormat
[6];
1266 for (i
= 0; i
< rep
; i
++) {
1267 PFORMAT_STRING info
= pFormat
;
1268 unsigned char *bufdstbase
= pDstBuffer
+ (i
* stride
);
1269 unsigned char *memsrcbase
= pSrcMemoryPtrs
+ (i
* stride
);
1270 unsigned char *bufbase
= Mark
+ (i
* stride
);
1273 for (u
=0; u
<count
; u
++,info
+=8) {
1274 unsigned char **bufdstptr
= (unsigned char **)(bufdstbase
+ *(const SHORT
*)&info
[2]);
1275 unsigned char **memsrcptr
= (unsigned char **)(memsrcbase
+ *(const SHORT
*)&info
[0]);
1276 unsigned char *bufptr
= bufbase
+ *(const SHORT
*)&info
[2];
1277 PointerUnmarshall(pStubMsg
, bufptr
, bufdstptr
, *memsrcptr
, info
+4, fMustAlloc
);
1280 pFormat
+= 8 * count
;
1285 pStubMsg
->PointerBufferMark
= pStubMsg
->Buffer
;
1286 pStubMsg
->Buffer
= saved_buffer
;
1292 /***********************************************************************
1293 * EmbeddedPointerBufferSize
1295 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg
,
1296 unsigned char *pMemory
,
1297 PFORMAT_STRING pFormat
)
1299 unsigned rep
, count
, stride
;
1301 ULONG saved_buffer_length
= 0;
1303 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
1305 if (pStubMsg
->IgnoreEmbeddedPointers
) return;
1307 if (*pFormat
!= RPC_FC_PP
) return;
1310 if (pStubMsg
->PointerLength
)
1312 saved_buffer_length
= pStubMsg
->BufferLength
;
1313 pStubMsg
->BufferLength
= pStubMsg
->PointerLength
;
1314 pStubMsg
->PointerLength
= 0;
1317 while (pFormat
[0] != RPC_FC_END
) {
1318 switch (pFormat
[0]) {
1320 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat
[0]);
1322 case RPC_FC_NO_REPEAT
:
1328 case RPC_FC_FIXED_REPEAT
:
1329 rep
= *(const WORD
*)&pFormat
[2];
1330 stride
= *(const WORD
*)&pFormat
[4];
1331 count
= *(const WORD
*)&pFormat
[8];
1334 case RPC_FC_VARIABLE_REPEAT
:
1335 rep
= (pFormat
[1] == RPC_FC_VARIABLE_OFFSET
) ? pStubMsg
->ActualCount
: pStubMsg
->MaxCount
;
1336 stride
= *(const WORD
*)&pFormat
[2];
1337 count
= *(const WORD
*)&pFormat
[6];
1341 for (i
= 0; i
< rep
; i
++) {
1342 PFORMAT_STRING info
= pFormat
;
1343 unsigned char *membase
= pMemory
+ (i
* stride
);
1346 for (u
=0; u
<count
; u
++,info
+=8) {
1347 unsigned char *memptr
= membase
+ *(const SHORT
*)&info
[0];
1348 unsigned char *saved_memory
= pStubMsg
->Memory
;
1350 pStubMsg
->Memory
= pMemory
;
1351 PointerBufferSize(pStubMsg
, *(unsigned char**)memptr
, info
+4);
1352 pStubMsg
->Memory
= saved_memory
;
1355 pFormat
+= 8 * count
;
1358 if (saved_buffer_length
)
1360 pStubMsg
->PointerLength
= pStubMsg
->BufferLength
;
1361 pStubMsg
->BufferLength
= saved_buffer_length
;
1365 /***********************************************************************
1366 * EmbeddedPointerMemorySize [internal]
1368 static ULONG
EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg
,
1369 PFORMAT_STRING pFormat
)
1371 unsigned char *Mark
= pStubMsg
->BufferMark
;
1372 unsigned rep
, count
, stride
;
1374 unsigned char *saved_buffer
= NULL
;
1376 TRACE("(%p,%p)\n", pStubMsg
, pFormat
);
1378 if (pStubMsg
->IgnoreEmbeddedPointers
) return 0;
1380 if (pStubMsg
->PointerBufferMark
)
1382 saved_buffer
= pStubMsg
->Buffer
;
1383 pStubMsg
->Buffer
= pStubMsg
->PointerBufferMark
;
1384 pStubMsg
->PointerBufferMark
= NULL
;
1387 if (*pFormat
!= RPC_FC_PP
) return 0;
1390 while (pFormat
[0] != RPC_FC_END
) {
1391 switch (pFormat
[0]) {
1393 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat
[0]);
1395 case RPC_FC_NO_REPEAT
:
1401 case RPC_FC_FIXED_REPEAT
:
1402 rep
= *(const WORD
*)&pFormat
[2];
1403 stride
= *(const WORD
*)&pFormat
[4];
1404 count
= *(const WORD
*)&pFormat
[8];
1407 case RPC_FC_VARIABLE_REPEAT
:
1408 rep
= (pFormat
[1] == RPC_FC_VARIABLE_OFFSET
) ? pStubMsg
->ActualCount
: pStubMsg
->MaxCount
;
1409 stride
= *(const WORD
*)&pFormat
[2];
1410 count
= *(const WORD
*)&pFormat
[6];
1414 for (i
= 0; i
< rep
; i
++) {
1415 PFORMAT_STRING info
= pFormat
;
1416 unsigned char *bufbase
= Mark
+ (i
* stride
);
1418 for (u
=0; u
<count
; u
++,info
+=8) {
1419 unsigned char *bufptr
= bufbase
+ *(const SHORT
*)&info
[2];
1420 PointerMemorySize(pStubMsg
, bufptr
, info
+4);
1423 pFormat
+= 8 * count
;
1428 pStubMsg
->PointerBufferMark
= pStubMsg
->Buffer
;
1429 pStubMsg
->Buffer
= saved_buffer
;
1435 /***********************************************************************
1436 * EmbeddedPointerFree [internal]
1438 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg
,
1439 unsigned char *pMemory
,
1440 PFORMAT_STRING pFormat
)
1442 unsigned rep
, count
, stride
;
1445 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
1446 if (*pFormat
!= RPC_FC_PP
) return;
1449 while (pFormat
[0] != RPC_FC_END
) {
1450 switch (pFormat
[0]) {
1452 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat
[0]);
1454 case RPC_FC_NO_REPEAT
:
1460 case RPC_FC_FIXED_REPEAT
:
1461 rep
= *(const WORD
*)&pFormat
[2];
1462 stride
= *(const WORD
*)&pFormat
[4];
1463 count
= *(const WORD
*)&pFormat
[8];
1466 case RPC_FC_VARIABLE_REPEAT
:
1467 rep
= (pFormat
[1] == RPC_FC_VARIABLE_OFFSET
) ? pStubMsg
->ActualCount
: pStubMsg
->MaxCount
;
1468 stride
= *(const WORD
*)&pFormat
[2];
1469 count
= *(const WORD
*)&pFormat
[6];
1473 for (i
= 0; i
< rep
; i
++) {
1474 PFORMAT_STRING info
= pFormat
;
1475 unsigned char *membase
= pMemory
+ (i
* stride
);
1478 for (u
=0; u
<count
; u
++,info
+=8) {
1479 unsigned char *memptr
= membase
+ *(const SHORT
*)&info
[0];
1480 unsigned char *saved_memory
= pStubMsg
->Memory
;
1482 pStubMsg
->Memory
= pMemory
;
1483 PointerFree(pStubMsg
, *(unsigned char**)memptr
, info
+4);
1484 pStubMsg
->Memory
= saved_memory
;
1487 pFormat
+= 8 * count
;
1491 /***********************************************************************
1492 * NdrPointerMarshall [RPCRT4.@]
1494 unsigned char * WINAPI
NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg
,
1495 unsigned char *pMemory
,
1496 PFORMAT_STRING pFormat
)
1498 unsigned char *Buffer
;
1500 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
1502 /* Increment the buffer here instead of in PointerMarshall,
1503 * as that is used by embedded pointers which already handle the incrementing
1504 * the buffer, and shouldn't write any additional pointer data to the wire */
1505 if (*pFormat
!= RPC_FC_RP
)
1507 align_pointer_clear(&pStubMsg
->Buffer
, 4);
1508 Buffer
= pStubMsg
->Buffer
;
1509 safe_buffer_increment(pStubMsg
, 4);
1512 Buffer
= pStubMsg
->Buffer
;
1514 PointerMarshall(pStubMsg
, Buffer
, pMemory
, pFormat
);
1519 /***********************************************************************
1520 * NdrPointerUnmarshall [RPCRT4.@]
1522 unsigned char * WINAPI
NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg
,
1523 unsigned char **ppMemory
,
1524 PFORMAT_STRING pFormat
,
1525 unsigned char fMustAlloc
)
1527 unsigned char *Buffer
;
1529 TRACE("(%p,%p,%p,%d)\n", pStubMsg
, ppMemory
, pFormat
, fMustAlloc
);
1531 if (*pFormat
== RPC_FC_RP
)
1533 Buffer
= pStubMsg
->Buffer
;
1534 /* Do the NULL ref pointer check here because embedded pointers can be
1535 * NULL if the type the pointer is embedded in was allocated rather than
1536 * being passed in by the client */
1537 if (pStubMsg
->IsClient
&& !*ppMemory
)
1539 ERR("NULL ref pointer is not allowed\n");
1540 RpcRaiseException(RPC_X_NULL_REF_POINTER
);
1545 /* Increment the buffer here instead of in PointerUnmarshall,
1546 * as that is used by embedded pointers which already handle the incrementing
1547 * the buffer, and shouldn't read any additional pointer data from the
1549 align_pointer(&pStubMsg
->Buffer
, 4);
1550 Buffer
= pStubMsg
->Buffer
;
1551 safe_buffer_increment(pStubMsg
, 4);
1554 PointerUnmarshall(pStubMsg
, Buffer
, ppMemory
, *ppMemory
, pFormat
, fMustAlloc
);
1559 /***********************************************************************
1560 * NdrPointerBufferSize [RPCRT4.@]
1562 void WINAPI
NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg
,
1563 unsigned char *pMemory
,
1564 PFORMAT_STRING pFormat
)
1566 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
1568 /* Increment the buffer length here instead of in PointerBufferSize,
1569 * as that is used by embedded pointers which already handle the buffer
1570 * length, and shouldn't write anything more to the wire */
1571 if (*pFormat
!= RPC_FC_RP
)
1573 align_length(&pStubMsg
->BufferLength
, 4);
1574 safe_buffer_length_increment(pStubMsg
, 4);
1577 PointerBufferSize(pStubMsg
, pMemory
, pFormat
);
1580 /***********************************************************************
1581 * NdrPointerMemorySize [RPCRT4.@]
1583 ULONG WINAPI
NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg
,
1584 PFORMAT_STRING pFormat
)
1586 unsigned char *Buffer
= pStubMsg
->Buffer
;
1587 if (*pFormat
!= RPC_FC_RP
)
1589 align_pointer(&pStubMsg
->Buffer
, 4);
1590 safe_buffer_increment(pStubMsg
, 4);
1592 align_length(&pStubMsg
->MemorySize
, sizeof(void *));
1593 return PointerMemorySize(pStubMsg
, Buffer
, pFormat
);
1596 /***********************************************************************
1597 * NdrPointerFree [RPCRT4.@]
1599 void WINAPI
NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg
,
1600 unsigned char *pMemory
,
1601 PFORMAT_STRING pFormat
)
1603 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
1604 PointerFree(pStubMsg
, pMemory
, pFormat
);
1607 /***********************************************************************
1608 * NdrSimpleTypeMarshall [RPCRT4.@]
1610 void WINAPI
NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg
, unsigned char* pMemory
,
1611 unsigned char FormatChar
)
1613 NdrBaseTypeMarshall(pStubMsg
, pMemory
, &FormatChar
);
1616 /***********************************************************************
1617 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1619 * Unmarshall a base type.
1622 * Doesn't check that the buffer is long enough before copying, so the caller
1625 void WINAPI
NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg
, unsigned char* pMemory
,
1626 unsigned char FormatChar
)
1628 #define BASE_TYPE_UNMARSHALL(type) \
1629 align_pointer(&pStubMsg->Buffer, sizeof(type)); \
1630 TRACE("pMemory: %p\n", pMemory); \
1631 *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1632 pStubMsg->Buffer += sizeof(type);
1640 BASE_TYPE_UNMARSHALL(UCHAR
);
1641 TRACE("value: 0x%02x\n", *pMemory
);
1646 BASE_TYPE_UNMARSHALL(USHORT
);
1647 TRACE("value: 0x%04x\n", *(USHORT
*)pMemory
);
1651 case RPC_FC_ERROR_STATUS_T
:
1653 BASE_TYPE_UNMARSHALL(ULONG
);
1654 TRACE("value: 0x%08x\n", *(ULONG
*)pMemory
);
1657 BASE_TYPE_UNMARSHALL(float);
1658 TRACE("value: %f\n", *(float *)pMemory
);
1661 BASE_TYPE_UNMARSHALL(double);
1662 TRACE("value: %f\n", *(double *)pMemory
);
1665 BASE_TYPE_UNMARSHALL(ULONGLONG
);
1666 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG
*)pMemory
));
1669 align_pointer(&pStubMsg
->Buffer
, sizeof(USHORT
));
1670 TRACE("pMemory: %p\n", pMemory
);
1671 /* 16-bits on the wire, but int in memory */
1672 *(UINT
*)pMemory
= *(USHORT
*)pStubMsg
->Buffer
;
1673 pStubMsg
->Buffer
+= sizeof(USHORT
);
1674 TRACE("value: 0x%08x\n", *(UINT
*)pMemory
);
1676 case RPC_FC_INT3264
:
1677 align_pointer(&pStubMsg
->Buffer
, sizeof(INT
));
1678 /* 32-bits on the wire, but int_ptr in memory */
1679 *(INT_PTR
*)pMemory
= *(INT
*)pStubMsg
->Buffer
;
1680 pStubMsg
->Buffer
+= sizeof(INT
);
1681 TRACE("value: 0x%08lx\n", *(INT_PTR
*)pMemory
);
1683 case RPC_FC_UINT3264
:
1684 align_pointer(&pStubMsg
->Buffer
, sizeof(UINT
));
1685 /* 32-bits on the wire, but int_ptr in memory */
1686 *(UINT_PTR
*)pMemory
= *(UINT
*)pStubMsg
->Buffer
;
1687 pStubMsg
->Buffer
+= sizeof(UINT
);
1688 TRACE("value: 0x%08lx\n", *(UINT_PTR
*)pMemory
);
1693 FIXME("Unhandled base type: 0x%02x\n", FormatChar
);
1695 #undef BASE_TYPE_UNMARSHALL
1698 /***********************************************************************
1699 * NdrSimpleStructMarshall [RPCRT4.@]
1701 unsigned char * WINAPI
NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg
,
1702 unsigned char *pMemory
,
1703 PFORMAT_STRING pFormat
)
1705 unsigned size
= *(const WORD
*)(pFormat
+2);
1706 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
1708 align_pointer_clear(&pStubMsg
->Buffer
, pFormat
[1] + 1);
1710 pStubMsg
->BufferMark
= pStubMsg
->Buffer
;
1711 safe_copy_to_buffer(pStubMsg
, pMemory
, size
);
1713 if (pFormat
[0] != RPC_FC_STRUCT
)
1714 EmbeddedPointerMarshall(pStubMsg
, pMemory
, pFormat
+4);
1719 /***********************************************************************
1720 * NdrSimpleStructUnmarshall [RPCRT4.@]
1722 unsigned char * WINAPI
NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg
,
1723 unsigned char **ppMemory
,
1724 PFORMAT_STRING pFormat
,
1725 unsigned char fMustAlloc
)
1727 unsigned size
= *(const WORD
*)(pFormat
+2);
1728 unsigned char *saved_buffer
;
1729 TRACE("(%p,%p,%p,%d)\n", pStubMsg
, ppMemory
, pFormat
, fMustAlloc
);
1731 align_pointer(&pStubMsg
->Buffer
, pFormat
[1] + 1);
1734 *ppMemory
= NdrAllocate(pStubMsg
, size
);
1737 if (!pStubMsg
->IsClient
&& !*ppMemory
)
1738 /* for servers, we just point straight into the RPC buffer */
1739 *ppMemory
= pStubMsg
->Buffer
;
1742 saved_buffer
= pStubMsg
->BufferMark
= pStubMsg
->Buffer
;
1743 safe_buffer_increment(pStubMsg
, size
);
1744 if (pFormat
[0] == RPC_FC_PSTRUCT
)
1745 EmbeddedPointerUnmarshall(pStubMsg
, saved_buffer
, *ppMemory
, pFormat
+4, fMustAlloc
);
1747 TRACE("copying %p to %p\n", saved_buffer
, *ppMemory
);
1748 if (*ppMemory
!= saved_buffer
)
1749 memcpy(*ppMemory
, saved_buffer
, size
);
1754 /***********************************************************************
1755 * NdrSimpleStructBufferSize [RPCRT4.@]
1757 void WINAPI
NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg
,
1758 unsigned char *pMemory
,
1759 PFORMAT_STRING pFormat
)
1761 unsigned size
= *(const WORD
*)(pFormat
+2);
1762 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
1764 align_length(&pStubMsg
->BufferLength
, pFormat
[1] + 1);
1766 safe_buffer_length_increment(pStubMsg
, size
);
1767 if (pFormat
[0] != RPC_FC_STRUCT
)
1768 EmbeddedPointerBufferSize(pStubMsg
, pMemory
, pFormat
+4);
1771 /***********************************************************************
1772 * NdrSimpleStructMemorySize [RPCRT4.@]
1774 ULONG WINAPI
NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg
,
1775 PFORMAT_STRING pFormat
)
1777 unsigned short size
= *(const WORD
*)(pFormat
+2);
1779 TRACE("(%p,%p)\n", pStubMsg
, pFormat
);
1781 align_pointer(&pStubMsg
->Buffer
, pFormat
[1] + 1);
1782 pStubMsg
->MemorySize
+= size
;
1783 safe_buffer_increment(pStubMsg
, size
);
1785 if (pFormat
[0] != RPC_FC_STRUCT
)
1786 EmbeddedPointerMemorySize(pStubMsg
, pFormat
+4);
1787 return pStubMsg
->MemorySize
;
1790 /***********************************************************************
1791 * NdrSimpleStructFree [RPCRT4.@]
1793 void WINAPI
NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg
,
1794 unsigned char *pMemory
,
1795 PFORMAT_STRING pFormat
)
1797 TRACE("(%p,%p,%p)\n", pStubMsg
, pMemory
, pFormat
);
1798 if (pFormat
[0] != RPC_FC_STRUCT
)
1799 EmbeddedPointerFree(pStubMsg
, pMemory
, pFormat
+4);
1804 static inline void array_compute_and_size_conformance(
1805 unsigned char fc
, PMIDL_STUB_MESSAGE pStubMsg
, unsigned char *pMemory
,
1806 PFORMAT_STRING pFormat
)
1813 ComputeConformance(pStubMsg
, pMemory
, pFormat
+4, 0);
1814 SizeConformance(pStubMsg
);
1816 case RPC_FC_CVARRAY
:
1817 pFormat
= ComputeConformance(pStubMsg
, pMemory
, pFormat
+ 4, 0);
1818 pFormat
= ComputeVariance(pStubMsg
, pMemory
, pFormat
, 0);
1819 SizeConformance(pStubMsg
);
1821 case RPC_FC_C_CSTRING
:
1822 case RPC_FC_C_WSTRING
:
1823 if (fc
== RPC_FC_C_CSTRING
)
1825 TRACE("string=%s\n", debugstr_a((const char *)pMemory
));
1826 pStubMsg
->ActualCount
= strlen((const char *)pMemory
)+1;
1830 TRACE("string=%s\n", debugstr_w((LPCWSTR
)pMemory
));
1831 pStubMsg
->ActualCount
= strlenW((LPCWSTR
)pMemory
)+1;
1834 if (pFormat
[1] == RPC_FC_STRING_SIZED
)
1835 pFormat
= ComputeConformance(pStubMsg
, pMemory
, pFormat
+ 2, 0);
1837 pStubMsg
->MaxCount
= pStubMsg
->ActualCount
;
1839 SizeConformance(pStubMsg
);
1841 case RPC_FC_BOGUS_ARRAY
:
1842 count
= *(const WORD
*)(pFormat
+ 2);
1844 if (IsConformanceOrVariancePresent(pFormat
)) SizeConformance(pStubMsg
);
1845 pFormat
= ComputeConformance(pStubMsg
, pMemory
, pFormat
, count
);
1846 pFormat
= ComputeVariance(pStubMsg
, pMemory
, pFormat
, pStubMsg
->MaxCount
);
1849 ERR("unknown array format 0x%x\n", fc
);
1850 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
1854 static inline void array_buffer_size(
1855 unsigned char fc
, PMIDL_STUB_MESSAGE pStubMsg
, unsigned char *pMemory
,
1856 PFORMAT_STRING pFormat
, unsigned char fHasPointers
)
1860 unsigned char alignment
;
1865 esize
= *(const WORD
*)(pFormat
+2);
1866 alignment
= pFormat
[1] + 1;
1868 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
1870 align_length(&pStubMsg
->BufferLength
, alignment
);
1872 size
= safe_multiply(esize
, pStubMsg
->MaxCount
);
1873 /* conformance value plus array */
1874 safe_buffer_length_increment(pStubMsg
, size
);
1877 EmbeddedPointerBufferSize(pStubMsg
, pMemory
, pFormat
);
1879 case RPC_FC_CVARRAY
:
1880 esize
= *(const WORD
*)(pFormat
+2);
1881 alignment
= pFormat
[1] + 1;
1883 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
1884 pFormat
= SkipVariance(pStubMsg
, pFormat
);
1886 SizeVariance(pStubMsg
);
1888 align_length(&pStubMsg
->BufferLength
, alignment
);
1890 size
= safe_multiply(esize
, pStubMsg
->ActualCount
);
1891 safe_buffer_length_increment(pStubMsg
, size
);
1894 EmbeddedPointerBufferSize(pStubMsg
, pMemory
, pFormat
);
1896 case RPC_FC_C_CSTRING
:
1897 case RPC_FC_C_WSTRING
:
1898 if (fc
== RPC_FC_C_CSTRING
)
1903 SizeVariance(pStubMsg
);
1905 size
= safe_multiply(esize
, pStubMsg
->ActualCount
);
1906 safe_buffer_length_increment(pStubMsg
, size
);
1908 case RPC_FC_BOGUS_ARRAY
:
1909 alignment
= pFormat
[1] + 1;
1910 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
1911 if (IsConformanceOrVariancePresent(pFormat
)) SizeVariance(pStubMsg
);
1912 pFormat
= SkipVariance(pStubMsg
, pFormat
);
1914 align_length(&pStubMsg
->BufferLength
, alignment
);
1916 size
= pStubMsg
->ActualCount
;
1917 for (i
= 0; i
< size
; i
++)
1918 pMemory
= ComplexBufferSize(pStubMsg
, pMemory
, pFormat
, NULL
);
1921 ERR("unknown array format 0x%x\n", fc
);
1922 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
1926 static inline void array_compute_and_write_conformance(
1927 unsigned char fc
, PMIDL_STUB_MESSAGE pStubMsg
, unsigned char *pMemory
,
1928 PFORMAT_STRING pFormat
)
1931 BOOL conformance_present
;
1936 ComputeConformance(pStubMsg
, pMemory
, pFormat
+4, 0);
1937 WriteConformance(pStubMsg
);
1939 case RPC_FC_CVARRAY
:
1940 pFormat
= ComputeConformance(pStubMsg
, pMemory
, pFormat
+ 4, 0);
1941 pFormat
= ComputeVariance(pStubMsg
, pMemory
, pFormat
, 0);
1942 WriteConformance(pStubMsg
);
1944 case RPC_FC_C_CSTRING
:
1945 case RPC_FC_C_WSTRING
:
1946 if (fc
== RPC_FC_C_CSTRING
)
1948 TRACE("string=%s\n", debugstr_a((const char *)pMemory
));
1949 pStubMsg
->ActualCount
= strlen((const char *)pMemory
)+1;
1953 TRACE("string=%s\n", debugstr_w((LPCWSTR
)pMemory
));
1954 pStubMsg
->ActualCount
= strlenW((LPCWSTR
)pMemory
)+1;
1956 if (pFormat
[1] == RPC_FC_STRING_SIZED
)
1957 pFormat
= ComputeConformance(pStubMsg
, pMemory
, pFormat
+ 2, 0);
1959 pStubMsg
->MaxCount
= pStubMsg
->ActualCount
;
1960 pStubMsg
->Offset
= 0;
1961 WriteConformance(pStubMsg
);
1963 case RPC_FC_BOGUS_ARRAY
:
1964 def
= *(const WORD
*)(pFormat
+ 2);
1966 conformance_present
= IsConformanceOrVariancePresent(pFormat
);
1967 pFormat
= ComputeConformance(pStubMsg
, pMemory
, pFormat
, def
);
1968 pFormat
= ComputeVariance(pStubMsg
, pMemory
, pFormat
, pStubMsg
->MaxCount
);
1969 if (conformance_present
) WriteConformance(pStubMsg
);
1972 ERR("unknown array format 0x%x\n", fc
);
1973 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
1977 static inline void array_write_variance_and_marshall(
1978 unsigned char fc
, PMIDL_STUB_MESSAGE pStubMsg
, unsigned char *pMemory
,
1979 PFORMAT_STRING pFormat
, unsigned char fHasPointers
)
1983 unsigned char alignment
;
1988 esize
= *(const WORD
*)(pFormat
+2);
1989 alignment
= pFormat
[1] + 1;
1991 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
1993 align_pointer_clear(&pStubMsg
->Buffer
, alignment
);
1995 size
= safe_multiply(esize
, pStubMsg
->MaxCount
);
1997 pStubMsg
->BufferMark
= pStubMsg
->Buffer
;
1998 safe_copy_to_buffer(pStubMsg
, pMemory
, size
);
2001 EmbeddedPointerMarshall(pStubMsg
, pMemory
, pFormat
);
2003 case RPC_FC_CVARRAY
:
2004 esize
= *(const WORD
*)(pFormat
+2);
2005 alignment
= pFormat
[1] + 1;
2007 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
2008 pFormat
= SkipVariance(pStubMsg
, pFormat
);
2010 WriteVariance(pStubMsg
);
2012 align_pointer_clear(&pStubMsg
->Buffer
, alignment
);
2014 size
= safe_multiply(esize
, pStubMsg
->ActualCount
);
2017 pStubMsg
->BufferMark
= pStubMsg
->Buffer
;
2018 safe_copy_to_buffer(pStubMsg
, pMemory
+ pStubMsg
->Offset
, size
);
2021 EmbeddedPointerMarshall(pStubMsg
, pMemory
, pFormat
);
2023 case RPC_FC_C_CSTRING
:
2024 case RPC_FC_C_WSTRING
:
2025 if (fc
== RPC_FC_C_CSTRING
)
2030 WriteVariance(pStubMsg
);
2032 size
= safe_multiply(esize
, pStubMsg
->ActualCount
);
2033 safe_copy_to_buffer(pStubMsg
, pMemory
, size
); /* the string itself */
2035 case RPC_FC_BOGUS_ARRAY
:
2036 alignment
= pFormat
[1] + 1;
2037 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
2038 if (IsConformanceOrVariancePresent(pFormat
)) WriteVariance(pStubMsg
);
2039 pFormat
= SkipVariance(pStubMsg
, pFormat
);
2041 align_pointer_clear(&pStubMsg
->Buffer
, alignment
);
2043 size
= pStubMsg
->ActualCount
;
2044 for (i
= 0; i
< size
; i
++)
2045 pMemory
= ComplexMarshall(pStubMsg
, pMemory
, pFormat
, NULL
);
2048 ERR("unknown array format 0x%x\n", fc
);
2049 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2053 static inline ULONG
array_read_conformance(
2054 unsigned char fc
, PMIDL_STUB_MESSAGE pStubMsg
, PFORMAT_STRING pFormat
)
2061 esize
= *(const WORD
*)(pFormat
+2);
2062 pFormat
= ReadConformance(pStubMsg
, pFormat
+4);
2063 return safe_multiply(esize
, pStubMsg
->MaxCount
);
2064 case RPC_FC_CVARRAY
:
2065 esize
= *(const WORD
*)(pFormat
+2);
2066 pFormat
= ReadConformance(pStubMsg
, pFormat
+4);
2067 return safe_multiply(esize
, pStubMsg
->MaxCount
);
2068 case RPC_FC_C_CSTRING
:
2069 case RPC_FC_C_WSTRING
:
2070 if (fc
== RPC_FC_C_CSTRING
)
2075 if (pFormat
[1] == RPC_FC_STRING_SIZED
)
2076 ReadConformance(pStubMsg
, pFormat
+ 2);
2078 ReadConformance(pStubMsg
, NULL
);
2079 return safe_multiply(esize
, pStubMsg
->MaxCount
);
2080 case RPC_FC_BOGUS_ARRAY
:
2081 def
= *(const WORD
*)(pFormat
+ 2);
2083 if (IsConformanceOrVariancePresent(pFormat
)) pFormat
= ReadConformance(pStubMsg
, pFormat
);
2086 pStubMsg
->MaxCount
= def
;
2087 pFormat
= SkipConformance( pStubMsg
, pFormat
);
2089 pFormat
= SkipVariance( pStubMsg
, pFormat
);
2091 esize
= ComplexStructSize(pStubMsg
, pFormat
);
2092 return safe_multiply(pStubMsg
->MaxCount
, esize
);
2094 ERR("unknown array format 0x%x\n", fc
);
2095 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2099 static inline ULONG
array_read_variance_and_unmarshall(
2100 unsigned char fc
, PMIDL_STUB_MESSAGE pStubMsg
, unsigned char **ppMemory
,
2101 PFORMAT_STRING pFormat
, unsigned char fMustAlloc
,
2102 unsigned char fUseBufferMemoryServer
, unsigned char fUnmarshall
)
2104 ULONG bufsize
, memsize
;
2106 unsigned char alignment
;
2107 unsigned char *saved_buffer
, *pMemory
;
2108 ULONG i
, offset
, count
;
2113 esize
= *(const WORD
*)(pFormat
+2);
2114 alignment
= pFormat
[1] + 1;
2116 bufsize
= memsize
= safe_multiply(esize
, pStubMsg
->MaxCount
);
2118 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
2120 align_pointer(&pStubMsg
->Buffer
, alignment
);
2125 *ppMemory
= NdrAllocate(pStubMsg
, memsize
);
2128 if (fUseBufferMemoryServer
&& !pStubMsg
->IsClient
&& !*ppMemory
)
2129 /* for servers, we just point straight into the RPC buffer */
2130 *ppMemory
= pStubMsg
->Buffer
;
2133 saved_buffer
= pStubMsg
->Buffer
;
2134 safe_buffer_increment(pStubMsg
, bufsize
);
2136 pStubMsg
->BufferMark
= saved_buffer
;
2137 EmbeddedPointerUnmarshall(pStubMsg
, saved_buffer
, *ppMemory
, pFormat
, fMustAlloc
);
2139 TRACE("copying %p to %p\n", saved_buffer
, *ppMemory
);
2140 if (*ppMemory
!= saved_buffer
)
2141 memcpy(*ppMemory
, saved_buffer
, bufsize
);
2144 case RPC_FC_CVARRAY
:
2145 esize
= *(const WORD
*)(pFormat
+2);
2146 alignment
= pFormat
[1] + 1;
2148 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
2150 pFormat
= ReadVariance(pStubMsg
, pFormat
, pStubMsg
->MaxCount
);
2152 align_pointer(&pStubMsg
->Buffer
, alignment
);
2154 bufsize
= safe_multiply(esize
, pStubMsg
->ActualCount
);
2155 memsize
= safe_multiply(esize
, pStubMsg
->MaxCount
);
2159 offset
= pStubMsg
->Offset
;
2161 if (!fMustAlloc
&& !*ppMemory
)
2164 *ppMemory
= NdrAllocate(pStubMsg
, memsize
);
2165 saved_buffer
= pStubMsg
->Buffer
;
2166 safe_buffer_increment(pStubMsg
, bufsize
);
2168 pStubMsg
->BufferMark
= saved_buffer
;
2169 EmbeddedPointerUnmarshall(pStubMsg
, saved_buffer
, *ppMemory
, pFormat
,
2172 memcpy(*ppMemory
+ offset
, saved_buffer
, bufsize
);
2175 case RPC_FC_C_CSTRING
:
2176 case RPC_FC_C_WSTRING
:
2177 if (fc
== RPC_FC_C_CSTRING
)
2182 ReadVariance(pStubMsg
, NULL
, pStubMsg
->MaxCount
);
2184 if (pFormat
[1] != RPC_FC_STRING_SIZED
&& (pStubMsg
->MaxCount
!= pStubMsg
->ActualCount
))
2186 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2187 pStubMsg
->ActualCount
, pStubMsg
->MaxCount
);
2188 RpcRaiseException(RPC_S_INVALID_BOUND
);
2190 if (pStubMsg
->Offset
)
2192 ERR("conformant strings can't have Offset (%d)\n", pStubMsg
->Offset
);
2193 RpcRaiseException(RPC_S_INVALID_BOUND
);
2196 memsize
= safe_multiply(esize
, pStubMsg
->MaxCount
);
2197 bufsize
= safe_multiply(esize
, pStubMsg
->ActualCount
);
2199 validate_string_data(pStubMsg
, bufsize
, esize
);
2204 *ppMemory
= NdrAllocate(pStubMsg
, memsize
);
2207 if (fUseBufferMemoryServer
&& !pStubMsg
->IsClient
&&
2208 !*ppMemory
&& (pStubMsg
->MaxCount
== pStubMsg
->ActualCount
))
2209 /* if the data in the RPC buffer is big enough, we just point
2210 * straight into it */
2211 *ppMemory
= pStubMsg
->Buffer
;
2212 else if (!*ppMemory
)
2213 *ppMemory
= NdrAllocate(pStubMsg
, memsize
);
2216 if (*ppMemory
== pStubMsg
->Buffer
)
2217 safe_buffer_increment(pStubMsg
, bufsize
);
2219 safe_copy_from_buffer(pStubMsg
, *ppMemory
, bufsize
);
2221 if (*pFormat
== RPC_FC_C_CSTRING
)
2222 TRACE("string=%s\n", debugstr_a((char*)*ppMemory
));
2224 TRACE("string=%s\n", debugstr_w((LPWSTR
)*ppMemory
));
2228 case RPC_FC_BOGUS_ARRAY
:
2229 alignment
= pFormat
[1] + 1;
2230 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
2231 pFormat
= ReadVariance(pStubMsg
, pFormat
, pStubMsg
->MaxCount
);
2233 esize
= ComplexStructSize(pStubMsg
, pFormat
);
2234 memsize
= safe_multiply(esize
, pStubMsg
->MaxCount
);
2236 assert( fUnmarshall
);
2238 if (!fMustAlloc
&& !*ppMemory
)
2241 *ppMemory
= NdrAllocate(pStubMsg
, memsize
);
2243 align_pointer(&pStubMsg
->Buffer
, alignment
);
2244 saved_buffer
= pStubMsg
->Buffer
;
2246 pMemory
= *ppMemory
;
2247 count
= pStubMsg
->ActualCount
;
2248 for (i
= 0; i
< count
; i
++)
2249 pMemory
= ComplexUnmarshall(pStubMsg
, pMemory
, pFormat
, NULL
, fMustAlloc
);
2250 return pStubMsg
->Buffer
- saved_buffer
;
2253 ERR("unknown array format 0x%x\n", fc
);
2254 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2258 static inline void array_memory_size(
2259 unsigned char fc
, PMIDL_STUB_MESSAGE pStubMsg
, PFORMAT_STRING pFormat
,
2260 unsigned char fHasPointers
)
2262 ULONG i
, count
, SavedMemorySize
;
2263 ULONG bufsize
, memsize
;
2265 unsigned char alignment
;
2270 esize
= *(const WORD
*)(pFormat
+2);
2271 alignment
= pFormat
[1] + 1;
2273 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
2275 bufsize
= memsize
= safe_multiply(esize
, pStubMsg
->MaxCount
);
2276 pStubMsg
->MemorySize
+= memsize
;
2278 align_pointer(&pStubMsg
->Buffer
, alignment
);
2280 pStubMsg
->BufferMark
= pStubMsg
->Buffer
;
2281 safe_buffer_increment(pStubMsg
, bufsize
);
2284 EmbeddedPointerMemorySize(pStubMsg
, pFormat
);
2286 case RPC_FC_CVARRAY
:
2287 esize
= *(const WORD
*)(pFormat
+2);
2288 alignment
= pFormat
[1] + 1;
2290 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
2292 pFormat
= ReadVariance(pStubMsg
, pFormat
, pStubMsg
->MaxCount
);
2294 bufsize
= safe_multiply(esize
, pStubMsg
->ActualCount
);
2295 memsize
= safe_multiply(esize
, pStubMsg
->MaxCount
);
2296 pStubMsg
->MemorySize
+= memsize
;
2298 align_pointer(&pStubMsg
->Buffer
, alignment
);
2300 pStubMsg
->BufferMark
= pStubMsg
->Buffer
;
2301 safe_buffer_increment(pStubMsg
, bufsize
);
2304 EmbeddedPointerMemorySize(pStubMsg
, pFormat
);
2306 case RPC_FC_C_CSTRING
:
2307 case RPC_FC_C_WSTRING
:
2308 if (fc
== RPC_FC_C_CSTRING
)
2313 ReadVariance(pStubMsg
, NULL
, pStubMsg
->MaxCount
);
2315 if (pFormat
[1] != RPC_FC_STRING_SIZED
&& (pStubMsg
->MaxCount
!= pStubMsg
->ActualCount
))
2317 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2318 pStubMsg
->ActualCount
, pStubMsg
->MaxCount
);
2319 RpcRaiseException(RPC_S_INVALID_BOUND
);
2321 if (pStubMsg
->Offset
)
2323 ERR("conformant strings can't have Offset (%d)\n", pStubMsg
->Offset
);
2324 RpcRaiseException(RPC_S_INVALID_BOUND
);
2327 memsize
= safe_multiply(esize
, pStubMsg
->MaxCount
);
2328 bufsize
= safe_multiply(esize
, pStubMsg
->ActualCount
);
2330 validate_string_data(pStubMsg
, bufsize
, esize
);
2332 safe_buffer_increment(pStubMsg
, bufsize
);
2333 pStubMsg
->MemorySize
+= memsize
;
2335 case RPC_FC_BOGUS_ARRAY
:
2336 alignment
= pFormat
[1] + 1;
2337 pFormat
= SkipConformance(pStubMsg
, pFormat
+ 4);
2338 pFormat
= ReadVariance(pStubMsg
, pFormat
, pStubMsg
->MaxCount
);
2340 align_pointer(&pStubMsg
->Buffer
, alignment
);
2342 SavedMemorySize
= pStubMsg
->MemorySize
;
2344 esize
= ComplexStructSize(pStubMsg
, pFormat
);
2345 memsize
= safe_multiply(pStubMsg
->MaxCount
, esize
);
2347 count
= pStubMsg
->ActualCount
;
2348 for (i
= 0; i
< count
; i
++)
2349 ComplexStructMemorySize(pStubMsg
, pFormat
, NULL
);
2351 pStubMsg
->MemorySize
= SavedMemorySize
+ memsize
;
2354 ERR("unknown array format 0x%x\n", fc
);
2355 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2359 static inline void array_free(
2360 unsigned char fc
, PMIDL_STUB_MESSAGE pStubMsg
,
2361 unsigned char *pMemory
, PFORMAT_STRING pFormat
, unsigned char fHasPointers
)
2368 pFormat
= ComputeConformance(pStubMsg
, pMemory
, pFormat
+4, 0);
2370 EmbeddedPointerFree(pStubMsg
, pMemory
, pFormat
);
2372 case RPC_FC_CVARRAY
:
2373 pFormat
= ComputeConformance(pStubMsg
, pMemory
, pFormat
+4, 0);
2374 pFormat
= ComputeVariance(pStubMsg
, pMemory
, pFormat
, 0);
2376 EmbeddedPointerFree(pStubMsg
, pMemory
, pFormat
);
2378 case RPC_FC_C_CSTRING
:
2379 case RPC_FC_C_WSTRING
:
2380 /* No embedded pointers so nothing to do */
2382 case RPC_FC_BOGUS_ARRAY
:
2383 count
= *(const WORD
*)(pFormat
+ 2);
2384 pFormat
= ComputeConformance(pStubMsg
, pMemory
, pFormat
+ 4, count
);
2385 pFormat
= ComputeVariance(pStubMsg
, pMemory
, pFormat
, pStubMsg
->MaxCount
);
2387 count
= pStubMsg
->ActualCount
;
2388 for (i
= 0; i
< count
; i
++)
2389 pMemory
= ComplexFree(pStubMsg
, pMemory
, pFormat
, NULL
);
2392 ERR("unknown array format 0x%x\n", fc
);
2393 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2398 * NdrConformantString:
2400 * What MS calls a ConformantString is, in DCE terminology,
2401 * a Varying-Conformant String.
2403 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2404 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
2405 * into unmarshalled string)
2406 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2408 * data: CHARTYPE[maxlen]
2410 * ], where CHARTYPE is the appropriate character type (specified externally)
2414 /***********************************************************************
2415 * NdrConformantStringMarshall [RPCRT4.@]
2417 unsigned char *WINAPI
NdrConformantStringMarshall(MIDL_STUB_MESSAGE
*pStubMsg
,
2418 unsigned char *pszMessage
, PFORMAT_STRING pFormat
)
2420 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg
, pszMessage
, pFormat
);
2422 if (pFormat
[0] != RPC_FC_C_CSTRING
&& pFormat
[0] != RPC_FC_C_WSTRING
) {
2423 ERR("Unhandled string type: %#x\n", pFormat
[0]);
2424 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2427 /* allow compiler to optimise inline function by passing constant into
2428 * these functions */
2429 if (pFormat
[0] == RPC_FC_C_CSTRING
) {
2430 array_compute_and_write_conformance(RPC_FC_C_CSTRING
, pStubMsg
, pszMessage
,
2432 array_write_variance_and_marshall(RPC_FC_C_CSTRING
, pStubMsg
, pszMessage
,
2433 pFormat
, TRUE
/* fHasPointers */);
2435 array_compute_and_write_conformance(RPC_FC_C_WSTRING
, pStubMsg
, pszMessage
,
2437 array_write_variance_and_marshall(RPC_FC_C_WSTRING
, pStubMsg
, pszMessage
,
2438 pFormat
, TRUE
/* fHasPointers */);
2444 /***********************************************************************
2445 * NdrConformantStringBufferSize [RPCRT4.@]
2447 void WINAPI
NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg
,
2448 unsigned char* pMemory
, PFORMAT_STRING pFormat
)
2450 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg
, pMemory
, pFormat
);
2452 if (pFormat
[0] != RPC_FC_C_CSTRING
&& pFormat
[0] != RPC_FC_C_WSTRING
) {
2453 ERR("Unhandled string type: %#x\n", pFormat
[0]);
2454 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2457 /* allow compiler to optimise inline function by passing constant into
2458 * these functions */
2459 if (pFormat
[0] == RPC_FC_C_CSTRING
) {
2460 array_compute_and_size_conformance(RPC_FC_C_CSTRING
, pStubMsg
, pMemory
,
2462 array_buffer_size(RPC_FC_C_CSTRING
, pStubMsg
, pMemory
, pFormat
,
2463 TRUE
/* fHasPointers */);
2465 array_compute_and_size_conformance(RPC_FC_C_WSTRING
, pStubMsg
, pMemory
,
2467 array_buffer_size(RPC_FC_C_WSTRING
, pStubMsg
, pMemory
, pFormat
,
2468 TRUE
/* fHasPointers */);
2472 /************************************************************************
2473 * NdrConformantStringMemorySize [RPCRT4.@]
2475 ULONG WINAPI
NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg
,
2476 PFORMAT_STRING pFormat
)
2478 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg
, pFormat
);
2480 if (pFormat
[0] != RPC_FC_C_CSTRING
&& pFormat
[0] != RPC_FC_C_WSTRING
) {
2481 ERR("Unhandled string type: %#x\n", pFormat
[0]);
2482 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2485 /* allow compiler to optimise inline function by passing constant into
2486 * these functions */
2487 if (pFormat
[0] == RPC_FC_C_CSTRING
) {
2488 array_read_conformance(RPC_FC_C_CSTRING
, pStubMsg
, pFormat
);
2489 array_memory_size(RPC_FC_C_CSTRING
, pStubMsg
, pFormat
,
2490 TRUE
/* fHasPointers */);
2492 array_read_conformance(RPC_FC_C_WSTRING
, pStubMsg
, pFormat
);
2493 array_memory_size(RPC_FC_C_WSTRING
, pStubMsg
, pFormat
,
2494 TRUE
/* fHasPointers */);
2497 return pStubMsg
->MemorySize
;
2500 /************************************************************************
2501 * NdrConformantStringUnmarshall [RPCRT4.@]
2503 unsigned char *WINAPI
NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg
,
2504 unsigned char** ppMemory
, PFORMAT_STRING pFormat
, unsigned char fMustAlloc
)
2506 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2507 pStubMsg
, *ppMemory
, pFormat
, fMustAlloc
);
2509 if (pFormat
[0] != RPC_FC_C_CSTRING
&& pFormat
[0] != RPC_FC_C_WSTRING
) {
2510 ERR("Unhandled string type: %#x\n", *pFormat
);
2511 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2514 /* allow compiler to optimise inline function by passing constant into
2515 * these functions */
2516 if (pFormat
[0] == RPC_FC_C_CSTRING
) {
2517 array_read_conformance(RPC_FC_C_CSTRING
, pStubMsg
, pFormat
);
2518 array_read_variance_and_unmarshall(RPC_FC_C_CSTRING
, pStubMsg
, ppMemory
,
2519 pFormat
, fMustAlloc
,
2520 TRUE
/* fUseBufferMemoryServer */,
2521 TRUE
/* fUnmarshall */);
2523 array_read_conformance(RPC_FC_C_WSTRING
, pStubMsg
, pFormat
);
2524 array_read_variance_and_unmarshall(RPC_FC_C_WSTRING
, pStubMsg
, ppMemory
,
2525 pFormat
, fMustAlloc
,
2526 TRUE
/* fUseBufferMemoryServer */,
2527 TRUE
/* fUnmarshall */);
2533 /***********************************************************************
2534 * NdrNonConformantStringMarshall [RPCRT4.@]
2536 unsigned char * WINAPI
NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg
,
2537 unsigned char *pMemory
,
2538 PFORMAT_STRING pFormat
)
2540 ULONG esize
, size
, maxsize
;
2542 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg
, pMemory
, pFormat
);
2544 maxsize
= *(const USHORT
*)&pFormat
[2];
2546 if (*pFormat
== RPC_FC_CSTRING
)
2549 const char *str
= (const char *)pMemory
;
2550 while (i
< maxsize
&& str
[i
]) i
++;
2551 TRACE("string=%s\n", debugstr_an(str
, i
));
2552 pStubMsg
->ActualCount
= i
+ 1;
2555 else if (*pFormat
== RPC_FC_WSTRING
)
2558 const WCHAR
*str
= (const WCHAR
*)pMemory
;
2559 while (i
< maxsize
&& str
[i
]) i
++;
2560 TRACE("string=%s\n", debugstr_wn(str
, i
));
2561 pStubMsg
->ActualCount
= i
+ 1;
2566 ERR("Unhandled string type: %#x\n", *pFormat
);
2567 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2570 pStubMsg
->Offset
= 0;
2571 WriteVariance(pStubMsg
);
2573 size
= safe_multiply(esize
, pStubMsg
->ActualCount
);
2574 safe_copy_to_buffer(pStubMsg
, pMemory
, size
); /* the string itself */
2579 /***********************************************************************
2580 * NdrNonConformantStringUnmarshall [RPCRT4.@]
2582 unsigned char * WINAPI
NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg
,
2583 unsigned char **ppMemory
,
2584 PFORMAT_STRING pFormat
,
2585 unsigned char fMustAlloc
)
2587 ULONG bufsize
, memsize
, esize
, maxsize
;
2589 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2590 pStubMsg
, *ppMemory
, pFormat
, fMustAlloc
);
2592 maxsize
= *(const USHORT
*)&pFormat
[2];
2594 ReadVariance(pStubMsg
, NULL
, maxsize
);
2595 if (pStubMsg
->Offset
)
2597 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg
->Offset
);
2598 RpcRaiseException(RPC_S_INVALID_BOUND
);
2601 if (*pFormat
== RPC_FC_CSTRING
) esize
= 1;
2602 else if (*pFormat
== RPC_FC_WSTRING
) esize
= 2;
2605 ERR("Unhandled string type: %#x\n", *pFormat
);
2606 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2609 memsize
= esize
* maxsize
;
2610 bufsize
= safe_multiply(esize
, pStubMsg
->ActualCount
);
2612 validate_string_data(pStubMsg
, bufsize
, esize
);
2614 if (!fMustAlloc
&& !*ppMemory
)
2617 *ppMemory
= NdrAllocate(pStubMsg
, memsize
);
2619 safe_copy_from_buffer(pStubMsg
, *ppMemory
, bufsize
);
2621 if (*pFormat
== RPC_FC_CSTRING
) {
2622 TRACE("string=%s\n", debugstr_an((char*)*ppMemory
, pStubMsg
->ActualCount
));
2624 else if (*pFormat
== RPC_FC_WSTRING
) {
2625 TRACE("string=%s\n", debugstr_wn((LPWSTR
)*ppMemory
, pStubMsg
->ActualCount
));
2631 /***********************************************************************
2632 * NdrNonConformantStringBufferSize [RPCRT4.@]
2634 void WINAPI
NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg
,
2635 unsigned char *pMemory
,
2636 PFORMAT_STRING pFormat
)
2638 ULONG esize
, maxsize
;
2640 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg
, pMemory
, pFormat
);
2642 maxsize
= *(const USHORT
*)&pFormat
[2];
2644 SizeVariance(pStubMsg
);
2646 if (*pFormat
== RPC_FC_CSTRING
)
2649 const char *str
= (const char *)pMemory
;
2650 while (i
< maxsize
&& str
[i
]) i
++;
2651 TRACE("string=%s\n", debugstr_an(str
, i
));
2652 pStubMsg
->ActualCount
= i
+ 1;
2655 else if (*pFormat
== RPC_FC_WSTRING
)
2658 const WCHAR
*str
= (const WCHAR
*)pMemory
;
2659 while (i
< maxsize
&& str
[i
]) i
++;
2660 TRACE("string=%s\n", debugstr_wn(str
, i
));
2661 pStubMsg
->ActualCount
= i
+ 1;
2666 ERR("Unhandled string type: %#x\n", *pFormat
);
2667 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2670 safe_buffer_length_increment(pStubMsg
, safe_multiply(esize
, pStubMsg
->ActualCount
));
2673 /***********************************************************************
2674 * NdrNonConformantStringMemorySize [RPCRT4.@]
2676 ULONG WINAPI
NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg
,
2677 PFORMAT_STRING pFormat
)
2679 ULONG bufsize
, memsize
, esize
, maxsize
;
2681 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg
, pFormat
);
2683 maxsize
= *(const USHORT
*)&pFormat
[2];
2685 ReadVariance(pStubMsg
, NULL
, maxsize
);
2687 if (pStubMsg
->Offset
)
2689 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg
->Offset
);
2690 RpcRaiseException(RPC_S_INVALID_BOUND
);
2693 if (*pFormat
== RPC_FC_CSTRING
) esize
= 1;
2694 else if (*pFormat
== RPC_FC_WSTRING
) esize
= 2;
2697 ERR("Unhandled string type: %#x\n", *pFormat
);
2698 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2701 memsize
= esize
* maxsize
;
2702 bufsize
= safe_multiply(esize
, pStubMsg
->ActualCount
);
2704 validate_string_data(pStubMsg
, bufsize
, esize
);
2706 safe_buffer_increment(pStubMsg
, bufsize
);
2707 pStubMsg
->MemorySize
+= memsize
;
2709 return pStubMsg
->MemorySize
;
2714 #include "pshpack1.h"
2718 unsigned char flags_type
; /* flags in upper nibble, type in lower nibble */
2722 #include "poppack.h"
2724 static ULONG
EmbeddedComplexSize(MIDL_STUB_MESSAGE
*pStubMsg
,
2725 PFORMAT_STRING pFormat
)
2729 case RPC_FC_PSTRUCT
:
2730 case RPC_FC_CSTRUCT
:
2731 case RPC_FC_BOGUS_STRUCT
:
2732 case RPC_FC_SMFARRAY
:
2733 case RPC_FC_SMVARRAY
:
2734 case RPC_FC_CSTRING
:
2735 return *(const WORD
*)&pFormat
[2];
2736 case RPC_FC_USER_MARSHAL
:
2737 return *(const WORD
*)&pFormat
[4];
2738 case RPC_FC_RANGE
: {
2739 switch (((const NDR_RANGE
*)pFormat
)->flags_type
& 0xf) {
2744 return sizeof(UCHAR
);
2748 return sizeof(USHORT
);
2752 case RPC_FC_INT3264
:
2753 case RPC_FC_UINT3264
:
2754 return sizeof(ULONG
);
2756 return sizeof(float);
2758 return sizeof(double);
2760 return sizeof(ULONGLONG
);
2762 return sizeof(UINT
);
2764 ERR("unknown type 0x%x\n", ((const NDR_RANGE
*)pFormat
)->flags_type
& 0xf);
2765 RpcRaiseException(RPC_X_BAD_STUB_DATA
);
2768 case RPC_FC_NON_ENCAPSULATED_UNION
:
2770 if (pStubMsg
->fHasNewCorrDesc
)
2775 pFormat
+= *(const SHORT
*)pFormat
;
2776 return *(const SHORT
*)pFormat
;
2778 return sizeof(void *);
2779 case RPC_FC_WSTRING
:
2780 return *(const WORD
*)&pFormat
[2] * 2;
2782 FIXME("unhandled embedded type %02x\n", *pFormat
);
2788 static ULONG
EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg
,
2789 PFORMAT_STRING pFormat
)
2791 NDR_MEMORYSIZE m
= NdrMemorySizer
[*pFormat
& NDR_TABLE_MASK
];
2795 FIXME("no memorysizer for data type=%02x\n", *pFormat
);
2799 return m(pStubMsg
, pFormat
);
2803 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg
,
2804 unsigned char *pMemory
,
2805 PFORMAT_STRING pFormat
,
2806 PFORMAT_STRING pPointer
)
2808 PFORMAT_STRING desc
;
2812 while (*pFormat
!= RPC_FC_END
) {
2818 TRACE("byte=%d <= %p\n", *(WORD
*)pMemory
, pMemory
);
2819 safe_copy_to_buffer(pStubMsg
, pMemory
, 1);
2825 TRACE("short=%d <= %p\n", *(WORD
*)pMemory
, pMemory
);
2826 safe_copy_to_buffer(pStubMsg
, pMemory
, 2);
2831 USHORT val
= *(DWORD
*)pMemory
;
2832 TRACE("enum16=%d <= %p\n", *(DWORD
*)pMemory
, pMemory
);
2833 if (32767 < *(DWORD
*)pMemory
)
2834 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE
);
2835 safe_copy_to_buffer(pStubMsg
, &val
, 2);
2842 TRACE("long=%d <= %p\n", *(DWORD
*)pMemory
, pMemory
);
2843 safe_copy_to_buffer(pStubMsg
, pMemory
, 4);
2846 case RPC_FC_INT3264
:
2847 case RPC_FC_UINT3264
:
2849 UINT val
= *(UINT_PTR
*)pMemory
;
2850 TRACE("int3264=%ld <= %p\n", *(UINT_PTR
*)pMemory
, pMemory
);
2851 safe_copy_to_buffer(pStubMsg
, &val
, sizeof(UINT
));
2852 pMemory
+= sizeof(UINT_PTR
);
2856 TRACE("float=%f <= %p\n", *(float*)pMemory
, pMemory
);
2857 safe_copy_to_buffer(pStubMsg
, pMemory
, sizeof(float));
2858 pMemory
+= sizeof(float);
2861 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG
*)pMemory
), pMemory
);
2862 safe_copy_to_buffer(pStubMsg
, pMemory
, 8);
2866 TRACE("double=%f <= %p\n", *(double*)pMemory
, pMemory
);
2867 safe_copy_to_buffer(pStubMsg
, pMemory
, sizeof(double));
2868 pMemory
+= sizeof(double);
2874 case RPC_FC_POINTER
:
2876 unsigned char *saved_buffer
;
2877 BOOL pointer_buffer_mark_set
= FALSE
;
2878 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory
, pMemory
);
2879 TRACE("pStubMsg->Buffer before %p\n", pStubMsg
->Buffer
);
2880 if (*pFormat
!= RPC_FC_POINTER
)
2882 if (*pPointer
!= RPC_FC_RP
)
2883 align_pointer_clear(&pStubMsg
->Buffer
, 4);
2884 saved_buffer
= pStubMsg
->Buffer
;
2885 if (pStubMsg
->PointerBufferMark
)
2887 pStubMsg
->Buffer
= pStubMsg
->PointerBufferMark
;
2888 pStubMsg
->PointerBufferMark
= NULL
;
2889 pointer_buffer_mark_set
= TRUE
;
2891 else if (*pPointer
!= RPC_FC_RP
)
2892 safe_buffer_increment(pStubMsg
, 4); /* for pointer ID */
2893 PointerMarshall(pStubMsg
, saved_buffer
, *(unsigned char**)pMemory
, pPointer
);
2894 if (pointer_buffer_mark_set
)
2896 STD_OVERFLOW_CHECK(pStubMsg
);
2897 pStubMsg
->PointerBufferMark
= pStubMsg
->Buffer
;
2898 pStubMsg
->Buffer
= saved_buffer
;
2899 if (*pPointer
!= RPC_FC_RP
)
2900 safe_buffer_increment(pStubMsg
, 4); /* for pointer ID */
2902 TRACE("pStubMsg->Buffer after %p\n", pStubMsg
->Buffer
);
2903 if (*pFormat
== RPC_FC_POINTER
)
2907 pMemory
+= sizeof(void *);
2910 case RPC_FC_ALIGNM2
:
2911 align_pointer(&pMemory
, 2);
2913 case RPC_FC_ALIGNM4
:
2914 align_pointer(&pMemory
, 4);
2916 case RPC_FC_ALIGNM8
:
2917 align_pointer(&pMemory
, 8);
2919 case RPC_FC_STRUCTPAD1
:
2920 case RPC_FC_STRUCTPAD2
:
2921 case RPC_FC_STRUCTPAD3
:
2922 case RPC_FC_STRUCTPAD4
:
2923 case RPC_FC_STRUCTPAD5
:
2924 case RPC_FC_STRUCTPAD6
:
2925 case RPC_FC_STRUCTPAD7
:
2926 pMemory
+= *pFormat
- RPC_FC_STRUCTPAD1
+ 1;
2928 case RPC_FC_EMBEDDED_COMPLEX
:
2929 pMemory
+= pFormat
[1];
2931 desc
= pFormat
+ *(const SHORT
*)pFormat
;
2932 size
= EmbeddedComplexSize(pStubMsg
, desc
);
2933 TRACE("embedded complex (size=%d) <= %p\n", size
, pMemory
);
2934 m
= NdrMarshaller
[*desc
& NDR_TABLE_MASK
];
2937 /* for some reason interface pointers aren't generated as
2938 * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
2939 * they still need the derefencing treatment that pointers are
2941 if (*desc
== RPC_FC_IP
)
2942 m(pStubMsg
, *(unsigned char **)pMemory
, desc
);
2944 m(pStubMsg
, pMemory
, desc
);
2946 else FIXME("no marshaller for embedded type %02x\n", *desc
);
2953 FIXME("unhandled format 0x%02x\n", *pFormat
);
2961 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg
,
2962 unsigned char *pMemory
,
2963 PFORMAT_STRING pFormat
,
2964 PFORMAT_STRING pPointer
,
2965 unsigned char fMustAlloc
)
2967 PFORMAT_STRING desc
;
2971 while (*pFormat
!= RPC_FC_END
) {
2977 safe_copy_from_buffer(pStubMsg
, pMemory
, 1);
2978 TRACE("byte=%d => %p\n", *(WORD
*)pMemory
, pMemory
);
2984 safe_copy_from_buffer(pStubMsg
, pMemory
, 2);
2985 TRACE("short=%d => %p\n", *(WORD
*)pMemory
, pMemory
);
2991 safe_copy_from_buffer(pStubMsg
, &val
, 2);
2992 *(DWORD
*)pMemory
= val
;
2993 TRACE("enum16=%d => %p\n", *(DWORD
*)pMemory
, pMemory
);
2994 if (32767 < *(DWORD
*)pMemory
)
2995 RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE
);
3002 safe_copy_from_buffer(pStubMsg
, pMemory
, 4);
3003 TRACE("long=%d => %p\n", *(DWORD
*)pMemory
, pMemory
);
3006 case RPC_FC_INT3264
:
3009 safe_copy_from_buffer(pStubMsg
, &val
, 4);
3010 *(INT_PTR
*)pMemory
= val
;
3011 TRACE("int3264=%ld => %p\n", *(INT_PTR
*)pMemory
, pMemory
);
3012 pMemory
+= sizeof(INT_PTR
);
3015 case RPC_FC_UINT3264
:
3018 safe_copy_from_buffer(pStubMsg
, &val
, 4);
3019 *(UINT_PTR
*)pMemory
= val
;
3020 TRACE("uint3264=%ld => %p\n", *(UINT_PTR
*)pMemory
, pMemory
);
3021 pMemory
+= sizeof(UINT_PTR
);
3025 safe_copy_from_buffer(pStubMsg
, pMemory
, sizeof(float));
3026 TRACE("float=%f => %p\n", *(float*)pMemory
, pMemory
);
3027 pMemory
+= sizeof(float);
3030 safe_copy_from_buffer(pStubMsg
, pMemory
, 8);
3031 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG
*)pMemory
), pMemory
);
3035 safe_copy_from_buffer(pStubMsg
, pMemory
, sizeof(double));
3036 TRACE("double=%f => %p\n", *(double*)pMemory
, pMemory
);
3037 pMemory
+= sizeof(double);
3043 case RPC_FC_POINTER
:
3045 unsigned char *saved_buffer
;
3046 BOOL pointer_buffer_mark_set
= FALSE
;
3047 TRACE("pointer => %p\n", pMemory
);
3048 if (*pFormat
!= RPC_FC_POINTER
)
3050 if (*pPointer
!= RPC_FC_RP
)
3051 align_pointer(&pStubMsg
->Buffer
, 4);
3052 saved_buffer
= pStubMsg
->Buffer
;
3053 if (pStubMsg
->PointerBufferMark
)
3055 pStubMsg
->Buffer
= pStubMsg
->PointerBufferMark
;
3056 pStubMsg
->PointerBufferMark
= NULL
;