[RPCRT4]
[reactos.git] / reactos / dll / win32 / rpcrt4 / ndr_marshall.c
index 37d286d..839a4ca 100644 (file)
 #include <string.h>
 #include <limits.h>
 
+#define NONAMELESSUNION
 #include "windef.h"
 #include "winbase.h"
 #include "winerror.h"
 
 #include "ndr_misc.h"
 #include "rpcndr.h"
+#include "ndrtypes.h"
 
 #include "wine/unicode.h"
 #include "wine/rpcfc.h"
@@ -102,9 +104,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
     } while(0)
 
 #define STD_OVERFLOW_CHECK(_Msg) do { \
-    TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
+    TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \
     if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
-        ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
+        ERR("buffer overflow %d bytes\n", (ULONG)(_Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength))); \
   } while (0)
 
 #define NDR_POINTER_ID_BASE 0x20000
@@ -112,6 +114,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
 #define NDR_TABLE_SIZE 128
 #define NDR_TABLE_MASK 127
 
+#define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL))
+
 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
@@ -122,6 +126,13 @@ static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsign
 static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
 static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
 
+static unsigned char *WINAPI NdrRangeMarshall(PMIDL_STUB_MESSAGE,unsigned char *, PFORMAT_STRING);
+static void WINAPI NdrRangeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
+static ULONG WINAPI NdrRangeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
+static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
+
+static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
+
 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
   0,
   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
@@ -540,7 +551,8 @@ PFORMAT_STRING ComputeConformanceOrVariance(
     }
     break;
   default:
-    FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
+    FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0);
+    goto finish_conf;
   }
 
   switch (pFormat[1]) {
@@ -927,7 +939,7 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
 
     if (type == RPC_FC_FP)
       NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id,
-                                base_ptr_val);
+                                *pPointer);
   }
 
   TRACE("pointer=%p\n", *pPointer);
@@ -991,9 +1003,8 @@ static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
 /***********************************************************************
  *           PointerMemorySize [internal]
  */
-static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
-                                       unsigned char *Buffer,
-                                       PFORMAT_STRING pFormat)
+static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
+                               unsigned char *Buffer, PFORMAT_STRING pFormat)
 {
   unsigned type = pFormat[0], attr = pFormat[1];
   PFORMAT_STRING desc;
@@ -1036,6 +1047,8 @@ static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
   }
 
   if (attr & RPC_FC_P_DEREF) {
+    ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void*));
+    pStubMsg->MemorySize += sizeof(void*);
     TRACE("deref\n");
   }
 
@@ -1332,8 +1345,8 @@ static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
 /***********************************************************************
  *           EmbeddedPointerMemorySize [internal]
  */
-static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
-                                               PFORMAT_STRING pFormat)
+static ULONG EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
+                                       PFORMAT_STRING pFormat)
 {
   unsigned char *Mark = pStubMsg->BufferMark;
   unsigned rep, count, stride;
@@ -1493,18 +1506,28 @@ unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
 
   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
 
-  /* Increment the buffer here instead of in PointerUnmarshall,
-   * as that is used by embedded pointers which already handle the incrementing
-   * the buffer, and shouldn't read any additional pointer data from the
-   * buffer */
-  if (*pFormat != RPC_FC_RP)
+  if (*pFormat == RPC_FC_RP)
   {
-    ALIGN_POINTER(pStubMsg->Buffer, 4);
     Buffer = pStubMsg->Buffer;
-    safe_buffer_increment(pStubMsg, 4);
+    /* Do the NULL ref pointer check here because embedded pointers can be
+     * NULL if the type the pointer is embedded in was allocated rather than
+     * being passed in by the client */
+    if (pStubMsg->IsClient && !*ppMemory)
+    {
+      ERR("NULL ref pointer is not allowed\n");
+      RpcRaiseException(RPC_X_NULL_REF_POINTER);
+    }
   }
   else
+  {
+    /* Increment the buffer here instead of in PointerUnmarshall,
+     * as that is used by embedded pointers which already handle the incrementing
+     * the buffer, and shouldn't read any additional pointer data from the
+     * buffer */
+    ALIGN_POINTER(pStubMsg->Buffer, 4);
     Buffer = pStubMsg->Buffer;
+    safe_buffer_increment(pStubMsg, 4);
+  }
 
   PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc);
 
@@ -1538,10 +1561,14 @@ void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
 ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
                                   PFORMAT_STRING pFormat)
 {
-  /* unsigned size = *(LPWORD)(pFormat+2); */
-  FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
-  PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
-  return 0;
+    unsigned char *Buffer = pStubMsg->Buffer;
+    if (*pFormat != RPC_FC_RP)
+    {
+        ALIGN_POINTER(pStubMsg->Buffer, 4);
+        safe_buffer_increment(pStubMsg, 4);
+    }
+    ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
+    return PointerMemorySize(pStubMsg, Buffer, pFormat);
 }
 
 /***********************************************************************
@@ -1755,7 +1782,7 @@ static inline void array_compute_and_size_conformance(
     break;
   case RPC_FC_C_CSTRING:
   case RPC_FC_C_WSTRING:
-    if (pFormat[0] == RPC_FC_C_CSTRING)
+    if (fc == RPC_FC_C_CSTRING)
     {
       TRACE("string=%s\n", debugstr_a((const char *)pMemory));
       pStubMsg->ActualCount = strlen((const char *)pMemory)+1;
@@ -1766,7 +1793,7 @@ static inline void array_compute_and_size_conformance(
       pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1;
     }
 
-    if (fc == RPC_FC_STRING_SIZED)
+    if (pFormat[1] == RPC_FC_STRING_SIZED)
       pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0);
     else
       pStubMsg->MaxCount = pStubMsg->ActualCount;
@@ -2552,8 +2579,8 @@ typedef struct
 } NDR_RANGE;
 #include "poppack.h"
 
-static unsigned long EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
-                                         PFORMAT_STRING pFormat)
+static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
+                                 PFORMAT_STRING pFormat)
 {
   switch (*pFormat) {
   case RPC_FC_STRUCT:
@@ -2614,8 +2641,8 @@ static unsigned long EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg,
 }
 
 
-static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
-                                               PFORMAT_STRING pFormat)
+static ULONG EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
+                                       PFORMAT_STRING pFormat)
 {
   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
 
@@ -2636,7 +2663,7 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
 {
   PFORMAT_STRING desc;
   NDR_MARSHALL m;
-  unsigned long size;
+  ULONG size;
 
   while (*pFormat != RPC_FC_END) {
     switch (*pFormat) {
@@ -2669,17 +2696,33 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
       safe_copy_to_buffer(pStubMsg, pMemory, 4);
       pMemory += 4;
       break;
+    case RPC_FC_FLOAT:
+      TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory);
+      safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float));
+      pMemory += sizeof(float);
+      break;
     case RPC_FC_HYPER:
       TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
       safe_copy_to_buffer(pStubMsg, pMemory, 8);
       pMemory += 8;
       break;
+    case RPC_FC_DOUBLE:
+      TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory);
+      safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double));
+      pMemory += sizeof(double);
+      break;
+    case RPC_FC_RP:
+    case RPC_FC_UP:
+    case RPC_FC_OP:
+    case RPC_FC_FP:
     case RPC_FC_POINTER:
     {
       unsigned char *saved_buffer;
       int pointer_buffer_mark_set = 0;
       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
       TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer);
+      if (*pFormat != RPC_FC_POINTER)
+        pPointer = pFormat;
       if (*pPointer != RPC_FC_RP)
         ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4);
       saved_buffer = pStubMsg->Buffer;
@@ -2701,10 +2744,16 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
       }
       TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer);
-      pPointer += 4;
-      pMemory += 4;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
+      pMemory += sizeof(void *);
       break;
     }
+    case RPC_FC_ALIGNM2:
+      ALIGN_POINTER(pMemory, 2);
+      break;
     case RPC_FC_ALIGNM4:
       ALIGN_POINTER(pMemory, 4);
       break;
@@ -2725,7 +2774,7 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
       pFormat += 2;
       desc = pFormat + *(const SHORT*)pFormat;
       size = EmbeddedComplexSize(pStubMsg, desc);
-      TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
+      TRACE("embedded complex (size=%d) <= %p\n", size, pMemory);
       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
       if (m)
       {
@@ -2761,7 +2810,7 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
 {
   PFORMAT_STRING desc;
   NDR_UNMARSHALL m;
-  unsigned long size;
+  ULONG size;
 
   while (*pFormat != RPC_FC_END) {
     switch (*pFormat) {
@@ -2795,16 +2844,32 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
       TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory);
       pMemory += 4;
       break;
+    case RPC_FC_FLOAT:
+      safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float));
+      TRACE("float=%f => %p\n", *(float*)pMemory, pMemory);
+      pMemory += sizeof(float);
+      break;
     case RPC_FC_HYPER:
       safe_copy_from_buffer(pStubMsg, pMemory, 8);
       TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory);
       pMemory += 8;
       break;
+    case RPC_FC_DOUBLE:
+      safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double));
+      TRACE("double=%f => %p\n", *(double*)pMemory, pMemory);
+      pMemory += sizeof(double);
+      break;
+    case RPC_FC_RP:
+    case RPC_FC_UP:
+    case RPC_FC_OP:
+    case RPC_FC_FP:
     case RPC_FC_POINTER:
     {
       unsigned char *saved_buffer;
       int pointer_buffer_mark_set = 0;
       TRACE("pointer => %p\n", pMemory);
+      if (*pFormat != RPC_FC_POINTER)
+        pPointer = pFormat;
       if (*pPointer != RPC_FC_RP)
         ALIGN_POINTER(pStubMsg->Buffer, 4);
       saved_buffer = pStubMsg->Buffer;
@@ -2826,10 +2891,16 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
         if (*pPointer != RPC_FC_RP)
           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
       }
-      pPointer += 4;
-      pMemory += 4;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
+      pMemory += sizeof(void *);
       break;
     }
+    case RPC_FC_ALIGNM2:
+      ALIGN_POINTER_CLEAR(pMemory, 2);
+      break;
     case RPC_FC_ALIGNM4:
       ALIGN_POINTER_CLEAR(pMemory, 4);
       break;
@@ -2851,7 +2922,7 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
       pFormat += 2;
       desc = pFormat + *(const SHORT*)pFormat;
       size = EmbeddedComplexSize(pStubMsg, desc);
-      TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
+      TRACE("embedded complex (size=%d) => %p\n", size, pMemory);
       if (fMustAlloc)
         /* we can't pass fMustAlloc=TRUE into the marshaller for this type
          * since the type is part of the memory block that is encompassed by
@@ -2893,7 +2964,7 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
 {
   PFORMAT_STRING desc;
   NDR_BUFFERSIZE m;
-  unsigned long size;
+  ULONG size;
 
   while (*pFormat != RPC_FC_END) {
     switch (*pFormat) {
@@ -2917,14 +2988,22 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_LONG:
     case RPC_FC_ULONG:
     case RPC_FC_ENUM32:
+    case RPC_FC_FLOAT:
       safe_buffer_length_increment(pStubMsg, 4);
       pMemory += 4;
       break;
     case RPC_FC_HYPER:
+    case RPC_FC_DOUBLE:
       safe_buffer_length_increment(pStubMsg, 8);
       pMemory += 8;
       break;
+    case RPC_FC_RP:
+    case RPC_FC_UP:
+    case RPC_FC_OP:
+    case RPC_FC_FP:
     case RPC_FC_POINTER:
+      if (*pFormat != RPC_FC_POINTER)
+        pPointer = pFormat;
       if (!pStubMsg->IgnoreEmbeddedPointers)
       {
         int saved_buffer_length = pStubMsg->BufferLength;
@@ -2941,8 +3020,14 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
         ALIGN_LENGTH(pStubMsg->BufferLength, 4);
         safe_buffer_length_increment(pStubMsg, 4);
       }
-      pPointer += 4;
-      pMemory += 4;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
+      pMemory += sizeof(void*);
+      break;
+    case RPC_FC_ALIGNM2:
+      ALIGN_POINTER(pMemory, 2);
       break;
     case RPC_FC_ALIGNM4:
       ALIGN_POINTER(pMemory, 4);
@@ -2998,7 +3083,7 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
 {
   PFORMAT_STRING desc;
   NDR_FREE m;
-  unsigned long size;
+  ULONG size;
 
   while (*pFormat != RPC_FC_END) {
     switch (*pFormat) {
@@ -3017,15 +3102,29 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_ULONG:
     case RPC_FC_ENUM16:
     case RPC_FC_ENUM32:
+    case RPC_FC_FLOAT:
       pMemory += 4;
       break;
     case RPC_FC_HYPER:
+    case RPC_FC_DOUBLE:
       pMemory += 8;
       break;
+    case RPC_FC_RP:
+    case RPC_FC_UP:
+    case RPC_FC_OP:
+    case RPC_FC_FP:
     case RPC_FC_POINTER:
+      if (*pFormat != RPC_FC_POINTER)
+        pPointer = pFormat;
       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
-      pPointer += 4;
-      pMemory += 4;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
+      pMemory += sizeof(void *);
+      break;
+    case RPC_FC_ALIGNM2:
+      ALIGN_POINTER(pMemory, 2);
       break;
     case RPC_FC_ALIGNM4:
       ALIGN_POINTER(pMemory, 4);
@@ -3073,12 +3172,12 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
   return pMemory;
 }
 
-static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
-                                             PFORMAT_STRING pFormat,
-                                             PFORMAT_STRING pPointer)
+static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
+                                     PFORMAT_STRING pFormat,
+                                     PFORMAT_STRING pPointer)
 {
   PFORMAT_STRING desc;
-  unsigned long size = 0;
+  ULONG size = 0;
 
   while (*pFormat != RPC_FC_END) {
     switch (*pFormat) {
@@ -3102,17 +3201,25 @@ static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_LONG:
     case RPC_FC_ULONG:
     case RPC_FC_ENUM32:
+    case RPC_FC_FLOAT:
       size += 4;
       safe_buffer_increment(pStubMsg, 4);
       break;
     case RPC_FC_HYPER:
+    case RPC_FC_DOUBLE:
       size += 8;
       safe_buffer_increment(pStubMsg, 8);
       break;
+    case RPC_FC_RP:
+    case RPC_FC_UP:
+    case RPC_FC_OP:
+    case RPC_FC_FP:
     case RPC_FC_POINTER:
     {
       unsigned char *saved_buffer;
       int pointer_buffer_mark_set = 0;
+      if (*pFormat != RPC_FC_POINTER)
+        pPointer = pFormat;
       if (*pPointer != RPC_FC_RP)
         ALIGN_POINTER(pStubMsg->Buffer, 4);
       saved_buffer = pStubMsg->Buffer;
@@ -3135,17 +3242,21 @@ static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
         if (*pPointer != RPC_FC_RP)
           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
       }
-      pPointer += 4;
-      size += 4;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
+      size += sizeof(void *);
       break;
     }
+    case RPC_FC_ALIGNM2:
+      ALIGN_LENGTH(size, 2);
+      break;
     case RPC_FC_ALIGNM4:
       ALIGN_LENGTH(size, 4);
-      ALIGN_POINTER(pStubMsg->Buffer, 4);
       break;
     case RPC_FC_ALIGNM8:
       ALIGN_LENGTH(size, 8);
-      ALIGN_POINTER(pStubMsg->Buffer, 8);
       break;
     case RPC_FC_STRUCTPAD1:
     case RPC_FC_STRUCTPAD2:
@@ -3174,11 +3285,10 @@ static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
   return size;
 }
 
-unsigned long ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,
-                                PFORMAT_STRING pFormat)
+ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
 {
   PFORMAT_STRING desc;
-  unsigned long size = 0;
+  ULONG size = 0;
 
   while (*pFormat != RPC_FC_END) {
     switch (*pFormat) {
@@ -3197,13 +3307,24 @@ unsigned long ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_ULONG:
     case RPC_FC_ENUM16:
     case RPC_FC_ENUM32:
+    case RPC_FC_FLOAT:
       size += 4;
       break;
     case RPC_FC_HYPER:
+    case RPC_FC_DOUBLE:
       size += 8;
       break;
+    case RPC_FC_RP:
+    case RPC_FC_UP:
+    case RPC_FC_OP:
+    case RPC_FC_FP:
     case RPC_FC_POINTER:
       size += sizeof(void *);
+      if (*pFormat != RPC_FC_POINTER)
+        pFormat += 4;
+      break;
+    case RPC_FC_ALIGNM2:
+      ALIGN_LENGTH(size, 2);
       break;
     case RPC_FC_ALIGNM4:
       ALIGN_LENGTH(size, 4);
@@ -3259,18 +3380,18 @@ unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
   {
     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
     /* save buffer length */
-    unsigned long saved_buffer_length = pStubMsg->BufferLength;
+    ULONG saved_buffer_length = pStubMsg->BufferLength;
 
     /* get the buffer pointer after complex array data, but before
      * pointer data */
-    pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
+    pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
     pStubMsg->IgnoreEmbeddedPointers = 1;
     NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat);
     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
 
     /* save it for use by embedded pointer code later */
-    pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
-    TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer);
+    pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
+    TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - pStubMsg->Buffer));
     pointer_buffer_mark_set = 1;
 
     /* restore the original buffer length */
@@ -3289,7 +3410,7 @@ unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
 
   if (conf_array)
   {
-    unsigned long struct_size = ComplexStructSize(pStubMsg, pFormat);
+    ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
     array_compute_and_write_conformance(conf_array[0], pStubMsg,
                                         pMemory + struct_size, conf_array);
     /* these could be changed in ComplexMarshall so save them for later */
@@ -3356,7 +3477,7 @@ unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
 
     /* save it for use by embedded pointer code later */
     pStubMsg->PointerBufferMark = pStubMsg->Buffer;
-    TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer));
+    TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->PointerBufferMark - saved_buffer));
     pointer_buffer_mark_set = 1;
 
     /* restore the original buffer */
@@ -3433,7 +3554,7 @@ void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
   if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength)
   {
     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
-    unsigned long saved_buffer_length = pStubMsg->BufferLength;
+    ULONG saved_buffer_length = pStubMsg->BufferLength;
 
     /* get the buffer length after complex struct data, but before
      * pointer data */
@@ -3444,7 +3565,7 @@ void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
     /* save it for use by embedded pointer code later */
     pStubMsg->PointerLength = pStubMsg->BufferLength;
     pointer_length_set = 1;
-    TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length);
+    TRACE("difference = 0x%x\n", pStubMsg->PointerLength - saved_buffer_length);
 
     /* restore the original buffer length */
     pStubMsg->BufferLength = saved_buffer_length;
@@ -3460,7 +3581,7 @@ void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
 
   if (conf_array)
   {
-    unsigned long struct_size = ComplexStructSize(pStubMsg, pFormat);
+    ULONG struct_size = ComplexStructSize(pStubMsg, pFormat);
     array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size,
                                        conf_array);
 
@@ -3818,21 +3939,21 @@ unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
     /* save buffer fields that may be changed by buffer sizer functions
      * and that may be needed later on */
     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
-    unsigned long saved_buffer_length = pStubMsg->BufferLength;
-    unsigned long saved_max_count = pStubMsg->MaxCount;
-    unsigned long saved_offset = pStubMsg->Offset;
-    unsigned long saved_actual_count = pStubMsg->ActualCount;
+    ULONG saved_buffer_length = pStubMsg->BufferLength;
+    ULONG_PTR saved_max_count = pStubMsg->MaxCount;
+    ULONG saved_offset = pStubMsg->Offset;
+    ULONG saved_actual_count = pStubMsg->ActualCount;
 
     /* get the buffer pointer after complex array data, but before
      * pointer data */
-    pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart;
+    pStubMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
     pStubMsg->IgnoreEmbeddedPointers = 1;
     NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat);
     pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
 
     /* save it for use by embedded pointer code later */
-    pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength;
-    TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart);
+    pStubMsg->PointerBufferMark = (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength;
+    TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer));
     pointer_buffer_mark_set = 1;
 
     /* restore fields */
@@ -3910,7 +4031,7 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
   size = pStubMsg->MemorySize;
   pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded;
 
-  TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer));
+  TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer));
   if (!pStubMsg->PointerBufferMark)
   {
     /* save it for use by embedded pointer code later */
@@ -3974,10 +4095,10 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
     /* save buffer fields that may be changed by buffer sizer functions
      * and that may be needed later on */
     int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers;
-    unsigned long saved_buffer_length = pStubMsg->BufferLength;
-    unsigned long saved_max_count = pStubMsg->MaxCount;
-    unsigned long saved_offset = pStubMsg->Offset;
-    unsigned long saved_actual_count = pStubMsg->ActualCount;
+    ULONG saved_buffer_length = pStubMsg->BufferLength;
+    ULONG_PTR saved_max_count = pStubMsg->MaxCount;
+    ULONG saved_offset = pStubMsg->Offset;
+    ULONG saved_actual_count = pStubMsg->ActualCount;
 
     /* get the buffer pointer after complex array data, but before
      * pointer data */
@@ -4232,7 +4353,7 @@ void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
   unsigned index = *(const WORD*)&pFormat[2];
   DWORD bufsize = *(const WORD*)&pFormat[6];
   USER_MARSHAL_CB umcb;
-  unsigned long saved_buffer_length = 0;
+  ULONG saved_buffer_length = 0;
 
   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
   TRACE("index=%d\n", index);
@@ -4330,6 +4451,56 @@ void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
     &umcb.Flags, pMemory);
 }
 
+/***********************************************************************
+ *           NdrGetUserMarshalInfo [RPCRT4.@]
+ */
+RPC_STATUS RPC_ENTRY NdrGetUserMarshalInfo(ULONG *flags, ULONG level, NDR_USER_MARSHAL_INFO *umi)
+{
+    USER_MARSHAL_CB *umcb = CONTAINING_RECORD(flags, USER_MARSHAL_CB, Flags);
+
+    TRACE("(%p,%u,%p)\n", flags, level, umi);
+
+    if (level != 1)
+        return RPC_S_INVALID_ARG;
+
+    memset(&umi->u1.Level1, 0, sizeof(umi->u1.Level1));
+    umi->InformationLevel = level;
+
+    if (umcb->Signature != USER_MARSHAL_CB_SIGNATURE)
+        return RPC_S_INVALID_ARG;
+
+    umi->u1.Level1.pfnAllocate = umcb->pStubMsg->pfnAllocate;
+    umi->u1.Level1.pfnFree = umcb->pStubMsg->pfnFree;
+    umi->u1.Level1.pRpcChannelBuffer = umcb->pStubMsg->pRpcChannelBuffer;
+
+    switch (umcb->CBType)
+    {
+    case USER_MARSHAL_CB_MARSHALL:
+    case USER_MARSHAL_CB_UNMARSHALL:
+    {
+        RPC_MESSAGE *msg = umcb->pStubMsg->RpcMsg;
+        unsigned char *buffer_start = msg->Buffer;
+        unsigned char *buffer_end =
+            (unsigned char *)msg->Buffer + msg->BufferLength;
+
+        if (umcb->pStubMsg->Buffer < buffer_start ||
+            umcb->pStubMsg->Buffer > buffer_end)
+            return ERROR_INVALID_USER_BUFFER;
+
+        umi->u1.Level1.Buffer = umcb->pStubMsg->Buffer;
+        umi->u1.Level1.BufferSize = buffer_end - umcb->pStubMsg->Buffer;
+        break;
+    }
+    case USER_MARSHAL_CB_BUFFER_SIZE:
+    case USER_MARSHAL_CB_FREE:
+        break;
+    default:
+        WARN("unrecognised CBType %d\n", umcb->CBType);
+    }
+
+    return RPC_S_OK;
+}
+
 /***********************************************************************
  *           NdrClearOutParameters [RPCRT4.@]
  */
@@ -4836,7 +5007,7 @@ typedef struct
 {
     unsigned char type;
     unsigned char alignment;
-    unsigned long total_size;
+    ULONG total_size;
 } NDR_LGFARRAY_FORMAT;
 #include "poppack.h"
 
@@ -4848,7 +5019,7 @@ unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
                                 PFORMAT_STRING pFormat)
 {
     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
-    unsigned long total_size;
+    ULONG total_size;
 
     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
 
@@ -4891,7 +5062,7 @@ unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
                                 unsigned char fMustAlloc)
 {
     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
-    unsigned long total_size;
+    ULONG total_size;
     unsigned char *saved_buffer;
 
     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
@@ -4946,7 +5117,7 @@ void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
                                 PFORMAT_STRING pFormat)
 {
     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
-    unsigned long total_size;
+    ULONG total_size;
 
     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
 
@@ -5358,7 +5529,7 @@ static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory)
 }
 
 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
-                                                             unsigned long discriminant,
+                                                             ULONG discriminant,
                                                              PFORMAT_STRING pFormat)
 {
     unsigned short num_arms, arm, type;
@@ -5381,13 +5552,13 @@ static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE
     {
         if(type == 0xffff)
         {
-            ERR("no arm for 0x%lx and no default case\n", discriminant);
+            ERR("no arm for 0x%x and no default case\n", discriminant);
             RpcRaiseException(RPC_S_INVALID_TAG);
             return NULL;
         }
         if(type == 0)
         {
-            TRACE("falling back to empty default case for 0x%lx\n", discriminant);
+            TRACE("falling back to empty default case for 0x%x\n", discriminant);
             return NULL;
         }
     }
@@ -5492,7 +5663,6 @@ static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg,
             case RPC_FC_UP:
             case RPC_FC_OP:
             case RPC_FC_FP:
-                **(void***)ppMemory = NULL;
                 ALIGN_POINTER(pStubMsg->Buffer, 4);
                 saved_buffer = pStubMsg->Buffer;
                 if (pStubMsg->PointerBufferMark)
@@ -5616,8 +5786,8 @@ static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg,
                 ALIGN_POINTER(pStubMsg->Buffer, 4);
                 saved_buffer = pStubMsg->Buffer;
                 safe_buffer_increment(pStubMsg, 4);
-                ALIGN_LENGTH(pStubMsg->MemorySize, 4);
-                pStubMsg->MemorySize += 4;
+                ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
+                pStubMsg->MemorySize += sizeof(void *);
                 if (!pStubMsg->IgnoreEmbeddedPointers)
                     PointerMemorySize(pStubMsg, saved_buffer, pFormat);
                 break;
@@ -5727,10 +5897,18 @@ unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubM
     if (fMustAlloc)
         *ppMemory = NdrAllocate(pStubMsg, size);
 
+    /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
+     * since the arm is part of the memory block that is encompassed by
+     * the whole union. Memory is forced to allocate when pointers
+     * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
+     * clearing the memory we pass in to the unmarshaller */
+    if (fMustAlloc)
+        memset(*ppMemory, 0, size);
+
     NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE);
     pMemoryArm = *ppMemory + increment;
 
-    return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc);
+    return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, FALSE);
 }
 
 /***********************************************************************
@@ -5834,10 +6012,10 @@ unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStub
     return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat);
 }
 
-static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
+static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
                                     PFORMAT_STRING *ppFormat)
 {
-    long discriminant = 0;
+    LONG discriminant = 0;
 
     switch(**ppFormat)
     {
@@ -5854,6 +6032,7 @@ static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_WCHAR:
     case RPC_FC_SHORT:
     case RPC_FC_USHORT:
+    case RPC_FC_ENUM16:
     {
         USHORT d;
         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
@@ -5890,7 +6069,7 @@ unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pSt
                                 PFORMAT_STRING pFormat,
                                 unsigned char fMustAlloc)
 {
-    long discriminant;
+    LONG discriminant;
     unsigned short size;
 
     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
@@ -5898,7 +6077,7 @@ unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pSt
 
     /* Unmarshall discriminant */
     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
-    TRACE("unmarshalled discriminant %lx\n", discriminant);
+    TRACE("unmarshalled discriminant %x\n", discriminant);
 
     pFormat += *(const SHORT*)pFormat;
 
@@ -5909,7 +6088,15 @@ unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pSt
     if (fMustAlloc)
         *ppMemory = NdrAllocate(pStubMsg, size);
 
-    return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc);
+    /* we can't pass fMustAlloc=TRUE into the marshaller for the arm
+     * since the arm is part of the memory block that is encompassed by
+     * the whole union. Memory is forced to allocate when pointers
+     * are set to NULL, so we emulate that part of fMustAlloc=TRUE by
+     * clearing the memory we pass in to the unmarshaller */
+    if (fMustAlloc)
+        memset(*ppMemory, 0, size);
+
+    return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, FALSE);
 }
 
 /***********************************************************************
@@ -6002,10 +6189,10 @@ void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
 }
 
 /***********************************************************************
- *           NdrByteCountPointerMemorySize [RPCRT4.@]
+ *           NdrByteCountPointerMemorySize [internal]
  */
-ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
-                                PFORMAT_STRING pFormat)
+static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
+                                                  PFORMAT_STRING pFormat)
 {
     FIXME("stub\n");
     return 0;
@@ -6077,7 +6264,7 @@ void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
 /***********************************************************************
  *           NdrRangeMarshall [internal]
  */
-unsigned char *WINAPI NdrRangeMarshall(
+static unsigned char *WINAPI NdrRangeMarshall(
     PMIDL_STUB_MESSAGE pStubMsg,
     unsigned char *pMemory,
     PFORMAT_STRING pFormat)
@@ -6100,7 +6287,7 @@ unsigned char *WINAPI NdrRangeMarshall(
 }
 
 /***********************************************************************
- *           NdrRangeUnmarshall
+ *           NdrRangeUnmarshall [RPCRT4.@]
  */
 unsigned char *WINAPI NdrRangeUnmarshall(
     PMIDL_STUB_MESSAGE pStubMsg,
@@ -6124,68 +6311,68 @@ unsigned char *WINAPI NdrRangeUnmarshall(
     TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n",
         base_type, pRange->low_value, pRange->high_value);
 
-#define RANGE_UNMARSHALL(type, format_spec) \
+#define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \
     do \
     { \
-        ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(wire_type)); \
         if (!fMustAlloc && !*ppMemory) \
             fMustAlloc = TRUE; \
         if (fMustAlloc) \
-            *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \
-        if (pStubMsg->Buffer + sizeof(type) > pStubMsg->BufferEnd) \
+            *ppMemory = NdrAllocate(pStubMsg, sizeof(mem_type)); \
+        if (pStubMsg->Buffer + sizeof(wire_type) > pStubMsg->BufferEnd) \
         { \
             ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \
                 pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \
             RpcRaiseException(RPC_X_BAD_STUB_DATA); \
         } \
-        if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \
-            (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \
+        if ((*(wire_type *)pStubMsg->Buffer < (mem_type)pRange->low_value) || \
+            (*(wire_type *)pStubMsg->Buffer > (mem_type)pRange->high_value)) \
         { \
             ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \
-                *(type *)pStubMsg->Buffer, (type)pRange->low_value, \
-                (type)pRange->high_value); \
+                *(wire_type *)pStubMsg->Buffer, (mem_type)pRange->low_value, \
+                (mem_type)pRange->high_value); \
             RpcRaiseException(RPC_S_INVALID_BOUND); \
             return NULL; \
         } \
         TRACE("*ppMemory: %p\n", *ppMemory); \
-        **(type **)ppMemory = *(type *)pStubMsg->Buffer; \
-        pStubMsg->Buffer += sizeof(type); \
+        **(mem_type **)ppMemory = *(wire_type *)pStubMsg->Buffer; \
+        pStubMsg->Buffer += sizeof(wire_type); \
     } while (0)
 
     switch(base_type)
     {
     case RPC_FC_CHAR:
     case RPC_FC_SMALL:
-        RANGE_UNMARSHALL(UCHAR, "%d");
+        RANGE_UNMARSHALL(UCHAR, UCHAR, "%d");
         TRACE("value: 0x%02x\n", **ppMemory);
         break;
     case RPC_FC_BYTE:
     case RPC_FC_USMALL:
-        RANGE_UNMARSHALL(CHAR, "%u");
+        RANGE_UNMARSHALL(CHAR, CHAR, "%u");
         TRACE("value: 0x%02x\n", **ppMemory);
         break;
     case RPC_FC_WCHAR: /* FIXME: valid? */
     case RPC_FC_USHORT:
-        RANGE_UNMARSHALL(USHORT, "%u");
+        RANGE_UNMARSHALL(USHORT, USHORT, "%u");
         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
         break;
     case RPC_FC_SHORT:
-        RANGE_UNMARSHALL(SHORT, "%d");
+        RANGE_UNMARSHALL(SHORT, SHORT, "%d");
         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
         break;
     case RPC_FC_LONG:
-        RANGE_UNMARSHALL(LONG, "%d");
+    case RPC_FC_ENUM32:
+        RANGE_UNMARSHALL(LONG, LONG, "%d");
         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
         break;
     case RPC_FC_ULONG:
-        RANGE_UNMARSHALL(ULONG, "%u");
+        RANGE_UNMARSHALL(ULONG, ULONG, "%u");
         TRACE("value: 0x%08x\n", **(ULONG **)ppMemory);
         break;
     case RPC_FC_ENUM16:
-    case RPC_FC_ENUM32:
-        FIXME("Unhandled enum type\n");
+        RANGE_UNMARSHALL(UINT, USHORT, "%u");
+        TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
         break;
-    case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */
     case RPC_FC_FLOAT:
     case RPC_FC_DOUBLE:
     case RPC_FC_HYPER:
@@ -6200,7 +6387,7 @@ unsigned char *WINAPI NdrRangeUnmarshall(
 /***********************************************************************
  *           NdrRangeBufferSize [internal]
  */
-void WINAPI NdrRangeBufferSize(
+static void WINAPI NdrRangeBufferSize(
     PMIDL_STUB_MESSAGE pStubMsg,
     unsigned char *pMemory,
     PFORMAT_STRING pFormat)
@@ -6223,7 +6410,7 @@ void WINAPI NdrRangeBufferSize(
 /***********************************************************************
  *           NdrRangeMemorySize [internal]
  */
-ULONG WINAPI NdrRangeMemorySize(
+static ULONG WINAPI NdrRangeMemorySize(
     PMIDL_STUB_MESSAGE pStubMsg,
     PFORMAT_STRING pFormat)
 {
@@ -6244,7 +6431,7 @@ ULONG WINAPI NdrRangeMemorySize(
 /***********************************************************************
  *           NdrRangeFree [internal]
  */
-void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
+static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg,
                                 unsigned char *pMemory,
                                 PFORMAT_STRING pFormat)
 {
@@ -6483,36 +6670,51 @@ static ULONG WINAPI NdrBaseTypeMemorySize(
     case RPC_FC_WCHAR:
     case RPC_FC_SHORT:
     case RPC_FC_USHORT:
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
         safe_buffer_increment(pStubMsg, sizeof(USHORT));
+        ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(USHORT));
         pStubMsg->MemorySize += sizeof(USHORT);
         return sizeof(USHORT);
     case RPC_FC_LONG:
     case RPC_FC_ULONG:
     case RPC_FC_ENUM32:
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
         safe_buffer_increment(pStubMsg, sizeof(ULONG));
+        ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONG));
         pStubMsg->MemorySize += sizeof(ULONG);
         return sizeof(ULONG);
     case RPC_FC_FLOAT:
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
         safe_buffer_increment(pStubMsg, sizeof(float));
+        ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(float));
         pStubMsg->MemorySize += sizeof(float);
         return sizeof(float);
     case RPC_FC_DOUBLE:
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
         safe_buffer_increment(pStubMsg, sizeof(double));
+        ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(double));
         pStubMsg->MemorySize += sizeof(double);
         return sizeof(double);
     case RPC_FC_HYPER:
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
         safe_buffer_increment(pStubMsg, sizeof(ULONGLONG));
+        ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONGLONG));
         pStubMsg->MemorySize += sizeof(ULONGLONG);
         return sizeof(ULONGLONG);
     case RPC_FC_ERROR_STATUS_T:
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(error_status_t));
         safe_buffer_increment(pStubMsg, sizeof(error_status_t));
+        ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(error_status_t));
         pStubMsg->MemorySize += sizeof(error_status_t);
         return sizeof(error_status_t);
     case RPC_FC_ENUM16:
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
         safe_buffer_increment(pStubMsg, sizeof(USHORT));
+        ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(UINT));
         pStubMsg->MemorySize += sizeof(UINT);
         return sizeof(UINT);
     case RPC_FC_IGNORE:
+        ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *));
         pStubMsg->MemorySize += sizeof(void *);
         return sizeof(void *);
     default:
@@ -6569,10 +6771,19 @@ static unsigned char *WINAPI NdrContextHandleMarshall(
     }
     TRACE("flags: 0x%02x\n", pFormat[1]);
 
-    if (pFormat[1] & 0x80)
-        NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
+    if (pStubMsg->IsClient)
+    {
+        if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
+            NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE);
+        else
+            NdrClientContextMarshall(pStubMsg, pMemory, FALSE);
+    }
     else
-        NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE);
+    {
+        NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
+        NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
+        NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
+    }
 
     return NULL;
 }
@@ -6596,10 +6807,22 @@ static unsigned char *WINAPI NdrContextHandleUnmarshall(
     }
     TRACE("flags: 0x%02x\n", pFormat[1]);
 
-    /* [out]-only or [ret] param */
-    if ((pFormat[1] & 0x60) == 0x20)
-        **(NDR_CCONTEXT **)ppMemory = NULL;
-    NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
+    if (pStubMsg->IsClient)
+    {
+        /* [out]-only or [ret] param */
+        if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT)
+            **(NDR_CCONTEXT **)ppMemory = NULL;
+        NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle);
+    }
+    else
+    {
+        NDR_SCONTEXT ctxt;
+        ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat);
+        if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR)
+            *(void **)ppMemory = NDRSContextValue(ctxt);
+        else
+            *(void **)ppMemory = *NDRSContextValue(ctxt);
+    }
 
     return NULL;
 }