📄 verfysup.c
字号:
This routine checks a specific Fcb to see if it is different from what's
on the disk. The following things are checked:
- File Name
- File Size (if not directory)
- First Cluster Of File
- Dirent Attributes
Arguments:
Fcb - Supplies the Fcb to examine
Return Value:
None.
--*/
{
PDIRENT Dirent;
PBCB DirentBcb;
ULONG FirstClusterOfFile;
OEM_STRING Name;
CHAR Buffer[16];
//
// If this is the Root Dcb, special case it. That is, we know
// by definition that it is good since it is fixed in the volume
// structure.
//
if ( NodeType(Fcb) == FAT_NTC_ROOT_DCB ) {
FatResetFcb( IrpContext, Fcb );
FatMarkFcbCondition( IrpContext, Fcb, FcbGood, FALSE );
return;
}
// The first thing we need to do to verify ourselves is
// locate the dirent on the disk.
//
FatGetDirentFromFcbOrDcb( IrpContext,
Fcb,
TRUE,
&Dirent,
&DirentBcb );
//
// If we couldn't get the dirent, this fcb must be bad (case of
// enclosing directory shrinking during the time it was ejected).
//
if (DirentBcb == NULL) {
FatMarkFcbCondition( IrpContext, Fcb, FcbBad, TRUE );
return;
}
//
// We located the dirent for ourselves now make sure it
// is really ours by comparing the Name and FatFlags.
// Then for a file we also check the file size.
//
// Note that we have to unpin the Bcb before calling FatResetFcb
// in order to avoid a deadlock in CcUninitializeCacheMap.
//
try {
Name.MaximumLength = 16;
Name.Buffer = &Buffer[0];
Fat8dot3ToString( IrpContext, Dirent, FALSE, &Name );
//
// We need to calculate the first cluster 'cause FAT32 splits
// this field across the dirent.
//
FirstClusterOfFile = Dirent->FirstClusterOfFile;
if (FatIsFat32( Fcb->Vcb )) {
FirstClusterOfFile += Dirent->FirstClusterOfFileHi << 16;
}
if (!RtlEqualString( &Name, &Fcb->ShortName.Name.Oem, TRUE )
||
( (NodeType(Fcb) == FAT_NTC_FCB) &&
(Fcb->Header.FileSize.LowPart != Dirent->FileSize) )
||
(FirstClusterOfFile != Fcb->FirstClusterOfFile)
||
(Dirent->Attributes != Fcb->DirentFatFlags) ) {
FatMarkFcbCondition( IrpContext, Fcb, FcbBad, TRUE );
} else {
//
// We passed. Get the Fcb ready to use again.
//
FatResetFcb( IrpContext, Fcb );
FatMarkFcbCondition( IrpContext, Fcb, FcbGood, FALSE );
}
} finally {
FatUnpinBcb( IrpContext, DirentBcb );
}
return;
}
//
// Internal support routine
//
VOID
FatQuickVerifyVcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
)
/*++
Routine Description:
This routines just checks the verify bit in the real device and the
Vcb condition and raises an appropriate exception if so warented.
It is called when verifying both Fcbs and Vcbs.
Arguments:
Vcb - Supplies the Vcb to check the condition of.
Return Value:
None.
--*/
{
//
// If the real device needs to be verified we'll set the
// DeviceToVerify to be our real device and raise VerifyRequired.
//
if (FlagOn(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME)) {
DebugTrace(0, Dbg, "The Vcb needs to be verified\n", 0);
IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
Vcb->Vpb->RealDevice );
FatRaiseStatus( IrpContext, STATUS_VERIFY_REQUIRED );
}
//
// Based on the condition of the Vcb we'll either return to our
// caller or raise an error condition
//
switch (Vcb->VcbCondition) {
case VcbGood:
DebugTrace(0, Dbg, "The Vcb is good\n", 0);
//
// Do a check here of an operation that would try to modify a
// write protected media.
//
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED) &&
((IrpContext->MajorFunction == IRP_MJ_WRITE) ||
(IrpContext->MajorFunction == IRP_MJ_SET_INFORMATION) ||
(IrpContext->MajorFunction == IRP_MJ_SET_EA) ||
(IrpContext->MajorFunction == IRP_MJ_FLUSH_BUFFERS) ||
(IrpContext->MajorFunction == IRP_MJ_SET_VOLUME_INFORMATION) ||
(IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST &&
IoGetCurrentIrpStackLocation(IrpContext->OriginatingIrp)->Parameters.FileSystemControl.FsControlCode ==
FSCTL_MARK_VOLUME_DIRTY))) {
//
// Set the real device for the pop-up info, and set the verify
// bit in the device object, so that we will force a verify
// in case the user put the correct media back in.
//
IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
Vcb->Vpb->RealDevice );
FatMarkDevForVerifyIfVcbMounted(Vcb);
FatRaiseStatus( IrpContext, STATUS_MEDIA_WRITE_PROTECTED );
}
break;
case VcbNotMounted:
DebugTrace(0, Dbg, "The Vcb is not mounted\n", 0);
//
// Set the real device for the pop-up info, and set the verify
// bit in the device object, so that we will force a verify
// in case the user put the correct media back in.
//
IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
Vcb->Vpb->RealDevice );
FatRaiseStatus( IrpContext, STATUS_WRONG_VOLUME );
break;
case VcbBad:
DebugTrace(0, Dbg, "The Vcb is bad\n", 0);
if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DISMOUNTED )) {
FatRaiseStatus( IrpContext, STATUS_VOLUME_DISMOUNTED );
} else {
FatRaiseStatus( IrpContext, STATUS_FILE_INVALID );
}
break;
default:
DebugDump("Invalid VcbCondition\n", 0, Vcb);
FatBugCheck( Vcb->VcbCondition, 0, 0 );
}
}
NTSTATUS
FatPerformVerify (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PDEVICE_OBJECT Device
)
/*++
Routine Description:
This routines performs an IoVerifyVolume operation and takes the
appropriate action. After the Verify is complete the originating
Irp is sent off to an Ex Worker Thread. This routine is called
from the exception handler.
Arguments:
Irp - The irp to send off after all is well and done.
Device - The real device needing verification.
Return Value:
None.
--*/
{
PVCB Vcb;
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
BOOLEAN AllowRawMount = FALSE;
BOOLEAN VcbDeleted = FALSE;
//
// Check if this Irp has a status of Verify required and if it does
// then call the I/O system to do a verify.
//
// Skip the IoVerifyVolume if this is a mount or verify request
// itself. Trying a recursive mount will cause a deadlock with
// the DeviceObject->DeviceLock.
//
if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
((IrpContext->MinorFunction == IRP_MN_MOUNT_VOLUME) ||
(IrpContext->MinorFunction == IRP_MN_VERIFY_VOLUME)) ) {
return FatFsdPostRequest( IrpContext, Irp );
}
DebugTrace(0, Dbg, "Verify Required, DeviceObject = %08lx\n", Device);
//
// Extract a pointer to the Vcb from the VolumeDeviceObject.
// Note that since we have specifically excluded mount,
// requests, we know that IrpSp->DeviceObject is indeed a
// volume device object.
//
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Vcb = &CONTAINING_RECORD( IrpSp->DeviceObject,
VOLUME_DEVICE_OBJECT,
DeviceObject )->Vcb;
//
// Check if the volume still thinks it needs to be verified,
// if it doesn't then we can skip doing a verify because someone
// else beat us to it.
//
try {
//
// We will allow Raw to mount this volume if we were doing a
// a DASD open.
//
if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) &&
(IrpSp->FileObject->FileName.Length == 0) &&
(IrpSp->FileObject->RelatedFileObject == NULL) ) {
AllowRawMount = TRUE;
}
//
// Send down the verify. This could be going to a different
// filesystem.
//
Status = IoVerifyVolume( Device, AllowRawMount );
//
// If the verify operation completed it will return
// either STATUS_SUCCESS or STATUS_WRONG_VOLUME, exactly.
//
// If FatVerifyVolume encountered an error during
// processing, it will return that error. If we got
// STATUS_WRONG_VOLUME from the verfy, and our volume
// is now mounted, commute the status to STATUS_SUCCESS.
//
// Acquire the Vcb so we're working with a stable Vcb condition.
//
FatAcquireSharedVcb(IrpContext, Vcb);
if ( (Status == STATUS_WRONG_VOLUME) &&
(Vcb->VcbCondition == VcbGood) ) {
Status = STATUS_SUCCESS;
}
else if ((STATUS_SUCCESS == Status) && (Vcb->VcbCondition != VcbGood)) {
Status = STATUS_WRONG_VOLUME;
}
//
// Do a quick unprotected check here. The routine will do
// a safe check. After here we can release the resource.
// Note that if the volume really went away, we will be taking
// the Reparse path.
//
if ((VcbGood != Vcb->VcbCondition) &&
(0 == Vcb->OpenFileCount) ) {
FatReleaseVcb( IrpContext, Vcb);
FatAcquireExclusiveGlobal( IrpContext );
FatAcquireExclusiveVcb( IrpContext,
Vcb );
VcbDeleted = FatCheckForDismount( IrpContext,
Vcb,
FALSE );
if (!VcbDeleted) {
FatReleaseVcb( IrpContext,
Vcb );
}
FatReleaseGlobal( IrpContext );
}
else {
FatReleaseVcb( IrpContext, Vcb);
}
//
// If the IopMount in IoVerifyVolume did something, and
// this is an absolute open, force a reparse.
//
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
(FileObject->RelatedFileObject == NULL) &&
((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) {
Irp->IoStatus.Information = IO_REMOUNT;
FatCompleteRequest( IrpContext, Irp, STATUS_REPARSE );
Status = STATUS_REPARSE;
Irp = NULL;
}
if ( (Irp != NULL) && !NT_SUCCESS(Status) ) {
//
// Fill in the device object if required.
//
if ( IoIsErrorUserInduced( Status ) ) {
IoSetHardErrorOrVerifyDevice( Irp, Device );
}
ASSERT( STATUS_VERIFY_REQUIRED != Status);
FatNormalizeAndRaiseStatus( IrpContext, Status );
}
//
// If there is still an Irp, send it off to an Ex Worker thread.
//
if ( Irp != NULL ) {
Status = FatFsdPostRequest( IrpContext, Irp );
}
}
except (FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
//
// We had some trouble trying to perform the verify or raised
// an error ourselves. So we'll abort the I/O request with
// the error status that we get back from the execption code.
//
Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
}
return Status;
}
//
// Local support routine
//
NTSTATUS
FatMarkVolumeCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
)
{
//
// Set the event so that our call will wake up.
//
KeSetEvent( (PKEVENT)Contxt, 0, FALSE );
UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( Irp );
return STATUS_MORE_PROCESSING_REQUIRED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -