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