OSDN Git Service

* autoload.cc (NtQueryVolumeInformationFile): Add.
authorcorinna <corinna>
Tue, 12 Apr 2005 14:26:28 +0000 (14:26 +0000)
committercorinna <corinna>
Tue, 12 Apr 2005 14:26:28 +0000 (14:26 +0000)
* 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
winsup/cygwin/autoload.cc
winsup/cygwin/fhandler.cc
winsup/cygwin/fhandler.h
winsup/cygwin/fhandler_disk_file.cc
winsup/cygwin/ntdll.h

index d330c5c..958941e 100644 (file)
@@ -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.
index f018016..8986c79 100644 (file)
@@ -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)
index dc7485a..1e7efc7 100644 (file)
@@ -295,7 +295,6 @@ fhandler_base::raw_write (const void *ptr, size_t len)
       return -1;
     }
 written:
-  has_changed (data_changed);
   return bytes_written;
 }
 
index e1ad64a..12c5b64 100644 (file)
@@ -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)
index 0cf1e1f..118308a 100644 (file)
@@ -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 ();
index 844a131..dfebe77 100644 (file)
@@ -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);