ReactOS 0.4.16-dev-92-g0c2cdca
ndr_marshall.c
Go to the documentation of this file.
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 <assert.h>
31#include <stdarg.h>
32#include <stdio.h>
33#include <string.h>
34#include <limits.h>
35
36#define NONAMELESSUNION
37#include "windef.h"
38#include "winbase.h"
39#include "winerror.h"
40
41#include "ndr_misc.h"
42#include "rpcndr.h"
43#include "ndrtypes.h"
44
45#include "wine/debug.h"
46
48
49#if defined(__i386__)
50# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
51 (*((UINT32 *)(pchar)) = (uint32))
52
53# define LITTLE_ENDIAN_UINT32_READ(pchar) \
54 (*((UINT32 *)(pchar)))
55#else
56 /* these would work for i386 too, but less efficient */
57# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
58 (*(pchar) = LOBYTE(LOWORD(uint32)), \
59 *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
60 *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
61 *((pchar)+3) = HIBYTE(HIWORD(uint32)))
62
63# define LITTLE_ENDIAN_UINT32_READ(pchar) \
64 (MAKELONG( \
65 MAKEWORD(*(pchar), *((pchar)+1)), \
66 MAKEWORD(*((pchar)+2), *((pchar)+3))))
67#endif
68
69#define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
70 (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
71 *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
72 *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
73 *(pchar) = HIBYTE(HIWORD(uint32)))
74
75#define BIG_ENDIAN_UINT32_READ(pchar) \
76 (MAKELONG( \
77 MAKEWORD(*((pchar)+3), *((pchar)+2)), \
78 MAKEWORD(*((pchar)+1), *(pchar))))
79
80#ifdef NDR_LOCAL_IS_BIG_ENDIAN
81# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
82 BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
83# define NDR_LOCAL_UINT32_READ(pchar) \
84 BIG_ENDIAN_UINT32_READ(pchar)
85#else
86# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
87 LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
88# define NDR_LOCAL_UINT32_READ(pchar) \
89 LITTLE_ENDIAN_UINT32_READ(pchar)
90#endif
91
92static inline void align_length( ULONG *len, unsigned int align )
93{
94 *len = (*len + align - 1) & ~(align - 1);
95}
96
97static inline void align_pointer( unsigned char **ptr, unsigned int align )
98{
99 ULONG_PTR mask = align - 1;
100 *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
101}
102
103static inline void align_pointer_clear( unsigned char **ptr, unsigned int align )
104{
105 ULONG_PTR mask = align - 1;
106 memset( *ptr, 0, (align - (ULONG_PTR)*ptr) & mask );
107 *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
108}
109
110static inline void align_pointer_offset( unsigned char **ptr, unsigned char *base, unsigned int align )
111{
112 ULONG_PTR mask = align - 1;
113 *ptr = base + (((ULONG_PTR)(*ptr - base) + mask) & ~mask);
114}
115
116static inline void align_pointer_offset_clear( unsigned char **ptr, unsigned char *base, unsigned int align )
117{
118 ULONG_PTR mask = align - 1;
119 memset( *ptr, 0, (align - (ULONG_PTR)(*ptr - base)) & mask );
120 *ptr = base + (((ULONG_PTR)(*ptr - base) + mask) & ~mask);
121}
122
123#define STD_OVERFLOW_CHECK(_Msg) do { \
124 TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
125 if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
126 ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
127 } while (0)
128
129#define NDR_POINTER_ID_BASE 0x20000
130#define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
131#define NDR_TABLE_SIZE 128
132#define NDR_TABLE_MASK 127
133
134static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
135static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
137static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
139
140static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
142static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
143
144static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
145static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
147static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
148
150
151static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
152 unsigned char *pMemory,
153 PFORMAT_STRING pFormat,
154 PFORMAT_STRING pPointer);
155static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
156 unsigned char *pMemory,
157 PFORMAT_STRING pFormat,
158 PFORMAT_STRING pPointer);
159static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
160 unsigned char *pMemory,
161 PFORMAT_STRING pFormat,
162 PFORMAT_STRING pPointer,
163 unsigned char fMustAlloc);
165 PFORMAT_STRING pFormat,
166 PFORMAT_STRING pPointer);
167static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
168 unsigned char *pMemory,
169 PFORMAT_STRING pFormat,
170 PFORMAT_STRING pPointer);
171
173 0,
178 /* 0x10 */
180 /* 0x11 */
183 /* 0x15 */
188 /* 0x1b */
194 /* 0x22 */
198 /* 0x2a */
203 /* 0x2f */
205 /* 0x30 */
207 /* 0xb1 */
208 0, 0, 0,
210 0, 0,
211 /* 0xb7 */
215};
217 0,
222 /* 0x10 */
224 /* 0x11 */
227 /* 0x15 */
232 /* 0x1b */
238 /* 0x22 */
242 /* 0x2a */
247 /* 0x2f */
249 /* 0x30 */
251 /* 0xb1 */
252 0, 0, 0,
254 0, 0,
255 /* 0xb7 */
259};
261 0,
266 /* 0x10 */
268 /* 0x11 */
271 /* 0x15 */
276 /* 0x1b */
282 /* 0x22 */
286 /* 0x2a */
291 /* 0x2f */
293 /* 0x30 */
295 /* 0xb1 */
296 0, 0, 0,
298 0, 0,
299 /* 0xb7 */
303};
305 0,
310 /* 0x10 */
312 /* 0x11 */
315 /* 0x15 */
320 /* 0x1b */
326 /* 0x22 */
330 /* 0x2a */
335 /* 0x2f */
337 /* 0x30 */
338 0,
339 /* 0xb1 */
340 0, 0, 0,
342 0, 0,
343 /* 0xb7 */
347};
349 0,
354 /* 0x10 */
356 /* 0x11 */
359 /* 0x15 */
364 /* 0x1b */
370 /* 0x22 */
371 0, 0, 0,
372 0, 0, 0, 0, 0,
373 /* 0x2a */
376 0,
378 /* 0x2f */
380 /* 0x30 */
381 0,
382 /* 0xb1 */
383 0, 0, 0,
385 0, 0,
386 /* 0xb7 */
390};
391
392typedef struct _NDR_MEMORY_LIST
393{
399
400#define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
401
402/***********************************************************************
403 * NdrAllocate [RPCRT4.@]
404 *
405 * Allocates a block of memory using pStubMsg->pfnAllocate.
406 *
407 * PARAMS
408 * pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
409 * len [I] Size of memory block to allocate.
410 *
411 * RETURNS
412 * The memory block of size len that was allocated.
413 *
414 * NOTES
415 * The memory block is always 8-byte aligned.
416 * If the function is unable to allocate memory an RPC_X_NO_MEMORY
417 * exception is raised.
418 */
420{
421 SIZE_T aligned_len;
422 SIZE_T adjusted_len;
423 void *p;
424 NDR_MEMORY_LIST *mem_list;
425
426 aligned_len = (len + 7) & ~7;
427 adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
428 /* check for overflow */
429 if (adjusted_len < len)
430 {
431 ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len);
433 }
434
435 p = pStubMsg->pfnAllocate(adjusted_len);
437
438 mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
439 mem_list->magic = MEML_MAGIC;
440 mem_list->size = aligned_len;
441 mem_list->reserved = 0;
442 mem_list->next = pStubMsg->pMemoryList;
443 pStubMsg->pMemoryList = mem_list;
444
445 TRACE("-- %p\n", p);
446 return p;
447}
448
450{
451 void *mem = NdrAllocate(stubmsg, len);
452 memset(mem, 0, len);
453 return mem;
454}
455
456static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
457{
458 TRACE("(%p, %p)\n", pStubMsg, Pointer);
459
460 pStubMsg->pfnFree(Pointer);
461}
462
464{
465 return (*(const ULONG *)pFormat != -1);
466}
467
468static inline PFORMAT_STRING SkipConformance(const PMIDL_STUB_MESSAGE pStubMsg, const PFORMAT_STRING pFormat)
469{
470 return pFormat + 4 + pStubMsg->CorrDespIncrement;
471}
472
474{
475 align_pointer(&pStubMsg->Buffer, 4);
476 if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
478 pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
479 pStubMsg->Buffer += 4;
480 TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
481 return SkipConformance(pStubMsg, pFormat);
482}
483
484static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
485{
486 if (pFormat && !IsConformanceOrVariancePresent(pFormat))
487 {
488 pStubMsg->Offset = 0;
489 pStubMsg->ActualCount = pStubMsg->MaxCount;
490 goto done;
491 }
492
493 align_pointer(&pStubMsg->Buffer, 4);
494 if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
496 pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
497 pStubMsg->Buffer += 4;
498 TRACE("offset is %d\n", pStubMsg->Offset);
499 pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
500 pStubMsg->Buffer += 4;
501 TRACE("variance is %d\n", pStubMsg->ActualCount);
502
503 if ((pStubMsg->ActualCount > MaxValue) ||
504 (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
505 {
506 ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
507 pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
509 return NULL;
510 }
511
512done:
513 return SkipConformance(pStubMsg, pFormat);
514}
515
516/* writes the conformance value to the buffer */
517static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
518{
519 align_pointer_clear(&pStubMsg->Buffer, 4);
520 if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
522 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
523 pStubMsg->Buffer += 4;
524}
525
526/* writes the variance values to the buffer */
527static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
528{
529 align_pointer_clear(&pStubMsg->Buffer, 4);
530 if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
532 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
533 pStubMsg->Buffer += 4;
534 NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
535 pStubMsg->Buffer += 4;
536}
537
538/* requests buffer space for the conformance value */
539static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
540{
541 align_length(&pStubMsg->BufferLength, 4);
542 if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
544 pStubMsg->BufferLength += 4;
545}
546
547/* requests buffer space for the variance values */
548static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
549{
550 align_length(&pStubMsg->BufferLength, 4);
551 if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
553 pStubMsg->BufferLength += 8;
554}
555
557 MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
558 PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
559{
560 BYTE dtype = pFormat[0] & 0xf;
561 short ofs = *(const short *)&pFormat[2];
562 LPVOID ptr = NULL;
563 ULONG_PTR data = 0;
564
565 if (!IsConformanceOrVariancePresent(pFormat)) {
566 /* null descriptor */
567 *pCount = def;
568 goto finish_conf;
569 }
570
571 switch (pFormat[0] & 0xf0) {
573 TRACE("normal conformance, ofs=%d\n", ofs);
574 ptr = pMemory;
575 break;
577 TRACE("pointer conformance, ofs=%d\n", ofs);
578 ptr = pStubMsg->Memory;
579 break;
581 TRACE("toplevel conformance, ofs=%d\n", ofs);
582 if (pStubMsg->StackTop) {
583 ptr = pStubMsg->StackTop;
584 }
585 else {
586 /* -Os mode, *pCount is already set */
587 goto finish_conf;
588 }
589 break;
591 data = ofs | ((DWORD)pFormat[1] << 16);
592 TRACE("constant conformance, val=%ld\n", data);
593 *pCount = data;
594 goto finish_conf;
596 FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
597 if (pStubMsg->StackTop) {
598 ptr = pStubMsg->StackTop;
599 }
600 else {
601 /* ? */
602 goto done_conf_grab;
603 }
604 break;
605 default:
606 FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0);
607 goto finish_conf;
608 }
609
610 switch (pFormat[1]) {
611 case FC_DEREFERENCE:
612 ptr = *(LPVOID*)((char *)ptr + ofs);
613 break;
614 case FC_CALLBACK:
615 {
616 unsigned char *old_stack_top = pStubMsg->StackTop;
617 ULONG_PTR max_count, old_max_count = pStubMsg->MaxCount;
618
619 pStubMsg->StackTop = ptr;
620
621 /* ofs is index into StubDesc->apfnExprEval */
622 TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
623 pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
624
625 pStubMsg->StackTop = old_stack_top;
626
627 /* the callback function always stores the computed value in MaxCount */
628 max_count = pStubMsg->MaxCount;
629 pStubMsg->MaxCount = old_max_count;
630 *pCount = max_count;
631 goto finish_conf;
632 }
633 default:
634 ptr = (char *)ptr + ofs;
635 break;
636 }
637
638 switch (dtype) {
639 case FC_LONG:
640 case FC_ULONG:
641 data = *(DWORD*)ptr;
642 break;
643 case FC_SHORT:
644 data = *(SHORT*)ptr;
645 break;
646 case FC_USHORT:
647 data = *(USHORT*)ptr;
648 break;
649 case FC_CHAR:
650 case FC_SMALL:
651 data = *(CHAR*)ptr;
652 break;
653 case FC_BYTE:
654 case FC_USMALL:
655 data = *(UCHAR*)ptr;
656 break;
657 case FC_HYPER:
658 data = *(ULONGLONG *)ptr;
659 break;
660 default:
661 FIXME("unknown conformance data type %x\n", dtype);
662 goto done_conf_grab;
663 }
664 TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);
665
666done_conf_grab:
667 switch (pFormat[1]) {
668 case FC_DEREFERENCE: /* already handled */
669 case 0: /* no op */
670 *pCount = data;
671 break;
672 case FC_ADD_1:
673 *pCount = data + 1;
674 break;
675 case FC_SUB_1:
676 *pCount = data - 1;
677 break;
678 case FC_MULT_2:
679 *pCount = data * 2;
680 break;
681 case FC_DIV_2:
682 *pCount = data / 2;
683 break;
684 default:
685 FIXME("unknown conformance op %d\n", pFormat[1]);
686 goto finish_conf;
687 }
688
689finish_conf:
690 TRACE("resulting conformance is %ld\n", *pCount);
691
692 return SkipConformance(pStubMsg, pFormat);
693}
694
696{
697 return SkipConformance( pStubMsg, pFormat );
698}
699
700/* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
701 * the result overflows 32-bits */
703{
705 if (ret > 0xffffffff)
706 {
708 return 0;
709 }
710 return ret;
711}
712
713static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
714{
715 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
716 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
718 pStubMsg->Buffer += size;
719}
720
722{
723 if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
724 {
725 ERR("buffer length overflow - BufferLength = %u, size = %u\n",
726 pStubMsg->BufferLength, size);
728 }
729 pStubMsg->BufferLength += size;
730}
731
732/* copies data from the buffer, checking that there is enough data in the buffer
733 * to do so */
734static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
735{
736 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
737 (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
738 {
739 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
740 pStubMsg->Buffer, pStubMsg->BufferEnd, size);
742 }
743 if (p == pStubMsg->Buffer)
744 ERR("pointer is the same as the buffer\n");
745 memcpy(p, pStubMsg->Buffer, size);
746 pStubMsg->Buffer += size;
747}
748
749/* copies data to the buffer, checking that there is enough space to do so */
750static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
751{
752 if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
753 (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
754 {
755 ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
756 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
757 size);
759 }
760 memcpy(pStubMsg->Buffer, p, size);
761 pStubMsg->Buffer += size;
762}
763
764/* verify that string data sitting in the buffer is valid and safe to
765 * unmarshall */
767{
768 ULONG i;
769
770 /* verify the buffer is safe to access */
771 if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
772 (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
773 {
774 ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
775 pStubMsg->BufferEnd, pStubMsg->Buffer);
777 }
778
779 /* strings must always have null terminating bytes */
780 if (bufsize < esize)
781 {
782 ERR("invalid string length of %d\n", bufsize / esize);
784 }
785
786 for (i = bufsize - esize; i < bufsize; i++)
787 if (pStubMsg->Buffer[i] != 0)
788 {
789 ERR("string not null-terminated at byte position %d, data is 0x%x\n",
790 i, pStubMsg->Buffer[i]);
792 }
793}
794
795static inline void dump_pointer_attr(unsigned char attr)
796{
798 TRACE(" FC_ALLOCATE_ALL_NODES");
799 if (attr & FC_DONT_FREE)
800 TRACE(" FC_DONT_FREE");
802 TRACE(" FC_ALLOCED_ON_STACK");
804 TRACE(" FC_SIMPLE_POINTER");
806 TRACE(" FC_POINTER_DEREF");
807 TRACE("\n");
808}
809
810/***********************************************************************
811 * PointerMarshall [internal]
812 */
814 unsigned char *Buffer,
815 unsigned char *Pointer,
816 PFORMAT_STRING pFormat)
817{
818 unsigned type = pFormat[0], attr = pFormat[1];
821 ULONG pointer_id;
822 BOOL pointer_needs_marshaling;
823
824 TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
825 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
826 pFormat += 2;
827 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
828 else desc = pFormat + *(const SHORT*)pFormat;
829
830 switch (type) {
831 case FC_RP: /* ref pointer (always non-null) */
832 if (!Pointer)
833 {
834 ERR("NULL ref pointer is not allowed\n");
836 }
837 pointer_needs_marshaling = TRUE;
838 break;
839 case FC_UP: /* unique pointer */
840 case FC_OP: /* object pointer - same as unique here */
841 if (Pointer)
842 pointer_needs_marshaling = TRUE;
843 else
844 pointer_needs_marshaling = FALSE;
845 pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
846 TRACE("writing 0x%08x to buffer\n", pointer_id);
847 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
848 break;
849 case FC_FP:
850 pointer_needs_marshaling = !NdrFullPointerQueryPointer(
851 pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
852 TRACE("writing 0x%08x to buffer\n", pointer_id);
853 NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
854 break;
855 default:
856 FIXME("unhandled ptr type=%02x\n", type);
858 return;
859 }
860
861 TRACE("calling marshaller for type 0x%x\n", (int)*desc);
862
863 if (pointer_needs_marshaling) {
864 if (attr & FC_POINTER_DEREF) {
865 Pointer = *(unsigned char**)Pointer;
866 TRACE("deref => %p\n", Pointer);
867 }
869 if (m) m(pStubMsg, Pointer, desc);
870 else FIXME("no marshaller for data type=%02x\n", *desc);
871 }
872
873 STD_OVERFLOW_CHECK(pStubMsg);
874}
875
876/* pPointer is the pointer that we will unmarshal into; pSrcPointer is the
877 * pointer to memory which we may attempt to reuse if non-NULL. Usually these
878 * are the same; for the case when they aren't, see EmbeddedPointerUnmarshall().
879 *
880 * fMustAlloc seems to determine whether we can allocate from the buffer (if we
881 * are on the server side). It's ignored here, since we can't allocate a pointer
882 * from the buffer. */
884 unsigned char *Buffer,
885 unsigned char **pPointer,
886 unsigned char *pSrcPointer,
887 PFORMAT_STRING pFormat,
888 unsigned char fMustAlloc)
889{
890 unsigned type = pFormat[0], attr = pFormat[1];
893 DWORD pointer_id = 0;
894 BOOL pointer_needs_unmarshaling, need_alloc = FALSE, inner_must_alloc = FALSE;
895
896 TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
897 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
898 pFormat += 2;
899 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
900 else desc = pFormat + *(const SHORT*)pFormat;
901
902 switch (type) {
903 case FC_RP: /* ref pointer (always non-null) */
904 pointer_needs_unmarshaling = TRUE;
905 break;
906 case FC_UP: /* unique pointer */
907 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
908 TRACE("pointer_id is 0x%08x\n", pointer_id);
909 if (pointer_id)
910 pointer_needs_unmarshaling = TRUE;
911 else {
912 *pPointer = NULL;
913 pointer_needs_unmarshaling = FALSE;
914 }
915 break;
916 case FC_OP: /* object pointer - we must free data before overwriting it */
917 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
918 TRACE("pointer_id is 0x%08x\n", pointer_id);
919
920 /* An object pointer always allocates new memory (it cannot point to the
921 * buffer). */
922 inner_must_alloc = TRUE;
923
924 if (pSrcPointer)
925 FIXME("free object pointer %p\n", pSrcPointer);
926 if (pointer_id)
927 pointer_needs_unmarshaling = TRUE;
928 else
929 {
930 *pPointer = NULL;
931 pointer_needs_unmarshaling = FALSE;
932 }
933 break;
934 case FC_FP:
935 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
936 TRACE("pointer_id is 0x%08x\n", pointer_id);
937 pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
938 pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
939 break;
940 default:
941 FIXME("unhandled ptr type=%02x\n", type);
943 return;
944 }
945
946 if (pointer_needs_unmarshaling) {
947 unsigned char **current_ptr = pPointer;
948 if (pStubMsg->IsClient) {
949 TRACE("client\n");
950 /* Try to use the existing (source) pointer to unmarshall the data into
951 * so that [in, out] or [out, ref] parameters behave correctly. If the
952 * source pointer is NULL and we are not dereferencing, we must force the
953 * inner marshalling routine to allocate, since otherwise it will crash. */
954 if (pSrcPointer)
955 {
956 TRACE("setting *pPointer to %p\n", pSrcPointer);
957 *pPointer = pSrcPointer;
958 }
959 else
960 need_alloc = inner_must_alloc = TRUE;
961 } else {
962 TRACE("server\n");
963 /* We can use an existing source pointer here only if it is on-stack,
964 * probably since otherwise NdrPointerFree() might later try to free a
965 * pointer we don't know the provenance of. Otherwise we must always
966 * allocate if we are dereferencing. We never need to force the inner
967 * routine to allocate here, since it will either write into an existing
968 * pointer, or use a pointer to the buffer. */
970 {
971 if (pSrcPointer && (attr & FC_ALLOCED_ON_STACK))
972 *pPointer = pSrcPointer;
973 else
974 need_alloc = TRUE;
975 }
976 else
977 *pPointer = NULL;
978 }
979
981 FIXME("FC_ALLOCATE_ALL_NODES not implemented\n");
982
983 if (attr & FC_POINTER_DEREF) {
984 if (need_alloc)
985 *pPointer = NdrAllocateZero(pStubMsg, sizeof(void *));
986
987 current_ptr = *(unsigned char***)current_ptr;
988 TRACE("deref => %p\n", current_ptr);
989 }
991 if (m) m(pStubMsg, current_ptr, desc, inner_must_alloc);
992 else FIXME("no unmarshaller for data type=%02x\n", *desc);
993
994 if (type == FC_FP)
995 NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
996 *pPointer);
997 }
998
999 TRACE("pointer=%p\n", *pPointer);
1000}
1001
1002/***********************************************************************
1003 * PointerBufferSize [internal]
1004 */
1006 unsigned char *Pointer,
1007 PFORMAT_STRING pFormat)
1008{
1009 unsigned type = pFormat[0], attr = pFormat[1];
1012 BOOL pointer_needs_sizing;
1013 ULONG pointer_id;
1014
1015 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1016 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1017 pFormat += 2;
1018 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
1019 else desc = pFormat + *(const SHORT*)pFormat;
1020
1021 switch (type) {
1022 case FC_RP: /* ref pointer (always non-null) */
1023 if (!Pointer)
1024 {
1025 ERR("NULL ref pointer is not allowed\n");
1027 }
1028 break;
1029 case FC_OP:
1030 case FC_UP:
1031 /* NULL pointer has no further representation */
1032 if (!Pointer)
1033 return;
1034 break;
1035 case FC_FP:
1036 pointer_needs_sizing = !NdrFullPointerQueryPointer(
1037 pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
1038 if (!pointer_needs_sizing)
1039 return;
1040 break;
1041 default:
1042 FIXME("unhandled ptr type=%02x\n", type);
1044 return;
1045 }
1046
1047 if (attr & FC_POINTER_DEREF) {
1048 Pointer = *(unsigned char**)Pointer;
1049 TRACE("deref => %p\n", Pointer);
1050 }
1051
1053 if (m) m(pStubMsg, Pointer, desc);
1054 else FIXME("no buffersizer for data type=%02x\n", *desc);
1055}
1056
1057/***********************************************************************
1058 * PointerMemorySize [internal]
1059 */
1061 unsigned char *Buffer, PFORMAT_STRING pFormat)
1062{
1063 unsigned type = pFormat[0], attr = pFormat[1];
1066 DWORD pointer_id = 0;
1067 BOOL pointer_needs_sizing;
1068
1069 TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
1070 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1071 pFormat += 2;
1072 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
1073 else desc = pFormat + *(const SHORT*)pFormat;
1074
1075 switch (type) {
1076 case FC_RP: /* ref pointer (always non-null) */
1077 pointer_needs_sizing = TRUE;
1078 break;
1079 case FC_UP: /* unique pointer */
1080 case FC_OP: /* object pointer - we must free data before overwriting it */
1081 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1082 TRACE("pointer_id is 0x%08x\n", pointer_id);
1083 if (pointer_id)
1084 pointer_needs_sizing = TRUE;
1085 else
1086 pointer_needs_sizing = FALSE;
1087 break;
1088 case FC_FP:
1089 {
1090 void *pointer;
1091 pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
1092 TRACE("pointer_id is 0x%08x\n", pointer_id);
1093 pointer_needs_sizing = !NdrFullPointerQueryRefId(
1094 pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
1095 break;
1096 }
1097 default:
1098 FIXME("unhandled ptr type=%02x\n", type);
1100 return 0;
1101 }
1102
1103 if (attr & FC_POINTER_DEREF) {
1104 align_length(&pStubMsg->MemorySize, sizeof(void*));
1105 pStubMsg->MemorySize += sizeof(void*);
1106 TRACE("deref\n");
1107 }
1108
1109 if (pointer_needs_sizing) {
1111 if (m) m(pStubMsg, desc);
1112 else FIXME("no memorysizer for data type=%02x\n", *desc);
1113 }
1114
1115 return pStubMsg->MemorySize;
1116}
1117
1118/***********************************************************************
1119 * PointerFree [internal]
1120 */
1121static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1122 unsigned char *Pointer,
1123 PFORMAT_STRING pFormat)
1124{
1125 unsigned type = pFormat[0], attr = pFormat[1];
1127 NDR_FREE m;
1128 unsigned char *current_pointer = Pointer;
1129
1130 TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
1131 TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
1132 if (attr & FC_DONT_FREE) return;
1133 pFormat += 2;
1134 if (attr & FC_SIMPLE_POINTER) desc = pFormat;
1135 else desc = pFormat + *(const SHORT*)pFormat;
1136
1137 if (!Pointer) return;
1138
1139 if (type == FC_FP) {
1140 int pointer_needs_freeing = NdrFullPointerFree(
1141 pStubMsg->FullPtrXlatTables, Pointer);
1142 if (!pointer_needs_freeing)
1143 return;
1144 }
1145
1146 if (attr & FC_POINTER_DEREF) {
1147 current_pointer = *(unsigned char**)Pointer;
1148 TRACE("deref => %p\n", current_pointer);
1149 }
1150
1152 if (m) m(pStubMsg, current_pointer, desc);
1153
1154 /* this check stops us from trying to free buffer memory. we don't have to
1155 * worry about clients, since they won't call this function.
1156 * we don't have to check for the buffer being reallocated because
1157 * BufferStart and BufferEnd won't be reset when allocating memory for
1158 * sending the response. we don't have to check for the new buffer here as
1159 * it won't be used a type memory, only for buffer memory */
1160 if (Pointer >= pStubMsg->BufferStart && Pointer <= pStubMsg->BufferEnd)
1161 goto notfree;
1162
1163 if (attr & FC_ALLOCED_ON_STACK) {
1164 TRACE("not freeing stack ptr %p\n", Pointer);
1165 return;
1166 }
1167 TRACE("freeing %p\n", Pointer);
1168 NdrFree(pStubMsg, Pointer);
1169 return;
1170notfree:
1171 TRACE("not freeing %p\n", Pointer);
1172}
1173
1174/***********************************************************************
1175 * EmbeddedPointerMarshall
1176 */
1177static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1178 unsigned char *pMemory,
1179 PFORMAT_STRING pFormat)
1180{
1181 unsigned char *Mark = pStubMsg->BufferMark;
1182 unsigned rep, count, stride;
1183 unsigned i;
1184 unsigned char *saved_buffer = NULL;
1185
1186 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1187
1188 if (*pFormat != FC_PP) return NULL;
1189 pFormat += 2;
1190
1191 if (pStubMsg->PointerBufferMark)
1192 {
1193 saved_buffer = pStubMsg->Buffer;
1194 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1195 pStubMsg->PointerBufferMark = NULL;
1196 }
1197
1198 while (pFormat[0] != FC_END) {
1199 switch (pFormat[0]) {
1200 default:
1201 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1202 /* fallthrough */
1203 case FC_NO_REPEAT:
1204 rep = 1;
1205 stride = 0;
1206 count = 1;
1207 pFormat += 2;
1208 break;
1209 case FC_FIXED_REPEAT:
1210 rep = *(const WORD*)&pFormat[2];
1211 stride = *(const WORD*)&pFormat[4];
1212 count = *(const WORD*)&pFormat[8];
1213 pFormat += 10;
1214 break;
1215 case FC_VARIABLE_REPEAT:
1216 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1217 stride = *(const WORD*)&pFormat[2];
1218 count = *(const WORD*)&pFormat[6];
1219 pFormat += 8;
1220 break;
1221 }
1222 for (i = 0; i < rep; i++) {
1223 PFORMAT_STRING info = pFormat;
1224 unsigned char *membase = pMemory + (i * stride);
1225 unsigned char *bufbase = Mark + (i * stride);
1226 unsigned u;
1227
1228 for (u=0; u<count; u++,info+=8) {
1229 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1230 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1231 unsigned char *saved_memory = pStubMsg->Memory;
1232
1233 pStubMsg->Memory = membase;
1234 PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1235 pStubMsg->Memory = saved_memory;
1236 }
1237 }
1238 pFormat += 8 * count;
1239 }
1240
1241 if (saved_buffer)
1242 {
1243 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1244 pStubMsg->Buffer = saved_buffer;
1245 }
1246
1247 STD_OVERFLOW_CHECK(pStubMsg);
1248
1249 return NULL;
1250}
1251
1252/* rpcrt4 does something bizarre with embedded pointers: instead of copying the
1253 * struct/array/union from the buffer to memory and then unmarshalling pointers
1254 * into it, it unmarshals pointers into the buffer itself and then copies it to
1255 * memory. However, it will still attempt to use a user-supplied pointer where
1256 * appropriate (i.e. one on stack). Therefore we need to pass both pointers to
1257 * this function and to PointerUnmarshall: the pointer (to the buffer) that we
1258 * will actually unmarshal into (pDstBuffer), and the pointer (to memory) that
1259 * we will attempt to use for storage if possible (pSrcMemoryPtrs). */
1260static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1261 unsigned char *pDstBuffer,
1262 unsigned char *pSrcMemoryPtrs,
1263 PFORMAT_STRING pFormat,
1264 unsigned char fMustAlloc)
1265{
1266 unsigned char *Mark = pStubMsg->BufferMark;
1267 unsigned rep, count, stride;
1268 unsigned i;
1269 unsigned char *saved_buffer = NULL;
1270
1271 TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
1272
1273 if (*pFormat != FC_PP) return NULL;
1274 pFormat += 2;
1275
1276 if (pStubMsg->PointerBufferMark)
1277 {
1278 saved_buffer = pStubMsg->Buffer;
1279 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1280 pStubMsg->PointerBufferMark = NULL;
1281 }
1282
1283 while (pFormat[0] != FC_END) {
1284 TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1285 switch (pFormat[0]) {
1286 default:
1287 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1288 /* fallthrough */
1289 case FC_NO_REPEAT:
1290 rep = 1;
1291 stride = 0;
1292 count = 1;
1293 pFormat += 2;
1294 break;
1295 case FC_FIXED_REPEAT:
1296 rep = *(const WORD*)&pFormat[2];
1297 stride = *(const WORD*)&pFormat[4];
1298 count = *(const WORD*)&pFormat[8];
1299 pFormat += 10;
1300 break;
1301 case FC_VARIABLE_REPEAT:
1302 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1303 stride = *(const WORD*)&pFormat[2];
1304 count = *(const WORD*)&pFormat[6];
1305 pFormat += 8;
1306 break;
1307 }
1308 for (i = 0; i < rep; i++) {
1309 PFORMAT_STRING info = pFormat;
1310 unsigned char *bufdstbase = pDstBuffer + (i * stride);
1311 unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
1312 unsigned char *bufbase = Mark + (i * stride);
1313 unsigned u;
1314
1315 for (u=0; u<count; u++,info+=8) {
1316 unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
1317 unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
1318 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1319 PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
1320 }
1321 }
1322 pFormat += 8 * count;
1323 }
1324
1325 if (saved_buffer)
1326 {
1327 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1328 pStubMsg->Buffer = saved_buffer;
1329 }
1330
1331 return NULL;
1332}
1333
1334/***********************************************************************
1335 * EmbeddedPointerBufferSize
1336 */
1338 unsigned char *pMemory,
1339 PFORMAT_STRING pFormat)
1340{
1341 unsigned rep, count, stride;
1342 unsigned i;
1343 ULONG saved_buffer_length = 0;
1344
1345 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1346
1347 if (pStubMsg->IgnoreEmbeddedPointers) return;
1348
1349 if (*pFormat != FC_PP) return;
1350 pFormat += 2;
1351
1352 if (pStubMsg->PointerLength)
1353 {
1354 saved_buffer_length = pStubMsg->BufferLength;
1355 pStubMsg->BufferLength = pStubMsg->PointerLength;
1356 pStubMsg->PointerLength = 0;
1357 }
1358
1359 while (pFormat[0] != FC_END) {
1360 switch (pFormat[0]) {
1361 default:
1362 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1363 /* fallthrough */
1364 case FC_NO_REPEAT:
1365 rep = 1;
1366 stride = 0;
1367 count = 1;
1368 pFormat += 2;
1369 break;
1370 case FC_FIXED_REPEAT:
1371 rep = *(const WORD*)&pFormat[2];
1372 stride = *(const WORD*)&pFormat[4];
1373 count = *(const WORD*)&pFormat[8];
1374 pFormat += 10;
1375 break;
1376 case FC_VARIABLE_REPEAT:
1377 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1378 stride = *(const WORD*)&pFormat[2];
1379 count = *(const WORD*)&pFormat[6];
1380 pFormat += 8;
1381 break;
1382 }
1383 for (i = 0; i < rep; i++) {
1384 PFORMAT_STRING info = pFormat;
1385 unsigned char *membase = pMemory + (i * stride);
1386 unsigned u;
1387
1388 for (u=0; u<count; u++,info+=8) {
1389 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1390 unsigned char *saved_memory = pStubMsg->Memory;
1391
1392 pStubMsg->Memory = membase;
1393 PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1394 pStubMsg->Memory = saved_memory;
1395 }
1396 }
1397 pFormat += 8 * count;
1398 }
1399
1400 if (saved_buffer_length)
1401 {
1402 pStubMsg->PointerLength = pStubMsg->BufferLength;
1403 pStubMsg->BufferLength = saved_buffer_length;
1404 }
1405}
1406
1407/***********************************************************************
1408 * EmbeddedPointerMemorySize [internal]
1409 */
1411 PFORMAT_STRING pFormat)
1412{
1413 unsigned char *Mark = pStubMsg->BufferMark;
1414 unsigned rep, count, stride;
1415 unsigned i;
1416 unsigned char *saved_buffer = NULL;
1417
1418 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1419
1420 if (pStubMsg->IgnoreEmbeddedPointers) return 0;
1421
1422 if (pStubMsg->PointerBufferMark)
1423 {
1424 saved_buffer = pStubMsg->Buffer;
1425 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
1426 pStubMsg->PointerBufferMark = NULL;
1427 }
1428
1429 if (*pFormat != FC_PP) return 0;
1430 pFormat += 2;
1431
1432 while (pFormat[0] != FC_END) {
1433 switch (pFormat[0]) {
1434 default:
1435 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1436 /* fallthrough */
1437 case FC_NO_REPEAT:
1438 rep = 1;
1439 stride = 0;
1440 count = 1;
1441 pFormat += 2;
1442 break;
1443 case FC_FIXED_REPEAT:
1444 rep = *(const WORD*)&pFormat[2];
1445 stride = *(const WORD*)&pFormat[4];
1446 count = *(const WORD*)&pFormat[8];
1447 pFormat += 10;
1448 break;
1449 case FC_VARIABLE_REPEAT:
1450 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1451 stride = *(const WORD*)&pFormat[2];
1452 count = *(const WORD*)&pFormat[6];
1453 pFormat += 8;
1454 break;
1455 }
1456 for (i = 0; i < rep; i++) {
1457 PFORMAT_STRING info = pFormat;
1458 unsigned char *bufbase = Mark + (i * stride);
1459 unsigned u;
1460 for (u=0; u<count; u++,info+=8) {
1461 unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1462 PointerMemorySize(pStubMsg, bufptr, info+4);
1463 }
1464 }
1465 pFormat += 8 * count;
1466 }
1467
1468 if (saved_buffer)
1469 {
1470 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
1471 pStubMsg->Buffer = saved_buffer;
1472 }
1473
1474 return 0;
1475}
1476
1477/***********************************************************************
1478 * EmbeddedPointerFree [internal]
1479 */
1481 unsigned char *pMemory,
1482 PFORMAT_STRING pFormat)
1483{
1484 unsigned rep, count, stride;
1485 unsigned i;
1486
1487 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1488 if (*pFormat != FC_PP) return;
1489 pFormat += 2;
1490
1491 while (pFormat[0] != FC_END) {
1492 switch (pFormat[0]) {
1493 default:
1494 FIXME("unknown repeat type %d; assuming no repeat\n", pFormat[0]);
1495 /* fallthrough */
1496 case FC_NO_REPEAT:
1497 rep = 1;
1498 stride = 0;
1499 count = 1;
1500 pFormat += 2;
1501 break;
1502 case FC_FIXED_REPEAT:
1503 rep = *(const WORD*)&pFormat[2];
1504 stride = *(const WORD*)&pFormat[4];
1505 count = *(const WORD*)&pFormat[8];
1506 pFormat += 10;
1507 break;
1508 case FC_VARIABLE_REPEAT:
1509 rep = (pFormat[1] == FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
1510 stride = *(const WORD*)&pFormat[2];
1511 count = *(const WORD*)&pFormat[6];
1512 pFormat += 8;
1513 break;
1514 }
1515 for (i = 0; i < rep; i++) {
1516 PFORMAT_STRING info = pFormat;
1517 unsigned char *membase = pMemory + (i * stride);
1518 unsigned u;
1519
1520 for (u=0; u<count; u++,info+=8) {
1521 unsigned char *memptr = membase + *(const SHORT*)&info[0];
1522 unsigned char *saved_memory = pStubMsg->Memory;
1523
1524 pStubMsg->Memory = membase;
1525 PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1526 pStubMsg->Memory = saved_memory;
1527 }
1528 }
1529 pFormat += 8 * count;
1530 }
1531}
1532
1533/***********************************************************************
1534 * NdrPointerMarshall [RPCRT4.@]
1535 */
1537 unsigned char *pMemory,
1538 PFORMAT_STRING pFormat)
1539{
1540 unsigned char *Buffer;
1541
1542 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1543
1544 /* Increment the buffer here instead of in PointerMarshall,
1545 * as that is used by embedded pointers which already handle the incrementing
1546 * the buffer, and shouldn't write any additional pointer data to the wire */
1547 if (*pFormat != FC_RP)
1548 {
1549 align_pointer_clear(&pStubMsg->Buffer, 4);
1550 Buffer = pStubMsg->Buffer;
1551 safe_buffer_increment(pStubMsg, 4);
1552 }
1553 else
1554 Buffer = pStubMsg->Buffer;
1555
1556 PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1557
1558 return NULL;
1559}
1560
1561/***********************************************************************
1562 * NdrPointerUnmarshall [RPCRT4.@]
1563 */
1565 unsigned char **ppMemory,
1566 PFORMAT_STRING pFormat,
1567 unsigned char fMustAlloc)
1568{
1569 unsigned char *Buffer;
1570
1571 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1572
1573 if (*pFormat == FC_RP)
1574 {
1575 Buffer = pStubMsg->Buffer;
1576 /* Do the NULL ref pointer check here because embedded pointers can be
1577 * NULL if the type the pointer is embedded in was allocated rather than
1578 * being passed in by the client */
1579 if (pStubMsg->IsClient && !*ppMemory)
1580 {
1581 ERR("NULL ref pointer is not allowed\n");
1583 }
1584 }
1585 else
1586 {
1587 /* Increment the buffer here instead of in PointerUnmarshall,
1588 * as that is used by embedded pointers which already handle the incrementing
1589 * the buffer, and shouldn't read any additional pointer data from the
1590 * buffer */
1591 align_pointer(&pStubMsg->Buffer, 4);
1592 Buffer = pStubMsg->Buffer;
1593 safe_buffer_increment(pStubMsg, 4);
1594 }
1595
1596 PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
1597
1598 return NULL;
1599}
1600
1601/***********************************************************************
1602 * NdrPointerBufferSize [RPCRT4.@]
1603 */
1605 unsigned char *pMemory,
1606 PFORMAT_STRING pFormat)
1607{
1608 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1609
1610 /* Increment the buffer length here instead of in PointerBufferSize,
1611 * as that is used by embedded pointers which already handle the buffer
1612 * length, and shouldn't write anything more to the wire */
1613 if (*pFormat != FC_RP)
1614 {
1615 align_length(&pStubMsg->BufferLength, 4);
1616 safe_buffer_length_increment(pStubMsg, 4);
1617 }
1618
1619 PointerBufferSize(pStubMsg, pMemory, pFormat);
1620}
1621
1622/***********************************************************************
1623 * NdrPointerMemorySize [RPCRT4.@]
1624 */
1626 PFORMAT_STRING pFormat)
1627{
1628 unsigned char *Buffer = pStubMsg->Buffer;
1629 if (*pFormat != FC_RP)
1630 {
1631 align_pointer(&pStubMsg->Buffer, 4);
1632 safe_buffer_increment(pStubMsg, 4);
1633 }
1634 align_length(&pStubMsg->MemorySize, sizeof(void *));
1635 return PointerMemorySize(pStubMsg, Buffer, pFormat);
1636}
1637
1638/***********************************************************************
1639 * NdrPointerFree [RPCRT4.@]
1640 */
1642 unsigned char *pMemory,
1643 PFORMAT_STRING pFormat)
1644{
1645 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1646 PointerFree(pStubMsg, pMemory, pFormat);
1647}
1648
1649/***********************************************************************
1650 * NdrSimpleTypeMarshall [RPCRT4.@]
1651 */
1653 unsigned char FormatChar )
1654{
1655 NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
1656}
1657
1658/***********************************************************************
1659 * NdrSimpleTypeUnmarshall [RPCRT4.@]
1660 *
1661 * Unmarshall a base type.
1662 *
1663 * NOTES
1664 * Doesn't check that the buffer is long enough before copying, so the caller
1665 * should do this.
1666 */
1668 unsigned char FormatChar )
1669{
1670#define BASE_TYPE_UNMARSHALL(type) \
1671 align_pointer(&pStubMsg->Buffer, sizeof(type)); \
1672 TRACE("pMemory: %p\n", pMemory); \
1673 *(type *)pMemory = *(type *)pStubMsg->Buffer; \
1674 pStubMsg->Buffer += sizeof(type);
1675
1676 switch(FormatChar)
1677 {
1678 case FC_BYTE:
1679 case FC_CHAR:
1680 case FC_SMALL:
1681 case FC_USMALL:
1683 TRACE("value: 0x%02x\n", *pMemory);
1684 break;
1685 case FC_WCHAR:
1686 case FC_SHORT:
1687 case FC_USHORT:
1689 TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
1690 break;
1691 case FC_LONG:
1692 case FC_ULONG:
1693 case FC_ERROR_STATUS_T:
1694 case FC_ENUM32:
1696 TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
1697 break;
1698 case FC_FLOAT:
1699 BASE_TYPE_UNMARSHALL(float);
1700 TRACE("value: %f\n", *(float *)pMemory);
1701 break;
1702 case FC_DOUBLE:
1703 BASE_TYPE_UNMARSHALL(double);
1704 TRACE("value: %f\n", *(double *)pMemory);
1705 break;
1706 case FC_HYPER:
1708 TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
1709 break;
1710 case FC_ENUM16:
1711 align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
1712 TRACE("pMemory: %p\n", pMemory);
1713 /* 16-bits on the wire, but int in memory */
1714 *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
1715 pStubMsg->Buffer += sizeof(USHORT);
1716 TRACE("value: 0x%08x\n", *(UINT *)pMemory);
1717 break;
1718 case FC_INT3264:
1719 align_pointer(&pStubMsg->Buffer, sizeof(INT));
1720 /* 32-bits on the wire, but int_ptr in memory */
1721 *(INT_PTR *)pMemory = *(INT *)pStubMsg->Buffer;
1722 pStubMsg->Buffer += sizeof(INT);
1723 TRACE("value: 0x%08lx\n", *(INT_PTR *)pMemory);
1724 break;
1725 case FC_UINT3264:
1726 align_pointer(&pStubMsg->Buffer, sizeof(UINT));
1727 /* 32-bits on the wire, but int_ptr in memory */
1728 *(UINT_PTR *)pMemory = *(UINT *)pStubMsg->Buffer;
1729 pStubMsg->Buffer += sizeof(UINT);
1730 TRACE("value: 0x%08lx\n", *(UINT_PTR *)pMemory);
1731 break;
1732 case FC_IGNORE:
1733 break;
1734 default:
1735 FIXME("Unhandled base type: 0x%02x\n", FormatChar);
1736 }
1737#undef BASE_TYPE_UNMARSHALL
1738}
1739
1740/***********************************************************************
1741 * NdrSimpleStructMarshall [RPCRT4.@]
1742 */
1744 unsigned char *pMemory,
1745 PFORMAT_STRING pFormat)
1746{
1747 unsigned size = *(const WORD*)(pFormat+2);
1748 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1749
1750 align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
1751
1752 pStubMsg->BufferMark = pStubMsg->Buffer;
1753 safe_copy_to_buffer(pStubMsg, pMemory, size);
1754
1755 if (pFormat[0] != FC_STRUCT)
1756 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1757
1758 return NULL;
1759}
1760
1761/***********************************************************************
1762 * NdrSimpleStructUnmarshall [RPCRT4.@]
1763 */
1765 unsigned char **ppMemory,
1766 PFORMAT_STRING pFormat,
1767 unsigned char fMustAlloc)
1768{
1769 unsigned size = *(const WORD*)(pFormat+2);
1770 unsigned char *saved_buffer;
1771 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1772
1773 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1774
1775 if (fMustAlloc)
1776 *ppMemory = NdrAllocateZero(pStubMsg, size);
1777 else
1778 {
1779 if (!pStubMsg->IsClient && !*ppMemory)
1780 /* for servers, we just point straight into the RPC buffer */
1781 *ppMemory = pStubMsg->Buffer;
1782 }
1783
1784 saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
1785 safe_buffer_increment(pStubMsg, size);
1786 if (pFormat[0] == FC_PSTRUCT)
1787 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
1788
1789 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
1790 if (*ppMemory != saved_buffer)
1791 memcpy(*ppMemory, saved_buffer, size);
1792
1793 return NULL;
1794}
1795
1796/***********************************************************************
1797 * NdrSimpleStructBufferSize [RPCRT4.@]
1798 */
1800 unsigned char *pMemory,
1801 PFORMAT_STRING pFormat)
1802{
1803 unsigned size = *(const WORD*)(pFormat+2);
1804 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1805
1806 align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
1807
1809 if (pFormat[0] != FC_STRUCT)
1810 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1811}
1812
1813/***********************************************************************
1814 * NdrSimpleStructMemorySize [RPCRT4.@]
1815 */
1817 PFORMAT_STRING pFormat)
1818{
1819 unsigned short size = *(const WORD *)(pFormat+2);
1820
1821 TRACE("(%p,%p)\n", pStubMsg, pFormat);
1822
1823 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
1824 pStubMsg->MemorySize += size;
1825 safe_buffer_increment(pStubMsg, size);
1826
1827 if (pFormat[0] != FC_STRUCT)
1828 EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1829 return pStubMsg->MemorySize;
1830}
1831
1832/***********************************************************************
1833 * NdrSimpleStructFree [RPCRT4.@]
1834 */
1836 unsigned char *pMemory,
1837 PFORMAT_STRING pFormat)
1838{
1839 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1840 if (pFormat[0] != FC_STRUCT)
1841 EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1842}
1843
1844/* Array helpers */
1845
1847 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1848 PFORMAT_STRING pFormat)
1849{
1850 DWORD count;
1851
1852 switch (fc)
1853 {
1854 case FC_CARRAY:
1855 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1856 SizeConformance(pStubMsg);
1857 break;
1858 case FC_CVARRAY:
1859 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1860 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1861 SizeConformance(pStubMsg);
1862 break;
1863 case FC_C_CSTRING:
1864 case FC_C_WSTRING:
1865 if (fc == FC_C_CSTRING)
1866 {
1867 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1868 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1869 }
1870 else
1871 {
1872 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1873 pStubMsg->ActualCount = lstrlenW((LPCWSTR)pMemory)+1;
1874 }
1875
1876 if (pFormat[1] == FC_STRING_SIZED)
1877 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
1878 else
1879 pStubMsg->MaxCount = pStubMsg->ActualCount;
1880
1881 SizeConformance(pStubMsg);
1882 break;
1883 case FC_BOGUS_ARRAY:
1884 count = *(const WORD *)(pFormat + 2);
1885 pFormat += 4;
1886 if (IsConformanceOrVariancePresent(pFormat)) SizeConformance(pStubMsg);
1887 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, count);
1888 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
1889 break;
1890 default:
1891 ERR("unknown array format 0x%x\n", fc);
1893 }
1894}
1895
1896static inline void array_buffer_size(
1897 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1898 PFORMAT_STRING pFormat, unsigned char fHasPointers)
1899{
1900 DWORD i, size;
1901 DWORD esize;
1902 unsigned char alignment;
1903
1904 switch (fc)
1905 {
1906 case FC_CARRAY:
1907 esize = *(const WORD*)(pFormat+2);
1908 alignment = pFormat[1] + 1;
1909
1910 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1911
1912 align_length(&pStubMsg->BufferLength, alignment);
1913
1914 size = safe_multiply(esize, pStubMsg->MaxCount);
1915 /* conformance value plus array */
1917
1918 if (fHasPointers)
1919 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1920 break;
1921 case FC_CVARRAY:
1922 esize = *(const WORD*)(pFormat+2);
1923 alignment = pFormat[1] + 1;
1924
1925 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1926 pFormat = SkipVariance(pStubMsg, pFormat);
1927
1928 SizeVariance(pStubMsg);
1929
1930 align_length(&pStubMsg->BufferLength, alignment);
1931
1932 size = safe_multiply(esize, pStubMsg->ActualCount);
1934
1935 if (fHasPointers)
1936 EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1937 break;
1938 case FC_C_CSTRING:
1939 case FC_C_WSTRING:
1940 if (fc == FC_C_CSTRING)
1941 esize = 1;
1942 else
1943 esize = 2;
1944
1945 SizeVariance(pStubMsg);
1946
1947 size = safe_multiply(esize, pStubMsg->ActualCount);
1949 break;
1950 case FC_BOGUS_ARRAY:
1951 alignment = pFormat[1] + 1;
1952 pFormat = SkipConformance(pStubMsg, pFormat + 4);
1953 if (IsConformanceOrVariancePresent(pFormat)) SizeVariance(pStubMsg);
1954 pFormat = SkipVariance(pStubMsg, pFormat);
1955
1956 align_length(&pStubMsg->BufferLength, alignment);
1957
1958 size = pStubMsg->ActualCount;
1959 for (i = 0; i < size; i++)
1960 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
1961 break;
1962 default:
1963 ERR("unknown array format 0x%x\n", fc);
1965 }
1966}
1967
1969 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
1970 PFORMAT_STRING pFormat)
1971{
1972 ULONG def;
1973 BOOL conformance_present;
1974
1975 switch (fc)
1976 {
1977 case FC_CARRAY:
1978 ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1979 WriteConformance(pStubMsg);
1980 break;
1981 case FC_CVARRAY:
1982 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
1983 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
1984 WriteConformance(pStubMsg);
1985 break;
1986 case FC_C_CSTRING:
1987 case FC_C_WSTRING:
1988 if (fc == FC_C_CSTRING)
1989 {
1990 TRACE("string=%s\n", debugstr_a((const char *)pMemory));
1991 pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
1992 }
1993 else
1994 {
1995 TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
1996 pStubMsg->ActualCount = lstrlenW((LPCWSTR)pMemory)+1;
1997 }
1998 if (pFormat[1] == FC_STRING_SIZED)
1999 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
2000 else
2001 pStubMsg->MaxCount = pStubMsg->ActualCount;
2002 pStubMsg->Offset = 0;
2003 WriteConformance(pStubMsg);
2004 break;
2005 case FC_BOGUS_ARRAY:
2006 def = *(const WORD *)(pFormat + 2);
2007 pFormat += 4;
2008 conformance_present = IsConformanceOrVariancePresent(pFormat);
2009 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2010 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2011 if (conformance_present) WriteConformance(pStubMsg);
2012 break;
2013 default:
2014 ERR("unknown array format 0x%x\n", fc);
2016 }
2017}
2018
2020 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
2021 PFORMAT_STRING pFormat, unsigned char fHasPointers)
2022{
2023 DWORD i, size;
2024 DWORD esize;
2025 unsigned char alignment;
2026
2027 switch (fc)
2028 {
2029 case FC_CARRAY:
2030 esize = *(const WORD*)(pFormat+2);
2031 alignment = pFormat[1] + 1;
2032
2033 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2034
2035 align_pointer_clear(&pStubMsg->Buffer, alignment);
2036
2037 size = safe_multiply(esize, pStubMsg->MaxCount);
2038 if (fHasPointers)
2039 pStubMsg->BufferMark = pStubMsg->Buffer;
2040 safe_copy_to_buffer(pStubMsg, pMemory, size);
2041
2042 if (fHasPointers)
2043 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2044 break;
2045 case FC_CVARRAY:
2046 esize = *(const WORD*)(pFormat+2);
2047 alignment = pFormat[1] + 1;
2048
2049 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2050 pFormat = SkipVariance(pStubMsg, pFormat);
2051
2052 WriteVariance(pStubMsg);
2053
2054 align_pointer_clear(&pStubMsg->Buffer, alignment);
2055
2056 size = safe_multiply(esize, pStubMsg->ActualCount);
2057
2058 if (fHasPointers)
2059 pStubMsg->BufferMark = pStubMsg->Buffer;
2060 safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
2061
2062 if (fHasPointers)
2063 EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2064 break;
2065 case FC_C_CSTRING:
2066 case FC_C_WSTRING:
2067 if (fc == FC_C_CSTRING)
2068 esize = 1;
2069 else
2070 esize = 2;
2071
2072 WriteVariance(pStubMsg);
2073
2074 size = safe_multiply(esize, pStubMsg->ActualCount);
2075 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2076 break;
2077 case FC_BOGUS_ARRAY:
2078 alignment = pFormat[1] + 1;
2079 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2080 if (IsConformanceOrVariancePresent(pFormat)) WriteVariance(pStubMsg);
2081 pFormat = SkipVariance(pStubMsg, pFormat);
2082
2083 align_pointer_clear(&pStubMsg->Buffer, alignment);
2084
2085 size = pStubMsg->ActualCount;
2086 for (i = 0; i < size; i++)
2087 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2088 break;
2089 default:
2090 ERR("unknown array format 0x%x\n", fc);
2092 }
2093}
2094
2096 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
2097{
2098 DWORD def, esize;
2099
2100 switch (fc)
2101 {
2102 case FC_CARRAY:
2103 esize = *(const WORD*)(pFormat+2);
2104 pFormat = ReadConformance(pStubMsg, pFormat+4);
2105 return safe_multiply(esize, pStubMsg->MaxCount);
2106 case FC_CVARRAY:
2107 esize = *(const WORD*)(pFormat+2);
2108 pFormat = ReadConformance(pStubMsg, pFormat+4);
2109 return safe_multiply(esize, pStubMsg->MaxCount);
2110 case FC_C_CSTRING:
2111 case FC_C_WSTRING:
2112 if (fc == FC_C_CSTRING)
2113 esize = 1;
2114 else
2115 esize = 2;
2116
2117 if (pFormat[1] == FC_STRING_SIZED)
2118 ReadConformance(pStubMsg, pFormat + 2);
2119 else
2120 ReadConformance(pStubMsg, NULL);
2121 return safe_multiply(esize, pStubMsg->MaxCount);
2122 case FC_BOGUS_ARRAY:
2123 def = *(const WORD *)(pFormat + 2);
2124 pFormat += 4;
2125 if (IsConformanceOrVariancePresent(pFormat)) pFormat = ReadConformance(pStubMsg, pFormat);
2126 else
2127 {
2128 pStubMsg->MaxCount = def;
2129 pFormat = SkipConformance( pStubMsg, pFormat );
2130 }
2131 pFormat = SkipVariance( pStubMsg, pFormat );
2132
2133 esize = ComplexStructSize(pStubMsg, pFormat);
2134 return safe_multiply(pStubMsg->MaxCount, esize);
2135 default:
2136 ERR("unknown array format 0x%x\n", fc);
2138 }
2139}
2140
2142 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
2143 PFORMAT_STRING pFormat, unsigned char fMustAlloc,
2144 unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
2145{
2146 ULONG bufsize, memsize;
2147 WORD esize;
2148 unsigned char alignment;
2149 unsigned char *saved_buffer, *pMemory;
2150 ULONG i, offset, count;
2151
2152 switch (fc)
2153 {
2154 case FC_CARRAY:
2155 esize = *(const WORD*)(pFormat+2);
2156 alignment = pFormat[1] + 1;
2157
2158 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2159
2160 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2161
2162 align_pointer(&pStubMsg->Buffer, alignment);
2163
2164 if (fUnmarshall)
2165 {
2166 if (fMustAlloc)
2167 *ppMemory = NdrAllocateZero(pStubMsg, memsize);
2168 else
2169 {
2170 if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
2171 /* for servers, we just point straight into the RPC buffer */
2172 *ppMemory = pStubMsg->Buffer;
2173 }
2174
2175 saved_buffer = pStubMsg->Buffer;
2176 safe_buffer_increment(pStubMsg, bufsize);
2177
2178 pStubMsg->BufferMark = saved_buffer;
2179 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
2180
2181 TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
2182 if (*ppMemory != saved_buffer)
2183 memcpy(*ppMemory, saved_buffer, bufsize);
2184 }
2185 return bufsize;
2186 case FC_CVARRAY:
2187 esize = *(const WORD*)(pFormat+2);
2188 alignment = pFormat[1] + 1;
2189
2190 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2191
2192 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2193
2194 align_pointer(&pStubMsg->Buffer, alignment);
2195
2196 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2197 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2198
2199 if (fUnmarshall)
2200 {
2201 offset = pStubMsg->Offset;
2202
2203 if (!fMustAlloc && !*ppMemory)
2204 fMustAlloc = TRUE;
2205 if (fMustAlloc)
2206 *ppMemory = NdrAllocateZero(pStubMsg, memsize);
2207 saved_buffer = pStubMsg->Buffer;
2208 safe_buffer_increment(pStubMsg, bufsize);
2209
2210 pStubMsg->BufferMark = saved_buffer;
2211 EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
2212 fMustAlloc);
2213
2214 memcpy(*ppMemory + offset, saved_buffer, bufsize);
2215 }
2216 return bufsize;
2217 case FC_C_CSTRING:
2218 case FC_C_WSTRING:
2219 if (fc == FC_C_CSTRING)
2220 esize = 1;
2221 else
2222 esize = 2;
2223
2224 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2225
2226 if (pFormat[1] != FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2227 {
2228 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2229 pStubMsg->ActualCount, pStubMsg->MaxCount);
2231 }
2232 if (pStubMsg->Offset)
2233 {
2234 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2236 }
2237
2238 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2239 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2240
2241 validate_string_data(pStubMsg, bufsize, esize);
2242
2243 if (fUnmarshall)
2244 {
2245 if (fMustAlloc)
2246 *ppMemory = NdrAllocate(pStubMsg, memsize);
2247 else
2248 {
2249 if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
2250 !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
2251 /* if the data in the RPC buffer is big enough, we just point
2252 * straight into it */
2253 *ppMemory = pStubMsg->Buffer;
2254 else if (!*ppMemory)
2255 *ppMemory = NdrAllocate(pStubMsg, memsize);
2256 }
2257
2258 if (*ppMemory == pStubMsg->Buffer)
2259 safe_buffer_increment(pStubMsg, bufsize);
2260 else
2261 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2262
2263 if (*pFormat == FC_C_CSTRING)
2264 TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
2265 else
2266 TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
2267 }
2268 return bufsize;
2269
2270 case FC_BOGUS_ARRAY:
2271 alignment = pFormat[1] + 1;
2272 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2273 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2274
2275 esize = ComplexStructSize(pStubMsg, pFormat);
2276 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2277
2278 assert( fUnmarshall );
2279
2280 if (!fMustAlloc && !*ppMemory)
2281 fMustAlloc = TRUE;
2282 if (fMustAlloc)
2283 *ppMemory = NdrAllocateZero(pStubMsg, memsize);
2284
2285 align_pointer(&pStubMsg->Buffer, alignment);
2286 saved_buffer = pStubMsg->Buffer;
2287
2288 pMemory = *ppMemory;
2289 count = pStubMsg->ActualCount;
2290 for (i = 0; i < count; i++)
2291 pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
2292 return pStubMsg->Buffer - saved_buffer;
2293
2294 default:
2295 ERR("unknown array format 0x%x\n", fc);
2297 }
2298}
2299
2300static inline void array_memory_size(
2301 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
2302 unsigned char fHasPointers)
2303{
2304 ULONG i, count, SavedMemorySize;
2305 ULONG bufsize, memsize;
2306 DWORD esize;
2307 unsigned char alignment;
2308
2309 switch (fc)
2310 {
2311 case FC_CARRAY:
2312 esize = *(const WORD*)(pFormat+2);
2313 alignment = pFormat[1] + 1;
2314
2315 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2316
2317 bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
2318 pStubMsg->MemorySize += memsize;
2319
2320 align_pointer(&pStubMsg->Buffer, alignment);
2321 if (fHasPointers)
2322 pStubMsg->BufferMark = pStubMsg->Buffer;
2323 safe_buffer_increment(pStubMsg, bufsize);
2324
2325 if (fHasPointers)
2326 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2327 break;
2328 case FC_CVARRAY:
2329 esize = *(const WORD*)(pFormat+2);
2330 alignment = pFormat[1] + 1;
2331
2332 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2333
2334 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2335
2336 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2337 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2338 pStubMsg->MemorySize += memsize;
2339
2340 align_pointer(&pStubMsg->Buffer, alignment);
2341 if (fHasPointers)
2342 pStubMsg->BufferMark = pStubMsg->Buffer;
2343 safe_buffer_increment(pStubMsg, bufsize);
2344
2345 if (fHasPointers)
2346 EmbeddedPointerMemorySize(pStubMsg, pFormat);
2347 break;
2348 case FC_C_CSTRING:
2349 case FC_C_WSTRING:
2350 if (fc == FC_C_CSTRING)
2351 esize = 1;
2352 else
2353 esize = 2;
2354
2355 ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
2356
2357 if (pFormat[1] != FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
2358 {
2359 ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
2360 pStubMsg->ActualCount, pStubMsg->MaxCount);
2362 }
2363 if (pStubMsg->Offset)
2364 {
2365 ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2367 }
2368
2369 memsize = safe_multiply(esize, pStubMsg->MaxCount);
2370 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2371
2372 validate_string_data(pStubMsg, bufsize, esize);
2373
2374 safe_buffer_increment(pStubMsg, bufsize);
2375 pStubMsg->MemorySize += memsize;
2376 break;
2377 case FC_BOGUS_ARRAY:
2378 alignment = pFormat[1] + 1;
2379 pFormat = SkipConformance(pStubMsg, pFormat + 4);
2380 pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
2381
2382 align_pointer(&pStubMsg->Buffer, alignment);
2383
2384 SavedMemorySize = pStubMsg->MemorySize;
2385
2386 esize = ComplexStructSize(pStubMsg, pFormat);
2387 memsize = safe_multiply(pStubMsg->MaxCount, esize);
2388
2389 count = pStubMsg->ActualCount;
2390 for (i = 0; i < count; i++)
2391 ComplexStructMemorySize(pStubMsg, pFormat, NULL);
2392
2393 pStubMsg->MemorySize = SavedMemorySize + memsize;
2394 break;
2395 default:
2396 ERR("unknown array format 0x%x\n", fc);
2398 }
2399}
2400
2401static inline void array_free(
2402 unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
2403 unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
2404{
2405 DWORD i, count;
2406
2407 switch (fc)
2408 {
2409 case FC_CARRAY:
2410 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2411 if (fHasPointers)
2412 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2413 break;
2414 case FC_CVARRAY:
2415 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2416 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2417 if (fHasPointers)
2418 EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2419 break;
2420 case FC_C_CSTRING:
2421 case FC_C_WSTRING:
2422 /* No embedded pointers so nothing to do */
2423 break;
2424 case FC_BOGUS_ARRAY:
2425 count = *(const WORD *)(pFormat + 2);
2426 pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, count);
2427 pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2428
2429 count = pStubMsg->ActualCount;
2430 for (i = 0; i < count; i++)
2431 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2432 break;
2433 default:
2434 ERR("unknown array format 0x%x\n", fc);
2436 }
2437}
2438
2439/*
2440 * NdrConformantString:
2441 *
2442 * What MS calls a ConformantString is, in DCE terminology,
2443 * a Varying-Conformant String.
2444 * [
2445 * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
2446 * offset: DWORD (actual string data begins at (offset) CHARTYPE's
2447 * into unmarshalled string)
2448 * length: DWORD (# of CHARTYPE characters, inclusive of '\0')
2449 * [
2450 * data: CHARTYPE[maxlen]
2451 * ]
2452 * ], where CHARTYPE is the appropriate character type (specified externally)
2453 *
2454 */
2455
2456/***********************************************************************
2457 * NdrConformantStringMarshall [RPCRT4.@]
2458 */
2460 unsigned char *pszMessage, PFORMAT_STRING pFormat)
2461{
2462 TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
2463
2464 if (pFormat[0] != FC_C_CSTRING && pFormat[0] != FC_C_WSTRING) {
2465 ERR("Unhandled string type: %#x\n", pFormat[0]);
2467 }
2468
2469 /* allow compiler to optimise inline function by passing constant into
2470 * these functions */
2471 if (pFormat[0] == FC_C_CSTRING) {
2473 pFormat);
2474 array_write_variance_and_marshall(FC_C_CSTRING, pStubMsg, pszMessage,
2475 pFormat, TRUE /* fHasPointers */);
2476 } else {
2478 pFormat);
2479 array_write_variance_and_marshall(FC_C_WSTRING, pStubMsg, pszMessage,
2480 pFormat, TRUE /* fHasPointers */);
2481 }
2482
2483 return NULL;
2484}
2485
2486/***********************************************************************
2487 * NdrConformantStringBufferSize [RPCRT4.@]
2488 */
2490 unsigned char* pMemory, PFORMAT_STRING pFormat)
2491{
2492 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2493
2494 if (pFormat[0] != FC_C_CSTRING && pFormat[0] != FC_C_WSTRING) {
2495 ERR("Unhandled string type: %#x\n", pFormat[0]);
2497 }
2498
2499 /* allow compiler to optimise inline function by passing constant into
2500 * these functions */
2501 if (pFormat[0] == FC_C_CSTRING) {
2503 pFormat);
2504 array_buffer_size(FC_C_CSTRING, pStubMsg, pMemory, pFormat,
2505 TRUE /* fHasPointers */);
2506 } else {
2508 pFormat);
2509 array_buffer_size(FC_C_WSTRING, pStubMsg, pMemory, pFormat,
2510 TRUE /* fHasPointers */);
2511 }
2512}
2513
2514/************************************************************************
2515 * NdrConformantStringMemorySize [RPCRT4.@]
2516 */
2518 PFORMAT_STRING pFormat )
2519{
2520 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2521
2522 if (pFormat[0] != FC_C_CSTRING && pFormat[0] != FC_C_WSTRING) {
2523 ERR("Unhandled string type: %#x\n", pFormat[0]);
2525 }
2526
2527 /* allow compiler to optimise inline function by passing constant into
2528 * these functions */
2529 if (pFormat[0] == FC_C_CSTRING) {
2530 array_read_conformance(FC_C_CSTRING, pStubMsg, pFormat);
2531 array_memory_size(FC_C_CSTRING, pStubMsg, pFormat,
2532 TRUE /* fHasPointers */);
2533 } else {
2534 array_read_conformance(FC_C_WSTRING, pStubMsg, pFormat);
2535 array_memory_size(FC_C_WSTRING, pStubMsg, pFormat,
2536 TRUE /* fHasPointers */);
2537 }
2538
2539 return pStubMsg->MemorySize;
2540}
2541
2542/************************************************************************
2543 * NdrConformantStringUnmarshall [RPCRT4.@]
2544 */
2546 unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
2547{
2548 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2549 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2550
2551 if (pFormat[0] != FC_C_CSTRING && pFormat[0] != FC_C_WSTRING) {
2552 ERR("Unhandled string type: %#x\n", *pFormat);
2554 }
2555
2556 /* allow compiler to optimise inline function by passing constant into
2557 * these functions */
2558 if (pFormat[0] == FC_C_CSTRING) {
2559 array_read_conformance(FC_C_CSTRING, pStubMsg, pFormat);
2561 pFormat, fMustAlloc,
2562 TRUE /* fUseBufferMemoryServer */,
2563 TRUE /* fUnmarshall */);
2564 } else {
2565 array_read_conformance(FC_C_WSTRING, pStubMsg, pFormat);
2567 pFormat, fMustAlloc,
2568 TRUE /* fUseBufferMemoryServer */,
2569 TRUE /* fUnmarshall */);
2570 }
2571
2572 return NULL;
2573}
2574
2575/***********************************************************************
2576 * NdrNonConformantStringMarshall [RPCRT4.@]
2577 */
2579 unsigned char *pMemory,
2580 PFORMAT_STRING pFormat)
2581{
2582 ULONG esize, size, maxsize;
2583
2584 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2585
2586 maxsize = *(const USHORT *)&pFormat[2];
2587
2588 if (*pFormat == FC_CSTRING)
2589 {
2590 ULONG i = 0;
2591 const char *str = (const char *)pMemory;
2592 while (i < maxsize && str[i]) i++;
2593 TRACE("string=%s\n", debugstr_an(str, i));
2594 pStubMsg->ActualCount = i + 1;
2595 esize = 1;
2596 }
2597 else if (*pFormat == FC_WSTRING)
2598 {
2599 ULONG i = 0;
2600 const WCHAR *str = (const WCHAR *)pMemory;
2601 while (i < maxsize && str[i]) i++;
2602 TRACE("string=%s\n", debugstr_wn(str, i));
2603 pStubMsg->ActualCount = i + 1;
2604 esize = 2;
2605 }
2606 else
2607 {
2608 ERR("Unhandled string type: %#x\n", *pFormat);
2610 }
2611
2612 pStubMsg->Offset = 0;
2613 WriteVariance(pStubMsg);
2614
2615 size = safe_multiply(esize, pStubMsg->ActualCount);
2616 safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
2617
2618 return NULL;
2619}
2620
2621/***********************************************************************
2622 * NdrNonConformantStringUnmarshall [RPCRT4.@]
2623 */
2625 unsigned char **ppMemory,
2626 PFORMAT_STRING pFormat,
2627 unsigned char fMustAlloc)
2628{
2629 ULONG bufsize, memsize, esize, maxsize;
2630
2631 TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
2632 pStubMsg, *ppMemory, pFormat, fMustAlloc);
2633
2634 maxsize = *(const USHORT *)&pFormat[2];
2635
2636 ReadVariance(pStubMsg, NULL, maxsize);
2637 if (pStubMsg->Offset)
2638 {
2639 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2641 }
2642
2643 if (*pFormat == FC_CSTRING) esize = 1;
2644 else if (*pFormat == FC_WSTRING) esize = 2;
2645 else
2646 {
2647 ERR("Unhandled string type: %#x\n", *pFormat);
2649 }
2650
2651 memsize = esize * maxsize;
2652 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2653
2654 validate_string_data(pStubMsg, bufsize, esize);
2655
2656 if (!fMustAlloc && !*ppMemory)
2657 fMustAlloc = TRUE;
2658 if (fMustAlloc)
2659 *ppMemory = NdrAllocate(pStubMsg, memsize);
2660
2661 safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
2662
2663 if (*pFormat == FC_CSTRING) {
2664 TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
2665 }
2666 else if (*pFormat == FC_WSTRING) {
2667 TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
2668 }
2669
2670 return NULL;
2671}
2672
2673/***********************************************************************
2674 * NdrNonConformantStringBufferSize [RPCRT4.@]
2675 */
2677 unsigned char *pMemory,
2678 PFORMAT_STRING pFormat)
2679{
2680 ULONG esize, maxsize;
2681
2682 TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
2683
2684 maxsize = *(const USHORT *)&pFormat[2];
2685
2686 SizeVariance(pStubMsg);
2687
2688 if (*pFormat == FC_CSTRING)
2689 {
2690 ULONG i = 0;
2691 const char *str = (const char *)pMemory;
2692 while (i < maxsize && str[i]) i++;
2693 TRACE("string=%s\n", debugstr_an(str, i));
2694 pStubMsg->ActualCount = i + 1;
2695 esize = 1;
2696 }
2697 else if (*pFormat == FC_WSTRING)
2698 {
2699 ULONG i = 0;
2700 const WCHAR *str = (const WCHAR *)pMemory;
2701 while (i < maxsize && str[i]) i++;
2702 TRACE("string=%s\n", debugstr_wn(str, i));
2703 pStubMsg->ActualCount = i + 1;
2704 esize = 2;
2705 }
2706 else
2707 {
2708 ERR("Unhandled string type: %#x\n", *pFormat);
2710 }
2711
2712 safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
2713}
2714
2715/***********************************************************************
2716 * NdrNonConformantStringMemorySize [RPCRT4.@]
2717 */
2719 PFORMAT_STRING pFormat)
2720{
2721 ULONG bufsize, memsize, esize, maxsize;
2722
2723 TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
2724
2725 maxsize = *(const USHORT *)&pFormat[2];
2726
2727 ReadVariance(pStubMsg, NULL, maxsize);
2728
2729 if (pStubMsg->Offset)
2730 {
2731 ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
2733 }
2734
2735 if (*pFormat == FC_CSTRING) esize = 1;
2736 else if (*pFormat == FC_WSTRING) esize = 2;
2737 else
2738 {
2739 ERR("Unhandled string type: %#x\n", *pFormat);
2741 }
2742
2743 memsize = esize * maxsize;
2744 bufsize = safe_multiply(esize, pStubMsg->ActualCount);
2745
2746 validate_string_data(pStubMsg, bufsize, esize);
2747
2748 safe_buffer_increment(pStubMsg, bufsize);
2749 pStubMsg->MemorySize += memsize;
2750
2751 return pStubMsg->MemorySize;
2752}
2753
2754/* Complex types */
2755
2756#include "pshpack1.h"
2757typedef struct
2758{
2759 unsigned char type;
2760 unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
2763} NDR_RANGE;
2764#include "poppack.h"
2765
2767 PFORMAT_STRING pFormat)
2768{
2769 switch (*pFormat) {
2770 case FC_STRUCT:
2771 case FC_PSTRUCT:
2772 case FC_CSTRUCT:
2773 case FC_BOGUS_STRUCT:
2774 case FC_SMFARRAY:
2775 case FC_SMVARRAY:
2776 case FC_CSTRING:
2777 return *(const WORD*)&pFormat[2];
2778 case FC_LGFARRAY:
2779 case FC_LGVARRAY:
2780 return *(const ULONG*)&pFormat[2];
2781 case FC_USER_MARSHAL:
2782 return *(const WORD*)&pFormat[4];
2783 case FC_RANGE: {
2784 switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
2785 case FC_BYTE:
2786 case FC_CHAR:
2787 case FC_SMALL:
2788 case FC_USMALL:
2789 return sizeof(UCHAR);
2790 case FC_WCHAR:
2791 case FC_SHORT:
2792 case FC_USHORT:
2793 return sizeof(USHORT);
2794 case FC_LONG:
2795 case FC_ULONG:
2796 case FC_ENUM32:
2797 return sizeof(ULONG);
2798 case FC_FLOAT:
2799 return sizeof(float);
2800 case FC_DOUBLE:
2801 return sizeof(double);
2802 case FC_HYPER:
2803 return sizeof(ULONGLONG);
2804 case FC_ENUM16:
2805 return sizeof(UINT);
2806 default:
2807 ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
2809 }
2810 }
2812 pFormat += 2;
2813 pFormat = SkipConformance(pStubMsg, pFormat);
2814 pFormat += *(const SHORT*)pFormat;
2815 return *(const SHORT*)pFormat;
2816 case FC_IP:
2817 return sizeof(void *);
2818 case FC_WSTRING:
2819 return *(const WORD*)&pFormat[2] * 2;
2820 default:
2821 FIXME("unhandled embedded type %02x\n", *pFormat);
2822 }
2823 return 0;
2824}
2825
2826
2828 PFORMAT_STRING pFormat)
2829{
2831
2832 if (!m)
2833 {
2834 FIXME("no memorysizer for data type=%02x\n", *pFormat);
2835 return 0;
2836 }
2837
2838 return m(pStubMsg, pFormat);
2839}
2840
2841
2842static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2843 unsigned char *pMemory,
2844 PFORMAT_STRING pFormat,
2845 PFORMAT_STRING pPointer)
2846{
2847 unsigned char *mem_base = pMemory;
2850 ULONG size;
2851
2852 while (*pFormat != FC_END) {
2853 switch (*pFormat) {
2854 case FC_BYTE:
2855 case FC_CHAR:
2856 case FC_SMALL:
2857 case FC_USMALL:
2858 TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
2859 safe_copy_to_buffer(pStubMsg, pMemory, 1);
2860 pMemory += 1;
2861 break;
2862 case FC_WCHAR:
2863 case FC_SHORT:
2864 case FC_USHORT:
2865 TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
2866 safe_copy_to_buffer(pStubMsg, pMemory, 2);
2867 pMemory += 2;
2868 break;
2869 case FC_ENUM16:
2870 {
2871 USHORT val = *(DWORD *)pMemory;
2872 TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2873 if (32767 < *(DWORD*)pMemory)
2875 safe_copy_to_buffer(pStubMsg, &val, 2);
2876 pMemory += 4;
2877 break;
2878 }
2879 case FC_LONG:
2880 case FC_ULONG:
2881 case FC_ENUM32:
2882 TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
2883 safe_copy_to_buffer(pStubMsg, pMemory, 4);
2884 pMemory += 4;
2885 break;
2886 case FC_INT3264:
2887 case FC_UINT3264:
2888 {
2889 UINT val = *(UINT_PTR *)pMemory;
2890 TRACE("int3264=%ld <= %p\n", *(UINT_PTR *)pMemory, pMemory);
2891 safe_copy_to_buffer(pStubMsg, &val, sizeof(UINT));
2892 pMemory += sizeof(UINT_PTR);
2893 break;
2894 }
2895 case FC_FLOAT:
2896 TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
2897 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
2898 pMemory += sizeof(float);
2899 break;
2900 case FC_HYPER:
2901 TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
2902 safe_copy_to_buffer(pStubMsg, pMemory, 8);
2903 pMemory += 8;
2904 break;
2905 case FC_DOUBLE:
2906 TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
2907 safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
2908 pMemory += sizeof(double);
2909 break;
2910 case FC_RP:
2911 case FC_UP:
2912 case FC_OP:
2913 case FC_FP:
2914 case FC_POINTER:
2915 {
2916 unsigned char *saved_buffer;
2917 BOOL pointer_buffer_mark_set = FALSE;
2918 TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
2919 TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
2920 if (*pFormat != FC_POINTER)
2921 pPointer = pFormat;
2922 if (*pPointer != FC_RP)
2923 align_pointer_clear(&pStubMsg->Buffer, 4);
2924 saved_buffer = pStubMsg->Buffer;
2925 if (pStubMsg->PointerBufferMark)
2926 {
2927 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
2928 pStubMsg->PointerBufferMark = NULL;
2929 pointer_buffer_mark_set = TRUE;
2930 }
2931 else if (*pPointer != FC_RP)
2932 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2933 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
2934 if (pointer_buffer_mark_set)
2935 {
2936 STD_OVERFLOW_CHECK(pStubMsg);
2937 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
2938 pStubMsg->Buffer = saved_buffer;
2939 if (*pPointer != FC_RP)
2940 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
2941 }
2942 TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
2943 if (*pFormat == FC_POINTER)
2944 pPointer += 4;
2945 else
2946 pFormat += 4;
2947 pMemory += sizeof(void *);
2948 break;
2949 }
2950 case FC_ALIGNM2:
2951 align_pointer_offset(&pMemory, mem_base, 2);
2952 break;
2953 case FC_ALIGNM4:
2954 align_pointer_offset(&pMemory, mem_base, 4);
2955 break;
2956 case FC_ALIGNM8:
2957 align_pointer_offset(&pMemory, mem_base, 8);
2958 break;
2959 case FC_STRUCTPAD1:
2960 case FC_STRUCTPAD2:
2961 case FC_STRUCTPAD3:
2962 case FC_STRUCTPAD4:
2963 case FC_STRUCTPAD5:
2964 case FC_STRUCTPAD6:
2965 case FC_STRUCTPAD7:
2966 pMemory += *pFormat - FC_STRUCTPAD1 + 1;
2967 break;
2969 pMemory += pFormat[1];
2970 pFormat += 2;
2971 desc = pFormat + *(const SHORT*)pFormat;
2972 size = EmbeddedComplexSize(pStubMsg, desc);
2973 TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
2975 if (m)
2976 {
2977 /* for some reason interface pointers aren't generated as
2978 * FC_POINTER, but instead as FC_EMBEDDED_COMPLEX, yet
2979 * they still need the dereferencing treatment that pointers are
2980 * given */
2981 if (*desc == FC_IP)
2982 m(pStubMsg, *(unsigned char **)pMemory, desc);
2983 else
2984 m(pStubMsg, pMemory, desc);
2985 }
2986 else FIXME("no marshaller for embedded type %02x\n", *desc);
2987 pMemory += size;
2988 pFormat += 2;
2989 continue;
2990 case FC_PAD:
2991 break;
2992 default:
2993 FIXME("unhandled format 0x%02x\n", *pFormat);
2994 }
2995 pFormat++;
2996 }
2997
2998 return pMemory;
2999}
3000
3001static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3002 unsigned char *pMemory,
3003 PFORMAT_STRING pFormat,
3004 PFORMAT_STRING pPointer,
3005 unsigned char fMustAlloc)
3006{
3007 unsigned char *mem_base = pMemory;
3010 ULONG size;
3011
3012 while (*pFormat != FC_END) {
3013 switch (*pFormat) {
3014 case FC_BYTE:
3015 case FC_CHAR:
3016 case FC_SMALL:
3017 case FC_USMALL:
3018 safe_copy_from_buffer(pStubMsg, pMemory, 1);
3019 TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
3020 pMemory += 1;
3021 break;
3022 case FC_WCHAR:
3023 case FC_SHORT:
3024 case FC_USHORT:
3025 safe_copy_from_buffer(pStubMsg, pMemory, 2);
3026 TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
3027 pMemory += 2;
3028 break;
3029 case FC_ENUM16:
3030 {
3031 WORD val;
3032 safe_copy_from_buffer(pStubMsg, &val, 2);
3033 *(DWORD*)pMemory = val;
3034 TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
3035 if (32767 < *(DWORD*)pMemory)
3037 pMemory += 4;
3038 break;
3039 }
3040 case FC_LONG:
3041 case FC_ULONG:
3042 case FC_ENUM32:
3043 safe_copy_from_buffer(pStubMsg, pMemory, 4);
3044 TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
3045 pMemory += 4;
3046 break;
3047 case FC_INT3264:
3048 {
3049 INT val;
3050 safe_copy_from_buffer(pStubMsg, &val, 4);
3051 *(INT_PTR *)pMemory = val;
3052 TRACE("int3264=%ld => %p\n", *(INT_PTR*)pMemory, pMemory);
3053 pMemory += sizeof(INT_PTR);
3054 break;
3055 }
3056 case FC_UINT3264:
3057 {
3058 UINT val;
3059 safe_copy_from_buffer(pStubMsg, &val, 4);
3060 *(UINT_PTR *)pMemory = val;
3061 TRACE("uint3264=%ld => %p\n", *(UINT_PTR*)pMemory, pMemory);
3062 pMemory += sizeof(UINT_PTR);
3063 break;
3064 }
3065 case FC_FLOAT:
3066 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
3067 TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
3068 pMemory += sizeof(float);
3069 break;
3070 case FC_HYPER:
3071 safe_copy_from_buffer(pStubMsg, pMemory, 8);
3072 TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
3073 pMemory += 8;
3074 break;
3075 case FC_DOUBLE:
3076 safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
3077 TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
3078 pMemory += sizeof(double);
3079 break;
3080 case FC_RP:
3081 case FC_UP:
3082 case FC_OP:
3083 case FC_FP:
3084 case FC_POINTER:
3085 {
3086 unsigned char *saved_buffer;
3087 BOOL pointer_buffer_mark_set = FALSE;
3088 TRACE("pointer => %p\n", pMemory);
3089 if (*pFormat != FC_POINTER)
3090 pPointer = pFormat;
3091 if (*pPointer != FC_RP)
3092 align_pointer(&pStubMsg->Buffer, 4);
3093 saved_buffer = pStubMsg->Buffer;
3094 if (pStubMsg->PointerBufferMark)
3095 {
3096 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3097 pStubMsg->PointerBufferMark = NULL;
3098 pointer_buffer_mark_set = TRUE;
3099 }
3100 else if (*pPointer != FC_RP)
3101 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3102
3103 PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
3104 if (pointer_buffer_mark_set)
3105 {
3106 STD_OVERFLOW_CHECK(pStubMsg);
3107 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3108 pStubMsg->Buffer = saved_buffer;
3109 if (*pPointer != FC_RP)
3110 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3111 }
3112 if (*pFormat == FC_POINTER)
3113 pPointer += 4;
3114 else
3115 pFormat += 4;
3116 pMemory += sizeof(void *);
3117 break;
3118 }
3119 case FC_ALIGNM2:
3120 align_pointer_offset_clear(&pMemory, mem_base, 2);
3121 break;
3122 case FC_ALIGNM4:
3123 align_pointer_offset_clear(&pMemory, mem_base, 4);
3124 break;
3125 case FC_ALIGNM8:
3126 align_pointer_offset_clear(&pMemory, mem_base, 8);
3127 break;
3128 case FC_STRUCTPAD1:
3129 case FC_STRUCTPAD2:
3130 case FC_STRUCTPAD3:
3131 case FC_STRUCTPAD4:
3132 case FC_STRUCTPAD5:
3133 case FC_STRUCTPAD6:
3134 case FC_STRUCTPAD7:
3135 memset(pMemory, 0, *pFormat - FC_STRUCTPAD1 + 1);
3136 pMemory += *pFormat - FC_STRUCTPAD1 + 1;
3137 break;
3139 pMemory += pFormat[1];
3140 pFormat += 2;
3141 desc = pFormat + *(const SHORT*)pFormat;
3142 size = EmbeddedComplexSize(pStubMsg, desc);
3143 TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
3144 if (fMustAlloc)
3145 /* we can't pass fMustAlloc=TRUE into the marshaller for this type
3146 * since the type is part of the memory block that is encompassed by
3147 * the whole complex type. Memory is forced to allocate when pointers
3148 * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
3149 * clearing the memory we pass in to the unmarshaller */
3150 memset(pMemory, 0, size);
3152 if (m)
3153 {
3154 /* for some reason interface pointers aren't generated as
3155 * FC_POINTER, but instead as FC_EMBEDDED_COMPLEX, yet
3156 * they still need the dereferencing treatment that pointers are
3157 * given */
3158 if (*desc == FC_IP)
3159 m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
3160 else
3161 m(pStubMsg, &pMemory, desc, FALSE);
3162 }
3163 else FIXME("no unmarshaller for embedded type %02x\n", *desc);
3164 pMemory += size;
3165 pFormat += 2;
3166 continue;
3167 case FC_PAD:
3168 break;
3169 default:
3170 FIXME("unhandled format %d\n", *pFormat);
3171 }
3172 pFormat++;
3173 }
3174
3175 return pMemory;
3176}
3177
3178static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3179 unsigned char *pMemory,
3180 PFORMAT_STRING pFormat,
3181 PFORMAT_STRING pPointer)
3182{
3183 unsigned char *mem_base = pMemory;
3186 ULONG size;
3187
3188 while (*pFormat != FC_END) {
3189 switch (*pFormat) {
3190 case FC_BYTE:
3191 case FC_CHAR:
3192 case FC_SMALL:
3193 case FC_USMALL:
3194 safe_buffer_length_increment(pStubMsg, 1);
3195 pMemory += 1;
3196 break;
3197 case FC_WCHAR:
3198 case FC_SHORT:
3199 case FC_USHORT:
3200 safe_buffer_length_increment(pStubMsg, 2);
3201 pMemory += 2;
3202 break;
3203 case FC_ENUM16:
3204 safe_buffer_length_increment(pStubMsg, 2);
3205 pMemory += 4;
3206 break;
3207 case FC_LONG:
3208 case FC_ULONG:
3209 case FC_ENUM32:
3210 case FC_FLOAT:
3211 safe_buffer_length_increment(pStubMsg, 4);
3212 pMemory += 4;
3213 break;
3214 case FC_INT3264:
3215 case FC_UINT3264:
3216 safe_buffer_length_increment(pStubMsg, 4);
3217 pMemory += sizeof(INT_PTR);
3218 break;
3219 case FC_HYPER:
3220 case FC_DOUBLE:
3221 safe_buffer_length_increment(pStubMsg, 8);
3222 pMemory += 8;
3223 break;
3224 case FC_RP:
3225 case FC_UP:
3226 case FC_OP:
3227 case FC_FP:
3228 case FC_POINTER:
3229 if (*pFormat != FC_POINTER)
3230 pPointer = pFormat;
3231 if (!pStubMsg->IgnoreEmbeddedPointers)
3232 {
3233 int saved_buffer_length = pStubMsg->BufferLength;
3234 pStubMsg->BufferLength = pStubMsg->PointerLength;
3235 pStubMsg->PointerLength = 0;
3236 if(!pStubMsg->BufferLength)
3237 ERR("BufferLength == 0??\n");
3238 PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
3239 pStubMsg->PointerLength = pStubMsg->BufferLength;
3240 pStubMsg->BufferLength = saved_buffer_length;
3241 }
3242 if (*pPointer != FC_RP)
3243 {
3244 align_length(&pStubMsg->BufferLength, 4);
3245 safe_buffer_length_increment(pStubMsg, 4);
3246 }
3247 if (*pFormat == FC_POINTER)
3248 pPointer += 4;
3249 else
3250 pFormat += 4;
3251 pMemory += sizeof(void*);
3252 break;
3253 case FC_ALIGNM2:
3254 align_pointer_offset(&pMemory, mem_base, 2);
3255 break;
3256 case FC_ALIGNM4:
3257 align_pointer_offset(&pMemory, mem_base, 4);
3258 break;
3259 case FC_ALIGNM8:
3260 align_pointer_offset(&pMemory, mem_base, 8);
3261 break;
3262 case FC_STRUCTPAD1:
3263 case FC_STRUCTPAD2:
3264 case FC_STRUCTPAD3:
3265 case FC_STRUCTPAD4:
3266 case FC_STRUCTPAD5:
3267 case FC_STRUCTPAD6:
3268 case FC_STRUCTPAD7:
3269 pMemory += *pFormat - FC_STRUCTPAD1 + 1;
3270 break;
3272 pMemory += pFormat[1];
3273 pFormat += 2;
3274 desc = pFormat + *(const SHORT*)pFormat;
3275 size = EmbeddedComplexSize(pStubMsg, desc);
3277 if (m)
3278 {
3279 /* for some reason interface pointers aren't generated as
3280 * FC_POINTER, but instead as FC_EMBEDDED_COMPLEX, yet
3281 * they still need the dereferencing treatment that pointers are
3282 * given */
3283 if (*desc == FC_IP)
3284 m(pStubMsg, *(unsigned char **)pMemory, desc);
3285 else
3286 m(pStubMsg, pMemory, desc);
3287 }
3288 else FIXME("no buffersizer for embedded type %02x\n", *desc);
3289 pMemory += size;
3290 pFormat += 2;
3291 continue;
3292 case FC_PAD:
3293 break;
3294 default:
3295 FIXME("unhandled format 0x%02x\n", *pFormat);
3296 }
3297 pFormat++;
3298 }
3299
3300 return pMemory;
3301}
3302
3303static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
3304 unsigned char *pMemory,
3305 PFORMAT_STRING pFormat,
3306 PFORMAT_STRING pPointer)
3307{
3308 unsigned char *mem_base = pMemory;
3310 NDR_FREE m;
3311 ULONG size;
3312
3313 while (*pFormat != FC_END) {
3314 switch (*pFormat) {
3315 case FC_BYTE:
3316 case FC_CHAR:
3317 case FC_SMALL:
3318 case FC_USMALL:
3319 pMemory += 1;
3320 break;
3321 case FC_WCHAR:
3322 case FC_SHORT:
3323 case FC_USHORT:
3324 pMemory += 2;
3325 break;
3326 case FC_LONG:
3327 case FC_ULONG:
3328 case FC_ENUM16:
3329 case FC_ENUM32:
3330 case FC_FLOAT:
3331 pMemory += 4;
3332 break;
3333 case FC_INT3264:
3334 case FC_UINT3264:
3335 pMemory += sizeof(INT_PTR);
3336 break;
3337 case FC_HYPER:
3338 case FC_DOUBLE:
3339 pMemory += 8;
3340 break;
3341 case FC_RP:
3342 case FC_UP:
3343 case FC_OP:
3344 case FC_FP:
3345 case FC_POINTER:
3346 if (*pFormat != FC_POINTER)
3347 pPointer = pFormat;
3348 NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
3349 if (*pFormat == FC_POINTER)
3350 pPointer += 4;
3351 else
3352 pFormat += 4;
3353 pMemory += sizeof(void *);
3354 break;
3355 case FC_ALIGNM2:
3356 align_pointer_offset(&pMemory, mem_base, 2);
3357 break;
3358 case FC_ALIGNM4:
3359 align_pointer_offset(&pMemory, mem_base, 4);
3360 break;
3361 case FC_ALIGNM8:
3362 align_pointer_offset(&pMemory, mem_base, 8);
3363 break;
3364 case FC_STRUCTPAD1:
3365 case FC_STRUCTPAD2:
3366 case FC_STRUCTPAD3:
3367 case FC_STRUCTPAD4:
3368 case FC_STRUCTPAD5:
3369 case FC_STRUCTPAD6:
3370 case FC_STRUCTPAD7:
3371 pMemory += *pFormat - FC_STRUCTPAD1 + 1;
3372 break;
3374 pMemory += pFormat[1];
3375 pFormat += 2;
3376 desc = pFormat + *(const SHORT*)pFormat;
3377 size = EmbeddedComplexSize(pStubMsg, desc);
3379 if (m)
3380 {
3381 /* for some reason interface pointers aren't generated as
3382 * FC_POINTER, but instead as FC_EMBEDDED_COMPLEX, yet
3383 * they still need the dereferencing treatment that pointers are
3384 * given */
3385 if (*desc == FC_IP)
3386 m(pStubMsg, *(unsigned char **)pMemory, desc);
3387 else
3388 m(pStubMsg, pMemory, desc);
3389 }
3390 pMemory += size;
3391 pFormat += 2;
3392 continue;
3393 case FC_PAD:
3394 break;
3395 default:
3396 FIXME("unhandled format 0x%02x\n", *pFormat);
3397 }
3398 pFormat++;
3399 }
3400
3401 return pMemory;
3402}
3403
3405 PFORMAT_STRING pFormat,
3406 PFORMAT_STRING pPointer)
3407{
3409 ULONG size = 0;
3410
3411 while (*pFormat != FC_END) {
3412 switch (*pFormat) {
3413 case FC_BYTE:
3414 case FC_CHAR:
3415 case FC_SMALL:
3416 case FC_USMALL:
3417 size += 1;
3418 safe_buffer_increment(pStubMsg, 1);
3419 break;
3420 case FC_WCHAR:
3421 case FC_SHORT:
3422 case FC_USHORT:
3423 size += 2;
3424 safe_buffer_increment(pStubMsg, 2);
3425 break;
3426 case FC_ENUM16:
3427 size += 4;
3428 safe_buffer_increment(pStubMsg, 2);
3429 break;
3430 case FC_LONG:
3431 case FC_ULONG:
3432 case FC_ENUM32:
3433 case FC_FLOAT:
3434 size += 4;
3435 safe_buffer_increment(pStubMsg, 4);
3436 break;
3437 case FC_INT3264:
3438 case FC_UINT3264:
3439 size += sizeof(INT_PTR);
3440 safe_buffer_increment(pStubMsg, 4);
3441 break;
3442 case FC_HYPER:
3443 case FC_DOUBLE:
3444 size += 8;
3445 safe_buffer_increment(pStubMsg, 8);
3446 break;
3447 case FC_RP:
3448 case FC_UP:
3449 case FC_OP:
3450 case FC_FP:
3451 case FC_POINTER:
3452 {
3453 unsigned char *saved_buffer;
3454 BOOL pointer_buffer_mark_set = FALSE;
3455 if (*pFormat != FC_POINTER)
3456 pPointer = pFormat;
3457 if (*pPointer != FC_RP)
3458 align_pointer(&pStubMsg->Buffer, 4);
3459 saved_buffer = pStubMsg->Buffer;
3460 if (pStubMsg->PointerBufferMark)
3461 {
3462 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3463 pStubMsg->PointerBufferMark = NULL;
3464 pointer_buffer_mark_set = TRUE;
3465 }
3466 else if (*pPointer != FC_RP)
3467 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3468
3469 if (!pStubMsg->IgnoreEmbeddedPointers)
3470 PointerMemorySize(pStubMsg, saved_buffer, pPointer);
3471 if (pointer_buffer_mark_set)
3472 {
3473 STD_OVERFLOW_CHECK(pStubMsg);
3474 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3475 pStubMsg->Buffer = saved_buffer;
3476 if (*pPointer != FC_RP)
3477 safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
3478 }
3479 if (*pFormat == FC_POINTER)
3480 pPointer += 4;
3481 else
3482 pFormat += 4;
3483 size += sizeof(void *);
3484 break;
3485 }
3486 case FC_ALIGNM2:
3487 align_length(&size, 2);
3488 break;
3489 case FC_ALIGNM4:
3490 align_length(&size, 4);
3491 break;
3492 case FC_ALIGNM8:
3493 align_length(&size, 8);
3494 break;
3495 case FC_STRUCTPAD1:
3496 case FC_STRUCTPAD2:
3497 case FC_STRUCTPAD3:
3498 case FC_STRUCTPAD4:
3499 case FC_STRUCTPAD5:
3500 case FC_STRUCTPAD6:
3501 case FC_STRUCTPAD7:
3502 size += *pFormat - FC_STRUCTPAD1 + 1;
3503 break;
3505 size += pFormat[1];
3506 pFormat += 2;
3507 desc = pFormat + *(const SHORT*)pFormat;
3508 size += EmbeddedComplexMemorySize(pStubMsg, desc);
3509 pFormat += 2;
3510 continue;
3511 case FC_PAD:
3512 break;
3513 default:
3514 FIXME("unhandled format 0x%02x\n", *pFormat);
3515 }
3516 pFormat++;
3517 }
3518
3519 return size;
3520}
3521
3523{
3525 ULONG size = 0;
3526
3527 while (*pFormat != FC_END) {
3528 switch (*pFormat) {
3529 case FC_BYTE:
3530 case FC_CHAR:
3531 case FC_SMALL:
3532 case FC_USMALL:
3533 size += 1;
3534 break;
3535 case FC_WCHAR:
3536 case FC_SHORT:
3537 case FC_USHORT:
3538 size += 2;
3539 break;
3540 case FC_LONG:
3541 case FC_ULONG:
3542 case FC_ENUM16:
3543 case FC_ENUM32:
3544 case FC_FLOAT:
3545 size += 4;
3546 break;
3547 case FC_INT3264:
3548 case FC_UINT3264:
3549 size += sizeof(INT_PTR);
3550 break;
3551 case FC_HYPER:
3552 case FC_DOUBLE:
3553 size += 8;
3554 break;
3555 case FC_RP:
3556 case FC_UP:
3557 case FC_OP:
3558 case FC_FP:
3559 case FC_POINTER:
3560 size += sizeof(void *);
3561 if (*pFormat != FC_POINTER)
3562 pFormat += 4;
3563 break;
3564 case FC_ALIGNM2:
3565 align_length(&size, 2);
3566 break;
3567 case FC_ALIGNM4:
3568 align_length(&size, 4);
3569 break;
3570 case FC_ALIGNM8:
3571 align_length(&size, 8);
3572 break;
3573 case FC_STRUCTPAD1:
3574 case FC_STRUCTPAD2:
3575 case FC_STRUCTPAD3:
3576 case FC_STRUCTPAD4:
3577 case FC_STRUCTPAD5:
3578 case FC_STRUCTPAD6:
3579 case FC_STRUCTPAD7:
3580 size += *pFormat - FC_STRUCTPAD1 + 1;
3581 break;
3583 size += pFormat[1];
3584 pFormat += 2;
3585 desc = pFormat + *(const SHORT*)pFormat;
3586 size += EmbeddedComplexSize(pStubMsg, desc);
3587 pFormat += 2;
3588 continue;
3589 case FC_PAD:
3590 break;
3591 default:
3592 FIXME("unhandled format 0x%02x\n", *pFormat);
3593 }
3594 pFormat++;
3595 }
3596
3597 return size;
3598}
3599
3600/***********************************************************************
3601 * NdrComplexStructMarshall [RPCRT4.@]
3602 */
3604 unsigned char *pMemory,
3605 PFORMAT_STRING pFormat)
3606{
3607 PFORMAT_STRING conf_array = NULL;
3608 PFORMAT_STRING pointer_desc = NULL;
3609 unsigned char *OldMemory = pStubMsg->Memory;
3610 BOOL pointer_buffer_mark_set = FALSE;
3611 ULONG count = 0;
3612 ULONG max_count = 0;
3613 ULONG offset = 0;
3614
3615 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3616
3617 if (!pStubMsg->PointerBufferMark)
3618 {
3619 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3620 /* save buffer length */
3621 ULONG saved_buffer_length = pStubMsg->BufferLength;
3622
3623 /* get the buffer pointer after complex array data, but before
3624 * pointer data */
3625 pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
3626 pStubMsg->IgnoreEmbeddedPointers = 1;
3627 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3628 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3629
3630 /* save it for use by embedded pointer code later */
3631 pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
3632 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
3633 pointer_buffer_mark_set = TRUE;
3634
3635 /* restore the original buffer length */
3636 pStubMsg->BufferLength = saved_buffer_length;
3637 }
3638
3639 align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
3640
3641 pFormat += 4;
3642 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3643 pFormat += 2;
3644 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3645 pFormat += 2;
3646
3647 pStubMsg->Memory = pMemory;
3648
3649 if (conf_array)
3650 {
3651 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3652 array_compute_and_write_conformance(conf_array[0], pStubMsg,
3653 pMemory + struct_size, conf_array);
3654 /* these could be changed in ComplexMarshall so save them for later */
3655 max_count = pStubMsg->MaxCount;
3656 count = pStubMsg->ActualCount;
3657 offset = pStubMsg->Offset;
3658 }
3659
3660 pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
3661
3662 if (conf_array)
3663 {
3664 pStubMsg->MaxCount = max_count;
3665 pStubMsg->ActualCount = count;
3666 pStubMsg->Offset = offset;
3667 array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
3668 conf_array, TRUE /* fHasPointers */);
3669 }
3670
3671 pStubMsg->Memory = OldMemory;
3672
3673 if (pointer_buffer_mark_set)
3674 {
3675 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3676 pStubMsg->PointerBufferMark = NULL;
3677 }
3678
3679 STD_OVERFLOW_CHECK(pStubMsg);
3680
3681 return NULL;
3682}
3683
3684/***********************************************************************
3685 * NdrComplexStructUnmarshall [RPCRT4.@]
3686 */
3688 unsigned char **ppMemory,
3689 PFORMAT_STRING pFormat,
3690 unsigned char fMustAlloc)
3691{
3692 unsigned size = *(const WORD*)(pFormat+2);
3693 PFORMAT_STRING conf_array = NULL;
3694 PFORMAT_STRING pointer_desc = NULL;
3695 unsigned char *pMemory;
3696 BOOL pointer_buffer_mark_set = FALSE;
3697 ULONG count = 0;
3698 ULONG max_count = 0;
3699 ULONG offset = 0;
3700 ULONG array_size = 0;
3701
3702 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3703
3704 if (!pStubMsg->PointerBufferMark)
3705 {
3706 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3707 /* save buffer pointer */
3708 unsigned char *saved_buffer = pStubMsg->Buffer;
3709
3710 /* get the buffer pointer after complex array data, but before
3711 * pointer data */
3712 pStubMsg->IgnoreEmbeddedPointers = 1;
3713 NdrComplexStructMemorySize(pStubMsg, pFormat);
3714 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3715
3716 /* save it for use by embedded pointer code later */
3717 pStubMsg->PointerBufferMark = pStubMsg->Buffer;
3718 TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
3719 pointer_buffer_mark_set = TRUE;
3720
3721 /* restore the original buffer */
3722 pStubMsg->Buffer = saved_buffer;
3723 }
3724
3725 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
3726
3727 pFormat += 4;
3728 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3729 pFormat += 2;
3730 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3731 pFormat += 2;
3732
3733 if (conf_array)
3734 {
3735 array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
3736 size += array_size;
3737
3738 /* these could be changed in ComplexMarshall so save them for later */
3739 max_count = pStubMsg->MaxCount;
3740 count = pStubMsg->ActualCount;
3741 offset = pStubMsg->Offset;
3742 }
3743
3744 if (!fMustAlloc && !*ppMemory)
3745 fMustAlloc = TRUE;
3746 if (fMustAlloc)
3747 *ppMemory = NdrAllocateZero(pStubMsg, size);
3748
3749 pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
3750
3751 if (conf_array)
3752 {
3753 pStubMsg->MaxCount = max_count;
3754 pStubMsg->ActualCount = count;
3755 pStubMsg->Offset = offset;
3756 if (fMustAlloc)
3758 array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
3759 conf_array, FALSE,
3760 FALSE /* fUseBufferMemoryServer */,
3761 TRUE /* fUnmarshall */);
3762 }
3763
3764 if (pointer_buffer_mark_set)
3765 {
3766 pStubMsg->Buffer = pStubMsg->PointerBufferMark;
3767 pStubMsg->PointerBufferMark = NULL;
3768 }
3769
3770 return NULL;
3771}
3772
3773/***********************************************************************
3774 * NdrComplexStructBufferSize [RPCRT4.@]
3775 */
3777 unsigned char *pMemory,
3778 PFORMAT_STRING pFormat)
3779{
3780 PFORMAT_STRING conf_array = NULL;
3781 PFORMAT_STRING pointer_desc = NULL;
3782 unsigned char *OldMemory = pStubMsg->Memory;
3783 int pointer_length_set = 0;
3784 ULONG count = 0;
3785 ULONG max_count = 0;
3786 ULONG offset = 0;
3787
3788 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3789
3790 align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
3791
3792 if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
3793 {
3794 int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
3795 ULONG saved_buffer_length = pStubMsg->BufferLength;
3796
3797 /* get the buffer length after complex struct data, but before
3798 * pointer data */
3799 pStubMsg->IgnoreEmbeddedPointers = 1;
3800 NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
3801 pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
3802
3803 /* save it for use by embedded pointer code later */
3804 pStubMsg->PointerLength = pStubMsg->BufferLength;
3805 pointer_length_set = 1;
3806 TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
3807
3808 /* restore the original buffer length */
3809 pStubMsg->BufferLength = saved_buffer_length;
3810 }
3811
3812 pFormat += 4;
3813 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3814 pFormat += 2;
3815 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3816 pFormat += 2;
3817
3818 pStubMsg->Memory = pMemory;
3819
3820 if (conf_array)
3821 {
3822 ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
3823 array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
3824 conf_array);
3825
3826 /* these could be changed in ComplexMarshall so save them for later */
3827 max_count = pStubMsg->MaxCount;
3828 count = pStubMsg->ActualCount;
3829 offset = pStubMsg->Offset;
3830 }
3831
3832 pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
3833
3834 if (conf_array)
3835 {
3836 pStubMsg->MaxCount = max_count;
3837 pStubMsg->ActualCount = count;
3838 pStubMsg->Offset = offset;
3839 array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
3840 TRUE /* fHasPointers */);
3841 }
3842
3843 pStubMsg->Memory = OldMemory;
3844
3845 if(pointer_length_set)
3846 {
3847 pStubMsg->BufferLength = pStubMsg->PointerLength;
3848 pStubMsg->PointerLength = 0;
3849 }
3850
3851}
3852
3853/***********************************************************************
3854 * NdrComplexStructMemorySize [RPCRT4.@]
3855 */
3857 PFORMAT_STRING pFormat)
3858{
3859 unsigned size = *(const WORD*)(pFormat+2);
3860 PFORMAT_STRING conf_array = NULL;
3861 PFORMAT_STRING pointer_desc = NULL;
3862 ULONG count = 0;
3863 ULONG max_count = 0;
3864 ULONG offset = 0;
3865
3866 TRACE("(%p,%p)\n", pStubMsg, pFormat);
3867
3868 align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
3869
3870 pFormat += 4;
3871 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3872 pFormat += 2;
3873 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3874 pFormat += 2;
3875
3876 if (conf_array)
3877 {
3878 array_read_conformance(conf_array[0], pStubMsg, conf_array);
3879
3880 /* these could be changed in ComplexStructMemorySize so save them for
3881 * later */
3882 max_count = pStubMsg->MaxCount;
3883 count = pStubMsg->ActualCount;
3884 offset = pStubMsg->Offset;
3885 }
3886
3887 ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
3888
3889 if (conf_array)
3890 {
3891 pStubMsg->MaxCount = max_count;
3892 pStubMsg->ActualCount = count;
3893 pStubMsg->Offset = offset;
3894 array_memory_size(conf_array[0], pStubMsg, conf_array,
3895 TRUE /* fHasPointers */);
3896 }
3897
3898 return size;
3899}
3900
3901/***********************************************************************
3902 * NdrComplexStructFree [RPCRT4.@]
3903 */
3905 unsigned char *pMemory,
3906 PFORMAT_STRING pFormat)
3907{
3908 PFORMAT_STRING conf_array = NULL;
3909 PFORMAT_STRING pointer_desc = NULL;
3910 unsigned char *OldMemory = pStubMsg->Memory;
3911
3912 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3913
3914 pFormat += 4;
3915 if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
3916 pFormat += 2;
3917 if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
3918 pFormat += 2;
3919
3920 pStubMsg->Memory = pMemory;
3921
3922 pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
3923
3924 if (conf_array)
3925 array_free(conf_array[0], pStubMsg, pMemory, conf_array,
3926 TRUE /* fHasPointers */);
3927
3928 pStubMsg->Memory = OldMemory;
3929}
3930
3931/***********************************************************************
3932 * NdrConformantArrayMarshall [RPCRT4.@]
3933 */
3935 unsigned char *pMemory,
3936 PFORMAT_STRING pFormat)
3937{
3938 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3939 if (pFormat[0] != FC_CARRAY)
3940 {
3941 ERR("invalid format = 0x%x\n", pFormat[0]);
3943 }
3944
3946 pFormat);
3948 TRUE /* fHasPointers */);
3949
3950 return NULL;
3951}
3952
3953/***********************************************************************
3954 * NdrConformantArrayUnmarshall [RPCRT4.@]
3955 */
3957 unsigned char **ppMemory,
3958 PFORMAT_STRING pFormat,
3959 unsigned char fMustAlloc)
3960{
3961 TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3962 if (pFormat[0] != FC_CARRAY)
3963 {
3964 ERR("invalid format = 0x%x\n", pFormat[0]);
3966 }
3967
3968 array_read_conformance(FC_CARRAY, pStubMsg, pFormat);
3969 array_read_variance_and_unmarshall(FC_CARRAY, pStubMsg, ppMemory, pFormat,
3970 fMustAlloc,
3971 TRUE /* fUseBufferMemoryServer */,
3972 TRUE /* fUnmarshall */);
3973
3974 return NULL;
3975}
3976
3977/***********************************************************************
3978 * NdrConformantArrayBufferSize [RPCRT4.@]
3979 */
3981 unsigned char *pMemory,
3982 PFORMAT_STRING pFormat)
3983{
3984 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
3985 if (pFormat[0] != FC_CARRAY)
3986 {
3987 ERR("invalid format = 0x%x\n", pFormat[0]);
3989 }
3990
3992 array_buffer_size(FC_CARRAY, pStubMsg, pMemory, pFormat,
3993 TRUE /* fHasPointers */);
3994}
3995
3996/***********************************************************************
3997 * NdrConformantArrayMemorySize [RPCRT4.@]
3998 */
4000 PFORMAT_STRING pFormat)
4001{
4002 TRACE("(%p,%p)\n", pStubMsg, pFormat);
4003 if (pFormat[0] != FC_CARRAY)
4004 {
4005 ERR("invalid format = 0x%x\n", pFormat[0]);
4007 }
4008
4009 array_read_conformance(FC_CARRAY, pStubMsg, pFormat);
4010 array_memory_size(FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
4011
4012 return pStubMsg->MemorySize;
4013}
4014
4015/***********************************************************************
4016 * NdrConformantArrayFree [RPCRT4.@]
4017 */
4019 unsigned char *pMemory,
4020 PFORMAT_STRING pFormat)
4021{
4022 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4023 if (pFormat[0] != FC_CARRAY)
4024 {
4025 ERR("invalid format = 0x%x\n", pFormat[0]);
4027 }
4028
4029 array_free(FC_CARRAY, pStubMsg, pMemory, pFormat,
4030 TRUE /* fHasPointers */);
4031}
4032
4033
4034/***********************************************************************
4035 * NdrConformantVaryingArrayMarshall [RPCRT4.@]
4036 */
4038 unsigned char* pMemory,
4039 PFORMAT_STRING pFormat )
4040{
4041 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4042
4043 if (pFormat[0] != FC_CVARRAY)
4044 {
4045 ERR("invalid format type %x\n", pFormat[0]);
4047 return NULL;
4048 }
4049
4051 pFormat);
4053 pFormat, TRUE /* fHasPointers */);
4054
4055 return NULL;
4056}
4057
4058
4059/***********************************************************************
4060 * NdrConformantVaryingArrayUnmarshall [RPCRT4.@]
4061 */
4063 unsigned char** ppMemory,
4064 PFORMAT_STRING pFormat,
4065 unsigned char fMustAlloc )
4066{
4067 TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
4068
4069 if (pFormat[0] != FC_CVARRAY)
4070 {
4071 ERR("invalid format type %x\n", pFormat[0]);
4073 return NULL;
4074 }
4075
4076 array_read_conformance(FC_CVARRAY, pStubMsg, pFormat);
4078 pFormat, fMustAlloc,
4079 TRUE /* fUseBufferMemoryServer */,
4080 TRUE /* fUnmarshall */);
4081
4082 return NULL;
4083}
4084
4085
4086/***********************************************************************
4087 * NdrConformantVaryingArrayFree [RPCRT4.@]
4088 */
4090 unsigned char* pMemory,
4091 PFORMAT_STRING pFormat )
4092{
4093 TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
4094
4095 if (pFormat[0] != FC_CVARRAY)
4096 {
4097 ERR("invalid format type %x\n", pFormat[0]);
4099 return;
4100 }
4101
4102 array_free(FC_CVARRAY, pStubMsg, pMemory, pFormat,
4103 TRUE /* fHasPointers */);
4104}
4105
4106
4107/***********************************************************************
4108 * NdrConformantVaryingArrayBufferSize [RPCRT4.@]
4109 */
4111 unsigned char* pMemory, PFORMAT_STRING pFormat )
4112{
4113 TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
4114
4115 if (pFormat[0] != FC_CVARRAY)
4116 {
4117 ERR("invalid format type %x\n", pFormat[0]);
4119 return;
4120 }
4121
4123 pFormat);
4124 array_buffer_size(FC_CVARRAY, pStubMsg, pMemory, pFormat,
4125 TRUE /* fHasPointers */);
4126}
4127
4128
4129/***********************************************************************
4130 * NdrConformantVaryingArrayMemorySize [RPCRT4.@]
4131 */
4133 PFORMAT_STRING pFormat )
4134{
4135 TRACE("(%p, %p)\n", pStubMsg, pFormat);
4136
4137 if (pFormat[0] != FC_CVARRAY)
4138 {
4139 ERR("invalid format type %x\n", pFormat[0]);
4141 return pStubMsg->MemorySize;
4142 }
4143
4144 array_read_conformance(FC_CVARRAY, pStubMsg, pFormat);
4145 array_memory_size(FC_CVARRAY, pStubMsg, pFormat,
4146 TRUE /* fHasPointers */);
4147