156 lines
4.8 KiB
C
156 lines
4.8 KiB
C
/*++
|
|
|
|
Copyright (c) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
volinfo.c
|
|
|
|
Abstract:
|
|
|
|
This module implements routines related to handling
|
|
IRP_MJ_QUERY_VOLUME_INFORMATION.
|
|
|
|
--*/
|
|
|
|
#include "fatx.h"
|
|
|
|
NTSTATUS
|
|
FatxFsdQueryVolumeInformation(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by the I/O manager to handle
|
|
IRP_MJ_QUERY_VOLUME_INFORMATION requests.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Specifies the device object that the I/O request is for.
|
|
|
|
Irp - Specifies the packet that describes the I/O request.
|
|
|
|
Return Value:
|
|
|
|
Status of operation.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PFAT_VOLUME_EXTENSION VolumeExtension;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
ULONG BytesWritten;
|
|
PFILE_FS_VOLUME_INFORMATION VolumeInformation;
|
|
PFILE_FS_SIZE_INFORMATION SizeInformation;
|
|
PFILE_FS_DEVICE_INFORMATION DeviceInformation;
|
|
PFILE_FS_ATTRIBUTE_INFORMATION AttributeInformation;
|
|
|
|
VolumeExtension = (PFAT_VOLUME_EXTENSION)DeviceObject->DeviceExtension;
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
FatxAcquireVolumeMutexShared(VolumeExtension);
|
|
|
|
//
|
|
// Check if the volume has been dismounted.
|
|
//
|
|
|
|
if (FatxIsFlagSet(VolumeExtension->Flags, FAT_VOLUME_DISMOUNTED)) {
|
|
status = STATUS_VOLUME_DISMOUNTED;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
//
|
|
// Clear the output buffer.
|
|
//
|
|
|
|
RtlZeroMemory(Irp->UserBuffer, IrpSp->Parameters.QueryVolume.Length);
|
|
|
|
//
|
|
// Dispatch the information class function.
|
|
//
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
|
|
|
|
case FileFsVolumeInformation:
|
|
VolumeInformation = (PFILE_FS_VOLUME_INFORMATION)Irp->UserBuffer;
|
|
VolumeInformation->VolumeSerialNumber = VolumeExtension->SerialNumber;
|
|
BytesWritten = FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel);
|
|
break;
|
|
|
|
case FileFsSizeInformation:
|
|
SizeInformation = (PFILE_FS_SIZE_INFORMATION)Irp->UserBuffer;
|
|
SizeInformation->TotalAllocationUnits.QuadPart =
|
|
VolumeExtension->NumberOfClusters;
|
|
SizeInformation->AvailableAllocationUnits.QuadPart =
|
|
VolumeExtension->NumberOfClustersAvailable;
|
|
SizeInformation->SectorsPerAllocationUnit =
|
|
VolumeExtension->BytesPerCluster >> VolumeExtension->SectorShift;
|
|
SizeInformation->BytesPerSector = VolumeExtension->SectorSize;
|
|
BytesWritten = sizeof(FILE_FS_SIZE_INFORMATION);
|
|
break;
|
|
|
|
case FileFsDeviceInformation:
|
|
DeviceInformation = (PFILE_FS_DEVICE_INFORMATION)Irp->UserBuffer;
|
|
DeviceInformation->DeviceType =
|
|
VolumeExtension->TargetDeviceObject->DeviceType;
|
|
DeviceInformation->Characteristics = 0;
|
|
BytesWritten = sizeof(FILE_FS_DEVICE_INFORMATION);
|
|
break;
|
|
|
|
case FileFsAttributeInformation:
|
|
AttributeInformation =
|
|
(PFILE_FS_ATTRIBUTE_INFORMATION)Irp->UserBuffer;
|
|
AttributeInformation->FileSystemAttributes = 0;
|
|
AttributeInformation->MaximumComponentNameLength =
|
|
FAT_FILE_NAME_LENGTH;
|
|
AttributeInformation->FileSystemNameLength = sizeof(OCHAR) * 4;
|
|
|
|
if (IrpSp->Parameters.QueryVolume.Length <
|
|
FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName) +
|
|
sizeof(OCHAR) * 4) {
|
|
BytesWritten = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION,
|
|
FileSystemName);
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
} else {
|
|
RtlCopyMemory(AttributeInformation->FileSystemName, OTEXT("FATX"),
|
|
sizeof(OCHAR) * 4);
|
|
BytesWritten = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION,
|
|
FileSystemName) + sizeof(OCHAR) * 4;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
BytesWritten = 0;
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Fill in the number of bytes that we wrote to the user's buffer.
|
|
//
|
|
|
|
Irp->IoStatus.Information = BytesWritten;
|
|
|
|
//
|
|
// Check that we didn't overflow the user's buffer. The I/O manager does
|
|
// the initial check to make sure there's enough space for the static
|
|
// structure for a given information class, but we might overflow the buffer
|
|
// when copying in the variable length file name.
|
|
//
|
|
|
|
ASSERT(Irp->IoStatus.Information <= IrpSp->Parameters.QueryVolume.Length);
|
|
|
|
CleanupAndExit:
|
|
FatxReleaseVolumeMutex(VolumeExtension);
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|