Further server optimizations:
- merged request and reply structures
- build requests directly into the buffer to avoid a copy

diff --git a/scheduler/client.c b/scheduler/client.c
index 4f5dbdb..bc62f53 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -26,6 +26,14 @@
 #define SCM_RIGHTS 1
 #endif
 
+/* data structure used to pass an fd with sendmsg/recvmsg */
+struct cmsg_fd
+{
+    int len;   /* sizeof structure */
+    int level; /* SOL_SOCKET */
+    int type;  /* SCM_RIGHTS */
+    int fd;    /* fd to pass */
+};
 
 /***********************************************************************
  *           CLIENT_Die
@@ -39,9 +47,9 @@
 }
 
 /***********************************************************************
- *           CLIENT_ProtocolError
+ *           server_protocol_error
  */
-void CLIENT_ProtocolError( const char *err, ... )
+void server_protocol_error( const char *err, ... )
 {
     va_list args;
 
@@ -54,9 +62,9 @@
 
 
 /***********************************************************************
- *           CLIENT_perror
+ *           server_perror
  */
-void CLIENT_perror( const char *err )
+static void server_perror( const char *err )
 {
     fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
     perror( err );
@@ -71,24 +79,15 @@
  */
 static void send_request( enum request req )
 {
-    struct header *head = NtCurrentTeb()->buffer;
-    int ret, seq = NtCurrentTeb()->seq++;
-
-    assert( server_remaining() >= 0 );
-
-    head->type = req;
-    head->len  = (char *)NtCurrentTeb()->buffer_args - (char *)NtCurrentTeb()->buffer;
-
-    NtCurrentTeb()->buffer_args = head + 1;  /* reset the args buffer */
-
-    if ((ret = write( NtCurrentTeb()->socket, &seq, sizeof(seq) )) == sizeof(seq))
+    int ret;
+    if ((ret = write( NtCurrentTeb()->socket, &req, sizeof(req) )) == sizeof(req))
         return;
     if (ret == -1)
     {
         if (errno == EPIPE) CLIENT_Die();
-        CLIENT_perror( "sendmsg" );
+        server_perror( "sendmsg" );
     }
-    CLIENT_ProtocolError( "partial seq sent %d/%d\n", ret, sizeof(seq) );
+    server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
 }
 
 /***********************************************************************
@@ -98,23 +97,15 @@
  */
 static void send_request_fd( enum request req, int fd )
 {
-    struct header *head = NtCurrentTeb()->buffer;
-    int ret, seq = NtCurrentTeb()->seq++;
+    int ret;
 #ifndef HAVE_MSGHDR_ACCRIGHTS
     struct cmsg_fd cmsg;
 #endif
     struct msghdr msghdr;
     struct iovec vec;
 
-    assert( server_remaining() >= 0 );
-
-    head->type = req;
-    head->len  = (char *)NtCurrentTeb()->buffer_args - (char *)NtCurrentTeb()->buffer;
-
-    NtCurrentTeb()->buffer_args = head + 1;  /* reset the args buffer */
-
-    vec.iov_base = &seq;
-    vec.iov_len  = sizeof(seq);
+    vec.iov_base = &req;
+    vec.iov_len  = sizeof(req);
 
     msghdr.msg_name    = NULL;
     msghdr.msg_namelen = 0;
@@ -134,13 +125,13 @@
     msghdr.msg_flags      = 0;
 #endif  /* HAVE_MSGHDR_ACCRIGHTS */
 
-    if ((ret = sendmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(seq)) return;
+    if ((ret = sendmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(req)) return;
     if (ret == -1)
     {
         if (errno == EPIPE) CLIENT_Die();
-        CLIENT_perror( "sendmsg" );
+        server_perror( "sendmsg" );
     }
-    CLIENT_ProtocolError( "partial seq sent %d/%d\n", ret, sizeof(seq) );
+    server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
 }
 
 /***********************************************************************
@@ -148,26 +139,23 @@
  *
  * Wait for a reply from the server.
  */
-static void wait_reply(void)
+static unsigned int wait_reply(void)
 {
-    int seq, ret;
+    int ret;
+    unsigned int res;
 
     for (;;)
     {
-        if ((ret = read( NtCurrentTeb()->socket, &seq, sizeof(seq) )) == sizeof(seq))
-        {
-            if (seq != NtCurrentTeb()->seq++)
-                CLIENT_ProtocolError( "sequence %08x instead of %08x\n", seq, NtCurrentTeb()->seq - 1 );
-            return;
-        }
+        if ((ret = read( NtCurrentTeb()->socket, &res, sizeof(res) )) == sizeof(res))
+            return res;
         if (ret == -1)
         {
             if (errno == EINTR) continue;
             if (errno == EPIPE) CLIENT_Die();
-            CLIENT_perror("read");
+            server_perror("read");
         }
         if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
-        CLIENT_ProtocolError( "partial seq received %d/%d\n", ret, sizeof(seq) );
+        server_protocol_error( "partial msg received %d/%d\n", ret, sizeof(res) );
     }
 }
 
@@ -177,17 +165,18 @@
  *
  * Wait for a reply from the server, when a file descriptor is passed.
  */
-static int wait_reply_fd(void)
+static unsigned int wait_reply_fd( int *fd )
 {
     struct iovec vec;
-    int seq, ret;
+    int ret;
+    unsigned int res;
 
 #ifdef HAVE_MSGHDR_ACCRIGHTS
     struct msghdr msghdr;
-    int fd = -1;
 
-    msghdr.msg_accrights    = (void *)&fd;
-    msghdr.msg_accrightslen = sizeof(int);
+    *fd = -1;
+    msghdr.msg_accrights    = (void *)fd;
+    msghdr.msg_accrightslen = sizeof(*fd);
 #else  /* HAVE_MSGHDR_ACCRIGHTS */
     struct msghdr msghdr;
     struct cmsg_fd cmsg;
@@ -205,29 +194,26 @@
     msghdr.msg_namelen = 0;
     msghdr.msg_iov     = &vec;
     msghdr.msg_iovlen  = 1;
-    vec.iov_base = &seq;
-    vec.iov_len  = sizeof(seq);
+    vec.iov_base = &res;
+    vec.iov_len  = sizeof(res);
 
     for (;;)
     {
-        if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(seq))
+        if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(res))
         {
-            if (seq != NtCurrentTeb()->seq++)
-                CLIENT_ProtocolError( "sequence %08x instead of %08x\n", seq, NtCurrentTeb()->seq - 1 );
-#ifdef HAVE_MSGHDR_ACCRIGHTS
-            return fd;
-#else
-            return cmsg.fd;
+#ifndef HAVE_MSGHDR_ACCRIGHTS
+            *fd = cmsg.fd;
 #endif
+            return res;
         }
         if (ret == -1)
         {
             if (errno == EINTR) continue;
             if (errno == EPIPE) CLIENT_Die();
-            CLIENT_perror("recvmsg");
+            server_perror("recvmsg");
         }
         if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
-        CLIENT_ProtocolError( "partial seq received %d/%d\n", ret, sizeof(seq) );
+        server_protocol_error( "partial seq received %d/%d\n", ret, sizeof(res) );
     }
 }
 
@@ -239,18 +225,15 @@
  */
 unsigned int server_call( enum request req )
 {
-    struct header *head;
+    unsigned int res;
 
     send_request( req );
-    wait_reply();
-
-    head = (struct header *)NtCurrentTeb()->buffer;
-    if ((head->len < sizeof(*head)) || (head->len > NtCurrentTeb()->buffer_size))
-        CLIENT_ProtocolError( "header length %d\n", head->len );
-    if (head->type) SetLastError( head->type );
-    return head->type;  /* error code */
+    res = wait_reply();
+    if (res) SetLastError( res );
+    return res;  /* error code */
 }
 
+
 /***********************************************************************
  *           server_call_fd
  *
@@ -258,125 +241,17 @@
  * If *fd is != -1, it will be passed to the server.
  * If the server passes an fd, it will be stored into *fd.
  */
-unsigned int server_call_fd( enum request req, int *fd )
+unsigned int server_call_fd( enum request req, int fd_out, int *fd_in )
 {
-    struct header *head;
+    unsigned int res;
 
-    if (*fd == -1) send_request( req );
-    else send_request_fd( req, *fd );
-    *fd = wait_reply_fd();
+    if (fd_out == -1) send_request( req );
+    else send_request_fd( req, fd_out );
 
-    head = (struct header *)NtCurrentTeb()->buffer;
-    if ((head->len < sizeof(*head)) || (head->len > NtCurrentTeb()->buffer_size))
-        CLIENT_ProtocolError( "header length %d\n", head->len );
-    if (head->type) SetLastError( head->type );
-    return head->type;  /* error code */
-}
-
-/***********************************************************************
- *           CLIENT_SendRequest
- *
- * Send a request to the server.
- */
-void CLIENT_SendRequest( enum request req, int pass_fd,
-                         int n, ... /* arg_1, len_1, etc. */ )
-{
-    va_list args;
-
-    va_start( args, n );
-    while (n--)
-    {
-        void *ptr = va_arg( args, void * );
-        int len   = va_arg( args, int );
-        memcpy( server_add_data( len ), ptr, len );
-    }
-    va_end( args );
-
-    if (pass_fd == -1) send_request( req );
-    else
-    {
-        send_request_fd( req, pass_fd );
-        close( pass_fd ); /* we passed the fd now we can close it */
-    }
-}
-
-
-/***********************************************************************
- *           CLIENT_WaitReply_v
- *
- * Wait for a reply from the server.
- * Returns the error code (or 0 if OK).
- */
-static unsigned int CLIENT_WaitReply_v( int *len, int *passed_fd,
-                                        struct iovec *vec, int veclen )
-{
-    struct header *head;
-    char *ptr;
-    int i, remaining;
-
-    if (passed_fd) *passed_fd = wait_reply_fd();
-    else wait_reply();
-
-    head = (struct header *)NtCurrentTeb()->buffer;
-    if ((head->len < sizeof(*head)) || (head->len > NtCurrentTeb()->buffer_size))
-        CLIENT_ProtocolError( "header length %d\n", head->len );
-
-    remaining = head->len - sizeof(*head);
-    ptr = (char *)(head + 1);
-    for (i = 0; i < veclen; i++, vec++)
-    {
-        int len = MIN( remaining, vec->iov_len );
-        memcpy( vec->iov_base, ptr, len );
-        ptr += len;
-        if (!(remaining -= len)) break;
-    }
-    if (len) *len = head->len - sizeof(*head);
-    if (head->type) SetLastError( head->type );
-    return head->type;  /* error code */
-}
-
-
-/***********************************************************************
- *           CLIENT_WaitReply
- *
- * Wait for a reply from the server.
- */
-unsigned int CLIENT_WaitReply( int *len, int *passed_fd,
-                               int n, ... /* arg_1, len_1, etc. */ )
-{
-    struct iovec vec[16];
-    va_list args;
-    int i;
-
-    assert( n < 16 );
-    va_start( args, n );
-    for (i = 0; i < n; i++)
-    {
-        vec[i].iov_base = va_arg( args, void * );
-        vec[i].iov_len  = va_arg( args, int );
-    }
-    va_end( args );
-    return CLIENT_WaitReply_v( len, passed_fd, vec, n );
-}
-
-
-/***********************************************************************
- *           CLIENT_WaitSimpleReply
- *
- * Wait for a simple fixed-length reply from the server.
- */
-unsigned int CLIENT_WaitSimpleReply( void *reply, int len, int *passed_fd )
-{
-    struct iovec vec;
-    unsigned int ret;
-    int got;
-
-    vec.iov_base = reply;
-    vec.iov_len  = len;
-    ret = CLIENT_WaitReply_v( &got, passed_fd, &vec, 1 );
-    if (got != len)
-        CLIENT_ProtocolError( "WaitSimpleReply: len %d != %d\n", len, got );
-    return ret;
+    if (fd_in) res = wait_reply_fd( fd_in );
+    else res = wait_reply();
+    if (res) SetLastError( res );
+    return res;  /* error code */
 }
 
 
@@ -427,24 +302,23 @@
  */
 int CLIENT_InitThread(void)
 {
-    struct init_thread_request req;
-    struct init_thread_reply reply;
+    struct init_thread_request *req;
     TEB *teb = NtCurrentTeb();
+    int fd;
 
-    int fd = wait_reply_fd();
-    if (fd == -1) CLIENT_ProtocolError( "no fd passed on first request\n" );
-    if ((teb->buffer_size = lseek( fd, 0, SEEK_END )) == -1) CLIENT_perror( "lseek" );
+    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 );
     close( fd );
-    if (teb->buffer == (void*)-1) CLIENT_perror( "mmap" );
-    teb->buffer_args = (char *)teb->buffer + sizeof(struct header);
+    if (teb->buffer == (void*)-1) server_perror( "mmap" );
 
-    req.unix_pid = getpid();
-    req.teb      = teb;
-    CLIENT_SendRequest( REQ_INIT_THREAD, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return -1;
-    teb->process->server_pid = reply.pid;
-    teb->tid = reply.tid;
+    req = get_req_buffer();
+    req->unix_pid = getpid();
+    req->teb      = teb;
+    if (server_call( REQ_INIT_THREAD )) return -1;
+    teb->process->server_pid = req->pid;
+    teb->tid = req->tid;
     return 0;
 }
 
@@ -456,8 +330,9 @@
  */
 int CLIENT_SetDebug( int level )
 {
-    CLIENT_SendRequest( REQ_SET_DEBUG, -1, 1, &level, sizeof(level) );
-    return CLIENT_WaitReply( NULL, NULL, 0 );
+    struct set_debug_request *req = get_req_buffer();
+    req->level = level;
+    return server_call( REQ_SET_DEBUG );
 }
 
 /***********************************************************************
@@ -467,9 +342,8 @@
  */
 int CLIENT_DebuggerRequest( int op )
 {
-    struct debugger_request req;
-    req.op = op;
-    CLIENT_SendRequest( REQ_DEBUGGER, -1, 1, &req, sizeof(req) );
-    return CLIENT_WaitReply( NULL, NULL, 0 );
+    struct debugger_request *req = get_req_buffer();
+    req->op = op;
+    return server_call( REQ_DEBUGGER );
 }
 
diff --git a/scheduler/debugger.c b/scheduler/debugger.c
index fd96985..e5a4bea 100644
--- a/scheduler/debugger.c
+++ b/scheduler/debugger.c
@@ -17,13 +17,12 @@
  */
 static DWORD DEBUG_SendEvent( int code, void *data, int size )
 {
-    struct send_debug_event_request req;
-    struct send_debug_event_reply reply;
-
-    req.code = code;
-    CLIENT_SendRequest( REQ_SEND_DEBUG_EVENT, -1, 2, &req, sizeof(req), data, size );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0;
-    return reply.status;
+    DWORD ret = 0;
+    struct send_debug_event_request *req = get_req_buffer();
+    req->code = code;
+    memcpy( req + 1, data, size );
+    if (!server_call( REQ_SEND_DEBUG_EVENT )) ret = req->status;
+    return ret;
 }
 
 
@@ -135,94 +134,74 @@
  */
 BOOL WINAPI WaitForDebugEvent( LPDEBUG_EVENT event, DWORD timeout )
 {
-    /* size of the event data */
-    static const int event_sizes[] =
-    {
-        0,
-        sizeof(struct debug_event_exception),       /* EXCEPTION_DEBUG_EVENT */
-        sizeof(struct debug_event_create_thread),   /* CREATE_THREAD_DEBUG_EVENT */
-        sizeof(struct debug_event_create_process),  /* CREATE_PROCESS_DEBUG_EVENT */
-        sizeof(struct debug_event_exit),            /* EXIT_THREAD_DEBUG_EVENT */
-        sizeof(struct debug_event_exit),            /* EXIT_PROCESS_DEBUG_EVENT */
-        sizeof(struct debug_event_load_dll),        /* LOAD_DLL_DEBUG_EVENT */
-        sizeof(struct debug_event_unload_dll),      /* UNLOAD_DLL_DEBUG_EVENT */
-        sizeof(struct debug_event_output_string),   /* OUTPUT_DEBUG_STRING_EVENT */
-        sizeof(struct debug_event_rip_info)         /* RIP_EVENT */
-    };
+    struct wait_debug_event_request *req = get_req_buffer();
+    union debug_event_data *data = (union debug_event_data *)(req + 1);
+    int i;
 
-    struct wait_debug_event_request req;
-    struct wait_debug_event_reply reply;
-    union debug_event_data data;
-    int i, len;
+    req->timeout = timeout;
+    if (server_call( REQ_WAIT_DEBUG_EVENT )) return FALSE;
+    if ((req->code < 0) || (req->code > RIP_EVENT))
+        server_protocol_error( "WaitForDebugEvent: bad code %d\n", req->code );
 
-    req.timeout = timeout;
-    CLIENT_SendRequest( REQ_WAIT_DEBUG_EVENT, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply),
-                          &data, sizeof(data) )) return FALSE;
-    if ((reply.code < 0) || (reply.code > RIP_EVENT))
-        CLIENT_ProtocolError( "WaitForDebugEvent: bad code %d\n", reply.code );
-    if (len != sizeof(reply) + event_sizes[reply.code])
-        CLIENT_ProtocolError( "WaitForDebugEvent: bad len %d for code %d\n", len, reply.code );
-
-    event->dwDebugEventCode = reply.code;
-    event->dwProcessId      = (DWORD)reply.pid;
-    event->dwThreadId       = (DWORD)reply.tid;
-    switch(reply.code)
+    event->dwDebugEventCode = req->code;
+    event->dwProcessId      = (DWORD)req->pid;
+    event->dwThreadId       = (DWORD)req->tid;
+    switch(req->code)
     {
     case EXCEPTION_DEBUG_EVENT:
-        event->u.Exception.ExceptionRecord.ExceptionCode    = data.exception.code;
-        event->u.Exception.ExceptionRecord.ExceptionFlags   = data.exception.flags;
-        event->u.Exception.ExceptionRecord.ExceptionRecord  = data.exception.record;
-        event->u.Exception.ExceptionRecord.ExceptionAddress = data.exception.addr;
-        event->u.Exception.ExceptionRecord.NumberParameters = data.exception.nb_params;
-        for (i = 0; i < data.exception.nb_params; i++)
-            event->u.Exception.ExceptionRecord.ExceptionInformation[i] = data.exception.params[i];
-        event->u.Exception.dwFirstChance = data.exception.first_chance;
+        event->u.Exception.ExceptionRecord.ExceptionCode    = data->exception.code;
+        event->u.Exception.ExceptionRecord.ExceptionFlags   = data->exception.flags;
+        event->u.Exception.ExceptionRecord.ExceptionRecord  = data->exception.record;
+        event->u.Exception.ExceptionRecord.ExceptionAddress = data->exception.addr;
+        event->u.Exception.ExceptionRecord.NumberParameters = data->exception.nb_params;
+        for (i = 0; i < data->exception.nb_params; i++)
+            event->u.Exception.ExceptionRecord.ExceptionInformation[i] = data->exception.params[i];
+        event->u.Exception.dwFirstChance = data->exception.first_chance;
         break;
     case CREATE_THREAD_DEBUG_EVENT:
-        event->u.CreateThread.hThread           = data.create_thread.handle;
-        event->u.CreateThread.lpThreadLocalBase = data.create_thread.teb;
-        event->u.CreateThread.lpStartAddress    = data.create_thread.start;
+        event->u.CreateThread.hThread           = data->create_thread.handle;
+        event->u.CreateThread.lpThreadLocalBase = data->create_thread.teb;
+        event->u.CreateThread.lpStartAddress    = data->create_thread.start;
         break;
     case CREATE_PROCESS_DEBUG_EVENT:
-        event->u.CreateProcessInfo.hFile                 = data.create_process.file;
-        event->u.CreateProcessInfo.hProcess              = data.create_process.process;
-        event->u.CreateProcessInfo.hThread               = data.create_process.thread;
-        event->u.CreateProcessInfo.lpBaseOfImage         = data.create_process.base;
-        event->u.CreateProcessInfo.dwDebugInfoFileOffset = data.create_process.dbg_offset;
-        event->u.CreateProcessInfo.nDebugInfoSize        = data.create_process.dbg_size;
-        event->u.CreateProcessInfo.lpThreadLocalBase     = data.create_process.teb;
-        event->u.CreateProcessInfo.lpStartAddress        = data.create_process.start;
-        event->u.CreateProcessInfo.lpImageName           = data.create_process.name;
-        event->u.CreateProcessInfo.fUnicode              = data.create_process.unicode;
-        if (data.create_process.file == -1) event->u.CreateProcessInfo.hFile = 0;
+        event->u.CreateProcessInfo.hFile                 = data->create_process.file;
+        event->u.CreateProcessInfo.hProcess              = data->create_process.process;
+        event->u.CreateProcessInfo.hThread               = data->create_process.thread;
+        event->u.CreateProcessInfo.lpBaseOfImage         = data->create_process.base;
+        event->u.CreateProcessInfo.dwDebugInfoFileOffset = data->create_process.dbg_offset;
+        event->u.CreateProcessInfo.nDebugInfoSize        = data->create_process.dbg_size;
+        event->u.CreateProcessInfo.lpThreadLocalBase     = data->create_process.teb;
+        event->u.CreateProcessInfo.lpStartAddress        = data->create_process.start;
+        event->u.CreateProcessInfo.lpImageName           = data->create_process.name;
+        event->u.CreateProcessInfo.fUnicode              = data->create_process.unicode;
+        if (data->create_process.file == -1) event->u.CreateProcessInfo.hFile = 0;
         break;
     case EXIT_THREAD_DEBUG_EVENT:
-        event->u.ExitThread.dwExitCode = data.exit.exit_code;
+        event->u.ExitThread.dwExitCode = data->exit.exit_code;
         break;
     case EXIT_PROCESS_DEBUG_EVENT:
-        event->u.ExitProcess.dwExitCode = data.exit.exit_code;
+        event->u.ExitProcess.dwExitCode = data->exit.exit_code;
         break;
     case LOAD_DLL_DEBUG_EVENT:
-        event->u.LoadDll.hFile                 = data.load_dll.handle;
-        event->u.LoadDll.lpBaseOfDll           = data.load_dll.base;
-        event->u.LoadDll.dwDebugInfoFileOffset = data.load_dll.dbg_offset;
-        event->u.LoadDll.nDebugInfoSize        = data.load_dll.dbg_size;
-        event->u.LoadDll.lpImageName           = data.load_dll.name;
-        event->u.LoadDll.fUnicode              = data.load_dll.unicode;
-        if (data.load_dll.handle == -1) event->u.LoadDll.hFile = 0;
+        event->u.LoadDll.hFile                 = data->load_dll.handle;
+        event->u.LoadDll.lpBaseOfDll           = data->load_dll.base;
+        event->u.LoadDll.dwDebugInfoFileOffset = data->load_dll.dbg_offset;
+        event->u.LoadDll.nDebugInfoSize        = data->load_dll.dbg_size;
+        event->u.LoadDll.lpImageName           = data->load_dll.name;
+        event->u.LoadDll.fUnicode              = data->load_dll.unicode;
+        if (data->load_dll.handle == -1) event->u.LoadDll.hFile = 0;
         break;
     case UNLOAD_DLL_DEBUG_EVENT:
-        event->u.UnloadDll.lpBaseOfDll = data.unload_dll.base;
+        event->u.UnloadDll.lpBaseOfDll = data->unload_dll.base;
         break;
     case OUTPUT_DEBUG_STRING_EVENT:
-        event->u.DebugString.lpDebugStringData  = data.output_string.string;
-        event->u.DebugString.fUnicode           = data.output_string.unicode;
-        event->u.DebugString.nDebugStringLength = data.output_string.length;
+        event->u.DebugString.lpDebugStringData  = data->output_string.string;
+        event->u.DebugString.fUnicode           = data->output_string.unicode;
+        event->u.DebugString.nDebugStringLength = data->output_string.length;
         break;
     case RIP_EVENT:
-        event->u.RipInfo.dwError = data.rip_info.error;
-        event->u.RipInfo.dwType  = data.rip_info.type;
+        event->u.RipInfo.dwError = data->rip_info.error;
+        event->u.RipInfo.dwType  = data->rip_info.type;
         break;
     }
     return TRUE;
@@ -234,13 +213,11 @@
  */
 BOOL WINAPI ContinueDebugEvent( DWORD pid, DWORD tid, DWORD status )
 {
-    struct continue_debug_event_request req;
-
-    req.pid    = (void *)pid;
-    req.tid    = (void *)tid;
-    req.status = status;
-    CLIENT_SendRequest( REQ_CONTINUE_DEBUG_EVENT, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct continue_debug_event_request *req = get_req_buffer();
+    req->pid    = (void *)pid;
+    req->tid    = (void *)tid;
+    req->status = status;
+    return !server_call( REQ_CONTINUE_DEBUG_EVENT );
 }
 
 
@@ -249,10 +226,9 @@
  */
 BOOL WINAPI DebugActiveProcess( DWORD pid )
 {
-    struct debug_process_request req;
-    req.pid = (void *)pid;
-    CLIENT_SendRequest( REQ_DEBUG_PROCESS, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct debug_process_request *req = get_req_buffer();
+    req->pid = (void *)pid;
+    return !server_call( REQ_DEBUG_PROCESS );
 }
 
 
diff --git a/scheduler/event.c b/scheduler/event.c
index a145c76..9c37bc3 100644
--- a/scheduler/event.c
+++ b/scheduler/event.c
@@ -18,18 +18,16 @@
 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
                                 BOOL initial_state, LPCSTR name )
 {
-    struct create_event_request req;
-    struct create_event_reply reply;
+    struct create_event_request *req = get_req_buffer();
 
-    if (!name) name = "";
-    req.manual_reset = manual_reset;
-    req.initial_state = initial_state;
-    req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-    CLIENT_SendRequest( REQ_CREATE_EVENT, -1, 2, &req, sizeof(req), name, strlen(name)+1 );
+    req->manual_reset = manual_reset;
+    req->initial_state = initial_state;
+    req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+    lstrcpynA( req->name, name ? name : "", server_remaining(req->name) );
     SetLastError(0);
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    if (reply.handle == -1) return 0;
-    return reply.handle;
+    server_call( REQ_CREATE_EVENT );
+    if (req->handle == -1) return 0;
+    return req->handle;
 }
 
 
@@ -59,16 +57,14 @@
  */
 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
 {
-    struct open_event_request req;
-    struct open_event_reply reply;
-    int len = name ? strlen(name) + 1 : 0;
+    struct open_event_request *req = get_req_buffer();
 
-    req.access  = access;
-    req.inherit = inherit;
-    CLIENT_SendRequest( REQ_OPEN_EVENT, -1, 2, &req, sizeof(req), name, len );
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    if (reply.handle == -1) return 0; /* must return 0 on failure, not -1 */
-    return (HANDLE)reply.handle;
+    req->access  = access;
+    req->inherit = inherit;
+    lstrcpynA( req->name, name ? name : "", server_remaining(req->name) );
+    server_call( REQ_OPEN_EVENT );
+    if (req->handle == -1) return 0; /* must return 0 on failure, not -1 */
+    return req->handle;
 }
 
 
@@ -91,12 +87,10 @@
  */
 static BOOL EVENT_Operation( HANDLE handle, enum event_op op )
 {
-    struct event_op_request req;
-
-    req.handle = handle;
-    req.op     = op;
-    CLIENT_SendRequest( REQ_EVENT_OP, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct event_op_request *req = get_req_buffer();
+    req->handle = handle;
+    req->op     = op;
+    return !server_call( REQ_EVENT_OP );
 }
 
 
diff --git a/scheduler/handle.c b/scheduler/handle.c
index 98d9c59..8555a46 100644
--- a/scheduler/handle.c
+++ b/scheduler/handle.c
@@ -18,11 +18,9 @@
  */
 BOOL WINAPI CloseHandle( HANDLE handle )
 {
-    struct close_handle_request req;
-    
-    req.handle = handle;
-    CLIENT_SendRequest( REQ_CLOSE_HANDLE, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct close_handle_request *req = get_req_buffer();
+    req->handle = handle;
+    return !server_call( REQ_CLOSE_HANDLE );
 }
 
 
@@ -31,13 +29,10 @@
  */
 BOOL WINAPI GetHandleInformation( HANDLE handle, LPDWORD flags )
 {
-    struct get_handle_info_request req;
-    struct get_handle_info_reply reply;
-
-    req.handle = handle;
-    CLIENT_SendRequest( REQ_GET_HANDLE_INFO, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
-    if (flags) *flags = reply.flags;
+    struct get_handle_info_request *req = get_req_buffer();
+    req->handle = handle;
+    if (server_call( REQ_GET_HANDLE_INFO )) return FALSE;
+    if (flags) *flags = req->flags;
     return TRUE;
 }
 
@@ -47,13 +42,11 @@
  */
 BOOL WINAPI SetHandleInformation( HANDLE handle, DWORD mask, DWORD flags )
 {
-    struct set_handle_info_request req;
-
-    req.handle = handle;
-    req.flags  = flags;
-    req.mask   = mask;
-    CLIENT_SendRequest( REQ_SET_HANDLE_INFO, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct set_handle_info_request *req = get_req_buffer();
+    req->handle = handle;
+    req->flags  = flags;
+    req->mask   = mask;
+    return !server_call( REQ_SET_HANDLE_INFO );
 }
 
 
@@ -64,19 +57,17 @@
                                HANDLE dest_process, HANDLE *dest,
                                DWORD access, BOOL inherit, DWORD options )
 {
-    struct dup_handle_request req;
-    struct dup_handle_reply reply;
+    struct dup_handle_request *req = get_req_buffer();
 
-    req.src_process = source_process;
-    req.src_handle  = source;
-    req.dst_process = dest_process;
-    req.access      = access;
-    req.inherit     = inherit;
-    req.options     = options;
+    req->src_process = source_process;
+    req->src_handle  = source;
+    req->dst_process = dest_process;
+    req->access      = access;
+    req->inherit     = inherit;
+    req->options     = options;
 
-    CLIENT_SendRequest( REQ_DUP_HANDLE, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
-    if (dest) *dest = reply.handle;
+    if (server_call( REQ_DUP_HANDLE )) return FALSE;
+    if (dest) *dest = req->handle;
     return TRUE;
 }
 
@@ -86,19 +77,17 @@
  */
 HANDLE WINAPI ConvertToGlobalHandle(HANDLE hSrc)
 {
-    struct dup_handle_request req;
-    struct dup_handle_reply reply;
+    struct dup_handle_request *req = get_req_buffer();
 
-    req.src_process = GetCurrentProcess();
-    req.src_handle  = hSrc;
-    req.dst_process = -1;
-    req.access      = 0;
-    req.inherit     = FALSE;
-    req.options     = DUP_HANDLE_MAKE_GLOBAL | DUP_HANDLE_SAME_ACCESS;
+    req->src_process = GetCurrentProcess();
+    req->src_handle  = hSrc;
+    req->dst_process = -1;
+    req->access      = 0;
+    req->inherit     = FALSE;
+    req->options     = DUP_HANDLE_MAKE_GLOBAL | DUP_HANDLE_SAME_ACCESS;
 
-    CLIENT_SendRequest( REQ_DUP_HANDLE, -1, 1, &req, sizeof(req) );
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    return reply.handle;
+    server_call( REQ_DUP_HANDLE );
+    return req->handle;
 }
 
 /***********************************************************************
diff --git a/scheduler/mutex.c b/scheduler/mutex.c
index 9567495..94110f1 100644
--- a/scheduler/mutex.c
+++ b/scheduler/mutex.c
@@ -16,17 +16,15 @@
  */
 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
 {
-    struct create_mutex_request req;
-    struct create_mutex_reply reply;
+    struct create_mutex_request *req = get_req_buffer();
 
-    if (!name) name = "";
-    req.owned   = owner;
-    req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-    CLIENT_SendRequest( REQ_CREATE_MUTEX, -1, 2, &req, sizeof(req), name, strlen(name)+1 );
+    req->owned   = owner;
+    req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+    lstrcpynA( req->name, name ? name : "", server_remaining(req->name) );
     SetLastError(0);
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    if (reply.handle == -1) return 0;
-    return reply.handle;
+    server_call( REQ_CREATE_MUTEX );
+    if (req->handle == -1) return 0;
+    return req->handle;
 }
 
 
@@ -48,16 +46,14 @@
  */
 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
 {
-    struct open_mutex_request req;
-    struct open_mutex_reply reply;
-    int len = name ? strlen(name) + 1 : 0;
+    struct open_mutex_request *req = get_req_buffer();
 
-    req.access  = access;
-    req.inherit = inherit;
-    CLIENT_SendRequest( REQ_OPEN_MUTEX, -1, 2, &req, sizeof(req), name, len );
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    if (reply.handle == -1) return 0; /* must return 0 on failure, not -1 */
-    return reply.handle;
+    req->access  = access;
+    req->inherit = inherit;
+    lstrcpynA( req->name, name ? name : "", server_remaining(req->name) );
+    server_call( REQ_OPEN_MUTEX );
+    if (req->handle == -1) return 0; /* must return 0 on failure, not -1 */
+    return req->handle;
 }
 
 
@@ -78,9 +74,7 @@
  */
 BOOL WINAPI ReleaseMutex( HANDLE handle )
 {
-    struct release_mutex_request req;
-
-    req.handle = handle;
-    CLIENT_SendRequest( REQ_RELEASE_MUTEX, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct release_mutex_request *req = get_req_buffer();
+    req->handle = handle;
+    return !server_call( REQ_RELEASE_MUTEX );
 }
diff --git a/scheduler/pipe.c b/scheduler/pipe.c
index 74fff8c..6b018c7 100644
--- a/scheduler/pipe.c
+++ b/scheduler/pipe.c
@@ -16,15 +16,11 @@
 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
                           LPSECURITY_ATTRIBUTES sa, DWORD size )
 {
-    struct create_pipe_request req;
-    struct create_pipe_reply reply;
-    int len;
+    struct create_pipe_request *req = get_req_buffer();
 
-    req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-    CLIENT_SendRequest( REQ_CREATE_PIPE, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) ) != ERROR_SUCCESS)
-        return FALSE;
-    *hReadPipe  = reply.handle_read;
-    *hWritePipe = reply.handle_write;
+    req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+    if (server_call( REQ_CREATE_PIPE )) return FALSE;
+    *hReadPipe  = req->handle_read;
+    *hWritePipe = req->handle_write;
     return TRUE;
 }
diff --git a/scheduler/process.c b/scheduler/process.c
index 20d2737..70cc709 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -74,29 +74,16 @@
 }
 
 /***********************************************************************
- *           PROCESS_QueryInfo
- *
- * Retrieve information about a process
- */
-static BOOL PROCESS_QueryInfo( HANDLE handle,
-                                 struct get_process_info_reply *reply )
-{
-    struct get_process_info_request req;
-    req.handle = handle;
-    CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
-}
-
-/***********************************************************************
  *           PROCESS_IsCurrent
  *
  * Check if a handle is to the current process
  */
 BOOL PROCESS_IsCurrent( HANDLE handle )
 {
-    struct get_process_info_reply reply;
-    return (PROCESS_QueryInfo( handle, &reply ) &&
-            (reply.pid == PROCESS_Current()->server_pid));
+    struct get_process_info_request *req = get_req_buffer();
+    req->handle = handle;
+    return (!server_call( REQ_GET_PROCESS_INFO ) &&
+            (req->pid == PROCESS_Current()->server_pid));
 }
 
 
@@ -252,21 +239,12 @@
  */
 static BOOL PROCESS_CreateEnvDB(void)
 {
-    struct init_process_request req;
-    struct init_process_reply reply;
+    struct init_process_request *req = get_req_buffer();
     STARTUPINFOA *startup;
     ENVDB *env_db;
     char cmd_line[4096];
-    int len;
     PDB *pdb = PROCESS_Current();
 
-    /* Retrieve startup info from the server */
-
-    req.dummy = 0;
-    CLIENT_SendRequest( REQ_INIT_PROCESS, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply), cmd_line, sizeof(cmd_line) ))
-        return FALSE;
-
     /* Allocate the env DB */
 
     if (!(env_db = HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB) )))
@@ -278,15 +256,20 @@
     if (!(startup = HeapAlloc( pdb->heap, HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
         return FALSE;
     env_db->startup_info = startup;
-    startup->dwFlags     = reply.start_flags;
-    startup->wShowWindow = reply.cmd_show;
-    env_db->hStdin  = startup->hStdInput  = reply.hstdin;
-    env_db->hStdout = startup->hStdOutput = reply.hstdout;
-    env_db->hStderr = startup->hStdError  = reply.hstderr;
+
+    /* Retrieve startup info from the server */
+
+    if (server_call( REQ_INIT_PROCESS )) return FALSE;
+    startup->dwFlags     = req->start_flags;
+    startup->wShowWindow = req->cmd_show;
+    env_db->hStdin  = startup->hStdInput  = req->hstdin;
+    env_db->hStdout = startup->hStdOutput = req->hstdout;
+    env_db->hStderr = startup->hStdError  = req->hstderr;
+    lstrcpynA( cmd_line, req->cmdline, sizeof(cmd_line) );
 
     /* Copy the parent environment */
 
-    if (!ENV_InheritEnvironment( pdb, reply.env_ptr )) return FALSE;
+    if (!ENV_InheritEnvironment( pdb, req->env_ptr )) return FALSE;
 
     /* Copy the command line */
 
@@ -527,8 +510,7 @@
     HANDLE handles[2], load_done_evt = INVALID_HANDLE_VALUE;
     DWORD exitcode, size;
     int server_thandle;
-    struct new_process_request req;
-    struct new_process_reply reply;
+    struct new_process_request *req = get_req_buffer();
     TEB *teb = NULL;
     PDB *parent = PROCESS_Current();
     PDB *pdb = PROCESS_CreatePDB( parent, inherit );
@@ -538,29 +520,28 @@
 
     /* Create the process on the server side */
 
-    req.inherit      = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
-    req.inherit_all  = inherit;
-    req.create_flags = flags;
-    req.start_flags  = startup->dwFlags;
+    req->inherit      = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
+    req->inherit_all  = inherit;
+    req->create_flags = flags;
+    req->start_flags  = startup->dwFlags;
     if (startup->dwFlags & STARTF_USESTDHANDLES)
     {
-        req.hstdin  = startup->hStdInput;
-        req.hstdout = startup->hStdOutput;
-        req.hstderr = startup->hStdError;
+        req->hstdin  = startup->hStdInput;
+        req->hstdout = startup->hStdOutput;
+        req->hstderr = startup->hStdError;
     }
     else
     {
-        req.hstdin  = GetStdHandle( STD_INPUT_HANDLE );
-        req.hstdout = GetStdHandle( STD_OUTPUT_HANDLE );
-        req.hstderr = GetStdHandle( STD_ERROR_HANDLE );
+        req->hstdin  = GetStdHandle( STD_INPUT_HANDLE );
+        req->hstdout = GetStdHandle( STD_OUTPUT_HANDLE );
+        req->hstderr = GetStdHandle( STD_ERROR_HANDLE );
     }
-    req.cmd_show = startup->wShowWindow;
-    req.env_ptr = (void*)env;  /* FIXME: hack */
-    CLIENT_SendRequest( REQ_NEW_PROCESS, -1, 2,
-                        &req, sizeof(req), cmd_line, strlen(cmd_line) + 1 );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error;
-    pdb->server_pid   = reply.pid;
-    info->hProcess    = reply.handle;
+    req->cmd_show = startup->wShowWindow;
+    req->env_ptr = (void*)env;  /* FIXME: hack */
+    lstrcpynA( req->cmdline, cmd_line, server_remaining(req->cmdline) );
+    if (server_call( REQ_NEW_PROCESS )) goto error;
+    pdb->server_pid   = req->pid;
+    info->hProcess    = req->handle;
     info->dwProcessId = (DWORD)pdb->server_pid;
 
     if ((flags & DEBUG_PROCESS) ||
@@ -675,11 +656,10 @@
  */
 BOOL WINAPI TerminateProcess( HANDLE handle, DWORD exit_code )
 {
-    struct terminate_process_request req;
-    req.handle    = handle;
-    req.exit_code = exit_code;
-    CLIENT_SendRequest( REQ_TERMINATE_PROCESS, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct terminate_process_request *req = get_req_buffer();
+    req->handle    = handle;
+    req->exit_code = exit_code;
+    return !server_call( REQ_TERMINATE_PROCESS );
 }
 
 
@@ -816,15 +796,14 @@
  */
 HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id )
 {
-    struct open_process_request req;
-    struct open_process_reply reply;
+    HANDLE ret = 0;
+    struct open_process_request *req = get_req_buffer();
 
-    req.pid     = (void *)id;
-    req.access  = access;
-    req.inherit = inherit;
-    CLIENT_SendRequest( REQ_OPEN_PROCESS, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0;
-    return reply.handle;
+    req->pid     = (void *)id;
+    req->access  = access;
+    req->inherit = inherit;
+    if (!server_call( REQ_OPEN_PROCESS )) ret = req->handle;
+    return ret;
 }			      
 
 /*********************************************************************
@@ -832,9 +811,11 @@
  */
 DWORD WINAPI MapProcessHandle( HANDLE handle )
 {
-    struct get_process_info_reply reply;
-    if ( !PROCESS_QueryInfo( handle, &reply ) ) return 0;
-    return (DWORD)reply.pid;
+    DWORD ret = 0;
+    struct get_process_info_request *req = get_req_buffer();
+    req->handle = handle;
+    if (!server_call( REQ_GET_PROCESS_INFO )) ret = (DWORD)req->pid;
+    return ret;
 }
 
 /***********************************************************************
@@ -870,12 +851,11 @@
  */
 BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass )
 {
-    struct set_process_info_request req;
-    req.handle   = hprocess;
-    req.priority = priorityclass;
-    req.mask     = SET_PROCESS_INFO_PRIORITY;
-    CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct set_process_info_request *req = get_req_buffer();
+    req->handle   = hprocess;
+    req->priority = priorityclass;
+    req->mask     = SET_PROCESS_INFO_PRIORITY;
+    return !server_call( REQ_SET_PROCESS_INFO );
 }
 
 
@@ -884,9 +864,11 @@
  */
 DWORD WINAPI GetPriorityClass(HANDLE hprocess)
 {
-    struct get_process_info_reply reply;
-    if (!PROCESS_QueryInfo( hprocess, &reply )) return 0;
-    return reply.priority;
+    DWORD ret = 0;
+    struct get_process_info_request *req = get_req_buffer();
+    req->handle = hprocess;
+    if (!server_call( REQ_GET_PROCESS_INFO )) ret = req->priority;
+    return ret;
 }
 
 
@@ -895,12 +877,11 @@
  */
 BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask )
 {
-    struct set_process_info_request req;
-    req.handle   = hProcess;
-    req.affinity = affmask;
-    req.mask     = SET_PROCESS_INFO_AFFINITY;
-    CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct set_process_info_request *req = get_req_buffer();
+    req->handle   = hProcess;
+    req->affinity = affmask;
+    req->mask     = SET_PROCESS_INFO_AFFINITY;
+    return !server_call( REQ_SET_PROCESS_INFO );
 }
 
 /**********************************************************************
@@ -910,11 +891,16 @@
                                       LPDWORD lpProcessAffinityMask,
                                       LPDWORD lpSystemAffinityMask )
 {
-    struct get_process_info_reply reply;
-    if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
-    if (lpProcessAffinityMask) *lpProcessAffinityMask = reply.process_affinity;
-    if (lpSystemAffinityMask) *lpSystemAffinityMask = reply.system_affinity;
-    return TRUE;
+    BOOL ret = FALSE;
+    struct get_process_info_request *req = get_req_buffer();
+    req->handle = hProcess;
+    if (!server_call( REQ_GET_PROCESS_INFO ))
+    {
+        if (lpProcessAffinityMask) *lpProcessAffinityMask = req->process_affinity;
+        if (lpSystemAffinityMask) *lpSystemAffinityMask = req->system_affinity;
+        ret = TRUE;
+    }
+    return ret;
 }
 
 
@@ -1119,10 +1105,15 @@
     HANDLE hProcess,  /* [I] handle to the process */
     LPDWORD lpExitCode) /* [O] address to receive termination status */
 {
-    struct get_process_info_reply reply;
-    if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
-    if (lpExitCode) *lpExitCode = reply.exit_code;
-    return TRUE;
+    BOOL ret = FALSE;
+    struct get_process_info_request *req = get_req_buffer();
+    req->handle = hProcess;
+    if (!server_call( REQ_GET_PROCESS_INFO ))
+    {
+        if (lpExitCode) *lpExitCode = req->exit_code;
+        ret = TRUE;
+    }
+    return ret;
 }
 
 
diff --git a/scheduler/semaphore.c b/scheduler/semaphore.c
index 018606b..890efa8 100644
--- a/scheduler/semaphore.c
+++ b/scheduler/semaphore.c
@@ -16,8 +16,7 @@
  */
 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
 {
-    struct create_semaphore_request req;
-    struct create_semaphore_reply reply;
+    struct create_semaphore_request *req = get_req_buffer();
 
     /* Check parameters */
 
@@ -27,16 +26,14 @@
         return 0;
     }
 
-    if (!name) name = "";
-    req.initial = (unsigned int)initial;
-    req.max     = (unsigned int)max;
-    req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-
-    CLIENT_SendRequest( REQ_CREATE_SEMAPHORE, -1, 2, &req, sizeof(req), name, strlen(name)+1 );
+    req->initial = (unsigned int)initial;
+    req->max     = (unsigned int)max;
+    req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+    lstrcpynA( req->name, name ? name : "", server_remaining(req->name) );
     SetLastError(0);
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    if (reply.handle == -1) return 0;
-    return reply.handle;
+    server_call( REQ_CREATE_SEMAPHORE );
+    if (req->handle == -1) return 0;
+    return req->handle;
 }
 
 
@@ -58,16 +55,14 @@
  */
 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
 {
-    struct open_semaphore_request req;
-    struct open_semaphore_reply reply;
-    int len = name ? strlen(name) + 1 : 0;
+    struct open_semaphore_request *req = get_req_buffer();
 
-    req.access  = access;
-    req.inherit = inherit;
-    CLIENT_SendRequest( REQ_OPEN_SEMAPHORE, -1, 2, &req, sizeof(req), name, len );
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    if (reply.handle == -1) return 0; /* must return 0 on failure, not -1 */
-    return reply.handle;
+    req->access  = access;
+    req->inherit = inherit;
+    lstrcpynA( req->name, name ? name : "", server_remaining(req->name) );
+    server_call( REQ_OPEN_SEMAPHORE );
+    if (req->handle == -1) return 0; /* must return 0 on failure, not -1 */
+    return req->handle;
 }
 
 
@@ -88,18 +83,16 @@
  */
 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
 {
-    struct release_semaphore_request req;
-    struct release_semaphore_reply reply;
+    struct release_semaphore_request *req = get_req_buffer();
 
     if (count < 0)
     {
         SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
-    req.handle = handle;
-    req.count  = (unsigned int)count;
-    CLIENT_SendRequest( REQ_RELEASE_SEMAPHORE, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
-    if (previous) *previous = reply.prev_count;
+    req->handle = handle;
+    req->count  = (unsigned int)count;
+    if (server_call( REQ_RELEASE_SEMAPHORE )) return FALSE;
+    if (previous) *previous = req->prev_count;
     return TRUE;
 }
diff --git a/scheduler/synchro.c b/scheduler/synchro.c
index 5504656..7c57e51 100644
--- a/scheduler/synchro.c
+++ b/scheduler/synchro.c
@@ -17,6 +17,27 @@
 #include "x11drv.h"
 #include "server.h"
 
+/***********************************************************************
+ *              call_apcs
+ *
+ * Call outstanding APCs.
+ */
+static void call_apcs(void)
+{
+#define MAX_APCS 16
+    int i;
+    void *buffer[MAX_APCS * 2];
+    struct get_apcs_request *req = get_req_buffer();
+
+    if (server_call( REQ_GET_APCS ) || !req->count) return;
+    assert( req->count <= MAX_APCS );
+    memcpy( buffer, req->apcs, req->count * 2 * sizeof(req->apcs[0]) );
+    for (i = 0; i < req->count * 2; i += 2)
+    {
+        PAPCFUNC func = (PAPCFUNC)req->apcs[i];
+        if (func) func( (ULONG_PTR)req->apcs[i+1] );
+    }
+}
 
 /***********************************************************************
  *              Sleep  (KERNEL32.679)
@@ -73,11 +94,8 @@
                                        BOOL wait_all, DWORD timeout,
                                        BOOL alertable )
 {
-    struct select_request req;
-    struct select_reply reply;
-    int server_handle[MAXIMUM_WAIT_OBJECTS];
-    void *apc[32];
-    int i, len;
+    struct select_request *req = get_req_buffer();
+    int i, ret;
 
     if (count > MAXIMUM_WAIT_OBJECTS)
     {
@@ -99,32 +117,18 @@
             EVENT_Synchronize( FALSE );
     }
 
-    for (i = 0; i < count; i++) server_handle[i] = handles[i];
+    req->count   = count;
+    req->flags   = 0;
+    req->timeout = timeout;
+    for (i = 0; i < count; i++) req->handles[i] = handles[i];
 
-    req.count   = count;
-    req.flags   = 0;
-    req.timeout = timeout;
+    if (wait_all) req->flags |= SELECT_ALL;
+    if (alertable) req->flags |= SELECT_ALERTABLE;
+    if (timeout != INFINITE) req->flags |= SELECT_TIMEOUT;
 
-    if (wait_all) req.flags |= SELECT_ALL;
-    if (alertable) req.flags |= SELECT_ALERTABLE;
-    if (timeout != INFINITE) req.flags |= SELECT_TIMEOUT;
-
-    CLIENT_SendRequest( REQ_SELECT, -1, 2,
-                        &req, sizeof(req),
-                        server_handle, count * sizeof(int) );
-    CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply),
-                      apc, sizeof(apc) );
-    if ((reply.signaled == STATUS_USER_APC) && (len > sizeof(reply)))
-    {
-        int i;
-        len -= sizeof(reply);
-        for (i = 0; i < len / sizeof(void*); i += 2)
-        {
-            PAPCFUNC func = (PAPCFUNC)apc[i];
-            if ( func ) func( (ULONG_PTR)apc[i+1] );
-        }
-    }
-    return reply.signaled;
+    server_call( REQ_SELECT );
+    if ((ret = req->signaled) == STATUS_USER_APC) call_apcs();
+    return ret;
 }
 
 
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 7a5b9de..62e4dc7 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -199,8 +199,7 @@
 TEB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16,
                      LPSECURITY_ATTRIBUTES sa, int *server_handle )
 {
-    struct new_thread_request request;
-    struct new_thread_reply reply = { NULL, -1 };
+    struct new_thread_request *req = get_req_buffer();
     int fd[2];
     HANDLE cleanup_object;
 
@@ -217,6 +216,7 @@
 
     /* Allocate the TEB selector (%fs register) */
 
+    *server_handle = -1;
     teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE );
     if (!teb->teb_sel) goto error;
 
@@ -232,13 +232,12 @@
 
     /* Create the thread on the server side */
 
-    request.pid     = teb->process->server_pid;
-    request.suspend = ((flags & CREATE_SUSPENDED) != 0);
-    request.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-    CLIENT_SendRequest( REQ_NEW_THREAD, fd[1], 1, &request, sizeof(request) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error;
-    teb->tid = reply.tid;
-    *server_handle = reply.handle;
+    req->pid     = teb->process->server_pid;
+    req->suspend = ((flags & CREATE_SUSPENDED) != 0);
+    req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+    if (server_call_fd( REQ_NEW_THREAD, fd[1], NULL )) goto error;
+    teb->tid = req->tid;
+    *server_handle = req->handle;
 
     /* Do the rest of the initialization */
 
@@ -255,7 +254,7 @@
     return teb;
 
 error:
-    if (reply.handle != -1) CloseHandle( reply.handle );
+    if (*server_handle != -1) CloseHandle( *server_handle );
     if (teb->teb_sel) SELECTOR_FreeBlock( teb->teb_sel, 1 );
     if (teb->socket != -1) close( teb->socket );
     HeapFree( SystemHeap, 0, teb );
@@ -532,13 +531,11 @@
 INT WINAPI GetThreadPriority(
     HANDLE hthread) /* [in] Handle to thread */
 {
-    struct get_thread_info_request req;
-    struct get_thread_info_reply reply;
-    req.handle = hthread;
-    CLIENT_SendRequest( REQ_GET_THREAD_INFO, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ))
-        return THREAD_PRIORITY_ERROR_RETURN;
-    return reply.priority;
+    INT ret = THREAD_PRIORITY_ERROR_RETURN;
+    struct get_thread_info_request *req = get_req_buffer();
+    req->handle = hthread;
+    if (!server_call( REQ_GET_THREAD_INFO )) ret = req->priority;
+    return ret;
 }
 
 
@@ -553,12 +550,11 @@
     HANDLE hthread, /* [in] Handle to thread */
     INT priority)   /* [in] Thread priority level */
 {
-    struct set_thread_info_request req;
-    req.handle   = hthread;
-    req.priority = priority;
-    req.mask     = SET_THREAD_INFO_PRIORITY;
-    CLIENT_SendRequest( REQ_SET_THREAD_INFO, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct set_thread_info_request *req = get_req_buffer();
+    req->handle   = hthread;
+    req->priority = priority;
+    req->mask     = SET_THREAD_INFO_PRIORITY;
+    return !server_call( REQ_SET_THREAD_INFO );
 }
 
 
@@ -567,12 +563,11 @@
  */
 DWORD WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD dwThreadAffinityMask )
 {
-    struct set_thread_info_request req;
-    req.handle   = hThread;
-    req.affinity = dwThreadAffinityMask;
-    req.mask     = SET_THREAD_INFO_AFFINITY;
-    CLIENT_SendRequest( REQ_SET_THREAD_INFO, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitReply( NULL, NULL, 0 )) return 0;
+    struct set_thread_info_request *req = get_req_buffer();
+    req->handle   = hThread;
+    req->affinity = dwThreadAffinityMask;
+    req->mask     = SET_THREAD_INFO_AFFINITY;
+    if (server_call( REQ_SET_THREAD_INFO )) return 0;
     return 1;  /* FIXME: should return previous value */
 }
 
@@ -588,11 +583,10 @@
     HANDLE handle, /* [in] Handle to thread */
     DWORD exitcode)  /* [in] Exit code for thread */
 {
-    struct terminate_thread_request req;
-    req.handle    = handle;
-    req.exit_code = exitcode;
-    CLIENT_SendRequest( REQ_TERMINATE_THREAD, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct terminate_thread_request *req = get_req_buffer();
+    req->handle    = handle;
+    req->exit_code = exitcode;
+    return !server_call( REQ_TERMINATE_THREAD );
 }
 
 
@@ -607,13 +601,15 @@
     HANDLE hthread, /* [in]  Handle to thread */
     LPDWORD exitcode) /* [out] Address to receive termination status */
 {
-    struct get_thread_info_request req;
-    struct get_thread_info_reply reply;
-    req.handle = hthread;
-    CLIENT_SendRequest( REQ_GET_THREAD_INFO, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
-    if (exitcode) *exitcode = reply.exit_code;
-    return TRUE;
+    BOOL ret = FALSE;
+    struct get_thread_info_request *req = get_req_buffer();
+    req->handle = hthread;
+    if (!server_call( REQ_GET_THREAD_INFO ))
+    {
+        if (exitcode) *exitcode = req->exit_code;
+        ret = TRUE;
+    }
+    return ret;
 }
 
 
@@ -631,12 +627,11 @@
 DWORD WINAPI ResumeThread(
     HANDLE hthread) /* [in] Identifies thread to restart */
 {
-    struct resume_thread_request req;
-    struct resume_thread_reply reply;
-    req.handle = hthread;
-    CLIENT_SendRequest( REQ_RESUME_THREAD, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0xffffffff;
-    return reply.count;
+    DWORD ret = 0xffffffff;
+    struct resume_thread_request *req = get_req_buffer();
+    req->handle = hthread;
+    if (!server_call( REQ_RESUME_THREAD )) ret = req->count;
+    return ret;
 }
 
 
@@ -650,12 +645,11 @@
 DWORD WINAPI SuspendThread(
     HANDLE hthread) /* [in] Handle to the thread */
 {
-    struct suspend_thread_request req;
-    struct suspend_thread_reply reply;
-    req.handle = hthread;
-    CLIENT_SendRequest( REQ_SUSPEND_THREAD, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0xffffffff;
-    return reply.count;
+    DWORD ret = 0xffffffff;
+    struct suspend_thread_request *req = get_req_buffer();
+    req->handle = hthread;
+    if (!server_call( REQ_SUSPEND_THREAD )) ret = req->count;
+    return ret;
 }
 
 
@@ -664,12 +658,11 @@
  */
 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
 {
-    struct queue_apc_request req;
-    req.handle = hthread;
-    req.func   = func;
-    req.param  = (void *)data;
-    CLIENT_SendRequest( REQ_QUEUE_APC, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct queue_apc_request *req = get_req_buffer();
+    req->handle = hthread;
+    req->func   = func;
+    req->param  = (void *)data;
+    return !server_call( REQ_QUEUE_APC );
 }