Import and merge Wine-20041201
authorGé van Geldorp <ge@gse.nl>
Fri, 31 Dec 2004 15:52:05 +0000 (15:52 +0000)
committerGé van Geldorp <ge@gse.nl>
Fri, 31 Dec 2004 15:52:05 +0000 (15:52 +0000)
svn path=/trunk/; revision=12595

25 files changed:
reactos/lib/rpcrt4/Makefile [new file with mode: 0644]
reactos/lib/rpcrt4/Makefile.in [new file with mode: 0644]
reactos/lib/rpcrt4/Makefile.ros-template [new file with mode: 0644]
reactos/lib/rpcrt4/cproxy.c [new file with mode: 0644]
reactos/lib/rpcrt4/cpsf.c [new file with mode: 0644]
reactos/lib/rpcrt4/cpsf.h [new file with mode: 0644]
reactos/lib/rpcrt4/cstub.c [new file with mode: 0644]
reactos/lib/rpcrt4/ndr_marshall.c [new file with mode: 0644]
reactos/lib/rpcrt4/ndr_midl.c [new file with mode: 0644]
reactos/lib/rpcrt4/ndr_misc.h [new file with mode: 0644]
reactos/lib/rpcrt4/ndr_ole.c [new file with mode: 0644]
reactos/lib/rpcrt4/ndr_stubless.c [new file with mode: 0644]
reactos/lib/rpcrt4/rpc_binding.c [new file with mode: 0644]
reactos/lib/rpcrt4/rpc_binding.h [new file with mode: 0644]
reactos/lib/rpcrt4/rpc_defs.h [new file with mode: 0644]
reactos/lib/rpcrt4/rpc_epmap.c [new file with mode: 0644]
reactos/lib/rpcrt4/rpc_message.c [new file with mode: 0644]
reactos/lib/rpcrt4/rpc_message.h [new file with mode: 0644]
reactos/lib/rpcrt4/rpc_misc.h [new file with mode: 0644]
reactos/lib/rpcrt4/rpc_server.c [new file with mode: 0644]
reactos/lib/rpcrt4/rpc_server.h [new file with mode: 0644]
reactos/lib/rpcrt4/rpcrt4.spec [new file with mode: 0644]
reactos/lib/rpcrt4/rpcrt4_main.c [new file with mode: 0644]
reactos/lib/rpcrt4/rpcss_np_client.c [new file with mode: 0644]
reactos/lib/rpcrt4/rpcss_np_client.h [new file with mode: 0644]

diff --git a/reactos/lib/rpcrt4/Makefile b/reactos/lib/rpcrt4/Makefile
new file mode 100644 (file)
index 0000000..63b677f
--- /dev/null
@@ -0,0 +1,9 @@
+# $Id: Makefile 9303 2004-05-04 20:10:07Z navaraf $\r
+\r
+PATH_TO_TOP = ../..\r
+\r
+TARGET_TYPE = winedll\r
+\r
+include $(PATH_TO_TOP)/rules.mak\r
+\r
+include $(TOOLS_PATH)/helper.mk\r
diff --git a/reactos/lib/rpcrt4/Makefile.in b/reactos/lib/rpcrt4/Makefile.in
new file mode 100644 (file)
index 0000000..b0df10c
--- /dev/null
@@ -0,0 +1,29 @@
+EXTRADEFS = -D_RPCRT4_ -DCOM_NO_WINDOWS_H -DMSWMSG\r
+TOPSRCDIR = @top_srcdir@\r
+TOPOBJDIR = ../..\r
+SRCDIR    = @srcdir@\r
+VPATH     = @srcdir@\r
+MODULE    = rpcrt4.dll\r
+IMPORTS   = iphlpapi advapi32 kernel32 ntdll\r
+EXTRALIBS = -luuid\r
+\r
+C_SRCS = \\r
+       cproxy.c \\r
+       cpsf.c \\r
+       cstub.c \\r
+       ndr_marshall.c \\r
+       ndr_midl.c \\r
+       ndr_ole.c \\r
+       ndr_stubless.c \\r
+       rpc_binding.c \\r
+       rpc_epmap.c \\r
+       rpc_message.c \\r
+       rpc_server.c \\r
+       rpcrt4_main.c \\r
+       rpcss_np_client.c\r
+\r
+SUBDIRS = tests\r
+\r
+@MAKE_DLL_RULES@\r
+\r
+### Dependencies:\r
diff --git a/reactos/lib/rpcrt4/Makefile.ros-template b/reactos/lib/rpcrt4/Makefile.ros-template
new file mode 100644 (file)
index 0000000..8ffa506
--- /dev/null
@@ -0,0 +1,22 @@
+# $Id: Makefile.ros-template 11910 2004-12-03 23:37:44Z blight $\r
+\r
+TARGET_NAME = rpcrt4\r
+\r
+TARGET_OBJECTS = @C_SRCS@\r
+\r
+TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__ -Wall\r
+\r
+TARGET_SDKLIBS = @IMPORTS@ winmm.a wine.a wine_uuid.a ntdll.a\r
+\r
+TARGET_BASE = $(TARGET_BASE_LIB_RPCRT4)\r
+\r
+TARGET_RC_BINSRC = @RC_BINSRC@\r
+TARGET_RC_BINARIES = @RC_BINARIES@\r
+\r
+TARGET_NORC = yes\r
+\r
+default: all\r
+\r
+DEP_OBJECTS = $(TARGET_OBJECTS)\r
+\r
+include $(TOOLS_PATH)/depend.mk\r
diff --git a/reactos/lib/rpcrt4/cproxy.c b/reactos/lib/rpcrt4/cproxy.c
new file mode 100644 (file)
index 0000000..f5645ab
--- /dev/null
@@ -0,0 +1,342 @@
+/*\r
+ * COM proxy implementation\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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
+ * TODO: Handle non-i386 architectures\r
+ *       Get rid of #if 0'ed code.\r
+ */\r
+\r
+#include <stdarg.h>\r
+\r
+#define COBJMACROS\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+\r
+#include "objbase.h"\r
+#include "rpcproxy.h"\r
+\r
+#include "cpsf.h"\r
+#include "ndr_misc.h"\r
+#include "wine/debug.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+struct StublessThunk;\r
+\r
+/* I don't know what MS's std proxy structure looks like,\r
+   so this probably doesn't match, but that shouldn't matter */\r
+typedef struct {\r
+  IRpcProxyBufferVtbl *lpVtbl;\r
+  LPVOID *PVtbl;\r
+  DWORD RefCount;\r
+  const MIDL_STUBLESS_PROXY_INFO *stubless;\r
+  const IID* piid;\r
+  LPUNKNOWN pUnkOuter;\r
+  PCInterfaceName name;\r
+  LPPSFACTORYBUFFER pPSFactory;\r
+  LPRPCCHANNELBUFFER pChannel;\r
+  struct StublessThunk *thunks;\r
+} StdProxyImpl;\r
+\r
+static IRpcProxyBufferVtbl StdProxy_Vtbl;\r
+\r
+#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))\r
+\r
+/* How the Windows stubless proxy thunks work is explained at\r
+ * http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp,\r
+ * but I'll use a slightly different method, to make life easier */\r
+\r
+#if defined(__i386__)\r
+\r
+#include "pshpack1.h"\r
+\r
+struct StublessThunk {\r
+  BYTE push;\r
+  DWORD index;\r
+  BYTE call;\r
+  LONG handler;\r
+  BYTE ret;\r
+  WORD bytes;\r
+  BYTE pad[3];\r
+};\r
+\r
+#include "poppack.h"\r
+\r
+/* adjust the stack size since we don't use Windows's method */\r
+#define STACK_ADJUST sizeof(DWORD)\r
+\r
+#define FILL_STUBLESS(x,idx,stk) \\r
+ x->push = 0x68; /* pushl [immediate] */ \\r
+ x->index = (idx); \\r
+ x->call = 0xe8; /* call [near] */ \\r
+ x->handler = (char*)ObjectStubless - (char*)&x->ret; \\r
+ x->ret = 0xc2; /* ret [immediate] */ \\r
+ x->bytes = stk; \\r
+ x->pad[0] = 0x8d; /* leal (%esi),%esi */ \\r
+ x->pad[1] = 0x76; \\r
+ x->pad[2] = 0x00;\r
+\r
+static HRESULT WINAPI ObjectStubless(DWORD index)\r
+{\r
+  char *args = (char*)(&index + 2);\r
+  LPVOID iface = *(LPVOID*)args;\r
+\r
+  ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface);\r
+\r
+  PFORMAT_STRING fs = This->stubless->ProcFormatString + This->stubless->FormatStringOffset[index];\r
+  unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST;\r
+  TRACE("(%p)->(%ld)([%d bytes]) ret=%08lx\n", iface, index, bytes, *(DWORD*)(args+bytes));\r
+\r
+  return RPCRT4_NdrClientCall2(This->stubless->pStubDesc, fs, args);\r
+}\r
+\r
+#else  /* __i386__ */\r
+\r
+/* can't do that on this arch */\r
+struct StublessThunk { int dummy; };\r
+#define FILL_STUBLESS(x,idx,stk) \\r
+ ERR("stubless proxies are not supported on this architecture\n");\r
+#define STACK_ADJUST 0\r
+\r
+#endif  /* __i386__ */\r
+\r
+HRESULT WINAPI StdProxy_Construct(REFIID riid,\r
+                                 LPUNKNOWN pUnkOuter,\r
+                                 PCInterfaceName name,\r
+                                 CInterfaceProxyVtbl *vtbl,\r
+                                 CInterfaceStubVtbl *svtbl,\r
+                                 LPPSFACTORYBUFFER pPSFactory,\r
+                                 LPRPCPROXYBUFFER *ppProxy,\r
+                                 LPVOID *ppvObj)\r
+{\r
+  StdProxyImpl *This;\r
+  const MIDL_STUBLESS_PROXY_INFO *stubless = NULL;\r
+\r
+  TRACE("(%p,%p,%p,%p,%p) %s\n", pUnkOuter, vtbl, pPSFactory, ppProxy, ppvObj, name);\r
+\r
+  /* I can't find any other way to detect stubless proxies than this hack */\r
+  if (!IsEqualGUID(vtbl->header.piid, riid)) {\r
+    stubless = *(const void **)vtbl;\r
+    vtbl = (CInterfaceProxyVtbl *)((const void **)vtbl + 1);\r
+    TRACE("stubless=%p\n", stubless);\r
+  }\r
+\r
+  TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid));\r
+  TRACE("vtbl=%p\n", vtbl->Vtbl);\r
+\r
+  if (!IsEqualGUID(vtbl->header.piid, riid)) {\r
+    ERR("IID mismatch during proxy creation\n");\r
+    return RPC_E_UNEXPECTED;\r
+  }\r
+\r
+  This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(StdProxyImpl));\r
+  if (!This) return E_OUTOFMEMORY;\r
+\r
+  if (stubless) {\r
+    unsigned i, count = svtbl->header.DispatchTableCount;\r
+    /* Maybe the original vtbl is just modified directly to point at\r
+     * ObjectStublessClientXXX thunks in real Windows, but I don't like it\r
+     */\r
+    TRACE("stubless thunks: count=%d\n", count);\r
+    This->thunks = HeapAlloc(GetProcessHeap(),0,sizeof(struct StublessThunk)*count);\r
+    This->PVtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID)*count);\r
+    for (i=0; i<count; i++) {\r
+      struct StublessThunk *thunk = &This->thunks[i];\r
+      if (vtbl->Vtbl[i] == (LPVOID)-1) {\r
+        PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i];\r
+        unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST;\r
+        TRACE("method %d: stacksize=%d\n", i, bytes);\r
+        FILL_STUBLESS(thunk, i, bytes)\r
+        This->PVtbl[i] = thunk;\r
+      }\r
+      else {\r
+        memset(thunk, 0, sizeof(struct StublessThunk));\r
+        This->PVtbl[i] = vtbl->Vtbl[i];\r
+      }\r
+    }\r
+  }\r
+  else \r
+    This->PVtbl = vtbl->Vtbl;\r
+\r
+  This->lpVtbl = &StdProxy_Vtbl;\r
+  /* 1 reference for the proxy and 1 for the object */\r
+  This->RefCount = 2;\r
+  This->stubless = stubless;\r
+  This->piid = vtbl->header.piid;\r
+  This->pUnkOuter = pUnkOuter;\r
+  This->name = name;\r
+  This->pPSFactory = pPSFactory;\r
+  This->pChannel = NULL;\r
+  *ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl;\r
+  *ppvObj = &This->PVtbl;\r
+  IPSFactoryBuffer_AddRef(pPSFactory);\r
+\r
+  return S_OK;\r
+}\r
+\r
+static void WINAPI StdProxy_Destruct(LPRPCPROXYBUFFER iface)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface);\r
+\r
+  if (This->pChannel)\r
+    IRpcProxyBuffer_Disconnect(iface);\r
+\r
+  IPSFactoryBuffer_Release(This->pPSFactory);\r
+  if (This->thunks) {\r
+    HeapFree(GetProcessHeap(),0,This->PVtbl);\r
+    HeapFree(GetProcessHeap(),0,This->thunks);\r
+  }\r
+  HeapFree(GetProcessHeap(),0,This);\r
+}\r
+\r
+static HRESULT WINAPI StdProxy_QueryInterface(LPRPCPROXYBUFFER iface,\r
+                                             REFIID riid,\r
+                                             LPVOID *obj)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface);\r
+  TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);\r
+\r
+  if (IsEqualGUID(&IID_IUnknown,riid) ||\r
+      IsEqualGUID(This->piid,riid)) {\r
+    *obj = &This->PVtbl;\r
+    This->RefCount++;\r
+    return S_OK;\r
+  }\r
+\r
+  if (IsEqualGUID(&IID_IRpcProxyBuffer,riid)) {\r
+    *obj = &This->lpVtbl;\r
+    This->RefCount++;\r
+    return S_OK;\r
+  }\r
+\r
+  return E_NOINTERFACE;\r
+}\r
+\r
+static ULONG WINAPI StdProxy_AddRef(LPRPCPROXYBUFFER iface)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface);\r
+  TRACE("(%p)->AddRef()\n",This);\r
+\r
+  return ++(This->RefCount);\r
+}\r
+\r
+static ULONG WINAPI StdProxy_Release(LPRPCPROXYBUFFER iface)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface);\r
+  TRACE("(%p)->Release()\n",This);\r
+\r
+  if (!--(This->RefCount)) {\r
+    StdProxy_Destruct((LPRPCPROXYBUFFER)&This->lpVtbl);\r
+    return 0;\r
+  }\r
+  return This->RefCount;\r
+}\r
+\r
+static HRESULT WINAPI StdProxy_Connect(LPRPCPROXYBUFFER iface,\r
+                                      LPRPCCHANNELBUFFER pChannel)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface);\r
+  TRACE("(%p)->Connect(%p)\n",This,pChannel);\r
+\r
+  This->pChannel = pChannel;\r
+  IRpcChannelBuffer_AddRef(pChannel);\r
+  return S_OK;\r
+}\r
+\r
+static VOID WINAPI StdProxy_Disconnect(LPRPCPROXYBUFFER iface)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface);\r
+  TRACE("(%p)->Disconnect()\n",This);\r
+\r
+  IRpcChannelBuffer_Release(This->pChannel);\r
+  This->pChannel = NULL;\r
+}\r
+\r
+static IRpcProxyBufferVtbl StdProxy_Vtbl =\r
+{\r
+  StdProxy_QueryInterface,\r
+  StdProxy_AddRef,\r
+  StdProxy_Release,\r
+  StdProxy_Connect,\r
+  StdProxy_Disconnect\r
+};\r
+\r
+HRESULT WINAPI StdProxy_GetChannel(LPVOID iface,\r
+                                  LPRPCCHANNELBUFFER *ppChannel)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface);\r
+  TRACE("(%p)->GetChannel(%p) %s\n",This,ppChannel,This->name);\r
+\r
+  *ppChannel = This->pChannel;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT WINAPI StdProxy_GetIID(LPVOID iface,\r
+                              const IID **ppiid)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface);\r
+  TRACE("(%p)->GetIID(%p) %s\n",This,ppiid,This->name);\r
+\r
+  *ppiid = This->piid;\r
+  return S_OK;\r
+}\r
+\r
+HRESULT WINAPI IUnknown_QueryInterface_Proxy(LPUNKNOWN iface,\r
+                                            REFIID riid,\r
+                                            LPVOID *ppvObj)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface);\r
+  TRACE("(%p)->QueryInterface(%s,%p) %s\n",This,debugstr_guid(riid),ppvObj,This->name);\r
+  return IUnknown_QueryInterface(This->pUnkOuter,riid,ppvObj);\r
+}\r
+\r
+ULONG WINAPI IUnknown_AddRef_Proxy(LPUNKNOWN iface)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface);\r
+  TRACE("(%p)->AddRef() %s\n",This,This->name);\r
+#if 0 /* interface refcounting */\r
+  return ++(This->RefCount);\r
+#else /* object refcounting */\r
+  return IUnknown_AddRef(This->pUnkOuter);\r
+#endif\r
+}\r
+\r
+ULONG WINAPI IUnknown_Release_Proxy(LPUNKNOWN iface)\r
+{\r
+  ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface);\r
+  TRACE("(%p)->Release() %s\n",This,This->name);\r
+#if 0 /* interface refcounting */\r
+  if (!--(This->RefCount)) {\r
+    StdProxy_Destruct((LPRPCPROXYBUFFER)&This->lpVtbl);\r
+    return 0;\r
+  }\r
+  return This->RefCount;\r
+#else /* object refcounting */\r
+  return IUnknown_Release(This->pUnkOuter);\r
+#endif\r
+}\r
+\r
+HRESULT WINAPI\r
+CreateProxyFromTypeInfo( LPTYPEINFO pTypeInfo, LPUNKNOWN pUnkOuter, REFIID riid,\r
+                         LPRPCPROXYBUFFER *ppProxy, LPVOID *ppv )\r
+{\r
+    FIXME("%p %p %s %p %p\n", pTypeInfo, pUnkOuter, debugstr_guid(riid), ppProxy, ppv);\r
+    return E_NOTIMPL;\r
+}\r
diff --git a/reactos/lib/rpcrt4/cpsf.c b/reactos/lib/rpcrt4/cpsf.c
new file mode 100644 (file)
index 0000000..0bd8eca
--- /dev/null
@@ -0,0 +1,263 @@
+/*\r
+ * COM proxy/stub factory (CStdPSFactory) implementation\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#define COBJMACROS\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+#include "winreg.h"\r
+\r
+#include "objbase.h"\r
+\r
+#include "rpcproxy.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+#include "cpsf.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+static BOOL FindProxyInfo(const ProxyFileInfo **pProxyFileList, REFIID riid, const ProxyFileInfo **pProxyInfo, int *pIndex)\r
+{\r
+  while (*pProxyFileList) {\r
+    if ((*pProxyFileList)->pIIDLookupRtn(riid, pIndex)) {\r
+      *pProxyInfo = *pProxyFileList;\r
+      TRACE("found: ProxyInfo %p Index %d\n", *pProxyInfo, *pIndex);\r
+      return TRUE;\r
+    }\r
+    pProxyFileList++;\r
+  }\r
+  TRACE("not found\n");\r
+  return FALSE;\r
+}\r
+\r
+static HRESULT WINAPI CStdPSFactory_QueryInterface(LPPSFACTORYBUFFER iface,\r
+                                                  REFIID riid,\r
+                                                  LPVOID *obj)\r
+{\r
+  CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;\r
+  TRACE("(%p)->QueryInterface(%s,%p)\n",iface,debugstr_guid(riid),obj);\r
+  if (IsEqualGUID(&IID_IUnknown,riid) ||\r
+      IsEqualGUID(&IID_IPSFactoryBuffer,riid)) {\r
+    *obj = This;\r
+    This->RefCount++;\r
+    return S_OK;\r
+  }\r
+  return E_NOINTERFACE;\r
+}\r
+\r
+static ULONG WINAPI CStdPSFactory_AddRef(LPPSFACTORYBUFFER iface)\r
+{\r
+  CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;\r
+  TRACE("(%p)->AddRef()\n",iface);\r
+  return ++(This->RefCount);\r
+}\r
+\r
+static ULONG WINAPI CStdPSFactory_Release(LPPSFACTORYBUFFER iface)\r
+{\r
+  CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;\r
+  TRACE("(%p)->Release()\n",iface);\r
+  return --(This->RefCount);\r
+}\r
+\r
+static HRESULT WINAPI CStdPSFactory_CreateProxy(LPPSFACTORYBUFFER iface,\r
+                                               LPUNKNOWN pUnkOuter,\r
+                                               REFIID riid,\r
+                                               LPRPCPROXYBUFFER *ppProxy,\r
+                                               LPVOID *ppv)\r
+{\r
+  CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;\r
+  const ProxyFileInfo *ProxyInfo;\r
+  int Index;\r
+  TRACE("(%p)->CreateProxy(%p,%s,%p,%p)\n",iface,pUnkOuter,\r
+       debugstr_guid(riid),ppProxy,ppv);\r
+  if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))\r
+    return E_NOINTERFACE;\r
+  return StdProxy_Construct(riid, pUnkOuter, ProxyInfo->pNamesArray[Index],\r
+                            ProxyInfo->pProxyVtblList[Index],\r
+                            ProxyInfo->pStubVtblList[Index], iface, ppProxy, ppv);\r
+}\r
+\r
+static HRESULT WINAPI CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface,\r
+                                              REFIID riid,\r
+                                              LPUNKNOWN pUnkServer,\r
+                                              LPRPCSTUBBUFFER *ppStub)\r
+{\r
+  CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;\r
+  const ProxyFileInfo *ProxyInfo;\r
+  int Index;\r
+  TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface,debugstr_guid(riid),\r
+       pUnkServer,ppStub);\r
+  if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))\r
+    return E_NOINTERFACE;\r
+  return CStdStubBuffer_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index],\r
+                                  ProxyInfo->pStubVtblList[Index], iface, ppStub);\r
+}\r
+\r
+static IPSFactoryBufferVtbl CStdPSFactory_Vtbl =\r
+{\r
+  CStdPSFactory_QueryInterface,\r
+  CStdPSFactory_AddRef,\r
+  CStdPSFactory_Release,\r
+  CStdPSFactory_CreateProxy,\r
+  CStdPSFactory_CreateStub\r
+};\r
+\r
+/***********************************************************************\r
+ *           NdrDllGetClassObject [RPCRT4.@]\r
+ */\r
+HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv,\r
+                                   const ProxyFileInfo **pProxyFileList,\r
+                                   const CLSID *pclsid,\r
+                                   CStdPSFactoryBuffer *pPSFactoryBuffer)\r
+{\r
+  *ppv = NULL;\r
+  if (!pPSFactoryBuffer->lpVtbl) {\r
+    pPSFactoryBuffer->lpVtbl = &CStdPSFactory_Vtbl;\r
+    pPSFactoryBuffer->RefCount = 0;\r
+    pPSFactoryBuffer->pProxyFileList = pProxyFileList;\r
+  }\r
+  if (IsEqualGUID(rclsid, pclsid))\r
+    return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv);\r
+  return CLASS_E_CLASSNOTAVAILABLE;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrDllCanUnloadNow [RPCRT4.@]\r
+ */\r
+HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer)\r
+{\r
+  return !(pPSFactoryBuffer->RefCount);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrDllRegisterProxy [RPCRT4.@]\r
+ */\r
+HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll,\r
+                                  const ProxyFileInfo **pProxyFileList,\r
+                                  const CLSID *pclsid)\r
+{\r
+  LPSTR clsid;\r
+  char keyname[120], module[MAX_PATH];\r
+  HKEY key, subkey;\r
+  DWORD len;\r
+\r
+  TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));\r
+  UuidToStringA((UUID*)pclsid, (unsigned char**)&clsid);\r
+\r
+  /* register interfaces to point to clsid */\r
+  while (*pProxyFileList) {\r
+    unsigned u;\r
+    for (u=0; u<(*pProxyFileList)->TableSize; u++) {\r
+      CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u];\r
+      PCInterfaceName name = (*pProxyFileList)->pNamesArray[u];\r
+      LPSTR iid;\r
+\r
+      TRACE("registering %s %s => %s\n", name, debugstr_guid(proxy->header.piid), clsid);\r
+\r
+      UuidToStringA((UUID*)proxy->header.piid, (unsigned char**)&iid);\r
+      snprintf(keyname, sizeof(keyname), "Interface\\{%s}", iid);\r
+      RpcStringFreeA((unsigned char**)&iid);\r
+      if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyname, 0, NULL, 0,\r
+                          KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {\r
+        if (name)\r
+          RegSetValueExA(key, NULL, 0, REG_SZ, name, strlen(name));\r
+        if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,\r
+                            KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) {\r
+          snprintf(module, sizeof(module), "{%s}", clsid);\r
+          RegSetValueExA(subkey, NULL, 0, REG_SZ, module, strlen(module));\r
+          RegCloseKey(subkey);\r
+        }\r
+        RegCloseKey(key);\r
+      }\r
+    }\r
+    pProxyFileList++;\r
+  }\r
+\r
+  /* register clsid to point to module */\r
+  snprintf(keyname, sizeof(keyname), "CLSID\\{%s}", clsid);\r
+  len = GetModuleFileNameA(hDll, module, sizeof(module));\r
+  if (len && len < sizeof(module)) {\r
+    TRACE("registering CLSID %s => %s\n", clsid, module);\r
+    if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyname, 0, NULL, 0,\r
+                        KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {\r
+      if (RegCreateKeyExA(key, "InProcServer32", 0, NULL, 0,\r
+                          KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) {\r
+        RegSetValueExA(subkey, NULL, 0, REG_SZ, module, strlen(module));\r
+        RegCloseKey(subkey);\r
+      }\r
+      RegCloseKey(key);\r
+    }\r
+  }\r
+\r
+  /* done */\r
+  RpcStringFreeA((unsigned char**)&clsid);\r
+  return S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrDllUnregisterProxy [RPCRT4.@]\r
+ */\r
+HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll,\r
+                                    const ProxyFileInfo **pProxyFileList,\r
+                                    const CLSID *pclsid)\r
+{\r
+  LPSTR clsid;\r
+  char keyname[120], module[MAX_PATH];\r
+  DWORD len;\r
+\r
+  TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));\r
+  UuidToStringA((UUID*)pclsid, (unsigned char**)&clsid);\r
+\r
+  /* unregister interfaces */\r
+  while (*pProxyFileList) {\r
+    unsigned u;\r
+    for (u=0; u<(*pProxyFileList)->TableSize; u++) {\r
+      CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u];\r
+      PCInterfaceName name = (*pProxyFileList)->pNamesArray[u];\r
+      LPSTR iid;\r
+\r
+      TRACE("unregistering %s %s <= %s\n", name, debugstr_guid(proxy->header.piid), clsid);\r
+\r
+      UuidToStringA((UUID*)proxy->header.piid, (unsigned char**)&iid);\r
+      snprintf(keyname, sizeof(keyname), "Interface\\{%s}", iid);\r
+      RpcStringFreeA((unsigned char**)&iid);\r
+      RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname);\r
+    }\r
+    pProxyFileList++;\r
+  }\r
+\r
+  /* unregister clsid */\r
+  snprintf(keyname, sizeof(keyname), "CLSID\\{%s}", clsid);\r
+  len = GetModuleFileNameA(hDll, module, sizeof(module));\r
+  if (len && len < sizeof(module)) {\r
+    TRACE("unregistering CLSID %s <= %s\n", clsid, module);\r
+    RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname);\r
+  }\r
+\r
+  /* done */\r
+  RpcStringFreeA((unsigned char**)&clsid);\r
+  return S_OK;\r
+}\r
diff --git a/reactos/lib/rpcrt4/cpsf.h b/reactos/lib/rpcrt4/cpsf.h
new file mode 100644 (file)
index 0000000..12f3375
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+ * COM proxy definitions\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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 __WINE_CPSF_H\r
+#define __WINE_CPSF_H\r
+\r
+HRESULT WINAPI StdProxy_Construct(REFIID riid,\r
+                                 LPUNKNOWN pUnkOuter,\r
+                                 PCInterfaceName name,\r
+                                 CInterfaceProxyVtbl *vtbl,\r
+                                 CInterfaceStubVtbl *svtbl,\r
+                                 LPPSFACTORYBUFFER pPSFactory,\r
+                                 LPRPCPROXYBUFFER *ppProxy,\r
+                                 LPVOID *ppvObj);\r
+HRESULT WINAPI StdProxy_GetChannel(LPVOID iface,\r
+                                  LPRPCCHANNELBUFFER *ppChannel);\r
+HRESULT WINAPI StdProxy_GetIID(LPVOID iface,\r
+                              const IID **piid);\r
+\r
+HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid,\r
+                                       LPUNKNOWN pUnkServer,\r
+                                       PCInterfaceName name,\r
+                                       CInterfaceStubVtbl *vtbl,\r
+                                       LPPSFACTORYBUFFER pPSFactory,\r
+                                       LPRPCSTUBBUFFER *ppStub);\r
+\r
+#endif  /* __WINE_CPSF_H */\r
diff --git a/reactos/lib/rpcrt4/cstub.c b/reactos/lib/rpcrt4/cstub.c
new file mode 100644 (file)
index 0000000..bf590d8
--- /dev/null
@@ -0,0 +1,169 @@
+/*\r
+ * COM stub (CStdStubBuffer) implementation\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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
+#include <stdarg.h>\r
+\r
+#define COBJMACROS\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+\r
+#include "objbase.h"\r
+\r
+#include "rpcproxy.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+#include "cpsf.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+#define STUB_HEADER(This) (((CInterfaceStubHeader*)((This)->lpVtbl))[-1])\r
+\r
+HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid,\r
+                                       LPUNKNOWN pUnkServer,\r
+                                       PCInterfaceName name,\r
+                                       CInterfaceStubVtbl *vtbl,\r
+                                       LPPSFACTORYBUFFER pPSFactory,\r
+                                       LPRPCSTUBBUFFER *ppStub)\r
+{\r
+  CStdStubBuffer *This;\r
+\r
+  TRACE("(%p,%p,%p,%p) %s\n", pUnkServer, vtbl, pPSFactory, ppStub, name);\r
+  TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid));\r
+  TRACE("vtbl=%p\n", &vtbl->Vtbl);\r
+\r
+  if (!IsEqualGUID(vtbl->header.piid, riid)) {\r
+    ERR("IID mismatch during stub creation\n");\r
+    return RPC_E_UNEXPECTED;\r
+  }\r
+\r
+  This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CStdStubBuffer));\r
+  if (!This) return E_OUTOFMEMORY;\r
+\r
+  This->lpVtbl = &vtbl->Vtbl;\r
+  This->RefCount = 1;\r
+  This->pvServerObject = pUnkServer;\r
+  This->pPSFactory = pPSFactory;\r
+  *ppStub = (LPRPCSTUBBUFFER)This;\r
+\r
+  IUnknown_AddRef(This->pvServerObject);\r
+  IPSFactoryBuffer_AddRef(pPSFactory);\r
+  return S_OK;\r
+}\r
+\r
+HRESULT WINAPI CStdStubBuffer_QueryInterface(LPRPCSTUBBUFFER iface,\r
+                                            REFIID riid,\r
+                                            LPVOID *obj)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);\r
+\r
+  if (IsEqualGUID(&IID_IUnknown,riid) ||\r
+      IsEqualGUID(&IID_IRpcStubBuffer,riid)) {\r
+    *obj = This;\r
+    This->RefCount++;\r
+    return S_OK;\r
+  }\r
+  return E_NOINTERFACE;\r
+}\r
+\r
+ULONG WINAPI CStdStubBuffer_AddRef(LPRPCSTUBBUFFER iface)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  TRACE("(%p)->AddRef()\n",This);\r
+  return ++(This->RefCount);\r
+}\r
+\r
+ULONG WINAPI NdrCStdStubBuffer_Release(LPRPCSTUBBUFFER iface,\r
+                                      LPPSFACTORYBUFFER pPSF)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  TRACE("(%p)->Release()\n",This);\r
+\r
+  if (!--(This->RefCount)) {\r
+    if(This->pvServerObject)\r
+        IUnknown_Release(This->pvServerObject);\r
+    if(This->pPSFactory)\r
+        IPSFactoryBuffer_Release(This->pPSFactory);\r
+    HeapFree(GetProcessHeap(),0,This);\r
+    return 0;\r
+  }\r
+  return This->RefCount;\r
+}\r
+\r
+HRESULT WINAPI CStdStubBuffer_Connect(LPRPCSTUBBUFFER iface,\r
+                                     LPUNKNOWN lpUnkServer)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  TRACE("(%p)->Connect(%p)\n",This,lpUnkServer);\r
+  This->pvServerObject = lpUnkServer;\r
+  return S_OK;\r
+}\r
+\r
+void WINAPI CStdStubBuffer_Disconnect(LPRPCSTUBBUFFER iface)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  TRACE("(%p)->Disconnect()\n",This);\r
+  This->pvServerObject = NULL;\r
+}\r
+\r
+HRESULT WINAPI CStdStubBuffer_Invoke(LPRPCSTUBBUFFER iface,\r
+                                    PRPCOLEMESSAGE pMsg,\r
+                                    LPRPCCHANNELBUFFER pChannel)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  DWORD dwPhase = STUB_UNMARSHAL;\r
+  TRACE("(%p)->Invoke(%p,%p)\n",This,pMsg,pChannel);\r
+\r
+  STUB_HEADER(This).pDispatchTable[pMsg->iMethod](iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase);\r
+  return S_OK;\r
+}\r
+\r
+LPRPCSTUBBUFFER WINAPI CStdStubBuffer_IsIIDSupported(LPRPCSTUBBUFFER iface,\r
+                                                    REFIID riid)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  TRACE("(%p)->IsIIDSupported(%s)\n",This,debugstr_guid(riid));\r
+  return IsEqualGUID(STUB_HEADER(This).piid, riid) ? iface : NULL;\r
+}\r
+\r
+ULONG WINAPI CStdStubBuffer_CountRefs(LPRPCSTUBBUFFER iface)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  TRACE("(%p)->CountRefs()\n",This);\r
+  return This->RefCount;\r
+}\r
+\r
+HRESULT WINAPI CStdStubBuffer_DebugServerQueryInterface(LPRPCSTUBBUFFER iface,\r
+                                                       LPVOID *ppv)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  TRACE("(%p)->DebugServerQueryInterface(%p)\n",This,ppv);\r
+  return S_OK;\r
+}\r
+\r
+void WINAPI CStdStubBuffer_DebugServerRelease(LPRPCSTUBBUFFER iface,\r
+                                             LPVOID pv)\r
+{\r
+  CStdStubBuffer *This = (CStdStubBuffer *)iface;\r
+  TRACE("(%p)->DebugServerRelease(%p)\n",This,pv);\r
+}\r
diff --git a/reactos/lib/rpcrt4/ndr_marshall.c b/reactos/lib/rpcrt4/ndr_marshall.c
new file mode 100644 (file)
index 0000000..33ff8f5
--- /dev/null
@@ -0,0 +1,2118 @@
+/*\r
+ * NDR data marshalling\r
+ *\r
+ * Copyright 2002 Greg Turner\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
+ * TODO:\r
+ *  - figure out whether we *really* got this right\r
+ *  - check for errors and throw exceptions\r
+ */\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <assert.h>\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+#include "winreg.h"\r
+\r
+#include "ndr_misc.h"\r
+#include "rpcndr.h"\r
+\r
+#include "wine/unicode.h"\r
+#include "wine/rpcfc.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+#define BUFFER_PARANOIA 20\r
+\r
+#if defined(__i386__)\r
+  #define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \\r
+    (*((UINT32 *)(pchar)) = (uint32))\r
+\r
+  #define LITTLE_ENDIAN_UINT32_READ(pchar) \\r
+    (*((UINT32 *)(pchar)))\r
+#else\r
+  /* these would work for i386 too, but less efficient */\r
+  #define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \\r
+    (*(pchar)     = LOBYTE(LOWORD(uint32)), \\r
+     *((pchar)+1) = HIBYTE(LOWORD(uint32)), \\r
+     *((pchar)+2) = LOBYTE(HIWORD(uint32)), \\r
+     *((pchar)+3) = HIBYTE(HIWORD(uint32)), \\r
+     (uint32)) /* allow as r-value */\r
+\r
+  #define LITTLE_ENDIAN_UINT32_READ(pchar) \\r
+    (MAKELONG( \\r
+      MAKEWORD(*(pchar), *((pchar)+1)), \\r
+      MAKEWORD(*((pchar)+2), *((pchar)+3))))\r
+#endif\r
+\r
+#define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \\r
+  (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \\r
+   *((pchar)+2) = HIBYTE(LOWORD(uint32)), \\r
+   *((pchar)+1) = LOBYTE(HIWORD(uint32)), \\r
+   *(pchar)     = HIBYTE(HIWORD(uint32)), \\r
+   (uint32)) /* allow as r-value */\r
+\r
+#define BIG_ENDIAN_UINT32_READ(pchar) \\r
+  (MAKELONG( \\r
+    MAKEWORD(*((pchar)+3), *((pchar)+2)), \\r
+    MAKEWORD(*((pchar)+1), *(pchar))))\r
+\r
+#ifdef NDR_LOCAL_IS_BIG_ENDIAN\r
+  #define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \\r
+    BIG_ENDIAN_UINT32_WRITE(pchar, uint32)\r
+  #define NDR_LOCAL_UINT32_READ(pchar) \\r
+    BIG_ENDIAN_UINT32_READ(pchar)\r
+#else\r
+  #define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \\r
+    LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)\r
+  #define NDR_LOCAL_UINT32_READ(pchar) \\r
+    LITTLE_ENDIAN_UINT32_READ(pchar)\r
+#endif\r
+\r
+/* _Align must be the desired alignment minus 1,\r
+ * e.g. ALIGN_LENGTH(len, 3) to align on a dword boundary. */\r
+#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))\r
+#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))\r
+#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)\r
+#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)\r
+\r
+#define STD_OVERFLOW_CHECK(_Msg) do { \\r
+    TRACE("buffer=%d/%ld\n", _Msg->Buffer - _Msg->BufferStart, _Msg->BufferLength); \\r
+    if (_Msg->Buffer > _Msg->BufferEnd) ERR("buffer overflow %d bytes\n", _Msg->Buffer - _Msg->BufferEnd); \\r
+  } while (0)\r
+\r
+#define NDR_TABLE_SIZE 128\r
+#define NDR_TABLE_MASK 127\r
+\r
+NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  /* 0x10 */\r
+  0,\r
+  /* 0x11 */\r
+  NdrPointerMarshall, NdrPointerMarshall,\r
+  NdrPointerMarshall, NdrPointerMarshall,\r
+  /* 0x15 */\r
+  NdrSimpleStructMarshall, NdrSimpleStructMarshall,\r
+  0, 0, 0,\r
+  NdrComplexStructMarshall,\r
+  /* 0x1b */\r
+  NdrConformantArrayMarshall, 0, 0, 0, 0, 0,\r
+  NdrComplexArrayMarshall,\r
+  /* 0x22 */\r
+  NdrConformantStringMarshall, 0, 0,\r
+  NdrConformantStringMarshall, 0, 0, 0, 0,\r
+  /* 0x2a */\r
+  0, 0, 0, 0, 0,\r
+  /* 0x2f */\r
+  NdrInterfacePointerMarshall,\r
+  /* 0xb0 */\r
+  0, 0, 0, 0,\r
+  NdrUserMarshalMarshall\r
+};\r
+NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  /* 0x10 */\r
+  0,\r
+  /* 0x11 */\r
+  NdrPointerUnmarshall, NdrPointerUnmarshall,\r
+  NdrPointerUnmarshall, NdrPointerUnmarshall,\r
+  /* 0x15 */\r
+  NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,\r
+  0, 0, 0,\r
+  NdrComplexStructUnmarshall,\r
+  /* 0x1b */\r
+  NdrConformantArrayUnmarshall, 0, 0, 0, 0, 0,\r
+  NdrComplexArrayUnmarshall,\r
+  /* 0x22 */\r
+  NdrConformantStringUnmarshall, 0, 0,\r
+  NdrConformantStringUnmarshall, 0, 0, 0, 0,\r
+  /* 0x2a */\r
+  0, 0, 0, 0, 0,\r
+  /* 0x2f */\r
+  NdrInterfacePointerUnmarshall,\r
+  /* 0xb0 */\r
+  0, 0, 0, 0,\r
+  NdrUserMarshalUnmarshall\r
+};\r
+NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  /* 0x10 */\r
+  0,\r
+  /* 0x11 */\r
+  NdrPointerBufferSize, NdrPointerBufferSize,\r
+  NdrPointerBufferSize, NdrPointerBufferSize,\r
+  /* 0x15 */\r
+  NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,\r
+  0, 0, 0,\r
+  NdrComplexStructBufferSize,\r
+  /* 0x1b */\r
+  NdrConformantArrayBufferSize, 0, 0, 0, 0, 0,\r
+  NdrComplexArrayBufferSize,\r
+  /* 0x22 */\r
+  NdrConformantStringBufferSize, 0, 0,\r
+  NdrConformantStringBufferSize, 0, 0, 0, 0,\r
+  /* 0x2a */\r
+  0, 0, 0, 0, 0,\r
+  /* 0x2f */\r
+  NdrInterfacePointerBufferSize,\r
+  /* 0xb0 */\r
+  0, 0, 0, 0,\r
+  NdrUserMarshalBufferSize\r
+};\r
+NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  /* 0x10 */\r
+  0,\r
+  /* 0x11 */\r
+  NdrPointerMemorySize, NdrPointerMemorySize,\r
+  NdrPointerMemorySize, NdrPointerMemorySize,\r
+  /* 0x15 */\r
+  NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,\r
+  0, 0, 0,\r
+  NdrComplexStructMemorySize,\r
+  /* 0x1b */\r
+  NdrConformantArrayMemorySize, 0, 0, 0, 0, 0,\r
+  NdrComplexArrayMemorySize,\r
+  /* 0x22 */\r
+  NdrConformantStringMemorySize, 0, 0,\r
+  NdrConformantStringMemorySize, 0, 0, 0, 0,\r
+  /* 0x2a */\r
+  0, 0, 0, 0, 0,\r
+  /* 0x2f */\r
+  NdrInterfacePointerMemorySize,\r
+  /* 0xb0 */\r
+  0, 0, 0, 0,\r
+  NdrUserMarshalMemorySize\r
+};\r
+NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  /* 0x10 */\r
+  0,\r
+  /* 0x11 */\r
+  NdrPointerFree, NdrPointerFree,\r
+  NdrPointerFree, NdrPointerFree,\r
+  /* 0x15 */\r
+  NdrSimpleStructFree, NdrSimpleStructFree,\r
+  0, 0, 0,\r
+  NdrComplexStructFree,\r
+  /* 0x1b */\r
+  NdrConformantArrayFree, 0, 0, 0, 0, 0,\r
+  NdrComplexArrayFree,\r
+  /* 0x22 */\r
+  0, 0, 0, 0, 0, 0, 0, 0,\r
+  /* 0x2a */\r
+  0, 0, 0, 0, 0,\r
+  /* 0x2f */\r
+  NdrInterfacePointerFree,\r
+  /* 0xb0 */\r
+  0, 0, 0, 0,\r
+  NdrUserMarshalFree\r
+};\r
+\r
+void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)\r
+{\r
+  /* hmm, this is probably supposed to do more? */\r
+  return pStubMsg->pfnAllocate(len);\r
+}\r
+\r
+static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)\r
+{\r
+  pStubMsg->pfnFree(Pointer);\r
+}\r
+\r
+PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)\r
+{\r
+  pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);\r
+  pStubMsg->Buffer += 4;\r
+  TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);\r
+  return pFormat+4;\r
+}\r
+\r
+PFORMAT_STRING ComputeConformance(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,\r
+                                  PFORMAT_STRING pFormat, ULONG_PTR def)\r
+{\r
+  BYTE dtype = pFormat[0] & 0xf;\r
+  DWORD ofs = (DWORD)pFormat[2] | ((DWORD)pFormat[3] << 8);\r
+  LPVOID ptr = NULL;\r
+  DWORD data = 0;\r
+\r
+  if (pFormat[0] == 0xff) {\r
+    /* null descriptor */\r
+    pStubMsg->MaxCount = def;\r
+    goto finish_conf;\r
+  }\r
+\r
+  switch (pFormat[0] & 0xf0) {\r
+  case RPC_FC_NORMAL_CONFORMANCE:\r
+    TRACE("normal conformance, ofs=%ld\n", ofs);\r
+    ptr = pMemory + ofs;\r
+    break;\r
+  case RPC_FC_POINTER_CONFORMANCE:\r
+    TRACE("pointer conformance, ofs=%ld\n", ofs);\r
+    ptr = pStubMsg->Memory + ofs;\r
+    break;\r
+  case RPC_FC_TOP_LEVEL_CONFORMANCE:\r
+    TRACE("toplevel conformance, ofs=%ld\n", ofs);\r
+    if (pStubMsg->StackTop) {\r
+      ptr = pStubMsg->StackTop + ofs;\r
+    }\r
+    else {\r
+      /* -Os mode, MaxCount is already set */\r
+      goto finish_conf;\r
+    }\r
+    break;\r
+  case RPC_FC_CONSTANT_CONFORMANCE:\r
+    data = ofs | ((DWORD)pFormat[1] << 16);\r
+    TRACE("constant conformance, val=%ld\n", data);\r
+    pStubMsg->MaxCount = data;\r
+    goto finish_conf;\r
+  case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:\r
+    FIXME("toplevel multidimensional conformance, ofs=%ld\n", ofs);\r
+    if (pStubMsg->StackTop) {\r
+      ptr = pStubMsg->StackTop + ofs;\r
+    }\r
+    else {\r
+      /* ? */\r
+      goto done_conf_grab;\r
+    }\r
+    break;\r
+  default:\r
+    FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);\r
+  }\r
+\r
+  switch (pFormat[1]) {\r
+  case RPC_FC_DEREFERENCE:\r
+    ptr = *(LPVOID*)ptr;\r
+    break;\r
+  case RPC_FC_CALLBACK:\r
+    /* ofs is index into StubDesc->apfnExprEval */\r
+    FIXME("handle callback\n");\r
+    goto finish_conf;\r
+  default:\r
+    break;\r
+  }\r
+\r
+  switch (dtype) {\r
+  case RPC_FC_LONG:\r
+  case RPC_FC_ULONG:\r
+    data = *(DWORD*)ptr;\r
+    break;\r
+  case RPC_FC_SHORT:\r
+    data = *(SHORT*)ptr;\r
+    break;\r
+  case RPC_FC_USHORT:\r
+    data = *(USHORT*)ptr;\r
+    break;\r
+  case RPC_FC_SMALL:\r
+    data = *(CHAR*)ptr;\r
+    break;\r
+  case RPC_FC_USMALL:\r
+    data = *(UCHAR*)ptr;\r
+    break;\r
+  default:\r
+    FIXME("unknown conformance data type %x\n", dtype);\r
+    goto done_conf_grab;\r
+  }\r
+  TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);\r
+\r
+done_conf_grab:\r
+  switch (pFormat[1]) {\r
+  case 0: /* no op */\r
+    pStubMsg->MaxCount = data;\r
+    break;\r
+  case RPC_FC_DEREFERENCE:\r
+    /* already handled */\r
+    break;\r
+  default:\r
+    FIXME("unknown conformance op %d\n", pFormat[1]);\r
+    goto finish_conf;\r
+  }\r
+\r
+finish_conf:\r
+  TRACE("resulting conformance is %ld\n", pStubMsg->MaxCount);\r
+  return pFormat+4;\r
+}\r
+\r
+\r
+/*\r
+ * NdrConformantString:\r
+ * \r
+ * What MS calls a ConformantString is, in DCE terminology,\r
+ * a Varying-Conformant String.\r
+ * [\r
+ *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')\r
+ *   offset: DWORD (actual string data begins at (offset) CHARTYPE's\r
+ *           into unmarshalled string) \r
+ *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')\r
+ *   [ \r
+ *     data: CHARTYPE[maxlen]\r
+ *   ] \r
+ * ], where CHARTYPE is the appropriate character type (specified externally)\r
+ *\r
+ */\r
+\r
+/***********************************************************************\r
+ *            NdrConformantStringMarshall [RPCRT4.@]\r
+ */\r
+unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,\r
+  unsigned char *pszMessage, PFORMAT_STRING pFormat)\r
+{ \r
+  unsigned long len, esize;\r
+  unsigned char *c;\r
+\r
+  TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);\r
+  \r
+  assert(pFormat);\r
+  if (*pFormat == RPC_FC_C_CSTRING) {\r
+    TRACE("string=%s\n", debugstr_a(pszMessage));\r
+    len = strlen(pszMessage)+1;\r
+    esize = 1;\r
+  }\r
+  else if (*pFormat == RPC_FC_C_WSTRING) {\r
+    TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));\r
+    len = strlenW((LPWSTR)pszMessage)+1;\r
+    esize = 2;\r
+  }\r
+  else {\r
+    ERR("Unhandled string type: %#x\n", *pFormat); \r
+    /* FIXME: raise an exception. */\r
+    return NULL;\r
+  }\r
+\r
+  if (pFormat[1] != RPC_FC_PAD) {\r
+    FIXME("sized string format=%d\n", pFormat[1]);\r
+  }\r
+\r
+  assert( (pStubMsg->BufferLength >= (len*esize + 13)) && (pStubMsg->Buffer != NULL) );\r
+\r
+  c = pStubMsg->Buffer;\r
+  memset(c, 0, 12);\r
+  NDR_LOCAL_UINT32_WRITE(c, len); /* max length: strlen + 1 (for '\0') */\r
+  c += 8;                         /* offset: 0 */\r
+  NDR_LOCAL_UINT32_WRITE(c, len); /* actual length: (same) */\r
+  c += 4;\r
+  memcpy(c, pszMessage, len*esize); /* the string itself */\r
+  c += len*esize;\r
+  pStubMsg->Buffer = c;\r
+\r
+  STD_OVERFLOW_CHECK(pStubMsg);\r
+\r
+  /* success */\r
+  return NULL; /* is this always right? */\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrConformantStringBufferSize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+  unsigned char* pMemory, PFORMAT_STRING pFormat)\r
+{\r
+  TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  assert(pFormat);\r
+  if (*pFormat == RPC_FC_C_CSTRING) {\r
+    /* we need 12 octets for the [maxlen, offset, len] DWORDS, + 1 octet for '\0' */\r
+    TRACE("string=%s\n", debugstr_a(pMemory));\r
+    pStubMsg->BufferLength += strlen(pMemory) + 13 + BUFFER_PARANOIA;\r
+  }\r
+  else if (*pFormat == RPC_FC_C_WSTRING) {\r
+    /* we need 12 octets for the [maxlen, offset, len] DWORDS, + 2 octets for L'\0' */\r
+    TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));\r
+    pStubMsg->BufferLength += strlenW((LPWSTR)pMemory)*2 + 14 + BUFFER_PARANOIA;\r
+  }\r
+  else {\r
+    ERR("Unhandled string type: %#x\n", *pFormat); \r
+    /* FIXME: raise an exception */\r
+  }\r
+\r
+  if (pFormat[1] != RPC_FC_PAD) {\r
+    FIXME("sized string format=%d\n", pFormat[1]);\r
+  }\r
+}\r
+\r
+/************************************************************************\r
+ *            NdrConformantStringMemorySize [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,\r
+  PFORMAT_STRING pFormat )\r
+{\r
+  unsigned long rslt = 0;\r
+\r
+  TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);\r
+   \r
+  assert(pStubMsg && pFormat);\r
+\r
+  if (*pFormat == RPC_FC_C_CSTRING) {\r
+    rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */\r
+  }\r
+  else if (*pFormat == RPC_FC_C_WSTRING) {\r
+    rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */\r
+  }\r
+  else {\r
+    ERR("Unhandled string type: %#x\n", *pFormat);\r
+    /* FIXME: raise an exception */\r
+  }\r
+\r
+  if (pFormat[1] != RPC_FC_PAD) {\r
+    FIXME("sized string format=%d\n", pFormat[1]);\r
+  }\r
+\r
+  TRACE("  --> %lu\n", rslt);\r
+  return rslt;\r
+}\r
+\r
+/************************************************************************\r
+ *           NdrConformantStringUnmarshall [RPCRT4.@]\r
+ */\r
+unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,\r
+  unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )\r
+{\r
+  unsigned long len, esize, ofs;\r
+  unsigned char *pMem;\r
+\r
+  TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",\r
+    pStubMsg, *ppMemory, pFormat, fMustAlloc);\r
+\r
+  assert(pFormat && ppMemory && pStubMsg);\r
+\r
+  pStubMsg->Buffer += 4;\r
+  ofs = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);\r
+  pStubMsg->Buffer += 4;\r
+  len = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);\r
+  pStubMsg->Buffer += 4;\r
+\r
+  if (*pFormat == RPC_FC_C_CSTRING) esize = 1;\r
+  else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;\r
+  else {\r
+    ERR("Unhandled string type: %#x\n", *pFormat);\r
+    /* FIXME: raise an exception */\r
+    esize = 0;\r
+  }\r
+\r
+  if (pFormat[1] != RPC_FC_PAD) {\r
+    FIXME("sized string format=%d\n", pFormat[1]);\r
+  }\r
+\r
+  if (fMustAlloc) {\r
+    *ppMemory = NdrAllocate(pStubMsg, len*esize + BUFFER_PARANOIA);\r
+  } else {\r
+    if (pStubMsg->ReuseBuffer && !*ppMemory)\r
+      /* for servers, we may just point straight into the RPC buffer, I think\r
+       * (I guess that's what MS does since MIDL code doesn't try to free) */\r
+      *ppMemory = pStubMsg->Buffer - ofs*esize;\r
+    /* for clients, memory should be provided by caller */\r
+  }\r
+\r
+  pMem = *ppMemory + ofs*esize;\r
+\r
+  if (pMem != pStubMsg->Buffer)\r
+    memcpy(pMem, pStubMsg->Buffer, len*esize);\r
+\r
+  pStubMsg->Buffer += len*esize;\r
+\r
+  if (*pFormat == RPC_FC_C_CSTRING) {\r
+    TRACE("string=%s\n", debugstr_a(pMem));\r
+  }\r
+  else if (*pFormat == RPC_FC_C_WSTRING) {\r
+    TRACE("string=%s\n", debugstr_w((LPWSTR)pMem));\r
+  }\r
+\r
+  return NULL; /* FIXME: is this always right? */\r
+}\r
+\r
+/***********************************************************************\r
+ *           PointerMarshall\r
+ */\r
+void WINAPI PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                            unsigned char *Buffer,\r
+                            unsigned char *Pointer,\r
+                            PFORMAT_STRING pFormat)\r
+{\r
+  unsigned type = pFormat[0], attr = pFormat[1];\r
+  PFORMAT_STRING desc;\r
+  NDR_MARSHALL m;\r
+\r
+  TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);\r
+  TRACE("type=%d, attr=%d\n", type, attr);\r
+  pFormat += 2;\r
+  if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;\r
+  else desc = pFormat + *(const SHORT*)pFormat;\r
+  if (attr & RPC_FC_P_DEREF) {\r
+    Pointer = *(unsigned char**)Pointer;\r
+    TRACE("deref => %p\n", Pointer);\r
+  }\r
+\r
+  *(LPVOID*)Buffer = 0;\r
+\r
+  switch (type) {\r
+  case RPC_FC_RP: /* ref pointer (always non-null) */\r
+    break;\r
+  default:\r
+    FIXME("unhandled ptr type=%02x\n", type);\r
+  }\r
+\r
+  m = NdrMarshaller[*desc & NDR_TABLE_MASK];\r
+  if (m) m(pStubMsg, Pointer, desc);\r
+  else FIXME("no marshaller for data type=%02x\n", *desc);\r
+\r
+  STD_OVERFLOW_CHECK(pStubMsg);\r
+}\r
+\r
+/***********************************************************************\r
+ *           PointerUnmarshall\r
+ */\r
+void WINAPI PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                              unsigned char *Buffer,\r
+                              unsigned char **pPointer,\r
+                              PFORMAT_STRING pFormat,\r
+                              unsigned char fMustAlloc)\r
+{\r
+  unsigned type = pFormat[0], attr = pFormat[1];\r
+  PFORMAT_STRING desc;\r
+  NDR_UNMARSHALL m;\r
+\r
+  TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc);\r
+  TRACE("type=%d, attr=%d\n", type, attr);\r
+  pFormat += 2;\r
+  if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;\r
+  else desc = pFormat + *(const SHORT*)pFormat;\r
+  if (attr & RPC_FC_P_DEREF) {\r
+    pPointer = *(unsigned char***)pPointer;\r
+    TRACE("deref => %p\n", pPointer);\r
+  }\r
+\r
+  switch (type) {\r
+  case RPC_FC_RP: /* ref pointer (always non-null) */\r
+    break;\r
+  default:\r
+    FIXME("unhandled ptr type=%02x\n", type);\r
+  }\r
+\r
+  *pPointer = NULL;\r
+\r
+  m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];\r
+  if (m) m(pStubMsg, pPointer, desc, fMustAlloc);\r
+  else FIXME("no unmarshaller for data type=%02x\n", *desc);\r
+  TRACE("pointer=%p\n", *pPointer);\r
+}\r
+\r
+/***********************************************************************\r
+ *           PointerBufferSize\r
+ */\r
+void WINAPI PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                              unsigned char *Pointer,\r
+                              PFORMAT_STRING pFormat)\r
+{\r
+  unsigned type = pFormat[0], attr = pFormat[1];\r
+  PFORMAT_STRING desc;\r
+  NDR_BUFFERSIZE m;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);\r
+  TRACE("type=%d, attr=%d\n", type, attr);\r
+  pFormat += 2;\r
+  if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;\r
+  else desc = pFormat + *(const SHORT*)pFormat;\r
+  if (attr & RPC_FC_P_DEREF) {\r
+    Pointer = *(unsigned char**)Pointer;\r
+    TRACE("deref => %p\n", Pointer);\r
+  }\r
+\r
+  switch (type) {\r
+  case RPC_FC_RP: /* ref pointer (always non-null) */\r
+    break;\r
+  default:\r
+    FIXME("unhandled ptr type=%02x\n", type);\r
+  }\r
+\r
+  m = NdrBufferSizer[*desc & NDR_TABLE_MASK];\r
+  if (m) m(pStubMsg, Pointer, desc);\r
+  else FIXME("no buffersizer for data type=%02x\n", *desc);\r
+}\r
+\r
+/***********************************************************************\r
+ *           PointerMemorySize [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                       unsigned char *Buffer,\r
+                                       PFORMAT_STRING pFormat)\r
+{\r
+  unsigned type = pFormat[0], attr = pFormat[1];\r
+  PFORMAT_STRING desc;\r
+  NDR_MEMORYSIZE m;\r
+\r
+  FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat);\r
+  TRACE("type=%d, attr=%d\n", type, attr);\r
+  pFormat += 2;\r
+  if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;\r
+  else desc = pFormat + *(const SHORT*)pFormat;\r
+  if (attr & RPC_FC_P_DEREF) {\r
+    TRACE("deref\n");\r
+  }\r
+\r
+  switch (type) {\r
+  case RPC_FC_RP: /* ref pointer (always non-null) */\r
+    break;\r
+  default:\r
+    FIXME("unhandled ptr type=%02x\n", type);\r
+  }\r
+\r
+  m = NdrMemorySizer[*desc & NDR_TABLE_MASK];\r
+  if (m) m(pStubMsg, desc);\r
+  else FIXME("no memorysizer for data type=%02x\n", *desc);\r
+\r
+  return 0;\r
+}\r
+\r
+/***********************************************************************\r
+ *           PointerFree [RPCRT4.@]\r
+ */\r
+void WINAPI PointerFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                        unsigned char *Pointer,\r
+                        PFORMAT_STRING pFormat)\r
+{\r
+  unsigned type = pFormat[0], attr = pFormat[1];\r
+  PFORMAT_STRING desc;\r
+  NDR_FREE m;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);\r
+  TRACE("type=%d, attr=%d\n", type, attr);\r
+  if (attr & RPC_FC_P_DONTFREE) return;\r
+  pFormat += 2;\r
+  if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;\r
+  else desc = pFormat + *(const SHORT*)pFormat;\r
+  if (attr & RPC_FC_P_DEREF) {\r
+    Pointer = *(unsigned char**)Pointer;\r
+    TRACE("deref => %p\n", Pointer);\r
+  }\r
+\r
+  if (!Pointer) return;\r
+\r
+  m = NdrFreer[*desc & NDR_TABLE_MASK];\r
+  if (m) m(pStubMsg, Pointer, desc);\r
+\r
+  /* hmm... is this sensible?\r
+   * perhaps we should check if the memory comes from NdrAllocate,\r
+   * and deallocate only if so - checking if the pointer is between\r
+   * BufferStart and BufferEnd is probably no good since the buffer\r
+   * may be reallocated when the server wants to marshal the reply */\r
+  switch (*desc) {\r
+  case RPC_FC_BOGUS_STRUCT:\r
+  case RPC_FC_BOGUS_ARRAY:\r
+  case RPC_FC_USER_MARSHAL:\r
+    break;\r
+  default:\r
+    FIXME("unhandled data type=%02x\n", *desc);\r
+  case RPC_FC_CARRAY:\r
+  case RPC_FC_C_CSTRING:\r
+  case RPC_FC_C_WSTRING:\r
+    if (pStubMsg->ReuseBuffer) goto notfree;\r
+    break;\r
+  case RPC_FC_IP:\r
+    goto notfree;\r
+  }\r
+\r
+  if (attr & RPC_FC_P_ONSTACK) {\r
+    TRACE("not freeing stack ptr %p\n", Pointer);\r
+    return;\r
+  }\r
+  TRACE("freeing %p\n", Pointer);\r
+  NdrFree(pStubMsg, Pointer);\r
+  return;\r
+notfree:\r
+  TRACE("not freeing %p\n", Pointer);\r
+}\r
+\r
+/***********************************************************************\r
+ *           EmbeddedPointerMarshall\r
+ */\r
+unsigned char * WINAPI EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                               unsigned char *pMemory,\r
+                                               PFORMAT_STRING pFormat)\r
+{\r
+  unsigned char *Mark = pStubMsg->BufferMark;\r
+  unsigned long Offset = pStubMsg->Offset;\r
+  unsigned ofs, rep, count, stride, xofs;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  if (*pFormat != RPC_FC_PP) return NULL;\r
+  pFormat += 2;\r
+\r
+  while (pFormat[0] != RPC_FC_END) {\r
+    switch (pFormat[0]) {\r
+    default:\r
+      FIXME("unknown repeat type %d\n", pFormat[0]);\r
+    case RPC_FC_NO_REPEAT:\r
+      rep = 1;\r
+      stride = 0;\r
+      ofs = 0;\r
+      count = 1;\r
+      xofs = 0;\r
+      pFormat += 2;\r
+      break;\r
+    case RPC_FC_FIXED_REPEAT:\r
+      rep = *(const WORD*)&pFormat[2];\r
+      stride = *(const WORD*)&pFormat[4];\r
+      ofs = *(const WORD*)&pFormat[6];\r
+      count = *(const WORD*)&pFormat[8];\r
+      xofs = 0;\r
+      pFormat += 10;\r
+      break;\r
+    case RPC_FC_VARIABLE_REPEAT:\r
+      rep = pStubMsg->MaxCount;\r
+      stride = *(const WORD*)&pFormat[2];\r
+      ofs = *(const WORD*)&pFormat[4];\r
+      count = *(const WORD*)&pFormat[6];\r
+      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;\r
+      pFormat += 8;\r
+      break;\r
+    }\r
+    /* ofs doesn't seem to matter in this context */\r
+    while (rep) {\r
+      PFORMAT_STRING info = pFormat;\r
+      unsigned char *membase = pMemory + xofs;\r
+      unsigned u;\r
+      for (u=0; u<count; u++,info+=8) {\r
+        unsigned char *memptr = membase + *(const SHORT*)&info[0];\r
+        unsigned char *bufptr = Mark + *(const SHORT*)&info[2];\r
+        PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);\r
+      }\r
+      rep--;\r
+    }\r
+    pFormat += 8 * count;\r
+  }\r
+\r
+  STD_OVERFLOW_CHECK(pStubMsg);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           EmbeddedPointerUnmarshall\r
+ */\r
+unsigned char * WINAPI EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                 unsigned char **ppMemory,\r
+                                                 PFORMAT_STRING pFormat,\r
+                                                 unsigned char fMustAlloc)\r
+{\r
+  unsigned char *Mark = pStubMsg->BufferMark;\r
+  unsigned long Offset = pStubMsg->Offset;\r
+  unsigned ofs, rep, count, stride, xofs;\r
+\r
+  TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);\r
+\r
+  if (*pFormat != RPC_FC_PP) return NULL;\r
+  pFormat += 2;\r
+\r
+  while (pFormat[0] != RPC_FC_END) {\r
+    switch (pFormat[0]) {\r
+    default:\r
+      FIXME("unknown repeat type %d\n", pFormat[0]);\r
+    case RPC_FC_NO_REPEAT:\r
+      rep = 1;\r
+      stride = 0;\r
+      ofs = 0;\r
+      count = 1;\r
+      xofs = 0;\r
+      pFormat += 2;\r
+      break;\r
+    case RPC_FC_FIXED_REPEAT:\r
+      rep = *(const WORD*)&pFormat[2];\r
+      stride = *(const WORD*)&pFormat[4];\r
+      ofs = *(const WORD*)&pFormat[6];\r
+      count = *(const WORD*)&pFormat[8];\r
+      xofs = 0;\r
+      pFormat += 10;\r
+      break;\r
+    case RPC_FC_VARIABLE_REPEAT:\r
+      rep = pStubMsg->MaxCount;\r
+      stride = *(const WORD*)&pFormat[2];\r
+      ofs = *(const WORD*)&pFormat[4];\r
+      count = *(const WORD*)&pFormat[6];\r
+      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;\r
+      pFormat += 8;\r
+      break;\r
+    }\r
+    /* ofs doesn't seem to matter in this context */\r
+    while (rep) {\r
+      PFORMAT_STRING info = pFormat;\r
+      unsigned char *membase = *ppMemory + xofs;\r
+      unsigned u;\r
+      for (u=0; u<count; u++,info+=8) {\r
+        unsigned char *memptr = membase + *(const SHORT*)&info[0];\r
+        unsigned char *bufptr = Mark + *(const SHORT*)&info[2];\r
+        PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, fMustAlloc);\r
+      }\r
+      rep--;\r
+    }\r
+    pFormat += 8 * count;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           EmbeddedPointerBufferSize\r
+ */\r
+void WINAPI EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                      unsigned char *pMemory,\r
+                                      PFORMAT_STRING pFormat)\r
+{\r
+  unsigned long Offset = pStubMsg->Offset;\r
+  unsigned ofs, rep, count, stride, xofs;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  if (*pFormat != RPC_FC_PP) return;\r
+  pFormat += 2;\r
+\r
+  while (pFormat[0] != RPC_FC_END) {\r
+    switch (pFormat[0]) {\r
+    default:\r
+      FIXME("unknown repeat type %d\n", pFormat[0]);\r
+    case RPC_FC_NO_REPEAT:\r
+      rep = 1;\r
+      stride = 0;\r
+      ofs = 0;\r
+      count = 1;\r
+      xofs = 0;\r
+      pFormat += 2;\r
+      break;\r
+    case RPC_FC_FIXED_REPEAT:\r
+      rep = *(const WORD*)&pFormat[2];\r
+      stride = *(const WORD*)&pFormat[4];\r
+      ofs = *(const WORD*)&pFormat[6];\r
+      count = *(const WORD*)&pFormat[8];\r
+      xofs = 0;\r
+      pFormat += 10;\r
+      break;\r
+    case RPC_FC_VARIABLE_REPEAT:\r
+      rep = pStubMsg->MaxCount;\r
+      stride = *(const WORD*)&pFormat[2];\r
+      ofs = *(const WORD*)&pFormat[4];\r
+      count = *(const WORD*)&pFormat[6];\r
+      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;\r
+      pFormat += 8;\r
+      break;\r
+    }\r
+    /* ofs doesn't seem to matter in this context */\r
+    while (rep) {\r
+      PFORMAT_STRING info = pFormat;\r
+      unsigned char *membase = pMemory + xofs;\r
+      unsigned u;\r
+      for (u=0; u<count; u++,info+=8) {\r
+        unsigned char *memptr = membase + *(const SHORT*)&info[0];\r
+        PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);\r
+      }\r
+      rep--;\r
+    }\r
+    pFormat += 8 * count;\r
+  }\r
+}\r
+\r
+/***********************************************************************\r
+ *           EmbeddedPointerMemorySize\r
+ */\r
+unsigned long WINAPI EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                               PFORMAT_STRING pFormat)\r
+{\r
+  unsigned long Offset = pStubMsg->Offset;\r
+  unsigned char *Mark = pStubMsg->BufferMark;\r
+  unsigned ofs, rep, count, stride, xofs;\r
+\r
+  FIXME("(%p,%p): stub\n", pStubMsg, pFormat);\r
+  if (*pFormat != RPC_FC_PP) return 0;\r
+  pFormat += 2;\r
+\r
+  while (pFormat[0] != RPC_FC_END) {\r
+    switch (pFormat[0]) {\r
+    default:\r
+      FIXME("unknown repeat type %d\n", pFormat[0]);\r
+    case RPC_FC_NO_REPEAT:\r
+      rep = 1;\r
+      stride = 0;\r
+      ofs = 0;\r
+      count = 1;\r
+      xofs = 0;\r
+      pFormat += 2;\r
+      break;\r
+    case RPC_FC_FIXED_REPEAT:\r
+      rep = *(const WORD*)&pFormat[2];\r
+      stride = *(const WORD*)&pFormat[4];\r
+      ofs = *(const WORD*)&pFormat[6];\r
+      count = *(const WORD*)&pFormat[8];\r
+      xofs = 0;\r
+      pFormat += 10;\r
+      break;\r
+    case RPC_FC_VARIABLE_REPEAT:\r
+      rep = pStubMsg->MaxCount;\r
+      stride = *(const WORD*)&pFormat[2];\r
+      ofs = *(const WORD*)&pFormat[4];\r
+      count = *(const WORD*)&pFormat[6];\r
+      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;\r
+      pFormat += 8;\r
+      break;\r
+    }\r
+    /* ofs doesn't seem to matter in this context */\r
+    while (rep) {\r
+      PFORMAT_STRING info = pFormat;\r
+      unsigned u;\r
+      for (u=0; u<count; u++,info+=8) {\r
+        unsigned char *bufptr = Mark + *(const SHORT*)&info[2];\r
+        PointerMemorySize(pStubMsg, bufptr, info+4);\r
+      }\r
+      rep--;\r
+    }\r
+    pFormat += 8 * count;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/***********************************************************************\r
+ *           EmbeddedPointerFree\r
+ */\r
+void WINAPI EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                unsigned char *pMemory,\r
+                                PFORMAT_STRING pFormat)\r
+{\r
+  unsigned long Offset = pStubMsg->Offset;\r
+  unsigned ofs, rep, count, stride, xofs;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  if (*pFormat != RPC_FC_PP) return;\r
+  pFormat += 2;\r
+\r
+  while (pFormat[0] != RPC_FC_END) {\r
+    switch (pFormat[0]) {\r
+    default:\r
+      FIXME("unknown repeat type %d\n", pFormat[0]);\r
+    case RPC_FC_NO_REPEAT:\r
+      rep = 1;\r
+      stride = 0;\r
+      ofs = 0;\r
+      count = 1;\r
+      xofs = 0;\r
+      pFormat += 2;\r
+      break;\r
+    case RPC_FC_FIXED_REPEAT:\r
+      rep = *(const WORD*)&pFormat[2];\r
+      stride = *(const WORD*)&pFormat[4];\r
+      ofs = *(const WORD*)&pFormat[6];\r
+      count = *(const WORD*)&pFormat[8];\r
+      xofs = 0;\r
+      pFormat += 10;\r
+      break;\r
+    case RPC_FC_VARIABLE_REPEAT:\r
+      rep = pStubMsg->MaxCount;\r
+      stride = *(const WORD*)&pFormat[2];\r
+      ofs = *(const WORD*)&pFormat[4];\r
+      count = *(const WORD*)&pFormat[6];\r
+      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;\r
+      pFormat += 8;\r
+      break;\r
+    }\r
+    /* ofs doesn't seem to matter in this context */\r
+    while (rep) {\r
+      PFORMAT_STRING info = pFormat;\r
+      unsigned char *membase = pMemory + xofs;\r
+      unsigned u;\r
+      for (u=0; u<count; u++,info+=8) {\r
+        unsigned char *memptr = membase + *(const SHORT*)&info[0];\r
+        PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);\r
+      }\r
+      rep--;\r
+    }\r
+    pFormat += 8 * count;\r
+  }\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrPointerMarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                          unsigned char *pMemory,\r
+                                          PFORMAT_STRING pFormat)\r
+{\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  pStubMsg->BufferMark = pStubMsg->Buffer;\r
+  PointerMarshall(pStubMsg, pStubMsg->Buffer, pMemory, pFormat);\r
+  pStubMsg->Buffer += 4;\r
+\r
+  STD_OVERFLOW_CHECK(pStubMsg);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrPointerUnmarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                            unsigned char **ppMemory,\r
+                                            PFORMAT_STRING pFormat,\r
+                                            unsigned char fMustAlloc)\r
+{\r
+  TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);\r
+\r
+  pStubMsg->BufferMark = pStubMsg->Buffer;\r
+  PointerUnmarshall(pStubMsg, pStubMsg->Buffer, ppMemory, pFormat, fMustAlloc);\r
+  pStubMsg->Buffer += 4;\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrPointerBufferSize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                      unsigned char *pMemory,\r
+                                      PFORMAT_STRING pFormat)\r
+{\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  pStubMsg->BufferLength += 4;\r
+  PointerBufferSize(pStubMsg, pMemory, pFormat);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrPointerMemorySize [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                          PFORMAT_STRING pFormat)\r
+{\r
+  /* unsigned size = *(LPWORD)(pFormat+2); */\r
+  FIXME("(%p,%p): stub\n", pStubMsg, pFormat);\r
+  PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);\r
+  return 0;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrPointerFree [RPCRT4.@]\r
+ */\r
+void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                           unsigned char *pMemory,\r
+                           PFORMAT_STRING pFormat)\r
+{\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  PointerFree(pStubMsg, pMemory, pFormat);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrSimpleStructMarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                               unsigned char *pMemory,\r
+                                               PFORMAT_STRING pFormat)\r
+{\r
+  unsigned size = *(const WORD*)(pFormat+2);\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  memcpy(pStubMsg->Buffer, pMemory, size);\r
+  pStubMsg->BufferMark = pStubMsg->Buffer;\r
+  pStubMsg->Buffer += size;\r
+\r
+  if (pFormat[0] != RPC_FC_STRUCT)\r
+    EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);\r
+\r
+  STD_OVERFLOW_CHECK(pStubMsg);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrSimpleStructUnmarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                 unsigned char **ppMemory,\r
+                                                 PFORMAT_STRING pFormat,\r
+                                                 unsigned char fMustAlloc)\r
+{\r
+  unsigned size = *(const WORD*)(pFormat+2);\r
+  TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);\r
+\r
+  if (fMustAlloc) {\r
+    *ppMemory = NdrAllocate(pStubMsg, size);\r
+    memcpy(*ppMemory, pStubMsg->Buffer, size);\r
+  } else {\r
+    if (pStubMsg->ReuseBuffer && !*ppMemory)\r
+      /* for servers, we may just point straight into the RPC buffer, I think\r
+       * (I guess that's what MS does since MIDL code doesn't try to free) */\r
+      *ppMemory = pStubMsg->Buffer;\r
+    else\r
+      /* for clients, memory should be provided by caller */\r
+      memcpy(*ppMemory, pStubMsg->Buffer, size);\r
+  }\r
+\r
+  pStubMsg->BufferMark = pStubMsg->Buffer;\r
+  pStubMsg->Buffer += size;\r
+\r
+  if (pFormat[0] != RPC_FC_STRUCT)\r
+    EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *           NdrSimpleStructUnmarshall [RPCRT4.@]\r
+ */\r
+void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,\r
+                                   unsigned char FormatChar )\r
+{\r
+    FIXME("stub\n");\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *           NdrSimpleStructUnmarshall [RPCRT4.@]\r
+ */\r
+void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,\r
+                                     unsigned char FormatChar )\r
+{\r
+    FIXME("stub\n");\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *           NdrSimpleStructBufferSize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                      unsigned char *pMemory,\r
+                                      PFORMAT_STRING pFormat)\r
+{\r
+  unsigned size = *(const WORD*)(pFormat+2);\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  pStubMsg->BufferLength += size;\r
+  if (pFormat[0] != RPC_FC_STRUCT)\r
+    EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrSimpleStructMemorySize [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                               PFORMAT_STRING pFormat)\r
+{\r
+  /* unsigned size = *(LPWORD)(pFormat+2); */\r
+  FIXME("(%p,%p): stub\n", pStubMsg, pFormat);\r
+  if (pFormat[0] != RPC_FC_STRUCT)\r
+    EmbeddedPointerMemorySize(pStubMsg, pFormat+4);\r
+  return 0;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrSimpleStructFree [RPCRT4.@]\r
+ */\r
+void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                unsigned char *pMemory,\r
+                                PFORMAT_STRING pFormat)\r
+{\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  if (pFormat[0] != RPC_FC_STRUCT)\r
+    EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);\r
+}\r
+\r
+\r
+unsigned long WINAPI EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                         PFORMAT_STRING pFormat)\r
+{\r
+  switch (*pFormat) {\r
+  case RPC_FC_STRUCT:\r
+  case RPC_FC_PSTRUCT:\r
+  case RPC_FC_CSTRUCT:\r
+  case RPC_FC_BOGUS_STRUCT:\r
+    return *(const WORD*)&pFormat[2];\r
+  case RPC_FC_USER_MARSHAL:\r
+    return *(const WORD*)&pFormat[4];\r
+  default:\r
+    FIXME("unhandled embedded type %02x\n", *pFormat);\r
+  }\r
+  return 0;\r
+}\r
+\r
+\r
+unsigned char * WINAPI ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                       unsigned char *pMemory,\r
+                                       PFORMAT_STRING pFormat,\r
+                                       PFORMAT_STRING pPointer)\r
+{\r
+  PFORMAT_STRING desc;\r
+  NDR_MARSHALL m;\r
+  unsigned long size;\r
+\r
+  while (*pFormat != RPC_FC_END) {\r
+    switch (*pFormat) {\r
+    case RPC_FC_SHORT:\r
+    case RPC_FC_USHORT:\r
+      TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);\r
+      memcpy(pStubMsg->Buffer, pMemory, 2);\r
+      pStubMsg->Buffer += 2;\r
+      pMemory += 2;\r
+      break;\r
+    case RPC_FC_LONG:\r
+    case RPC_FC_ULONG:\r
+      TRACE("long=%ld <= %p\n", *(DWORD*)pMemory, pMemory);\r
+      memcpy(pStubMsg->Buffer, pMemory, 4);\r
+      pStubMsg->Buffer += 4;\r
+      pMemory += 4;\r
+      break;\r
+    case RPC_FC_POINTER:\r
+      TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);\r
+      NdrPointerMarshall(pStubMsg, *(unsigned char**)pMemory, pPointer);\r
+      pPointer += 4;\r
+      pMemory += 4;\r
+      break;\r
+    case RPC_FC_ALIGNM4:\r
+      ALIGN_POINTER(pMemory, 3);\r
+      break;\r
+    case RPC_FC_ALIGNM8:\r
+      ALIGN_POINTER(pMemory, 7);\r
+      break;\r
+    case RPC_FC_EMBEDDED_COMPLEX:\r
+      pMemory += pFormat[1];\r
+      pFormat += 2;\r
+      desc = pFormat + *(const SHORT*)pFormat;\r
+      size = EmbeddedComplexSize(pStubMsg, desc);\r
+      TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);\r
+      m = NdrMarshaller[*desc & NDR_TABLE_MASK];\r
+      if (m) m(pStubMsg, pMemory, desc);\r
+      else FIXME("no marshaller for embedded type %02x\n", *desc);\r
+      pMemory += size;\r
+      pFormat += 2;\r
+      continue;\r
+    case RPC_FC_PAD:\r
+      break;\r
+    default:\r
+      FIXME("unhandled format %02x\n", *pFormat);\r
+    }\r
+    pFormat++;\r
+  }\r
+\r
+  return pMemory;\r
+}\r
+\r
+unsigned char * WINAPI ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                         unsigned char *pMemory,\r
+                                         PFORMAT_STRING pFormat,\r
+                                         PFORMAT_STRING pPointer,\r
+                                         unsigned char fMustAlloc)\r
+{\r
+  PFORMAT_STRING desc;\r
+  NDR_UNMARSHALL m;\r
+  unsigned long size;\r
+\r
+  while (*pFormat != RPC_FC_END) {\r
+    switch (*pFormat) {\r
+    case RPC_FC_SHORT:\r
+    case RPC_FC_USHORT:\r
+      memcpy(pMemory, pStubMsg->Buffer, 2);\r
+      TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);\r
+      pStubMsg->Buffer += 2;\r
+      pMemory += 2;\r
+      break;\r
+    case RPC_FC_LONG:\r
+    case RPC_FC_ULONG:\r
+      memcpy(pMemory, pStubMsg->Buffer, 4);\r
+      TRACE("long=%ld => %p\n", *(DWORD*)pMemory, pMemory);\r
+      pStubMsg->Buffer += 4;\r
+      pMemory += 4;\r
+      break;\r
+    case RPC_FC_POINTER:\r
+      *(unsigned char**)pMemory = NULL;\r
+      TRACE("pointer => %p\n", pMemory);\r
+      NdrPointerUnmarshall(pStubMsg, (unsigned char**)pMemory, pPointer, fMustAlloc);\r
+      pPointer += 4;\r
+      pMemory += 4;\r
+      break;\r
+    case RPC_FC_ALIGNM4:\r
+      ALIGN_POINTER(pMemory, 3);\r
+      break;\r
+    case RPC_FC_ALIGNM8:\r
+      ALIGN_POINTER(pMemory, 7);\r
+      break;\r
+    case RPC_FC_EMBEDDED_COMPLEX:\r
+      pMemory += pFormat[1];\r
+      pFormat += 2;\r
+      desc = pFormat + *(const SHORT*)pFormat;\r
+      size = EmbeddedComplexSize(pStubMsg, desc);\r
+      TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);\r
+      m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];\r
+      memset(pMemory, 0, size); /* just in case */\r
+      if (m) m(pStubMsg, &pMemory, desc, fMustAlloc);\r
+      else FIXME("no unmarshaller for embedded type %02x\n", *desc);\r
+      pMemory += size;\r
+      pFormat += 2;\r
+      continue;\r
+    case RPC_FC_PAD:\r
+      break;\r
+    default:\r
+      FIXME("unhandled format %d\n", *pFormat);\r
+    }\r
+    pFormat++;\r
+  }\r
+\r
+  return pMemory;\r
+}\r
+\r
+unsigned char * WINAPI ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                         unsigned char *pMemory,\r
+                                         PFORMAT_STRING pFormat,\r
+                                         PFORMAT_STRING pPointer)\r
+{\r
+  PFORMAT_STRING desc;\r
+  NDR_BUFFERSIZE m;\r
+  unsigned long size;\r
+\r
+  while (*pFormat != RPC_FC_END) {\r
+    switch (*pFormat) {\r
+    case RPC_FC_SHORT:\r
+    case RPC_FC_USHORT:\r
+      pStubMsg->BufferLength += 2;\r
+      pMemory += 2;\r
+      break;\r
+    case RPC_FC_LONG:\r
+    case RPC_FC_ULONG:\r
+      pStubMsg->BufferLength += 4;\r
+      pMemory += 4;\r
+      break;\r
+    case RPC_FC_POINTER:\r
+      NdrPointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);\r
+      pPointer += 4;\r
+      pMemory += 4;\r
+      break;\r
+    case RPC_FC_ALIGNM4:\r
+      ALIGN_POINTER(pMemory, 3);\r
+      break;\r
+    case RPC_FC_ALIGNM8:\r
+      ALIGN_POINTER(pMemory, 7);\r
+      break;\r
+    case RPC_FC_EMBEDDED_COMPLEX:\r
+      pMemory += pFormat[1];\r
+      pFormat += 2;\r
+      desc = pFormat + *(const SHORT*)pFormat;\r
+      size = EmbeddedComplexSize(pStubMsg, desc);\r
+      m = NdrBufferSizer[*desc & NDR_TABLE_MASK];\r
+      if (m) m(pStubMsg, pMemory, desc);\r
+      else FIXME("no buffersizer for embedded type %02x\n", *desc);\r
+      pMemory += size;\r
+      pFormat += 2;\r
+      continue;\r
+    case RPC_FC_PAD:\r
+      break;\r
+    default:\r
+      FIXME("unhandled format %d\n", *pFormat);\r
+    }\r
+    pFormat++;\r
+  }\r
+\r
+  return pMemory;\r
+}\r
+\r
+unsigned char * WINAPI ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                   unsigned char *pMemory,\r
+                                   PFORMAT_STRING pFormat,\r
+                                   PFORMAT_STRING pPointer)\r
+{\r
+  PFORMAT_STRING desc;\r
+  NDR_FREE m;\r
+  unsigned long size;\r
+\r
+  while (*pFormat != RPC_FC_END) {\r
+    switch (*pFormat) {\r
+    case RPC_FC_SHORT:\r
+    case RPC_FC_USHORT:\r
+      pMemory += 2;\r
+      break;\r
+    case RPC_FC_LONG:\r
+    case RPC_FC_ULONG:\r
+      pMemory += 4;\r
+      break;\r
+    case RPC_FC_POINTER:\r
+      NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);\r
+      pPointer += 4;\r
+      pMemory += 4;\r
+      break;\r
+    case RPC_FC_ALIGNM4:\r
+      ALIGN_POINTER(pMemory, 3);\r
+      break;\r
+    case RPC_FC_ALIGNM8:\r
+      ALIGN_POINTER(pMemory, 7);\r
+      break;\r
+    case RPC_FC_EMBEDDED_COMPLEX:\r
+      pMemory += pFormat[1];\r
+      pFormat += 2;\r
+      desc = pFormat + *(const SHORT*)pFormat;\r
+      size = EmbeddedComplexSize(pStubMsg, desc);\r
+      m = NdrFreer[*desc & NDR_TABLE_MASK];\r
+      if (m) m(pStubMsg, pMemory, desc);\r
+      else FIXME("no freer for embedded type %02x\n", *desc);\r
+      pMemory += size;\r
+      pFormat += 2;\r
+      continue;\r
+    case RPC_FC_PAD:\r
+      break;\r
+    default:\r
+      FIXME("unhandled format %d\n", *pFormat);\r
+    }\r
+    pFormat++;\r
+  }\r
+\r
+  return pMemory;\r
+}\r
+\r
+unsigned long WINAPI ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                       PFORMAT_STRING pFormat)\r
+{\r
+  PFORMAT_STRING desc;\r
+  unsigned long size = 0;\r
+\r
+  while (*pFormat != RPC_FC_END) {\r
+    switch (*pFormat) {\r
+    case RPC_FC_SHORT:\r
+    case RPC_FC_USHORT:\r
+      size += 2;\r
+      break;\r
+    case RPC_FC_LONG:\r
+    case RPC_FC_ULONG:\r
+      size += 4;\r
+      break;\r
+    case RPC_FC_POINTER:\r
+      size += 4;\r
+      break;\r
+    case RPC_FC_ALIGNM4:\r
+      ALIGN_LENGTH(size, 3);\r
+      break;\r
+    case RPC_FC_ALIGNM8:\r
+      ALIGN_LENGTH(size, 7);\r
+      break;\r
+    case RPC_FC_EMBEDDED_COMPLEX:\r
+      size += pFormat[1];\r
+      pFormat += 2;\r
+      desc = pFormat + *(const SHORT*)pFormat;\r
+      size += EmbeddedComplexSize(pStubMsg, desc);\r
+      pFormat += 2;\r
+      continue;\r
+    case RPC_FC_PAD:\r
+      break;\r
+    default:\r
+      FIXME("unhandled format %d\n", *pFormat);\r
+    }\r
+    pFormat++;\r
+  }\r
+\r
+  return size;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrComplexStructMarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                unsigned char *pMemory,\r
+                                                PFORMAT_STRING pFormat)\r
+{\r
+  PFORMAT_STRING conf_array = NULL;\r
+  PFORMAT_STRING pointer_desc = NULL;\r
+  unsigned char *OldMemory = pStubMsg->Memory;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  pFormat += 4;\r
+  if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+  if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+\r
+  pStubMsg->Memory = pMemory;\r
+\r
+  ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);\r
+\r
+  if (conf_array)\r
+    NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);\r
+\r
+  pStubMsg->Memory = OldMemory;\r
+\r
+  STD_OVERFLOW_CHECK(pStubMsg);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrComplexStructUnmarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                  unsigned char **ppMemory,\r
+                                                  PFORMAT_STRING pFormat,\r
+                                                  unsigned char fMustAlloc)\r
+{\r
+  unsigned size = *(const WORD*)(pFormat+2);\r
+  PFORMAT_STRING conf_array = NULL;\r
+  PFORMAT_STRING pointer_desc = NULL;\r
+  unsigned char *pMemory;\r
+\r
+  TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);\r
+\r
+  if (fMustAlloc || !*ppMemory)\r
+    *ppMemory = NdrAllocate(pStubMsg, size);\r
+\r
+  pFormat += 4;\r
+  if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+  if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+\r
+  pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);\r
+\r
+  if (conf_array)\r
+    NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrComplexStructBufferSize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                       unsigned char *pMemory,\r
+                                       PFORMAT_STRING pFormat)\r
+{\r
+  PFORMAT_STRING conf_array = NULL;\r
+  PFORMAT_STRING pointer_desc = NULL;\r
+  unsigned char *OldMemory = pStubMsg->Memory;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  pFormat += 4;\r
+  if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+  if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+\r
+  pStubMsg->Memory = pMemory;\r
+\r
+  pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);\r
+\r
+  if (conf_array)\r
+    NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);\r
+\r
+  pStubMsg->Memory = OldMemory;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrComplexStructMemorySize [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                PFORMAT_STRING pFormat)\r
+{\r
+  /* unsigned size = *(LPWORD)(pFormat+2); */\r
+  PFORMAT_STRING conf_array = NULL;\r
+  PFORMAT_STRING pointer_desc = NULL;\r
+\r
+  FIXME("(%p,%p): stub\n", pStubMsg, pFormat);\r
+\r
+  pFormat += 4;\r
+  if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+  if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+\r
+  return 0;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrComplexStructFree [RPCRT4.@]\r
+ */\r
+void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                 unsigned char *pMemory,\r
+                                 PFORMAT_STRING pFormat)\r
+{\r
+  PFORMAT_STRING conf_array = NULL;\r
+  PFORMAT_STRING pointer_desc = NULL;\r
+  unsigned char *OldMemory = pStubMsg->Memory;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  pFormat += 4;\r
+  if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+  if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;\r
+  pFormat += 2;\r
+\r
+  pStubMsg->Memory = pMemory;\r
+\r
+  pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);\r
+\r
+  if (conf_array)\r
+    NdrConformantArrayFree(pStubMsg, pMemory, conf_array);\r
+\r
+  pStubMsg->Memory = OldMemory;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrConformantArrayMarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                  unsigned char *pMemory,\r
+                                                  PFORMAT_STRING pFormat)\r
+{\r
+  DWORD size = 0, esize = *(const WORD*)(pFormat+2);\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);\r
+\r
+  pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);\r
+  size = pStubMsg->MaxCount;\r
+\r
+  NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, size);\r
+  pStubMsg->Buffer += 4;\r
+\r
+  memcpy(pStubMsg->Buffer, pMemory, size*esize);\r
+  pStubMsg->BufferMark = pStubMsg->Buffer;\r
+  pStubMsg->Buffer += size*esize;\r
+\r
+  EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);\r
+\r
+  STD_OVERFLOW_CHECK(pStubMsg);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrConformantArrayUnmarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                    unsigned char **ppMemory,\r
+                                                    PFORMAT_STRING pFormat,\r
+                                                    unsigned char fMustAlloc)\r
+{\r
+  DWORD size = 0, esize = *(const WORD*)(pFormat+2);\r
+  TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);\r
+  if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);\r
+\r
+  pFormat = ReadConformance(pStubMsg, pFormat+4);\r
+  size = pStubMsg->MaxCount;\r
+\r
+  if (fMustAlloc) {\r
+    *ppMemory = NdrAllocate(pStubMsg, size*esize);\r
+    memcpy(*ppMemory, pStubMsg->Buffer, size*esize);\r
+  } else {\r
+    if (pStubMsg->ReuseBuffer && !*ppMemory)\r
+      /* for servers, we may just point straight into the RPC buffer, I think\r
+       * (I guess that's what MS does since MIDL code doesn't try to free) */\r
+      *ppMemory = pStubMsg->Buffer;\r
+    else\r
+      /* for clients, memory should be provided by caller */\r
+      memcpy(*ppMemory, pStubMsg->Buffer, size*esize);\r
+  }\r
+\r
+  pStubMsg->BufferMark = pStubMsg->Buffer;\r
+  pStubMsg->Buffer += size*esize;\r
+\r
+  EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrConformantArrayBufferSize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                         unsigned char *pMemory,\r
+                                         PFORMAT_STRING pFormat)\r
+{\r
+  DWORD size = 0, esize = *(const WORD*)(pFormat+2);\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);\r
+\r
+  pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);\r
+  size = pStubMsg->MaxCount;\r
+\r
+  pStubMsg->BufferLength += size*esize;\r
+\r
+  EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrConformantArrayMemorySize [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                  PFORMAT_STRING pFormat)\r
+{\r
+  DWORD size = 0;\r
+  FIXME("(%p,%p): stub\n", pStubMsg, pFormat);\r
+  if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);\r
+\r
+  pFormat = ReadConformance(pStubMsg, pFormat+4);\r
+  size = pStubMsg->MaxCount;\r
+\r
+  EmbeddedPointerMemorySize(pStubMsg, pFormat);\r
+\r
+  return 0;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrConformantArrayFree [RPCRT4.@]\r
+ */\r
+void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                   unsigned char *pMemory,\r
+                                   PFORMAT_STRING pFormat)\r
+{\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);\r
+\r
+  EmbeddedPointerFree(pStubMsg, pMemory, pFormat);\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]\r
+ */\r
+unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                         unsigned char* pMemory,\r
+                                                         PFORMAT_STRING pFormat )\r
+{\r
+    FIXME( "stub\n" );\r
+    return NULL;\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]\r
+ */\r
+unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                           unsigned char** ppMemory,\r
+                                                           PFORMAT_STRING pFormat,\r
+                                                           unsigned char fMustAlloc )\r
+{\r
+    FIXME( "stub\n" );\r
+    return NULL;\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *           NdrConformantVaryingArrayFree  [RPCRT4.@]\r
+ */\r
+void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,\r
+                                           unsigned char* pMemory,\r
+                                           PFORMAT_STRING pFormat )\r
+{\r
+    FIXME( "stub\n" );\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]\r
+ */\r
+void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                 unsigned char* pMemory, PFORMAT_STRING pFormat )\r
+{\r
+    FIXME( "stub\n" );\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                          PFORMAT_STRING pFormat )\r
+{\r
+    FIXME( "stub\n" );\r
+    return 0;\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *           NdrComplexArrayMarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                               unsigned char *pMemory,\r
+                                               PFORMAT_STRING pFormat)\r
+{\r
+  DWORD size = 0, count, def;\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  def = *(const WORD*)&pFormat[2];\r
+  pFormat += 4;\r
+\r
+  pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);\r
+  size = pStubMsg->MaxCount;\r
+  TRACE("conformance=%ld\n", size);\r
+\r
+  if (*(const DWORD*)pFormat != 0xffffffff)\r
+    FIXME("compute variance\n");\r
+  pFormat += 4;\r
+\r
+  NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, size);\r
+  pStubMsg->Buffer += 4;\r
+\r
+  for (count=0; count<size; count++)\r
+    pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);\r
+\r
+  STD_OVERFLOW_CHECK(pStubMsg);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrComplexArrayUnmarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                 unsigned char **ppMemory,\r
+                                                 PFORMAT_STRING pFormat,\r
+                                                 unsigned char fMustAlloc)\r
+{\r
+  DWORD size = 0, count, esize;\r
+  unsigned char *pMemory;\r
+  TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);\r
+\r
+  pFormat += 4;\r
+\r
+  pFormat = ReadConformance(pStubMsg, pFormat);\r
+  size = pStubMsg->MaxCount;\r
+  TRACE("conformance=%ld\n", size);\r
+\r
+  pFormat += 4;\r
+\r
+  esize = ComplexStructSize(pStubMsg, pFormat);\r
+\r
+  if (fMustAlloc || !*ppMemory)\r
+    *ppMemory = NdrAllocate(pStubMsg, size*esize);\r
+\r
+  pMemory = *ppMemory;\r
+  for (count=0; count<size; count++)\r
+    pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrComplexArrayBufferSize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                      unsigned char *pMemory,\r
+                                      PFORMAT_STRING pFormat)\r
+{\r
+  DWORD size = 0, count, def;\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  def = *(const WORD*)&pFormat[2];\r
+  pFormat += 4;\r
+\r
+  pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);\r
+  size = pStubMsg->MaxCount;\r
+  TRACE("conformance=%ld\n", size);\r
+\r
+  if (*(const DWORD*)pFormat != 0xffffffff)\r
+    FIXME("compute variance\n");\r
+  pFormat += 4;\r
+\r
+  for (count=0; count<size; count++)\r
+    pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrComplexArrayMemorySize [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                               PFORMAT_STRING pFormat)\r
+{\r
+  DWORD size = 0;\r
+  FIXME("(%p,%p): stub\n", pStubMsg, pFormat);\r
+\r
+  pFormat += 4;\r
+\r
+  pFormat = ReadConformance(pStubMsg, pFormat);\r
+  size = pStubMsg->MaxCount;\r
+  TRACE("conformance=%ld\n", size);\r
+\r
+  pFormat += 4;\r
+\r
+  return 0;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrComplexArrayFree [RPCRT4.@]\r
+ */\r
+void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                unsigned char *pMemory,\r
+                                PFORMAT_STRING pFormat)\r
+{\r
+  DWORD size = 0, count, def;\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+\r
+  def = *(const WORD*)&pFormat[2];\r
+  pFormat += 4;\r
+\r
+  pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);\r
+  size = pStubMsg->MaxCount;\r
+  TRACE("conformance=%ld\n", size);\r
+\r
+  if (*(const DWORD*)pFormat != 0xffffffff)\r
+    FIXME("compute variance\n");\r
+  pFormat += 4;\r
+\r
+  for (count=0; count<size; count++)\r
+    pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);\r
+}\r
+\r
+unsigned long UserMarshalFlags(PMIDL_STUB_MESSAGE pStubMsg)\r
+{\r
+  return MAKELONG(pStubMsg->dwDestContext,\r
+                  pStubMsg->RpcMsg->DataRepresentation);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrUserMarshalMarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                              unsigned char *pMemory,\r
+                                              PFORMAT_STRING pFormat)\r
+{\r
+/*  unsigned flags = pFormat[1]; */\r
+  unsigned index = *(const WORD*)&pFormat[2];\r
+  unsigned long uflag = UserMarshalFlags(pStubMsg);\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  TRACE("index=%d\n", index);\r
+\r
+  pStubMsg->Buffer =\r
+    pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(\r
+      &uflag, pStubMsg->Buffer, pMemory);\r
+\r
+  STD_OVERFLOW_CHECK(pStubMsg);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrUserMarshalUnmarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                 unsigned char **ppMemory,\r
+                                                 PFORMAT_STRING pFormat,\r
+                                                 unsigned char fMustAlloc)\r
+{\r
+/*  unsigned flags = pFormat[1];*/\r
+  unsigned index = *(const WORD*)&pFormat[2];\r
+  DWORD memsize = *(const WORD*)&pFormat[4];\r
+  unsigned long uflag = UserMarshalFlags(pStubMsg);\r
+  TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);\r
+  TRACE("index=%d\n", index);\r
+\r
+  if (fMustAlloc || !*ppMemory)\r
+    *ppMemory = NdrAllocate(pStubMsg, memsize);\r
+\r
+  pStubMsg->Buffer =\r
+    pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(\r
+      &uflag, pStubMsg->Buffer, *ppMemory);\r
+\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrUserMarshalBufferSize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                      unsigned char *pMemory,\r
+                                      PFORMAT_STRING pFormat)\r
+{\r
+/*  unsigned flags = pFormat[1];*/\r
+  unsigned index = *(const WORD*)&pFormat[2];\r
+  DWORD bufsize = *(const WORD*)&pFormat[6];\r
+  unsigned long uflag = UserMarshalFlags(pStubMsg);\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  TRACE("index=%d\n", index);\r
+\r
+  if (bufsize) {\r
+    TRACE("size=%ld\n", bufsize);\r
+    pStubMsg->BufferLength += bufsize;\r
+    return;\r
+  }\r
+\r
+  pStubMsg->BufferLength =\r
+    pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(\r
+      &uflag, pStubMsg->BufferLength, pMemory);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrUserMarshalMemorySize [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                              PFORMAT_STRING pFormat)\r
+{\r
+  unsigned index = *(const WORD*)&pFormat[2];\r
+/*  DWORD memsize = *(const WORD*)&pFormat[4]; */\r
+  FIXME("(%p,%p): stub\n", pStubMsg, pFormat);\r
+  TRACE("index=%d\n", index);\r
+\r
+  return 0;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrUserMarshalFree [RPCRT4.@]\r
+ */\r
+void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                unsigned char *pMemory,\r
+                                PFORMAT_STRING pFormat)\r
+{\r
+/*  unsigned flags = pFormat[1]; */\r
+  unsigned index = *(const WORD*)&pFormat[2];\r
+  unsigned long uflag = UserMarshalFlags(pStubMsg);\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  TRACE("index=%d\n", index);\r
+\r
+  pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(\r
+    &uflag, pMemory);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrClearOutParameters [RPCRT4.@]\r
+ */\r
+void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                  PFORMAT_STRING pFormat,\r
+                                  void *ArgAddr)\r
+{\r
+  FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrConvert [RPCRT4.@]\r
+ */\r
+void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )\r
+{\r
+  FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);\r
+  /* FIXME: since this stub doesn't do any converting, the proper behavior\r
+     is to raise an exception */\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrConvert2 [RPCRT4.@]\r
+ */\r
+void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )\r
+{\r
+  FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n",\r
+    pStubMsg, pFormat, NumberParams);\r
+  /* FIXME: since this stub doesn't do any converting, the proper behavior\r
+     is to raise an exception */\r
+}\r
diff --git a/reactos/lib/rpcrt4/ndr_midl.c b/reactos/lib/rpcrt4/ndr_midl.c
new file mode 100644 (file)
index 0000000..9804b7c
--- /dev/null
@@ -0,0 +1,282 @@
+/*\r
+ * MIDL proxy/stub stuff\r
+ *\r
+ * Copyright 2002 Ove Kåven, TransGaming Technologies\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
+ * TODO:\r
+ *  - figure out whether we *really* got this right\r
+ *  - check for errors and throw exceptions\r
+ */\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <assert.h>\r
+\r
+#define COBJMACROS\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+#include "winreg.h"\r
+\r
+#include "objbase.h"\r
+\r
+#include "rpcproxy.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+#include "cpsf.h"\r
+#include "ndr_misc.h"\r
+#include "rpcndr.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+/***********************************************************************\r
+ *           NdrProxyInitialize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrProxyInitialize(void *This,\r
+                              PRPC_MESSAGE pRpcMsg,\r
+                              PMIDL_STUB_MESSAGE pStubMsg,\r
+                              PMIDL_STUB_DESC pStubDescriptor,\r
+                              unsigned int ProcNum)\r
+{\r
+  HRESULT hr;\r
+\r
+  TRACE("(%p,%p,%p,%p,%d)\n", This, pRpcMsg, pStubMsg, pStubDescriptor, ProcNum);\r
+  NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor, ProcNum);\r
+  if (This) StdProxy_GetChannel(This, &pStubMsg->pRpcChannelBuffer);\r
+  if (pStubMsg->pRpcChannelBuffer) {\r
+    hr = IRpcChannelBuffer_GetDestCtx(pStubMsg->pRpcChannelBuffer,\r
+                                     &pStubMsg->dwDestContext,\r
+                                     &pStubMsg->pvDestContext);\r
+  }\r
+  TRACE("channel=%p\n", pStubMsg->pRpcChannelBuffer);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrProxyGetBuffer [RPCRT4.@]\r
+ */\r
+void WINAPI NdrProxyGetBuffer(void *This,\r
+                             PMIDL_STUB_MESSAGE pStubMsg)\r
+{\r
+  HRESULT hr;\r
+  const IID *riid = NULL;\r
+\r
+  TRACE("(%p,%p)\n", This, pStubMsg);\r
+  pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength;\r
+  pStubMsg->dwStubPhase = PROXY_GETBUFFER;\r
+  hr = StdProxy_GetIID(This, &riid);\r
+  hr = IRpcChannelBuffer_GetBuffer(pStubMsg->pRpcChannelBuffer,\r
+                                  (RPCOLEMESSAGE*)pStubMsg->RpcMsg,\r
+                                  riid);\r
+  pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;\r
+  pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;\r
+  pStubMsg->Buffer = pStubMsg->BufferStart;\r
+  pStubMsg->dwStubPhase = PROXY_MARSHAL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrProxySendReceive [RPCRT4.@]\r
+ */\r
+void WINAPI NdrProxySendReceive(void *This,\r
+                               PMIDL_STUB_MESSAGE pStubMsg)\r
+{\r
+  ULONG Status = 0;\r
+  HRESULT hr;\r
+\r
+  TRACE("(%p,%p)\n", This, pStubMsg);\r
+  pStubMsg->dwStubPhase = PROXY_SENDRECEIVE;\r
+  hr = IRpcChannelBuffer_SendReceive(pStubMsg->pRpcChannelBuffer,\r
+                                    (RPCOLEMESSAGE*)pStubMsg->RpcMsg,\r
+                                    &Status);\r
+  pStubMsg->dwStubPhase = PROXY_UNMARSHAL;\r
+  pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;\r
+  pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;\r
+  pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;\r
+  pStubMsg->Buffer = pStubMsg->BufferStart;\r
+\r
+  /* raise exception if call failed */\r
+  if (hr == RPC_S_CALL_FAILED) RpcRaiseException(*(DWORD*)pStubMsg->Buffer);\r
+  else if (FAILED(hr)) RpcRaiseException(hr);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrProxyFreeBuffer [RPCRT4.@]\r
+ */\r
+void WINAPI NdrProxyFreeBuffer(void *This,\r
+                              PMIDL_STUB_MESSAGE pStubMsg)\r
+{\r
+  HRESULT hr;\r
+\r
+  TRACE("(%p,%p)\n", This, pStubMsg);\r
+  hr = IRpcChannelBuffer_FreeBuffer(pStubMsg->pRpcChannelBuffer,\r
+                                   (RPCOLEMESSAGE*)pStubMsg->RpcMsg);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrProxyErrorHandler [RPCRT4.@]\r
+ */\r
+HRESULT WINAPI NdrProxyErrorHandler(DWORD dwExceptionCode)\r
+{\r
+  FIXME("(0x%08lx): semi-stub\n", dwExceptionCode);\r
+  return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_RPC, RPC_S_CALL_FAILED);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrStubInitialize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrStubInitialize(PRPC_MESSAGE pRpcMsg,\r
+                             PMIDL_STUB_MESSAGE pStubMsg,\r
+                             PMIDL_STUB_DESC pStubDescriptor,\r
+                             LPRPCCHANNELBUFFER pRpcChannelBuffer)\r
+{\r
+  TRACE("(%p,%p,%p,%p)\n", pRpcMsg, pStubMsg, pStubDescriptor, pRpcChannelBuffer);\r
+  NdrServerInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor);\r
+  pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrStubGetBuffer [RPCRT4.@]\r
+ */\r
+void WINAPI NdrStubGetBuffer(LPRPCSTUBBUFFER This,\r
+                            LPRPCCHANNELBUFFER pRpcChannelBuffer,\r
+                            PMIDL_STUB_MESSAGE pStubMsg)\r
+{\r
+  TRACE("(%p,%p)\n", This, pStubMsg);\r
+  pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer;\r
+  pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength;\r
+  I_RpcGetBuffer(pStubMsg->RpcMsg); /* ? */\r
+  pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;\r
+  pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;\r
+  pStubMsg->Buffer = pStubMsg->BufferStart;\r
+}\r
+\r
+/************************************************************************\r
+ *             NdrClientInitializeNew [RPCRT4.@]\r
+ */\r
+void WINAPI NdrClientInitializeNew( PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg, \r
+                                    PMIDL_STUB_DESC pStubDesc, unsigned int ProcNum )\r
+{\r
+  TRACE("(pRpcMessage == ^%p, pStubMsg == ^%p, pStubDesc == ^%p, ProcNum == %d)\n",\r
+    pRpcMessage, pStubMsg, pStubDesc, ProcNum);\r
+\r
+  assert( pRpcMessage && pStubMsg && pStubDesc );\r
+\r
+  memset(pRpcMessage, 0, sizeof(RPC_MESSAGE));\r
+\r
+  /* not everyone allocates stack space for w2kReserved */\r
+  memset(pStubMsg, 0, FIELD_OFFSET(MIDL_STUB_MESSAGE,pCSInfo));\r
+\r
+  pStubMsg->ReuseBuffer = FALSE;\r
+  pStubMsg->IsClient = TRUE;\r
+  pStubMsg->StubDesc = pStubDesc;\r
+  pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;\r
+  pStubMsg->pfnFree = pStubDesc->pfnFree;\r
+  pStubMsg->RpcMsg = pRpcMessage;\r
+\r
+  pRpcMessage->ProcNum = ProcNum;\r
+  pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation;\r
+}\r
+\r
+/***********************************************************************\r
+ *             NdrServerInitializeNew [RPCRT4.@]\r
+ */\r
+unsigned char* WINAPI NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg,\r
+                                              PMIDL_STUB_DESC pStubDesc )\r
+{\r
+  TRACE("(pRpcMsg == ^%p, pStubMsg == ^%p, pStubDesc == ^%p)\n", pRpcMsg, pStubMsg, pStubDesc);\r
+\r
+  assert( pRpcMsg && pStubMsg && pStubDesc );\r
+\r
+  /* not everyone allocates stack space for w2kReserved */\r
+  memset(pStubMsg, 0, FIELD_OFFSET(MIDL_STUB_MESSAGE,pCSInfo));\r
+\r
+  pStubMsg->ReuseBuffer = TRUE;\r
+  pStubMsg->IsClient = FALSE;\r
+  pStubMsg->StubDesc = pStubDesc;\r
+  pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;\r
+  pStubMsg->pfnFree = pStubDesc->pfnFree;\r
+  pStubMsg->RpcMsg = pRpcMsg;\r
+  pStubMsg->Buffer = pStubMsg->BufferStart = pRpcMsg->Buffer;\r
+  pStubMsg->BufferLength = pRpcMsg->BufferLength;\r
+  pStubMsg->BufferEnd = pStubMsg->Buffer + pStubMsg->BufferLength;\r
+\r
+  /* FIXME: determine the proper return value */\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrGetBuffer [RPCRT4.@]\r
+ */\r
+unsigned char *WINAPI NdrGetBuffer(MIDL_STUB_MESSAGE *stubmsg, unsigned long buflen, RPC_BINDING_HANDLE handle)\r
+{\r
+  TRACE("(stubmsg == ^%p, buflen == %lu, handle == %p): wild guess.\n", stubmsg, buflen, handle);\r
+  \r
+  assert( stubmsg && stubmsg->RpcMsg );\r
+\r
+  /* I guess this is our chance to put the binding handle into the RPC_MESSAGE */\r
+  stubmsg->RpcMsg->Handle = handle;\r
+  \r
+  stubmsg->RpcMsg->BufferLength = buflen;\r
+  if (I_RpcGetBuffer(stubmsg->RpcMsg) != S_OK)\r
+    return NULL;\r
+\r
+  stubmsg->Buffer = stubmsg->BufferStart = stubmsg->RpcMsg->Buffer;\r
+  stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength;\r
+  stubmsg->BufferEnd = stubmsg->Buffer + stubmsg->BufferLength;\r
+  return (stubmsg->Buffer = (unsigned char *)stubmsg->RpcMsg->Buffer);\r
+}\r
+/***********************************************************************\r
+ *           NdrFreeBuffer [RPCRT4.@]\r
+ */\r
+void WINAPI NdrFreeBuffer(MIDL_STUB_MESSAGE *pStubMsg)\r
+{\r
+  TRACE("(pStubMsg == ^%p): wild guess.\n", pStubMsg);\r
+  I_RpcFreeBuffer(pStubMsg->RpcMsg);\r
+  pStubMsg->BufferLength = 0;\r
+  pStubMsg->Buffer = pStubMsg->BufferEnd = (unsigned char *)(pStubMsg->RpcMsg->Buffer = NULL);\r
+}\r
+\r
+/************************************************************************\r
+ *           NdrSendReceive [RPCRT4.@]\r
+ */\r
+unsigned char *WINAPI NdrSendReceive( MIDL_STUB_MESSAGE *stubmsg, unsigned char *buffer  )\r
+{\r
+  TRACE("(stubmsg == ^%p, buffer == ^%p)\n", stubmsg, buffer);\r
+\r
+  /* FIXME: how to handle errors? (raise exception?) */\r
+  if (!stubmsg) {\r
+    ERR("NULL stub message.  No action taken.\n");\r
+    return NULL;\r
+  }\r
+  if (!stubmsg->RpcMsg) {\r
+    ERR("RPC Message not present in stub message.  No action taken.\n");\r
+    return NULL;\r
+  }\r
+\r
+  /* FIXME: Seems wrong.  Where should this really come from, and when? */\r
+  stubmsg->RpcMsg->DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;\r
+\r
+  if (I_RpcSendReceive(stubmsg->RpcMsg) != RPC_S_OK) {\r
+    WARN("I_RpcSendReceive did not return success.\n");\r
+    /* FIXME: raise exception? */\r
+  }\r
+\r
+  /* FIXME: is this the right return value? */\r
+  return NULL;\r
+}\r
diff --git a/reactos/lib/rpcrt4/ndr_misc.h b/reactos/lib/rpcrt4/ndr_misc.h
new file mode 100644 (file)
index 0000000..9ffeed2
--- /dev/null
@@ -0,0 +1,53 @@
+/*\r
+ * NDR definitions\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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 __WINE_NDR_MISC_H\r
+#define __WINE_NDR_MISC_H\r
+\r
+#include <stdarg.h>\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "rpc.h"\r
+#include "rpcndr.h"\r
+\r
+struct IPSFactoryBuffer;\r
+\r
+LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc,\r
+                              PFORMAT_STRING pFormat, va_list args );\r
+\r
+HRESULT RPCRT4_GetPSFactory(REFIID riid, struct IPSFactoryBuffer **ppPS);\r
+\r
+PFORMAT_STRING ComputeConformance(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,\r
+                                  PFORMAT_STRING pFormat, ULONG_PTR def);\r
+\r
+typedef unsigned char* (WINAPI *NDR_MARSHALL)  (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING);\r
+typedef unsigned char* (WINAPI *NDR_UNMARSHALL)(PMIDL_STUB_MESSAGE, unsigned char**,PFORMAT_STRING, unsigned char);\r
+typedef void           (WINAPI *NDR_BUFFERSIZE)(PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING);\r
+typedef unsigned long  (WINAPI *NDR_MEMORYSIZE)(PMIDL_STUB_MESSAGE,                 PFORMAT_STRING);\r
+typedef void           (WINAPI *NDR_FREE)      (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING);\r
+\r
+extern NDR_MARSHALL   NdrMarshaller[];\r
+extern NDR_UNMARSHALL NdrUnmarshaller[];\r
+extern NDR_BUFFERSIZE NdrBufferSizer[];\r
+extern NDR_MEMORYSIZE NdrMemorySizer[];\r
+extern NDR_FREE       NdrFreer[];\r
+\r
+#endif  /* __WINE_NDR_MISC_H */\r
diff --git a/reactos/lib/rpcrt4/ndr_ole.c b/reactos/lib/rpcrt4/ndr_ole.c
new file mode 100644 (file)
index 0000000..aef1c94
--- /dev/null
@@ -0,0 +1,350 @@
+/*\r
+ * OLE32 callouts, COM interface marshalling\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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
+ * TODO:\r
+ *  - figure out whether we *really* got this right\r
+ *  - check for errors and throw exceptions\r
+ *  - what are the marshalling functions supposed to return?\r
+ *  - finish RpcStream_Vtbl\r
+ */\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#define COBJMACROS\r
+#define NONAMELESSUNION\r
+#define NONAMELESSSTRUCT\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+#include "winreg.h"\r
+\r
+#include "objbase.h"\r
+\r
+#include "ndr_misc.h"\r
+#include "rpcndr.h"\r
+#include "wine/rpcfc.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+static HMODULE hOLE;\r
+\r
+static HRESULT (WINAPI *COM_GetMarshalSizeMax)(ULONG *,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD);\r
+static HRESULT (WINAPI *COM_MarshalInterface)(LPSTREAM,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD);\r
+static HRESULT (WINAPI *COM_UnmarshalInterface)(LPSTREAM,REFIID,LPVOID*);\r
+static HRESULT (WINAPI *COM_ReleaseMarshalData)(LPSTREAM);\r
+static HRESULT (WINAPI *COM_GetClassObject)(REFCLSID,DWORD,COSERVERINFO *,REFIID,LPVOID *);\r
+static HRESULT (WINAPI *COM_GetPSClsid)(REFIID,CLSID *);\r
+static LPVOID (WINAPI *COM_MemAlloc)(ULONG);\r
+static void (WINAPI *COM_MemFree)(LPVOID);\r
+\r
+static HMODULE LoadCOM(void)\r
+{\r
+  if (hOLE) return hOLE;\r
+  hOLE = LoadLibraryA("OLE32.DLL");\r
+  if (!hOLE) return 0;\r
+  COM_GetMarshalSizeMax  = (LPVOID)GetProcAddress(hOLE, "CoGetMarshalSizeMax");\r
+  COM_MarshalInterface   = (LPVOID)GetProcAddress(hOLE, "CoMarshalInterface");\r
+  COM_UnmarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoUnmarshalInterface");\r
+  COM_ReleaseMarshalData = (LPVOID)GetProcAddress(hOLE, "CoReleaseMarshalData");\r
+  COM_GetClassObject     = (LPVOID)GetProcAddress(hOLE, "CoGetClassObject");\r
+  COM_GetPSClsid         = (LPVOID)GetProcAddress(hOLE, "CoGetPSClsid");\r
+  COM_MemAlloc = (LPVOID)GetProcAddress(hOLE, "CoTaskMemAlloc");\r
+  COM_MemFree  = (LPVOID)GetProcAddress(hOLE, "CoTaskMemFree");\r
+  return hOLE;\r
+}\r
+\r
+/* CoMarshalInterface/CoUnmarshalInterface works on streams,\r
+ * so implement a simple stream on top of the RPC buffer\r
+ * (which also implements the MInterfacePointer structure) */\r
+typedef struct RpcStreamImpl\r
+{\r
+  IStreamVtbl *lpVtbl;\r
+  DWORD RefCount;\r
+  PMIDL_STUB_MESSAGE pMsg;\r
+  LPDWORD size;\r
+  char *data;\r
+  DWORD pos;\r
+} RpcStreamImpl;\r
+\r
+static HRESULT WINAPI RpcStream_QueryInterface(LPSTREAM iface,\r
+                                              REFIID riid,\r
+                                              LPVOID *obj)\r
+{\r
+  RpcStreamImpl *This = (RpcStreamImpl *)iface;\r
+  if (IsEqualGUID(&IID_IUnknown, riid) ||\r
+      IsEqualGUID(&IID_ISequentialStream, riid) ||\r
+      IsEqualGUID(&IID_IStream, riid)) {\r
+    *obj = This;\r
+    This->RefCount++;\r
+    return S_OK;\r
+  }\r
+  return E_NOINTERFACE;\r
+}\r
+\r
+static ULONG WINAPI RpcStream_AddRef(LPSTREAM iface)\r
+{\r
+  RpcStreamImpl *This = (RpcStreamImpl *)iface;\r
+  return ++(This->RefCount);\r
+}\r
+\r
+static ULONG WINAPI RpcStream_Release(LPSTREAM iface)\r
+{\r
+  RpcStreamImpl *This = (RpcStreamImpl *)iface;\r
+  if (!--(This->RefCount)) {\r
+    TRACE("size=%ld\n", *This->size);\r
+    This->pMsg->Buffer = This->data + *This->size;\r
+    HeapFree(GetProcessHeap(),0,This);\r
+    return 0;\r
+  }\r
+  return This->RefCount;\r
+}\r
+\r
+static HRESULT WINAPI RpcStream_Read(LPSTREAM iface,\r
+                                    void *pv,\r
+                                    ULONG cb,\r
+                                    ULONG *pcbRead)\r
+{\r
+  RpcStreamImpl *This = (RpcStreamImpl *)iface;\r
+  if (This->pos + cb > *This->size) cb = *This->size - This->pos;\r
+  if (cb) {\r
+    memcpy(pv, This->data + This->pos, cb);\r
+    This->pos += cb;\r
+  }\r
+  if (pcbRead) *pcbRead = cb;\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT WINAPI RpcStream_Write(LPSTREAM iface,\r
+                                     const void *pv,\r
+                                     ULONG cb,\r
+                                     ULONG *pcbWritten)\r
+{\r
+  RpcStreamImpl *This = (RpcStreamImpl *)iface;\r
+  memcpy(This->data + This->pos, pv, cb);\r
+  This->pos += cb;\r
+  if (This->pos > *This->size) *This->size = This->pos;\r
+  if (pcbWritten) *pcbWritten = cb;\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT WINAPI RpcStream_Seek(LPSTREAM iface,\r
+                                    LARGE_INTEGER move,\r
+                                    DWORD origin,\r
+                                    ULARGE_INTEGER *newPos)\r
+{\r
+  RpcStreamImpl *This = (RpcStreamImpl *)iface;\r
+  switch (origin) {\r
+  case STREAM_SEEK_SET:\r
+    This->pos = move.u.LowPart;\r
+    break;\r
+  case STREAM_SEEK_CUR:\r
+    This->pos = This->pos + move.u.LowPart;\r
+    break;\r
+  case STREAM_SEEK_END:\r
+    This->pos = *This->size + move.u.LowPart;\r
+    break;\r
+  default:\r
+    return STG_E_INVALIDFUNCTION;\r
+  }\r
+  if (newPos) {\r
+    newPos->u.LowPart = This->pos;\r
+    newPos->u.HighPart = 0;\r
+  }\r
+  return S_OK;\r
+}\r
+\r
+static HRESULT WINAPI RpcStream_SetSize(LPSTREAM iface,\r
+                                       ULARGE_INTEGER newSize)\r
+{\r
+  RpcStreamImpl *This = (RpcStreamImpl *)iface;\r
+  *This->size = newSize.u.LowPart;\r
+  return S_OK;\r
+}\r
+\r
+static IStreamVtbl RpcStream_Vtbl =\r
+{\r
+  RpcStream_QueryInterface,\r
+  RpcStream_AddRef,\r
+  RpcStream_Release,\r
+  RpcStream_Read,\r
+  RpcStream_Write,\r
+  RpcStream_Seek,\r
+  RpcStream_SetSize,\r
+  NULL, /* CopyTo */\r
+  NULL, /* Commit */\r
+  NULL, /* Revert */\r
+  NULL, /* LockRegion */\r
+  NULL, /* UnlockRegion */\r
+  NULL, /* Stat */\r
+  NULL  /* Clone */\r
+};\r
+\r
+static LPSTREAM RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg, BOOL init)\r
+{\r
+  RpcStreamImpl *This;\r
+  This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(RpcStreamImpl));\r
+  if (!This) return NULL;\r
+  This->lpVtbl = &RpcStream_Vtbl;\r
+  This->RefCount = 1;\r
+  This->pMsg = pStubMsg;\r
+  This->size = (LPDWORD)pStubMsg->Buffer;\r
+  This->data = (char*)(This->size + 1);\r
+  This->pos = 0;\r
+  if (init) *This->size = 0;\r
+  TRACE("init size=%ld\n", *This->size);\r
+  return (LPSTREAM)This;\r
+}\r
+\r
+const IID* get_ip_iid(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)\r
+{\r
+  const IID *riid;\r
+  if (!pFormat) return &IID_IUnknown;\r
+  TRACE("format=%02x %02x\n", pFormat[0], pFormat[1]);\r
+  if (pFormat[0] != RPC_FC_IP) FIXME("format=%d\n", pFormat[0]);\r
+  if (pFormat[1] == RPC_FC_CONSTANT_IID) {\r
+    riid = (const IID *)&pFormat[2];\r
+  } else {\r
+    ComputeConformance(pStubMsg, pMemory, pFormat+2, 0);\r
+    riid = (const IID *)pStubMsg->MaxCount;\r
+  }\r
+  if (!riid) riid = &IID_IUnknown;\r
+  TRACE("got %s\n", debugstr_guid(riid));\r
+  return riid;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrInterfacePointerMarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                  unsigned char *pMemory,\r
+                                                  PFORMAT_STRING pFormat)\r
+{\r
+  const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat);\r
+  LPSTREAM stream;\r
+  HRESULT hr;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  pStubMsg->MaxCount = 0;\r
+  if (!LoadCOM()) return NULL;\r
+  stream = RpcStream_Create(pStubMsg, TRUE);\r
+  hr = COM_MarshalInterface(stream, riid, (LPUNKNOWN)pMemory,\r
+                           pStubMsg->dwDestContext, pStubMsg->pvDestContext,\r
+                           MSHLFLAGS_NORMAL);\r
+  IStream_Release(stream);\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrInterfacePointerUnmarshall [RPCRT4.@]\r
+ */\r
+unsigned char * WINAPI NdrInterfacePointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                    unsigned char **ppMemory,\r
+                                                    PFORMAT_STRING pFormat,\r
+                                                    unsigned char fMustAlloc)\r
+{\r
+  LPSTREAM stream;\r
+  HRESULT hr;\r
+\r
+  TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);\r
+  if (!LoadCOM()) return NULL;\r
+  *(LPVOID*)ppMemory = NULL;\r
+  stream = RpcStream_Create(pStubMsg, FALSE);\r
+  hr = COM_UnmarshalInterface(stream, &IID_NULL, (LPVOID*)ppMemory);\r
+  IStream_Release(stream);\r
+  return NULL;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrInterfacePointerBufferSize [RPCRT4.@]\r
+ */\r
+void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                         unsigned char *pMemory,\r
+                                         PFORMAT_STRING pFormat)\r
+{\r
+  const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat);\r
+  ULONG size = 0;\r
+  HRESULT hr;\r
+\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  if (!LoadCOM()) return;\r
+  hr = COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory,\r
+                            pStubMsg->dwDestContext, pStubMsg->pvDestContext,\r
+                            MSHLFLAGS_NORMAL);\r
+  TRACE("size=%ld\n", size);\r
+  pStubMsg->BufferLength += sizeof(DWORD) + size;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrInterfacePointerMemorySize [RPCRT4.@]\r
+ */\r
+unsigned long WINAPI NdrInterfacePointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                                  PFORMAT_STRING pFormat)\r
+{\r
+  FIXME("(%p,%p): stub\n", pStubMsg, pFormat);\r
+  return 0;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrInterfacePointerFree [RPCRT4.@]\r
+ */\r
+void WINAPI NdrInterfacePointerFree(PMIDL_STUB_MESSAGE pStubMsg,\r
+                                   unsigned char *pMemory,\r
+                                   PFORMAT_STRING pFormat)\r
+{\r
+  LPUNKNOWN pUnk = (LPUNKNOWN)pMemory;\r
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);\r
+  if (pUnk) IUnknown_Release(pUnk);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrOleAllocate [RPCRT4.@]\r
+ */\r
+void * WINAPI NdrOleAllocate(size_t Size)\r
+{\r
+  if (!LoadCOM()) return NULL;\r
+  return COM_MemAlloc(Size);\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrOleFree [RPCRT4.@]\r
+ */\r
+void WINAPI NdrOleFree(void *NodeToFree)\r
+{\r
+  if (!LoadCOM()) return;\r
+  COM_MemFree(NodeToFree);\r
+}\r
+\r
+/* internal */\r
+HRESULT RPCRT4_GetPSFactory(REFIID riid, LPPSFACTORYBUFFER *pPS)\r
+{\r
+  HRESULT hr;\r
+  CLSID clsid;\r
+\r
+  if (!LoadCOM()) return RPC_E_UNEXPECTED;\r
+  hr = COM_GetPSClsid(riid, &clsid);\r
+  if (FAILED(hr)) return hr;\r
+  hr = COM_GetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,\r
+                          &IID_IPSFactoryBuffer, (LPVOID *)pPS);\r
+  return hr;\r
+}\r
diff --git a/reactos/lib/rpcrt4/ndr_stubless.c b/reactos/lib/rpcrt4/ndr_stubless.c
new file mode 100644 (file)
index 0000000..b6bb11d
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+ * NDR client stuff\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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
+ * TODO:\r
+ *  - Exception handling\r
+ *  - Context stuff\r
+ *  - Who knows\r
+ */\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+#include "winreg.h"\r
+\r
+#include "rpc.h"\r
+#include "rpcndr.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+#include "ndr_misc.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+LONG_PTR /* CLIENT_CALL_RETURN */ RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, va_list args)\r
+{\r
+\r
+  RPC_CLIENT_INTERFACE *rpc_cli_if = (RPC_CLIENT_INTERFACE *)(pStubDesc->RpcInterfaceInformation);\r
+  LONG_PTR ret = 0;\r
+/*\r
+  RPC_BINDING_HANDLE handle = 0;\r
+  RPC_MESSAGE rpcmsg;\r
+  MIDL_STUB_MESSAGE stubmsg;\r
+*/\r
+\r
+  FIXME("(pStubDec == ^%p,pFormat = ^%p,...): stub\n", pStubDesc, pFormat);\r
+  if (rpc_cli_if) /* NULL for objects */ {\r
+    TRACE("  *rpc_cli_if (== ^%p) == (RPC_CLIENT_INTERFACE):\n", pStubDesc);\r
+    TRACE("    Length == %d\n", rpc_cli_if->Length);\r
+    TRACE("    InterfaceID == %s (%d.%d)\n", debugstr_guid(&rpc_cli_if->InterfaceId.SyntaxGUID), \r
+      rpc_cli_if->InterfaceId.SyntaxVersion.MajorVersion, rpc_cli_if->InterfaceId.SyntaxVersion.MinorVersion);\r
+    TRACE("    TransferSyntax == %s (%d.%d)\n", debugstr_guid(&rpc_cli_if->TransferSyntax.SyntaxGUID),\r
+      rpc_cli_if->TransferSyntax.SyntaxVersion.MajorVersion, rpc_cli_if->TransferSyntax.SyntaxVersion.MinorVersion);\r
+    TRACE("    DispatchTable == ^%p\n", rpc_cli_if->DispatchTable);\r
+    TRACE("    RpcProtseqEndpointCount == ^%d\n", rpc_cli_if->RpcProtseqEndpointCount);\r
+    TRACE("    RpcProtseqEndpoint == ^%p\n", rpc_cli_if->RpcProtseqEndpoint);\r
+    TRACE("    Flags == ^%d\n", rpc_cli_if->Flags);\r
+  }\r
+\r
+  /* for now, while these functons are under development, this is too sketchy.  commented out. */\r
+  /*\r
+  NdrClientInitializeNew( &rpcmsg, &stubmsg, pStubDesc, 0 );\r
+        \r
+  handle = (RPC_BINDING_HANDLE)0xdeadbeef; */ /* FIXME */\r
+\r
+  /* stubmsg.BufferLength = 0;*/ /* FIXME */\r
+  /*\r
+  NdrGetBuffer( &stubmsg, stubmsg.BufferLength, handle );\r
+  NdrSendReceive( &stubmsg, stubmsg.Buffer  );\r
+  NdrFreeBuffer( &stubmsg );\r
+  */\r
+  return ret;\r
+}\r
+\r
+/***********************************************************************\r
+ *           NdrClientCall2 [RPCRT4.@]\r
+ */\r
+LONG_PTR /* CLIENT_CALL_RETURN */ WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc,\r
+  PFORMAT_STRING pFormat, ...)\r
+{\r
+    LONG_PTR ret;\r
+    va_list args;\r
+\r
+    TRACE("(%p,%p,...)\n", pStubDesc, pFormat);\r
+\r
+    va_start(args, pFormat);\r
+    ret = RPCRT4_NdrClientCall2(pStubDesc, pFormat, args);\r
+    va_end(args);\r
+    return ret;\r
+}\r
diff --git a/reactos/lib/rpcrt4/rpc_binding.c b/reactos/lib/rpcrt4/rpc_binding.c
new file mode 100644 (file)
index 0000000..32b7143
--- /dev/null
@@ -0,0 +1,1096 @@
+/*\r
+ * RPC binding API\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\r
+ * Copyright 2003 Mike Hearn\r
+ * Copyright 2004 Filip Navara\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
+ * TODO:\r
+ *  - a whole lot\r
+ */\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <assert.h>\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winnls.h"\r
+#include "winerror.h"\r
+#include "winreg.h"\r
+#include "winternl.h"\r
+#include "wine/unicode.h"\r
+\r
+#include "rpc.h"\r
+#include "rpcndr.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+#include "rpc_binding.h"\r
+#include "rpc_message.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)\r
+{\r
+  DWORD len;\r
+  LPSTR s;\r
+  if (!src) return NULL;\r
+  if (slen == -1) slen = strlen(src);\r
+  len = slen;\r
+  s = HeapAlloc(GetProcessHeap(), 0, len+1);\r
+  memcpy(s, src, len);\r
+  s[len] = 0;\r
+  return s;\r
+}\r
+\r
+LPSTR RPCRT4_strdupWtoA(LPWSTR src)\r
+{\r
+  DWORD len;\r
+  LPSTR s;\r
+  if (!src) return NULL;\r
+  len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);\r
+  s = HeapAlloc(GetProcessHeap(), 0, len);\r
+  WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);\r
+  return s;\r
+}\r
+\r
+LPWSTR RPCRT4_strdupAtoW(LPSTR src)\r
+{\r
+  DWORD len;\r
+  LPWSTR s;\r
+  if (!src) return NULL;\r
+  len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);\r
+  s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));\r
+  MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);\r
+  return s;\r
+}\r
+\r
+LPWSTR RPCRT4_strndupW(LPWSTR src, INT slen)\r
+{\r
+  DWORD len;\r
+  LPWSTR s;\r
+  if (!src) return NULL;\r
+  if (slen == -1) slen = strlenW(src);\r
+  len = slen;\r
+  s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));\r
+  memcpy(s, src, len*sizeof(WCHAR));\r
+  s[len] = 0;\r
+  return s;\r
+}\r
+\r
+void RPCRT4_strfree(LPSTR src)\r
+{\r
+  if (src) HeapFree(GetProcessHeap(), 0, src);\r
+}\r
+\r
+RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions, RpcBinding* Binding)\r
+{\r
+  RpcConnection* NewConnection;\r
+\r
+  NewConnection = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcConnection));\r
+  NewConnection->server = server;\r
+  NewConnection->Protseq = RPCRT4_strdupA(Protseq);\r
+  NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);\r
+  NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);\r
+  NewConnection->Used = Binding;\r
+  NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;\r
+\r
+  TRACE("connection: %p\n", NewConnection);\r
+  *Connection = NewConnection;\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)\r
+{\r
+  TRACE("connection: %p\n", Connection);\r
+\r
+  RPCRT4_CloseConnection(Connection);\r
+  RPCRT4_strfree(Connection->Endpoint);\r
+  RPCRT4_strfree(Connection->NetworkAddr);\r
+  RPCRT4_strfree(Connection->Protseq);\r
+  HeapFree(GetProcessHeap(), 0, Connection);\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection)\r
+{\r
+  TRACE("(Connection == ^%p)\n", Connection);\r
+  if (!Connection->conn) {\r
+    if (Connection->server) { /* server */\r
+      /* protseq=ncalrpc: supposed to use NT LPC ports,\r
+       * but we'll implement it with named pipes for now */\r
+      if (strcmp(Connection->Protseq, "ncalrpc") == 0) {\r
+        static LPCSTR prefix = "\\\\.\\pipe\\lrpc\\";\r
+        LPSTR pname;\r
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);\r
+        strcat(strcpy(pname, prefix), Connection->Endpoint);\r
+        TRACE("listening on %s\n", pname);\r
+        Connection->conn = CreateNamedPipeA(pname, PROFILE_SERVER | PIPE_ACCESS_DUPLEX,\r
+                                         PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES,\r
+                                         RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);\r
+        HeapFree(GetProcessHeap(), 0, pname);\r
+        memset(&Connection->ovl, 0, sizeof(Connection->ovl));\r
+        Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);\r
+        if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) {\r
+          WARN("Couldn't ConnectNamedPipe (error was %ld)\n", GetLastError());\r
+          if (GetLastError() == ERROR_PIPE_CONNECTED) {\r
+            SetEvent(Connection->ovl.hEvent);\r
+            return RPC_S_OK;\r
+          } else if (GetLastError() == ERROR_IO_PENDING) {\r
+            return RPC_S_OK;\r
+          }\r
+          return RPC_S_SERVER_UNAVAILABLE;\r
+        }\r
+      }\r
+      /* protseq=ncacn_np: named pipes */\r
+      else if (strcmp(Connection->Protseq, "ncacn_np") == 0) {\r
+        static LPCSTR prefix = "\\\\.";\r
+        LPSTR pname;\r
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);\r
+        strcat(strcpy(pname, prefix), Connection->Endpoint);\r
+        TRACE("listening on %s\n", pname);\r
+        Connection->conn = CreateNamedPipeA(pname, PROFILE_SERVER | PIPE_ACCESS_DUPLEX,\r
+                                         PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,\r
+                                         RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);\r
+        HeapFree(GetProcessHeap(), 0, pname);\r
+        memset(&Connection->ovl, 0, sizeof(Connection->ovl));\r
+        Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);\r
+        if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) {\r
+          WARN("Couldn't ConnectNamedPipe (error was %ld)\n", GetLastError());\r
+          if (GetLastError() == ERROR_PIPE_CONNECTED) {\r
+            SetEvent(Connection->ovl.hEvent);\r
+            return RPC_S_OK;\r
+          }\r
+          return RPC_S_SERVER_UNAVAILABLE;\r
+        }\r
+      }\r
+      else {\r
+        ERR("protseq %s not supported\n", Connection->Protseq);\r
+        return RPC_S_PROTSEQ_NOT_SUPPORTED;\r
+      }\r
+    }\r
+    else { /* client */\r
+      /* protseq=ncalrpc: supposed to use NT LPC ports,\r
+       * but we'll implement it with named pipes for now */\r
+      if (strcmp(Connection->Protseq, "ncalrpc") == 0) {\r
+        static LPCSTR prefix = "\\\\.\\pipe\\lrpc\\";\r
+        LPSTR pname;\r
+        HANDLE conn;\r
+        DWORD err;\r
+        DWORD dwMode;\r
+\r
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);\r
+        strcat(strcpy(pname, prefix), Connection->Endpoint);\r
+        TRACE("connecting to %s\n", pname);\r
+        while (TRUE) {\r
+          if (WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {\r
+            conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,\r
+                               OPEN_EXISTING, 0, 0);\r
+            if (conn != INVALID_HANDLE_VALUE) break;\r
+            err = GetLastError();\r
+            if (err == ERROR_PIPE_BUSY) continue;\r
+            TRACE("connection failed, error=%lx\n", err);\r
+            HeapFree(GetProcessHeap(), 0, pname);\r
+            return RPC_S_SERVER_TOO_BUSY;\r
+          } else {\r
+            err = GetLastError();\r
+            TRACE("connection failed, error=%lx\n", err);\r
+            HeapFree(GetProcessHeap(), 0, pname);\r
+            return RPC_S_SERVER_UNAVAILABLE;\r
+          }\r
+        }\r
+\r
+        /* success */\r
+        HeapFree(GetProcessHeap(), 0, pname);\r
+        memset(&Connection->ovl, 0, sizeof(Connection->ovl));\r
+        /* pipe is connected; change to message-read mode. */\r
+        dwMode = PIPE_READMODE_MESSAGE; \r
+        SetNamedPipeHandleState(conn, &dwMode, NULL, NULL);\r
+        Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);\r
+        Connection->conn = conn;\r
+      }\r
+      /* protseq=ncacn_np: named pipes */\r
+      else if (strcmp(Connection->Protseq, "ncacn_np") == 0) {\r
+        static LPCSTR prefix = "\\\\.";\r
+        LPSTR pname;\r
+        HANDLE conn;\r
+        DWORD err;\r
+        DWORD dwMode;\r
+\r
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);\r
+        strcat(strcpy(pname, prefix), Connection->Endpoint);\r
+        TRACE("connecting to %s\n", pname);\r
+        conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,\r
+                           OPEN_EXISTING, 0, 0);\r
+        if (conn == INVALID_HANDLE_VALUE) {\r
+          err = GetLastError();\r
+          /* we don't need to handle ERROR_PIPE_BUSY here,\r
+           * the doc says that it is returned to the app */\r
+          TRACE("connection failed, error=%lx\n", err);\r
+          HeapFree(GetProcessHeap(), 0, pname);\r
+          if (err == ERROR_PIPE_BUSY)\r
+            return RPC_S_SERVER_TOO_BUSY;\r
+          else\r
+            return RPC_S_SERVER_UNAVAILABLE;\r
+        }\r
+\r
+        /* success */\r
+        HeapFree(GetProcessHeap(), 0, pname);\r
+        memset(&Connection->ovl, 0, sizeof(Connection->ovl));\r
+        /* pipe is connected; change to message-read mode. */\r
+        dwMode = PIPE_READMODE_MESSAGE;\r
+        SetNamedPipeHandleState(conn, &dwMode, NULL, NULL);\r
+        Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);\r
+        Connection->conn = conn;\r
+      } else {\r
+        ERR("protseq %s not supported\n", Connection->Protseq);\r
+        return RPC_S_PROTSEQ_NOT_SUPPORTED;\r
+      }\r
+    }\r
+  }\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)\r
+{\r
+  TRACE("(Connection == ^%p)\n", Connection);\r
+  if (Connection->conn) {\r
+    CancelIo(Connection->conn);\r
+    CloseHandle(Connection->conn);\r
+    Connection->conn = 0;\r
+  }\r
+  if (Connection->ovl.hEvent) {\r
+    CloseHandle(Connection->ovl.hEvent);\r
+    Connection->ovl.hEvent = 0;\r
+  }\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)\r
+{\r
+  RpcConnection* NewConnection;\r
+  RPC_STATUS err = RPCRT4_CreateConnection(&NewConnection, OldConnection->server, OldConnection->Protseq,\r
+                                           OldConnection->NetworkAddr, OldConnection->Endpoint, NULL, NULL);\r
+  if (err == RPC_S_OK) {\r
+    /* because of the way named pipes work, we'll transfer the connected pipe\r
+     * to the child, then reopen the server binding to continue listening */\r
+    NewConnection->conn = OldConnection->conn;\r
+    NewConnection->ovl = OldConnection->ovl;\r
+    OldConnection->conn = 0;\r
+    memset(&OldConnection->ovl, 0, sizeof(OldConnection->ovl));\r
+    *Connection = NewConnection;\r
+    RPCRT4_OpenConnection(OldConnection);\r
+  }\r
+  return err;\r
+}\r
+\r
+RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)\r
+{\r
+  RpcBinding* NewBinding;\r
+\r
+  NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));\r
+  NewBinding->refs = 1;\r
+  NewBinding->server = server;\r
+\r
+  *Binding = NewBinding;\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq)\r
+{\r
+  RpcBinding* NewBinding;\r
+\r
+  RPCRT4_AllocBinding(&NewBinding, server);\r
+  NewBinding->Protseq = RPCRT4_strdupA(Protseq);\r
+\r
+  TRACE("binding: %p\n", NewBinding);\r
+  *Binding = NewBinding;\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq)\r
+{\r
+  RpcBinding* NewBinding;\r
+\r
+  RPCRT4_AllocBinding(&NewBinding, server);\r
+  NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);\r
+\r
+  TRACE("binding: %p\n", NewBinding);\r
+  *Binding = NewBinding;\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr,  LPSTR Endpoint,  LPSTR NetworkOptions)\r
+{\r
+  TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding,\r
+   debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));\r
+\r
+  RPCRT4_strfree(Binding->NetworkAddr);\r
+  Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);\r
+  RPCRT4_strfree(Binding->Endpoint);\r
+  if (Endpoint) {\r
+    Binding->Endpoint = RPCRT4_strdupA(Endpoint);\r
+  } else {\r
+    Binding->Endpoint = RPCRT4_strdupA("");\r
+  }\r
+  if (!Binding->Endpoint) ERR("out of memory?\n");\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions)\r
+{\r
+  TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding, \r
+   debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));\r
+\r
+  RPCRT4_strfree(Binding->NetworkAddr);\r
+  Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);\r
+  RPCRT4_strfree(Binding->Endpoint);\r
+  if (Endpoint) {\r
+    Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);\r
+  } else {\r
+    Binding->Endpoint = RPCRT4_strdupA("");\r
+  }\r
+  if (!Binding->Endpoint) ERR("out of memory?\n");\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint)\r
+{\r
+  TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);\r
+\r
+  RPCRT4_strfree(Binding->Endpoint);\r
+  Binding->Endpoint = RPCRT4_strdupA(Endpoint);\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid)\r
+{\r
+  TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid)); \r
+  if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));\r
+  else UuidCreateNil(&Binding->ObjectUuid);\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)\r
+{\r
+  RpcBinding* NewBinding;\r
+  TRACE("(*RpcBinding == ^%p, Connection == ^%p)\n", *Binding, Connection);\r
+\r
+  RPCRT4_AllocBinding(&NewBinding, Connection->server);\r
+  NewBinding->Protseq = RPCRT4_strdupA(Connection->Protseq);\r
+  NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);\r
+  NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);\r
+  NewBinding->FromConn = Connection;\r
+\r
+  TRACE("binding: %p\n", NewBinding);\r
+  *Binding = NewBinding;\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)\r
+{\r
+  InterlockedIncrement(&OldBinding->refs);\r
+  *Binding = OldBinding;\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)\r
+{\r
+  if (InterlockedDecrement(&Binding->refs))\r
+    return RPC_S_OK;\r
+\r
+  TRACE("binding: %p\n", Binding);\r
+  /* FIXME: release connections */\r
+  RPCRT4_strfree(Binding->Endpoint);\r
+  RPCRT4_strfree(Binding->NetworkAddr);\r
+  RPCRT4_strfree(Binding->Protseq);\r
+  HeapFree(GetProcessHeap(), 0, Binding);\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,\r
+                              PRPC_SYNTAX_IDENTIFIER TransferSyntax,\r
+                              PRPC_SYNTAX_IDENTIFIER InterfaceId)\r
+{\r
+  RpcConnection* NewConnection;\r
+  RPC_STATUS status;\r
+\r
+  TRACE("(Binding == ^%p)\n", Binding);\r
+\r
+  /* if we try to bind a new interface and the connection is already opened,\r
+   * close the current connection and create a new with the new binding. */ \r
+  if (!Binding->server && Binding->FromConn &&\r
+      memcmp(&Binding->FromConn->ActiveInterface, InterfaceId,\r
+             sizeof(RPC_SYNTAX_IDENTIFIER))) {\r
+\r
+    TRACE("releasing pre-existing connection\n");\r
+    RPCRT4_DestroyConnection(Binding->FromConn);\r
+    Binding->FromConn = NULL;\r
+  } else {\r
+    /* we already have an connection with acceptable binding, so use it */\r
+    if (Binding->FromConn) {\r
+      *Connection = Binding->FromConn;\r
+      return RPC_S_OK;\r
+    }\r
+  }\r
+  \r
+  /* create a new connection */\r
+  RPCRT4_CreateConnection(&NewConnection, Binding->server, Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint, NULL, Binding);\r
+  *Connection = NewConnection;\r
+  status = RPCRT4_OpenConnection(NewConnection);\r
+  if (status != RPC_S_OK) {\r
+    return status;\r
+  }\r
+\r
+  /* we need to send a binding packet if we are client. */\r
+  if (!(*Connection)->server) {\r
+    RpcPktHdr *hdr;\r
+    DWORD count;\r
+    BYTE *response;\r
+    RpcPktHdr *response_hdr;\r
+\r
+    TRACE("sending bind request to server\n");\r
+\r
+    hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,\r
+                                 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,\r
+                                 InterfaceId, TransferSyntax);\r
+\r
+    status = RPCRT4_Send(*Connection, hdr, NULL, 0);\r
+    if (status != RPC_S_OK) {\r
+      RPCRT4_DestroyConnection(*Connection);\r
+      return status;\r
+    }\r
+\r
+    response = HeapAlloc(GetProcessHeap(), 0, RPC_MAX_PACKET_SIZE);\r
+    if (response == NULL) {\r
+      WARN("Can't allocate memory for binding response\n");\r
+      RPCRT4_DestroyConnection(*Connection);\r
+      return E_OUTOFMEMORY;\r
+    }\r
+\r
+    /* get a reply */\r
+    if (!ReadFile(NewConnection->conn, response, RPC_MAX_PACKET_SIZE, &count, NULL)) {\r
+      WARN("ReadFile failed with error %ld\n", GetLastError());\r
+      RPCRT4_DestroyConnection(*Connection);\r
+      return RPC_S_PROTOCOL_ERROR;\r
+    }\r
+\r
+    if (count < sizeof(response_hdr->common)) {\r
+      WARN("received invalid header\n");\r
+      RPCRT4_DestroyConnection(*Connection);\r
+      return RPC_S_PROTOCOL_ERROR;\r
+    }\r
+\r
+    response_hdr = (RpcPktHdr*)response;\r
+\r
+    if (response_hdr->common.rpc_ver != RPC_VER_MAJOR ||\r
+        response_hdr->common.rpc_ver_minor != RPC_VER_MINOR ||\r
+        response_hdr->common.ptype != PKT_BIND_ACK) {\r
+      WARN("invalid protocol version or rejection packet\n");\r
+      RPCRT4_DestroyConnection(*Connection);\r
+      return RPC_S_PROTOCOL_ERROR;\r
+    }\r
+\r
+    if (response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {\r
+      WARN("server doesn't allow large enough packets\n");\r
+      RPCRT4_DestroyConnection(*Connection);\r
+      return RPC_S_PROTOCOL_ERROR;\r
+    }\r
+\r
+    /* FIXME: do more checks? */\r
+\r
+    (*Connection)->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;\r
+    (*Connection)->ActiveInterface = *InterfaceId;\r
+  }\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)\r
+{\r
+  TRACE("(Binding == ^%p)\n", Binding);\r
+  if (!Connection) return RPC_S_OK;\r
+  if (Binding->FromConn == Connection) return RPC_S_OK;\r
+  return RPCRT4_DestroyConnection(Connection);\r
+}\r
+\r
+/* utility functions for string composing and parsing */\r
+static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)\r
+{\r
+  unsigned len = strlen(src);\r
+  memcpy(data, src, len*sizeof(CHAR));\r
+  return len;\r
+}\r
+\r
+static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)\r
+{\r
+  unsigned len = strlenW(src);\r
+  memcpy(data, src, len*sizeof(WCHAR));\r
+  return len;\r
+}\r
+\r
+static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)\r
+{\r
+  DWORD len = strlen(dst), slen = strlen(src);\r
+  LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));\r
+  if (!ndst)\r
+  {\r
+    HeapFree(GetProcessHeap(), 0, dst);\r
+    return NULL;\r
+  }\r
+  ndst[len] = ',';\r
+  memcpy(ndst+len+1, src, slen+1);\r
+  return ndst;\r
+}\r
+\r
+static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)\r
+{\r
+  DWORD len = strlenW(dst), slen = strlenW(src);\r
+  LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));\r
+  if (!ndst) \r
+  {\r
+    HeapFree(GetProcessHeap(), 0, dst);\r
+    return NULL;\r
+  }\r
+  ndst[len] = ',';\r
+  memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));\r
+  return ndst;\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *             RpcStringBindingComposeA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcStringBindingComposeA(unsigned char *ObjUuid, unsigned char *Protseq,\r
+                                           unsigned char *NetworkAddr, unsigned char *Endpoint,\r
+                                           unsigned char *Options, unsigned char** StringBinding )\r
+{\r
+  DWORD len = 1;\r
+  LPSTR data;\r
+\r
+  TRACE( "(%s,%s,%s,%s,%s,%p)\n",\r
+        debugstr_a( ObjUuid ), debugstr_a( Protseq ),\r
+        debugstr_a( NetworkAddr ), debugstr_a( Endpoint ),\r
+        debugstr_a( Options ), StringBinding );\r
+\r
+  if (ObjUuid && *ObjUuid) len += strlen(ObjUuid) + 1;\r
+  if (Protseq && *Protseq) len += strlen(Protseq) + 1;\r
+  if (NetworkAddr && *NetworkAddr) len += strlen(NetworkAddr);\r
+  if (Endpoint && *Endpoint) len += strlen(Endpoint) + 2;\r
+  if (Options && *Options) len += strlen(Options) + 2;\r
+\r
+  data = HeapAlloc(GetProcessHeap(), 0, len);\r
+  *StringBinding = data;\r
+\r
+  if (ObjUuid && *ObjUuid) {\r
+    data += RPCRT4_strcopyA(data, ObjUuid);\r
+    *data++ = '@';\r
+  }\r
+  if (Protseq && *Protseq) {\r
+    data += RPCRT4_strcopyA(data, Protseq);\r
+    *data++ = ':';\r
+  }\r
+  if (NetworkAddr && *NetworkAddr)\r
+    data += RPCRT4_strcopyA(data, NetworkAddr);\r
+\r
+  if ((Endpoint && *Endpoint) ||\r
+      (Options && *Options)) {\r
+    *data++ = '[';\r
+    if (Endpoint && *Endpoint) {\r
+      data += RPCRT4_strcopyA(data, Endpoint);\r
+      if (Options && *Options) *data++ = ',';\r
+    }\r
+    if (Options && *Options) {\r
+      data += RPCRT4_strcopyA(data, Options);\r
+    }\r
+    *data++ = ']';\r
+  }\r
+  *data = 0;\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcStringBindingComposeW (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcStringBindingComposeW( LPWSTR ObjUuid, LPWSTR Protseq,\r
+                                            LPWSTR NetworkAddr, LPWSTR Endpoint,\r
+                                            LPWSTR Options, LPWSTR* StringBinding )\r
+{\r
+  DWORD len = 1;\r
+  LPWSTR data;\r
+\r
+  TRACE("(%s,%s,%s,%s,%s,%p)\n",\r
+       debugstr_w( ObjUuid ), debugstr_w( Protseq ),\r
+       debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),\r
+       debugstr_w( Options ), StringBinding);\r
+\r
+  if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;\r
+  if (Protseq && *Protseq) len += strlenW(Protseq) + 1;\r
+  if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);\r
+  if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;\r
+  if (Options && *Options) len += strlenW(Options) + 2;\r
+\r
+  data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));\r
+  *StringBinding = data;\r
+\r
+  if (ObjUuid && *ObjUuid) {\r
+    data += RPCRT4_strcopyW(data, ObjUuid);\r
+    *data++ = '@';\r
+  }\r
+  if (Protseq && *Protseq) {\r
+    data += RPCRT4_strcopyW(data, Protseq);\r
+    *data++ = ':';\r
+  }\r
+  if (NetworkAddr && *NetworkAddr) {\r
+    data += RPCRT4_strcopyW(data, NetworkAddr);\r
+  }\r
+  if ((Endpoint && *Endpoint) ||\r
+      (Options && *Options)) {\r
+    *data++ = '[';\r
+    if (Endpoint && *Endpoint) {\r
+      data += RPCRT4_strcopyW(data, Endpoint);\r
+      if (Options && *Options) *data++ = ',';\r
+    }\r
+    if (Options && *Options) {\r
+      data += RPCRT4_strcopyW(data, Options);\r
+    }\r
+    *data++ = ']';\r
+  }\r
+  *data = 0;\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ *             RpcStringBindingParseA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcStringBindingParseA( unsigned char *StringBinding, unsigned char **ObjUuid,\r
+                                          unsigned char **Protseq, unsigned char **NetworkAddr,\r
+                                          unsigned char **Endpoint, unsigned char **Options)\r
+{\r
+  CHAR *data, *next;\r
+  static const char ep_opt[] = "endpoint=";\r
+\r
+  TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a(StringBinding),\r
+       ObjUuid, Protseq, NetworkAddr, Endpoint, Options);\r
+\r
+  if (ObjUuid) *ObjUuid = NULL;\r
+  if (Protseq) *Protseq = NULL;\r
+  if (NetworkAddr) *NetworkAddr = NULL;\r
+  if (Endpoint) *Endpoint = NULL;\r
+  if (Options) *Options = NULL;\r
+\r
+  data = StringBinding;\r
+\r
+  next = strchr(data, '@');\r
+  if (next) {\r
+    if (ObjUuid) *ObjUuid = RPCRT4_strndupA(data, next - data);\r
+    data = next+1;\r
+  }\r
+\r
+  next = strchr(data, ':');\r
+  if (next) {\r
+    if (Protseq) *Protseq = RPCRT4_strndupA(data, next - data);\r
+    data = next+1;\r
+  }\r
+\r
+  next = strchr(data, '[');\r
+  if (next) {\r
+    CHAR *close, *opt;\r
+\r
+    if (NetworkAddr) *NetworkAddr = RPCRT4_strndupA(data, next - data);\r
+    data = next+1;\r
+    close = strchr(data, ']');\r
+    if (!close) goto fail;\r
+\r
+    /* tokenize options */\r
+    while (data < close) {\r
+      next = strchr(data, ',');\r
+      if (!next || next > close) next = close;\r
+      /* FIXME: this is kind of inefficient */\r
+      opt = RPCRT4_strndupA(data, next - data);\r
+      data = next+1;\r
+\r
+      /* parse option */\r
+      next = strchr(opt, '=');\r
+      if (!next) {\r
+        /* not an option, must be an endpoint */\r
+        if (*Endpoint) goto fail;\r
+        *Endpoint = opt;\r
+      } else {\r
+        if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {\r
+          /* endpoint option */\r
+          if (*Endpoint) goto fail;\r
+          *Endpoint = RPCRT4_strdupA(next+1);\r
+          HeapFree(GetProcessHeap(), 0, opt);\r
+        } else {\r
+          /* network option */\r
+          if (*Options) {\r
+            /* FIXME: this is kind of inefficient */\r
+            *Options = RPCRT4_strconcatA(*Options, opt);\r
+            HeapFree(GetProcessHeap(), 0, opt);\r
+          } else \r
+           *Options = opt;\r
+        }\r
+      }\r
+    }\r
+\r
+    data = close+1;\r
+    if (*data) goto fail;\r
+  }\r
+  else if (NetworkAddr) \r
+    *NetworkAddr = RPCRT4_strdupA(data);\r
+\r
+  return RPC_S_OK;\r
+\r
+fail:\r
+  if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);\r
+  if (Protseq) RpcStringFreeA((unsigned char**)Protseq);\r
+  if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);\r
+  if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);\r
+  if (Options) RpcStringFreeA((unsigned char**)Options);\r
+  return RPC_S_INVALID_STRING_BINDING;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcStringBindingParseW (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcStringBindingParseW( LPWSTR StringBinding, LPWSTR *ObjUuid,\r
+                                          LPWSTR *Protseq, LPWSTR *NetworkAddr,\r
+                                          LPWSTR *Endpoint, LPWSTR *Options)\r
+{\r
+  WCHAR *data, *next;\r
+  static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};\r
+\r
+  TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),\r
+       ObjUuid, Protseq, NetworkAddr, Endpoint, Options);\r
+\r
+  if (ObjUuid) *ObjUuid = NULL;\r
+  if (Protseq) *Protseq = NULL;\r
+  if (NetworkAddr) *NetworkAddr = NULL;\r
+  if (Endpoint) *Endpoint = NULL;\r
+  if (Options) *Options = NULL;\r
+\r
+  data = StringBinding;\r
+\r
+  next = strchrW(data, '@');\r
+  if (next) {\r
+    if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);\r
+    data = next+1;\r
+  }\r
+\r
+  next = strchrW(data, ':');\r
+  if (next) {\r
+    if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);\r
+    data = next+1;\r
+  }\r
+\r
+  next = strchrW(data, '[');\r
+  if (next) {\r
+    WCHAR *close, *opt;\r
+\r
+    if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);\r
+    data = next+1;\r
+    close = strchrW(data, ']');\r
+    if (!close) goto fail;\r
+\r
+    /* tokenize options */\r
+    while (data < close) {\r
+      next = strchrW(data, ',');\r
+      if (!next || next > close) next = close;\r
+      /* FIXME: this is kind of inefficient */\r
+      opt = RPCRT4_strndupW(data, next - data);\r
+      data = next+1;\r
+\r
+      /* parse option */\r
+      next = strchrW(opt, '=');\r
+      if (!next) {\r
+        /* not an option, must be an endpoint */\r
+        if (*Endpoint) goto fail;\r
+        *Endpoint = opt;\r
+      } else {\r
+        if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {\r
+          /* endpoint option */\r
+          if (*Endpoint) goto fail;\r
+          *Endpoint = RPCRT4_strdupW(next+1);\r
+          HeapFree(GetProcessHeap(), 0, opt);\r
+        } else {\r
+          /* network option */\r
+          if (*Options) {\r
+            /* FIXME: this is kind of inefficient */\r
+            *Options = RPCRT4_strconcatW(*Options, opt);\r
+            HeapFree(GetProcessHeap(), 0, opt);\r
+          } else \r
+           *Options = opt;\r
+        }\r
+      }\r
+    }\r
+\r
+    data = close+1;\r
+    if (*data) goto fail;\r
+  } else if (NetworkAddr) \r
+    *NetworkAddr = RPCRT4_strdupW(data);\r
+\r
+  return RPC_S_OK;\r
+\r
+fail:\r
+  if (ObjUuid) RpcStringFreeW(ObjUuid);\r
+  if (Protseq) RpcStringFreeW(Protseq);\r
+  if (NetworkAddr) RpcStringFreeW(NetworkAddr);\r
+  if (Endpoint) RpcStringFreeW(Endpoint);\r
+  if (Options) RpcStringFreeW(Options);\r
+  return RPC_S_INVALID_STRING_BINDING;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcBindingFree (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )\r
+{\r
+  RPC_STATUS status;\r
+  TRACE("(%p) = %p\n", Binding, *Binding);\r
+  status = RPCRT4_DestroyBinding(*Binding);\r
+  if (status == RPC_S_OK) *Binding = 0;\r
+  return status;\r
+}\r
+  \r
+/***********************************************************************\r
+ *             RpcBindingVectorFree (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )\r
+{\r
+  RPC_STATUS status;\r
+  unsigned long c;\r
+\r
+  TRACE("(%p)\n", BindingVector);\r
+  for (c=0; c<(*BindingVector)->Count; c++) {\r
+    status = RpcBindingFree(&(*BindingVector)->BindingH[c]);\r
+  }\r
+  HeapFree(GetProcessHeap(), 0, *BindingVector);\r
+  *BindingVector = NULL;\r
+  return RPC_S_OK;\r
+}\r
+  \r
+/***********************************************************************\r
+ *             RpcBindingInqObject (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )\r
+{\r
+  RpcBinding* bind = (RpcBinding*)Binding;\r
+\r
+  TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));\r
+  memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));\r
+  return RPC_S_OK;\r
+}\r
+  \r
+/***********************************************************************\r
+ *             RpcBindingSetObject (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )\r
+{\r
+  RpcBinding* bind = (RpcBinding*)Binding;\r
+\r
+  TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));\r
+  if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;\r
+  return RPCRT4_SetBindingObject(Binding, ObjectUuid);\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcBindingFromStringBindingA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcBindingFromStringBindingA( unsigned char *StringBinding, RPC_BINDING_HANDLE* Binding )\r
+{\r
+  RPC_STATUS ret;\r
+  RpcBinding* bind = NULL;\r
+  unsigned char *ObjectUuid, *Protseq, *NetworkAddr, *Endpoint, *Options;\r
+  UUID Uuid;\r
+\r
+  TRACE("(%s,%p)\n", debugstr_a(StringBinding), Binding);\r
+\r
+  ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,\r
+                              &NetworkAddr, &Endpoint, &Options);\r
+  if (ret != RPC_S_OK) return ret;\r
+\r
+  ret = UuidFromStringA(ObjectUuid, &Uuid);\r
+\r
+  if (ret == RPC_S_OK)\r
+    ret = RPCRT4_CreateBindingA(&bind, FALSE, Protseq);\r
+  if (ret == RPC_S_OK)\r
+    ret = RPCRT4_SetBindingObject(bind, &Uuid);\r
+  if (ret == RPC_S_OK)\r
+    ret = RPCRT4_CompleteBindingA(bind, NetworkAddr, Endpoint, Options);\r
+\r
+  RpcStringFreeA((unsigned char**)&Options);\r
+  RpcStringFreeA((unsigned char**)&Endpoint);\r
+  RpcStringFreeA((unsigned char**)&NetworkAddr);\r
+  RpcStringFreeA((unsigned char**)&Protseq);\r
+  RpcStringFreeA((unsigned char**)&ObjectUuid);\r
+\r
+  if (ret == RPC_S_OK) \r
+    *Binding = (RPC_BINDING_HANDLE)bind;\r
+  else \r
+    RPCRT4_DestroyBinding(bind);\r
+\r
+  return ret;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcBindingFromStringBindingW (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcBindingFromStringBindingW( LPWSTR StringBinding, RPC_BINDING_HANDLE* Binding )\r
+{\r
+  RPC_STATUS ret;\r
+  RpcBinding* bind = NULL;\r
+  LPWSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;\r
+  UUID Uuid;\r
+\r
+  TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);\r
+\r
+  ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,\r
+                              &NetworkAddr, &Endpoint, &Options);\r
+  if (ret != RPC_S_OK) return ret;\r
+\r
+  ret = UuidFromStringW(ObjectUuid, &Uuid);\r
+\r
+  if (ret == RPC_S_OK)\r
+    ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);\r
+  if (ret == RPC_S_OK)\r
+    ret = RPCRT4_SetBindingObject(bind, &Uuid);\r
+  if (ret == RPC_S_OK)\r
+    ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);\r
+\r
+  RpcStringFreeW(&Options);\r
+  RpcStringFreeW(&Endpoint);\r
+  RpcStringFreeW(&NetworkAddr);\r
+  RpcStringFreeW(&Protseq);\r
+  RpcStringFreeW(&ObjectUuid);\r
+\r
+  if (ret == RPC_S_OK)\r
+    *Binding = (RPC_BINDING_HANDLE)bind;\r
+  else\r
+    RPCRT4_DestroyBinding(bind);\r
+\r
+  return ret;\r
+}\r
+  \r
+/***********************************************************************\r
+ *             RpcBindingToStringBindingA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, unsigned char** StringBinding )\r
+{\r
+  RPC_STATUS ret;\r
+  RpcBinding* bind = (RpcBinding*)Binding;\r
+  LPSTR ObjectUuid;\r
+\r
+  TRACE("(%p,%p)\n", Binding, StringBinding);\r
+\r
+  ret = UuidToStringA(&bind->ObjectUuid, (unsigned char**)&ObjectUuid);\r
+  if (ret != RPC_S_OK) return ret;\r
+\r
+  ret = RpcStringBindingComposeA(ObjectUuid, bind->Protseq, bind->NetworkAddr,\r
+                                 bind->Endpoint, NULL, StringBinding);\r
+\r
+  RpcStringFreeA((unsigned char**)&ObjectUuid);\r
+\r
+  return ret;\r
+}\r
+  \r
+/***********************************************************************\r
+ *             RpcBindingToStringBindingW (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, unsigned short** StringBinding )\r
+{\r
+  RPC_STATUS ret;\r
+  unsigned char *str = NULL;\r
+  TRACE("(%p,%p)\n", Binding, StringBinding);\r
+  ret = RpcBindingToStringBindingA(Binding, &str);\r
+  *StringBinding = RPCRT4_strdupAtoW(str);\r
+  RpcStringFreeA((unsigned char**)&str);\r
+  return ret;\r
+}\r
+\r
+/***********************************************************************\r
+ *             I_RpcBindingSetAsync (RPCRT4.@)\r
+ * NOTES\r
+ *  Exists in win9x and winNT, but with different number of arguments\r
+ *  (9x version has 3 arguments, NT has 2).\r
+ */\r
+RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)\r
+{\r
+  RpcBinding* bind = (RpcBinding*)Binding;\r
+\r
+  TRACE( "(%p,%p): stub\n", Binding, BlockingFn );\r
+\r
+  bind->BlockingFn = BlockingFn;\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcNetworkIsProtseqValidA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(unsigned char *protseq) {\r
+  UNICODE_STRING protseqW;\r
+\r
+  if (!protseq) return RPC_S_INVALID_RPC_PROTSEQ; /* ? */\r
+  \r
+  if (RtlCreateUnicodeStringFromAsciiz(&protseqW, protseq)) {\r
+    RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer);\r
+    RtlFreeUnicodeString(&protseqW);\r
+    return ret;\r
+  } else return RPC_S_OUT_OF_MEMORY;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcNetworkIsProtseqValidW (RPCRT4.@)\r
+ * \r
+ * Checks if the given protocol sequence is known by the RPC system.\r
+ * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.\r
+ *\r
+ * We currently support:\r
+ *   ncalrpc   local-only rpc over LPC (LPC is not really used)\r
+ *   ncacn_np  rpc over named pipes\r
+ */\r
+RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(LPWSTR protseq) {\r
+  static const WCHAR protseqsW[][15] = { \r
+    {'n','c','a','l','r','p','c',0},\r
+    {'n','c','a','c','n','_','n','p',0}\r
+  };\r
+  static const int count = sizeof(protseqsW) / sizeof(protseqsW[0]);\r
+  int i;\r
+\r
+  if (!protseq) return RPC_S_INVALID_RPC_PROTSEQ; /* ? */\r
+\r
+  for (i = 0; i < count; i++) {\r
+    if (!strcmpW(protseq, protseqsW[i])) return RPC_S_OK;\r
+  }\r
+  \r
+  FIXME("Unknown protseq %s - we probably need to implement it one day\n", debugstr_w(protseq));\r
+  return RPC_S_PROTSEQ_NOT_SUPPORTED;\r
+}\r
diff --git a/reactos/lib/rpcrt4/rpc_binding.h b/reactos/lib/rpcrt4/rpc_binding.h
new file mode 100644 (file)
index 0000000..0d7daa5
--- /dev/null
@@ -0,0 +1,86 @@
+/*\r
+ * RPC binding API\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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 __WINE_RPC_BINDING_H\r
+#define __WINE_RPC_BINDING_H\r
+\r
+#include "wine/rpcss_shared.h"\r
+\r
+typedef struct _RpcConnection\r
+{\r
+  struct _RpcConnection* Next;\r
+  struct _RpcBinding* Used;\r
+  BOOL server;\r
+  LPSTR Protseq;\r
+  LPSTR NetworkAddr;\r
+  LPSTR Endpoint;\r
+  HANDLE conn, thread;\r
+  OVERLAPPED ovl;\r
+  USHORT MaxTransmissionSize;\r
+  /* The active interface bound to server. */\r
+  RPC_SYNTAX_IDENTIFIER ActiveInterface;\r
+} RpcConnection;\r
+\r
+/* don't know what MS's structure looks like */\r
+typedef struct _RpcBinding\r
+{\r
+  DWORD refs;\r
+  struct _RpcBinding* Next;\r
+  BOOL server;\r
+  UUID ObjectUuid;\r
+  LPSTR Protseq;\r
+  LPSTR NetworkAddr;\r
+  LPSTR Endpoint;\r
+  RPC_BLOCKING_FN BlockingFn;\r
+  ULONG ServerTid;\r
+  RpcConnection* FromConn;\r
+} RpcBinding;\r
+\r
+LPSTR RPCRT4_strndupA(LPCSTR src, INT len);\r
+LPWSTR RPCRT4_strndupW(LPWSTR src, INT len);\r
+LPSTR RPCRT4_strdupWtoA(LPWSTR src);\r
+LPWSTR RPCRT4_strdupAtoW(LPSTR src);\r
+void RPCRT4_strfree(LPSTR src);\r
+\r
+#define RPCRT4_strdupA(x) RPCRT4_strndupA((x),-1)\r
+#define RPCRT4_strdupW(x) RPCRT4_strndupW((x),-1)\r
+\r
+RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions, RpcBinding* Binding);\r
+RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection);\r
+RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection);\r
+RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection);\r
+RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection);\r
+\r
+RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq);\r
+RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq);\r
+RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr,  LPSTR Endpoint,  LPSTR NetworkOptions);\r
+RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions);\r
+RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint);\r
+RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid);\r
+RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection);\r
+RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding);\r
+RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding);\r
+RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection, PRPC_SYNTAX_IDENTIFIER TransferSyntax, PRPC_SYNTAX_IDENTIFIER InterfaceId);\r
+RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection);\r
+BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply);\r
+HANDLE RPCRT4_GetMasterMutex(void);\r
+HANDLE RPCRT4_RpcssNPConnect(void);\r
+\r
+#endif\r
diff --git a/reactos/lib/rpcrt4/rpc_defs.h b/reactos/lib/rpcrt4/rpc_defs.h
new file mode 100644 (file)
index 0000000..f2fc382
--- /dev/null
@@ -0,0 +1,183 @@
+/*\r
+ * RPC definitions\r
+ *\r
+ * Copyright 2001-2002 Ove Kåven, TransGaming Technologies\r
+ * Copyright 2004 Filip Navara\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 __WINE_RPC_DEFS_H\r
+#define __WINE_RPC_DEFS_H\r
+\r
+/* info from http://www.microsoft.com/msj/0398/dcomtextfigs.htm */\r
+\r
+typedef struct\r
+{\r
+  unsigned char rpc_ver;          /* RPC major version (5) */\r
+  unsigned char rpc_ver_minor;    /* RPC minor version (0) */\r
+  unsigned char ptype;            /* Packet type (PKT_*) */\r
+  unsigned char flags;\r
+  unsigned char drep[4];          /* Data representation */\r
+  unsigned short frag_len;        /* Data size in bytes including header and tail. */\r
+  unsigned short auth_len;        /* Authentication length  */\r
+  unsigned long call_id;          /* Call identifier. */\r
+} RpcPktCommonHdr;\r
+\r
+typedef struct\r
+{\r
+  RpcPktCommonHdr common;\r
+  unsigned long alloc_hint;       /* Data size in bytes excluding header and tail. */\r
+  unsigned short context_id;      /* Presentation context identifier */\r
+  unsigned short opnum;\r
+} RpcPktRequestHdr;\r
+\r
+typedef struct\r
+{\r
+  RpcPktCommonHdr common;\r
+  unsigned long alloc_hint;       /* Data size in bytes excluding header and tail. */\r
+  unsigned short context_id;      /* Presentation context identifier */\r
+  unsigned char cancel_count;\r
+  unsigned char reserved;\r
+} RpcPktResponseHdr;\r
+\r
+typedef struct\r
+{\r
+  RpcPktCommonHdr common;\r
+  unsigned long alloc_hint;       /* Data size in bytes excluding header and tail. */\r
+  unsigned short context_id;      /* Presentation context identifier */\r
+  unsigned char alert_count;      /* Pending alert count */\r
+  unsigned char padding[3];       /* Force alignment! */\r
+  unsigned long status;           /* Runtime fault code (RPC_STATUS) */\r
+  unsigned long reserved;\r
+} RpcPktFaultHdr;\r
+\r
+typedef struct\r
+{\r
+  RpcPktCommonHdr common;\r
+  unsigned short max_tsize;       /* Maximum transmission fragment size */\r
+  unsigned short max_rsize;       /* Maximum receive fragment size */\r
+  unsigned long assoc_gid;        /* Associated group id */\r
+  unsigned char num_elements;     /* Number of elements */\r
+  unsigned char padding[3];       /* Force alignment! */\r
+  unsigned short context_id;      /* Presentation context identifier */\r
+  unsigned char num_syntaxes;     /* Number of syntaxes */\r
+  RPC_SYNTAX_IDENTIFIER abstract;\r
+  RPC_SYNTAX_IDENTIFIER transfer;\r
+} RpcPktBindHdr;\r
+\r
+#include "pshpack1.h"\r
+typedef struct\r
+{\r
+  unsigned short length;  /* Length of the string including null terminator */\r
+  char string[1];         /* String data in single byte, null terminated form */\r
+} RpcAddressString;\r
+#include "poppack.h"\r
+\r
+typedef struct\r
+{\r
+  unsigned char padding1[2];       /* Force alignment! */\r
+  unsigned char num_results;       /* Number of results */\r
+  unsigned char padding2[3];       /* Force alignment! */\r
+  struct {\r
+    unsigned short result;\r
+    unsigned short reason;\r
+  } results[1];\r
+} RpcResults;\r
+\r
+typedef struct\r
+{\r
+  RpcPktCommonHdr common;\r
+  unsigned short max_tsize;       /* Maximum transmission fragment size */\r
+  unsigned short max_rsize;       /* Maximum receive fragment size */\r
+  unsigned long assoc_gid;        /* Associated group id */\r
+  /* \r
+   * Following this header are these fields:\r
+   *   RpcAddressString server_address;\r
+   *   RpcResults results;\r
+   *   RPC_SYNTAX_IDENTIFIER transfer;\r
+   */\r
+} RpcPktBindAckHdr;\r
+\r
+typedef struct\r
+{\r
+  RpcPktCommonHdr common;\r
+  unsigned short reject_reason;\r
+  unsigned char protocols_count;\r
+  struct {\r
+    unsigned char rpc_ver;\r
+    unsigned char rpc_ver_minor;\r
+  } protocols[1];\r
+} RpcPktBindNAckHdr;\r
+\r
+/* Union representing all possible packet headers */\r
+typedef union\r
+{\r
+  RpcPktCommonHdr common;\r
+  RpcPktRequestHdr request;\r
+  RpcPktResponseHdr response;\r
+  RpcPktFaultHdr fault;\r
+  RpcPktBindHdr bind;\r
+  RpcPktBindAckHdr bind_ack;\r
+  RpcPktBindNAckHdr bind_nack;\r
+} RpcPktHdr;\r
+\r
+#define RPC_VER_MAJOR             5\r
+#define RPC_VER_MINOR             0\r
+\r
+#define RPC_FLG_FIRST             1\r
+#define RPC_FLG_LAST              2\r
+#define RPC_FLG_OBJECT_UUID    0x80\r
+\r
+#define RPC_MIN_PACKET_SIZE  0x1000\r
+#define RPC_MAX_PACKET_SIZE  0x16D0\r
+\r
+#define PKT_REQUEST             0\r
+#define PKT_PING                1\r
+#define PKT_RESPONSE            2\r
+#define PKT_FAULT               3\r
+#define PKT_WORKING             4\r
+#define PKT_NOCALL              5\r
+#define PKT_REJECT              6\r
+#define PKT_ACK                 7\r
+#define PKT_CL_CANCEL           8\r
+#define PKT_FACK                9\r
+#define PKT_CANCEL_ACK         10\r
+#define PKT_BIND               11\r
+#define PKT_BIND_ACK           12\r
+#define PKT_BIND_NACK          13\r
+#define PKT_ALTER_CONTEXT      14\r
+#define PKT_ALTER_CONTEXT_RESP 15\r
+#define PKT_SHUTDOWN           17\r
+#define PKT_CO_CANCEL          18\r
+#define PKT_ORPHANED           19\r
+\r
+#define RESULT_ACCEPT           0\r
+\r
+#define NO_REASON               0\r
+\r
+#define NCADG_IP_UDP   0x08\r
+#define NCACN_IP_TCP   0x07\r
+#define NCADG_IPX      0x0E\r
+#define NCACN_SPX      0x0C\r
+#define NCACN_NB_NB    0x12\r
+#define NCACN_NB_IPX   0x0D\r
+#define NCACN_DNET_NSP 0x04\r
+#define NCACN_HTTP     0x1F\r
+\r
+/* FreeDCE: TWR_C_FLR_PROT_ID_IP */\r
+#define TWR_IP 0x09\r
+\r
+#endif  /* __WINE_RPC_DEFS_H */\r
diff --git a/reactos/lib/rpcrt4/rpc_epmap.c b/reactos/lib/rpcrt4/rpc_epmap.c
new file mode 100644 (file)
index 0000000..1986ec6
--- /dev/null
@@ -0,0 +1,247 @@
+/*\r
+ * RPC endpoint mapper\r
+ *\r
+ * Copyright 2002 Greg Turner\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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
+ * TODO:\r
+ *  - actually do things right\r
+ */\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+#include "winreg.h"\r
+\r
+#include "rpc.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+#include "rpc_binding.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+/* The "real" RPC portmapper endpoints that I know of are:\r
+ *\r
+ *  ncadg_ip_udp: 135\r
+ *  ncacn_ip_tcp: 135\r
+ *  ncacn_np: \\pipe\epmapper (?)\r
+ *  ncalrpc: epmapper\r
+ *\r
+ * If the user's machine ran a DCE RPC daemon, it would\r
+ * probably be possible to connect to it, but there are many\r
+ * reasons not to, like:\r
+ *  - the user probably does *not* run one, and probably\r
+ *    shouldn't be forced to run one just for local COM\r
+ *  - very few Unix systems use DCE RPC... if they run a RPC\r
+ *    daemon at all, it's usually Sun RPC\r
+ *  - DCE RPC registrations are persistent and saved on disk,\r
+ *    while MS-RPC registrations are documented as non-persistent\r
+ *    and stored only in RAM, and auto-destroyed when the process\r
+ *    dies (something DCE RPC can't do)\r
+ *\r
+ * Of course, if the user *did* want to run a DCE RPC daemon anyway,\r
+ * there would be interoperability advantages, like the possibility\r
+ * of running a fully functional DCOM server using Wine...\r
+ */\r
+\r
+/***********************************************************************\r
+ *             RpcEpRegisterA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,\r
+                                  UUID_VECTOR *UuidVector, unsigned char *Annotation )\r
+{\r
+  RPCSS_NP_MESSAGE msg;\r
+  RPCSS_NP_REPLY reply;\r
+  char *vardata_payload, *vp;\r
+  PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;\r
+  unsigned long c;\r
+  RPC_STATUS rslt = RPC_S_OK;\r
+\r
+  TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a(Annotation));\r
+  TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));\r
+  for (c=0; c<BindingVector->Count; c++) {\r
+    RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]);\r
+    TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq));\r
+    TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint));\r
+  }\r
+  if (UuidVector) {\r
+    for (c=0; c<UuidVector->Count; c++)\r
+      TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c]));\r
+  }\r
+\r
+  /* FIXME: Do something with annotation. */\r
+\r
+  /* construct the message to rpcss */\r
+  msg.message_type = RPCSS_NP_MESSAGE_TYPEID_REGISTEREPMSG;\r
+  msg.message.registerepmsg.iface = If->InterfaceId;\r
+  msg.message.registerepmsg.no_replace = 0;\r
+\r
+  msg.message.registerepmsg.object_count = (UuidVector) ? UuidVector->Count : 0;\r
+  msg.message.registerepmsg.binding_count = BindingVector->Count;\r
+\r
+  /* calculate vardata payload size */\r
+  msg.vardata_payload_size = msg.message.registerepmsg.object_count * sizeof(UUID);\r
+  for (c=0; c < msg.message.registerepmsg.binding_count; c++) {\r
+    RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]);\r
+    msg.vardata_payload_size += strlen(bind->Protseq) + 1;\r
+    msg.vardata_payload_size += strlen(bind->Endpoint) + 1;\r
+  }\r
+\r
+  /* allocate the payload buffer */\r
+  vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size);\r
+  if (!vardata_payload)\r
+    return RPC_S_OUT_OF_MEMORY;\r
+\r
+  /* populate the payload data */\r
+  for (c=0; c < msg.message.registerepmsg.object_count; c++) {\r
+    CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID));\r
+    vp += sizeof(UUID);\r
+  }\r
+\r
+  for (c=0; c < msg.message.registerepmsg.binding_count; c++) {\r
+    RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]);\r
+    unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1;\r
+    CopyMemory(vp, bind->Protseq, pslen);\r
+    vp += pslen;\r
+    CopyMemory(vp, bind->Endpoint, eplen);\r
+    vp += eplen;\r
+  }\r
+\r
+  /* send our request */\r
+  if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply))\r
+    rslt = RPC_S_OUT_OF_MEMORY;\r
+\r
+  /* free the payload buffer */\r
+  LocalFree(vardata_payload);\r
+\r
+  return rslt;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcEpUnregister (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,\r
+                                   UUID_VECTOR *UuidVector )\r
+{\r
+  RPCSS_NP_MESSAGE msg;\r
+  RPCSS_NP_REPLY reply;\r
+  char *vardata_payload, *vp;\r
+  PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;\r
+  unsigned long c;\r
+  RPC_STATUS rslt = RPC_S_OK;\r
+\r
+  TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector);\r
+  TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));\r
+  for (c=0; c<BindingVector->Count; c++) {\r
+    RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]);\r
+    TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq));\r
+    TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint));\r
+  }\r
+  if (UuidVector) {\r
+    for (c=0; c<UuidVector->Count; c++)\r
+      TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c]));\r
+  }\r
+\r
+  /* construct the message to rpcss */\r
+  msg.message_type = RPCSS_NP_MESSAGE_TYPEID_UNREGISTEREPMSG;\r
+  msg.message.unregisterepmsg.iface = If->InterfaceId;\r
+\r
+  msg.message.unregisterepmsg.object_count = (UuidVector) ? UuidVector->Count : 0;\r
+  msg.message.unregisterepmsg.binding_count = BindingVector->Count;\r
+\r
+  /* calculate vardata payload size */\r
+  msg.vardata_payload_size = msg.message.unregisterepmsg.object_count * sizeof(UUID);\r
+  for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) {\r
+    RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]);\r
+    msg.vardata_payload_size += strlen(bind->Protseq) + 1;\r
+    msg.vardata_payload_size += strlen(bind->Endpoint) + 1;\r
+  }\r
+\r
+  /* allocate the payload buffer */\r
+  vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size);\r
+  if (!vardata_payload)\r
+    return RPC_S_OUT_OF_MEMORY;\r
+\r
+  /* populate the payload data */\r
+  for (c=0; c < msg.message.unregisterepmsg.object_count; c++) {\r
+    CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID));\r
+    vp += sizeof(UUID);\r
+  }\r
+\r
+  for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) {\r
+    RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]);\r
+    unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1;\r
+    CopyMemory(vp, bind->Protseq, pslen);\r
+    vp += pslen;\r
+    CopyMemory(vp, bind->Endpoint, eplen);\r
+    vp += eplen;\r
+  }\r
+\r
+  /* send our request */\r
+  if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply))\r
+    rslt = RPC_S_OUT_OF_MEMORY;\r
+\r
+  /* free the payload buffer */\r
+  LocalFree(vardata_payload);\r
+\r
+  return rslt;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcEpResolveBinding (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec )\r
+{\r
+  RPCSS_NP_MESSAGE msg;\r
+  RPCSS_NP_REPLY reply;\r
+  PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec;\r
+  RpcBinding* bind = (RpcBinding*)Binding;\r
+\r
+  TRACE("(%p,%p)\n", Binding, IfSpec);\r
+  TRACE(" protseq=%s\n", debugstr_a(bind->Protseq));\r
+  TRACE(" obj=%s\n", debugstr_guid(&bind->ObjectUuid));\r
+  TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));\r
+\r
+  /* FIXME: totally untested */\r
+\r
+  /* just return for fully bound handles */\r
+  if (bind->Endpoint && (bind->Endpoint[0] != '\0'))\r
+    return RPC_S_OK;\r
+\r
+  /* construct the message to rpcss */\r
+  msg.message_type = RPCSS_NP_MESSAGE_TYPEID_RESOLVEEPMSG;\r
+  msg.message.resolveepmsg.iface = If->InterfaceId;\r
+  msg.message.resolveepmsg.object = bind->ObjectUuid;\r
\r
+  msg.vardata_payload_size = strlen(bind->Protseq) + 1;\r
+\r
+  /* send the message */\r
+  if (!RPCRT4_RPCSSOnDemandCall(&msg, bind->Protseq, &reply))\r
+    return RPC_S_OUT_OF_MEMORY;\r
+\r
+  /* empty-string result means not registered */\r
+  if (reply.as_string[0] == '\0')\r
+    return EPT_S_NOT_REGISTERED;\r
+  \r
+  /* otherwise we fully bind the handle & return RPC_S_OK */\r
+  return RPCRT4_ResolveBinding(Binding, reply.as_string);\r
+}\r
diff --git a/reactos/lib/rpcrt4/rpc_message.c b/reactos/lib/rpcrt4/rpc_message.c
new file mode 100644 (file)
index 0000000..6a2b836
--- /dev/null
@@ -0,0 +1,612 @@
+/*\r
+ * RPC messages\r
+ *\r
+ * Copyright 2001-2002 Ove Kåven, TransGaming Technologies\r
+ * Copyright 2004 Filip Navara\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
+ * TODO:\r
+ *  - figure out whether we *really* got this right\r
+ *  - check for errors and throw exceptions\r
+ */\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+#include "winreg.h"\r
+\r
+#include "rpc.h"\r
+#include "rpcndr.h"\r
+#include "rpcdcep.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+#include "rpc_binding.h"\r
+#include "rpc_misc.h"\r
+#include "rpc_defs.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+DWORD RPCRT4_GetHeaderSize(RpcPktHdr *Header)\r
+{\r
+  static const DWORD header_sizes[] = {\r
+    sizeof(Header->request), 0, sizeof(Header->response),\r
+    sizeof(Header->fault), 0, 0, 0, 0, 0, 0, 0, sizeof(Header->bind),\r
+    sizeof(Header->bind_ack), sizeof(Header->bind_nack),\r
+    0, 0, 0, 0, 0\r
+  };\r
+  ULONG ret = 0;\r
+  \r
+  if (Header->common.ptype < sizeof(header_sizes) / sizeof(header_sizes[0])) {\r
+    ret = header_sizes[Header->common.ptype];\r
+    if (ret == 0)\r
+      FIXME("unhandled packet type\n");\r
+    if (Header->common.flags & RPC_FLG_OBJECT_UUID)\r
+      ret += sizeof(UUID);\r
+  } else {\r
+    TRACE("invalid packet type\n");\r
+  }\r
+\r
+  return ret;\r
+}\r
+\r
+VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType,\r
+                              unsigned long DataRepresentation)\r
+{\r
+  Header->common.rpc_ver = RPC_VER_MAJOR;\r
+  Header->common.rpc_ver_minor = RPC_VER_MINOR;\r
+  Header->common.ptype = PacketType;\r
+  Header->common.drep[0] = LOBYTE(LOWORD(DataRepresentation));\r
+  Header->common.drep[1] = HIBYTE(LOWORD(DataRepresentation));\r
+  Header->common.drep[2] = LOBYTE(HIWORD(DataRepresentation));\r
+  Header->common.drep[3] = HIBYTE(HIWORD(DataRepresentation));\r
+  Header->common.auth_len = 0;\r
+  Header->common.call_id = 1;\r
+  Header->common.flags = 0;\r
+  /* Flags and fragment length are computed in RPCRT4_Send. */\r
+}                              \r
+\r
+RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation,\r
+                                     unsigned long BufferLength,\r
+                                     unsigned short ProcNum,\r
+                                     UUID *ObjectUuid)\r
+{\r
+  RpcPktHdr *header;\r
+  BOOL has_object;\r
+  RPC_STATUS status;\r
+\r
+  has_object = (ObjectUuid != NULL && !UuidIsNil(ObjectUuid, &status));\r
+  header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
+                     sizeof(header->request) + (has_object ? sizeof(UUID) : 0));\r
+  if (header == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  RPCRT4_BuildCommonHeader(header, PKT_REQUEST, DataRepresentation);\r
+  header->common.frag_len = sizeof(header->request);\r
+  header->request.alloc_hint = BufferLength;\r
+  header->request.context_id = 0;\r
+  header->request.opnum = ProcNum;\r
+  if (has_object) {\r
+    header->common.flags |= RPC_FLG_OBJECT_UUID;\r
+    header->common.frag_len += sizeof(UUID);\r
+    memcpy(&header->request + 1, ObjectUuid, sizeof(UUID));\r
+  }\r
+\r
+  return header;\r
+}\r
+\r
+RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation,\r
+                                      unsigned long BufferLength)\r
+{\r
+  RpcPktHdr *header;\r
+\r
+  header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->response));\r
+  if (header == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  RPCRT4_BuildCommonHeader(header, PKT_RESPONSE, DataRepresentation);\r
+  header->common.frag_len = sizeof(header->response);\r
+  header->response.alloc_hint = BufferLength;\r
+\r
+  return header;\r
+}\r
+\r
+RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation,\r
+                                   RPC_STATUS Status)\r
+{\r
+  RpcPktHdr *header;\r
+\r
+  header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->fault));\r
+  if (header == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  RPCRT4_BuildCommonHeader(header, PKT_FAULT, DataRepresentation);\r
+  header->common.frag_len = sizeof(header->fault);\r
+  header->fault.status = Status;\r
+\r
+  return header;\r
+}\r
+\r
+RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation,\r
+                                  unsigned short MaxTransmissionSize,\r
+                                  unsigned short MaxReceiveSize,\r
+                                  RPC_SYNTAX_IDENTIFIER *AbstractId,\r
+                                  RPC_SYNTAX_IDENTIFIER *TransferId)\r
+{\r
+  RpcPktHdr *header;\r
+\r
+  header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind));\r
+  if (header == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  RPCRT4_BuildCommonHeader(header, PKT_BIND, DataRepresentation);\r
+  header->common.frag_len = sizeof(header->bind);\r
+  header->bind.max_tsize = MaxTransmissionSize;\r
+  header->bind.max_rsize = MaxReceiveSize;\r
+  header->bind.num_elements = 1;\r
+  header->bind.num_syntaxes = 1;\r
+  memcpy(&header->bind.abstract, AbstractId, sizeof(RPC_SYNTAX_IDENTIFIER));\r
+  memcpy(&header->bind.transfer, TransferId, sizeof(RPC_SYNTAX_IDENTIFIER));\r
+\r
+  return header;\r
+}\r
+\r
+RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation,\r
+                                      unsigned char RpcVersion,\r
+                                      unsigned char RpcVersionMinor)\r
+{\r
+  RpcPktHdr *header;\r
+\r
+  header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind_nack));\r
+  if (header == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  RPCRT4_BuildCommonHeader(header, PKT_BIND_NACK, DataRepresentation);\r
+  header->common.frag_len = sizeof(header->bind_nack);\r
+  header->bind_nack.protocols_count = 1;\r
+  header->bind_nack.protocols[0].rpc_ver = RpcVersion;\r
+  header->bind_nack.protocols[0].rpc_ver_minor = RpcVersionMinor;\r
+\r
+  return header;\r
+}\r
+\r
+RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation,\r
+                                     unsigned short MaxTransmissionSize,\r
+                                     unsigned short MaxReceiveSize,\r
+                                     LPSTR ServerAddress,\r
+                                     unsigned long Result,\r
+                                     unsigned long Reason,\r
+                                     RPC_SYNTAX_IDENTIFIER *TransferId)\r
+{\r
+  RpcPktHdr *header;\r
+  unsigned long header_size;\r
+  RpcAddressString *server_address;\r
+  RpcResults *results;\r
+  RPC_SYNTAX_IDENTIFIER *transfer_id;\r
+\r
+  header_size = sizeof(header->bind_ack) + sizeof(RpcResults) +\r
+                sizeof(RPC_SYNTAX_IDENTIFIER) + sizeof(RpcAddressString) +\r
+                strlen(ServerAddress);\r
+\r
+  header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, header_size);\r
+  if (header == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  RPCRT4_BuildCommonHeader(header, PKT_BIND_ACK, DataRepresentation);\r
+  header->common.frag_len = header_size;\r
+  header->bind_ack.max_tsize = MaxTransmissionSize;\r
+  header->bind_ack.max_rsize = MaxReceiveSize;\r
+  server_address = (RpcAddressString*)(&header->bind_ack + 1);\r
+  server_address->length = strlen(ServerAddress) + 1;\r
+  strcpy(server_address->string, ServerAddress);\r
+  results = (RpcResults*)((ULONG_PTR)server_address + sizeof(RpcAddressString) + server_address->length - 1);\r
+  results->num_results = 1;\r
+  results->results[0].result = Result;\r
+  results->results[0].reason = Reason;\r
+  transfer_id = (RPC_SYNTAX_IDENTIFIER*)(results + 1);\r
+  memcpy(transfer_id, TransferId, sizeof(RPC_SYNTAX_IDENTIFIER));\r
+\r
+  return header;\r
+}\r
+\r
+VOID RPCRT4_FreeHeader(RpcPktHdr *Header)\r
+{\r
+  HeapFree(GetProcessHeap(), 0, Header);\r
+}\r
+\r
+/***********************************************************************\r
+ *           RPCRT4_Send (internal)\r
+ * \r
+ * Transmit a packet over connection in acceptable fragments.\r
+ */\r
+RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header,\r
+                       void *Buffer, unsigned int BufferLength)\r
+{\r
+  PUCHAR buffer_pos;\r
+  DWORD hdr_size, count;\r
+\r
+  buffer_pos = Buffer;\r
+  /* The packet building functions save the packet header size, so we can use it. */\r
+  hdr_size = Header->common.frag_len;\r
+  Header->common.flags |= RPC_FLG_FIRST;\r
+  Header->common.flags &= ~RPC_FLG_LAST;\r
+  while (!(Header->common.flags & RPC_FLG_LAST)) {    \r
+    /* decide if we need to split the packet into fragments */\r
+    if ((BufferLength + hdr_size) <= Connection->MaxTransmissionSize) {\r
+      Header->common.flags |= RPC_FLG_LAST;\r
+      Header->common.frag_len = BufferLength + hdr_size;\r
+    } else {\r
+      Header->common.frag_len = Connection->MaxTransmissionSize;\r
+      buffer_pos += Header->common.frag_len - hdr_size;\r
+      BufferLength -= Header->common.frag_len - hdr_size;\r
+    }\r
+\r
+    /* transmit packet header */\r
+    if (!WriteFile(Connection->conn, Header, hdr_size, &count, NULL)) {\r
+      WARN("WriteFile failed with error %ld\n", GetLastError());\r
+      return GetLastError();\r
+    }\r
+\r
+    /* fragment consisted of header only and is the last one */\r
+    if (hdr_size == Header->common.frag_len &&\r
+        Header->common.flags & RPC_FLG_LAST) {\r
+      return RPC_S_OK;\r
+    }\r
+\r
+    /* send the fragment data */\r
+    if (!WriteFile(Connection->conn, buffer_pos, Header->common.frag_len - hdr_size, &count, NULL)) {\r
+      WARN("WriteFile failed with error %ld\n", GetLastError());\r
+      return GetLastError();\r
+    }\r
+\r
+    Header->common.flags &= ~RPC_FLG_FIRST;\r
+  }\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *           RPCRT4_Receive (internal)\r
+ * \r
+ * Receive a packet from connection and merge the fragments.\r
+ */\r
+RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,\r
+                          PRPC_MESSAGE pMsg)\r
+{\r
+  RPC_STATUS status;\r
+  DWORD dwRead, hdr_length;\r
+  unsigned short first_flag;\r
+  unsigned long data_length;\r
+  unsigned long buffer_length;\r
+  unsigned char *buffer_ptr;\r
+  RpcPktCommonHdr common_hdr;\r
+\r
+  *Header = NULL;\r
+\r
+  TRACE("(%p, %p, %p)\n", Connection, Header, pMsg);\r
+\r
+  /* read packet common header */\r
+  if (!ReadFile(Connection->conn, &common_hdr, sizeof(common_hdr), &dwRead, NULL)) {\r
+    if (GetLastError() != ERROR_MORE_DATA) {\r
+      WARN("ReadFile failed with error %ld\n", GetLastError());\r
+      status = RPC_S_PROTOCOL_ERROR;\r
+      goto fail;\r
+    }\r
+  }\r
+  if (dwRead != sizeof(common_hdr)) {\r
+    status = RPC_S_PROTOCOL_ERROR;\r
+    goto fail;\r
+  }\r
+\r
+  /* verify if the header really makes sense */\r
+  if (common_hdr.rpc_ver != RPC_VER_MAJOR ||\r
+      common_hdr.rpc_ver_minor != RPC_VER_MINOR) {\r
+    WARN("unhandled packet version\n");\r
+    status = RPC_S_PROTOCOL_ERROR;\r
+    goto fail;\r
+  }\r
+\r
+  hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr);\r
+  if (hdr_length == 0) {\r
+    status = RPC_S_PROTOCOL_ERROR;\r
+    goto fail;\r
+  }\r
+\r
+  *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length);\r
+  memcpy(*Header, &common_hdr, sizeof(common_hdr));\r
+\r
+  /* read the rest of packet header */\r
+  if (!ReadFile(Connection->conn, &(*Header)->common + 1,\r
+                hdr_length - sizeof(common_hdr), &dwRead, NULL)) {\r
+    if (GetLastError() != ERROR_MORE_DATA) {\r
+      WARN("ReadFile failed with error %ld\n", GetLastError());\r
+      status = RPC_S_PROTOCOL_ERROR;\r
+      goto fail;\r
+    }\r
+  }\r
+  if (dwRead != hdr_length - sizeof(common_hdr)) {\r
+    status = RPC_S_PROTOCOL_ERROR;\r
+    goto fail;\r
+  }\r
+\r
+  /* read packet body */\r
+  switch (common_hdr.ptype) {\r
+  case PKT_RESPONSE:\r
+    pMsg->BufferLength = (*Header)->response.alloc_hint;\r
+    break;\r
+  case PKT_REQUEST:\r
+    pMsg->BufferLength = (*Header)->request.alloc_hint;\r
+    break;\r
+  default:\r
+    pMsg->BufferLength = common_hdr.frag_len - hdr_length;\r
+  }\r
+  status = I_RpcGetBuffer(pMsg);\r
+  if (status != RPC_S_OK) goto fail;\r
+\r
+  first_flag = RPC_FLG_FIRST;\r
+  buffer_length = 0;\r
+  buffer_ptr = pMsg->Buffer;\r
+  while (buffer_length < pMsg->BufferLength)\r
+  {\r
+    data_length = (*Header)->common.frag_len - hdr_length;\r
+    if (((*Header)->common.flags & RPC_FLG_FIRST) != first_flag ||\r
+        data_length + buffer_length > pMsg->BufferLength) {\r
+      TRACE("invalid packet flags or buffer length\n");\r
+      status = RPC_S_PROTOCOL_ERROR;\r
+      goto fail;\r
+    }\r
+\r
+    if (data_length == 0) dwRead = 0; else\r
+    if (!ReadFile(Connection->conn, buffer_ptr, data_length, &dwRead, NULL)) {\r
+      if (GetLastError() != ERROR_MORE_DATA) {\r
+        WARN("ReadFile failed with error %ld\n", GetLastError());\r
+        status = RPC_S_PROTOCOL_ERROR;\r
+        goto fail;\r
+      }\r
+    }\r
+    if (dwRead != data_length) {\r
+      status = RPC_S_PROTOCOL_ERROR;\r
+      goto fail;\r
+    }\r
+\r
+    if (buffer_length == pMsg->BufferLength &&\r
+        ((*Header)->common.flags & RPC_FLG_LAST) == 0) {\r
+      status = RPC_S_PROTOCOL_ERROR;\r
+      goto fail;\r
+    }\r
+\r
+    buffer_length += data_length;\r
+    if (buffer_length < pMsg->BufferLength) {\r
+      TRACE("next header\n");\r
+\r
+      /* read the header of next packet */\r
+      if (!ReadFile(Connection->conn, *Header, hdr_length, &dwRead, NULL)) {\r
+        if (GetLastError() != ERROR_MORE_DATA) {\r
+          WARN("ReadFile failed with error %ld\n", GetLastError());\r
+          status = GetLastError();\r
+          goto fail;\r
+        }\r
+      }\r
+      if (dwRead != hdr_length) {\r
+        WARN("invalid packet header size (%ld)\n", dwRead);\r
+        status = RPC_S_PROTOCOL_ERROR;\r
+        goto fail;\r
+      }\r
+\r
+      buffer_ptr += data_length;\r
+      first_flag = 0;\r
+    }\r
+  }\r
+\r
+  /* success */\r
+  status = RPC_S_OK;\r
+\r
+fail:\r
+  if (status != RPC_S_OK && *Header) {\r
+    RPCRT4_FreeHeader(*Header);\r
+    *Header = NULL;\r
+  }\r
+  return status;\r
+}\r
+\r
+/***********************************************************************\r
+ *           I_RpcGetBuffer [RPCRT4.@]\r
+ */\r
+RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)\r
+{\r
+  RpcBinding* bind = (RpcBinding*)pMsg->Handle;\r
+\r
+  TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);\r
+  /* FIXME: pfnAllocate? */\r
+  if (bind->server) {\r
+    /* it turns out that the original buffer data must still be available\r
+     * while the RPC server is marshalling a reply, so we should not deallocate\r
+     * it, we'll leave deallocating the original buffer to the RPC server */\r
+    pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength);\r
+  } else {\r
+    if (pMsg->Buffer)\r
+        HeapFree(GetProcessHeap(), 0, pMsg->Buffer);\r
+    pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength);\r
+  }\r
+  TRACE("Buffer=%p\n", pMsg->Buffer);\r
+  /* FIXME: which errors to return? */\r
+  return pMsg->Buffer ? S_OK : E_OUTOFMEMORY;\r
+}\r
+\r
+/***********************************************************************\r
+ *           I_RpcFreeBuffer [RPCRT4.@]\r
+ */\r
+RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)\r
+{\r
+  TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer);\r
+  /* FIXME: pfnFree? */\r
+  if (pMsg->Buffer != NULL) {\r
+    HeapFree(GetProcessHeap(), 0, pMsg->Buffer);\r
+  }\r
+  pMsg->Buffer = NULL;\r
+  return S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *           I_RpcSend [RPCRT4.@]\r
+ */\r
+RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)\r
+{\r
+  RpcBinding* bind = (RpcBinding*)pMsg->Handle;\r
+  RpcConnection* conn;\r
+  RPC_CLIENT_INTERFACE* cif = NULL;\r
+  RPC_SERVER_INTERFACE* sif = NULL;\r
+  RPC_STATUS status;\r
+  RpcPktHdr *hdr;\r
+\r
+  TRACE("(%p)\n", pMsg);\r
+  if (!bind) return RPC_S_INVALID_BINDING;\r
+\r
+  if (bind->server) {\r
+    sif = pMsg->RpcInterfaceInformation;\r
+    if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */\r
+    status = RPCRT4_OpenBinding(bind, &conn, &sif->TransferSyntax,\r
+                                &sif->InterfaceId);\r
+  } else {\r
+    cif = pMsg->RpcInterfaceInformation;\r
+    if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */\r
+    status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax,\r
+                                &cif->InterfaceId);\r
+  }\r
+\r
+  if (status != RPC_S_OK) return status;\r
+\r
+  if (bind->server) {\r
+    if (pMsg->RpcFlags & WINE_RPCFLAG_EXCEPTION) {\r
+      hdr = RPCRT4_BuildFaultHeader(pMsg->DataRepresentation,\r
+                                    RPC_S_CALL_FAILED);\r
+    } else {\r
+      hdr = RPCRT4_BuildResponseHeader(pMsg->DataRepresentation,\r
+                                       pMsg->BufferLength);\r
+    }\r
+  } else {\r
+    hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation,\r
+                                    pMsg->BufferLength, pMsg->ProcNum,\r
+                                    &bind->ObjectUuid);\r
+  }\r
+\r
+  status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength);\r
+\r
+  RPCRT4_FreeHeader(hdr);\r
+\r
+  /* success */\r
+  if (!bind->server) {\r
+    /* save the connection, so the response can be read from it */\r
+    pMsg->ReservedForRuntime = conn;\r
+    return RPC_S_OK;\r
+  }\r
+  RPCRT4_CloseBinding(bind, conn);\r
+  status = RPC_S_OK;\r
+\r
+  return status;\r
+}\r
+\r
+/***********************************************************************\r
+ *           I_RpcReceive [RPCRT4.@]\r
+ */\r
+RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)\r
+{\r
+  RpcBinding* bind = (RpcBinding*)pMsg->Handle;\r
+  RpcConnection* conn;\r
+  RPC_CLIENT_INTERFACE* cif = NULL;\r
+  RPC_SERVER_INTERFACE* sif = NULL;\r
+  RPC_STATUS status;\r
+  RpcPktHdr *hdr = NULL;\r
+\r
+  TRACE("(%p)\n", pMsg);\r
+  if (!bind) return RPC_S_INVALID_BINDING;\r
+\r
+  if (pMsg->ReservedForRuntime) {\r
+    conn = pMsg->ReservedForRuntime;\r
+    pMsg->ReservedForRuntime = NULL;\r
+  } else {\r
+    if (bind->server) {\r
+      sif = pMsg->RpcInterfaceInformation;\r
+      if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */\r
+      status = RPCRT4_OpenBinding(bind, &conn, &sif->TransferSyntax,\r
+                                  &sif->InterfaceId);\r
+    } else {\r
+      cif = pMsg->RpcInterfaceInformation;\r
+      if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */\r
+      status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax,\r
+                                  &cif->InterfaceId);\r
+    }\r
+    if (status != RPC_S_OK) return status;\r
+  }\r
+\r
+  status = RPCRT4_Receive(conn, &hdr, pMsg);\r
+  if (status != RPC_S_OK) {\r
+    WARN("receive failed with error %lx\n", status);\r
+    goto fail;\r
+  }\r
+\r
+  status = RPC_S_PROTOCOL_ERROR;\r
+\r
+  switch (hdr->common.ptype) {\r
+  case PKT_RESPONSE:\r
+    if (bind->server) goto fail;\r
+    break;\r
+  case PKT_REQUEST:\r
+    if (!bind->server) goto fail;\r
+    break;\r
+  case PKT_FAULT:\r
+    pMsg->RpcFlags |= WINE_RPCFLAG_EXCEPTION;\r
+    ERR ("we got fault packet with status %lx\n", hdr->fault.status);\r
+    status = RPC_S_CALL_FAILED; /* ? */\r
+    goto fail;\r
+  default:\r
+    goto fail;\r
+  }\r
+\r
+  /* success */\r
+  status = RPC_S_OK;\r
+\r
+fail:\r
+  if (hdr) {\r
+    RPCRT4_FreeHeader(hdr);\r
+  }\r
+  RPCRT4_CloseBinding(bind, conn);\r
+  return status;\r
+}\r
+\r
+/***********************************************************************\r
+ *           I_RpcSendReceive [RPCRT4.@]\r
+ */\r
+RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)\r
+{\r
+  RPC_STATUS status;\r
+\r
+  TRACE("(%p)\n", pMsg);\r
+  status = I_RpcSend(pMsg);\r
+  if (status == RPC_S_OK)\r
+    status = I_RpcReceive(pMsg);\r
+  return status;\r
+}\r
diff --git a/reactos/lib/rpcrt4/rpc_message.h b/reactos/lib/rpcrt4/rpc_message.h
new file mode 100644 (file)
index 0000000..9b46399
--- /dev/null
@@ -0,0 +1,38 @@
+/*\r
+ * RPC message API\r
+ *\r
+ * Copyright 2004 Filip Navara\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 __WINE_RPC_MESSAGE_H\r
+#define __WINE_RPC_MESSAGE_H\r
+\r
+#include "wine/rpcss_shared.h"\r
+#include "rpc_defs.h"\r
+\r
+VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType, unsigned long DataRepresentation);\r
+RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, unsigned long BufferLength, unsigned short ProcNum, UUID *ObjectUuid);\r
+RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, unsigned long BufferLength);\r
+RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, RPC_STATUS Status);\r
+RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, RPC_SYNTAX_IDENTIFIER *AbstractId, RPC_SYNTAX_IDENTIFIER *TransferId);\r
+RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor);\r
+RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, LPSTR ServerAddress, unsigned long Result, unsigned long Reason, RPC_SYNTAX_IDENTIFIER *TransferId);\r
+VOID RPCRT4_FreeHeader(RpcPktHdr *Header);\r
+RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength);\r
+RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg);\r
+\r
+#endif\r
diff --git a/reactos/lib/rpcrt4/rpc_misc.h b/reactos/lib/rpcrt4/rpc_misc.h
new file mode 100644 (file)
index 0000000..c94d72a
--- /dev/null
@@ -0,0 +1,28 @@
+/*\r
+ * RPC definitions\r
+ *\r
+ * Copyright 2003 Ove Kåven, TransGaming Technologies\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
+\r
+#ifndef __WINE_RPC_MISC_H\r
+#define __WINE_RPC_MISC_H\r
+\r
+/* flags for RPC_MESSAGE.RpcFlags */\r
+#define WINE_RPCFLAG_EXCEPTION 0x0001\r
+\r
+#endif  /* __WINE_RPC_MISC_H */\r
diff --git a/reactos/lib/rpcrt4/rpc_server.c b/reactos/lib/rpcrt4/rpc_server.c
new file mode 100644 (file)
index 0000000..57eb4ab
--- /dev/null
@@ -0,0 +1,1032 @@
+/*\r
+ * RPC server API\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\r
+ * Copyright 2004 Filip Navara\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
+ * TODO:\r
+ *  - a whole lot\r
+ */\r
+\r
+#include "config.h"\r
+#include "wine/port.h"\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <assert.h>\r
+\r
+#include "windef.h"\r
+#include "winbase.h"\r
+#include "winerror.h"\r
+#include "winreg.h"\r
+#include "ntstatus.h"\r
+\r
+#include "rpc.h"\r
+#include "rpcndr.h"\r
+#include "excpt.h"\r
+\r
+#include "wine/debug.h"\r
+#include "wine/exception.h"\r
+\r
+#include "rpc_server.h"\r
+#include "rpc_misc.h"\r
+#include "rpc_message.h"\r
+#include "rpc_defs.h"\r
+\r
+#define MAX_THREADS 128\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+typedef struct _RpcPacket\r
+{\r
+  struct _RpcPacket* next;\r
+  struct _RpcConnection* conn;\r
+  RpcPktHdr* hdr;\r
+  RPC_MESSAGE* msg;\r
+} RpcPacket;\r
+\r
+typedef struct _RpcObjTypeMap\r
+{\r
+  /* FIXME: a hash table would be better. */\r
+  struct _RpcObjTypeMap *next;\r
+  UUID Object;\r
+  UUID Type;\r
+} RpcObjTypeMap;\r
+\r
+static RpcObjTypeMap *RpcObjTypeMaps;\r
+\r
+static RpcServerProtseq* protseqs;\r
+static RpcServerInterface* ifs;\r
+\r
+static CRITICAL_SECTION server_cs;\r
+static CRITICAL_SECTION_DEBUG server_cs_debug =\r
+{\r
+    0, 0, &server_cs,\r
+    { &server_cs_debug.ProcessLocksList, &server_cs_debug.ProcessLocksList },\r
+      0, 0, { 0, (DWORD)(__FILE__ ": server_cs") }\r
+};\r
+static CRITICAL_SECTION server_cs = { &server_cs_debug, -1, 0, 0, 0, 0 };\r
+\r
+static CRITICAL_SECTION listen_cs;\r
+static CRITICAL_SECTION_DEBUG listen_cs_debug =\r
+{\r
+    0, 0, &listen_cs,\r
+    { &listen_cs_debug.ProcessLocksList, &listen_cs_debug.ProcessLocksList },\r
+      0, 0, { 0, (DWORD)(__FILE__ ": listen_cs") }\r
+};\r
+static CRITICAL_SECTION listen_cs = { &listen_cs_debug, -1, 0, 0, 0, 0 };\r
+\r
+static BOOL std_listen;\r
+static LONG listen_count = -1;\r
+static HANDLE mgr_event, server_thread;\r
+\r
+static CRITICAL_SECTION spacket_cs;\r
+static CRITICAL_SECTION_DEBUG spacket_cs_debug =\r
+{\r
+    0, 0, &spacket_cs,\r
+    { &spacket_cs_debug.ProcessLocksList, &spacket_cs_debug.ProcessLocksList },\r
+      0, 0, { 0, (DWORD)(__FILE__ ": spacket_cs") }\r
+};\r
+static CRITICAL_SECTION spacket_cs = { &spacket_cs_debug, -1, 0, 0, 0, 0 };\r
+\r
+static RpcPacket* spacket_head;\r
+static RpcPacket* spacket_tail;\r
+static HANDLE server_sem;\r
+\r
+static DWORD worker_count, worker_free, worker_tls;\r
+\r
+static UUID uuid_nil;\r
+\r
+inline static RpcObjTypeMap *LookupObjTypeMap(UUID *ObjUuid)\r
+{\r
+  RpcObjTypeMap *rslt = RpcObjTypeMaps;\r
+  RPC_STATUS dummy;\r
+\r
+  while (rslt) {\r
+    if (! UuidCompare(ObjUuid, &rslt->Object, &dummy)) break;\r
+    rslt = rslt->next;\r
+  }\r
+\r
+  return rslt;\r
+}\r
+\r
+inline static UUID *LookupObjType(UUID *ObjUuid)\r
+{\r
+  RpcObjTypeMap *map = LookupObjTypeMap(ObjUuid);\r
+  if (map)\r
+    return &map->Type;\r
+  else\r
+    return &uuid_nil;\r
+}\r
+\r
+static RpcServerInterface* RPCRT4_find_interface(UUID* object,\r
+                                                 RPC_SYNTAX_IDENTIFIER* if_id,\r
+                                                 BOOL check_object)\r
+{\r
+  UUID* MgrType = NULL;\r
+  RpcServerInterface* cif = NULL;\r
+  RPC_STATUS status;\r
+\r
+  if (check_object)\r
+    MgrType = LookupObjType(object);\r
+  EnterCriticalSection(&server_cs);\r
+  cif = ifs;\r
+  while (cif) {\r
+    if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) &&\r
+        (check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) &&\r
+        (std_listen || (cif->Flags & RPC_IF_AUTOLISTEN))) break;\r
+    cif = cif->Next;\r
+  }\r
+  LeaveCriticalSection(&server_cs);\r
+  TRACE("returning %p for %s\n", cif, debugstr_guid(object));\r
+  return cif;\r
+}\r
+\r
+static void RPCRT4_push_packet(RpcPacket* packet)\r
+{\r
+  packet->next = NULL;\r
+  EnterCriticalSection(&spacket_cs);\r
+  if (spacket_tail) {\r
+    spacket_tail->next = packet;\r
+    spacket_tail = packet;\r
+  } else {\r
+    spacket_head = packet;\r
+    spacket_tail = packet;\r
+  }\r
+  LeaveCriticalSection(&spacket_cs);\r
+}\r
+\r
+static RpcPacket* RPCRT4_pop_packet(void)\r
+{\r
+  RpcPacket* packet;\r
+  EnterCriticalSection(&spacket_cs);\r
+  packet = spacket_head;\r
+  if (packet) {\r
+    spacket_head = packet->next;\r
+    if (!spacket_head) spacket_tail = NULL;\r
+  }\r
+  LeaveCriticalSection(&spacket_cs);\r
+  if (packet) packet->next = NULL;\r
+  return packet;\r
+}\r
+\r
+#ifndef __REACTOS__\r
+typedef struct {\r
+  PRPC_MESSAGE msg;\r
+  void* buf;\r
+} packet_state;\r
+\r
+static WINE_EXCEPTION_FILTER(rpc_filter)\r
+{\r
+  packet_state* state;\r
+  PRPC_MESSAGE msg;\r
+  state = TlsGetValue(worker_tls);\r
+  msg = state->msg;\r
+  if (msg->Buffer != state->buf) I_RpcFreeBuffer(msg);\r
+  msg->RpcFlags |= WINE_RPCFLAG_EXCEPTION;\r
+  msg->BufferLength = sizeof(DWORD);\r
+  I_RpcGetBuffer(msg);\r
+  *(DWORD*)msg->Buffer = GetExceptionCode();\r
+  WARN("exception caught with code 0x%08lx = %ld\n", *(DWORD*)msg->Buffer, *(DWORD*)msg->Buffer);\r
+  TRACE("returning failure packet\n");\r
+  return EXCEPTION_EXECUTE_HANDLER;\r
+}\r
+#endif\r
+\r
+static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSAGE* msg)\r
+{\r
+  RpcServerInterface* sif;\r
+  RPC_DISPATCH_FUNCTION func;\r
+#ifndef __REACTOS__\r
+  packet_state state;\r
+#endif\r
+  UUID *object_uuid;\r
+  RpcPktHdr *response;\r
+  void *buf = msg->Buffer;\r
+  RPC_STATUS status;\r
+\r
+#ifndef __REACTOS__\r
+  state.msg = msg;\r
+  state.buf = buf;\r
+  TlsSetValue(worker_tls, &state);\r
+#endif\r
+\r
+  switch (hdr->common.ptype) {\r
+    case PKT_BIND:\r
+      TRACE("got bind packet\n");\r
+\r
+      /* FIXME: do more checks! */\r
+      if (hdr->bind.max_tsize < RPC_MIN_PACKET_SIZE ||\r
+          !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) {\r
+        TRACE("packet size less than min size, or active interface syntax guid non-null\n");\r
+        sif = NULL;\r
+      } else {\r
+        sif = RPCRT4_find_interface(NULL, &hdr->bind.abstract, FALSE);\r
+      }\r
+      if (sif == NULL) {\r
+        TRACE("rejecting bind request on connection %p\n", conn);\r
+        /* Report failure to client. */\r
+        response = RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,\r
+                                              RPC_VER_MAJOR, RPC_VER_MINOR);\r
+      } else {\r
+        TRACE("accepting bind request on connection %p\n", conn);\r
+\r
+        /* accept. */\r
+        response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION,\r
+                                             RPC_MAX_PACKET_SIZE,\r
+                                             RPC_MAX_PACKET_SIZE,\r
+                                             conn->Endpoint,\r
+                                             RESULT_ACCEPT, NO_REASON,\r
+                                             &sif->If->TransferSyntax);\r
+\r
+        /* save the interface for later use */\r
+        conn->ActiveInterface = hdr->bind.abstract;\r
+        conn->MaxTransmissionSize = hdr->bind.max_tsize;\r
+      }\r
+\r
+      if (RPCRT4_Send(conn, response, NULL, 0) != RPC_S_OK)\r
+        goto fail;\r
+\r
+      break;\r
+\r
+    case PKT_REQUEST:\r
+      TRACE("got request packet\n");\r
+\r
+      /* fail if the connection isn't bound with an interface */\r
+      if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) {\r
+        response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,\r
+                                           status);\r
+\r
+        RPCRT4_Send(conn, response, NULL, 0);\r
+        break;\r
+      }\r
+\r
+      if (hdr->common.flags & RPC_FLG_OBJECT_UUID) {\r
+        object_uuid = (UUID*)(&hdr->request + 1);\r
+      } else {\r
+        object_uuid = NULL;\r
+      }\r
+\r
+      sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, TRUE);\r
+      msg->RpcInterfaceInformation = sif->If;\r
+      /* copy the endpoint vector from sif to msg so that midl-generated code will use it */\r
+      msg->ManagerEpv = sif->MgrEpv;\r
+      if (object_uuid != NULL) {\r
+        RPCRT4_SetBindingObject(msg->Handle, object_uuid);\r
+      }\r
+\r
+      /* find dispatch function */\r
+      msg->ProcNum = hdr->request.opnum;\r
+      if (sif->Flags & RPC_IF_OLE) {\r
+        /* native ole32 always gives us a dispatch table with a single entry\r
+         * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */\r
+        func = *sif->If->DispatchTable->DispatchTable;\r
+      } else {\r
+        if (msg->ProcNum >= sif->If->DispatchTable->DispatchTableCount) {\r
+          ERR("invalid procnum\n");\r
+          func = NULL;\r
+        }\r
+        func = sif->If->DispatchTable->DispatchTable[msg->ProcNum];\r
+      }\r
+\r
+      /* put in the drep. FIXME: is this more universally applicable?\r
+         perhaps we should move this outward... */\r
+      msg->DataRepresentation = \r
+        MAKELONG( MAKEWORD(hdr->common.drep[0], hdr->common.drep[1]),\r
+                  MAKEWORD(hdr->common.drep[2], hdr->common.drep[3]));\r
+\r
+      /* dispatch */\r
+#ifndef __REACTOS__\r
+      __TRY {\r
+        if (func) func(msg);\r
+      } __EXCEPT(rpc_filter) {\r
+        /* failure packet was created in rpc_filter */\r
+      } __ENDTRY\r
+#else\r
+      if (func) func(msg);\r
+#endif\r
+\r
+      /* send response packet */\r
+      I_RpcSend(msg);\r
+\r
+      msg->RpcInterfaceInformation = NULL;\r
+\r
+      break;\r
+\r
+    default:\r
+      FIXME("unhandled packet type\n");\r
+      break;\r
+  }\r
+\r
+fail:\r
+  /* clean up */\r
+  if (msg->Buffer == buf) msg->Buffer = NULL;\r
+  TRACE("freeing Buffer=%p\n", buf);\r
+  HeapFree(GetProcessHeap(), 0, buf);\r
+  RPCRT4_DestroyBinding(msg->Handle);\r
+  msg->Handle = 0;\r
+  I_RpcFreeBuffer(msg);\r
+  msg->Buffer = NULL;\r
+  RPCRT4_FreeHeader(hdr);\r
+#ifndef __REACTOS__\r
+  TlsSetValue(worker_tls, NULL);\r
+#endif\r
+}\r
+\r
+static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)\r
+{\r
+  DWORD obj;\r
+  RpcPacket* pkt;\r
+\r
+  for (;;) {\r
+    /* idle timeout after 5s */\r
+    obj = WaitForSingleObject(server_sem, 5000);\r
+    if (obj == WAIT_TIMEOUT) {\r
+      /* if another idle thread exist, self-destruct */\r
+      if (worker_free > 1) break;\r
+      continue;\r
+    }\r
+    pkt = RPCRT4_pop_packet();\r
+    if (!pkt) continue;\r
+    InterlockedDecrement(&worker_free);\r
+    for (;;) {\r
+      RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg);\r
+      HeapFree(GetProcessHeap(), 0, pkt);\r
+      /* try to grab another packet here without waiting\r
+       * on the semaphore, in case it hits max */\r
+      pkt = RPCRT4_pop_packet();\r
+      if (!pkt) break;\r
+      /* decrement semaphore */\r
+      WaitForSingleObject(server_sem, 0);\r
+    }\r
+    InterlockedIncrement(&worker_free);\r
+  }\r
+  InterlockedDecrement(&worker_free);\r
+  InterlockedDecrement(&worker_count);\r
+  return 0;\r
+}\r
+\r
+static void RPCRT4_create_worker_if_needed(void)\r
+{\r
+  if (!worker_free && worker_count < MAX_THREADS) {\r
+    HANDLE thread;\r
+    InterlockedIncrement(&worker_count);\r
+    InterlockedIncrement(&worker_free);\r
+    thread = CreateThread(NULL, 0, RPCRT4_worker_thread, NULL, 0, NULL);\r
+    if (thread) CloseHandle(thread);\r
+    else {\r
+      InterlockedDecrement(&worker_free);\r
+      InterlockedDecrement(&worker_count);\r
+    }\r
+  }\r
+}\r
+\r
+static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)\r
+{\r
+  RpcConnection* conn = (RpcConnection*)the_arg;\r
+  RpcPktHdr *hdr;\r
+  RpcBinding *pbind;\r
+  RPC_MESSAGE *msg;\r
+  RPC_STATUS status;\r
+  RpcPacket *packet;\r
+\r
+  TRACE("(%p)\n", conn);\r
+\r
+  for (;;) {\r
+    msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE));\r
+\r
+    /* create temporary binding for dispatch, it will be freed in\r
+     * RPCRT4_process_packet */\r
+    RPCRT4_MakeBinding(&pbind, conn);\r
+    msg->Handle = (RPC_BINDING_HANDLE)pbind;\r
+\r
+    status = RPCRT4_Receive(conn, &hdr, msg);\r
+    if (status != RPC_S_OK) {\r
+      WARN("receive failed with error %lx\n", status);\r
+      break;\r
+    }\r
+\r
+#if 0\r
+    RPCRT4_process_packet(conn, hdr, msg);\r
+#else\r
+    packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket));\r
+    packet->conn = conn;\r
+    packet->hdr = hdr;\r
+    packet->msg = msg;\r
+    RPCRT4_create_worker_if_needed();\r
+    RPCRT4_push_packet(packet);\r
+    ReleaseSemaphore(server_sem, 1, NULL);\r
+#endif\r
+    msg = NULL;\r
+  }\r
+  if (msg) HeapFree(GetProcessHeap(), 0, msg);\r
+  RPCRT4_DestroyConnection(conn);\r
+  return 0;\r
+}\r
+\r
+static void RPCRT4_new_client(RpcConnection* conn)\r
+{\r
+  HANDLE thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL);\r
+  if (!thread) {\r
+    DWORD err = GetLastError();\r
+    ERR("failed to create thread, error=%08lx\n", err);\r
+    RPCRT4_DestroyConnection(conn);\r
+  }\r
+  /* we could set conn->thread, but then we'd have to make the io_thread wait\r
+   * for that, otherwise the thread might finish, destroy the connection, and\r
+   * free the memory we'd write to before we did, causing crashes and stuff -\r
+   * so let's implement that later, when we really need conn->thread */\r
+\r
+  CloseHandle( thread );\r
+}\r
+\r
+static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)\r
+{\r
+  HANDLE m_event = mgr_event, b_handle;\r
+  HANDLE *objs = NULL;\r
+  DWORD count, res;\r
+  RpcServerProtseq* cps;\r
+  RpcConnection* conn;\r
+  RpcConnection* cconn;\r
+\r
+  TRACE("(the_arg == ^%p)\n", the_arg);\r
+\r
+  for (;;) {\r
+    EnterCriticalSection(&server_cs);\r
+    /* open and count connections */\r
+    count = 1;\r
+    cps = protseqs;\r
+    while (cps) {\r
+      conn = cps->conn;\r
+      while (conn) {\r
+        RPCRT4_OpenConnection(conn);\r
+        if (conn->ovl.hEvent) count++;\r
+        conn = conn->Next;\r
+      }\r
+      cps = cps->Next;\r
+    }\r
+    /* make array of connections */\r
+    if (objs)\r
+       objs = HeapReAlloc(GetProcessHeap(), 0, objs, count*sizeof(HANDLE));\r
+    else\r
+       objs = HeapAlloc(GetProcessHeap(), 0, count*sizeof(HANDLE));\r
+\r
+    objs[0] = m_event;\r
+    count = 1;\r
+    cps = protseqs;\r
+    while (cps) {\r
+      conn = cps->conn;\r
+      while (conn) {\r
+        if (conn->ovl.hEvent) objs[count++] = conn->ovl.hEvent;\r
+        conn = conn->Next;\r
+      }\r
+      cps = cps->Next;\r
+    }\r
+    LeaveCriticalSection(&server_cs);\r
+\r
+    /* start waiting */\r
+    res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);\r
+    if (res == WAIT_OBJECT_0) {\r
+      ResetEvent(m_event);\r
+      if (!std_listen) break;\r
+    }\r
+    else if (res == WAIT_FAILED) {\r
+      ERR("wait failed\n");\r
+    }\r
+    else {\r
+      b_handle = objs[res - WAIT_OBJECT_0];\r
+      /* find which connection got a RPC */\r
+      EnterCriticalSection(&server_cs);\r
+      conn = NULL;\r
+      cps = protseqs;\r
+      while (cps) {\r
+        conn = cps->conn;\r
+        while (conn) {\r
+          if (conn->ovl.hEvent == b_handle) break;\r
+          conn = conn->Next;\r
+        }\r
+        if (conn) break;\r
+        cps = cps->Next;\r
+      }\r
+      cconn = NULL;\r
+      if (conn) RPCRT4_SpawnConnection(&cconn, conn);\r
+      LeaveCriticalSection(&server_cs);\r
+      if (!conn) {\r
+        ERR("failed to locate connection for handle %p\n", b_handle);\r
+      }\r
+      if (cconn) RPCRT4_new_client(cconn);\r
+    }\r
+  }\r
+  HeapFree(GetProcessHeap(), 0, objs);\r
+  EnterCriticalSection(&server_cs);\r
+  /* close connections */\r
+  cps = protseqs;\r
+  while (cps) {\r
+    conn = cps->conn;\r
+    while (conn) {\r
+      RPCRT4_CloseConnection(conn);\r
+      conn = conn->Next;\r
+    }\r
+    cps = cps->Next;\r
+  }\r
+  LeaveCriticalSection(&server_cs);\r
+  return 0;\r
+}\r
+\r
+static void RPCRT4_start_listen(void)\r
+{\r
+  TRACE("\n");\r
+\r
+  EnterCriticalSection(&listen_cs);\r
+  if (! ++listen_count) {\r
+    if (!mgr_event) mgr_event = CreateEventA(NULL, TRUE, FALSE, NULL);\r
+    if (!server_sem) server_sem = CreateSemaphoreA(NULL, 0, MAX_THREADS, NULL);\r
+    if (!worker_tls) worker_tls = TlsAlloc();\r
+    std_listen = TRUE;\r
+    server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL);\r
+    LeaveCriticalSection(&listen_cs);\r
+  } else {\r
+    LeaveCriticalSection(&listen_cs);\r
+    SetEvent(mgr_event);\r
+  }\r
+}\r
+\r
+static void RPCRT4_stop_listen(void)\r
+{\r
+  EnterCriticalSection(&listen_cs);\r
+  if (listen_count == -1)\r
+    LeaveCriticalSection(&listen_cs);\r
+  else if (--listen_count == -1) {\r
+    std_listen = FALSE;\r
+    LeaveCriticalSection(&listen_cs);\r
+    SetEvent(mgr_event);\r
+  } else\r
+    LeaveCriticalSection(&listen_cs);\r
+  assert(listen_count > -2);\r
+}\r
+\r
+static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps)\r
+{\r
+  RPCRT4_CreateConnection(&ps->conn, TRUE, ps->Protseq, NULL, ps->Endpoint, NULL, NULL);\r
+\r
+  EnterCriticalSection(&server_cs);\r
+  ps->Next = protseqs;\r
+  protseqs = ps;\r
+  LeaveCriticalSection(&server_cs);\r
+\r
+  if (std_listen) SetEvent(mgr_event);\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerInqBindings (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )\r
+{\r
+  RPC_STATUS status;\r
+  DWORD count;\r
+  RpcServerProtseq* ps;\r
+  RpcConnection* conn;\r
+\r
+  if (BindingVector)\r
+    TRACE("(*BindingVector == ^%p)\n", *BindingVector);\r
+  else\r
+    ERR("(BindingVector == NULL!!?)\n");\r
+\r
+  EnterCriticalSection(&server_cs);\r
+  /* count connections */\r
+  count = 0;\r
+  ps = protseqs;\r
+  while (ps) {\r
+    conn = ps->conn;\r
+    while (conn) {\r
+      count++;\r
+      conn = conn->Next;\r
+    }\r
+    ps = ps->Next;\r
+  }\r
+  if (count) {\r
+    /* export bindings */\r
+    *BindingVector = HeapAlloc(GetProcessHeap(), 0,\r
+                              sizeof(RPC_BINDING_VECTOR) +\r
+                              sizeof(RPC_BINDING_HANDLE)*(count-1));\r
+    (*BindingVector)->Count = count;\r
+    count = 0;\r
+    ps = protseqs;\r
+    while (ps) {\r
+      conn = ps->conn;\r
+      while (conn) {\r
+       RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count],\r
+                          conn);\r
+       count++;\r
+       conn = conn->Next;\r
+      }\r
+      ps = ps->Next;\r
+    }\r
+    status = RPC_S_OK;\r
+  } else {\r
+    *BindingVector = NULL;\r
+    status = RPC_S_NO_BINDINGS;\r
+  }\r
+  LeaveCriticalSection(&server_cs);\r
+  return status;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerUseProtseqEpA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerUseProtseqEpA( unsigned char *Protseq, UINT MaxCalls, unsigned char *Endpoint, LPVOID SecurityDescriptor )\r
+{\r
+  RPC_POLICY policy;\r
+  \r
+  TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor );\r
+  \r
+  /* This should provide the default behaviour */\r
+  policy.Length        = sizeof( policy );\r
+  policy.EndpointFlags = 0;\r
+  policy.NICFlags      = 0;\r
+  \r
+  return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerUseProtseqEpW (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerUseProtseqEpW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor )\r
+{\r
+  RPC_POLICY policy;\r
+  \r
+  TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor );\r
+  \r
+  /* This should provide the default behaviour */\r
+  policy.Length        = sizeof( policy );\r
+  policy.EndpointFlags = 0;\r
+  policy.NICFlags      = 0;\r
+  \r
+  return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerUseProtseqEpExA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerUseProtseqEpExA( unsigned char *Protseq, UINT MaxCalls, unsigned char *Endpoint, LPVOID SecurityDescriptor,\r
+                                            PRPC_POLICY lpPolicy )\r
+{\r
+  RpcServerProtseq* ps;\r
+\r
+  TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_a( Protseq ), MaxCalls,\r
+       debugstr_a( Endpoint ), SecurityDescriptor,\r
+       lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );\r
+\r
+  ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));\r
+  ps->MaxCalls = MaxCalls;\r
+  ps->Protseq = RPCRT4_strdupA(Protseq);\r
+  ps->Endpoint = RPCRT4_strdupA(Endpoint);\r
+\r
+  return RPCRT4_use_protseq(ps);\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerUseProtseqEpExW (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerUseProtseqEpExW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor,\r
+                                            PRPC_POLICY lpPolicy )\r
+{\r
+  RpcServerProtseq* ps;\r
+\r
+  TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_w( Protseq ), MaxCalls,\r
+       debugstr_w( Endpoint ), SecurityDescriptor,\r
+       lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );\r
+\r
+  ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));\r
+  ps->MaxCalls = MaxCalls;\r
+  ps->Protseq = RPCRT4_strdupWtoA(Protseq);\r
+  ps->Endpoint = RPCRT4_strdupWtoA(Endpoint);\r
+\r
+  return RPCRT4_use_protseq(ps);\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerUseProtseqA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerUseProtseqA(unsigned char *Protseq, unsigned int MaxCalls, void *SecurityDescriptor)\r
+{\r
+  TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a(Protseq), MaxCalls, SecurityDescriptor);\r
+  return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, SecurityDescriptor);\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerUseProtseqW (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerUseProtseqW(LPWSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)\r
+{\r
+  TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor);\r
+  return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor);\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerRegisterIf (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv )\r
+{\r
+  TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv);\r
+  return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL );\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerRegisterIfEx (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,\r
+                       UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn )\r
+{\r
+  TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn);\r
+  return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn );\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerRegisterIf2 (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,\r
+                      UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )\r
+{\r
+  PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;\r
+  RpcServerInterface* sif;\r
+  unsigned int i;\r
+\r
+  TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls,\r
+         MaxRpcSize, IfCallbackFn);\r
+  TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),\r
+                                     If->InterfaceId.SyntaxVersion.MajorVersion,\r
+                                     If->InterfaceId.SyntaxVersion.MinorVersion);\r
+  TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID),\r
+                                        If->TransferSyntax.SyntaxVersion.MajorVersion,\r
+                                        If->TransferSyntax.SyntaxVersion.MinorVersion);\r
+  TRACE(" dispatch table: %p\n", If->DispatchTable);\r
+  if (If->DispatchTable) {\r
+    TRACE("  dispatch table count: %d\n", If->DispatchTable->DispatchTableCount);\r
+    for (i=0; i<If->DispatchTable->DispatchTableCount; i++) {\r
+      TRACE("   entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]);\r
+    }\r
+    TRACE("  reserved: %ld\n", If->DispatchTable->Reserved);\r
+  }\r
+  TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount);\r
+  TRACE(" default manager epv: %p\n", If->DefaultManagerEpv);\r
+  TRACE(" interpreter info: %p\n", If->InterpreterInfo);\r
+\r
+  sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface));\r
+  sif->If           = If;\r
+  if (MgrTypeUuid) {\r
+    memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID));\r
+    sif->MgrEpv       = MgrEpv;\r
+  } else {\r
+    memset(&sif->MgrTypeUuid, 0, sizeof(UUID));\r
+    sif->MgrEpv       = If->DefaultManagerEpv;\r
+  }\r
+  sif->Flags        = Flags;\r
+  sif->MaxCalls     = MaxCalls;\r
+  sif->MaxRpcSize   = MaxRpcSize;\r
+  sif->IfCallbackFn = IfCallbackFn;\r
+\r
+  EnterCriticalSection(&server_cs);\r
+  sif->Next = ifs;\r
+  ifs = sif;\r
+  LeaveCriticalSection(&server_cs);\r
+\r
+  if (sif->Flags & RPC_IF_AUTOLISTEN) {\r
+    /* well, start listening, I think... */\r
+    RPCRT4_start_listen();\r
+  }\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerUnregisterIf (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )\r
+{\r
+  FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, WaitForCallsToComplete == %u): stub\n",\r
+    IfSpec, debugstr_guid(MgrTypeUuid), WaitForCallsToComplete);\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerUnregisterIfEx (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles )\r
+{\r
+  FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n",\r
+    IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles);\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcObjectSetType (RPCRT4.@)\r
+ *\r
+ * PARAMS\r
+ *   ObjUuid  [I] "Object" UUID\r
+ *   TypeUuid [I] "Type" UUID\r
+ *\r
+ * RETURNS\r
+ *   RPC_S_OK                 The call succeeded\r
+ *   RPC_S_INVALID_OBJECT     The provided object (nil) is not valid\r
+ *   RPC_S_ALREADY_REGISTERED The provided object is already registered\r
+ *\r
+ * Maps "Object" UUIDs to "Type" UUID's.  Passing the nil UUID as the type\r
+ * resets the mapping for the specified object UUID to nil (the default).\r
+ * The nil object is always associated with the nil type and cannot be\r
+ * reassigned.  Servers can support multiple implementations on the same\r
+ * interface by registering different end-point vectors for the different\r
+ * types.  There's no need to call this if a server only supports the nil\r
+ * type, as is typical.\r
+ */\r
+RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid )\r
+{\r
+  RpcObjTypeMap *map = RpcObjTypeMaps, *prev = NULL;\r
+  RPC_STATUS dummy;\r
+\r
+  TRACE("(ObjUUID == %s, TypeUuid == %s).\n", debugstr_guid(ObjUuid), debugstr_guid(TypeUuid));\r
+  if ((! ObjUuid) || UuidIsNil(ObjUuid, &dummy)) {\r
+    /* nil uuid cannot be remapped */\r
+    return RPC_S_INVALID_OBJECT;\r
+  }\r
+\r
+  /* find the mapping for this object if there is one ... */\r
+  while (map) {\r
+    if (! UuidCompare(ObjUuid, &map->Object, &dummy)) break;\r
+    prev = map;\r
+    map = map->next;\r
+  }\r
+  if ((! TypeUuid) || UuidIsNil(TypeUuid, &dummy)) {\r
+    /* ... and drop it from the list */\r
+    if (map) {\r
+      if (prev) \r
+        prev->next = map->next;\r
+      else\r
+        RpcObjTypeMaps = map->next;\r
+      HeapFree(GetProcessHeap(), 0, map);\r
+    }\r
+  } else {\r
+    /* ... , fail if we found it ... */\r
+    if (map)\r
+      return RPC_S_ALREADY_REGISTERED;\r
+    /* ... otherwise create a new one and add it in. */\r
+    map = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcObjTypeMap));\r
+    memcpy(&map->Object, ObjUuid, sizeof(UUID));\r
+    memcpy(&map->Type, TypeUuid, sizeof(UUID));\r
+    map->next = NULL;\r
+    if (prev)\r
+      prev->next = map; /* prev is the last map in the linklist */\r
+    else\r
+      RpcObjTypeMaps = map;\r
+  }\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerRegisterAuthInfoA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( unsigned char *ServerPrincName, unsigned long AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,\r
+                            LPVOID Arg )\r
+{\r
+  FIXME( "(%s,%lu,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg );\r
+  \r
+  return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerRegisterAuthInfoW (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( LPWSTR ServerPrincName, unsigned long AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,\r
+                            LPVOID Arg )\r
+{\r
+  FIXME( "(%s,%lu,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg );\r
+  \r
+  return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcServerListen (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )\r
+{\r
+  TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait);\r
+\r
+  if (!protseqs)\r
+    return RPC_S_NO_PROTSEQS_REGISTERED;\r
+\r
+  EnterCriticalSection(&listen_cs);\r
+\r
+  if (std_listen) {\r
+    LeaveCriticalSection(&listen_cs);\r
+    return RPC_S_ALREADY_LISTENING;\r
+  }\r
+\r
+  RPCRT4_start_listen();\r
+\r
+  LeaveCriticalSection(&listen_cs);\r
+\r
+  if (DontWait) return RPC_S_OK;\r
+\r
+  return RpcMgmtWaitServerListen();\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcMgmtServerWaitListen (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )\r
+{\r
+  RPC_STATUS rslt = RPC_S_OK;\r
+\r
+  TRACE("\n");\r
+\r
+  EnterCriticalSection(&listen_cs);\r
+\r
+  if (!std_listen)\r
+    if ( (rslt = RpcServerListen(1, 0, TRUE)) != RPC_S_OK ) {\r
+      LeaveCriticalSection(&listen_cs);\r
+      return rslt;\r
+    }\r
+  \r
+  LeaveCriticalSection(&listen_cs);\r
+\r
+  while (std_listen) {\r
+    WaitForSingleObject(mgr_event, INFINITE);\r
+    if (!std_listen) {\r
+      Sleep(100); /* don't spin violently */\r
+      TRACE("spinning.\n");\r
+    }\r
+  }\r
+\r
+  return rslt;\r
+}\r
+\r
+/***********************************************************************\r
+ *             RpcMgmtStopServerListening (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding )\r
+{\r
+  TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding);\r
+\r
+  if (Binding) {\r
+    FIXME("client-side invocation not implemented.\n");\r
+    return RPC_S_WRONG_KIND_OF_BINDING;\r
+  }\r
+  \r
+  /* hmm... */\r
+  EnterCriticalSection(&listen_cs);\r
+  while (std_listen)\r
+    RPCRT4_stop_listen();\r
+  LeaveCriticalSection(&listen_cs);\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             I_RpcServerStartListening (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI I_RpcServerStartListening( HWND hWnd )\r
+{\r
+  FIXME( "(%p): stub\n", hWnd );\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             I_RpcServerStopListening (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI I_RpcServerStopListening( void )\r
+{\r
+  FIXME( "(): stub\n" );\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ *             I_RpcWindowProc (RPCRT4.@)\r
+ */\r
+UINT WINAPI I_RpcWindowProc( void *hWnd, UINT Message, UINT wParam, ULONG lParam )\r
+{\r
+  FIXME( "(%p,%08x,%08x,%08lx): stub\n", hWnd, Message, wParam, lParam );\r
+\r
+  return 0;\r
+}\r
diff --git a/reactos/lib/rpcrt4/rpc_server.h b/reactos/lib/rpcrt4/rpc_server.h
new file mode 100644 (file)
index 0000000..df950bb
--- /dev/null
@@ -0,0 +1,47 @@
+/*\r
+ * RPC server API\r
+ *\r
+ * Copyright 2001 Ove Kåven, TransGaming Technologies\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 __WINE_RPC_SERVER_H\r
+#define __WINE_RPC_SERVER_H\r
+\r
+#include "rpc_binding.h"\r
+\r
+typedef struct _RpcServerProtseq\r
+{\r
+  struct _RpcServerProtseq* Next;\r
+  LPSTR Protseq;\r
+  LPSTR Endpoint;\r
+  UINT MaxCalls;\r
+  RpcConnection* conn;\r
+} RpcServerProtseq;\r
+\r
+typedef struct _RpcServerInterface\r
+{\r
+  struct _RpcServerInterface* Next;\r
+  RPC_SERVER_INTERFACE* If;\r
+  UUID MgrTypeUuid;\r
+  RPC_MGR_EPV* MgrEpv;\r
+  UINT Flags;\r
+  UINT MaxCalls;\r
+  UINT MaxRpcSize;\r
+  RPC_IF_CALLBACK_FN* IfCallbackFn;\r
+} RpcServerInterface;\r
+\r
+#endif  /* __WINE_RPC_SERVER_H */\r
diff --git a/reactos/lib/rpcrt4/rpcrt4.spec b/reactos/lib/rpcrt4/rpcrt4.spec
new file mode 100644 (file)
index 0000000..72efb41
--- /dev/null
@@ -0,0 +1,581 @@
+@ stub DceErrorInqTextA\r
+@ stub DceErrorInqTextW\r
+@ stdcall -private DllRegisterServer() RPCRT4_DllRegisterServer\r
+\r
+@ stub MesBufferHandleReset\r
+@ stub MesDecodeBufferHandleCreate\r
+@ stub MesDecodeIncrementalHandleCreate\r
+@ stub MesEncodeDynBufferHandleCreate\r
+@ stub MesEncodeFixedBufferHandleCreate\r
+@ stub MesEncodeIncrementalHandleCreate\r
+@ stub MesHandleFree\r
+@ stub MesIncrementalHandleReset\r
+@ stub MesInqProcEncodingId\r
+\r
+@ stub MqGetContext # win9x\r
+@ stub MqRegisterQueue # win9x\r
+\r
+@ stub RpcAbortAsyncCall\r
+@ stub RpcAsyncAbortCall\r
+@ stub RpcAsyncCancelCall\r
+@ stub RpcAsyncCompleteCall\r
+@ stub RpcAsyncGetCallStatus\r
+@ stub RpcAsyncInitializeHandle\r
+@ stub RpcAsyncRegisterInfo\r
+@ stub RpcBindingCopy\r
+@ stdcall RpcBindingFree(ptr)\r
+@ stdcall RpcBindingFromStringBindingA(str  ptr)\r
+@ stdcall RpcBindingFromStringBindingW(wstr ptr)\r
+@ stub RpcBindingInqAuthClientA\r
+@ stub RpcBindingInqAuthClientW\r
+@ stub RpcBindingInqAuthClientExA\r
+@ stub RpcBindingInqAuthClientExW\r
+@ stub RpcBindingInqAuthInfoA\r
+@ stub RpcBindingInqAuthInfoW\r
+@ stub RpcBindingInqAuthInfoExA\r
+@ stub RpcBindingInqAuthInfoExW\r
+@ stdcall RpcBindingInqObject(ptr ptr)\r
+@ stub RpcBindingInqOption\r
+@ stub RpcBindingReset\r
+@ stub RpcBindingServerFromClient\r
+@ stub RpcBindingSetAuthInfoA\r
+@ stub RpcBindingSetAuthInfoW\r
+@ stub RpcBindingSetAuthInfoExA\r
+@ stub RpcBindingSetAuthInfoExW\r
+@ stdcall RpcBindingSetObject(ptr ptr)\r
+@ stub RpcBindingSetOption\r
+@ stdcall RpcBindingToStringBindingA(ptr ptr)\r
+@ stdcall RpcBindingToStringBindingW(ptr ptr)\r
+@ stdcall RpcBindingVectorFree(ptr)\r
+@ stub RpcCancelAsyncCall\r
+@ stub RpcCancelThread\r
+@ stub RpcCancelThreadEx\r
+@ stub RpcCertGeneratePrincipalNameA\r
+@ stub RpcCertGeneratePrincipalNameW\r
+@ stub RpcCompleteAsyncCall\r
+@ stdcall RpcEpRegisterA(ptr ptr ptr str)\r
+@ stub RpcEpRegisterW\r
+@ stub RpcEpRegisterNoReplaceA\r
+@ stub RpcEpRegisterNoReplaceW\r
+@ stdcall RpcEpResolveBinding(ptr ptr)\r
+@ stdcall RpcEpUnregister(ptr ptr ptr)\r
+@ stub RpcErrorAddRecord # wxp\r
+@ stub RpcErrorClearInformation # wxp\r
+@ stub RpcErrorEndEnumeration # wxp\r
+@ stub RpcErrorGetNextRecord # wxp\r
+@ stub RpcErrorNumberOfRecords # wxp\r
+@ stub RpcErrorLoadErrorInfo # wxp\r
+@ stub RpcErrorResetEnumeration # wxp\r
+@ stub RpcErrorSaveErrorInfo # wxp\r
+@ stub RpcErrorStartEnumeration # wxp\r
+@ stub RpcFreeAuthorizationContext # wxp\r
+@ stub RpcGetAsyncCallStatus\r
+@ stub RpcIfIdVectorFree\r
+@ stub RpcIfInqId\r
+@ stub RpcImpersonateClient\r
+@ stub RpcInitializeAsyncHandle\r
+@ stub RpcMgmtBindingInqParameter # win9x\r
+@ stub RpcMgmtBindingSetParameter # win9x\r
+@ stub RpcMgmtEnableIdleCleanup\r
+@ stub RpcMgmtEpEltInqBegin\r
+@ stub RpcMgmtEpEltInqDone\r
+@ stub RpcMgmtEpEltInqNextA\r
+@ stub RpcMgmtEpEltInqNextW\r
+@ stub RpcMgmtEpUnregister\r
+@ stub RpcMgmtInqComTimeout\r
+@ stub RpcMgmtInqDefaultProtectLevel\r
+@ stub RpcMgmtInqIfIds\r
+@ stub RpcMgmtInqParameter # win9x\r
+@ stub RpcMgmtInqServerPrincNameA\r
+@ stub RpcMgmtInqServerPrincNameW\r
+@ stub RpcMgmtInqStats\r
+@ stub RpcMgmtIsServerListening\r
+@ stub RpcMgmtSetAuthorizationFn\r
+@ stub RpcMgmtSetCancelTimeout\r
+@ stub RpcMgmtSetComTimeout\r
+@ stub RpcMgmtSetParameter # win9x\r
+@ stub RpcMgmtSetServerStackSize\r
+@ stub RpcMgmtStatsVectorFree\r
+@ stdcall RpcMgmtStopServerListening(ptr)\r
+@ stdcall RpcMgmtWaitServerListen()\r
+@ stub RpcNetworkInqProtseqsA\r
+@ stub RpcNetworkInqProtseqsW\r
+@ stdcall RpcNetworkIsProtseqValidA(ptr)\r
+@ stdcall RpcNetworkIsProtseqValidW(ptr)\r
+@ stub RpcNsBindingInqEntryNameA\r
+@ stub RpcNsBindingInqEntryNameW\r
+@ stub RpcObjectInqType\r
+@ stub RpcObjectSetInqFn\r
+@ stdcall RpcObjectSetType(ptr ptr)\r
+@ stub RpcProtseqVectorFreeA\r
+@ stub RpcProtseqVectorFreeW\r
+@ stdcall RpcRaiseException(long)\r
+@ stub RpcRegisterAsyncInfo\r
+@ stub RpcRevertToSelf\r
+@ stub RpcRevertToSelfEx\r
+@ stdcall RpcServerInqBindings(ptr)\r
+@ stub RpcServerInqCallAttributesA # wxp\r
+@ stub RpcServerInqCallAttributesW # wxp\r
+@ stub RpcServerInqDefaultPrincNameA\r
+@ stub RpcServerInqDefaultPrincNameW\r
+@ stub RpcServerInqIf\r
+@ stdcall RpcServerListen(long long long)\r
+@ stdcall RpcServerRegisterAuthInfoA(str  long ptr ptr)\r
+@ stdcall RpcServerRegisterAuthInfoW(wstr long ptr ptr)\r
+@ stdcall RpcServerRegisterIf(ptr ptr ptr)\r
+@ stdcall RpcServerRegisterIfEx(ptr ptr ptr long long ptr)\r
+@ stdcall RpcServerRegisterIf2(ptr ptr ptr long long long ptr)\r
+@ stub RpcServerTestCancel\r
+@ stdcall RpcServerUnregisterIf(ptr ptr long)\r
+@ stdcall RpcServerUnregisterIfEx(ptr ptr long)\r
+@ stub RpcServerUseAllProtseqs\r
+@ stub RpcServerUseAllProtseqsEx\r
+@ stub RpcServerUseAllProtseqsIf\r
+@ stub RpcServerUseAllProtseqsIfEx\r
+@ stdcall RpcServerUseProtseqA(str long ptr)\r
+@ stdcall RpcServerUseProtseqW(wstr long ptr)\r
+@ stub RpcServerUseProtseqExA\r
+@ stub RpcServerUseProtseqExW\r
+@ stdcall RpcServerUseProtseqEpA(str  long str  ptr)\r
+@ stdcall RpcServerUseProtseqEpW(wstr long wstr ptr)\r
+@ stdcall RpcServerUseProtseqEpExA(str  long str  ptr ptr)\r
+@ stdcall RpcServerUseProtseqEpExW(wstr long wstr ptr ptr)\r
+@ stub RpcServerUseProtseqIfA\r
+@ stub RpcServerUseProtseqIfW\r
+@ stub RpcServerUseProtseqIfExA\r
+@ stub RpcServerUseProtseqIfExW\r
+@ stub RpcServerYield\r
+@ stub RpcSmAllocate\r
+@ stub RpcSmClientFree\r
+@ stub RpcSmDestroyClientContext\r
+@ stub RpcSmDisableAllocate\r
+@ stub RpcSmEnableAllocate\r
+@ stub RpcSmFree\r
+@ stub RpcSmGetThreadHandle\r
+@ stub RpcSmSetClientAllocFree\r
+@ stub RpcSmSetThreadHandle\r
+@ stub RpcSmSwapClientAllocFree\r
+@ stub RpcSsAllocate\r
+@ stub RpcSsContextLockExclusive # wxp\r
+@ stub RpcSsContextLockShared # wxp\r
+@ stub RpcSsDestroyClientContext\r
+@ stub RpcSsDisableAllocate\r
+@ stub RpcSsDontSerializeContext\r
+@ stub RpcSsEnableAllocate\r
+@ stub RpcSsFree\r
+@ stub RpcSsGetContextBinding\r
+@ stub RpcSsGetThreadHandle\r
+@ stub RpcSsSetClientAllocFree\r
+@ stub RpcSsSetThreadHandle\r
+@ stub RpcSsSwapClientAllocFree\r
+@ stdcall RpcStringBindingComposeA(str  str  str  str  str  ptr)\r
+@ stdcall RpcStringBindingComposeW(wstr wstr wstr wstr wstr ptr)\r
+@ stdcall RpcStringBindingParseA(str  ptr ptr ptr ptr ptr)\r
+@ stdcall RpcStringBindingParseW(wstr ptr ptr ptr ptr ptr)\r
+@ stdcall RpcStringFreeA(ptr)\r
+@ stdcall RpcStringFreeW(ptr)\r
+@ stub RpcTestCancel\r
+@ stub RpcUserFree # wxp\r
+\r
+@ stub TowerConstruct\r
+@ stub TowerExplode\r
+\r
+@ stub SimpleTypeAlignment # wxp\r
+@ stub SimpleTypeBufferSize # wxp\r
+@ stub SimpleTypeMemorySize # wxp\r
+\r
+@ stub pfnFreeRoutines # wxp\r
+@ stub pfnMarshallRouteines # wxp\r
+@ stub pfnSizeRoutines # wxp\r
+@ stub pfnUnmarshallRouteines # wxp\r
+\r
+@ stdcall UuidCompare(ptr ptr ptr)\r
+@ stdcall UuidCreate(ptr)\r
+@ stdcall UuidCreateSequential(ptr) # win 2000\r
+@ stdcall UuidCreateNil(ptr)\r
+@ stdcall UuidEqual(ptr ptr ptr)\r
+@ stdcall UuidFromStringA(str ptr)\r
+@ stdcall UuidFromStringW(wstr ptr)\r
+@ stdcall UuidHash(ptr ptr)\r
+@ stdcall UuidIsNil(ptr ptr)\r
+@ stdcall UuidToStringA(ptr ptr)\r
+@ stdcall UuidToStringW(ptr ptr)\r
+\r
+@ stdcall CStdStubBuffer_QueryInterface(ptr ptr ptr)\r
+@ stdcall CStdStubBuffer_AddRef(ptr)\r
+@ stdcall CStdStubBuffer_Connect(ptr ptr)\r
+@ stdcall CStdStubBuffer_Disconnect(ptr)\r
+@ stdcall CStdStubBuffer_Invoke(ptr ptr ptr)\r
+@ stdcall CStdStubBuffer_IsIIDSupported(ptr ptr)\r
+@ stdcall CStdStubBuffer_CountRefs(ptr)\r
+@ stdcall CStdStubBuffer_DebugServerQueryInterface(ptr ptr)\r
+@ stdcall CStdStubBuffer_DebugServerRelease(ptr ptr)\r
+@ stdcall NdrCStdStubBuffer_Release(ptr ptr)\r
+@ stub NdrCStdStubBuffer2_Release\r
+\r
+@ stdcall IUnknown_QueryInterface_Proxy(ptr ptr ptr)\r
+@ stdcall IUnknown_AddRef_Proxy(ptr)\r
+@ stdcall IUnknown_Release_Proxy(ptr)\r
+\r
+@ stdcall NdrDllCanUnloadNow(ptr)\r
+@ stdcall NdrDllGetClassObject(ptr ptr ptr ptr ptr ptr)\r
+@ stdcall NdrDllRegisterProxy(long ptr ptr)\r
+@ stdcall NdrDllUnregisterProxy(long ptr ptr)\r
+\r
+@ stdcall NdrAllocate(ptr long)\r
+@ stub NdrAsyncClientCall\r
+@ stub NdrAsyncServerCall\r
+@ stdcall NdrClearOutParameters(ptr ptr ptr)\r
+@ stub NdrClientCall\r
+@ varargs NdrClientCall2(ptr ptr)\r
+@ stub NdrClientInitialize\r
+@ stdcall NdrClientInitializeNew(ptr ptr ptr long)\r
+@ stub NdrContextHandleInitialize\r
+@ stub NdrContextHandleSize\r
+@ stdcall NdrConvert(ptr ptr)\r
+@ stdcall NdrConvert2(ptr ptr long)\r
+@ stub NdrCorrelationFree\r
+@ stub NdrCorrelationInitialize\r
+@ stub NdrCorrelationPass\r
+@ stub CreateServerInterfaceFromStub # wxp\r
+@ stub NdrDcomAsyncClientCall\r
+@ stub NdrDcomAsyncStubCall\r
+@ stdcall NdrFreeBuffer(ptr)\r
+@ stub NdrFullPointerFree\r
+@ stub NdrFullPointerInsertRefId\r
+@ stub NdrFullPointerQueryPointer\r
+@ stub NdrFullPointerQueryRefId\r
+@ stub NdrFullPointerXlatFree\r
+@ stub NdrFullPointerXlatInit\r
+@ stdcall NdrGetBuffer(ptr long ptr)\r
+@ stub NdrGetDcomProtocolVersion\r
+@ stub NdrGetSimpleTypeBufferAlignment # wxp\r
+@ stub NdrGetSimpleTypeBufferSize # wxp\r
+@ stub NdrGetSimpleTypeMemorySize # wxp\r
+@ stub NdrGetTypeFlags # wxp\r
+@ stub NdrGetPartialBuffer\r
+@ stub NdrGetPipeBuffer\r
+@ stub NdrGetUserMarshallInfo\r
+@ stub NdrIsAppDoneWithPipes\r
+@ stub NdrMapCommAndFaultStatus\r
+@ stub NdrMarkNextActivePipe\r
+@ stub NdrMesProcEncodeDecode\r
+@ stub NdrMesProcEncodeDecode2\r
+@ stub NdrMesSimpleTypeAlignSize\r
+@ stub NdrMesSimpleTypeDecode\r
+@ stub NdrMesSimpleTypeEncode\r
+@ stub NdrMesTypeAlignSize\r
+@ stub NdrMesTypeAlignSize2\r
+@ stub NdrMesTypeDecode\r
+@ stub NdrMesTypeDecode2\r
+@ stub NdrMesTypeEncode\r
+@ stub NdrMesTypeEncode2\r
+@ stub NdrMesTypeFree2\r
+@ stub NdrNsGetBuffer\r
+@ stub NdrNsSendReceive\r
+@ stdcall NdrOleAllocate(long)\r
+@ stdcall NdrOleFree(ptr)\r
+@ stub NdrOutInit # wxp\r
+@ stub NdrPartialIgnoreClientBufferSize # wxp\r
+@ stub NdrPartialIgnoreClientMarshall # wxp\r
+@ stub NdrPartialIgnoreServerInitialize # wxp\r
+@ stub NdrPartialIgnoreServerUnmarshall # wxp\r
+@ stub NdrPipePull\r
+@ stub NdrPipePush\r
+@ stub NdrPipeSendReceive\r
+@ stub NdrPipesDone\r
+@ stub NdrPipesInitialize\r
+@ stdcall NdrProxyErrorHandler(long)\r
+@ stdcall NdrProxyFreeBuffer(ptr ptr)\r
+@ stdcall NdrProxyGetBuffer(ptr ptr)\r
+@ stdcall NdrProxyInitialize(ptr ptr ptr ptr long)\r
+@ stdcall NdrProxySendReceive(ptr ptr)\r
+@ stub NdrRangeUnmarshall\r
+@ stub NdrRpcSmClientAllocate\r
+@ stub NdrRpcSmClientFree\r
+@ stub NdrRpcSmSetClientToOsf\r
+@ stub NdrRpcSsDefaultAllocate\r
+@ stub NdrRpcSsDefaultFree\r
+@ stub NdrRpcSsDisableAllocate\r
+@ stub NdrRpcSsEnableAllocate\r
+@ stdcall NdrSendReceive(ptr ptr)\r
+@ stub NdrServerCall\r
+@ stub NdrServerCall2\r
+@ stub NdrStubCall\r
+@ stub NdrStubCall2\r
+@ stub NdrStubForwardingFunction\r
+@ stdcall NdrStubGetBuffer(ptr ptr ptr)\r
+@ stdcall NdrStubInitialize(ptr ptr ptr ptr)\r
+@ stub NdrStubInitializeMarshall\r
+@ stub NdrpCreateProxy # wxp\r
+@ stub NdrpCreateStub # wxp\r
+@ stub NdrpGetProcFormatString # wxp\r
+@ stub NdrpGetTypeFormatString # wxp\r
+@ stub NdrpGetTypeGenCookie # wxp\r
+@ stub NdrpMemoryIncrement # wxp\r
+@ stub NdrpReleaseTypeFormatString # wxp\r
+@ stub NdrpReleaseTypeGenCookie # wxp\r
+@ stub NdrpSetRpcSsDefaults\r
+@ stub NdrpVarVtOfTypeDesc # wxp\r
+@ stub NdrTypeFlags # wxp\r
+@ stub NdrTypeFree # wxp\r
+@ stub NdrTypeMarshall # wxp\r
+@ stub NdrTypeSize # wxp\r
+@ stub NdrTypeUnmarshall # wxp\r
+@ stub NdrUnmarshallBasetypeInline # wxp\r
+\r
+@ stub NdrByteCountPointerBufferSize\r
+@ stub NdrByteCountPointerFree\r
+@ stub NdrByteCountPointerMarshall\r
+@ stub NdrByteCountPointerUnmarshall\r
+@ stub NdrClientContextMarshall\r
+@ stub NdrClientContextUnmarshall\r
+@ stdcall NdrComplexArrayBufferSize(ptr ptr ptr)\r
+@ stdcall NdrComplexArrayFree(ptr ptr ptr)\r
+@ stdcall NdrComplexArrayMarshall(ptr ptr ptr)\r
+@ stdcall NdrComplexArrayMemorySize(ptr ptr)\r
+@ stdcall NdrComplexArrayUnmarshall(ptr ptr ptr long)\r
+@ stdcall NdrComplexStructBufferSize(ptr ptr ptr)\r
+@ stdcall NdrComplexStructFree(ptr ptr ptr)\r
+@ stdcall NdrComplexStructMarshall(ptr ptr ptr)\r
+@ stdcall NdrComplexStructMemorySize(ptr ptr)\r
+@ stdcall NdrComplexStructUnmarshall(ptr ptr ptr long)\r
+@ stdcall NdrConformantArrayBufferSize(ptr ptr ptr)\r
+@ stdcall NdrConformantArrayFree(ptr ptr ptr)\r
+@ stdcall NdrConformantArrayMarshall(ptr ptr ptr)\r
+@ stdcall NdrConformantArrayMemorySize(ptr ptr)\r
+@ stdcall NdrConformantArrayUnmarshall(ptr ptr ptr long)\r
+@ stdcall NdrConformantStringBufferSize(ptr ptr ptr)\r
+@ stdcall NdrConformantStringMarshall(ptr ptr ptr)\r
+@ stdcall NdrConformantStringMemorySize(ptr ptr)\r
+@ stdcall NdrConformantStringUnmarshall(ptr ptr ptr long)\r
+@ stub NdrConformantStructBufferSize\r
+@ stub NdrConformantStructFree\r
+@ stub NdrConformantStructMarshall\r
+@ stub NdrConformantStructMemorySize\r
+@ stub NdrConformantStructUnmarshall\r
+@ stdcall NdrConformantVaryingArrayBufferSize(ptr ptr ptr)\r
+@ stdcall NdrConformantVaryingArrayFree(ptr ptr ptr)\r
+@ stdcall NdrConformantVaryingArrayMarshall(ptr ptr ptr)\r
+@ stdcall NdrConformantVaryingArrayMemorySize(ptr ptr)\r
+@ stdcall NdrConformantVaryingArrayUnmarshall(ptr ptr ptr long)\r
+@ stub NdrConformantVaryingStructBufferSize\r
+@ stub NdrConformantVaryingStructFree\r
+@ stub NdrConformantVaryingStructMarshall\r
+@ stub NdrConformantVaryingStructMemorySize\r
+@ stub NdrConformantVaryingStructUnmarshall\r
+@ stub NdrEncapsulatedUnionBufferSize\r
+@ stub NdrEncapsulatedUnionFree\r
+@ stub NdrEncapsulatedUnionMarshall\r
+@ stub NdrEncapsulatedUnionMemorySize\r
+@ stub NdrEncapsulatedUnionUnmarshall\r
+@ stub NdrFixedArrayBufferSize\r
+@ stub NdrFixedArrayFree\r
+@ stub NdrFixedArrayMarshall\r
+@ stub NdrFixedArrayMemorySize\r
+@ stub NdrFixedArrayUnmarshall\r
+@ stub NdrHardStructBufferSize\r
+@ stub NdrHardStructFree\r
+@ stub NdrHardStructMarshall\r
+@ stub NdrHardStructMemorySize\r
+@ stub NdrHardStructUnmarshall\r
+@ stdcall NdrInterfacePointerBufferSize(ptr ptr ptr)\r
+@ stdcall NdrInterfacePointerFree(ptr ptr ptr)\r
+@ stdcall NdrInterfacePointerMarshall(ptr ptr ptr)\r
+@ stdcall NdrInterfacePointerMemorySize(ptr ptr)\r
+@ stdcall NdrInterfacePointerUnmarshall(ptr ptr ptr long)\r
+@ stub NdrNonConformantStringBufferSize\r
+@ stub NdrNonConformantStringMarshall\r
+@ stub NdrNonConformantStringMemorySize\r
+@ stub NdrNonConformantStringUnmarshall\r
+@ stub NdrNonEncapsulatedUnionBufferSize\r
+@ stub NdrNonEncapsulatedUnionFree\r
+@ stub NdrNonEncapsulatedUnionMarshall\r
+@ stub NdrNonEncapsulatedUnionMemorySize\r
+@ stub NdrNonEncapsulatedUnionUnmarshall\r
+@ stdcall NdrPointerBufferSize(ptr ptr ptr)\r
+@ stdcall NdrPointerFree(ptr ptr ptr)\r
+@ stdcall NdrPointerMarshall(ptr ptr ptr)\r
+@ stdcall NdrPointerMemorySize(ptr ptr)\r
+@ stdcall NdrPointerUnmarshall(ptr ptr ptr long)\r
+@ stub NdrServerContextMarshall\r
+@ stub NdrServerContextUnmarshall\r
+@ stub NdrServerContextNewMarshall # wxp\r
+@ stub NdrServerContextNewUnmarshall # wxp\r
+@ stub NdrServerInitialize\r
+@ stub NdrServerInitializeMarshall\r
+@ stdcall NdrServerInitializeNew(ptr ptr ptr)\r
+@ stub NdrServerInitializePartial # wxp\r
+@ stub NdrServerInitializeUnmarshall\r
+@ stub NdrServerMarshall\r
+@ stub NdrServerUnmarshall\r
+@ stdcall NdrSimpleStructBufferSize(ptr ptr ptr)\r
+@ stdcall NdrSimpleStructFree(ptr ptr ptr)\r
+@ stdcall NdrSimpleStructMarshall(ptr ptr ptr)\r
+@ stdcall NdrSimpleStructMemorySize(ptr ptr)\r
+@ stdcall NdrSimpleStructUnmarshall(ptr ptr ptr long)\r
+@ stdcall NdrSimpleTypeMarshall(ptr ptr long)\r
+@ stdcall NdrSimpleTypeUnmarshall(ptr ptr long)\r
+@ stdcall NdrUserMarshalBufferSize(ptr ptr ptr)\r
+@ stdcall NdrUserMarshalFree(ptr ptr ptr)\r
+@ stdcall NdrUserMarshalMarshall(ptr ptr ptr)\r
+@ stdcall NdrUserMarshalMemorySize(ptr ptr)\r
+@ stub NdrUserMarshalSimpleTypeConvert\r
+@ stdcall NdrUserMarshalUnmarshall(ptr ptr ptr long)\r
+@ stub NdrVaryingArrayBufferSize\r
+@ stub NdrVaryingArrayFree\r
+@ stub NdrVaryingArrayMarshall\r
+@ stub NdrVaryingArrayMemorySize\r
+@ stub NdrVaryingArrayUnmarshall\r
+@ stub NdrXmitOrRepAsBufferSize\r
+@ stub NdrXmitOrRepAsFree\r
+@ stub NdrXmitOrRepAsMarshall\r
+@ stub NdrXmitOrRepAsMemorySize\r
+@ stub NdrXmitOrRepAsUnmarshall\r
+\r
+@ stub NDRCContextBinding\r
+@ stub NDRCContextMarshall\r
+@ stub NDRCContextUnmarshall\r
+@ stub NDRSContextMarshall\r
+@ stub NDRSContextUnmarshall\r
+@ stub NDRSContextMarshallEx\r
+@ stub NDRSContextUnmarshallEx\r
+@ stub NDRSContextMarshall2\r
+@ stub NDRSContextUnmarshall2\r
+@ stub NDRcopy\r
+\r
+@ stub MIDL_wchar_strcpy\r
+@ stub MIDL_wchar_strlen\r
+@ stub char_array_from_ndr\r
+@ stub char_from_ndr\r
+@ stub data_from_ndr\r
+@ stub data_into_ndr\r
+@ stub data_size_ndr\r
+@ stub double_array_from_ndr\r
+@ stub double_from_ndr\r
+@ stub enum_from_ndr\r
+@ stub float_array_from_ndr\r
+@ stub float_from_ndr\r
+@ stub long_array_from_ndr\r
+@ stub long_from_ndr\r
+@ stub long_from_ndr_temp\r
+@ stub short_array_from_ndr\r
+@ stub short_from_ndr\r
+@ stub short_from_ndr_temp\r
+@ stub tree_into_ndr\r
+@ stub tree_peek_ndr\r
+@ stub tree_size_ndr\r
+\r
+@ stub I_RpcAbortAsyncCall\r
+@ stub I_RpcAllocate\r
+@ stub I_RpcAsyncAbortCall\r
+@ stub I_RpcAsyncSendReceive # NT4\r
+@ stub I_RpcAsyncSetHandle\r
+@ stub I_RpcBCacheAllocate\r
+@ stub I_RpcBCacheFree\r
+@ stub I_RpcBindingCopy\r
+@ stub I_RpcBindingInqConnId\r
+@ stub I_RpcBindingInqDynamicEndPoint\r
+@ stub I_RpcBindingInqDynamicEndPointA\r
+@ stub I_RpcBindingInqDynamicEndPointW\r
+@ stub I_RpcBindingInqLocalClientPID # wxp\r
+@ stub I_RpcBindingInqSecurityContext\r
+@ stub I_RpcBindingInqTransportType\r
+@ stub I_RpcBindingInqWireIdForSnego\r
+@ stub I_RpcBindingIsClientLocal\r
+@ stub I_RpcBindingToStaticStringBindingW\r
+@ stdcall I_RpcBindingSetAsync(ptr ptr)\r
+# 9x version of I_RpcBindingSetAsync has 3 arguments, not 2\r
+@ stub I_RpcClearMutex\r
+@ stub I_RpcConnectionInqSockBuffSize\r
+@ stub I_RpcConnectionInqSockBuffSize2\r
+@ stub I_RpcConnectionSetSockBuffSize\r
+@ stub I_RpcDeleteMutex\r
+@ stub I_RpcEnableWmiTrace # wxp\r
+@ stub I_RpcExceptionFilter # wxp\r
+@ stub I_RpcFree\r
+@ stdcall I_RpcFreeBuffer(ptr)\r
+@ stub I_RpcFreePipeBuffer\r
+@ stub I_RpcGetAssociationContext\r
+@ stdcall I_RpcGetBuffer(ptr)\r
+@ stub I_RpcGetBufferWithObject\r
+@ stub I_RpcGetCurrentCallHandle\r
+@ stub I_RpcGetExtendedError\r
+@ stub I_RpcGetServerContextList\r
+@ stub I_RpcGetThreadEvent # win9x\r
+@ stub I_RpcGetThreadWindowHandle # win9x\r
+@ stub I_RpcIfInqTransferSyntaxes\r
+@ stub I_RpcLaunchDatagramReceiveThread # win9x\r
+@ stub I_RpcLogEvent\r
+@ stub I_RpcMapWin32Status\r
+@ stub I_RpcMonitorAssociation\r
+@ stub I_RpcNegotiateTransferSyntax # wxp\r
+@ stub I_RpcNsBindingSetEntryName\r
+@ stub I_RpcNsBindingSetEntryNameA\r
+@ stub I_RpcNsBindingSetEntryNameW\r
+@ stub I_RpcNsInterfaceExported\r
+@ stub I_RpcNsInterfaceUnexported\r
+@ stub I_RpcParseSecurity\r
+@ stub I_RpcPauseExecution\r
+@ stub I_RpcProxyNewConnection # wxp\r
+@ stub I_RpcReallocPipeBuffer\r
+@ stdcall I_RpcReceive(ptr)\r
+@ stub I_RpcRequestMutex\r
+@ stdcall I_RpcSend(ptr)\r
+@ stdcall I_RpcSendReceive(ptr)\r
+@ stub I_RpcServerAllocateIpPort\r
+@ stub I_RpcServerInqAddressChangeFn\r
+@ stub I_RpcServerInqLocalConnAddress # wxp\r
+@ stub I_RpcServerInqTransportType\r
+@ stub I_RpcServerRegisterForwardFunction\r
+@ stub I_RpcServerSetAddressChangeFn\r
+@ stdcall I_RpcServerStartListening(ptr) # win9x\r
+@ stdcall I_RpcServerStopListening() # win9x\r
+@ stub I_RpcServerUnregisterEndpointA # win9x\r
+@ stub I_RpcServerUnregisterEndpointW # win9x\r
+@ stub I_RpcServerUseProtseq2A\r
+@ stub I_RpcServerUseProtseq2W\r
+@ stub I_RpcServerUseProtseqEp2A\r
+@ stub I_RpcServerUseProtseqEp2W\r
+@ stub I_RpcSetAsyncHandle\r
+@ stub I_RpcSetAssociationContext # win9x\r
+@ stub I_RpcSetServerContextList\r
+@ stub I_RpcSetThreadParams # win9x\r
+@ stub I_RpcSetWMsgEndpoint # NT4\r
+@ stub I_RpcSsDontSerializeContext\r
+@ stub I_RpcSystemFunction001 # wxp (oh, brother!)\r
+@ stub I_RpcStopMonitorAssociation\r
+@ stub I_RpcTransCancelMigration # win9x\r
+@ stub I_RpcTransClientMaxFrag # win9x\r
+@ stub I_RpcTransClientReallocBuffer # win9x\r
+@ stub I_RpcTransConnectionAllocatePacket\r
+@ stub I_RpcTransConnectionFreePacket\r
+@ stub I_RpcTransConnectionReallocPacket\r
+@ stub I_RpcTransDatagramAllocate\r
+@ stub I_RpcTransDatagramAllocate2\r
+@ stub I_RpcTransDatagramFree\r
+@ stub I_RpcTransGetAddressList\r
+@ stub I_RpcTransGetThreadEvent\r
+@ stub I_RpcTransIoCancelled\r
+@ stub I_RpcTransMaybeMakeReceiveAny # win9x\r
+@ stub I_RpcTransMaybeMakeReceiveDirect # win9x\r
+@ stub I_RpcTransPingServer # win9x\r
+@ stub I_RpcTransServerFindConnection # win9x\r
+@ stub I_RpcTransServerFreeBuffer # win9x\r
+@ stub I_RpcTransServerMaxFrag # win9x\r
+@ stub I_RpcTransServerNewConnection\r
+@ stub I_RpcTransServerProtectThread # win9x\r
+@ stub I_RpcTransServerReallocBuffer # win9x\r
+@ stub I_RpcTransServerReceiveDirectReady # win9x\r
+@ stub I_RpcTransServerUnprotectThread # win9x\r
+@ stub I_RpcTurnOnEEInfoPropagation # wxp\r
+@ stdcall I_RpcWindowProc(ptr long long long) # win9x\r
+@ stub I_RpcltDebugSetPDUFilter\r
+@ stub I_UuidCreate\r
+\r
+@ stdcall CreateProxyFromTypeInfo(ptr ptr ptr ptr ptr)\r
+@ stub CreateStubFromTypeInfo\r
+@ stub PerformRpcInitialization\r
+@ stub StartServiceIfNecessary # win9x\r
+@ stub GlobalMutexClearExternal\r
+@ stub GlobalMutexRequestExternal\r
diff --git a/reactos/lib/rpcrt4/rpcrt4_main.c b/reactos/lib/rpcrt4/rpcrt4_main.c
new file mode 100644 (file)
index 0000000..baf7914
--- /dev/null
@@ -0,0 +1,750 @@
+/*\r
+ *  RPCRT4\r
+ *\r
+ * Copyright 2000 Huw D M Davies 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
+ * WINE RPC TODO's (and a few TODONT's)\r
+ *\r
+ * - Ove's decreasingly incomplete widl is an IDL compiler for wine.  For widl\r
+ *   to be wine's only IDL compiler, a fair bit of work remains to be done.\r
+ *   until then we have used some midl-generated stuff.  (What?)\r
+ *   widl currently doesn't generate stub/proxy files required by wine's (O)RPC\r
+ *   capabilities -- nor does it make those lovely format strings :(\r
+ *   The MS MIDL compiler does some really esoteric stuff.  Of course Ove has\r
+ *   started with the less esoteric stuff.  There are also lots of nice\r
+ *   comments in there if you want to flex your bison and help build this monster.\r
+ *\r
+ * - RPC has a quite featureful error handling mechanism; basically none of this is\r
+ *   implemented right now.  We also have deficiencies on the compiler side, where\r
+ *   wine's __TRY / __EXCEPT / __FINALLY macros are not even used for RpcTryExcept & co,\r
+ *   due to syntactic differences! (we can fix it with widl by using __TRY)\r
+ *\r
+ * - There are several different memory allocation schemes for MSRPC.\r
+ *   I don't even understand what they all are yet, much less have them\r
+ *   properly implemented.  Surely we are supposed to be doing something with\r
+ *   the user-provided allocation/deallocation functions, but so far,\r
+ *   I don't think we are doing this...\r
+ *\r
+ * - MSRPC provides impersonation capabilities which currently are not possible\r
+ *   to implement in wine.  At the very least we should implement the authorization\r
+ *   API's & gracefully ignore the irrelevant stuff (to an extent we already do).\r
+ *\r
+ * - Some transports are not yet implemented.  The existing transport implementations\r
+ *   are incomplete and may be bug-infested.\r
+ * \r
+ * - The various transports that we do support ought to be supported in a more\r
+ *   object-oriented manner, as in DCE's RPC implementation, instead of cluttering\r
+ *   up the code with conditionals like we do now.\r
+ * \r
+ * - Data marshalling: So far, only the beginnings of a full implementation\r
+ *   exist in wine.  NDR protocol itself is documented, but the MS API's to\r
+ *   convert data-types in memory into NDR are not.  This is challenging work,\r
+ *   and has supposedly been "at the top of Greg's queue" for several months now.\r
+ *\r
+ * - ORPC is RPC for OLE; once we have a working RPC framework, we can\r
+ *   use it to implement out-of-process OLE client/server communications.\r
+ *   ATM there is maybe a disconnect between the marshalling in the OLE DLL's\r
+ *   and the marshalling going on here [TODO: well, is there or not?]\r
+ * \r
+ * - In-source API Documentation, at least for those functions which we have\r
+ *   implemented, but preferably for everything we can document, would be nice,\r
+ *   since some of this stuff is quite obscure.\r
+ *\r
+ * - Name services... [TODO: what about them]\r
+ *\r
+ * - Protocol Towers: Totally unimplemented.... I think.\r
+ *\r
+ * - Context Handle Rundown: whatever that is.\r
+ *\r
+ * - Nested RPC's: Totally unimplemented.\r
+ *\r
+ * - Statistics: we are supposed to be keeping various counters.  we aren't.\r
+ *\r
+ * - Async RPC: Unimplemented.\r
+ *\r
+ * - XML/http RPC: Somewhere there's an XML fiend that wants to do this! Betcha\r
+ *   we could use these as a transport for RPC's across computers without a\r
+ *   permissions and/or licensing crisis.\r
+ *\r
+ * - The NT "ports" API, aka LPC.  Greg claims this is on his radar.  Might (or\r
+ *   might not) enable users to get some kind of meaningful result out of\r
+ *   NT-based native rpcrt4's.  Commonly-used transport for self-to-self RPC's.\r
+ *\r
+ * - ...?  More stuff I haven't thought of.  If you think of more RPC todo's\r
+ *   drop me an e-mail <gmturner007@ameritech.net> or send a patch to the\r
+ *   wine-patches mailing list.\r
+ */\r
+\r
+#include "config.h"\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "windef.h"\r
+#include "winerror.h"\r
+#include "winbase.h"\r
+#include "winuser.h"\r
+#include "iptypes.h"\r
+#include "iphlpapi.h"\r
+#include "wine/unicode.h"\r
+#include "rpc.h"\r
+\r
+#include "ole2.h"\r
+#include "rpcndr.h"\r
+#include "rpcproxy.h"\r
+\r
+#include "rpc_binding.h"\r
+#include "rpcss_np_client.h"\r
+\r
+#include "wine/debug.h"\r
+\r
+WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
+\r
+static UUID uuid_nil;\r
+static HANDLE master_mutex;\r
+\r
+HANDLE RPCRT4_GetMasterMutex(void)\r
+{\r
+    return master_mutex;\r
+}\r
+\r
+static CRITICAL_SECTION uuid_cs;\r
+static CRITICAL_SECTION_DEBUG critsect_debug =\r
+{\r
+    0, 0, &uuid_cs,\r
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },\r
+      0, 0, { 0, (DWORD)(__FILE__ ": uuid_cs") }\r
+};\r
+static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 };\r
+\r
+/***********************************************************************\r
+ * DllMain\r
+ *\r
+ * PARAMS\r
+ *     hinstDLL    [I] handle to the DLL's instance\r
+ *     fdwReason   [I]\r
+ *     lpvReserved [I] reserved, must be NULL\r
+ *\r
+ * RETURNS\r
+ *     Success: TRUE\r
+ *     Failure: FALSE\r
+ */\r
+\r
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\r
+{\r
+    switch (fdwReason) {\r
+    case DLL_PROCESS_ATTACH:\r
+        DisableThreadLibraryCalls(hinstDLL);\r
+        master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME);\r
+        if (!master_mutex)\r
+          ERR("Failed to create master mutex\n");\r
+        break;\r
+\r
+    case DLL_PROCESS_DETACH:\r
+        CloseHandle(master_mutex);\r
+        master_mutex = NULL;\r
+        break;\r
+    }\r
+\r
+    return TRUE;\r
+}\r
+\r
+/*************************************************************************\r
+ *           RpcStringFreeA   [RPCRT4.@]\r
+ *\r
+ * Frees a character string allocated by the RPC run-time library.\r
+ *\r
+ * RETURNS\r
+ *\r
+ *  S_OK if successful.\r
+ */\r
+RPC_STATUS WINAPI RpcStringFreeA(unsigned char** String)\r
+{\r
+  HeapFree( GetProcessHeap(), 0, *String);\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/*************************************************************************\r
+ *           RpcStringFreeW   [RPCRT4.@]\r
+ *\r
+ * Frees a character string allocated by the RPC run-time library.\r
+ *\r
+ * RETURNS\r
+ *\r
+ *  S_OK if successful.\r
+ */\r
+RPC_STATUS WINAPI RpcStringFreeW(unsigned short** String)\r
+{\r
+  HeapFree( GetProcessHeap(), 0, *String);\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/*************************************************************************\r
+ *           RpcRaiseException   [RPCRT4.@]\r
+ *\r
+ * Raises an exception.\r
+ */\r
+void WINAPI RpcRaiseException(RPC_STATUS exception)\r
+{\r
+  /* FIXME: translate exception? */\r
+  RaiseException(exception, 0, 0, NULL);\r
+}\r
+\r
+/*************************************************************************\r
+ * UuidCompare [RPCRT4.@]\r
+ *\r
+ * PARAMS\r
+ *     UUID *Uuid1        [I] Uuid to compare\r
+ *     UUID *Uuid2        [I] Uuid to compare\r
+ *     RPC_STATUS *Status [O] returns RPC_S_OK\r
+ * \r
+ * RETURNS\r
+ *    -1  if Uuid1 is less than Uuid2\r
+ *     0  if Uuid1 and Uuid2 are equal\r
+ *     1  if Uuid1 is greater than Uuid2\r
+ */\r
+int WINAPI UuidCompare(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status)\r
+{\r
+  int i;\r
+\r
+  TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2));\r
+\r
+  *Status = RPC_S_OK;\r
+\r
+  if (!Uuid1) Uuid1 = &uuid_nil;\r
+  if (!Uuid2) Uuid2 = &uuid_nil;\r
+\r
+  if (Uuid1 == Uuid2) return 0;\r
+\r
+  if (Uuid1->Data1 != Uuid2->Data1)\r
+    return Uuid1->Data1 < Uuid2->Data1 ? -1 : 1;\r
+\r
+  if (Uuid1->Data2 != Uuid2->Data2)\r
+    return Uuid1->Data2 < Uuid2->Data2 ? -1 : 1;\r
+\r
+  if (Uuid1->Data3 != Uuid2->Data3)\r
+    return Uuid1->Data3 < Uuid2->Data3 ? -1 : 1;\r
+\r
+  for (i = 0; i < 8; i++) {\r
+    if (Uuid1->Data4[i] < Uuid2->Data4[i])\r
+      return -1;\r
+    if (Uuid1->Data4[i] > Uuid2->Data4[i])\r
+      return 1;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/*************************************************************************\r
+ * UuidEqual [RPCRT4.@]\r
+ *\r
+ * PARAMS\r
+ *     UUID *Uuid1        [I] Uuid to compare\r
+ *     UUID *Uuid2        [I] Uuid to compare\r
+ *     RPC_STATUS *Status [O] returns RPC_S_OK\r
+ *\r
+ * RETURNS\r
+ *     TRUE/FALSE\r
+ */\r
+int WINAPI UuidEqual(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status)\r
+{\r
+  TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2));\r
+  return !UuidCompare(Uuid1, Uuid2, Status);\r
+}\r
+\r
+/*************************************************************************\r
+ * UuidIsNil [RPCRT4.@]\r
+ *\r
+ * PARAMS\r
+ *     UUID *Uuid         [I] Uuid to compare\r
+ *     RPC_STATUS *Status [O] retuns RPC_S_OK\r
+ *\r
+ * RETURNS\r
+ *     TRUE/FALSE\r
+ */\r
+int WINAPI UuidIsNil(UUID *Uuid, RPC_STATUS *Status)\r
+{\r
+  TRACE("(%s)\n", debugstr_guid(Uuid));\r
+  if (!Uuid) return TRUE;\r
+  return !UuidCompare(Uuid, &uuid_nil, Status);\r
+}\r
+\r
+ /*************************************************************************\r
+ * UuidCreateNil [RPCRT4.@]\r
+ *\r
+ * PARAMS\r
+ *     UUID *Uuid [O] returns a nil UUID\r
+ *\r
+ * RETURNS\r
+ *     RPC_S_OK\r
+ */\r
+RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)\r
+{\r
+  *Uuid = uuid_nil;\r
+  return RPC_S_OK;\r
+}\r
+\r
+/* Number of 100ns ticks per clock tick. To be safe, assume that the clock\r
+   resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */\r
+#define TICKS_PER_CLOCK_TICK 1000\r
+#define SECSPERDAY  86400\r
+#define TICKSPERSEC 10000000\r
+/* UUID system time starts at October 15, 1582 */\r
+#define SECS_15_OCT_1582_TO_1601  ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)\r
+#define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)\r
+\r
+static void RPC_UuidGetSystemTime(ULONGLONG *time)\r
+{\r
+    FILETIME ft;\r
+\r
+    GetSystemTimeAsFileTime(&ft);\r
+\r
+    *time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime;\r
+    *time += TICKS_15_OCT_1582_TO_1601;\r
+}\r
+\r
+/* Assume that a hardware address is at least 6 bytes long */ \r
+#define ADDRESS_BYTES_NEEDED 6\r
+\r
+static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)\r
+{\r
+    int i;\r
+    DWORD status = RPC_S_OK;\r
+\r
+    ULONG buflen = sizeof(IP_ADAPTER_INFO);\r
+    PIP_ADAPTER_INFO adapter = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, buflen);\r
+\r
+    if (GetAdaptersInfo(adapter, &buflen) == ERROR_BUFFER_OVERFLOW) {\r
+        HeapFree(GetProcessHeap(), 0, adapter);\r
+        adapter = (IP_ADAPTER_INFO *)HeapAlloc(GetProcessHeap(), 0, buflen);\r
+    }\r
+\r
+    if (GetAdaptersInfo(adapter, &buflen) == NO_ERROR) {\r
+        for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) {\r
+            address[i] = adapter->Address[i];\r
+        }\r
+    }\r
+    /* We can't get a hardware address, just use random numbers.\r
+       Set the multicast bit to prevent conflicts with real cards. */\r
+    else {\r
+        for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) {\r
+            address[i] = rand() & 0xff;\r
+        }\r
+\r
+        address[0] |= 0x80;\r
+        status = RPC_S_UUID_LOCAL_ONLY;\r
+    }\r
+\r
+    HeapFree(GetProcessHeap(), 0, adapter);\r
+    return status;\r
+}\r
+\r
+/*************************************************************************\r
+ *           UuidCreate   [RPCRT4.@]\r
+ *\r
+ * Creates a 128bit UUID.\r
+ *\r
+ * RETURNS\r
+ *\r
+ *  RPC_S_OK if successful.\r
+ *  RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.\r
+ *\r
+ *  FIXME: No compensation for changes across reloading\r
+ *         this dll or across reboots (e.g. clock going \r
+ *         backwards and swapped network cards). The RFC\r
+ *         suggests using NVRAM for storing persistent \r
+ *         values.\r
+ */\r
+RPC_STATUS WINAPI UuidCreate(UUID *Uuid)\r
+{\r
+    static int initialised, count;\r
+\r
+    ULONGLONG time;\r
+    static ULONGLONG timelast;\r
+    static WORD sequence;\r
+\r
+    static DWORD status;\r
+    static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH];\r
+\r
+    EnterCriticalSection(&uuid_cs);\r
+\r
+    if (!initialised) {\r
+        RPC_UuidGetSystemTime(&timelast);\r
+        count = TICKS_PER_CLOCK_TICK;\r
+\r
+        sequence = ((rand() & 0xff) << 8) + (rand() & 0xff);\r
+        sequence &= 0x1fff;\r
+\r
+        status = RPC_UuidGetNodeAddress(address);\r
+        initialised = 1;\r
+    }\r
+\r
+    /* Generate time element of the UUID. Account for going faster\r
+       than our clock as well as the clock going backwards. */\r
+    while (1) {\r
+        RPC_UuidGetSystemTime(&time);\r
+        if (time > timelast) {\r
+            count = 0;\r
+            break;\r
+        }\r
+        if (time < timelast) {\r
+            sequence = (sequence + 1) & 0x1fff;\r
+            count = 0;\r
+            break;\r
+        }\r
+        if (count < TICKS_PER_CLOCK_TICK) {\r
+            count++;\r
+            break;\r
+        }\r
+    }\r
+\r
+    timelast = time;\r
+    time += count;\r
+\r
+    /* Pack the information into the UUID structure. */\r
+\r
+    Uuid->Data1  = (unsigned long)(time & 0xffffffff);\r
+    Uuid->Data2  = (unsigned short)((time >> 32) & 0xffff);\r
+    Uuid->Data3  = (unsigned short)((time >> 48) & 0x0fff);\r
+\r
+    /* This is a version 1 UUID */\r
+    Uuid->Data3 |= (1 << 12);\r
+\r
+    Uuid->Data4[0]  = sequence & 0xff;\r
+    Uuid->Data4[1]  = (sequence & 0x3f00) >> 8;\r
+    Uuid->Data4[1] |= 0x80;\r
+\r
+    Uuid->Data4[2] = address[0];\r
+    Uuid->Data4[3] = address[1];\r
+    Uuid->Data4[4] = address[2];\r
+    Uuid->Data4[5] = address[3];\r
+    Uuid->Data4[6] = address[4];\r
+    Uuid->Data4[7] = address[5];\r
+\r
+    LeaveCriticalSection(&uuid_cs);\r
+\r
+    TRACE("%s\n", debugstr_guid(Uuid));\r
+\r
+    return status;\r
+}\r
+\r
+/*************************************************************************\r
+ *           UuidCreateSequential   [RPCRT4.@]\r
+ *\r
+ * Creates a 128bit UUID.\r
+ *\r
+ * RETURNS\r
+ *\r
+ *  RPC_S_OK if successful.\r
+ *  RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.\r
+ *\r
+ */\r
+RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid)\r
+{\r
+   return UuidCreate(Uuid);\r
+}\r
+\r
+\r
+/*************************************************************************\r
+ *           UuidHash   [RPCRT4.@]\r
+ *\r
+ * Generates a hash value for a given UUID\r
+ *\r
+ * Code based on FreeDCE implementation\r
+ *\r
+ */\r
+unsigned short WINAPI UuidHash(UUID *uuid, RPC_STATUS *Status)\r
+{\r
+  BYTE *data = (BYTE*)uuid;\r
+  short c0 = 0, c1 = 0, x, y;\r
+  unsigned int i;\r
+\r
+  if (!uuid) data = (BYTE*)(uuid = &uuid_nil);\r
+\r
+  TRACE("(%s)\n", debugstr_guid(uuid));\r
+\r
+  for (i=0; i<sizeof(UUID); i++) {\r
+    c0 += data[i];\r
+    c1 += c0;\r
+  }\r
+\r
+  x = -c1 % 255;\r
+  if (x < 0) x += 255;\r
+\r
+  y = (c1 - c0) % 255;\r
+  if (y < 0) y += 255;\r
+\r
+  *Status = RPC_S_OK;\r
+  return y*256 + x;\r
+}\r
+\r
+/*************************************************************************\r
+ *           UuidToStringA   [RPCRT4.@]\r
+ *\r
+ * Converts a UUID to a string.\r
+ *\r
+ * UUID format is 8 hex digits, followed by a hyphen then three groups of\r
+ * 4 hex digits each followed by a hyphen and then 12 hex digits\r
+ *\r
+ * RETURNS\r
+ *\r
+ *  S_OK if successful.\r
+ *  S_OUT_OF_MEMORY if unsucessful.\r
+ */\r
+RPC_STATUS WINAPI UuidToStringA(UUID *Uuid, unsigned char** StringUuid)\r
+{\r
+  *StringUuid = HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37);\r
+\r
+  if(!(*StringUuid))\r
+    return RPC_S_OUT_OF_MEMORY;\r
+\r
+  if (!Uuid) Uuid = &uuid_nil;\r
+\r
+  sprintf(*StringUuid, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
+                 Uuid->Data1, Uuid->Data2, Uuid->Data3,\r
+                 Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2],\r
+                 Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5],\r
+                 Uuid->Data4[6], Uuid->Data4[7] );\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+/*************************************************************************\r
+ *           UuidToStringW   [RPCRT4.@]\r
+ *\r
+ * Converts a UUID to a string.\r
+ *\r
+ *  S_OK if successful.\r
+ *  S_OUT_OF_MEMORY if unsucessful.\r
+ */\r
+RPC_STATUS WINAPI UuidToStringW(UUID *Uuid, unsigned short** StringUuid)\r
+{\r
+  char buf[37];\r
+\r
+  if (!Uuid) Uuid = &uuid_nil;\r
+\r
+  sprintf(buf, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
+               Uuid->Data1, Uuid->Data2, Uuid->Data3,\r
+               Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2],\r
+               Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5],\r
+               Uuid->Data4[6], Uuid->Data4[7] );\r
+\r
+  *StringUuid = RPCRT4_strdupAtoW(buf);\r
+\r
+  if(!(*StringUuid))\r
+    return RPC_S_OUT_OF_MEMORY;\r
+\r
+  return RPC_S_OK;\r
+}\r
+\r
+static const BYTE hex2bin[] =\r
+{\r
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x00 */\r
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x10 */\r
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x20 */\r
+    0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,        /* 0x30 */\r
+    0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,  /* 0x40 */\r
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        /* 0x50 */\r
+    0,10,11,12,13,14,15                     /* 0x60 */\r
+};\r
+\r
+/***********************************************************************\r
+ *             UuidFromStringA (RPCRT4.@)\r
+ */\r
+RPC_STATUS WINAPI UuidFromStringA(unsigned char* str, UUID *uuid)\r
+{\r
+    BYTE *s = (BYTE *)str;\r
+    int i;\r
+\r
+    if (!s) return UuidCreateNil( uuid );\r
+\r
+    if (strlen(s) != 36) return RPC_S_INVALID_STRING_UUID;\r
+\r
+    if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-'))\r
+        return RPC_S_INVALID_STRING_UUID;\r
+\r
+    for (i=0; i<36; i++)\r
+    {\r
+        if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue;\r
+        if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID;\r
+    }\r
+\r
+    /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */\r
+\r
+    uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 |\r
+                   hex2bin[s[4]] << 12 | hex2bin[s[5]]  << 8 | hex2bin[s[6]]  << 4 | hex2bin[s[7]]);\r
+    uuid->Data2 =  hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]];\r
+    uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]];\r
+\r
+    /* these are just sequential bytes */\r
+    uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]];\r
+    uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]];\r
+    uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]];\r
+    uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]];\r
+    uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]];\r
+    uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]];\r
+    uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]];\