149 lines
3.9 KiB
C++
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;
|
|
}
|