⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 verfysup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 2 页
字号:
        
                MediaChangeCount = 0;
            }

            //
            //  There are four cases when we want to do a verify.  These are the
            //  first three.
            //
            //  1. We are mounted,  and the device has become empty
            //  2. The device has returned verify required (=> DO_VERIFY_VOL flag is
            //     set, but could be due to hardware condition)
            //  3. Media change count doesn't match the one in the Vcb
            //
            
            if (((Vcb->VcbCondition == VcbMounted) &&
                 CdIsRawDevice( IrpContext, Status )) 
                ||
                (Status == STATUS_VERIFY_REQUIRED)
                ||
                (NT_SUCCESS(Status) &&
                 (Vcb->MediaChangeCount != MediaChangeCount))) {

                //
                //  If we are currently the volume on the device then it is our
                //  responsibility to set the verify flag.  If we're not on the device,
                //  then we shouldn't touch the flag.
                //

                if (!FlagOn( Vcb->VcbState, VCB_STATE_VPB_NOT_ON_DEVICE) &&
                    !DevMarkedForVerify)  {

                     DevMarkedForVerify = CdMarkDevForVerifyIfVcbMounted( Vcb);
                }

                ForceVerify = TRUE;

                //
                //  NOTE that we no longer update the media change count here. We
                //  do so only when we've actually completed a verify at a particular
                //  change count value.
                //
            } 
        }

        //
        //  This is the 4th verify case.
        //
        //  We ALWAYS force CREATE requests on unmounted volumes through the 
        //  verify path.  These requests could have been in limbo between
        //  IoCheckMountedVpb and us when a verify/mount took place and caused
        //  a completely different fs/volume to be mounted.  In this case the
        //  checks above may not have caught the condition,  since we may already
        //  have verified (wrong volume) and decided that we have nothing to do.
        //  We want the requests to be re routed to the currently mounted volume,
        //  since they were directed at the 'drive',  not our volume.
        //

        if (NT_SUCCESS( Status) && !ForceVerify && !DevMarkedForVerify &&
            (IrpContext->MajorFunction == IRP_MJ_CREATE))  {

            PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->Irp);

            ForceVerify = (IrpSp->FileObject->RelatedFileObject == NULL) &&
                          ((Vcb->VcbCondition == VcbDismountInProgress) ||
                           (Vcb->VcbCondition == VcbNotMounted));

            //
            //  Note that we don't touch the device verify flag here.  It required
            //  it would have been caught and set by the first set of checks.
            //
        }
    }

    //
    //  Raise the verify / error if neccessary.
    //
    
    if (ForceVerify || DevMarkedForVerify || !NT_SUCCESS( Status)) {
    
        IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
                                      Vcb->Vpb->RealDevice );
       
        CdRaiseStatus( IrpContext, (ForceVerify || DevMarkedForVerify) 
                                   ? STATUS_VERIFY_REQUIRED 
                                   : Status);
    }

    //
    //  Based on the condition of the Vcb we'll either return to our
    //  caller or raise an error condition
    //

    switch (Vcb->VcbCondition) {

    case VcbNotMounted:

        IoSetHardErrorOrVerifyDevice( IrpContext->Irp, Vcb->Vpb->RealDevice );

        CdRaiseStatus( IrpContext, STATUS_WRONG_VOLUME );
        break;

    case VcbInvalid:
    case VcbDismountInProgress :

        CdRaiseStatus( IrpContext, STATUS_FILE_INVALID );
        break;
    }
}


BOOLEAN
CdVerifyFcbOperation (
    IN PIRP_CONTEXT IrpContext OPTIONAL,
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine is called to verify that the state of the Fcb is valid
    to allow the current operation to continue.  We use the state of the
    Vcb, target device and type of operation to determine this.

Arguments:

    IrpContext - IrpContext for the request.  If not present then we
        were called from the fast IO path.

    Fcb - Fcb to perform the request on.

Return Value:

    BOOLEAN - TRUE if the request can continue, FALSE otherwise.

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;
    PVCB Vcb = Fcb->Vcb;
    PDEVICE_OBJECT RealDevice = Vcb->Vpb->RealDevice;
    PIRP Irp;

    PAGED_CODE();
    
    //
    //  Check that the fileobject has not been cleaned up.
    //
    
    if ( ARGUMENT_PRESENT( IrpContext ))  {

        PFILE_OBJECT FileObject;

        Irp = IrpContext->Irp;
        FileObject = IoGetCurrentIrpStackLocation( Irp)->FileObject;
        
        if ( FileObject && FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE))  {

            PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );

            //
            //  Following FAT,  we allow certain operations even on cleaned up
            //  file objects.  Everything else,  we fail.
            //
            
            if ( (FlagOn(Irp->Flags, IRP_PAGING_IO)) ||
                 (IrpSp->MajorFunction == IRP_MJ_CLOSE ) ||
                 (IrpSp->MajorFunction == IRP_MJ_QUERY_INFORMATION) ||
                 ( (IrpSp->MajorFunction == IRP_MJ_READ) &&
                   FlagOn(IrpSp->MinorFunction, IRP_MN_COMPLETE) ) ) {

                NOTHING;

            } else {

                CdRaiseStatus( IrpContext, STATUS_FILE_CLOSED );
            }
        }
    }

    //
    //  Fail immediately if the volume is in the progress of being dismounted
    //  or has been marked invalid.
    //

    if ((Vcb->VcbCondition == VcbInvalid) ||
        (Vcb->VcbCondition == VcbDismountInProgress)) {

        if (ARGUMENT_PRESENT( IrpContext )) {

            CdRaiseStatus( IrpContext, STATUS_FILE_INVALID );
        }

        return FALSE;
    }

    //
    //  Always fail if the volume needs to be verified.
    //

    if (CdRealDevNeedsVerify( RealDevice)) {

        if (ARGUMENT_PRESENT( IrpContext )) {

            IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
                                          RealDevice );

            CdRaiseStatus( IrpContext, STATUS_VERIFY_REQUIRED );
        }

        return FALSE;

    //
    //
    //  All operations are allowed on mounted.
    //

    } else if ((Vcb->VcbCondition == VcbMounted) ||
               (Vcb->VcbCondition == VcbMountInProgress)) {

        return TRUE;

    //
    //  Fail all requests for fast Io on other Vcb conditions.
    //

    } else if (!ARGUMENT_PRESENT( IrpContext )) {

        return FALSE;

    //
    //  The remaining case is VcbNotMounted.
    //  Mark the device to be verified and raise WRONG_VOLUME.
    //

    } else if (Vcb->VcbCondition == VcbNotMounted) {

        if (ARGUMENT_PRESENT( IrpContext )) {

            IoSetHardErrorOrVerifyDevice( IrpContext->Irp, RealDevice );
            CdRaiseStatus( IrpContext, STATUS_WRONG_VOLUME );
        }

        return FALSE;
    }

    return TRUE;
}


BOOLEAN
CdDismountVcb (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb
    )

/*++

Routine Description:

    This routine is called when all of the user references to a volume are
    gone.  We will initiate all of the teardown any system resources.

    If all of the references to this volume are gone at the end of this routine
    then we will complete the teardown of this Vcb and mark the current Vpb
    as not mounted.  Otherwise we will allocated a new Vpb for this device
    and keep the current Vpb attached to the Vcb.

Arguments:

    Vcb - Vcb for the volume to dismount.

Return Value:

    BOOLEAN - TRUE if we didn't delete the Vcb, FALSE otherwise.

--*/

{
    PVPB OldVpb;
    BOOLEAN VcbPresent = TRUE;
    KIRQL SavedIrql;

    BOOLEAN FinalReference;

    ASSERT_EXCLUSIVE_CDDATA;
    ASSERT_EXCLUSIVE_VCB( Vcb );

    CdLockVcb( IrpContext, Vcb );

    //
    //  We should only take this path once.
    //

    ASSERT( Vcb->VcbCondition != VcbDismountInProgress );

    //
    //  Mark the Vcb as DismountInProgress.
    //

    Vcb->VcbCondition = VcbDismountInProgress;

    if (Vcb->XASector != NULL) {

        CdFreePool( &Vcb->XASector );
        Vcb->XASector = 0;
        Vcb->XADiskOffset = 0;
    }

    //
    //  Remove our reference to the internal Fcb's.  The Fcb's will then
    //  be removed in the purge path below.
    //

    if (Vcb->RootIndexFcb != NULL) {

        Vcb->RootIndexFcb->FcbReference -= 1;
        Vcb->RootIndexFcb->FcbUserReference -= 1;
    }

    if (Vcb->PathTableFcb != NULL) {

        Vcb->PathTableFcb->FcbReference -= 1;
        Vcb->PathTableFcb->FcbUserReference -= 1;
    }

    if (Vcb->VolumeDasdFcb != NULL) {

        Vcb->VolumeDasdFcb->FcbReference -= 1;
        Vcb->VolumeDasdFcb->FcbUserReference -= 1;
    }

    CdUnlockVcb( IrpContext, Vcb );

    //
    //  Purge the volume.
    //

    CdPurgeVolume( IrpContext, Vcb, TRUE );

    //
    //  Empty the delayed and async close queues.
    //

    CdFspClose( Vcb );

    OldVpb = Vcb->Vpb;

    //
    //  Remove the mount volume reference.
    //

    CdLockVcb( IrpContext, Vcb );
    Vcb->VcbReference -= 1;

    //
    //  Acquire the Vpb spinlock to check for Vpb references.
    //

    IoAcquireVpbSpinLock( &SavedIrql );

    //
    //  Remember if this is the last reference on this Vcb.  We incremented
    //  the count on the Vpb earlier so we get one last crack it.  If our
    //  reference has gone to zero but the vpb reference count is greater
    //  than zero then the Io system will be responsible for deleting the
    //  Vpb.
    //

    FinalReference = (BOOLEAN) ((Vcb->VcbReference == 0) &&
                                (OldVpb->ReferenceCount == 1));

    //
    //  There is a reference count in the Vpb and in the Vcb.  We have
    //  incremented the reference count in the Vpb to make sure that
    //  we have last crack at it.  If this is a failed mount then we
    //  want to return the Vpb to the IO system to use for the next
    //  mount request.
    //

    if (OldVpb->RealDevice->Vpb == OldVpb) {

        //
        //  If not the final reference then swap out the Vpb.  We must
        //  preserve the REMOVE_PENDING flag so that the device is
        //  not remounted in the middle of a PnP remove operation.
        //

        if (!FinalReference) {

            ASSERT( Vcb->SwapVpb != NULL );

            Vcb->SwapVpb->Type = IO_TYPE_VPB;
            Vcb->SwapVpb->Size = sizeof( VPB );
            Vcb->SwapVpb->RealDevice = OldVpb->RealDevice;

            Vcb->SwapVpb->RealDevice->Vpb = Vcb->SwapVpb;

            Vcb->SwapVpb->Flags = FlagOn( OldVpb->Flags, VPB_REMOVE_PENDING );

            IoReleaseVpbSpinLock( SavedIrql );

            //
            //  Indicate we used up the swap.
            //

            Vcb->SwapVpb = NULL;            

            CdUnlockVcb( IrpContext, Vcb );

        //
        //  We want to leave the Vpb for the IO system.  Mark it
        //  as being not mounted.  Go ahead and delete the Vcb as
        //  well.
        //

        } else {

            //
            //  Make sure to remove the last reference on the Vpb.
            //

            OldVpb->ReferenceCount -= 1;

            OldVpb->DeviceObject = NULL;
            ClearFlag( Vcb->Vpb->Flags, VPB_MOUNTED );
            ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED );

            //
            //  Clear the Vpb flag so we know not to delete it.
            //

            Vcb->Vpb = NULL;

            IoReleaseVpbSpinLock( SavedIrql );
            CdUnlockVcb( IrpContext, Vcb );
            CdDeleteVcb( IrpContext, Vcb );
            VcbPresent = FALSE;
        }

    //
    //  Someone has already swapped in a new Vpb.  If this is the final reference
    //  then the file system is responsible for deleting the Vpb.
    //

    } else if (FinalReference) {

        //
        //  Make sure to remove the last reference on the Vpb.
        //

        OldVpb->ReferenceCount -= 1;

        IoReleaseVpbSpinLock( SavedIrql );
        CdUnlockVcb( IrpContext, Vcb );
        CdDeleteVcb( IrpContext, Vcb );
        VcbPresent = FALSE;

    //
    //  The current Vpb is no longer the Vpb for the device (the IO system
    //  has already allocated a new one).  We leave our reference in the
    //  Vpb and will be responsible for deleting it at a later time.
    //

    } else {

        IoReleaseVpbSpinLock( SavedIrql );
        CdUnlockVcb( IrpContext, Vcb );
    }

    //
    //  Let our caller know whether the Vcb is still present.
    //

    return VcbPresent;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -