sync with trunk r46493
[reactos.git] / dll / win32 / rpcrt4 / ndr_marshall.c
index d1b57fd..9946bd1 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "ndr_misc.h"
 #include "rpcndr.h"
+#include "ndrtypes.h"
 
 #include "wine/unicode.h"
 #include "wine/rpcfc.h"
@@ -113,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);
@@ -548,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]) {
@@ -935,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);
@@ -1778,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;
@@ -1789,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;
@@ -2692,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;
@@ -2724,7 +2744,10 @@ 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;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
       pMemory += sizeof(void *);
       break;
     }
@@ -2821,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;
@@ -2852,7 +2891,10 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
         if (*pPointer != RPC_FC_RP)
           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
       }
-      pPointer += 4;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
       pMemory += sizeof(void *);
       break;
     }
@@ -2946,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;
@@ -2970,7 +3020,10 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
         ALIGN_LENGTH(pStubMsg->BufferLength, 4);
         safe_buffer_length_increment(pStubMsg, 4);
       }
-      pPointer += 4;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
       pMemory += sizeof(void*);
       break;
     case RPC_FC_ALIGNM2:
@@ -3049,14 +3102,25 @@ 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;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
       pMemory += sizeof(void *);
       break;
     case RPC_FC_ALIGNM2:
@@ -3137,17 +3201,25 @@ static ULONG 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;
@@ -3170,7 +3242,10 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
         if (*pPointer != RPC_FC_RP)
           safe_buffer_increment(pStubMsg, 4); /* for pointer ID */
       }
-      pPointer += 4;
+      if (*pFormat == RPC_FC_POINTER)
+        pPointer += 4;
+      else
+        pFormat += 4;
       size += sizeof(void *);
       break;
     }
@@ -3232,13 +3307,21 @@ ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
     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);
@@ -6687,10 +6770,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, pMemory, FALSE);
+    {
+        NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory);
+        NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]];
+        NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat);
+    }
 
     return NULL;
 }
@@ -6714,10 +6806,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;
 }