📄 allocsup.c
字号:
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 + -