📄 dirsup.c
字号:
&FileContext->InitialDirent->Dirent );
//
// Exit the loop if we had the end for the previous file.
//
if (FoundLastDirent) {
break;
}
//
// Always use a single dirent from this point on.
//
CurrentDirContext = TargetDirContext;
}
return FoundDirent;
}
VOID
CdLookupLastFileDirent (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PFILE_ENUM_CONTEXT FileContext
)
/*++
Routine Description:
This routine is called when we've found the matching initial dirent for
a file. Now we want to find all of the dirents for a file as well as
compute the running total for the file size.
We also go out to the system use area and check whether this is an
XA sector. In that case we will compute the real file size.
The dirent in the initial compound dirent has been updated from the
raw dirent when this routine is called.
Arguments:
Fcb - Directory containing the entries for the file.
FileContext - Enumeration context for this search. It currently points
to the first dirent of the file and the in-memory dirent has been
updated.
Return Value:
None. This routine may raise STATUS_FILE_CORRUPT.
--*/
{
XA_EXTENT_TYPE ExtentType;
PCOMPOUND_DIRENT CurrentCompoundDirent;
PDIRENT CurrentDirent;
BOOLEAN FirstPass = TRUE;
BOOLEAN FoundDirent;
PAGED_CODE();
//
// The current dirent to look at is the initial dirent for the file.
//
CurrentCompoundDirent = FileContext->InitialDirent;
//
// Loop until we reach the last dirent for the file.
//
while (TRUE) {
CurrentDirent = &CurrentCompoundDirent->Dirent;
//
// Check if this extent has XA sectors.
//
if ((CurrentDirent->SystemUseOffset != 0) &&
FlagOn( Fcb->Vcb->VcbState, VCB_STATE_CDXA ) &&
CdCheckForXAExtent( IrpContext,
CdRawDirent( IrpContext, &CurrentCompoundDirent->DirContext ),
CurrentDirent )) {
//
// Any previous dirent must describe XA sectors as well.
//
if (!FirstPass && (ExtentType != CurrentDirent->ExtentType)) {
CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// If there are XA sectors then the data on the disk must
// be correctly aligned on sectors and be an integral number of
// sectors. Only an issue if the logical block size is not
// 2048.
//
if (Fcb->Vcb->BlockSize != SECTOR_SIZE) {
//
// We will do the following checks.
//
// Data must start on a sector boundary.
// Data length must be integral number of sectors.
//
if ((SectorBlockOffset( Fcb->Vcb, CurrentDirent->StartingOffset ) != 0) ||
(SectorBlockOffset( Fcb->Vcb, CurrentDirent->DataLength ) != 0)) {
CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// If interleaved then both the file unit and interleave
// gap must be integral number of sectors.
//
if ((CurrentDirent->FileUnitSize != 0) &&
((SectorBlockOffset( Fcb->Vcb, CurrentDirent->FileUnitSize ) != 0) ||
(SectorBlockOffset( Fcb->Vcb, CurrentDirent->InterleaveGapSize ) != 0))) {
CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
}
//
// If this is the first dirent then add the bytes for the RIFF
// header.
//
if (FirstPass) {
FileContext->FileSize = sizeof( RIFF_HEADER );
}
//
// Add the size of the mode2-form2 sector for each sector
// we have here.
//
FileContext->FileSize += Int32x32To64( CurrentDirent->DataLength >> SECTOR_SHIFT,
XA_SECTOR_SIZE);
} else {
//
// This extent does not have XA sectors. Any previous dirent
// better not have XA sectors.
//
if (!FirstPass && (ExtentType != CurrentDirent->ExtentType)) {
CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// Add these bytes to the file size.
//
FileContext->FileSize += CurrentDirent->DataLength;
}
//
// If we are at the last dirent then exit.
//
if (!FlagOn( CurrentDirent->DirentFlags, CD_ATTRIBUTE_MULTI )) {
break;
}
//
// Remember the extent type of the current extent.
//
ExtentType = CurrentDirent->ExtentType;
//
// Look for the next dirent of the file.
//
FoundDirent = CdLookupNextDirent( IrpContext,
Fcb,
&CurrentCompoundDirent->DirContext,
&FileContext->CurrentDirent->DirContext );
//
// If we didn't find the entry then this is a corrupt directory.
//
if (!FoundDirent) {
CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// Remember the dirent we just found.
//
CurrentCompoundDirent = FileContext->CurrentDirent;
FirstPass = FALSE;
//
// Look up all of the dirent information for the given dirent.
//
CdUpdateDirentFromRawDirent( IrpContext,
Fcb,
&CurrentCompoundDirent->DirContext,
&CurrentCompoundDirent->Dirent );
//
// Set flag to show there were multiple extents.
//
SetFlag( FileContext->Flags, FILE_CONTEXT_MULTIPLE_DIRENTS );
}
return;
}
VOID
CdCleanupFileContext (
IN PIRP_CONTEXT IrpContext,
IN PFILE_ENUM_CONTEXT FileContext
)
/*++
Routine Description:
This routine is called to cleanup the enumeration context for a file
search in a directory. We will unpin any remaining Bcbs and free
any allocated buffers.
Arguments:
FileContext - Enumeration context for the file search.
Return Value:
None.
--*/
{
PCOMPOUND_DIRENT CurrentCompoundDirent;
ULONG Count = 2;
PAGED_CODE();
//
// Cleanup the individual compound dirents.
//
do {
CurrentCompoundDirent = &FileContext->Dirents[ Count ];
CdCleanupDirContext( IrpContext, &CurrentCompoundDirent->DirContext );
CdCleanupDirent( IrpContext, &CurrentCompoundDirent->Dirent );
} while (Count--);
return;
}
//
// Local support routine
//
ULONG
CdCheckRawDirentBounds (
IN PIRP_CONTEXT IrpContext,
IN PDIRENT_ENUM_CONTEXT DirContext
)
/*++
Routine Description:
This routine takes a Dirent enumeration context and computes the offset
to the next dirent. A non-zero value indicates the offset within this
sector. A zero value indicates to move to the next sector. If the
current dirent does not fit within the sector then we will raise
STATUS_CORRUPT.
Arguments:
DirContext - Enumeration context indicating the current position in
the sector.
Return Value:
ULONG - Offset to the next dirent in this sector or zero if the
next dirent is in the next sector.
This routine will raise on a dirent which does not fit into the
described data buffer.
--*/
{
ULONG NextDirentOffset;
PRAW_DIRENT RawDirent;
PAGED_CODE();
//
// We should always have at least a byte still available in the
// current buffer.
//
ASSERT( (DirContext->DataLength - DirContext->SectorOffset) >= 1 );
//
// Get a pointer to the current dirent.
//
RawDirent = CdRawDirent( IrpContext, DirContext );
//
// If the dirent length is non-zero then look at the current dirent.
//
if (RawDirent->DirLen != 0) {
//
// Check the following bound for the dirent length.
//
// - Fits in the available bytes in the sector.
// - Is at least the minimal dirent size.
// - Is large enough to hold the file name.
//
if ((RawDirent->DirLen > (DirContext->DataLength - DirContext->SectorOffset)) ||
(RawDirent->DirLen < MIN_RAW_DIRENT_LEN) ||
(RawDirent->DirLen < (MIN_RAW_DIRENT_LEN - 1 + RawDirent->FileIdLen))) {
CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// Copy the dirent length field.
//
NextDirentOffset = RawDirent->DirLen;
//
// If we are exactly at the next sector then tell our caller by
// returning zero.
//
if (NextDirentOffset == (DirContext->DataLength - DirContext->SectorOffset)) {
NextDirentOffset = 0;
}
} else {
NextDirentOffset = 0;
}
return NextDirentOffset;
}
//
// Local support routine
//
XA_EXTENT_TYPE
CdCheckForXAExtent (
IN PIRP_CONTEXT IrpContext,
IN PRAW_DIRENT RawDirent,
IN OUT PDIRENT Dirent
)
/*++
Routine Description:
This routine is called to scan through the system use area to test if
the current dirent has the XA bit set. The bit in the in-memory
dirent will be set as appropriate.
Arguments:
RawDirent - Pointer to the on-disk dirent.
Dirent - Pointer to the in-memory dirent. We will update this with the
appropriate XA flag.
Return Value:
XA_EXTENT_TYPE - Type of physical extent for this on disk dirent.
--*/
{
XA_EXTENT_TYPE ExtentType = Form1Data;
PSYSTEM_USE_XA SystemUseArea;
PAGED_CODE();
//
// Check if there is enough space for the XA system use area.
//
if (Dirent->DirentLength - Dirent->SystemUseOffset >= sizeof( SYSTEM_USE_XA )) {
SystemUseArea = Add2Ptr( RawDirent, Dirent->SystemUseOffset, PSYSTEM_USE_XA );
//
// Check for a valid signature.
//
if (SystemUseArea->Signature == SYSTEM_XA_SIGNATURE) {
//
// Check for an audio track.
//
if (FlagOn( SystemUseArea->Attributes, SYSTEM_USE_XA_DA )) {
ExtentType = CDAudio;
} else if (FlagOn( SystemUseArea->Attributes, SYSTEM_USE_XA_FORM2 )) {
//
// Check for XA data. Note that a number of discs (video CDs)
// have files marked as type XA Mode 2 Form 1 (2048 bytes of
// user data), but actually record these sectors as Mode2 Form 2
// (2352). We will fail to read these files, since for M2F1,
// a normal read CD command is issued (as per SCSI specs).
//
ExtentType = Mode2Form2Data;
}
Dirent->XAAttributes = SystemUseArea->Attributes;
Dirent->XAFileNumber = SystemUseArea->FileNumber;
}
}
Dirent->ExtentType = ExtentType;
return ExtentType;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -