https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ce6488df31de64092f41aa78bb87e829ded3dc6b

commit ce6488df31de64092f41aa78bb87e829ded3dc6b
Author:     Pierre Schweitzer <[email protected]>
AuthorDate: Thu Mar 28 22:29:22 2019 +0100
Commit:     Pierre Schweitzer <[email protected]>
CommitDate: Thu Mar 28 22:39:38 2019 +0100

    [NTOSKRNL] Add a quick path for FileFsDeviceInformation in 
NtQueryVolumeInformationFile
    
    This allows querying volume information without issuing an IRP to the owner 
device.
    The kernel is supposed to already have all the required information to 
return
    to the caller.
    
    Side effect: this allows querying volume information for devices not 
implementing
    IRP_MJ_QUERY_VOLUME_INFORMATION such as null.sys
    This fixes opening null device in Python.
    
    Fix based on debugging by Maxim Smirnov in PR #1442
    
    CORE-14551
---
 ntoskrnl/io/iomgr/iofunc.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/ntoskrnl/io/iomgr/iofunc.c b/ntoskrnl/io/iomgr/iofunc.c
index f2d3e59dd2c..73938adb93a 100644
--- a/ntoskrnl/io/iomgr/iofunc.c
+++ b/ntoskrnl/io/iomgr/iofunc.c
@@ -1026,6 +1026,32 @@ IopGetFileMode(IN PFILE_OBJECT FileObject)
     return Mode;
 }
 
+static
+BOOLEAN
+IopGetMountFlag(IN PDEVICE_OBJECT DeviceObject)
+{
+    KIRQL OldIrql;
+    PVPB Vpb;
+    BOOLEAN Mounted;
+
+    /* Assume not mounted */
+    Mounted = FALSE;
+
+    /* Check whether we have the mount flag */
+    IoAcquireVpbSpinLock(&OldIrql);
+
+    Vpb = DeviceObject->Vpb;
+    if (Vpb != NULL &&
+        BooleanFlagOn(Vpb->Flags, VPB_MOUNTED))
+    {
+        Mounted = TRUE;
+    }
+
+    IoReleaseVpbSpinLock(OldIrql);
+
+    return Mounted;
+}
+
 /* PUBLIC FUNCTIONS **********************************************************/
 
 /*
@@ -4061,6 +4087,59 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
         LocalEvent = TRUE;
     }
 
+    /*
+     * Quick path for FileFsDeviceInformation - the kernel has enough
+     * info to reply instead of the driver, excepted for network file systems
+     */
+    if (FsInformationClass == FileFsDeviceInformation &&
+        (BooleanFlagOn(FileObject->Flags, FO_DIRECT_DEVICE_OPEN) || 
FileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM))
+    {
+        PFILE_FS_DEVICE_INFORMATION FsDeviceInfo = FsInformation;
+        DeviceObject = FileObject->DeviceObject;
+
+        _SEH2_TRY
+        {
+            FsDeviceInfo->DeviceType = DeviceObject->DeviceType;
+
+            /* Complete characteristcs with mount status if relevant */
+            FsDeviceInfo->Characteristics = DeviceObject->Characteristics;
+            if (IopGetMountFlag(DeviceObject))
+            {
+                SetFlag(FsDeviceInfo->Characteristics, FILE_DEVICE_IS_MOUNTED);
+            }
+
+            IoStatusBlock->Information = sizeof(FILE_FS_DEVICE_INFORMATION);
+            IoStatusBlock->Status = STATUS_SUCCESS;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Check if we had a file lock */
+            if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+            {
+                /* Release it */
+                IopUnlockFileObject(FileObject);
+            }
+
+            /* Dereference the FO */
+            ObDereferenceObject(FileObject);
+
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        }
+        _SEH2_END;
+
+        /* Check if we had a file lock */
+        if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+        {
+            /* Release it */
+            IopUnlockFileObject(FileObject);
+        }
+
+        /* Dereference the FO */
+        ObDereferenceObject(FileObject);
+
+        return STATUS_SUCCESS;
+    }
+
     /* Get the device object */
     DeviceObject = IoGetRelatedDeviceObject(FileObject);
 

Reply via email to