RPC client/server connections

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



For better concurrency, this patch separates the connections from the
bindings.

For RPC clients, a new RPC client connection is grabbed for every RPC
call, and released when the call ends. This allows multiple RPC calls to
happen simultaneously using the same binding (and is in fact how this is
supposed to work, as far as I can tell from the freedce sources), but
since we don't have a connection cache yet this is going to be somewhat
inefficient (a connection will be opened and closed for every RPC call).
Oh well, at least it works for me this way.

And RPC servers now work with connections, not bindings, bindings are
now created dynamically for every incoming RPC call. RPC calls are also
now dispatched to worker threads, so more than one call can be processed
simultaneously on the same connection (if we can reliably multiplex
multiple calls on the same connection on the client side, that is).

Log:
Ove Kaaven <ovek@transgaming.com>

Index: dlls/rpcrt4/rpc_binding.c
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/rpc_binding.c,v
retrieving revision 1.10
diff -u -r1.10 rpc_binding.c
--- dlls/rpcrt4/rpc_binding.c	31 Jan 2003 03:22:38 -0000	1.10
+++ dlls/rpcrt4/rpc_binding.c	15 Feb 2003 23:38:50 -0000
@@ -93,13 +93,209 @@
   if (src) HeapFree(GetProcessHeap(), 0, src);
 }
 
-RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq)
+RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions)
+{
+  RpcConnection* NewConnection;
+
+  NewConnection = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcConnection));
+  NewConnection->server = server;
+  NewConnection->Protseq = RPCRT4_strdupA(Protseq);
+  NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
+  NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
+
+  TRACE("connection: %p\n", NewConnection);
+  *Connection = NewConnection;
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
+{
+  TRACE("connection: %p\n", Connection);
+  if (Connection->Used) ERR("connection is still in use\n");
+  RPCRT4_CloseConnection(Connection);
+  RPCRT4_strfree(Connection->Endpoint);
+  RPCRT4_strfree(Connection->NetworkAddr);
+  RPCRT4_strfree(Connection->Protseq);
+  HeapFree(GetProcessHeap(), 0, Connection);
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection)
+{
+  TRACE("(Connection == ^%p)\n", Connection);
+  if (!Connection->conn) {
+    if (Connection->server) { /* server */
+      /* protseq=ncalrpc: supposed to use NT LPC ports,
+       * but we'll implement it with named pipes for now */
+      if (strcmp(Connection->Protseq, "ncalrpc") == 0) {
+        static LPSTR prefix = "\\\\.\\pipe\\lrpc\\";
+        LPSTR pname;
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Connection->Endpoint);
+        TRACE("listening on %s\n", pname);
+        Connection->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                                         0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
+        HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Connection->ovl, 0, sizeof(Connection->ovl));
+        Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+        if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) {
+          DWORD err = GetLastError();
+          if (err == ERROR_PIPE_CONNECTED) {
+            SetEvent(Connection->ovl.hEvent);
+            return RPC_S_OK;
+          }
+          return err;
+        }
+      }
+      /* protseq=ncacn_np: named pipes */
+      else if (strcmp(Connection->Protseq, "ncacn_np") == 0) {
+        static LPSTR prefix = "\\\\.";
+        LPSTR pname;
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Connection->Endpoint);
+        TRACE("listening on %s\n", pname);
+        Connection->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                                         0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
+        HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Connection->ovl, 0, sizeof(Connection->ovl));
+        Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+        if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) {
+          DWORD err = GetLastError();
+          if (err == ERROR_PIPE_CONNECTED) {
+            SetEvent(Connection->ovl.hEvent);
+            return RPC_S_OK;
+          }
+          return err;
+        }
+      }
+      else {
+        ERR("protseq %s not supported\n", Connection->Protseq);
+        return RPC_S_PROTSEQ_NOT_SUPPORTED;
+      }
+    }
+    else { /* client */
+      /* protseq=ncalrpc: supposed to use NT LPC ports,
+       * but we'll implement it with named pipes for now */
+      if (strcmp(Connection->Protseq, "ncalrpc") == 0) {
+        static LPSTR prefix = "\\\\.\\pipe\\lrpc\\";
+        LPSTR pname;
+        HANDLE conn;
+        DWORD err;
+
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Connection->Endpoint);
+        TRACE("connecting to %s\n", pname);
+        while (TRUE) {
+          if (WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
+            conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+                               OPEN_EXISTING, 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(&Connection->ovl, 0, sizeof(Connection->ovl));
+        Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+        Connection->conn = conn;
+      }
+      /* protseq=ncacn_np: named pipes */
+      else if (strcmp(Connection->Protseq, "ncacn_np") == 0) {
+        static LPSTR prefix = "\\\\.";
+        LPSTR pname;
+        HANDLE conn;
+        DWORD err;
+
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Connection->Endpoint);
+        TRACE("connecting to %s\n", pname);
+        conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+                           OPEN_EXISTING, 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(&Connection->ovl, 0, sizeof(Connection->ovl));
+        Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+        Connection->conn = conn;
+      } else {
+        ERR("protseq %s not supported\n", Connection->Protseq);
+        return RPC_S_PROTSEQ_NOT_SUPPORTED;
+      }
+    }
+  }
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)
+{
+  TRACE("(Connection == ^%p)\n", Connection);
+  if (Connection->conn) {
+    CancelIo(Connection->conn);
+    CloseHandle(Connection->conn);
+    Connection->conn = 0;
+  }
+  if (Connection->ovl.hEvent) {
+    CloseHandle(Connection->ovl.hEvent);
+    Connection->ovl.hEvent = 0;
+  }
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
+{
+  RpcConnection* NewConnection;
+  RPC_STATUS err = RPCRT4_CreateConnection(&NewConnection, OldConnection->server, OldConnection->Protseq,
+                                           OldConnection->NetworkAddr, OldConnection->Endpoint, NULL);
+  if (err == RPC_S_OK) {
+    /* because of the way named pipes work, we'll transfer the connected pipe
+     * to the child, then reopen the server binding to continue listening */
+    NewConnection->conn = OldConnection->conn;
+    NewConnection->ovl = OldConnection->ovl;
+    OldConnection->conn = 0;
+    memset(&OldConnection->ovl, 0, sizeof(OldConnection->ovl));
+    *Connection = NewConnection;
+    RPCRT4_OpenConnection(OldConnection);
+  }
+  return err;
+}
+
+RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
 {
   RpcBinding* NewBinding;
 
   NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
   NewBinding->refs = 1;
   NewBinding->server = server;
+
+  *Binding = NewBinding;
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq)
+{
+  RpcBinding* NewBinding;
+
+  RPCRT4_AllocBinding(&NewBinding, server);
   NewBinding->Protseq = RPCRT4_strdupA(Protseq);
 
   TRACE("binding: %p\n", NewBinding);
@@ -111,16 +307,8 @@
 RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq)
 {
   RpcBinding* NewBinding;
-  if (Binding)
-    TRACE("(*Binding == ^%p, server == %s, Protseq == \"%s\")\n", *Binding, server ? "Yes" : "No", debugstr_w(Protseq));
-  else {
-    ERR("!RpcBinding?\n"); 
-    assert(FALSE); /* we will crash below anyhow... */
-  }
 
-  NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
-  NewBinding->refs = 1;
-  NewBinding->server = server;
+  RPCRT4_AllocBinding(&NewBinding, server);
   NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
 
   TRACE("binding: %p\n", NewBinding);
@@ -131,8 +319,8 @@
 
 RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr,  LPSTR Endpoint,  LPSTR NetworkOptions)
 {
-  
-  TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding, NetworkAddr, Endpoint, NetworkOptions);
+  TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding,
+   debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
 
   RPCRT4_strfree(Binding->NetworkAddr);
   Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
@@ -183,31 +371,19 @@
   return RPC_S_OK;
 }
 
-RPC_STATUS RPCRT4_SpawnBinding(RpcBinding** Binding, RpcBinding* OldBinding)
+RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
 {
   RpcBinding* NewBinding;
-  if (Binding)
-    TRACE("(*RpcBinding == ^%p, OldBinding == ^%p)\n", *Binding, OldBinding);
-  else {
-    ERR("!RpcBinding?"); 
-    /* we will crash below anyhow... */
-    *((char *)0) = 0;
-  }
+  TRACE("(*RpcBinding == ^%p, Connection == ^%p)\n", *Binding, Connection);
 
-  NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
-  NewBinding->refs = 1;
-  NewBinding->server = OldBinding->server;
-  NewBinding->Protseq = RPCRT4_strdupA(OldBinding->Protseq);
-  NewBinding->NetworkAddr = RPCRT4_strdupA(OldBinding->NetworkAddr);
-  NewBinding->Endpoint = RPCRT4_strdupA(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));
+  RPCRT4_AllocBinding(&NewBinding, Connection->server);
+  NewBinding->Protseq = RPCRT4_strdupA(Connection->Protseq);
+  NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
+  NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
+  NewBinding->FromConn = Connection;
+
+  TRACE("binding: %p\n", NewBinding);
   *Binding = NewBinding;
-  RPCRT4_OpenBinding(OldBinding);
 
   return RPC_S_OK;
 }
@@ -225,7 +401,7 @@
     return RPC_S_OK;
 
   TRACE("binding: %p\n", Binding);
-  RPCRT4_CloseBinding(Binding);
+  /* FIXME: release connections */
   RPCRT4_strfree(Binding->Endpoint);
   RPCRT4_strfree(Binding->NetworkAddr);
   RPCRT4_strfree(Binding->Protseq);
@@ -233,143 +409,29 @@
   return RPC_S_OK;
 }
 
-RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding)
+RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection)
 {
+  RpcConnection* NewConnection;
   TRACE("(Binding == ^%p)\n", 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;
-      }
-    }
+  if (Binding->FromConn) {
+    *Connection = Binding->FromConn;
+    return RPC_S_OK;
   }
-  return RPC_S_OK;
+
+  /* FIXME: cache connections */
+  RPCRT4_CreateConnection(&NewConnection, Binding->server, Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint, NULL);
+  NewConnection->Used = Binding;
+  *Connection = NewConnection;
+  return RPCRT4_OpenConnection(NewConnection);
 }
 
-RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding)
+RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
 {
   TRACE("(Binding == ^%p)\n", 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;
+  if (!Connection) return RPC_S_OK;
+  if (Binding->FromConn == Connection) return RPC_S_OK;
+  Connection->Used = NULL;
+  return RPCRT4_DestroyConnection(Connection);
 }
 
 /* utility functions for string composing and parsing */
@@ -862,7 +924,7 @@
   RpcStringFreeA((unsigned char**)&str);
   return ret;
 }
-  
+
 /***********************************************************************
  *             I_RpcBindingSetAsync (RPCRT4.@)
  * NOTES
Index: dlls/rpcrt4/rpc_binding.h
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/rpc_binding.h,v
retrieving revision 1.2
diff -u -r1.2 rpc_binding.h
--- dlls/rpcrt4/rpc_binding.h	2 Dec 2002 21:17:05 -0000	1.2
+++ dlls/rpcrt4/rpc_binding.h	15 Feb 2003 23:38:50 -0000
@@ -23,20 +23,32 @@
 
 #include "wine/rpcss_shared.h"
 
+typedef struct _RpcConnection
+{
+  struct _RpcConnection* Next;
+  struct _RpcBinding* Used;
+  BOOL server;
+  LPSTR Protseq;
+  LPSTR NetworkAddr;
+  LPSTR Endpoint;
+  HANDLE conn, thread;
+  OVERLAPPED ovl;
+} RpcConnection;
+
 /* don't know what MS's structure looks like */
 typedef struct _RpcBinding
 {
   DWORD refs;
-  struct _RpcBinding* Next; /* for rpc server */
+  struct _RpcBinding* Next;
   BOOL server;
   UUID ObjectUuid;
+  UUID ActiveUuid;
   LPSTR Protseq;
   LPSTR NetworkAddr;
   LPSTR Endpoint;
   RPC_BLOCKING_FN BlockingFn;
   ULONG ServerTid;
-  HANDLE conn, thread;
-  OVERLAPPED ovl;
+  RpcConnection* FromConn;
 } RpcBinding;
 
 LPSTR RPCRT4_strndupA(LPSTR src, INT len);
@@ -48,17 +60,23 @@
 #define RPCRT4_strdupA(x) RPCRT4_strndupA((x),-1)
 #define RPCRT4_strdupW(x) RPCRT4_strndupW((x),-1)
 
+RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions);
+RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection);
+RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection);
+RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection);
+RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection);
+
 RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq);
 RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq);
 RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr,  LPSTR Endpoint,  LPSTR NetworkOptions);
 RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions);
 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint);
 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid);
-RPC_STATUS RPCRT4_SpawnBinding(RpcBinding** Binding, RpcBinding* OldBinding);
+RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection);
 RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding);
 RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding);
-RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding);
-RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding);
+RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection);
+RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection);
 BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply);
 HANDLE RPCRT4_GetMasterMutex(void);
 HANDLE RPCRT4_RpcssNPConnect(void);
Index: dlls/rpcrt4/rpc_message.c
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/rpc_message.c,v
retrieving revision 1.4
diff -u -r1.4 rpc_message.c
--- dlls/rpcrt4/rpc_message.c	28 Oct 2002 23:53:23 -0000	1.4
+++ dlls/rpcrt4/rpc_message.c	15 Feb 2003 23:38:51 -0000
@@ -48,9 +48,10 @@
 {
   void* buf;
 
-  TRACE("(%p)\n", pMsg);
+  TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);
   /* FIXME: pfnAllocate? */
   buf = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength);
+  TRACE("Buffer=%p\n", buf);
   if (buf) pMsg->Buffer = buf;
   /* FIXME: which errors to return? */
   return buf ? S_OK : E_OUTOFMEMORY;
@@ -74,14 +75,23 @@
 RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
 {
   RpcBinding* bind = (RpcBinding*)pMsg->Handle;
+  RpcConnection* conn;
   RPC_CLIENT_INTERFACE* cif = NULL;
   RPC_SERVER_INTERFACE* sif = NULL;
+  UUID* obj;
+  UUID* act;
   RPC_STATUS status;
   RpcPktHdr hdr;
 
   TRACE("(%p)\n", pMsg);
   if (!bind) return RPC_S_INVALID_BINDING;
 
+  status = RPCRT4_OpenBinding(bind, &conn);
+  if (status != RPC_S_OK) return status;
+
+  obj = &bind->ObjectUuid;
+  act = &bind->ActiveUuid;
+
   if (bind->server) {
     sif = pMsg->RpcInterfaceInformation;
     if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
@@ -90,19 +100,17 @@
     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; /* FIXME: IIRC iff no object, the header structure excludes this elt */
+  hdr.ptype = bind->server ? PKT_RESPONSE : PKT_REQUEST;
+  hdr.object = *obj; /* FIXME: IIRC iff no object, the header structure excludes this elt */
   hdr.if_id = (bind->server) ? sif->InterfaceId.SyntaxGUID : cif->InterfaceId.SyntaxGUID;
   hdr.if_vers = 
     (bind->server) ?
     MAKELONG(sif->InterfaceId.SyntaxVersion.MinorVersion, sif->InterfaceId.SyntaxVersion.MajorVersion) :
     MAKELONG(cif->InterfaceId.SyntaxVersion.MinorVersion, cif->InterfaceId.SyntaxVersion.MajorVersion);
+  hdr.act_id = *act;
   hdr.opnum = pMsg->ProcNum;
   /* only the low-order 3 octets of the DataRepresentation go in the header */
   hdr.drep[0] = LOBYTE(LOWORD(pMsg->DataRepresentation));
@@ -111,13 +119,26 @@
   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();
+  if (!WriteFile(conn->conn, &hdr, sizeof(hdr), NULL, NULL)) {
+    status = GetLastError();
+    goto fail;
+  }
+  if (pMsg->BufferLength && !WriteFile(conn->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL)) {
+    status = GetLastError();
+    goto fail;
+  }
 
   /* success */
-  return RPC_S_OK;
+  if (!bind->server) {
+    /* save the connection, so the response can be read from it */
+    pMsg->ReservedForRuntime = conn;
+    return RPC_S_OK;
+  }
+  RPCRT4_CloseBinding(bind, conn);
+  status = RPC_S_OK;
+fail:
+
+  return status;
 }
 
 /***********************************************************************
@@ -126,6 +147,8 @@
 RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
 {
   RpcBinding* bind = (RpcBinding*)pMsg->Handle;
+  RpcConnection* conn;
+  UUID* act;
   RPC_STATUS status;
   RpcPktHdr hdr;
   DWORD dwRead;
@@ -133,44 +156,78 @@
   TRACE("(%p)\n", pMsg);
   if (!bind) return RPC_S_INVALID_BINDING;
 
-  status = RPCRT4_OpenBinding(bind);
-  if (status != RPC_S_OK) return status;
+  if (pMsg->ReservedForRuntime) {
+    conn = pMsg->ReservedForRuntime;
+    pMsg->ReservedForRuntime = NULL;
+  } else {
+    status = RPCRT4_OpenBinding(bind, &conn);
+    if (status != RPC_S_OK) return status;
+  }
+
+  act = &bind->ActiveUuid;
 
-  /* read packet header */
+  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) {
-      return err;
+    if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, &conn->ovl)) {
+      DWORD err = GetLastError();
+      if (err != ERROR_IO_PENDING) {
+        status = err;
+        goto fail;
+      }
+      if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
+        status = GetLastError();
+        goto fail;
+      }
     }
-    if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError();
-  }
 #else
-  if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL))
-    return GetLastError();
+    if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
+      status = GetLastError();
+      goto fail;
+    }
 #endif
-  if (dwRead != sizeof(hdr)) return RPC_S_PROTOCOL_ERROR;
+    if (dwRead != sizeof(hdr)) {
+      status = RPC_S_PROTOCOL_ERROR;
+      goto fail;
+    }
 
-  /* read packet body */
-  pMsg->BufferLength = hdr.len;
-  status = I_RpcGetBuffer(pMsg);
-  if (status != RPC_S_OK) return status;
+    /* read packet body */
+    pMsg->BufferLength = hdr.len;
+    status = I_RpcGetBuffer(pMsg);
+    if (status != RPC_S_OK) goto fail;
+    if (!pMsg->BufferLength) dwRead = 0; else
 #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 (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, &conn->ovl)) {
+      DWORD err = GetLastError();
+      if (err != ERROR_IO_PENDING) {
+        status = err;
+        goto fail;
+      }
+      if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
+        status = GetLastError();
+        goto fail;
+      }
     }
-    if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError();
-  }
 #else
-  if (!ReadFile(bind->conn, pMsg->Buffer, hdr.len, &dwRead, NULL))
-    return GetLastError();
+    if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, NULL)) {
+      status = GetLastError();
+      goto fail;
+    }
 #endif
-  if (dwRead != hdr.len) return RPC_S_PROTOCOL_ERROR;
+    if (dwRead != hdr.len) {
+      status = RPC_S_PROTOCOL_ERROR;
+      goto fail;
+    }
 
-  /* success */
-  return RPC_S_OK;
+    /* success */
+    status = RPC_S_OK;
+
+    /* FIXME: check packet type, destination, etc? */
+    break;
+  }
+fail:
+  RPCRT4_CloseBinding(bind, conn);
+  return status;
 }
 
 /***********************************************************************
Index: dlls/rpcrt4/rpc_server.c
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/rpc_server.c,v
retrieving revision 1.12
diff -u -r1.12 rpc_server.c
--- dlls/rpcrt4/rpc_server.c	1 Nov 2002 01:47:43 -0000	1.12
+++ dlls/rpcrt4/rpc_server.c	15 Feb 2003 23:38:51 -0000
@@ -37,8 +37,18 @@
 #include "rpc_server.h"
 #include "rpc_defs.h"
 
+#define MAX_THREADS 128
+
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
+typedef struct _RpcPacket
+{
+  struct _RpcPacket* next;
+  struct _RpcConnection* conn;
+  RpcPktHdr hdr;
+  void* buf;
+} RpcPacket;
+
 static RpcServerProtseq* protseqs;
 static RpcServerInterface* ifs;
 
@@ -48,6 +58,13 @@
 static LONG listen_count = -1;
 static HANDLE mgr_event, server_thread;
 
+static CRITICAL_SECTION spacket_cs = CRITICAL_SECTION_INIT("RpcServerPacket");
+static RpcPacket* spacket_head;
+static RpcPacket* spacket_tail;
+static HANDLE server_sem;
+
+static DWORD worker_count, worker_free;
+
 static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id)
 {
   UUID* MgrType = NULL;
@@ -67,31 +84,168 @@
   return cif;
 }
 
-static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
+static void RPCRT4_push_packet(RpcPacket* packet)
 {
-  RpcBinding* bind = (RpcBinding*)the_arg;
-  RpcPktHdr hdr;
-  DWORD dwRead;
+  packet->next = NULL;
+  EnterCriticalSection(&spacket_cs);
+  if (spacket_tail) spacket_tail->next = packet;
+  else {
+    spacket_head = packet;
+    spacket_tail = packet;
+  }
+  LeaveCriticalSection(&spacket_cs);
+}
+
+static RpcPacket* RPCRT4_pop_packet(void)
+{
+  RpcPacket* packet;
+  EnterCriticalSection(&spacket_cs);
+  packet = spacket_head;
+  if (packet) {
+    spacket_head = packet->next;
+    if (!spacket_head) spacket_tail = NULL;
+  }
+  LeaveCriticalSection(&spacket_cs);
+  if (packet) packet->next = NULL;
+  return packet;
+}
+
+static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, void* buf)
+{
+  RpcBinding* pbind;
   RPC_MESSAGE msg;
   RpcServerInterface* sif;
   RPC_DISPATCH_FUNCTION func;
 
   memset(&msg, 0, sizeof(msg));
-  msg.Handle = (RPC_BINDING_HANDLE)bind;
+  msg.BufferLength = hdr->len;
+  msg.Buffer = buf;
+  sif = RPCRT4_find_interface(&hdr->object, &hdr->if_id);
+  if (sif) {
+    TRACE("packet received for interface %s\n", debugstr_guid(&hdr->if_id));
+    msg.RpcInterfaceInformation = sif->If;
+    /* create temporary binding for dispatch */
+    RPCRT4_MakeBinding(&pbind, conn);
+    RPCRT4_SetBindingObject(pbind, &hdr->object);
+    msg.Handle = (RPC_BINDING_HANDLE)pbind;
+    /* 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];
+      }
+
+      /* put in the drep. FIXME: is this more universally applicable?
+         perhaps we should move this outward... */
+      msg.DataRepresentation = 
+        MAKELONG( MAKEWORD(hdr->drep[0], hdr->drep[1]),
+                  MAKEWORD(hdr->drep[2], 0));
+
+      /* dispatch */
+      if (func) func(&msg);
+
+      /* send response packet */
+      I_RpcSend(&msg);
+      break;
+    default:
+      ERR("unknown packet type\n");
+      break;
+    }
+
+    RPCRT4_DestroyBinding(pbind);
+    msg.Handle = 0;
+    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;
+}
+
+static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
+{
+  HANDLE obj;
+  RpcPacket* pkt;
+
+  for (;;) {
+    /* idle timeout after 5s */
+    obj = WaitForSingleObject(server_sem, 5000);
+    if (obj == WAIT_TIMEOUT) {
+      /* if another idle thread exist, self-destruct */
+      if (worker_free > 1) break;
+      continue;
+    }
+    pkt = RPCRT4_pop_packet();
+    if (!pkt) continue;
+    InterlockedDecrement(&worker_free);
+    for (;;) {
+      RPCRT4_process_packet(pkt->conn, &pkt->hdr, pkt->buf);
+      HeapFree(GetProcessHeap(), 0, pkt);
+      /* try to grab another packet here without waiting
+       * on the semaphore, in case it hits max */
+      pkt = RPCRT4_pop_packet();
+      if (!pkt) break;
+      /* decrement semaphore */
+      WaitForSingleObject(server_sem, 0);
+    }
+    InterlockedIncrement(&worker_free);
+  }
+  InterlockedDecrement(&worker_free);
+  InterlockedDecrement(&worker_count);
+  return 0;
+}
+
+static void RPCRT4_create_worker_if_needed(void)
+{
+  if (!worker_free && worker_count < MAX_THREADS) {
+    HANDLE thread;
+    InterlockedIncrement(&worker_count);
+    InterlockedIncrement(&worker_free);
+    thread = CreateThread(NULL, 0, RPCRT4_worker_thread, NULL, 0, NULL);
+    if (thread) CloseHandle(thread);
+    else {
+      InterlockedDecrement(&worker_free);
+      InterlockedDecrement(&worker_count);
+    }
+  }
+}
+
+static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
+{
+  RpcConnection* conn = (RpcConnection*)the_arg;
+  RpcPktHdr hdr;
+  DWORD dwRead;
+  void* buf = NULL;
+  RpcPacket* packet;
+
+  TRACE("(%p)\n", conn);
 
   for (;;) {
     /* read packet header */
 #ifdef OVERLAPPED_WORKS
-    if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, &bind->ovl)) {
+    if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, &conn->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;
+      if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) break;
     }
 #else
-    if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
+    if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
       TRACE("connection lost, error=%08lx\n", GetLastError());
       break;
     }
@@ -102,19 +256,20 @@
     }
 
     /* read packet body */
-    msg.BufferLength = hdr.len;
-    msg.Buffer = HeapAlloc(GetProcessHeap(), 0, msg.BufferLength);
+    buf = HeapAlloc(GetProcessHeap(), 0, hdr.len);
+    TRACE("receiving payload=%d\n", hdr.len);
+    if (!hdr.len) dwRead = 0; else
 #ifdef OVERLAPPED_WORKS
-    if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, &bind->ovl)) {
+    if (!ReadFile(conn->conn, buf, hdr.len, &dwRead, &conn->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;
+      if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) break;
     }
 #else
-    if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, NULL)) {
+    if (!ReadFile(conn->conn, buf, hdr.len, &dwRead, NULL)) {
       TRACE("connection lost, error=%08lx\n", GetLastError());
       break;
     }
@@ -124,72 +279,31 @@
       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];
-       }
-       
-       /* put in the drep. FIXME: is this more universally applicable?
-          perhaps we should move this outward... */
-       msg.DataRepresentation = 
-         MAKELONG( MAKEWORD(hdr.drep[0], hdr.drep[1]),
-                   MAKEWORD(hdr.drep[2], 0));
-
-       /* 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 0
+    RPCRT4_process_packet(conn, &hdr, buf);
+#else
+    packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket));
+    packet->conn = conn;
+    packet->hdr = hdr;
+    packet->buf = buf;
+    RPCRT4_create_worker_if_needed();
+    RPCRT4_push_packet(packet);
+    ReleaseSemaphore(server_sem, 1, NULL);
+#endif
+    buf = NULL;
   }
-  if (msg.Buffer) HeapFree(GetProcessHeap(), 0, msg.Buffer);
-  RPCRT4_DestroyBinding(bind);
+  if (buf) HeapFree(GetProcessHeap(), 0, buf);
+  RPCRT4_DestroyConnection(conn);
   return 0;
 }
 
-static void RPCRT4_new_client(RpcBinding* bind)
+static void RPCRT4_new_client(RpcConnection* conn)
 {
-  bind->thread = CreateThread(NULL, 0, RPCRT4_io_thread, bind, 0, NULL);
+  conn->thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL);
+  if (!conn->thread) {
+    DWORD err = GetLastError();
+    ERR("failed to create thread, error=%08lx\n", err);
+  }
 }
 
 static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
@@ -198,33 +312,33 @@
   HANDLE *objs = NULL;
   DWORD count, res;
   RpcServerProtseq* cps;
-  RpcBinding* bind;
-  RpcBinding* cbind;
+  RpcConnection* conn;
+  RpcConnection* cconn;
 
   for (;;) {
     EnterCriticalSection(&server_cs);
-    /* open and count bindings */
+    /* open and count connections */
     count = 1;
     cps = protseqs;
     while (cps) {
-      bind = cps->bind;
-      while (bind) {
-       RPCRT4_OpenBinding(bind);
-        if (bind->ovl.hEvent) count++;
-        bind = bind->Next;
+      conn = cps->conn;
+      while (conn) {
+        RPCRT4_OpenConnection(conn);
+        if (conn->ovl.hEvent) count++;
+        conn = conn->Next;
       }
       cps = cps->Next;
     }
-    /* make array of bindings */
+    /* make array of connings */
     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;
+      conn = cps->conn;
+      while (conn) {
+        if (conn->ovl.hEvent) objs[count++] = conn->ovl.hEvent;
+        conn = conn->Next;
       }
       cps = cps->Next;
     }
@@ -241,37 +355,37 @@
     }
     else {
       b_handle = objs[res - WAIT_OBJECT_0];
-      /* find which binding got a RPC */
+      /* find which connection got a RPC */
       EnterCriticalSection(&server_cs);
-      bind = NULL;
+      conn = NULL;
       cps = protseqs;
       while (cps) {
-        bind = cps->bind;
-        while (bind) {
-          if (bind->ovl.hEvent == b_handle) break;
-          bind = bind->Next;
+        conn = cps->conn;
+        while (conn) {
+          if (conn->ovl.hEvent == b_handle) break;
+          conn = conn->Next;
         }
-        if (bind) break;
+        if (conn) break;
         cps = cps->Next;
       }
-      cbind = NULL;
-      if (bind) RPCRT4_SpawnBinding(&cbind, bind);
+      cconn = NULL;
+      if (conn) RPCRT4_SpawnConnection(&cconn, bind);
       LeaveCriticalSection(&server_cs);
-      if (!bind) {
-        ERR("failed to locate binding for handle %p\n", b_handle);
+      if (!conn) {
+        ERR("failed to locate connection for handle %p\n", b_handle);
       }
-      if (cbind) RPCRT4_new_client(cbind);
+      if (cconn) RPCRT4_new_client(cconn);
     }
   }
   HeapFree(GetProcessHeap(), 0, objs);
   EnterCriticalSection(&server_cs);
-  /* close bindings */
+  /* close connections */
   cps = protseqs;
   while (cps) {
-    bind = cps->bind;
-    while (bind) {
-      RPCRT4_CloseBinding(bind);
-      bind = bind->Next;
+    conn = cps->conn;
+    while (conn) {
+      RPCRT4_CloseConnection(conn);
+      conn = conn->Next;
     }
     cps = cps->Next;
   }
@@ -286,6 +400,7 @@
   EnterCriticalSection(&listen_cs);
   if (! ++listen_count) {
     if (!mgr_event) mgr_event = CreateEventA(NULL, TRUE, FALSE, NULL);
+    if (!server_sem) server_sem = CreateSemaphoreA(NULL, 0, MAX_THREADS, NULL);
     std_listen = TRUE;
     server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL);
     LeaveCriticalSection(&listen_cs);
@@ -311,8 +426,7 @@
 
 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps)
 {
-  RPCRT4_CreateBindingA(&ps->bind, TRUE, ps->Protseq);
-  RPCRT4_CompleteBindingA(ps->bind, NULL, ps->Endpoint, NULL);
+  RPCRT4_CreateConnection(&ps->conn, TRUE, ps->Protseq, NULL, ps->Endpoint, NULL);
 
   EnterCriticalSection(&server_cs);
   ps->Next = protseqs;
@@ -332,7 +446,7 @@
   RPC_STATUS status;
   DWORD count;
   RpcServerProtseq* ps;
-  RpcBinding* bind;
+  RpcConnection* conn;
 
   if (BindingVector)
     TRACE("(*BindingVector == ^%p)\n", *BindingVector);
@@ -340,14 +454,14 @@
     ERR("(BindingVector == ^null!!?)\n");
 
   EnterCriticalSection(&server_cs);
-  /* count bindings */
+  /* count connections */
   count = 0;
   ps = protseqs;
   while (ps) {
-    bind = ps->bind;
-    while (bind) {
+    conn = ps->conn;
+    while (conn) {
       count++;
-      bind = bind->Next;
+      conn = conn->Next;
     }
     ps = ps->Next;
   }
@@ -360,12 +474,12 @@
     count = 0;
     ps = protseqs;
     while (ps) {
-      bind = ps->bind;
-      while (bind) {
-       RPCRT4_ExportBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
-                            bind);
+      conn = ps->conn;
+      while (conn) {
+       RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
+                          conn);
        count++;
-       bind = bind->Next;
+       conn = conn->Next;
       }
       ps = ps->Next;
     }
Index: dlls/rpcrt4/rpc_server.h
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/rpc_server.h,v
retrieving revision 1.1
diff -u -r1.1 rpc_server.h
--- dlls/rpcrt4/rpc_server.h	11 Oct 2002 17:52:37 -0000	1.1
+++ dlls/rpcrt4/rpc_server.h	15 Feb 2003 23:38:51 -0000
@@ -29,7 +29,7 @@
   LPSTR Protseq;
   LPSTR Endpoint;
   UINT MaxCalls;
-  RpcBinding* bind;
+  RpcConnection* conn;
 } RpcServerProtseq;
 
 typedef struct _RpcServerInterface

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux