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

diff --git a/files/dos_fs.c b/files/dos_fs.c
index 0919d03..2120131 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -649,7 +649,7 @@
 			return handle;
 		}
 		if (!strcmp(DOSFS_Devices[i].name,"SCSIMGR$")) {
-		        if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
+		        if ((handle = FILE_Alloc( &file, -1 )) == INVALID_HANDLE_VALUE32)
 				return HFILE_ERROR32;
 			else {
 				file->unix_name = HEAP_strdupA( SystemHeap, 0, name );
@@ -657,7 +657,7 @@
 			}
 		}
                 if (!strcmp(DOSFS_Devices[i].name,"HPSCAN")) {
-                        if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
+                        if ((handle = FILE_Alloc( &file, -1 )) == INVALID_HANDLE_VALUE32)
                                 return HFILE_ERROR32;
                         else {
                                 file->unix_name = HEAP_strdupA( SystemHeap, 0, name );
diff --git a/files/file.c b/files/file.c
index 6a5cac0..779c41b 100644
--- a/files/file.c
+++ b/files/file.c
@@ -38,6 +38,9 @@
 #include "async.h"
 #include "debug.h"
 
+#include "server/request.h"
+#include "server.h"
+
 #if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
 #define MAP_ANON MAP_ANONYMOUS
 #endif
@@ -80,29 +83,42 @@
 /***********************************************************************
  *           FILE_Alloc
  *
- * Allocate a file.
+ * Allocate a file. The unix_handle is closed.
  */
-HFILE32 FILE_Alloc( FILE_OBJECT **file )
+HFILE32 FILE_Alloc( FILE_OBJECT **file, int unix_handle )
 {
     HFILE32 handle;
+    struct create_file_request req;
+    struct create_file_reply reply;
+    int len;
+    int fd = dup(unix_handle);
+
+    req.access = FILE_ALL_ACCESS | GENERIC_READ |
+                 GENERIC_WRITE | GENERIC_EXECUTE;  /* FIXME */
+    req.inherit = 1;  /* FIXME */
+    CLIENT_SendRequest( REQ_CREATE_FILE, unix_handle, 1, &req, sizeof(req) );
+    CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
+    CHECK_LEN( len, sizeof(reply) );
+    if (reply.handle == -1) return INVALID_HANDLE_VALUE32;
+
     *file = HeapAlloc( SystemHeap, 0, sizeof(FILE_OBJECT) );
     if (!*file)
     {
         DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
+        CLIENT_CloseHandle( reply.handle );
         return (HFILE32)NULL;
     }
     (*file)->header.type = K32OBJ_FILE;
     (*file)->header.refcount = 0;
-    (*file)->unix_handle = -1;
     (*file)->unix_name = NULL;
+    (*file)->unix_handle = fd;
     (*file)->type = FILE_TYPE_DISK;
     (*file)->pos = 0;
     (*file)->mode = 0;
     (*file)->wait_queue = NULL;
 
-    handle = HANDLE_Alloc( PROCESS_Current(), &(*file)->header,
-                           FILE_ALL_ACCESS | GENERIC_READ |
-                           GENERIC_WRITE | GENERIC_EXECUTE /*FIXME*/, TRUE, -1 );
+    handle = HANDLE_Alloc( PROCESS_Current(), &(*file)->header, req.access,
+                           req.inherit, reply.handle );
     /* If the allocation failed, the object is already destroyed */
     if (handle == INVALID_HANDLE_VALUE32) *file = NULL;
     return handle;
@@ -111,6 +127,7 @@
 /***********************************************************************
  *		FILE_async_handler			[internal]
  */
+#if 1
 static void
 FILE_async_handler(int unixfd,void *private) {
 	FILE_OBJECT *file = (FILE_OBJECT*)private;
@@ -157,6 +174,7 @@
 {
 	return FALSE; /* not abandoned. Hmm? */
 }
+#endif
 
 /* FIXME: lpOverlapped is ignored */
 static BOOL32 FILE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
@@ -241,7 +259,6 @@
 
     DOS_RemoveFileLocks(file);
 
-    if (file->unix_handle != -1) close( file->unix_handle );
     if (file->unix_name) HeapFree( SystemHeap, 0, file->unix_name );
     ptr->type = K32OBJ_UNKNOWN;
     HeapFree( SystemHeap, 0, file );
@@ -254,10 +271,11 @@
  * Return the DOS file associated to a task file handle. FILE_ReleaseFile must
  * be called to release the file.
  */
-FILE_OBJECT *FILE_GetFile( HFILE32 handle )
+FILE_OBJECT *FILE_GetFile( HFILE32 handle, DWORD access, int *server_handle )
 {
     return (FILE_OBJECT *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
-                                            K32OBJ_FILE, 0 /*FIXME*/, NULL );
+                                            K32OBJ_FILE, access,
+                                            server_handle );
 }
 
 
@@ -276,16 +294,22 @@
  *           FILE_GetUnixHandle
  *
  * Return the Unix handle associated to a file handle.
+ * The Unix handle must be closed after use.
  */
-int FILE_GetUnixHandle( HFILE32 hFile )
+int FILE_GetUnixHandle( HFILE32 hFile, DWORD access )
 {
     FILE_OBJECT *file;
-    int ret;
+    int unix_handle;
+    struct get_unix_handle_request req;
 
-    if (!(file = FILE_GetFile( hFile ))) return -1;
-    ret = file->unix_handle;
-    FILE_ReleaseFile( file );
-    return ret;
+    file = (FILE_OBJECT *)HANDLE_GetObjPtr( PROCESS_Current(), hFile,
+                                            K32OBJ_FILE, access, &req.handle );
+    if (!file) return -1;
+    req.access = access;
+    CLIENT_SendRequest( REQ_GET_UNIX_HANDLE, -1, 1, &req, sizeof(req) );
+    CLIENT_WaitReply( NULL, &unix_handle, 0 );
+    K32OBJ_DecCount( &file->header );
+    return unix_handle;
 }
 
 /***********************************************************************
@@ -526,7 +550,7 @@
   if (!pdb) return 0;
   for (i=0;i<pdb->nbFiles;i++)
     {
-      file =FILE_GetFile( (HFILE32) i);
+      file =FILE_GetFile( (HFILE32)i, 0, NULL );
       if(file)
        {
          if(file->unix_name)
@@ -610,19 +634,15 @@
  */
 HFILE32 FILE_DupUnixHandle( int fd )
 {
-    HFILE32 handle;
+    int unix_handle;
     FILE_OBJECT *file;
 
-    if ((handle = FILE_Alloc( &file )) != INVALID_HANDLE_VALUE32)
+    if ((unix_handle = dup(fd)) == -1)
     {
-        if ((file->unix_handle = dup(fd)) == -1)
-        {
-            FILE_SetDosError();
-            CloseHandle( handle );
-            return INVALID_HANDLE_VALUE32;
-        }
+        FILE_SetDosError();
+        return INVALID_HANDLE_VALUE32;
     }
-    return handle;
+    return FILE_Alloc( &file, unix_handle );
 }
 
 
@@ -632,32 +652,31 @@
 HFILE32 FILE_OpenUnixFile( const char *name, int mode )
 {
     HFILE32 handle;
+    int unix_handle;
     FILE_OBJECT *file;
     struct stat st;
 
-    if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
-        return INVALID_HANDLE_VALUE32;
-
-    if ((file->unix_handle = open( name, mode, 0666 )) == -1)
+    if ((unix_handle = open( name, mode, 0666 )) == -1)
     {
         if (!Options.failReadOnly && (mode == O_RDWR))
-            file->unix_handle = open( name, O_RDONLY );
+            unix_handle = open( name, O_RDONLY );
     }
-    if ((file->unix_handle == -1) || (fstat( file->unix_handle, &st ) == -1))
+    if ((unix_handle == -1) || (fstat( unix_handle, &st ) == -1))
     {
         FILE_SetDosError();
-        CloseHandle( handle );
         return INVALID_HANDLE_VALUE32;
     }
     if (S_ISDIR(st.st_mode))
     {
         DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
-        CloseHandle( handle );
+        close( unix_handle );
         return INVALID_HANDLE_VALUE32;
     }
 
     /* File opened OK, now fill the FILE_OBJECT */
 
+    if ((handle = FILE_Alloc( &file, unix_handle )) == INVALID_HANDLE_VALUE32)
+        return INVALID_HANDLE_VALUE32;
     file->unix_name = HEAP_strdupA( SystemHeap, 0, name );
     return handle;
 }
@@ -716,7 +735,7 @@
       }
     hFileRet = FILE_OpenUnixFile( unixName, mode );
     /* we need to save the mode, but only if it is not in use yet*/
-    if ((hFileRet) && (!fileInUse) && ((file =FILE_GetFile(hFileRet))))
+    if ((hFileRet) && (!fileInUse) && ((file =FILE_GetFile(hFileRet, 0, NULL))))
       {
        file->mode=dosMode;
        FILE_ReleaseFile(file);
@@ -732,6 +751,7 @@
 static HFILE32 FILE_Create( LPCSTR path, int mode, int unique )
 {
     HFILE32 handle;
+    int unix_handle;
     FILE_OBJECT *file;
     DOS_FULL_NAME full_name;
     BOOL32 fileInUse = FALSE;
@@ -749,14 +769,7 @@
         return INVALID_HANDLE_VALUE32;
     }
 
-    if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
-        return INVALID_HANDLE_VALUE32;
-
-    if (!DOSFS_GetFullName( path, FALSE, &full_name ))
-    {
-        CloseHandle( handle );
-        return INVALID_HANDLE_VALUE32;
-    }
+    if (!DOSFS_GetFullName( path, FALSE, &full_name )) return INVALID_HANDLE_VALUE32;
     
     dosMode = FILE_UnixToDosMode(mode);
     fileInUse = FILE_InUse(full_name.long_name,&oldMode);
@@ -766,17 +779,18 @@
 	if (FILE_ShareDeny(dosMode,oldMode)) return INVALID_HANDLE_VALUE32;
       }
     
-    if ((file->unix_handle = open( full_name.long_name,
+    if ((unix_handle = open( full_name.long_name,
                            O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0),
                            mode )) == -1)
     {
         FILE_SetDosError();
-        CloseHandle( handle );
         return INVALID_HANDLE_VALUE32;
     } 
 
     /* File created OK, now fill the FILE_OBJECT */
 
+    if ((handle = FILE_Alloc( &file, unix_handle )) == INVALID_HANDLE_VALUE32)
+        return INVALID_HANDLE_VALUE32;
     file->unix_name = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
     file->mode = dosMode;
     return handle;
@@ -838,20 +852,28 @@
                                          BY_HANDLE_FILE_INFORMATION *info )
 {
     FILE_OBJECT *file;
-    DWORD ret = 0;
-    struct stat st;
+    struct get_file_info_request req;
+    struct get_file_info_reply reply;
+    int len;
 
     if (!info) return 0;
-
-    if (!(file = FILE_GetFile( hFile ))) return 0;
-    if (fstat( file->unix_handle, &st ) == -1) FILE_SetDosError();
-    else
-    {
-        FILE_FillInfo( &st, info );
-        ret = 1;
-    }
+    if (!(file = FILE_GetFile( hFile, 0, &req.handle ))) return 0;
+    CLIENT_SendRequest( REQ_GET_FILE_INFO, -1, 1, &req, sizeof(req) );
+    CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
+    CHECK_LEN( len, sizeof(reply) );
     FILE_ReleaseFile( file );
-    return ret;
+
+    DOSFS_UnixTimeToFileTime( reply.write_time, &info->ftCreationTime, 0 );
+    DOSFS_UnixTimeToFileTime( reply.write_time, &info->ftLastWriteTime, 0 );
+    DOSFS_UnixTimeToFileTime( reply.access_time, &info->ftLastAccessTime, 0 );
+    info->dwFileAttributes     = reply.attr;
+    info->dwVolumeSerialNumber = reply.serial;
+    info->nFileSizeHigh        = reply.size_high;
+    info->nFileSizeLow         = reply.size_low;
+    info->nNumberOfLinks       = reply.links;
+    info->nFileIndexHigh       = reply.index_high;
+    info->nFileIndexLow        = reply.index_low;
+    return 1;
 }
 
 
@@ -966,7 +988,7 @@
 
     TRACE(file, "FILE_Dup2 for handle %d\n", hFile1 );
     /* FIXME: should use DuplicateHandle */
-    if (!(file = FILE_GetFile( hFile1 ))) return HFILE_ERROR32;
+    if (!(file = FILE_GetFile( hFile1, 0, NULL ))) return HFILE_ERROR32;
     if (!HANDLE_SetObjPtr( PROCESS_Current(), hFile2, &file->header, 0 ))
         hFile2 = HFILE_ERROR32;
     FILE_ReleaseFile( file );
@@ -1207,7 +1229,7 @@
     hFileRet = FILE_OpenUnixFile( full_name.long_name, unixMode );
     if (hFileRet == HFILE_ERROR32) goto not_found;
     /* we need to save the mode, but only if it is not in use yet*/
-    if( (!fileInUse) &&(file =FILE_GetFile(hFileRet)))
+    if( (!fileInUse) &&(file =FILE_GetFile(hFileRet,0,NULL)))
       {
        file->mode=mode;
        FILE_ReleaseFile(file);
@@ -1382,6 +1404,7 @@
 {
     FILE_OBJECT *file;
     DWORD result = 0xffffffff;
+    int unix_handle;
 
     if (highword && *highword)
     {
@@ -1392,8 +1415,12 @@
     TRACE(file, "handle %d offset %ld origin %ld\n",
           hFile, distance, method );
 
-    if (!(file = FILE_GetFile( hFile ))) return 0xffffffff;
-
+    if (!(file = FILE_GetFile( hFile, 0, NULL ))) return 0xffffffff;
+    if ((unix_handle = FILE_GetUnixHandle( hFile, 0 )) == -1)
+    {
+        FILE_ReleaseFile( file );
+        return 0xffffffff;
+    }
 
     /* the pointer may be positioned before the start of the file;
         no error is returned in that case,
@@ -1405,7 +1432,7 @@
         case FILE_CURRENT:
             distance += file->pos; /* fall through */
         case FILE_BEGIN:
-            if ((result = lseek(file->unix_handle, distance, SEEK_SET)) == -1)
+            if ((result = lseek(unix_handle, distance, SEEK_SET)) == -1)
             {
                 if ((INT32)distance < 0)
                     file->pos = result = distance;
@@ -1414,15 +1441,15 @@
             file->pos = result;
             break;
         case FILE_END:
-            if ((result = lseek(file->unix_handle, distance, SEEK_END)) == -1)
+            if ((result = lseek(unix_handle, distance, SEEK_END)) == -1)
             {
                 if ((INT32)distance < 0)
                 {
                     /* get EOF */
-                    result = lseek(file->unix_handle, 0, SEEK_END);
+                    result = lseek(unix_handle, 0, SEEK_END);
 
                     /* return to the old pos, as the first lseek failed */
-                    lseek(file->unix_handle, file->pos, SEEK_END);
+                    lseek(unix_handle, file->pos, SEEK_END);
 
                     file->pos = (result += distance);
                 }
@@ -1438,6 +1465,7 @@
     if (result == -1)
         FILE_SetDosError();
 
+    close( unix_handle );
     FILE_ReleaseFile( file );
     return result;
 }
@@ -1547,15 +1575,16 @@
 	TRACE(file, "%d %p %ld\n", handle, buffer, count );
 
 	if (count == 0) {       /* Expand or truncate at current position */
-		FILE_OBJECT *file = FILE_GetFile(handle);
-
-		if ( ftruncate(file->unix_handle,
-			       lseek( file->unix_handle, 0, SEEK_CUR)) == 0 ) {
-			FILE_ReleaseFile(file);
+                int unix_handle = FILE_GetUnixHandle( handle, GENERIC_WRITE );
+                if ((unix_handle != -1) &&
+                    (ftruncate(unix_handle,
+			       lseek( unix_handle, 0, SEEK_CUR)) == 0 ))
+                {
+                        close( unix_handle );
 			return 0;
 		} else {
 			FILE_SetDosError();
-			FILE_ReleaseFile(file);
+                        close( unix_handle );
 			return HFILE_ERROR32;
 		}
 	}
@@ -1637,18 +1666,18 @@
  */
 BOOL32 WINAPI FlushFileBuffers( HFILE32 hFile )
 {
-    FILE_OBJECT *file;
+    int unix_handle;
     BOOL32 ret;
 
     TRACE(file, "(%d)\n", hFile );
-    if (!(file = FILE_GetFile( hFile ))) return FALSE;
-    if (fsync( file->unix_handle ) != -1) ret = TRUE;
+    if ((unix_handle = FILE_GetUnixHandle( hFile, 0)) == -1) return FALSE;
+    if (fsync( unix_handle ) != -1) ret = TRUE;
     else
     {
         FILE_SetDosError();
         ret = FALSE;
     }
-    FILE_ReleaseFile( file );
+    close( unix_handle );
     return ret;
 }
 
@@ -1658,18 +1687,18 @@
  */
 BOOL32 WINAPI SetEndOfFile( HFILE32 hFile )
 {
-    FILE_OBJECT *file;
+    int unix_handle;
     BOOL32 ret = TRUE;
 
     TRACE(file, "(%d)\n", hFile );
-    if (!(file = FILE_GetFile( hFile ))) return FALSE;
-    if (ftruncate( file->unix_handle,
-                   lseek( file->unix_handle, 0, SEEK_CUR ) ))
+    if ((unix_handle = FILE_GetUnixHandle( hFile, GENERIC_WRITE )) == -1) return FALSE;
+    if (ftruncate( unix_handle,
+                   lseek( unix_handle, 0, SEEK_CUR ) ))
     {
         FILE_SetDosError();
         ret = FALSE;
     }
-    FILE_ReleaseFile( file );
+    close( unix_handle );
     return ret;
 }
 
@@ -1726,7 +1755,7 @@
  */
 BOOL32 FILE_SetFileType( HFILE32 hFile, DWORD type )
 {
-    FILE_OBJECT *file = FILE_GetFile( hFile );
+    FILE_OBJECT *file = FILE_GetFile( hFile, 0, NULL );
     if (!file) return FALSE;
     file->type = type;
     FILE_ReleaseFile( file );
@@ -1743,10 +1772,16 @@
                   int prot, int flags )
 {
     LPVOID ret;
-    FILE_OBJECT *file = FILE_GetFile( hFile );
+    int unix_handle;
+    FILE_OBJECT *file = FILE_GetFile( hFile, 0, NULL );
     if (!file) return (LPVOID)-1;
-    ret = FILE_dommap( file, start, size_high, size_low,
-                       offset_high, offset_low, prot, flags );
+    if ((unix_handle = FILE_GetUnixHandle( hFile, 0 )) == -1) ret = (LPVOID)-1;
+    else
+    {
+        ret = FILE_dommap( file, unix_handle, start, size_high, size_low,
+                           offset_high, offset_low, prot, flags );
+        close( unix_handle );
+    }
     FILE_ReleaseFile( file );
     return ret;
 }
@@ -1755,7 +1790,7 @@
 /***********************************************************************
  *           FILE_dommap
  */
-LPVOID FILE_dommap( FILE_OBJECT *file, LPVOID start,
+LPVOID FILE_dommap( FILE_OBJECT *file, int unix_handle, LPVOID start,
                     DWORD size_high, DWORD size_low,
                     DWORD offset_high, DWORD offset_low,
                     int prot, int flags )
@@ -1792,7 +1827,7 @@
 	flags |= MAP_PRIVATE;
 #endif
     }
-    else fd = file->unix_handle;
+    else fd = unix_handle;
 
     if ((ret = mmap( start, size_low, prot,
                      flags, fd, offset_low )) != (LPVOID)-1)
@@ -1816,7 +1851,7 @@
     }
 /*    printf( "FILE_mmap: mmap failed (%d), faking it\n", errno );*/
     /* Reserve the memory with an anonymous mmap */
-    ret = FILE_dommap( NULL, start, size_high, size_low, 0, 0,
+    ret = FILE_dommap( NULL, -1, start, size_high, size_low, 0, 0,
                        PROT_READ | PROT_WRITE, flags );
     if (ret == (LPVOID)-1) return ret;
     /* Now read in the file */
@@ -1848,7 +1883,7 @@
  */
 DWORD WINAPI GetFileType( HFILE32 hFile )
 {
-    FILE_OBJECT *file = FILE_GetFile(hFile);
+    FILE_OBJECT *file = FILE_GetFile(hFile, 0, NULL);
     if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
     FILE_ReleaseFile( file );
     return file->type;
@@ -2126,7 +2161,7 @@
                            const FILETIME *lpLastAccessTime,
                            const FILETIME *lpLastWriteTime )
 {
-    FILE_OBJECT *file = FILE_GetFile(hFile);
+    FILE_OBJECT *file = FILE_GetFile(hFile, 0, NULL);
     struct utimbuf utimbuf;
     
     if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
@@ -2263,7 +2298,7 @@
   f.l_pid = 0;
   f.l_type = F_WRLCK;
 
-  if (!(file = FILE_GetFile(hFile))) return FALSE;
+  if (!(file = FILE_GetFile(hFile,0,NULL))) return FALSE;
 
   /* shadow locks internally */
   if (!DOS_AddLock(file, &f)) {
@@ -2314,7 +2349,7 @@
   f.l_pid = 0;
   f.l_type = F_UNLCK;
 
-  if (!(file = FILE_GetFile(hFile))) return FALSE;
+  if (!(file = FILE_GetFile(hFile,0,NULL))) return FALSE;
 
   DOS_RemoveLock(file, &f);	/* ok if fails - may be another wine */
 
diff --git a/include/debug.h b/include/debug.h
index 15a66ad..f5e6447 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -5,159 +5,153 @@
 #endif
 
 /* Definitions for channels identifiers */
-#define dbch_1 0
-#define dbch_2 1
-#define dbch_3 2
-#define dbch_4 3
-#define dbch_5 4
-#define dbch_6 5
-#define dbch_accel 6
-#define dbch_advapi 7
-#define dbch_animate 8
-#define dbch_aspi 9
-#define dbch_atom 10
-#define dbch_bitblt 11
-#define dbch_bitmap 12
-#define dbch_caret 13
-#define dbch_cdaudio 14
-#define dbch_class 15
-#define dbch_clipboard 16
-#define dbch_clipping 17
-#define dbch_combo 18
-#define dbch_comboex 19
-#define dbch_comm 20
-#define dbch_commctrl 21
-#define dbch_commdlg 22
-#define dbch_console 23
-#define dbch_crtdll 24
-#define dbch_cursor 25
-#define dbch_datetime 26
-#define dbch_dc 27
-#define dbch_dde 28
-#define dbch_ddeml 29
-#define dbch_ddraw 30
-#define dbch_debug 31
-#define dbch_dialog 32
-#define dbch_dinput 33
-#define dbch_dll 34
-#define dbch_dosfs 35
-#define dbch_dosmem 36
-#define dbch_dplay 37
-#define dbch_driver 38
-#define dbch_dsound 39
-#define dbch_edit 40
-#define dbch_event 41
-#define dbch_exec 42
-#define dbch_file 43
-#define dbch_fixup 44
-#define dbch_font 45
-#define dbch_gdi 46
-#define dbch_global 47
-#define dbch_graphics 48
-#define dbch_header 49
-#define dbch_heap 50
-#define dbch_hook 51
-#define dbch_hotkey 52
-#define dbch_icon 53
-#define dbch_imagehlp 54
-#define dbch_imagelist 55
-#define dbch_imm 56
-#define dbch_int 57
-#define dbch_int10 58
-#define dbch_int16 59
-#define dbch_int17 60
-#define dbch_int19 61
-#define dbch_int21 62
-#define dbch_int31 63
-#define dbch_io 64
-#define dbch_ipaddress 65
-#define dbch_key 66
-#define dbch_keyboard 67
-#define dbch_ldt 68
-#define dbch_listbox 69
-#define dbch_listview 70
-#define dbch_local 71
-#define dbch_mci 72
-#define dbch_mcianim 73
-#define dbch_mcimidi 74
-#define dbch_mciwave 75
-#define dbch_mdi 76
-#define dbch_menu 77
-#define dbch_message 78
-#define dbch_metafile 79
-#define dbch_midi 80
-#define dbch_mmaux 81
-#define dbch_mmio 82
-#define dbch_mmsys 83
-#define dbch_mmtime 84
-#define dbch_module 85
-#define dbch_monthcal 86
-#define dbch_mpr 87
-#define dbch_msacm 88
-#define dbch_msg 89
-#define dbch_nativefont 90
-#define dbch_nonclient 91
-#define dbch_ntdll 92
-#define dbch_ole 93
-#define dbch_pager 94
-#define dbch_palette 95
-#define dbch_pidl 96
-#define dbch_print 97
-#define dbch_process 98
-#define dbch_profile 99
-#define dbch_progress 100
-#define dbch_prop 101
-#define dbch_psapi 102
-#define dbch_psdrv 103
-#define dbch_ras 104
-#define dbch_rebar 105
-#define dbch_reg 106
-#define dbch_region 107
-#define dbch_relay 108
-#define dbch_resource 109
-#define dbch_s 110
-#define dbch_scroll 111
-#define dbch_security 112
-#define dbch_segment 113
-#define dbch_selector 114
-#define dbch_sem 115
-#define dbch_sendmsg 116
-#define dbch_shell 117
-#define dbch_shm 118
-#define dbch_snoop 119
-#define dbch_sound 120
-#define dbch_static 121
-#define dbch_statusbar 122
-#define dbch_stress 123
-#define dbch_string 124
-#define dbch_syscolor 125
-#define dbch_system 126
-#define dbch_tab 127
-#define dbch_task 128
-#define dbch_text 129
-#define dbch_thread 130
-#define dbch_thunk 131
-#define dbch_timer 132
-#define dbch_toolbar 133
-#define dbch_toolhelp 134
-#define dbch_tooltips 135
-#define dbch_trackbar 136
-#define dbch_treeview 137
-#define dbch_tweak 138
-#define dbch_uitools 139
-#define dbch_updown 140
-#define dbch_ver 141
-#define dbch_virtual 142
-#define dbch_vxd 143
-#define dbch_wave 144
-#define dbch_win 145
-#define dbch_win16drv 146
-#define dbch_win32 147
-#define dbch_wing 148
-#define dbch_winsock 149
-#define dbch_wnet 150
-#define dbch_x11 151
-#define dbch_x11drv 152
+#define dbch_accel 0
+#define dbch_advapi 1
+#define dbch_animate 2
+#define dbch_aspi 3
+#define dbch_atom 4
+#define dbch_bitblt 5
+#define dbch_bitmap 6
+#define dbch_caret 7
+#define dbch_cdaudio 8
+#define dbch_class 9
+#define dbch_clipboard 10
+#define dbch_clipping 11
+#define dbch_combo 12
+#define dbch_comboex 13
+#define dbch_comm 14
+#define dbch_commctrl 15
+#define dbch_commdlg 16
+#define dbch_console 17
+#define dbch_crtdll 18
+#define dbch_cursor 19
+#define dbch_datetime 20
+#define dbch_dc 21
+#define dbch_dde 22
+#define dbch_ddeml 23
+#define dbch_ddraw 24
+#define dbch_debug 25
+#define dbch_dialog 26
+#define dbch_dinput 27
+#define dbch_dll 28
+#define dbch_dosfs 29
+#define dbch_dosmem 30
+#define dbch_dplay 31
+#define dbch_driver 32
+#define dbch_dsound 33
+#define dbch_edit 34
+#define dbch_event 35
+#define dbch_exec 36
+#define dbch_file 37
+#define dbch_fixup 38
+#define dbch_font 39
+#define dbch_gdi 40
+#define dbch_global 41
+#define dbch_graphics 42
+#define dbch_header 43
+#define dbch_heap 44
+#define dbch_hook 45
+#define dbch_hotkey 46
+#define dbch_icon 47
+#define dbch_imagehlp 48
+#define dbch_imagelist 49
+#define dbch_imm 50
+#define dbch_int 51
+#define dbch_int10 52
+#define dbch_int16 53
+#define dbch_int17 54
+#define dbch_int19 55
+#define dbch_int21 56
+#define dbch_int31 57
+#define dbch_io 58
+#define dbch_ipaddress 59
+#define dbch_key 60
+#define dbch_keyboard 61
+#define dbch_ldt 62
+#define dbch_listbox 63
+#define dbch_listview 64
+#define dbch_local 65
+#define dbch_mci 66
+#define dbch_mcianim 67
+#define dbch_mcimidi 68
+#define dbch_mciwave 69
+#define dbch_mdi 70
+#define dbch_menu 71
+#define dbch_message 72
+#define dbch_metafile 73
+#define dbch_midi 74
+#define dbch_mmaux 75
+#define dbch_mmio 76
+#define dbch_mmsys 77
+#define dbch_mmtime 78
+#define dbch_module 79
+#define dbch_monthcal 80
+#define dbch_mpr 81
+#define dbch_msacm 82
+#define dbch_msg 83
+#define dbch_nativefont 84
+#define dbch_nonclient 85
+#define dbch_ntdll 86
+#define dbch_ole 87
+#define dbch_pager 88
+#define dbch_palette 89
+#define dbch_pidl 90
+#define dbch_print 91
+#define dbch_process 92
+#define dbch_profile 93
+#define dbch_progress 94
+#define dbch_prop 95
+#define dbch_psapi 96
+#define dbch_psdrv 97
+#define dbch_ras 98
+#define dbch_rebar 99
+#define dbch_reg 100
+#define dbch_region 101
+#define dbch_relay 102
+#define dbch_resource 103
+#define dbch_scroll 104
+#define dbch_security 105
+#define dbch_segment 106
+#define dbch_selector 107
+#define dbch_sem 108
+#define dbch_sendmsg 109
+#define dbch_server 110
+#define dbch_shell 111
+#define dbch_shm 112
+#define dbch_snoop 113
+#define dbch_sound 114
+#define dbch_static 115
+#define dbch_statusbar 116
+#define dbch_stress 117
+#define dbch_string 118
+#define dbch_syscolor 119
+#define dbch_system 120
+#define dbch_tab 121
+#define dbch_task 122
+#define dbch_text 123
+#define dbch_thread 124
+#define dbch_thunk 125
+#define dbch_timer 126
+#define dbch_toolbar 127
+#define dbch_toolhelp 128
+#define dbch_tooltips 129
+#define dbch_trackbar 130
+#define dbch_treeview 131
+#define dbch_tweak 132
+#define dbch_uitools 133
+#define dbch_updown 134
+#define dbch_ver 135
+#define dbch_virtual 136
+#define dbch_vxd 137
+#define dbch_wave 138
+#define dbch_win 139
+#define dbch_win16drv 140
+#define dbch_win32 141
+#define dbch_wing 142
+#define dbch_winsock 143
+#define dbch_wnet 144
+#define dbch_x11 145
+#define dbch_x11drv 146
 /* Definitions for classes identifiers */
 #define dbcl_fixme 0
 #define dbcl_err 1
diff --git a/include/debugdefs.h b/include/debugdefs.h
index b30c315..ea469b5 100644
--- a/include/debugdefs.h
+++ b/include/debugdefs.h
@@ -4,7 +4,7 @@
 #include "debugtools.h"
 #endif
 
-#define DEBUG_CHANNEL_COUNT 153
+#define DEBUG_CHANNEL_COUNT 147
 #ifdef DEBUG_RUNTIME
 short debug_msg_enabled[][DEBUG_CLASS_COUNT] = {
 {1, 1, 0, 0},
@@ -154,20 +154,8 @@
 {1, 1, 0, 0},
 {1, 1, 0, 0},
 {1, 1, 0, 0},
-{1, 1, 0, 0},
-{1, 1, 0, 0},
-{1, 1, 0, 0},
-{1, 1, 0, 0},
-{1, 1, 0, 0},
-{1, 1, 0, 0},
 };
 const char* debug_ch_name[] = {
-"1",
-"2",
-"3",
-"4",
-"5",
-"6",
 "accel",
 "advapi",
 "animate",
@@ -272,13 +260,13 @@
 "region",
 "relay",
 "resource",
-"s",
 "scroll",
 "security",
 "segment",
 "selector",
 "sem",
 "sendmsg",
+"server",
 "shell",
 "shm",
 "snoop",
diff --git a/include/file.h b/include/file.h
index e782724..b70ae64 100644
--- a/include/file.h
+++ b/include/file.h
@@ -62,11 +62,12 @@
 
 
 /* files/file.c */
-extern FILE_OBJECT *FILE_GetFile( HFILE32 handle );
+extern FILE_OBJECT *FILE_GetFile( HFILE32 handle, DWORD access,
+                                  int *server_handle );
 extern void FILE_ReleaseFile( FILE_OBJECT *file );
-extern HFILE32 FILE_Alloc( FILE_OBJECT **file );
+extern HFILE32 FILE_Alloc( FILE_OBJECT **file, int unix_handle );
 extern void FILE_SetDosError(void);
-extern int FILE_GetUnixHandle( HFILE32 hFile );
+extern int FILE_GetUnixHandle( HFILE32 hFile, DWORD access );
 extern HFILE32 FILE_DupUnixHandle( int fd );
 extern BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
 extern HFILE32 FILE_Dup( HFILE32 hFile );
@@ -78,7 +79,7 @@
                          DWORD size_high, DWORD size_low,
                          DWORD offset_high, DWORD offset_low,
                          int prot, int flags );
-extern LPVOID FILE_dommap( FILE_OBJECT *file, LPVOID start,
+extern LPVOID FILE_dommap( FILE_OBJECT *file, int unix_handle, LPVOID start,
                            DWORD size_high, DWORD size_low,
                            DWORD offset_high, DWORD offset_low,
                          int prot, int flags );
diff --git a/include/server.h b/include/server.h
index e93cea7..d81ac71 100644
--- a/include/server.h
+++ b/include/server.h
@@ -7,6 +7,9 @@
 #ifndef __WINE_SERVER_H
 #define __WINE_SERVER_H
 
+#include <stdlib.h>
+#include <time.h>
+
 /* message header as sent on the wire */
 struct header
 {
@@ -51,10 +54,18 @@
 };
 
 
+/* Set the server debug level */
+struct set_debug_request
+{
+    int          level;        /* New debug level */
+};
+
+
 /* Initialize a thread; called from the child after fork()/clone() */
 struct init_thread_request
 {
     int          unix_pid;     /* Unix pid of new thread */
+    char         cmd_line[0];  /* Thread command line */
 };
 
 
@@ -159,7 +170,7 @@
     int          manual_reset;  /* manual reset event */
     int          initial_state; /* initial state of the event */
     int          inherit;       /* inherit flag */
-    /* char name[] */
+    char         name[0];       /* event name */
 };
 struct create_event_reply
 {
@@ -180,7 +191,7 @@
 {
     int          owned;         /* initially owned? */
     int          inherit;       /* inherit flag */
-    /* char name[] */
+    char         name[0];       /* mutex name */
 };
 struct create_mutex_reply
 {
@@ -220,6 +231,7 @@
     unsigned int prev_count;    /* previous semaphore count */
 };
 
+
 /* Open a named object (event, mutex, semaphore) */
 struct open_named_obj_request
 {
@@ -236,6 +248,43 @@
 };
 
 
+/* Create a file */
+struct create_file_request
+{
+    unsigned int access;        /* wanted access rights */
+    int          inherit;       /* inherit flag */
+};
+struct create_file_reply
+{
+    int          handle;        /* handle to the file */
+};
+
+
+/* Get a Unix handle to a file */
+struct get_unix_handle_request
+{
+    int          handle;        /* handle to the file */
+    unsigned int access;        /* desired access */
+};
+
+
+struct get_file_info_request
+{
+    int          handle;        /* handle to the file */
+};
+struct get_file_info_reply
+{
+    int          attr;          /* file attributes */
+    time_t       access_time;   /* last access time */
+    time_t       write_time;    /* last write time */
+    int          size_high;     /* file size */
+    int          size_low;      /* file size */
+    int          links;         /* number of links */
+    int          index_high;    /* unique index */
+    int          index_low;     /* unique index */
+    unsigned int serial;        /* volume serial number */
+};
+
 /* client-side functions */
 
 #ifndef __WINE_SERVER__
@@ -253,6 +302,7 @@
 
 struct _THDB;
 extern int CLIENT_NewThread( struct _THDB *thdb, int *thandle, int *phandle );
+extern int CLIENT_SetDebug( int level );
 extern int CLIENT_InitThread(void);
 extern int CLIENT_TerminateProcess( int handle, int exit_code );
 extern int CLIENT_TerminateThread( int handle, int exit_code );
diff --git a/include/server/object.h b/include/server/object.h
index c00fbc0..d55b8101 100644
--- a/include/server/object.h
+++ b/include/server/object.h
@@ -156,6 +156,13 @@
 extern int open_semaphore( unsigned int access, int inherit, const char *name );
 extern int release_semaphore( int handle, unsigned int count, unsigned int *prev_count );
 
+
+/* file functions */
+
+extern struct object *create_file( int fd );
+extern int file_get_unix_handle( int handle, unsigned int access );
+extern int get_file_info( int handle, struct get_file_info_reply *reply );
+
 extern int debug_level;
 
 #endif  /* __WINE_SERVER_OBJECT_H */
diff --git a/include/server/request.h b/include/server/request.h
index 2dc80a5..b647223 100644
--- a/include/server/request.h
+++ b/include/server/request.h
@@ -6,6 +6,7 @@
 enum request
 {
     REQ_NEW_THREAD,
+    REQ_SET_DEBUG,
     REQ_INIT_THREAD,
     REQ_TERMINATE_PROCESS,
     REQ_TERMINATE_THREAD,
@@ -22,6 +23,9 @@
     REQ_CREATE_SEMAPHORE,
     REQ_RELEASE_SEMAPHORE,
     REQ_OPEN_NAMED_OBJ,
+    REQ_CREATE_FILE,
+    REQ_GET_UNIX_HANDLE,
+    REQ_GET_FILE_INFO,
     REQ_NB_REQUESTS
 };
 
@@ -31,6 +35,7 @@
     static void req_##name( struct name##_request *req, void *data, int len, int fd )
 
 DECL_HANDLER(new_thread);
+DECL_HANDLER(set_debug);
 DECL_HANDLER(init_thread);
 DECL_HANDLER(terminate_process);
 DECL_HANDLER(terminate_thread);
@@ -47,12 +52,16 @@
 DECL_HANDLER(create_semaphore);
 DECL_HANDLER(release_semaphore);
 DECL_HANDLER(open_named_obj);
+DECL_HANDLER(create_file);
+DECL_HANDLER(get_unix_handle);
+DECL_HANDLER(get_file_info);
 
 static const struct handler {
     void       (*handler)();
     unsigned int min_size;
 } req_handlers[REQ_NB_REQUESTS] = {
     { (void(*)())req_new_thread, sizeof(struct new_thread_request) },
+    { (void(*)())req_set_debug, sizeof(struct set_debug_request) },
     { (void(*)())req_init_thread, sizeof(struct init_thread_request) },
     { (void(*)())req_terminate_process, sizeof(struct terminate_process_request) },
     { (void(*)())req_terminate_thread, sizeof(struct terminate_thread_request) },
@@ -69,6 +78,9 @@
     { (void(*)())req_create_semaphore, sizeof(struct create_semaphore_request) },
     { (void(*)())req_release_semaphore, sizeof(struct release_semaphore_request) },
     { (void(*)())req_open_named_obj, sizeof(struct open_named_obj_request) },
+    { (void(*)())req_create_file, sizeof(struct create_file_request) },
+    { (void(*)())req_get_unix_handle, sizeof(struct get_unix_handle_request) },
+    { (void(*)())req_get_file_info, sizeof(struct get_file_info_request) },
 };
 #endif  /* WANT_REQUEST_HANDLERS */
 
diff --git a/loader/main.c b/loader/main.c
index 4c2d667..002f29d 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -42,6 +42,7 @@
 #include "task.h"
 #include "debug.h"
 #include "psdrv.h"
+#include "server.h"
 
 int __winelib = 1;  /* Winelib run-time flag */
 
@@ -50,6 +51,10 @@
  */
 BOOL32 MAIN_MainInit(void)
 {
+    /* Set server debug level */
+    /* To fool make_debug: TRACE(server) */
+    CLIENT_SetDebug( TRACE_ON(server) );
+
     /* Initialize syslevel handling */
     SYSLEVEL_Init();
 
diff --git a/memory/virtual.c b/memory/virtual.c
index 5d90f73..7493022 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -33,6 +33,7 @@
     DWORD         size_high;
     DWORD         size_low;
     FILE_OBJECT  *file;
+    int           unix_handle;
     BYTE          protect;
 } FILE_MAPPING;
 
@@ -604,7 +605,7 @@
     if ((type & MEM_RESERVE) || !base)
     {
         view_size = size + (base ? 0 : granularity_mask + 1);
-        ptr = (UINT32)FILE_dommap( NULL, (LPVOID)base, 0, view_size, 0, 0,
+        ptr = (UINT32)FILE_dommap( NULL, -1, (LPVOID)base, 0, view_size, 0, 0,
                                    VIRTUAL_GetUnixProt( vprot ), MAP_PRIVATE );
         if (ptr == (UINT32)-1)
         {
@@ -1086,6 +1087,7 @@
                 LPCSTR name      /* [in] Name of file-mapping object */ )
 {
     FILE_MAPPING *mapping = NULL;
+    int unix_handle = -1;
     HANDLE32 handle;
     BYTE vprot;
     BOOL32 inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
@@ -1172,7 +1174,7 @@
         if (!(obj = HANDLE_GetObjPtr( PROCESS_Current(), hFile,
                                       K32OBJ_FILE, access, NULL )))
             goto error;
-
+        if ((unix_handle = FILE_GetUnixHandle( hFile, access )) == -1) goto error;
         if (!GetFileInformationByHandle( hFile, &info )) goto error;
         if (!size_high && !size_low)
         {
@@ -1199,6 +1201,7 @@
     mapping->size_high       = size_high;
     mapping->size_low        = ROUND_SIZE( 0, size_low );
     mapping->file            = (FILE_OBJECT *)obj;
+    mapping->unix_handle     = unix_handle;
 
     if (!K32OBJ_AddName( &mapping->header, name )) handle = 0;
     else handle = HANDLE_Alloc( PROCESS_Current(), &mapping->header,
@@ -1209,6 +1212,7 @@
 
 error:
     if (obj) K32OBJ_DecCount( obj );
+    if (unix_handle != -1) close( unix_handle );
     if (mapping) HeapFree( SystemHeap, 0, mapping );
     return 0;
 }
@@ -1280,6 +1284,7 @@
     assert( ptr->type == K32OBJ_MEM_MAPPED_FILE );
 
     if (mapping->file) K32OBJ_DecCount( &mapping->file->header );
+    if (mapping->unix_handle != -1) close( mapping->unix_handle );
     ptr->type = K32OBJ_UNKNOWN;
     HeapFree( SystemHeap, 0, mapping );
 }
@@ -1380,7 +1385,8 @@
     TRACE(virtual, "handle=%x size=%x offset=%lx\n",
                      handle, size, offset_low );
 
-    ptr = (UINT32)FILE_dommap( mapping->file, addr, 0, size, 0, offset_low,
+    ptr = (UINT32)FILE_dommap( mapping->file, mapping->unix_handle,
+                               addr, 0, size, 0, offset_low,
                                VIRTUAL_GetUnixProt( mapping->protect ),
                                flags );
     if (ptr == (UINT32)-1) {
diff --git a/misc/crtdll.c b/misc/crtdll.c
index 9994674..c142b7e 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -50,8 +50,6 @@
 #include "options.h"
 #include "winnls.h"
 
-extern int FILE_GetUnixHandle( HFILE32  );
-
 static DOS_FULL_NAME CRTDLL_tmpname;
 
 UINT32 CRTDLL_argc_dll;         /* CRTDLL.23 */
@@ -310,7 +308,7 @@
     TRACE(crtdll, "%s in BINARY mode\n",path);
       
   dos_fildes=FILE_Open(path, flagmode,0);
-  unix_fildes=FILE_GetUnixHandle(dos_fildes);
+  unix_fildes=FILE_GetUnixHandle(dos_fildes,0);
   file = fdopen(unix_fildes,mode);
 
   TRACE(crtdll, "file %s mode %s got ufh %d dfh %d file %p\n",
@@ -1100,7 +1098,12 @@
 
     if (unix_handle<4) ret= fclose(stream);
     else {
-      while(FILE_GetUnixHandle(dos_handle) != unix_handle) dos_handle++;
+      int h;
+      while((h = FILE_GetUnixHandle(dos_handle,0)) != unix_handle)
+      {
+          close(h);
+          dos_handle++;
+      }
       fclose(stream);
       ret = _lclose32( dos_handle);
     }
diff --git a/msdos/int21.c b/msdos/int21.c
index cc5ec8a..da14020 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -223,7 +223,7 @@
     RESET_CFLAG(context);
 
     /* DOS device ? */
-    if ((file = FILE_GetFile( HFILE16_TO_HFILE32(BX_reg(context)) )))
+    if ((file = FILE_GetFile( HFILE16_TO_HFILE32(BX_reg(context)), 0, NULL )))
     {
         const DOS_DEVICE *dev = DOSFS_GetDevice( file->unix_name );
         FILE_ReleaseFile( file );
@@ -1520,7 +1520,7 @@
             break;
         case 0x02:{
            FILE_OBJECT *file;
-           file = FILE_GetFile(HFILE16_TO_HFILE32(BX_reg(context)));
+           file = FILE_GetFile(HFILE16_TO_HFILE32(BX_reg(context)),0,NULL);
            if (!strcasecmp(file->unix_name, "SCSIMGR$"))
                         ASPI_DOS_HandleInt(context);
            FILE_ReleaseFile( file );
diff --git a/scheduler/client.c b/scheduler/client.c
index 5f819cf..47670a4 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -247,6 +247,7 @@
         case 0:  /* child */
             close( tmpfd[0] );
             sprintf( buffer, "%d", tmpfd[1] );
+/*#define EXEC_SERVER*/
 #ifdef EXEC_SERVER
             execlp( "wineserver", "wineserver", buffer, NULL );
             execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL );
@@ -316,6 +317,17 @@
 
 
 /***********************************************************************
+ *           CLIENT_SetDebug
+ *
+ * Send a set debug level request. Return 0 if OK.
+ */
+int CLIENT_SetDebug( int level )
+{
+    CLIENT_SendRequest( REQ_SET_DEBUG, -1, 1, &level, sizeof(level) );
+    return CLIENT_WaitReply( NULL, NULL, 0 );
+}
+
+/***********************************************************************
  *           CLIENT_TerminateProcess
  *
  * Send a terminate process request. Return 0 if OK.
diff --git a/scheduler/k32obj.c b/scheduler/k32obj.c
index f6543bf..d191c12 100644
--- a/scheduler/k32obj.c
+++ b/scheduler/k32obj.c
@@ -12,9 +12,6 @@
 
 
 /* The declarations are here to avoid including a lot of unnecessary files */
-extern const K32OBJ_OPS SEMAPHORE_Ops;
-extern const K32OBJ_OPS EVENT_Ops;
-extern const K32OBJ_OPS MUTEX_Ops;
 extern const K32OBJ_OPS CRITICAL_SECTION_Ops;
 extern const K32OBJ_OPS PROCESS_Ops;
 extern const K32OBJ_OPS THREAD_Ops;
@@ -25,6 +22,11 @@
 extern const K32OBJ_OPS CONSOLE_Ops;
 extern const K32OBJ_OPS SNAPSHOT_Ops;
 
+/* The following are fully implemented in the server and could be removed */
+extern const K32OBJ_OPS SEMAPHORE_Ops;
+extern const K32OBJ_OPS EVENT_Ops;
+extern const K32OBJ_OPS MUTEX_Ops;
+
 static const K32OBJ_OPS K32OBJ_NullOps =
 {
     NULL,    /* signaled */
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 );
diff --git a/tools/make_requests b/tools/make_requests
index f02bd43..5c80ecf 100755
--- a/tools/make_requests
+++ b/tools/make_requests
@@ -9,8 +9,11 @@
 %formats =
 (
     "int"          => "%d",
+    "char"         => "%c",
+    "char[0]"      => "\\\"%.*s\\\"",
     "unsigned int" => "%08x",
-    "void*"        => "%p"
+    "void*"        => "%p",
+    "time_t"       => "%ld"
 );
 
 my @requests = ();
@@ -46,9 +49,8 @@
 
 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] =
@@ -59,9 +61,8 @@
 {
     $request = $req . "_request";
     $reply = $replies{$req} ? "dump_${req}_reply" : "0";
-    print TRACE "    { (void(*)())dump_$request,\n";
-    print TRACE "      (void(*)())$reply,\n";
-    print TRACE "      sizeof(struct $request) },\n";
+    print TRACE "    { (int(*)(void *,int))dump_$request,\n";
+    print TRACE "      (void(*)())$reply },\n";
 }
 
 print TRACE <<EOF;
@@ -82,13 +83,13 @@
 
 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 );
@@ -196,8 +197,8 @@
         next if /^{$/;
 	s!/\*.*\*/!!g;
 	next if /^\s*$/;
-	/ *(\w+\**( +\w+\**)*) +(\w+);/ or die "Unrecognized syntax $_";
-	my $type = $1;
+	/ *(\w+\**( +\w+\**)*) +(\w+)(\[0\])?;/ or die "Unrecognized syntax $_";
+	my $type = $1 . ($4 || "");
 	my $var = $3;
         die "Unrecognized type $type" unless defined($formats{$type});
 	push @struct, $type, $var;
@@ -232,15 +233,25 @@
 
 sub DO_DUMP_FUNC
 {
+    my $vararg = 0;
     my $name = shift;
-    print TRACE "\nstatic void dump_$name( struct $name *req )\n{\n";
+    print TRACE "\nstatic int dump_$name( struct $name *req, int len )\n{\n";
     while ($#_ >= 0)
     {
 	my $type = shift;
 	my $var = shift;
 	print TRACE "    printf( \" $var=$formats{$type}";
 	print TRACE "," if ($#_ > 0);
-	print TRACE "\", req->$var );\n";
+	print TRACE "\", ";
+	if ($type =~ s/\[0\]$//g)  # vararg type?
+	{
+	    $vararg = 1;
+	    print TRACE "len - (int)sizeof(*req), ($type *)(req+1) );\n";
+	}
+	else
+	{
+	    print TRACE "req->$var );\n";
+        }
     }
-    print TRACE "}\n";
+    print TRACE "    return ", $vararg ? "len" : "(int)sizeof(*req)", ";\n}\n";
 }