ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ndr_marshall.c
Go to the documentation of this file.
00001 /*
00002  * NDR data marshalling
00003  *
00004  * Copyright 2002 Greg Turner
00005  * Copyright 2003-2006 CodeWeavers
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  *
00021  * TODO:
00022  *  - String structs
00023  *  - Byte count pointers
00024  *  - transmit_as/represent as
00025  *  - Multi-dimensional arrays
00026  *  - Conversion functions (NdrConvert)
00027  *  - Checks for integer addition overflow in user marshall functions
00028  */
00029 
00030 #include <assert.h>
00031 #include <stdarg.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <limits.h>
00035 
00036 #define NONAMELESSUNION
00037 #include "windef.h"
00038 #include "winbase.h"
00039 #include "winerror.h"
00040 
00041 #include "ndr_misc.h"
00042 #include "rpcndr.h"
00043 #include "ndrtypes.h"
00044 
00045 #include "wine/unicode.h"
00046 #include "wine/rpcfc.h"
00047 
00048 #include "wine/debug.h"
00049 
00050 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00051 
00052 #if defined(__i386__)
00053 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
00054     (*((UINT32 *)(pchar)) = (uint32))
00055 
00056 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
00057     (*((UINT32 *)(pchar)))
00058 #else
00059   /* these would work for i386 too, but less efficient */
00060 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
00061     (*(pchar)     = LOBYTE(LOWORD(uint32)), \
00062      *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
00063      *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
00064      *((pchar)+3) = HIBYTE(HIWORD(uint32)))
00065 
00066 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
00067     (MAKELONG( \
00068       MAKEWORD(*(pchar), *((pchar)+1)), \
00069       MAKEWORD(*((pchar)+2), *((pchar)+3))))
00070 #endif
00071 
00072 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
00073   (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
00074    *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
00075    *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
00076    *(pchar)     = HIBYTE(HIWORD(uint32)))
00077 
00078 #define BIG_ENDIAN_UINT32_READ(pchar) \
00079   (MAKELONG( \
00080     MAKEWORD(*((pchar)+3), *((pchar)+2)), \
00081     MAKEWORD(*((pchar)+1), *(pchar))))
00082 
00083 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
00084 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
00085     BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
00086 # define NDR_LOCAL_UINT32_READ(pchar) \
00087     BIG_ENDIAN_UINT32_READ(pchar)
00088 #else
00089 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
00090     LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
00091 # define NDR_LOCAL_UINT32_READ(pchar) \
00092     LITTLE_ENDIAN_UINT32_READ(pchar)
00093 #endif
00094 
00095 static inline void align_length( ULONG *len, unsigned int align )
00096 {
00097     *len = (*len + align - 1) & ~(align - 1);
00098 }
00099 
00100 static inline void align_pointer( unsigned char **ptr, unsigned int align )
00101 {
00102     ULONG_PTR mask = align - 1;
00103     *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
00104 }
00105 
00106 static inline void align_pointer_clear( unsigned char **ptr, unsigned int align )
00107 {
00108     ULONG_PTR mask = align - 1;
00109     memset( *ptr, 0, (align - (ULONG_PTR)*ptr) & mask );
00110     *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask);
00111 }
00112 
00113 #define STD_OVERFLOW_CHECK(_Msg) do { \
00114     TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
00115     if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
00116         ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
00117   } while (0)
00118 
00119 #define NDR_POINTER_ID_BASE 0x20000
00120 #define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4)
00121 #define NDR_TABLE_SIZE 128
00122 #define NDR_TABLE_MASK 127
00123 
00124 #define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL))
00125 
00126 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
00127 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
00128 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
00129 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
00130 static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
00131 
00132 static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
00133 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
00134 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
00135 
00136 static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
00137 static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
00138 static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
00139 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
00140 
00141 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
00142 
00143 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
00144                                          unsigned char *pMemory,
00145                                          PFORMAT_STRING pFormat,
00146                                          PFORMAT_STRING pPointer);
00147 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
00148                                        unsigned char *pMemory,
00149                                        PFORMAT_STRING pFormat,
00150                                        PFORMAT_STRING pPointer);
00151 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
00152                                          unsigned char *pMemory,
00153                                          PFORMAT_STRING pFormat,
00154                                          PFORMAT_STRING pPointer,
00155                                          unsigned char fMustAlloc);
00156 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
00157                                      PFORMAT_STRING pFormat,
00158                                      PFORMAT_STRING pPointer);
00159 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
00160                                    unsigned char *pMemory,
00161                                    PFORMAT_STRING pFormat,
00162                                    PFORMAT_STRING pPointer);
00163 
00164 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
00165   0,
00166   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
00167   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
00168   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
00169   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
00170   /* 0x10 */
00171   NdrBaseTypeMarshall,
00172   /* 0x11 */
00173   NdrPointerMarshall, NdrPointerMarshall,
00174   NdrPointerMarshall, NdrPointerMarshall,
00175   /* 0x15 */
00176   NdrSimpleStructMarshall, NdrSimpleStructMarshall,
00177   NdrConformantStructMarshall, NdrConformantStructMarshall,
00178   NdrConformantVaryingStructMarshall,
00179   NdrComplexStructMarshall,
00180   /* 0x1b */
00181   NdrConformantArrayMarshall, 
00182   NdrConformantVaryingArrayMarshall,
00183   NdrFixedArrayMarshall, NdrFixedArrayMarshall,
00184   NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
00185   NdrComplexArrayMarshall,
00186   /* 0x22 */
00187   NdrConformantStringMarshall, 0, 0,
00188   NdrConformantStringMarshall,
00189   NdrNonConformantStringMarshall, 0, 0, 0,
00190   /* 0x2a */
00191   NdrEncapsulatedUnionMarshall,
00192   NdrNonEncapsulatedUnionMarshall,
00193   NdrByteCountPointerMarshall,
00194   NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
00195   /* 0x2f */
00196   NdrInterfacePointerMarshall,
00197   /* 0x30 */
00198   NdrContextHandleMarshall,
00199   /* 0xb1 */
00200   0, 0, 0,
00201   NdrUserMarshalMarshall,
00202   0, 0,
00203   /* 0xb7 */
00204   NdrRangeMarshall
00205 };
00206 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
00207   0,
00208   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
00209   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
00210   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
00211   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
00212   /* 0x10 */
00213   NdrBaseTypeUnmarshall,
00214   /* 0x11 */
00215   NdrPointerUnmarshall, NdrPointerUnmarshall,
00216   NdrPointerUnmarshall, NdrPointerUnmarshall,
00217   /* 0x15 */
00218   NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
00219   NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
00220   NdrConformantVaryingStructUnmarshall,
00221   NdrComplexStructUnmarshall,
00222   /* 0x1b */
00223   NdrConformantArrayUnmarshall, 
00224   NdrConformantVaryingArrayUnmarshall,
00225   NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
00226   NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
00227   NdrComplexArrayUnmarshall,
00228   /* 0x22 */
00229   NdrConformantStringUnmarshall, 0, 0,
00230   NdrConformantStringUnmarshall,
00231   NdrNonConformantStringUnmarshall, 0, 0, 0,
00232   /* 0x2a */
00233   NdrEncapsulatedUnionUnmarshall,
00234   NdrNonEncapsulatedUnionUnmarshall,
00235   NdrByteCountPointerUnmarshall,
00236   NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
00237   /* 0x2f */
00238   NdrInterfacePointerUnmarshall,
00239   /* 0x30 */
00240   NdrContextHandleUnmarshall,
00241   /* 0xb1 */
00242   0, 0, 0,
00243   NdrUserMarshalUnmarshall,
00244   0, 0,
00245   /* 0xb7 */
00246   NdrRangeUnmarshall
00247 };
00248 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
00249   0,
00250   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
00251   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
00252   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
00253   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
00254   /* 0x10 */
00255   NdrBaseTypeBufferSize,
00256   /* 0x11 */
00257   NdrPointerBufferSize, NdrPointerBufferSize,
00258   NdrPointerBufferSize, NdrPointerBufferSize,
00259   /* 0x15 */
00260   NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
00261   NdrConformantStructBufferSize, NdrConformantStructBufferSize,
00262   NdrConformantVaryingStructBufferSize,
00263   NdrComplexStructBufferSize,
00264   /* 0x1b */
00265   NdrConformantArrayBufferSize, 
00266   NdrConformantVaryingArrayBufferSize,
00267   NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
00268   NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
00269   NdrComplexArrayBufferSize,
00270   /* 0x22 */
00271   NdrConformantStringBufferSize, 0, 0,
00272   NdrConformantStringBufferSize,
00273   NdrNonConformantStringBufferSize, 0, 0, 0,
00274   /* 0x2a */
00275   NdrEncapsulatedUnionBufferSize,
00276   NdrNonEncapsulatedUnionBufferSize,
00277   NdrByteCountPointerBufferSize,
00278   NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
00279   /* 0x2f */
00280   NdrInterfacePointerBufferSize,
00281   /* 0x30 */
00282   NdrContextHandleBufferSize,
00283   /* 0xb1 */
00284   0, 0, 0,
00285   NdrUserMarshalBufferSize,
00286   0, 0,
00287   /* 0xb7 */
00288   NdrRangeBufferSize
00289 };
00290 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
00291   0,
00292   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
00293   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
00294   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
00295   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
00296   /* 0x10 */
00297   NdrBaseTypeMemorySize,
00298   /* 0x11 */
00299   NdrPointerMemorySize, NdrPointerMemorySize,
00300   NdrPointerMemorySize, NdrPointerMemorySize,
00301   /* 0x15 */
00302   NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
00303   NdrConformantStructMemorySize, NdrConformantStructMemorySize,
00304   NdrConformantVaryingStructMemorySize,
00305   NdrComplexStructMemorySize,
00306   /* 0x1b */
00307   NdrConformantArrayMemorySize,
00308   NdrConformantVaryingArrayMemorySize,
00309   NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
00310   NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
00311   NdrComplexArrayMemorySize,
00312   /* 0x22 */
00313   NdrConformantStringMemorySize, 0, 0,
00314   NdrConformantStringMemorySize,
00315   NdrNonConformantStringMemorySize, 0, 0, 0,
00316   /* 0x2a */
00317   NdrEncapsulatedUnionMemorySize,
00318   NdrNonEncapsulatedUnionMemorySize,
00319   NdrByteCountPointerMemorySize,
00320   NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
00321   /* 0x2f */
00322   NdrInterfacePointerMemorySize,
00323   /* 0x30 */
00324   0,
00325   /* 0xb1 */
00326   0, 0, 0,
00327   NdrUserMarshalMemorySize,
00328   0, 0,
00329   /* 0xb7 */
00330   NdrRangeMemorySize
00331 };
00332 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
00333   0,
00334   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
00335   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
00336   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
00337   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
00338   /* 0x10 */
00339   NdrBaseTypeFree,
00340   /* 0x11 */
00341   NdrPointerFree, NdrPointerFree,
00342   NdrPointerFree, NdrPointerFree,
00343   /* 0x15 */
00344   NdrSimpleStructFree, NdrSimpleStructFree,
00345   NdrConformantStructFree, NdrConformantStructFree,
00346   NdrConformantVaryingStructFree,
00347   NdrComplexStructFree,
00348   /* 0x1b */
00349   NdrConformantArrayFree, 
00350   NdrConformantVaryingArrayFree,
00351   NdrFixedArrayFree, NdrFixedArrayFree,
00352   NdrVaryingArrayFree, NdrVaryingArrayFree,
00353   NdrComplexArrayFree,
00354   /* 0x22 */
00355   0, 0, 0,
00356   0, 0, 0, 0, 0,
00357   /* 0x2a */
00358   NdrEncapsulatedUnionFree,
00359   NdrNonEncapsulatedUnionFree,
00360   0,
00361   NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
00362   /* 0x2f */
00363   NdrInterfacePointerFree,
00364   /* 0x30 */
00365   0,
00366   /* 0xb1 */
00367   0, 0, 0,
00368   NdrUserMarshalFree,
00369   0, 0,
00370   /* 0xb7 */
00371   NdrRangeFree
00372 };
00373 
00374 typedef struct _NDR_MEMORY_LIST
00375 {
00376     ULONG magic;
00377     ULONG size;
00378     ULONG reserved;
00379     struct _NDR_MEMORY_LIST *next;
00380 } NDR_MEMORY_LIST;
00381 
00382 #define MEML_MAGIC  ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L')
00383 
00384 /***********************************************************************
00385  *            NdrAllocate [RPCRT4.@]
00386  *
00387  * Allocates a block of memory using pStubMsg->pfnAllocate.
00388  *
00389  * PARAMS
00390  *  pStubMsg [I/O] MIDL_STUB_MESSAGE structure.
00391  *  len      [I]   Size of memory block to allocate.
00392  *
00393  * RETURNS
00394  *  The memory block of size len that was allocated.
00395  *
00396  * NOTES
00397  *  The memory block is always 8-byte aligned.
00398  *  If the function is unable to allocate memory an ERROR_OUTOFMEMORY
00399  *  exception is raised.
00400  */
00401 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len)
00402 {
00403     SIZE_T aligned_len;
00404     SIZE_T adjusted_len;
00405     void *p;
00406     NDR_MEMORY_LIST *mem_list;
00407 
00408     aligned_len = (len + 7) & ~7;
00409     adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST);
00410     /* check for overflow */
00411     if (adjusted_len < len)
00412     {
00413         ERR("overflow of adjusted_len %ld, len %ld\n", adjusted_len, len);
00414         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00415     }
00416 
00417     p = pStubMsg->pfnAllocate(adjusted_len);
00418     if (!p) RpcRaiseException(ERROR_OUTOFMEMORY);
00419 
00420     mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len);
00421     mem_list->magic = MEML_MAGIC;
00422     mem_list->size = aligned_len;
00423     mem_list->reserved = 0;
00424     mem_list->next = pStubMsg->pMemoryList;
00425     pStubMsg->pMemoryList = mem_list;
00426 
00427     TRACE("-- %p\n", p);
00428     return p;
00429 }
00430 
00431 static void NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
00432 {
00433     TRACE("(%p, %p)\n", pStubMsg, Pointer);
00434 
00435     pStubMsg->pfnFree(Pointer);
00436 }
00437 
00438 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
00439 {
00440     return (*(const ULONG *)pFormat != -1);
00441 }
00442 
00443 static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
00444 {
00445   align_pointer(&pStubMsg->Buffer, 4);
00446   if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd)
00447       RpcRaiseException(RPC_X_BAD_STUB_DATA);
00448   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
00449   pStubMsg->Buffer += 4;
00450   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
00451   if (pStubMsg->fHasNewCorrDesc)
00452     return pFormat+6;
00453   else
00454     return pFormat+4;
00455 }
00456 
00457 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue)
00458 {
00459   if (pFormat && !IsConformanceOrVariancePresent(pFormat))
00460   {
00461     pStubMsg->Offset = 0;
00462     pStubMsg->ActualCount = pStubMsg->MaxCount;
00463     goto done;
00464   }
00465 
00466   align_pointer(&pStubMsg->Buffer, 4);
00467   if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd)
00468     RpcRaiseException(RPC_X_BAD_STUB_DATA);
00469   pStubMsg->Offset      = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
00470   pStubMsg->Buffer += 4;
00471   TRACE("offset is %d\n", pStubMsg->Offset);
00472   pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
00473   pStubMsg->Buffer += 4;
00474   TRACE("variance is %d\n", pStubMsg->ActualCount);
00475 
00476   if ((pStubMsg->ActualCount > MaxValue) ||
00477       (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue))
00478   {
00479     ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n",
00480         pStubMsg->ActualCount, pStubMsg->Offset, MaxValue);
00481     RpcRaiseException(RPC_S_INVALID_BOUND);
00482     return NULL;
00483   }
00484 
00485 done:
00486   if (pStubMsg->fHasNewCorrDesc)
00487     return pFormat+6;
00488   else
00489     return pFormat+4;
00490 }
00491 
00492 /* writes the conformance value to the buffer */
00493 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
00494 {
00495     align_pointer_clear(&pStubMsg->Buffer, 4);
00496     if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
00497         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00498     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
00499     pStubMsg->Buffer += 4;
00500 }
00501 
00502 /* writes the variance values to the buffer */
00503 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
00504 {
00505     align_pointer_clear(&pStubMsg->Buffer, 4);
00506     if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
00507         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00508     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
00509     pStubMsg->Buffer += 4;
00510     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
00511     pStubMsg->Buffer += 4;
00512 }
00513 
00514 /* requests buffer space for the conformance value */
00515 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
00516 {
00517     align_length(&pStubMsg->BufferLength, 4);
00518     if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength)
00519         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00520     pStubMsg->BufferLength += 4;
00521 }
00522 
00523 /* requests buffer space for the variance values */
00524 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
00525 {
00526     align_length(&pStubMsg->BufferLength, 4);
00527     if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength)
00528         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00529     pStubMsg->BufferLength += 8;
00530 }
00531 
00532 PFORMAT_STRING ComputeConformanceOrVariance(
00533     MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
00534     PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount)
00535 {
00536   BYTE dtype = pFormat[0] & 0xf;
00537   short ofs = *(const short *)&pFormat[2];
00538   LPVOID ptr = NULL;
00539   ULONG_PTR data = 0;
00540 
00541   if (!IsConformanceOrVariancePresent(pFormat)) {
00542     /* null descriptor */
00543     *pCount = def;
00544     goto finish_conf;
00545   }
00546 
00547   switch (pFormat[0] & 0xf0) {
00548   case RPC_FC_NORMAL_CONFORMANCE:
00549     TRACE("normal conformance, ofs=%d\n", ofs);
00550     ptr = pMemory;
00551     break;
00552   case RPC_FC_POINTER_CONFORMANCE:
00553     TRACE("pointer conformance, ofs=%d\n", ofs);
00554     ptr = pStubMsg->Memory;
00555     break;
00556   case RPC_FC_TOP_LEVEL_CONFORMANCE:
00557     TRACE("toplevel conformance, ofs=%d\n", ofs);
00558     if (pStubMsg->StackTop) {
00559       ptr = pStubMsg->StackTop;
00560     }
00561     else {
00562       /* -Os mode, *pCount is already set */
00563       goto finish_conf;
00564     }
00565     break;
00566   case RPC_FC_CONSTANT_CONFORMANCE:
00567     data = ofs | ((DWORD)pFormat[1] << 16);
00568     TRACE("constant conformance, val=%ld\n", data);
00569     *pCount = data;
00570     goto finish_conf;
00571   case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
00572     FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
00573     if (pStubMsg->StackTop) {
00574       ptr = pStubMsg->StackTop;
00575     }
00576     else {
00577       /* ? */
00578       goto done_conf_grab;
00579     }
00580     break;
00581   default:
00582     FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0);
00583     goto finish_conf;
00584   }
00585 
00586   switch (pFormat[1]) {
00587   case RPC_FC_DEREFERENCE:
00588     ptr = *(LPVOID*)((char *)ptr + ofs);
00589     break;
00590   case RPC_FC_CALLBACK:
00591   {
00592     unsigned char *old_stack_top = pStubMsg->StackTop;
00593     ULONG_PTR max_count, old_max_count = pStubMsg->MaxCount;
00594 
00595     pStubMsg->StackTop = ptr;
00596 
00597     /* ofs is index into StubDesc->apfnExprEval */
00598     TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
00599     pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
00600 
00601     pStubMsg->StackTop = old_stack_top;
00602 
00603     /* the callback function always stores the computed value in MaxCount */
00604     max_count = pStubMsg->MaxCount;
00605     pStubMsg->MaxCount = old_max_count;
00606     *pCount = max_count;
00607     goto finish_conf;
00608   }
00609   default:
00610     ptr = (char *)ptr + ofs;
00611     break;
00612   }
00613 
00614   switch (dtype) {
00615   case RPC_FC_LONG:
00616   case RPC_FC_ULONG:
00617     data = *(DWORD*)ptr;
00618     break;
00619   case RPC_FC_SHORT:
00620     data = *(SHORT*)ptr;
00621     break;
00622   case RPC_FC_USHORT:
00623     data = *(USHORT*)ptr;
00624     break;
00625   case RPC_FC_CHAR:
00626   case RPC_FC_SMALL:
00627     data = *(CHAR*)ptr;
00628     break;
00629   case RPC_FC_BYTE:
00630   case RPC_FC_USMALL:
00631     data = *(UCHAR*)ptr;
00632     break;
00633   case RPC_FC_HYPER:
00634     data = *(ULONGLONG *)ptr;
00635     break;
00636   default:
00637     FIXME("unknown conformance data type %x\n", dtype);
00638     goto done_conf_grab;
00639   }
00640   TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);
00641 
00642 done_conf_grab:
00643   switch (pFormat[1]) {
00644   case RPC_FC_DEREFERENCE: /* already handled */
00645   case 0: /* no op */
00646     *pCount = data;
00647     break;
00648   case RPC_FC_ADD_1:
00649     *pCount = data + 1;
00650     break;
00651   case RPC_FC_SUB_1:
00652     *pCount = data - 1;
00653     break;
00654   case RPC_FC_MULT_2:
00655     *pCount = data * 2;
00656     break;
00657   case RPC_FC_DIV_2:
00658     *pCount = data / 2;
00659     break;
00660   default:
00661     FIXME("unknown conformance op %d\n", pFormat[1]);
00662     goto finish_conf;
00663   }
00664 
00665 finish_conf:
00666   TRACE("resulting conformance is %ld\n", *pCount);
00667   if (pStubMsg->fHasNewCorrDesc)
00668     return pFormat+6;
00669   else
00670     return pFormat+4;
00671 }
00672 
00673 static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg,
00674                                              PFORMAT_STRING pFormat)
00675 {
00676     if (pStubMsg->fHasNewCorrDesc)
00677       pFormat += 6;
00678     else
00679       pFormat += 4;
00680     return pFormat;
00681 }
00682 
00683 static inline PFORMAT_STRING SkipVariance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
00684 {
00685     return SkipConformance( pStubMsg, pFormat );
00686 }
00687 
00688 /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if
00689  * the result overflows 32-bits */
00690 static inline ULONG safe_multiply(ULONG a, ULONG b)
00691 {
00692     ULONGLONG ret = (ULONGLONG)a * b;
00693     if (ret > 0xffffffff)
00694     {
00695         RpcRaiseException(RPC_S_INVALID_BOUND);
00696         return 0;
00697     }
00698     return ret;
00699 }
00700 
00701 static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
00702 {
00703     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
00704         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
00705         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00706     pStubMsg->Buffer += size;
00707 }
00708 
00709 static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size)
00710 {
00711     if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */
00712     {
00713         ERR("buffer length overflow - BufferLength = %u, size = %u\n",
00714             pStubMsg->BufferLength, size);
00715         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00716     }
00717     pStubMsg->BufferLength += size;
00718 }
00719 
00720 /* copies data from the buffer, checking that there is enough data in the buffer
00721  * to do so */
00722 static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size)
00723 {
00724     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
00725         (pStubMsg->Buffer + size > pStubMsg->BufferEnd))
00726     {
00727         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
00728             pStubMsg->Buffer, pStubMsg->BufferEnd, size);
00729         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00730     }
00731     if (p == pStubMsg->Buffer)
00732         ERR("pointer is the same as the buffer\n");
00733     memcpy(p, pStubMsg->Buffer, size);
00734     pStubMsg->Buffer += size;
00735 }
00736 
00737 /* copies data to the buffer, checking that there is enough space to do so */
00738 static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size)
00739 {
00740     if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */
00741         (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength))
00742     {
00743         ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n",
00744             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength,
00745             size);
00746         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00747     }
00748     memcpy(pStubMsg->Buffer, p, size);
00749     pStubMsg->Buffer += size;
00750 }
00751 
00752 /* verify that string data sitting in the buffer is valid and safe to
00753  * unmarshall */
00754 static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize)
00755 {
00756     ULONG i;
00757 
00758     /* verify the buffer is safe to access */
00759     if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) ||
00760         (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd))
00761     {
00762         ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize,
00763             pStubMsg->BufferEnd, pStubMsg->Buffer);
00764         RpcRaiseException(RPC_X_BAD_STUB_DATA);
00765     }
00766 
00767     /* strings must always have null terminating bytes */
00768     if (bufsize < esize)
00769     {
00770         ERR("invalid string length of %d\n", bufsize / esize);
00771         RpcRaiseException(RPC_S_INVALID_BOUND);
00772     }
00773 
00774     for (i = bufsize - esize; i < bufsize; i++)
00775         if (pStubMsg->Buffer[i] != 0)
00776         {
00777             ERR("string not null-terminated at byte position %d, data is 0x%x\n",
00778                 i, pStubMsg->Buffer[i]);
00779             RpcRaiseException(RPC_S_INVALID_BOUND);
00780         }
00781 }
00782 
00783 static inline void dump_pointer_attr(unsigned char attr)
00784 {
00785     if (attr & RPC_FC_P_ALLOCALLNODES)
00786         TRACE(" RPC_FC_P_ALLOCALLNODES");
00787     if (attr & RPC_FC_P_DONTFREE)
00788         TRACE(" RPC_FC_P_DONTFREE");
00789     if (attr & RPC_FC_P_ONSTACK)
00790         TRACE(" RPC_FC_P_ONSTACK");
00791     if (attr & RPC_FC_P_SIMPLEPOINTER)
00792         TRACE(" RPC_FC_P_SIMPLEPOINTER");
00793     if (attr & RPC_FC_P_DEREF)
00794         TRACE(" RPC_FC_P_DEREF");
00795     TRACE("\n");
00796 }
00797 
00798 /***********************************************************************
00799  *           PointerMarshall [internal]
00800  */
00801 static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
00802                             unsigned char *Buffer,
00803                             unsigned char *Pointer,
00804                             PFORMAT_STRING pFormat)
00805 {
00806   unsigned type = pFormat[0], attr = pFormat[1];
00807   PFORMAT_STRING desc;
00808   NDR_MARSHALL m;
00809   ULONG pointer_id;
00810   int pointer_needs_marshaling;
00811 
00812   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
00813   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
00814   pFormat += 2;
00815   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
00816   else desc = pFormat + *(const SHORT*)pFormat;
00817 
00818   switch (type) {
00819   case RPC_FC_RP: /* ref pointer (always non-null) */
00820     if (!Pointer)
00821     {
00822       ERR("NULL ref pointer is not allowed\n");
00823       RpcRaiseException(RPC_X_NULL_REF_POINTER);
00824     }
00825     pointer_needs_marshaling = 1;
00826     break;
00827   case RPC_FC_UP: /* unique pointer */
00828   case RPC_FC_OP: /* object pointer - same as unique here */
00829     if (Pointer)
00830       pointer_needs_marshaling = 1;
00831     else
00832       pointer_needs_marshaling = 0;
00833     pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0;
00834     TRACE("writing 0x%08x to buffer\n", pointer_id);
00835     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
00836     break;
00837   case RPC_FC_FP:
00838     pointer_needs_marshaling = !NdrFullPointerQueryPointer(
00839       pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id);
00840     TRACE("writing 0x%08x to buffer\n", pointer_id);
00841     NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id);
00842     break;
00843   default:
00844     FIXME("unhandled ptr type=%02x\n", type);
00845     RpcRaiseException(RPC_X_BAD_STUB_DATA);
00846     return;
00847   }
00848 
00849   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
00850 
00851   if (pointer_needs_marshaling) {
00852     if (attr & RPC_FC_P_DEREF) {
00853       Pointer = *(unsigned char**)Pointer;
00854       TRACE("deref => %p\n", Pointer);
00855     }
00856     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
00857     if (m) m(pStubMsg, Pointer, desc);
00858     else FIXME("no marshaller for data type=%02x\n", *desc);
00859   }
00860 
00861   STD_OVERFLOW_CHECK(pStubMsg);
00862 }
00863 
00864 /***********************************************************************
00865  *           PointerUnmarshall [internal]
00866  */
00867 static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
00868                               unsigned char *Buffer,
00869                               unsigned char **pPointer,
00870                               unsigned char *pSrcPointer,
00871                               PFORMAT_STRING pFormat,
00872                               unsigned char fMustAlloc)
00873 {
00874   unsigned type = pFormat[0], attr = pFormat[1];
00875   PFORMAT_STRING desc;
00876   NDR_UNMARSHALL m;
00877   DWORD pointer_id = 0;
00878   int pointer_needs_unmarshaling;
00879 
00880   TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
00881   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
00882   pFormat += 2;
00883   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
00884   else desc = pFormat + *(const SHORT*)pFormat;
00885 
00886   switch (type) {
00887   case RPC_FC_RP: /* ref pointer (always non-null) */
00888     pointer_needs_unmarshaling = 1;
00889     break;
00890   case RPC_FC_UP: /* unique pointer */
00891     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
00892     TRACE("pointer_id is 0x%08x\n", pointer_id);
00893     if (pointer_id)
00894       pointer_needs_unmarshaling = 1;
00895     else {
00896       *pPointer = NULL;
00897       pointer_needs_unmarshaling = 0;
00898     }
00899     break;
00900   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
00901     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
00902     TRACE("pointer_id is 0x%08x\n", pointer_id);
00903     if (!fMustAlloc && pSrcPointer)
00904     {
00905         FIXME("free object pointer %p\n", pSrcPointer);
00906         fMustAlloc = TRUE;
00907     }
00908     if (pointer_id)
00909       pointer_needs_unmarshaling = 1;
00910     else
00911     {
00912       *pPointer = NULL;    
00913       pointer_needs_unmarshaling = 0;
00914     }
00915     break;
00916   case RPC_FC_FP:
00917     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
00918     TRACE("pointer_id is 0x%08x\n", pointer_id);
00919     pointer_needs_unmarshaling = !NdrFullPointerQueryRefId(
00920       pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer);
00921     break;
00922   default:
00923     FIXME("unhandled ptr type=%02x\n", type);
00924     RpcRaiseException(RPC_X_BAD_STUB_DATA);
00925     return;
00926   }
00927 
00928   if (pointer_needs_unmarshaling) {
00929     unsigned char **current_ptr = pPointer;
00930     if (pStubMsg->IsClient) {
00931       TRACE("client\n");
00932       /* if we aren't forcing allocation of memory then try to use the existing
00933        * (source) pointer to unmarshall the data into so that [in,out]
00934        * parameters behave correctly. it doesn't matter if the parameter is
00935        * [out] only since in that case the pointer will be NULL. we force
00936        * allocation when the source pointer is NULL here instead of in the type
00937        * unmarshalling routine for the benefit of the deref code below */
00938       if (!fMustAlloc) {
00939         if (pSrcPointer) {
00940           TRACE("setting *pPointer to %p\n", pSrcPointer);
00941           *pPointer = pSrcPointer;
00942         } else
00943           fMustAlloc = TRUE;
00944       }
00945     } else {
00946       TRACE("server\n");
00947       /* the memory in a stub is never initialised, so we have to work out here
00948        * whether we have to initialise it so we can use the optimisation of
00949        * setting the pointer to the buffer, if possible, or set fMustAlloc to
00950        * TRUE. */
00951       if (attr & RPC_FC_P_DEREF) {
00952         fMustAlloc = TRUE;
00953       } else {
00954         *current_ptr = NULL;
00955       }
00956     }
00957 
00958     if (attr & RPC_FC_P_ALLOCALLNODES)
00959         FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n");
00960 
00961     if (attr & RPC_FC_P_DEREF) {
00962       if (fMustAlloc) {
00963         unsigned char *base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *));
00964         *pPointer = base_ptr_val;
00965         current_ptr = (unsigned char **)base_ptr_val;
00966       } else
00967         current_ptr = *(unsigned char***)current_ptr;
00968       TRACE("deref => %p\n", current_ptr);
00969       if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
00970     }
00971     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
00972     if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
00973     else FIXME("no unmarshaller for data type=%02x\n", *desc);
00974 
00975     if (type == RPC_FC_FP)
00976       NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
00977                                 *pPointer);
00978   }
00979 
00980   TRACE("pointer=%p\n", *pPointer);
00981 }
00982 
00983 /***********************************************************************
00984  *           PointerBufferSize [internal]
00985  */
00986 static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
00987                               unsigned char *Pointer,
00988                               PFORMAT_STRING pFormat)
00989 {
00990   unsigned type = pFormat[0], attr = pFormat[1];
00991   PFORMAT_STRING desc;
00992   NDR_BUFFERSIZE m;
00993   int pointer_needs_sizing;
00994   ULONG pointer_id;
00995 
00996   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
00997   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
00998   pFormat += 2;
00999   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
01000   else desc = pFormat + *(const SHORT*)pFormat;
01001 
01002   switch (type) {
01003   case RPC_FC_RP: /* ref pointer (always non-null) */
01004     if (!Pointer)
01005     {
01006       ERR("NULL ref pointer is not allowed\n");
01007       RpcRaiseException(RPC_X_NULL_REF_POINTER);
01008     }
01009     break;
01010   case RPC_FC_OP:
01011   case RPC_FC_UP:
01012     /* NULL pointer has no further representation */
01013     if (!Pointer)
01014         return;
01015     break;
01016   case RPC_FC_FP:
01017     pointer_needs_sizing = !NdrFullPointerQueryPointer(
01018       pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id);
01019     if (!pointer_needs_sizing)
01020       return;
01021     break;
01022   default:
01023     FIXME("unhandled ptr type=%02x\n", type);
01024     RpcRaiseException(RPC_X_BAD_STUB_DATA);
01025     return;
01026   }
01027 
01028   if (attr & RPC_FC_P_DEREF) {
01029     Pointer = *(unsigned char**)Pointer;
01030     TRACE("deref => %p\n", Pointer);
01031   }
01032 
01033   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
01034   if (m) m(pStubMsg, Pointer, desc);
01035   else FIXME("no buffersizer for data type=%02x\n", *desc);
01036 }
01037 
01038 /***********************************************************************
01039  *           PointerMemorySize [internal]
01040  */
01041 static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
01042                                unsigned char *Buffer, PFORMAT_STRING pFormat)
01043 {
01044   unsigned type = pFormat[0], attr = pFormat[1];
01045   PFORMAT_STRING desc;
01046   NDR_MEMORYSIZE m;
01047   DWORD pointer_id = 0;
01048   int pointer_needs_sizing;
01049 
01050   TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat);
01051   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
01052   pFormat += 2;
01053   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
01054   else desc = pFormat + *(const SHORT*)pFormat;
01055 
01056   switch (type) {
01057   case RPC_FC_RP: /* ref pointer (always non-null) */
01058     pointer_needs_sizing = 1;
01059     break;
01060   case RPC_FC_UP: /* unique pointer */
01061   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
01062     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
01063     TRACE("pointer_id is 0x%08x\n", pointer_id);
01064     if (pointer_id)
01065       pointer_needs_sizing = 1;
01066     else
01067       pointer_needs_sizing = 0;
01068     break;
01069   case RPC_FC_FP:
01070   {
01071     void *pointer;
01072     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
01073     TRACE("pointer_id is 0x%08x\n", pointer_id);
01074     pointer_needs_sizing = !NdrFullPointerQueryRefId(
01075       pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer);
01076     break;
01077   }
01078   default:
01079     FIXME("unhandled ptr type=%02x\n", type);
01080     RpcRaiseException(RPC_X_BAD_STUB_DATA);
01081     return 0;
01082   }
01083 
01084   if (attr & RPC_FC_P_DEREF) {
01085     align_length(&pStubMsg->MemorySize, sizeof(void*));
01086     pStubMsg->MemorySize += sizeof(void*);
01087     TRACE("deref\n");
01088   }
01089 
01090   if (pointer_needs_sizing) {
01091     m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
01092     if (m) m(pStubMsg, desc);
01093     else FIXME("no memorysizer for data type=%02x\n", *desc);
01094   }
01095 
01096   return pStubMsg->MemorySize;
01097 }
01098 
01099 /***********************************************************************
01100  *           PointerFree [internal]
01101  */
01102 static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
01103                         unsigned char *Pointer,
01104                         PFORMAT_STRING pFormat)
01105 {
01106   unsigned type = pFormat[0], attr = pFormat[1];
01107   PFORMAT_STRING desc;
01108   NDR_FREE m;
01109   unsigned char *current_pointer = Pointer;
01110 
01111   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
01112   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
01113   if (attr & RPC_FC_P_DONTFREE) return;
01114   pFormat += 2;
01115   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
01116   else desc = pFormat + *(const SHORT*)pFormat;
01117 
01118   if (!Pointer) return;
01119 
01120   if (type == RPC_FC_FP) {
01121     int pointer_needs_freeing = NdrFullPointerFree(
01122       pStubMsg->FullPtrXlatTables, Pointer);
01123     if (!pointer_needs_freeing)
01124       return;
01125   }
01126 
01127   if (attr & RPC_FC_P_DEREF) {
01128     current_pointer = *(unsigned char**)Pointer;
01129     TRACE("deref => %p\n", current_pointer);
01130   }
01131 
01132   m = NdrFreer[*desc & NDR_TABLE_MASK];
01133   if (m) m(pStubMsg, current_pointer, desc);
01134 
01135   /* this check stops us from trying to free buffer memory. we don't have to
01136    * worry about clients, since they won't call this function.
01137    * we don't have to check for the buffer being reallocated because
01138    * BufferStart and BufferEnd won't be reset when allocating memory for
01139    * sending the response. we don't have to check for the new buffer here as
01140    * it won't be used a type memory, only for buffer memory */
01141   if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd)
01142       goto notfree;
01143 
01144   if (attr & RPC_FC_P_ONSTACK) {
01145     TRACE("not freeing stack ptr %p\n", Pointer);
01146     return;
01147   }
01148   TRACE("freeing %p\n", Pointer);
01149   NdrFree(pStubMsg, Pointer);
01150   return;
01151 notfree:
01152   TRACE("not freeing %p\n", Pointer);
01153 }
01154 
01155 /***********************************************************************
01156  *           EmbeddedPointerMarshall
01157  */
01158 static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
01159                                                unsigned char *pMemory,
01160                                                PFORMAT_STRING pFormat)
01161 {
01162   unsigned char *Mark = pStubMsg->BufferMark;
01163   unsigned rep, count, stride;
01164   unsigned i;
01165   unsigned char *saved_buffer = NULL;
01166 
01167   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
01168 
01169   if (*pFormat != RPC_FC_PP) return NULL;
01170   pFormat += 2;
01171 
01172   if (pStubMsg->PointerBufferMark)
01173   {
01174     saved_buffer = pStubMsg->Buffer;
01175     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
01176     pStubMsg->PointerBufferMark = NULL;
01177   }
01178 
01179   while (pFormat[0] != RPC_FC_END) {
01180     switch (pFormat[0]) {
01181     default:
01182       FIXME("unknown repeat type %d\n", pFormat[0]);
01183     case RPC_FC_NO_REPEAT:
01184       rep = 1;
01185       stride = 0;
01186       count = 1;
01187       pFormat += 2;
01188       break;
01189     case RPC_FC_FIXED_REPEAT:
01190       rep = *(const WORD*)&pFormat[2];
01191       stride = *(const WORD*)&pFormat[4];
01192       count = *(const WORD*)&pFormat[8];
01193       pFormat += 10;
01194       break;
01195     case RPC_FC_VARIABLE_REPEAT:
01196       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
01197       stride = *(const WORD*)&pFormat[2];
01198       count = *(const WORD*)&pFormat[6];
01199       pFormat += 8;
01200       break;
01201     }
01202     for (i = 0; i < rep; i++) {
01203       PFORMAT_STRING info = pFormat;
01204       unsigned char *membase = pMemory + (i * stride);
01205       unsigned char *bufbase = Mark + (i * stride);
01206       unsigned u;
01207 
01208       for (u=0; u<count; u++,info+=8) {
01209         unsigned char *memptr = membase + *(const SHORT*)&info[0];
01210         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
01211         unsigned char *saved_memory = pStubMsg->Memory;
01212 
01213         pStubMsg->Memory = pMemory;
01214         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
01215         pStubMsg->Memory = saved_memory;
01216       }
01217     }
01218     pFormat += 8 * count;
01219   }
01220 
01221   if (saved_buffer)
01222   {
01223     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
01224     pStubMsg->Buffer = saved_buffer;
01225   }
01226 
01227   STD_OVERFLOW_CHECK(pStubMsg);
01228 
01229   return NULL;
01230 }
01231 
01232 /***********************************************************************
01233  *           EmbeddedPointerUnmarshall
01234  */
01235 static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
01236                                                  unsigned char *pDstBuffer,
01237                                                  unsigned char *pSrcMemoryPtrs,
01238                                                  PFORMAT_STRING pFormat,
01239                                                  unsigned char fMustAlloc)
01240 {
01241   unsigned char *Mark = pStubMsg->BufferMark;
01242   unsigned rep, count, stride;
01243   unsigned i;
01244   unsigned char *saved_buffer = NULL;
01245 
01246   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc);
01247 
01248   if (*pFormat != RPC_FC_PP) return NULL;
01249   pFormat += 2;
01250 
01251   if (pStubMsg->PointerBufferMark)
01252   {
01253     saved_buffer = pStubMsg->Buffer;
01254     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
01255     pStubMsg->PointerBufferMark = NULL;
01256   }
01257 
01258   while (pFormat[0] != RPC_FC_END) {
01259     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
01260     switch (pFormat[0]) {
01261     default:
01262       FIXME("unknown repeat type %d\n", pFormat[0]);
01263     case RPC_FC_NO_REPEAT:
01264       rep = 1;
01265       stride = 0;
01266       count = 1;
01267       pFormat += 2;
01268       break;
01269     case RPC_FC_FIXED_REPEAT:
01270       rep = *(const WORD*)&pFormat[2];
01271       stride = *(const WORD*)&pFormat[4];
01272       count = *(const WORD*)&pFormat[8];
01273       pFormat += 10;
01274       break;
01275     case RPC_FC_VARIABLE_REPEAT:
01276       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
01277       stride = *(const WORD*)&pFormat[2];
01278       count = *(const WORD*)&pFormat[6];
01279       pFormat += 8;
01280       break;
01281     }
01282     for (i = 0; i < rep; i++) {
01283       PFORMAT_STRING info = pFormat;
01284       unsigned char *bufdstbase = pDstBuffer + (i * stride);
01285       unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride);
01286       unsigned char *bufbase = Mark + (i * stride);
01287       unsigned u;
01288 
01289       for (u=0; u<count; u++,info+=8) {
01290         unsigned char **bufdstptr = (unsigned char **)(bufdstbase + *(const SHORT*)&info[2]);
01291         unsigned char **memsrcptr = (unsigned char **)(memsrcbase + *(const SHORT*)&info[0]);
01292         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
01293         PointerUnmarshall(pStubMsg, bufptr, bufdstptr, *memsrcptr, info+4, fMustAlloc);
01294       }
01295     }
01296     pFormat += 8 * count;
01297   }
01298 
01299   if (saved_buffer)
01300   {
01301     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
01302     pStubMsg->Buffer = saved_buffer;
01303   }
01304 
01305   return NULL;
01306 }
01307 
01308 /***********************************************************************
01309  *           EmbeddedPointerBufferSize
01310  */
01311 static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
01312                                       unsigned char *pMemory,
01313                                       PFORMAT_STRING pFormat)
01314 {
01315   unsigned rep, count, stride;
01316   unsigned i;
01317   ULONG saved_buffer_length = 0;
01318 
01319   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
01320 
01321   if (pStubMsg->IgnoreEmbeddedPointers) return;
01322 
01323   if (*pFormat != RPC_FC_PP) return;
01324   pFormat += 2;
01325 
01326   if (pStubMsg->PointerLength)
01327   {
01328     saved_buffer_length = pStubMsg->BufferLength;
01329     pStubMsg->BufferLength = pStubMsg->PointerLength;
01330     pStubMsg->PointerLength = 0;
01331   }
01332 
01333   while (pFormat[0] != RPC_FC_END) {
01334     switch (pFormat[0]) {
01335     default:
01336       FIXME("unknown repeat type %d\n", pFormat[0]);
01337     case RPC_FC_NO_REPEAT:
01338       rep = 1;
01339       stride = 0;
01340       count = 1;
01341       pFormat += 2;
01342       break;
01343     case RPC_FC_FIXED_REPEAT:
01344       rep = *(const WORD*)&pFormat[2];
01345       stride = *(const WORD*)&pFormat[4];
01346       count = *(const WORD*)&pFormat[8];
01347       pFormat += 10;
01348       break;
01349     case RPC_FC_VARIABLE_REPEAT:
01350       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
01351       stride = *(const WORD*)&pFormat[2];
01352       count = *(const WORD*)&pFormat[6];
01353       pFormat += 8;
01354       break;
01355     }
01356     for (i = 0; i < rep; i++) {
01357       PFORMAT_STRING info = pFormat;
01358       unsigned char *membase = pMemory + (i * stride);
01359       unsigned u;
01360 
01361       for (u=0; u<count; u++,info+=8) {
01362         unsigned char *memptr = membase + *(const SHORT*)&info[0];
01363         unsigned char *saved_memory = pStubMsg->Memory;
01364 
01365         pStubMsg->Memory = pMemory;
01366         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
01367         pStubMsg->Memory = saved_memory;
01368       }
01369     }
01370     pFormat += 8 * count;
01371   }
01372 
01373   if (saved_buffer_length)
01374   {
01375     pStubMsg->PointerLength = pStubMsg->BufferLength;
01376     pStubMsg->BufferLength = saved_buffer_length;
01377   }
01378 }
01379 
01380 /***********************************************************************
01381  *           EmbeddedPointerMemorySize [internal]
01382  */
01383 static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
01384                                        PFORMAT_STRING pFormat)
01385 {
01386   unsigned char *Mark = pStubMsg->BufferMark;
01387   unsigned rep, count, stride;
01388   unsigned i;
01389   unsigned char *saved_buffer = NULL;
01390 
01391   TRACE("(%p,%p)\n", pStubMsg, pFormat);
01392 
01393   if (pStubMsg->IgnoreEmbeddedPointers) return 0;
01394 
01395   if (pStubMsg->PointerBufferMark)
01396   {
01397     saved_buffer = pStubMsg->Buffer;
01398     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
01399     pStubMsg->PointerBufferMark = NULL;
01400   }
01401 
01402   if (*pFormat != RPC_FC_PP) return 0;
01403   pFormat += 2;
01404 
01405   while (pFormat[0] != RPC_FC_END) {
01406     switch (pFormat[0]) {
01407     default:
01408       FIXME("unknown repeat type %d\n", pFormat[0]);
01409     case RPC_FC_NO_REPEAT:
01410       rep = 1;
01411       stride = 0;
01412       count = 1;
01413       pFormat += 2;
01414       break;
01415     case RPC_FC_FIXED_REPEAT:
01416       rep = *(const WORD*)&pFormat[2];
01417       stride = *(const WORD*)&pFormat[4];
01418       count = *(const WORD*)&pFormat[8];
01419       pFormat += 10;
01420       break;
01421     case RPC_FC_VARIABLE_REPEAT:
01422       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
01423       stride = *(const WORD*)&pFormat[2];
01424       count = *(const WORD*)&pFormat[6];
01425       pFormat += 8;
01426       break;
01427     }
01428     for (i = 0; i < rep; i++) {
01429       PFORMAT_STRING info = pFormat;
01430       unsigned char *bufbase = Mark + (i * stride);
01431       unsigned u;
01432       for (u=0; u<count; u++,info+=8) {
01433         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
01434         PointerMemorySize(pStubMsg, bufptr, info+4);
01435       }
01436     }
01437     pFormat += 8 * count;
01438   }
01439 
01440   if (saved_buffer)
01441   {
01442     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
01443     pStubMsg->Buffer = saved_buffer;
01444   }
01445 
01446   return 0;
01447 }
01448 
01449 /***********************************************************************
01450  *           EmbeddedPointerFree [internal]
01451  */
01452 static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
01453                                 unsigned char *pMemory,
01454                                 PFORMAT_STRING pFormat)
01455 {
01456   unsigned rep, count, stride;
01457   unsigned i;
01458 
01459   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
01460   if (*pFormat != RPC_FC_PP) return;
01461   pFormat += 2;
01462 
01463   while (pFormat[0] != RPC_FC_END) {
01464     switch (pFormat[0]) {
01465     default:
01466       FIXME("unknown repeat type %d\n", pFormat[0]);
01467     case RPC_FC_NO_REPEAT:
01468       rep = 1;
01469       stride = 0;
01470       count = 1;
01471       pFormat += 2;
01472       break;
01473     case RPC_FC_FIXED_REPEAT:
01474       rep = *(const WORD*)&pFormat[2];
01475       stride = *(const WORD*)&pFormat[4];
01476       count = *(const WORD*)&pFormat[8];
01477       pFormat += 10;
01478       break;
01479     case RPC_FC_VARIABLE_REPEAT:
01480       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
01481       stride = *(const WORD*)&pFormat[2];
01482       count = *(const WORD*)&pFormat[6];
01483       pFormat += 8;
01484       break;
01485     }
01486     for (i = 0; i < rep; i++) {
01487       PFORMAT_STRING info = pFormat;
01488       unsigned char *membase = pMemory + (i * stride);
01489       unsigned u;
01490 
01491       for (u=0; u<count; u++,info+=8) {
01492         unsigned char *memptr = membase + *(const SHORT*)&info[0];
01493         unsigned char *saved_memory = pStubMsg->Memory;
01494 
01495         pStubMsg->Memory = pMemory;
01496         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
01497         pStubMsg->Memory = saved_memory;
01498       }
01499     }
01500     pFormat += 8 * count;
01501   }
01502 }
01503 
01504 /***********************************************************************
01505  *           NdrPointerMarshall [RPCRT4.@]
01506  */
01507 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
01508                                           unsigned char *pMemory,
01509                                           PFORMAT_STRING pFormat)
01510 {
01511   unsigned char *Buffer;
01512 
01513   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
01514 
01515   /* Increment the buffer here instead of in PointerMarshall,
01516    * as that is used by embedded pointers which already handle the incrementing
01517    * the buffer, and shouldn't write any additional pointer data to the wire */
01518   if (*pFormat != RPC_FC_RP)
01519   {
01520     align_pointer_clear(&pStubMsg->Buffer, 4);
01521     Buffer = pStubMsg->Buffer;
01522     safe_buffer_increment(pStubMsg, 4);
01523   }
01524   else
01525     Buffer = pStubMsg->Buffer;
01526 
01527   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
01528 
01529   return NULL;
01530 }
01531 
01532 /***********************************************************************
01533  *           NdrPointerUnmarshall [RPCRT4.@]
01534  */
01535 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
01536                                             unsigned char **ppMemory,
01537                                             PFORMAT_STRING pFormat,
01538                                             unsigned char fMustAlloc)
01539 {
01540   unsigned char *Buffer;
01541 
01542   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
01543 
01544   if (*pFormat == RPC_FC_RP)
01545   {
01546     Buffer = pStubMsg->Buffer;
01547     /* Do the NULL ref pointer check here because embedded pointers can be
01548      * NULL if the type the pointer is embedded in was allocated rather than
01549      * being passed in by the client */
01550     if (pStubMsg->IsClient && !*ppMemory)
01551     {
01552       ERR("NULL ref pointer is not allowed\n");
01553       RpcRaiseException(RPC_X_NULL_REF_POINTER);
01554     }
01555   }
01556   else
01557   {
01558     /* Increment the buffer here instead of in PointerUnmarshall,
01559      * as that is used by embedded pointers which already handle the incrementing
01560      * the buffer, and shouldn't read any additional pointer data from the
01561      * buffer */
01562     align_pointer(&pStubMsg->Buffer, 4);
01563     Buffer = pStubMsg->Buffer;
01564     safe_buffer_increment(pStubMsg, 4);
01565   }
01566 
01567   PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
01568 
01569   return NULL;
01570 }
01571 
01572 /***********************************************************************
01573  *           NdrPointerBufferSize [RPCRT4.@]
01574  */
01575 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
01576                                       unsigned char *pMemory,
01577                                       PFORMAT_STRING pFormat)
01578 {
01579   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
01580 
01581   /* Increment the buffer length here instead of in PointerBufferSize,
01582    * as that is used by embedded pointers which already handle the buffer
01583    * length, and shouldn't write anything more to the wire */
01584   if (*pFormat != RPC_FC_RP)
01585   {
01586     align_length(&pStubMsg->BufferLength, 4);
01587     safe_buffer_length_increment(pStubMsg, 4);
01588   }
01589 
01590   PointerBufferSize(pStubMsg, pMemory, pFormat);
01591 }
01592 
01593 /***********************************************************************
01594  *           NdrPointerMemorySize [RPCRT4.@]
01595  */
01596 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
01597                                   PFORMAT_STRING pFormat)
01598 {
01599     unsigned char *Buffer = pStubMsg->Buffer;
01600     if (*pFormat != RPC_FC_RP)
01601     {
01602         align_pointer(&pStubMsg->Buffer, 4);
01603         safe_buffer_increment(pStubMsg, 4);
01604     }
01605     align_length(&pStubMsg->MemorySize, sizeof(void *));
01606     return PointerMemorySize(pStubMsg, Buffer, pFormat);
01607 }
01608 
01609 /***********************************************************************
01610  *           NdrPointerFree [RPCRT4.@]
01611  */
01612 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
01613                            unsigned char *pMemory,
01614                            PFORMAT_STRING pFormat)
01615 {
01616   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
01617   PointerFree(pStubMsg, pMemory, pFormat);
01618 }
01619 
01620 /***********************************************************************
01621  *           NdrSimpleTypeMarshall [RPCRT4.@]
01622  */
01623 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
01624                                    unsigned char FormatChar )
01625 {
01626     NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar);
01627 }
01628 
01629 /***********************************************************************
01630  *           NdrSimpleTypeUnmarshall [RPCRT4.@]
01631  *
01632  * Unmarshall a base type.
01633  *
01634  * NOTES
01635  *  Doesn't check that the buffer is long enough before copying, so the caller
01636  * should do this.
01637  */
01638 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
01639                                      unsigned char FormatChar )
01640 {
01641 #define BASE_TYPE_UNMARSHALL(type) \
01642         align_pointer(&pStubMsg->Buffer, sizeof(type)); \
01643     TRACE("pMemory: %p\n", pMemory); \
01644     *(type *)pMemory = *(type *)pStubMsg->Buffer; \
01645         pStubMsg->Buffer += sizeof(type);
01646 
01647     switch(FormatChar)
01648     {
01649     case RPC_FC_BYTE:
01650     case RPC_FC_CHAR:
01651     case RPC_FC_SMALL:
01652     case RPC_FC_USMALL:
01653         BASE_TYPE_UNMARSHALL(UCHAR);
01654         TRACE("value: 0x%02x\n", *pMemory);
01655         break;
01656     case RPC_FC_WCHAR:
01657     case RPC_FC_SHORT:
01658     case RPC_FC_USHORT:
01659         BASE_TYPE_UNMARSHALL(USHORT);
01660         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
01661         break;
01662     case RPC_FC_LONG:
01663     case RPC_FC_ULONG:
01664     case RPC_FC_ERROR_STATUS_T:
01665     case RPC_FC_ENUM32:
01666         BASE_TYPE_UNMARSHALL(ULONG);
01667         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
01668         break;
01669    case RPC_FC_FLOAT:
01670         BASE_TYPE_UNMARSHALL(float);
01671         TRACE("value: %f\n", *(float *)pMemory);
01672         break;
01673     case RPC_FC_DOUBLE:
01674         BASE_TYPE_UNMARSHALL(double);
01675         TRACE("value: %f\n", *(double *)pMemory);
01676         break;
01677     case RPC_FC_HYPER:
01678         BASE_TYPE_UNMARSHALL(ULONGLONG);
01679         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory));
01680         break;
01681     case RPC_FC_ENUM16:
01682         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
01683         TRACE("pMemory: %p\n", pMemory);
01684         /* 16-bits on the wire, but int in memory */
01685         *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer;
01686         pStubMsg->Buffer += sizeof(USHORT);
01687         TRACE("value: 0x%08x\n", *(UINT *)pMemory);
01688         break;
01689     case RPC_FC_INT3264:
01690         align_pointer(&pStubMsg->Buffer, sizeof(INT));
01691         /* 32-bits on the wire, but int_ptr in memory */
01692         *(INT_PTR *)pMemory = *(INT *)pStubMsg->Buffer;
01693         pStubMsg->Buffer += sizeof(INT);
01694         TRACE("value: 0x%08lx\n", *(INT_PTR *)pMemory);
01695         break;
01696     case RPC_FC_UINT3264:
01697         align_pointer(&pStubMsg->Buffer, sizeof(UINT));
01698         /* 32-bits on the wire, but int_ptr in memory */
01699         *(UINT_PTR *)pMemory = *(UINT *)pStubMsg->Buffer;
01700         pStubMsg->Buffer += sizeof(UINT);
01701         TRACE("value: 0x%08lx\n", *(UINT_PTR *)pMemory);
01702         break;
01703     case RPC_FC_IGNORE:
01704         break;
01705     default:
01706         FIXME("Unhandled base type: 0x%02x\n", FormatChar);
01707     }
01708 #undef BASE_TYPE_UNMARSHALL
01709 }
01710 
01711 /***********************************************************************
01712  *           NdrSimpleStructMarshall [RPCRT4.@]
01713  */
01714 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
01715                                                unsigned char *pMemory,
01716                                                PFORMAT_STRING pFormat)
01717 {
01718   unsigned size = *(const WORD*)(pFormat+2);
01719   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
01720 
01721   align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
01722 
01723   pStubMsg->BufferMark = pStubMsg->Buffer;
01724   safe_copy_to_buffer(pStubMsg, pMemory, size);
01725 
01726   if (pFormat[0] != RPC_FC_STRUCT)
01727     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
01728 
01729   return NULL;
01730 }
01731 
01732 /***********************************************************************
01733  *           NdrSimpleStructUnmarshall [RPCRT4.@]
01734  */
01735 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
01736                                                  unsigned char **ppMemory,
01737                                                  PFORMAT_STRING pFormat,
01738                                                  unsigned char fMustAlloc)
01739 {
01740   unsigned size = *(const WORD*)(pFormat+2);
01741   unsigned char *saved_buffer;
01742   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
01743 
01744   align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
01745 
01746   if (fMustAlloc)
01747     *ppMemory = NdrAllocate(pStubMsg, size);
01748   else
01749   {
01750     if (!pStubMsg->IsClient && !*ppMemory)
01751       /* for servers, we just point straight into the RPC buffer */
01752       *ppMemory = pStubMsg->Buffer;
01753   }
01754 
01755   saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
01756   safe_buffer_increment(pStubMsg, size);
01757   if (pFormat[0] == RPC_FC_PSTRUCT)
01758       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc);
01759 
01760   TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
01761   if (*ppMemory != saved_buffer)
01762       memcpy(*ppMemory, saved_buffer, size);
01763 
01764   return NULL;
01765 }
01766 
01767 /***********************************************************************
01768  *           NdrSimpleStructBufferSize [RPCRT4.@]
01769  */
01770 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
01771                                       unsigned char *pMemory,
01772                                       PFORMAT_STRING pFormat)
01773 {
01774   unsigned size = *(const WORD*)(pFormat+2);
01775   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
01776 
01777   align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
01778 
01779   safe_buffer_length_increment(pStubMsg, size);
01780   if (pFormat[0] != RPC_FC_STRUCT)
01781     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
01782 }
01783 
01784 /***********************************************************************
01785  *           NdrSimpleStructMemorySize [RPCRT4.@]
01786  */
01787 ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
01788                                        PFORMAT_STRING pFormat)
01789 {
01790   unsigned short size = *(const WORD *)(pFormat+2);
01791 
01792   TRACE("(%p,%p)\n", pStubMsg, pFormat);
01793 
01794   align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
01795   pStubMsg->MemorySize += size;
01796   safe_buffer_increment(pStubMsg, size);
01797 
01798   if (pFormat[0] != RPC_FC_STRUCT)
01799     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
01800   return pStubMsg->MemorySize;
01801 }
01802 
01803 /***********************************************************************
01804  *           NdrSimpleStructFree [RPCRT4.@]
01805  */
01806 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
01807                                 unsigned char *pMemory,
01808                                 PFORMAT_STRING pFormat)
01809 {
01810   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
01811   if (pFormat[0] != RPC_FC_STRUCT)
01812     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
01813 }
01814 
01815 /* Array helpers */
01816 
01817 static inline void array_compute_and_size_conformance(
01818     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
01819     PFORMAT_STRING pFormat)
01820 {
01821   DWORD count;
01822 
01823   switch (fc)
01824   {
01825   case RPC_FC_CARRAY:
01826     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
01827     SizeConformance(pStubMsg);
01828     break;
01829   case RPC_FC_CVARRAY:
01830     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
01831     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
01832     SizeConformance(pStubMsg);
01833     break;
01834   case RPC_FC_C_CSTRING:
01835   case RPC_FC_C_WSTRING:
01836     if (fc == RPC_FC_C_CSTRING)
01837     {
01838       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
01839       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
01840     }
01841     else
01842     {
01843       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
01844       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
01845     }
01846 
01847     if (pFormat[1] == RPC_FC_STRING_SIZED)
01848       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
01849     else
01850       pStubMsg->MaxCount = pStubMsg->ActualCount;
01851 
01852     SizeConformance(pStubMsg);
01853     break;
01854   case RPC_FC_BOGUS_ARRAY:
01855     count = *(const WORD *)(pFormat + 2);
01856     pFormat += 4;
01857     if (IsConformanceOrVariancePresent(pFormat)) SizeConformance(pStubMsg);
01858     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, count);
01859     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
01860     break;
01861   default:
01862     ERR("unknown array format 0x%x\n", fc);
01863     RpcRaiseException(RPC_X_BAD_STUB_DATA);
01864   }
01865 }
01866 
01867 static inline void array_buffer_size(
01868     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
01869     PFORMAT_STRING pFormat, unsigned char fHasPointers)
01870 {
01871   DWORD i, size;
01872   DWORD esize;
01873   unsigned char alignment;
01874 
01875   switch (fc)
01876   {
01877   case RPC_FC_CARRAY:
01878     esize = *(const WORD*)(pFormat+2);
01879     alignment = pFormat[1] + 1;
01880 
01881     pFormat = SkipConformance(pStubMsg, pFormat + 4);
01882 
01883     align_length(&pStubMsg->BufferLength, alignment);
01884 
01885     size = safe_multiply(esize, pStubMsg->MaxCount);
01886     /* conformance value plus array */
01887     safe_buffer_length_increment(pStubMsg, size);
01888 
01889     if (fHasPointers)
01890       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
01891     break;
01892   case RPC_FC_CVARRAY:
01893     esize = *(const WORD*)(pFormat+2);
01894     alignment = pFormat[1] + 1;
01895 
01896     pFormat = SkipConformance(pStubMsg, pFormat + 4);
01897     pFormat = SkipVariance(pStubMsg, pFormat);
01898 
01899     SizeVariance(pStubMsg);
01900 
01901     align_length(&pStubMsg->BufferLength, alignment);
01902 
01903     size = safe_multiply(esize, pStubMsg->ActualCount);
01904     safe_buffer_length_increment(pStubMsg, size);
01905 
01906     if (fHasPointers)
01907       EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
01908     break;
01909   case RPC_FC_C_CSTRING:
01910   case RPC_FC_C_WSTRING:
01911     if (fc == RPC_FC_C_CSTRING)
01912       esize = 1;
01913     else
01914       esize = 2;
01915 
01916     SizeVariance(pStubMsg);
01917 
01918     size = safe_multiply(esize, pStubMsg->ActualCount);
01919     safe_buffer_length_increment(pStubMsg, size);
01920     break;
01921   case RPC_FC_BOGUS_ARRAY:
01922     alignment = pFormat[1] + 1;
01923     pFormat = SkipConformance(pStubMsg, pFormat + 4);
01924     if (IsConformanceOrVariancePresent(pFormat)) SizeVariance(pStubMsg);
01925     pFormat = SkipVariance(pStubMsg, pFormat);
01926 
01927     align_length(&pStubMsg->BufferLength, alignment);
01928 
01929     size = pStubMsg->ActualCount;
01930     for (i = 0; i < size; i++)
01931       pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
01932     break;
01933   default:
01934     ERR("unknown array format 0x%x\n", fc);
01935     RpcRaiseException(RPC_X_BAD_STUB_DATA);
01936   }
01937 }
01938 
01939 static inline void array_compute_and_write_conformance(
01940     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
01941     PFORMAT_STRING pFormat)
01942 {
01943   ULONG def;
01944   BOOL conformance_present;
01945 
01946   switch (fc)
01947   {
01948   case RPC_FC_CARRAY:
01949     ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
01950     WriteConformance(pStubMsg);
01951     break;
01952   case RPC_FC_CVARRAY:
01953     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0);
01954     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
01955     WriteConformance(pStubMsg);
01956     break;
01957   case RPC_FC_C_CSTRING:
01958   case RPC_FC_C_WSTRING:
01959     if (fc == RPC_FC_C_CSTRING)
01960     {
01961       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
01962       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
01963     }
01964     else
01965     {
01966       TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory));
01967       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
01968     }
01969     if (pFormat[1] == RPC_FC_STRING_SIZED)
01970       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
01971     else
01972       pStubMsg->MaxCount = pStubMsg->ActualCount;
01973     pStubMsg->Offset = 0;
01974     WriteConformance(pStubMsg);
01975     break;
01976   case RPC_FC_BOGUS_ARRAY:
01977     def = *(const WORD *)(pFormat + 2);
01978     pFormat += 4;
01979     conformance_present = IsConformanceOrVariancePresent(pFormat);
01980     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
01981     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
01982     if (conformance_present) WriteConformance(pStubMsg);
01983     break;
01984   default:
01985     ERR("unknown array format 0x%x\n", fc);
01986     RpcRaiseException(RPC_X_BAD_STUB_DATA);
01987   }
01988 }
01989 
01990 static inline void array_write_variance_and_marshall(
01991     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
01992     PFORMAT_STRING pFormat, unsigned char fHasPointers)
01993 {
01994   DWORD i, size;
01995   DWORD esize;
01996   unsigned char alignment;
01997 
01998   switch (fc)
01999   {
02000   case RPC_FC_CARRAY:
02001     esize = *(const WORD*)(pFormat+2);
02002     alignment = pFormat[1] + 1;
02003 
02004     pFormat = SkipConformance(pStubMsg, pFormat + 4);
02005 
02006     align_pointer_clear(&pStubMsg->Buffer, alignment);
02007 
02008     size = safe_multiply(esize, pStubMsg->MaxCount);
02009     if (fHasPointers)
02010       pStubMsg->BufferMark = pStubMsg->Buffer;
02011     safe_copy_to_buffer(pStubMsg, pMemory, size);
02012 
02013     if (fHasPointers)
02014       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
02015     break;
02016   case RPC_FC_CVARRAY:
02017     esize = *(const WORD*)(pFormat+2);
02018     alignment = pFormat[1] + 1;
02019 
02020     pFormat = SkipConformance(pStubMsg, pFormat + 4);
02021     pFormat = SkipVariance(pStubMsg, pFormat);
02022 
02023     WriteVariance(pStubMsg);
02024 
02025     align_pointer_clear(&pStubMsg->Buffer, alignment);
02026 
02027     size = safe_multiply(esize, pStubMsg->ActualCount);
02028 
02029     if (fHasPointers)
02030       pStubMsg->BufferMark = pStubMsg->Buffer;
02031     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size);
02032 
02033     if (fHasPointers)
02034       EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
02035     break;
02036   case RPC_FC_C_CSTRING:
02037   case RPC_FC_C_WSTRING:
02038     if (fc == RPC_FC_C_CSTRING)
02039       esize = 1;
02040     else
02041       esize = 2;
02042 
02043     WriteVariance(pStubMsg);
02044 
02045     size = safe_multiply(esize, pStubMsg->ActualCount);
02046     safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
02047     break;
02048   case RPC_FC_BOGUS_ARRAY:
02049     alignment = pFormat[1] + 1;
02050     pFormat = SkipConformance(pStubMsg, pFormat + 4);
02051     if (IsConformanceOrVariancePresent(pFormat)) WriteVariance(pStubMsg);
02052     pFormat = SkipVariance(pStubMsg, pFormat);
02053 
02054     align_pointer_clear(&pStubMsg->Buffer, alignment);
02055 
02056     size = pStubMsg->ActualCount;
02057     for (i = 0; i < size; i++)
02058       pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
02059     break;
02060   default:
02061     ERR("unknown array format 0x%x\n", fc);
02062     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02063   }
02064 }
02065 
02066 static inline ULONG array_read_conformance(
02067     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
02068 {
02069   DWORD def, esize;
02070 
02071   switch (fc)
02072   {
02073   case RPC_FC_CARRAY:
02074     esize = *(const WORD*)(pFormat+2);
02075     pFormat = ReadConformance(pStubMsg, pFormat+4);
02076     return safe_multiply(esize, pStubMsg->MaxCount);
02077   case RPC_FC_CVARRAY:
02078     esize = *(const WORD*)(pFormat+2);
02079     pFormat = ReadConformance(pStubMsg, pFormat+4);
02080     return safe_multiply(esize, pStubMsg->MaxCount);
02081   case RPC_FC_C_CSTRING:
02082   case RPC_FC_C_WSTRING:
02083     if (fc == RPC_FC_C_CSTRING)
02084       esize = 1;
02085     else
02086       esize = 2;
02087 
02088     if (pFormat[1] == RPC_FC_STRING_SIZED)
02089       ReadConformance(pStubMsg, pFormat + 2);
02090     else
02091       ReadConformance(pStubMsg, NULL);
02092     return safe_multiply(esize, pStubMsg->MaxCount);
02093   case RPC_FC_BOGUS_ARRAY:
02094     def = *(const WORD *)(pFormat + 2);
02095     pFormat += 4;
02096     if (IsConformanceOrVariancePresent(pFormat)) pFormat = ReadConformance(pStubMsg, pFormat);
02097     else
02098     {
02099         pStubMsg->MaxCount = def;
02100         pFormat = SkipConformance( pStubMsg, pFormat );
02101     }
02102     pFormat = SkipVariance( pStubMsg, pFormat );
02103 
02104     esize = ComplexStructSize(pStubMsg, pFormat);
02105     return safe_multiply(pStubMsg->MaxCount, esize);
02106   default:
02107     ERR("unknown array format 0x%x\n", fc);
02108     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02109   }
02110 }
02111 
02112 static inline ULONG array_read_variance_and_unmarshall(
02113     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
02114     PFORMAT_STRING pFormat, unsigned char fMustAlloc,
02115     unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall)
02116 {
02117   ULONG bufsize, memsize;
02118   WORD esize;
02119   unsigned char alignment;
02120   unsigned char *saved_buffer, *pMemory;
02121   ULONG i, offset, count;
02122 
02123   switch (fc)
02124   {
02125   case RPC_FC_CARRAY:
02126     esize = *(const WORD*)(pFormat+2);
02127     alignment = pFormat[1] + 1;
02128 
02129     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
02130 
02131     pFormat = SkipConformance(pStubMsg, pFormat + 4);
02132 
02133     align_pointer(&pStubMsg->Buffer, alignment);
02134 
02135     if (fUnmarshall)
02136     {
02137       if (fMustAlloc)
02138         *ppMemory = NdrAllocate(pStubMsg, memsize);
02139       else
02140       {
02141         if (fUseBufferMemoryServer && !pStubMsg->IsClient && !*ppMemory)
02142           /* for servers, we just point straight into the RPC buffer */
02143           *ppMemory = pStubMsg->Buffer;
02144       }
02145 
02146       saved_buffer = pStubMsg->Buffer;
02147       safe_buffer_increment(pStubMsg, bufsize);
02148 
02149       pStubMsg->BufferMark = saved_buffer;
02150       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
02151 
02152       TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
02153       if (*ppMemory != saved_buffer)
02154         memcpy(*ppMemory, saved_buffer, bufsize);
02155     }
02156     return bufsize;
02157   case RPC_FC_CVARRAY:
02158     esize = *(const WORD*)(pFormat+2);
02159     alignment = pFormat[1] + 1;
02160 
02161     pFormat = SkipConformance(pStubMsg, pFormat + 4);
02162 
02163     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
02164 
02165     align_pointer(&pStubMsg->Buffer, alignment);
02166 
02167     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
02168     memsize = safe_multiply(esize, pStubMsg->MaxCount);
02169 
02170     if (fUnmarshall)
02171     {
02172       offset = pStubMsg->Offset;
02173 
02174       if (!fMustAlloc && !*ppMemory)
02175         fMustAlloc = TRUE;
02176       if (fMustAlloc)
02177         *ppMemory = NdrAllocate(pStubMsg, memsize);
02178       saved_buffer = pStubMsg->Buffer;
02179       safe_buffer_increment(pStubMsg, bufsize);
02180 
02181       pStubMsg->BufferMark = saved_buffer;
02182       EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat,
02183                                 fMustAlloc);
02184 
02185       memcpy(*ppMemory + offset, saved_buffer, bufsize);
02186     }
02187     return bufsize;
02188   case RPC_FC_C_CSTRING:
02189   case RPC_FC_C_WSTRING:
02190     if (fc == RPC_FC_C_CSTRING)
02191       esize = 1;
02192     else
02193       esize = 2;
02194 
02195     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
02196 
02197     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
02198     {
02199       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
02200           pStubMsg->ActualCount, pStubMsg->MaxCount);
02201       RpcRaiseException(RPC_S_INVALID_BOUND);
02202     }
02203     if (pStubMsg->Offset)
02204     {
02205       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
02206       RpcRaiseException(RPC_S_INVALID_BOUND);
02207     }
02208 
02209     memsize = safe_multiply(esize, pStubMsg->MaxCount);
02210     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
02211 
02212     validate_string_data(pStubMsg, bufsize, esize);
02213 
02214     if (fUnmarshall)
02215     {
02216       if (fMustAlloc)
02217         *ppMemory = NdrAllocate(pStubMsg, memsize);
02218       else
02219       {
02220         if (fUseBufferMemoryServer && !pStubMsg->IsClient &&
02221             !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount))
02222           /* if the data in the RPC buffer is big enough, we just point
02223            * straight into it */
02224           *ppMemory = pStubMsg->Buffer;
02225         else if (!*ppMemory)
02226           *ppMemory = NdrAllocate(pStubMsg, memsize);
02227       }
02228 
02229       if (*ppMemory == pStubMsg->Buffer)
02230         safe_buffer_increment(pStubMsg, bufsize);
02231       else
02232         safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
02233 
02234       if (*pFormat == RPC_FC_C_CSTRING)
02235         TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
02236       else
02237         TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
02238     }
02239     return bufsize;
02240 
02241   case RPC_FC_BOGUS_ARRAY:
02242     alignment = pFormat[1] + 1;
02243     pFormat = SkipConformance(pStubMsg, pFormat + 4);
02244     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
02245 
02246     esize = ComplexStructSize(pStubMsg, pFormat);
02247     memsize = safe_multiply(esize, pStubMsg->MaxCount);
02248 
02249     assert( fUnmarshall );
02250 
02251     if (!fMustAlloc && !*ppMemory)
02252       fMustAlloc = TRUE;
02253     if (fMustAlloc)
02254       *ppMemory = NdrAllocate(pStubMsg, memsize);
02255 
02256     align_pointer(&pStubMsg->Buffer, alignment);
02257     saved_buffer = pStubMsg->Buffer;
02258 
02259     pMemory = *ppMemory;
02260     count = pStubMsg->ActualCount;
02261     for (i = 0; i < count; i++)
02262         pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
02263     return pStubMsg->Buffer - saved_buffer;
02264 
02265   default:
02266     ERR("unknown array format 0x%x\n", fc);
02267     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02268   }
02269 }
02270 
02271 static inline void array_memory_size(
02272     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
02273     unsigned char fHasPointers)
02274 {
02275   ULONG i, count, SavedMemorySize;
02276   ULONG bufsize, memsize;
02277   DWORD esize;
02278   unsigned char alignment;
02279 
02280   switch (fc)
02281   {
02282   case RPC_FC_CARRAY:
02283     esize = *(const WORD*)(pFormat+2);
02284     alignment = pFormat[1] + 1;
02285 
02286     pFormat = SkipConformance(pStubMsg, pFormat + 4);
02287 
02288     bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount);
02289     pStubMsg->MemorySize += memsize;
02290 
02291     align_pointer(&pStubMsg->Buffer, alignment);
02292     if (fHasPointers)
02293       pStubMsg->BufferMark = pStubMsg->Buffer;
02294     safe_buffer_increment(pStubMsg, bufsize);
02295 
02296     if (fHasPointers)
02297       EmbeddedPointerMemorySize(pStubMsg, pFormat);
02298     break;
02299   case RPC_FC_CVARRAY:
02300     esize = *(const WORD*)(pFormat+2);
02301     alignment = pFormat[1] + 1;
02302 
02303     pFormat = SkipConformance(pStubMsg, pFormat + 4);
02304 
02305     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
02306 
02307     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
02308     memsize = safe_multiply(esize, pStubMsg->MaxCount);
02309     pStubMsg->MemorySize += memsize;
02310 
02311     align_pointer(&pStubMsg->Buffer, alignment);
02312     if (fHasPointers)
02313       pStubMsg->BufferMark = pStubMsg->Buffer;
02314     safe_buffer_increment(pStubMsg, bufsize);
02315 
02316     if (fHasPointers)
02317       EmbeddedPointerMemorySize(pStubMsg, pFormat);
02318     break;
02319   case RPC_FC_C_CSTRING:
02320   case RPC_FC_C_WSTRING:
02321     if (fc == RPC_FC_C_CSTRING)
02322       esize = 1;
02323     else
02324       esize = 2;
02325 
02326     ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount);
02327 
02328     if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount))
02329     {
02330       ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n",
02331           pStubMsg->ActualCount, pStubMsg->MaxCount);
02332       RpcRaiseException(RPC_S_INVALID_BOUND);
02333     }
02334     if (pStubMsg->Offset)
02335     {
02336       ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
02337       RpcRaiseException(RPC_S_INVALID_BOUND);
02338     }
02339 
02340     memsize = safe_multiply(esize, pStubMsg->MaxCount);
02341     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
02342 
02343     validate_string_data(pStubMsg, bufsize, esize);
02344 
02345     safe_buffer_increment(pStubMsg, bufsize);
02346     pStubMsg->MemorySize += memsize;
02347     break;
02348   case RPC_FC_BOGUS_ARRAY:
02349     alignment = pFormat[1] + 1;
02350     pFormat = SkipConformance(pStubMsg, pFormat + 4);
02351     pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount);
02352 
02353     align_pointer(&pStubMsg->Buffer, alignment);
02354 
02355     SavedMemorySize = pStubMsg->MemorySize;
02356 
02357     esize = ComplexStructSize(pStubMsg, pFormat);
02358     memsize = safe_multiply(pStubMsg->MaxCount, esize);
02359 
02360     count = pStubMsg->ActualCount;
02361     for (i = 0; i < count; i++)
02362         ComplexStructMemorySize(pStubMsg, pFormat, NULL);
02363 
02364     pStubMsg->MemorySize = SavedMemorySize + memsize;
02365     break;
02366   default:
02367     ERR("unknown array format 0x%x\n", fc);
02368     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02369   }
02370 }
02371 
02372 static inline void array_free(
02373     unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg,
02374     unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers)
02375 {
02376   DWORD i, count;
02377 
02378   switch (fc)
02379   {
02380   case RPC_FC_CARRAY:
02381     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
02382     if (fHasPointers)
02383       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
02384     break;
02385   case RPC_FC_CVARRAY:
02386     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
02387     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
02388     if (fHasPointers)
02389       EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
02390     break;
02391   case RPC_FC_C_CSTRING:
02392   case RPC_FC_C_WSTRING:
02393     /* No embedded pointers so nothing to do */
02394     break;
02395   case RPC_FC_BOGUS_ARRAY:
02396       count = *(const WORD *)(pFormat + 2);
02397       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, count);
02398       pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
02399 
02400       count = pStubMsg->ActualCount;
02401       for (i = 0; i < count; i++)
02402           pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
02403     break;
02404   default:
02405     ERR("unknown array format 0x%x\n", fc);
02406     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02407   }
02408 }
02409 
02410 /*
02411  * NdrConformantString:
02412  *
02413  * What MS calls a ConformantString is, in DCE terminology,
02414  * a Varying-Conformant String.
02415  * [
02416  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
02417  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
02418  *           into unmarshalled string)
02419  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
02420  *   [
02421  *     data: CHARTYPE[maxlen]
02422  *   ]
02423  * ], where CHARTYPE is the appropriate character type (specified externally)
02424  *
02425  */
02426 
02427 /***********************************************************************
02428  *            NdrConformantStringMarshall [RPCRT4.@]
02429  */
02430 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
02431   unsigned char *pszMessage, PFORMAT_STRING pFormat)
02432 {
02433   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
02434 
02435   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
02436     ERR("Unhandled string type: %#x\n", pFormat[0]);
02437     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02438   }
02439 
02440   /* allow compiler to optimise inline function by passing constant into
02441    * these functions */
02442   if (pFormat[0] == RPC_FC_C_CSTRING) {
02443     array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
02444                                         pFormat);
02445     array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage,
02446                                       pFormat, TRUE /* fHasPointers */);
02447   } else {
02448     array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
02449                                         pFormat);
02450     array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage,
02451                                       pFormat, TRUE /* fHasPointers */);
02452   }
02453 
02454   return NULL;
02455 }
02456 
02457 /***********************************************************************
02458  *           NdrConformantStringBufferSize [RPCRT4.@]
02459  */
02460 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
02461   unsigned char* pMemory, PFORMAT_STRING pFormat)
02462 {
02463   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
02464 
02465   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
02466     ERR("Unhandled string type: %#x\n", pFormat[0]);
02467     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02468   }
02469 
02470   /* allow compiler to optimise inline function by passing constant into
02471    * these functions */
02472   if (pFormat[0] == RPC_FC_C_CSTRING) {
02473     array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory,
02474                                        pFormat);
02475     array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat,
02476                       TRUE /* fHasPointers */);
02477   } else {
02478     array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory,
02479                                        pFormat);
02480     array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat,
02481                       TRUE /* fHasPointers */);
02482   }
02483 }
02484 
02485 /************************************************************************
02486  *            NdrConformantStringMemorySize [RPCRT4.@]
02487  */
02488 ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
02489   PFORMAT_STRING pFormat )
02490 {
02491   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
02492 
02493   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
02494     ERR("Unhandled string type: %#x\n", pFormat[0]);
02495     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02496   }
02497 
02498   /* allow compiler to optimise inline function by passing constant into
02499    * these functions */
02500   if (pFormat[0] == RPC_FC_C_CSTRING) {
02501     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
02502     array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat,
02503                       TRUE /* fHasPointers */);
02504   } else {
02505     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
02506     array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat,
02507                       TRUE /* fHasPointers */);
02508   }
02509 
02510   return pStubMsg->MemorySize;
02511 }
02512 
02513 /************************************************************************
02514  *           NdrConformantStringUnmarshall [RPCRT4.@]
02515  */
02516 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
02517   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
02518 {
02519   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
02520     pStubMsg, *ppMemory, pFormat, fMustAlloc);
02521 
02522   if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) {
02523     ERR("Unhandled string type: %#x\n", *pFormat);
02524     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02525   }
02526 
02527   /* allow compiler to optimise inline function by passing constant into
02528    * these functions */
02529   if (pFormat[0] == RPC_FC_C_CSTRING) {
02530     array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat);
02531     array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory,
02532                                        pFormat, fMustAlloc,
02533                                        TRUE /* fUseBufferMemoryServer */,
02534                                        TRUE /* fUnmarshall */);
02535   } else {
02536     array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat);
02537     array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory,
02538                                        pFormat, fMustAlloc,
02539                                        TRUE /* fUseBufferMemoryServer */,
02540                                        TRUE /* fUnmarshall */);
02541   }
02542 
02543   return NULL;
02544 }
02545 
02546 /***********************************************************************
02547  *           NdrNonConformantStringMarshall [RPCRT4.@]
02548  */
02549 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
02550                                 unsigned char *pMemory,
02551                                 PFORMAT_STRING pFormat)
02552 {
02553   ULONG esize, size, maxsize;
02554 
02555   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
02556 
02557   maxsize = *(const USHORT *)&pFormat[2];
02558 
02559   if (*pFormat == RPC_FC_CSTRING)
02560   {
02561     ULONG i = 0;
02562     const char *str = (const char *)pMemory;
02563     while (i < maxsize && str[i]) i++;
02564     TRACE("string=%s\n", debugstr_an(str, i));
02565     pStubMsg->ActualCount = i + 1;
02566     esize = 1;
02567   }
02568   else if (*pFormat == RPC_FC_WSTRING)
02569   {
02570     ULONG i = 0;
02571     const WCHAR *str = (const WCHAR *)pMemory;
02572     while (i < maxsize && str[i]) i++;
02573     TRACE("string=%s\n", debugstr_wn(str, i));
02574     pStubMsg->ActualCount = i + 1;
02575     esize = 2;
02576   }
02577   else
02578   {
02579     ERR("Unhandled string type: %#x\n", *pFormat);
02580     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02581   }
02582 
02583   pStubMsg->Offset = 0;
02584   WriteVariance(pStubMsg);
02585 
02586   size = safe_multiply(esize, pStubMsg->ActualCount);
02587   safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */
02588 
02589   return NULL;
02590 }
02591 
02592 /***********************************************************************
02593  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
02594  */
02595 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
02596                                 unsigned char **ppMemory,
02597                                 PFORMAT_STRING pFormat,
02598                                 unsigned char fMustAlloc)
02599 {
02600   ULONG bufsize, memsize, esize, maxsize;
02601 
02602   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
02603     pStubMsg, *ppMemory, pFormat, fMustAlloc);
02604 
02605   maxsize = *(const USHORT *)&pFormat[2];
02606 
02607   ReadVariance(pStubMsg, NULL, maxsize);
02608   if (pStubMsg->Offset)
02609   {
02610     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
02611     RpcRaiseException(RPC_S_INVALID_BOUND);
02612   }
02613 
02614   if (*pFormat == RPC_FC_CSTRING) esize = 1;
02615   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
02616   else
02617   {
02618     ERR("Unhandled string type: %#x\n", *pFormat);
02619     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02620   }
02621 
02622   memsize = esize * maxsize;
02623   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
02624 
02625   validate_string_data(pStubMsg, bufsize, esize);
02626 
02627   if (!fMustAlloc && !*ppMemory)
02628     fMustAlloc = TRUE;
02629   if (fMustAlloc)
02630     *ppMemory = NdrAllocate(pStubMsg, memsize);
02631 
02632   safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize);
02633 
02634   if (*pFormat == RPC_FC_CSTRING) {
02635     TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount));
02636   }
02637   else if (*pFormat == RPC_FC_WSTRING) {
02638     TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount));
02639   }
02640 
02641   return NULL;
02642 }
02643 
02644 /***********************************************************************
02645  *           NdrNonConformantStringBufferSize [RPCRT4.@]
02646  */
02647 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
02648                                 unsigned char *pMemory,
02649                                 PFORMAT_STRING pFormat)
02650 {
02651   ULONG esize, maxsize;
02652 
02653   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
02654 
02655   maxsize = *(const USHORT *)&pFormat[2];
02656 
02657   SizeVariance(pStubMsg);
02658 
02659   if (*pFormat == RPC_FC_CSTRING)
02660   {
02661     ULONG i = 0;
02662     const char *str = (const char *)pMemory;
02663     while (i < maxsize && str[i]) i++;
02664     TRACE("string=%s\n", debugstr_an(str, i));
02665     pStubMsg->ActualCount = i + 1;
02666     esize = 1;
02667   }
02668   else if (*pFormat == RPC_FC_WSTRING)
02669   {
02670     ULONG i = 0;
02671     const WCHAR *str = (const WCHAR *)pMemory;
02672     while (i < maxsize && str[i]) i++;
02673     TRACE("string=%s\n", debugstr_wn(str, i));
02674     pStubMsg->ActualCount = i + 1;
02675     esize = 2;
02676   }
02677   else
02678   {
02679     ERR("Unhandled string type: %#x\n", *pFormat);
02680     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02681   }
02682 
02683   safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
02684 }
02685 
02686 /***********************************************************************
02687  *           NdrNonConformantStringMemorySize [RPCRT4.@]
02688  */
02689 ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
02690                                 PFORMAT_STRING pFormat)
02691 {
02692   ULONG bufsize, memsize, esize, maxsize;
02693 
02694   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
02695 
02696   maxsize = *(const USHORT *)&pFormat[2];
02697 
02698   ReadVariance(pStubMsg, NULL, maxsize);
02699 
02700   if (pStubMsg->Offset)
02701   {
02702     ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset);
02703     RpcRaiseException(RPC_S_INVALID_BOUND);
02704   }
02705 
02706   if (*pFormat == RPC_FC_CSTRING) esize = 1;
02707   else if (*pFormat == RPC_FC_WSTRING) esize = 2;
02708   else
02709   {
02710     ERR("Unhandled string type: %#x\n", *pFormat);
02711     RpcRaiseException(RPC_X_BAD_STUB_DATA);
02712   }
02713 
02714   memsize = esize * maxsize;
02715   bufsize = safe_multiply(esize, pStubMsg->ActualCount);
02716 
02717   validate_string_data(pStubMsg, bufsize, esize);
02718 
02719   safe_buffer_increment(pStubMsg, bufsize);
02720   pStubMsg->MemorySize += memsize;
02721 
02722   return pStubMsg->MemorySize;
02723 }
02724 
02725 /* Complex types */
02726 
02727 #include "pshpack1.h"
02728 typedef struct
02729 {
02730     unsigned char type;
02731     unsigned char flags_type; /* flags in upper nibble, type in lower nibble */
02732     ULONG low_value;
02733     ULONG high_value;
02734 } NDR_RANGE;
02735 #include "poppack.h"
02736 
02737 static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
02738                                  PFORMAT_STRING pFormat)
02739 {
02740   switch (*pFormat) {
02741   case RPC_FC_STRUCT:
02742   case RPC_FC_PSTRUCT:
02743   case RPC_FC_CSTRUCT:
02744   case RPC_FC_BOGUS_STRUCT:
02745   case RPC_FC_SMFARRAY:
02746   case RPC_FC_SMVARRAY:
02747   case RPC_FC_CSTRING:
02748     return *(const WORD*)&pFormat[2];
02749   case RPC_FC_USER_MARSHAL:
02750     return *(const WORD*)&pFormat[4];
02751   case RPC_FC_RANGE: {
02752     switch (((const NDR_RANGE *)pFormat)->flags_type & 0xf) {
02753     case RPC_FC_BYTE:
02754     case RPC_FC_CHAR:
02755     case RPC_FC_SMALL:
02756     case RPC_FC_USMALL:
02757         return sizeof(UCHAR);
02758     case RPC_FC_WCHAR:
02759     case RPC_FC_SHORT:
02760     case RPC_FC_USHORT:
02761         return sizeof(USHORT);
02762     case RPC_FC_LONG:
02763     case RPC_FC_ULONG:
02764     case RPC_FC_ENUM32:
02765     case RPC_FC_INT3264:
02766     case RPC_FC_UINT3264:
02767         return sizeof(ULONG);
02768     case RPC_FC_FLOAT:
02769         return sizeof(float);
02770     case RPC_FC_DOUBLE:
02771         return sizeof(double);
02772     case RPC_FC_HYPER:
02773         return sizeof(ULONGLONG);
02774     case RPC_FC_ENUM16:
02775         return sizeof(UINT);
02776     default:
02777         ERR("unknown type 0x%x\n", ((const NDR_RANGE *)pFormat)->flags_type & 0xf);
02778         RpcRaiseException(RPC_X_BAD_STUB_DATA);
02779     }
02780   }
02781   case RPC_FC_NON_ENCAPSULATED_UNION:
02782     pFormat += 2;
02783     if (pStubMsg->fHasNewCorrDesc)
02784         pFormat += 6;
02785     else
02786         pFormat += 4;
02787 
02788     pFormat += *(const SHORT*)pFormat;
02789     return *(const SHORT*)pFormat;
02790   case RPC_FC_IP:
02791     return sizeof(void *);
02792   case RPC_FC_WSTRING:
02793     return *(const WORD*)&pFormat[2] * 2;
02794   default:
02795     FIXME("unhandled embedded type %02x\n", *pFormat);
02796   }
02797   return 0;
02798 }
02799 
02800 
02801 static ULONG EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
02802                                        PFORMAT_STRING pFormat)
02803 {
02804   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
02805 
02806   if (!m)
02807   {
02808     FIXME("no memorysizer for data type=%02x\n", *pFormat);
02809     return 0;
02810   }
02811 
02812   return m(pStubMsg, pFormat);
02813 }
02814 
02815 
02816 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
02817                                        unsigned char *pMemory,
02818                                        PFORMAT_STRING pFormat,
02819                                        PFORMAT_STRING pPointer)
02820 {
02821   PFORMAT_STRING desc;
02822   NDR_MARSHALL m;
02823   ULONG size;
02824 
02825   while (*pFormat != RPC_FC_END) {
02826     switch (*pFormat) {
02827     case RPC_FC_BYTE:
02828     case RPC_FC_CHAR:
02829     case RPC_FC_SMALL:
02830     case RPC_FC_USMALL:
02831       TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory);
02832       safe_copy_to_buffer(pStubMsg, pMemory, 1);
02833       pMemory += 1;
02834       break;
02835     case RPC_FC_WCHAR:
02836     case RPC_FC_SHORT:
02837     case RPC_FC_USHORT:
02838       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
02839       safe_copy_to_buffer(pStubMsg, pMemory, 2);
02840       pMemory += 2;
02841       break;
02842     case RPC_FC_ENUM16:
02843     {
02844       USHORT val = *(DWORD *)pMemory;
02845       TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory);
02846       if (32767 < *(DWORD*)pMemory)
02847         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
02848       safe_copy_to_buffer(pStubMsg, &val, 2);
02849       pMemory += 4;
02850       break;
02851     }
02852     case RPC_FC_LONG:
02853     case RPC_FC_ULONG:
02854     case RPC_FC_ENUM32:
02855       TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory);
02856       safe_copy_to_buffer(pStubMsg, pMemory, 4);
02857       pMemory += 4;
02858       break;
02859     case RPC_FC_INT3264:
02860     case RPC_FC_UINT3264:
02861     {
02862       UINT val = *(UINT_PTR *)pMemory;
02863       TRACE("int3264=%ld <= %p\n", *(UINT_PTR *)pMemory, pMemory);
02864       safe_copy_to_buffer(pStubMsg, &val, sizeof(UINT));
02865       pMemory += sizeof(UINT_PTR);
02866       break;
02867     }
02868     case RPC_FC_FLOAT:
02869       TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
02870       safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
02871       pMemory += sizeof(float);
02872       break;
02873     case RPC_FC_HYPER:
02874       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
02875       safe_copy_to_buffer(pStubMsg, pMemory, 8);
02876       pMemory += 8;
02877       break;
02878     case RPC_FC_DOUBLE:
02879       TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
02880       safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
02881       pMemory += sizeof(double);
02882       break;
02883     case RPC_FC_RP:
02884     case RPC_FC_UP:
02885     case RPC_FC_OP:
02886     case RPC_FC_FP:
02887     case RPC_FC_POINTER:
02888     {
02889       unsigned char *saved_buffer;
02890       int pointer_buffer_mark_set = 0;
02891       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
02892       TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
02893       if (*pFormat != RPC_FC_POINTER)
02894         pPointer = pFormat;
02895       if (*pPointer != RPC_FC_RP)
02896         align_pointer_clear(&pStubMsg->Buffer, 4);
02897       saved_buffer = pStubMsg->Buffer;
02898       if (pStubMsg->PointerBufferMark)
02899       {
02900         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
02901         pStubMsg->PointerBufferMark = NULL;
02902         pointer_buffer_mark_set = 1;
02903       }
02904       else if (*pPointer != RPC_FC_RP)
02905         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
02906       PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer);
02907       if (pointer_buffer_mark_set)
02908       {
02909         STD_OVERFLOW_CHECK(pStubMsg);
02910         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
02911         pStubMsg->Buffer = saved_buffer;
02912         if (*pPointer != RPC_FC_RP)
02913           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
02914       }
02915       TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
02916       if (*pFormat == RPC_FC_POINTER)
02917         pPointer += 4;
02918       else
02919         pFormat += 4;
02920       pMemory += sizeof(void *);
02921       break;
02922     }
02923     case RPC_FC_ALIGNM2:
02924       align_pointer(&pMemory, 2);
02925       break;
02926     case RPC_FC_ALIGNM4:
02927       align_pointer(&pMemory, 4);
02928       break;
02929     case RPC_FC_ALIGNM8:
02930       align_pointer(&pMemory, 8);
02931       break;
02932     case RPC_FC_STRUCTPAD1:
02933     case RPC_FC_STRUCTPAD2:
02934     case RPC_FC_STRUCTPAD3:
02935     case RPC_FC_STRUCTPAD4:
02936     case RPC_FC_STRUCTPAD5:
02937     case RPC_FC_STRUCTPAD6:
02938     case RPC_FC_STRUCTPAD7:
02939       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
02940       break;
02941     case RPC_FC_EMBEDDED_COMPLEX:
02942       pMemory += pFormat[1];
02943       pFormat += 2;
02944       desc = pFormat + *(const SHORT*)pFormat;
02945       size = EmbeddedComplexSize(pStubMsg, desc);
02946       TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
02947       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
02948       if (m)
02949       {
02950         /* for some reason interface pointers aren't generated as
02951          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
02952          * they still need the derefencing treatment that pointers are
02953          * given */
02954         if (*desc == RPC_FC_IP)
02955           m(pStubMsg, *(unsigned char **)pMemory, desc);
02956         else
02957           m(pStubMsg, pMemory, desc);
02958       }
02959       else FIXME("no marshaller for embedded type %02x\n", *desc);
02960       pMemory += size;
02961       pFormat += 2;
02962       continue;
02963     case RPC_FC_PAD:
02964       break;
02965     default:
02966       FIXME("unhandled format 0x%02x\n", *pFormat);
02967     }
02968     pFormat++;
02969   }
02970 
02971   return pMemory;
02972 }
02973 
02974 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
02975                                          unsigned char *pMemory,
02976                                          PFORMAT_STRING pFormat,
02977                                          PFORMAT_STRING pPointer,
02978                                          unsigned char fMustAlloc)
02979 {
02980   PFORMAT_STRING desc;
02981   NDR_UNMARSHALL m;
02982   ULONG size;
02983 
02984   while (*pFormat != RPC_FC_END) {
02985     switch (*pFormat) {
02986     case RPC_FC_BYTE:
02987     case RPC_FC_CHAR:
02988     case RPC_FC_SMALL:
02989     case RPC_FC_USMALL:
02990       safe_copy_from_buffer(pStubMsg, pMemory, 1);
02991       TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory);
02992       pMemory += 1;
02993       break;
02994     case RPC_FC_WCHAR:
02995     case RPC_FC_SHORT:
02996     case RPC_FC_USHORT:
02997       safe_copy_from_buffer(pStubMsg, pMemory, 2);
02998       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
02999       pMemory += 2;
03000       break;
03001     case RPC_FC_ENUM16:
03002     {
03003       WORD val;
03004       safe_copy_from_buffer(pStubMsg, &val, 2);
03005       *(DWORD*)pMemory = val;
03006       TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory);
03007       if (32767 < *(DWORD*)pMemory)
03008         RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
03009       pMemory += 4;
03010       break;
03011     }
03012     case RPC_FC_LONG:
03013     case RPC_FC_ULONG:
03014     case RPC_FC_ENUM32:
03015       safe_copy_from_buffer(pStubMsg, pMemory, 4);
03016       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
03017       pMemory += 4;
03018       break;
03019     case RPC_FC_INT3264:
03020     {
03021       INT val;
03022       safe_copy_from_buffer(pStubMsg, &val, 4);
03023       *(INT_PTR *)pMemory = val;
03024       TRACE("int3264=%ld => %p\n", *(INT_PTR*)pMemory, pMemory);
03025       pMemory += sizeof(INT_PTR);
03026       break;
03027     }
03028     case RPC_FC_UINT3264:
03029     {
03030       UINT val;
03031       safe_copy_from_buffer(pStubMsg, &val, 4);
03032       *(UINT_PTR *)pMemory = val;
03033       TRACE("uint3264=%ld => %p\n", *(UINT_PTR*)pMemory, pMemory);
03034       pMemory += sizeof(UINT_PTR);
03035       break;
03036     }
03037     case RPC_FC_FLOAT:
03038       safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
03039       TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
03040       pMemory += sizeof(float);
03041       break;
03042     case RPC_FC_HYPER:
03043       safe_copy_from_buffer(pStubMsg, pMemory, 8);
03044       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
03045       pMemory += 8;
03046       break;
03047     case RPC_FC_DOUBLE:
03048       safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
03049       TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
03050       pMemory += sizeof(double);
03051       break;
03052     case RPC_FC_RP:
03053     case RPC_FC_UP:
03054     case RPC_FC_OP:
03055     case RPC_FC_FP:
03056     case RPC_FC_POINTER:
03057     {
03058       unsigned char *saved_buffer;
03059       int pointer_buffer_mark_set = 0;
03060       TRACE("pointer => %p\n", pMemory);
03061       if (*pFormat != RPC_FC_POINTER)
03062         pPointer = pFormat;
03063       if (*pPointer != RPC_FC_RP)
03064         align_pointer(&pStubMsg->Buffer, 4);
03065       saved_buffer = pStubMsg->Buffer;
03066       if (pStubMsg->PointerBufferMark)
03067       {
03068         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
03069         pStubMsg->PointerBufferMark = NULL;
03070         pointer_buffer_mark_set = 1;
03071       }
03072       else if (*pPointer != RPC_FC_RP)
03073         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
03074 
03075       PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, fMustAlloc);
03076       if (pointer_buffer_mark_set)
03077       {
03078         STD_OVERFLOW_CHECK(pStubMsg);
03079         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
03080         pStubMsg->Buffer = saved_buffer;
03081         if (*pPointer != RPC_FC_RP)
03082           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
03083       }
03084       if (*pFormat == RPC_FC_POINTER)
03085         pPointer += 4;
03086       else
03087         pFormat += 4;
03088       pMemory += sizeof(void *);
03089       break;
03090     }
03091     case RPC_FC_ALIGNM2:
03092       align_pointer_clear(&pMemory, 2);
03093       break;
03094     case RPC_FC_ALIGNM4:
03095       align_pointer_clear(&pMemory, 4);
03096       break;
03097     case RPC_FC_ALIGNM8:
03098       align_pointer_clear(&pMemory, 8);
03099       break;
03100     case RPC_FC_STRUCTPAD1:
03101     case RPC_FC_STRUCTPAD2:
03102     case RPC_FC_STRUCTPAD3:
03103     case RPC_FC_STRUCTPAD4:
03104     case RPC_FC_STRUCTPAD5:
03105     case RPC_FC_STRUCTPAD6:
03106     case RPC_FC_STRUCTPAD7:
03107       memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1);
03108       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
03109       break;
03110     case RPC_FC_EMBEDDED_COMPLEX:
03111       pMemory += pFormat[1];
03112       pFormat += 2;
03113       desc = pFormat + *(const SHORT*)pFormat;
03114       size = EmbeddedComplexSize(pStubMsg, desc);
03115       TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
03116       if (fMustAlloc)
03117         /* we can't pass fMustAlloc=TRUE into the marshaller for this type
03118          * since the type is part of the memory block that is encompassed by
03119          * the whole complex type. Memory is forced to allocate when pointers
03120          * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
03121          * clearing the memory we pass in to the unmarshaller */
03122         memset(pMemory, 0, size);
03123       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
03124       if (m)
03125       {
03126         /* for some reason interface pointers aren't generated as
03127          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
03128          * they still need the derefencing treatment that pointers are
03129          * given */
03130         if (*desc == RPC_FC_IP)
03131           m(pStubMsg, (unsigned char **)pMemory, desc, FALSE);
03132         else
03133           m(pStubMsg, &pMemory, desc, FALSE);
03134       }
03135       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
03136       pMemory += size;
03137       pFormat += 2;
03138       continue;
03139     case RPC_FC_PAD:
03140       break;
03141     default:
03142       FIXME("unhandled format %d\n", *pFormat);
03143     }
03144     pFormat++;
03145   }
03146 
03147   return pMemory;
03148 }
03149 
03150 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
03151                                          unsigned char *pMemory,
03152                                          PFORMAT_STRING pFormat,
03153                                          PFORMAT_STRING pPointer)
03154 {
03155   PFORMAT_STRING desc;
03156   NDR_BUFFERSIZE m;
03157   ULONG size;
03158 
03159   while (*pFormat != RPC_FC_END) {
03160     switch (*pFormat) {
03161     case RPC_FC_BYTE:
03162     case RPC_FC_CHAR:
03163     case RPC_FC_SMALL:
03164     case RPC_FC_USMALL:
03165       safe_buffer_length_increment(pStubMsg, 1);
03166       pMemory += 1;
03167       break;
03168     case RPC_FC_WCHAR:
03169     case RPC_FC_SHORT:
03170     case RPC_FC_USHORT:
03171       safe_buffer_length_increment(pStubMsg, 2);
03172       pMemory += 2;
03173       break;
03174     case RPC_FC_ENUM16:
03175       safe_buffer_length_increment(pStubMsg, 2);
03176       pMemory += 4;
03177       break;
03178     case RPC_FC_LONG:
03179     case RPC_FC_ULONG:
03180     case RPC_FC_ENUM32:
03181     case RPC_FC_FLOAT:
03182       safe_buffer_length_increment(pStubMsg, 4);
03183       pMemory += 4;
03184       break;
03185     case RPC_FC_INT3264:
03186     case RPC_FC_UINT3264:
03187       safe_buffer_length_increment(pStubMsg, 4);
03188       pMemory += sizeof(INT_PTR);
03189       break;
03190     case RPC_FC_HYPER:
03191     case RPC_FC_DOUBLE:
03192       safe_buffer_length_increment(pStubMsg, 8);
03193       pMemory += 8;
03194       break;
03195     case RPC_FC_RP:
03196     case RPC_FC_UP:
03197     case RPC_FC_OP:
03198     case RPC_FC_FP:
03199     case RPC_FC_POINTER:
03200       if (*pFormat != RPC_FC_POINTER)
03201         pPointer = pFormat;
03202       if (!pStubMsg->IgnoreEmbeddedPointers)
03203       {
03204         int saved_buffer_length = pStubMsg->BufferLength;
03205         pStubMsg->BufferLength = pStubMsg->PointerLength;
03206         pStubMsg->PointerLength = 0;
03207         if(!pStubMsg->BufferLength)
03208           ERR("BufferLength == 0??\n");
03209         PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
03210         pStubMsg->PointerLength = pStubMsg->BufferLength;
03211         pStubMsg->BufferLength = saved_buffer_length;
03212       }
03213       if (*pPointer != RPC_FC_RP)
03214       {
03215         align_length(&pStubMsg->BufferLength, 4);
03216         safe_buffer_length_increment(pStubMsg, 4);
03217       }
03218       if (*pFormat == RPC_FC_POINTER)
03219         pPointer += 4;
03220       else
03221         pFormat += 4;
03222       pMemory += sizeof(void*);
03223       break;
03224     case RPC_FC_ALIGNM2:
03225       align_pointer(&pMemory, 2);
03226       break;
03227     case RPC_FC_ALIGNM4:
03228       align_pointer(&pMemory, 4);
03229       break;
03230     case RPC_FC_ALIGNM8:
03231       align_pointer(&pMemory, 8);
03232       break;
03233     case RPC_FC_STRUCTPAD1:
03234     case RPC_FC_STRUCTPAD2:
03235     case RPC_FC_STRUCTPAD3:
03236     case RPC_FC_STRUCTPAD4:
03237     case RPC_FC_STRUCTPAD5:
03238     case RPC_FC_STRUCTPAD6:
03239     case RPC_FC_STRUCTPAD7:
03240       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
03241       break;
03242     case RPC_FC_EMBEDDED_COMPLEX:
03243       pMemory += pFormat[1];
03244       pFormat += 2;
03245       desc = pFormat + *(const SHORT*)pFormat;
03246       size = EmbeddedComplexSize(pStubMsg, desc);
03247       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
03248       if (m)
03249       {
03250         /* for some reason interface pointers aren't generated as
03251          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
03252          * they still need the derefencing treatment that pointers are
03253          * given */
03254         if (*desc == RPC_FC_IP)
03255           m(pStubMsg, *(unsigned char **)pMemory, desc);
03256         else
03257           m(pStubMsg, pMemory, desc);
03258       }
03259       else FIXME("no buffersizer for embedded type %02x\n", *desc);
03260       pMemory += size;
03261       pFormat += 2;
03262       continue;
03263     case RPC_FC_PAD:
03264       break;
03265     default:
03266       FIXME("unhandled format 0x%02x\n", *pFormat);
03267     }
03268     pFormat++;
03269   }
03270 
03271   return pMemory;
03272 }
03273 
03274 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
03275                                    unsigned char *pMemory,
03276                                    PFORMAT_STRING pFormat,
03277                                    PFORMAT_STRING pPointer)
03278 {
03279   PFORMAT_STRING desc;
03280   NDR_FREE m;
03281   ULONG size;
03282 
03283   while (*pFormat != RPC_FC_END) {
03284     switch (*pFormat) {
03285     case RPC_FC_BYTE:
03286     case RPC_FC_CHAR:
03287     case RPC_FC_SMALL:
03288     case RPC_FC_USMALL:
03289       pMemory += 1;
03290       break;
03291     case RPC_FC_WCHAR:
03292     case RPC_FC_SHORT:
03293     case RPC_FC_USHORT:
03294       pMemory += 2;
03295       break;
03296     case RPC_FC_LONG:
03297     case RPC_FC_ULONG:
03298     case RPC_FC_ENUM16:
03299     case RPC_FC_ENUM32:
03300     case RPC_FC_FLOAT:
03301       pMemory += 4;
03302       break;
03303     case RPC_FC_INT3264:
03304     case RPC_FC_UINT3264:
03305       pMemory += sizeof(INT_PTR);
03306       break;
03307     case RPC_FC_HYPER:
03308     case RPC_FC_DOUBLE:
03309       pMemory += 8;
03310       break;
03311     case RPC_FC_RP:
03312     case RPC_FC_UP:
03313     case RPC_FC_OP:
03314     case RPC_FC_FP:
03315     case RPC_FC_POINTER:
03316       if (*pFormat != RPC_FC_POINTER)
03317         pPointer = pFormat;
03318       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
03319       if (*pFormat == RPC_FC_POINTER)
03320         pPointer += 4;
03321       else
03322         pFormat += 4;
03323       pMemory += sizeof(void *);
03324       break;
03325     case RPC_FC_ALIGNM2:
03326       align_pointer(&pMemory, 2);
03327       break;
03328     case RPC_FC_ALIGNM4:
03329       align_pointer(&pMemory, 4);
03330       break;
03331     case RPC_FC_ALIGNM8:
03332       align_pointer(&pMemory, 8);
03333       break;
03334     case RPC_FC_STRUCTPAD1:
03335     case RPC_FC_STRUCTPAD2:
03336     case RPC_FC_STRUCTPAD3:
03337     case RPC_FC_STRUCTPAD4:
03338     case RPC_FC_STRUCTPAD5:
03339     case RPC_FC_STRUCTPAD6:
03340     case RPC_FC_STRUCTPAD7:
03341       pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1;
03342       break;
03343     case RPC_FC_EMBEDDED_COMPLEX:
03344       pMemory += pFormat[1];
03345       pFormat += 2;
03346       desc = pFormat + *(const SHORT*)pFormat;
03347       size = EmbeddedComplexSize(pStubMsg, desc);
03348       m = NdrFreer[*desc & NDR_TABLE_MASK];
03349       if (m)
03350       {
03351         /* for some reason interface pointers aren't generated as
03352          * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet
03353          * they still need the derefencing treatment that pointers are
03354          * given */
03355         if (*desc == RPC_FC_IP)
03356           m(pStubMsg, *(unsigned char **)pMemory, desc);
03357         else
03358           m(pStubMsg, pMemory, desc);
03359       }
03360       pMemory += size;
03361       pFormat += 2;
03362       continue;
03363     case RPC_FC_PAD:
03364       break;
03365     default:
03366       FIXME("unhandled format 0x%02x\n", *pFormat);
03367     }
03368     pFormat++;
03369   }
03370 
03371   return pMemory;
03372 }
03373 
03374 static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
03375                                      PFORMAT_STRING pFormat,
03376                                      PFORMAT_STRING pPointer)
03377 {
03378   PFORMAT_STRING desc;
03379   ULONG size = 0;
03380 
03381   while (*pFormat != RPC_FC_END) {
03382     switch (*pFormat) {
03383     case RPC_FC_BYTE:
03384     case RPC_FC_CHAR:
03385     case RPC_FC_SMALL:
03386     case RPC_FC_USMALL:
03387       size += 1;
03388       safe_buffer_increment(pStubMsg, 1);
03389       break;
03390     case RPC_FC_WCHAR:
03391     case RPC_FC_SHORT:
03392     case RPC_FC_USHORT:
03393       size += 2;
03394       safe_buffer_increment(pStubMsg, 2);
03395       break;
03396     case RPC_FC_ENUM16:
03397       size += 4;
03398       safe_buffer_increment(pStubMsg, 2);
03399       break;
03400     case RPC_FC_LONG:
03401     case RPC_FC_ULONG:
03402     case RPC_FC_ENUM32:
03403     case RPC_FC_FLOAT:
03404       size += 4;
03405       safe_buffer_increment(pStubMsg, 4);
03406       break;
03407     case RPC_FC_INT3264:
03408     case RPC_FC_UINT3264:
03409       size += sizeof(INT_PTR);
03410       safe_buffer_increment(pStubMsg, 4);
03411       break;
03412     case RPC_FC_HYPER:
03413     case RPC_FC_DOUBLE:
03414       size += 8;
03415       safe_buffer_increment(pStubMsg, 8);
03416       break;
03417     case RPC_FC_RP:
03418     case RPC_FC_UP:
03419     case RPC_FC_OP:
03420     case RPC_FC_FP:
03421     case RPC_FC_POINTER:
03422     {
03423       unsigned char *saved_buffer;
03424       int pointer_buffer_mark_set = 0;
03425       if (*pFormat != RPC_FC_POINTER)
03426         pPointer = pFormat;
03427       if (*pPointer != RPC_FC_RP)
03428         align_pointer(&pStubMsg->Buffer, 4);
03429       saved_buffer = pStubMsg->Buffer;
03430       if (pStubMsg->PointerBufferMark)
03431       {
03432         pStubMsg->Buffer = pStubMsg->PointerBufferMark;
03433         pStubMsg->PointerBufferMark = NULL;
03434         pointer_buffer_mark_set = 1;
03435       }
03436       else if (*pPointer != RPC_FC_RP)
03437         safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
03438 
03439       if (!pStubMsg->IgnoreEmbeddedPointers)
03440         PointerMemorySize(pStubMsg, saved_buffer, pPointer);
03441       if (pointer_buffer_mark_set)
03442       {
03443         STD_OVERFLOW_CHECK(pStubMsg);
03444         pStubMsg->PointerBufferMark = pStubMsg->Buffer;
03445         pStubMsg->Buffer = saved_buffer;
03446         if (*pPointer != RPC_FC_RP)
03447           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
03448       }
03449       if (*pFormat == RPC_FC_POINTER)
03450         pPointer += 4;
03451       else
03452         pFormat += 4;
03453       size += sizeof(void *);
03454       break;
03455     }
03456     case RPC_FC_ALIGNM2:
03457       align_length(&size, 2);
03458       break;
03459     case RPC_FC_ALIGNM4:
03460       align_length(&size, 4);
03461       break;
03462     case RPC_FC_ALIGNM8:
03463       align_length(&size, 8);
03464       break;
03465     case RPC_FC_STRUCTPAD1:
03466     case RPC_FC_STRUCTPAD2:
03467     case RPC_FC_STRUCTPAD3:
03468     case RPC_FC_STRUCTPAD4:
03469     case RPC_FC_STRUCTPAD5:
03470     case RPC_FC_STRUCTPAD6:
03471     case RPC_FC_STRUCTPAD7:
03472       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
03473       break;
03474     case RPC_FC_EMBEDDED_COMPLEX:
03475       size += pFormat[1];
03476       pFormat += 2;
03477       desc = pFormat + *(const SHORT*)pFormat;
03478       size += EmbeddedComplexMemorySize(pStubMsg, desc);
03479       pFormat += 2;
03480       continue;
03481     case RPC_FC_PAD:
03482       break;
03483     default:
03484       FIXME("unhandled format 0x%02x\n", *pFormat);
03485     }
03486     pFormat++;
03487   }
03488 
03489   return size;
03490 }
03491 
03492 ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
03493 {
03494   PFORMAT_STRING desc;
03495   ULONG size = 0;
03496 
03497   while (*pFormat != RPC_FC_END) {
03498     switch (*pFormat) {
03499     case RPC_FC_BYTE:
03500     case RPC_FC_CHAR:
03501     case RPC_FC_SMALL:
03502     case RPC_FC_USMALL:
03503       size += 1;
03504       break;
03505     case RPC_FC_WCHAR:
03506     case RPC_FC_SHORT:
03507     case RPC_FC_USHORT:
03508       size += 2;
03509       break;
03510     case RPC_FC_LONG:
03511     case RPC_FC_ULONG:
03512     case RPC_FC_ENUM16:
03513     case RPC_FC_ENUM32:
03514     case RPC_FC_FLOAT:
03515       size += 4;
03516       break;
03517     case RPC_FC_INT3264:
03518     case RPC_FC_UINT3264:
03519       size += sizeof(INT_PTR);
03520       break;
03521     case RPC_FC_HYPER:
03522     case RPC_FC_DOUBLE:
03523       size += 8;
03524       break;
03525     case RPC_FC_RP:
03526     case RPC_FC_UP:
03527     case RPC_FC_OP:
03528     case RPC_FC_FP:
03529     case RPC_FC_POINTER:
03530       size += sizeof(void *);
03531       if (*pFormat != RPC_FC_POINTER)
03532         pFormat += 4;
03533       break;
03534     case RPC_FC_ALIGNM2:
03535       align_length(&size, 2);
03536       break;
03537     case RPC_FC_ALIGNM4:
03538       align_length(&size, 4);
03539       break;
03540     case RPC_FC_ALIGNM8:
03541       align_length(&size, 8);
03542       break;
03543     case RPC_FC_STRUCTPAD1:
03544     case RPC_FC_STRUCTPAD2:
03545     case RPC_FC_STRUCTPAD3:
03546     case RPC_FC_STRUCTPAD4:
03547     case RPC_FC_STRUCTPAD5:
03548     case RPC_FC_STRUCTPAD6:
03549     case RPC_FC_STRUCTPAD7:
03550       size += *pFormat - RPC_FC_STRUCTPAD1 + 1;
03551       break;
03552     case RPC_FC_EMBEDDED_COMPLEX:
03553       size += pFormat[1];
03554       pFormat += 2;
03555       desc = pFormat + *(const SHORT*)pFormat;
03556       size += EmbeddedComplexSize(pStubMsg, desc);
03557       pFormat += 2;
03558       continue;
03559     case RPC_FC_PAD:
03560       break;
03561     default:
03562       FIXME("unhandled format 0x%02x\n", *pFormat);
03563     }
03564     pFormat++;
03565   }
03566 
03567   return size;
03568 }
03569 
03570 /***********************************************************************
03571  *           NdrComplexStructMarshall [RPCRT4.@]
03572  */
03573 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
03574                                                 unsigned char *pMemory,
03575                                                 PFORMAT_STRING pFormat)
03576 {
03577   PFORMAT_STRING conf_array = NULL;
03578   PFORMAT_STRING pointer_desc = NULL;
03579   unsigned char *OldMemory = pStubMsg->Memory;
03580   int pointer_buffer_mark_set = 0;
03581   ULONG count = 0;
03582   ULONG max_count = 0;
03583   ULONG offset = 0;
03584 
03585   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
03586 
03587   if (!pStubMsg->PointerBufferMark)
03588   {
03589     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
03590     /* save buffer length */
03591     ULONG saved_buffer_length = pStubMsg->BufferLength;
03592 
03593     /* get the buffer pointer after complex array data, but before
03594      * pointer data */
03595     pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
03596     pStubMsg->IgnoreEmbeddedPointers = 1;
03597     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
03598     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
03599 
03600     /* save it for use by embedded pointer code later */
03601     pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
03602     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
03603     pointer_buffer_mark_set = 1;
03604 
03605     /* restore the original buffer length */
03606     pStubMsg->BufferLength = saved_buffer_length;
03607   }
03608 
03609   align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1);
03610 
03611   pFormat += 4;
03612   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
03613   pFormat += 2;
03614   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
03615   pFormat += 2;
03616 
03617   pStubMsg->Memory = pMemory;
03618 
03619   if (conf_array)
03620   {
03621     ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
03622     array_compute_and_write_conformance(conf_array[0], pStubMsg,
03623                                         pMemory + struct_size, conf_array);
03624     /* these could be changed in ComplexMarshall so save them for later */
03625     max_count = pStubMsg->MaxCount;
03626     count = pStubMsg->ActualCount;
03627     offset = pStubMsg->Offset;
03628   }
03629 
03630   pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
03631 
03632   if (conf_array)
03633   {
03634     pStubMsg->MaxCount = max_count;
03635     pStubMsg->ActualCount = count;
03636     pStubMsg->Offset = offset;
03637     array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory,
03638                                       conf_array, TRUE /* fHasPointers */);
03639   }
03640 
03641   pStubMsg->Memory = OldMemory;
03642 
03643   if (pointer_buffer_mark_set)
03644   {
03645     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
03646     pStubMsg->PointerBufferMark = NULL;
03647   }
03648 
03649   STD_OVERFLOW_CHECK(pStubMsg);
03650 
03651   return NULL;
03652 }
03653 
03654 /***********************************************************************
03655  *           NdrComplexStructUnmarshall [RPCRT4.@]
03656  */
03657 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
03658                                                   unsigned char **ppMemory,
03659                                                   PFORMAT_STRING pFormat,
03660                                                   unsigned char fMustAlloc)
03661 {
03662   unsigned size = *(const WORD*)(pFormat+2);
03663   PFORMAT_STRING conf_array = NULL;
03664   PFORMAT_STRING pointer_desc = NULL;
03665   unsigned char *pMemory;
03666   int pointer_buffer_mark_set = 0;
03667   ULONG count = 0;
03668   ULONG max_count = 0;
03669   ULONG offset = 0;
03670   ULONG array_size = 0;
03671 
03672   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
03673 
03674   if (!pStubMsg->PointerBufferMark)
03675   {
03676     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
03677     /* save buffer pointer */
03678     unsigned char *saved_buffer = pStubMsg->Buffer;
03679 
03680     /* get the buffer pointer after complex array data, but before
03681      * pointer data */
03682     pStubMsg->IgnoreEmbeddedPointers = 1;
03683     NdrComplexStructMemorySize(pStubMsg, pFormat);
03684     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
03685 
03686     /* save it for use by embedded pointer code later */
03687     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
03688     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
03689     pointer_buffer_mark_set = 1;
03690 
03691     /* restore the original buffer */
03692     pStubMsg->Buffer = saved_buffer;
03693   }
03694 
03695   align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
03696 
03697   pFormat += 4;
03698   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
03699   pFormat += 2;
03700   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
03701   pFormat += 2;
03702 
03703   if (conf_array)
03704   {
03705     array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array);
03706     size += array_size;
03707 
03708     /* these could be changed in ComplexMarshall so save them for later */
03709     max_count = pStubMsg->MaxCount;
03710     count = pStubMsg->ActualCount;
03711     offset = pStubMsg->Offset;
03712   }
03713 
03714   if (!fMustAlloc && !*ppMemory)
03715     fMustAlloc = TRUE;
03716   if (fMustAlloc)
03717     *ppMemory = NdrAllocate(pStubMsg, size);
03718 
03719   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
03720 
03721   if (conf_array)
03722   {
03723     pStubMsg->MaxCount = max_count;
03724     pStubMsg->ActualCount = count;
03725     pStubMsg->Offset = offset;
03726     if (fMustAlloc)
03727       memset(pMemory, 0, array_size);
03728     array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory,
03729                                        conf_array, FALSE,
03730                                        FALSE /* fUseBufferMemoryServer */,
03731                                        TRUE /* fUnmarshall */);
03732   }
03733 
03734   if (pointer_buffer_mark_set)
03735   {
03736     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
03737     pStubMsg->PointerBufferMark = NULL;
03738   }
03739 
03740   return NULL;
03741 }
03742 
03743 /***********************************************************************
03744  *           NdrComplexStructBufferSize [RPCRT4.@]
03745  */
03746 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
03747                                        unsigned char *pMemory,
03748                                        PFORMAT_STRING pFormat)
03749 {
03750   PFORMAT_STRING conf_array = NULL;
03751   PFORMAT_STRING pointer_desc = NULL;
03752   unsigned char *OldMemory = pStubMsg->Memory;
03753   int pointer_length_set = 0;
03754   ULONG count = 0;
03755   ULONG max_count = 0;
03756   ULONG offset = 0;
03757 
03758   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
03759 
03760   align_length(&pStubMsg->BufferLength, pFormat[1] + 1);
03761 
03762   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
03763   {
03764     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
03765     ULONG saved_buffer_length = pStubMsg->BufferLength;
03766 
03767     /* get the buffer length after complex struct data, but before
03768      * pointer data */
03769     pStubMsg->IgnoreEmbeddedPointers = 1;
03770     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
03771     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
03772 
03773     /* save it for use by embedded pointer code later */
03774     pStubMsg->PointerLength = pStubMsg->BufferLength;
03775     pointer_length_set = 1;
03776     TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
03777 
03778     /* restore the original buffer length */
03779     pStubMsg->BufferLength = saved_buffer_length;
03780   }
03781 
03782   pFormat += 4;
03783   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
03784   pFormat += 2;
03785   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
03786   pFormat += 2;
03787 
03788   pStubMsg->Memory = pMemory;
03789 
03790   if (conf_array)
03791   {
03792     ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
03793     array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
03794                                        conf_array);
03795 
03796     /* these could be changed in ComplexMarshall so save them for later */
03797     max_count = pStubMsg->MaxCount;
03798     count = pStubMsg->ActualCount;
03799     offset = pStubMsg->Offset;
03800   }
03801 
03802   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
03803 
03804   if (conf_array)
03805   {
03806     pStubMsg->MaxCount = max_count;
03807     pStubMsg->ActualCount = count;
03808     pStubMsg->Offset = offset;
03809     array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array,
03810                       TRUE /* fHasPointers */);
03811   }
03812 
03813   pStubMsg->Memory = OldMemory;
03814 
03815   if(pointer_length_set)
03816   {
03817     pStubMsg->BufferLength = pStubMsg->PointerLength;
03818     pStubMsg->PointerLength = 0;
03819   }
03820 
03821 }
03822 
03823 /***********************************************************************
03824  *           NdrComplexStructMemorySize [RPCRT4.@]
03825  */
03826 ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
03827                                         PFORMAT_STRING pFormat)
03828 {
03829   unsigned size = *(const WORD*)(pFormat+2);
03830   PFORMAT_STRING conf_array = NULL;
03831   PFORMAT_STRING pointer_desc = NULL;
03832   ULONG count = 0;
03833   ULONG max_count = 0;
03834   ULONG offset = 0;
03835 
03836   TRACE("(%p,%p)\n", pStubMsg, pFormat);
03837 
03838   align_pointer(&pStubMsg->Buffer, pFormat[1] + 1);
03839 
03840   pFormat += 4;
03841   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
03842   pFormat += 2;
03843   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
03844   pFormat += 2;
03845 
03846   if (conf_array)
03847   {
03848     array_read_conformance(conf_array[0], pStubMsg, conf_array);
03849 
03850     /* these could be changed in ComplexStructMemorySize so save them for
03851      * later */
03852     max_count = pStubMsg->MaxCount;
03853     count = pStubMsg->ActualCount;
03854     offset = pStubMsg->Offset;
03855   }
03856 
03857   ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc);
03858 
03859   if (conf_array)
03860   {
03861     pStubMsg->MaxCount = max_count;
03862     pStubMsg->ActualCount = count;
03863     pStubMsg->Offset = offset;
03864     array_memory_size(conf_array[0], pStubMsg, conf_array,
03865                       TRUE /* fHasPointers */);
03866   }
03867 
03868   return size;
03869 }
03870 
03871 /***********************************************************************
03872  *           NdrComplexStructFree [RPCRT4.@]
03873  */
03874 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
03875                                  unsigned char *pMemory,
03876                                  PFORMAT_STRING pFormat)
03877 {
03878   PFORMAT_STRING conf_array = NULL;
03879   PFORMAT_STRING pointer_desc = NULL;
03880   unsigned char *OldMemory = pStubMsg->Memory;
03881 
03882   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
03883 
03884   pFormat += 4;
03885   if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat;
03886   pFormat += 2;
03887   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
03888   pFormat += 2;
03889 
03890   pStubMsg->Memory = pMemory;
03891 
03892   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
03893 
03894   if (conf_array)
03895     array_free(conf_array[0], pStubMsg, pMemory, conf_array,
03896                TRUE /* fHasPointers */);
03897 
03898   pStubMsg->Memory = OldMemory;
03899 }
03900 
03901 /***********************************************************************
03902  *           NdrConformantArrayMarshall [RPCRT4.@]
03903  */
03904 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
03905                                                   unsigned char *pMemory,
03906                                                   PFORMAT_STRING pFormat)
03907 {
03908   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
03909   if (pFormat[0] != RPC_FC_CARRAY)
03910   {
03911     ERR("invalid format = 0x%x\n", pFormat[0]);
03912     RpcRaiseException(RPC_X_BAD_STUB_DATA);
03913   }
03914 
03915   array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory,
03916                                       pFormat);
03917   array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
03918                                     TRUE /* fHasPointers */);
03919 
03920   return NULL;
03921 }
03922 
03923 /***********************************************************************
03924  *           NdrConformantArrayUnmarshall [RPCRT4.@]
03925  */
03926 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
03927                                                     unsigned char **ppMemory,
03928                                                     PFORMAT_STRING pFormat,
03929                                                     unsigned char fMustAlloc)
03930 {
03931   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
03932   if (pFormat[0] != RPC_FC_CARRAY)
03933   {
03934     ERR("invalid format = 0x%x\n", pFormat[0]);
03935     RpcRaiseException(RPC_X_BAD_STUB_DATA);
03936   }
03937 
03938   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
03939   array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat,
03940                                      fMustAlloc,
03941                                      TRUE /* fUseBufferMemoryServer */,
03942                                      TRUE /* fUnmarshall */);
03943 
03944   return NULL;
03945 }
03946 
03947 /***********************************************************************
03948  *           NdrConformantArrayBufferSize [RPCRT4.@]
03949  */
03950 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
03951                                          unsigned char *pMemory,
03952                                          PFORMAT_STRING pFormat)
03953 {
03954   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
03955   if (pFormat[0] != RPC_FC_CARRAY)
03956   {
03957     ERR("invalid format = 0x%x\n", pFormat[0]);
03958     RpcRaiseException(RPC_X_BAD_STUB_DATA);
03959   }
03960 
03961   array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat);
03962   array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
03963                     TRUE /* fHasPointers */);
03964 }
03965 
03966 /***********************************************************************
03967  *           NdrConformantArrayMemorySize [RPCRT4.@]
03968  */
03969 ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
03970                                           PFORMAT_STRING pFormat)
03971 {
03972   TRACE("(%p,%p)\n", pStubMsg, pFormat);
03973   if (pFormat[0] != RPC_FC_CARRAY)
03974   {
03975     ERR("invalid format = 0x%x\n", pFormat[0]);
03976     RpcRaiseException(RPC_X_BAD_STUB_DATA);
03977   }
03978 
03979   array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat);
03980   array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
03981 
03982   return pStubMsg->MemorySize;
03983 }
03984 
03985 /***********************************************************************
03986  *           NdrConformantArrayFree [RPCRT4.@]
03987  */
03988 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
03989                                    unsigned char *pMemory,
03990                                    PFORMAT_STRING pFormat)
03991 {
03992   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
03993   if (pFormat[0] != RPC_FC_CARRAY)
03994   {
03995     ERR("invalid format = 0x%x\n", pFormat[0]);
03996     RpcRaiseException(RPC_X_BAD_STUB_DATA);
03997   }
03998 
03999   array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat,
04000              TRUE /* fHasPointers */);
04001 }
04002 
04003 
04004 /***********************************************************************
04005  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
04006  */
04007 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
04008                                                          unsigned char* pMemory,
04009                                                          PFORMAT_STRING pFormat )
04010 {
04011     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
04012 
04013     if (pFormat[0] != RPC_FC_CVARRAY)
04014     {
04015         ERR("invalid format type %x\n", pFormat[0]);
04016         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04017         return NULL;
04018     }
04019 
04020     array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
04021                                         pFormat);
04022     array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory,
04023                                       pFormat, TRUE /* fHasPointers */);
04024 
04025     return NULL;
04026 }
04027 
04028 
04029 /***********************************************************************
04030  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
04031  */
04032 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
04033                                                            unsigned char** ppMemory,
04034                                                            PFORMAT_STRING pFormat,
04035                                                            unsigned char fMustAlloc )
04036 {
04037     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
04038 
04039     if (pFormat[0] != RPC_FC_CVARRAY)
04040     {
04041         ERR("invalid format type %x\n", pFormat[0]);
04042         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04043         return NULL;
04044     }
04045 
04046     array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
04047     array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory,
04048                                        pFormat, fMustAlloc,
04049                                        TRUE /* fUseBufferMemoryServer */,
04050                                        TRUE /* fUnmarshall */);
04051 
04052     return NULL;
04053 }
04054 
04055 
04056 /***********************************************************************
04057  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
04058  */
04059 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
04060                                            unsigned char* pMemory,
04061                                            PFORMAT_STRING pFormat )
04062 {
04063     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
04064 
04065     if (pFormat[0] != RPC_FC_CVARRAY)
04066     {
04067         ERR("invalid format type %x\n", pFormat[0]);
04068         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04069         return;
04070     }
04071 
04072     array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
04073                TRUE /* fHasPointers */);
04074 }
04075 
04076 
04077 /***********************************************************************
04078  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
04079  */
04080 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
04081                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
04082 {
04083     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
04084 
04085     if (pFormat[0] != RPC_FC_CVARRAY)
04086     {
04087         ERR("invalid format type %x\n", pFormat[0]);
04088         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04089         return;
04090     }
04091 
04092     array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory,
04093                                        pFormat);
04094     array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat,
04095                       TRUE /* fHasPointers */);
04096 }
04097 
04098 
04099 /***********************************************************************
04100  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
04101  */
04102 ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
04103                                                   PFORMAT_STRING pFormat )
04104 {
04105     TRACE("(%p, %p)\n", pStubMsg, pFormat);
04106 
04107     if (pFormat[0] != RPC_FC_CVARRAY)
04108     {
04109         ERR("invalid format type %x\n", pFormat[0]);
04110         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04111         return pStubMsg->MemorySize;
04112     }
04113 
04114     array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat);
04115     array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat,
04116                       TRUE /* fHasPointers */);
04117 
04118     return pStubMsg->MemorySize;
04119 }
04120 
04121 
04122 /***********************************************************************
04123  *           NdrComplexArrayMarshall [RPCRT4.@]
04124  */
04125 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
04126                                                unsigned char *pMemory,
04127                                                PFORMAT_STRING pFormat)
04128 {
04129   int pointer_buffer_mark_set = 0;
04130 
04131   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
04132 
04133   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
04134   {
04135       ERR("invalid format type %x\n", pFormat[0]);
04136       RpcRaiseException(RPC_S_INTERNAL_ERROR);
04137       return NULL;
04138   }
04139 
04140   if (!pStubMsg->PointerBufferMark)
04141   {
04142     /* save buffer fields that may be changed by buffer sizer functions
04143      * and that may be needed later on */
04144     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
04145     ULONG saved_buffer_length = pStubMsg->BufferLength;
04146     ULONG_PTR saved_max_count = pStubMsg->MaxCount;
04147     ULONG saved_offset = pStubMsg->Offset;
04148     ULONG saved_actual_count = pStubMsg->ActualCount;
04149 
04150     /* get the buffer pointer after complex array data, but before
04151      * pointer data */
04152     pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
04153     pStubMsg->IgnoreEmbeddedPointers = 1;
04154     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
04155     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
04156 
04157     /* save it for use by embedded pointer code later */
04158     pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
04159     TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
04160     pointer_buffer_mark_set = 1;
04161 
04162     /* restore fields */
04163     pStubMsg->ActualCount = saved_actual_count;
04164     pStubMsg->Offset = saved_offset;
04165     pStubMsg->MaxCount = saved_max_count;
04166     pStubMsg->BufferLength = saved_buffer_length;
04167   }
04168 
04169   array_compute_and_write_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat);
04170   array_write_variance_and_marshall(RPC_FC_BOGUS_ARRAY, pStubMsg,
04171                                     pMemory, pFormat, TRUE /* fHasPointers */);
04172 
04173   STD_OVERFLOW_CHECK(pStubMsg);
04174 
04175   if (pointer_buffer_mark_set)
04176   {
04177     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
04178     pStubMsg->PointerBufferMark = NULL;
04179   }
04180 
04181   return NULL;
04182 }
04183 
04184 /***********************************************************************
04185  *           NdrComplexArrayUnmarshall [RPCRT4.@]
04186  */
04187 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
04188                                                  unsigned char **ppMemory,
04189                                                  PFORMAT_STRING pFormat,
04190                                                  unsigned char fMustAlloc)
04191 {
04192   unsigned char *saved_buffer;
04193   int pointer_buffer_mark_set = 0;
04194   int saved_ignore_embedded;
04195 
04196   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
04197 
04198   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
04199   {
04200       ERR("invalid format type %x\n", pFormat[0]);
04201       RpcRaiseException(RPC_S_INTERNAL_ERROR);
04202       return NULL;
04203   }
04204 
04205   saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
04206   /* save buffer pointer */
04207   saved_buffer = pStubMsg->Buffer;
04208   /* get the buffer pointer after complex array data, but before
04209    * pointer data */
04210   pStubMsg->IgnoreEmbeddedPointers = 1;
04211   pStubMsg->MemorySize = 0;
04212   NdrComplexArrayMemorySize(pStubMsg, pFormat);
04213   pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
04214 
04215   TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer));
04216   if (!pStubMsg->PointerBufferMark)
04217   {
04218     /* save it for use by embedded pointer code later */
04219     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
04220     pointer_buffer_mark_set = 1;
04221   }
04222   /* restore the original buffer */
04223   pStubMsg->Buffer = saved_buffer;
04224 
04225   array_read_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat);
04226   array_read_variance_and_unmarshall(RPC_FC_BOGUS_ARRAY, pStubMsg, ppMemory, pFormat, fMustAlloc,
04227                                      TRUE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */);
04228 
04229   if (pointer_buffer_mark_set)
04230   {
04231     pStubMsg->Buffer = pStubMsg->PointerBufferMark;
04232     pStubMsg->PointerBufferMark = NULL;
04233   }
04234 
04235   return NULL;
04236 }
04237 
04238 /***********************************************************************
04239  *           NdrComplexArrayBufferSize [RPCRT4.@]
04240  */
04241 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
04242                                       unsigned char *pMemory,
04243                                       PFORMAT_STRING pFormat)
04244 {
04245   int pointer_length_set = 0;
04246 
04247   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
04248 
04249   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
04250   {
04251       ERR("invalid format type %x\n", pFormat[0]);
04252       RpcRaiseException(RPC_S_INTERNAL_ERROR);
04253       return;
04254   }
04255 
04256   if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
04257   {
04258     /* save buffer fields that may be changed by buffer sizer functions
04259      * and that may be needed later on */
04260     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
04261     ULONG saved_buffer_length = pStubMsg->BufferLength;
04262     ULONG_PTR saved_max_count = pStubMsg->MaxCount;
04263     ULONG saved_offset = pStubMsg->Offset;
04264     ULONG saved_actual_count = pStubMsg->ActualCount;
04265 
04266     /* get the buffer pointer after complex array data, but before
04267      * pointer data */
04268     pStubMsg->IgnoreEmbeddedPointers = 1;
04269     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
04270     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
04271 
04272     /* save it for use by embedded pointer code later */
04273     pStubMsg->PointerLength = pStubMsg->BufferLength;
04274     pointer_length_set = 1;
04275 
04276     /* restore fields */
04277     pStubMsg->ActualCount = saved_actual_count;
04278     pStubMsg->Offset = saved_offset;
04279     pStubMsg->MaxCount = saved_max_count;
04280     pStubMsg->BufferLength = saved_buffer_length;
04281   }
04282 
04283   array_compute_and_size_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat);
04284   array_buffer_size(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */);
04285 
04286   if(pointer_length_set)
04287   {
04288     pStubMsg->BufferLength = pStubMsg->PointerLength;
04289     pStubMsg->PointerLength = 0;
04290   }
04291 }
04292 
04293 /***********************************************************************
04294  *           NdrComplexArrayMemorySize [RPCRT4.@]
04295  */
04296 ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
04297                                        PFORMAT_STRING pFormat)
04298 {
04299   TRACE("(%p,%p)\n", pStubMsg, pFormat);
04300 
04301   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
04302   {
04303       ERR("invalid format type %x\n", pFormat[0]);
04304       RpcRaiseException(RPC_S_INTERNAL_ERROR);
04305       return 0;
04306   }
04307 
04308   array_read_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat);
04309   array_memory_size(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */);
04310   return pStubMsg->MemorySize;
04311 }
04312 
04313 /***********************************************************************
04314  *           NdrComplexArrayFree [RPCRT4.@]
04315  */
04316 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
04317                                 unsigned char *pMemory,
04318                                 PFORMAT_STRING pFormat)
04319 {
04320   ULONG i, count, def;
04321 
04322   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
04323 
04324   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
04325   {
04326       ERR("invalid format type %x\n", pFormat[0]);
04327       RpcRaiseException(RPC_S_INTERNAL_ERROR);
04328       return;
04329   }
04330 
04331   def = *(const WORD*)&pFormat[2];
04332   pFormat += 4;
04333 
04334   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
04335   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
04336 
04337   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
04338   TRACE("variance = %d\n", pStubMsg->ActualCount);
04339 
04340   count = pStubMsg->ActualCount;
04341   for (i = 0; i < count; i++)
04342     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
04343 }
04344 
04345 static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg,
04346                           USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat,
04347                           USER_MARSHAL_CB *umcb)
04348 {
04349   umcb->Flags = MAKELONG(pStubMsg->dwDestContext,
04350                          pStubMsg->RpcMsg->DataRepresentation);
04351   umcb->pStubMsg = pStubMsg;
04352   umcb->pReserve = NULL;
04353   umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
04354   umcb->CBType = cbtype;
04355   umcb->pFormat = pFormat;
04356   umcb->pTypeFormat = NULL /* FIXME */;
04357 }
04358 
04359 #define USER_MARSHAL_PTR_PREFIX \
04360         ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
04361         ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
04362 
04363 /***********************************************************************
04364  *           NdrUserMarshalMarshall [RPCRT4.@]
04365  */
04366 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
04367                                               unsigned char *pMemory,
04368                                               PFORMAT_STRING pFormat)
04369 {
04370   unsigned flags = pFormat[1];
04371   unsigned index = *(const WORD*)&pFormat[2];
04372   unsigned char *saved_buffer = NULL;
04373   USER_MARSHAL_CB umcb;
04374 
04375   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
04376   TRACE("index=%d\n", index);
04377 
04378   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb);
04379 
04380   if (flags & USER_MARSHAL_POINTER)
04381   {
04382     align_pointer_clear(&pStubMsg->Buffer, 4);
04383     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
04384     pStubMsg->Buffer += 4;
04385     if (pStubMsg->PointerBufferMark)
04386     {
04387       saved_buffer = pStubMsg->Buffer;
04388       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
04389       pStubMsg->PointerBufferMark = NULL;
04390     }
04391     align_pointer_clear(&pStubMsg->Buffer, 8);
04392   }
04393   else
04394     align_pointer_clear(&pStubMsg->Buffer, (flags & 0xf) + 1);
04395 
04396   pStubMsg->Buffer =
04397     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
04398       &umcb.Flags, pStubMsg->Buffer, pMemory);
04399 
04400   if (saved_buffer)
04401   {
04402     STD_OVERFLOW_CHECK(pStubMsg);
04403     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
04404     pStubMsg->Buffer = saved_buffer;
04405   }
04406 
04407   STD_OVERFLOW_CHECK(pStubMsg);
04408 
04409   return NULL;
04410 }
04411 
04412 /***********************************************************************
04413  *           NdrUserMarshalUnmarshall [RPCRT4.@]
04414  */
04415 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
04416                                                  unsigned char **ppMemory,
04417                                                  PFORMAT_STRING pFormat,
04418                                                  unsigned char fMustAlloc)
04419 {
04420   unsigned flags = pFormat[1];
04421   unsigned index = *(const WORD*)&pFormat[2];
04422   DWORD memsize = *(const WORD*)&pFormat[4];
04423   unsigned char *saved_buffer = NULL;
04424   USER_MARSHAL_CB umcb;
04425 
04426   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
04427   TRACE("index=%d\n", index);
04428 
04429   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb);
04430 
04431   if (flags & USER_MARSHAL_POINTER)
04432   {
04433     align_pointer(&pStubMsg->Buffer, 4);
04434     /* skip pointer prefix */
04435     pStubMsg->Buffer += 4;
04436     if (pStubMsg->PointerBufferMark)
04437     {
04438       saved_buffer = pStubMsg->Buffer;
04439       pStubMsg->Buffer = pStubMsg->PointerBufferMark;
04440       pStubMsg->PointerBufferMark = NULL;
04441     }
04442     align_pointer(&pStubMsg->Buffer, 8);
04443   }
04444   else
04445     align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1);
04446 
04447   if (!fMustAlloc && !*ppMemory)
04448     fMustAlloc = TRUE;
04449   if (fMustAlloc)
04450   {
04451     *ppMemory = NdrAllocate(pStubMsg, memsize);
04452     memset(*ppMemory, 0, memsize);
04453   }
04454 
04455   pStubMsg->Buffer =
04456     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
04457       &umcb.Flags, pStubMsg->Buffer, *ppMemory);
04458 
04459   if (saved_buffer)
04460   {
04461     STD_OVERFLOW_CHECK(pStubMsg);
04462     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
04463     pStubMsg->Buffer = saved_buffer;
04464   }
04465 
04466   return NULL;
04467 }
04468 
04469 /***********************************************************************
04470  *           NdrUserMarshalBufferSize [RPCRT4.@]
04471  */
04472 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
04473                                       unsigned char *pMemory,
04474                                       PFORMAT_STRING pFormat)
04475 {
04476   unsigned flags = pFormat[1];
04477   unsigned index = *(const WORD*)&pFormat[2];
04478   DWORD bufsize = *(const WORD*)&pFormat[6];
04479   USER_MARSHAL_CB umcb;
04480   ULONG saved_buffer_length = 0;
04481 
04482   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
04483   TRACE("index=%d\n", index);
04484 
04485   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb);
04486 
04487   if (flags & USER_MARSHAL_POINTER)
04488   {
04489     align_length(&pStubMsg->BufferLength, 4);
04490     /* skip pointer prefix */
04491     safe_buffer_length_increment(pStubMsg, 4);
04492     if (pStubMsg->IgnoreEmbeddedPointers)
04493       return;
04494     if (pStubMsg->PointerLength)
04495     {
04496       saved_buffer_length = pStubMsg->BufferLength;
04497       pStubMsg->BufferLength = pStubMsg->PointerLength;
04498       pStubMsg->PointerLength = 0;
04499     }
04500     align_length(&pStubMsg->BufferLength, 8);
04501   }
04502   else
04503     align_length(&pStubMsg->BufferLength, (flags & 0xf) + 1);
04504 
04505   if (bufsize) {
04506     TRACE("size=%d\n", bufsize);
04507     safe_buffer_length_increment(pStubMsg, bufsize);
04508   }
04509   else
04510     pStubMsg->BufferLength =
04511         pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
04512                              &umcb.Flags, pStubMsg->BufferLength, pMemory);
04513 
04514   if (saved_buffer_length)
04515   {
04516     pStubMsg->PointerLength = pStubMsg->BufferLength;
04517     pStubMsg->BufferLength = saved_buffer_length;
04518   }
04519 
04520 }
04521 
04522 /***********************************************************************
04523  *           NdrUserMarshalMemorySize [RPCRT4.@]
04524  */
04525 ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
04526                                       PFORMAT_STRING pFormat)
04527 {
04528   unsigned flags = pFormat[1];
04529   unsigned index = *(const WORD*)&pFormat[2];
04530   DWORD memsize = *(const WORD*)&pFormat[4];
04531   DWORD bufsize = *(const WORD*)&pFormat[6];
04532 
04533   TRACE("(%p,%p)\n", pStubMsg, pFormat);
04534   TRACE("index=%d\n", index);
04535 
04536   pStubMsg->MemorySize += memsize;
04537 
04538   if (flags & USER_MARSHAL_POINTER)
04539   {
04540     align_pointer(&pStubMsg->Buffer, 4);
04541     /* skip pointer prefix */
04542     pStubMsg->Buffer += 4;
04543     if (pStubMsg->IgnoreEmbeddedPointers)
04544       return pStubMsg->MemorySize;
04545     align_pointer(&pStubMsg->Buffer, 8);
04546   }
04547   else
04548     align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1);
04549 
04550   if (!bufsize)
04551     FIXME("not implemented for varying buffer size\n");
04552 
04553   pStubMsg->Buffer += bufsize;
04554 
04555   return pStubMsg->MemorySize;
04556 }
04557 
04558 /***********************************************************************
04559  *           NdrUserMarshalFree [RPCRT4.@]
04560  */
04561 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
04562                                 unsigned char *pMemory,
04563                                 PFORMAT_STRING pFormat)
04564 {
04565 /*  unsigned flags = pFormat[1]; */
04566   unsigned index = *(const WORD*)&pFormat[2];
04567   USER_MARSHAL_CB umcb;
04568 
04569   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
04570   TRACE("index=%d\n", index);
04571 
04572   UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb);
04573 
04574   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
04575     &umcb.Flags, pMemory);
04576 }
04577 
04578 /***********************************************************************
04579  *           NdrGetUserMarshalInfo [RPCRT4.@]
04580  */
04581 RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi)
04582 {
04583     USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags);
04584 
04585     TRACE("(%p,%u,%p)\n", flags, level, umi);
04586 
04587     if (level != 1)
04588         return RPC_S_INVALID_ARG;
04589 
04590     memset(&umi->u1.Level1, 0, sizeof(umi->u1.Level1));
04591     umi->InformationLevel = level;
04592 
04593     if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE)
04594         return RPC_S_INVALID_ARG;
04595 
04596     umi->u1.Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate;
04597     umi->u1.Level1.pfnFree = umcb->pStubMsg->pfnFree;
04598     umi->u1.Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer;
04599 
04600     switch (umcb->CBType)
04601     {
04602     case USER_MARSHAL_CB_MARSHALL:
04603     case USER_MARSHAL_CB_UNMARSHALL:
04604     {
04605         RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg;
04606         unsigned char *buffer_start = msg->Buffer;
04607         unsigned char *buffer_end =
04608             (unsigned char *)msg->Buffer + msg->BufferLength;
04609 
04610         if (umcb->pStubMsg->Buffer < buffer_start ||
04611             umcb->pStubMsg->Buffer > buffer_end)
04612             return ERROR_INVALID_USER_BUFFER;
04613 
04614         umi->u1.Level1.Buffer = umcb->pStubMsg->Buffer;
04615         umi->u1.Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer;
04616         break;
04617     }
04618     case USER_MARSHAL_CB_BUFFER_SIZE:
04619     case USER_MARSHAL_CB_FREE:
04620         break;
04621     default:
04622         WARN("unrecognised CBType %d\n", umcb->CBType);
04623     }
04624 
04625     return RPC_S_OK;
04626 }
04627 
04628 /***********************************************************************
04629  *           NdrClearOutParameters [RPCRT4.@]
04630  */
04631 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
04632                                   PFORMAT_STRING pFormat,
04633                                   void *ArgAddr)
04634 {
04635   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
04636 }
04637 
04638 /***********************************************************************
04639  *           NdrConvert [RPCRT4.@]
04640  */
04641 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
04642 {
04643   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
04644   /* FIXME: since this stub doesn't do any converting, the proper behavior
04645      is to raise an exception */
04646 }
04647 
04648 /***********************************************************************
04649  *           NdrConvert2 [RPCRT4.@]
04650  */
04651 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams )
04652 {
04653   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n",
04654     pStubMsg, pFormat, NumberParams);
04655   /* FIXME: since this stub doesn't do any converting, the proper behavior
04656      is to raise an exception */
04657 }
04658 
04659 #include "pshpack1.h"
04660 typedef struct _NDR_CSTRUCT_FORMAT
04661 {
04662     unsigned char type;
04663     unsigned char alignment;
04664     unsigned short memory_size;
04665     short offset_to_array_description;
04666 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
04667 #include "poppack.h"
04668 
04669 /***********************************************************************
04670  *           NdrConformantStructMarshall [RPCRT4.@]
04671  */
04672 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
04673                                 unsigned char *pMemory,
04674                                 PFORMAT_STRING pFormat)
04675 {
04676     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
04677     PFORMAT_STRING pCArrayFormat;
04678     ULONG esize, bufsize;
04679 
04680     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
04681 
04682     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
04683     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
04684     {
04685         ERR("invalid format type %x\n", pCStructFormat->type);
04686         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04687         return NULL;
04688     }
04689 
04690     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
04691         pCStructFormat->offset_to_array_description;
04692     if (*pCArrayFormat != RPC_FC_CARRAY)
04693     {
04694         ERR("invalid array format type %x\n", pCStructFormat->type);
04695         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04696         return NULL;
04697     }
04698     esize = *(const WORD*)(pCArrayFormat+2);
04699 
04700     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
04701                        pCArrayFormat + 4, 0);
04702 
04703     WriteConformance(pStubMsg);
04704 
04705     align_pointer_clear(&pStubMsg->Buffer, pCStructFormat->alignment + 1);
04706 
04707     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
04708 
04709     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
04710     if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
04711     {
04712         ERR("integer overflow of memory_size %u with bufsize %u\n",
04713             pCStructFormat->memory_size, bufsize);
04714         RpcRaiseException(RPC_X_BAD_STUB_DATA);
04715     }
04716     /* copy constant sized part of struct */
04717     pStubMsg->BufferMark = pStubMsg->Buffer;
04718     safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize);
04719 
04720     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
04721         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
04722 
04723     return NULL;
04724 }
04725 
04726 /***********************************************************************
04727  *           NdrConformantStructUnmarshall [RPCRT4.@]
04728  */
04729 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
04730                                 unsigned char **ppMemory,
04731                                 PFORMAT_STRING pFormat,
04732                                 unsigned char fMustAlloc)
04733 {
04734     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
04735     PFORMAT_STRING pCArrayFormat;
04736     ULONG esize, bufsize;
04737     unsigned char *saved_buffer;
04738 
04739     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
04740 
04741     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
04742     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
04743     {
04744         ERR("invalid format type %x\n", pCStructFormat->type);
04745         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04746         return NULL;
04747     }
04748     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
04749         pCStructFormat->offset_to_array_description;
04750     if (*pCArrayFormat != RPC_FC_CARRAY)
04751     {
04752         ERR("invalid array format type %x\n", pCStructFormat->type);
04753         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04754         return NULL;
04755     }
04756     esize = *(const WORD*)(pCArrayFormat+2);
04757 
04758     pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
04759 
04760     align_pointer(&pStubMsg->Buffer, pCStructFormat->alignment + 1);
04761 
04762     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
04763 
04764     bufsize = safe_multiply(esize, pStubMsg->MaxCount);
04765     if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */
04766     {
04767         ERR("integer overflow of memory_size %u with bufsize %u\n",
04768             pCStructFormat->memory_size, bufsize);
04769         RpcRaiseException(RPC_X_BAD_STUB_DATA);
04770     }
04771 
04772     if (fMustAlloc)
04773     {
04774         SIZE_T size = pCStructFormat->memory_size + bufsize;
04775         *ppMemory = NdrAllocate(pStubMsg, size);
04776     }
04777     else
04778     {
04779         if (!pStubMsg->IsClient && !*ppMemory)
04780             /* for servers, we just point straight into the RPC buffer */
04781             *ppMemory = pStubMsg->Buffer;
04782     }
04783 
04784     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
04785     safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize);
04786     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
04787         EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
04788 
04789     TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
04790     if (*ppMemory != saved_buffer)
04791         memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize);
04792 
04793     return NULL;
04794 }
04795 
04796 /***********************************************************************
04797  *           NdrConformantStructBufferSize [RPCRT4.@]
04798  */
04799 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
04800                                 unsigned char *pMemory,
04801                                 PFORMAT_STRING pFormat)
04802 {
04803     const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
04804     PFORMAT_STRING pCArrayFormat;
04805     ULONG esize;
04806 
04807     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
04808 
04809     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
04810     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
04811     {
04812         ERR("invalid format type %x\n", pCStructFormat->type);
04813         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04814         return;
04815     }
04816     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
04817         pCStructFormat->offset_to_array_description;
04818     if (*pCArrayFormat != RPC_FC_CARRAY)
04819     {
04820         ERR("invalid array format type %x\n", pCStructFormat->type);
04821         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04822         return;
04823     }
04824     esize = *(const WORD*)(pCArrayFormat+2);
04825 
04826     pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
04827     SizeConformance(pStubMsg);
04828 
04829     align_length(&pStubMsg->BufferLength, pCStructFormat->alignment + 1);
04830 
04831     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
04832 
04833     safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size);
04834     safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize));
04835 
04836     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
04837         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
04838 }
04839 
04840 /***********************************************************************
04841  *           NdrConformantStructMemorySize [RPCRT4.@]
04842  */
04843 ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
04844                                 PFORMAT_STRING pFormat)
04845 {
04846     FIXME("stub\n");
04847     return 0;
04848 }
04849 
04850 /***********************************************************************
04851  *           NdrConformantStructFree [RPCRT4.@]
04852  */
04853 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
04854                                 unsigned char *pMemory,
04855                                 PFORMAT_STRING pFormat)
04856 {
04857     const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat;
04858     PFORMAT_STRING pCArrayFormat;
04859 
04860     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
04861 
04862     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
04863     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
04864     {
04865         ERR("invalid format type %x\n", pCStructFormat->type);
04866         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04867         return;
04868     }
04869 
04870     pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description +
04871         pCStructFormat->offset_to_array_description;
04872     if (*pCArrayFormat != RPC_FC_CARRAY)
04873     {
04874         ERR("invalid array format type %x\n", pCStructFormat->type);
04875         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04876         return;
04877     }
04878 
04879     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
04880                        pCArrayFormat + 4, 0);
04881 
04882     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
04883 
04884     /* copy constant sized part of struct */
04885     pStubMsg->BufferMark = pStubMsg->Buffer;
04886 
04887     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
04888         EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
04889 }
04890 
04891 /***********************************************************************
04892  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
04893  */
04894 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
04895                                 unsigned char *pMemory,
04896                                 PFORMAT_STRING pFormat)
04897 {
04898     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
04899     PFORMAT_STRING pCVArrayFormat;
04900 
04901     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
04902 
04903     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
04904     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
04905     {
04906         ERR("invalid format type %x\n", pCVStructFormat->type);
04907         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04908         return NULL;
04909     }
04910 
04911     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
04912         pCVStructFormat->offset_to_array_description;
04913 
04914     array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg,
04915                                         pMemory + pCVStructFormat->memory_size,
04916                                         pCVArrayFormat);
04917 
04918     align_pointer_clear(&pStubMsg->Buffer, pCVStructFormat->alignment + 1);
04919 
04920     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
04921 
04922     /* write constant sized part */
04923     pStubMsg->BufferMark = pStubMsg->Buffer;
04924     safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size);
04925 
04926     array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg,
04927                                       pMemory + pCVStructFormat->memory_size,
04928                                       pCVArrayFormat, FALSE /* fHasPointers */);
04929 
04930     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
04931 
04932     return NULL;
04933 }
04934 
04935 /***********************************************************************
04936  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
04937  */
04938 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
04939                                 unsigned char **ppMemory,
04940                                 PFORMAT_STRING pFormat,
04941                                 unsigned char fMustAlloc)
04942 {
04943     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
04944     PFORMAT_STRING pCVArrayFormat;
04945     ULONG memsize, bufsize;
04946     unsigned char *saved_buffer, *saved_array_buffer;
04947     ULONG offset;
04948     unsigned char *array_memory;
04949 
04950     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
04951 
04952     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
04953     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
04954     {
04955         ERR("invalid format type %x\n", pCVStructFormat->type);
04956         RpcRaiseException(RPC_S_INTERNAL_ERROR);
04957         return NULL;
04958     }
04959 
04960     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
04961         pCVStructFormat->offset_to_array_description;
04962 
04963     memsize = array_read_conformance(*pCVArrayFormat, pStubMsg,
04964                                      pCVArrayFormat);
04965 
04966     align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1);
04967 
04968     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
04969 
04970     /* work out how much memory to allocate if we need to do so */
04971     if (!fMustAlloc && !*ppMemory)
04972         fMustAlloc = TRUE;
04973     if (fMustAlloc)
04974     {
04975         SIZE_T size = pCVStructFormat->memory_size + memsize;
04976         *ppMemory = NdrAllocate(pStubMsg, size);
04977     }
04978 
04979     /* mark the start of the constant data */
04980     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
04981     safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
04982 
04983     array_memory = *ppMemory + pCVStructFormat->memory_size;
04984     bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg,
04985                                                  &array_memory, pCVArrayFormat,
04986                                                  FALSE /* fMustAlloc */,
04987                                                  FALSE /* fUseServerBufferMemory */,
04988                                                  FALSE /* fUnmarshall */);
04989 
04990     /* save offset in case unmarshalling pointers changes it */
04991     offset = pStubMsg->Offset;
04992 
04993     /* mark the start of the array data */
04994     saved_array_buffer = pStubMsg->Buffer;
04995     safe_buffer_increment(pStubMsg, bufsize);
04996 
04997     EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
04998 
04999     /* copy the constant data */
05000     memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size);
05001     /* copy the array data */
05002     TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size);
05003     memcpy(*ppMemory + pCVStructFormat->memory_size + offset,
05004            saved_array_buffer, bufsize);
05005 
05006     if (*pCVArrayFormat == RPC_FC_C_CSTRING)
05007         TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
05008     else if (*pCVArrayFormat == RPC_FC_C_WSTRING)
05009         TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
05010 
05011     return NULL;
05012 }
05013 
05014 /***********************************************************************
05015  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
05016  */
05017 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
05018                                 unsigned char *pMemory,
05019                                 PFORMAT_STRING pFormat)
05020 {
05021     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
05022     PFORMAT_STRING pCVArrayFormat;
05023 
05024     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
05025 
05026     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
05027     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
05028     {
05029         ERR("invalid format type %x\n", pCVStructFormat->type);
05030         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05031         return;
05032     }
05033 
05034     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
05035         pCVStructFormat->offset_to_array_description;
05036     array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg,
05037                                        pMemory + pCVStructFormat->memory_size,
05038                                        pCVArrayFormat);
05039 
05040     align_length(&pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
05041 
05042     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
05043 
05044     safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size);
05045 
05046     array_buffer_size(*pCVArrayFormat, pStubMsg,
05047                       pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
05048                       FALSE /* fHasPointers */);
05049 
05050     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
05051 }
05052 
05053 /***********************************************************************
05054  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
05055  */
05056 ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
05057                                 PFORMAT_STRING pFormat)
05058 {
05059     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
05060     PFORMAT_STRING pCVArrayFormat;
05061 
05062     TRACE("(%p, %p)\n", pStubMsg, pFormat);
05063 
05064     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
05065     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
05066     {
05067         ERR("invalid format type %x\n", pCVStructFormat->type);
05068         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05069         return 0;
05070     }
05071 
05072     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
05073         pCVStructFormat->offset_to_array_description;
05074     array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat);
05075 
05076     align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1);
05077 
05078     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
05079 
05080     safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size);
05081     array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat,
05082                       FALSE /* fHasPointers */);
05083 
05084     pStubMsg->MemorySize += pCVStructFormat->memory_size;
05085 
05086     EmbeddedPointerMemorySize(pStubMsg, pFormat);
05087 
05088     return pStubMsg->MemorySize;
05089 }
05090 
05091 /***********************************************************************
05092  *           NdrConformantVaryingStructFree [RPCRT4.@]
05093  */
05094 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
05095                                 unsigned char *pMemory,
05096                                 PFORMAT_STRING pFormat)
05097 {
05098     const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat;
05099     PFORMAT_STRING pCVArrayFormat;
05100 
05101     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
05102 
05103     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
05104     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
05105     {
05106         ERR("invalid format type %x\n", pCVStructFormat->type);
05107         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05108         return;
05109     }
05110 
05111     pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description +
05112         pCVStructFormat->offset_to_array_description;
05113     array_free(*pCVArrayFormat, pStubMsg,
05114                pMemory + pCVStructFormat->memory_size, pCVArrayFormat,
05115                FALSE /* fHasPointers */);
05116 
05117     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
05118 
05119     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
05120 }
05121 
05122 #include "pshpack1.h"
05123 typedef struct
05124 {
05125     unsigned char type;
05126     unsigned char alignment;
05127     unsigned short total_size;
05128 } NDR_SMFARRAY_FORMAT;
05129 
05130 typedef struct
05131 {
05132     unsigned char type;
05133     unsigned char alignment;
05134     ULONG total_size;
05135 } NDR_LGFARRAY_FORMAT;
05136 #include "poppack.h"
05137 
05138 /***********************************************************************
05139  *           NdrFixedArrayMarshall [RPCRT4.@]
05140  */
05141 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
05142                                 unsigned char *pMemory,
05143                                 PFORMAT_STRING pFormat)
05144 {
05145     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
05146     ULONG total_size;
05147 
05148     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
05149 
05150     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
05151         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
05152     {
05153         ERR("invalid format type %x\n", pSmFArrayFormat->type);
05154         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05155         return NULL;
05156     }
05157 
05158     align_pointer_clear(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
05159 
05160     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
05161     {
05162         total_size = pSmFArrayFormat->total_size;
05163         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
05164     }
05165     else
05166     {
05167         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
05168         total_size = pLgFArrayFormat->total_size;
05169         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
05170     }
05171 
05172     pStubMsg->BufferMark = pStubMsg->Buffer;
05173     safe_copy_to_buffer(pStubMsg, pMemory, total_size);
05174 
05175     pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
05176 
05177     return NULL;
05178 }
05179 
05180 /***********************************************************************
05181  *           NdrFixedArrayUnmarshall [RPCRT4.@]
05182  */
05183 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
05184                                 unsigned char **ppMemory,
05185                                 PFORMAT_STRING pFormat,
05186                                 unsigned char fMustAlloc)
05187 {
05188     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
05189     ULONG total_size;
05190     unsigned char *saved_buffer;
05191 
05192     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
05193 
05194     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
05195         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
05196     {
05197         ERR("invalid format type %x\n", pSmFArrayFormat->type);
05198         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05199         return NULL;
05200     }
05201 
05202     align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
05203 
05204     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
05205     {
05206         total_size = pSmFArrayFormat->total_size;
05207         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
05208     }
05209     else
05210     {
05211         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
05212         total_size = pLgFArrayFormat->total_size;
05213         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
05214     }
05215 
05216     if (fMustAlloc)
05217         *ppMemory = NdrAllocate(pStubMsg, total_size);
05218     else
05219     {
05220         if (!pStubMsg->IsClient && !*ppMemory)
05221             /* for servers, we just point straight into the RPC buffer */
05222             *ppMemory = pStubMsg->Buffer;
05223     }
05224 
05225     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
05226     safe_buffer_increment(pStubMsg, total_size);
05227     pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
05228 
05229     TRACE("copying %p to %p\n", saved_buffer, *ppMemory);
05230     if (*ppMemory != saved_buffer)
05231         memcpy(*ppMemory, saved_buffer, total_size);
05232 
05233     return NULL;
05234 }
05235 
05236 /***********************************************************************
05237  *           NdrFixedArrayBufferSize [RPCRT4.@]
05238  */
05239 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
05240                                 unsigned char *pMemory,
05241                                 PFORMAT_STRING pFormat)
05242 {
05243     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
05244     ULONG total_size;
05245 
05246     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
05247 
05248     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
05249         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
05250     {
05251         ERR("invalid format type %x\n", pSmFArrayFormat->type);
05252         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05253         return;
05254     }
05255 
05256     align_length(&pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
05257 
05258     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
05259     {
05260         total_size = pSmFArrayFormat->total_size;
05261         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
05262     }
05263     else
05264     {
05265         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
05266         total_size = pLgFArrayFormat->total_size;
05267         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
05268     }
05269     safe_buffer_length_increment(pStubMsg, total_size);
05270 
05271     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
05272 }
05273 
05274 /***********************************************************************
05275  *           NdrFixedArrayMemorySize [RPCRT4.@]
05276  */
05277 ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
05278                                 PFORMAT_STRING pFormat)
05279 {
05280     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
05281     ULONG total_size;
05282 
05283     TRACE("(%p, %p)\n", pStubMsg, pFormat);
05284 
05285     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
05286         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
05287     {
05288         ERR("invalid format type %x\n", pSmFArrayFormat->type);
05289         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05290         return 0;
05291     }
05292 
05293     align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
05294 
05295     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
05296     {
05297         total_size = pSmFArrayFormat->total_size;
05298         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
05299     }
05300     else
05301     {
05302         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
05303         total_size = pLgFArrayFormat->total_size;
05304         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
05305     }
05306     pStubMsg->BufferMark = pStubMsg->Buffer;
05307     safe_buffer_increment(pStubMsg, total_size);
05308     pStubMsg->MemorySize += total_size;
05309 
05310     EmbeddedPointerMemorySize(pStubMsg, pFormat);
05311 
05312     return total_size;
05313 }
05314 
05315 /***********************************************************************
05316  *           NdrFixedArrayFree [RPCRT4.@]
05317  */
05318 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
05319                                 unsigned char *pMemory,
05320                                 PFORMAT_STRING pFormat)
05321 {
05322     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
05323 
05324     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
05325 
05326     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
05327         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
05328     {
05329         ERR("invalid format type %x\n", pSmFArrayFormat->type);
05330         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05331         return;
05332     }
05333 
05334     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
05335         pFormat = (const unsigned char *)(pSmFArrayFormat + 1);
05336     else
05337     {
05338         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
05339         pFormat = (const unsigned char *)(pLgFArrayFormat + 1);
05340     }
05341 
05342     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
05343 }
05344 
05345 /***********************************************************************
05346  *           NdrVaryingArrayMarshall [RPCRT4.@]
05347  */
05348 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
05349                                 unsigned char *pMemory,
05350                                 PFORMAT_STRING pFormat)
05351 {
05352     unsigned char alignment;
05353     DWORD elements, esize;
05354     ULONG bufsize;
05355 
05356     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
05357 
05358     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
05359         (pFormat[0] != RPC_FC_LGVARRAY))
05360     {
05361         ERR("invalid format type %x\n", pFormat[0]);
05362         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05363         return NULL;
05364     }
05365 
05366     alignment = pFormat[1] + 1;
05367 
05368     if (pFormat[0] == RPC_FC_SMVARRAY)
05369     {
05370         pFormat += 2;
05371         pFormat += sizeof(WORD);
05372         elements = *(const WORD*)pFormat;
05373         pFormat += sizeof(WORD);
05374     }
05375     else
05376     {
05377         pFormat += 2;
05378         pFormat += sizeof(DWORD);
05379         elements = *(const DWORD*)pFormat;
05380         pFormat += sizeof(DWORD);
05381     }
05382 
05383     esize = *(const WORD*)pFormat;
05384     pFormat += sizeof(WORD);
05385 
05386     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
05387     if ((pStubMsg->ActualCount > elements) ||
05388         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
05389     {
05390         RpcRaiseException(RPC_S_INVALID_BOUND);
05391         return NULL;
05392     }
05393 
05394     WriteVariance(pStubMsg);
05395 
05396     align_pointer_clear(&pStubMsg->Buffer, alignment);
05397 
05398     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
05399     pStubMsg->BufferMark = pStubMsg->Buffer;
05400     safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize);
05401 
05402     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
05403 
05404     return NULL;
05405 }
05406 
05407 /***********************************************************************
05408  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
05409  */
05410 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
05411                                 unsigned char **ppMemory,
05412                                 PFORMAT_STRING pFormat,
05413                                 unsigned char fMustAlloc)
05414 {
05415     unsigned char alignment;
05416     DWORD size, elements, esize;
05417     ULONG bufsize;
05418     unsigned char *saved_buffer;
05419     ULONG offset;
05420 
05421     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
05422 
05423     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
05424         (pFormat[0] != RPC_FC_LGVARRAY))
05425     {
05426         ERR("invalid format type %x\n", pFormat[0]);
05427         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05428         return NULL;
05429     }
05430 
05431     alignment = pFormat[1] + 1;
05432 
05433     if (pFormat[0] == RPC_FC_SMVARRAY)
05434     {
05435         pFormat += 2;
05436         size = *(const WORD*)pFormat;
05437         pFormat += sizeof(WORD);
05438         elements = *(const WORD*)pFormat;
05439         pFormat += sizeof(WORD);
05440     }
05441     else
05442     {
05443         pFormat += 2;
05444         size = *(const DWORD*)pFormat;
05445         pFormat += sizeof(DWORD);
05446         elements = *(const DWORD*)pFormat;
05447         pFormat += sizeof(DWORD);
05448     }
05449 
05450     esize = *(const WORD*)pFormat;
05451     pFormat += sizeof(WORD);
05452 
05453     pFormat = ReadVariance(pStubMsg, pFormat, elements);
05454 
05455     align_pointer(&pStubMsg->Buffer, alignment);
05456 
05457     bufsize = safe_multiply(esize, pStubMsg->ActualCount);
05458     offset = pStubMsg->Offset;
05459 
05460     if (!fMustAlloc && !*ppMemory)
05461         fMustAlloc = TRUE;
05462     if (fMustAlloc)
05463         *ppMemory = NdrAllocate(pStubMsg, size);
05464     saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer;
05465     safe_buffer_increment(pStubMsg, bufsize);
05466 
05467     EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc);
05468 
05469     memcpy(*ppMemory + offset, saved_buffer, bufsize);
05470 
05471     return NULL;
05472 }
05473 
05474 /***********************************************************************
05475  *           NdrVaryingArrayBufferSize [RPCRT4.@]
05476  */
05477 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
05478                                 unsigned char *pMemory,
05479                                 PFORMAT_STRING pFormat)
05480 {
05481     unsigned char alignment;
05482     DWORD elements, esize;
05483 
05484     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
05485 
05486     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
05487         (pFormat[0] != RPC_FC_LGVARRAY))
05488     {
05489         ERR("invalid format type %x\n", pFormat[0]);
05490         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05491         return;
05492     }
05493 
05494     alignment = pFormat[1] + 1;
05495 
05496     if (pFormat[0] == RPC_FC_SMVARRAY)
05497     {
05498         pFormat += 2;
05499         pFormat += sizeof(WORD);
05500         elements = *(const WORD*)pFormat;
05501         pFormat += sizeof(WORD);
05502     }
05503     else
05504     {
05505         pFormat += 2;
05506         pFormat += sizeof(DWORD);
05507         elements = *(const DWORD*)pFormat;
05508         pFormat += sizeof(DWORD);
05509     }
05510 
05511     esize = *(const WORD*)pFormat;
05512     pFormat += sizeof(WORD);
05513 
05514     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
05515     if ((pStubMsg->ActualCount > elements) ||
05516         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
05517     {
05518         RpcRaiseException(RPC_S_INVALID_BOUND);
05519         return;
05520     }
05521 
05522     SizeVariance(pStubMsg);
05523 
05524     align_length(&pStubMsg->BufferLength, alignment);
05525 
05526     safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
05527 
05528     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
05529 }
05530 
05531 /***********************************************************************
05532  *           NdrVaryingArrayMemorySize [RPCRT4.@]
05533  */
05534 ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
05535                                 PFORMAT_STRING pFormat)
05536 {
05537     unsigned char alignment;
05538     DWORD size, elements, esize;
05539 
05540     TRACE("(%p, %p)\n", pStubMsg, pFormat);
05541 
05542     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
05543         (pFormat[0] != RPC_FC_LGVARRAY))
05544     {
05545         ERR("invalid format type %x\n", pFormat[0]);
05546         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05547         return 0;
05548     }
05549 
05550     alignment = pFormat[1] + 1;
05551 
05552     if (pFormat[0] == RPC_FC_SMVARRAY)
05553     {
05554         pFormat += 2;
05555         size = *(const WORD*)pFormat;
05556         pFormat += sizeof(WORD);
05557         elements = *(const WORD*)pFormat;
05558         pFormat += sizeof(WORD);
05559     }
05560     else
05561     {
05562         pFormat += 2;
05563         size = *(const DWORD*)pFormat;
05564         pFormat += sizeof(DWORD);
05565         elements = *(const DWORD*)pFormat;
05566         pFormat += sizeof(DWORD);
05567     }
05568 
05569     esize = *(const WORD*)pFormat;
05570     pFormat += sizeof(WORD);
05571 
05572     pFormat = ReadVariance(pStubMsg, pFormat, elements);
05573 
05574     align_pointer(&pStubMsg->Buffer, alignment);
05575 
05576     safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount));
05577     pStubMsg->MemorySize += size;
05578 
05579     EmbeddedPointerMemorySize(pStubMsg, pFormat);
05580 
05581     return pStubMsg->MemorySize;
05582 }
05583 
05584 /***********************************************************************
05585  *           NdrVaryingArrayFree [RPCRT4.@]
05586  */
05587 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
05588                                 unsigned char *pMemory,
05589                                 PFORMAT_STRING pFormat)
05590 {
05591     DWORD elements;
05592 
05593     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
05594 
05595     if ((pFormat[0] != RPC_FC_SMVARRAY) &&
05596         (pFormat[0] != RPC_FC_LGVARRAY))
05597     {
05598         ERR("invalid format type %x\n", pFormat[0]);
05599         RpcRaiseException(RPC_S_INTERNAL_ERROR);
05600         return;
05601     }
05602 
05603     if (pFormat[0] == RPC_FC_SMVARRAY)
05604     {
05605         pFormat += 2;
05606         pFormat += sizeof(WORD);
05607         elements = *(const WORD*)pFormat;
05608         pFormat += sizeof(WORD);
05609     }
05610     else
05611     {
05612         pFormat += 2;
05613         pFormat += sizeof(DWORD);
05614         elements = *(const DWORD*)pFormat;
05615         pFormat += sizeof(DWORD);
05616     }
05617 
05618     pFormat += sizeof(WORD);
05619 
05620     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
05621     if ((pStubMsg->ActualCount > elements) ||
05622         (pStubMsg->ActualCount + pStubMsg->Offset > elements))
05623     {
05624         RpcRaiseException(RPC_S_INVALID_BOUND);
05625         return;
05626     }
05627 
05628     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
05629 }
05630 
05631 static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
05632 {
05633     switch (fc)
05634     {
05635     case RPC_FC_BYTE:
05636     case RPC_FC_CHAR:
05637     case RPC_FC_SMALL:
05638     case RPC_FC_USMALL:
05639         return *pMemory;
05640     case RPC_FC_WCHAR:
05641     case RPC_FC_SHORT:
05642     case RPC_FC_USHORT:
05643     case RPC_FC_ENUM16:
05644         return *(const USHORT *)pMemory;
05645     case RPC_FC_LONG:
05646     case RPC_FC_ULONG:
05647     case RPC_FC_ENUM32:
05648         return *(const ULONG *)pMemory;
05649     case RPC_FC_INT3264:
05650     case RPC_FC_UINT3264:
05651         return *(const ULONG_PTR *)pMemory;
05652     default:
05653         FIXME("Unhandled base type: 0x%02x\n", fc);
05654         return 0;
05655     }
05656 }
05657 
05658 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
05659                                                              ULONG discriminant,
05660                                                              PFORMAT_STRING pFormat)
05661 {
05662     unsigned short num_arms, arm, type;
05663 
05664     num_arms = *(const SHORT*)pFormat & 0x0fff;
05665     pFormat += 2;
05666     for(arm = 0; arm < num_arms; arm++)
05667     {
05668         if(discriminant == *(const ULONG*)pFormat)
05669         {
05670             pFormat += 4;
05671             break;
05672         }
05673         pFormat += 6;
05674     }
05675 
05676     type = *(const unsigned short*)pFormat;
05677     TRACE("type %04x\n", type);
05678     if(arm == num_arms) /* default arm extras */
05679     {
05680         if(type == 0xffff)
05681         {
05682             ERR("no arm for 0x%x and no default case\n", discriminant);
05683             RpcRaiseException(RPC_S_INVALID_TAG);
05684             return NULL;
05685         }
05686         if(type == 0)
05687         {
05688             TRACE("falling back to empty default case for 0x%x\n", discriminant);
05689             return NULL;
05690         }
05691     }
05692     return pFormat;
05693 }
05694 
05695 static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat)
05696 {
05697     unsigned short type;
05698 
05699     pFormat += 2;
05700 
05701     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
05702     if(!pFormat)
05703         return NULL;
05704 
05705     type = *(const unsigned short*)pFormat;
05706     if((type & 0xff00) == 0x8000)
05707     {
05708         unsigned char basetype = LOBYTE(type);
05709         return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
05710     }
05711     else
05712     {
05713         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
05714         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
05715         if (m)
05716         {
05717             unsigned char *saved_buffer = NULL;
05718             int pointer_buffer_mark_set = 0;
05719             switch(*desc)
05720             {
05721             case RPC_FC_RP:
05722             case RPC_FC_UP:
05723             case RPC_FC_OP:
05724             case RPC_FC_FP:
05725                 align_pointer_clear(&pStubMsg->Buffer, 4);
05726                 saved_buffer = pStubMsg->Buffer;
05727                 if (pStubMsg->PointerBufferMark)
05728                 {
05729                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
05730                   pStubMsg->PointerBufferMark = NULL;
05731                   pointer_buffer_mark_set = 1;
05732                 }
05733                 else
05734                   safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
05735 
05736                 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
05737                 if (pointer_buffer_mark_set)
05738                 {
05739                   STD_OVERFLOW_CHECK(pStubMsg);
05740                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
05741                   if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
05742                   {
05743                       ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
05744                           saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
05745                       RpcRaiseException(RPC_X_BAD_STUB_DATA);
05746                   }
05747                   pStubMsg->Buffer = saved_buffer + 4;
05748                 }
05749                 break;
05750             default:
05751                 m(pStubMsg, pMemory, desc);
05752             }
05753         }
05754         else FIXME("no marshaller for embedded type %02x\n", *desc);
05755     }
05756     return NULL;
05757 }
05758 
05759 static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
05760                                 unsigned char **ppMemory,
05761                                 ULONG discriminant,
05762                                 PFORMAT_STRING pFormat,
05763                                 unsigned char fMustAlloc)
05764 {
05765     unsigned short type;
05766 
05767     pFormat += 2;
05768 
05769     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
05770     if(!pFormat)
05771         return NULL;
05772 
05773     type = *(const unsigned short*)pFormat;
05774     if((type & 0xff00) == 0x8000)
05775     {
05776         unsigned char basetype = LOBYTE(type);
05777         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE);
05778     }
05779     else
05780     {
05781         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
05782         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
05783         if (m)
05784         {
05785             unsigned char *saved_buffer = NULL;
05786             int pointer_buffer_mark_set = 0;
05787             switch(*desc)
05788             {
05789             case RPC_FC_RP:
05790             case RPC_FC_UP:
05791             case RPC_FC_OP:
05792             case RPC_FC_FP:
05793                 align_pointer(&pStubMsg->Buffer, 4);
05794                 saved_buffer = pStubMsg->Buffer;
05795                 if (pStubMsg->PointerBufferMark)
05796                 {
05797                   pStubMsg->Buffer = pStubMsg->PointerBufferMark;
05798                   pStubMsg->PointerBufferMark = NULL;
05799                   pointer_buffer_mark_set = 1;
05800                 }
05801                 else
05802                   pStubMsg->Buffer += 4; /* for pointer ID */
05803 
05804                 if (saved_buffer + 4 > pStubMsg->BufferEnd)
05805                 {
05806                     ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n",
05807                         saved_buffer, pStubMsg->BufferEnd);
05808                     RpcRaiseException(RPC_X_BAD_STUB_DATA);
05809                 }
05810 
05811                 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc);
05812                 if (pointer_buffer_mark_set)
05813                 {
05814                   STD_OVERFLOW_CHECK(pStubMsg);
05815                   pStubMsg->PointerBufferMark = pStubMsg->Buffer;
05816                   pStubMsg->Buffer = saved_buffer + 4;
05817                 }
05818                 break;
05819             default:
05820                 m(pStubMsg, ppMemory, desc, fMustAlloc);
05821             }
05822         }
05823         else FIXME("no marshaller for embedded type %02x\n", *desc);
05824     }
05825     return NULL;
05826 }
05827 
05828 static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg,
05829                                   unsigned char *pMemory,
05830                                   ULONG discriminant,
05831                                   PFORMAT_STRING pFormat)
05832 {
05833     unsigned short type;
05834 
05835     pFormat += 2;
05836 
05837     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
05838     if(!pFormat)
05839         return;
05840 
05841     type = *(const unsigned short*)pFormat;
05842     if((type & 0xff00) == 0x8000)
05843     {
05844         unsigned char basetype = LOBYTE(type);
05845         NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
05846     }
05847     else
05848     {
05849         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
05850         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
05851         if (m)
05852         {
05853             switch(*desc)
05854             {
05855             case RPC_FC_RP:
05856             case RPC_FC_UP:
05857             case RPC_FC_OP:
05858             case RPC_FC_FP:
05859                 align_length(&pStubMsg->BufferLength, 4);
05860                 safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */
05861                 if (!pStubMsg->IgnoreEmbeddedPointers)
05862                 {
05863                     int saved_buffer_length = pStubMsg->BufferLength;
05864                     pStubMsg->BufferLength = pStubMsg->PointerLength;
05865                     pStubMsg->PointerLength = 0;
05866                     if(!pStubMsg->BufferLength)
05867                         ERR("BufferLength == 0??\n");
05868                     PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
05869                     pStubMsg->PointerLength = pStubMsg->BufferLength;
05870                     pStubMsg->BufferLength = saved_buffer_length;
05871                 }
05872                 break;
05873             default:
05874                 m(pStubMsg, pMemory, desc);
05875             }
05876         }
05877         else FIXME("no buffersizer for embedded type %02x\n", *desc);
05878     }
05879 }
05880 
05881 static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
05882                                    ULONG discriminant,
05883                                    PFORMAT_STRING pFormat)
05884 {
05885     unsigned short type, size;
05886 
05887     size = *(const unsigned short*)pFormat;
05888     pStubMsg->Memory += size;
05889     pFormat += 2;
05890 
05891     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
05892     if(!pFormat)
05893         return 0;
05894 
05895     type = *(const unsigned short*)pFormat;
05896     if((type & 0xff00) == 0x8000)
05897     {
05898         return NdrBaseTypeMemorySize(pStubMsg, pFormat);
05899     }
05900     else
05901     {
05902         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
05903         NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
05904         unsigned char *saved_buffer;
05905         if (m)
05906         {
05907             switch(*desc)
05908             {
05909             case RPC_FC_RP:
05910             case RPC_FC_UP:
05911             case RPC_FC_OP:
05912             case RPC_FC_FP:
05913                 align_pointer(&pStubMsg->Buffer, 4);
05914                 saved_buffer = pStubMsg->Buffer;
05915                 safe_buffer_increment(pStubMsg, 4);
05916                 align_length(&pStubMsg->MemorySize, sizeof(void *));
05917                 pStubMsg->MemorySize += sizeof(void *);
05918                 if (!pStubMsg->IgnoreEmbeddedPointers)
05919                     PointerMemorySize(pStubMsg, saved_buffer, pFormat);
05920                 break;
05921             default:
05922                 return m(pStubMsg, desc);
05923             }
05924         }
05925         else FIXME("no marshaller for embedded type %02x\n", *desc);
05926     }
05927 
05928     TRACE("size %d\n", size);
05929     return size;
05930 }
05931 
05932 static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg,
05933                            unsigned char *pMemory,
05934                            ULONG discriminant,
05935                            PFORMAT_STRING pFormat)
05936 {
05937     unsigned short type;
05938 
05939     pFormat += 2;
05940 
05941     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
05942     if(!pFormat)
05943         return;
05944 
05945     type = *(const unsigned short*)pFormat;
05946     if((type & 0xff00) != 0x8000)
05947     {
05948         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
05949         NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK];
05950         if (m)
05951         {
05952             switch(*desc)
05953             {
05954             case RPC_FC_RP:
05955             case RPC_FC_UP:
05956             case RPC_FC_OP:
05957             case RPC_FC_FP:
05958                 PointerFree(pStubMsg, *(unsigned char **)pMemory, desc);
05959                 break;
05960             default:
05961                 m(pStubMsg, pMemory, desc);
05962             }
05963         }
05964     }
05965 }
05966 
05967 /***********************************************************************
05968  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
05969  */
05970 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
05971                                 unsigned char *pMemory,
05972                                 PFORMAT_STRING pFormat)
05973 {
05974     unsigned char switch_type;
05975     unsigned char increment;
05976     ULONG switch_value;
05977 
05978     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
05979     pFormat++;
05980 
05981     switch_type = *pFormat & 0xf;
05982     increment = (*pFormat & 0xf0) >> 4;
05983     pFormat++;
05984 
05985     align_pointer_clear(&pStubMsg->Buffer, increment);
05986 
05987     switch_value = get_discriminant(switch_type, pMemory);
05988     TRACE("got switch value 0x%x\n", switch_value);
05989 
05990     NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type);
05991     pMemory += increment;
05992 
05993     return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat);
05994 }
05995 
05996 /***********************************************************************
05997  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
05998  */
05999 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
06000                                 unsigned char **ppMemory,
06001                                 PFORMAT_STRING pFormat,
06002                                 unsigned char fMustAlloc)
06003 {
06004     unsigned char switch_type;
06005     unsigned char increment;
06006     ULONG switch_value;
06007     unsigned short size;
06008     unsigned char *pMemoryArm;
06009 
06010     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
06011     pFormat++;
06012 
06013     switch_type = *pFormat & 0xf;
06014     increment = (*pFormat & 0xf0) >> 4;
06015     pFormat++;
06016 
06017     align_pointer(&pStubMsg->Buffer, increment);
06018     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
06019     TRACE("got switch value 0x%x\n", switch_value);
06020 
06021     size = *(const unsigned short*)pFormat + increment;
06022     if (!fMustAlloc && !*ppMemory)
06023         fMustAlloc = TRUE;
06024     if (fMustAlloc)
06025         *ppMemory = NdrAllocate(pStubMsg, size);
06026 
06027     /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
06028      * since the arm is part of the memory block that is encompassed by
06029      * the whole union. Memory is forced to allocate when pointers
06030      * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
06031      * clearing the memory we pass in to the unmarshaller */
06032     if (fMustAlloc)
06033         memset(*ppMemory, 0, size);
06034 
06035     NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
06036     pMemoryArm = *ppMemory + increment;
06037 
06038     return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE);
06039 }
06040 
06041 /***********************************************************************
06042  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
06043  */
06044 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
06045                                 unsigned char *pMemory,
06046                                 PFORMAT_STRING pFormat)
06047 {
06048     unsigned char switch_type;
06049     unsigned char increment;
06050     ULONG switch_value;
06051 
06052     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
06053     pFormat++;
06054 
06055     switch_type = *pFormat & 0xf;
06056     increment = (*pFormat & 0xf0) >> 4;
06057     pFormat++;
06058 
06059     align_length(&pStubMsg->BufferLength, increment);
06060     switch_value = get_discriminant(switch_type, pMemory);
06061     TRACE("got switch value 0x%x\n", switch_value);
06062 
06063     /* Add discriminant size */
06064     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type);
06065     pMemory += increment;
06066 
06067     union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat);
06068 }
06069 
06070 /***********************************************************************
06071  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
06072  */
06073 ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
06074                                 PFORMAT_STRING pFormat)
06075 {
06076     unsigned char switch_type;
06077     unsigned char increment;
06078     ULONG switch_value;
06079 
06080     switch_type = *pFormat & 0xf;
06081     increment = (*pFormat & 0xf0) >> 4;
06082     pFormat++;
06083 
06084     align_pointer(&pStubMsg->Buffer, increment);
06085     switch_value = get_discriminant(switch_type, pStubMsg->Buffer);
06086     TRACE("got switch value 0x%x\n", switch_value);
06087 
06088     pStubMsg->Memory += increment;
06089 
06090     return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat);
06091 }
06092 
06093 /***********************************************************************
06094  *           NdrEncapsulatedUnionFree [RPCRT4.@]
06095  */
06096 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
06097                                 unsigned char *pMemory,
06098                                 PFORMAT_STRING pFormat)
06099 {
06100     unsigned char switch_type;
06101     unsigned char increment;
06102     ULONG switch_value;
06103 
06104     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
06105     pFormat++;
06106 
06107     switch_type = *pFormat & 0xf;
06108     increment = (*pFormat & 0xf0) >> 4;
06109     pFormat++;
06110 
06111     switch_value = get_discriminant(switch_type, pMemory);
06112     TRACE("got switch value 0x%x\n", switch_value);
06113 
06114     pMemory += increment;
06115 
06116     union_arm_free(pStubMsg, pMemory, switch_value, pFormat);
06117 }
06118 
06119 /***********************************************************************
06120  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
06121  */
06122 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
06123                                 unsigned char *pMemory,
06124                                 PFORMAT_STRING pFormat)
06125 {
06126     unsigned char switch_type;
06127 
06128     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
06129     pFormat++;
06130 
06131     switch_type = *pFormat;
06132     pFormat++;
06133 
06134     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
06135     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
06136     /* Marshall discriminant */
06137     NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
06138 
06139     return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
06140 }
06141 
06142 static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
06143                                     PFORMAT_STRING *ppFormat)
06144 {
06145     LONG discriminant = 0;
06146 
06147     switch(**ppFormat)
06148     {
06149     case RPC_FC_BYTE:
06150     case RPC_FC_CHAR:
06151     case RPC_FC_SMALL:
06152     case RPC_FC_USMALL:
06153     {
06154         UCHAR d;
06155         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
06156         discriminant = d;
06157         break;
06158     }
06159     case RPC_FC_WCHAR:
06160     case RPC_FC_SHORT:
06161     case RPC_FC_USHORT:
06162     case RPC_FC_ENUM16:
06163     {
06164         USHORT d;
06165         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
06166         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
06167         discriminant = d;
06168         break;
06169     }
06170     case RPC_FC_LONG:
06171     case RPC_FC_ULONG:
06172     {
06173         ULONG d;
06174         align_pointer(&pStubMsg->Buffer, sizeof(ULONG));
06175         safe_copy_from_buffer(pStubMsg, &d, sizeof(d));
06176         discriminant = d;
06177         break;
06178     }
06179     default:
06180         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
06181     }
06182     (*ppFormat)++;
06183 
06184     if (pStubMsg->fHasNewCorrDesc)
06185         *ppFormat += 6;
06186     else
06187         *ppFormat += 4;
06188     return discriminant;
06189 }
06190 
06191 /**********************************************************************
06192  *           NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@]
06193  */
06194 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
06195                                 unsigned char **ppMemory,
06196                                 PFORMAT_STRING pFormat,
06197                                 unsigned char fMustAlloc)
06198 {
06199     LONG discriminant;
06200     unsigned short size;
06201 
06202     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
06203     pFormat++;
06204 
06205     /* Unmarshall discriminant */
06206     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
06207     TRACE("unmarshalled discriminant %x\n", discriminant);
06208 
06209     pFormat += *(const SHORT*)pFormat;
06210 
06211     size = *(const unsigned short*)pFormat;
06212 
06213     if (!fMustAlloc && !*ppMemory)
06214         fMustAlloc = TRUE;
06215     if (fMustAlloc)
06216         *ppMemory = NdrAllocate(pStubMsg, size);
06217 
06218     /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
06219      * since the arm is part of the memory block that is encompassed by
06220      * the whole union. Memory is forced to allocate when pointers
06221      * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
06222      * clearing the memory we pass in to the unmarshaller */
06223     if (fMustAlloc)
06224         memset(*ppMemory, 0, size);
06225 
06226     return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
06227 }
06228 
06229 /***********************************************************************
06230  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
06231  */
06232 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
06233                                 unsigned char *pMemory,
06234                                 PFORMAT_STRING pFormat)
06235 {
06236     unsigned char switch_type;
06237 
06238     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
06239     pFormat++;
06240 
06241     switch_type = *pFormat;
06242     pFormat++;
06243 
06244     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
06245     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
06246     /* Add discriminant size */
06247     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
06248 
06249     union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
06250 }
06251 
06252 /***********************************************************************
06253  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
06254  */
06255 ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
06256                                 PFORMAT_STRING pFormat)
06257 {
06258     ULONG discriminant;
06259 
06260     pFormat++;
06261     /* Unmarshall discriminant */
06262     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
06263     TRACE("unmarshalled discriminant 0x%x\n", discriminant);
06264 
06265     return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat);
06266 }
06267 
06268 /***********************************************************************
06269  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
06270  */
06271 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
06272                                 unsigned char *pMemory,
06273                                 PFORMAT_STRING pFormat)
06274 {
06275     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
06276     pFormat++;
06277     pFormat++;
06278 
06279     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
06280     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
06281 
06282     union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
06283 }
06284 
06285 /***********************************************************************
06286  *           NdrByteCountPointerMarshall [RPCRT4.@]
06287  */
06288 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
06289                                 unsigned char *pMemory,
06290                                 PFORMAT_STRING pFormat)
06291 {
06292     FIXME("stub\n");
06293     return NULL;
06294 }
06295 
06296 /***********************************************************************
06297  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
06298  */
06299 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
06300                                 unsigned char **ppMemory,
06301                                 PFORMAT_STRING pFormat,
06302                                 unsigned char fMustAlloc)
06303 {
06304     FIXME("stub\n");
06305     return NULL;
06306 }
06307 
06308 /***********************************************************************
06309  *           NdrByteCountPointerBufferSize [RPCRT4.@]
06310  */
06311 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
06312                                 unsigned char *pMemory,
06313                                 PFORMAT_STRING pFormat)
06314 {
06315     FIXME("stub\n");
06316 }
06317 
06318 /***********************************************************************
06319  *           NdrByteCountPointerMemorySize [internal]
06320  */
06321 static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
06322                                                   PFORMAT_STRING pFormat)
06323 {
06324     FIXME("stub\n");
06325     return 0;
06326 }
06327 
06328 /***********************************************************************
06329  *           NdrByteCountPointerFree [RPCRT4.@]
06330  */
06331 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
06332                                 unsigned char *pMemory,
06333                                 PFORMAT_STRING pFormat)
06334 {
06335     FIXME("stub\n");
06336 }
06337 
06338 /***********************************************************************
06339  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
06340  */
06341 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
06342                                 unsigned char *pMemory,
06343                                 PFORMAT_STRING pFormat)
06344 {
06345     FIXME("stub\n");
06346     return NULL;
06347 }
06348 
06349 /***********************************************************************
06350  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
06351  */
06352 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
06353                                 unsigned char **ppMemory,
06354                                 PFORMAT_STRING pFormat,
06355                                 unsigned char fMustAlloc)
06356 {
06357     FIXME("stub\n");
06358     return NULL;
06359 }
06360 
06361 /***********************************************************************
06362  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
06363  */
06364 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
06365                                 unsigned char *pMemory,
06366                                 PFORMAT_STRING pFormat)
06367 {
06368     FIXME("stub\n");
06369 }
06370 
06371 /***********************************************************************
06372  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
06373  */
06374 ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
06375                                 PFORMAT_STRING pFormat)
06376 {
06377     FIXME("stub\n");
06378     return 0;
06379 }
06380 
06381 /***********************************************************************
06382  *           NdrXmitOrRepAsFree [RPCRT4.@]
06383  */
06384 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
06385                                 unsigned char *pMemory,
06386                                 PFORMAT_STRING pFormat)
06387 {
06388     FIXME("stub\n");
06389 }
06390 
06391 /***********************************************************************
06392  *           NdrRangeMarshall [internal]
06393  */
06394 static unsigned char *WINAPI NdrRangeMarshall(
06395     PMIDL_STUB_MESSAGE pStubMsg,
06396     unsigned char *pMemory,
06397     PFORMAT_STRING pFormat)
06398 {
06399     const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
06400     unsigned char base_type;
06401 
06402     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
06403 
06404     if (pRange->type != RPC_FC_RANGE)
06405     {
06406         ERR("invalid format type %x\n", pRange->type);
06407         RpcRaiseException(RPC_S_INTERNAL_ERROR);
06408         return NULL;
06409     }
06410 
06411     base_type = pRange->flags_type & 0xf;
06412 
06413     return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type);
06414 }
06415 
06416 /***********************************************************************
06417  *           NdrRangeUnmarshall [RPCRT4.@]
06418  */
06419 unsigned char *WINAPI NdrRangeUnmarshall(
06420     PMIDL_STUB_MESSAGE pStubMsg,
06421     unsigned char **ppMemory,
06422     PFORMAT_STRING pFormat,
06423     unsigned char fMustAlloc)
06424 {
06425     const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
06426     unsigned char base_type;
06427 
06428     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
06429 
06430     if (pRange->type != RPC_FC_RANGE)
06431     {
06432         ERR("invalid format type %x\n", pRange->type);
06433         RpcRaiseException(RPC_S_INTERNAL_ERROR);
06434         return NULL;
06435     }
06436     base_type = pRange->flags_type & 0xf;
06437 
06438     TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
06439         base_type, pRange->low_value, pRange->high_value);
06440 
06441 #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
06442     do \
06443     { \
06444         align_pointer(&pStubMsg->Buffer, sizeof(wire_type)); \
06445         if (!fMustAlloc && !*ppMemory) \
06446             fMustAlloc = TRUE; \
06447         if (fMustAlloc) \
06448             *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
06449         if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
06450         { \
06451             ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
06452                 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
06453             RpcRaiseException(RPC_X_BAD_STUB_DATA); \
06454         } \
06455         if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
06456             (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
06457         { \
06458             ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
06459                 *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
06460                 (mem_type)pRange->high_value); \
06461             RpcRaiseException(RPC_S_INVALID_BOUND); \
06462             return NULL; \
06463         } \
06464         TRACE("*ppMemory: %p\n", *ppMemory); \
06465         **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
06466         pStubMsg->Buffer += sizeof(wire_type); \
06467     } while (0)
06468 
06469     switch(base_type)
06470     {
06471     case RPC_FC_CHAR:
06472     case RPC_FC_SMALL:
06473         RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
06474         TRACE("value: 0x%02x\n", **ppMemory);
06475         break;
06476     case RPC_FC_BYTE:
06477     case RPC_FC_USMALL:
06478         RANGE_UNMARSHALL(CHAR, CHAR, "%u");
06479         TRACE("value: 0x%02x\n", **ppMemory);
06480         break;
06481     case RPC_FC_WCHAR: /* FIXME: valid? */
06482     case RPC_FC_USHORT:
06483         RANGE_UNMARSHALL(USHORT, USHORT, "%u");
06484         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
06485         break;
06486     case RPC_FC_SHORT:
06487         RANGE_UNMARSHALL(SHORT, SHORT, "%d");
06488         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
06489         break;
06490     case RPC_FC_LONG:
06491     case RPC_FC_ENUM32:
06492         RANGE_UNMARSHALL(LONG, LONG, "%d");
06493         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
06494         break;
06495     case RPC_FC_ULONG:
06496         RANGE_UNMARSHALL(ULONG, ULONG, "%u");
06497         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
06498         break;
06499     case RPC_FC_ENUM16:
06500         RANGE_UNMARSHALL(UINT, USHORT, "%u");
06501         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
06502         break;
06503     case RPC_FC_FLOAT:
06504     case RPC_FC_DOUBLE:
06505     case RPC_FC_HYPER:
06506     default:
06507         ERR("invalid range base type: 0x%02x\n", base_type);
06508         RpcRaiseException(RPC_S_INTERNAL_ERROR);
06509     }
06510 
06511     return NULL;
06512 }
06513 
06514 /***********************************************************************
06515  *           NdrRangeBufferSize [internal]
06516  */
06517 static void WINAPI NdrRangeBufferSize(
06518     PMIDL_STUB_MESSAGE pStubMsg,
06519     unsigned char *pMemory,
06520     PFORMAT_STRING pFormat)
06521 {
06522     const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
06523     unsigned char base_type;
06524 
06525     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
06526 
06527     if (pRange->type != RPC_FC_RANGE)
06528     {
06529         ERR("invalid format type %x\n", pRange->type);
06530         RpcRaiseException(RPC_S_INTERNAL_ERROR);
06531     }
06532     base_type = pRange->flags_type & 0xf;
06533 
06534     NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type);
06535 }
06536 
06537 /***********************************************************************
06538  *           NdrRangeMemorySize [internal]
06539  */
06540 static ULONG WINAPI NdrRangeMemorySize(
06541     PMIDL_STUB_MESSAGE pStubMsg,
06542     PFORMAT_STRING pFormat)
06543 {
06544     const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat;
06545     unsigned char base_type;
06546 
06547     if (pRange->type != RPC_FC_RANGE)
06548     {
06549         ERR("invalid format type %x\n", pRange->type);
06550         RpcRaiseException(RPC_S_INTERNAL_ERROR);
06551         return 0;
06552     }
06553     base_type = pRange->flags_type & 0xf;
06554 
06555     return NdrBaseTypeMemorySize(pStubMsg, &base_type);
06556 }
06557 
06558 /***********************************************************************
06559  *           NdrRangeFree [internal]
06560  */
06561 static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
06562                                 unsigned char *pMemory,
06563                                 PFORMAT_STRING pFormat)
06564 {
06565    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
06566 
06567    /* nothing to do */
06568 }
06569 
06570 /***********************************************************************
06571  *           NdrBaseTypeMarshall [internal]
06572  */
06573 static unsigned char *WINAPI NdrBaseTypeMarshall(
06574     PMIDL_STUB_MESSAGE pStubMsg,
06575     unsigned char *pMemory,
06576     PFORMAT_STRING pFormat)
06577 {
06578     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
06579 
06580     switch(*pFormat)
06581     {
06582     case RPC_FC_BYTE:
06583     case RPC_FC_CHAR:
06584     case RPC_FC_SMALL:
06585     case RPC_FC_USMALL:
06586         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR));
06587         TRACE("value: 0x%02x\n", *pMemory);
06588         break;
06589     case RPC_FC_WCHAR:
06590     case RPC_FC_SHORT:
06591     case RPC_FC_USHORT:
06592         align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT));
06593         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT));
06594         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
06595         break;
06596     case RPC_FC_LONG:
06597     case RPC_FC_ULONG:
06598     case RPC_FC_ERROR_STATUS_T:
06599     case RPC_FC_ENUM32:
06600         align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONG));
06601         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG));
06602         TRACE("value: 0x%08x\n", *(ULONG *)pMemory);
06603         break;
06604     case RPC_FC_FLOAT:
06605         align_pointer_clear(&pStubMsg->Buffer, sizeof(float));
06606         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
06607         break;
06608     case RPC_FC_DOUBLE:
06609         align_pointer_clear(&pStubMsg->Buffer, sizeof(double));
06610         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
06611         break;
06612     case RPC_FC_HYPER:
06613         align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONGLONG));
06614         safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG));
06615         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
06616         break;
06617     case RPC_FC_ENUM16:
06618     {
06619         USHORT val = *(UINT *)pMemory;
06620         /* only 16-bits on the wire, so do a sanity check */
06621         if (*(UINT *)pMemory > SHRT_MAX)
06622             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
06623         align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT));
06624         safe_copy_to_buffer(pStubMsg, &val, sizeof(val));
06625         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
06626         break;
06627     }
06628     case RPC_FC_INT3264:
06629     case RPC_FC_UINT3264:
06630     {
06631         UINT val = *(UINT_PTR *)pMemory;
06632         align_pointer_clear(&pStubMsg->Buffer, sizeof(UINT));
06633         safe_copy_to_buffer(pStubMsg, &val, sizeof(val));
06634         break;
06635     }
06636     case RPC_FC_IGNORE:
06637         break;
06638     default:
06639         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
06640     }
06641 
06642     /* FIXME: what is the correct return value? */
06643     return NULL;
06644 }
06645 
06646 /***********************************************************************
06647  *           NdrBaseTypeUnmarshall [internal]
06648  */
06649 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
06650     PMIDL_STUB_MESSAGE pStubMsg,
06651     unsigned char **ppMemory,
06652     PFORMAT_STRING pFormat,
06653     unsigned char fMustAlloc)
06654 {
06655     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
06656 
06657 #define BASE_TYPE_UNMARSHALL(type) do { \
06658         align_pointer(&pStubMsg->Buffer, sizeof(type)); \
06659         if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \
06660         { \
06661             *ppMemory = pStubMsg->Buffer; \
06662             TRACE("*ppMemory: %p\n", *ppMemory); \
06663             safe_buffer_increment(pStubMsg, sizeof(type)); \
06664         } \
06665         else \
06666         {  \
06667             if (fMustAlloc) \
06668                 *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
06669             TRACE("*ppMemory: %p\n", *ppMemory); \
06670             safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \
06671         } \
06672     } while (0)
06673 
06674     switch(*pFormat)
06675     {
06676     case RPC_FC_BYTE:
06677     case RPC_FC_CHAR:
06678     case RPC_FC_SMALL:
06679     case RPC_FC_USMALL:
06680         BASE_TYPE_UNMARSHALL(UCHAR);
06681         TRACE("value: 0x%02x\n", **ppMemory);
06682         break;
06683     case RPC_FC_WCHAR:
06684     case RPC_FC_SHORT:
06685     case RPC_FC_USHORT:
06686         BASE_TYPE_UNMARSHALL(USHORT);
06687         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
06688         break;
06689     case RPC_FC_LONG:
06690     case RPC_FC_ULONG:
06691     case RPC_FC_ERROR_STATUS_T:
06692     case RPC_FC_ENUM32:
06693         BASE_TYPE_UNMARSHALL(ULONG);
06694         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
06695         break;
06696    case RPC_FC_FLOAT:
06697         BASE_TYPE_UNMARSHALL(float);
06698         TRACE("value: %f\n", **(float **)ppMemory);
06699         break;
06700     case RPC_FC_DOUBLE:
06701         BASE_TYPE_UNMARSHALL(double);
06702         TRACE("value: %f\n", **(double **)ppMemory);
06703         break;
06704     case RPC_FC_HYPER:
06705         BASE_TYPE_UNMARSHALL(ULONGLONG);
06706         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
06707         break;
06708     case RPC_FC_ENUM16:
06709     {
06710         USHORT val;
06711         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
06712         if (!fMustAlloc && !*ppMemory)
06713             fMustAlloc = TRUE;
06714         if (fMustAlloc)
06715             *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT));
06716         safe_copy_from_buffer(pStubMsg, &val, sizeof(USHORT));
06717         /* 16-bits on the wire, but int in memory */
06718         **(UINT **)ppMemory = val;
06719         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
06720         break;
06721     }
06722     case RPC_FC_INT3264:
06723         if (sizeof(INT_PTR) == sizeof(INT)) BASE_TYPE_UNMARSHALL(INT);
06724         else
06725         {
06726             INT val;
06727             align_pointer(&pStubMsg->Buffer, sizeof(INT));
06728             if (!fMustAlloc && !*ppMemory)
06729                 fMustAlloc = TRUE;
06730             if (fMustAlloc)
06731                 *ppMemory = NdrAllocate(pStubMsg, sizeof(INT_PTR));
06732             safe_copy_from_buffer(pStubMsg, &val, sizeof(INT));
06733             **(INT_PTR **)ppMemory = val;
06734             TRACE("value: 0x%08lx\n", **(INT_PTR **)ppMemory);
06735         }
06736         break;
06737     case RPC_FC_UINT3264:
06738         if (sizeof(UINT_PTR) == sizeof(UINT)) BASE_TYPE_UNMARSHALL(UINT);
06739         else
06740         {
06741             UINT val;
06742             align_pointer(&pStubMsg->Buffer, sizeof(UINT));
06743             if (!fMustAlloc && !*ppMemory)
06744                 fMustAlloc = TRUE;
06745             if (fMustAlloc)
06746                 *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT_PTR));
06747             safe_copy_from_buffer(pStubMsg, &val, sizeof(UINT));
06748             **(UINT_PTR **)ppMemory = val;
06749             TRACE("value: 0x%08lx\n", **(UINT_PTR **)ppMemory);
06750         }
06751         break;
06752     case RPC_FC_IGNORE:
06753         break;
06754     default:
06755         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
06756     }
06757 #undef BASE_TYPE_UNMARSHALL
06758 
06759     /* FIXME: what is the correct return value? */
06760 
06761     return NULL;
06762 }
06763 
06764 /***********************************************************************
06765  *           NdrBaseTypeBufferSize [internal]
06766  */
06767 static void WINAPI NdrBaseTypeBufferSize(
06768     PMIDL_STUB_MESSAGE pStubMsg,
06769     unsigned char *pMemory,
06770     PFORMAT_STRING pFormat)
06771 {
06772     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
06773 
06774     switch(*pFormat)
06775     {
06776     case RPC_FC_BYTE:
06777     case RPC_FC_CHAR:
06778     case RPC_FC_SMALL:
06779     case RPC_FC_USMALL:
06780         safe_buffer_length_increment(pStubMsg, sizeof(UCHAR));
06781         break;
06782     case RPC_FC_WCHAR:
06783     case RPC_FC_SHORT:
06784     case RPC_FC_USHORT:
06785     case RPC_FC_ENUM16:
06786         align_length(&pStubMsg->BufferLength, sizeof(USHORT));
06787         safe_buffer_length_increment(pStubMsg, sizeof(USHORT));
06788         break;
06789     case RPC_FC_LONG:
06790     case RPC_FC_ULONG:
06791     case RPC_FC_ENUM32:
06792     case RPC_FC_INT3264:
06793     case RPC_FC_UINT3264:
06794         align_length(&pStubMsg->BufferLength, sizeof(ULONG));
06795         safe_buffer_length_increment(pStubMsg, sizeof(ULONG));
06796         break;
06797     case RPC_FC_FLOAT:
06798         align_length(&pStubMsg->BufferLength, sizeof(float));
06799         safe_buffer_length_increment(pStubMsg, sizeof(float));
06800         break;
06801     case RPC_FC_DOUBLE:
06802         align_length(&pStubMsg->BufferLength, sizeof(double));
06803         safe_buffer_length_increment(pStubMsg, sizeof(double));
06804         break;
06805     case RPC_FC_HYPER:
06806         align_length(&pStubMsg->BufferLength, sizeof(ULONGLONG));
06807         safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG));
06808         break;
06809     case RPC_FC_ERROR_STATUS_T:
06810         align_length(&pStubMsg->BufferLength, sizeof(error_status_t));
06811         safe_buffer_length_increment(pStubMsg, sizeof(error_status_t));
06812         break;
06813     case RPC_FC_IGNORE:
06814         break;
06815     default:
06816         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
06817     }
06818 }
06819 
06820 /***********************************************************************
06821  *           NdrBaseTypeMemorySize [internal]
06822  */
06823 static ULONG WINAPI NdrBaseTypeMemorySize(
06824     PMIDL_STUB_MESSAGE pStubMsg,
06825     PFORMAT_STRING pFormat)
06826 {
06827     TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat);
06828 
06829     switch(*pFormat)
06830     {
06831     case RPC_FC_BYTE:
06832     case RPC_FC_CHAR:
06833     case RPC_FC_SMALL:
06834     case RPC_FC_USMALL:
06835         safe_buffer_increment(pStubMsg, sizeof(UCHAR));
06836         pStubMsg->MemorySize += sizeof(UCHAR);
06837         return sizeof(UCHAR);
06838     case RPC_FC_WCHAR:
06839     case RPC_FC_SHORT:
06840     case RPC_FC_USHORT:
06841         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
06842         safe_buffer_increment(pStubMsg, sizeof(USHORT));
06843         align_length(&pStubMsg->MemorySize, sizeof(USHORT));
06844         pStubMsg->MemorySize += sizeof(USHORT);
06845         return sizeof(USHORT);
06846     case RPC_FC_LONG:
06847     case RPC_FC_ULONG:
06848     case RPC_FC_ENUM32:
06849         align_pointer(&pStubMsg->Buffer, sizeof(ULONG));
06850         safe_buffer_increment(pStubMsg, sizeof(ULONG));
06851         align_length(&pStubMsg->MemorySize, sizeof(ULONG));
06852         pStubMsg->MemorySize += sizeof(ULONG);
06853         return sizeof(ULONG);
06854     case RPC_FC_FLOAT:
06855         align_pointer(&pStubMsg->Buffer, sizeof(float));
06856         safe_buffer_increment(pStubMsg, sizeof(float));
06857         align_length(&pStubMsg->MemorySize, sizeof(float));
06858         pStubMsg->MemorySize += sizeof(float);
06859         return sizeof(float);
06860     case RPC_FC_DOUBLE:
06861         align_pointer(&pStubMsg->Buffer, sizeof(double));
06862         safe_buffer_increment(pStubMsg, sizeof(double));
06863         align_length(&pStubMsg->MemorySize, sizeof(double));
06864         pStubMsg->MemorySize += sizeof(double);
06865         return sizeof(double);
06866     case RPC_FC_HYPER:
06867         align_pointer(&pStubMsg->Buffer, sizeof(ULONGLONG));
06868         safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
06869         align_length(&pStubMsg->MemorySize, sizeof(ULONGLONG));
06870         pStubMsg->MemorySize += sizeof(ULONGLONG);
06871         return sizeof(ULONGLONG);
06872     case RPC_FC_ERROR_STATUS_T:
06873         align_pointer(&pStubMsg->Buffer, sizeof(error_status_t));
06874         safe_buffer_increment(pStubMsg, sizeof(error_status_t));
06875         align_length(&pStubMsg->MemorySize, sizeof(error_status_t));
06876         pStubMsg->MemorySize += sizeof(error_status_t);
06877         return sizeof(error_status_t);
06878     case RPC_FC_ENUM16:
06879         align_pointer(&pStubMsg->Buffer, sizeof(USHORT));
06880         safe_buffer_increment(pStubMsg, sizeof(USHORT));
06881         align_length(&pStubMsg->MemorySize, sizeof(UINT));
06882         pStubMsg->MemorySize += sizeof(UINT);
06883         return sizeof(UINT);
06884     case RPC_FC_INT3264:
06885     case RPC_FC_UINT3264:
06886         align_pointer(&pStubMsg->Buffer, sizeof(UINT));
06887         safe_buffer_increment(pStubMsg, sizeof(UINT));
06888         align_length(&pStubMsg->MemorySize, sizeof(UINT_PTR));
06889         pStubMsg->MemorySize += sizeof(UINT_PTR);
06890         return sizeof(UINT_PTR);
06891     case RPC_FC_IGNORE:
06892         align_length(&pStubMsg->MemorySize, sizeof(void *));
06893         pStubMsg->MemorySize += sizeof(void *);
06894         return sizeof(void *);
06895     default:
06896         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
06897        return 0;
06898     }
06899 }
06900 
06901 /***********************************************************************
06902  *           NdrBaseTypeFree [internal]
06903  */
06904 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
06905                                 unsigned char *pMemory,
06906                                 PFORMAT_STRING pFormat)
06907 {
06908    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
06909 
06910    /* nothing to do */
06911 }
06912 
06913 /***********************************************************************
06914  *           NdrContextHandleBufferSize [internal]
06915  */
06916 static void WINAPI NdrContextHandleBufferSize(
06917     PMIDL_STUB_MESSAGE pStubMsg,
06918     unsigned char *pMemory,
06919     PFORMAT_STRING pFormat)
06920 {
06921     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
06922 
06923     if (*pFormat != RPC_FC_BIND_CONTEXT)
06924     {
06925         ERR("invalid format type %x\n", *pFormat);
06926         RpcRaiseException(RPC_S_INTERNAL_ERROR);
06927     }
06928     align_length(&pStubMsg->BufferLength, 4);
06929     safe_buffer_length_increment(pStubMsg, cbNDRContext);
06930 }
06931 
06932 /***********************************************************************
06933  *           NdrContextHandleMarshall [internal]
06934  */
06935 static unsigned char *WINAPI NdrContextHandleMarshall(
06936     PMIDL_STUB_MESSAGE pStubMsg,
06937     unsigned char *pMemory,
06938     PFORMAT_STRING pFormat)
06939 {
06940     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
06941 
06942     if (*pFormat != RPC_FC_BIND_CONTEXT)
06943     {
06944         ERR("invalid format type %x\n", *pFormat);
06945         RpcRaiseException(RPC_S_INTERNAL_ERROR);
06946     }
06947     TRACE("flags: 0x%02x\n", pFormat[1]);
06948 
06949     if (pStubMsg->IsClient)
06950     {
06951         if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
06952             NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
06953         else
06954             NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
06955     }
06956     else
06957     {
06958         NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
06959         NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
06960         NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
06961     }
06962 
06963     return NULL;
06964 }
06965 
06966 /***********************************************************************
06967  *           NdrContextHandleUnmarshall [internal]
06968  */
06969 static unsigned char *WINAPI NdrContextHandleUnmarshall(
06970     PMIDL_STUB_MESSAGE pStubMsg,
06971     unsigned char **ppMemory,
06972     PFORMAT_STRING pFormat,
06973     unsigned char fMustAlloc)
06974 {
06975     TRACE("pStubMsg %p, ppMemory %p, pFormat %p, fMustAlloc %s\n", pStubMsg,
06976         ppMemory, pFormat, fMustAlloc ? "TRUE": "FALSE");
06977 
06978     if (*pFormat != RPC_FC_BIND_CONTEXT)
06979     {
06980         ERR("invalid format type %x\n", *pFormat);
06981         RpcRaiseException(RPC_S_INTERNAL_ERROR);
06982     }
06983     TRACE("flags: 0x%02x\n", pFormat[1]);
06984 
06985     if (pStubMsg->IsClient)
06986     {
06987         /* [out]-only or [ret] param */
06988         if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT)
06989             **(NDR_CCONTEXT **)ppMemory = NULL;
06990         NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
06991     }
06992     else
06993     {
06994         NDR_SCONTEXT ctxt;
06995         ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat);
06996         if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
06997             *(void **)ppMemory = NDRSContextValue(ctxt);
06998         else
06999             *(void **)ppMemory = *NDRSContextValue(ctxt);
07000     }
07001 
07002     return NULL;
07003 }
07004 
07005 /***********************************************************************
07006  *           NdrClientContextMarshall [RPCRT4.@]
07007  */
07008 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
07009                                      NDR_CCONTEXT ContextHandle,
07010                                      int fCheck)
07011 {
07012     TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck);
07013 
07014     align_pointer_clear(&pStubMsg->Buffer, 4);
07015 
07016     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
07017     {
07018         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
07019             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
07020         RpcRaiseException(RPC_X_BAD_STUB_DATA);
07021     }
07022 
07023     /* FIXME: what does fCheck do? */
07024     NDRCContextMarshall(ContextHandle,
07025                         pStubMsg->Buffer);
07026 
07027     pStubMsg->Buffer += cbNDRContext;
07028 }
07029 
07030 /***********************************************************************
07031  *           NdrClientContextUnmarshall [RPCRT4.@]
07032  */
07033 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
07034                                        NDR_CCONTEXT * pContextHandle,
07035                                        RPC_BINDING_HANDLE BindHandle)
07036 {
07037     TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle);
07038 
07039     align_pointer(&pStubMsg->Buffer, 4);
07040 
07041     if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd)
07042         RpcRaiseException(RPC_X_BAD_STUB_DATA);
07043 
07044     NDRCContextUnmarshall(pContextHandle,
07045                           BindHandle,
07046                           pStubMsg->Buffer,
07047                           pStubMsg->RpcMsg->DataRepresentation);
07048 
07049     pStubMsg->Buffer += cbNDRContext;
07050 }
07051 
07052 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
07053                                      NDR_SCONTEXT ContextHandle,
07054                                      NDR_RUNDOWN RundownRoutine )
07055 {
07056     TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine);
07057 
07058     align_pointer(&pStubMsg->Buffer, 4);
07059 
07060     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
07061     {
07062         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
07063             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
07064         RpcRaiseException(RPC_X_BAD_STUB_DATA);
07065     }
07066 
07067     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
07068                          pStubMsg->Buffer, RundownRoutine, NULL,
07069                          RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
07070     pStubMsg->Buffer += cbNDRContext;
07071 }
07072 
07073 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
07074 {
07075     NDR_SCONTEXT ContextHandle;
07076 
07077     TRACE("(%p)\n", pStubMsg);
07078 
07079     align_pointer(&pStubMsg->Buffer, 4);
07080 
07081     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
07082     {
07083         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
07084             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
07085         RpcRaiseException(RPC_X_BAD_STUB_DATA);
07086     }
07087 
07088     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
07089                                            pStubMsg->Buffer,
07090                                            pStubMsg->RpcMsg->DataRepresentation,
07091                                            NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
07092     pStubMsg->Buffer += cbNDRContext;
07093 
07094     return ContextHandle;
07095 }
07096 
07097 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
07098                                  unsigned char* pMemory,
07099                                  PFORMAT_STRING pFormat)
07100 {
07101     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
07102 }
07103 
07104 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
07105                                                PFORMAT_STRING pFormat)
07106 {
07107     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
07108     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
07109 
07110     TRACE("(%p, %p)\n", pStubMsg, pFormat);
07111 
07112     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
07113         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
07114     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
07115         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
07116     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
07117     {
07118         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
07119         if_id = &sif->InterfaceId;
07120     }
07121 
07122     return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL,
07123                                   pStubMsg->RpcMsg->DataRepresentation, if_id,
07124                                   flags);
07125 }
07126 
07127 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
07128                                         NDR_SCONTEXT ContextHandle,
07129                                         NDR_RUNDOWN RundownRoutine,
07130                                         PFORMAT_STRING pFormat)
07131 {
07132     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
07133     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
07134 
07135     TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
07136 
07137     align_pointer(&pStubMsg->Buffer, 4);
07138 
07139     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
07140     {
07141         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
07142             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
07143         RpcRaiseException(RPC_X_BAD_STUB_DATA);
07144     }
07145 
07146     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
07147         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
07148     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
07149         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
07150     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
07151     {
07152         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
07153         if_id = &sif->InterfaceId;
07154     }
07155 
07156     NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle,
07157                           pStubMsg->Buffer, RundownRoutine, if_id, flags);
07158     pStubMsg->Buffer += cbNDRContext;
07159 }
07160 
07161 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
07162                                                   PFORMAT_STRING pFormat)
07163 {
07164     NDR_SCONTEXT ContextHandle;
07165     RPC_SYNTAX_IDENTIFIER *if_id = NULL;
07166     ULONG flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
07167 
07168     TRACE("(%p, %p)\n", pStubMsg, pFormat);
07169 
07170     align_pointer(&pStubMsg->Buffer, 4);
07171 
07172     if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)
07173     {
07174         ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n",
07175             pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength);
07176         RpcRaiseException(RPC_X_BAD_STUB_DATA);
07177     }
07178 
07179     if (pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE)
07180         flags |= RPC_CONTEXT_HANDLE_SERIALIZE;
07181     if (pFormat[1] & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
07182         flags |= RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
07183     if (pFormat[1] & NDR_STRICT_CONTEXT_HANDLE)
07184     {
07185         RPC_SERVER_INTERFACE *sif = pStubMsg->StubDesc->RpcInterfaceInformation;
07186         if_id = &sif->InterfaceId;
07187     }
07188 
07189     ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle,
07190                                            pStubMsg->Buffer,
07191                                            pStubMsg->RpcMsg->DataRepresentation,
07192                                            if_id, flags);
07193     pStubMsg->Buffer += cbNDRContext;
07194 
07195     return ContextHandle;
07196 }
07197 
07198 /***********************************************************************
07199  *           NdrCorrelationInitialize [RPCRT4.@]
07200  *
07201  * Initializes correlation validity checking.
07202  *
07203  * PARAMS
07204  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
07205  *  pMemory     [I] Pointer to memory to use as a cache.
07206  *  CacheSize   [I] Size of the memory pointed to by pMemory.
07207  *  Flags       [I] Reserved. Set to zero.
07208  *
07209  * RETURNS
07210  *  Nothing.
07211  */
07212 void WINAPI NdrCorrelationInitialize(PMIDL_STUB_MESSAGE pStubMsg, void *pMemory, ULONG CacheSize, ULONG Flags)
07213 {
07214     FIXME("(%p, %p, %d, 0x%x): stub\n", pStubMsg, pMemory, CacheSize, Flags);
07215     pStubMsg->fHasNewCorrDesc = TRUE;
07216 }
07217 
07218 /***********************************************************************
07219  *           NdrCorrelationPass [RPCRT4.@]
07220  *
07221  * Performs correlation validity checking.
07222  *
07223  * PARAMS
07224  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
07225  *
07226  * RETURNS
07227  *  Nothing.
07228  */
07229 void WINAPI NdrCorrelationPass(PMIDL_STUB_MESSAGE pStubMsg)
07230 {
07231     FIXME("(%p): stub\n", pStubMsg);
07232 }
07233 
07234 /***********************************************************************
07235  *           NdrCorrelationFree [RPCRT4.@]
07236  *
07237  * Frees any resources used while unmarshalling parameters that need
07238  * correlation validity checking.
07239  *
07240  * PARAMS
07241  *  pStubMsg    [I] MIDL_STUB_MESSAGE used during unmarshalling.
07242  *
07243  * RETURNS
07244  *  Nothing.
07245  */
07246 void WINAPI NdrCorrelationFree(PMIDL_STUB_MESSAGE pStubMsg)
07247 {
07248     FIXME("(%p): stub\n", pStubMsg);
07249 }

Generated on Mon May 28 2012 04:25:40 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.