reactos/drivers/filesystems/ffs/src/volinfo.c

479 lines
11 KiB
C
Raw Normal View History

/*
* FFS File System Driver for Windows
*
* volinfo.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSQueryVolumeInformation)
#pragma alloc_text(PAGE, FFSSetVolumeInformation)
#endif
__drv_mustHoldCriticalRegion
NTSTATUS
FFSQueryVolumeInformation(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFFS_VCB Vcb = 0;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
FS_INFORMATION_CLASS FsInformationClass;
ULONG Length;
PVOID Buffer;
BOOLEAN VcbResourceAcquired = FALSE;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
if (!ExAcquireResourceSharedLite(
&Vcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
VcbResourceAcquired = TRUE;
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
FsInformationClass =
IoStackLocation->Parameters.QueryVolume.FsInformationClass;
Length = IoStackLocation->Parameters.QueryVolume.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(Buffer, Length);
switch (FsInformationClass)
{
case FileFsVolumeInformation:
{
PFILE_FS_VOLUME_INFORMATION FsVolInfo;
ULONG VolumeLabelLength;
ULONG RequiredLength;
if (Length < sizeof(FILE_FS_VOLUME_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FsVolInfo = (PFILE_FS_VOLUME_INFORMATION)Buffer;
FsVolInfo->VolumeCreationTime.QuadPart = 0;
FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
FsVolInfo->VolumeLabelLength = VolumeLabelLength;
// I don't know what this means
FsVolInfo->SupportsObjects = FALSE;
RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION)
+ VolumeLabelLength - sizeof(WCHAR);
if (Length < RequiredLength)
{
Irp->IoStatus.Information =
sizeof(FILE_FS_VOLUME_INFORMATION);
Status = STATUS_BUFFER_OVERFLOW;
_SEH2_LEAVE;
}
RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength);
Irp->IoStatus.Information = RequiredLength;
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileFsSizeInformation:
{
PFILE_FS_SIZE_INFORMATION FsSizeInfo;
if (Length < sizeof(FILE_FS_SIZE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FsSizeInfo = (PFILE_FS_SIZE_INFORMATION)Buffer;
{
if (FS_VERSION == 1)
{
FsSizeInfo->TotalAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_size / 8);
FsSizeInfo->AvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8);
}
else
{
FsSizeInfo->TotalAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_size / 8);
FsSizeInfo->AvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8);
}
}
FsSizeInfo->SectorsPerAllocationUnit =
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
FsSizeInfo->BytesPerSector =
Vcb->DiskGeometry.BytesPerSector;
Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileFsDeviceInformation:
{
PFILE_FS_DEVICE_INFORMATION FsDevInfo;
if (Length < sizeof(FILE_FS_DEVICE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FsDevInfo = (PFILE_FS_DEVICE_INFORMATION)Buffer;
FsDevInfo->DeviceType =
Vcb->TargetDeviceObject->DeviceType;
FsDevInfo->Characteristics =
Vcb->TargetDeviceObject->Characteristics;
if (FlagOn(Vcb->Flags, VCB_READ_ONLY))
{
SetFlag(FsDevInfo->Characteristics,
FILE_READ_ONLY_DEVICE);
}
Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
case FileFsAttributeInformation:
{
PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
ULONG RequiredLength;
if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
FsAttrInfo =
(PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
FsAttrInfo->FileSystemAttributes =
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
FsAttrInfo->MaximumComponentNameLength = FFS_NAME_LEN;
FsAttrInfo->FileSystemNameLength = 10;
RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
10 - sizeof(WCHAR);
if (Length < RequiredLength)
{
Irp->IoStatus.Information =
sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
Status = STATUS_BUFFER_OVERFLOW;
_SEH2_LEAVE;
}
RtlCopyMemory(
FsAttrInfo->FileSystemName,
L"FFS\0", 8);
Irp->IoStatus.Information = RequiredLength;
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
#if (_WIN32_WINNT >= 0x0500)
case FileFsFullSizeInformation:
{
PFILE_FS_FULL_SIZE_INFORMATION PFFFSI;
if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
_SEH2_LEAVE;
}
PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION)Buffer;
/*
typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
LARGE_INTEGER TotalAllocationUnits;
LARGE_INTEGER CallerAvailableAllocationUnits;
LARGE_INTEGER ActualAvailableAllocationUnits;
ULONG SectorsPerAllocationUnit;
ULONG BytesPerSector;
} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
*/
{
if (FS_VERSION == 1)
{
PFFFSI->TotalAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_size / 8);
PFFFSI->CallerAvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8);
PFFFSI->ActualAvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8);
}
else
{
PFFFSI->TotalAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_size / 8);
PFFFSI->CallerAvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8);
PFFFSI->ActualAvailableAllocationUnits.QuadPart =
(Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8);
}
}
PFFFSI->SectorsPerAllocationUnit =
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;
Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
#endif // (_WIN32_WINNT >= 0x0500)
default:
Status = STATUS_INVALID_INFO_CLASS;
}
}
_SEH2_FINALLY
{
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
FFSQueueRequest(IrpContext);
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
} _SEH2_END;
return Status;
}
#if !FFS_READ_ONLY
__drv_mustHoldCriticalRegion
NTSTATUS
FFSSetVolumeInformation(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFFS_VCB Vcb;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
FS_INFORMATION_CLASS FsInformationClass;
PAGED_CODE();
_SEH2_TRY
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
Status = STATUS_MEDIA_WRITE_PROTECTED;
_SEH2_LEAVE;
}
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
//Notes: SetVolume is not defined in ntddk.h of win2k ddk,
// But it's same to QueryVolume ....
FsInformationClass =
IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass;
switch (FsInformationClass)
{
case FileFsLabelInformation:
{
PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL;
ULONG VolLabelLen;
UNICODE_STRING LabelName ;
OEM_STRING OemName;
VolLabelInfo = (PFILE_FS_LABEL_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
VolLabelLen = VolLabelInfo->VolumeLabelLength;
if(VolLabelLen > (16 * sizeof(WCHAR)))
{
Status = STATUS_INVALID_VOLUME_LABEL;
_SEH2_LEAVE;
}
RtlCopyMemory(Vcb->Vpb->VolumeLabel,
VolLabelInfo->VolumeLabel,
VolLabelLen);
RtlZeroMemory(Vcb->ffs_super_block->fs_volname, 16);
LabelName.Buffer = VolLabelInfo->VolumeLabel;
LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR);
LabelName.Length = (USHORT)VolLabelLen;
OemName.Buffer = SUPER_BLOCK->fs_volname;
OemName.Length = 0;
OemName.MaximumLength = 16;
FFSUnicodeToOEM(&OemName,
&LabelName);
Vcb->Vpb->VolumeLabelLength =
(USHORT)VolLabelLen;
if (FFSSaveSuper(IrpContext, Vcb))
{
Status = STATUS_SUCCESS;
}
Irp->IoStatus.Information = 0;
}
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
}
}
_SEH2_FINALLY
{
if (!IrpContext->ExceptionInProgress)
{
if (Status == STATUS_PENDING)
{
FFSQueueRequest(IrpContext);
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
} _SEH2_END;
return Status;
}
#endif // !FFS_READ_ONLY