📄 strucsup.c
字号:
//
// Initialize the Mcb, and setup its mapping. Note that the root
// directory is a fixed size so we can set it everything up now.
//
FsRtlInitializeLargeMcb( &Dcb->Mcb, NonPagedPool );
UnwindMcb = &Dcb->Mcb;
if (FatIsFat32(Vcb)) {
//
// The first cluster of fat32 roots comes from the BPB
//
Dcb->FirstClusterOfFile = Vcb->Bpb.RootDirFirstCluster;
} else {
FatAddMcbEntry( Vcb, &Dcb->Mcb,
0,
FatRootDirectoryLbo( &Vcb->Bpb ),
FatRootDirectorySize( &Vcb->Bpb ));
}
if (FatIsFat32(Vcb)) {
//
// Find the size of the fat32 root. As a side-effect, this will create
// MCBs for the entire root. In the process of doing this, we may
// discover that the FAT chain is bogus and raise corruption.
//
Dcb->Header.AllocationSize.LowPart = 0xFFFFFFFF;
FatLookupFileAllocationSize( IrpContext, Dcb);
Dcb->Header.FileSize.QuadPart =
Dcb->Header.AllocationSize.QuadPart;
} else {
//
// set the allocation size to real size of the root directory
//
Dcb->Header.FileSize.QuadPart =
Dcb->Header.AllocationSize.QuadPart = FatRootDirectorySize( &Vcb->Bpb );
}
//
// Set our two create dirent aids to represent that we have yet to
// enumerate the directory for never used or deleted dirents.
//
Dcb->Specific.Dcb.UnusedDirentVbo = 0xffffffff;
Dcb->Specific.Dcb.DeletedDirentHint = 0xffffffff;
//
// Setup the free dirent bitmap buffer.
//
RtlInitializeBitMap( &Dcb->Specific.Dcb.FreeDirentBitmap,
NULL,
0 );
FatCheckFreeDirentBitmap( IrpContext, Dcb );
} finally {
DebugUnwind( FatCreateRootDcb );
//
// If this is an abnormal termination then undo our work
//
if (AbnormalTermination()) {
ULONG i;
if (UnwindFileObject != NULL) { ObDereferenceObject( UnwindFileObject ); }
if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }
for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
}
//
// Re-zero the entry in the Vcb.
//
Vcb->RootDcb = NULL;
}
DebugTrace(-1, Dbg, "FatCreateRootDcb -> %8lx\n", Dcb);
}
return;
}
PFCB
FatCreateFcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDCB ParentDcb,
IN ULONG LfnOffsetWithinDirectory,
IN ULONG DirentOffsetWithinDirectory,
IN PDIRENT Dirent,
IN PUNICODE_STRING Lfn OPTIONAL,
IN BOOLEAN IsPagingFile,
IN BOOLEAN SingleResource
)
/*++
Routine Description:
This routine allocates, initializes, and inserts a new Fcb record into
the in-memory data structures.
Arguments:
Vcb - Supplies the Vcb to associate the new FCB under.
ParentDcb - Supplies the parent dcb that the new FCB is under.
LfnOffsetWithinDirectory - Supplies the offset of the LFN. If there is
no LFN associated with this file then this value is same as
DirentOffsetWithinDirectory.
DirentOffsetWithinDirectory - Supplies the offset, in bytes from the
start of the directory file where the dirent for the fcb is located
Dirent - Supplies the dirent for the fcb being created
Lfn - Supplies a long UNICODE name associated with this file.
IsPagingFile - Indicates if we are creating an FCB for a paging file
or some other type of file.
SingleResource - Indicates if this Fcb should share a single resource
as both main and paging.
Return Value:
PFCB - Returns a pointer to the newly allocated FCB
--*/
{
PFCB Fcb;
POOL_TYPE PoolType;
//
// The following variables are used for abnormal unwind
//
PVOID UnwindStorage[2] = { NULL, NULL };
PERESOURCE UnwindResource = NULL;
PERESOURCE UnwindResource2 = NULL;
PLIST_ENTRY UnwindEntryList = NULL;
PLARGE_MCB UnwindMcb = NULL;
PFILE_LOCK UnwindFileLock = NULL;
POPLOCK UnwindOplock = NULL;
DebugTrace(+1, Dbg, "FatCreateFcb\n", 0);
try {
//
// Determine the pool type we should be using for the fcb and the
// mcb structure
//
if (IsPagingFile) {
PoolType = NonPagedPool;
Fcb = UnwindStorage[0] = FsRtlAllocatePoolWithTag( NonPagedPool,
sizeof(FCB),
TAG_FCB );
} else {
PoolType = PagedPool;
Fcb = UnwindStorage[0] = FatAllocateFcb();
}
//
// ... and zero it out
//
RtlZeroMemory( Fcb, sizeof(FCB) );
UnwindStorage[1] =
Fcb->NonPaged = FatAllocateNonPagedFcb();
RtlZeroMemory( Fcb->NonPaged, sizeof( NON_PAGED_FCB ) );
//
// Set the proper node type code, node byte size, and call backs
//
Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
Fcb->Header.NodeByteSize = sizeof(FCB);
Fcb->FcbCondition = FcbGood;
//
// Check to see if we need to set the Fcb state to indicate that this
// is a paging/system file. This will prevent it from being opened
// again.
//
if (IsPagingFile) {
SetFlag( Fcb->FcbState, FCB_STATE_PAGING_FILE | FCB_STATE_SYSTEM_FILE );
}
//
// The initial state, open count, and segment objects fields are already
// zero so we can skip setting them
//
//
// Initialize the resource variable
//
UnwindResource =
Fcb->Header.Resource = FatAllocateResource();
//
// Initialize the PagingIo Resource. We no longer use the FsRtl common
// shared pool because this led to a) deadlocks due to cases where files
// and their parent directories shared a resource and b) there is no way
// to anticipate inter-driver induced deadlock via recursive operation.
//
if (SingleResource) {
Fcb->Header.PagingIoResource = Fcb->Header.Resource;
} else {
UnwindResource2 =
Fcb->Header.PagingIoResource = FatAllocateResource();
}
//
// Insert this fcb into our parent dcb's queue.
//
// There is a deep reason why this goes on the tail, to allow us
// to easily enumerate all child directories before child files.
// This is important to let us maintain whole-volume lockorder
// via BottomUp enumeration.
//
InsertTailList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
&Fcb->ParentDcbLinks );
UnwindEntryList = &Fcb->ParentDcbLinks;
//
// Point back to our parent dcb
//
Fcb->ParentDcb = ParentDcb;
//
// Set the Vcb
//
Fcb->Vcb = Vcb;
//
// Set the dirent offset within the directory
//
Fcb->LfnOffsetWithinDirectory = LfnOffsetWithinDirectory;
Fcb->DirentOffsetWithinDirectory = DirentOffsetWithinDirectory;
//
// Set the DirentFatFlags and LastWriteTime
//
Fcb->DirentFatFlags = Dirent->Attributes;
Fcb->LastWriteTime = FatFatTimeToNtTime( IrpContext,
Dirent->LastWriteTime,
0 );
//
// These fields are only non-zero when in Chicago mode.
//
if (FatData.ChicagoMode) {
LARGE_INTEGER FatSystemJanOne1980;
//
// If either date is possibly zero, get the system
// version of 1/1/80.
//
if ((((PUSHORT)Dirent)[9] & ((PUSHORT)Dirent)[8]) == 0) {
ExLocalTimeToSystemTime( &FatJanOne1980,
&FatSystemJanOne1980 );
}
//
// Only do the really hard work if this field is non-zero.
//
if (((PUSHORT)Dirent)[9] != 0) {
Fcb->LastAccessTime =
FatFatDateToNtTime( IrpContext,
Dirent->LastAccessDate );
} else {
Fcb->LastAccessTime = FatSystemJanOne1980;
}
//
// Only do the really hard work if this field is non-zero.
//
if (((PUSHORT)Dirent)[8] != 0) {
Fcb->CreationTime =
FatFatTimeToNtTime( IrpContext,
Dirent->CreationTime,
Dirent->CreationMSec );
} else {
Fcb->CreationTime = FatSystemJanOne1980;
}
}
//
// Initialize Advanced FCB Header fields
//
ExInitializeFastMutex( &Fcb->NonPaged->AdvancedFcbHeaderMutex );
FsRtlSetupAdvancedHeader( &Fcb->Header,
&Fcb->NonPaged->AdvancedFcbHeaderMutex );
//
// To make FAT match the present functionality of NTFS, disable
// stream contexts on paging files
//
if (IsPagingFile) {
SetFlag( Fcb->Header.Flags2, FSRTL_FLAG2_IS_PAGING_FILE );
ClearFlag( Fcb->Header.Flags2, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS );
}
//
// Initialize the Mcb
//
FsRtlInitializeLargeMcb( &Fcb->Mcb, PoolType );
UnwindMcb = &Fcb->Mcb;
//
// Set the file size, valid data length, first cluster of file,
// and allocation size based on the information stored in the dirent
//
Fcb->Header.FileSize.LowPart = Dirent->FileSize;
Fcb->Header.ValidDataLength.LowPart = Dirent->FileSize;
Fcb->ValidDataToDisk = Dirent->FileSize;
Fcb->FirstClusterOfFile = (ULONG)Dirent->FirstClusterOfFile;
if ( FatIsFat32(Vcb) ) {
Fcb->FirstClusterOfFile += Dirent->FirstClusterOfFileHi << 16;
}
if ( Fcb->FirstClusterOfFile == 0 ) {
Fcb->Header.AllocationSize.QuadPart = 0;
} else {
Fcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
}
//
// Initialize the Fcb's file lock record
//
FsRtlInitializeFileLock( &Fcb->Specific.Fcb.FileLock, NULL, NULL );
UnwindFileLock = &Fcb->Specific.Fcb.FileLock;
//
// Initialize the oplock structure.
//
FsRtlInitializeOplock( &Fcb->Specific.Fcb.Oplock );
UnwindOplock = &Fcb->Specific.Fcb.Oplock;
//
// Indicate that Fast I/O is possible
//
Fcb->Header.IsFastIoPossible = TRUE;
//
// Set the file names. This must be the last thing we do.
//
FatConstructNamesInFcb( IrpContext,
Fcb,
Dirent,
Lfn );
//
// Drop the shortname hint so prefix searches can figure out
// what they found
//
Fcb->ShortName.FileNameDos = TRUE;
} finally {
DebugUnwind( FatCreateFcb );
//
// If this is an abnormal termination then undo our work
//
if (AbnormalTermination()) {
ULONG i;
if (UnwindOplock != NULL) { FsRtlUninitializeOplock( UnwindOplock ); }
if (UnwindFileLock != NULL) { FsRtlUninitializeFileLock( UnwindFileLock ); }
if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
if (UnwindEntryList != NULL) { RemoveEntryList( UnwindEntryList ); }
if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }
for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
}
}
DebugTrace(-1, Dbg, "FatCreateFcb -> %08lx\n", Fcb);
}
//
// return and tell the caller
//
return Fcb;
}
PDCB
FatCreateDcb (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDCB ParentDcb,
IN ULONG LfnOffsetWithinDirectory,
IN ULONG DirentOffsetWithinDirectory,
IN PDIRENT Dirent,
IN PUNICODE_STRING Lfn OPTIONAL
)
/*++
Routine Description:
This routine allocates, initializes, and inserts a new Dcb record into
the in memory data structures.
Arguments:
Vcb - Supplies the Vcb to associate the new DCB under.
ParentDcb - Supplies the parent dcb that the new DCB is under.
LfnOffsetWithinDirectory - Supplies the offset of the LFN. If there is
no LFN associated with this file then this value is same as
DirentOffsetWithinDirectory.
DirentOffsetWithinDirectory - Supplies the offset, in bytes from the
start of the directory file where the dirent for the fcb is located
Dirent - Supplies the dirent for the dcb being created
FileName - Supplies the file name of the file relative to the directory
it's in (e.g., the file \config.sys is called "CONFIG.SYS" without
the preceding backslash).
Lfn - Supplies a long UNICODE name associated with this directory.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -