FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster;
FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster);
FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID;
+ FatInfo.FSInfoSector = ((struct _BootSector32*) Boot)->FSInfoSector;
RtlCopyMemory(&FatInfo.VolumeLabel, &((struct _BootSector32*)Boot)->VolumeLabel, sizeof(FatInfo.VolumeLabel));
}
else
UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
UNICODE_STRING VolumeLabelU;
ULONG HashTableSize;
- ULONG eocMark;
ULONG i;
FATINFO FatInfo;
+ BOOLEAN Dirty;
DPRINT("VfatMount(IrpContext %p)\n", IrpContext);
DeviceExt->GetNextCluster = FAT12GetNextCluster;
DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
DeviceExt->WriteCluster = FAT12WriteCluster;
- DeviceExt->CleanShutBitMask = 0;
+ /* We don't define dirty bit functions here
+ * FAT12 doesn't have such bit and they won't get called
+ */
break;
case FAT16:
DeviceExt->GetNextCluster = FAT16GetNextCluster;
DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
DeviceExt->WriteCluster = FAT16WriteCluster;
- DeviceExt->CleanShutBitMask = 0x8000;
+ DeviceExt->GetDirtyStatus = FAT16GetDirtyStatus;
+ DeviceExt->SetDirtyStatus = FAT16SetDirtyStatus;
break;
case FAT32:
DeviceExt->GetNextCluster = FAT32GetNextCluster;
DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
DeviceExt->WriteCluster = FAT32WriteCluster;
- DeviceExt->CleanShutBitMask = 0x80000000;
+ DeviceExt->GetDirtyStatus = FAT32GetDirtyStatus;
+ DeviceExt->SetDirtyStatus = FAT32SetDirtyStatus;
break;
}
DeviceExt->Statistics = ExAllocatePoolWithTag(NonPagedPool,
sizeof(STATISTICS) * VfatGlobalData->NumberProcessors,
- TAG_VFAT);
+ TAG_STATS);
if (DeviceExt->Statistics == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH2_END;
DeviceExt->LastAvailableCluster = 2;
+ CountAvailableClusters(DeviceExt, NULL);
ExInitializeResourceLite(&DeviceExt->FatResource);
InitializeListHead(&DeviceExt->FcbListHead);
ReadVolumeLabel(DeviceExt, 0, vfatVolumeIsFatX(DeviceExt), &VolumeLabelU);
Vpb->VolumeLabelLength = VolumeLabelU.Length;
- /* read clean shutdown bit status */
- Status = GetNextCluster(DeviceExt, 1, &eocMark);
+ /* read dirty bit status */
+ Status = GetDirtyStatus(DeviceExt, &Dirty);
if (NT_SUCCESS(Status))
{
- if (eocMark & DeviceExt->CleanShutBitMask)
+ /* The volume wasn't dirty, it was properly dismounted */
+ if (!Dirty)
{
- /* unset clean shutdown bit */
- eocMark &= ~DeviceExt->CleanShutBitMask;
- WriteCluster(DeviceExt, 1, eocMark);
+ /* Mark it dirty now! */
+ SetDirtyStatus(DeviceExt, TRUE);
VolumeFcb->Flags |= VCB_CLEAR_DIRTY;
}
+ else
+ {
+ DPRINT1("Mounting a dirty volume\n");
+ }
}
VolumeFcb->Flags |= VCB_IS_DIRTY;
+ if (BooleanFlagOn(Vpb->RealDevice->Flags, DO_SYSTEM_BOOT_PARTITION))
+ {
+ SetFlag(DeviceExt->Flags, VCB_IS_SYS_OR_HAS_PAGE);
+ }
FsRtlNotifyVolumeEvent(DeviceExt->FATFileObject, FSRTL_VOLUME_MOUNT);
FsRtlNotifyInitializeSync(&DeviceExt->NotifySync);
if (DeviceExt && DeviceExt->SpareVPB)
ExFreePoolWithTag(DeviceExt->SpareVPB, TAG_VFAT);
if (DeviceExt && DeviceExt->Statistics)
- ExFreePoolWithTag(DeviceExt->Statistics, TAG_VFAT);
+ ExFreePoolWithTag(DeviceExt->Statistics, TAG_STATS);
if (Fcb)
vfatDestroyFCB(Fcb);
if (Ccb)
VfatMarkVolumeDirty(
PVFAT_IRP_CONTEXT IrpContext)
{
- ULONG eocMark;
PDEVICE_EXTENSION DeviceExt;
NTSTATUS Status = STATUS_SUCCESS;
if (!BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY))
{
- Status = GetNextCluster(DeviceExt, 1, &eocMark);
- if (NT_SUCCESS(Status))
- {
- /* unset clean shutdown bit */
- eocMark &= ~DeviceExt->CleanShutBitMask;
- Status = WriteCluster(DeviceExt, 1, eocMark);
- }
+ Status = SetDirtyStatus(DeviceExt, TRUE);
}
DeviceExt->VolumeFcb->Flags &= ~VCB_CLEAR_DIRTY;
{
PLIST_ENTRY ListEntry;
+#if 1
+ /* FIXME: Hack that allows locking the system volume on
+ * boot so that autochk can run properly
+ * That hack is, on purpose, really restrictive
+ * it will only allow locking with two directories
+ * open: current directory of smss and autochk.
+ */
+ BOOLEAN ForceLock = TRUE;
+ ULONG HandleCount = 0;
+
+ /* Only allow boot volume */
+ if (BooleanFlagOn(DeviceExt->Flags, VCB_IS_SYS_OR_HAS_PAGE))
+ {
+ /* We'll browse all the FCB */
+ ListEntry = DeviceExt->FcbListHead.Flink;
+ while (ListEntry != &DeviceExt->FcbListHead)
+ {
+ Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
+ ListEntry = ListEntry->Flink;
+
+ /* If no handle: that FCB is no problem for locking
+ * so ignore it
+ */
+ if (Fcb->OpenHandleCount == 0)
+ {
+ continue;
+ }
+
+ /* Not a dir? We're no longer at boot */
+ if (!vfatFCBIsDirectory(Fcb))
+ {
+ ForceLock = FALSE;
+ break;
+ }
+
+ /* If we have cached initialized and several handles, we're
+ not in the boot case
+ */
+ if (Fcb->FileObject != NULL && Fcb->OpenHandleCount > 1)
+ {
+ ForceLock = FALSE;
+ break;
+ }
+
+ /* Count the handles */
+ HandleCount += Fcb->OpenHandleCount;
+ /* More than two handles? Then, we're not booting anymore */
+ if (HandleCount > 2)
+ {
+ ForceLock = FALSE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ ForceLock = FALSE;
+ }
+
+ /* Here comes the hack, ignore the failure! */
+ if (!ForceLock)
+ {
+#endif
+
DPRINT1("Can't lock: %u opened\n", DeviceExt->OpenHandleCount);
ListEntry = DeviceExt->FcbListHead.Flink;
}
return STATUS_ACCESS_DENIED;
+
+#if 1
+ /* End of the hack: be verbose about its usage,
+ * just in case we would mess up everything!
+ */
+ }
+ else
+ {
+ DPRINT1("HACK: Using lock-hack!\n");
+ }
+#endif
}
/* Finally, proceed */
PLIST_ENTRY NextEntry;
PVFATFCB Fcb;
PFILE_OBJECT FileObject;
- ULONG eocMark;
- NTSTATUS Status;
DPRINT("VfatDismountVolume(%p)\n", IrpContext);
return STATUS_ACCESS_DENIED;
}
+ /* Deny dismount of boot volume */
+ if (BooleanFlagOn(DeviceExt->Flags, VCB_IS_SYS_OR_HAS_PAGE))
+ {
+ return STATUS_ACCESS_DENIED;
+ }
+
/* Race condition? */
if (BooleanFlagOn(DeviceExt->Flags, VCB_DISMOUNT_PENDING))
{
ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
+ /* We're performing a clean shutdown */
if (BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_CLEAR_DIRTY))
{
- /* Set clean shutdown bit */
- Status = GetNextCluster(DeviceExt, 1, &eocMark);
- if (NT_SUCCESS(Status))
- {
- eocMark |= DeviceExt->CleanShutBitMask;
- if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark)))
- DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
- }
+ /* Drop the dirty bit */
+ if (NT_SUCCESS(SetDirtyStatus(DeviceExt, FALSE)))
+ DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
}
/* Flush volume & files */
ExReleaseResourceLite(&DeviceExt->FatResource);
/* Release a few resources and quit, we're done */
+ ExFreePoolWithTag(DeviceExt->Statistics, TAG_STATS);
ExDeleteResourceLite(&DeviceExt->DirResource);
ExDeleteResourceLite(&DeviceExt->FatResource);
ObDereferenceObject(DeviceExt->FATFileObject);