Sync to Wine-0_9_10:
authorAleksey Bragin <aleksey@reactos.org>
Mon, 20 Mar 2006 21:52:24 +0000 (21:52 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Mon, 20 Mar 2006 21:52:24 +0000 (21:52 +0000)
Robert Shearman <rob@codeweavers.com>
- ndrtypes.h added into reactos/include
- too many changes to paste here. Look at the url below, checking all changes done after Wine-0_9_5 tag (including Wine-0_9_10 as the last one)
- http://cvs.winehq.com/cvsweb/wine/dlls/rpcrt4/?cvsroot=home/wine

svn path=/trunk/; revision=21362

14 files changed:
reactos/dll/win32/rpcrt4/cproxy.c
reactos/dll/win32/rpcrt4/cpsf.c
reactos/dll/win32/rpcrt4/cpsf.h
reactos/dll/win32/rpcrt4/cstub.c
reactos/dll/win32/rpcrt4/ndr_marshall.c
reactos/dll/win32/rpcrt4/ndr_midl.c
reactos/dll/win32/rpcrt4/ndr_misc.h
reactos/dll/win32/rpcrt4/ndr_ole.c
reactos/dll/win32/rpcrt4/ndr_stubless.c
reactos/dll/win32/rpcrt4/rpc_message.c
reactos/dll/win32/rpcrt4/rpcrt4.spec
reactos/include/ndrtypes.h [new file with mode: 0644]
reactos/include/rpcndr.h
reactos/include/rpcnterr.h

index c2d71f9..f045e0c 100644 (file)
@@ -104,7 +104,7 @@ static HRESULT WINAPI ObjectStubless(DWORD index)
   unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST;
   TRACE("(%p)->(%ld)([%d bytes]) ret=%08lx\n", iface, index, bytes, *(DWORD*)(args+bytes));
 
-  return RPCRT4_NdrClientCall2(This->stubless->pStubDesc, fs, args);
+  return NdrClientCall2(This->stubless->pStubDesc, fs, args);
 }
 
 #else  /* __i386__ */
@@ -119,20 +119,21 @@ struct StublessThunk { int dummy; };
 
 HRESULT WINAPI StdProxy_Construct(REFIID riid,
                                  LPUNKNOWN pUnkOuter,
-                                 PCInterfaceName name,
-                                 CInterfaceProxyVtbl *vtbl,
-                                 CInterfaceStubVtbl *svtbl,
+                                 const ProxyFileInfo *ProxyInfo,
+                                 int Index,
                                  LPPSFACTORYBUFFER pPSFactory,
                                  LPRPCPROXYBUFFER *ppProxy,
                                  LPVOID *ppvObj)
 {
   StdProxyImpl *This;
   const MIDL_STUBLESS_PROXY_INFO *stubless = NULL;
+  PCInterfaceName name = ProxyInfo->pNamesArray[Index];
+  CInterfaceProxyVtbl *vtbl = ProxyInfo->pProxyVtblList[Index];
 
   TRACE("(%p,%p,%p,%p,%p) %s\n", pUnkOuter, vtbl, pPSFactory, ppProxy, ppvObj, name);
 
-  /* I can't find any other way to detect stubless proxies than this hack */
-  if (!IsEqualGUID(vtbl->header.piid, riid)) {
+  /* TableVersion = 2 means it is the stubless version of CInterfaceProxyVtbl */
+  if (ProxyInfo->TableVersion > 1) {
     stubless = *(const void **)vtbl;
     vtbl = (CInterfaceProxyVtbl *)((const void **)vtbl + 1);
     TRACE("stubless=%p\n", stubless);
@@ -150,11 +151,12 @@ HRESULT WINAPI StdProxy_Construct(REFIID riid,
   if (!This) return E_OUTOFMEMORY;
 
   if (stubless) {
-    unsigned i, count = svtbl->header.DispatchTableCount;
+    CInterfaceStubVtbl *svtbl = ProxyInfo->pStubVtblList[Index];
+    unsigned long i, count = svtbl->header.DispatchTableCount;
     /* Maybe the original vtbl is just modified directly to point at
      * ObjectStublessClientXXX thunks in real Windows, but I don't like it
      */
-    TRACE("stubless thunks: count=%d\n", count);
+    TRACE("stubless thunks: count=%ld\n", count);
     This->thunks = HeapAlloc(GetProcessHeap(),0,sizeof(struct StublessThunk)*count);
     This->PVtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID)*count);
     for (i=0; i<count; i++) {
@@ -162,7 +164,7 @@ HRESULT WINAPI StdProxy_Construct(REFIID riid,
       if (vtbl->Vtbl[i] == (LPVOID)-1) {
         PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i];
         unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST;
-        TRACE("method %d: stacksize=%d\n", i, bytes);
+        TRACE("method %ld: stacksize=%d\n", i, bytes);
         FILL_STUBLESS(thunk, i, bytes)
         This->PVtbl[i] = thunk;
       }
@@ -186,7 +188,11 @@ HRESULT WINAPI StdProxy_Construct(REFIID riid,
   This->pChannel = NULL;
   *ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl;
   *ppvObj = &This->PVtbl;
-  IUnknown_AddRef((IUnknown *)*ppvObj);
+  /* if there is no outer unknown then the caller will control the lifetime
+   * of the proxy object through the proxy buffer, so no need to increment the
+   * ref count of the proxy object */
+  if (pUnkOuter)
+    IUnknown_AddRef((IUnknown *)*ppvObj);
   IPSFactoryBuffer_AddRef(pPSFactory);
 
   return S_OK;
index 3f0190c..44bb5a9 100644 (file)
@@ -95,9 +95,7 @@ static HRESULT WINAPI CStdPSFactory_CreateProxy(LPPSFACTORYBUFFER iface,
        debugstr_guid(riid),ppProxy,ppv);
   if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))
     return E_NOINTERFACE;
-  return StdProxy_Construct(riid, pUnkOuter, ProxyInfo->pNamesArray[Index],
-                            ProxyInfo->pProxyVtblList[Index],
-                            ProxyInfo->pStubVtblList[Index], iface, ppProxy, ppv);
+  return StdProxy_Construct(riid, pUnkOuter, ProxyInfo, Index, iface, ppProxy, ppv);
 }
 
 static HRESULT WINAPI CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface,
@@ -139,9 +137,24 @@ HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv,
 
   *ppv = NULL;
   if (!pPSFactoryBuffer->lpVtbl) {
+    const ProxyFileInfo **pProxyFileList2;
     pPSFactoryBuffer->lpVtbl = &CStdPSFactory_Vtbl;
     pPSFactoryBuffer->RefCount = 0;
     pPSFactoryBuffer->pProxyFileList = pProxyFileList;
+    for (pProxyFileList2 = pProxyFileList; *pProxyFileList2; pProxyFileList2++) {
+      int i;
+      for (i = 0; i < (*pProxyFileList2)->TableSize; i++) {
+        /* FIXME: i think that different vtables should be copied for
+         * async interfaces */
+        void * const *pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Vtbl;
+        void **pRpcStubVtbl = (void **)&(*pProxyFileList2)->pStubVtblList[i]->Vtbl;
+        int j;
+
+        for (j = 0; j < sizeof(IRpcStubBufferVtbl)/sizeof(void *); j++)
+          if (!pRpcStubVtbl[j])
+            pRpcStubVtbl[j] = pSrcRpcStubVtbl[j];
+      }
+    }
   }
   if (IsEqualGUID(rclsid, pclsid))
     return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv);
index 60364d3..cf1572b 100644 (file)
@@ -23,9 +23,8 @@
 
 HRESULT WINAPI StdProxy_Construct(REFIID riid,
                                  LPUNKNOWN pUnkOuter,
-                                 PCInterfaceName name,
-                                 CInterfaceProxyVtbl *vtbl,
-                                 CInterfaceStubVtbl *svtbl,
+                                 const ProxyFileInfo *ProxyInfo,
+                                 int Index,
                                  LPPSFACTORYBUFFER pPSFactory,
                                  LPRPCPROXYBUFFER *ppProxy,
                                  LPVOID *ppvObj);
@@ -43,4 +42,6 @@ HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid,
 
 const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface);
 
+const IRpcStubBufferVtbl CStdStubBuffer_Vtbl;
+
 #endif  /* __WINE_CPSF_H */
index 2633298..41c0943 100644 (file)
@@ -144,7 +144,10 @@ HRESULT WINAPI CStdStubBuffer_Invoke(LPRPCSTUBBUFFER iface,
   DWORD dwPhase = STUB_UNMARSHAL;
   TRACE("(%p)->Invoke(%p,%p)\n",This,pMsg,pChannel);
 
-  STUB_HEADER(This).pDispatchTable[pMsg->iMethod](iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase);
+  if (STUB_HEADER(This).pDispatchTable)
+    STUB_HEADER(This).pDispatchTable[pMsg->iMethod](iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase);
+  else /* pure interpreted */
+    NdrStubCall2(iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase);
   return S_OK;
 }
 
@@ -178,6 +181,20 @@ void WINAPI CStdStubBuffer_DebugServerRelease(LPRPCSTUBBUFFER iface,
   TRACE("(%p)->DebugServerRelease(%p)\n",This,pv);
 }
 
+const IRpcStubBufferVtbl CStdStubBuffer_Vtbl =
+{
+    CStdStubBuffer_QueryInterface,
+    CStdStubBuffer_AddRef,
+    NULL,
+    CStdStubBuffer_Connect,
+    CStdStubBuffer_Disconnect,
+    CStdStubBuffer_Invoke,
+    CStdStubBuffer_IsIIDSupported,
+    CStdStubBuffer_CountRefs,
+    CStdStubBuffer_DebugServerQueryInterface,
+    CStdStubBuffer_DebugServerRelease
+};
+
 const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface)
 {
   CStdStubBuffer *This = (CStdStubBuffer *)iface;
index 4156a0e..47d78f5 100644 (file)
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
+#include <limits.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -300,20 +301,43 @@ static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
   pStubMsg->pfnFree(Pointer);
 }
 
+static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
+{
+    return (*(const ULONG *)pFormat != -1);
+}
+
 PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
 {
   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
   pStubMsg->Buffer += 4;
   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
-  return pFormat+4;
+  if (pStubMsg->fHasNewCorrDesc)
+    return pFormat+6;
+  else
+    return pFormat+4;
 }
 
 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
 {
+  if (!IsConformanceOrVariancePresent(pFormat))
+  {
+    pStubMsg->Offset = 0;
+    pStubMsg->ActualCount = pStubMsg->MaxCount;
+    goto done;
+  }
+
+  pStubMsg->Offset      = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
+  pStubMsg->Buffer += 4;
+  TRACE("offset is %ld\n", pStubMsg->Offset);
   pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
   pStubMsg->Buffer += 4;
-  TRACE("unmarshalled variance is %ld\n", pStubMsg->ActualCount);
-  return pFormat+4;
+  TRACE("variance is %ld\n", pStubMsg->ActualCount);
+
+done:
+  if (pStubMsg->fHasNewCorrDesc)
+    return pFormat+6;
+  else
+    return pFormat+4;
 }
 
 PFORMAT_STRING ComputeConformanceOrVariance(
@@ -325,8 +349,7 @@ PFORMAT_STRING ComputeConformanceOrVariance(
   LPVOID ptr = NULL;
   DWORD data = 0;
 
-  /* FIXME: is this correct? */
-  if (pFormat[0] == 0xff) {
+  if (!IsConformanceOrVariancePresent(pFormat)) {
     /* null descriptor */
     *pCount = def;
     goto finish_conf;
@@ -428,7 +451,10 @@ done_conf_grab:
 
 finish_conf:
   TRACE("resulting conformance is %ld\n", *pCount);
-  return pFormat+4;
+  if (pStubMsg->fHasNewCorrDesc)
+    return pFormat+6;
+  else
+    return pFormat+4;
 }
 
 
@@ -1773,7 +1799,10 @@ unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
 
   if (fMustAlloc || !*ppMemory)
+  {
     *ppMemory = NdrAllocate(pStubMsg, size);
+    memset(*ppMemory, 0, size);
+  }
 
   pFormat += 4;
   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
@@ -2026,7 +2055,6 @@ unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pS
                                                            PFORMAT_STRING pFormat,
                                                            unsigned char fMustAlloc )
 {
-    DWORD offset;
     DWORD esize = *(const WORD*)(pFormat+2);
 
     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
@@ -2038,13 +2066,11 @@ unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pS
         return NULL;
     }
     pFormat = ReadConformance(pStubMsg, pFormat);
-    offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
-    pStubMsg->Buffer += 4;
     pFormat = ReadVariance(pStubMsg, pFormat);
 
     if (!*ppMemory || fMustAlloc)
         *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
-    memcpy(*ppMemory + offset, pStubMsg->Buffer, pStubMsg->ActualCount * esize);
+    memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, pStubMsg->ActualCount * esize);
     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
 
     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
@@ -2111,24 +2137,39 @@ unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
                                                unsigned char *pMemory,
                                                PFORMAT_STRING pFormat)
 {
-  DWORD size = 0, count, def;
+  ULONG count, def;
+  BOOL variance_present;
+
   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
 
+  if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
+  {
+      ERR("invalid format type %x\n", pFormat[0]);
+      RpcRaiseException(RPC_S_INTERNAL_ERROR);
+      return NULL;
+  }
+
   def = *(const WORD*)&pFormat[2];
   pFormat += 4;
 
   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
-  size = pStubMsg->MaxCount;
-  TRACE("conformance=%ld\n", size);
+  TRACE("conformance = %ld\n", pStubMsg->MaxCount);
 
-  if (*(const DWORD*)pFormat != 0xffffffff)
-    FIXME("compute variance\n");
-  pFormat += 4;
+  variance_present = IsConformanceOrVariancePresent(pFormat);
+  pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
+  TRACE("variance = %ld\n", pStubMsg->ActualCount);
 
-  NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, size);
+  NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
   pStubMsg->Buffer += 4;
+  if (variance_present)
+  {
+    NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
+    pStubMsg->Buffer += 4;
+    NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
+    pStubMsg->Buffer += 4;
+  }
 
-  for (count=0; count<size; count++)
+  for (count = 0; count < pStubMsg->ActualCount; count++)
     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
 
   STD_OVERFLOW_CHECK(pStubMsg);
@@ -2144,25 +2185,33 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
                                                  PFORMAT_STRING pFormat,
                                                  unsigned char fMustAlloc)
 {
-  DWORD size = 0, count, esize;
+  ULONG count, esize;
   unsigned char *pMemory;
+
   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
 
+  if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
+  {
+      ERR("invalid format type %x\n", pFormat[0]);
+      RpcRaiseException(RPC_S_INTERNAL_ERROR);
+      return NULL;
+  }
+
   pFormat += 4;
 
   pFormat = ReadConformance(pStubMsg, pFormat);
-  size = pStubMsg->MaxCount;
-  TRACE("conformance=%ld\n", size);
-
-  pFormat += 4;
+  pFormat = ReadVariance(pStubMsg, pFormat);
 
   esize = ComplexStructSize(pStubMsg, pFormat);
 
   if (fMustAlloc || !*ppMemory)
-    *ppMemory = NdrAllocate(pStubMsg, size*esize);
+  {
+    *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
+    memset(*ppMemory, 0, pStubMsg->MaxCount * esize);
+  }
 
   pMemory = *ppMemory;
-  for (count=0; count<size; count++)
+  for (count = 0; count < pStubMsg->ActualCount; count++)
     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
 
   return NULL;
@@ -2175,21 +2224,33 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
                                       unsigned char *pMemory,
                                       PFORMAT_STRING pFormat)
 {
-  DWORD size = 0, count, def;
+  ULONG count, def;
+  BOOL variance_present;
+
   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
 
+  if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
+  {
+      ERR("invalid format type %x\n", pFormat[0]);
+      RpcRaiseException(RPC_S_INTERNAL_ERROR);
+      return;
+  }
+
   def = *(const WORD*)&pFormat[2];
   pFormat += 4;
 
   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
-  size = pStubMsg->MaxCount;
-  TRACE("conformance=%ld\n", size);
+  TRACE("conformance = %ld\n", pStubMsg->MaxCount);
+  pStubMsg->BufferLength += sizeof(ULONG);
 
-  if (*(const DWORD*)pFormat != 0xffffffff)
-    FIXME("compute variance\n");
-  pFormat += 4;
+  variance_present = IsConformanceOrVariancePresent(pFormat);
+  pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
+  TRACE("variance = %ld\n", pStubMsg->ActualCount);
 
-  for (count=0; count<size; count++)
+  if (variance_present)
+    pStubMsg->BufferLength += 2*sizeof(ULONG);
+
+  for (count=0; count < pStubMsg->ActualCount; count++)
     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
 }
 
@@ -2202,6 +2263,13 @@ unsigned long WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
   DWORD size = 0;
   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
 
+  if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
+  {
+      ERR("invalid format type %x\n", pFormat[0]);
+      RpcRaiseException(RPC_S_INTERNAL_ERROR);
+      return 0;
+  }
+
   pFormat += 4;
 
   pFormat = ReadConformance(pStubMsg, pFormat);
@@ -2220,21 +2288,27 @@ void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
                                 unsigned char *pMemory,
                                 PFORMAT_STRING pFormat)
 {
-  DWORD size = 0, count, def;
+  ULONG count, def;
+
   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
 
+  if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
+  {
+      ERR("invalid format type %x\n", pFormat[0]);
+      RpcRaiseException(RPC_S_INTERNAL_ERROR);
+      return;
+  }
+
   def = *(const WORD*)&pFormat[2];
   pFormat += 4;
 
   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
-  size = pStubMsg->MaxCount;
-  TRACE("conformance=%ld\n", size);
+  TRACE("conformance = %ld\n", pStubMsg->MaxCount);
 
-  if (*(const DWORD*)pFormat != 0xffffffff)
-    FIXME("compute variance\n");
-  pFormat += 4;
+  pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
+  TRACE("variance = %ld\n", pStubMsg->ActualCount);
 
-  for (count=0; count<size; count++)
+  for (count=0; count < pStubMsg->ActualCount; count++)
     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
 }
 
@@ -2934,6 +3008,7 @@ static unsigned char *WINAPI NdrBaseTypeMarshall(
     case RPC_FC_LONG:
     case RPC_FC_ULONG:
     case RPC_FC_ERROR_STATUS_T:
+    case RPC_FC_ENUM32:
         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG) - 1);
         *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory;
         pStubMsg->Buffer += sizeof(ULONG);
@@ -2956,7 +3031,14 @@ static unsigned char *WINAPI NdrBaseTypeMarshall(
         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
         break;
     case RPC_FC_ENUM16:
-    case RPC_FC_ENUM32:
+        /* only 16-bits on the wire, so do a sanity check */
+        if (*(UINT *)pMemory > USHRT_MAX)
+            RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT) - 1);
+        *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
+        pStubMsg->Buffer += sizeof(USHORT);
+        TRACE("value: 0x%04x\n", *(UINT *)pMemory);
+        break;
     default:
         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
     }
@@ -3004,6 +3086,7 @@ static unsigned char *WINAPI NdrBaseTypeUnmarshall(
     case RPC_FC_LONG:
     case RPC_FC_ULONG:
     case RPC_FC_ERROR_STATUS_T:
+    case RPC_FC_ENUM32:
         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG) - 1);
         **(ULONG **)ppMemory = *(ULONG *)pStubMsg->Buffer;
         pStubMsg->Buffer += sizeof(ULONG);
@@ -3028,7 +3111,12 @@ static unsigned char *WINAPI NdrBaseTypeUnmarshall(
         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
         break;
     case RPC_FC_ENUM16:
-    case RPC_FC_ENUM32:
+        ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT) - 1);
+        /* 16-bits on the wire, but int in memory */
+        **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
+        pStubMsg->Buffer += sizeof(USHORT);
+        TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
+        break;
     default:
         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
     }
@@ -3059,11 +3147,13 @@ static void WINAPI NdrBaseTypeBufferSize(
     case RPC_FC_WCHAR:
     case RPC_FC_SHORT:
     case RPC_FC_USHORT:
+    case RPC_FC_ENUM16:
         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT) - 1);
         pStubMsg->BufferLength += sizeof(USHORT);
         break;
     case RPC_FC_LONG:
     case RPC_FC_ULONG:
+    case RPC_FC_ENUM32:
         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG) - 1);
         pStubMsg->BufferLength += sizeof(ULONG);
         break;
@@ -3083,8 +3173,6 @@ static void WINAPI NdrBaseTypeBufferSize(
         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t) - 1);
         pStubMsg->BufferLength += sizeof(error_status_t);
         break;
-    case RPC_FC_ENUM16:
-    case RPC_FC_ENUM32:
     default:
         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
     }
@@ -3121,6 +3209,7 @@ static unsigned long WINAPI NdrBaseTypeMemorySize(
         return sizeof(error_status_t);
     case RPC_FC_ENUM16:
     case RPC_FC_ENUM32:
+        return sizeof(INT);
     default:
         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
        return 0;
index 723c3c1..cc43817 100644 (file)
@@ -269,6 +269,8 @@ void WINAPI NdrFreeBuffer(MIDL_STUB_MESSAGE *pStubMsg)
  */
 unsigned char *WINAPI NdrSendReceive( MIDL_STUB_MESSAGE *stubmsg, unsigned char *buffer  )
 {
+  RPC_STATUS status;
+
   TRACE("(stubmsg == ^%p, buffer == ^%p)\n", stubmsg, buffer);
 
   /* FIXME: how to handle errors? (raise exception?) */
@@ -281,10 +283,9 @@ unsigned char *WINAPI NdrSendReceive( MIDL_STUB_MESSAGE *stubmsg, unsigned char
     return NULL;
   }
 
-  if (I_RpcSendReceive(stubmsg->RpcMsg) != RPC_S_OK) {
-    WARN("I_RpcSendReceive did not return success.\n");
-    /* FIXME: raise exception? */
-  }
+  status = I_RpcSendReceive(stubmsg->RpcMsg);
+  if (status != RPC_S_OK)
+    RpcRaiseException(status);
 
   stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength;
   stubmsg->BufferStart = stubmsg->RpcMsg->Buffer;
index 32f835d..0abeaed 100644 (file)
 
 struct IPSFactoryBuffer;
 
-LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc,
-                              PFORMAT_STRING pFormat, va_list args );
-
-HRESULT RPCRT4_GetPSFactory(REFIID riid, struct IPSFactoryBuffer **ppPS);
-
 #define ComputeConformance(pStubMsg, pMemory, pFormat, def) ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &pStubMsg->MaxCount)
 #define ComputeVariance(pStubMsg, pMemory, pFormat, def) ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &pStubMsg->ActualCount)
 PFORMAT_STRING ComputeConformanceOrVariance(
index 0919f9f..4bdeefe 100644 (file)
@@ -257,14 +257,16 @@ unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
   if (pStubMsg->Buffer + sizeof(DWORD) < (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) {
     stream = RpcStream_Create(pStubMsg, TRUE);
     if (stream) {
-      hr = COM_MarshalInterface(stream, riid, (LPUNKNOWN)pMemory,
-                                pStubMsg->dwDestContext, pStubMsg->pvDestContext,
-                                MSHLFLAGS_NORMAL);
+      if (pMemory)
+        hr = COM_MarshalInterface(stream, riid, (LPUNKNOWN)pMemory,
+                                  pStubMsg->dwDestContext, pStubMsg->pvDestContext,
+                                  MSHLFLAGS_NORMAL);
+      else
+        hr = S_OK;
+
       IStream_Release(stream);
-      if (FAILED(hr)) {
-        IUnknown_Release((LPUNKNOWN)pMemory);
+      if (FAILED(hr))
         RpcRaiseException(hr);
-      }
     }
   }
   return NULL;
@@ -355,17 +357,3 @@ void WINAPI NdrOleFree(void *NodeToFree)
   if (!LoadCOM()) return;
   COM_MemFree(NodeToFree);
 }
-
-/* internal */
-HRESULT RPCRT4_GetPSFactory(REFIID riid, LPPSFACTORYBUFFER *pPS)
-{
-  HRESULT hr;
-  CLSID clsid;
-
-  if (!LoadCOM()) return RPC_E_UNEXPECTED;
-  hr = COM_GetPSClsid(riid, &clsid);
-  if (FAILED(hr)) return hr;
-  hr = COM_GetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
-                          &IID_IPSFactoryBuffer, (LPVOID *)pPS);
-  return hr;
-}
index 40f8dcc..ec31fda 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * NDR client stuff
+ * NDR -Oi,-Oif,-Oicf Interpreter
  *
  * Copyright 2001 Ove KÃ¥ven, TransGaming Technologies
+ * Copyright 2003-5 Robert Shearman (for CodeWeavers)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * TODO:
- *  - Exception handling
- *  - Context stuff
- *  - Who knows
+ *  - Pipes
+ *  - Some types of binding handles
  */
 
+#include "config.h"
+#include "wine/port.h"
+
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 #include "winerror.h"
 #include "winreg.h"
 
+#include "objbase.h"
 #include "rpc.h"
-#include "rpcndr.h"
+#include "rpcproxy.h"
+#include "ndrtypes.h"
 
 #include "wine/debug.h"
+#include "wine/rpcfc.h"
 
 #include "ndr_misc.h"
+#include "cpsf.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(ole);
+WINE_DEFAULT_DEBUG_CHANNEL(rpc);
 
-/***********************************************************************
- * Note: this should return a CLIENT_CALL_RETURN, but calling convention for
- * returning structures/unions is different between Windows and gcc on i386.
- */
-LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, va_list args)
+#define NDR_TABLE_MASK 127
+
+static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
 {
+    NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK];
+    if (m) m(pStubMsg, pMemory, pFormat);
+    else
+    {
+        FIXME("format type 0x%x not implemented\n", pFormat[0]);
+        RpcRaiseException(RPC_X_BAD_STUB_DATA);
+    }
+}
 
-  RPC_CLIENT_INTERFACE *rpc_cli_if = (RPC_CLIENT_INTERFACE *)(pStubDesc->RpcInterfaceInformation);
-  LONG_PTR ret = 0;
-/*
-  RPC_BINDING_HANDLE handle = 0;
-  RPC_MESSAGE rpcmsg;
-  MIDL_STUB_MESSAGE stubmsg;
-*/
-
-  FIXME("(pStubDec == ^%p,pFormat = ^%p,...): stub\n", pStubDesc, pFormat);
-  if (rpc_cli_if) /* NULL for objects */ {
-    TRACE("  *rpc_cli_if (== ^%p) == (RPC_CLIENT_INTERFACE):\n", pStubDesc);
-    TRACE("    Length == %d\n", rpc_cli_if->Length);
-    TRACE("    InterfaceID == %s (%d.%d)\n", debugstr_guid(&rpc_cli_if->InterfaceId.SyntaxGUID), 
-      rpc_cli_if->InterfaceId.SyntaxVersion.MajorVersion, rpc_cli_if->InterfaceId.SyntaxVersion.MinorVersion);
-    TRACE("    TransferSyntax == %s (%d.%d)\n", debugstr_guid(&rpc_cli_if->TransferSyntax.SyntaxGUID),
-      rpc_cli_if->TransferSyntax.SyntaxVersion.MajorVersion, rpc_cli_if->TransferSyntax.SyntaxVersion.MinorVersion);
-    TRACE("    DispatchTable == ^%p\n", rpc_cli_if->DispatchTable);
-    TRACE("    RpcProtseqEndpointCount == ^%d\n", rpc_cli_if->RpcProtseqEndpointCount);
-    TRACE("    RpcProtseqEndpoint == ^%p\n", rpc_cli_if->RpcProtseqEndpoint);
-    TRACE("    Flags == ^%d\n", rpc_cli_if->Flags);
-  }
-
-  /* for now, while these functons are under development, this is too sketchy.  commented out. */
-  /*
-  NdrClientInitializeNew( &rpcmsg, &stubmsg, pStubDesc, 0 );
-        
-  handle = (RPC_BINDING_HANDLE)0xdeadbeef; */ /* FIXME */
-
-  /* stubmsg.BufferLength = 0;*/ /* FIXME */
-  /*
-  NdrGetBuffer( &stubmsg, stubmsg.BufferLength, handle );
-  NdrSendReceive( &stubmsg, stubmsg.Buffer  );
-  NdrFreeBuffer( &stubmsg );
-  */
-  return ret;
+static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
+{
+    NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK];
+    if (m) return m(pStubMsg, pMemory, pFormat);
+    else
+    {
+        FIXME("format type 0x%x not implemented\n", pFormat[0]);
+        RpcRaiseException(RPC_X_BAD_STUB_DATA);
+        return NULL;
+    }
 }
 
-/***********************************************************************
- *           NdrClientCall2 [RPCRT4.@]
- *
- * Note: this should return a CLIENT_CALL_RETURN, but calling convention for
- * returning structures/unions is different between Windows and gcc on i386.
- */
-LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc,
-  PFORMAT_STRING pFormat, ...)
+static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc)
+{
+    NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK];
+    if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc);
+    else
+    {
+        FIXME("format type 0x%x not implemented\n", pFormat[0]);
+        RpcRaiseException(RPC_X_BAD_STUB_DATA);
+        return NULL;
+    }
+}
+
+static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
+{
+    NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK];
+    if (m) m(pStubMsg, pMemory, pFormat);
+    else
+    {
+        FIXME("format type 0x%x not implemented\n", pFormat[0]);
+        RpcRaiseException(RPC_X_BAD_STUB_DATA);
+    }
+}
+
+static inline unsigned long call_memory_sizer(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
+{
+    NDR_MEMORYSIZE m = NdrMemorySizer[pFormat[0] & NDR_TABLE_MASK];
+    if (m) return m(pStubMsg, pFormat);
+    else
+    {
+        FIXME("format type 0x%x not implemented\n", pFormat[0]);
+        RpcRaiseException(RPC_X_BAD_STUB_DATA);
+        return 0;
+    }
+}
+
+/* there can't be any alignment with the structures in this file */
+#include "pshpack1.h"
+
+#define STUBLESS_UNMARSHAL  1
+#define STUBLESS_CALLSERVER 2
+#define STUBLESS_CALCSIZE   3
+#define STUBLESS_GETBUFFER  4
+#define STUBLESS_MARSHAL    5
+
+/* From http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/rpc/parameter_descriptors.asp */
+typedef struct _NDR_PROC_HEADER
+{
+    /* type of handle to use:
+     * RPC_FC_BIND_EXPLICIT = 0 - Explicit handle.
+     *   Handle is passed as a parameter to the function.
+     *   Indicates that explicit handle information follows the header,
+     *   which actually describes the handle.
+     * RPC_FC_BIND_GENERIC = 31 - Implicit handle with custom binding routines
+     *   (MIDL_STUB_DESC::IMPLICIT_HANDLE_INFO::pGenericBindingInfo)
+     * RPC_FC_BIND_PRIMITIVE = 32 - Implicit handle using handle_t created by
+     *   calling application
+     * RPC_FC_AUTO_HANDLE = 33 - Automatic handle
+     * RPC_FC_CALLBACK_HANDLE = 34 - undocmented
+     */
+    unsigned char handle_type;
+
+    /* procedure flags:
+     * Oi_FULL_PTR_USED = 0x01 - A full pointer can have the value NULL and can
+     *   change during the call from NULL to non-NULL and supports aliasing
+     *   and cycles. Indicates that the NdrFullPointerXlatInit function
+     *   should be called.
+     * Oi_RPCSS_ALLOC_USED = 0x02 - Use RpcSS allocate/free routines instead of
+     *   normal allocate/free routines
+     * Oi_OBJECT_PROC = 0x04 - Indicates a procedure that is part of an OLE
+     *   interface, rather than a DCE RPC interface.
+     * Oi_HAS_RPCFLAGS = 0x08 - Indicates that the rpc_flags element is 
+     *   present in the header.
+     * Oi_HAS_COMM_OR_FAULT = 0x20 - If Oi_OBJECT_PROC not present only then
+     *   indicates that the procedure has the comm_status or fault_status
+     *   MIDL attribute.
+     * Oi_OBJ_USE_V2_INTERPRETER = 0x20 - If Oi_OBJECT_PROC present only
+     *   then indicates that the format string is in -Oif or -Oicf format
+     * Oi_USE_NEW_INIT_ROUTINES = 0x40 - Use NdrXInitializeNew instead of
+     *   NdrXInitialize?
+     */
+    unsigned char Oi_flags;
+
+    /* the zero-based index of the procedure */
+    unsigned short proc_num;
+
+    /* total size of all parameters on the stack, including any "this"
+     * pointer and/or return value */
+    unsigned short stack_size;
+} NDR_PROC_HEADER;
+
+/* same as above struct except additional element rpc_flags */
+typedef struct _NDR_PROC_HEADER_RPC
+{
+    unsigned char handle_type;
+    unsigned char Oi_flags;
+
+    /*
+     * RPCF_Idempotent = 0x0001 - [idempotent] MIDL attribute
+     * RPCF_Broadcast = 0x0002 - [broadcast] MIDL attribute
+     * RPCF_Maybe = 0x0004 - [maybe] MIDL attribute
+     * Reserved = 0x0008 - 0x0080
+     * RPCF_Message = 0x0100 - [message] MIDL attribute
+     * Reserved = 0x0200 - 0x1000
+     * RPCF_InputSynchronous = 0x2000 - unknown
+     * RPCF_Asynchronous = 0x4000 - [async] MIDL attribute
+     * Reserved = 0x8000
+     */
+    unsigned long rpc_flags;
+    unsigned short proc_num;
+    unsigned short stack_size;
+
+} NDR_PROC_HEADER_RPC;
+
+typedef struct _NDR_PROC_PARTIAL_OIF_HEADER
+{
+    /* the pre-computed client buffer size so that interpreter can skip all
+     * or some (if the flag RPC_FC_PROC_OI2F_CLTMUSTSIZE is specified) of the
+     * sizing pass */
+    unsigned short constant_client_buffer_size;
+
+    /* the pre-computed server buffer size so that interpreter can skip all
+     * or some (if the flag RPC_FC_PROC_OI2F_SRVMUSTSIZE is specified) of the
+     * sizing pass */
+    unsigned short constant_server_buffer_size;
+
+    /* -Oif flags:
+     * RPC_FC_PROC_OI2F_SRVMUSTSIZE = 0x01 - the server must perform a
+     *   sizing pass.
+     * RPC_FC_PROC_OI2F_CLTMUSTSIZE = 0x02 - the client must perform a
+     *   sizing pass.
+     * RPC_FC_PROC_OI2F_HASRETURN = 0x04 - procedure has a return value.
+     * RPC_FC_PROC_OI2F_HASPIPES = 0x08 - the pipe package should be used.
+     * RPC_FC_PROC_OI2F_HASASYNCUUID = 0x20 - indicates an asynchronous DCOM
+     *   procedure.
+     * RPC_FC_PROC_OI2F_HASEXTS = 0x40 - indicates that Windows 2000
+     *   extensions are in use.
+     * RPC_FC_PROC_OI2F_HASASYNCHND = 0x80 - indicates an asynchronous RPC
+     *   procedure.
+     */
+    unsigned char Oif_flags;
+
+    /* number of params */
+    unsigned char number_of_params;
+} NDR_PROC_PARTIAL_OIF_HEADER;
+
+/* Windows 2000 extensions */
+typedef struct _NDR_PROC_EXTENSION
+{
+    /* size in bytes of all following extensions */
+    unsigned char extension_version;
+
+    /* extension flags:
+     * HasNewCorrDesc = 0x01 - indicates new correlation descriptors in use
+     * ClientCorrCheck = 0x02 - client needs correlation check
+     * ServerCorrCheck = 0x04 - server needs correlation check
+     * HasNotify = 0x08 - should call MIDL [notify] routine @ NotifyIndex
+     * HasNotify2 = 0x10 - should call MIDL [notify_flag] routine @ 
+     *   NotifyIndex
+     */
+    unsigned char ext_flags;
+
+    /* client cache size hint */
+    unsigned short ClientCorrHint;
+
+    /* server cache size hint */
+    unsigned short ServerCorrHint;
+
+    /* index of routine in MIDL_STUB_DESC::NotifyRoutineTable to call if
+     * HasNotify or HasNotify2 flag set */
+    unsigned short NotifyIndex;
+} NDR_PROC_EXTENSION;
+
+/* usually generated only on IA64 */
+typedef struct _NDR_PROC_EXTENSION_64
 {
-    LONG_PTR ret;
-    va_list args;
+    NDR_PROC_EXTENSION ext;
+
+    /* needed only on IA64 to cope with float/register loading */
+    unsigned short FloatDoubleMask;
+} NDR_PROC_EXTENSION_64;
+
+
+typedef struct _NDR_PARAM_OI_BASETYPE
+{
+    /* parameter direction. One of:
+     * FC_IN_PARAM_BASETYPE = 0x4e - an in param
+     * FC_RETURN_PARAM_BASETYPE = 0x53 - a return param
+     */
+    unsigned char param_direction;
+
+    /* One of: FC_BYTE,FC_CHAR,FC_SMALL,FC_USMALL,FC_WCHAR,FC_SHORT,FC_USHORT,
+     * FC_LONG,FC_ULONG,FC_FLOAT,FC_HYPER,FC_DOUBLE,FC_ENUM16,FC_ENUM32,
+     * FC_ERROR_STATUS_T,FC_INT3264,FC_UINT3264 */
+    unsigned char type_format_char;
+} NDR_PARAM_OI_BASETYPE;
+
+typedef struct _NDR_PARAM_OI_OTHER
+{
+    /* One of:
+     * FC_IN_PARAM = 0x4d - An in param
+     * FC_IN_OUT_PARAM = 0x50 - An in/out param
+     * FC_OUT_PARAM = 0x51 - An out param
+     * FC_RETURN_PARAM = 0x52 - A return value
+     * FC_IN_PARAM_NO_FREE_INST = 0x4f - A param for which no freeing is done
+     */
+    unsigned char param_direction;
+
+    /* Size of param on stack in NUMBERS OF INTS */
+    unsigned char stack_size;
+
+    /* offset in the type format string table */
+    unsigned short type_offset;
+} NDR_PARAM_OI_OTHER;
+
+typedef struct _NDR_PARAM_OIF_BASETYPE
+{
+    PARAM_ATTRIBUTES param_attributes;
+
+    /* the offset on the calling stack where the parameter is located */
+    unsigned short stack_offset;
+
+    /* see NDR_PARAM_OI_BASETYPE::type_format_char */
+    unsigned char type_format_char;
+
+    /* always FC_PAD */
+    unsigned char unused;
+} NDR_PARAM_OIF_BASETYPE;
+
+typedef struct _NDR_PARAM_OIF_OTHER
+{
+    PARAM_ATTRIBUTES param_attributes;
+
+    /* see NDR_PARAM_OIF_BASETYPE::stack_offset */
+    unsigned short stack_offset;
+
+    /* offset into the provided type format string where the type for this
+     * parameter starts */
+    unsigned short type_offset;
+} NDR_PARAM_OIF_OTHER;
+
+/* explicit handle description for FC_BIND_PRIMITIVE type */
+typedef struct _NDR_EHD_PRIMITIVE
+{
+    /* FC_BIND_PRIMITIVE */
+    unsigned char handle_type;
+
+    /* is the handle passed in via a pointer? */
+    unsigned char flag;
+
+    /* offset from the beginning of the stack to the handle in bytes */
+    unsigned short offset;
+} NDR_EHD_PRIMITIVE;
+
+/* explicit handle description for FC_BIND_GENERIC type */
+typedef struct _NDR_EHD_GENERIC
+{
+    /* FC_BIND_GENERIC */
+    unsigned char handle_type;
+
+    /* upper 4bits is a flag indicating whether the handle is passed in
+     * via a pointer. lower 4bits is the size of the user defined generic
+     * handle type. the size must be less than or equal to the machine
+     * register size */
+    unsigned char flag_and_size;
+
+    /* offset from the beginning of the stack to the handle in bytes */
+    unsigned short offset;
+
+    /* the index into the aGenericBindingRoutinesPairs field of MIDL_STUB_DESC
+     * giving the bind and unbind routines for the handle */
+    unsigned char binding_routine_pair_index;
+
+    /* FC_PAD */
+    unsigned char unused;
+} NDR_EHD_GENERIC;
+
+/* explicit handle description for FC_BIND_CONTEXT type */
+typedef struct _NDR_EHD_CONTEXT
+{
+    /* FC_BIND_CONTEXT */
+    unsigned char handle_type;
+
+    /* Any of the following flags:
+     * NDR_CONTEXT_HANDLE_CANNOT_BE_NULL = 0x01
+     * NDR_CONTEXT_HANDLE_SERIALIZE = 0x02
+     * NDR_CONTEXT_HANDLE_NO_SERIALIZE = 0x04
+     * NDR_STRICT_CONTEXT_HANDLE = 0x08
+     * HANDLE_PARAM_IS_OUT = 0x20
+     * HANDLE_PARAM_IS_RETURN = 0x21
+     * HANDLE_PARAM_IS_IN = 0x40
+     * HANDLE_PARAM_IS_VIA_PTR = 0x80
+     */
+    unsigned char flags;
+
+    /* offset from the beginning of the stack to the handle in bytes */
+    unsigned short offset;
+
+    /* zero-based index on rundown routine in apfnNdrRundownRoutines field
+     * of MIDL_STUB_DESC */
+    unsigned char context_rundown_routine_index;
+
+    /* varies depending on NDR version used.
+     * V1: zero-based index into parameters 
+     * V2: zero-based index into handles that are parameters */
+    unsigned char param_num;
+} NDR_EHD_CONTEXT;
+
+#include "poppack.h"
+
+void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage)
+{
+#if 0 /* these functions are not defined yet */
+    pMessage->pfnAllocate = NdrRpcSmClientAllocate;
+    pMessage->pfnFree = NdrRpcSmClientFree;
+#endif
+}
+
+static void WINAPI dump_RPC_FC_PROC_PF(PARAM_ATTRIBUTES param_attributes)
+{
+    if (param_attributes.MustSize) TRACE(" MustSize");
+    if (param_attributes.MustFree) TRACE(" MustFree");
+    if (param_attributes.IsPipe) TRACE(" IsPipe");
+    if (param_attributes.IsIn) TRACE(" IsIn");
+    if (param_attributes.IsOut) TRACE(" IsOut");
+    if (param_attributes.IsReturn) TRACE(" IsReturn");
+    if (param_attributes.IsBasetype) TRACE(" IsBasetype");
+    if (param_attributes.IsByValue) TRACE(" IsByValue");
+    if (param_attributes.IsSimpleRef) TRACE(" IsSimpleRef");
+    if (param_attributes.IsDontCallFreeInst) TRACE(" IsDontCallFreeInst");
+    if (param_attributes.SaveForAsyncFinish) TRACE(" SaveForAsyncFinish");
+    if (param_attributes.ServerAllocSize) TRACE(" ServerAllocSize = %d", param_attributes.ServerAllocSize * 8);
+}
+
+/* FIXME: this will be different on other plaftorms than i386 */
+#define ARG_FROM_OFFSET(args, offset) (*(unsigned char **)args + offset)
+
+/* the return type should be CLIENT_CALL_RETURN, but this is incompatible
+ * with the way gcc returns structures. "void *" should be the largest type
+ * that MIDL should allow you to return anyway */
+LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, ...)
+{
+    /* pointer to start of stack where arguments start */
+    /* FIXME: not portable */
+    unsigned char *args = (unsigned char *)(&pFormat+1);
+    RPC_MESSAGE rpcMsg;
+    MIDL_STUB_MESSAGE stubMsg;
+    handle_t hBinding = NULL;
+    /* procedure number */
+    unsigned short procedure_number;
+    /* size of stack */
+    unsigned short stack_size;
+    /* current stack offset */
+    unsigned short current_stack_offset;
+    /* number of parameters. optional for client to give it to us */
+    unsigned char number_of_params = ~0;
+    /* counter */
+    unsigned short i;
+    /* cache of Oif_flags from v2 procedure header */
+    unsigned char Oif_flags = 0;
+    /* cache of extension flags from NDR_PROC_EXTENSION */
+    unsigned char ext_flags = 0;
+    /* the type of pass we are currently doing */
+    int phase;
+    /* header for procedure string */
+    const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
+    /* offset in format string for start of params */
+    int parameter_start_offset;
+    /* current format string offset */
+    int current_offset;
+    /* -Oif or -Oicf generated format */
+    BOOL bV2Format = FALSE;
+    /* the value to return to the client from the remote procedure */
+    LONG_PTR RetVal = 0;
+    /* the pointer to the object when in OLE mode */
+    void * This = NULL;
+
+    TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
+    TRACE("&first_argument = %p -> %p\n", args, ARG_FROM_OFFSET(args, 0));
+
+    /* Later NDR language versions probably won't be backwards compatible */
+    if (pStubDesc->Version > 0x50002)
+    {
+        FIXME("Incompatible stub description version: 0x%lx\n", pStubDesc->Version);
+        RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
+    }
+
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
+    {
+        NDR_PROC_HEADER_RPC * pProcHeader = (NDR_PROC_HEADER_RPC *)&pFormat[0];
+        stack_size = pProcHeader->stack_size;
+        procedure_number = pProcHeader->proc_num;
+        current_offset = sizeof(NDR_PROC_HEADER_RPC);
+    }
+    else
+    {
+        stack_size = pProcHeader->stack_size;
+        procedure_number = pProcHeader->proc_num;
+        TRACE("proc num: %d\n", procedure_number);
+        current_offset = sizeof(NDR_PROC_HEADER);
+    }
+
+    TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
+    TRACE("MIDL stub version = 0x%lx\n", pStubDesc->MIDLVersion);
+
+    /* we only need a handle if this isn't an object method */
+    if (!(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT))
+    {
+        /* binding */
+        switch (pProcHeader->handle_type)
+        {
+        /* explicit binding: parse additional section */
+        case RPC_FC_BIND_EXPLICIT:
+            switch (pFormat[current_offset]) /* handle_type */
+            {
+            case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
+                {
+                    NDR_EHD_PRIMITIVE * pDesc = (NDR_EHD_PRIMITIVE *)&pFormat[current_offset];
+
+                    TRACE("Explicit primitive handle @ %d\n", pDesc->offset);
+
+                    if (pDesc->flag) /* pointer to binding */
+                        hBinding = **(handle_t **)ARG_FROM_OFFSET(args, pDesc->offset);
+                    else
+                        hBinding = *(handle_t *)ARG_FROM_OFFSET(args, pDesc->offset);
+                    current_offset += sizeof(NDR_EHD_PRIMITIVE);
+                    break;
+                }
+            case RPC_FC_BIND_GENERIC: /* explicit generic */
+                FIXME("RPC_FC_BIND_GENERIC\n");
+                RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
+                current_offset += sizeof(NDR_EHD_GENERIC);
+                break;
+            case RPC_FC_BIND_CONTEXT: /* explicit context */
+                {
+                    NDR_EHD_CONTEXT * pDesc = (NDR_EHD_CONTEXT *)&pFormat[current_offset];
+                    TRACE("Explicit bind context\n");
+                    hBinding = NDRCContextBinding(*(NDR_CCONTEXT *)ARG_FROM_OFFSET(args, pDesc->offset));
+                    /* FIXME: should we store this structure in stubMsg.pContext? */
+                    current_offset += sizeof(NDR_EHD_CONTEXT);
+                    break;
+                }
+            default:
+                ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
+                RpcRaiseException(RPC_X_BAD_STUB_DATA);
+            }
+            break;
+        case RPC_FC_BIND_GENERIC: /* implicit generic */
+            FIXME("RPC_FC_BIND_GENERIC\n");
+            RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
+            break;
+        case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
+            TRACE("Implicit primitive handle\n");
+            hBinding = *pStubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle;
+            break;
+        case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
+            FIXME("RPC_FC_CALLBACK_HANDLE\n");
+            break;
+        case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
+            /* strictly speaking, it isn't necessary to set hBinding here
+            * since it isn't actually used (hence the automatic in its name),
+            * but then why does MIDL generate a valid entry in the
+            * MIDL_STUB_DESC for it? */
+            TRACE("Implicit auto handle\n");
+            hBinding = *pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle;
+            break;
+        default:
+            ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
+            RpcRaiseException(RPC_X_BAD_STUB_DATA);
+        }
+    }
+
+    bV2Format = (pStubDesc->Version >= 0x20000);
+
+    if (bV2Format)
+    {
+        NDR_PROC_PARTIAL_OIF_HEADER * pOIFHeader =
+            (NDR_PROC_PARTIAL_OIF_HEADER*)&pFormat[current_offset];
+
+        Oif_flags = pOIFHeader->Oif_flags;
+        number_of_params = pOIFHeader->number_of_params;
+
+        current_offset += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
+    }
+
+    TRACE("Oif_flags = 0x%02x\n", Oif_flags);
+
+    if (Oif_flags & RPC_FC_PROC_OI2F_HASEXTS)
+    {
+        NDR_PROC_EXTENSION * pExtensions =
+            (NDR_PROC_EXTENSION *)&pFormat[current_offset];
+        ext_flags = pExtensions->ext_flags;
+        current_offset += pExtensions->extension_version;
+    }
+
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
+    {
+        /* object is always the first argument */
+        This = *(void **)ARG_FROM_OFFSET(args, 0);
+        NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number);
+    }
+    else
+        NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number);
+
+    /* create the full pointer translation tables, if requested */
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
+#if 0
+        stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
+#else
+        FIXME("initialize full pointer translation tables\n");
+#endif
+
+    stubMsg.BufferLength = 0;
+
+    /* store the RPC flags away */
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
+        rpcMsg.RpcFlags = ((NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
+
+    /* use alternate memory allocation routines */
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
+        NdrRpcSmSetClientToOsf(&stubMsg);
+
+    if (Oif_flags & RPC_FC_PROC_OI2F_HASPIPES)
+    {
+        FIXME("pipes not supported yet\n");
+        RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
+        /* init pipes package */
+        /* NdrPipesInitialize(...) */
+    }
+    if (ext_flags & RPC_FC_PROC_EXT_NEWCORRDESC)
+    {
+        /* initialize extra correlation package */
+        FIXME("new correlation description not implemented\n");
+        stubMsg.fHasNewCorrDesc = TRUE;
+    }
+
+    parameter_start_offset = current_offset;
 
-    TRACE("(%p,%p,...)\n", pStubDesc, pFormat);
+    /* order of phases:
+     * 1. PROXY_CALCSIZE - calculate the buffer size
+     * 2. PROXY_GETBUFFER - allocate the buffer
+     * 3. PROXY_MARHSAL - marshal [in] params into the buffer
+     * 4. PROXY_SENDRECEIVE - send/receive buffer
+     * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer
+     */
+    for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++)
+    {
+        TRACE("phase = %d\n", phase);
+        switch (phase)
+        {
+        case PROXY_GETBUFFER:
+            /* allocate the buffer */
+            if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
+                NdrProxyGetBuffer(This, &stubMsg);
+            else if (Oif_flags & RPC_FC_PROC_OI2F_HASPIPES)
+                /* NdrGetPipeBuffer(...) */
+                FIXME("pipes not supported yet\n");
+            else
+            {
+                if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
+#if 0
+                    NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
+#else
+                    FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
+#endif
+                else
+                    NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
+            }
+            break;
+        case PROXY_SENDRECEIVE:
+            /* send the [in] params and receive the [out] and [retval]
+             * params */
+            if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
+                NdrProxySendReceive(This, &stubMsg);
+            else if (Oif_flags & RPC_FC_PROC_OI2F_HASPIPES)
+                /* NdrPipesSendReceive(...) */
+                FIXME("pipes not supported yet\n");
+            else
+            {
+                if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
+#if 0
+                    NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
+#else
+                    FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
+#endif
+                else
+                    NdrSendReceive(&stubMsg, stubMsg.Buffer);
+            }
 
-    va_start(args, pFormat);
-    ret = RPCRT4_NdrClientCall2(pStubDesc, pFormat, args);
-    va_end(args);
-    return ret;
+            /* convert strings, floating point values and endianess into our
+             * preferred format */
+            if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
+                NdrConvert(&stubMsg, pFormat);
+
+            break;
+        case PROXY_CALCSIZE:
+        case PROXY_MARSHAL:
+        case PROXY_UNMARSHAL:
+            current_offset = parameter_start_offset;
+            current_stack_offset = 0;
+
+            /* NOTE: V1 style format does't terminate on the number_of_params
+             * condition as it doesn't have this attribute. Instead it
+             * terminates when the stack size given in the header is exceeded.
+             */
+            for (i = 0; i < number_of_params; i++)
+            {
+                if (bV2Format) /* new parameter format */
+                {
+                    NDR_PARAM_OIF_BASETYPE * pParam =
+                        (NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
+                    unsigned char * pArg;
+
+                    current_stack_offset = pParam->stack_offset;
+                    pArg = ARG_FROM_OFFSET(args, current_stack_offset);
+
+                    TRACE("param[%d]: new format\n", i);
+                    TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
+                    TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
+                    TRACE("\tmemory addr (before): %p\n", pArg);
+
+                    if (pParam->param_attributes.IsBasetype)
+                    {
+                        const unsigned char * pTypeFormat =
+                            &pParam->type_format_char;
+
+                        if (pParam->param_attributes.IsSimpleRef)
+                            pArg = *(unsigned char **)pArg;
+
+                        TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
+
+                        switch (phase)
+                        {
+                        case PROXY_CALCSIZE:
+                            if (pParam->param_attributes.IsIn)
+                                call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
+                            break;
+                        case PROXY_MARSHAL:
+                            if (pParam->param_attributes.IsIn)
+                                call_marshaller(&stubMsg, pArg, pTypeFormat);
+                            break;
+                        case PROXY_UNMARSHAL:
+                            if (pParam->param_attributes.IsOut)
+                            {
+                                unsigned char *pRetVal = (unsigned char *)&RetVal;
+                                if (pParam->param_attributes.IsReturn)
+                                    call_unmarshaller(&stubMsg, &pRetVal, pTypeFormat, 0);
+                                else
+                                    call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
+                                TRACE("pRetVal = %p\n", pRetVal);
+                            }
+                            break;
+                        default:
+                            RpcRaiseException(RPC_S_INTERNAL_ERROR);
+                        }
+
+                        current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
+                    }
+                    else
+                    {
+                        NDR_PARAM_OIF_OTHER * pParamOther =
+                            (NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
+
+                        const unsigned char * pTypeFormat =
+                            &(pStubDesc->pFormatTypes[pParamOther->type_offset]);
+
+                        /* if a simple ref pointer then we have to do the
+                         * check for the pointer being non-NULL. */
+                        if (pParam->param_attributes.IsSimpleRef)
+                        {
+                            if (!*(unsigned char **)pArg)
+                                RpcRaiseException(RPC_X_NULL_REF_POINTER);
+                        }
+
+                        TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat);
+
+                        switch (phase)
+                        {
+                        case PROXY_CALCSIZE:
+                            if (pParam->param_attributes.IsIn)
+                            {
+                                if (pParam->param_attributes.IsByValue)
+                                    call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
+                                else
+                                    call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
+                            }
+                            break;
+                        case PROXY_MARSHAL:
+                            if (pParam->param_attributes.IsIn)
+                            {
+                                if (pParam->param_attributes.IsByValue)
+                                    call_marshaller(&stubMsg, pArg, pTypeFormat);
+                                else
+                                    call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
+                            }
+                            break;
+                        case PROXY_UNMARSHAL:
+                            if (pParam->param_attributes.IsOut)
+                            {
+                                unsigned char *pRetVal = (unsigned char *)&RetVal;
+                                if (pParam->param_attributes.IsReturn)
+                                    call_unmarshaller(&stubMsg, &pRetVal, pTypeFormat, 0);
+                                else if (pParam->param_attributes.IsByValue)
+                                    call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
+                                else
+                                    call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0);
+                            }
+                            break;
+                        default:
+                            RpcRaiseException(RPC_S_INTERNAL_ERROR);
+                        }
+
+                        current_offset += sizeof(NDR_PARAM_OIF_OTHER);
+                    }
+                    TRACE("\tmemory addr (after): %p\n", pArg);
+                }
+                else /* old parameter format */
+                {
+                    NDR_PARAM_OI_BASETYPE * pParam =
+                        (NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
+                    unsigned char * pArg = ARG_FROM_OFFSET(args, current_stack_offset);
+
+                    /* no more parameters; exit loop */
+                    if (current_stack_offset > stack_size)
+                        break;
+
+                    TRACE("param[%d]: old format\n", i);
+                    TRACE("\tparam_direction: %x\n", pParam->param_direction);
+                    TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
+                    TRACE("\tmemory addr (before): %p\n", pArg);
+
+                    if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
+                        pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
+                    {
+                        const unsigned char * pTypeFormat =
+                            &pParam->type_format_char;
+
+                        TRACE("\tbase type 0x%02x\n", *pTypeFormat);
+
+                        switch (phase)
+                        {
+                        case PROXY_CALCSIZE:
+                            if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
+                                call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
+                            break;
+                        case PROXY_MARSHAL:
+                            if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
+                                call_marshaller(&stubMsg, pArg, pTypeFormat);
+                            break;
+                        case PROXY_UNMARSHAL:
+                            if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
+                            {
+                                if (pParam->param_direction & RPC_FC_RETURN_PARAM)
+                                    call_unmarshaller(&stubMsg, (unsigned char **)&RetVal, pTypeFormat, 0);
+                                else
+                                    call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
+                            }
+                            break;
+                        default:
+                            RpcRaiseException(RPC_S_INTERNAL_ERROR);
+                        }
+
+                        current_stack_offset += call_memory_sizer(&stubMsg, pTypeFormat);
+                        current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
+                    }
+                    else
+                    {
+                        NDR_PARAM_OI_OTHER * pParamOther = 
+                            (NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
+
+                        const unsigned char *pTypeFormat =
+                            &pStubDesc->pFormatTypes[pParamOther->type_offset];
+
+                        TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
+
+                        switch (phase)
+                        {
+                        case PROXY_CALCSIZE:
+                            if (pParam->param_direction == RPC_FC_IN_PARAM ||
+                                pParam->param_direction & RPC_FC_IN_OUT_PARAM)
+                                call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
+                            break;
+                        case PROXY_MARSHAL:
+                            if (pParam->param_direction == RPC_FC_IN_PARAM ||
+                                pParam->param_direction & RPC_FC_IN_OUT_PARAM)
+                                call_marshaller(&stubMsg, pArg, pTypeFormat);
+                            break;
+                        case PROXY_UNMARSHAL:
+                            if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
+                                pParam->param_direction == RPC_FC_OUT_PARAM)
+                                 call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
+                            else if (pParam->param_direction == RPC_FC_RETURN_PARAM)
+                                call_unmarshaller(&stubMsg, (unsigned char **)&RetVal, pTypeFormat, 0);
+                            break;
+                        default:
+                            RpcRaiseException(RPC_S_INTERNAL_ERROR);
+                        }
+
+                        current_stack_offset += pParamOther->stack_size * sizeof(INT);
+                        current_offset += sizeof(NDR_PARAM_OI_OTHER);
+                    }
+                    TRACE("\tmemory addr (after): %p\n", pArg);
+                }
+            }
+
+            break;
+        default:
+            ERR("shouldn't reach here. phase %d\n", phase);
+            break;
+        }
+    }
+
+    /* FIXME: unbind the binding handle */
+
+    if (ext_flags & RPC_FC_PROC_EXT_NEWCORRDESC)
+    {
+        /* free extra correlation package */
+        /* NdrCorrelationFree(&stubMsg); */
+    }
+
+    if (Oif_flags & RPC_FC_PROC_OI2F_HASPIPES)
+    {
+        /* NdrPipesDone(...) */
+    }
+
+#if 0
+    /* free the full pointer translation tables */
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
+        NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
+#endif
+
+    /* free marshalling buffer */
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
+        NdrProxyFreeBuffer(This, &stubMsg);
+    else
+        NdrFreeBuffer(&stubMsg);
+
+    TRACE("RetVal = 0x%lx\n", RetVal);
+
+    return RetVal;
+}
+
+/* calls a function with the specificed arguments, restoring the stack
+ * properly afterwards as we don't know the calling convention of the
+ * function */
+#if defined __i386__ && defined _MSC_VER
+__declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size)
+{
+    __asm
+    {
+        push ebp
+        push edi            ; Save registers
+        push esi
+        mov ebp, esp
+        mov eax, [ebp+16]   ; Get stack size
+        sub esp, eax        ; Make room in stack for arguments
+        mov edi, esp
+        mov ecx, eax
+        mov esi, [ebp+12]
+        shr ecx, 2
+        cld
+        rep movsd           ; Copy dword blocks
+        call [ebp+8]        ; Call function
+        lea esp, [ebp-8]    ; Restore stack
+        pop ebp             ; Restore registers
+        pop esi
+        pop edi
+        ret
+    }
+}
+#elif defined __i386__ && defined __GNUC__
+LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
+__ASM_GLOBAL_FUNC(call_server_func,
+    "pushl %ebp\n\t"
+    "movl %esp, %ebp\n\t"
+    "pushl %edi\n\t"            /* Save registers */
+    "pushl %esi\n\t"
+    "movl 16(%ebp), %eax\n\t"   /* Get stack size */
+    "subl %eax, %esp\n\t"       /* Make room in stack for arguments */
+    "andl $~15, %esp\n\t"      /* Make sure stack has 16-byte alignment for MacOS X */
+    "movl %esp, %edi\n\t"
+    "movl %eax, %ecx\n\t"
+    "movl 12(%ebp), %esi\n\t"
+    "shrl $2, %ecx\n\t"         /* divide by 4 */
+    "cld\n\t"
+    "rep; movsl\n\t"            /* Copy dword blocks */
+    "call *8(%ebp)\n\t"         /* Call function */
+    "leal -8(%ebp), %esp\n\t"   /* Restore stack */
+    "popl %esi\n\t"             /* Restore registers */
+    "popl %edi\n\t"
+    "popl %ebp\n\t"
+    "ret\n" );
+#else
+#warning call_server_func not implemented for your architecture
+LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
+{
+    FIXME("Not implemented for your architecture\n");
+    return 0;
+}
+#endif
+
+/* FIXME: need to free some stuff in here too */
+long WINAPI NdrStubCall2(
+    struct IRpcStubBuffer * pThis,
+    struct IRpcChannelBuffer * pChannel,
+    PRPC_MESSAGE pRpcMsg,
+    unsigned long * pdwStubPhase)
+{
+    const MIDL_SERVER_INFO *pServerInfo;
+    const MIDL_STUB_DESC *pStubDesc;
+    PFORMAT_STRING pFormat;
+    MIDL_STUB_MESSAGE stubMsg;
+    /* pointer to start of stack to pass into stub implementation */
+    unsigned char * args;
+    /* size of stack */
+    unsigned short stack_size;
+    /* current stack offset */
+    unsigned short current_stack_offset;
+    /* number of parameters. optional for client to give it to us */
+    unsigned char number_of_params = ~0;
+    /* counter */
+    unsigned short i;
+    /* cache of Oif_flags from v2 procedure header */
+    unsigned char Oif_flags = 0;
+    /* cache of extension flags from NDR_PROC_EXTENSION */
+    unsigned char ext_flags = 0;
+    /* the type of pass we are currently doing */
+    int phase;
+    /* header for procedure string */
+    const NDR_PROC_HEADER *pProcHeader;
+    /* offset in format string for start of params */
+    int parameter_start_offset;
+    /* current format string offset */
+    int current_offset;
+    /* -Oif or -Oicf generated format */
+    BOOL bV2Format = FALSE;
+    /* the return value (not from this function, but to be put back onto
+     * the wire */
+    LONG_PTR RetVal = 0;
+
+    TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase);
+
+    if (pThis)
+        pServerInfo = CStdStubBuffer_GetServerInfo(pThis);
+    else
+        pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
+
+    pStubDesc = pServerInfo->pStubDesc;
+    pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
+    pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
+
+    /* Later NDR language versions probably won't be backwards compatible */
+    if (pStubDesc->Version > 0x50002)
+    {
+        FIXME("Incompatible stub description version: 0x%lx\n", pStubDesc->Version);
+        RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
+    }
+
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
+    {
+        NDR_PROC_HEADER_RPC * pProcHeader = (NDR_PROC_HEADER_RPC *)&pFormat[0];
+        stack_size = pProcHeader->stack_size;
+        current_offset = sizeof(NDR_PROC_HEADER_RPC);
+
+    }
+    else
+    {
+        stack_size = pProcHeader->stack_size;
+        current_offset = sizeof(NDR_PROC_HEADER);
+    }
+
+    TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
+
+    /* binding */
+    switch (pProcHeader->handle_type)
+    {
+    /* explicit binding: parse additional section */
+    case RPC_FC_BIND_EXPLICIT:
+        switch (pFormat[current_offset]) /* handle_type */
+        {
+        case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
+            current_offset += sizeof(NDR_EHD_PRIMITIVE);
+            break;
+        case RPC_FC_BIND_GENERIC: /* explicit generic */
+            current_offset += sizeof(NDR_EHD_GENERIC);
+            break;
+        case RPC_FC_BIND_CONTEXT: /* explicit context */
+            current_offset += sizeof(NDR_EHD_CONTEXT);
+            break;
+        default:
+            ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
+            RpcRaiseException(RPC_X_BAD_STUB_DATA);
+        }
+        break;
+    case RPC_FC_BIND_GENERIC: /* implicit generic */
+    case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
+    case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
+    case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
+        break;
+    default:
+        ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
+        RpcRaiseException(RPC_X_BAD_STUB_DATA);
+    }
+
+    bV2Format = (pStubDesc->Version >= 0x20000);
+
+    if (bV2Format)
+    {
+        NDR_PROC_PARTIAL_OIF_HEADER * pOIFHeader =
+            (NDR_PROC_PARTIAL_OIF_HEADER*)&pFormat[current_offset];
+
+        Oif_flags = pOIFHeader->Oif_flags;
+        number_of_params = pOIFHeader->number_of_params;
+
+        current_offset += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
+    }
+
+    TRACE("Oif_flags = 0x%02x\n", Oif_flags);
+
+    if (Oif_flags & RPC_FC_PROC_OI2F_HASEXTS)
+    {
+        NDR_PROC_EXTENSION * pExtensions =
+            (NDR_PROC_EXTENSION *)&pFormat[current_offset];
+        ext_flags = pExtensions->ext_flags;
+        current_offset += pExtensions->extension_version;
+    }
+
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
+        NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel);
+    else
+        NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc);
+
+    /* create the full pointer translation tables, if requested */
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
+#if 0
+        stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
+#else
+        FIXME("initialize full pointer translation tables\n");
+#endif
+
+    /* store the RPC flags away */
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
+        pRpcMsg->RpcFlags = ((NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
+
+    /* use alternate memory allocation routines */
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
+#if 0
+          NdrRpcSsEnableAllocate(&stubMsg);
+#else
+          FIXME("Set RPCSS memory allocation routines\n");
+#endif
+
+    if (Oif_flags & RPC_FC_PROC_OI2F_HASPIPES)
+    {
+        FIXME("pipes not supported yet\n");
+        RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
+        /* init pipes package */
+        /* NdrPipesInitialize(...) */
+    }
+    if (ext_flags & RPC_FC_PROC_EXT_NEWCORRDESC)
+    {
+        /* initialize extra correlation package */
+        FIXME("new correlation description not implemented\n");
+        stubMsg.fHasNewCorrDesc = TRUE;
+    }
+
+
+    /* convert strings, floating point values and endianess into our
+     * preferred format */
+    if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
+        NdrConvert(&stubMsg, pFormat);
+
+    parameter_start_offset = current_offset;
+
+    TRACE("allocating memory for stack of size %x\n", stack_size);
+
+    args = HeapAlloc(GetProcessHeap(), 0, stack_size);
+    ZeroMemory(args, stack_size);
+
+    /* add the implicit This pointer as the first arg to the function if we
+     * are calling an object method */
+    if (pThis)
+        *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject;
+
+    /* order of phases:
+     * 1. STUBLESS_UNMARHSAL - unmarshal [in] params from buffer
+     * 2. STUBLESS_CALLSERVER - send/receive buffer
+     * 3. STUBLESS_CALCSIZE - get [out] buffer size
+     * 4. STUBLESS_GETBUFFER - allocate [out] buffer
+     * 5. STUBLESS_MARHSAL - marshal [out] params to buffer
+     */
+    for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_MARSHAL; phase++)
+    {
+        TRACE("phase = %d\n", phase);
+        switch (phase)
+        {
+        case STUBLESS_CALLSERVER:
+            /* call the server function */
+            if (pServerInfo->ThunkTable)
+            {
+                stubMsg.StackTop = args;
+                pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg);
+                /* FIXME: RetVal is stored as the last argument - retrieve it */
+            }
+            else if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
+            {
+                SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject;
+                RetVal = call_server_func(vtbl[pRpcMsg->ProcNum], args, stack_size);
+            }
+            else
+                RetVal = call_server_func(pServerInfo->DispatchTable[pRpcMsg->ProcNum], args, stack_size);
+
+            TRACE("stub implementation returned %p\n", (void *)RetVal);
+
+            stubMsg.Buffer = NULL;
+            stubMsg.BufferLength = 0;
+
+            break;
+        case STUBLESS_GETBUFFER:
+            if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
+                NdrStubGetBuffer(pThis, pChannel, &stubMsg);
+            else
+            {
+                RPC_STATUS Status;
+
+                pRpcMsg->BufferLength = stubMsg.BufferLength;
+                /* allocate buffer for [out] and [ret] params */
+                Status = I_RpcGetBuffer(pRpcMsg); 
+                if (Status)
+                    RpcRaiseException(Status);
+                stubMsg.BufferStart = pRpcMsg->Buffer;
+                stubMsg.BufferEnd = stubMsg.BufferStart + stubMsg.BufferLength;
+                stubMsg.Buffer = stubMsg.BufferStart;
+            }
+            break;
+        case STUBLESS_MARSHAL:
+        case STUBLESS_UNMARSHAL:
+        case STUBLESS_CALCSIZE:
+            current_offset = parameter_start_offset;
+            current_stack_offset = 0;
+
+            /* NOTE: V1 style format does't terminate on the number_of_params
+             * condition as it doesn't have this attribute. Instead it
+             * terminates when the stack size given in the header is exceeded.
+             */
+            for (i = 0; i < number_of_params; i++)
+            {
+                if (bV2Format) /* new parameter format */
+                {
+                    const NDR_PARAM_OIF_BASETYPE *pParam =
+                        (NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
+                    unsigned char *pArg;
+
+                    current_stack_offset = pParam->stack_offset;
+                    pArg = (unsigned char *)(args+current_stack_offset);
+
+                    TRACE("param[%d]: new format\n", i);
+                    TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
+                    TRACE("\tstack_offset: %x\n", current_stack_offset);
+                    TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg);
+
+                    if (pParam->param_attributes.ServerAllocSize)
+                        FIXME("ServerAllocSize of %d ignored for parameter %d\n",
+                            pParam->param_attributes.ServerAllocSize * 8, i);
+
+                    if (pParam->param_attributes.IsBasetype)
+                    {
+                        const unsigned char *pTypeFormat =
+                            &pParam->type_format_char;
+
+                        TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
+
+                        switch (phase)
+                        {
+                        case STUBLESS_MARSHAL:
+                            if (pParam->param_attributes.IsReturn)
+                                call_marshaller(&stubMsg, (unsigned char *)&RetVal, pTypeFormat);
+                            else if (pParam->param_attributes.IsOut)
+                            {
+                                if (pParam->param_attributes.IsSimpleRef)
+                                    call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
+                                else
+                                    call_marshaller(&stubMsg, pArg, pTypeFormat);
+                            }
+                            /* FIXME: call call_freer here */
+                            break;
+                        case STUBLESS_UNMARSHAL:
+                            if (pParam->param_attributes.IsIn)
+                            {
+                                if (pParam->param_attributes.IsSimpleRef)
+                                    call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0);
+                                else
+                                    call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
+                            }
+                            break;
+                        case STUBLESS_CALCSIZE:
+                            if (pParam->param_attributes.IsReturn)
+                                call_buffer_sizer(&stubMsg, (unsigned char *)&RetVal, pTypeFormat);
+                            else if (pParam->param_attributes.IsOut)
+                            {
+                                if (pParam->param_attributes.IsSimpleRef)
+                                    call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
+                                else
+                                    call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
+                            }
+                            break;
+                        default:
+                            RpcRaiseException(RPC_S_INTERNAL_ERROR);
+                        }
+
+                        current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
+                    }
+                    else
+                    {
+                        NDR_PARAM_OIF_OTHER * pParamOther =
+                            (NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
+
+                        const unsigned char * pTypeFormat =
+                            &(pStubDesc->pFormatTypes[pParamOther->type_offset]);
+
+                        TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
+
+                        switch (phase)
+                        {
+                        case STUBLESS_MARSHAL:
+                            if (pParam->param_attributes.IsReturn)
+                                call_marshaller(&stubMsg, (unsigned char *)&RetVal, pTypeFormat);
+                            else if (pParam->param_attributes.IsOut)
+                            {
+                                if (pParam->param_attributes.IsByValue)
+                                    call_marshaller(&stubMsg, pArg, pTypeFormat);
+                                else
+                                {
+                                    call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
+                                    stubMsg.pfnFree(*(void **)pArg);
+                                }
+                            }
+                            /* FIXME: call call_freer here for IN types */
+                            break;
+                        case STUBLESS_UNMARSHAL:
+                            if (pParam->param_attributes.IsIn)
+                            {
+                                if (pParam->param_attributes.IsByValue)
+                                    call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
+                                else
+                                    call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0);
+                            }
+                            else if ((pParam->param_attributes.IsOut) && 
+                                      !(pParam->param_attributes.IsByValue))
+                            {
+                                *(void **)pArg = NdrAllocate(&stubMsg, sizeof(void *));
+                                **(void ***)pArg = 0;
+                            }
+                            break;
+                        case STUBLESS_CALCSIZE:
+                            if (pParam->param_attributes.IsReturn)
+                                call_buffer_sizer(&stubMsg, (unsigned char *)&RetVal, pTypeFormat);
+                            else if (pParam->param_attributes.IsOut)
+                            {
+                                if (pParam->param_attributes.IsByValue)
+                                    call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
+                                else
+                                    call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
+                            }
+                            break;
+                        default:
+                            RpcRaiseException(RPC_S_INTERNAL_ERROR);
+                        }
+
+                        current_offset += sizeof(NDR_PARAM_OIF_OTHER);
+                    }
+                    TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
+                }
+                else /* old parameter format */
+                {
+                    NDR_PARAM_OI_BASETYPE *pParam =
+                        (NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
+                    unsigned char *pArg = (unsigned char *)(args+current_stack_offset);
+
+                    /* no more parameters; exit loop */
+                    if (current_stack_offset > stack_size)
+                        break;
+
+                    TRACE("param[%d]: old format\n\tparam_direction: 0x%x\n", i, pParam->param_direction);
+
+                    if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
+                        pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
+                    {
+                        const unsigned char *pTypeFormat =
+                            &pParam->type_format_char;
+
+                        TRACE("\tbase type 0x%02x\n", *pTypeFormat);
+
+                        switch (phase)
+                        {
+                        case STUBLESS_MARSHAL:
+                            if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
+                            {
+                                unsigned char *pRetVal = (unsigned char *)&RetVal;
+                                call_marshaller(&stubMsg, (unsigned char *)&pRetVal, pTypeFormat);
+                            }
+                            break;
+                        case STUBLESS_UNMARSHAL:
+                            if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
+                                call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
+                            break;
+                        case STUBLESS_CALCSIZE:
+                            if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
+                            {
+                                unsigned char * pRetVal = (unsigned char *)&RetVal;
+                                call_buffer_sizer(&stubMsg, (unsigned char *)&pRetVal, pTypeFormat);
+                            }
+                            break;
+                        default:
+                            RpcRaiseException(RPC_S_INTERNAL_ERROR);
+                        }
+
+                        current_stack_offset += call_memory_sizer(&stubMsg, pTypeFormat);
+                        current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
+                    }
+                    else
+                    {
+                        NDR_PARAM_OI_OTHER * pParamOther = 
+                            (NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
+
+                        const unsigned char * pTypeFormat =
+                            &pStubDesc->pFormatTypes[pParamOther->type_offset];
+
+                        TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
+
+                        switch (phase)
+                        {
+                        case STUBLESS_MARSHAL:
+                            if (pParam->param_direction == RPC_FC_RETURN_PARAM)
+                            {
+                                unsigned char *pRetVal = (unsigned char *)&RetVal;
+                                call_marshaller(&stubMsg, (unsigned char *)&pRetVal, pTypeFormat);
+                            }
+                            else if (pParam->param_direction == RPC_FC_OUT_PARAM ||
+                                pParam->param_direction == RPC_FC_IN_OUT_PARAM)
+                                call_marshaller(&stubMsg, pArg, pTypeFormat);
+                            break;
+                        case STUBLESS_UNMARSHAL:
+                            if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
+                                pParam->param_direction == RPC_FC_IN_PARAM)
+                                call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
+                            break;
+                        case STUBLESS_CALCSIZE:
+                            if (pParam->param_direction == RPC_FC_RETURN_PARAM)
+                            {
+                                unsigned char * pRetVal = (unsigned char *)&RetVal;
+                                call_buffer_sizer(&stubMsg, (unsigned char *)&pRetVal, pTypeFormat);
+                            }
+                            else if (pParam->param_direction == RPC_FC_OUT_PARAM ||
+                                pParam->param_direction == RPC_FC_IN_OUT_PARAM)
+                                call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
+                            break;
+                        default:
+                            RpcRaiseException(RPC_S_INTERNAL_ERROR);
+                        }
+
+                        current_stack_offset += pParamOther->stack_size * sizeof(INT);
+                        current_offset += sizeof(NDR_PARAM_OI_OTHER);
+                    }
+                }
+            }
+
+            break;
+        default:
+            ERR("shouldn't reach here. phase %d\n", phase);
+            break;
+        }
+    }
+
+    pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer);
+
+    if (ext_flags & RPC_FC_PROC_EXT_NEWCORRDESC)
+    {
+        /* free extra correlation package */
+        /* NdrCorrelationFree(&stubMsg); */
+    }
+
+    if (Oif_flags & RPC_FC_PROC_OI2F_HASPIPES)
+    {
+        /* NdrPipesDone(...) */
+    }
+
+#if 0
+    /* free the full pointer translation tables */
+    if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
+        NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
+#endif
+
+    /* free server function stack */
+    HeapFree(GetProcessHeap(), 0, args);
+
+    return S_OK;
+}
+
+void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
+{
+    DWORD dwPhase;
+    NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
 }
index dcd3670..7c34719 100644 (file)
@@ -254,15 +254,13 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header,
   hdr_size = Header->common.frag_len;
   Header->common.flags |= RPC_FLG_FIRST;
   Header->common.flags &= ~RPC_FLG_LAST;
-  while (!(Header->common.flags & RPC_FLG_LAST)) {    
+  while (!(Header->common.flags & RPC_FLG_LAST)) {
     /* decide if we need to split the packet into fragments */
     if ((BufferLength + hdr_size) <= Connection->MaxTransmissionSize) {
       Header->common.flags |= RPC_FLG_LAST;
       Header->common.frag_len = BufferLength + hdr_size;
     } else {
       Header->common.frag_len = Connection->MaxTransmissionSize;
-      buffer_pos += Header->common.frag_len - hdr_size;
-      BufferLength -= Header->common.frag_len - hdr_size;
     }
 
     /* transmit packet header */
@@ -293,6 +291,8 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header,
       return GetLastError();
     }
 
+    buffer_pos += Header->common.frag_len - hdr_size;
+    BufferLength -= Header->common.frag_len - hdr_size;
     Header->common.flags &= ~RPC_FLG_FIRST;
   }
 
index b238b61..ad4e04f 100644 (file)
 @ stub NdrRpcSsDisableAllocate
 @ stub NdrRpcSsEnableAllocate
 @ stdcall NdrSendReceive(ptr ptr)
-@ stub NdrServerCall2
+@ stdcall NdrServerCall2(ptr)
 @ stub NdrServerCall
 @ stdcall NdrServerContextMarshall(ptr ptr long)
 @ stdcall NdrServerContextNewMarshall(ptr ptr ptr ptr) # wxp
 @ stdcall NdrSimpleStructUnmarshall(ptr ptr ptr long)
 @ stdcall NdrSimpleTypeMarshall(ptr ptr long)
 @ stdcall NdrSimpleTypeUnmarshall(ptr ptr long)
-@ stub NdrStubCall2
+@ stdcall NdrStubCall2(ptr ptr ptr ptr)
 @ stub NdrStubCall
 @ stdcall NdrStubForwardingFunction(ptr ptr ptr ptr)
 @ stdcall NdrStubGetBuffer(ptr ptr ptr)
diff --git a/reactos/include/ndrtypes.h b/reactos/include/ndrtypes.h
new file mode 100644 (file)
index 0000000..aa47acf
--- /dev/null
@@ -0,0 +1,57 @@
+/*\r
+ * NDR Types\r
+ *\r
+ * Copyright 2006 Robert Shearman (for CodeWeavers)\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Lesser General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2.1 of the License, or (at your option) any later version.\r
+ *\r
+ * This library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ * Lesser General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Lesser General Public\r
+ * License along with this library; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#ifndef __NDRTYPES_H__\r
+#define __NDRTYPES_H__\r
+\r
+typedef struct\r
+{\r
+    unsigned short MustSize : 1; /* 0x0001 - client interpreter MUST size this\r
+     *  parameter, other parameters may be skipped, using the value in\r
+     *  NDR_PROC_PARTIAL_OIF_HEADER::constant_client_buffer_size instead. */\r
+    unsigned short MustFree : 1; /* 0x0002 - server interpreter MUST size this\r
+     *  parameter, other parameters may be skipped, using the value in\r
+     *  NDR_PROC_PARTIAL_OIF_HEADER::constant_server_buffer_size instead. */\r
+    unsigned short IsPipe : 1; /* 0x0004 - The parameter is a pipe handle. See\r
+     *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/rpc/pipes.asp\r
+     *  for more information on pipes. */\r
+    unsigned short IsIn : 1; /* 0x0008 - The parameter is an input */\r
+    unsigned short IsOut : 1; /* 0x0010 - The parameter is an output */\r
+    unsigned short IsReturn : 1; /* 0x0020 - The parameter is to be returned */\r
+    unsigned short IsBasetype : 1; /* 0x0040 - The parameter is simple and has the\r
+     *  format defined by NDR_PARAM_OIF_BASETYPE rather than by\r
+     *  NDR_PARAM_OIF_OTHER. */\r
+    unsigned short IsByValue : 1; /* 0x0080 - Set for compound types being sent by\r
+     *  value. Can be of type: structure, union, transmit_as, represent_as,\r
+     *  wire_marshal and SAFEARRAY. */\r
+    unsigned short IsSimpleRef : 1; /* 0x0100 - parameter that is a reference\r
+     *  pointer to anything other than another pointer, and which has no\r
+     *  allocate attributes. */\r
+    unsigned short IsDontCallFreeInst : 1; /*  0x0200 - Used for some represent_as types\r
+     *  for when the free instance routine should not be called. */\r
+    unsigned short SaveForAsyncFinish : 1; /* 0x0400 - Unknown */\r
+    unsigned short Unused : 2;\r
+    unsigned short ServerAllocSize : 3; /* 0xe000 - If non-zero\r
+     *  specifies the size of the object in numbers of 8byte blocks needed.\r
+     *  It will be stored on the server's stack rather than using an allocate\r
+     *  call. */\r
+} PARAM_ATTRIBUTES;\r
+\r
+#endif\r
index d777e86..99c1669 100644 (file)
@@ -164,67 +164,73 @@ typedef struct _NDR_ASYNC_MESSAGE *PNDR_ASYNC_MESSAGE;
 typedef struct _NDR_CORRELATION_INFO *PNDR_CORRELATION_INFO;
 
 #pragma pack(push,4)
-typedef struct _MIDL_STUB_MESSAGE {
-       PRPC_MESSAGE RpcMsg;
-       unsigned char *Buffer;
-       unsigned char *BufferStart;
-       unsigned char *BufferEnd;
-       unsigned char *BufferMark;
-       unsigned long BufferLength;
-       unsigned long MemorySize;
-       unsigned char *Memory;
-       int IsClient;
-       int ReuseBuffer;
-       unsigned char *AllocAllNodesMemory;
-       unsigned char *AllocAllNodesMemoryEnd;
-       int IgnoreEmbeddedPointers;
-       unsigned char *PointerBufferMark;
-       unsigned char fBufferValid;
-       unsigned char uFlags;
-       unsigned long MaxCount;
-       unsigned long Offset;
-       unsigned long ActualCount;
-       void*(__RPC_API *pfnAllocate)(unsigned int);
-       void(__RPC_API *pfnFree)(void*);
-       unsigned char *StackTop;
-       unsigned char *pPresentedType;
-       unsigned char *pTransmitType;
-       handle_t SavedHandle;
-       const struct _MIDL_STUB_DESC *StubDesc;
-       struct _FULL_PTR_XLAT_TABLES *FullPtrXlatTables;
-       unsigned long FullPtrRefId;
-       int fCheckBounds;
-       int fInDontFree :1;
-       int fDontCallFreeInst :1;
-       int fInOnlyParam :1;
-       int fHasReturn :1;
-       unsigned long dwDestContext;
-       void*pvDestContext;
-       NDR_SCONTEXT *SavedContextHandles;
-       long ParamNumber;
-       struct IRpcChannelBuffer *pRpcChannelBuffer;
-       PARRAY_INFO pArrayInfo;
-       unsigned long *SizePtrCountArray;
-       unsigned long *SizePtrOffsetArray;
-       unsigned long *SizePtrLengthArray;
-       void*pArgQueue;
-       unsigned long dwStubPhase;
-       void *LowStackMark;
-       PNDR_ASYNC_MESSAGE pAsyncMsg;
-       PNDR_CORRELATION_INFO pCorrInfo;
-       unsigned char *pCorrMemory;
-       void *pMemoryList;
-       CS_STUB_INFO *pCSInfo;
-       unsigned char *ConformanceMark;
-       unsigned char *VarianceMark;
-       INT_PTR Unused;
-       struct _NDR_PROC_CONTEXT *pContext;
-       INT_PTR Reserved51_1;
-       INT_PTR Reserved51_2;
-       INT_PTR Reserved51_3;
-       INT_PTR Reserved51_4;
-       INT_PTR Reserved51_5;
-} MIDL_STUB_MESSAGE,*PMIDL_STUB_MESSAGE;
+typedef struct _MIDL_STUB_MESSAGE
+{
+  PRPC_MESSAGE RpcMsg;
+  unsigned char *Buffer;
+  unsigned char *BufferStart;
+  unsigned char *BufferEnd;
+  unsigned char *BufferMark;
+  unsigned long BufferLength;
+  unsigned long MemorySize;
+  unsigned char *Memory;
+  int IsClient;
+  int ReuseBuffer;
+  struct NDR_ALLOC_ALL_NODES_CONTEXT *pAllocAllNodesContext;
+  struct NDR_POINTER_QUEUE_STATE *pPointerQueueState;
+  int IgnoreEmbeddedPointers;
+  unsigned char *PointerBufferMark;
+  unsigned char fBufferValid;
+  unsigned char uFlags;
+  unsigned short UniquePtrCount;
+  ULONG_PTR MaxCount;
+  unsigned long Offset;
+  unsigned long ActualCount;
+  void * (__RPC_API *pfnAllocate)(size_t);
+  void (__RPC_API *pfnFree)(void *);
+  unsigned char *StackTop;
+  unsigned char *pPresentedType;
+  unsigned char *pTransmitType;
+  handle_t SavedHandle;
+  const struct _MIDL_STUB_DESC *StubDesc;
+  struct _FULL_PTR_XLAT_TABLES *FullPtrXlatTables;
+  unsigned long FullPtrRefId;
+  unsigned long PointerLength;
+  int fInDontFree:1;
+  int fDontCallFreeInst:1;
+  int fInOnlyParam:1;
+  int fHasReturn:1;
+  int fHasExtensions:1;
+  int fHasNewCorrDesc:1;
+  int fUnused:10;
+  int fUnused2:16;
+  unsigned long dwDestContext;
+  void *pvDestContext;
+  NDR_SCONTEXT *SavedContextHandles;
+  long ParamNumber;
+  struct IRpcChannelBuffer *pRpcChannelBuffer;
+  PARRAY_INFO pArrayInfo;
+  unsigned long *SizePtrCountArray;
+  unsigned long *SizePtrOffsetArray;
+  unsigned long *SizePtrLengthArray;
+  void *pArgQueue;
+  unsigned long dwStubPhase;
+  void *LowStackMark;
+  PNDR_ASYNC_MESSAGE pAsyncMsg;
+  PNDR_CORRELATION_INFO pCorrInfo;
+  unsigned char *pCorrMemory;
+  void *pMemoryList;
+  CS_STUB_INFO *pCSInfo;
+  unsigned char *ConformanceMark;
+  unsigned char *VarianceMark;
+  INT_PTR Unused;
+  struct _NDR_PROC_CONTEXT *pContext;
+  INT_PTR Reserved51_1;
+  INT_PTR Reserved51_2;
+  INT_PTR Reserved51_3;
+  INT_PTR Reserved51_4;
+  INT_PTR Reserved51_5;
+} MIDL_STUB_MESSAGE, *PMIDL_STUB_MESSAGE;
 #pragma pack(pop)
 typedef void*(__RPC_API *GENERIC_BINDING_ROUTINE)(void*);
 typedef void (__RPC_API *GENERIC_UNBIND_ROUTINE)(void*,unsigned char*);
index b23c429..ad342ba 100644 (file)
@@ -1,23 +1,44 @@
-#ifndef _RPCNTERR_H
-#define _RPCNTERR_H
-#if __GNUC__ >=3
-#pragma GCC system_header
-#endif
+/*
+ * Copyright (C) 2001 Peter Hunnisett
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
 
-#define RPC_S_OK ERROR_SUCCESS
-#define RPC_S_INVALID_ARG ERROR_INVALID_PARAMETER
-#define RPC_S_OUT_OF_MEMORY ERROR_OUTOFMEMORY
-#define RPC_S_OUT_OF_THREADS ERROR_MAX_THRDS_REACHED
-#define RPC_S_INVALID_LEVEL ERROR_INVALID_PARAMETER
-#define RPC_S_BUFFER_TOO_SMALL ERROR_INSUFFICIENT_BUFFER
-#define RPC_S_INVALID_SECURITY_DESC ERROR_INVALID_SECURITY_DESCR
-#define RPC_S_ACCESS_DENIED ERROR_ACCESS_DENIED
-#define RPC_S_SERVER_OUT_OF_MEMORY ERROR_NOT_ENOUGH_SERVER_MEMORY
-#define RPC_X_NO_MEMORY RPC_S_OUT_OF_MEMORY
-#define RPC_X_INVALID_BOUND RPC_S_INVALID_BOUND
-#define RPC_X_INVALID_TAG RPC_S_INVALID_TAG
-#define RPC_X_ENUM_VALUE_TOO_LARGE RPC_X_ENUM_VALUE_OUT_OF_RANGE
-#define RPC_X_SS_CONTEXT_MISMATCH ERROR_INVALID_HANDLE
-#define RPC_X_INVALID_BUFFER ERROR_INVALID_USER_BUFFER
-#define RPC_X_INVALID_PIPE_OPERATION RPC_X_WRONG_PIPE_ORDER
-#endif
+#ifndef __RPCNTERR_H__
+#define __RPCNTERR_H__
+
+#define RPC_S_OK                          ERROR_SUCCESS
+#define RPC_S_INVALID_ARG                 ERROR_INVALID_PARAMETER
+#define RPC_S_OUT_OF_MEMORY               ERROR_OUTOFMEMORY
+#define RPC_S_OUT_OF_THREADS              ERROR_MAX_THRDS_REACHED
+#define RPC_S_INVALID_LEVEL               ERROR_INVALID_PARAMETER
+#define RPC_S_BUFFER_TOO_SMALL            ERROR_INSUFFICIENT_BUFFER
+#define RPC_S_INVALID_SECURITY_DESC       ERROR_INVALID_SECURITY_DESCR
+#define RPC_S_ACCESS_DENIED               ERROR_ACCESS_DENIED
+#define RPC_S_SERVER_OUT_OF_MEMORY        ERROR_NOT_ENOUGH_SERVER_MEMORY
+#define RPC_S_ASYNC_CALL_PENDING          ERROR_IO_PENDING
+#define RPC_S_UNKNOWN_PRINCIPAL           ERROR_NONE_MAPPED
+#define RPC_S_TIMEOUT                     ERROR_TIMEOUT
+
+#define RPC_X_NO_MEMORY                   RPC_S_OUT_OF_MEMORY
+#define RPC_X_INVALID_BOUND               RPC_S_INVALID_BOUND
+#define RPC_X_INVALID_TAG                 RPC_S_INVALID_TAG
+#define RPC_X_ENUM_VALUE_TOO_LARGE        RPC_X_ENUM_VALUE_OUT_OF_RANGE
+#define RPC_X_SS_CONTEXT_MISMATCH         ERROR_INVALID_HANDLE
+#define RPC_X_INVALID_BUFFER              ERROR_INVALID_USER_BUFFER
+#define RPC_X_PIPE_APP_MEMORY             ERROR_OUTOFMEMORY
+#define RPC_X_INVALID_PIPE_OPERATION      RPC_X_WRONG_PIPE_ORDER
+
+#endif  /* __RPCNTERR_H__ */