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