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

📄 allocsup.c

📁 windows 2000中的UDF文件系统的驱动程序.只有读的功能,不支持未关闭的盘片.只支持UDF2.0以下版本,不支持VAT格式的UDF.
💻 C
📖 第 1 页 / 共 4 页
字号:
    PAGED_CODE();

    //
    //  Check inputs
    //

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_VCB( Vcb );
    ASSERT_PCB( Pcb );

    DebugTrace(( +1, Dbg, "UdfCompletePcb, Vcb %08x Pcb %08x\n", Vcb, Pcb ));

    //
    //  Complete intialization all physical partitions
    //

    for (Reference = 0;
         Reference < Pcb->Partitions;
         Reference++) {

        DebugTrace(( 0, Dbg, "UdfCompletePcb, Examining Ref %u (type %u)!\n", Reference, Pcb->Partition[Reference].Type));

        switch (Pcb->Partition[Reference].Type) {

            case Physical:

                if (Pcb->Partition[Reference].Physical.PartitionDescriptor == NULL) {

                    DebugTrace(( 0, Dbg,
                                 "UdfCompletePcb, ... but didn't find Partition# %u!\n",
                                 Pcb->Partition[Reference].Physical.PartitionNumber ));

                    DebugTrace(( -1, Dbg, "UdfCompletePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));

                    return STATUS_DISK_CORRUPT_ERROR;
                }

                Pcb->Partition[Reference].Physical.Start =
                    Pcb->Partition[Reference].Physical.PartitionDescriptor->Start;
                Pcb->Partition[Reference].Physical.Length =
                    Pcb->Partition[Reference].Physical.PartitionDescriptor->Length;


                //
                //  Retrieve the sparing information at this point if appropriate.
                //  We have to do this when we can map logical -> physical blocks.
                //

                if (Pcb->Partition[Reference].Physical.SparingMap) {

                    Status = UdfLoadSparingTables( IrpContext,
                                                   Vcb,
                                                   Pcb,
                                                   Reference );

                    if (!NT_SUCCESS( Status )) {

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

                //
                //  We will not need the descriptor or sparing map anymore, so drop them.  
                //

                UdfFreePool( &Pcb->Partition[Reference].Physical.PartitionDescriptor );
                UdfFreePool( &Pcb->Partition[Reference].Physical.SparingMap );
                break;

            case Virtual:
                break;

            default:

                ASSERT(FALSE);
                break;
        }
    }

    DebugTrace(( -1, Dbg, "UdfCompletePcb -> STATUS_SUCCESS\n" ));

    return STATUS_SUCCESS;
}


BOOLEAN
UdfEquivalentPcb (
    IN PIRP_CONTEXT IrpContext,
    IN PPCB Pcb1,
    IN PPCB Pcb2
    )

/*++

Routine Description:

    This routine compares two completed Pcbs to see if they appear equivalent.

Arguments:

    Pcb1 - Pcb being compared

    Pcb2 - Pcb being compared

Return Value:

    BOOLEAN according to whether they are equivalent (TRUE, else FALSE)

--*/

{
    ULONG Index;

    PAGED_CODE();

    //
    //  Check input.
    //

    ASSERT_IRP_CONTEXT( IrpContext );

    if (Pcb1->Partitions != Pcb2->Partitions) {

        return FALSE;
    }

    for (Index = 0;
         Index < Pcb1->Partitions;
         Index++) {

        //
        //  First check that the partitions are of the same type.
        //

        if (Pcb1->Partition[Index].Type != Pcb2->Partition[Index].Type) {

            return FALSE;
        }

        //
        //  Now the map content must be the same ...
        //

        switch (Pcb1->Partition[Index].Type) {

            case Physical:

                if (Pcb1->Partition[Index].Physical.PartitionNumber != Pcb2->Partition[Index].Physical.PartitionNumber ||
                    Pcb1->Partition[Index].Physical.Length != Pcb2->Partition[Index].Physical.Length ||
                    Pcb1->Partition[Index].Physical.Start != Pcb2->Partition[Index].Physical.Start) {

                    return FALSE;
                }
                break;

            case Virtual:

                if (Pcb1->Partition[Index].Virtual.RelatedReference != Pcb2->Partition[Index].Virtual.RelatedReference) {

                    return FALSE;
                }
                break;

            default:

                ASSERT( FALSE);
                return FALSE;
                break;
        }
    }

    //
    //  All map elements were equivalent.
    //

    return TRUE;
}


ULONG
UdfLookupPsnOfExtent (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN USHORT Reference,
    IN ULONG Lbn,
    IN ULONG Len
    )

/*++

Routine Description:

    This routine maps the input logical block extent on a given partition to
    a starting physical sector.  It doubles as a bounds checker - if the routine
    does not raise, the caller is guaranteed that the extent lies within the
    partition.

Arguments:

    Vcb - Vcb of logical volume

    Reference - Partition reference to use in the mapping

    Lbn - Logical block number

    Len - Length of extent in bytes

Return Value:

    ULONG physical sector number

--*/

{
    PPCB Pcb = Vcb->Pcb;
    ULONG Psn;

    PBCB Bcb;
    LARGE_INTEGER Offset;
    PULONG MappedLbn;

    PAGED_CODE();

    //
    //  Check inputs
    //

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_VCB( Vcb );
    ASSERT_PCB( Pcb );

    DebugTrace(( +1, Dbg, "UdfLookupPsnOfExtent, [%04x/%08x, +%08x)\n", Reference, Lbn, Len ));

    if (Reference < Pcb->Partitions) {

        while (TRUE) {

            switch (Pcb->Partition[Reference].Type) {

                case Physical:

                    //
                    //  Check that the input extent lies inside the partition.  Calculate the
                    //  Lbn of the last block and see that it is interior.
                    //

                    if (SectorsFromBlocks( Vcb, Lbn ) + SectorsFromBytes( Vcb, Len ) >
                        Pcb->Partition[Reference].Physical.Length) {

                        goto NoGood;
                    }

                    Psn = Pcb->Partition[Reference].Physical.Start + SectorsFromBlocks( Vcb, Lbn );

                    DebugTrace(( -1, Dbg, "UdfLookupPsnOfExtent -> %08x\n", Psn ));
                    return Psn;

                case Virtual:

                    //
                    //  Bounds check.  Per UDF 2.00 2.3.10 and implied in UDF 1.50, virtual
                    //  extent lengths cannot be greater than one block in size.
                    //

                    if (Lbn + BlocksFromBytes( Vcb, Len ) > Pcb->Partition[Reference].Virtual.Length ||
                        Len > BlockSize( Vcb )) {

                        goto NoGood;
                    }

                    try {

                        //
                        //  Calculate the location of the mapping element in the VAT
                        //  and retrieve.
                        //

                        Offset.QuadPart = Lbn * sizeof(ULONG);

                        CcMapData( Vcb->VatFcb->FileObject,
                                   &Offset,
                                   sizeof(ULONG),
                                   TRUE,
                                   &Bcb,
                                   &MappedLbn );

                        //
                        //  Now rewrite the inputs in terms of the virtual mapping.  We
                        //  will reloop to perform the logical -> physical mapping.
                        //

                        DebugTrace(( 0, Dbg,
                                     "UdfLookupPsnOfExtent, Mapping V %04x/%08x -> L %04x/%08x\n",
                                     Reference,
                                     Lbn,
                                     Pcb->Partition[Reference].Virtual.RelatedReference,
                                     *MappedLbn ));

                        Lbn = *MappedLbn;
                        Reference = Pcb->Partition[Reference].Virtual.RelatedReference;

                    } finally {

                        DebugUnwind( UdfLookupPsnOfExtent );

                        UdfUnpinData( IrpContext, &Bcb );
                    }

                    //
                    //  An Lbn of ~0 in the VAT is defined to indicate that the sector is unused,
                    //  so we should never see such a thing.
                    //

                    if (Lbn == ~0) {

                        goto NoGood;
                    }

                    break;

                default:

                    ASSERT(FALSE);
                    break;
            }
        }
    }

    NoGood:

    //
    //  Some people have misinterpreted a partition number to equal a
    //  partition reference, or perhaps this is just corrupt media.
    //

    UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}


ULONG
UdfLookupMetaVsnOfExtent (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN USHORT Reference,
    IN ULONG Lbn,
    IN ULONG Len,
    IN BOOLEAN ExactEnd
    )

/*++

Routine Description:

    This routine maps the input logical block extent on a given partition to
    a starting virtual block in the metadata stream.  If a mapping does not
    exist, one will be created and the metadata stream extended.

Arguments:

    Vcb - Vcb of logical volume

    Reference - Partition reference to use in the mapping

    Lbn - Logical block number

    Len - Length of extent in bytes
    
    ExactEnd - Indicates the extension policy if these blocks are not mapped.

Return Value:

    ULONG virtual sector number

    Raised status if the Lbn extent is split across multiple Vbn extents.

--*/

{
    ULONG Vsn;
    ULONG Psn;
    ULONG SectorCount;

    BOOLEAN Result;

    BOOLEAN UnwindExtension = FALSE;
    LONGLONG UnwindAllocationSize;

    PFCB Fcb = NULL;

    //
    //  Check inputs
    //

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_VCB( Vcb );

    //
    //  The extent must be an integral number of logical blocks in length.
    //

    if (Len == 0 || BlockOffset( Vcb, Len )) {

        UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    }


    //
    //  Get the physical mapping of the extent.  The Mcb package operates on ULONG/ULONG
    //  keys and values so we must render our 48bit address into 32.  We can do this since
    //  this is a single surface implementation, and it is guaranteed that a surface cannot
    //  contain more than MAXULONG physical sectors.
    //

    Psn = UdfLookupPsnOfExtent( IrpContext,
                                Vcb,

⌨️ 快捷键说明

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