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

diff --git a/include/server.h b/include/server.h
index 8c18e3f..2c8b06d 100644
--- a/include/server.h
+++ b/include/server.h
@@ -22,7 +22,24 @@
 /* to generate the request/reply tracing functions */
 #define IN  /*nothing*/
 #define OUT /*nothing*/
+#define VARARG(name,func) /*nothing*/
 
+struct request_header
+{
+    IN  int            req;          /* request code */
+    IN  unsigned short fixed_size;   /* size of the fixed part of the request */
+    IN  unsigned short var_size;     /* size of the variable part of the request */
+    OUT unsigned int   error;        /* error result */
+};
+#define REQUEST_HEADER  struct request_header header
+
+
+/* placeholder structure for the maximum allowed request size */
+/* this is used to construct the generic_request union */
+struct request_max_size
+{
+    int pad[16]; /* the max request size is 16 ints */
+};
 
 /* a path name for server requests (Unicode) */
 typedef WCHAR path_t[MAX_PATH+1];
@@ -104,6 +121,7 @@
 /* Create a new process from the context of the parent */
 struct new_process_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          inherit_all;  /* inherit all handles from parent */
     IN  int          create_flags; /* creation flags */
     IN  int          start_flags;  /* flags from startup info */
@@ -120,6 +138,7 @@
 /* Wait for the new process to start */
 struct wait_process_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          pinherit;     /* process handle inherit flag */
     IN  int          tinherit;     /* thread handle inherit flag */
     IN  int          timeout;      /* wait timeout */
@@ -135,6 +154,7 @@
 /* Create a new thread from the context of the parent */
 struct new_thread_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          suspend;      /* new thread should be suspended on creation */ 
     IN  int          inherit;      /* inherit flag */
     OUT void*        tid;          /* thread id */
@@ -145,6 +165,7 @@
 /* Signal that we are finished booting on the client side */
 struct boot_done_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          debug_level;  /* new debug level */
 };
 
@@ -152,6 +173,7 @@
 /* Initialize a process; called from the new process context */
 struct init_process_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  void*        ldt_copy;     /* addr of LDT copy */
     IN  void*        ldt_flags;    /* addr of LDT flags */
     IN  int          ppid;         /* parent Unix pid */
@@ -168,6 +190,7 @@
 /* Signal the end of the process initialization */
 struct init_process_done_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  void*        module;       /* main module base address */
     IN  void*        entry;        /* process entry point */
     IN  void*        name;         /* ptr to ptr to name (in process addr space) */
@@ -179,6 +202,7 @@
 /* Initialize a thread; called from the child after fork()/clone() */
 struct init_thread_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          unix_pid;     /* Unix pid of new thread */
     IN  void*        teb;          /* TEB of new thread (in thread address space) */
     IN  void*        entry;        /* thread entry point (in thread address space) */
@@ -190,6 +214,7 @@
 /* created thread gets (without having to request it) */
 struct get_thread_buffer_request
 {
+    REQUEST_HEADER;                /* request header */
     OUT void*        pid;          /* process id of the new thread's process */
     OUT void*        tid;          /* thread id of the new thread */
     OUT int          boot;         /* is this the boot thread? */
@@ -200,6 +225,7 @@
 /* Terminate a process */
 struct terminate_process_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* process handle to terminate */
     IN  int          exit_code;    /* process exit code */
     OUT int          self;         /* suicide? */
@@ -209,6 +235,7 @@
 /* Terminate a thread */
 struct terminate_thread_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* thread handle to terminate */
     IN  int          exit_code;    /* thread exit code */
     OUT int          self;         /* suicide? */
@@ -219,6 +246,7 @@
 /* Retrieve information about a process */
 struct get_process_info_request
 {
+    REQUEST_HEADER;                    /* request header */
     IN  int          handle;           /* process handle */
     OUT void*        pid;              /* server process id */
     OUT int          debugged;         /* debugged? */
@@ -232,6 +260,7 @@
 /* Set a process informations */
 struct set_process_info_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* process handle */
     IN  int          mask;         /* setting mask (see below) */
     IN  int          priority;     /* priority class */
@@ -244,6 +273,7 @@
 /* Retrieve information about a thread */
 struct get_thread_info_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* thread handle */
     IN  void*        tid_in;       /* thread id (optional) */
     OUT void*        tid;          /* server thread id */
@@ -256,6 +286,7 @@
 /* Set a thread informations */
 struct set_thread_info_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* thread handle */
     IN  int          mask;         /* setting mask (see below) */
     IN  int          priority;     /* priority class */
@@ -268,6 +299,7 @@
 /* Suspend a thread */
 struct suspend_thread_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* thread handle */
     OUT int          count;        /* new suspend count */
 };
@@ -276,6 +308,7 @@
 /* Resume a thread */
 struct resume_thread_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* thread handle */
     OUT int          count;        /* new suspend count */
 };
@@ -284,6 +317,7 @@
 /* Notify the server that a dll has been loaded */
 struct load_dll_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* file handle */
     IN  void*        base;         /* base address */
     IN  int          dbg_offset;   /* debug info offset */
@@ -295,6 +329,7 @@
 /* Notify the server that a dll is being unloaded */
 struct unload_dll_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  void*        base;         /* base address */
 };
 
@@ -302,6 +337,7 @@
 /* Queue an APC for a thread */
 struct queue_apc_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* thread handle */
     IN  void*        func;         /* function to call */
     IN  void*        param;        /* param for function to call */
@@ -311,6 +347,7 @@
 /* Get next APC to call */
 struct get_apc_request
 {
+    REQUEST_HEADER;                /* request header */
     OUT void*        func;         /* function to call */
     OUT int          type;         /* function type */
     OUT int          nb_args;      /* number of arguments */
@@ -322,6 +359,7 @@
 /* Close a handle for the current process */
 struct close_handle_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* handle to close */
 };
 
@@ -329,6 +367,7 @@
 /* Get information about a handle */
 struct get_handle_info_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* handle we are interested in */
     OUT int          flags;        /* handle flags */
 };
@@ -337,6 +376,7 @@
 /* Set a handle information */
 struct set_handle_info_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* handle we are interested in */
     IN  int          flags;        /* new handle flags */
     IN  int          mask;         /* mask for flags to set */
@@ -346,6 +386,7 @@
 /* Duplicate a handle */
 struct dup_handle_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          src_process;  /* src process handle */
     IN  int          src_handle;   /* src handle to duplicate */
     IN  int          dst_process;  /* dst process handle */
@@ -362,6 +403,7 @@
 /* Open a handle to a process */
 struct open_process_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  void*        pid;          /* process id to open */
     IN  unsigned int access;       /* wanted access rights */
     IN  int          inherit;      /* inherit flag */
@@ -372,6 +414,7 @@
 /* Wait for handles */
 struct select_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          count;        /* handles count */
     IN  int          flags;        /* wait flags (see below) */
     IN  int          timeout;      /* timeout in ms */
@@ -386,6 +429,7 @@
 /* Create an event */
 struct create_event_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          manual_reset;  /* manual reset event */
     IN  int          initial_state; /* initial state of the event */
     IN  int          inherit;       /* inherit flag */
@@ -396,6 +440,7 @@
 /* Event operation */
 struct event_op_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int           handle;       /* handle to event */
     IN  int           op;           /* event operation (see below) */
 };
@@ -405,6 +450,7 @@
 /* Open an event */
 struct open_event_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
     OUT int          handle;        /* handle to the event */
@@ -415,6 +461,7 @@
 /* Create a mutex */
 struct create_mutex_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          owned;         /* initially owned? */
     IN  int          inherit;       /* inherit flag */
     OUT int          handle;        /* handle to the mutex */
@@ -425,6 +472,7 @@
 /* Release a mutex */
 struct release_mutex_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the mutex */
 };
 
@@ -432,6 +480,7 @@
 /* Open a mutex */
 struct open_mutex_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
     OUT int          handle;        /* handle to the mutex */
@@ -442,6 +491,7 @@
 /* Create a semaphore */
 struct create_semaphore_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int initial;       /* initial count */
     IN  unsigned int max;           /* maximum count */
     IN  int          inherit;       /* inherit flag */
@@ -453,6 +503,7 @@
 /* Release a semaphore */
 struct release_semaphore_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the semaphore */
     IN  unsigned int count;         /* count to add to semaphore */
     OUT unsigned int prev_count;    /* previous semaphore count */
@@ -462,6 +513,7 @@
 /* Open a semaphore */
 struct open_semaphore_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
     OUT int          handle;        /* handle to the semaphore */
@@ -472,6 +524,7 @@
 /* Create a file */
 struct create_file_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
     IN  unsigned int sharing;       /* sharing flags */
@@ -485,6 +538,7 @@
 /* Allocate a file handle for a Unix fd */
 struct alloc_file_handle_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     OUT int          handle;        /* handle to the file */
 };
@@ -493,6 +547,7 @@
 /* Get a Unix fd to read from a file */
 struct get_read_fd_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the file */
 };
 
@@ -500,6 +555,7 @@
 /* Get a Unix fd to write to a file */
 struct get_write_fd_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the file */
 };
 
@@ -507,6 +563,7 @@
 /* Set a file current position */
 struct set_file_pointer_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the file */
     IN  int          low;           /* position low word */
     IN  int          high;          /* position high word */
@@ -519,6 +576,7 @@
 /* Truncate (or extend) a file */
 struct truncate_file_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the file */
 };
 
@@ -526,6 +584,7 @@
 /* Set a file access and modification times */
 struct set_file_time_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the file */
     IN  time_t       access_time;   /* last access time */
     IN  time_t       write_time;    /* last write time */
@@ -535,6 +594,7 @@
 /* Flush a file buffers */
 struct flush_file_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the file */
 };
 
@@ -542,6 +602,7 @@
 /* Get information about a file */
 struct get_file_info_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the file */
     OUT int          type;          /* file type */
     OUT int          attr;          /* file attributes */
@@ -559,6 +620,7 @@
 /* Lock a region of a file */
 struct lock_file_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the file */
     IN  unsigned int offset_low;    /* offset of start of lock */
     IN  unsigned int offset_high;   /* offset of start of lock */
@@ -570,6 +632,7 @@
 /* Unlock a region of a file */
 struct unlock_file_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the file */
     IN  unsigned int offset_low;    /* offset of start of unlock */
     IN  unsigned int offset_high;   /* offset of start of unlock */
@@ -581,6 +644,7 @@
 /* Create an anonymous pipe */
 struct create_pipe_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          inherit;       /* inherit flag */
     OUT int          handle_read;   /* handle to the read-side of the pipe */
     OUT int          handle_write;  /* handle to the write-side of the pipe */
@@ -590,6 +654,7 @@
 /* Create a socket */
 struct create_socket_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
     IN  int          family;        /* family, see socket manpage */
@@ -602,6 +667,7 @@
 /* Accept a socket */
 struct accept_socket_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          lhandle;       /* handle to the listening socket */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
@@ -612,6 +678,7 @@
 /* Set socket event parameters */
 struct set_socket_event_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the socket */
     IN  unsigned int mask;          /* event mask */
     IN  int          event;         /* event object */
@@ -621,6 +688,7 @@
 /* Get socket event parameters */
 struct get_socket_event_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the socket */
     IN  int          service;       /* clear pending? */
     IN  int          s_event;       /* "expected" event object */
@@ -635,6 +703,7 @@
 /* Reenable pending socket events */
 struct enable_socket_event_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the socket */
     IN  unsigned int mask;          /* events to re-enable */
     IN  unsigned int sstate;        /* status bits to set */
@@ -645,6 +714,7 @@
 /* Allocate a console for the current process */
 struct alloc_console_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
     OUT int          handle_in;     /* handle to console input */
@@ -655,13 +725,14 @@
 /* Free the console of the current process */
 struct free_console_request
 {
-    IN  int dummy;
+    REQUEST_HEADER;                 /* request header */
 };
 
 
 /* Open a handle to the process console */
 struct open_console_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          output;        /* input or output? */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
@@ -672,6 +743,7 @@
 /* Set a console file descriptor */
 struct set_console_fd_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the console */
     IN  int          file_handle;   /* handle of file to use as file descriptor */
     IN  int          pid;           /* pid of xterm (hack) */
@@ -681,6 +753,7 @@
 /* Get a console mode (input or output) */
 struct get_console_mode_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the console */
     OUT int          mode;          /* console mode */
 };
@@ -689,6 +762,7 @@
 /* Set a console mode (input or output) */
 struct set_console_mode_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the console */
     IN  int          mode;          /* console mode */
 };
@@ -697,6 +771,7 @@
 /* Set info about a console (output only) */
 struct set_console_info_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the console */
     IN  int          mask;          /* setting mask (see below) */
     IN  int          cursor_size;   /* size of cursor (percentage filled) */
@@ -709,6 +784,7 @@
 /* Get info about a console (output only) */
 struct get_console_info_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the console */
     OUT int          cursor_size;   /* size of cursor (percentage filled) */
     OUT int          cursor_visible;/* cursor visibility flag */
@@ -720,6 +796,7 @@
 /* Add input records to a console input queue */
 struct write_console_input_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the console input */
     IN  int          count;         /* number of input records */
     OUT int          written;       /* number of records written */
@@ -729,6 +806,7 @@
 /* Fetch input records from a console input queue */
 struct read_console_input_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the console input */
     IN  int          count;         /* max number of records to retrieve */
     IN  int          flush;         /* flush the retrieved records from the queue? */
@@ -740,6 +818,7 @@
 /* Create a change notification */
 struct create_change_notification_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          subtree;       /* watch all the subtree */
     IN  int          filter;        /* notification filter */
     OUT int          handle;        /* handle to the change notification */
@@ -749,6 +828,7 @@
 /* Create a file mapping */
 struct create_mapping_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          size_high;     /* mapping size */
     IN  int          size_low;      /* mapping size */
     IN  int          protect;       /* protection flags (see below) */
@@ -771,6 +851,7 @@
 /* Open a mapping */
 struct open_mapping_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
     OUT int          handle;        /* handle to the mapping */
@@ -781,6 +862,7 @@
 /* Get information about a file mapping */
 struct get_mapping_info_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the mapping */
     OUT int          size_high;     /* mapping size */
     OUT int          size_low;      /* mapping size */
@@ -795,6 +877,7 @@
 /* Create a device */
 struct create_device_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
     IN  int          id;            /* client private id */
@@ -805,6 +888,7 @@
 /* Create a snapshot */
 struct create_snapshot_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          inherit;       /* inherit flag */
     IN  int          flags;         /* snapshot flags (TH32CS_*) */
     IN  void*        pid;           /* process id */
@@ -815,6 +899,7 @@
 /* Get the next process from a snapshot */
 struct next_process_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the snapshot */
     IN  int          reset;         /* reset snapshot position? */
     OUT int          count;         /* process usage count */
@@ -827,6 +912,7 @@
 /* Get the next thread from a snapshot */
 struct next_thread_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the snapshot */
     IN  int          reset;         /* reset snapshot position? */
     OUT int          count;         /* thread usage count */
@@ -840,6 +926,7 @@
 /* Get the next module from a snapshot */
 struct next_module_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the snapshot */
     IN  int          reset;         /* reset snapshot position? */
     OUT void*        pid;           /* process id */
@@ -850,6 +937,7 @@
 /* Wait for a debug event */
 struct wait_debug_event_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int           timeout;     /* timeout in ms */
     OUT void*         pid;         /* process id */
     OUT void*         tid;         /* thread id */
@@ -860,6 +948,7 @@
 /* Send an exception event */
 struct exception_event_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  EXCEPTION_RECORD record;   /* exception record */
     IN  int              first;    /* first chance exception? */
     IN  CONTEXT          context;  /* thread context */
@@ -870,6 +959,7 @@
 /* Send an output string to the debugger */
 struct output_debug_string_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  void*         string;      /* string to display (in debugged process address space) */
     IN  int           unicode;     /* is it Unicode? */
     IN  int           length;      /* string length */
@@ -879,6 +969,7 @@
 /* Continue a debug event */
 struct continue_debug_event_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  void*        pid;          /* process id to continue */
     IN  void*        tid;          /* thread id to continue */
     IN  int          status;       /* continuation status */
@@ -888,6 +979,7 @@
 /* Start debugging an existing process */
 struct debug_process_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  void*        pid;          /* id of the process to debug */
 };
 
@@ -895,6 +987,7 @@
 /* Read data from a process address space */
 struct read_process_memory_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* process handle */
     IN  void*        addr;         /* addr to read from (must be int-aligned) */
     IN  int          len;          /* number of ints to read */
@@ -905,6 +998,7 @@
 /* Write data to a process address space */
 struct write_process_memory_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* process handle */
     IN  void*        addr;         /* addr to write to (must be int-aligned) */
     IN  int          len;          /* number of ints to write */
@@ -917,6 +1011,7 @@
 /* Create a registry key */
 struct create_key_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          parent;       /* handle to the parent key */
     IN  unsigned int access;       /* desired access rights */
     IN  unsigned int options;      /* creation options */
@@ -931,6 +1026,7 @@
 /* Open a registry key */
 struct open_key_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          parent;       /* handle to the parent key */
     IN  unsigned int access;       /* desired access rights */
     OUT int          hkey;         /* handle to the open key */
@@ -941,6 +1037,7 @@
 /* Delete a registry key */
 struct delete_key_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* handle to the parent key */
     IN  path_t       name;         /* key name */
 };
@@ -949,6 +1046,7 @@
 /* Close a registry key */
 struct close_key_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          hkey;          /* key to close */
 };
 
@@ -956,6 +1054,7 @@
 /* Enumerate registry subkeys */
 struct enum_key_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* handle to registry key */
     IN  int          index;        /* index of subkey */
     OUT time_t       modif;        /* last modification time */
@@ -967,6 +1066,7 @@
 /* Query information about a registry key */
 struct query_key_info_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* handle to registry key */
     OUT int          subkeys;      /* number of subkeys */
     OUT int          max_subkey;   /* longest subkey name */
@@ -983,6 +1083,7 @@
 /* Set a value of a registry key */
 struct set_key_value_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* handle to registry key */
     IN  int          type;         /* value type */
     IN  unsigned int total;        /* total value len */
@@ -996,6 +1097,7 @@
 /* Retrieve the value of a registry key */
 struct get_key_value_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* handle to registry key */
     IN  unsigned int offset;       /* offset for getting data */
     OUT int          type;         /* value type */
@@ -1008,6 +1110,7 @@
 /* Enumerate a value of a registry key */
 struct enum_key_value_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* handle to registry key */
     IN  int          index;        /* value index */
     IN  unsigned int offset;       /* offset for getting data */
@@ -1021,6 +1124,7 @@
 /* Delete a value of a registry key */
 struct delete_key_value_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* handle to registry key */
     IN  path_t       name;         /* value name */
 };
@@ -1029,6 +1133,7 @@
 /* Load a registry branch from a file */
 struct load_registry_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* root key to load to */
     IN  int          file;         /* file to load from */
     IN  path_t       name;         /* subkey name */
@@ -1038,6 +1143,7 @@
 /* Save a registry branch to a file */
 struct save_registry_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* key to save */
     IN  int          file;         /* file to save to */
 };
@@ -1046,6 +1152,7 @@
 /* Save a registry branch at server exit */
 struct save_registry_atexit_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* key to save */
     IN  char         file[1];      /* file to save to */
 };
@@ -1054,6 +1161,7 @@
 /* Set the current and saving level for the registry */
 struct set_registry_levels_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          current;      /* new current level */
     IN  int          saving;       /* new saving level */
     IN  int          period;       /* duration between periodic saves (milliseconds) */
@@ -1063,6 +1171,7 @@
 /* Create a waitable timer */
 struct create_timer_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          inherit;       /* inherit flag */
     IN  int          manual;        /* manual reset */
     OUT int          handle;        /* handle to the timer */
@@ -1073,6 +1182,7 @@
 /* Open a waitable timer */
 struct open_timer_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  unsigned int access;        /* wanted access rights */
     IN  int          inherit;       /* inherit flag */
     OUT int          handle;        /* handle to the timer */
@@ -1082,6 +1192,7 @@
 /* Set a waitable timer */
 struct set_timer_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the timer */
     IN  int          sec;           /* next expiration absolute time */
     IN  int          usec;          /* next expiration absolute time */
@@ -1093,6 +1204,7 @@
 /* Cancel a waitable timer */
 struct cancel_timer_request
 {
+    REQUEST_HEADER;                 /* request header */
     IN  int          handle;        /* handle to the timer */
 };
 
@@ -1100,6 +1212,7 @@
 /* Retrieve the current context of a thread */
 struct get_thread_context_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* thread handle */
     IN  unsigned int flags;        /* context flags */
     OUT CONTEXT      context;      /* thread context */
@@ -1109,6 +1222,7 @@
 /* Set the current context of a thread */
 struct set_thread_context_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* thread handle */
     IN  unsigned int flags;        /* context flags */
     IN  CONTEXT      context;      /* thread context */
@@ -1118,6 +1232,7 @@
 /* Fetch a selector entry for a thread */
 struct get_selector_entry_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int           handle;      /* thread handle */
     IN  int           entry;       /* LDT entry */
     OUT unsigned int  base;        /* selector base */
@@ -1129,6 +1244,7 @@
 /* Add an atom */
 struct add_atom_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int           local;       /* is atom in local process table? */
     OUT int           atom;        /* resulting atom */
     IN  WCHAR         name[1];     /* atom name */
@@ -1138,6 +1254,7 @@
 /* Delete an atom */
 struct delete_atom_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int           atom;        /* atom handle */
     IN  int           local;       /* is atom in local process table? */
 };
@@ -1146,6 +1263,7 @@
 /* Find an atom */
 struct find_atom_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          local;        /* is atom in local process table? */
     OUT int          atom;         /* atom handle */
     IN  WCHAR        name[1];      /* atom name */
@@ -1155,6 +1273,7 @@
 /* Get an atom name */
 struct get_atom_name_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          atom;         /* atom handle */
     IN  int          local;        /* is atom in local process table? */
     OUT int          count;        /* atom lock count */
@@ -1165,6 +1284,7 @@
 /* Init the process atom table */
 struct init_atom_table_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          entries;      /* number of entries */
 };
 
@@ -1172,12 +1292,14 @@
 /* Get the message queue of the current thread */
 struct get_msg_queue_request
 {
+    REQUEST_HEADER;                /* request header */
     OUT int          handle;       /* handle to the queue */
 };
 
 /* Wake up a message queue */
 struct wake_queue_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* handle to the queue */
     IN  unsigned int bits;         /* wake bits */
 };
@@ -1185,6 +1307,7 @@
 /* Wait for a process to start waiting on input */
 struct wait_input_idle_request
 {
+    REQUEST_HEADER;                /* request header */
     IN  int          handle;       /* process handle */
     IN  int          timeout;      /* timeout */
     OUT int          event;        /* handle to idle event */
@@ -1306,11 +1429,133 @@
     REQ_NB_REQUESTS
 };
 
-#define SERVER_PROTOCOL_VERSION 17
+union generic_request
+{
+    struct request_max_size max_size;
+    struct request_header header;
+    struct new_process_request new_process;
+    struct wait_process_request wait_process;
+    struct new_thread_request new_thread;
+    struct boot_done_request boot_done;
+    struct init_process_request init_process;
+    struct init_process_done_request init_process_done;
+    struct init_thread_request init_thread;
+    struct get_thread_buffer_request get_thread_buffer;
+    struct terminate_process_request terminate_process;
+    struct terminate_thread_request terminate_thread;
+    struct get_process_info_request get_process_info;
+    struct set_process_info_request set_process_info;
+    struct get_thread_info_request get_thread_info;
+    struct set_thread_info_request set_thread_info;
+    struct suspend_thread_request suspend_thread;
+    struct resume_thread_request resume_thread;
+    struct load_dll_request load_dll;
+    struct unload_dll_request unload_dll;
+    struct queue_apc_request queue_apc;
+    struct get_apc_request get_apc;
+    struct close_handle_request close_handle;
+    struct get_handle_info_request get_handle_info;
+    struct set_handle_info_request set_handle_info;
+    struct dup_handle_request dup_handle;
+    struct open_process_request open_process;
+    struct select_request select;
+    struct create_event_request create_event;
+    struct event_op_request event_op;
+    struct open_event_request open_event;
+    struct create_mutex_request create_mutex;
+    struct release_mutex_request release_mutex;
+    struct open_mutex_request open_mutex;
+    struct create_semaphore_request create_semaphore;
+    struct release_semaphore_request release_semaphore;
+    struct open_semaphore_request open_semaphore;
+    struct create_file_request create_file;
+    struct alloc_file_handle_request alloc_file_handle;
+    struct get_read_fd_request get_read_fd;
+    struct get_write_fd_request get_write_fd;
+    struct set_file_pointer_request set_file_pointer;
+    struct truncate_file_request truncate_file;
+    struct set_file_time_request set_file_time;
+    struct flush_file_request flush_file;
+    struct get_file_info_request get_file_info;
+    struct lock_file_request lock_file;
+    struct unlock_file_request unlock_file;
+    struct create_pipe_request create_pipe;
+    struct create_socket_request create_socket;
+    struct accept_socket_request accept_socket;
+    struct set_socket_event_request set_socket_event;
+    struct get_socket_event_request get_socket_event;
+    struct enable_socket_event_request enable_socket_event;
+    struct alloc_console_request alloc_console;
+    struct free_console_request free_console;
+    struct open_console_request open_console;
+    struct set_console_fd_request set_console_fd;
+    struct get_console_mode_request get_console_mode;
+    struct set_console_mode_request set_console_mode;
+    struct set_console_info_request set_console_info;
+    struct get_console_info_request get_console_info;
+    struct write_console_input_request write_console_input;
+    struct read_console_input_request read_console_input;
+    struct create_change_notification_request create_change_notification;
+    struct create_mapping_request create_mapping;
+    struct open_mapping_request open_mapping;
+    struct get_mapping_info_request get_mapping_info;
+    struct create_device_request create_device;
+    struct create_snapshot_request create_snapshot;
+    struct next_process_request next_process;
+    struct next_thread_request next_thread;
+    struct next_module_request next_module;
+    struct wait_debug_event_request wait_debug_event;
+    struct exception_event_request exception_event;
+    struct output_debug_string_request output_debug_string;
+    struct continue_debug_event_request continue_debug_event;
+    struct debug_process_request debug_process;
+    struct read_process_memory_request read_process_memory;
+    struct write_process_memory_request write_process_memory;
+    struct create_key_request create_key;
+    struct open_key_request open_key;
+    struct delete_key_request delete_key;
+    struct close_key_request close_key;
+    struct enum_key_request enum_key;
+    struct query_key_info_request query_key_info;
+    struct set_key_value_request set_key_value;
+    struct get_key_value_request get_key_value;
+    struct enum_key_value_request enum_key_value;
+    struct delete_key_value_request delete_key_value;
+    struct load_registry_request load_registry;
+    struct save_registry_request save_registry;
+    struct save_registry_atexit_request save_registry_atexit;
+    struct set_registry_levels_request set_registry_levels;
+    struct create_timer_request create_timer;
+    struct open_timer_request open_timer;
+    struct set_timer_request set_timer;
+    struct cancel_timer_request cancel_timer;
+    struct get_thread_context_request get_thread_context;
+    struct set_thread_context_request set_thread_context;
+    struct get_selector_entry_request get_selector_entry;
+    struct add_atom_request add_atom;
+    struct delete_atom_request delete_atom;
+    struct find_atom_request find_atom;
+    struct get_atom_name_request get_atom_name;
+    struct init_atom_table_request init_atom_table;
+    struct get_msg_queue_request get_msg_queue;
+    struct wake_queue_request wake_queue;
+    struct wait_input_idle_request wait_input_idle;
+};
+
+#define SERVER_PROTOCOL_VERSION 18
 
 /* ### make_requests end ### */
 /* Everything above this line is generated automatically by tools/make_requests */
 
+#undef REQUEST_HEADER
+#undef VARARG
+
+/* format of the server buffer */
+struct server_buffer_info
+{
+    volatile unsigned int cur_req;    /* offset of the current request */
+    volatile unsigned int cur_pos;    /* first available position in buffer */
+};
 
 /* client-side functions */
 
@@ -1318,12 +1563,14 @@
 
 #include "thread.h"
 #include "ntddk.h"
+#include "wine/exception.h"
 
 /* client communication functions */
 
 extern unsigned int server_call_noerr( enum request req );
 extern unsigned int server_call_fd( enum request req, int fd_out, int *fd_in );
 extern void server_protocol_error( const char *err, ... ) WINE_NORETURN;
+extern void *server_alloc_req( size_t fixed_size, size_t var_size );
 extern const char *get_config_dir(void);
 
 /* get a pointer to the request buffer */
@@ -1335,7 +1582,7 @@
 /* maximum remaining size in the server buffer */
 static inline int WINE_UNUSED server_remaining( const void *ptr )
 {
-    return (char *)NtCurrentTeb()->buffer + NtCurrentTeb()->buffer_size - (char *)ptr;
+    return (char *)NtCurrentTeb()->buffer_info - (char *)ptr;
 }
 
 /* do a server call and set the last error code */
@@ -1351,7 +1598,7 @@
 {
     if (src)
     {
-        WCHAR *end = (WCHAR *)((char *)NtCurrentTeb()->buffer + NtCurrentTeb()->buffer_size) - 1;
+        WCHAR *end = (WCHAR *)NtCurrentTeb()->buffer_info - 1;
         while ((dst < end) && *src) *dst++ = *src++;
     }
     *dst = 0;
@@ -1362,12 +1609,44 @@
 {
     if (src)
     {
-        WCHAR *end = (WCHAR *)((char *)NtCurrentTeb()->buffer + NtCurrentTeb()->buffer_size) - 1;
+        WCHAR *end = (WCHAR *)NtCurrentTeb()->buffer_info - 1;
         while ((dst < end) && *src) *dst++ = (WCHAR)(unsigned char)*src++;
     }
     *dst = 0;
 }
 
+/* get a pointer to the variable part of the request */
+inline static void *server_data_ptr( void *req )
+{
+    return (union generic_request *)req + 1;
+}
+
+
+/* exception support for server calls */
+
+extern DWORD server_exception_handler( PEXCEPTION_RECORD record, EXCEPTION_FRAME *frame,
+                                       CONTEXT *context, EXCEPTION_FRAME **pdispatcher );
+
+struct __server_exception_frame
+{
+    EXCEPTION_FRAME           frame;
+    struct server_buffer_info info;  /* saved buffer information */
+};
+
+#define SERVER_START_REQ \
+    do { \
+        struct __server_exception_frame __f; \
+        __f.frame.Handler = server_exception_handler; \
+        __f.info = *NtCurrentTeb()->buffer_info; \
+        __wine_push_frame( &__f.frame ); \
+        do {
+
+#define SERVER_END_REQ \
+        } while(0); \
+        *NtCurrentTeb()->buffer_info = __f.info; \
+        __wine_pop_frame( &__f.frame ); \
+    } while(0);
+
 extern int CLIENT_InitServer(void);
 extern int CLIENT_BootDone( int debug_level );
 extern int CLIENT_IsBootThread(void);
diff --git a/include/thread.h b/include/thread.h
index c120025..b0c6aeb 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -15,6 +15,7 @@
 struct __EXCEPTION_FRAME;
 struct _SECURITY_ATTRIBUTES;
 struct tagSYSLEVEL;
+struct server_buffer_info;
 
 /* Thread exception block
 
@@ -89,17 +90,16 @@
     DWORD        unknown6[5];    /* --n 1e8 Unknown */
 
     /* The following are Wine-specific fields (NT: GDI stuff) */
-    struct _TEB *next;           /* --3 1fc Global thread list */
-    DWORD        cleanup;        /* --3 200 Cleanup service handle */
-    int          socket;         /* --3 204 Socket for server communication */
-    void        *buffer;         /* --3 208 Buffer shared with server */
-    int          buffer_size;    /* --3 20c Size of server buffer */
-    void        *debug_info;     /* --3 210 Info for debugstr functions */
-    void        *pthread_data;   /* --3 214 Data for pthread emulation */
+    DWORD        cleanup;        /* --3 1fc Cleanup service handle */
+    int          socket;         /* --3 200 Socket for server communication */
+    void        *buffer;         /* --3 204 Buffer shared with server */
+    struct server_buffer_info *buffer_info;   /* --3 208 Buffer information */
+    void        *debug_info;     /* --3 20c Info for debugstr functions */
+    void        *pthread_data;   /* --3 210 Data for pthread emulation */
     /* here is plenty space for wine specific fields (don't forget to change pad6!!) */
 
     /* the following are nt specific fields */
-    DWORD        pad6[632];                  /* --n 218 */
+    DWORD        pad6[633];                  /* --n 214 */
     UNICODE_STRING StaticUnicodeString;      /* -2- bf8 used by advapi32 */
     USHORT       StaticUnicodeBuffer[261];   /* -2- c00 used by advapi32 */
     DWORD        pad7;                       /* --n e0c */
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;
 }
 
 
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 50ccc3c..5004c7f 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -105,7 +105,8 @@
     if (teb->socket != -1) close( teb->socket );
     if (teb->stack_sel) SELECTOR_FreeBlock( teb->stack_sel, 1 );
     SELECTOR_FreeBlock( teb->teb_sel, 1 );
-    if (teb->buffer) munmap( teb->buffer, teb->buffer_size );
+    if (teb->buffer) munmap( (void *)teb->buffer,
+                             (char *)(teb->buffer_info+1) - (char *)teb->buffer );
     if (teb->debug_info) HeapFree( GetProcessHeap(), 0, teb->debug_info );
     VirtualFree( teb->stack_base, 0, MEM_RELEASE );
 }
diff --git a/server/request.c b/server/request.c
index 3c619a4..9853e1e 100644
--- a/server/request.c
+++ b/server/request.c
@@ -129,11 +129,14 @@
 }
 
 /* call a request handler */
-static inline void call_req_handler( struct thread *thread, enum request req )
+static inline void call_req_handler( struct thread *thread )
 {
+    enum request req;
     current = thread;
     clear_error();
 
+    req = ((struct request_header *)current->buffer)->req;
+
     if (debug_level) trace_request( req );
 
     if (req < REQ_NB_REQUESTS)
@@ -165,7 +168,7 @@
 void read_request( struct thread *thread )
 {
     int ret;
-    enum request req;
+    char dummy[1];
 
 #ifdef HAVE_MSGHDR_ACCRIGHTS
     msghdr.msg_accrightslen = sizeof(int);
@@ -178,43 +181,42 @@
 
     assert( thread->pass_fd == -1 );
 
-    myiovec.iov_base = (void *)&req;
-    myiovec.iov_len  = sizeof(req);
+    myiovec.iov_base = dummy;
+    myiovec.iov_len  = 1;
 
     ret = recvmsg( thread->obj.fd, &msghdr, 0 );
 #ifndef HAVE_MSGHDR_ACCRIGHTS
     thread->pass_fd = cmsg.fd;
 #endif
 
-    if (ret == sizeof(req))
+    if (ret > 0)
     {
-        call_req_handler( thread, req );
+        call_req_handler( thread );
         thread->pass_fd = -1;
         return;
     }
-    if (ret == -1)
-    {
-        perror("recvmsg");
-        thread->exit_code = 1;
-        kill_thread( thread, 1 );
-        return;
-    }
     if (!ret)  /* closed pipe */
     {
         kill_thread( thread, 0 );
         return;
     }
-    fatal_protocol_error( thread, "partial message received %d/%d\n", ret, sizeof(req) );
+    perror("recvmsg");
+    thread->exit_code = 1;
+    kill_thread( thread, 1 );
 }
 
 /* send a message to a client that is ready to receive something */
 int write_request( struct thread *thread )
 {
     int ret;
+    struct request_header *header = thread->buffer;
+
+    header->error = thread->error;
 
     if (thread->pass_fd == -1)
     {
-        ret = write( thread->obj.fd, &thread->error, sizeof(thread->error) );
+        /* write a single byte; the value is ignored anyway */
+        ret = write( thread->obj.fd, header, 1 );
     }
     else  /* we have an fd to send */
     {
@@ -227,37 +229,28 @@
         cmsg.fd = thread->pass_fd;
 #endif  /* HAVE_MSGHDR_ACCRIGHTS */
 
-        myiovec.iov_base = (void *)&thread->error;
-        myiovec.iov_len  = sizeof(thread->error);
+        myiovec.iov_base = (void *)header;
+        myiovec.iov_len  = 1;
 
         ret = sendmsg( thread->obj.fd, &msghdr, 0 );
         close( thread->pass_fd );
         thread->pass_fd = -1;
     }
-    if (ret == sizeof(thread->error))
+    if (ret > 0)
     {
         set_select_events( &thread->obj, POLLIN );
         return 1;
     }
-    if (ret == -1)
+    if (errno == EWOULDBLOCK) return 0;  /* not a fatal error */
+    if (errno == EPIPE)
     {
-        if (errno == EWOULDBLOCK) return 0;  /* not a fatal error */
-        if (errno == EPIPE)
-        {
-            kill_thread( thread, 0 );  /* normal death */
-        }
-        else
-        {
-            perror("sendmsg");
-            thread->exit_code = 1;
-            kill_thread( thread, 1 );
-        }
+        kill_thread( thread, 0 );  /* normal death */
     }
     else
     {
+        perror("sendmsg");
         thread->exit_code = 1;
         kill_thread( thread, 1 );
-        fprintf( stderr, "Partial message sent %d/%d\n", ret, sizeof(thread->error) );
     }
     return -1;
 }
diff --git a/server/request.h b/server/request.h
index 3ad0d33..aa46902 100644
--- a/server/request.h
+++ b/server/request.h
@@ -48,17 +48,26 @@
     return thread->buffer;
 }
 
+/* get the request vararg data */
+inline static void *get_req_data( const void *req )
+{
+    return ((union generic_request *)req + 1);
+}
+
+
+#define REQUEST_END(req) ((char *)(req) + MAX_REQUEST_LENGTH - sizeof(struct server_buffer_info))
+
 /* get the remaining size in the request buffer for object of a given size */
 static inline int get_req_size( const void *req, const void *ptr, size_t typesize )
 {
-    return ((char *)req + MAX_REQUEST_LENGTH - (char *)ptr) / typesize;
+    return (REQUEST_END(req) - (char *)ptr) / typesize;
 }
 
 /* get the length of a request string, without going past the end of the request */
 static inline size_t get_req_strlen( const void *req, const char *str )
 {
     const char *p = str;
-    while (*p && (p < (char *)req + MAX_REQUEST_LENGTH - 1)) p++;
+    while (*p && (p < REQUEST_END(req) - 1)) p++;
     return p - str;
 }
 
@@ -66,7 +75,7 @@
 static inline size_t get_req_strlenW( const void *req, const WCHAR *str )
 {
     const WCHAR *p = str;
-    while (*p && (p < (WCHAR *)req + MAX_REQUEST_LENGTH/sizeof(WCHAR) - 1)) p++;
+    while (*p && (p < (WCHAR *)REQUEST_END(req) - 1)) p++;
     return p - str;
 }
 
diff --git a/server/thread.c b/server/thread.c
index c00e61e..c1b79fa 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -96,6 +96,7 @@
     if (ftruncate( fd, MAX_REQUEST_LENGTH ) == -1) goto error;
     if ((thread->buffer = mmap( 0, MAX_REQUEST_LENGTH, PROT_READ | PROT_WRITE,
                                 MAP_SHARED, fd, 0 )) == (void*)-1) goto error;
+    thread->buffer_info = (struct server_buffer_info *)((char *)thread->buffer + MAX_REQUEST_LENGTH) - 1;
     /* build the first request into the buffer and send it */
     req = thread->buffer;
     req->pid  = get_process_id( thread->process );
diff --git a/server/thread.h b/server/thread.h
index 7c9ae9e..f0f170b 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -59,6 +59,7 @@
     int                 affinity;  /* affinity mask */
     int                 suspend;   /* suspend count */
     void               *buffer;    /* buffer for communication with the client */
+    struct server_buffer_info *buffer_info;   /* buffer information structure */
     enum request        last_req;  /* last request received (for debugging) */
 };
 
diff --git a/server/trace.c b/server/trace.c
index 8774c81..34ff39c 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -787,7 +787,6 @@
 
 static void dump_free_console_request( const struct free_console_request *req )
 {
-    fprintf( stderr, " dummy=%d", req->dummy );
 }
 
 static void dump_open_console_request( const struct open_console_request *req )
diff --git a/tools/make_requests b/tools/make_requests
index e882e8a..fd5aed9 100755
--- a/tools/make_requests
+++ b/tools/make_requests
@@ -9,7 +9,6 @@
 %formats =
 (
     "int"           => "%d",
-    "long"          => "%ld",
     "char"          => "%c",
     "unsigned char" => "%02x",
     "unsigned int"  => "%08x",
@@ -70,8 +69,13 @@
 
 push @server_lines, "enum request\n{\n";
 foreach $req (@requests) { push @server_lines, "    REQ_\U$req,\n"; }
-push @server_lines, "    REQ_NB_REQUESTS\n};\n";
-push @server_lines, "\n#define SERVER_PROTOCOL_VERSION $protocol\n";
+push @server_lines, "    REQ_NB_REQUESTS\n};\n\n";
+push @server_lines, "union generic_request\n{\n";
+push @server_lines, "    struct request_max_size max_size;\n";
+push @server_lines, "    struct request_header header;\n";
+foreach $req (@requests) { push @server_lines, "    struct ${req}_request $req;\n"; }
+push @server_lines, "};\n\n";
+push @server_lines, "#define SERVER_PROTOCOL_VERSION $protocol\n";
 
 REPLACE_IN_FILE( "include/server.h", @server_lines );
 
@@ -98,6 +102,7 @@
     my $name = shift;
     my @in_struct = ();
     my @out_struct = ();
+    my $got_header = 0;
     while (<SERVER>)
     {
 	my ($dir, $type, $var);
@@ -105,14 +110,34 @@
         next if /^{$/;
 	s!/\*.*\*/!!g;
 	next if /^\s*$/;
-	/^\s*(IN|OUT)\s*(\w+\**(\s+\w+\**)*)\s+(\w+)(\[[1]\])?;/ or die "Unrecognized syntax $_";
-	$dir = $1;
-	$type = $2 . ($5 || "");
-	$var = $4;
-	die "Unrecognized type $type" unless (defined($formats{$type}) || $5);
+        if (/REQUEST_HEADER/)
+        {
+            die "Duplicated header" if $got_header;
+            die "Header must be first" if ($#in_struct != -1 || $#out_struct != -1);
+            $got_header++;
+            next;
+        }
+        if (/^\s*(IN|OUT)\s*VARARG\((\w+),(\w+)\)/)
+        {
+            $dir = $1;
+            $var = $2;
+            $type = "&" . $3;
+        }
+	elsif (/^\s*(IN|OUT)\s*(\w+\**(\s+\w+\**)*)\s+(\w+)(\[[1]\])?;/)
+        {
+            $dir = $1;
+            $type = $2 . ($5 || "");
+            $var = $4;
+            die "Unrecognized type $type" unless (defined($formats{$type}) || $5);
+        }
+        else
+        {
+            die "Unrecognized syntax $_";
+        }
 	if ($dir =~ /IN/) { push @in_struct, $type, $var; }
 	if ($dir =~ /OUT/) { push @out_struct, $type, $var; }
     }
+    die "Missing header" unless $got_header;
     push @requests, $name;
     &DO_DUMP_FUNC( $name, "request", @in_struct);
     if ($#out_struct >= 0)