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

📄 allocsup.c

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

        FatEntry = (FAT_ENTRY)FatGetIndexFromLbo( Vcb, CurrentLbo );

        //
        //  ASSERT that CurrentVbo and CurrentLbo are now cluster alligned.
        //  The assumption here, is that only whole clusters of Vbos and Lbos
        //  are mapped in the Mcb.
        //

        ASSERT( ((CurrentLbo - Vcb->AllocationSupport.FileAreaLbo)
                                                    % BytesPerCluster == 0) &&
                (CurrentVbo % BytesPerCluster == 0) );

        //
        //  Starting from the first Vbo after the last Mcb entry, scan through
        //  the Fat looking for our Vbo. We continue through the Fat until we
        //  hit a noncontiguity beyond the desired Vbo, or the last cluster.
        //

        while ( !LastCluster ) {

            //
            //  Get the next fat entry, and update our Current variables.
            //

            FatLookupFatEntry( IrpContext, Vcb, FatEntry, &FatEntry, &Context );

            PriorLbo = CurrentLbo;
            CurrentLbo = FatGetLboFromIndex( Vcb, FatEntry );
            CurrentVbo += BytesPerCluster;

            switch ( FatInterpretClusterType( Vcb, FatEntry )) {

            //
            //  Check for a break in the Fat allocation chain.
            //

            case FatClusterAvailable:
            case FatClusterReserved:
            case FatClusterBad:

                DebugTrace( 0, Dbg, "Break in allocation chain, entry = %d\n", FatEntry);
                DebugTrace(-1, Dbg, "FatLookupFileAllocation -> Fat Corrupt.  Raise Status.\n", 0);

                FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
                FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
                break;

            //
            //  If this is the last cluster, we must update the Mcb and
            //  exit the loop.
            //

            case FatClusterLast:

                //
                //  Assert we know where the current run started.  If the
                //  Mcb was empty when we were called, thenFirstLboOfCurrentRun
                //  was set to the start of the file.  If the Mcb contained an
                //  entry, then FirstLboOfCurrentRun was set on the first
                //  iteration through the loop.  Thus if FirstLboOfCurrentRun
                //  is 0, then there was an Mcb entry and we are on our first
                //  iteration, meaing that the last cluster in the Mcb was
                //  really the last allocated cluster, but we checked Vbo
                //  against AllocationSize, and found it OK, thus AllocationSize
                //  must be too large.
                //
                //  Note that, when we finally arrive here, CurrentVbo is actually
                //  the first Vbo beyond the file allocation and CurrentLbo is
                //  meaningless.
                //

                DebugTrace( 0, Dbg, "Read last cluster of file.\n", 0);

                //
                //  Detect the case of the maximal file.  Note that this really isn't
                //  a proper Vbo - those are zero-based, and this is a one-based number.
                //  The maximal file, of 2^32 - 1 bytes, has a maximum byte offset of
                //  2^32 - 2.
                //
                //  Just so we don't get confused here.
                //

                if (CurrentVbo == 0) {

                    *EndOnMax = TRUE;
                    CurrentVbo -= 1;
                }

                LastCluster = TRUE;

                if (FirstLboOfCurrentRun != 0 ) {

                    DebugTrace( 0, Dbg, "Adding a run to the Mcb.\n", 0);
                    DebugTrace( 0, Dbg, "  Vbo    = %08lx.\n", FirstVboOfCurrentRun);
                    DebugTrace( 0, Dbg, "  Lbo    = %08lx.\n", FirstLboOfCurrentRun);
                    DebugTrace( 0, Dbg, "  Length = %08lx.\n", CurrentVbo - FirstVboOfCurrentRun);

                    (VOID)FatAddMcbEntry( Vcb,
                                          &FcbOrDcb->Mcb,
                                          FirstVboOfCurrentRun,
                                          FirstLboOfCurrentRun,
                                          CurrentVbo - FirstVboOfCurrentRun );

                    Runs += 1;
                }

                //
                //  Being at the end of allocation, make sure we have found
                //  the Vbo.  If we haven't, seeing as we checked VBO
                //  against AllocationSize, the real disk allocation is less
                //  than that of AllocationSize.  This comes about when the
                //  real allocation is not yet known, and AllocaitonSize
                //  contains MAXULONG.
                //
                //  KLUDGE! - If we were called by FatLookupFileAllocationSize
                //  Vbo is set to MAXULONG - 1, and AllocationSize to the lookup
                //  hint. Thus we merrily go along looking for a match that isn't
                //  there, but in the meantime building an Mcb.  If this is
                //  the case, fill in AllocationSize and return.
                //

                if ( Vbo == MAXULONG - 1 ) {

                    *Allocated = FALSE;
                    FcbOrDcb->Header.AllocationSize.QuadPart = CurrentVbo;

                    DebugTrace( 0, Dbg, "New file allocation size = %08lx.\n", CurrentVbo);
                    try_return ( NOTHING );
                }

                //
                //  We will lie ever so slightly if we really terminated on the
                //  maximal byte of a file.  It is really allocated.
                //

                if (Vbo >= CurrentVbo && !*EndOnMax) {

                    *Allocated = FALSE;
                    try_return ( NOTHING );
                }

                break;

            //
            //  This is a continuation in the chain.  If the run has a
            //  discontiguity at this point, update the Mcb, and if we are beyond
            //  the desired Vbo, this is the end of the run, so set LastCluster
            //  and exit the loop.
            //

            case FatClusterNext:

                //
                //  This is the loop check.  The Vbo must not be bigger than the size of
                //  the volume, and the Vbo must not have a) wrapped and b) not been at the
                //  very last cluster in the chain, for the case of the maximal file.
                //

                if ( CurrentVbo == 0 ||
                     (BytesOnVolume.HighPart == 0 && CurrentVbo > BytesOnVolume.LowPart)) {

                    FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
                    FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
                }

                if ( PriorLbo + BytesPerCluster != CurrentLbo ) {

                    //
                    //  Note that on the first time through the loop
                    //  (FirstLboOfCurrentRun == 0), we don't add the
                    //  run to the Mcb since it curresponds to the last
                    //  run already stored in the Mcb.
                    //

                    if ( FirstLboOfCurrentRun != 0 ) {

                        DebugTrace( 0, Dbg, "Adding a run to the Mcb.\n", 0);
                        DebugTrace( 0, Dbg, "  Vbo    = %08lx.\n", FirstVboOfCurrentRun);
                        DebugTrace( 0, Dbg, "  Lbo    = %08lx.\n", FirstLboOfCurrentRun);
                        DebugTrace( 0, Dbg, "  Length = %08lx.\n", CurrentVbo - FirstVboOfCurrentRun);

                        FatAddMcbEntry( Vcb,
                                        &FcbOrDcb->Mcb,
                                        FirstVboOfCurrentRun,
                                        FirstLboOfCurrentRun,
                                        CurrentVbo - FirstVboOfCurrentRun );

                        Runs += 1;
                    }

                    //
                    //  Since we are at a run boundry, with CurrentLbo and
                    //  CurrentVbo being the first cluster of the next run,
                    //  we see if the run we just added encompases the desired
                    //  Vbo, and if so exit.  Otherwise we set up two new
                    //  First*boOfCurrentRun, and continue.
                    //

                    if (CurrentVbo > Vbo) {

                        LastCluster = TRUE;

                    } else {

                        FirstVboOfCurrentRun = CurrentVbo;
                        FirstLboOfCurrentRun = CurrentLbo;
                    }
                }
                break;

            default:

                DebugTrace(0, Dbg, "Illegal Cluster Type.\n", FatEntry);

                FatBugCheck( 0, 0, 0 );

                break;

            } // switch()
        } // while()

        //
        //  Load up the return parameters.
        //
        //  On exit from the loop, Vbo still contains the desired Vbo, and
        //  CurrentVbo is the first byte after the run that contained the
        //  desired Vbo.
        //

        *Allocated = TRUE;

        *Lbo = FirstLboOfCurrentRun + (Vbo - FirstVboOfCurrentRun);

        *ByteCount = CurrentVbo - Vbo;

        if (ARGUMENT_PRESENT(Index)) {

            //
            //  Note that Runs only needs to be accurate with respect to where we
            //  ended.  Since partial-lookup cases will occur without exclusive
            //  synchronization, the Mcb itself may be much bigger by now.
            //

            *Index = Runs - 1;
        }

    try_exit: NOTHING;

    } finally {

        DebugUnwind( FatLookupFileAllocation );

        //
        //  We are done reading the Fat, so unpin the last page of fat
        //  that is hanging around
        //

        FatUnpinBcb( IrpContext, Context.Bcb );

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

    return;
}


VOID
FatAddFileAllocation (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB FcbOrDcb,
    IN PFILE_OBJECT FileObject OPTIONAL,
    IN ULONG DesiredAllocationSize
    )

/*++

Routine Description:

    This routine adds additional allocation to the specified file/directory.
    Additional allocation is added by appending clusters to the file/directory.

    If the file already has a sufficient allocation then this procedure
    is effectively a noop.

Arguments:

    FcbOrDcb - Supplies the Fcb/Dcb of the file/directory being modified.
               This parameter must not specify the root dcb.

    FileObject - If supplied inform the cache manager of the change.

    DesiredAllocationSize - Supplies the minimum size, in bytes, that we want
                            allocated to the file/directory.

--*/

{
    PVCB Vcb;
    LARGE_MCB NewMcb;
    PLARGE_MCB McbToCleanup = NULL;
    PDIRENT Dirent = NULL;
    ULONG NewAllocation;
    PBCB Bcb = NULL;
    BOOLEAN UnwindWeAllocatedDiskSpace = FALSE;
    BOOLEAN UnwindAllocationSizeSet = FALSE;
    BOOLEAN UnwindCacheManagerInformed = FALSE;
    BOOLEAN UnwindWeInitializedMcb = FALSE;

    PAGED_CODE();

    DebugTrace(+1, Dbg, "FatAddFileAllocation\n", 0);
    DebugTrace( 0, Dbg, "  FcbOrDcb  =             %8lx\n", FcbOrDcb);
    DebugTrace( 0, Dbg, "  DesiredAllocationSize = %8lx\n", DesiredAllocationSize);

    //
    //  If we haven't yet set the correct AllocationSize, do so.
    //

    if (FcbOrDcb->Header.AllocationSize.QuadPart == FCB_LOOKUP_ALLOCATIONSIZE_HINT)  {

        FatLookupFileAllocationSize( IrpContext, FcbOrDcb );
    }

    //
    //  Check for the benign case that the desired allocation is already
    //  within the allocation size.
    //

    if (DesiredAllocationSize <= FcbOrDcb->Header.AllocationSize.LowPart) {

        DebugTrace(0, Dbg, "Desired size within current allocation.\n", 0);

        DebugTrace(-1, Dbg, "FatAddFileAllocation -> (VOID)\n", 0);
        return;
    }

    DebugTrace( 0, Dbg, "InitialAllocation = %08lx.\n", FcbOrDcb->Header.AllocationSize.LowPart);

    //
    //  Get a chunk of disk space that will fullfill our needs.  If there
    //  was no initial allocation, start from the hint in the Vcb, otherwise
    //  try to allocate from the cluster after the initial allocation.
    //
    //  If there was no initial allocation to the file, we can just use the
    //  Mcb in the FcbOrDcb, otherwise we have to use a new one, and merge
    //  it to the one in the FcbOrDcb.
    //

    Vcb = FcbOrDcb->Vcb;

    try {

        if (FcbOrDcb->Header.AllocationSize.LowPart == 0) {

            LBO FirstLboOfFile;

            ASSERT( FcbOrDcb->FcbCondition == FcbGood );
            
            FatGetDirentFromFcbOrDcb( IrpContext,
                                      FcbOrDcb,
                                      FALSE,
                                      &Dirent,
                                      &Bcb );
            //
            //  Set this dirty right now since this call can fail.
            //

            FatSetDirtyBcb( IrpContext, Bcb, Vcb, TRUE );


            FatAllocateDiskSpace( IrpContext,
                                  Vcb,
                                  0,
                                  &DesiredAllocationSize,
                                  FALSE,
                                  &FcbOrDcb->Mcb );

            UnwindWeAllocatedDiskSpace = TRUE;
            McbToCleanup = &FcbOrDcb->Mcb;

            //
            //  We have to update the dirent and FcbOrDcb copies of
            //  FirstClusterOfFile since before it was 0
            //

            FatLookupMcbEntry( FcbOrDcb->Vcb,
                               &FcbOrDcb->Mcb,
                               0,
                               &FirstLboOfFile,
                               (PULONG)NULL,
                               NULL );

            DebugTrace( 0, Dbg, "First Lbo of file will be %08lx.\n", FirstLboOfFile );

            FcbOrDcb->FirstClusterOfFile = FatGetIndexFromLbo( Vcb, FirstLboOfFile );

            Dirent->FirstClusterOfFile = (USHORT)FcbOrDcb->FirstClusterOfFile;

            if ( FatIsFat32(Vcb) ) {

                Dirent->FirstClusterOfFileHi = (USHORT)(FcbOrDcb->FirstClusterOfFile >> 16);
            }

            //
            //   Note the size of the allocation we need to tell the cache manager about.
            //

            NewAllocation = DesiredAllocationSize;

        } else {

⌨️ 快捷键说明

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