📄 strucsup.c
字号:
Routine Description:
This routine is called to verify and process the TOC for this disk.
We hide a data track for a CD+ volume.
Arguments:
TargetDeviceObject - Device object to send TOC request to.
CdromToc - Pointer to TOC structure.
Length - On input this is the length of the TOC. On return is the TOC
length we will show to the user.
TrackCount - This is the count of tracks for the TOC. We use this
when creating a pseudo directory for a music disk.
DiskFlags - We return flags indicating what we know about this disk.
Return Value:
NTSTATUS - The result of trying to read the TOC.
--*/
{
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
CDROM_READ_TOC_EX Command;
ULONG CurrentTrack;
ULONG LocalTrackCount;
ULONG LocalTocLength;
ULONG Address = 0;
union {
UCHAR BigEndian[2];
USHORT Length;
} BiasedTocLength;
PTRACK_DATA Track;
PAGED_CODE();
//
// Zero the command block. This conveniently corresponds to an
// LBA mode READ_TOC request.
//
RtlZeroMemory( &Command, sizeof( Command));
//
// Go ahead and read the table of contents
//
Status = CdPerformDevIoCtrlEx( IrpContext,
IOCTL_CDROM_READ_TOC_EX,
TargetDeviceObject,
&Command,
sizeof( Command),
CdromToc,
sizeof( CDROM_TOC_LARGE ),
FALSE,
TRUE,
&Iosb );
//
// Nothing to process if this request fails.
//
if (Status != STATUS_SUCCESS) {
return Status;
}
//
// Get the number of tracks and stated size of this structure.
//
CurrentTrack = 0;
LocalTrackCount = CdromToc->LastTrack - CdromToc->FirstTrack + 1;
LocalTocLength = PtrOffset( CdromToc, &CdromToc->TrackData[LocalTrackCount + 1] );
//
// Get out if there is an immediate problem with the TOC.
//
if ((LocalTocLength > Iosb.Information) ||
(CdromToc->FirstTrack > CdromToc->LastTrack)) {
Status = STATUS_DISK_CORRUPT_ERROR;
return Status;
}
//
// Walk through the individual tracks. Stop at the first data track after
// any lead-in audio tracks.
//
do {
//
// Get the next track.
//
Track = &CdromToc->TrackData[CurrentTrack];
//
// If this is a data track then check if we have only seen audio tracks
// to this point.
//
if (FlagOn( Track->Control, TOC_DATA_TRACK )) {
//
// If we have only seen audio tracks then assume this is a
// CD+ disk. Hide the current data track and only return
// the previous audio tracks. Set the disk type to be mixed
// data/audio.
//
if (FlagOn( *DiskFlags, CDROM_DISK_AUDIO_TRACK ) &&
!FlagOn( *DiskFlags, CDROM_DISK_DATA_TRACK )) {
//
// Remove one track from the TOC.
//
CdromToc->LastTrack -= 1;
//
// Knock 2.5 minutes off the current track to hide the final leadin.
// 2.5 min = 150 sec = (x 75) 11250 frames (sectors).
//
SwapCopyUchar4( &Address, &Track->Address);
Address -= 11250;
SwapCopyUchar4( &Track->Address, &Address);
Track->TrackNumber = TOC_LAST_TRACK;
//
// Set the disk type to mixed data/audio.
//
SetFlag( *DiskFlags, CDROM_DISK_DATA_TRACK );
break;
}
//
// Set the flag to indicate data tracks present.
//
SetFlag( *DiskFlags, CDROM_DISK_DATA_TRACK );
//
// If this is a audio track then set the flag indicating audio
// tracks.
//
} else {
SetFlag( *DiskFlags, CDROM_DISK_AUDIO_TRACK );
}
//
// Set our index for the next track.
//
CurrentTrack += 1;
} while (CurrentTrack < LocalTrackCount);
//
// Set the length to point just past the last track we looked at.
//
*TrackCount = CurrentTrack;
*Length = PtrOffset( CdromToc, &CdromToc->TrackData[CurrentTrack + 1] );
BiasedTocLength.Length = (USHORT) *Length - 2;
CdromToc->Length[0] = BiasedTocLength.BigEndian[1];
CdromToc->Length[1] = BiasedTocLength.BigEndian[0];
return Status;
}
//
// Local support routine
//
VOID
CdDeleteFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
)
/*++
Routine Description:
This routine is called to cleanup and deallocate an Fcb. We know there
are no references remaining. We cleanup any auxilary structures and
deallocate this Fcb.
Arguments:
Fcb - This is the Fcb to deallcoate.
Return Value:
None
--*/
{
PVCB Vcb = NULL;
PAGED_CODE();
//
// Sanity check the counts.
//
ASSERT( Fcb->FcbCleanup == 0 );
ASSERT( Fcb->FcbReference == 0 );
//
// Release any Filter Context structures associated with this FCB
//
FsRtlTeardownPerStreamContexts( &Fcb->Header );
//
// Start with the common structures.
//
CdUninitializeMcb( IrpContext, Fcb );
CdDeleteFcbNonpaged( IrpContext, Fcb->FcbNonpaged );
//
// Check if we need to deallocate the prefix name buffer.
//
if ((Fcb->FileNamePrefix.ExactCaseName.FileName.Buffer != (PWCHAR) Fcb->FileNamePrefix.FileNameBuffer) &&
(Fcb->FileNamePrefix.ExactCaseName.FileName.Buffer != NULL)) {
CdFreePool( &Fcb->FileNamePrefix.ExactCaseName.FileName.Buffer );
}
//
// Now look at the short name prefix.
//
if (Fcb->ShortNamePrefix != NULL) {
CdFreePool( &Fcb->ShortNamePrefix );
}
//
// Now do the type specific structures.
//
switch (Fcb->NodeTypeCode) {
case CDFS_NTC_FCB_PATH_TABLE:
case CDFS_NTC_FCB_INDEX:
ASSERT( Fcb->FileObject == NULL );
ASSERT( IsListEmpty( &Fcb->FcbQueue ));
if (Fcb == Fcb->Vcb->RootIndexFcb) {
Vcb = Fcb->Vcb;
Vcb->RootIndexFcb = NULL;
} else if (Fcb == Fcb->Vcb->PathTableFcb) {
Vcb = Fcb->Vcb;
Vcb->PathTableFcb = NULL;
}
CdDeallocateFcbIndex( IrpContext, Fcb );
break;
case CDFS_NTC_FCB_DATA :
if (Fcb->FileLock != NULL) {
FsRtlFreeFileLock( Fcb->FileLock );
}
FsRtlUninitializeOplock( &Fcb->Oplock );
if (Fcb == Fcb->Vcb->VolumeDasdFcb) {
Vcb = Fcb->Vcb;
Vcb->VolumeDasdFcb = NULL;
}
CdDeallocateFcbData( IrpContext, Fcb );
}
//
// Decrement the Vcb reference count if this is a system
// Fcb.
//
if (Vcb != NULL) {
InterlockedDecrement( &Vcb->VcbReference );
InterlockedDecrement( &Vcb->VcbUserReference );
}
return;
}
//
// Local support routine
//
PFCB_NONPAGED
CdCreateFcbNonpaged (
IN PIRP_CONTEXT IrpContext
)
/*++
Routine Description:
This routine is called to create and initialize the non-paged portion
of an Fcb.
Arguments:
Return Value:
PFCB_NONPAGED - Pointer to the created nonpaged Fcb. NULL if not created.
--*/
{
PFCB_NONPAGED FcbNonpaged;
PAGED_CODE();
//
// Allocate the non-paged pool and initialize the various
// synchronization objects.
//
FcbNonpaged = CdAllocateFcbNonpaged( IrpContext );
if (FcbNonpaged != NULL) {
RtlZeroMemory( FcbNonpaged, sizeof( FCB_NONPAGED ));
FcbNonpaged->NodeTypeCode = CDFS_NTC_FCB_NONPAGED;
FcbNonpaged->NodeByteSize = sizeof( FCB_NONPAGED );
ExInitializeResourceLite( &FcbNonpaged->FcbResource );
ExInitializeFastMutex( &FcbNonpaged->FcbMutex );
}
return FcbNonpaged;
}
//
// Local support routine
//
VOID
CdDeleteFcbNonpaged (
IN PIRP_CONTEXT IrpContext,
IN PFCB_NONPAGED FcbNonpaged
)
/*++
Routine Description:
This routine is called to cleanup the non-paged portion of an Fcb.
Arguments:
FcbNonpaged - Structure to clean up.
Return Value:
None
--*/
{
PAGED_CODE();
ExDeleteResourceLite( &FcbNonpaged->FcbResource );
CdDeallocateFcbNonpaged( IrpContext, FcbNonpaged );
return;
}
//
// Local support routine
//
RTL_GENERIC_COMPARE_RESULTS
CdFcbTableCompare (
IN PRTL_GENERIC_TABLE FcbTable,
IN PVOID Fid1,
IN PVOID Fid2
)
/*++
Routine Description:
This routine is the Cdfs compare routine called by the generic table package.
If will compare the two File Id values and return a comparison result.
Arguments:
FcbTable - This is the table being searched.
Fid1 - First key value.
Fid2 - Second key value.
Return Value:
RTL_GENERIC_COMPARE_RESULTS - The results of comparing the two
input structures
--*/
{
FILE_ID Id1, Id2;
PAGED_CODE();
Id1 = *((FILE_ID UNALIGNED *) Fid1);
Id2 = *((FILE_ID UNALIGNED *) Fid2);
if (Id1.QuadPart < Id2.QuadPart) {
return GenericLessThan;
} else if (Id1.QuadPart > Id2.QuadPart) {
return GenericGreaterThan;
} else {
return GenericEqual;
}
UNREFERENCED_PARAMETER( FcbTable );
}
//
// Local support routine
//
PVOID
CdAllocateFcbTable (
IN PRTL_GENERIC_TABLE FcbTable,
IN CLONG ByteSize
)
/*++
Routine Description:
This is a generic table support routine to allocate memory
Arguments:
FcbTable - Supplies the generic table being used
ByteSize - Supplies the number of bytes to allocate
Return Value:
PVOID - Returns a pointer to the allocated data
--*/
{
PAGED_CODE();
return( FsRtlAllocatePoolWithTag( CdPagedPool, ByteSize, TAG_FCB_TABLE ));
}
//
// Local support routine
//
VOID
CdDeallocateFcbTable (
IN PRTL_GENERIC_TABLE FcbTable,
IN PVOID Buffer
)
/*++
Routine Description:
This is a generic table support routine that deallocates memory
Arguments:
FcbTable - Supplies the generic table being used
Buffer - Supplies the buffer being deallocated
Return Value:
None.
--*/
{
PAGED_CODE();
CdFreePool( &Buffer );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -