RPCRT from rewind - rpcrt4.dll

Jürgen Schmied juergenschmied at lycos.de
Sun Jun 16 06:18:01 CDT 2002


merged rpcrt-dll part from transgaming (Ove)
---
juergen.schmied at debitel.net



-------------- next part --------------
Index: wine/dlls/rpcrt4/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/Makefile.in,v
retrieving revision 1.8
diff -d -u -r1.8 Makefile.in
--- wine/dlls/rpcrt4/Makefile.in	17 May 2002 03:37:14 -0000	1.8
+++ wine/dlls/rpcrt4/Makefile.in	16 Jun 2002 10:53:10 -0000
@@ -4,14 +4,29 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = rpcrt4.dll
-IMPORTS   = kernel32
+IMPORTS   = kernel32 ntdll advapi32
+EXTRALIBS = $(LIBUUID)
 
 LDDLLFLAGS = @LDDLLFLAGS@
 SYMBOLFILE = $(MODULE).tmp.o
 
 C_SRCS = \
+	cproxy.c \
+	cpsf.c \
+	cstub.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
 
 @MAKE_DLL_RULES@
 
 ### Dependencies:
+
+
+
+
Index: wine/dlls/rpcrt4/rpcrt4.spec
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/rpcrt4.spec,v
retrieving revision 1.17
diff -d -u -r1.17 rpcrt4.spec
--- wine/dlls/rpcrt4/rpcrt4.spec	13 Jun 2002 21:50:12 -0000	1.17
+++ wine/dlls/rpcrt4/rpcrt4.spec	16 Jun 2002 10:53:11 -0000
@@ -18,11 +18,6 @@
 @ stub MqGetContext # win9x
 @ stub MqRegisterQueue # win9x
 
-@ stdcall NdrDllCanUnloadNow(ptr) NdrDllCanUnloadNow
-@ stdcall NdrDllGetClassObject(ptr ptr ptr ptr ptr ptr) NdrDllGetClassObject
-@ stdcall NdrDllRegisterProxy(long ptr ptr) NdrDllRegisterProxy
-@ stub NdrDllUnregisterProxy
-
 @ stub RpcAbortAsyncCall
 @ stub RpcAsyncAbortCall
 @ stub RpcAsyncCancelCall
@@ -42,7 +37,7 @@
 @ stub RpcBindingInqAuthInfoW
 @ stub RpcBindingInqAuthInfoExA
 @ stub RpcBindingInqAuthInfoExW
-@ stub RpcBindingInqObject
+@ stdcall RpcBindingInqObject(ptr ptr) RpcBindingInqObject
 @ stub RpcBindingInqOption
 @ stub RpcBindingReset
 @ stub RpcBindingServerFromClient
@@ -50,23 +45,23 @@
 @ stub RpcBindingSetAuthInfoW
 @ stub RpcBindingSetAuthInfoExA
 @ stub RpcBindingSetAuthInfoExW
-@ stub RpcBindingSetObject
+@ stdcall RpcBindingSetObject(ptr ptr) RpcBindingSetObject
 @ stub RpcBindingSetOption
-@ stub RpcBindingToStringBindingA
-@ stub RpcBindingToStringBindingW
-@ stub RpcBindingVectorFree
+@ stdcall RpcBindingToStringBindingA(ptr ptr) RpcBindingToStringBindingA
+@ stdcall RpcBindingToStringBindingW(ptr ptr) RpcBindingToStringBindingW
+@ stdcall RpcBindingVectorFree(ptr) RpcBindingVectorFree
 @ stub RpcCancelAsyncCall
 @ stub RpcCancelThread
 @ stub RpcCancelThreadEx
 @ stub RpcCertGeneratePrincipalNameA
 @ stub RpcCertGeneratePrincipalNameW
 @ stub RpcCompleteAsyncCall
-@ stub RpcEpRegisterA
+@ stdcall RpcEpRegisterA(ptr ptr ptr str) RpcEpRegisterA
 @ stub RpcEpRegisterW
 @ stub RpcEpRegisterNoReplaceA
 @ stub RpcEpRegisterNoReplaceW
-@ stub RpcEpResolveBinding
-@ stub RpcEpUnregister
+@ stdcall RpcEpResolveBinding(ptr ptr) RpcEpResolveBinding
+@ stdcall RpcEpUnregister(ptr ptr ptr) RpcEpUnregister
 @ stub RpcGetAsyncCallStatus
 @ stub RpcIfIdVectorFree
 @ stub RpcIfInqId
@@ -111,7 +106,7 @@
 @ stub RpcRegisterAsyncInfo
 @ stub RpcRevertToSelf
 @ stub RpcRevertToSelfEx
-@ stub RpcServerInqBindings
+@ stdcall RpcServerInqBindings(ptr) RpcServerInqBindings
 @ stub RpcServerInqDefaultPrincNameA
 @ stub RpcServerInqDefaultPrincNameW
 @ stub RpcServerInqIf
@@ -163,49 +158,54 @@
 @ stub RpcSsSwapClientAllocFree
 @ stdcall RpcStringBindingComposeA(str  str  str  str  str  ptr) RpcStringBindingComposeA
 @ stdcall RpcStringBindingComposeW(wstr wstr wstr wstr wstr ptr) RpcStringBindingComposeW
-@ stub RpcStringBindingParseA
-@ stub RpcStringBindingParseW
+@ stdcall RpcStringBindingParseA(str  ptr ptr ptr ptr ptr) RpcStringBindingParseA
+@ stdcall RpcStringBindingParseW(wstr ptr ptr ptr ptr ptr) RpcStringBindingParseW
 @ stdcall RpcStringFreeA(ptr) RpcStringFreeA
-@ stub RpcStringFreeW
+@ stdcall RpcStringFreeW(ptr) RpcStringFreeW
 @ stub RpcTestCancel
 
 @ stub TowerConstruct
 @ stub TowerExplode
 
 @ stub UuidCompare
-@ stdcall UuidCreate(ptr) UuidCreate
-@ stdcall UuidCreateSequential(ptr) UuidCreateSequential # win 2000
-@ stub UuidCreateNil
-@ stub UuidEqual
-@ stdcall UuidFromStringA(ptr ptr) UuidFromStringA
-@ stdcall UuidFromStringW(ptr ptr) UuidFromStringW
-@ stdcall UuidHash(ptr ptr) UuidHash
-@ stub UuidIsNil
-@ stdcall UuidToStringA(ptr ptr) UuidToStringA
-@ stub UuidToStringW
+@ stdcall UuidCreate(ptr)           UuidCreate
+@ stdcall UuidCreateNil(ptr)        UuidCreateNil
+@ stdcall UuidCreateSequential(ptr) UuidCreateSequential
+@ stdcall UuidEqual(ptr ptr ptr)    UuidEqual
+@ stdcall UuidFromStringA(str  ptr) UuidFromStringA
+@ stdcall UuidFromStringW(wstr ptr) UuidFromStringW
+@ stdcall UuidHash(ptr ptr)         UuidHash
+@ stdcall UuidIsNil(ptr ptr)        UuidIsNil
+@ stdcall UuidToStringA(ptr ptr)    UuidToStringA
+@ stdcall UuidToStringW(ptr ptr)    UuidToStringW
 
-@ stub CStdStubBuffer_QueryInterface
-@ stub CStdStubBuffer_AddRef
-@ stub CStdStubBuffer_Connect
-@ stub CStdStubBuffer_Disconnect
-@ stub CStdStubBuffer_Invoke
-@ stub CStdStubBuffer_IsIIDSupported
-@ stub CStdStubBuffer_CountRefs
-@ stub CStdStubBuffer_DebugServerQueryInterface
-@ stub CStdStubBuffer_DebugServerRelease
+@ stdcall CStdStubBuffer_QueryInterface(ptr ptr) CStdStubBuffer_QueryInterface
+@ stdcall CStdStubBuffer_AddRef(ptr)             CStdStubBuffer_AddRef
+@ stdcall CStdStubBuffer_Connect(ptr ptr)        CStdStubBuffer_Connect
+@ stdcall CStdStubBuffer_Disconnect(ptr)         CStdStubBuffer_Disconnect
+@ stdcall CStdStubBuffer_Invoke(ptr ptr ptr)     CStdStubBuffer_Invoke
+@ stdcall CStdStubBuffer_IsIIDSupported(ptr ptr) CStdStubBuffer_IsIIDSupported
+@ stdcall CStdStubBuffer_CountRefs(ptr)          CStdStubBuffer_CountRefs
+@ stdcall CStdStubBuffer_DebugServerQueryInterface(ptr ptr) CStdStubBuffer_DebugServerQueryInterface
+@ stdcall CStdStubBuffer_DebugServerRelease(ptr ptr)        CStdStubBuffer_DebugServerRelease
+@ stdcall NdrCStdStubBuffer_Release(ptr ptr)  NdrCStdStubBuffer_Release
 @ stub NdrCStdStubBuffer2_Release
-@ stub NdrCStdStubBuffer_Release
 
-@ stub IUnknown_QueryInterface_Proxy
-@ stub IUnknown_AddRef_Proxy
-@ stub IUnknown_Release_Proxy
+@ stdcall IUnknown_QueryInterface_Proxy(ptr ptr ptr) IUnknown_QueryInterface_Proxy
+@ stdcall IUnknown_AddRef_Proxy(ptr)                 IUnknown_AddRef_Proxy
+@ stdcall IUnknown_Release_Proxy(ptr)                IUnknown_Release_Proxy
+
+@ stdcall NdrDllCanUnloadNow(ptr) NdrDllCanUnloadNow
+@ stdcall NdrDllGetClassObject(ptr ptr ptr ptr ptr ptr) NdrDllGetClassObject
+@ stdcall NdrDllRegisterProxy(long ptr ptr) NdrDllRegisterProxy
+@ stdcall NdrDllUnregisterProxy(long ptr ptr) NdrDllUnregisterProxy
 
 @ stub NdrAllocate
 @ stub NdrAsyncClientCall
 @ stub NdrAsyncServerCall
 @ stub NdrClearOutParameters
 @ stub NdrClientCall
-@ stub NdrClientCall2
+@ varargs NdrClientCall2(ptr ptr) NdrClientCall2
 @ stub NdrClientInitialize
 @ stub NdrClientInitializeNew
 @ stub NdrContextHandleInitialize
@@ -246,18 +246,18 @@
 @ stub NdrMesTypeFree2
 @ stub NdrNsGetBuffer
 @ stub NdrNsSendReceive
-@ stub NdrOleAllocate
-@ stub NdrOleFree
+@ stdcall NdrOleAllocate(long) NdrOleAllocate
+@ stdcall NdrOleFree(ptr) NdrOleFree
 @ stub NdrPipePull
 @ stub NdrPipePush
 @ stub NdrPipeSendReceive
 @ stub NdrPipesDone
 @ stub NdrPipesInitialize
 @ stub NdrProxyErrorHandler
-@ stub NdrProxyFreeBuffer
-@ stub NdrProxyGetBuffer
-@ stub NdrProxyInitialize
-@ stub NdrProxySendReceive
+@ stdcall NdrProxyFreeBuffer(ptr ptr) NdrProxyFreeBuffer
+@ stdcall NdrProxyGetBuffer(ptr ptr) NdrProxyGetBuffer
+@ stdcall NdrProxyInitialize(ptr ptr ptr ptr long) NdrProxyInitialize
+@ stdcall NdrProxySendReceive(ptr ptr) NdrProxySendReceive
 @ stub NdrRangeUnmarshall
 @ stub NdrRpcSmClientAllocate
 @ stub NdrRpcSmClientFree
@@ -272,7 +272,9 @@
 @ stub NdrStubCall
 @ stub NdrStubCall2
 @ stub NdrStubForwardingFunction
-@ stub NdrStubGetBuffer
+@ stdcall NdrStubGetBuffer(ptr ptr ptr) NdrStubGetBuffer
+@ stdcall NdrStubInitialize(ptr ptr ptr ptr) NdrStubInitialize
+@ stub NdrStubInitializeMarshall
 @ stub NdrpSetRpcSsDefaults
 
 @ stub NdrByteCountPointerBufferSize
@@ -325,11 +327,11 @@
 @ stub NdrHardStructMarshall
 @ stub NdrHardStructMemorySize
 @ stub NdrHardStructUnmarshall
-@ stub NdrInterfacePointerBufferSize
-@ stub NdrInterfacePointerFree
-@ stub NdrInterfacePointerMarshall
-@ stub NdrInterfacePointerMemorySize
-@ stub NdrInterfacePointerUnmarshall
+@ stdcall NdrInterfacePointerBufferSize(ptr ptr ptr) NdrInterfacePointerBufferSize
+@ stdcall NdrInterfacePointerFree(ptr ptr ptr) NdrInterfacePointerFree
+@ stdcall NdrInterfacePointerMarshall(ptr ptr ptr) NdrInterfacePointerMarshall
+@ stdcall NdrInterfacePointerMemorySize(ptr ptr) NdrInterfacePointerMemorySize
+@ stdcall NdrInterfacePointerUnmarshall(ptr ptr ptr long) NdrInterfacePointerUnmarshall
 @ stub NdrNonConformantStringBufferSize
 @ stub NdrNonConformantStringMarshall
 @ stub NdrNonConformantStringMemorySize
@@ -359,8 +361,6 @@
 @ stub NdrSimpleStructUnmarshall
 @ stub NdrSimpleTypeMarshall
 @ stub NdrSimpleTypeUnmarshall
-@ stub NdrStubInitialize
-@ stub NdrStubInitializeMarshall
 @ stub NdrUserMarshalBufferSize
 @ stub NdrUserMarshalFree
 @ stub NdrUserMarshalMarshall
@@ -428,17 +428,18 @@
 @ stub I_RpcBindingInqWireIdForSnego
 @ stub I_RpcBindingIsClientLocal
 @ stub I_RpcBindingToStaticStringBindingW
-@ stub I_RpcBindingSetAsync # win9x
+@ stdcall I_RpcBindingSetAsync(ptr ptr long) I_RpcBindingSetAsync # win9x
+# NT version of I_RpcBindingSetAsync has 2 arguments, not 3
 @ stub I_RpcClearMutex
 @ stub I_RpcConnectionInqSockBuffSize
 @ stub I_RpcConnectionInqSockBuffSize2
 @ stub I_RpcConnectionSetSockBuffSize
 @ stub I_RpcDeleteMutex
 @ stub I_RpcFree
-@ stub I_RpcFreeBuffer
+@ stdcall I_RpcFreeBuffer(ptr) I_RpcFreeBuffer
 @ stub I_RpcFreePipeBuffer
 @ stub I_RpcGetAssociationContext
-@ stub I_RpcGetBuffer
+@ stdcall I_RpcGetBuffer(ptr) I_RpcGetBuffer
 @ stub I_RpcGetBufferWithObject
 @ stub I_RpcGetCurrentCallHandle
 @ stub I_RpcGetExtendedError
@@ -458,17 +459,17 @@
 @ stub I_RpcParseSecurity
 @ stub I_RpcPauseExecution
 @ stub I_RpcReallocPipeBuffer
-@ stub I_RpcReceive
+@ stdcall I_RpcReceive(ptr) I_RpcReceive
 @ stub I_RpcRequestMutex
-@ stub I_RpcSend
-@ stub I_RpcSendReceive
+@ stdcall I_RpcSend(ptr) I_RpcSend
+@ stdcall I_RpcSendReceive(ptr) I_RpcSendReceive
 @ stub I_RpcServerAllocateIpPort
 @ stub I_RpcServerInqAddressChangeFn
 @ stub I_RpcServerInqTransportType
 @ stub I_RpcServerRegisterForwardFunction
 @ stub I_RpcServerSetAddressChangeFn
-@ stub I_RpcServerStartListening # win9x
-@ stub I_RpcServerStopListening # win9x
+@ stdcall I_RpcServerStartListening(ptr) I_RpcServerStartListening # win9x
+@ stdcall I_RpcServerStopListening() I_RpcServerStopListening # win9x
 @ stub I_RpcServerUnregisterEndpointA # win9x
 @ stub I_RpcServerUnregisterEndpointW # win9x
 @ stub I_RpcServerUseProtseq2A
@@ -505,7 +506,7 @@
 @ stub I_RpcTransServerReallocBuffer # win9x
 @ stub I_RpcTransServerReceiveDirectReady # win9x
 @ stub I_RpcTransServerUnprotectThread # win9x
-@ stub I_RpcWindowProc # win9x
+@ stdcall I_RpcWindowProc(ptr long long long) I_RpcWindowProc # win9x
 @ stub I_RpcltDebugSetPDUFilter
 @ stub I_UuidCreate
 
@@ -515,3 +516,5 @@
 @ stub StartServiceIfNecessary # win9x
 @ stub GlobalMutexClearExternal
 @ stub GlobalMutexRequestExternal
+
+
Index: wine/dlls/rpcrt4/rpcrt4_main.c
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/rpcrt4_main.c,v
retrieving revision 1.25
diff -d -u -r1.25 rpcrt4_main.c
--- wine/dlls/rpcrt4/rpcrt4_main.c	13 Jun 2002 21:50:12 -0000	1.25
+++ wine/dlls/rpcrt4/rpcrt4_main.c	16 Jun 2002 10:53:12 -0000
@@ -28,9 +28,9 @@
 #include <unistd.h>
 
 #include "windef.h"
-#include "wine/windef16.h"
 #include "winerror.h"
 #include "winbase.h"
+#include "wine/unicode.h"
 #include "rpc.h"
 
 #include "ole2.h"
@@ -58,8 +58,12 @@
 
 #include "wine/debug.h"
 
+#include "rpc_binding.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
+static UUID uuid_nil;
+
 /***********************************************************************
  * RPCRT4_LibMain
  *
@@ -87,6 +91,41 @@
     return TRUE;
 }
 
+
+/*************************************************************************
+ *           RpcStringFreeA   [RPCRT4.@]
+ *
+ * Frees a character string allocated by the RPC run-time library.
+ *
+ * RETURNS
+ *
+ *  S_OK if successful.
+ */
+RPC_STATUS WINAPI RpcStringFreeA(LPSTR* 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(LPWSTR* String)
+{
+  HeapFree( GetProcessHeap(), 0, *String);
+
+  return RPC_S_OK;
+}
+
+
 /*************************************************************************
  *           UuidCreate   [RPCRT4.@]
  *
@@ -105,11 +144,11 @@
    static unsigned char a[6];
    static int                      adjustment = 0;
    static struct timeval           last = {0, 0};
-   static UINT16                   clock_seq;
+   static WORD                     clock_seq;
    struct timeval                  tv;
    unsigned long long              clock_reg;
-   UINT clock_high, clock_low;
-   UINT16 temp_clock_seq, temp_clock_mid, temp_clock_hi_and_version;
+   DWORD clock_high, clock_low;
+   WORD temp_clock_seq, temp_clock_mid, temp_clock_hi_and_version;
 #ifdef HAVE_NET_IF_H
    int             sd;
    struct ifreq    ifr, *ifrp;
@@ -248,7 +287,7 @@
    clock_high = clock_reg >> 32;
    clock_low = clock_reg;
    temp_clock_seq = clock_seq | 0x8000;
-   temp_clock_mid = (UINT16)clock_high;
+   temp_clock_mid = (WORD)clock_high;
    temp_clock_hi_and_version = (clock_high >> 16) | 0x1000;
 
    /* pack the information into the GUID structure */
@@ -285,6 +324,14 @@
    return RPC_S_OK;
 }
 
+/*************************************************************************
+ *           UuidCreateNil   [RPCRT4.@]
+ */
+RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
+{
+  *Uuid = uuid_nil;
+  return RPC_S_OK;
+}
 
 /*************************************************************************
  *           UuidCreateSequential   [RPCRT4.@]
@@ -292,45 +339,87 @@
  * Creates a 128bit UUID by calling UuidCreate.
  * New API in Win 2000
  */
-
 RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid)
 {
    return UuidCreate (Uuid);
 }
 
-
 /*************************************************************************
- *           RpcStringFreeA   [RPCRT4.@]
- *
- * Frees a character string allocated by the RPC run-time library.
- *
- * RETURNS
- *
- *  S_OK if successful.
+ *           UuidEqual   [RPCRT4.@]
  */
-RPC_STATUS WINAPI RpcStringFreeA(unsigned char** String)
+int WINAPI UuidEqual(UUID *uuid1, UUID *uuid2, RPC_STATUS *Status)
 {
-  HeapFree( GetProcessHeap(), 0, *String);
-
-  return RPC_S_OK;
+  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 TRUE;
+  return !memcmp(uuid1, uuid2, sizeof(UUID));
 }
 
+/*************************************************************************
+ *           UuidIsNil   [RPCRT4.@]
+ */
+int WINAPI UuidIsNil(UUID *uuid, RPC_STATUS *Status)
+{
+  TRACE("(%s)\n", debugstr_guid(uuid));
+  *Status = RPC_S_OK;
+  if (!uuid) return TRUE;
+  return !memcmp(uuid, &uuid_nil, sizeof(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)
 {
-  FIXME("stub:\n");
+  BYTE *data = (BYTE*)uuid;
+  short c0 = 0, c1 = 0, x, y;
+  int i;
+
+  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 0xabcd;
+  return y*256 + x;
 }
 
 /*************************************************************************
  *           UuidToStringA   [RPCRT4.@]
+ */
+RPC_STATUS WINAPI UuidToStringA(UUID *Uuid, LPSTR* StringUuid)
+{
+  char buf[37];
+
+  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_strdupAA(buf, -1);
+
+  if(!(*StringUuid))
+    return RPC_S_OUT_OF_MEMORY;
+
+  return RPC_S_OK;
+}
+
+/*************************************************************************
+ *           UuidToStringW   [RPCRT4.@]
  *
  * Converts a UUID to a string.
  *
@@ -342,256 +431,151 @@
  *  S_OK if successful.
  *  S_OUT_OF_MEMORY if unsucessful.
  */
-RPC_STATUS WINAPI UuidToStringA(UUID *Uuid, unsigned char** StringUuid)
+RPC_STATUS WINAPI UuidToStringW(UUID *Uuid, LPWSTR* StringUuid)
 {
-  *StringUuid = HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37);
+  char buf[37];
+
+  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_strdupWA(buf, -1);
 
   if(!(*StringUuid))
     return RPC_S_OUT_OF_MEMORY;
 
-  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;
 }
 
-/***********************************************************************
- *		UuidFromStringA (RPCRT4.@)
- */
-RPC_STATUS WINAPI UuidFromStringA(unsigned char *str, UUID *uuid)
-{
-    FIXME("%s %p\n",debugstr_a(str),uuid);
-    return RPC_S_INVALID_STRING_UUID;
-}
-
-/***********************************************************************
- *		UuidFromStringW (RPCRT4.@)
- */
-RPC_STATUS WINAPI UuidFromStringW(unsigned short *str, UUID *uuid)
-{
-    FIXME("%s %p\n",debugstr_w(str),uuid);
-    return RPC_S_INVALID_STRING_UUID;
-}
-
-/***********************************************************************
- *		NdrDllRegisterProxy (RPCRT4.@)
- */
-HRESULT WINAPI NdrDllRegisterProxy(
-  HMODULE hDll,          /* [in] */
-  const ProxyFileInfo **pProxyFileList, /* [in] */
-  const CLSID *pclsid    /* [in] */
-)
+static inline int hex_d(WCHAR v)
 {
-  FIXME("(%x,%p,%s), stub!\n",hDll,pProxyFileList,debugstr_guid(pclsid));
-  return S_OK;
+  switch (v) {
+  case '0': case '1': case '2': case '3': case '4':
+  case '5': case '6': case '7': case '8': case '9':
+    return v - '0';
+  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    return v - 'a' + 10;
+  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    return v - 'A' + 10;
+  default:
+    return -1;
+  }
 }
 
-/***********************************************************************
- *		RpcServerUseProtseqEpA (RPCRT4.@)
- */
-
-RPC_STATUS WINAPI RpcServerUseProtseqEpA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor )
+static inline unsigned char hex1A(LPSTR s)
 {
-  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 );
+  unsigned char v1 = hex_d(s[0]), v2 = hex_d(s[1]);
+  return (v1 << 4) | v2;
 }
 
-/***********************************************************************
- *		RpcServerUseProtseqEpW (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcServerUseProtseqEpW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor )
+static inline unsigned char hex1W(LPWSTR s)
 {
-  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 );
+  unsigned char v1 = hex_d(s[0]), v2 = hex_d(s[1]);
+  return (v1 << 4) | v2;
 }
 
-/***********************************************************************
- *		RpcServerUseProtseqEpExA (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcServerUseProtseqEpExA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor,
-                          PRPC_POLICY lpPolicy )
+static inline unsigned short hex2A(LPSTR s)
 {
-  FIXME( "(%s,%u,%s,%p,{%u,%lu,%lu}): stub\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor,
-                                               lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
-
-  return RPC_S_PROTSEQ_NOT_SUPPORTED; /* We don't support anything at this point */
+  unsigned char v1 = hex1A(s+0), v2 = hex1A(s+2);
+  return (unsigned short)(v1 << 8) | v2;
 }
 
-/***********************************************************************
- *		RpcServerUseProtseqEpExW (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcServerUseProtseqEpExW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor,
-                          PRPC_POLICY lpPolicy )
+static inline unsigned short hex2W(LPWSTR s)
 {
-  FIXME( "(%s,%u,%s,%p,{%u,%lu,%lu}): stub\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ),
-                                               SecurityDescriptor,
-                                               lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
-
-  return RPC_S_PROTSEQ_NOT_SUPPORTED; /* We don't support anything at this point */
+  unsigned char v1 = hex1W(s+0), v2 = hex1W(s+2);
+  return (unsigned short)(v1 << 8) | v2;
 }
 
-/***********************************************************************
- *		RpcServerRegisterIf (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv )
+static inline unsigned long hex4A(LPSTR s)
 {
-  /* FIXME: Dump UUID using UuidToStringA */
-  TRACE( "(%p,%p,%p)\n", IfSpec, MgrTypeUuid, MgrEpv );
-
-  return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL );
+  unsigned short v1 = hex2A(s+0), v2 = hex2A(s+4);
+  return (unsigned long)(v1 << 16) | v2;
 }
 
-/***********************************************************************
- *		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 )
+static inline unsigned long hex4W(LPWSTR s)
 {
-  /* FIXME: Dump UUID using UuidToStringA */
-  TRACE( "(%p,%p,%p,%u,%u,%p)\n", IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, IfCallbackFn );
-
-  return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn );
+  unsigned short v1 = hex2W(s+0), v2 = hex2W(s+4);
+  return (unsigned long)(v1 << 16) | v2;
 }
 
-/***********************************************************************
- *		RpcServerRegisterIf2 (RPCRT4.@)
+/*************************************************************************
+ *           UuidFromStringA   [RPCRT4.@]
+ *
+ * Converts a string to a UUID.
  */
-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 )
+RPC_STATUS WINAPI UuidFromStringA(LPSTR StringUuid, UUID *Uuid)
 {
-  /* FIXME: Dump UUID using UuidToStringA */
-  FIXME( "(%p,%p,%p,%u,%u,%u,%p): stub\n", IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, MaxRpcSize, IfCallbackFn );
-
-  return RPC_S_UNKNOWN_IF; /* I guess this return code is as good as any failure */
-}
+  unsigned i;
 
+  if(!StringUuid)
+    return UuidCreateNil(Uuid);
 
-/***********************************************************************
- *		RpcServerRegisterAuthInfoA (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( LPSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
-                            LPVOID Arg )
-{
-  FIXME( "(%s,%lu,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg );
+  if (strlen(StringUuid) != 36)
+    return RPC_S_INVALID_STRING_UUID;
 
-  return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
-}
+  if (StringUuid[8]!='-' || StringUuid[13]!='-' || StringUuid[18]!='-' || StringUuid[23]!='-')
+    return RPC_S_INVALID_STRING_UUID;
 
-/***********************************************************************
- *		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 );
+  for (i=0; i<36; i++) {
+    if (i==8 || i == 13 || i == 18 || i == 23) continue;
+    if (hex_d(StringUuid[i]) == -1)
+      return RPC_S_INVALID_STRING_UUID;
+  }
 
-  return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
+  Uuid->Data1 = hex4A(StringUuid);
+  Uuid->Data2 = hex2A(StringUuid+9);
+  Uuid->Data3 = hex2A(StringUuid+14);
+  Uuid->Data4[0] = hex1A(StringUuid+19);
+  Uuid->Data4[1] = hex1A(StringUuid+21);
+  Uuid->Data4[2] = hex1A(StringUuid+24);
+  Uuid->Data4[3] = hex1A(StringUuid+26);
+  Uuid->Data4[4] = hex1A(StringUuid+28);
+  Uuid->Data4[5] = hex1A(StringUuid+30);
+  Uuid->Data4[6] = hex1A(StringUuid+32);
+  Uuid->Data4[7] = hex1A(StringUuid+34);
+  return RPC_S_OK;
 }
 
-/***********************************************************************
- *		RpcServerListen (RPCRT4.@)
+/*************************************************************************
+ *           UuidFromStringW   [RPCRT4.@]
+ *
+ * Converts a string to a UUID.
  */
-RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )
+RPC_STATUS WINAPI UuidFromStringW(LPWSTR StringUuid, UUID *Uuid)
 {
-  FIXME( "(%u,%u,%u): stub\n", MinimumCallThreads, MaxCalls, DontWait );
+  unsigned i;
 
-  return RPC_S_NO_PROTSEQS_REGISTERED; /* Since we don't allow registration this seems reasonable */
-}
+  if(!StringUuid)
+    return UuidCreateNil(Uuid);
 
-/***********************************************************************
- *		RpcStringBindingComposeA (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcStringBindingComposeA( LPSTR ObjUuid, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint,
-                          LPSTR Options, LPSTR* StringBinding )
-{
-  FIXME( "(%s,%s,%s,%s,%s,%p): stub\n", ObjUuid, Protseq, NetworkAddr, Endpoint, Options, StringBinding );
-  *StringBinding = NULL;
+  if (strlenW(StringUuid) != 36)
+    return RPC_S_INVALID_STRING_UUID;
 
-  return RPC_S_INVALID_STRING_UUID; /* Failure */
-}
+  if (StringUuid[8]!='-' || StringUuid[13]!='-' || StringUuid[18]!='-' || StringUuid[23]!='-')
+    return RPC_S_INVALID_STRING_UUID;
 
-/***********************************************************************
- *		RpcStringBindingComposeW (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcStringBindingComposeW( LPWSTR ObjUuid, LPWSTR Protseq, LPWSTR NetworkAddr, LPWSTR Endpoint,
-                          LPWSTR Options, LPWSTR* StringBinding )
-{
-  FIXME( "(%s,%s,%s,%s,%s,%p): stub\n", debugstr_w( ObjUuid ), debugstr_w( Protseq ), debugstr_w( NetworkAddr ),
-                                        debugstr_w( Endpoint ), debugstr_w( Options ), StringBinding );
-  *StringBinding = NULL;
+  for (i=0; i<36; i++) {
+    if (i==8 || i == 13 || i == 18 || i == 23) continue;
+    if (hex_d(StringUuid[i]) == -1)
+      return RPC_S_INVALID_STRING_UUID;
+  }
 
-  return RPC_S_INVALID_STRING_UUID; /* Failure */
-}
+  Uuid->Data1 = hex4W(StringUuid);
+  Uuid->Data2 = hex2W(StringUuid+9);
+  Uuid->Data3 = hex2W(StringUuid+14);
+  Uuid->Data4[0] = hex1W(StringUuid+19);
+  Uuid->Data4[1] = hex1W(StringUuid+21);
+  Uuid->Data4[2] = hex1W(StringUuid+24);
+  Uuid->Data4[3] = hex1W(StringUuid+26);
+  Uuid->Data4[4] = hex1W(StringUuid+28);
+  Uuid->Data4[5] = hex1W(StringUuid+30);
+  Uuid->Data4[6] = hex1W(StringUuid+32);
+  Uuid->Data4[7] = hex1W(StringUuid+34);
 
-/***********************************************************************
- *		RpcBindingFree (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcBindingFree(RPC_BINDING_HANDLE* Binding)
-{
-  FIXME("(%p): stub\n", Binding);
   return RPC_S_OK;
 }
-/***********************************************************************
- *		RpcBindingFromStringBindingA (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcBindingFromStringBindingA( LPSTR StringBinding, RPC_BINDING_HANDLE* Binding )
-{
-  FIXME( "(%s,%p): stub\n", StringBinding, Binding );
-
-  return RPC_S_INVALID_STRING_BINDING; /* As good as any failure code */
-}
-
-/***********************************************************************
- *		RpcBindingFromStringBindingW (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcBindingFromStringBindingW( LPWSTR StringBinding, RPC_BINDING_HANDLE* Binding )
-{
-  FIXME( "(%s,%p): stub\n", debugstr_w( StringBinding ), Binding );
-
-  return RPC_S_INVALID_STRING_BINDING; /* As good as any failure code */
-}
-
-/***********************************************************************
- *		NdrDllCanUnloadNow (RPCRT4.@)
- */
-HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer)
-{
-    FIXME("%p\n",pPSFactoryBuffer);
-    return FALSE;
-}
-
-/***********************************************************************
- *		NdrDllGetClassObject (RPCRT4.@)
- */
-HRESULT WINAPI NdrDllGetClassObject(
-    REFCLSID rclsid, REFIID riid , LPVOID *ppv,
-    const ProxyFileInfo **   pProxyFileList,
-    const CLSID *            pclsid,
-    CStdPSFactoryBuffer *    pPSFactoryBuffer)
-{
-    if(ppv)
-        *ppv = NULL;
-    return RPC_S_UNKNOWN_IF;
-}
 
 /***********************************************************************
  *              DllRegisterServer (RPCRT4.@)
@@ -602,3 +586,4 @@
         FIXME( "(): stub\n" );
         return S_OK;
 }
+
Index: wine/include/rpc.h
===================================================================
RCS file: /home/wine/wine/include/rpc.h,v
retrieving revision 1.8
diff -d -u -r1.8 rpc.h
--- wine/include/rpc.h	10 Mar 2002 00:02:34 -0000	1.8
+++ wine/include/rpc.h	16 Jun 2002 10:53:43 -0000
@@ -25,6 +25,8 @@
 #ifndef __WINE_RPC_H
 #define __WINE_RPC_H
 
+#define __RPC_WIN32__
+
 #define __RPC_FAR
 #define __RPC_API  WINAPI
 #define __RPC_USER WINAPI
Index: wine/include/rpcdce.h
===================================================================
RCS file: /home/wine/wine/include/rpcdce.h,v
retrieving revision 1.8
diff -d -u -r1.8 rpcdce.h
--- wine/include/rpcdce.h	31 May 2002 23:06:48 -0000	1.8
+++ wine/include/rpcdce.h	16 Jun 2002 10:53:43 -0000
@@ -29,8 +29,6 @@
 typedef void* RPC_AUTHZ_HANDLE;
 typedef void* RPC_IF_HANDLE;
 typedef I_RPC_HANDLE RPC_BINDING_HANDLE;
-typedef RPC_BINDING_HANDLE handle_t;
-#define rpc_binding_handle_t RPC_BINDING_HANDLE
 #define RPC_MGR_EPV void
 
 typedef struct _RPC_BINDING_VECTOR
@@ -38,14 +36,19 @@
   unsigned long Count;
   RPC_BINDING_HANDLE BindingH[1];
 } RPC_BINDING_VECTOR;
-#define rpc_binding_vector_t RPC_BINDING_VECTOR
 
 typedef struct _UUID_VECTOR
 {
   unsigned long Count;
   UUID *Uuid[1];
 } UUID_VECTOR;
+
+#ifndef __WINE__
+typedef RPC_BINDING_HANDLE handle_t;
+#define rpc_binding_handle_t RPC_BINDING_HANDLE
+#define rpc_binding_vector_t RPC_BINDING_VECTOR
 #define uuid_vector_t UUID_VECTOR
+#endif
 
 typedef struct _RPC_IF_ID
 {
@@ -90,6 +93,11 @@
   ULONG NICFlags;
 } RPC_POLICY,  *PRPC_POLICY;
 
+/* RpcServerRegisterIfEx Flags */
+#define RPC_IF_AUTOLISTEN               0x1
+#define RPC_IF_OLE                      0x2
+#define RPC_IF_ALLOW_UNKNOWN_AUTHORITY  0x4
+#define RPC_IF_ALLOW_SECURE_ONLY        0x8
 
 RPCRTAPI RPC_STATUS RPC_ENTRY
   RpcBindingCopy( RPC_BINDING_HANDLE SourceBinding, RPC_BINDING_HANDLE* DestinationBinding );
@@ -98,6 +106,13 @@
   RpcBindingFree( RPC_BINDING_HANDLE* Binding );
 
 RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcBindingReset( RPC_BINDING_HANDLE Binding );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid );
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
   RpcBindingFromStringBindingA( LPSTR StringBinding, RPC_BINDING_HANDLE* Binding );
 RPCRTAPI RPC_STATUS RPC_ENTRY
   RpcBindingFromStringBindingW( LPWSTR StringBinding, RPC_BINDING_HANDLE* Binding );
@@ -113,6 +128,45 @@
   RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector );
 
 RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcStringBindingComposeA( LPSTR ObjUuid, LPSTR Protseq, LPSTR NetworkAddr,
+                            LPSTR Endpoint, LPSTR Options, LPSTR* StringBinding );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcStringBindingComposeW( LPWSTR ObjUuid, LPWSTR Protseq, LPWSTR NetworkAddr,
+                            LPWSTR Endpoint, LPWSTR Options, LPWSTR* StringBinding );
+#define RpcStringBindingCompose WINELIB_NAME_AW(RpcStringBindingCompose)
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcStringBindingParseA( LPSTR StringBinding, LPSTR* ObjUuid, LPSTR* Protseq,
+                          LPSTR* NetworkAddr, LPSTR* Endpoint, LPSTR* NetworkOptions );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcStringBindingParseW( LPWSTR StringBinding, LPWSTR* ObjUuid, LPWSTR* Protseq,
+                          LPWSTR* NetworkAddr, LPWSTR* Endpoint, LPWSTR* NetworkOptions );
+#define RpcStringBindingParse WINELIB_NAME_AW(RpcStringBindingParse)
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec );
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector,
+                  UUID_VECTOR* UuidVector, LPSTR Annotation );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcEpRegisterW( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector,
+                  UUID_VECTOR* UuidVector, LPWSTR Annotation );
+#define RpcEpRegister WINELIB_NAME_AW(RpcEpRegister)
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcEpRegisterNoReplaceA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector,
+                           UUID_VECTOR* UuidVector, LPSTR Annotation );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcEpRegisterNoReplaceW( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector,
+                           UUID_VECTOR* UuidVector, LPWSTR Annotation );
+#define RpcEpRegisterNoReplace WINELIB_NAME_AW(RpcEpRegisterNoReplace)
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector,
+                   UUID_VECTOR* UuidVector );
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
   RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector );
 
 RPCRTAPI RPC_STATUS RPC_ENTRY
@@ -163,22 +217,37 @@
 #define RpcStringBindingCompose WINELIB_NAME_AW(RpcStringBindingCompose)
 
 RPCRTAPI RPC_STATUS RPC_ENTRY
-  RpcStringFreeA(unsigned char** String);
+  RpcStringFreeA(LPSTR* String);
 RPCRTAPI RPC_STATUS RPC_ENTRY
-  RpcStringFreeW(unsigned short** String);
+  RpcStringFreeW(LPWSTR* String);
 #define RpcStringFree WINELIB_NAME_AW(RpcStringFree)
 
 RPCRTAPI RPC_STATUS RPC_ENTRY
-  UuidCreate( UUID* Uuid );
+  UuidToStringA( UUID* Uuid, LPSTR* StringUuid );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  UuidToStringW( UUID* Uuid, LPWSTR* StringUuid );
+#define UuidToString WINELIB_NAME_AW(UuidToString)
 
 RPCRTAPI RPC_STATUS RPC_ENTRY
-  UuidToStringA( UUID* Uuid, unsigned char** StringUuid );
+  UuidFromStringA( LPSTR StringUuid, UUID* Uuid );
 RPCRTAPI RPC_STATUS RPC_ENTRY
-  UuidToStringW( UUID* Uuid, unsigned short** StringUuid );
-#define UuidToString WINELIB_NAME_AW(UuidToString)
+  UuidFromStringW( LPWSTR StringUuid, UUID* Uuid );
+#define UuidFromString WINELIB_NAME_AW(UuidFromString)
 
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  UuidCreate( UUID* Uuid );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  UuidCreateSequential( UUID* Uuid );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  UuidCreateNil( UUID* Uuid );
+RPCRTAPI signed int RPC_ENTRY
+  UuidCompare( UUID* Uuid1, UUID* Uuid2, RPC_STATUS* Status_ );
+RPCRTAPI int RPC_ENTRY
+  UuidEqual( UUID* Uuid1, UUID* Uuid2, RPC_STATUS* Status_ );
 RPCRTAPI unsigned short RPC_ENTRY
   UuidHash(UUID* Uuid, RPC_STATUS* Status_ );
+RPCRTAPI int RPC_ENTRY
+  UuidIsNil( UUID* Uuid, RPC_STATUS* Status_ );
 
 #include "rpcdcep.h"
 
Index: wine/include/rpcdcep.h
===================================================================
RCS file: /home/wine/wine/include/rpcdcep.h,v
retrieving revision 1.2
diff -d -u -r1.2 rpcdcep.h
--- wine/include/rpcdcep.h	10 Mar 2002 00:02:34 -0000	1.2
+++ wine/include/rpcdcep.h	16 Jun 2002 10:53:43 -0000
@@ -19,7 +19,6 @@
 #ifndef __WINE_RPCDCEP_H
 #define __WINE_RPCDCEP_H
 
-
 typedef struct _RPC_VERSION {
     unsigned short MajorVersion;
     unsigned short MinorVersion;
@@ -45,4 +44,117 @@
     unsigned long RpcFlags;
 } RPC_MESSAGE, *PRPC_MESSAGE;
 
-#endif /*__WINE_RPCDCE_H */
+typedef void __RPC_STUB (*RPC_DISPATCH_FUNCTION)(PRPC_MESSAGE Message);
+
+typedef struct
+{
+    unsigned int DispatchTableCount;
+    RPC_DISPATCH_FUNCTION* DispatchTable;
+    LONG_PTR Reserved;
+} RPC_DISPATCH_TABLE, *PRPC_DISPATCH_TABLE;
+
+typedef struct _RPC_PROTSEQ_ENDPOINT
+{
+    unsigned char* RpcProtocolSequence;
+    unsigned char* Endpoint;
+} RPC_PROTSEQ_ENDPOINT, *PRPC_PROTSEQ_ENDPOINT;
+
+#define NT351_INTERFACE_SIZE 0x40
+#define RPC_INTERFACE_HAS_PIPES 0x0001
+
+typedef struct _RPC_SERVER_INTERFACE
+{
+    unsigned int Length;
+    RPC_SYNTAX_IDENTIFIER InterfaceId;
+    RPC_SYNTAX_IDENTIFIER TransferSyntax;
+    PRPC_DISPATCH_TABLE DispatchTable;
+    unsigned int RpcProtseqEndpointCount;
+    PRPC_PROTSEQ_ENDPOINT RpcProtseqEndpoint;
+    RPC_MGR_EPV* DefaultManagerEpv;
+    void const* InterpreterInfo;
+    unsigned int Flags;
+} RPC_SERVER_INTERFACE, *PRPC_SERVER_INTERFACE;
+
+typedef struct _RPC_CLIENT_INTERFACE
+{
+    unsigned int Length;
+    RPC_SYNTAX_IDENTIFIER InterfaceId;
+    RPC_SYNTAX_IDENTIFIER TransferSyntax;
+    PRPC_DISPATCH_TABLE DispatchTable;
+    unsigned int RpcProtseqEndpointCount;
+    PRPC_PROTSEQ_ENDPOINT RpcProtseqEndpoint;
+    ULONG_PTR Reserved;
+    void const* InterpreterInfo;
+    unsigned int Flags;
+} RPC_CLIENT_INTERFACE, *PRPC_CLIENT_INTERFACE;
+
+#define TRANSPORT_TYPE_CN   0x01
+#define TRANSPORT_TYPE_DG   0x02
+#define TRANSPORT_TYPE_LPC  0x04
+#define TRANSPORT_TYPE_WMSG 0x08
+
+#ifdef WINNT
+typedef RPC_STATUS (*RPC_BLOCKING_FN)(void* hWnd, void* Context, HANDLE hSyncEvent);
+#else
+typedef RPC_STATUS (*RPC_BLOCKING_FN)(void* hWnd, void* Context, void* hSyncEvent);
+#endif
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcGetBuffer( RPC_MESSAGE* Message );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcGetBufferWithObject( RPC_MESSAGE* Message, UUID* ObjectUuid );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcSendReceive( RPC_MESSAGE* Message );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcFreeBuffer( RPC_MESSAGE* Message );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcSend( RPC_MESSAGE* Message );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcReceive( RPC_MESSAGE* Message );
+
+RPCRTAPI void* RPC_ENTRY
+  I_RpcAllocate( unsigned int Size );
+RPCRTAPI void RPC_ENTRY
+  I_RpcFree( void* Object );
+
+RPCRTAPI RPC_BINDING_HANDLE RPC_ENTRY
+  I_RpcGetCurrentCallHandle( void );
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcServerStartListening( void* hWnd );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcServerStopListening( void );
+/* WINNT */
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_GetThreadWindowHandle( HWND* hWnd );
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcAsyncSendReceive( RPC_MESSAGE* Message, void* Context, HWND hWnd );
+
+#ifdef WINNT
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn );
+#else
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn, unsigned long ServerTid );
+#endif
+
+/* WIN9x */
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcSetThreadParams( int fClientFree, void* Context, void* hWndClient );
+
+#ifdef WINNT
+RPCRTAPI LONG RPC_ENTRY
+  I_RpcWindowProc( HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam );
+#else
+RPCRTAPI unsigned int RPC_ENTRY
+  I_RpcWindowProc( void* hWnd, unsigned int Message, unsigned int wParam, unsigned long lParam );
+#endif
+
+/* WINNT */
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcSetWMsgEndpoint( WCHAR* Endpoint );
+
+RPCRTAPI RPC_STATUS RPC_ENTRY
+  I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int* Type );
+
+#endif /*__WINE_RPCDCEP_H */
Index: wine/include/rpcndr.h
===================================================================
RCS file: /home/wine/wine/include/rpcndr.h,v
retrieving revision 1.5
diff -d -u -r1.5 rpcndr.h
--- wine/include/rpcndr.h	10 Mar 2002 00:02:34 -0000	1.5
+++ wine/include/rpcndr.h	16 Jun 2002 10:53:44 -0000
@@ -22,7 +22,10 @@
 #ifndef __RPCNDR_H_VERSION__
 /* FIXME: I'm not sure what version though */
 #define __RPCNDR_H_VERSION__
-#endif // __RPCNDR_H_VERSION__
+#endif
+
+#define TARGET_IS_NT40_OR_LATER 1
+#define TARGET_IS_NT351_OR_WIN95_OR_LATER 1
 
 typedef unsigned char byte;
 typedef __int64 hyper;
@@ -31,6 +34,9 @@
 typedef unsigned char _wine_boolean;
 /* typedef _wine_boolean boolean; */
 
+#define __RPC_CALLEE WINAPI
+#define RPC_VAR_ENTRY WINAPIV
+
 typedef struct
 {
   void *pad[2];
@@ -96,7 +102,7 @@
   unsigned char *StackTop;
   unsigned char *pPresentedType;
   unsigned char *pTransmitType;
-  handle_t SavedHandle;
+  RPC_BINDING_HANDLE SavedHandle;
   const struct _MIDL_STUB_DESC *StubDesc;
   struct _FULL_PTR_XLAT_TABLES *FullPtrXlatTables;
   unsigned long FullPtrRefId;
@@ -146,8 +152,8 @@
   void * (__RPC_API *pfnAllocate)(size_t);
   void (__RPC_API *pfnFree)(void *);
   union {
-    handle_t *pAutoHandle;
-    handle_t *pPrimitiveHandle;
+    RPC_BINDING_HANDLE *pAutoHandle;
+    RPC_BINDING_HANDLE *pPrimitiveHandle;
     PGENERIC_BINDING_INFO pGenericBindingInfo;
   } IMPLICIT_HANDLE_INFO;
   const NDR_RUNDOWN *apfnNdrRundownRoutines;
@@ -195,6 +201,22 @@
   const unsigned short *LocalFmtStringOffset;
 } MIDL_SERVER_INFO, *PMIDL_SERVER_INFO;
 
+typedef struct _MIDL_STUBLESS_PROXY_INFO
+{
+  PMIDL_STUB_DESC pStubDesc;
+  PFORMAT_STRING ProcFormatString;
+  const unsigned short *FormatStringOffset;
+  PFORMAT_STRING LocalFormatTypes;
+  PFORMAT_STRING LocalProcStrings;
+  const unsigned short *LocalFmtStringOffset;
+} MIDL_STUBLESS_PROXY_INFO, *PMIDL_STUBLESS_PROXY_INFO;
+
+typedef union _CLIENT_CALL_RETURN
+{
+  void *Pointer;
+  LONG_PTR Simple;
+} CLIENT_CALL_RETURN;
+
 typedef enum {
   STUB_UNMARSHAL,
   STUB_CALL_SERVER,
@@ -253,6 +275,21 @@
   NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams );
 RPCRTAPI void RPC_ENTRY
   NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat );
+
+CLIENT_CALL_RETURN RPC_VAR_ENTRY
+  NdrClientCall2( PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ... );
+CLIENT_CALL_RETURN RPC_VAR_ENTRY
+  NdrClientCall( PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ... );
+
+RPCRTAPI void RPC_ENTRY
+  NdrServerCall2( PRPC_MESSAGE pRpcMsg );
+RPCRTAPI void RPC_ENTRY
+  NdrServerCall( PRPC_MESSAGE pRpcMsg );
+
+RPCRTAPI long RPC_ENTRY
+  NdrStubCall2( struct IRpcStubBuffer* pThis, struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, LPDWORD pdwStubPhase );
+RPCRTAPI long RPC_ENTRY
+  NdrStubCall( struct IRpcStubBuffer* pThis, struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, LPDWORD pdwStubPhase );
 
 RPCRTAPI void* RPC_ENTRY
   NdrOleAllocate( size_t Size );
Index: wine/include/rpcproxy.h
===================================================================
RCS file: /home/wine/wine/include/rpcproxy.h,v
retrieving revision 1.2
diff -d -u -r1.2 rpcproxy.h
--- wine/include/rpcproxy.h	10 Mar 2002 00:02:34 -0000	1.2
+++ wine/include/rpcproxy.h	16 Jun 2002 10:53:44 -0000
@@ -19,8 +19,14 @@
 #ifndef __WINE_RPCPROXY_H
 #define __WINE_RPCPROXY_H
 
+#ifndef __RPCPROXY_H_VERSION__
+/* FIXME: I'm not sure what version though */
+#define __RPCPROXY_H_VERSION__
+#endif
+
 #include "basetsd.h"
 #include "guiddef.h"
+#include "winnt.h"
 
 typedef struct tagCInterfaceStubVtbl *PCInterfaceStubVtblList;
 typedef struct tagCInterfaceProxyVtbl *PCInterfaceProxyVtblList;
@@ -47,6 +53,8 @@
 
 #include "rpc.h"
 #include "rpcndr.h"
+#include "wine/obj_base.h"
+#include "wine/obj_channel.h"
 
 typedef struct tagCInterfaceProxyHeader
 {
@@ -147,6 +155,32 @@
   CStdStubBuffer_DebugServerQueryInterface, \
   CStdStubBuffer_DebugServerRelease
 
+RPCRTAPI void RPC_ENTRY
+  NdrProxyInitialize( void *This, PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg,
+                      PMIDL_STUB_DESC pStubDescriptor, unsigned int ProcNum );
+RPCRTAPI void RPC_ENTRY
+  NdrProxyGetBuffer( void *This, PMIDL_STUB_MESSAGE pStubMsg );
+RPCRTAPI void RPC_ENTRY
+  NdrProxySendReceive( void *This, PMIDL_STUB_MESSAGE pStubMsg );
+RPCRTAPI void RPC_ENTRY
+  NdrProxyFreeBuffer( void *This, PMIDL_STUB_MESSAGE pStubMsg );
+RPCRTAPI HRESULT RPC_ENTRY
+  NdrProxyErrorHandler( DWORD dwExceptionCode );
+
+RPCRTAPI void RPC_ENTRY
+  NdrStubInitialize( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg,
+                     PMIDL_STUB_DESC pStubDescriptor, IRpcChannelBuffer *pRpcChannelBuffer );
+RPCRTAPI void RPC_ENTRY
+  NdrStubInitializePartial( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg,
+                            PMIDL_STUB_DESC pStubDescriptor, IRpcChannelBuffer *pRpcChannelBuffer,
+                            unsigned long RequestedBufferSize );
+void __RPC_STUB NdrStubForwardingFunction( IRpcStubBuffer *This, IRpcChannelBuffer *pChannel,
+                                           PRPC_MESSAGE pMsg, DWORD *pdwStubPhase );
+RPCRTAPI void RPC_ENTRY
+  NdrStubGetBuffer( IRpcStubBuffer *This, IRpcChannelBuffer *pRpcChannelBuffer, PMIDL_STUB_MESSAGE pStubMsg );
+RPCRTAPI HRESULT RPC_ENTRY
+  NdrStubErrorHandler( DWORD dwExceptionCode );
+
 RPCRTAPI HRESULT RPC_ENTRY
   NdrDllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv, const ProxyFileInfo **pProxyFileList,
                         const CLSID *pclsid, CStdPSFactoryBuffer *pPSFactoryBuffer );
@@ -161,6 +195,8 @@
 #define CSTDSTUBBUFFERRELEASE(pFactory) \
 ULONG WINAPI CStdStubBuffer_Release(IRpcStubBuffer *This) \
   { return NdrCStdStubBuffer_Release(This, (IPSFactoryBuffer *)pFactory); }
+
+#define IID_GENERIC_CHECK_IID(name,pIID,index) memcmp(pIID, name##_ProxyVtblList[index]->header.piid, sizeof(IID))
 
 #if defined(__WINE__) && defined(__WINE_WINE_OBJ_OLEAUT_H)
 /* see http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp?frame=true */

--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/cproxy.c	Thu Jun 13 17:15:25 2002
@@ -0,0 +1,276 @@
+/*
+ * COM proxy implementation
+ *
+ * Copyright 2001 Ove K???en, TransGaming Technologies
+ */
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+
+#include "wine/obj_base.h"
+#include "wine/obj_channel.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;
+  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__)
+
+struct StublessThunk {
+  BYTE push WINE_PACKED;
+  DWORD index WINE_PACKED;
+  BYTE call WINE_PACKED;
+  LONG handler WINE_PACKED;
+  BYTE ret WINE_PACKED;
+  WORD bytes WINE_PACKED;
+  BYTE pad[3];
+};
+
+/* 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;
+
+#else
+/* can't do that on this arch */
+struct ObjectStubless {};
+#define FILL_STUBLESS(x,idx) \
+ ERR("stubless proxies are not supported on this architecture\n");
+#endif
+
+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);
+}
+
+HRESULT WINAPI StdProxy_Construct(REFIID riid,
+				  LPUNKNOWN pUnkOuter,
+				  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)\n", pUnkOuter, vtbl, pPSFactory, ppProxy, ppvObj);
+  /* I can't find any other way to detect stubless proxies than this hack */
+  if (!IsEqualGUID(vtbl->header.piid, riid)) {
+    stubless = *((const void **)vtbl)++;
+    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->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)\n",This,ppChannel);
+  *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)\n",This,ppiid);
+  *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)\n",This,debugstr_guid(riid),ppvObj);
+  return IUnknown_QueryInterface(This->pUnkOuter,riid,ppvObj);
+}
+
+ULONG WINAPI IUnknown_AddRef_Proxy(LPUNKNOWN iface)
+{
+  ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface);
+  TRACE("(%p)->AddRef()\n",This);
+#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()\n",This);
+#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
+}
+
--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/cpsf.c	Thu Jun 13 17:15:56 2002
@@ -0,0 +1,245 @@
+/*
+ * COM proxy/stub factory (CStdPSFactory) implementation
+ *
+ * Copyright 2001 Ove K???en, TransGaming Technologies
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+
+#include "wine/obj_base.h"
+#include "wine/obj_channel.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->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->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)
+{
+/* #define INSTALLSHIELD_HACK */
+#ifndef INSTALLSHIELD_HACK
+  LPSTR clsid;
+  char keyname[120], module[120];
+  HKEY key, subkey;
+
+  TRACE("(%x,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
+  UuidToStringA((UUID*)pclsid, &clsid);
+
+  /* register interfaces to point to clsid */
+  while (*pProxyFileList) {
+    unsigned u;
+    for (u=0; u<(*pProxyFileList)->TableSize; u++) {
+      CInterfaceProxyVtbl *proxy = (*pProxyFileList)->pProxyVtblList[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, &iid);
+      snprintf(keyname, sizeof(keyname), "Interface\\%s", iid);
+      RpcStringFreeA(&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) {
+          RegSetValueExA(subkey, NULL, 0, REG_SZ, clsid, strlen(clsid));
+          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 %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(&clsid);
+#endif
+  return S_OK;
+}
+
+/***********************************************************************
+ *           NdrDllUnregisterProxy [RPCRT4.@]
+ */
+HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll,
+				     const ProxyFileInfo **pProxyFileList,
+				     const CLSID *pclsid)
+{
+#ifndef INSTALLSHIELD_HACK
+  LPSTR clsid;
+  char keyname[120], module[120];
+
+  TRACE("(%x,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
+  UuidToStringA((UUID*)pclsid, &clsid);
+
+  /* unregister interfaces */
+  while (*pProxyFileList) {
+    unsigned u;
+    for (u=0; u<(*pProxyFileList)->TableSize; u++) {
+      CInterfaceProxyVtbl *proxy = (*pProxyFileList)->pProxyVtblList[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, &iid);
+      snprintf(keyname, sizeof(keyname), "Interface\\%s", iid);
+      RpcStringFreeA(&iid);
+      RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname);
+    }
+    pProxyFileList++;
+  }
+
+  /* unregister clsid */
+  snprintf(keyname, sizeof(keyname), "CLSID\\%s", clsid);
+  GetModuleFileNameA(hDll, module, sizeof(module));
+  TRACE("unregistering %s <= %s\n", clsid, module);
+  RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname);
+
+  /* done */
+  RpcStringFreeA(&clsid);
+#endif
+  return S_OK;
+}
+
--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/cstub.c	Thu Jun 13 17:16:27 2002
@@ -0,0 +1,141 @@
+/*
+ * COM stub (CStdStubBuffer) implementation
+ *
+ * Copyright 2001 Ove K???en, TransGaming Technologies
+ */
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+
+#include "wine/obj_base.h"
+#include "wine/obj_channel.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,
+					CInterfaceStubVtbl *vtbl,
+					LPPSFACTORYBUFFER pPSFactory,
+					LPRPCSTUBBUFFER *ppStub)
+{
+  CStdStubBuffer *This;
+  TRACE("(%p,%p,%p,%p)\n", pUnkServer, vtbl, pPSFactory, ppStub);
+  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;
+  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)) {
+    IUnknown_Release(This->pvServerObject);
+    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);
+}
+
--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/ndr_midl.c	Thu Jun 13 17:16:55 2002
@@ -0,0 +1,157 @@
+/*
+ * MIDL proxy/stub stuff
+ *
+ * Copyright 2002 Ove K???en, TransGaming Technologies
+ *
+ * TODO:
+ *  - figure out whether we *really* got this right
+ *  - check for errors and throw exceptions
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+
+#include "wine/obj_base.h"
+#include "wine/obj_channel.h"
+
+#include "rpcproxy.h"
+
+#include "wine/debug.h"
+
+#include "cpsf.h"
+#include "ndr_misc.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);
+  memset(pRpcMsg, 0, sizeof(RPC_MESSAGE));
+  memset(pStubMsg, 0, sizeof(MIDL_STUB_MESSAGE));
+  pRpcMsg->ProcNum = ProcNum;
+  pRpcMsg->RpcInterfaceInformation = pStubDescriptor->RpcInterfaceInformation;
+  pStubMsg->RpcMsg = pRpcMsg;
+  pStubMsg->IsClient = 1;
+  pStubMsg->ReuseBuffer = 1;
+  pStubMsg->pfnAllocate = pStubDescriptor->pfnAllocate;
+  pStubMsg->pfnFree = pStubDescriptor->pfnFree;
+  pStubMsg->StubDesc = pStubDescriptor;
+  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;
+}
+
+/***********************************************************************
+ *           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);
+}
+
+/***********************************************************************
+ *           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);
+  memset(pStubMsg, 0, sizeof(MIDL_STUB_MESSAGE));
+  pStubMsg->RpcMsg = pRpcMsg;
+  pStubMsg->IsClient = 0;
+  pStubMsg->ReuseBuffer = 1;
+  pStubMsg->pfnAllocate = pStubDescriptor->pfnAllocate;
+  pStubMsg->pfnFree = pStubDescriptor->pfnFree;
+  pStubMsg->StubDesc = pStubDescriptor;
+  pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer;
+  pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;
+  pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
+  pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
+  pStubMsg->Buffer = pStubMsg->BufferStart;
+}
+
+/***********************************************************************
+ *           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;
+}
+
+
--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/ndr_ole.c	Thu Jun 13 17:17:39 2002
@@ -0,0 +1,319 @@
+/*
+ * OLE32 callouts, COM interface marshalling
+ *
+ * Copyright 2001 Ove K???en, TransGaming Technologies
+ *
+ * TODO:
+ *  - figure out whether we *really* got this right
+ *  - check for errors and throw exceptions
+ *  - what's the marshalling functions supposed to return?
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+
+#include "wine/obj_base.h"
+#include "wine/obj_storage.h"
+#include "wine/obj_marshal.h"
+#include "wine/obj_channel.h"
+
+#include "rpcndr.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.s.LowPart;
+    break;
+  case STREAM_SEEK_CUR:
+    This->pos = This->pos + move.s.LowPart;
+    break;
+  case STREAM_SEEK_END:
+    This->pos = *This->size + move.s.LowPart;
+    break;
+  default:
+    return STG_E_INVALIDFUNCTION;
+  }
+  if (newPos) {
+    newPos->s.LowPart = This->pos;
+    newPos->s.HighPart = 0;
+  }
+  return S_OK;
+}
+
+static HRESULT WINAPI RpcStream_SetSize(LPSTREAM iface,
+					ULARGE_INTEGER newSize)
+{
+  ICOM_THIS(RpcStreamImpl, iface);
+  *This->size = newSize.s.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;
+}
+
+/***********************************************************************
+ *           NdrInterfacePointerMarshall [RPCRT4.@]
+ */
+unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
+						   unsigned char *pMemory,
+						   PFORMAT_STRING pFormat)
+{
+  const IID *riid = (const IID *)pStubMsg->MaxCount;
+  LPSTREAM stream;
+  HRESULT hr;
+
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
+  if (!riid) riid = &IID_IUnknown;
+  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 = (const IID *)pStubMsg->MaxCount;
+  ULONG size = 0;
+  HRESULT hr;
+
+  TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
+  if (!riid) riid = &IID_IUnknown;
+  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;
+}
+
+
--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/ndr_stubless.c	Thu Jun 13 17:18:32 2002
@@ -0,0 +1,46 @@
+/*
+ * NDR client stuff
+ *
+ * Copyright 2001 Ove K???en, TransGaming Technologies
+ *
+ * TODO:
+ *  - figure out whether we *really* got this right
+ *  - check for errors and throw exceptions
+ */
+
+#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 RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc,
+			       PFORMAT_STRING pFormat,
+			       LPVOID args)
+{
+  FIXME("(%p,%p,...)\n", pStubDesc, pFormat);
+  return 0;
+}
+
+/***********************************************************************
+ *           NdrClientCall2 [RPCRT4.@]
+ */
+CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc,
+					  PFORMAT_STRING pFormat,
+					  ...)
+{
+  TRACE("(%p,%p,...)\n", pStubDesc, pFormat);
+  return (CLIENT_CALL_RETURN)RPCRT4_NdrClientCall2(pStubDesc, pFormat, &pFormat + 1);
+}
+
--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/rpc_binding.c	Thu Jun 13 17:19:45 2002
@@ -0,0 +1,743 @@
+/*
+ * RPC binding API
+ *
+ * Copyright 2001 Ove K???en, TransGaming Technologies
+ *
+ * TODO:
+ *  - a whole lot
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "wine/unicode.h"
+
+#include "rpc.h"
+
+#include "wine/debug.h"
+
+#include "rpc_binding.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+
+LPSTR RPCRT4_strdupAA(LPSTR 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_strdupAW(LPWSTR src, INT slen)
+{
+  DWORD len;
+  LPSTR s;
+  if (!src) return NULL;
+  if (slen == -1) slen = strlenW(src);
+  len = WideCharToMultiByte(CP_ACP, 0, src, slen, NULL, 0, NULL, NULL);
+  s = HeapAlloc(GetProcessHeap(), 0, len+1);
+  WideCharToMultiByte(CP_ACP, 0, src, slen, s, len, NULL, NULL);
+  s[len] = 0;
+  return s;
+}
+
+LPWSTR RPCRT4_strdupWA(LPSTR src, INT slen)
+{
+  DWORD len;
+  LPWSTR s;
+  if (!src) return NULL;
+  if (slen == -1) slen = strlen(src);
+  len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0);
+  s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
+  MultiByteToWideChar(CP_ACP, 0, src, slen, s, len);
+  s[len] = 0;
+  return s;
+}
+
+LPWSTR RPCRT4_strdupWW(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_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq)
+{
+  RpcBinding* NewBinding;
+
+  NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
+  NewBinding->refs = 1;
+  NewBinding->server = 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;
+
+  NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
+  NewBinding->refs = 1;
+  NewBinding->server = server;
+  NewBinding->Protseq = RPCRT4_strdupW(Protseq);
+
+  TRACE("binding: %p\n", NewBinding);
+  *Binding = NewBinding;
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr,  LPSTR Endpoint,  LPSTR NetworkOptions)
+{
+  RPCRT4_strfree(Binding->NetworkAddr);
+  Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
+  RPCRT4_strfree(Binding->Endpoint);
+  Binding->Endpoint = RPCRT4_strdupA(Endpoint);
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions)
+{
+  RPCRT4_strfree(Binding->NetworkAddr);
+  Binding->NetworkAddr = RPCRT4_strdupW(NetworkAddr);
+  RPCRT4_strfree(Binding->Endpoint);
+  Binding->Endpoint = RPCRT4_strdupW(Endpoint);
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint)
+{
+  RPCRT4_strfree(Binding->Endpoint);
+  Binding->Endpoint = RPCRT4_strdup(Endpoint);
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid)
+{
+  if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
+  else UuidCreateNil(&Binding->ObjectUuid);
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_SpawnBinding(RpcBinding** Binding, RpcBinding* OldBinding)
+{
+  RpcBinding* NewBinding;
+
+  NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
+  NewBinding->refs = 1;
+  NewBinding->server = OldBinding->server;
+  NewBinding->Protseq = RPCRT4_strdup(OldBinding->Protseq);
+  NewBinding->NetworkAddr = RPCRT4_strdup(OldBinding->NetworkAddr);
+  NewBinding->Endpoint = RPCRT4_strdup(OldBinding->Endpoint);
+  /* because of the way named pipes work, we'll transfer the connected pipe
+   * to the child, then reopen the server binding to continue listening */
+  NewBinding->conn = OldBinding->conn;
+  NewBinding->ovl = OldBinding->ovl;
+  OldBinding->conn = 0;
+  memset(&OldBinding->ovl, 0, sizeof(OldBinding->ovl));
+  *Binding = NewBinding;
+  RPCRT4_OpenBinding(OldBinding);
+
+  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);
+  RPCRT4_CloseBinding(Binding);
+  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)
+{
+  if (!Binding->conn) {
+    if (Binding->server) { /* server */
+      /* protseq=ncalrpc: supposed to use NT LPC ports,
+       * but we'll implement it with named pipes for now */
+      if (strcmp(Binding->Protseq, "ncalrpc") == 0) {
+        static LPSTR prefix = "\\\\.\\pipe\\lrpc\\";
+        LPSTR pname;
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Binding->Endpoint);
+	TRACE("listening on %s\n", pname);
+        Binding->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                                         0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
+        HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Binding->ovl, 0, sizeof(Binding->ovl));
+        Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+        if (!ConnectNamedPipe(Binding->conn, &Binding->ovl)) {
+          DWORD err = GetLastError();
+          if (err == ERROR_PIPE_CONNECTED) {
+            SetEvent(Binding->ovl.hEvent);
+            return RPC_S_OK;
+          }
+          return err;
+        }
+      }
+      /* protseq=ncacn_np: named pipes */
+      else if (strcmp(Binding->Protseq, "ncacn_np") == 0) {
+        static LPSTR prefix = "\\\\.";
+        LPSTR pname;
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Binding->Endpoint);
+	TRACE("listening on %s\n", pname);
+        Binding->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                                         0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
+        HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Binding->ovl, 0, sizeof(Binding->ovl));
+        Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+        if (!ConnectNamedPipe(Binding->conn, &Binding->ovl)) {
+          DWORD err = GetLastError();
+          if (err == ERROR_PIPE_CONNECTED) {
+            SetEvent(Binding->ovl.hEvent);
+            return RPC_S_OK;
+          }
+          return err;
+        }
+      }
+      else {
+	ERR("protseq %s not supported\n", Binding->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(Binding->Protseq, "ncalrpc") == 0) {
+        static LPSTR prefix = "\\\\.\\pipe\\lrpc\\";
+        LPSTR pname;
+	HANDLE conn;
+	DWORD err;
+
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Binding->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, FILE_FLAG_OVERLAPPED, 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 err;
+	  }
+	  else {
+	    err = GetLastError();
+	    TRACE("connection failed, error=%lx\n", err);
+	    HeapFree(GetProcessHeap(), 0, pname);
+	    return err;
+	  }
+	}
+
+	/* success */
+	HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Binding->ovl, 0, sizeof(Binding->ovl));
+        Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+	Binding->conn = conn;
+      }
+      /* protseq=ncacn_np: named pipes */
+      else if (strcmp(Binding->Protseq, "ncacn_np") == 0) {
+        static LPSTR prefix = "\\\\.";
+        LPSTR pname;
+	HANDLE conn;
+	DWORD err;
+
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Binding->Endpoint);
+	TRACE("connecting to %s\n", pname);
+	conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+			   OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 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);
+	  return err;
+	}
+
+	/* success */
+	HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Binding->ovl, 0, sizeof(Binding->ovl));
+        Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+	Binding->conn = conn;
+      }
+      else {
+	ERR("protseq %s not supported\n", Binding->Protseq);
+	return RPC_S_PROTSEQ_NOT_SUPPORTED;
+      }
+    }
+  }
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding)
+{
+  if (Binding->conn) {
+    CancelIo(Binding->conn);
+    CloseHandle(Binding->conn);
+    Binding->conn = 0;
+  }
+  if (Binding->ovl.hEvent) {
+    CloseHandle(Binding->ovl.hEvent);
+    Binding->ovl.hEvent = 0;
+  }
+  return RPC_S_OK;
+}
+
+/* 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);
+  ndst[len] = ',';
+  memcpy(ndst+len+1, src, slen*sizeof(CHAR));
+  ndst[len+slen+1] = 0;
+  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);
+  ndst[len] = ',';
+  memcpy(ndst+len+1, src, slen*sizeof(WCHAR));
+  ndst[len+slen+1] = 0;
+  return ndst;
+}
+
+#define RPC_STRING_BINDING_COMPOSE(char_t,strlen_t,strcopy_t) \
+  if (ObjUuid && *ObjUuid) len += strlen_t(ObjUuid) + 1; \
+  if (Protseq && *Protseq) len += strlen_t(Protseq) + 1; \
+  if (NetworkAddr && *NetworkAddr) len += strlen_t(NetworkAddr); \
+  if (Endpoint && *Endpoint) len += strlen_t(Endpoint) + 2; \
+  if (Options && *Options) len += strlen_t(Options) + 2; \
+  \
+  data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(char_t)); \
+  *StringBinding = data; \
+  \
+  if (ObjUuid && *ObjUuid) { \
+    data += strcopy_t(data, ObjUuid); \
+    *data++ = '@'; \
+  } \
+  if (Protseq && *Protseq) { \
+    data += strcopy_t(data, Protseq); \
+    *data++ = ':'; \
+  } \
+  if (NetworkAddr && *NetworkAddr) { \
+    data += strcopy_t(data, NetworkAddr); \
+  } \
+  if ((Endpoint && *Endpoint) || \
+      (Options && *Options)) { \
+    *data++ = '['; \
+    if (Endpoint && *Endpoint) { \
+      data += strcopy_t(data, Endpoint); \
+      if (Options && *Options) *data++ = ','; \
+    } \
+    if (Options && *Options) { \
+      data += strcopy_t(data, Options); \
+    } \
+    *data++ = ']'; \
+  } \
+  *data = 0;
+
+/***********************************************************************
+ *		RpcStringBindingComposeA (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcStringBindingComposeA( LPSTR ObjUuid, LPSTR Protseq,
+					    LPSTR NetworkAddr, LPSTR Endpoint,
+					    LPSTR Options, LPSTR* 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 );
+
+  RPC_STRING_BINDING_COMPOSE(CHAR,strlen,RPCRT4_strcopyA)
+
+  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);
+
+  RPC_STRING_BINDING_COMPOSE(WCHAR,strlenW,RPCRT4_strcopyW)
+
+  return RPC_S_OK;
+}
+
+#define RPC_STRING_BINDING_PARSE(char_t,strlen_t,strchr_t,strncmp_t,strdup_t,strconc_t) \
+  if (ObjUuid) *ObjUuid = NULL; \
+  if (Protseq) *Protseq = NULL; \
+  if (NetworkAddr) *NetworkAddr = NULL; \
+  if (Endpoint) *Endpoint = NULL; \
+  if (Options) *Options = NULL; \
+  \
+  data = StringBinding; \
+  \
+  next = strchr_t(data, '@'); \
+  if (next) { \
+    if (ObjUuid) *ObjUuid = strdup_t(data, next - data); \
+    data = next+1; \
+  } \
+  \
+  next = strchr_t(data, ':'); \
+  if (next) { \
+    if (Protseq) *Protseq = strdup_t(data, next - data); \
+    data = next+1; \
+  } \
+  \
+  next = strchr_t(data, '['); \
+  if (next) { \
+    char_t *close, *opt; \
+    \
+    if (NetworkAddr) *NetworkAddr = strdup_t(data, next - data); \
+    data = next+1; \
+    close = strchr_t(data, ']'); \
+    if (!close) goto fail; \
+    \
+    /* tokenize options */ \
+    while (data < close) { \
+      next = strchr_t(data, ','); \
+      if (!next || next > close) next = close; \
+      /* FIXME: this is kind of inefficient */ \
+      opt = strdup_t(data, next - data); \
+      data = next+1; \
+      \
+      /* parse option */ \
+      next = strchr_t(opt, '='); \
+      if (!next) { \
+	/* not an option, must be an endpoint */ \
+	if (*Endpoint) goto fail; \
+	*Endpoint = opt; \
+      } \
+      else { \
+	if (strncmp_t(opt, ep_opt, strlen_t(ep_opt)) == 0) { \
+	  /* endpoint option */ \
+	  if (*Endpoint) goto fail; \
+	  *Endpoint = strdup_t(next+1, strlen_t(next+1)); \
+	  HeapFree(GetProcessHeap(), 0, opt); \
+	} \
+	else { \
+	  /* network option */ \
+	  if (*Options) { \
+            /* FIXME: this is kind of inefficient */ \
+	    *Options = strconc_t(*Options, opt); \
+	    HeapFree(GetProcessHeap(), 0, opt); \
+	  } \
+	  else *Options = opt; \
+	} \
+      } \
+    } \
+    \
+    data = close+1; \
+    if (*data) goto fail; \
+  } \
+  else if (NetworkAddr) *NetworkAddr = strdup_t(data, strlen_t(data)); \
+
+/***********************************************************************
+ *		RpcStringBindingParseA (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcStringBindingParseA( LPSTR StringBinding, LPSTR *ObjUuid,
+					  LPSTR *Protseq, LPSTR *NetworkAddr,
+					  LPSTR *Endpoint, LPSTR *Options)
+{
+  CHAR *data, *next;
+  static CHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
+
+  TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a(StringBinding),
+	ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
+
+  RPC_STRING_BINDING_PARSE(CHAR,strlen,strchr,strncmp,RPCRT4_strdupAA,RPCRT4_strconcatA)
+
+  return RPC_S_OK;
+fail:
+  if (ObjUuid) RpcStringFreeA(ObjUuid);
+  if (Protseq) RpcStringFreeA(Protseq);
+  if (NetworkAddr) RpcStringFreeA(NetworkAddr);
+  if (Endpoint) RpcStringFreeA(Endpoint);
+  if (Options) RpcStringFreeA(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 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);
+
+  RPC_STRING_BINDING_PARSE(WCHAR,strlenW,strchrW,strncmpW,RPCRT4_strdupWW,RPCRT4_strconcatW)
+
+  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( LPSTR StringBinding, RPC_BINDING_HANDLE* Binding )
+{
+  RPC_STATUS ret;
+  RpcBinding* bind = NULL;
+  LPSTR 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(&Options);
+  RpcStringFreeA(&Endpoint);
+  RpcStringFreeA(&NetworkAddr);
+  RpcStringFreeA(&Protseq);
+  RpcStringFreeA(&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, LPSTR* StringBinding )
+{
+  RPC_STATUS ret;
+  RpcBinding* bind = (RpcBinding*)Binding;
+  LPSTR ObjectUuid;
+
+  TRACE("(%p,%p)\n", Binding, StringBinding);
+
+  ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
+  if (ret != RPC_S_OK) return ret;
+
+  ret = RpcStringBindingComposeA(ObjectUuid, bind->Protseq, bind->NetworkAddr,
+                                 bind->Endpoint, NULL, StringBinding);
+
+  RpcStringFreeA(&ObjectUuid);
+
+  return ret;
+}
+  
+/***********************************************************************
+ *		RpcBindingToStringBindingW (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, LPWSTR* StringBinding )
+{
+  RPC_STATUS ret;
+  LPSTR str = NULL;
+  TRACE("(%p,%p)\n", Binding, StringBinding);
+  ret = RpcBindingToStringBindingA(Binding, &str);
+  *StringBinding = RPCRT4_strdupWA(str, -1);
+  RpcStringFreeA(&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, unsigned long ServerTid )
+{
+  RpcBinding* bind = (RpcBinding*)Binding;
+
+  TRACE( "(%p,%p,%ld): stub\n", Binding, BlockingFn, ServerTid );
+
+  bind->BlockingFn = BlockingFn;
+  bind->ServerTid = ServerTid;
+
+  return RPC_S_OK;
+}
+
--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/rpc_epmap.c	Thu Jun 13 17:20:10 2002
@@ -0,0 +1,172 @@
+/*
+ * RPC endpoint mapper
+ *
+ * Copyright 2001 Ove K???en, TransGaming Technologies
+ *
+ * TODO:
+ *  - actually do things right
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+
+#include "wine/server.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...
+ *
+ * But for now, I'll just use the wineserver...
+ */
+
+/***********************************************************************
+ *		RpcEpRegisterA (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector,
+                                  UUID_VECTOR* UuidVector, LPSTR Annotation )
+{
+  NTSTATUS ret;
+  PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
+  unsigned long c;
+
+  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, bind->Protseq);
+    TRACE(" endpoint[%ld]=%s\n", c, bind->Endpoint);
+  }
+  if (UuidVector) {
+    for (c=0; c<UuidVector->Count; c++)
+      TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c]));
+  }
+
+  SERVER_START_REQ( register_rpc_endpoints )
+  {
+    wine_server_add_data( req, &If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER) );
+    if (UuidVector) {
+      req->objects = UuidVector->Count;
+      for (c=0; c<req->objects; c++)
+        wine_server_add_data( req, UuidVector->Uuid[c], sizeof(UUID) );
+    }
+    else req->objects = 0;
+    req->bindings = BindingVector->Count;
+    for (c=0; c<req->bindings; c++) {
+      RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]);
+      wine_server_add_data( req, bind->Protseq, strlen(bind->Protseq)+1 );
+      wine_server_add_data( req, bind->Endpoint, strlen(bind->Endpoint)+1 );
+    }
+    req->no_replace = 0;
+    /* FIXME: annotation */
+    ret = wine_server_call( req );
+  }
+  SERVER_END_REQ;
+
+  return RtlNtStatusToDosError(ret);
+}
+
+/***********************************************************************
+ *		RpcEpUnregister (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector,
+                                   UUID_VECTOR* UuidVector )
+{
+  NTSTATUS ret;
+  PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
+  unsigned long c;
+
+  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, bind->Protseq);
+    TRACE(" endpoint[%ld]=%s\n", c, bind->Endpoint);
+  }
+  if (UuidVector) {
+    for (c=0; c<UuidVector->Count; c++)
+      TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c]));
+  }
+
+  SERVER_START_REQ( unregister_rpc_endpoints )
+  {
+    wine_server_add_data( req, &If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER) );
+    if (UuidVector) {
+      req->objects = UuidVector->Count;
+      for (c=0; c<req->objects; c++)
+        wine_server_add_data( req, UuidVector->Uuid[c], sizeof(UUID) );
+    }
+    else req->objects = 0;
+    req->bindings = BindingVector->Count;
+    for (c=0; c<req->bindings; c++) {
+      RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]);
+      wine_server_add_data( req, bind->Protseq, strlen(bind->Protseq)+1 );
+      wine_server_add_data( req, bind->Endpoint, strlen(bind->Endpoint)+1 );
+    }
+    ret = wine_server_call( req );
+  }
+  SERVER_END_REQ;
+
+  return RtlNtStatusToDosError(ret);
+}
+
+/***********************************************************************
+ *		RpcEpResolveBinding (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec )
+{
+  NTSTATUS ret;
+  PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec;
+  RpcBinding* bind = (RpcBinding*)Binding;
+  char Endpoint[64];
+
+  TRACE("(%p,%p)\n", Binding, IfSpec);
+  TRACE(" protseq=%s\n", bind->Protseq);
+  TRACE(" obj=%s\n", debugstr_guid(&bind->ObjectUuid));
+  TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
+
+  SERVER_START_REQ( resolve_rpc_endpoint )
+  {
+    wine_server_add_data( req, &If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER) );
+    wine_server_add_data( req, &bind->ObjectUuid, sizeof(UUID) );
+    wine_server_add_data( req, bind->Protseq, strlen(bind->Protseq)+1 );
+    wine_server_set_reply( req, Endpoint, sizeof(Endpoint) );
+    ret = wine_server_call( req );
+  }
+  SERVER_END_REQ;
+
+  if (ret) return RtlNtStatusToDosError(ret);
+
+  return RPCRT4_ResolveBinding(Binding, Endpoint);
+}
+
--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/rpc_message.c	Thu Jun 13 17:26:16 2002
@@ -0,0 +1,166 @@
+/*
+ * RPC messages
+ *
+ * Copyright 2001-2002 Ove K???en, TransGaming Technologies
+ *
+ * TODO:
+ *  - figure out whether we *really* got this right
+ *  - check for errors and throw exceptions
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+
+#include "rpc.h"
+#include "rpcdcep.h"
+
+#include "wine/debug.h"
+
+#include "rpc_binding.h"
+#include "rpc_defs.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+
+/***********************************************************************
+ *           I_RpcGetBuffer [RPCRT4.@]
+ */
+RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
+{
+  void* buf;
+
+  TRACE("(%p)\n", pMsg);
+  buf = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength);
+  if (buf) pMsg->Buffer = buf;
+  /* FIXME: which errors to return? */
+  return buf ? S_OK : E_OUTOFMEMORY;
+}
+
+/***********************************************************************
+ *           I_RpcFreeBuffer [RPCRT4.@]
+ */
+RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
+{
+  TRACE("(%p)\n", pMsg);
+  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;
+  RPC_CLIENT_INTERFACE* cif;
+  RPC_STATUS status;
+  RpcPktHdr hdr;
+
+  TRACE("(%p)\n", pMsg);
+  if (!bind) return RPC_S_INVALID_BINDING;
+
+  /* I'll only implement this for client handles for now */
+  if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
+
+  cif = pMsg->RpcInterfaceInformation;
+  if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
+
+  status = RPCRT4_OpenBinding(bind);
+  if (status != RPC_S_OK) return status;
+
+  /* initialize packet header */
+  memset(&hdr, 0, sizeof(hdr));
+  hdr.rpc_ver = 4;
+  hdr.ptype = PKT_REQUEST;
+  hdr.object = bind->ObjectUuid;
+  hdr.if_id = cif->InterfaceId.SyntaxGUID;
+  hdr.if_vers = MAKELONG(cif->InterfaceId.SyntaxVersion.MinorVersion,
+			 cif->InterfaceId.SyntaxVersion.MajorVersion);
+  hdr.opnum = pMsg->ProcNum;
+  hdr.len = pMsg->BufferLength;
+
+  /* transmit packet */
+  if (!WriteFile(bind->conn, &hdr, sizeof(hdr), NULL, NULL))
+    return GetLastError();
+  if (!WriteFile(bind->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL))
+    return GetLastError();
+
+  /* success */
+  return RPC_S_OK;
+}
+
+/***********************************************************************
+ *           I_RpcReceive [RPCRT4.@]
+ */
+RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
+{
+  RpcBinding* bind = (RpcBinding*)pMsg->Handle;
+  RPC_STATUS status;
+  RpcPktHdr hdr;
+  DWORD dwRead;
+
+  TRACE("(%p)\n", pMsg);
+  if (!bind) return RPC_S_INVALID_BINDING;
+
+  /* I'll only implement this for client handles for now */
+  if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
+
+  status = RPCRT4_OpenBinding(bind);
+  if (status != RPC_S_OK) return status;
+
+  /* read packet header */
+#ifdef OVERLAPPED_WORKS
+  if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, &bind->ovl)) {
+    DWORD err = GetLastError();
+    if (err != ERROR_IO_PENDING) {
+      return err;
+    }
+    if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError();
+  }
+#else
+  if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL))
+    return GetLastError();
+#endif
+  if (dwRead != sizeof(hdr)) return RPC_S_PROTOCOL_ERROR;
+
+  /* read packet body */
+  pMsg->BufferLength = hdr.len;
+  status = I_RpcGetBuffer(pMsg);
+  if (status != RPC_S_OK) return status;
+#ifdef OVERLAPPED_WORKS
+  if (!ReadFile(bind->conn, pMsg->Buffer, hdr.len, &dwRead, &bind->ovl)) {
+    DWORD err = GetLastError();
+    if (err != ERROR_IO_PENDING) {
+      return err;
+    }
+    if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError();
+  }
+#else
+  if (!ReadFile(bind->conn, pMsg->Buffer, hdr.len, &dwRead, NULL))
+    return GetLastError();
+#endif
+  if (dwRead != hdr.len) return RPC_S_PROTOCOL_ERROR;
+
+  /* success */
+  return RPC_S_OK;
+}
+
+/***********************************************************************
+ *           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;
+}
+
--- /dev/null	Mon Mar  4 08:42:02 2002
+++ wine/dlls/rpcrt4/rpc_server.c	Thu Jun 13 17:26:43 2002
@@ -0,0 +1,563 @@
+/*
+ * RPC server API
+ *
+ * Copyright 2001 Ove K???en, TransGaming Technologies
+ *
+ * TODO:
+ *  - a whole lot
+ */
+
+#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_server.h"
+#include "rpc_defs.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+
+static RpcServerProtseq* protseqs;
+static RpcServerInterface* ifs;
+
+static CRITICAL_SECTION server_cs = CRITICAL_SECTION_INIT("RpcServer");
+static BOOL std_listen;
+static LONG listen_count = -1;
+static HANDLE mgr_event, server_thread;
+
+static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id)
+{
+  UUID* MgrType = NULL;
+  RpcServerInterface* cif = NULL;
+  RPC_STATUS status;
+
+  /* FIXME: object -> MgrType */
+  EnterCriticalSection(&server_cs);
+  cif = ifs;
+  while (cif) {
+    if (UuidEqual(if_id, &cif->If->InterfaceId.SyntaxGUID, &status) &&
+	UuidEqual(MgrType, &cif->MgrTypeUuid, &status) &&
+	(std_listen || (cif->Flags & RPC_IF_AUTOLISTEN))) break;
+    cif = cif->Next;
+  }
+  LeaveCriticalSection(&server_cs);
+  return cif;
+}
+
+static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
+{
+  RpcBinding* bind = (RpcBinding*)the_arg;
+  RpcPktHdr hdr;
+  DWORD dwRead;
+  RPC_MESSAGE msg;
+  RpcServerInterface* sif;
+  RPC_DISPATCH_FUNCTION func;
+
+  memset(&msg, 0, sizeof(msg));
+  msg.Handle = (RPC_BINDING_HANDLE)bind;
+
+  for (;;) {
+    /* read packet header */
+#ifdef OVERLAPPED_WORKS
+    if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, &bind->ovl)) {
+      DWORD err = GetLastError();
+      if (err != ERROR_IO_PENDING) {
+        TRACE("connection lost, error=%08lx\n", err);
+        break;
+      }
+      if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break;
+    }
+#else
+    if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
+      TRACE("connection lost, error=%08lx\n", GetLastError());
+      break;
+    }
+#endif
+    if (dwRead != sizeof(hdr)) {
+      TRACE("protocol error\n");
+      break;
+    }
+
+    /* read packet body */
+    msg.BufferLength = hdr.len;
+    msg.Buffer = HeapAlloc(GetProcessHeap(), 0, msg.BufferLength);
+#ifdef OVERLAPPED_WORKS
+    if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, &bind->ovl)) {
+      DWORD err = GetLastError();
+      if (err != ERROR_IO_PENDING) {
+        TRACE("connection lost, error=%08lx\n", err);
+        break;
+      }
+      if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break;
+    }
+#else
+    if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, NULL)) {
+      TRACE("connection lost, error=%08lx\n", GetLastError());
+      break;
+    }
+#endif
+    if (dwRead != hdr.len) {
+      TRACE("protocol error\n");
+      break;
+    }
+
+    sif = RPCRT4_find_interface(&hdr.object, &hdr.if_id);
+    if (sif) {
+      msg.RpcInterfaceInformation = sif->If;
+      /* associate object with binding (this is a bit of a hack...
+       * a new binding should probably be created for each object) */
+      RPCRT4_SetBindingObject(bind, &hdr.object);
+      /* process packet*/
+      switch (hdr.ptype) {
+      case PKT_REQUEST:
+	/* find dispatch function */
+	msg.ProcNum = hdr.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];
+	}
+
+	/* dispatch */
+	if (func) func(&msg);
+
+	/* prepare response packet */
+	hdr.ptype = PKT_RESPONSE;
+	break;
+      default:
+	ERR("unknown packet type\n");
+	goto no_reply;
+      }
+
+      /* write reply packet */
+      hdr.len = msg.BufferLength;
+      WriteFile(bind->conn, &hdr, sizeof(hdr), NULL, NULL);
+      WriteFile(bind->conn, msg.Buffer, msg.BufferLength, NULL, NULL);
+
+    no_reply:
+      /* un-associate object */
+      RPCRT4_SetBindingObject(bind, NULL);
+      msg.RpcInterfaceInformation = NULL;
+    }
+    else {
+      ERR("got RPC packet to unregistered interface %s\n", debugstr_guid(&hdr.if_id));
+    }
+
+    /* clean up */
+    HeapFree(GetProcessHeap(), 0, msg.Buffer);
+    msg.Buffer = NULL;
+  }
+  if (msg.Buffer) HeapFree(GetProcessHeap(), 0, msg.Buffer);
+  RPCRT4_DestroyBinding(bind);
+  return 0;
+}
+
+static void RPCRT4_new_client(RpcBinding* bind)
+{
+  bind->thread = CreateThread(NULL, 0, RPCRT4_io_thread, bind, 0, NULL);
+}
+
+static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
+{
+  HANDLE m_event = mgr_event, b_handle;
+  HANDLE *objs = NULL;
+  DWORD count, res;
+  RpcServerProtseq* cps;
+  RpcBinding* bind;
+  RpcBinding* cbind;
+
+  for (;;) {
+    EnterCriticalSection(&server_cs);
+    /* open and count bindings */
+    count = 1;
+    cps = protseqs;
+    while (cps) {
+      bind = cps->bind;
+      while (bind) {
+	RPCRT4_OpenBinding(bind);
+        if (bind->ovl.hEvent) count++;
+        bind = bind->Next;
+      }
+      cps = cps->Next;
+    }
+    /* make array of bindings */
+    objs = HeapReAlloc(GetProcessHeap(), 0, objs, count*sizeof(HANDLE));
+    objs[0] = m_event;
+    count = 1;
+    cps = protseqs;
+    while (cps) {
+      bind = cps->bind;
+      while (bind) {
+        if (bind->ovl.hEvent) objs[count++] = bind->ovl.hEvent;
+        bind = bind->Next;
+      }
+      cps = cps->Next;
+    }
+    LeaveCriticalSection(&server_cs);
+
+    /* start waiting */
+    res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);
+    if (res == WAIT_OBJECT_0) {
+      if (listen_count == -1) break;
+    }
+    else if (res == WAIT_FAILED) {
+      ERR("wait failed\n");
+    }
+    else {
+      b_handle = objs[res - WAIT_OBJECT_0];
+      /* find which binding got a RPC */
+      EnterCriticalSection(&server_cs);
+      bind = NULL;
+      cps = protseqs;
+      while (cps) {
+        bind = cps->bind;
+        while (bind) {
+          if (bind->ovl.hEvent == b_handle) break;
+          bind = bind->Next;
+        }
+        if (bind) break;
+        cps = cps->Next;
+      }
+      cbind = NULL;
+      if (bind) RPCRT4_SpawnBinding(&cbind, bind);
+      LeaveCriticalSection(&server_cs);
+      if (!bind) {
+        ERR("failed to locate binding for handle %d\n", b_handle);
+      }
+      if (cbind) RPCRT4_new_client(cbind);
+    }
+  }
+  HeapFree(GetProcessHeap(), 0, objs);
+  EnterCriticalSection(&server_cs);
+  /* close bindings */
+  cps = protseqs;
+  while (cps) {
+    bind = cps->bind;
+    while (bind) {
+      RPCRT4_CloseBinding(bind);
+      bind = bind->Next;
+    }
+    cps = cps->Next;
+  }
+  LeaveCriticalSection(&server_cs);
+  return 0;
+}
+
+static void RPCRT4_start_listen(void)
+{
+  if (!InterlockedIncrement(&listen_count)) {
+    mgr_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+    server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL);
+  }
+  else SetEvent(mgr_event);
+}
+
+static void RPCRT4_stop_listen(void)
+{
+  HANDLE m_event = mgr_event;
+  if (InterlockedDecrement(&listen_count) < 0)
+    SetEvent(m_event);
+}
+
+static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps)
+{
+  RPCRT4_CreateBindingA(&ps->bind, TRUE, ps->Protseq);
+  RPCRT4_CompleteBindingA(ps->bind, NULL, ps->Endpoint, NULL);
+
+  EnterCriticalSection(&server_cs);
+  ps->Next = protseqs;
+  protseqs = ps;
+  LeaveCriticalSection(&server_cs);
+
+  if (listen_count >= 0) SetEvent(mgr_event);
+
+  return RPC_S_OK;
+}
+
+/***********************************************************************
+ *		RpcServerInqBindings (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
+{
+  RPC_STATUS status;
+  DWORD count;
+  RpcServerProtseq* ps;
+  RpcBinding* bind;
+
+  EnterCriticalSection(&server_cs);
+  /* count bindings */
+  count = 0;
+  ps = protseqs;
+  while (ps) {
+    bind = ps->bind;
+    while (bind) {
+      count++;
+      bind = bind->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) {
+      bind = ps->bind;
+      while (bind) {
+	RPCRT4_ExportBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
+			     bind);
+	count++;
+	bind = bind->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( LPSTR Protseq, UINT MaxCalls, LPSTR 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( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor,
+                                            PRPC_POLICY lpPolicy )
+{
+  RpcServerProtseq* ps;
+
+  TRACE("(%s,%u,%s,%p,{%u,%lu,%lu}): stub\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}): stub\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_strdupW(Protseq);
+  ps->Endpoint = RPCRT4_strdupW(Endpoint);
+
+  return RPCRT4_use_protseq(ps);
+}
+
+/***********************************************************************
+ *		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->InterfaceId.SyntaxGUID),
+                                        If->InterfaceId.SyntaxVersion.MajorVersion,
+                                        If->InterfaceId.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: %d\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);
+  TRACE(" flags: %08x\n", If->Flags);
+
+  sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface));
+  sif->If           = If;
+  if (MgrTypeUuid)
+    memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID));
+  else
+    memset(&sif->MgrTypeUuid, 0, sizeof(UUID));
+  sif->MgrEpv       = MgrEpv;
+  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;
+}
+
+/***********************************************************************
+ *		RpcServerRegisterAuthInfoA (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( LPSTR 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 (std_listen)
+    return RPC_S_ALREADY_LISTENING;
+
+  if (!protseqs)
+    return RPC_S_NO_PROTSEQS_REGISTERED;
+
+  std_listen = TRUE;
+  RPCRT4_start_listen();
+
+  if (DontWait) return RPC_S_OK;
+
+  /* RpcMgmtWaitServerListen(); */
+  FIXME("can't wait yet\n");
+  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;
+}
+
+


More information about the wine-patches mailing list