--- /dev/null
+/*
+ * 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