VfatHasFileSystem(
PDEVICE_OBJECT DeviceToMount,
PBOOLEAN RecognizedFS,
- PFATINFO pFatInfo)
+ PFATINFO pFatInfo,
+ BOOLEAN Override)
{
NTSTATUS Status;
PARTITION_INFORMATION PartitionInfo;
0,
&DiskGeometry,
&Size,
- FALSE);
+ Override);
if (!NT_SUCCESS(Status))
{
- DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
+ DPRINT("VfatBlockDeviceIoControl failed (%x)\n", Status);
return Status;
}
0,
&PartitionInfo,
&Size,
- FALSE);
+ Override);
if (!NT_SUCCESS(Status))
{
- DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
+ DPRINT("VfatBlockDeviceIoControl failed (%x)\n", Status);
return Status;
}
*RecognizedFS = TRUE;
}
}
- else if (DiskGeometry.MediaType == Unknown)
- {
- /*
- * Floppy disk driver can return Unknown as media type if it
- * doesn't know yet what floppy in the drive really is. This is
- * perfectly correct to do under Windows.
- */
- *RecognizedFS = TRUE;
- DiskGeometry.BytesPerSector = 512;
- }
else
{
*RecognizedFS = TRUE;
Offset.QuadPart = 0;
/* Try to recognize FAT12/FAT16/FAT32 partitions */
- Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, FALSE);
+ Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, Override);
if (NT_SUCCESS(Status))
{
if (Boot->Signatur1 != 0xaa55)
DPRINT("FAT12\n");
FatInfo.FatType = FAT12;
FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
+ RtlCopyMemory(&FatInfo.VolumeLabel, &Boot->VolumeLabel, sizeof(FatInfo.VolumeLabel));
}
else if (FatInfo.NumberOfClusters >= 65525)
{
FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster;
FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster);
FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID;
+ RtlCopyMemory(&FatInfo.VolumeLabel, &((struct _BootSector32*)Boot)->VolumeLabel, sizeof(FatInfo.VolumeLabel));
}
else
{
DPRINT("FAT16\n");
FatInfo.FatType = FAT16;
FatInfo.RootCluster = FatInfo.rootStart / FatInfo.SectorsPerCluster;
+ RtlCopyMemory(&FatInfo.VolumeLabel, &Boot->VolumeLabel, sizeof(FatInfo.VolumeLabel));
}
if (PartitionInfoIsValid &&
Offset.QuadPart = 0;
/* Try to recognize FATX16/FATX32 partitions (Xbox) */
- Status = VfatReadDisk(DeviceToMount, &Offset, sizeof(struct _BootSectorFatX), (PUCHAR) BootFatX, FALSE);
+ Status = VfatReadDisk(DeviceToMount, &Offset, sizeof(struct _BootSectorFatX), (PUCHAR) BootFatX, Override);
if (NT_SUCCESS(Status))
{
*RecognizedFS = TRUE;
return Status;
}
-/*
- * FUNCTION: Mounts the device
- */
-static
-NTSTATUS
-VfatMountDevice(
- PDEVICE_EXTENSION DeviceExt,
- PDEVICE_OBJECT DeviceToMount)
-{
- NTSTATUS Status;
- BOOLEAN RecognizedFS;
-
- DPRINT("Mounting VFAT device...\n");
-
- Status = VfatHasFileSystem(DeviceToMount, &RecognizedFS, &DeviceExt->FatInfo);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- DPRINT("MountVfatdev %u, PAGE_SIZE = %d\n", DeviceExt->FatInfo.BytesPerCluster, PAGE_SIZE);
-
- return STATUS_SUCCESS;
-}
-
/*
* FUNCTION: Mount the filesystem
DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
Vpb = IrpContext->Stack->Parameters.MountVolume.Vpb;
- Status = VfatHasFileSystem(DeviceToMount, &RecognizedFS, &FatInfo);
+ Status = VfatHasFileSystem(DeviceToMount, &RecognizedFS, &FatInfo, FALSE);
if (!NT_SUCCESS(Status))
{
goto ByeBye;
{
HashTableSize = 65537; // 65536 = 64 * 1024;
}
- HashTableSize = FCB_HASH_TABLE_SIZE;
DPRINT("VFAT: Recognized volume\n");
Status = IoCreateDevice(VfatGlobalData->DriverObject,
ROUND_UP(sizeof (DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize,
RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize);
DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)));
DeviceExt->HashTableSize = HashTableSize;
+ DeviceExt->VolumeDevice = DeviceObject;
/* use same vpb as device disk */
DeviceObject->Vpb = Vpb;
DeviceToMount->Vpb = Vpb;
- Status = VfatMountDevice(DeviceExt, DeviceToMount);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: delete device object */
- goto ByeBye;
- }
+ RtlCopyMemory(&DeviceExt->FatInfo, &FatInfo, sizeof(FATINFO));
DPRINT("BytesPerSector: %u\n", DeviceExt->FatInfo.BytesPerSector);
DPRINT("SectorsPerCluster: %u\n", DeviceExt->FatInfo.SectorsPerCluster);
/* Initialize this resource early ... it's used in VfatCleanup */
ExInitializeResourceLite(&DeviceExt->DirResource);
+ DeviceExt->IoVPB = DeviceObject->Vpb;
+ DeviceExt->SpareVPB = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), TAG_VFAT);
+ if (DeviceExt->SpareVPB == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto ByeBye;
+ }
+
DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
Fcb = vfatNewFCB(DeviceExt, &NameU);
if (Fcb == NULL)
}
VolumeFcb->Flags = FCB_IS_VOLUME;
- VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
+ VolumeFcb->RFCB.FileSize.QuadPart = (LONGLONG) DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;
VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize;
DeviceExt->VolumeFcb = VolumeFcb;
/* Cleanup */
if (DeviceExt && DeviceExt->FATFileObject)
ObDereferenceObject (DeviceExt->FATFileObject);
+ if (DeviceExt && DeviceExt->SpareVPB)
+ ExFreePoolWithTag(DeviceExt->SpareVPB, TAG_VFAT);
if (Fcb)
vfatDestroyFCB(Fcb);
if (Ccb)
PVFAT_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceToVerify;
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
FATINFO FatInfo;
BOOLEAN RecognizedFS;
- PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt;
+ PDEVICE_EXTENSION DeviceExt;
+ BOOLEAN AllowRaw;
+ PVPB Vpb;
+ ULONG ChangeCount, BufSize = sizeof(ChangeCount);
DPRINT("VfatVerify(IrpContext %p)\n", IrpContext);
DeviceToVerify = IrpContext->Stack->Parameters.VerifyVolume.DeviceObject;
- Status = VfatBlockDeviceIoControl(DeviceToVerify,
+ DeviceExt = DeviceToVerify->DeviceExtension;
+ Vpb = IrpContext->Stack->Parameters.VerifyVolume.Vpb;
+ AllowRaw = BooleanFlagOn(IrpContext->Stack->Flags, SL_ALLOW_RAW_MOUNT);
+
+ if (!BooleanFlagOn(Vpb->RealDevice->Flags, DO_VERIFY_VOLUME))
+ {
+ DPRINT("Already verified\n");
+ return STATUS_SUCCESS;
+ }
+
+ Status = VfatBlockDeviceIoControl(DeviceExt->StorageDevice,
IOCTL_DISK_CHECK_VERIFY,
NULL,
0,
- NULL,
- 0,
+ &ChangeCount,
+ &BufSize,
TRUE);
- DeviceToVerify->Flags &= ~DO_VERIFY_VOLUME;
if (!NT_SUCCESS(Status) && Status != STATUS_VERIFY_REQUIRED)
{
DPRINT("VfatBlockDeviceIoControl() failed (Status %lx)\n", Status);
- Status = STATUS_WRONG_VOLUME;
+ Status = (AllowRaw ? STATUS_WRONG_VOLUME : Status);
}
else
{
- Status = VfatHasFileSystem(DeviceToVerify, &RecognizedFS, &FatInfo);
+ Status = VfatHasFileSystem(DeviceExt->StorageDevice, &RecognizedFS, &FatInfo, TRUE);
if (!NT_SUCCESS(Status) || RecognizedFS == FALSE)
{
- Status = STATUS_WRONG_VOLUME;
+ if (NT_SUCCESS(Status) || AllowRaw)
+ Status = STATUS_WRONG_VOLUME;
}
else if (sizeof(FATINFO) == RtlCompareMemory(&FatInfo, &DeviceExt->FatInfo, sizeof(FATINFO)))
{
+ DPRINT1("Same volume\n");
/*
* FIXME:
- * Preformated floppy disks have very often a serial number of 0000:0000.
+ * Preformatted floppy disks have very often a serial number of 0000:0000.
* We should calculate a crc sum over the sectors from the root directory as secondary volume number.
* Each write to the root directory must update this crc sum.
*/
+ /* HACK */
+ if (!FatInfo.FixedMedia && FatInfo.FatType >= FATX16)
+ {
+ Status = STATUS_WRONG_VOLUME;
+ }
}
else
{
}
}
+ Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME;
+
return Status;
}
PDEVICE_EXTENSION DeviceExt;
PLIST_ENTRY NextEntry;
PVFATFCB Fcb;
+ PFILE_OBJECT FileObject;
+ ULONG eocMark;
+ NTSTATUS Status;
DPRINT("VfatDismountVolume(%p)\n", IrpContext);
DeviceExt = IrpContext->DeviceExt;
+ FileObject = IrpContext->FileObject;
/* We HAVE to be locked. Windows also allows dismount with no lock
* but we're here mainly for 1st stage, so KISS
ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
- /* Browse all the available FCBs first, and force data writing to disk */
- for (NextEntry = DeviceExt->FcbListHead.Flink;
- NextEntry != &DeviceExt->FcbListHead;
- NextEntry = NextEntry->Flink)
+ if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY)
{
- Fcb = CONTAINING_RECORD(NextEntry, VFATFCB, FcbListEntry);
-
- ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
- ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
-
- if (Fcb->FileObject)
+ /* Set clean shutdown bit */
+ Status = GetNextCluster(DeviceExt, 1, &eocMark);
+ if (NT_SUCCESS(Status))
{
- if (Fcb->Flags & FCB_IS_DIRTY)
- {
- VfatUpdateEntry(Fcb);
- }
-
- CcPurgeCacheSection(Fcb->FileObject->SectionObjectPointer, NULL, 0, FALSE);
- CcUninitializeCacheMap(Fcb->FileObject, &Fcb->RFCB.FileSize, NULL);
+ eocMark |= DeviceExt->CleanShutBitMask;
+ if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark)))
+ DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
}
-
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- ExReleaseResourceLite(&Fcb->MainResource);
}
+ /* Flush volume & files */
+ VfatFlushVolume(DeviceExt, (PVFATFCB)FileObject->FsContext);
+
/* Rebrowse the FCB in order to free them now */
while (!IsListEmpty(&DeviceExt->FcbListHead))
{
/* Mark we're being dismounted */
DeviceExt->Flags |= VCB_DISMOUNT_PENDING;
+#ifndef ENABLE_SWAPOUT
IrpContext->DeviceObject->Vpb->Flags &= ~VPB_MOUNTED;
+#endif
ExReleaseResourceLite(&DeviceExt->FatResource);
break;
}
- IrpContext->Irp->IoStatus.Status = Status;
-
- IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
- VfatFreeIrpContext(IrpContext);
return Status;
}