📄 strucsup.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
StrucSup.c
Abstract:
This module implements the Cdfs in-memory data structure manipulation
routines
--*/
#include "CdProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_STRUCSUP)
//
// Local macros
//
//
// PFCB
// CdAllocateFcbData (
// IN PIRP_CONTEXT IrpContext
// );
//
// VOID
// CdDeallocateFcbData (
// IN PIRP_CONTEXT IrpContext,
// IN PFCB Fcb
// );
//
// PFCB
// CdAllocateFcbIndex (
// IN PIRP_CONTEXT IrpContext
// );
//
// VOID
// CdDeallocateFcbIndex (
// IN PIRP_CONTEXT IrpContext,
// IN PFCB Fcb
// );
//
// PFCB_NONPAGED
// CdAllocateFcbNonpaged (
// IN PIRP_CONTEXT IrpContext
// );
//
// VOID
// CdDeallocateFcbNonpaged (
// IN PIRP_CONTEXT IrpContext,
// IN PFCB_NONPAGED FcbNonpaged
// );
//
// PCCB
// CdAllocateCcb (
// IN PIRP_CONTEXT IrpContext
// );
//
// VOID
// CdDeallocateCcb (
// IN PIRP_CONTEXT IrpContext,
// IN PCCB Ccb
// );
//
#define CdAllocateFcbData(IC) \
FsRtlAllocatePoolWithTag( CdPagedPool, SIZEOF_FCB_DATA, TAG_FCB_DATA )
#define CdDeallocateFcbData(IC,F) \
CdFreePool( &(F) )
#define CdAllocateFcbIndex(IC) \
FsRtlAllocatePoolWithTag( CdPagedPool, SIZEOF_FCB_INDEX, TAG_FCB_INDEX )
#define CdDeallocateFcbIndex(IC,F) \
CdFreePool( &(F) )
#define CdAllocateFcbNonpaged(IC) \
ExAllocatePoolWithTag( CdNonPagedPool, sizeof( FCB_NONPAGED ), TAG_FCB_NONPAGED )
#define CdDeallocateFcbNonpaged(IC,FNP) \
CdFreePool( &(FNP) )
#define CdAllocateCcb(IC) \
FsRtlAllocatePoolWithTag( CdPagedPool, sizeof( CCB ), TAG_CCB )
#define CdDeallocateCcb(IC,C) \
CdFreePool( &(C) )
//
// Local structures
//
typedef struct _FCB_TABLE_ELEMENT {
FILE_ID FileId;
PFCB Fcb;
} FCB_TABLE_ELEMENT, *PFCB_TABLE_ELEMENT;
//
// Local macros
//
//
// VOID
// CdInsertFcbTable (
// IN PIRP_CONTEXT IrpContext,
// IN PFCB Fcb
// );
//
// VOID
// CdDeleteFcbTable (
// IN PIRP_CONTEXT IrpContext,
// IN PFCB Fcb
// );
//
#define CdInsertFcbTable(IC,F) { \
FCB_TABLE_ELEMENT _Key; \
_Key.Fcb = (F); \
_Key.FileId = (F)->FileId; \
RtlInsertElementGenericTable( &(F)->Vcb->FcbTable, \
&_Key, \
sizeof( FCB_TABLE_ELEMENT ), \
NULL ); \
}
#define CdDeleteFcbTable(IC,F) { \
FCB_TABLE_ELEMENT _Key; \
_Key.FileId = (F)->FileId; \
RtlDeleteElementGenericTable( &(F)->Vcb->FcbTable, &_Key ); \
}
//
// Local support routines
//
VOID
CdDeleteFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
);
PFCB_NONPAGED
CdCreateFcbNonpaged (
IN PIRP_CONTEXT IrpContext
);
VOID
CdDeleteFcbNonpaged (
IN PIRP_CONTEXT IrpContext,
IN PFCB_NONPAGED FcbNonpaged
);
RTL_GENERIC_COMPARE_RESULTS
CdFcbTableCompare (
IN PRTL_GENERIC_TABLE FcbTable,
IN PVOID Fid1,
IN PVOID Fid2
);
PVOID
CdAllocateFcbTable (
IN PRTL_GENERIC_TABLE FcbTable,
IN CLONG ByteSize
);
VOID
CdDeallocateFcbTable (
IN PRTL_GENERIC_TABLE FcbTable,
IN PVOID Buffer
);
ULONG
CdTocSerial (
IN PIRP_CONTEXT IrpContext,
IN PCDROM_TOC_LARGE CdromToc
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdAllocateFcbTable)
#pragma alloc_text(PAGE, CdCleanupIrpContext)
#pragma alloc_text(PAGE, CdCreateCcb)
#pragma alloc_text(PAGE, CdCreateFcb)
#pragma alloc_text(PAGE, CdCreateFcbNonpaged)
#pragma alloc_text(PAGE, CdCreateFileLock)
#pragma alloc_text(PAGE, CdCreateIrpContext)
#pragma alloc_text(PAGE, CdDeallocateFcbTable)
#pragma alloc_text(PAGE, CdDeleteCcb)
#pragma alloc_text(PAGE, CdDeleteFcb)
#pragma alloc_text(PAGE, CdDeleteFcbNonpaged)
#pragma alloc_text(PAGE, CdDeleteFileLock)
#pragma alloc_text(PAGE, CdDeleteVcb)
#pragma alloc_text(PAGE, CdFcbTableCompare)
#pragma alloc_text(PAGE, CdGetNextFcb)
#pragma alloc_text(PAGE, CdInitializeFcbFromFileContext)
#pragma alloc_text(PAGE, CdInitializeFcbFromPathEntry)
#pragma alloc_text(PAGE, CdInitializeStackIrpContext)
#pragma alloc_text(PAGE, CdInitializeVcb)
#pragma alloc_text(PAGE, CdLookupFcbTable)
#pragma alloc_text(PAGE, CdProcessToc)
#pragma alloc_text(PAGE, CdTeardownStructures)
#pragma alloc_text(PAGE, CdTocSerial)
#pragma alloc_text(PAGE, CdUpdateVcbFromVolDescriptor)
#endif
//
// Some static names for volume streams
//
UNICODE_STRING CdInternalStreamNames[] = {
{ 24, 24, L"$PATH_TABLE$"},
{ 2, 2, L"\\"}
};
VOID
CdInitializeVcb (
IN PIRP_CONTEXT IrpContext,
IN OUT PVCB Vcb,
IN PDEVICE_OBJECT TargetDeviceObject,
IN PVPB Vpb,
IN PCDROM_TOC_LARGE CdromToc,
IN ULONG TocLength,
IN ULONG TocTrackCount,
IN ULONG TocDiskFlags,
IN ULONG BlockFactor,
IN ULONG MediaChangeCount
)
/*++
Routine Description:
This routine initializes and inserts a new Vcb record into the in-memory
data structure. The Vcb record "hangs" off the end of the Volume device
object and must be allocated by our caller.
Arguments:
Vcb - Supplies the address of the Vcb record being initialized.
TargetDeviceObject - Supplies the address of the target device object to
associate with the Vcb record.
Vpb - Supplies the address of the Vpb to associate with the Vcb record.
CdromToc - Buffer to hold table of contents. NULL if TOC command not
supported.
TocLength - Byte count length of TOC. We use this as the TOC length to
return on a user query.
TocTrackCount - Count of tracks in TOC. Used to create pseudo files for
audio disks.
TocDiskFlags - Flag field to indicate the type of tracks on the disk.
BlockFactor - Used to decode any multi-session information.
MediaChangeCount - Initial media change count of the target device
Return Value:
None.
--*/
{
PAGED_CODE();
//
// We start by first zeroing out all of the VCB, this will guarantee
// that any stale data is wiped clean.
//
RtlZeroMemory( Vcb, sizeof( VCB ));
//
// Set the proper node type code and node byte size.
//
Vcb->NodeTypeCode = CDFS_NTC_VCB;
Vcb->NodeByteSize = sizeof( VCB );
//
// Initialize the DirNotify structs. FsRtlNotifyInitializeSync can raise.
//
InitializeListHead( &Vcb->DirNotifyList );
FsRtlNotifyInitializeSync( &Vcb->NotifySync );
//
// Pick up a VPB right now so we know we can pull this filesystem stack
// off of the storage stack on demand. This can raise - if it does,
// uninitialize the notify structures before returning.
//
try {
Vcb->SwapVpb = FsRtlAllocatePoolWithTag( NonPagedPool,
sizeof( VPB ),
TAG_VPB );
}
finally {
if (AbnormalTermination()) {
FsRtlNotifyUninitializeSync( &Vcb->NotifySync );
}
}
//
// Nothing beyond this point should raise.
//
RtlZeroMemory( Vcb->SwapVpb, sizeof( VPB ) );
//
// Initialize the resource variable for the Vcb and files.
//
ExInitializeResourceLite( &Vcb->VcbResource );
ExInitializeResourceLite( &Vcb->FileResource );
ExInitializeFastMutex( &Vcb->VcbMutex );
//
// Insert this Vcb record on the CdData.VcbQueue.
//
InsertHeadList( &CdData.VcbQueue, &Vcb->VcbLinks );
//
// Set the Target Device Object and Vpb fields, referencing the
// Target device for the mount.
//
ObReferenceObject( TargetDeviceObject );
Vcb->TargetDeviceObject = TargetDeviceObject;
Vcb->Vpb = Vpb;
//
// Set the removable media flag based on the real device's
// characteristics
//
if (FlagOn( Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA )) {
SetFlag( Vcb->VcbState, VCB_STATE_REMOVABLE_MEDIA );
}
//
// Initialize the generic Fcb Table.
//
RtlInitializeGenericTable( &Vcb->FcbTable,
(PRTL_GENERIC_COMPARE_ROUTINE) CdFcbTableCompare,
(PRTL_GENERIC_ALLOCATE_ROUTINE) CdAllocateFcbTable,
(PRTL_GENERIC_FREE_ROUTINE) CdDeallocateFcbTable,
NULL );
//
// Show that we have a mount in progress.
//
CdUpdateVcbCondition( Vcb, VcbMountInProgress);
//
// Refererence the Vcb for two reasons. The first is a reference
// that prevents the Vcb from going away on the last close unless
// dismount has already occurred. The second is to make sure
// we don't go into the dismount path on any error during mount
// until we get to the Mount cleanup.
//
Vcb->VcbReference = 1 + CDFS_RESIDUAL_REFERENCE;
//
// Update the TOC information in the Vcb.
//
Vcb->CdromToc = CdromToc;
Vcb->TocLength = TocLength;
Vcb->TrackCount = TocTrackCount;
Vcb->DiskFlags = TocDiskFlags;
//
// If this disk contains audio tracks only then set the audio flag.
//
if (TocDiskFlags == CDROM_DISK_AUDIO_TRACK) {
SetFlag( Vcb->VcbState, VCB_STATE_AUDIO_DISK | VCB_STATE_CDXA );
}
//
// Set the block factor.
//
Vcb->BlockFactor = BlockFactor;
//
// Set the media change count on the device
//
CdUpdateMediaChangeCount( Vcb, MediaChangeCount);
}
VOID
CdUpdateVcbFromVolDescriptor (
IN PIRP_CONTEXT IrpContext,
IN OUT PVCB Vcb,
IN PCHAR RawIsoVd OPTIONAL
)
/*++
Routine Description:
This routine is called to perform the final initialization of a Vcb from the
volume descriptor on the disk.
Arguments:
Vcb - Vcb for the volume being mounted. We have already set the flags for the
type of descriptor.
RawIsoVd - If specified this is the volume descriptor to use to mount the
volume. Not specified for a raw disk.
Return Value:
None
--*/
{
ULONG Shift;
ULONG StartingBlock;
ULONG ByteCount;
LONGLONG FileId = 0;
PRAW_DIRENT RawDirent;
PATH_ENTRY PathEntry;
PCD_MCB_ENTRY McbEntry;
BOOLEAN UnlockVcb = FALSE;
PAGED_CODE();
//
// Use a try-finally to facilitate cleanup.
//
try {
//
// Copy the block size and compute the various block masks.
// Block size must not be larger than the sector size. We will
// use a default of the CD physical sector size if we are not
// on a data-full disc.
//
// This must always be set.
//
Vcb->BlockSize = ( ARGUMENT_PRESENT( RawIsoVd ) ?
CdRvdBlkSz( RawIsoVd, Vcb->VcbState ) :
SECTOR_SIZE );
//
// We no longer accept media where blocksize != sector size.
//
if (Vcb->BlockSize != SECTOR_SIZE) {
CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
}
Vcb->BlocksPerSector = SECTOR_SIZE / Vcb->BlockSize;
Vcb->BlockMask = Vcb->BlockSize - 1;
Vcb->BlockInverseMask = ~Vcb->BlockMask;
Vcb->BlockToSectorShift = 0;
Vcb->BlockToByteShift = SECTOR_SHIFT;
//
// If there is a volume descriptor then do the internal Fcb's and
// other Vcb fields.
//
if (ARGUMENT_PRESENT( RawIsoVd )) {
//
// Create the path table Fcb and refererence it and the Vcb.
//
CdLockVcb( IrpContext, Vcb );
UnlockVcb = TRUE;
Vcb->PathTableFcb = CdCreateFcb( IrpContext,
*((PFILE_ID) &FileId),
CDFS_NTC_FCB_PATH_TABLE,
NULL );
CdIncrementReferenceCounts( IrpContext, Vcb->PathTableFcb, 1, 1 );
CdUnlockVcb( IrpContext, Vcb );
UnlockVcb = FALSE;
//
// Compute the stream offset and size of this path table.
//
StartingBlock = CdRvdPtLoc( RawIsoVd, Vcb->VcbState );
ByteCount = CdRvdPtSz( RawIsoVd, Vcb->VcbState );
Vcb->PathTableFcb->StreamOffset = BytesFromBlocks( Vcb,
SectorBlockOffset( Vcb, StartingBlock ));
Vcb->PathTableFcb->FileSize.QuadPart = (LONGLONG) (Vcb->PathTableFcb->StreamOffset +
ByteCount);
Vcb->PathTableFcb->ValidDataLength.QuadPart = Vcb->PathTableFcb->FileSize.QuadPart;
Vcb->PathTableFcb->AllocationSize.QuadPart = LlSectorAlign( Vcb->PathTableFcb->FileSize.QuadPart );
//
// Now add the mapping information.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -