Added beginnings of server-side file handling.
Added -debugmsg +server support.
Better server request dumping for varargs requests.

diff --git a/server/Makefile.in b/server/Makefile.in
index 1dfd55d..e1f28df 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -7,6 +7,7 @@
 
 C_SRCS = \
 	event.c \
+	file.c \
 	mutex.c \
 	object.c \
 	process.c \
diff --git a/server/event.c b/server/event.c
index 2483002..f1da91f 100644
--- a/server/event.c
+++ b/server/event.c
@@ -19,19 +19,19 @@
     int            signaled;        /* event has been signaled */
 };
 
-static void dump_event( struct object *obj, int verbose );
+static void event_dump( struct object *obj, int verbose );
 static int event_signaled( struct object *obj, struct thread *thread );
 static int event_satisfied( struct object *obj, struct thread *thread );
-static void destroy_event( struct object *obj );
+static void event_destroy( struct object *obj );
 
 static const struct object_ops event_ops =
 {
-    dump_event,
+    event_dump,
     add_queue,
     remove_queue,
     event_signaled,
     event_satisfied,
-    destroy_event
+    event_destroy
 };
 
 
@@ -96,7 +96,7 @@
     return 1;
 }
 
-static void dump_event( struct object *obj, int verbose )
+static void event_dump( struct object *obj, int verbose )
 {
     struct event *event = (struct event *)obj;
     assert( obj->ops == &event_ops );
@@ -119,7 +119,7 @@
     return 0;  /* Not abandoned */
 }
 
-static void destroy_event( struct object *obj )
+static void event_destroy( struct object *obj )
 {
     struct event *event = (struct event *)obj;
     assert( obj->ops == &event_ops );
diff --git a/server/file.c b/server/file.c
new file mode 100644
index 0000000..82319f3
--- /dev/null
+++ b/server/file.c
@@ -0,0 +1,195 @@
+/*
+ * Server-side file management
+ *
+ * Copyright (C) 1998 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "winerror.h"
+#include "winnt.h"
+#include "server/thread.h"
+
+struct file
+{
+    struct object  obj;             /* object header */
+    int            fd;              /* Unix file descriptor */
+    int            event;           /* possible events on this file */
+};
+
+static void file_dump( struct object *obj, int verbose );
+static void file_add_queue( struct object *obj, struct wait_queue_entry *entry );
+static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry );
+static int file_signaled( struct object *obj, struct thread *thread );
+static int file_satisfied( struct object *obj, struct thread *thread );
+static void file_destroy( struct object *obj );
+
+static const struct object_ops file_ops =
+{
+    file_dump,
+    file_add_queue,
+    file_remove_queue,
+    file_signaled,
+    file_satisfied,
+    file_destroy
+};
+
+static void file_event( int fd, int event, void *private );
+static void file_timeout( int fd, void *private );
+
+static const struct select_ops select_ops =
+{
+    file_event,
+    file_timeout
+};
+
+struct object *create_file( int fd )
+{
+    struct file *file;
+    int flags;
+
+    if ((flags = fcntl( fd, F_GETFL )) == -1)
+    {
+        perror( "fcntl" );
+        return NULL;
+    }
+    if (!(file = mem_alloc( sizeof(*file) ))) return NULL;
+    init_object( &file->obj, &file_ops, NULL );
+    file->fd = fd;
+    switch(flags & 3)
+    {
+    case O_RDONLY:
+        file->event = READ_EVENT;
+        break;
+    case O_WRONLY:
+        file->event = WRITE_EVENT;
+        break;
+    case O_RDWR:
+        file->event = READ_EVENT | WRITE_EVENT;
+        break;
+    }
+    CLEAR_ERROR();
+    return &file->obj;
+}
+
+static void file_dump( struct object *obj, int verbose )
+{
+    struct file *file = (struct file *)obj;
+    assert( obj->ops == &file_ops );
+    printf( "File fd=%d\n", file->fd );
+}
+
+static void file_add_queue( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct file *file = (struct file *)obj;
+    assert( obj->ops == &file_ops );
+    if (!obj->head)  /* first on the queue */
+        add_select_user( file->fd, READ_EVENT | WRITE_EVENT, &select_ops, file );
+    add_queue( obj, entry );
+}
+
+static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct file *file = (struct file *)grab_object(obj);
+    assert( obj->ops == &file_ops );
+
+    remove_queue( obj, entry );
+    if (!obj->head)  /* last on the queue is gone */
+        remove_select_user( file->fd );
+    release_object( obj );
+}
+
+static int file_signaled( struct object *obj, struct thread *thread )
+{
+    fd_set read_fds, write_fds;
+    struct timeval tv = { 0, 0 };
+
+    struct file *file = (struct file *)obj;
+    assert( obj->ops == &file_ops );
+
+    FD_ZERO( &read_fds );
+    FD_ZERO( &write_fds );
+    if (file->event & READ_EVENT) FD_SET( file->fd, &read_fds );
+    if (file->event & WRITE_EVENT) FD_SET( file->fd, &write_fds );
+    return select( file->fd + 1, &read_fds, &write_fds, NULL, &tv ) > 0;
+}
+
+static int file_satisfied( struct object *obj, struct thread *thread )
+{
+    /* Nothing to do */
+    return 0;  /* Not abandoned */
+}
+
+static void file_destroy( struct object *obj )
+{
+    struct file *file = (struct file *)obj;
+    assert( obj->ops == &file_ops );
+    close( file->fd );
+    free( file );
+}
+
+static void file_event( int fd, int event, void *private )
+{
+    struct file *file = (struct file *)private;
+    assert( file );
+
+    wake_up( &file->obj, 0 );
+}
+
+static void file_timeout( int fd, void *private )
+{
+    /* we never set a timeout on a file */
+    assert( 0 );
+}
+
+int file_get_unix_handle( int handle, unsigned int access )
+{
+    struct file *file;
+    int unix_handle;
+
+    if (!(file = (struct file *)get_handle_obj( current->process, handle,
+                                                access, &file_ops )))
+        return -1;
+    unix_handle = dup( file->fd );
+    release_object( file );
+    return unix_handle;
+}
+
+int get_file_info( int handle, struct get_file_info_reply *reply )
+{
+    struct file *file;
+    struct stat st;
+
+    if (!(file = (struct file *)get_handle_obj( current->process, handle,
+                                                0, &file_ops )))
+        return 0;
+    if (fstat( file->fd, &st ) == -1)
+    {
+        /* file_set_error(); */
+        release_object( file );
+        return 0;
+    }
+    if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY;
+    else reply->attr = FILE_ATTRIBUTE_ARCHIVE;
+    if (!(st.st_mode & S_IWUSR)) reply->attr |= FILE_ATTRIBUTE_READONLY;
+    reply->access_time = st.st_atime;
+    reply->write_time  = st.st_mtime;
+    reply->size_high   = 0;
+    reply->size_low    = S_ISDIR(st.st_mode) ? 0 : st.st_size;
+    reply->links       = st.st_nlink;
+    reply->index_high  = st.st_dev;
+    reply->index_low   = st.st_ino;
+    reply->serial      = 0; /* FIXME */
+    
+    release_object( file );
+    return 1;
+}
diff --git a/server/mutex.c b/server/mutex.c
index aee0771..375294f 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -22,19 +22,19 @@
     struct mutex  *prev;
 };
 
-static void dump_mutex( struct object *obj, int verbose );
+static void mutex_dump( struct object *obj, int verbose );
 static int mutex_signaled( struct object *obj, struct thread *thread );
 static int mutex_satisfied( struct object *obj, struct thread *thread );
-static void destroy_mutex( struct object *obj );
+static void mutex_destroy( struct object *obj );
 
 static const struct object_ops mutex_ops =
 {
-    dump_mutex,
+    mutex_dump,
     add_queue,
     remove_queue,
     mutex_signaled,
     mutex_satisfied,
-    destroy_mutex
+    mutex_destroy
 };
 
 
@@ -103,7 +103,7 @@
     }
 }
 
-static void dump_mutex( struct object *obj, int verbose )
+static void mutex_dump( struct object *obj, int verbose )
 {
     struct mutex *mutex = (struct mutex *)obj;
     assert( obj->ops == &mutex_ops );
@@ -136,7 +136,7 @@
     return 1;
 }
 
-static void destroy_mutex( struct object *obj )
+static void mutex_destroy( struct object *obj )
 {
     struct mutex *mutex = (struct mutex *)obj;
     assert( obj->ops == &mutex_ops );
diff --git a/server/process.c b/server/process.c
index 79b3833..da3f06c 100644
--- a/server/process.c
+++ b/server/process.c
@@ -54,21 +54,21 @@
 
 /* process operations */
 
-static void dump_process( struct object *obj, int verbose );
+static void process_dump( struct object *obj, int verbose );
 static int process_signaled( struct object *obj, struct thread *thread );
 static int process_satisfied( struct object *obj, struct thread *thread );
-static void destroy_process( struct object *obj );
+static void process_destroy( struct object *obj );
 static void free_handles( struct process *process );
 static int copy_handle_table( struct process *process, struct process *parent );
 
 static const struct object_ops process_ops =
 {
-    dump_process,
+    process_dump,
     add_queue,
     remove_queue,
     process_signaled,
     process_satisfied,
-    destroy_process
+    process_destroy
 };
 
 /* create a new process */
@@ -100,7 +100,7 @@
 }
 
 /* destroy a process when its refcount is 0 */
-static void destroy_process( struct object *obj )
+static void process_destroy( struct object *obj )
 {
     struct process *process = (struct process *)obj;
     assert( obj->ops == &process_ops );
@@ -116,7 +116,7 @@
 }
 
 /* dump a process on stdout for debugging purposes */
-static void dump_process( struct object *obj, int verbose )
+static void process_dump( struct object *obj, int verbose )
 {
     struct process *process = (struct process *)obj;
     assert( obj->ops == &process_ops );
diff --git a/server/request.c b/server/request.c
index 6ce5b35..4c14c48 100644
--- a/server/request.c
+++ b/server/request.c
@@ -152,6 +152,14 @@
     send_reply( current, -1, 0 );
 }
 
+/* set the debug level */
+DECL_HANDLER(set_debug)
+{
+    debug_level = req->level;
+    CLEAR_ERROR();
+    send_reply( current, -1, 0 );
+}
+
 /* terminate a process */
 DECL_HANDLER(terminate_process)
 {
@@ -372,3 +380,38 @@
     send_reply( current, -1, 1, &reply, sizeof(reply) );
 }
 
+/* create a file */
+DECL_HANDLER(create_file)
+{
+    struct create_file_reply reply = { -1 };
+    struct object *obj;
+    int new_fd;
+
+    if ((new_fd = dup(fd)) == -1)
+    {
+        SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
+        goto done;
+    }
+    if ((obj = create_file( new_fd )) != NULL)
+    {
+        reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
+        release_object( obj );
+    }
+ done:
+    send_reply( current, -1, 1, &reply, sizeof(reply) );
+}
+
+/* get a Unix handle to a file */
+DECL_HANDLER(get_unix_handle)
+{
+    int handle = file_get_unix_handle( req->handle, req->access );
+    send_reply( current, handle, 0 );
+}
+
+/* get a file information */
+DECL_HANDLER(get_file_info)
+{
+    struct get_file_info_reply reply;
+    get_file_info( req->handle, &reply );
+    send_reply( current, -1, 1, &reply, sizeof(reply) );
+}
diff --git a/server/semaphore.c b/server/semaphore.c
index 2753d96..cd77d16 100644
--- a/server/semaphore.c
+++ b/server/semaphore.c
@@ -19,19 +19,19 @@
     unsigned int   max;    /* maximum possible count */
 };
 
-static void dump_semaphore( struct object *obj, int verbose );
+static void semaphore_dump( struct object *obj, int verbose );
 static int semaphore_signaled( struct object *obj, struct thread *thread );
 static int semaphore_satisfied( struct object *obj, struct thread *thread );
-static void destroy_semaphore( struct object *obj );
+static void semaphore_destroy( struct object *obj );
 
 static const struct object_ops semaphore_ops =
 {
-    dump_semaphore,
+    semaphore_dump,
     add_queue,
     remove_queue,
     semaphore_signaled,
     semaphore_satisfied,
-    destroy_semaphore
+    semaphore_destroy
 };
 
 
@@ -89,7 +89,7 @@
     return 1;
 }
 
-static void dump_semaphore( struct object *obj, int verbose )
+static void semaphore_dump( struct object *obj, int verbose )
 {
     struct semaphore *sem = (struct semaphore *)obj;
     assert( obj->ops == &semaphore_ops );
@@ -112,7 +112,7 @@
     return 0;  /* not abandoned */
 }
 
-static void destroy_semaphore( struct object *obj )
+static void semaphore_destroy( struct object *obj )
 {
     struct semaphore *sem = (struct semaphore *)obj;
     assert( obj->ops == &semaphore_ops );
diff --git a/server/trace.c b/server/trace.c
index 0850fd5..1dc815c 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -6,64 +6,81 @@
 #include "server.h"
 #include "server/thread.h"
 
-static void dump_new_thread_request( struct new_thread_request *req )
+static int dump_new_thread_request( struct new_thread_request *req, int len )
 {
     printf( " pid=%p", req->pid );
+    return (int)sizeof(*req);
 }
 
-static void dump_new_thread_reply( struct new_thread_reply *req )
+static int dump_new_thread_reply( struct new_thread_reply *req, int len )
 {
     printf( " tid=%p,", req->tid );
     printf( " thandle=%d,", req->thandle );
     printf( " pid=%p,", req->pid );
     printf( " phandle=%d", req->phandle );
+    return (int)sizeof(*req);
 }
 
-static void dump_init_thread_request( struct init_thread_request *req )
+static int dump_set_debug_request( struct set_debug_request *req, int len )
 {
-    printf( " unix_pid=%d", req->unix_pid );
+    printf( " level=%d", req->level );
+    return (int)sizeof(*req);
 }
 
-static void dump_terminate_process_request( struct terminate_process_request *req )
+static int dump_init_thread_request( struct init_thread_request *req, int len )
+{
+    printf( " unix_pid=%d,", req->unix_pid );
+    printf( " cmd_line=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) );
+    return len;
+}
+
+static int dump_terminate_process_request( struct terminate_process_request *req, int len )
 {
     printf( " handle=%d,", req->handle );
     printf( " exit_code=%d", req->exit_code );
+    return (int)sizeof(*req);
 }
 
-static void dump_terminate_thread_request( struct terminate_thread_request *req )
+static int dump_terminate_thread_request( struct terminate_thread_request *req, int len )
 {
     printf( " handle=%d,", req->handle );
     printf( " exit_code=%d", req->exit_code );
+    return (int)sizeof(*req);
 }
 
-static void dump_get_process_info_request( struct get_process_info_request *req )
+static int dump_get_process_info_request( struct get_process_info_request *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
 }
 
-static void dump_get_process_info_reply( struct get_process_info_reply *req )
+static int dump_get_process_info_reply( struct get_process_info_reply *req, int len )
 {
     printf( " pid=%p,", req->pid );
     printf( " exit_code=%d", req->exit_code );
+    return (int)sizeof(*req);
 }
 
-static void dump_get_thread_info_request( struct get_thread_info_request *req )
+static int dump_get_thread_info_request( struct get_thread_info_request *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
 }
 
-static void dump_get_thread_info_reply( struct get_thread_info_reply *req )
+static int dump_get_thread_info_reply( struct get_thread_info_reply *req, int len )
 {
     printf( " pid=%p,", req->pid );
     printf( " exit_code=%d", req->exit_code );
+    return (int)sizeof(*req);
 }
 
-static void dump_close_handle_request( struct close_handle_request *req )
+static int dump_close_handle_request( struct close_handle_request *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
 }
 
-static void dump_dup_handle_request( struct dup_handle_request *req )
+static int dump_dup_handle_request( struct dup_handle_request *req, int len )
 {
     printf( " src_process=%d,", req->src_process );
     printf( " src_handle=%d,", req->src_handle );
@@ -72,171 +89,222 @@
     printf( " access=%08x,", req->access );
     printf( " inherit=%d,", req->inherit );
     printf( " options=%d", req->options );
+    return (int)sizeof(*req);
 }
 
-static void dump_dup_handle_reply( struct dup_handle_reply *req )
+static int dump_dup_handle_reply( struct dup_handle_reply *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
 }
 
-static void dump_open_process_request( struct open_process_request *req )
+static int dump_open_process_request( struct open_process_request *req, int len )
 {
     printf( " pid=%p,", req->pid );
     printf( " access=%08x,", req->access );
     printf( " inherit=%d", req->inherit );
+    return (int)sizeof(*req);
 }
 
-static void dump_open_process_reply( struct open_process_reply *req )
+static int dump_open_process_reply( struct open_process_reply *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
 }
 
-static void dump_select_request( struct select_request *req )
+static int dump_select_request( struct select_request *req, int len )
 {
     printf( " count=%d,", req->count );
     printf( " flags=%d,", req->flags );
     printf( " timeout=%d", req->timeout );
+    return (int)sizeof(*req);
 }
 
-static void dump_select_reply( struct select_reply *req )
+static int dump_select_reply( struct select_reply *req, int len )
 {
     printf( " signaled=%d", req->signaled );
+    return (int)sizeof(*req);
 }
 
-static void dump_create_event_request( struct create_event_request *req )
+static int dump_create_event_request( struct create_event_request *req, int len )
 {
     printf( " manual_reset=%d,", req->manual_reset );
     printf( " initial_state=%d,", req->initial_state );
-    printf( " inherit=%d", req->inherit );
+    printf( " inherit=%d,", req->inherit );
+    printf( " name=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) );
+    return len;
 }
 
-static void dump_create_event_reply( struct create_event_reply *req )
+static int dump_create_event_reply( struct create_event_reply *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
 }
 
-static void dump_event_op_request( struct event_op_request *req )
+static int dump_event_op_request( struct event_op_request *req, int len )
 {
     printf( " handle=%d,", req->handle );
     printf( " op=%d", req->op );
+    return (int)sizeof(*req);
 }
 
-static void dump_create_mutex_request( struct create_mutex_request *req )
+static int dump_create_mutex_request( struct create_mutex_request *req, int len )
 {
     printf( " owned=%d,", req->owned );
-    printf( " inherit=%d", req->inherit );
+    printf( " inherit=%d,", req->inherit );
+    printf( " name=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) );
+    return len;
 }
 
-static void dump_create_mutex_reply( struct create_mutex_reply *req )
+static int dump_create_mutex_reply( struct create_mutex_reply *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
 }
 
-static void dump_release_mutex_request( struct release_mutex_request *req )
+static int dump_release_mutex_request( struct release_mutex_request *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
 }
 
-static void dump_create_semaphore_request( struct create_semaphore_request *req )
+static int dump_create_semaphore_request( struct create_semaphore_request *req, int len )
 {
     printf( " initial=%08x,", req->initial );
     printf( " max=%08x,", req->max );
     printf( " inherit=%d", req->inherit );
+    return (int)sizeof(*req);
 }
 
-static void dump_create_semaphore_reply( struct create_semaphore_reply *req )
+static int dump_create_semaphore_reply( struct create_semaphore_reply *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
 }
 
-static void dump_release_semaphore_request( struct release_semaphore_request *req )
+static int dump_release_semaphore_request( struct release_semaphore_request *req, int len )
 {
     printf( " handle=%d,", req->handle );
     printf( " count=%08x", req->count );
+    return (int)sizeof(*req);
 }
 
-static void dump_release_semaphore_reply( struct release_semaphore_reply *req )
+static int dump_release_semaphore_reply( struct release_semaphore_reply *req, int len )
 {
     printf( " prev_count=%08x", req->prev_count );
+    return (int)sizeof(*req);
 }
 
-static void dump_open_named_obj_request( struct open_named_obj_request *req )
+static int dump_open_named_obj_request( struct open_named_obj_request *req, int len )
 {
     printf( " type=%d,", req->type );
     printf( " access=%08x,", req->access );
     printf( " inherit=%d", req->inherit );
+    return (int)sizeof(*req);
 }
 
-static void dump_open_named_obj_reply( struct open_named_obj_reply *req )
+static int dump_open_named_obj_reply( struct open_named_obj_reply *req, int len )
 {
     printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
+}
+
+static int dump_create_file_request( struct create_file_request *req, int len )
+{
+    printf( " access=%08x,", req->access );
+    printf( " inherit=%d", req->inherit );
+    return (int)sizeof(*req);
+}
+
+static int dump_create_file_reply( struct create_file_reply *req, int len )
+{
+    printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
+}
+
+static int dump_get_unix_handle_request( struct get_unix_handle_request *req, int len )
+{
+    printf( " handle=%d,", req->handle );
+    printf( " access=%08x", req->access );
+    return (int)sizeof(*req);
+}
+
+static int dump_get_file_info_request( struct get_file_info_request *req, int len )
+{
+    printf( " handle=%d", req->handle );
+    return (int)sizeof(*req);
+}
+
+static int dump_get_file_info_reply( struct get_file_info_reply *req, int len )
+{
+    printf( " attr=%d,", req->attr );
+    printf( " access_time=%ld,", req->access_time );
+    printf( " write_time=%ld,", req->write_time );
+    printf( " size_high=%d,", req->size_high );
+    printf( " size_low=%d,", req->size_low );
+    printf( " links=%d,", req->links );
+    printf( " index_high=%d,", req->index_high );
+    printf( " index_low=%d,", req->index_low );
+    printf( " serial=%08x", req->serial );
+    return (int)sizeof(*req);
 }
 
 struct dumper
 {
-    void (*dump_req)();
-    void (*dump_reply)();
-    unsigned int size;
+    int (*dump_req)( void *data, int len );
+    void (*dump_reply)( void *data );
 };
 
 static const struct dumper dumpers[REQ_NB_REQUESTS] =
 {
-    { (void(*)())dump_new_thread_request,
-      (void(*)())dump_new_thread_reply,
-      sizeof(struct new_thread_request) },
-    { (void(*)())dump_init_thread_request,
-      (void(*)())0,
-      sizeof(struct init_thread_request) },
-    { (void(*)())dump_terminate_process_request,
-      (void(*)())0,
-      sizeof(struct terminate_process_request) },
-    { (void(*)())dump_terminate_thread_request,
-      (void(*)())0,
-      sizeof(struct terminate_thread_request) },
-    { (void(*)())dump_get_process_info_request,
-      (void(*)())dump_get_process_info_reply,
-      sizeof(struct get_process_info_request) },
-    { (void(*)())dump_get_thread_info_request,
-      (void(*)())dump_get_thread_info_reply,
-      sizeof(struct get_thread_info_request) },
-    { (void(*)())dump_close_handle_request,
-      (void(*)())0,
-      sizeof(struct close_handle_request) },
-    { (void(*)())dump_dup_handle_request,
-      (void(*)())dump_dup_handle_reply,
-      sizeof(struct dup_handle_request) },
-    { (void(*)())dump_open_process_request,
-      (void(*)())dump_open_process_reply,
-      sizeof(struct open_process_request) },
-    { (void(*)())dump_select_request,
-      (void(*)())dump_select_reply,
-      sizeof(struct select_request) },
-    { (void(*)())dump_create_event_request,
-      (void(*)())dump_create_event_reply,
-      sizeof(struct create_event_request) },
-    { (void(*)())dump_event_op_request,
-      (void(*)())0,
-      sizeof(struct event_op_request) },
-    { (void(*)())dump_create_mutex_request,
-      (void(*)())dump_create_mutex_reply,
-      sizeof(struct create_mutex_request) },
-    { (void(*)())dump_release_mutex_request,
-      (void(*)())0,
-      sizeof(struct release_mutex_request) },
-    { (void(*)())dump_create_semaphore_request,
-      (void(*)())dump_create_semaphore_reply,
-      sizeof(struct create_semaphore_request) },
-    { (void(*)())dump_release_semaphore_request,
-      (void(*)())dump_release_semaphore_reply,
-      sizeof(struct release_semaphore_request) },
-    { (void(*)())dump_open_named_obj_request,
-      (void(*)())dump_open_named_obj_reply,
-      sizeof(struct open_named_obj_request) },
+    { (int(*)(void *,int))dump_new_thread_request,
+      (void(*)())dump_new_thread_reply },
+    { (int(*)(void *,int))dump_set_debug_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_init_thread_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_terminate_process_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_terminate_thread_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_get_process_info_request,
+      (void(*)())dump_get_process_info_reply },
+    { (int(*)(void *,int))dump_get_thread_info_request,
+      (void(*)())dump_get_thread_info_reply },
+    { (int(*)(void *,int))dump_close_handle_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_dup_handle_request,
+      (void(*)())dump_dup_handle_reply },
+    { (int(*)(void *,int))dump_open_process_request,
+      (void(*)())dump_open_process_reply },
+    { (int(*)(void *,int))dump_select_request,
+      (void(*)())dump_select_reply },
+    { (int(*)(void *,int))dump_create_event_request,
+      (void(*)())dump_create_event_reply },
+    { (int(*)(void *,int))dump_event_op_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_create_mutex_request,
+      (void(*)())dump_create_mutex_reply },
+    { (int(*)(void *,int))dump_release_mutex_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_create_semaphore_request,
+      (void(*)())dump_create_semaphore_reply },
+    { (int(*)(void *,int))dump_release_semaphore_request,
+      (void(*)())dump_release_semaphore_reply },
+    { (int(*)(void *,int))dump_open_named_obj_request,
+      (void(*)())dump_open_named_obj_reply },
+    { (int(*)(void *,int))dump_create_file_request,
+      (void(*)())dump_create_file_reply },
+    { (int(*)(void *,int))dump_get_unix_handle_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_get_file_info_request,
+      (void(*)())dump_get_file_info_reply },
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] =
 {
     "new_thread",
+    "set_debug",
     "init_thread",
     "terminate_process",
     "terminate_thread",
@@ -253,17 +321,20 @@
     "create_semaphore",
     "release_semaphore",
     "open_named_obj",
+    "create_file",
+    "get_unix_handle",
+    "get_file_info",
 };
 
 void trace_request( enum request req, void *data, int len, int fd )
 {
+    int size;
     current->last_req = req;
     printf( "%08x: %s(", (unsigned int)current, req_names[req] );
-    dumpers[req].dump_req( data );
-    if (len > dumpers[req].size)
+    size = dumpers[req].dump_req( data, len );
+    if ((len -= size) > 0)
     {
-        unsigned char *ptr = (unsigned char *)data + dumpers[req].size;
-	len -= dumpers[req].size;
+        unsigned char *ptr = (unsigned char *)data + size;
         while (len--) printf( ", %02x", *ptr++ );
     }
     if (fd != -1) printf( " ) fd=%d\n", fd );