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

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 */