2025-04-27 07:49:33 -04:00

149 lines
3.9 KiB
C++

/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
ScanADs.cxx
Author:
Centis Biks (cbiks) 05-May-2000
Environment:
ULIB, User Mode
--*/
#include "pch.cxx"
#include "UdfLVol.hxx"
DEFINE_CONSTRUCTOR( SCAN_ALLOCTION_DESCRIPTORS, OBJECT );
BOOL
SCAN_ALLOCTION_DESCRIPTORS::Initialize
(
PUDF_LVOL UdfLVol,
PICBFILE FileIcbEntry
)
{
BOOL Result = TRUE;
_AdType = 0;
_AllocationDescriptors = NULL;
_AllocationDescriptorLength = 0;
_AllocDescOffset = 0;
_ReadBuffer = NULL;
_SectorSize = 0;
_UdfLVol = NULL;
ASSERTMSG( "Unimplemented AD Type.\n",
(FileIcbEntry->Icbtag.Flags & ICBTAG_F_ALLOC_MASK) == ICBTAG_F_ALLOC_SHORT );
_AdType = FileIcbEntry->Icbtag.Flags & ICBTAG_F_ALLOC_MASK;
_AllocationDescriptors = (LPBYTE)( FileIcbEntry ) + FeEasFieldOffset( FileIcbEntry ) + FeEaLength( FileIcbEntry );
_AllocationDescriptorLength = FeAllocLength( FileIcbEntry );
_UdfLVol = UdfLVol;
_SectorSize = _UdfLVol->QuerySectorSize();
_ReadBuffer = (LPBYTE) malloc( _SectorSize );
return TRUE;
}
BOOL
SCAN_ALLOCTION_DESCRIPTORS::Next
(
PULONG StartBlockNum,
PULONG Length,
PSHORT Type
)
{
BOOL Result = FALSE;
if (_AllocDescOffset < _AllocationDescriptorLength) {
PSHORTAD ShortAd = (PSHORTAD)( _AllocationDescriptors + _AllocDescOffset );
*StartBlockNum = ShortAd->Start;
*Length = ShortAd->Length.Length;
*Type = ShortAd->Length.Type;
if (*Length != 0) {
if (*Type == NSRLENGTH_TYPE_CONTINUATION) {
if (RoundUp( *Length, _SectorSize ) != 1) {
// UDF 2.01/2.3.11 - The length of an extent of Allocation Descriptors shall not exceed
// the logical block size.
//
Result = FALSE;
} else {
Result = _UdfLVol->Read( *StartBlockNum, 1, _ReadBuffer );
if (Result) {
Result = _UdfLVol->MarkBlocksUsed( *StartBlockNum, 1 );
Result = VerifyDescriptor( _ReadBuffer, _SectorSize, DESTAG_ID_NSR_ALLOC, NULL );
if (Result) {
PNSR_ALLOC NsrAlloc = (PNSR_ALLOC) _ReadBuffer;
_AllocationDescriptors = _ReadBuffer + sizeof( NSR_ALLOC );
_AllocDescOffset = 0;
_AllocationDescriptorLength = NsrAlloc->AllocLen;
ShortAd = (PSHORTAD)( _AllocationDescriptors + _AllocDescOffset );
*StartBlockNum = ShortAd->Start;
*Length = ShortAd->Length.Length;
*Type = ShortAd->Length.Type;
_AllocDescOffset += sizeof( SHORTAD );
}
}
}
} else {
_AllocDescOffset += sizeof( SHORTAD );
}
}
Result = TRUE;
}
if (*Length == 0) {
// UNDONE, CBiks, 8/3/2000
// This code assumes a zero length means the end of the ADs. Is that ok???
//
// Try to catch the case where we reach the end of the AD's, but there are more blocks
// allocated that we have not read or marked as allocated. For example, this code detects the
// end of the AD's because a length is zero, but the _AllocationDescriptorLength says there
// are more blocks allocated to this AD chain. This should not happen because UDF says
// the AD's must all fit on one page...
//
ASSERTMSG( "End of AD's reached, but more blocks are allocated.",
_AllocationDescriptorLength < _SectorSize );
}
return Result;
}