[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
This commit is contained in:
Pierre Schweitzer 2019-03-28 22:29:22 +01:00
parent f8e0b4675f
commit ce6488df31
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B

View file

@ -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);