📄 allocsup.c
字号:
//
// Delete a pre-existing (partially initialized from a failed
// crawl of a VDS) Pcb.
//
if (*Pcb != NULL) {
UdfDeletePcb( *Pcb );
*Pcb = NULL;
}
*Pcb = UdfCreatePcb( LVD->MapTableCount );
//
// Walk the table of partition maps intializing the Pcb for the descriptor
// initialization pass.
//
for (Map = (PPARTMAP_UDF_GENERIC) LVD->MapTable,
Partition = (*Pcb)->Partition;
Partition < &(*Pcb)->Partition[(*Pcb)->Partitions];
Map = Add2Ptr( Map, Map->Length, PPARTMAP_UDF_GENERIC ),
Partition++) {
//
// Now check that this LVD can actually contain this map entry. First check that
// the descriptor can contain the first few fields, then check that it can hold
// all of the bytes claimed by the descriptor.
//
if (Add2Ptr( Map, sizeof( PARTMAP_GENERIC ), PCHAR ) > Add2Ptr( LVD, ISONsrLvolSize( LVD ), PCHAR ) ||
Add2Ptr( Map, Map->Length, PCHAR ) > Add2Ptr( LVD, ISONsrLvolSize( LVD ), PCHAR )) {
DebugTrace(( 0, Dbg,
"UdfInitializePcb, map at +%04x beyond Lvd size %04x\n",
(PCHAR) Map - (PCHAR) LVD,
ISONsrLvolSize( LVD )));
DebugTrace(( -1, Dbg,
"UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
return STATUS_DISK_CORRUPT_ERROR;
}
//
// Now load up this map entry.
//
switch (Map->Type) {
case PARTMAP_TYPE_PHYSICAL:
{
PPARTMAP_PHYSICAL MapPhysical = (PPARTMAP_PHYSICAL) Map;
//
// Type 1 - Physical Partition
//
DebugTrace(( 0, Dbg,
"UdfInitializePcb, map reference %02x is Physical (Partition # %08x)\n",
(Partition - (*Pcb)->Partition)/sizeof(PARTITION),
MapPhysical->Partition ));
//
// It must be the case that the volume the partition is on is the first
// one since we only do single disc UDF. This will have already been
// checked by the caller.
//
if (MapPhysical->VolSetSeq > 1) {
DebugTrace(( 0, Dbg,
"UdfInitializePcb, ... but physical partition resides on volume set volume # %08x (> 1)!\n",
MapPhysical->VolSetSeq ));
DebugTrace(( -1, Dbg,
"UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
return STATUS_DISK_CORRUPT_ERROR;
}
SetFlag( (*Pcb)->Flags, PCB_FLAG_PHYSICAL_PARTITION );
Partition->Type = Physical;
Partition->Physical.PartitionNumber = MapPhysical->Partition;
}
break;
case PARTMAP_TYPE_PROXY:
//
// Type 2 - a Proxy Partition, something not explicitly physical.
//
DebugTrace(( 0, Dbg,
"UdfInitializePcb, map reference %02x is a proxy\n",
(Partition - (*Pcb)->Partition)/sizeof(PARTITION)));
//
// Handle the various types of proxy partitions we recognize
//
if (UdfDomainIdentifierContained( &Map->PartID,
&UdfVirtualPartitionDomainIdentifier,
UDF_VERSION_150,
UDF_VERSION_RECOGNIZED )) {
{
PPARTMAP_VIRTUAL MapVirtual = (PPARTMAP_VIRTUAL) Map;
//
// Only one of these guys can exist, since there can be only one VAT per media surface.
//
if (FlagOn( (*Pcb)->Flags, PCB_FLAG_VIRTUAL_PARTITION )) {
DebugTrace(( 0, Dbg,
"UdfInitializePcb, ... but this is a second virtual partition!?!!\n" ));
DebugTrace(( -1, Dbg,
"UdfInitializePcb -> STATUS_UNCRECOGNIZED_VOLUME\n" ));
return STATUS_UNRECOGNIZED_VOLUME;
}
DebugTrace(( 0, Dbg,
"UdfInitializePcb, ... Virtual (Partition # %08x)\n",
MapVirtual->Partition ));
SetFlag( (*Pcb)->Flags, PCB_FLAG_VIRTUAL_PARTITION );
Partition->Type = Virtual;
//
// We will convert the partition number to a partition reference
// before returning.
//
Partition->Virtual.RelatedReference = MapVirtual->Partition;
}
} else if (UdfDomainIdentifierContained( &Map->PartID,
&UdfSparablePartitionDomainIdentifier,
UDF_VERSION_150,
UDF_VERSION_RECOGNIZED )) {
{
NTSTATUS Status;
PPARTMAP_SPARABLE MapSparable = (PPARTMAP_SPARABLE) Map;
//
// It must be the case that the volume the partition is on is the first
// one since we only do single disc UDF. This will have already been
// checked by the caller.
//
if (MapSparable->VolSetSeq > 1) {
DebugTrace(( 0, Dbg,
"UdfInitializePcb, ... but sparable partition resides on volume set volume # %08x (> 1)!\n",
MapSparable->VolSetSeq ));
DebugTrace(( -1, Dbg,
"UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
return STATUS_DISK_CORRUPT_ERROR;
}
DebugTrace(( 0, Dbg,
"UdfInitializePcb, ... Sparable (Partition # %08x)\n",
MapSparable->Partition ));
//
// We pretend that sparable partitions are basically the same as
// physical partitions. Since we are not r/w (and will never be
// on media that requires host-based sparing in any case), this
// is a good simplification.
//
SetFlag( (*Pcb)->Flags, PCB_FLAG_SPARABLE_PARTITION );
Partition->Type = Physical;
Partition->Physical.PartitionNumber = MapSparable->Partition;
//
// Save this map for use when the partition descriptor is found.
// We can't load the sparing table at this time because we have
// to turn the Lbn->Psn mapping into a Psn->Psn mapping. UDF
// believes that the way sparing will be used in concert with
// the Lbn->Psn mapping engine (like UdfLookupPsnOfExtent).
//
// Unfortunately, this would be a bit painful at this time.
// The users of UdfLookupPsnOfExtent would need to iterate
// over a new interface (not so bad) but the Vmcb package
// would need to be turned inside out so that it didn't do
// the page-filling alignment of blocks in the metadata
// stream - instead, UdfLookupMetaVsnOfExtent would need to
// do this itself. I choose to lay the sparing engine into
// the read path and raw sector read engine instead.
//
Partition->Physical.SparingMap = FsRtlAllocatePoolWithTag( PagedPool,
sizeof(PARTMAP_SPARABLE),
TAG_NSR_FSD);
RtlCopyMemory( Partition->Physical.SparingMap,
MapSparable,
sizeof(PARTMAP_SPARABLE));
}
} else {
DebugTrace(( 0, Dbg,
"UdfInitializePcb, ... but we don't recognize this proxy!\n" ));
DebugTrace(( -1, Dbg,
"UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" ));
return STATUS_UNRECOGNIZED_VOLUME;
}
break;
default:
DebugTrace(( 0, Dbg,
"UdfInitializePcb, map reference %02x is of unknown type %02x\n",
Map->Type ));
DebugTrace(( -1, Dbg,
"UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" ));
return STATUS_UNRECOGNIZED_VOLUME;
break;
}
}
if (!FlagOn( (*Pcb)->Flags, PCB_FLAG_PHYSICAL_PARTITION | PCB_FLAG_SPARABLE_PARTITION )) {
DebugTrace(( 0, Dbg,
"UdfInitializePcb, no physical partition seen on this logical volume!\n" ));
DebugTrace(( -1, Dbg,
"UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" ));
return STATUS_UNRECOGNIZED_VOLUME;
}
if (FlagOn( (*Pcb)->Flags, PCB_FLAG_VIRTUAL_PARTITION )) {
PPARTITION Host;
//
// Confirm the validity of any type 2 virtual maps on this volume
// and convert partition numbers to partition references that will
// immediately index an element of the Pcb.
//
for (Partition = (*Pcb)->Partition;
Partition < &(*Pcb)->Partition[(*Pcb)->Partitions];
Partition++) {
if (Partition->Type == Virtual) {
//
// Go find the partition this thing is talking about
//
Found = FALSE;
for (Host = (*Pcb)->Partition;
Host < &(*Pcb)->Partition[(*Pcb)->Partitions];
Host++) {
if (Host->Type == Physical &&
Host->Physical.PartitionNumber ==
Partition->Virtual.RelatedReference) {
Partition->Virtual.RelatedReference =
(USHORT)(Host - (*Pcb)->Partition)/sizeof(PARTITION);
Found = TRUE;
break;
}
}
//
// Failure to find a physical partition for this virtual guy
// is not a good sign.
//
if (!Found) {
return STATUS_DISK_CORRUPT_ERROR;
}
}
}
}
DebugTrace(( -1, Dbg,
"UdfInitializePcb -> STATUS_SUCCESS\n" ));
return STATUS_SUCCESS;
}
VOID
UdfAddToPcb (
IN PPCB Pcb,
IN PNSR_PART PartitionDescriptor
)
/*++
Routine Description:
This routine possibly adds a partition descriptor into a Pcb if it
turns out to be of higher precendence than a descriptor already
present. Used in building a Pcb already initialized in preperation
for UdfCompletePcb.
Arguments:
Vcb - Vcb of the volume the Pcb describes
Pcb - Pcb being filled in
Return Value:
None. An old partition descriptor may be returned in the input field.
--*/
{
USHORT Reference;
PAGED_CODE();
//
// Check inputs
//
ASSERT_PCB( Pcb );
ASSERT( PartitionDescriptor );
for (Reference = 0;
Reference < Pcb->Partitions;
Reference++) {
DebugTrace(( 0, Dbg, "UdfAddToPcb, considering partition reference %d (type %d)\n", (ULONG)Reference, Pcb->Partition[Reference].Type));
switch (Pcb->Partition[Reference].Type) {
case Physical:
//
// Now possibly store this descriptor in the Pcb if it is
// the partition number for this partition reference.
//
if (Pcb->Partition[Reference].Physical.PartitionNumber == PartitionDescriptor->Number) {
//
// It seems to be legal (if questionable) for multiple partition maps to reference
// the same partition descriptor. So we make a copy of the descriptor for each
// referencing partitionmap to make life easier when it comes to freeing it.
//
UdfStoreVolumeDescriptorIfPrevailing( (PNSR_VD_GENERIC *) &Pcb->Partition[Reference].Physical.PartitionDescriptor,
(PNSR_VD_GENERIC) PartitionDescriptor );
}
break;
case Virtual:
break;
default:
ASSERT(FALSE);
break;
}
}
}
NTSTATUS
UdfCompletePcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PPCB Pcb
)
/*++
Routine Description:
This routine completes initialization of a Pcb which has been filled
in with partition descriptors. Initialization-time data such as the
physical partition descriptors will be returned to the system.
Arguments:
Vcb - Vcb of the volume the Pcb describes
Pcb - Pcb being completed
Return Value:
NTSTATUS according to whether intialization completion was succesful
--*/
{
ULONG Reference;
NTSTATUS Status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -