📄 fsctrl.c
字号:
//
if (AllowRawMount) {
try_return( Status = STATUS_WRONG_VOLUME );
}
FatNormalizeAndRaiseStatus( IrpContext, Status );
}
//
// Read in the boot sector
//
SectorSize = (ULONG)Vcb->Bpb.BytesPerSector;
if (SectorSize != DiskGeometry.BytesPerSector) {
try_return( Status = STATUS_WRONG_VOLUME );
}
BootSector = FsRtlAllocatePoolWithTag(NonPagedPoolCacheAligned,
(ULONG) ROUND_TO_PAGES( SectorSize ),
TAG_VERIFY_BOOTSECTOR);
//
// If this verify is on behalf of a DASD open, allow a RAW mount.
//
if (!FatPerformVerifyDiskRead( IrpContext,
Vcb,
BootSector,
0,
SectorSize,
AllowRawMount )) {
try_return( Status = STATUS_WRONG_VOLUME );
}
//
// Call a routine to check the boot sector to see if it is fat.
// If it is not fat then mark the vcb as not mounted tell our
// caller its the wrong volume
//
if (!FatIsBootSectorFat( BootSector )) {
DebugTrace(0, Dbg, "Not a Fat Volume\n", 0);
try_return( Status = STATUS_WRONG_VOLUME );
}
//
// This is a fat volume, so extract serial number and see if it is
// ours.
//
{
ULONG SerialNumber;
if (IsBpbFat32(&BootSector->PackedBpb)) {
CopyUchar4( &SerialNumber, ((PPACKED_BOOT_SECTOR_EX)BootSector)->Id );
} else {
CopyUchar4( &SerialNumber, BootSector->Id );
}
if (SerialNumber != Vpb->SerialNumber) {
DebugTrace(0, Dbg, "Not our serial number\n", 0);
try_return( Status = STATUS_WRONG_VOLUME );
}
}
//
// Make sure the Bpbs are not different. We have to zero out our
// stack version of the Bpb since unpacking leaves holes.
//
RtlZeroMemory( &Bpb, sizeof(BIOS_PARAMETER_BLOCK) );
FatUnpackBios( &Bpb, &BootSector->PackedBpb );
if (Bpb.Sectors != 0) { Bpb.LargeSectors = 0; }
if ( !RtlEqualMemory( &Bpb,
&Vcb->Bpb,
IsBpbFat32(&Bpb) ?
sizeof(BIOS_PARAMETER_BLOCK) :
FIELD_OFFSET(BIOS_PARAMETER_BLOCK,
LargeSectorsPerFat) )) {
DebugTrace(0, Dbg, "Bpb is different\n", 0);
try_return( Status = STATUS_WRONG_VOLUME );
}
//
// Check the volume label. We do this by trying to locate the
// volume label, making two strings one for the saved volume label
// and the other for the new volume label and then we compare the
// two labels.
//
if (FatRootDirectorySize(&Bpb) > 0) {
RootDirectorySize = FatRootDirectorySize(&Bpb);
} else {
RootDirectorySize = FatBytesPerCluster(&Bpb);
}
RootDirectory = FsRtlAllocatePoolWithTag( NonPagedPoolCacheAligned,
(ULONG) ROUND_TO_PAGES( RootDirectorySize ),
TAG_VERIFY_ROOTDIR);
if (!IsBpbFat32(&BootSector->PackedBpb)) {
//
// The Fat12/16 case is simple -- read the root directory in and
// search it.
//
RootDirectoryLbo = FatRootDirectoryLbo(&Bpb);
if (!FatPerformVerifyDiskRead( IrpContext,
Vcb,
RootDirectory,
RootDirectoryLbo,
RootDirectorySize,
AllowRawMount )) {
try_return( Status = STATUS_WRONG_VOLUME );
}
Status = FatSearchBufferForLabel(IrpContext, Vpb,
RootDirectory, RootDirectorySize,
&LabelFound);
if (!NT_SUCCESS(Status)) {
try_return( Status );
}
if (!LabelFound && Vpb->VolumeLabelLength > 0) {
try_return( Status = STATUS_WRONG_VOLUME );
}
} else {
ULONG RootDirectoryCluster;
RootDirectoryCluster = Bpb.RootDirFirstCluster;
while (RootDirectoryCluster != FAT_CLUSTER_LAST) {
RootDirectoryLbo = FatGetLboFromIndex(Vcb, RootDirectoryCluster);
if (!FatPerformVerifyDiskRead( IrpContext,
Vcb,
RootDirectory,
RootDirectoryLbo,
RootDirectorySize,
AllowRawMount )) {
try_return( Status = STATUS_WRONG_VOLUME );
}
Status = FatSearchBufferForLabel(IrpContext, Vpb,
RootDirectory, RootDirectorySize,
&LabelFound);
if (!NT_SUCCESS(Status)) {
try_return( Status );
}
if (LabelFound) {
//
// Found a matching label.
//
break;
}
//
// Set ourselves up for the next loop iteration.
//
FatVerifyLookupFatEntry( IrpContext, Vcb,
RootDirectoryCluster,
&RootDirectoryCluster );
switch (FatInterpretClusterType(Vcb, RootDirectoryCluster)) {
case FatClusterAvailable:
case FatClusterReserved:
case FatClusterBad:
//
// Bail all the way out if we have a bad root.
//
FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
break;
default:
break;
}
}
if (RootDirectoryCluster == FAT_CLUSTER_LAST &&
Vpb->VolumeLabelLength > 0) {
//
// Should have found a label, didn't find any.
//
try_return( Status = STATUS_WRONG_VOLUME );
}
}
try_exit: NOTHING;
//
// Note that we have previously acquired the Vcb to serialize
// the EA file stuff the marking all the Fcbs as NeedToBeVerified.
//
// Put the Ea file back in a virgin state.
//
FatCloseEaFile( IrpContext, Vcb, (BOOLEAN)(Status == STATUS_SUCCESS) );
//
// Mark all Fcbs as needing verification, but only if we really have
// to do it.
//
if (!VerifyAlreadyDone) {
FatMarkFcbCondition( IrpContext, Vcb->RootDcb, FcbNeedsToBeVerified, TRUE );
}
//
// If the verify didn't succeed, get the volume ready for a
// remount or eventual deletion.
//
if (Vcb->VcbCondition == VcbNotMounted) {
//
// If the volume was already in an unmounted state, just bail
// and make sure we return STATUS_WRONG_VOLUME.
//
Status = STATUS_WRONG_VOLUME;
} else if ( Status == STATUS_WRONG_VOLUME ) {
//
// Grab everything so we can safely transition the volume state without
// having a thread stumble into the torn-down allocation engine.
//
FatAcquireExclusiveVolume( IrpContext, Vcb );
ReleaseEntireVolume = TRUE;
//
// Get rid of any cached data, without flushing
//
FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, NoFlush );
//
// Uninitialize the volume file cache map. Note that we cannot
// do a "FatSyncUninit" because of deadlock problems. However,
// since this FileObject is referenced by us, and thus included
// in the Vpb residual count, it is OK to do a normal CcUninit.
//
CcUninitializeCacheMap( Vcb->VirtualVolumeFile,
&FatLargeZero,
NULL );
FatTearDownAllocationSupport( IrpContext, Vcb );
FatSetVcbCondition( Vcb, VcbNotMounted);
ClearVerify = TRUE;
} else if (!VerifyAlreadyDone) {
//
// Grab everything so we can safely transition the volume state without
// having a thread stumble into the torn-down allocation engine.
//
FatAcquireExclusiveVolume( IrpContext, Vcb );
ReleaseEntireVolume = TRUE;
//
// Get rid of any cached data, flushing first.
//
// Future work (and for bonus points, around the other flush points)
// could address the possibility that the dirent filesize hasn't been
// updated yet, causing us to fail the re-verification of a file in
// DetermineAndMark. This is pretty subtle and very very uncommon.
//
FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, Flush );
//
// Flush and Purge the volume file.
//
(VOID)FatFlushFat( IrpContext, Vcb );
CcPurgeCacheSection( &Vcb->SectionObjectPointers, NULL, 0, FALSE );
//
// Redo the allocation support with newly paged stuff.
//
FatTearDownAllocationSupport( IrpContext, Vcb );
FatSetupAllocationSupport( IrpContext, Vcb );
FatCheckDirtyBit( IrpContext, Vcb );
//
// Check for write protected media.
//
if (FatIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject)) {
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED );
} else {
ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED );
}
ClearVerify = TRUE;
}
if (ClearVerify) {
//
// Mark the device as no longer needing verification.
//
ClearFlag( Vpb->RealDevice->Flags, DO_VERIFY_VOLUME );
}
} finally {
DebugUnwind( FatVerifyVolume );
//
// Free any buffer we may have allocated
//
if ( BootSector != NULL ) { ExFreePool( BootSector ); }
if ( RootDirectory != NULL ) { ExFreePool( RootDirectory ); }
//
// Show that we are done with this volume.
//
ASSERT( Vcb->VerifyThread == KeGetCurrentThread() );
Vcb->VerifyThread = NULL;
if (ReleaseEntireVolume) {
FatReleaseVolume( IrpContext, Vcb );
}
FatReleaseVcb( IrpContext, Vcb );
FatReleaseGlobal( IrpContext );
//
// If this was not an abnormal termination, complete the irp.
//
if (!AbnormalTermination()) {
FatCompleteRequest( IrpContext, Irp, Status );
}
DebugTrace(-1, Dbg, "FatVerifyVolume -> %08lx\n", Status);
}
return Status;
}
//
// Local Support Routine
//
BOOLEAN
FatIsBootSectorFat (
IN PPACKED_BOOT_SECTOR BootSector
)
/*++
Routine Description:
This routine checks if the boot sector is for a fat file volume.
Arguments:
BootSector - Supplies the packed boot sector to check
Return Value:
BOOLEAN - TRUE if the volume is Fat and FALSE otherwise.
--*/
{
BOOLEAN Result;
BIOS_PARAMETER_BLOCK Bpb;
DebugTrace(+1, Dbg, "FatIsBootSectorFat, BootSector = %08lx\n", BootSector);
//
// The result is true unless we decide that it should be false
//
Result = TRUE;
//
// Unpack the bios and then test everything
//
FatUnpackBios( &Bpb, &BootSector->PackedBpb );
if (Bpb.Sectors != 0) { Bpb.LargeSectors = 0; }
if ((BootSector->Jump[0] != 0xe9) &&
(BootSector->Jump[0] != 0xeb) &&
(BootSector->Jump[0] != 0x49)) {
Result = FALSE;
//
// Enforce some sanity on the sector size (easy check)
//
} else if ((Bpb.BytesPerSector != 128) &&
(Bpb.BytesPerSector != 256) &&
(Bpb.BytesPerSector != 512) &&
(Bpb.BytesPerSector != 1024) &&
(Bpb.BytesPerSector != 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -