📄 strucsup.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
StrucSup.c
Abstract:
This module implements the Fat in-memory data structure manipulation
routines
--*/
#include "FatProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (FAT_BUG_CHECK_STRUCSUP)
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_STRUCSUP)
#define FillMemory(BUF,SIZ,MASK) { \
ULONG i; \
for (i = 0; i < (((SIZ)/4) - 1); i += 2) { \
((PULONG)(BUF))[i] = (MASK); \
((PULONG)(BUF))[i+1] = (ULONG)PsGetCurrentThread(); \
} \
}
#define IRP_CONTEXT_HEADER (sizeof( IRP_CONTEXT ) * 0x10000 + FAT_NTC_IRP_CONTEXT)
//
// Local macros.
//
// Define our lookaside list allocators. For the time being, and perhaps
// permanently, the paged structures don't come off of lookasides. This
// is due to complications with clean unload as FAT can be in the paging
// path, making it really hard to find the right time to empty them.
//
// Fortunately, the hit rates on the Fcb/Ccb lists weren't stunning.
//
#define FAT_FILL_FREE 0
INLINE
PCCB
FatAllocateCcb (
)
{
return (PCCB) FsRtlAllocatePoolWithTag( PagedPool, sizeof(CCB), TAG_CCB );
}
INLINE
VOID
FatFreeCcb (
IN PCCB Ccb
)
{
#if FAT_FILL_FREE
RtlFillMemoryUlong(Ccb, sizeof(CCB), FAT_FILL_FREE);
#endif
ExFreePool( Ccb );
}
INLINE
PFCB
FatAllocateFcb (
)
{
return (PFCB) FsRtlAllocatePoolWithTag( PagedPool, sizeof(FCB), TAG_FCB );
}
INLINE
VOID
FatFreeFcb (
IN PFCB Fcb
)
{
#if FAT_FILL_FREE
RtlFillMemoryUlong(Fcb, sizeof(FCB), FAT_FILL_FREE);
#endif
ExFreePool( Fcb );
}
INLINE
PNON_PAGED_FCB
FatAllocateNonPagedFcb (
)
{
return (PNON_PAGED_FCB) ExAllocateFromNPagedLookasideList( &FatNonPagedFcbLookasideList );
}
INLINE
VOID
FatFreeNonPagedFcb (
PNON_PAGED_FCB NonPagedFcb
)
{
#if FAT_FILL_FREE
RtlFillMemoryUlong(NonPagedFcb, sizeof(NON_PAGED_FCB), FAT_FILL_FREE);
#endif
ExFreeToNPagedLookasideList( &FatNonPagedFcbLookasideList, (PVOID) NonPagedFcb );
}
INLINE
PERESOURCE
FatAllocateResource (
)
{
PERESOURCE Resource;
Resource = (PERESOURCE) ExAllocateFromNPagedLookasideList( &FatEResourceLookasideList );
ExInitializeResourceLite( Resource );
return Resource;
}
INLINE
VOID
FatFreeResource (
IN PERESOURCE Resource
)
{
ExDeleteResourceLite( Resource );
#if FAT_FILL_FREE
RtlFillMemoryUlong(Resource, sizeof(ERESOURCE), FAT_FILL_FREE);
#endif
ExFreeToNPagedLookasideList( &FatEResourceLookasideList, (PVOID) Resource );
}
INLINE
PIRP_CONTEXT
FatAllocateIrpContext (
)
{
return (PIRP_CONTEXT) ExAllocateFromNPagedLookasideList( &FatIrpContextLookasideList );
}
INLINE
VOID
FatFreeIrpContext (
IN PIRP_CONTEXT IrpContext
)
{
#if FAT_FILL_FREE
RtlFillMemoryUlong(IrpContext, sizeof(IRP_CONTEXT), FAT_FILL_FREE);
#endif
ExFreeToNPagedLookasideList( &FatIrpContextLookasideList, (PVOID) IrpContext );
}
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatInitializeVcb)
#pragma alloc_text(PAGE, FatTearDownVcb)
#pragma alloc_text(PAGE, FatDeleteVcb)
#pragma alloc_text(PAGE, FatCreateRootDcb)
#pragma alloc_text(PAGE, FatCreateFcb)
#pragma alloc_text(PAGE, FatCreateDcb)
#pragma alloc_text(PAGE, FatDeleteFcb)
#pragma alloc_text(PAGE, FatCreateCcb)
#pragma alloc_text(PAGE, FatDeallocateCcbStrings)
#pragma alloc_text(PAGE, FatDeleteCcb)
#pragma alloc_text(PAGE, FatGetNextFcbTopDown)
#pragma alloc_text(PAGE, FatGetNextFcbBottomUp)
#pragma alloc_text(PAGE, FatConstructNamesInFcb)
#pragma alloc_text(PAGE, FatCheckFreeDirentBitmap)
#pragma alloc_text(PAGE, FatCreateIrpContext)
#pragma alloc_text(PAGE, FatDeleteIrpContext_Real)
#pragma alloc_text(PAGE, FatIsHandleCountZero)
#pragma alloc_text(PAGE, FatPreallocateCloseContext)
#endif
VOID
FatInitializeVcb (
IN PIRP_CONTEXT IrpContext,
IN OUT PVCB Vcb,
IN PDEVICE_OBJECT TargetDeviceObject,
IN PVPB Vpb,
IN PDEVICE_OBJECT FsDeviceObject
)
/*++
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.
FsDeviceObject - The filesystem device object that the mount was directed
too.
Return Value:
None.
--*/
{
CC_FILE_SIZES FileSizes;
PDEVICE_OBJECT RealDevice;
LONG i;
STORAGE_HOTPLUG_INFO HotplugInfo;
NTSTATUS Status;
//
// The following variables are used for abnormal unwind
//
PLIST_ENTRY UnwindEntryList = NULL;
PERESOURCE UnwindResource = NULL;
PERESOURCE UnwindResource2 = NULL;
PFILE_OBJECT UnwindFileObject = NULL;
PFILE_OBJECT UnwindCacheMap = NULL;
BOOLEAN UnwindWeAllocatedMcb = FALSE;
PFILE_SYSTEM_STATISTICS UnwindStatistics = NULL;
DebugTrace(+1, Dbg, "FatInitializeVcb, Vcb = %08lx\n", Vcb);
try {
//
// 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->VolumeFileHeader.NodeTypeCode = FAT_NTC_VCB;
Vcb->VolumeFileHeader.NodeByteSize = sizeof(VCB);
//
// Initialize the tunneling cache
//
FsRtlInitializeTunnelCache(&Vcb->Tunnel);
//
// Insert this Vcb record on the FatData.VcbQueue
//
ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
(VOID)FatAcquireExclusiveGlobal( IrpContext );
InsertTailList( &FatData.VcbQueue, &Vcb->VcbLinks );
FatReleaseGlobal( IrpContext );
UnwindEntryList = &Vcb->VcbLinks;
//
// Set the Target Device Object, Vpb, and Vcb State fields
//
ObReferenceObject( TargetDeviceObject );
Vcb->TargetDeviceObject = TargetDeviceObject;
Vcb->Vpb = Vpb;
Vcb->CurrentDevice = Vpb->RealDevice;
//
// Set the removable media and defflush flags based on the storage
// inquiry and the old characteristic bits.
//
Status = FatPerformDevIoCtrl( IrpContext,
IOCTL_STORAGE_GET_HOTPLUG_INFO,
TargetDeviceObject,
&HotplugInfo,
sizeof(HotplugInfo),
FALSE,
TRUE,
NULL );
if (NT_SUCCESS( Status )) {
if (HotplugInfo.MediaRemovable) {
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA );
}
if (!HotplugInfo.WriteCacheEnableOverride) {
//
// If the device or media is hotplug and the override is not
// set, force defflush behavior for the device.
//
if (HotplugInfo.MediaHotplug || HotplugInfo.DeviceHotplug) {
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH );
//
// Now, for removables that claim to be lockable, lob a lock
// request and see if it works. There can unfortunately be
// transient, media dependent reasons that it can fail. If
// it does not, we must force defflush on.
//
} else if (HotplugInfo.MediaRemovable &&
!HotplugInfo.MediaHotplug) {
Status = FatToggleMediaEjectDisable( IrpContext, Vcb, TRUE );
if (!NT_SUCCESS( Status )) {
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH );
}
Status = FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
}
}
}
if (FlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA)) {
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA );
}
//
// Make sure we turn on deferred flushing for floppies like we always
// have.
//
if (FlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE)) {
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH );
}
FatSetVcbCondition( Vcb, VcbGood);
//
// Initialize the resource variable for the Vcb
//
ExInitializeResourceLite( &Vcb->Resource );
UnwindResource = &Vcb->Resource;
ExInitializeResourceLite( &Vcb->ChangeBitMapResource );
UnwindResource2 = &Vcb->ChangeBitMapResource;
//
// Initialize the free cluster bitmap mutex.
//
ExInitializeFastMutex( &Vcb->FreeClusterBitMapMutex );
//
// Create the special file object for the virtual volume file with a close
// context, its pointers back to the Vcb and the section object pointer.
//
// We don't have to unwind the close context. That will happen in the close
// path automatically.
//
RealDevice = Vcb->CurrentDevice;
Vcb->VirtualVolumeFile = UnwindFileObject = IoCreateStreamFileObject( NULL, RealDevice );
Vcb->CloseContext = FsRtlAllocatePoolWithTag( PagedPool,
sizeof(CLOSE_CONTEXT),
TAG_FAT_CLOSE_CONTEXT );
FatSetFileObject( Vcb->VirtualVolumeFile,
VirtualVolumeFile,
Vcb,
NULL );
//
// Remember this internal, residual open.
//
InterlockedIncrement( &(Vcb->InternalOpenCount) );
InterlockedIncrement( &(Vcb->ResidualOpenCount) );
Vcb->VirtualVolumeFile->SectionObjectPointer = &Vcb->SectionObjectPointers;
Vcb->VirtualVolumeFile->ReadAccess = TRUE;
Vcb->VirtualVolumeFile->WriteAccess = TRUE;
Vcb->VirtualVolumeFile->DeleteAccess = TRUE;
//
// Initialize the notify structures.
//
InitializeListHead( &Vcb->DirNotifyList );
FsRtlNotifyInitializeSync( &Vcb->NotifySync );
//
// Initialize the Cache Map for the volume file. The size is
// initially set to that of our first read. It will be extended
// when we know how big the Fat is.
//
FileSizes.AllocationSize.QuadPart =
FileSizes.FileSize.QuadPart = sizeof(PACKED_BOOT_SECTOR);
FileSizes.ValidDataLength = FatMaxLarge;
CcInitializeCacheMap( Vcb->VirtualVolumeFile,
&FileSizes,
TRUE,
&FatData.CacheManagerNoOpCallbacks,
Vcb );
UnwindCacheMap = Vcb->VirtualVolumeFile;
//
// Initialize the structure that will keep track of dirty fat sectors.
// The largest possible Mcb structures are less than 1K, so we use
// non paged pool.
//
FsRtlInitializeLargeMcb( &Vcb->DirtyFatMcb, PagedPool );
UnwindWeAllocatedMcb = TRUE;
//
// Set the cluster index hint to the first valid cluster of a fat: 2
//
Vcb->ClusterHint = 2;
//
// Initialize the directory stream file object creation event.
// This event is also "borrowed" for async non-cached writes.
//
ExInitializeFastMutex( &Vcb->DirectoryFileCreationMutex );
//
// Initialize the clean volume callback Timer and DPC.
//
KeInitializeTimer( &Vcb->CleanVolumeTimer );
KeInitializeDpc( &Vcb->CleanVolumeDpc, FatCleanVolumeDpc, Vcb );
//
// Initialize the performance counters.
//
Vcb->Statistics = FsRtlAllocatePoolWithTag( NonPagedPool,
sizeof(FILE_SYSTEM_STATISTICS) * KeNumberProcessors,
TAG_VCB_STATS );
UnwindStatistics = Vcb->Statistics;
RtlZeroMemory( Vcb->Statistics, sizeof(FILE_SYSTEM_STATISTICS) * KeNumberProcessors );
for (i = 0; i < KeNumberProcessors; i += 1) {
Vcb->Statistics[i].Common.FileSystemType = FILESYSTEM_STATISTICS_TYPE_FAT;
Vcb->Statistics[i].Common.Version = 1;
Vcb->Statistics[i].Common.SizeOfCompleteStructure =
sizeof(FILE_SYSTEM_STATISTICS);
}
//
// Pick up a VPB right now so we know we can pull this filesystem stack off
// of the storage stack on demand.
//
Vcb->SwapVpb = FsRtlAllocatePoolWithTag( NonPagedPool,
sizeof( VPB ),
TAG_VPB );
RtlZeroMemory( Vcb->SwapVpb, sizeof( VPB ) );
//
// Initialize the close queue listheads.
//
InitializeListHead( &Vcb->AsyncCloseList );
InitializeListHead( &Vcb->DelayedCloseList );
//
// Initialize the Advanced FCB Header
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -