From 2a24463d0bfef5d94e0918583cfffcf3a949f0df Mon Sep 17 00:00:00 2001
From: Corinna Vinschen <corinna@vinschen.de>
Date: Tue, 12 Apr 2005 14:26:31 +0000
Subject: [PATCH] 	* autoload.cc (NtQueryVolumeInformationFile): Add. 
 * fhandler.cc (fhandler_base::raw_write): Don't touch has_changed flag. 
 * fhandler.h (enum change_state): Remove. 	(fhandler_base::status):
 Revert has_changed to a simple bit. 	(fhandler_base::fstat_helper): Add
 nAllocSize parameter.  Rename 	ftCreationTime to ftChangeTime. 	*
 fhandler_disk_file.cc: 	Call fstat_helper with additional 
 allocation size throughout. 	(fhandler_base::fstat_by_handle): Use NT
 native functions to get 	full file information on NT.  Call
 fstat_helper with LastWriteTime 	as ctime, if ChangeTime is not
 available. 	(fhandler_base::fstat_by_name): Call fstat_helper with
 LastWriteTime 	as ctime. 	(fhandler_base::fstat_helper): Add comment.
 Drop special FAT 	handling since it's useless. Use nAllocSize for
 st_blocks if available. 	(fhandler_disk_file::touch_ctime): Only touch
 LastWriteTime. 	(fhandler_disk_file::fchmod): Set has_changed on 9x
 only. 	(fhandler_disk_file::fchown): Don't set has_changed. 
 (fhandler_disk_file::facl): Ditto. 	(fhandler_disk_file::ftruncate):
 Ditto. 	(fhandler_disk_file::link): Set has_changed on 9x only and on
 original 	file only. 	(fhandler_base::open_fs): Don't set
 has_changed in O_TRUNC case. 	* ntdll.h (FILE_BASIC_INFORMATION): Define. 
 (FILE_STANDARD_INFORMATION): Define. 	(FILE_INTERNAL_INFORMATION): Define. 
 (FILE_EA_INFORMATION): Define. 	(FILE_ACCESS_INFORMATION): Define. 
 (FILE_POSITION_INFORMATION): Define. 	(FILE_MODE_INFORMATION): Define. 
 (FILE_ALIGNMENT_INFORMATION): Define. 	(FILE_NAME_INFORMATION): Don't define
 with arbitrary FileName size. 	(FILE_ALL_INFORMATION): Define. 
 (FILE_INFORMATION_CLASS): Add FileAllInformation. 
 (FILE_FS_VOLUME_INFORMATION): Define. 	(FS_INFORMATION_CLASS): Define. 
 (NtQueryVolumeInformationFile): Define.

---
 winsup/cygwin/ChangeLog             |  41 +++++++++
 winsup/cygwin/autoload.cc           |   1 +
 winsup/cygwin/fhandler.cc           |   1 -
 winsup/cygwin/fhandler.h            |  15 ++--
 winsup/cygwin/fhandler_disk_file.cc | 129 +++++++++++++++++-----------
 winsup/cygwin/ntdll.h               |  81 +++++++++++++++--
 6 files changed, 202 insertions(+), 66 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index d330c5cfa..958941efe 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,44 @@
+2005-04-12  Corinna Vinschen  <corinna@vinschen.de>
+
+	* autoload.cc (NtQueryVolumeInformationFile): Add.
+	* fhandler.cc (fhandler_base::raw_write): Don't touch has_changed flag.
+	* fhandler.h (enum change_state): Remove.
+	(fhandler_base::status): Revert has_changed to a simple bit.
+	(fhandler_base::fstat_helper): Add nAllocSize parameter.  Rename
+	ftCreationTime to ftChangeTime.
+	* fhandler_disk_file.cc:
+	Call fstat_helper with additional
+	allocation size throughout.
+	(fhandler_base::fstat_by_handle): Use NT native functions to get
+	full file information on NT.  Call fstat_helper with LastWriteTime
+	as ctime, if ChangeTime is not available.
+	(fhandler_base::fstat_by_name): Call fstat_helper with LastWriteTime
+	as ctime.
+	(fhandler_base::fstat_helper): Add comment. Drop special FAT
+	handling since it's useless. Use nAllocSize for st_blocks if available.
+	(fhandler_disk_file::touch_ctime): Only touch LastWriteTime.
+	(fhandler_disk_file::fchmod): Set has_changed on 9x only.
+	(fhandler_disk_file::fchown): Don't set has_changed.
+	(fhandler_disk_file::facl): Ditto.
+	(fhandler_disk_file::ftruncate): Ditto.
+	(fhandler_disk_file::link): Set has_changed on 9x only and on original
+	file only.
+	(fhandler_base::open_fs): Don't set has_changed in O_TRUNC case.
+	* ntdll.h (FILE_BASIC_INFORMATION): Define.
+	(FILE_STANDARD_INFORMATION): Define.
+	(FILE_INTERNAL_INFORMATION): Define.
+	(FILE_EA_INFORMATION): Define.
+	(FILE_ACCESS_INFORMATION): Define.
+	(FILE_POSITION_INFORMATION): Define.
+	(FILE_MODE_INFORMATION): Define.
+	(FILE_ALIGNMENT_INFORMATION): Define.
+	(FILE_NAME_INFORMATION): Don't define with arbitrary FileName size.
+	(FILE_ALL_INFORMATION): Define.
+	(FILE_INFORMATION_CLASS): Add FileAllInformation.
+	(FILE_FS_VOLUME_INFORMATION): Define.
+	(FS_INFORMATION_CLASS): Define.
+	(NtQueryVolumeInformationFile): Define.
+
 2005-04-11  Corinna Vinschen  <corinna@vinschen.de>
 
 	Revert previous patch.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index f0180160b..8986c7924 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -394,6 +394,7 @@ LoadDLLfuncEx2 (NtQueryObject, 20, ntdll, 1, 1)
 LoadDLLfuncEx (NtQuerySystemInformation, 16, ntdll, 1)
 LoadDLLfuncEx (NtQuerySecurityObject, 20, ntdll, 1)
 LoadDLLfuncEx (NtQueryVirtualMemory, 24, ntdll, 1)
+LoadDLLfuncEx (NtQueryVolumeInformationFile, 20, ntdll, 1)
 LoadDLLfuncEx (NtSetSecurityObject, 12, ntdll, 1)
 LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1)
 LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index dc7485a79..1e7efc7d7 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -295,7 +295,6 @@ fhandler_base::raw_write (const void *ptr, size_t len)
       return -1;
     }
 written:
-  has_changed (data_changed);
   return bytes_written;
 }
 
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index e1ad64aa2..12c5b6445 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -78,12 +78,6 @@ enum query_state {
   query_write_attributes = 4
 };
 
-enum change_state {
-  no_change = 0,
-  inode_changed = 1,
-  data_changed = 2
-};
-
 class fhandler_base
 {
   friend class dtable;
@@ -106,14 +100,14 @@ class fhandler_base
 					read or write access */
     unsigned close_on_exec      : 1; /* close-on-exec */
     unsigned need_fork_fixup    : 1; /* Set if need to fixup after fork. */
-    unsigned has_changed	: 2; /* Flag used to set ctime on close. */
+    unsigned has_changed	: 1; /* Flag used to set ctime on close. */
 
    public:
     status_flags () :
       rbinary (0), rbinset (0), wbinary (0), wbinset (0), nohandle (0),
       uninterruptible_io (0), append_mode (0), did_lseek (0),
       query_open (no_query), close_on_exec (0), need_fork_fixup (0),
-      has_changed (no_change)
+      has_changed (0)
       {}
   } status, open_status;
 
@@ -194,7 +188,7 @@ class fhandler_base
   IMPLEMENT_STATUS_FLAG (query_state, query_open)
   IMPLEMENT_STATUS_FLAG (bool, close_on_exec)
   IMPLEMENT_STATUS_FLAG (bool, need_fork_fixup)
-  IMPLEMENT_STATUS_FLAG (change_state, has_changed)
+  IMPLEMENT_STATUS_FLAG (bool, has_changed)
 
   int get_default_fmode (int flags);
 
@@ -264,12 +258,13 @@ class fhandler_base
   virtual int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
   int __stdcall fstat_fs (struct __stat64 *buf) __attribute__ ((regparm (2)));
   int __stdcall fstat_helper (struct __stat64 *buf,
-			      FILETIME ftCreationTime,
+			      FILETIME ftChangeTime,
 			      FILETIME ftLastAccessTime,
 			      FILETIME ftLastWriteTime,
 			      DWORD dwVolumeSerialNumber,
 			      DWORD nFileSizeHigh,
 			      DWORD nFileSizeLow,
+			      LONGLONG nAllocSize,
 			      DWORD nFileIndexHigh,
 			      DWORD nFileIndexLow,
 			      DWORD nNumberOfLinks)
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 0cf1e1fb0..118308ab4 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -100,6 +100,51 @@ int __stdcall
 fhandler_base::fstat_by_handle (struct __stat64 *buf)
 {
   BY_HANDLE_FILE_INFORMATION local;
+
+  if (wincap.is_winnt ())
+    {
+      NTSTATUS status;
+      IO_STATUS_BLOCK io;
+      /* The entries potentially contain a name of MAX_PATH wide characters. */
+      DWORD fvi_size = 2 * CYG_MAX_PATH + sizeof (FILE_FS_VOLUME_INFORMATION);
+      DWORD fai_size = 2 * CYG_MAX_PATH + sizeof (FILE_ALL_INFORMATION);
+
+      PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
+      					 alloca (fvi_size);
+      PFILE_ALL_INFORMATION pfai = (PFILE_ALL_INFORMATION) alloca (fai_size);
+
+      status = NtQueryVolumeInformationFile (get_handle (), &io, pfvi, fvi_size,
+					     FileFsVolumeInformation);
+      if (!NT_SUCCESS (status))
+	{
+	  debug_printf ("%u = NtQueryVolumeInformationFile)",
+			RtlNtStatusToDosError (status));
+	  pfvi->VolumeSerialNumber = 0; /* Set to pc.volser () in helper. */
+        }
+      status = NtQueryInformationFile (get_handle (), &io, pfai, fai_size,
+				       FileAllInformation);
+      if (NT_SUCCESS (status))
+	/* If the change time is 0, it's a file system which doesn't
+	   support a change timestamp.  In that case use the LastWriteTime
+	   entry, as in other calls to fstat_helper. */
+	return fstat_helper (buf,
+			 pfai->BasicInformation.ChangeTime.QuadPart ?
+			 *(FILETIME *) &pfai->BasicInformation.ChangeTime :
+			 *(FILETIME *) &pfai->BasicInformation.LastWriteTime,
+			 *(FILETIME *) &pfai->BasicInformation.LastAccessTime,
+			 *(FILETIME *) &pfai->BasicInformation.LastWriteTime,
+			 pfvi->VolumeSerialNumber,
+			 pfai->StandardInformation.EndOfFile.HighPart,
+			 pfai->StandardInformation.EndOfFile.LowPart,
+			 pfai->StandardInformation.AllocationSize.QuadPart,
+			 pfai->InternalInformation.IndexNumber.HighPart,
+			 pfai->InternalInformation.IndexNumber.LowPart,
+			 pfai->StandardInformation.NumberOfLinks);
+
+      debug_printf ("%u = NtQuerynformationFile)",
+		    RtlNtStatusToDosError (status));
+    }
+
   BOOL res = GetFileInformationByHandle (get_handle (), &local);
   debug_printf ("%d = GetFileInformationByHandle (%s, %d)",
 		res, get_win32_name (), get_handle ());
@@ -111,12 +156,13 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
     }
 
   return fstat_helper (buf,
-		       local.ftCreationTime,
+		       local.ftLastWriteTime, /* see fstat_helper comment */
 		       local.ftLastAccessTime,
 		       local.ftLastWriteTime,
 		       local.dwVolumeSerialNumber,
 		       local.nFileSizeHigh,
 		       local.nFileSizeLow,
+		       -1LL,
 		       local.nFileIndexHigh,
 		       local.nFileIndexLow,
 		       local.nNumberOfLinks);
@@ -139,12 +185,13 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
     {
       FindClose (handle);
       res = fstat_helper (buf,
-			  local.ftCreationTime,
+			  local.ftLastWriteTime, /* see fstat_helper comment */
 			  local.ftLastAccessTime,
 			  local.ftLastWriteTime,
 			  pc.volser (),
 			  local.nFileSizeHigh,
 			  local.nFileSizeLow,
+			  -1LL,
 			  0,
 			  0,
 			  1);
@@ -152,7 +199,7 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
   else if (pc.isdir ())
     {
       FILETIME ft = {};
-      res = fstat_helper (buf, ft, ft, ft, pc.volser (), 0, 0, 0, 0, 1);
+      res = fstat_helper (buf, ft, ft, ft, pc.volser (), 0, 0, -1LL, 0, 0, 1);
     }
   else
     {
@@ -213,14 +260,21 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
   return res;
 }
 
+/* The ftChangeTime is taken from the NTFS ChangeTime entry, if reading
+   the file information using NtQueryInformationFile succeeded.  If not,
+   it's faked using the LastWriteTime entry from GetFileInformationByHandle
+   or FindFirstFile.  We're deliberatly not using the creation time anymore
+   to simplify interaction with native Windows applications which choke on
+   creation times >= access or write times. */
 int __stdcall
 fhandler_base::fstat_helper (struct __stat64 *buf,
-			     FILETIME ftCreationTime,
+			     FILETIME ftChangeTime,
 			     FILETIME ftLastAccessTime,
 			     FILETIME ftLastWriteTime,
 			     DWORD dwVolumeSerialNumber,
 			     DWORD nFileSizeHigh,
 			     DWORD nFileSizeLow,
+			     LONGLONG nAllocSize,
 			     DWORD nFileIndexHigh,
 			     DWORD nFileIndexLow,
 			     DWORD nNumberOfLinks)
@@ -228,17 +282,9 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
   IO_STATUS_BLOCK st;
   FILE_COMPRESSION_INFORMATION fci;
 
-  /* This is for FAT filesystems, which don't support atime/ctime */
-  if (ftLastAccessTime.dwLowDateTime == 0
-      && ftLastAccessTime.dwHighDateTime == 0)
-    ftLastAccessTime = ftLastWriteTime;
-  if (ftCreationTime.dwLowDateTime == 0
-      && ftCreationTime.dwHighDateTime == 0)
-    ftCreationTime = ftLastWriteTime;
-
   to_timestruc_t (&ftLastAccessTime, &buf->st_atim);
   to_timestruc_t (&ftLastWriteTime, &buf->st_mtim);
-  to_timestruc_t (&ftCreationTime, &buf->st_ctim);
+  to_timestruc_t (&ftChangeTime, &buf->st_ctim);
   buf->st_dev = dwVolumeSerialNumber ?: pc.volser ();
   buf->st_size = ((_off64_t) nFileSizeHigh << 32) + nFileSizeLow;
   /* The number of links to a directory includes the
@@ -273,15 +319,20 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
 
   buf->st_blksize = S_BLKSIZE;
 
-  /* On compressed and sparsed files, we request the actual amount of bytes
-     allocated on disk.  */
-  if (pc.has_attribute (FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_SPARSE_FILE)
+  if (nAllocSize >= 0LL)
+    /* A successful NtQueryInformationFile returns the allocation size
+       correctly for compressed and sparse files as well. */
+    buf->st_blocks = (nAllocSize + S_BLKSIZE - 1) / S_BLKSIZE;
+  else if (pc.has_attribute (FILE_ATTRIBUTE_COMPRESSED
+			     | FILE_ATTRIBUTE_SPARSE_FILE)
       && get_io_handle ()
       && !NtQueryInformationFile (get_io_handle (), &st, (PVOID) &fci,
 				  sizeof fci, FileCompressionInformation))
+    /* Otherwise we request the actual amount of bytes allocated for
+       compressed and sparsed files. */
     buf->st_blocks = (fci.CompressedSize.QuadPart + S_BLKSIZE - 1) / S_BLKSIZE;
   else
-    /* Just compute no. of blocks from file size. */
+    /* Otherwise compute no. of blocks from file size. */
     buf->st_blocks  = (buf->st_size + S_BLKSIZE - 1) / S_BLKSIZE;
 
   buf->st_mode = 0;
@@ -380,6 +431,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
 int __stdcall
 fhandler_disk_file::fstat (struct __stat64 *buf)
 {
+  /* Changing inode data requires setting ctime (only 9x). */
   if (has_changed ())
     touch_ctime ();
   return fstat_fs (buf);
@@ -393,11 +445,10 @@ fhandler_disk_file::touch_ctime (void)
   GetSystemTimeAsFileTime (&ft);
   /* Modification time is touched if the file data has changed as well.
      This happens for instance on write() or ftruncate(). */
-  if (!SetFileTime (get_io_handle (), &ft, NULL,
-		    has_changed () == data_changed ? &ft : NULL))
+  if (!SetFileTime (get_io_handle (), NULL, NULL, &ft))
     debug_printf ("SetFileTime (%s) failed, %E", get_win32_name ());
   else
-    has_changed (no_change);
+    has_changed (false);
 }
 
 int __stdcall
@@ -443,8 +494,8 @@ fhandler_disk_file::fchmod (mode_t mode)
     res = 0;
 
   /* Set ctime on success. */
-  if (!res)
-    has_changed (inode_changed);
+  if (!res && !wincap.is_winnt ())
+    has_changed (true);
 
   if (oret)
     close ();
@@ -476,13 +527,8 @@ fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid)
     attrib |= S_IFDIR;
   int res = get_file_attribute (pc.has_acls (), get_io_handle (), pc, &attrib);
   if (!res)
-    {
-      res = set_file_attribute (pc.has_acls (), get_io_handle (), pc,
-				uid, gid, attrib);
-      /* Set ctime on success. */
-      if (!res)
-	has_changed (inode_changed);
-    }
+    res = set_file_attribute (pc.has_acls (), get_io_handle (), pc,
+			      uid, gid, attrib);
 
   if (oret)
     close ();
@@ -576,10 +622,6 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
 	}
     }
 
-  /* Set ctime on success. */
-  if (!res && cmd == SETACL)
-    has_changed (inode_changed);
-
   if (oret)
     close ();
 
@@ -626,9 +668,6 @@ fhandler_disk_file::ftruncate (_off64_t length)
 	    res = res_bug;
 	  /* restore original file pointer location */
 	  lseek (prev_loc, SEEK_SET);
-	  /* Set ctime on success. */
-	  if (!res)
-	    has_changed (data_changed);
 	}
     }
   return res;
@@ -760,8 +799,6 @@ fhandler_disk_file::link (const char *newpath)
 	}
 
     success:
-      /* Set ctime on success. */
-      has_changed (inode_changed);
       close ();
       if (!allow_winsymlinks && pc.is_lnk_symlink ())
 	SetFileAttributes (newpc, (DWORD) pc
@@ -776,16 +813,14 @@ docopy:
       __seterrno ();
       return -1;
     }
-  /* Set ctime on success, also on the copy. */
-  has_changed (inode_changed);
+  /* Set ctime on success (copy gets it automatically). */
+  if (!wincap.is_winnt ())
+    has_changed (true);
   close ();
   fhandler_disk_file fh (newpc);
   fh.query_open (query_write_attributes);
   if (fh.open (O_BINARY, 0))
-    {
-      fh.has_changed (inode_changed);
-      fh.close ();
-    }
+    fh.close ();
   return 0;
 }
 
@@ -897,10 +932,6 @@ fhandler_base::open_fs (int flags, mode_t mode)
       && !allow_ntsec && allow_ntea)
     set_file_attribute (false, NULL, get_win32_name (), mode);
 
-  /* O_TRUNC on existing file requires setting ctime. */
-  if ((flags & (O_CREAT | O_TRUNC)) == O_TRUNC)
-    has_changed (data_changed);
-
   set_fs_flags (pc.fs_flags ());
 
 out:
@@ -912,7 +943,7 @@ out:
 int
 fhandler_disk_file::close ()
 {
-  /* Changing file data requires setting ctime. */
+  /* Changing inode data requires setting ctime (only 9x). */
   if (has_changed ())
     touch_ctime ();
   return close_fs ();
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 844a131b5..dfebe77d1 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -354,11 +354,62 @@ typedef struct _MEMORY_WORKING_SET_LIST
   ULONG WorkingSetList[1];
 } MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST;
 
-typedef struct _FILE_NAME_INFORMATION
-{
-  DWORD FileNameLength;
-  WCHAR FileName[MAX_PATH + 100];
-} FILE_NAME_INFORMATION;
+typedef struct _FILE_BASIC_INFORMATION {
+  LARGE_INTEGER CreationTime;
+  LARGE_INTEGER LastAccessTime;
+  LARGE_INTEGER LastWriteTime;
+  LARGE_INTEGER ChangeTime;
+  ULONG FileAttributes;
+} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
+
+typedef struct _FILE_STANDARD_INFORMATION {
+  LARGE_INTEGER AllocationSize;
+  LARGE_INTEGER EndOfFile;
+  ULONG NumberOfLinks;
+  BOOLEAN DeletePending;
+  BOOLEAN Directory;
+} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
+
+typedef struct _FILE_INTERNAL_INFORMATION {
+  LARGE_INTEGER IndexNumber;
+} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
+
+typedef struct _FILE_EA_INFORMATION {
+  ULONG EaSize;
+} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
+
+typedef struct _FILE_ACCESS_INFORMATION {
+  ACCESS_MASK AccessFlags;
+} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
+
+typedef struct _FILE_POSITION_INFORMATION {                 
+  LARGE_INTEGER CurrentByteOffset;                        
+} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;   
+
+typedef struct _FILE_MODE_INFORMATION {
+  ULONG Mode;
+} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
+
+typedef struct _FILE_ALIGNMENT_INFORMATION {
+  ULONG AlignmentRequirement;
+} FILE_ALIGNMENT_INFORMATION;
+
+typedef struct _FILE_NAME_INFORMATION {                     
+  ULONG FileNameLength;                                   
+  WCHAR FileName[1];                                      
+} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;           
+
+typedef struct _FILE_ALL_INFORMATION {
+  FILE_BASIC_INFORMATION     BasicInformation;
+  FILE_STANDARD_INFORMATION  StandardInformation;
+  FILE_INTERNAL_INFORMATION  InternalInformation;
+  FILE_EA_INFORMATION        EaInformation;
+  FILE_ACCESS_INFORMATION    AccessInformation;
+  FILE_POSITION_INFORMATION  PositionInformation;
+  FILE_MODE_INFORMATION      ModeInformation;
+  FILE_ALIGNMENT_INFORMATION AlignmentInformation;
+  FILE_NAME_INFORMATION      NameInformation;
+} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
 
 typedef struct _FILE_PIPE_LOCAL_INFORMATION
 {
@@ -385,10 +436,25 @@ typedef struct _FILE_COMPRESSION_INFORMATION
 
 typedef enum _FILE_INFORMATION_CLASS
 {
+  FileAllInformation = 18,
   FilePipeLocalInformation = 24,
   FileCompressionInformation = 28
 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
 
+typedef struct _FILE_FS_VOLUME_INFORMATION
+{
+  LARGE_INTEGER VolumeCreationTime;
+  ULONG VolumeSerialNumber;
+  ULONG VolumeLabelLength;
+  BOOLEAN SupportsObjects;
+  WCHAR VolumeLabel[1];
+} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;
+
+typedef enum _FSINFOCLASS
+{
+  FileFsVolumeInformation = 1
+} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
+
 typedef enum _OBJECT_INFORMATION_CLASS
 {
   ObjectBasicInformation = 0,
@@ -420,7 +486,7 @@ extern "C"
   NTSTATUS NTAPI NtOpenFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
 			     PIO_STATUS_BLOCK, ULONG, ULONG);
   NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
-  NTSTATUS NTAPI NtQueryInformationFile (HANDLE, IO_STATUS_BLOCK *, VOID *,
+  NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID,
 					 ULONG, FILE_INFORMATION_CLASS);
   NTSTATUS NTAPI NtQueryInformationProcess (HANDLE, PROCESSINFOCLASS,
 					    PVOID, ULONG, PULONG);
@@ -432,6 +498,9 @@ extern "C"
   					PSECURITY_DESCRIPTOR, ULONG, PULONG);
   NTSTATUS NTAPI NtQueryVirtualMemory (HANDLE, PVOID, MEMORY_INFORMATION_CLASS,
 				       PVOID, ULONG, PULONG);
+  NTSTATUS NTAPI NtQueryVolumeInformationFile (HANDLE, IO_STATUS_BLOCK *,
+					       VOID *, ULONG,
+					       FS_INFORMATION_CLASS);
   NTSTATUS NTAPI NtSetSecurityObject (HANDLE, SECURITY_INFORMATION,
 				      PSECURITY_DESCRIPTOR);
   NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID);