some rpcrt4 stuff

Jürgen Schmied juergen.schmied at debitel.net
Sun Oct 6 14:47:44 CDT 2002


Hi!

Here are the old patches from Ove...

Juergen



---
juergen.schmied at debitel.net



-------------- next part --------------
Hope I didn't forget any files? But this patch is definitely not ready for
prime time yet. Lots of stuff is missing, and the implementation of the 
RPC server is miserable. And it only supports named pipes, can't actually
marshal much yet, etc.

Ove Kaaven <ovek at transgaming.com>
Implemented some of the RPC/DCOM infrastructure.

Index: dlls/rpcrt4/Makefile.in
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/rpcrt4/Makefile.in,v
retrieving revision 1.4
diff -u -r1.4 Makefile.in
--- dlls/rpcrt4/Makefile.in	15 Feb 2002 19:12:37 -0000	1.4
+++ dlls/rpcrt4/Makefile.in	8 Jun 2002 01:39:22 -0000
@@ -4,11 +4,22 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = rpcrt4
+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@
Index: dlls/rpcrt4/rpcrt4.spec
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/rpcrt4/rpcrt4.spec,v
retrieving revision 1.13
diff -u -r1.13 rpcrt4.spec
--- dlls/rpcrt4/rpcrt4.spec	19 Feb 2002 18:37:26 -0000	1.13
+++ dlls/rpcrt4/rpcrt4.spec	8 Jun 2002 01:39:23 -0000
@@ -2,6 +2,7 @@
 type	win32
 init	RPCRT4_LibMain
 
+import	advapi32.dll
 import	kernel32.dll
 import	ntdll.dll
 
@@ -23,11 +24,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
@@ -47,7 +43,7 @@
 @ stub RpcBindingInqAuthInfoW
 @ stub RpcBindingInqAuthInfoExA
 @ stub RpcBindingInqAuthInfoExW
-@ stub RpcBindingInqObject
+@ stdcall RpcBindingInqObject(ptr ptr) RpcBindingInqObject
 @ stub RpcBindingInqOption
 @ stub RpcBindingReset
 @ stub RpcBindingServerFromClient
@@ -55,23 +51,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
@@ -116,7 +112,7 @@
 @ stub RpcRegisterAsyncInfo
 @ stub RpcRevertToSelf
 @ stub RpcRevertToSelfEx
-@ stub RpcServerInqBindings
+@ stdcall RpcServerInqBindings(ptr) RpcServerInqBindings
 @ stub RpcServerInqDefaultPrincNameA
 @ stub RpcServerInqDefaultPrincNameW
 @ stub RpcServerInqIf
@@ -168,49 +164,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
-@ stub UuidFromStringA
-@ stub UuidFromStringW
-@ stdcall UuidHash(ptr ptr) UuidHash
-@ stub UuidIsNil
-@ stdcall UuidToStringA(ptr ptr) UuidToStringA
-@ stub 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 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
+
+@ 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
@@ -251,18 +252,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
@@ -277,7 +278,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
@@ -330,11 +333,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
@@ -364,8 +367,6 @@
 @ stub NdrSimpleStructUnmarshall
 @ stub NdrSimpleTypeMarshall
 @ stub NdrSimpleTypeUnmarshall
-@ stub NdrStubInitialize
-@ stub NdrStubInitializeMarshall
 @ stub NdrUserMarshalBufferSize
 @ stub NdrUserMarshalFree
 @ stub NdrUserMarshalMarshall
@@ -433,17 +434,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
@@ -463,17 +465,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
@@ -510,7 +512,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
 
Index: dlls/rpcrt4/rpcrt4_main.c
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/rpcrt4/rpcrt4_main.c,v
retrieving revision 1.20
diff -u -r1.20 rpcrt4_main.c
--- dlls/rpcrt4/rpcrt4_main.c	31 Jan 2002 21:47:34 -0000	1.20
+++ dlls/rpcrt4/rpcrt4_main.c	8 Jun 2002 01:39:23 -0000
@@ -13,9 +13,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"
@@ -41,8 +41,12 @@
 
 #include "debugtools.h"
 
+#include "rpc_binding.h"
+
 DEFAULT_DEBUG_CHANNEL(ole);
 
+static UUID uuid_nil;
+
 /***********************************************************************
  * RPCRT4_LibMain
  *
@@ -70,6 +74,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.@]
  *
@@ -88,11 +127,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;
@@ -231,7 +270,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 */
@@ -268,6 +307,14 @@
    return RPC_S_OK;
 }
 
+/*************************************************************************
+ *           UuidCreateNil   [RPCRT4.@]
+ */
+RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
+{
+  *Uuid = uuid_nil;
+  return RPC_S_OK;
+}
 
 /*************************************************************************
  *           UuidCreateSequential   [RPCRT4.@]
@@ -275,45 +322,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.
  *
@@ -325,236 +414,149 @@
  *  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;
 }
 
-/***********************************************************************
- *		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.@)
- */
-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 )
-{
-  /* 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 */
-}
-
-
-/***********************************************************************
- *		RpcServerRegisterAuthInfoA (RPCRT4.@)
+/*************************************************************************
+ *           UuidFromStringA   [RPCRT4.@]
+ *
+ * Converts a string to a UUID.
  */
-RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( LPSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
-                            LPVOID Arg )
+RPC_STATUS WINAPI UuidFromStringA(LPSTR StringUuid, UUID *Uuid)
 {
-  FIXME( "(%s,%lu,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg );
-  
-  return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
-}
+  unsigned i;
 
-/***********************************************************************
- *		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 */
-}
+  if(!StringUuid)
+    return UuidCreateNil(Uuid);
+
+  if (strlen(StringUuid) != 36)
+    return RPC_S_INVALID_STRING_UUID;
+
+  if (StringUuid[8]!='-' || StringUuid[13]!='-' || StringUuid[18]!='-' || StringUuid[23]!='-')
+    return RPC_S_INVALID_STRING_UUID;
+
+  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;
+  }
+
+  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);
 
-/***********************************************************************
- *		RpcServerListen (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )
-{
-  FIXME( "(%u,%u,%u): stub\n", MinimumCallThreads, MaxCalls, DontWait );
-  
-  return RPC_S_NO_PROTSEQS_REGISTERED; /* Since we don't allow registration this seems reasonable */
+  return RPC_S_OK;
 }
 
-/***********************************************************************
- *		RpcStringBindingComposeA (RPCRT4.@)
+/*************************************************************************
+ *           UuidFromStringW   [RPCRT4.@]
+ *
+ * Converts a string to a UUID.
  */
-RPC_STATUS WINAPI RpcStringBindingComposeA( LPSTR ObjUuid, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint,
-                          LPSTR Options, LPSTR* StringBinding )
+RPC_STATUS WINAPI UuidFromStringW(LPWSTR StringUuid, UUID *Uuid)
 {
-  FIXME( "(%s,%s,%s,%s,%s,%p): stub\n", ObjUuid, Protseq, NetworkAddr, Endpoint, Options, StringBinding );
-  *StringBinding = NULL;
-  
-  return RPC_S_INVALID_STRING_UUID; /* Failure */
-}
+  unsigned i;
 
-/***********************************************************************
- *		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;
-  
-  return RPC_S_INVALID_STRING_UUID; /* Failure */
-}
+  if(!StringUuid)
+    return UuidCreateNil(Uuid);
+
+  if (strlenW(StringUuid) != 36)
+    return RPC_S_INVALID_STRING_UUID;
+
+  if (StringUuid[8]!='-' || StringUuid[13]!='-' || StringUuid[18]!='-' || StringUuid[23]!='-')
+    return RPC_S_INVALID_STRING_UUID;
+
+  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;
+  }
+
+  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;
-}
-
--- /dev/null	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/cproxy.c	Thu May  2 22:07:35 2002
@@ -0,0 +1,276 @@
+/*
+ * COM proxy implementation
+ *
+ * Copyright 2001 Ove K?ven, 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 "debugtools.h"
+
+#include "cpsf.h"
+#include "ndr_misc.h"
+
+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	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/cpsf.c	Mon Jan  7 12:22:51 2002
@@ -0,0 +1,244 @@
+/*
+ * COM proxy/stub factory (CStdPSFactory) implementation
+ *
+ * Copyright 2001 Ove K?ven, 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 "debugtools.h"
+
+#include "cpsf.h"
+
+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	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/cpsf.h	Thu May  2 22:07:23 2002
@@ -0,0 +1,22 @@
+#ifndef __WINE_CPSF_H
+#define __WINE_CPSF_H
+
+HRESULT WINAPI StdProxy_Construct(REFIID riid,
+				  LPUNKNOWN pUnkOuter,
+				  CInterfaceProxyVtbl *vtbl,
+				  CInterfaceStubVtbl *svtbl,
+				  LPPSFACTORYBUFFER pPSFactory,
+				  LPRPCPROXYBUFFER *ppProxy,
+				  LPVOID *ppvObj);
+HRESULT WINAPI StdProxy_GetChannel(LPVOID iface,
+				   LPRPCCHANNELBUFFER *ppChannel);
+HRESULT WINAPI StdProxy_GetIID(LPVOID iface,
+			       const IID **piid);
+
+HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid,
+					LPUNKNOWN pUnkServer,
+					CInterfaceStubVtbl *vtbl,
+					LPPSFACTORYBUFFER pPSFactory,
+					LPRPCSTUBBUFFER *ppStub);
+
+#endif
--- /dev/null	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/cstub.c	Sun Nov 11 18:24:34 2001
@@ -0,0 +1,140 @@
+/*
+ * COM stub (CStdStubBuffer) implementation
+ *
+ * Copyright 2001 Ove K?ven, 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 "debugtools.h"
+
+#include "cpsf.h"
+
+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	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/ndr_midl.c	Fri May  3 02:48:00 2002
@@ -0,0 +1,156 @@
+/*
+ * MIDL proxy/stub stuff
+ *
+ * Copyright 2002 Ove K?ven, 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 "debugtools.h"
+
+#include "cpsf.h"
+#include "ndr_misc.h"
+
+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	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/ndr_misc.h	Mon Nov 19 22:34:34 2001
@@ -0,0 +1,12 @@
+#ifndef __WINE_NDR_MISC_H
+#define __WINE_NDR_MISC_H
+
+struct IPSFactoryBuffer;
+
+LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc,
+			       PFORMAT_STRING pFormat,
+			       LPVOID args);
+
+HRESULT RPCRT4_GetPSFactory(REFIID riid, struct IPSFactoryBuffer **ppPS);
+
+#endif
--- /dev/null	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/ndr_ole.c	Wed May  8 19:11:27 2002
@@ -0,0 +1,317 @@
+/*
+ * OLE32 callouts, COM interface marshalling
+ *
+ * Copyright 2001 Ove K?ven, 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 "debugtools.h"
+
+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	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/ndr_stubless.c	Mon Nov 19 22:34:49 2001
@@ -0,0 +1,45 @@
+/*
+ * NDR client stuff
+ *
+ * Copyright 2001 Ove K?ven, 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 "debugtools.h"
+
+#include "ndr_misc.h"
+
+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	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/rpc_binding.c	Tue May 14 01:53:57 2002
@@ -0,0 +1,742 @@
+/*
+ * RPC binding API
+ *
+ * Copyright 2001 Ove K?ven, 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 "debugtools.h"
+
+#include "rpc_binding.h"
+
+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	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/rpc_binding.h	Tue May 14 01:43:55 2002
@@ -0,0 +1,42 @@
+#ifndef __WINE_RPC_BINDING_H
+#define __WINE_RPC_BINDING_H
+
+/* don't know what MS's structure looks like */
+typedef struct _RpcBinding
+{
+  DWORD refs;
+  struct _RpcBinding* Next; /* for rpc server */
+  BOOL server;
+  UUID ObjectUuid;
+  LPSTR Protseq;
+  LPSTR NetworkAddr;
+  LPSTR Endpoint;
+  RPC_BLOCKING_FN BlockingFn;
+  ULONG ServerTid;
+  HANDLE conn, thread;
+  OVERLAPPED ovl;
+} RpcBinding;
+
+LPSTR RPCRT4_strdupAA(LPSTR src, INT len);
+LPSTR RPCRT4_strdupAW(LPWSTR src, INT len);
+LPWSTR RPCRT4_strdupWA(LPSTR src, INT len);
+LPWSTR RPCRT4_strdupWW(LPWSTR src, INT len);
+void RPCRT4_strfree(LPSTR src);
+
+#define RPCRT4_strdup(x) RPCRT4_strdupAA(x,-1)
+#define RPCRT4_strdupA(x) RPCRT4_strdupAA(x,-1)
+#define RPCRT4_strdupW(x) RPCRT4_strdupAW(x,-1)
+
+RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq);
+RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq);
+RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr,  LPSTR Endpoint,  LPSTR NetworkOptions);
+RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions);
+RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint);
+RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid);
+RPC_STATUS RPCRT4_SpawnBinding(RpcBinding** Binding, RpcBinding* OldBinding);
+RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding);
+RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding);
+RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding);
+RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding);
+
+#endif
--- /dev/null	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/rpc_defs.h	Mon Dec  3 01:25:00 2001
@@ -0,0 +1,61 @@
+#ifndef __WINE_RPC_DEFS_H
+#define __WINE_RPC_DEFS_H
+
+/* info from http://www.microsoft.com/msj/0398/dcomtextfigs.htm */
+
+typedef struct
+{
+  unsigned char rpc_ver;
+  unsigned char ptype;
+  unsigned char flags1;
+  unsigned char flags2;
+  unsigned char drep[3];
+  unsigned char serial_hi;
+  GUID object;
+  GUID if_id;
+  GUID act_id;
+  unsigned long server_boot;
+  unsigned long if_vers;
+  unsigned long seqnum;
+  unsigned short opnum;
+  unsigned short ihint;
+  unsigned short ahint;
+  unsigned short len;
+  unsigned short fragnum;
+  unsigned char auth_proto;
+  unsigned char serial_lo;
+} RpcPktHdr;
+
+#define PKT_REQUEST             0
+#define PKT_PING                1
+#define PKT_RESPONSE            2
+#define PKT_FAULT               3
+#define PKT_WORKING             4
+#define PKT_NOCALL              5
+#define PKT_REJECT              6
+#define PKT_ACK                 7
+#define PKT_CL_CANCEL           8
+#define PKT_FACK                9
+#define PKT_CANCEL_ACK         10
+#define PKT_BIND               11
+#define PKT_BIND_ACK           12
+#define PKT_BIND_NAK           13
+#define PKT_ALTER_CONTEXT      14
+#define PKT_ALTER_CONTEXT_RESP 15
+#define PKT_SHUTDOWN           17
+#define PKT_CO_CANCEL          18
+#define PKT_ORPHANED           19
+
+#define NCADG_IP_UDP   0x08
+#define NCACN_IP_TCP   0x07
+#define NCADG_IPX      0x0E
+#define NCACN_SPX      0x0C
+#define NCACN_NB_NB    0x12
+#define NCACN_NB_IPX   0x0D
+#define NCACN_DNET_NSP 0x04
+#define NCACN_HTTP     0x1F
+
+/* FreeDCE: TWR_C_FLR_PROT_ID_IP */
+#define TWR_IP 0x09
+
+#endif
--- /dev/null	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/rpc_epmap.c	Mon Jan  7 12:21:32 2002
@@ -0,0 +1,171 @@
+/*
+ * RPC endpoint mapper
+ *
+ * Copyright 2001 Ove K?ven, 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 "debugtools.h"
+
+#include "rpc_binding.h"
+
+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	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/rpc_message.c	Tue May 14 02:17:37 2002
@@ -0,0 +1,165 @@
+/*
+ * RPC messages
+ *
+ * Copyright 2001-2002 Ove K?ven, 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 "debugtools.h"
+
+#include "rpc_binding.h"
+#include "rpc_defs.h"
+
+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	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/rpc_server.c	Wed May 15 00:35:43 2002
@@ -0,0 +1,562 @@
+/*
+ * RPC server API
+ *
+ * Copyright 2001 Ove K?ven, 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 "debugtools.h"
+
+#include "rpc_server.h"
+#include "rpc_defs.h"
+
+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;
+}
+
--- /dev/null	Thu Mar  7 01:17:34 2002
+++ dlls/rpcrt4/rpc_server.h	Fri Nov 30 20:38:13 2001
@@ -0,0 +1,27 @@
+#ifndef __WINE_RPC_SERVER_H
+#define __WINE_RPC_SERVER_H
+
+#include "rpc_binding.h"
+
+typedef struct _RpcServerProtseq
+{
+  struct _RpcServerProtseq* Next;
+  LPSTR Protseq;
+  LPSTR Endpoint;
+  UINT MaxCalls;
+  RpcBinding* bind;
+} RpcServerProtseq;
+
+typedef struct _RpcServerInterface
+{
+  struct _RpcServerInterface* Next;
+  RPC_SERVER_INTERFACE* If;
+  UUID MgrTypeUuid;
+  RPC_MGR_EPV* MgrEpv;
+  UINT Flags;
+  UINT MaxCalls;
+  UINT MaxRpcSize;
+  RPC_IF_CALLBACK_FN* IfCallbackFn;
+} RpcServerInterface;
+
+#endif



_______________________________________________________________

Don't miss the 2002 Sprint PCS Application Developer's Conference
August 25-28 in Las Vegas - http://devcon.sprintpcs.com/adp/index.cfm?source
_______________________________________________
rewind-patches mailing list
rewind-patches at lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rewind-patches

-------------- next part --------------
Ove Kaaven <ovek at transgaming.com>
Many RPC header definitions.

Index: include/rpc.h
===================================================================
RCS file: /cvsroot/rewind/rewind/include/rpc.h,v
retrieving revision 1.7
diff -u -r1.7 rpc.h
--- include/rpc.h	18 Jul 2001 20:04:08 -0000	1.7
+++ include/rpc.h	8 Jun 2002 01:10:18 -0000
@@ -9,6 +9,8 @@
 #ifndef __WINE_RPC_H
 #define __WINE_RPC_H
 
+#define __RPC_WIN32__
+
 #define __RPC_FAR
 #define __RPC_API  WINAPI
 #define __RPC_USER WINAPI
Index: include/rpcdce.h
===================================================================
RCS file: /cvsroot/rewind/rewind/include/rpcdce.h,v
retrieving revision 1.6
diff -u -r1.6 rpcdce.h
--- include/rpcdce.h	5 Feb 2002 18:09:29 -0000	1.6
+++ include/rpcdce.h	8 Jun 2002 01:10:18 -0000
@@ -11,8 +11,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
@@ -20,14 +18,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
 {
@@ -72,6 +75,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 );
@@ -80,6 +88,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 );
@@ -95,6 +110,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
@@ -145,22 +199,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: include/rpcdcep.h
===================================================================
RCS file: /cvsroot/rewind/rewind/include/rpcdcep.h,v
retrieving revision 1.1
diff -u -r1.1 rpcdcep.h
--- include/rpcdcep.h	8 Nov 2000 05:06:10 -0000	1.1
+++ include/rpcdcep.h	8 Jun 2002 01:10:19 -0000
@@ -1,7 +1,6 @@
 #ifndef __WINE_RPCDCEP_H
 #define __WINE_RPCDCEP_H
 
-
 typedef struct _RPC_VERSION {
     unsigned short MajorVersion;
     unsigned short MinorVersion;
@@ -27,4 +26,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: include/rpcndr.h
===================================================================
RCS file: /cvsroot/rewind/rewind/include/rpcndr.h,v
retrieving revision 1.4
diff -u -r1.4 rpcndr.h
--- include/rpcndr.h	5 Feb 2002 18:09:29 -0000	1.4
+++ include/rpcndr.h	8 Jun 2002 01:10:19 -0000
@@ -4,7 +4,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;
@@ -13,6 +16,9 @@
 typedef unsigned char _wine_boolean;
 /* typedef _wine_boolean boolean; */
 
+#define __RPC_CALLEE WINAPI
+#define RPC_VAR_ENTRY WINAPIV
+
 typedef struct
 {
   void *pad[2];
@@ -78,7 +84,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;
@@ -128,8 +134,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;
@@ -177,6 +183,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,
@@ -235,6 +257,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: include/rpcproxy.h
===================================================================
RCS file: /cvsroot/rewind/rewind/include/rpcproxy.h,v
retrieving revision 1.1
diff -u -r1.1 rpcproxy.h
--- include/rpcproxy.h	14 Oct 2001 16:15:37 -0000	1.1
+++ include/rpcproxy.h	8 Jun 2002 01:10:19 -0000
@@ -1,8 +1,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;
@@ -29,6 +35,8 @@
 
 #include "rpc.h"
 #include "rpcndr.h"
+#include "wine/obj_base.h"
+#include "wine/obj_channel.h"
 
 typedef struct tagCInterfaceProxyHeader
 {
@@ -129,6 +137,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 );
@@ -143,6 +177,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 */


_______________________________________________________________

Don't miss the 2002 Sprint PCS Application Developer's Conference
August 25-28 in Las Vegas - http://devcon.sprintpcs.com/adp/index.cfm?source=osdntextlink

_______________________________________________
rewind-patches mailing list
rewind-patches at lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rewind-patches

-------------- next part --------------
This is the wineserver part of the current code; it seemed easiest to put
the RPC epmapper into the wineserver for now. This patch may not be ready
for prime time yet.

Ove Kaaven <ovek at transgaming.com>
RPC epmapper.

Index: server/Makefile.in
===================================================================
RCS file: /cvsroot/rewind/rewind/server/Makefile.in,v
retrieving revision 1.30
diff -u -r1.30 Makefile.in
--- server/Makefile.in	28 Aug 2001 18:44:53 -0000	1.30
+++ server/Makefile.in	8 Jun 2002 01:44:21 -0000
@@ -28,6 +28,7 @@
 	queue.c \
 	registry.c \
 	request.c \
+	rpc_epmap.c \
 	select.c \
 	semaphore.c \
 	serial.c \
Index: server/protocol.def
===================================================================
RCS file: /cvsroot/rewind/rewind/server/protocol.def,v
retrieving revision 1.27
diff -u -r1.27 protocol.def
--- server/protocol.def	27 Apr 2002 20:31:14 -0000	1.27
+++ server/protocol.def	8 Jun 2002 01:43:08 -0000
@@ -1816,3 +1816,28 @@
     int            total;         /* total number of properties */
     VARARG(props,properties);     /* list of properties */
 @END
+
+
+/* Register RPC endpoints */
+ at REQ(register_rpc_endpoints)
+    int            objects;       /* number of objects */
+    int            bindings;      /* number of bindings */
+    int            no_replace;    /* don't replace existing endpoints */
+    VARARG(eps,bytes);            /* list of bindings and objects */
+ at END
+
+
+/* Unregister RPC endpoints */
+ at REQ(unregister_rpc_endpoints)
+    int            objects;       /* number of objects */
+    int            bindings;      /* number of bindings */
+    VARARG(eps,bytes);            /* list of bindings and objects */
+ at END
+
+
+/* Resolve RPC endpoint */
+ at REQ(resolve_rpc_endpoint)
+    VARARG(binding,bytes);        /* unmapped binding */
+ at REPLY
+    VARARG(ep,bytes);             /* mapped endpoint */
+ at END
--- /dev/null	Thu Mar  7 01:17:34 2002
+++ server/rpc_epmap.c	Tue Dec  4 18:13:26 2001
@@ -0,0 +1,191 @@
+/*
+ * RPC endpoint mapper
+ *
+ * Copyright (C) 2001 Ove K?ven, TransGaming Technologies Inc.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "unicode.h"
+#include "request.h"
+#include "process.h"
+
+#include "rpc.h"
+
+struct epmap_entry
+{
+    struct epmap_entry *next;
+    RPC_SYNTAX_IDENTIFIER iface;
+    UUID object;
+    char *protseq;
+    char *endpoint;
+};
+
+struct epmap_entry *epmap;
+
+static const UUID nil_object;
+
+static struct epmap_entry *find_endpoint(const RPC_SYNTAX_IDENTIFIER *iface,
+                                         const char *protseq, const UUID *object)
+{
+    struct epmap_entry *map;
+    for (map=epmap; map; map=map->next) {
+        if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
+        if (memcmp(&map->object, object, sizeof(UUID))) continue;
+        if (strcmp(map->protseq, protseq)) continue;
+        return map;
+    }
+    return NULL;
+}
+
+static void register_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq,
+                              const char *endpoint, const UUID *objects, int objcount,
+                              int no_replace)
+{
+    int c;
+
+    if (!objcount) {
+        objects = &nil_object;
+        objcount = 1;
+    }
+
+    for (c=0; c<objcount; c++) {
+        struct epmap_entry *map = NULL;
+        if (!no_replace)
+            map = find_endpoint(iface, protseq, &objects[c]);
+        if (map) {
+            free(map->endpoint);
+        }
+        else {
+            map = mem_alloc(sizeof(struct epmap_entry));
+            memcpy(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER));
+            memcpy(&map->object, &objects[c], sizeof(UUID));
+            map->protseq = strdup(protseq);
+            map->next = epmap;
+            epmap = map;
+        }
+        map->endpoint = strdup(endpoint);
+    }
+}
+
+static void unregister_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq,
+                                const char *endpoint, const UUID *objects, int objcount)
+{
+    struct epmap_entry *map, *prev, *nprev, *next;
+    int c;
+
+    if (!objcount) {
+        objects = &nil_object;
+        objcount = 1;
+    }
+
+    for (prev=NULL,nprev=NULL,map=epmap,next=map->next; map; prev=nprev,map=next,next=map->next) {
+        nprev = map;
+        if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
+        for (c=0; c<objcount; c++)
+            if (!memcmp(&map->object, &objects[c], sizeof(UUID))) break;
+        if (c==objcount) continue;
+        if (strcmp(map->protseq, protseq)) continue;
+
+        if (prev) prev->next = map->next;
+        else epmap = map->next;
+        nprev = prev;
+
+        free(map->protseq);
+        free(map->endpoint);
+        free(map);
+    }
+}
+
+static void resolve_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq,
+                             const UUID *object)
+{
+    size_t len;
+    char *data;
+    struct epmap_entry *map;
+
+    if (!(map = find_endpoint(iface, protseq, object))) {
+        set_error( EPT_NT_NOT_REGISTERED );
+        return;
+    }
+
+    len = min( get_reply_max_size(), strlen(map->endpoint)+1 );
+    if (len && ((data = set_reply_data_size(len))))
+       memcpy(data, map->endpoint, len);
+}
+
+static const void *get_struct(const char**ptr, const char*end, size_t size)
+{
+    const char *data = *ptr;
+
+    *ptr = data + size;
+    if (*ptr > end) {
+        set_error( STATUS_INVALID_PARAMETER );
+        return NULL;
+    }
+
+    return data;
+}
+
+static const char *get_string(const char**ptr, const char*end)
+{
+    const char *str = *ptr, *nptr = str;
+
+    while (nptr < end && *nptr) nptr++;
+    if (nptr == end) {
+        set_error( STATUS_INVALID_PARAMETER );
+        return NULL;
+    }
+    *ptr = nptr + 1;
+
+    return str;
+}
+
+DECL_HANDLER(register_rpc_endpoints)
+{
+    const char *data = get_req_data();
+    const char *end = data + get_req_data_size();
+    const RPC_SYNTAX_IDENTIFIER *iface = get_struct(&data, end, sizeof(RPC_SYNTAX_IDENTIFIER));
+    const UUID *objects = get_struct(&data, end, req->objects * sizeof(UUID));
+    if (iface && objects) {
+        int c;
+        for (c=0; c<req->bindings; c++) {
+            const char *protseq = get_string(&data, end);
+            const char *endpoint = get_string(&data, end);
+            if (protseq && endpoint)
+                register_endpoint(iface, protseq, endpoint, objects, req->objects, req->no_replace);
+        }
+    }
+}
+
+DECL_HANDLER(unregister_rpc_endpoints)
+{
+    const char *data = get_req_data();
+    const char *end = data + get_req_data_size();
+    const RPC_SYNTAX_IDENTIFIER *iface = get_struct(&data, end, sizeof(RPC_SYNTAX_IDENTIFIER));
+    const UUID *objects = get_struct(&data, end, req->objects * sizeof(UUID));
+    if (iface && objects) {
+        int c;
+        for (c=0; c<req->bindings; c++) {
+            const char *protseq = get_string(&data, end);
+            const char *endpoint = get_string(&data, end);
+            if (protseq && endpoint)
+                unregister_endpoint(iface, protseq, endpoint, objects, req->objects);
+        }
+    }
+}
+
+DECL_HANDLER(resolve_rpc_endpoint)
+{
+    const char *data = get_req_data();
+    const char *end = data + get_req_data_size();
+    const RPC_SYNTAX_IDENTIFIER *iface = get_struct(&data, end, sizeof(RPC_SYNTAX_IDENTIFIER));
+    const UUID *object = get_struct(&data, end, sizeof(UUID));
+    const char *protseq = get_string(&data, end);
+    if (iface && object && protseq) {
+        resolve_endpoint(iface, protseq, object);
+    }
+}


_______________________________________________________________

Don't miss the 2002 Sprint PCS Application Developer's Conference
August 25-28 in Las Vegas - http://devcon.sprintpcs.com/adp/index.cfm?source
_______________________________________________
rewind-patches mailing list
rewind-patches at lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rewind-patches



More information about the wine-devel mailing list