windows-nt/Source/XPSP1/NT/base/ntos/raw/volinfo.c

556 lines
12 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
VolInfo.c
Abstract:
This module implements the volume information routines for Raw called by
the dispatch driver.
Author:
Gary Kimura [GaryKi] 28-Dec-1989
Revision History:
--*/
#include "RawProcs.h"
NTSTATUS
RawQueryFsVolumeInfo (
IN PVCB Vcb,
IN PFILE_FS_VOLUME_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
RawQueryFsSizeInfo (
IN PVCB Vcb,
IN PFILE_FS_SIZE_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
RawQueryFsDeviceInfo (
IN PVCB Vcb,
IN PFILE_FS_DEVICE_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
RawQueryFsAttributeInfo (
IN PVCB Vcb,
IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
IN OUT PULONG Length
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RawQueryVolumeInformation)
#pragma alloc_text(PAGE, RawQueryFsVolumeInfo)
#pragma alloc_text(PAGE, RawQueryFsSizeInfo)
#pragma alloc_text(PAGE, RawQueryFsDeviceInfo)
#pragma alloc_text(PAGE, RawQueryFsAttributeInfo)
#endif
NTSTATUS
RawQueryVolumeInformation (
IN PVCB Vcb,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp
)
/*++
Routine Description:
This routine implements the NtQueryVolumeInformation API call.
Arguments:
Vcb - Supplies the volume being queried.
Irp - Supplies the Irp being processed.
IrpSp - Supplies parameters describing the read
Return Value:
NTSTATUS - The status for the Irp.
--*/
{
NTSTATUS Status;
ULONG Length;
FS_INFORMATION_CLASS FsInformationClass;
PVOID Buffer;
PAGED_CODE();
//
// Reference our input parameters to make things easier
//
Length = IrpSp->Parameters.QueryVolume.Length;
FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
Buffer = Irp->AssociatedIrp.SystemBuffer;
//
// Based on the information class we'll do different actions. Each
// of the procedures that we're calling fills up the output buffer
// if possible and returns true if it successfully filled the buffer
// and false if it couldn't wait for any I/O to complete.
//
switch (FsInformationClass) {
case FileFsVolumeInformation:
Status = RawQueryFsVolumeInfo( Vcb, Buffer, &Length );
break;
case FileFsSizeInformation:
Status = RawQueryFsSizeInfo( Vcb, Buffer, &Length );
break;
case FileFsDeviceInformation:
Status = RawQueryFsDeviceInfo( Vcb, Buffer, &Length );
break;
case FileFsAttributeInformation:
Status = RawQueryFsAttributeInfo( Vcb, Buffer, &Length );
break;
default:
Status = STATUS_INVALID_PARAMETER;
break;
}
//
// Set the information field to the number of bytes actually filled in,
// and complete the request.
//
Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
RawCompleteRequest( Irp, Status );
return Status;
}
//
// Internal support routine
//
NTSTATUS
RawQueryFsVolumeInfo (
IN PVCB Vcb,
IN PFILE_FS_VOLUME_INFORMATION Buffer,
IN OUT PULONG Length
)
/*++
Routine Description:
This routine implements the query volume info call
Arguments:
Vcb - Supplies the Vcb being queried
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
PAGED_CODE();
//
// Zero out the buffer, then extract and fill up the non zero fields.
//
RtlZeroMemory( Buffer, sizeof(FILE_FS_VOLUME_INFORMATION) );
Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
Buffer->SupportsObjects = FALSE;
Buffer->VolumeLabelLength = 0;
*Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
//
// Set our status and return to our caller
//
return STATUS_SUCCESS;
}
//
// Internal support routine
//
NTSTATUS
RawQueryFsSizeInfo (
IN PVCB Vcb,
IN PFILE_FS_SIZE_INFORMATION Buffer,
IN OUT PULONG Length
)
/*++
Routine Description:
This routine implements the query volume size call
Arguments:
Vcb - Supplies the Vcb being queried
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
Status - Returns the status for the query
--*/
{
PIRP Irp;
KEVENT Event;
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
PDEVICE_OBJECT RealDevice;
DISK_GEOMETRY DiskGeometry;
PARTITION_INFORMATION_EX PartitionInformation;
BOOLEAN DriveIsPartitioned;
PAGED_CODE();
//
// Make sure the buffer is large enough
//
if (*Length < sizeof(FILE_FS_SIZE_INFORMATION)) {
return STATUS_BUFFER_OVERFLOW;
}
RtlZeroMemory( Buffer, sizeof(FILE_FS_SIZE_INFORMATION) );
//
// Prepare for our device control below. The device drivers only
// have to copy geometry and partition info from in-memory strucures,
// so it is OK to make these calls even when we can't wait.
//
KeInitializeEvent( &Event, NotificationEvent, FALSE );
RealDevice = Vcb->Vpb->RealDevice;
//
// Query the disk geometry
//
Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_DRIVE_GEOMETRY,
RealDevice,
NULL,
0,
&DiskGeometry,
sizeof(DISK_GEOMETRY),
FALSE,
&Event,
&Iosb );
if ( Irp == NULL ) {
return STATUS_INSUFFICIENT_RESOURCES;
}
if ( (Status = IoCallDriver( RealDevice, Irp )) == STATUS_PENDING ) {
(VOID) KeWaitForSingleObject( &Event,
Executive,
KernelMode,
FALSE,
(PLARGE_INTEGER)NULL );
Status = Iosb.Status;
}
//
// If this call didn't succeed, the drive hasn't even been low-level
// formatted, and thus geometry information is undefined.
//
if (!NT_SUCCESS( Status )) {
*Length = 0;
return Status;
}
//
// See if we have to check the partition information (floppy disks are
// the only type that can't have partitions )
//
if ( FlagOn( RealDevice->Characteristics, FILE_FLOPPY_DISKETTE )) {
DriveIsPartitioned = FALSE;
} else {
//
// Query the partition table
//
KeResetEvent( &Event );
Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_PARTITION_INFO_EX,
RealDevice,
NULL,
0,
&PartitionInformation,
sizeof(PARTITION_INFORMATION_EX),
FALSE,
&Event,
&Iosb );
if ( Irp == NULL ) {
return STATUS_INSUFFICIENT_RESOURCES;
}
if ( (Status = IoCallDriver( RealDevice, Irp )) == STATUS_PENDING ) {
(VOID) KeWaitForSingleObject( &Event,
Executive,
KernelMode,
FALSE,
(PLARGE_INTEGER)NULL );
Status = Iosb.Status;
}
//
// If we get back invalid device request, the disk is not partitioned
//
if ( !NT_SUCCESS (Status) ) {
DriveIsPartitioned = FALSE;
} else {
DriveIsPartitioned = TRUE;
}
}
//
// Set the output buffer
//
Buffer->BytesPerSector = DiskGeometry.BytesPerSector;
Buffer->SectorsPerAllocationUnit = 1;
//
// Now, based on whether the disk is partitioned, compute the
// total number of sectors on this disk.
//
Buffer->TotalAllocationUnits =
Buffer->AvailableAllocationUnits = ( DriveIsPartitioned == TRUE ) ?
RtlExtendedLargeIntegerDivide( PartitionInformation.PartitionLength,
DiskGeometry.BytesPerSector,
NULL )
:
RtlExtendedIntegerMultiply( DiskGeometry.Cylinders,
DiskGeometry.TracksPerCylinder *
DiskGeometry.SectorsPerTrack );
//
// Adjust the length variable
//
*Length -= sizeof(FILE_FS_SIZE_INFORMATION);
//
// And return success to our caller
//
return STATUS_SUCCESS;
}
//
// Internal support routine
//
NTSTATUS
RawQueryFsDeviceInfo (
IN PVCB Vcb,
IN PFILE_FS_DEVICE_INFORMATION Buffer,
IN OUT PULONG Length
)
/*++
Routine Description:
This routine implements the query volume device call
Arguments:
Vcb - Supplies the Vcb being queried
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
Status - Returns the status for the query
--*/
{
PAGED_CODE();
//
// Make sure the buffer is large enough
//
if (*Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
return STATUS_BUFFER_OVERFLOW;
}
RtlZeroMemory( Buffer, sizeof(FILE_FS_DEVICE_INFORMATION) );
//
// Set the output buffer
//
Buffer->DeviceType = FILE_DEVICE_DISK;
Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
//
// Adjust the length variable
//
*Length -= sizeof(FILE_FS_DEVICE_INFORMATION);
//
// And return success to our caller
//
return STATUS_SUCCESS;
}
//
// Internal support routine
//
NTSTATUS
RawQueryFsAttributeInfo (
IN PVCB Vcb,
IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
IN OUT PULONG Length
)
/*++
Routine Description:
This routine implements the query volume attribute call
Arguments:
Vcb - Supplies the Vcb being queried
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
Status - Returns the status for the query
--*/
{
ULONG LengthUsed;
UNREFERENCED_PARAMETER( Vcb );
PAGED_CODE();
//
// Check if the buffer we're given is long enough to contain "Raw"
//
LengthUsed = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName[0]) + 6;
if (*Length < LengthUsed) {
return STATUS_BUFFER_OVERFLOW;
}
//
// Set the output buffer
//
Buffer->FileSystemAttributes = 0;
Buffer->MaximumComponentNameLength = 0;
Buffer->FileSystemNameLength = 6;
RtlCopyMemory( &Buffer->FileSystemName[0], L"RAW", 6 );
//
// Adjust the length variable
//
*Length -= LengthUsed;
//
// And return success to our caller
//
return STATUS_SUCCESS;
}