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

diff --git a/server/console.c b/server/console.c
index a4792b8..4790f90 100644
--- a/server/console.c
+++ b/server/console.c
@@ -69,7 +69,7 @@
 static void screen_buffer_destroy( struct object *obj );
 
 /* common routine */
-static int console_get_info( struct object *obj, struct get_file_info_reply *reply );
+static int console_get_info( struct object *obj, struct get_file_info_request *req );
 
 static const struct object_ops console_input_ops =
 {
@@ -183,12 +183,11 @@
     return 1;
 }
 
-static int set_console_fd( int handle, int fd, int pid )
+static int set_console_fd( int handle, int fd_in, int fd_out, int pid )
 {
     struct console_input *input;
     struct screen_buffer *output;
     struct object *obj;
-    int fd_in, fd_out;
 
     if (!(obj = get_handle_obj( current->process, handle, 0, NULL )))
         return 0;
@@ -215,21 +214,6 @@
     assert( !input->obj.head );
     assert( !output->obj.head );
 
-    if ((fd_in = dup(fd)) == -1)
-    {
-        file_set_error();
-        release_object( input );
-        release_object( output );
-        return 0;
-    }
-    if ((fd_out = dup(fd)) == -1)
-    {
-        file_set_error();
-        close( fd_in );
-        release_object( input );
-        release_object( output );
-        return 0;
-    }
     unregister_select_user( &input->select );
     unregister_select_user( &output->select );
     close( input->select.fd );
@@ -244,25 +228,21 @@
     return 1;
 }
 
-static int get_console_mode( int handle, int *mode )
+static int get_console_mode( int handle )
 {
     struct object *obj;
     int ret = 0;
 
-    if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
-        return 0;
-    if (obj->ops == &console_input_ops)
+    if ((obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
     {
-        *mode = ((struct console_input *)obj)->mode;
-        ret = 1;
+        if (obj->ops == &console_input_ops)
+            ret = ((struct console_input *)obj)->mode;
+        else if (obj->ops == &screen_buffer_ops)
+            ret = ((struct screen_buffer *)obj)->mode;
+        else
+            set_error( ERROR_INVALID_HANDLE );
+        release_object( obj );
     }
-    else if (obj->ops == &screen_buffer_ops)
-    {
-        *mode = ((struct screen_buffer *)obj)->mode;
-        ret = 1;
-    }
-    else set_error( ERROR_INVALID_HANDLE );
-    release_object( obj );
     return ret;
 }
 
@@ -316,21 +296,6 @@
     return 1;
 }
 
-/* get misc console information (output handle only) */
-static int get_console_info( int handle, struct get_console_info_reply *reply, const char **title )
-{
-    struct screen_buffer *console;
-    if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle,
-                                                            GENERIC_READ, &screen_buffer_ops )))
-        return 0;
-    reply->cursor_size    = console->cursor_size;
-    reply->cursor_visible = console->cursor_visible;
-    reply->pid            = console->pid;
-    *title                = console->title;
-    release_object( console );
-    return 1;
-}
-
 /* add input events to a console input queue */
 static int write_console_input( int handle, int count, INPUT_RECORD *records )
 {
@@ -355,16 +320,16 @@
 }
 
 /* retrieve a pointer to the console input records */
-static int read_console_input( int handle, int count, int flush )
+static int read_console_input( int handle, int count, INPUT_RECORD *rec, int max, int flush )
 {
     struct console_input *console;
-    struct read_console_input_reply *reply = push_reply_data( current, sizeof(*reply) );
 
     if (!(console = (struct console_input *)get_handle_obj( current->process, handle,
                                                             GENERIC_READ, &console_input_ops )))
         return -1;
     if ((count < 0) || (count > console->recnum)) count = console->recnum;
-    add_reply_data( current, console->records, count * sizeof(INPUT_RECORD) );
+    if (count > max) count = max;
+    memcpy( rec, console->records, count * sizeof(INPUT_RECORD) );
     if (flush)
     {
         int i;
@@ -440,10 +405,18 @@
     return dup( console->select.fd );
 }
 
-static int console_get_info( struct object *obj, struct get_file_info_reply *reply )
+static int console_get_info( struct object *obj, struct get_file_info_request *req )
 {
-    memset( reply, 0, sizeof(*reply) );
-    reply->type = FILE_TYPE_CHAR;
+    req->type        = FILE_TYPE_CHAR;
+    req->attr        = 0;
+    req->access_time = 0;
+    req->write_time  = 0;
+    req->size_high   = 0;
+    req->size_low    = 0;
+    req->links       = 0;
+    req->index_high  = 0;
+    req->index_low   = 0;
+    req->serial      = 0;
     return 1;
 }
 
@@ -517,14 +490,12 @@
     unregister_select_user( &console->select );
     close( console->select.fd );
     if (console->input) console->input->output = NULL;
-    if (console->pid) kill( console->pid, SIGTERM );
     if (console->title) free( console->title );
 }
 
 /* allocate a console for the current process */
 DECL_HANDLER(alloc_console)
 {
-    struct alloc_console_reply *reply = push_reply_data( current, sizeof(*reply) );
     int in = -1, out = -1;
 
     if (!alloc_console( current->process )) goto done;
@@ -541,8 +512,8 @@
     free_console( current->process );
 
  done:
-    reply->handle_in  = in;
-    reply->handle_out = out;
+    req->handle_in  = in;
+    req->handle_out = out;
 }
 
 /* free the console of the current process */
@@ -554,40 +525,61 @@
 /* open a handle to the process console */
 DECL_HANDLER(open_console)
 {
-    struct open_console_reply *reply = push_reply_data( current, sizeof(*reply) );
     struct object *obj= req->output ? current->process->console_out : current->process->console_in;
 
-    if (obj) reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
+    if (obj) req->handle = alloc_handle( current->process, obj, req->access, req->inherit );
     else set_error( ERROR_ACCESS_DENIED );
 }
 
 /* set info about a console (output only) */
 DECL_HANDLER(set_console_info)
 {
-    size_t len = get_req_strlen();
-    set_console_info( req->handle, req, get_req_data( len + 1 ), len );
+    size_t len = get_req_strlen( req->title );
+    set_console_info( req->handle, req, req->title, len );
 }
 
 /* get info about a console (output only) */
 DECL_HANDLER(get_console_info)
 {
-    struct get_console_info_reply *reply = push_reply_data( current, sizeof(*reply) );
-    const char *title;
-    get_console_info( req->handle, reply, &title );
-    if (title) add_reply_data( current, title, strlen(title) + 1 );
+    struct screen_buffer *console;
+    if ((console = (struct screen_buffer *)get_handle_obj( current->process, req->handle,
+                                                           GENERIC_READ, &screen_buffer_ops )))
+    {
+        req->cursor_size    = console->cursor_size;
+        req->cursor_visible = console->cursor_visible;
+        req->pid            = console->pid;
+        strcpy( req->title, console->title ? console->title : "" );
+        release_object( console );
+    }
 }
 
 /* set a console fd */
 DECL_HANDLER(set_console_fd)
 {
-    set_console_fd( req->handle, fd, req->pid );
+    struct object *obj;
+    int fd_in, fd_out;
+
+    if (!(obj = get_handle_obj( current->process, req->file_handle,
+                                GENERIC_READ | GENERIC_WRITE, NULL ))) return;
+    if ((fd_in = obj->ops->get_read_fd( obj )) == -1)
+    {
+        release_object( obj );
+        return;
+    }
+    fd_out = obj->ops->get_write_fd( obj );
+    release_object( obj );
+    if (fd_out != -1)
+    {
+        if (set_console_fd( req->handle, fd_in, fd_out, req->pid )) return;
+        close( fd_out );
+    }
+    close( fd_in );
 }
 
 /* get a console mode (input or output) */
 DECL_HANDLER(get_console_mode)
 {
-    struct get_console_mode_reply *reply = push_reply_data( current, sizeof(*reply) );
-    get_console_mode( req->handle, &reply->mode );
+    req->mode = get_console_mode( req->handle );
 }
 
 /* set a console mode (input or output) */
@@ -599,18 +591,17 @@
 /* add input records to a console input queue */
 DECL_HANDLER(write_console_input)
 {
-    struct write_console_input_reply *reply = push_reply_data( current, sizeof(*reply) );
+    int max = get_req_size( req + 1, sizeof(INPUT_RECORD) );
+    int count = req->count;
 
-    if (check_req_data( req->count * sizeof(INPUT_RECORD)))
-    {
-        INPUT_RECORD *records = get_req_data( req->count * sizeof(INPUT_RECORD) );
-        reply->written = write_console_input( req->handle, req->count, records );
-    }
-    else fatal_protocol_error( "write_console_input: bad length" );
+    if (count > max) count = max;
+    req->written = write_console_input( req->handle, count, (INPUT_RECORD *)(req + 1) );
 }
 
 /* fetch input records from a console input queue */
 DECL_HANDLER(read_console_input)
 {
-    read_console_input( req->handle, req->count, req->flush );
+    int max = get_req_size( req + 1, sizeof(INPUT_RECORD) );
+    req->read = read_console_input( req->handle, req->count, (INPUT_RECORD *)(req + 1),
+                                    max, req->flush );
 }