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

📄 fsctrl.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
                                      Vcb );

                //
                //  Redo the allocation support
                //

                FatSetupAllocationSupport( IrpContext, OldVcb );

                //
                //  Get the state of the dirty bit.
                //

                FatCheckDirtyBit( IrpContext, OldVcb );

                //
                //  Check for write protected media.
                //

                if (FatIsMediaWriteProtected(IrpContext, TargetDeviceObject)) {

                    SetFlag( OldVcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED );

                } else {

                    ClearFlag( OldVcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED );
                }
            }

            //
            //  Complete the request and return to our caller
            //

            try_return( Status = STATUS_SUCCESS );
        }

        DebugTrace(0, Dbg, "Mount a new volume\n", 0);

        //
        //  This is a new mount
        //
        //  Create a blank ea data file fcb, just not for Fat32.
        //

        if (!FatIsFat32(Vcb)) {

            DIRENT TempDirent;
            PFCB EaFcb;

            RtlZeroMemory( &TempDirent, sizeof(DIRENT) );
            RtlCopyMemory( &TempDirent.FileName[0], "EA DATA  SF", 11 );

            EaFcb = FatCreateFcb( IrpContext,
                                  Vcb,
                                  Vcb->RootDcb,
                                  0,
                                  0,
                                  &TempDirent,
                                  NULL,
                                  FALSE,
                                  TRUE );

            //
            //  Deny anybody who trys to open the file.
            //

            SetFlag( EaFcb->FcbState, FCB_STATE_SYSTEM_FILE );

            Vcb->EaFcb = EaFcb;
        }

        //
        //  Get the state of the dirty bit.
        //

        FatCheckDirtyBit( IrpContext, Vcb );

        //
        //  Check for write protected media.
        //

        if (FatIsMediaWriteProtected(IrpContext, TargetDeviceObject)) {

            SetFlag( Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED );

        } else {

            ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED );
        }

        //
        //  Lock volume in drive if we just mounted the boot drive.
        //

        if (FlagOn(RealDevice->Flags, DO_SYSTEM_BOOT_PARTITION)) {

            SetFlag(Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE);

            if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA)) {

                FatToggleMediaEjectDisable( IrpContext, Vcb, TRUE );
            }
        }

        //
        //  Indicate to our termination handler that we have mounted
        //  a new volume.
        //

        MountNewVolume = TRUE;

        //
        //  Complete the request
        //

        Status = STATUS_SUCCESS;

        //
        //  Ref the root dir stream object so we can send mount notification.
        //

        RootDirectoryFile = Vcb->RootDcb->Specific.Dcb.DirectoryFile;
        ObReferenceObject( RootDirectoryFile );

        //
        //  Remove the extra reference to this target DO made on behalf of us
        //  by the IO system.  In the remount case, we permit regular Vcb
        //  deletion to do this work.
        //

        ObDereferenceObject( TargetDeviceObject );


    try_exit: NOTHING;

    } finally {

        DebugUnwind( FatMountVolume );

        FatUnpinBcb( IrpContext, BootBcb );
        FatUnpinBcb( IrpContext, DirentBcb );

        //
        //  Check if a volume was mounted.  If not then we need to
        //  mark the Vpb not mounted again.
        //

        if ( !MountNewVolume ) {

            if ( Vcb != NULL ) {

                //
                //  A VCB was created and initialized.  We need to try to tear it down.
                //

                FatCheckForDismount( IrpContext,
                                     Vcb,
                                     TRUE );

                IrpContext->Vcb = NULL;

            } else if (VolDo != NULL) {

                //
                //  The VCB was never initialized, so we need to delete the
                //  device right here.
                //

                IoDeleteDevice( &VolDo->DeviceObject );
            }

            //
            //  See if a remount failed.
            //

            if (DoARemount && AbnormalTermination()) {

                //
                //  The remount failed. Try to tear down the old VCB as well.
                //

                FatCheckForDismount( IrpContext,
                                     OldVcb,
                                     TRUE );
            }
        }

        if ( WeClearedVerifyRequiredBit == TRUE ) {

            SetFlag(RealDevice->Flags, DO_VERIFY_VOLUME);
        }

        FatReleaseGlobal( IrpContext );

        DebugTrace(-1, Dbg, "FatMountVolume -> %08lx\n", Status);
    }

    //
    //  Now send mount notification. Note that since this is outside of any
    //  synchronization since the synchronous delivery of this may go to
    //  folks that provoke re-entrance to the FS.
    //

    if (RootDirectoryFile != NULL) {

        FsRtlNotifyVolumeEvent( RootDirectoryFile, FSRTL_VOLUME_MOUNT );
        ObDereferenceObject( RootDirectoryFile );
    }

    return Status;
}


//
//  Local Support Routine
//

NTSTATUS
FatVerifyVolume (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the verify volume operation by checking the volume
    label and serial number physically on the media with the the Vcb
    currently claiming to have the volume mounted. It is responsible for
    either completing or enqueuing the input Irp.

    Regardless of whether the verify operation succeeds, the following
    operations are performed:

        - Set Vcb->VirtualEaFile back to its virgin state.
        - Purge all cached data (flushing first if verify succeeds)
        - Mark all Fcbs as needing verification

    If the volumes verifies correctly we also must:

        - Check the volume dirty bit.
        - Reinitialize the allocation support
        - Flush any dirty data

    If the volume verify fails, it may never be mounted again.  If it is
    mounted again, it will happen as a remount operation.  In preparation
    for that, and to leave the volume in a state that can be "lazy deleted"
    the following operations are performed:

        - Set the Vcb condition to VcbNotMounted
        - Uninitialize the volume file cachemap
        - Tear down the allocation support

    In the case of an abnormal termination we haven't determined the state
    of the volume, so we set the Device Object as needing verification again.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - If the verify operation completes, it will return either
        STATUS_SUCCESS or STATUS_WRONG_VOLUME, exactly.  If an IO or
        other error is encountered, that status will be returned.

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;

    PIO_STACK_LOCATION IrpSp;

    PDIRENT RootDirectory = NULL;
    PPACKED_BOOT_SECTOR BootSector = NULL;

    BIOS_PARAMETER_BLOCK Bpb;

    PVOLUME_DEVICE_OBJECT VolDo;
    PVCB Vcb;
    PVPB Vpb;

    ULONG SectorSize;
    BOOLEAN ClearVerify = FALSE;
    BOOLEAN ReleaseEntireVolume = FALSE;
    BOOLEAN VerifyAlreadyDone = FALSE;

    DISK_GEOMETRY DiskGeometry;

    LBO RootDirectoryLbo;
    ULONG RootDirectorySize;
    BOOLEAN LabelFound;

    ULONG ChangeCount = 0;
    IO_STATUS_BLOCK Iosb;

    //
    //  Get the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace(+1, Dbg, "FatVerifyVolume\n", 0);
    DebugTrace( 0, Dbg, "DeviceObject = %08lx\n", IrpSp->Parameters.VerifyVolume.DeviceObject);
    DebugTrace( 0, Dbg, "Vpb          = %08lx\n", IrpSp->Parameters.VerifyVolume.Vpb);

    //
    //  Save some references to make our life a little easier.  Note the Vcb for the purposes
    //  of exception handling.
    //

    VolDo = (PVOLUME_DEVICE_OBJECT)IrpSp->Parameters.VerifyVolume.DeviceObject;

    Vpb                   = IrpSp->Parameters.VerifyVolume.Vpb;
    IrpContext->Vcb = Vcb = &VolDo->Vcb;

    //
    //  If we cannot wait then enqueue the irp to the fsp and
    //  return the status to our caller.
    //

    if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

        DebugTrace(0, Dbg, "Cannot wait for verify.\n", 0);

        Status = FatFsdPostRequest( IrpContext, Irp );

        DebugTrace(-1, Dbg, "FatVerifyVolume -> %08lx\n", Status );
        return Status;
    }

    //
    //  We are serialized at this point allowing only one thread to
    //  actually perform the verify operation.  Any others will just
    //  wait and then no-op when checking if the volume still needs
    //  verification.
    //

    (VOID)FatAcquireExclusiveGlobal( IrpContext );
    (VOID)FatAcquireExclusiveVcb( IrpContext, Vcb );

    try {

        BOOLEAN AllowRawMount = BooleanFlagOn( IrpSp->Flags, SL_ALLOW_RAW_MOUNT );

        //
        //  Mark ourselves as verifying this volume so that recursive I/Os
        //  will be able to complete.
        //

        ASSERT( Vcb->VerifyThread == NULL );
        Vcb->VerifyThread = KeGetCurrentThread();

        //
        //  Check if the real device still needs to be verified.  If it doesn't
        //  then obviously someone beat us here and already did the work
        //  so complete the verify irp with success.  Otherwise reenable
        //  the real device and get to work.
        //

        if (!FlagOn(Vpb->RealDevice->Flags, DO_VERIFY_VOLUME)) {

            DebugTrace(0, Dbg, "RealDevice has already been verified\n", 0);

            VerifyAlreadyDone = TRUE;
            try_return( Status = STATUS_SUCCESS );
        }

        //
        //  Ping the volume with a partition query to make Jeff happy.
        //

        {
            PARTITION_INFORMATION_EX PartitionInformation;

            (VOID) FatPerformDevIoCtrl( IrpContext,
                                        IOCTL_DISK_GET_PARTITION_INFO_EX,
                                        Vcb->TargetDeviceObject,
                                        &PartitionInformation,
                                        sizeof(PARTITION_INFORMATION_EX),
                                        FALSE,
                                        TRUE,
                                        &Iosb );
        }

        //
        //  Verify that there is a disk here and pick up the change count.
        //

        Status = FatPerformDevIoCtrl( IrpContext,
                                      IOCTL_DISK_CHECK_VERIFY,
                                      Vcb->TargetDeviceObject,
                                      &ChangeCount,
                                      sizeof(ULONG),
                                      FALSE,
                                      TRUE,
                                      &Iosb );

        if (!NT_SUCCESS( Status )) {

            //
            //  If we will allow a raw mount then return WRONG_VOLUME to
            //  allow the volume to be mounted by raw.
            //

            if (AllowRawMount) {

                try_return( Status = STATUS_WRONG_VOLUME );
            }

            FatNormalizeAndRaiseStatus( IrpContext, Status );
        }

        if (Iosb.Information != sizeof(ULONG)) {

            //
            //  Be safe about the count in case the driver didn't fill it in
            //

            ChangeCount = 0;
        }

        //
        //  Whatever happens we will have verified this volume at this change
        //  count, so record that fact.
        //

        Vcb->ChangeCount = ChangeCount;

        //
        //  If this is a CD class device,  then check to see if there is a 
        //  'data track' or not.  This is to avoid issuing paging reads which will
        //  fail later in the mount process (e.g. CD-DA or blank CD media)
        //

        if ((Vcb->TargetDeviceObject->DeviceType == FILE_DEVICE_CD_ROM) &&
            !FatScanForDataTrack( IrpContext, Vcb->TargetDeviceObject))  {

            try_return( Status = STATUS_WRONG_VOLUME);
        }

        //
        //  Some devices can change sector sizes on the fly.  Obviously, it
        //  isn't the same volume if that happens.
        //

        Status = FatPerformDevIoCtrl( IrpContext,
                                      IOCTL_DISK_GET_DRIVE_GEOMETRY,
                                      Vcb->TargetDeviceObject,
                                      &DiskGeometry,
                                      sizeof( DISK_GEOMETRY ),
                                      FALSE,
                                      TRUE,
                                      NULL );

        if (!NT_SUCCESS( Status )) {

            //
            //  If we will allow a raw mount then return WRONG_VOLUME to
            //  allow the volume to be mounted by raw.

⌨️ 快捷键说明

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