- Merge RPC runtime from Wine.
authorFilip Navara <filip.navara@gmail.com>
Tue, 4 May 2004 20:10:07 +0000 (20:10 +0000)
committerFilip Navara <filip.navara@gmail.com>
Tue, 4 May 2004 20:10:07 +0000 (20:10 +0000)
svn path=/trunk/; revision=9303

30 files changed:
reactos/doc/README.WINE
reactos/include/wine/rpcfc.h [new file with mode: 0644]
reactos/include/wine/rpcss_shared.h [new file with mode: 0644]
reactos/lib/rpcrt4/.cvsignore [new file with mode: 0644]
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]
reactos/lib/rpcrt4/winehq2ros.patch [new file with mode: 0644]

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