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

📄 fsctrl.c

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

            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 + -