📄 verfysup.c
字号:
(PVOID)Sector,
WriteLength,
&Offset,
NULL );
if ( Irp == NULL ) {
try_return(NOTHING);
}
//
// Make this operation write-through. It never hurts to try to be
// safer about this, even though we aren't logged.
//
SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_WRITE_THROUGH );
//
// Set up the completion routine
//
IoSetCompletionRoutine( Irp,
FatMarkVolumeCompletionRoutine,
&Event,
TRUE,
TRUE,
TRUE );
//
// Call the device to do the write and wait for it to finish.
// Igmore any return status.
//
Status = IoCallDriver( Vcb->TargetDeviceObject, Irp );
if (Status == STATUS_PENDING) {
(VOID)KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
}
try_exit: NOTHING;
} finally {
//
// Clean up the Irp and Mdl
//
if (Irp) {
//
// If there is an MDL (or MDLs) associated with this I/O
// request, Free it (them) here. This is accomplished by
// walking the MDL list hanging off of the IRP and deallocating
// each MDL encountered.
//
while (Irp->MdlAddress != NULL) {
PMDL NextMdl;
NextMdl = Irp->MdlAddress->Next;
MmUnlockPages( Irp->MdlAddress );
IoFreeMdl( Irp->MdlAddress );
Irp->MdlAddress = NextMdl;
}
IoFreeIrp( Irp );
}
if (Bcb != NULL) {
FatUnpinBcb( IrpContext, Bcb );
}
}
}
if (!abort) {
//
// Flip the dirty bit in the FAT
//
if (VolumeState == VolumeDirty) {
FatSetFatEntry( IrpContext, Vcb, FAT_DIRTY_BIT_INDEX, FAT_DIRTY_VOLUME);
} else {
FatSetFatEntry( IrpContext, Vcb, FAT_DIRTY_BIT_INDEX, FAT_CLEAN_VOLUME);
}
}
DebugTrace(-1, Dbg, "FatMarkVolume -> VOID\n", 0);
return;
}
VOID
FatFspMarkVolumeDirtyWithRecover(
PVOID Parameter
)
/*++
Routine Description:
This is the routine that performs the actual FatMarkVolume Dirty call
on a paging file Io that encounters a media error. It is responsible
for completing the PagingIo Irp as soon as this is done.
Note: this routine (and thus FatMarkVolume()) must be resident as
the paging file might be damaged at this point.
Arguments:
Parameter - Points to a dirty volume packet that was allocated from pool
Return Value:
None.
--*/
{
PCLEAN_AND_DIRTY_VOLUME_PACKET Packet;
PVCB Vcb;
IRP_CONTEXT IrpContext;
PIRP Irp;
BOOLEAN VcbExists = FALSE;
DebugTrace(+1, Dbg, "FatDeferredCleanVolume\n", 0);
Packet = (PCLEAN_AND_DIRTY_VOLUME_PACKET)Parameter;
Vcb = Packet->Vcb;
Irp = Packet->Irp;
//
// Dummy up the IrpContext so we can call our worker routines
//
RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT));
SetFlag(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT);
IrpContext.OriginatingIrp = Irp;
//
// Make us appear as a top level FSP request so that we will
// receive any errors from the operation.
//
IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );
//
// Try to write out the dirty bit. If something goes wrong, we
// tried.
//
try {
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY );
FatMarkVolume( &IrpContext, Vcb, VolumeDirtyWithSurfaceTest );
} except(FatExceptionFilter( &IrpContext, GetExceptionInformation() )) {
NOTHING;
}
IoSetTopLevelIrp( NULL );
//
// Now complete the originating Irp or set the synchronous event.
//
if (Packet->Event) {
KeSetEvent( Packet->Event, 0, FALSE );
} else {
IoCompleteRequest( Irp, IO_DISK_INCREMENT );
}
}
VOID
FatCheckDirtyBit (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
)
/*++
Routine Description:
This routine looks at the volume dirty bit, and depending on the state of
VCB_STATE_FLAG_MOUNTED_DIRTY, the appropriate action is taken.
Arguments:
Vcb - Supplies the Vcb being queried.
Return Value:
None.
--*/
{
BOOLEAN Dirty;
PPACKED_BOOT_SECTOR BootSector;
PBCB BootSectorBcb;
UNICODE_STRING VolumeLabel;
//
// Look in the boot sector
//
FatReadVolumeFile( IrpContext,
Vcb,
0,
sizeof(PACKED_BOOT_SECTOR),
&BootSectorBcb,
(PVOID *)&BootSector );
try {
//
// Check if the magic bit is set
//
if (IsBpbFat32(&BootSector->PackedBpb)) {
Dirty = BooleanFlagOn( ((PPACKED_BOOT_SECTOR_EX)BootSector)->CurrentHead,
FAT_BOOT_SECTOR_DIRTY );
} else {
Dirty = BooleanFlagOn( BootSector->CurrentHead, FAT_BOOT_SECTOR_DIRTY );
}
//
// Setup the VolumeLabel string
//
VolumeLabel.Length = Vcb->Vpb->VolumeLabelLength;
VolumeLabel.MaximumLength = MAXIMUM_VOLUME_LABEL_LENGTH;
VolumeLabel.Buffer = &Vcb->Vpb->VolumeLabel[0];
if ( Dirty ) {
//
// Do not trigger the mounted dirty bit if this is a verify
// and the volume is a boot or paging device. We know that
// a boot or paging device cannot leave the system, and thus
// that on its mount we will have figured this out correctly.
//
// This logic is a reasonable hack-o-rama to make BillG happy
// since his machine ran chkdsk after he installed Beta 3. Why?
// 'cause setup cracked a non-exclusive DASD handle near the
// end of setup, wrote some data, closed the handle and we
// set the verify bit ... came back around and saw that other
// arbitrary activity had left the volume in a temporarily dirty
// state.
//
// Of course, the real problem is that we don't have a journal.
//
if (!(IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
IrpContext->MinorFunction == IRP_MN_VERIFY_VOLUME &&
FlagOn( Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE))) {
KdPrintEx((DPFLTR_FASTFAT_ID,
DPFLTR_INFO_LEVEL,
"FASTFAT: WARNING! Mounting Dirty Volume %Z\n",
&VolumeLabel));
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY );
}
} else {
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {
KdPrintEx((DPFLTR_FASTFAT_ID,
DPFLTR_INFO_LEVEL,
"FASTFAT: Volume %Z has been cleaned.\n",
&VolumeLabel));
ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY );
} else {
(VOID)FsRtlBalanceReads( Vcb->TargetDeviceObject );
}
}
} finally {
FatUnpinBcb( IrpContext, BootSectorBcb );
}
}
VOID
FatVerifyOperationIsLegal (
IN PIRP_CONTEXT IrpContext
)
/*++
Routine Description:
This routine determines is the requested operation should be allowed to
continue. It either returns to the user if the request is Okay, or
raises an appropriate status.
Arguments:
Irp - Supplies the Irp to check
Return Value:
None.
--*/
{
PIRP Irp;
PFILE_OBJECT FileObject;
Irp = IrpContext->OriginatingIrp;
//
// If the Irp is not present, then we got here via close.
//
//
if ( Irp == NULL ) {
return;
}
FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
//
// If there is not a file object, we cannot continue.
//
if ( FileObject == NULL ) {
return;
}
//
// If the file object has already been cleaned up, and
//
// A) This request is a paging io read or write, or
// B) This request is a close operation, or
// C) This request is a set or query info call (for Lou)
// D) This is an MDL complete
//
// let it pass, otherwise return STATUS_FILE_CLOSED.
//
if ( FlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE) ) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
if ( (FlagOn(Irp->Flags, IRP_PAGING_IO)) ||
(IrpSp->MajorFunction == IRP_MJ_CLOSE ) ||
(IrpSp->MajorFunction == IRP_MJ_SET_INFORMATION) ||
(IrpSp->MajorFunction == IRP_MJ_QUERY_INFORMATION) ||
( ( (IrpSp->MajorFunction == IRP_MJ_READ) ||
(IrpSp->MajorFunction == IRP_MJ_WRITE) ) &&
FlagOn(IrpSp->MinorFunction, IRP_MN_COMPLETE) ) ) {
NOTHING;
} else {
FatRaiseStatus( IrpContext, STATUS_FILE_CLOSED );
}
}
return;
}
//
// Internal support routine
//
VOID
FatResetFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
)
/*++
Routine Description:
This routine is called when an Fcb has been marked as needs to be verified.
It does the following tasks:
- Reset Mcb mapping information
- For directories, reset dirent hints
- Set allocation size to unknown
Arguments:
Fcb - Supplies the Fcb to reset
Return Value:
None.
--*/
{
//
// Don't do the two following operations for the Root Dcb
// or paging files. Paging files!? Yes, if someone diddles
// a volume we try to reverify all of the Fcbs just in case;
// however, there is no safe way to chuck and retrieve the
// mapping pair information for the paging file. Lose it and
// die.
//
if ( NodeType(Fcb) != FAT_NTC_ROOT_DCB &&
!FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
//
// Reset the mcb mapping.
//
FsRtlRemoveLargeMcbEntry( &Fcb->Mcb, 0, 0xFFFFFFFF );
//
// Reset the allocation size to 0 or unknown
//
if ( Fcb->FirstClusterOfFile == 0 ) {
Fcb->Header.AllocationSize.QuadPart = 0;
} else {
Fcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
}
}
//
// If this is a directory, reset the hints.
//
if ( (NodeType(Fcb) == FAT_NTC_DCB) ||
(NodeType(Fcb) == FAT_NTC_ROOT_DCB) ) {
//
// Force a rescan of the directory
//
Fcb->Specific.Dcb.UnusedDirentVbo = 0xffffffff;
Fcb->Specific.Dcb.DeletedDirentHint = 0xffffffff;
}
}
//
// Internal support routine
//
VOID
FatDetermineAndMarkFcbCondition (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
)
/*++
Routine Description:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -