Added the data structures and macros that will be needed to support
reentrant server requests.

diff --git a/scheduler/client.c b/scheduler/client.c
index 4e2832d..03d4afe 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -111,21 +111,54 @@
 
 
 /***********************************************************************
+ *           server_exception_handler
+ */
+DWORD server_exception_handler( PEXCEPTION_RECORD record, EXCEPTION_FRAME *frame,
+                                CONTEXT *context, EXCEPTION_FRAME **pdispatcher )
+{
+    struct __server_exception_frame *server_frame = (struct __server_exception_frame *)frame;
+    if ((record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
+        *NtCurrentTeb()->buffer_info = server_frame->info;
+    return ExceptionContinueSearch;
+}
+
+
+/***********************************************************************
+ *           server_alloc_req
+ */
+void *server_alloc_req( size_t fixed_size, size_t var_size )
+{
+    unsigned int pos = NtCurrentTeb()->buffer_info->cur_pos;
+    union generic_request *req = (union generic_request *)((char *)NtCurrentTeb()->buffer + pos);
+    size_t size = sizeof(*req) + var_size;
+
+    assert( fixed_size <= sizeof(*req) );
+
+    if ((char *)req + size > (char *)NtCurrentTeb()->buffer_info)
+        server_protocol_error( "buffer overflow %d bytes\n",
+                               (char *)req + size - (char *)NtCurrentTeb()->buffer_info );
+    NtCurrentTeb()->buffer_info->cur_pos = pos + size;
+    req->header.fixed_size = fixed_size;
+    req->header.var_size = var_size;
+    return req;
+}
+
+
+/***********************************************************************
  *           send_request
  *
  * Send a request to the server.
  */
-static void send_request( enum request req )
+static void send_request( enum request req, struct request_header *header )
 {
-    int ret;
-    if ((ret = write( NtCurrentTeb()->socket, &req, sizeof(req) )) == sizeof(req))
-        return;
-    if (ret == -1)
+    header->req = req;
+    NtCurrentTeb()->buffer_info->cur_req = (char *)header - (char *)NtCurrentTeb()->buffer;
+    /* write a single byte; the value is ignored anyway */
+    if (write( NtCurrentTeb()->socket, header, 1 ) == -1)
     {
         if (errno == EPIPE) SYSDEPS_ExitThread(0);
         server_perror( "sendmsg" );
     }
-    server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
 }
 
 /***********************************************************************
@@ -133,17 +166,17 @@
  *
  * Send a request to the server, passing a file descriptor.
  */
-static void send_request_fd( enum request req, int fd )
+static void send_request_fd( enum request req, struct request_header *header, int fd )
 {
-    int ret;
 #ifndef HAVE_MSGHDR_ACCRIGHTS
     struct cmsg_fd cmsg;
 #endif
     struct msghdr msghdr;
     struct iovec vec;
 
-    vec.iov_base = (void *)&req;
-    vec.iov_len  = sizeof(req);
+    /* write a single byte; the value is ignored anyway */
+    vec.iov_base = (void *)header;
+    vec.iov_len  = 1;
 
     msghdr.msg_name    = NULL;
     msghdr.msg_namelen = 0;
@@ -163,13 +196,13 @@
     msghdr.msg_flags      = 0;
 #endif  /* HAVE_MSGHDR_ACCRIGHTS */
 
-    if ((ret = sendmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(req)) return;
-    if (ret == -1)
+    header->req = req;
+
+    if (sendmsg( NtCurrentTeb()->socket, &msghdr, 0 ) == -1)
     {
         if (errno == EPIPE) SYSDEPS_ExitThread(0);
         server_perror( "sendmsg" );
     }
-    server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
 }
 
 /***********************************************************************
@@ -177,23 +210,18 @@
  *
  * Wait for a reply from the server.
  */
-static unsigned int wait_reply(void)
+static void wait_reply(void)
 {
     int ret;
-    unsigned int res;
+    char dummy[1];
 
     for (;;)
     {
-        if ((ret = read( NtCurrentTeb()->socket, &res, sizeof(res) )) == sizeof(res))
-            return res;
+        if ((ret = read( NtCurrentTeb()->socket, dummy, 1 )) > 0) return;
         if (!ret) break;
-        if (ret == -1)
-        {
-            if (errno == EINTR) continue;
-            if (errno == EPIPE) break;
-            server_perror("read");
-        }
-        server_protocol_error( "partial msg received %d/%d\n", ret, sizeof(res) );
+        if (errno == EINTR) continue;
+        if (errno == EPIPE) break;
+        server_perror("read");
     }
     /* the server closed the connection; time to die... */
     SYSDEPS_ExitThread(0);
@@ -205,11 +233,11 @@
  *
  * Wait for a reply from the server, when a file descriptor is passed.
  */
-static unsigned int wait_reply_fd( int *fd )
+static void wait_reply_fd( int *fd )
 {
     struct iovec vec;
     int ret;
-    unsigned int res;
+    char dummy[1];
 
 #ifdef HAVE_MSGHDR_ACCRIGHTS
     struct msghdr msghdr;
@@ -234,26 +262,22 @@
     msghdr.msg_namelen = 0;
     msghdr.msg_iov     = &vec;
     msghdr.msg_iovlen  = 1;
-    vec.iov_base = (void *)&res;
-    vec.iov_len  = sizeof(res);
+    vec.iov_base = (void *)dummy;
+    vec.iov_len  = 1;
 
     for (;;)
     {
-        if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(res))
+        if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) > 0)
         {
 #ifndef HAVE_MSGHDR_ACCRIGHTS
             *fd = cmsg.fd;
 #endif
-            return res;
+            return;
         }
         if (!ret) break;
-        if (ret == -1)
-        {
-            if (errno == EINTR) continue;
-            if (errno == EPIPE) break;
-            server_perror("recvmsg");
-        }
-        server_protocol_error( "partial seq received %d/%d\n", ret, sizeof(res) );
+        if (errno == EINTR) continue;
+        if (errno == EPIPE) break;
+        server_perror("recvmsg");
     }
     /* the server closed the connection; time to die... */
     SYSDEPS_ExitThread(0);
@@ -267,8 +291,10 @@
  */
 unsigned int server_call_noerr( enum request req )
 {
-    send_request( req );
-    return wait_reply();
+    void *req_ptr = get_req_buffer();
+    send_request( req, req_ptr );
+    wait_reply();
+    return ((struct request_header *)req_ptr)->error;
 }
 
 
@@ -282,13 +308,16 @@
 unsigned int server_call_fd( enum request req, int fd_out, int *fd_in )
 {
     unsigned int res;
+    void *req_ptr = get_req_buffer();
 
-    if (fd_out == -1) send_request( req );
-    else send_request_fd( req, fd_out );
+    if (fd_out == -1) send_request( req, req_ptr );
+    else send_request_fd( req, req_ptr, fd_out );
 
-    if (fd_in) res = wait_reply_fd( fd_in );
-    else res = wait_reply();
-    if (res) SetLastError( RtlNtStatusToDosError(res) );
+    if (fd_in) wait_reply_fd( fd_in );
+    else wait_reply();
+
+    if ((res = ((struct request_header *)req_ptr)->error))
+        SetLastError( RtlNtStatusToDosError(res) );
     return res;  /* error code */
 }
 
@@ -517,37 +546,44 @@
  */
 int CLIENT_InitThread(void)
 {
-    struct get_thread_buffer_request *first_req;
-    struct init_thread_request *req;
+    struct get_thread_buffer_request *req;
     TEB *teb = NtCurrentTeb();
-    int fd;
+    int fd, ret, size;
 
     /* ignore SIGPIPE so that we get a EPIPE error instead  */
     signal( SIGPIPE, SIG_IGN );
 
-    if (wait_reply_fd( &fd ) || (fd == -1))
-        server_protocol_error( "no fd passed on first request\n" );
-    if ((teb->buffer_size = lseek( fd, 0, SEEK_END )) == -1) server_perror( "lseek" );
-    teb->buffer = mmap( 0, teb->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
+    wait_reply_fd( &fd );
+    if (fd == -1) server_protocol_error( "no fd passed on first request\n" );
+
+    if ((size = lseek( fd, 0, SEEK_END )) == -1) server_perror( "lseek" );
+    teb->buffer = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
     close( fd );
     if (teb->buffer == (void*)-1) server_perror( "mmap" );
-    first_req = teb->buffer;
-    teb->pid = first_req->pid;
-    teb->tid = first_req->tid;
-    if (first_req->version != SERVER_PROTOCOL_VERSION)
+    teb->buffer_info = (struct server_buffer_info *)((char *)teb->buffer + size) - 1;
+
+    req = (struct get_thread_buffer_request *)teb->buffer;
+    teb->pid = req->pid;
+    teb->tid = req->tid;
+    if (req->version != SERVER_PROTOCOL_VERSION)
         server_protocol_error( "version mismatch %d/%d.\n"
                                "Your %s binary was not upgraded correctly,\n"
                                "or you have an older one somewhere in your PATH.\n",
-                               first_req->version, SERVER_PROTOCOL_VERSION,
-                               (first_req->version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
-    if (first_req->boot) boot_thread_id = teb->tid;
+                               req->version, SERVER_PROTOCOL_VERSION,
+                               (req->version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
+    if (req->boot) boot_thread_id = teb->tid;
     else if (boot_thread_id == teb->tid) boot_thread_id = 0;
 
-    req = teb->buffer;
-    req->unix_pid = getpid();
-    req->teb      = teb;
-    req->entry    = teb->entry_point;
-    return server_call_noerr( REQ_INIT_THREAD );
+    SERVER_START_REQ
+    {
+        struct init_thread_request *req = server_alloc_req( sizeof(*req), 0 );
+        req->unix_pid = getpid();
+        req->teb      = teb;
+        req->entry    = teb->entry_point;
+        ret = server_call_noerr( REQ_INIT_THREAD );
+    }
+    SERVER_END_REQ;
+    return ret;
 }
 
 /***********************************************************************
@@ -557,9 +593,15 @@
  */
 int CLIENT_BootDone( int debug_level )
 {
-    struct boot_done_request *req = get_req_buffer();
-    req->debug_level = debug_level;
-    return server_call( REQ_BOOT_DONE );
+    int ret;
+    SERVER_START_REQ
+    {
+        struct boot_done_request *req = server_alloc_req( sizeof(*req), 0 );
+        req->debug_level = debug_level;
+        ret = server_call( REQ_BOOT_DONE );
+    }
+    SERVER_END_REQ;
+    return ret;
 }