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

📄 allocsup.c

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

            LBO LastAllocatedLbo;
            VBO DontCare;

            //
            //  Get the first cluster following the current allocation.  It is possible
            //  the Mcb is empty (or short, etc.) so we need to be slightly careful
            //  about making sure we don't lie with the hint.
            //

            (void)FatLookupLastMcbEntry( FcbOrDcb->Vcb, &FcbOrDcb->Mcb, &DontCare, &LastAllocatedLbo, NULL );

            //
            //  Try to get some disk space starting from there.
            //

            NewAllocation = DesiredAllocationSize - FcbOrDcb->Header.AllocationSize.LowPart;

            FsRtlInitializeLargeMcb( &NewMcb, PagedPool );
            UnwindWeInitializedMcb = TRUE;
            McbToCleanup = &NewMcb;

            FatAllocateDiskSpace( IrpContext,
                                  Vcb,
                                  (LastAllocatedLbo != ~0  ?
                                   FatGetIndexFromLbo(Vcb,LastAllocatedLbo + 1) :
                                   0),
                                  &NewAllocation,
                                  FALSE,
                                  &NewMcb );

            UnwindWeAllocatedDiskSpace = TRUE;
        }

        //
        //  Now that we increased the allocation of the file, mark it in the
        //  FcbOrDcb.  Carefully prepare to handle an inability to grow the cache
        //  structures.
        //

        FcbOrDcb->Header.AllocationSize.LowPart += NewAllocation;

        //
        //  Handle the maximal file case, where we may have just wrapped.  Note
        //  that this must be the precise boundary case wrap, i.e. by one byte,
        //  so that the new allocation is actually one byte "less" as far as we're
        //  concerned.  This is important for the extension case.
        //

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

            NewAllocation -= 1;
            FcbOrDcb->Header.AllocationSize.LowPart = 0xffffffff;
        }

        UnwindAllocationSizeSet = TRUE;

        //
        //  Inform the cache manager to increase the section size
        //

        if ( ARGUMENT_PRESENT(FileObject) && CcIsFileCached(FileObject) ) {

            CcSetFileSizes( FileObject,
                            (PCC_FILE_SIZES)&FcbOrDcb->Header.AllocationSize );
            UnwindCacheManagerInformed = TRUE;
        }

        //
        //  In the extension case, we have held off actually gluing the new
        //  allocation onto the file.  This simplifies exception cleanup since
        //  if it was already added and the section grow failed, we'd have to
        //  do extra work to unglue it.  This way, we can assume that if we
        //  raise the only thing we need to do is deallocate the disk space.
        //
        //  Merge the allocation now.
        //

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

            //
            //  Tack the new Mcb onto the end of the FcbOrDcb one.
            //

            FatMergeAllocation( IrpContext,
                                Vcb,
                                &FcbOrDcb->Mcb,
                                &NewMcb );
        }

    } finally {

        DebugUnwind( FatAddFileAllocation );

        //
        //  Give FlushFileBuffer/Cleanup a clue here, regardless of success/fail..
        //

        SetFlag(FcbOrDcb->FcbState, FCB_STATE_FLUSH_FAT);

        //
        //  If we were dogged trying to complete this operation, we need to go
        //  back various things out.
        //

        if (AbnormalTermination()) {

            //
            //  Pull off the allocation size we tried to add to this object if
            //  we failed to grow cache structures or Mcb structures.
            //

            if (UnwindAllocationSizeSet) {

                FcbOrDcb->Header.AllocationSize.LowPart -= NewAllocation;
            }

            if (UnwindCacheManagerInformed) {

                CcSetFileSizes( FileObject,
                                (PCC_FILE_SIZES)&FcbOrDcb->Header.AllocationSize );
            }

            //
            //  In the case of initial allocation, we used the Fcb's Mcb and have
            //  to clean that up as well as the FAT chain references.
            //

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

                if (Dirent != NULL) {

                    FcbOrDcb->FirstClusterOfFile = 0;
                    Dirent->FirstClusterOfFile = 0;

                    if ( FatIsFat32(Vcb) ) {

                        Dirent->FirstClusterOfFileHi = 0;
                    }
                }
            }

            //
            //  ... and drop the dirent Bcb if we got it.  Do it now
            //  so we can afford to take the exception if we have to.
            //

            FatUnpinBcb( IrpContext, Bcb );

            try {

                //
                //  Note this can re-raise.
                //

                if ( UnwindWeAllocatedDiskSpace ) {

                    FatDeallocateDiskSpace( IrpContext, Vcb, McbToCleanup );
                }

            } finally {

                //
                //  We always want to clean up the non-initial allocation temporary Mcb,
                //  otherwise we have the Fcb's Mcb and we just truncate it away.
                //

                if (UnwindWeInitializedMcb == TRUE) {

                    //
                    //  Note that we already know a raise is in progress.  No danger
                    //  of encountering the normal case code below and doing this again.
                    //

                    FsRtlUninitializeLargeMcb( McbToCleanup );

                } else {

                    if (McbToCleanup) {

                        FsRtlTruncateLargeMcb( McbToCleanup, 0 );
                    }
                }
            }
        }

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

    //
    //  Non-exceptional cleanup we always want to do.  In handling the re-raise possibilities
    //  during exceptions we had to make sure these two steps always happened there beforehand.
    //  So now we handle the usual case.
    //

    FatUnpinBcb( IrpContext, Bcb );

    if (UnwindWeInitializedMcb == TRUE) {

        FsRtlUninitializeLargeMcb( &NewMcb );
    }
}


VOID
FatTruncateFileAllocation (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB FcbOrDcb,
    IN ULONG DesiredAllocationSize
    )

/*++

Routine Description:

    This routine truncates the allocation to the specified file/directory.

    If the file is already smaller than the indicated size 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.

    DesiredAllocationSize - Supplies the maximum size, in bytes, that we want
                            allocated to the file/directory.  It is rounded
                            up to the nearest cluster.

Return Value:

    VOID - TRUE if the operation completed and FALSE if it had to
        block but could not.

--*/

{
    PVCB Vcb;
    PBCB Bcb = NULL;
    LARGE_MCB RemainingMcb;
    ULONG BytesPerCluster;
    PDIRENT Dirent = NULL;
    BOOLEAN UpdatedDirent = FALSE;

    ULONG UnwindInitialAllocationSize;
    ULONG UnwindInitialFirstClusterOfFile;
    BOOLEAN UnwindWeAllocatedMcb = FALSE;

    PAGED_CODE();

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

    //
    //  If the Fcb isn't in good condition, we have no business whacking around on
    //  the disk after "its" clusters.
    //
    //  Inspired by a Prefix complaint.
    //
    
    ASSERT( FcbOrDcb->FcbCondition == FcbGood );

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

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

        FatLookupFileAllocationSize( IrpContext, FcbOrDcb );
    }

    //
    //  Round up the Desired Allocation Size to the next cluster size
    //

    Vcb = FcbOrDcb->Vcb;

    BytesPerCluster = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;

    //
    //  Note if the desired allocation is zero, to distinguish this from
    //  the wrap case below.
    //

    if (DesiredAllocationSize != 0) {

        DesiredAllocationSize = (DesiredAllocationSize + (BytesPerCluster - 1)) &
                                ~(BytesPerCluster - 1);
        //
        //  Check for the benign case that the file is already smaller than
        //  the desired truncation.  Note that if it wraps, then a) it was
        //  specifying an offset in the maximally allocatable cluster and
        //  b) we're not asking to extend the file, either.  So stop.
        //

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

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

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

    }

    UnwindInitialAllocationSize = FcbOrDcb->Header.AllocationSize.LowPart;
    UnwindInitialFirstClusterOfFile = FcbOrDcb->FirstClusterOfFile;

    //
    //  Update the FcbOrDcb allocation size.  If it is now zero, we have the
    //  additional task of modifying the FcbOrDcb and Dirent copies of
    //  FirstClusterInFile.
    //
    //  Note that we must pin the dirent before actually deallocating the
    //  disk space since, in unwind, it would not be possible to reallocate
    //  deallocated disk space as someone else may have reallocated it and
    //  may cause an exception when you try to get some more disk space.
    //  Thus FatDeallocateDiskSpace must be the final dangerous operation.
    //

    try {

        FcbOrDcb->Header.AllocationSize.QuadPart = DesiredAllocationSize;

        //
        //  Special case 0
        //

        if (DesiredAllocationSize == 0) {

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

            ASSERT( FcbOrDcb->FcbCondition == FcbGood );
            
            FatGetDirentFromFcbOrDcb( IrpContext, FcbOrDcb, FALSE, &Dirent, &Bcb );

            Dirent->FirstClusterOfFile = 0;

            if (FatIsFat32(Vcb)) {

                Dirent->FirstClusterOfFileHi = 0;
            }

            FcbOrDcb->FirstClusterOfFile = 0;

            FatSetDirtyBcb( IrpContext, Bcb, Vcb, TRUE );
            UpdatedDirent = TRUE;

            FatDeallocateDiskSpace( IrpContext, Vcb, &FcbOrDcb->Mcb );

            FatRemoveMcbEntry( FcbOrDcb->Vcb, &FcbOrDcb->Mcb, 0, 0xFFFFFFFF );

        } else {

            //
            //  Split the existing allocation into two parts, one we will keep, and
            //  one we will deallocate.
            //

            FsRtlInitializeLargeMcb( &RemainingMcb, PagedPool );
            UnwindWeAllocatedMcb = TRUE;

            FatSplitAllocation( IrpContext,
                                Vcb,
                                &FcbOrDcb->Mcb,
                                DesiredAllocationSize,
                                &RemainingMcb );

            FatDeallocateDiskSpace( IrpContext, Vcb, &RemainingMcb );

            FsRtlUninitializeLargeMcb( &RemainingMcb );
        }

    } finally {

        DebugUnwind( FatTruncateFileAllocation );

        //
        //  Is this really the right backout strategy?  It would be nice if we could
        //  pretend the truncate worked if we knew that the file had gotten into
        //  a consistent state.  Leaving dangled clusters is probably quite preferable.
        //

        if ( AbnormalTermination() ) {

            FcbOrDcb->Header.AllocationSize.LowPart = UnwindInitialAllocationSize;

            if ( (DesiredAllocationSize == 0) && (Dirent != NULL)) {

                if (UpdatedDirent)  {

                    //
                    //  If the dirent has been updated ok and marked dirty,  then we
                    //  failed in deallocatediscspace,  and don't know what state
                    //  the on disc fat chain is in.  So we throw away the mcb,
                    //  and potentially loose a few clusters until the next
                    //  chkdsk.  The operation has succeeded,  but the exception
                    //  will still propogate.  5.1
                    //

                    FatRemoveMcbEntry( Vcb, &FcbOrDcb->Mcb, 0, 0xFFFFFFFF );
                    FcbOrDcb->Header.AllocationSize.QuadPart = 0;
                }
                else  {

⌨️ 快捷键说明

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