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

📄 verfysup.c

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

    default:

        DebugDump("Invalid FcbCondition\n", 0, Fcb);
        FatBugCheck( Fcb->FcbCondition, 0, 0 );
    }

    DebugTrace(-1, Dbg, "FatVerifyFcb -> VOID\n", 0);

    return;
}

VOID
FatDeferredCleanVolume (
    PVOID Parameter
    )

/*++

Routine Description:

    This is the routine that performs the actual FatMarkVolumeClean call.
    It assures that the target volume still exists as there ia a race
    condition between queueing the ExWorker item and volumes going away.

Arguments:

    Parameter - Points to a clean volume packet that was allocated from pool

Return Value:

    None.

--*/

{
    PCLEAN_AND_DIRTY_VOLUME_PACKET Packet;
    PLIST_ENTRY Links;
    PVCB Vcb;
    IRP_CONTEXT IrpContext;
    BOOLEAN VcbExists = FALSE;

    DebugTrace(+1, Dbg, "FatDeferredCleanVolume\n", 0);

    Packet = (PCLEAN_AND_DIRTY_VOLUME_PACKET)Parameter;

    Vcb = Packet->Vcb;

    //
    //  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 );

    //
    //  Dummy up and Irp Context so we can call our worker routines
    //

    RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT));

    SetFlag(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT);

    //
    //  Acquire shared access to the global lock and make sure this volume
    //  still exists.
    //

    FatAcquireSharedGlobal( &IrpContext );

    for (Links = FatData.VcbQueue.Flink;
         Links != &FatData.VcbQueue;
         Links = Links->Flink) {

        PVCB ExistingVcb;

        ExistingVcb = CONTAINING_RECORD(Links, VCB, VcbLinks);

        if ( Vcb == ExistingVcb ) {

            VcbExists = TRUE;
            break;
        }
    }

    //
    //  If the vcb is good then mark it clean.  Ignore any problems.
    //

    if ( VcbExists &&
         (Vcb->VcbCondition == VcbGood) &&
         !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN) ) {

        try {

            if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {

                FatMarkVolume( &IrpContext, Vcb, VolumeClean );
            }

            //
            //  Check for a pathological race condition, and fix it.
            //

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

                FatMarkVolume( &IrpContext, Vcb, VolumeDirty );

            } else {

                //
                //  Unlock the volume if it is removable.
                //

                if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
                    !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE)) {

                    FatToggleMediaEjectDisable( &IrpContext, Vcb, FALSE );
                }
            }

        } except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
                  EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {

              NOTHING;
        }
    }

    //
    //  Release the global resource, unpin and repinned Bcbs and return.
    //

    FatReleaseGlobal( &IrpContext );

    try {

        FatUnpinRepinnedBcbs( &IrpContext );

    } except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
              EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {

          NOTHING;
    }

    IoSetTopLevelIrp( NULL );

    //
    //  and finally free the packet.
    //

    ExFreePool( Packet );

    return;
}


VOID
FatCleanVolumeDpc (
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    )

/*++

Routine Description:

    This routine is dispatched 5 seconds after the last disk structure was
    modified in a specific volume, and exqueues an execuative worker thread
    to perform the actual task of marking the volume dirty.

Arguments:

    DefferedContext - Contains the Vcb to process.

Return Value:

    None.

--*/

{
    PVCB Vcb;
    PCLEAN_AND_DIRTY_VOLUME_PACKET Packet;

    Vcb = (PVCB)DeferredContext;

    //
    //  If there is still dirty data (highly unlikely), set the timer for a
    //  second in the future.
    //

    if (CcIsThereDirtyData(Vcb->Vpb)) {

        LARGE_INTEGER TwoSecondsFromNow;

        TwoSecondsFromNow.QuadPart = (LONG)-2*1000*1000*10;

        KeSetTimer( &Vcb->CleanVolumeTimer,
                    TwoSecondsFromNow,
                    &Vcb->CleanVolumeDpc );

        return;
    }

    //
    //  If we couldn't get pool, oh well....
    //

    Packet = ExAllocatePoolWithTag(NonPagedPool, sizeof(CLEAN_AND_DIRTY_VOLUME_PACKET), ' taF');

    if ( Packet ) {

        Packet->Vcb = Vcb;
        Packet->Irp = NULL;

        //
        //  Clear the dirty flag now since we cannot synchronize after this point.
        //

        ClearFlag( Packet->Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY );

        ExInitializeWorkItem( &Packet->Item, &FatDeferredCleanVolume, Packet );

        ExQueueWorkItem( &Packet->Item, CriticalWorkQueue );
    }

    return;
}


VOID
FatMarkVolume (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN FAT_VOLUME_STATE VolumeState
    )

/*++

Routine Description:

    This routine moves the physically marked volume state between the clean
    and dirty states.  For compatibility with Win9x, we manipulate both the
    historical DOS (on==clean in index 1 of the FAT) and NT (on==dirty in
    the CurrentHead field of the BPB) dirty bits.

Arguments:

    Vcb - Supplies the Vcb being modified

    VolumeState - Supplies the state the volume is transitioning to

Return Value:

    None.

--*/

{
    PCHAR Sector;
    PBCB Bcb = NULL;
    KEVENT Event;
    PIRP Irp = NULL;
    NTSTATUS Status;
    BOOLEAN FsInfoUpdate = FALSE;
    ULONG FsInfoOffset = 0;
    ULONG ThisPass;
    LARGE_INTEGER Offset;
    BOOLEAN abort = FALSE;

    DebugTrace(+1, Dbg, "FatMarkVolume, Vcb = %08lx\n", Vcb);

    //
    //  We had best not be trying to scribble dirty/clean bits if the
    //  volume is write protected.  The responsibility lies with the
    //  callers to make sure that operations that could cause a state
    //  change cannot happen.  There are a few, though, that show it
    //  just doesn't make sense to force everyone to do the dinky
    //  check.
    //

    //
    //  If we were called for FAT12 or readonly media, return immediately.
    //

    if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED) ||
        FatIsFat12( Vcb )) {

        return;
    }

    //
    //  We have two possible additional tasks to do to mark a volume
    //
    //      Pass 0) Flip the dirty bit in the Bpb
    //      Pass 1) Rewrite the FsInfo sector for FAT32 if needed
    //
    //  In most cases we can collapse these two either because the volume
    //  is either not FAT32 or the FsInfo sector is adjacent to the boot sector.
    //

    for (ThisPass = 0; ThisPass < 2; ThisPass++) {

        //
        //  If this volume is being dirtied, or isn't FAT32, or if it is and
        //  we were able to perform the fast update, or the bpb lied to us
        //  about where the FsInfo went, we're done - no FsInfo to update in
        //  a seperate write.
        //

        if (ThisPass == 1 && (!FatIsFat32( Vcb ) ||
                              VolumeState != VolumeClean ||
                              FsInfoUpdate ||
                              Vcb->Bpb.FsInfoSector == 0)) {

            break;
        }

        //
        //  Bail if we get an IO error.
        //

        try {

            ULONG PinLength;
            ULONG WriteLength;

            //
            // If the FAT table is 12-bit then our strategy is to pin the entire
            // thing when any of it is modified.  Here we're going to pin the
            // first page, so in the 12-bit case we also want to pin the rest
            // of the FAT table.
            //

            Offset.QuadPart = 0;

            if (Vcb->AllocationSupport.FatIndexBitSize == 12) {

                //
                //  But we only write back the first sector.
                //

                PinLength = FatReservedBytes(&Vcb->Bpb) + FatBytesPerFat(&Vcb->Bpb);
                WriteLength = Vcb->Bpb.BytesPerSector;

            } else {

                WriteLength = PinLength = Vcb->Bpb.BytesPerSector;

                //
                //  If this is a FAT32 volume going into the clean state,
                //  see about doing the FsInfo sector.
                //

                if (FatIsFat32( Vcb ) && VolumeState == VolumeClean) {

                    //
                    //  If the FsInfo sector immediately follows the boot sector,
                    //  we can do this in a single operation by rewriting both
                    //  sectors at once.
                    //

                    if (Vcb->Bpb.FsInfoSector == 1) {

                        ASSERT( ThisPass == 0 );

                        FsInfoUpdate = TRUE;
                        FsInfoOffset = Vcb->Bpb.BytesPerSector;
                        WriteLength = PinLength = Vcb->Bpb.BytesPerSector * 2;

                    } else if (ThisPass == 1) {

                        //
                        //  We are doing an explicit write to the FsInfo sector.
                        //

                        FsInfoUpdate = TRUE;
                        FsInfoOffset = 0;

                        Offset.QuadPart = Vcb->Bpb.BytesPerSector * Vcb->Bpb.FsInfoSector;
                    }
                }
            }

            //
            //  Call Cc directly here so that we can avoid overhead and push this
            //  right down to the disk.
            //

            CcPinRead( Vcb->VirtualVolumeFile,
                       &Offset,
                       PinLength,
                       TRUE,
                       &Bcb,
                       (PVOID *)&Sector );

            DbgDoit( IrpContext->PinCount += 1 )

            //
            //  Set the Bpb on Pass 0 always
            //

            if (ThisPass == 0) {

                PCHAR CurrentHead;

                //
                //  Before we do anything, doublecheck that this still looks like a
                //  FAT bootsector.  If it doesn't, something remarkable happened
                //  and we should avoid touching the volume.
                //
                //  THIS IS TEMPORARY (but may last a while)
                //

                if (!FatIsBootSectorFat( (PPACKED_BOOT_SECTOR) Sector )) {
                    abort = TRUE;
                    leave;
                }

                if (FatIsFat32( Vcb )) {

                    CurrentHead = &((PPACKED_BOOT_SECTOR_EX) Sector)->CurrentHead;

                } else {

                    CurrentHead = &((PPACKED_BOOT_SECTOR) Sector)->CurrentHead;
                }

                if (VolumeState == VolumeClean) {

                    ClearFlag( *CurrentHead, FAT_BOOT_SECTOR_DIRTY );

                } else {

                    SetFlag( *CurrentHead, FAT_BOOT_SECTOR_DIRTY );

                    //
                    //  In addition, if this request received an error that may indicate
                    //  media corruption, have autochk perform a surface test.
                    //

                    if ( VolumeState == VolumeDirtyWithSurfaceTest ) {

                        SetFlag( *CurrentHead, FAT_BOOT_SECTOR_TEST_SURFACE );
                    }
                }
            }

            //
            //  Update the FsInfo as appropriate.
            //

            if (FsInfoUpdate) {

                PFSINFO_SECTOR FsInfoSector = (PFSINFO_SECTOR) ((PCHAR)Sector + FsInfoOffset);

                //
                //  We just rewrite all of the spec'd fields.  Note that we don't
                //  care to synchronize with the allocation package - this will be
                //  quickly taken care of by a re-dirtying of the volume if a change
                //  is racing with us.  Remember that this is all a compatibility
                //  deference for Win9x FAT32 - NT will never look at this information.
                //

                FsInfoSector->SectorBeginSignature = FSINFO_SECTOR_BEGIN_SIGNATURE;
                FsInfoSector->FsInfoSignature = FSINFO_SIGNATURE;
                FsInfoSector->FreeClusterCount = Vcb->AllocationSupport.NumberOfFreeClusters;
                FsInfoSector->NextFreeCluster = Vcb->ClusterHint;
                FsInfoSector->SectorEndSignature = FSINFO_SECTOR_END_SIGNATURE;
            }

            //
            //  Initialize the event we're going to use
            //

            KeInitializeEvent( &Event, NotificationEvent, FALSE );

            //
            //  Build the irp for the operation and also set the override flag.
            //  Note that we may be at APC level, so do this asyncrhonously and
            //  use an event for synchronization as normal request completion
            //  cannot occur at APC level.
            //

            Irp = IoBuildAsynchronousFsdRequest( IRP_MJ_WRITE,
                                                 Vcb->TargetDeviceObject,

⌨️ 快捷键说明

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