📄 strucsup.c
字号:
Return Value:
PDCB - Returns a pointer to the newly allocated DCB
--*/
{
PDCB Dcb;
//
// 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;
DebugTrace(+1, Dbg, "FatCreateDcb\n", 0);
try {
//
// assert that the only time we are called is if wait is true
//
ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
//
// Allocate a new DCB, and zero it out
//
UnwindStorage[0] = Dcb = FatAllocateFcb();
RtlZeroMemory( Dcb, sizeof(DCB) );
UnwindStorage[1] =
Dcb->NonPaged = FatAllocateNonPagedFcb();
RtlZeroMemory( Dcb->NonPaged, sizeof( NON_PAGED_FCB ) );
//
// Set the proper node type code, node byte size and call backs
//
Dcb->Header.NodeTypeCode = FAT_NTC_DCB;
Dcb->Header.NodeByteSize = sizeof(DCB);
Dcb->FcbCondition = FcbGood;
//
// The initial state, open count, and directory change count fields are
// already zero so we can skip setting them
//
//
// Initialize the resource variable
//
UnwindResource =
Dcb->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.
//
UnwindResource2 =
Dcb->Header.PagingIoResource = FatAllocateResource();
//
// Insert this Dcb into our parent dcb's queue
//
// There is a deep reason why this goes on the head, 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.
//
InsertHeadList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
&Dcb->ParentDcbLinks );
UnwindEntryList = &Dcb->ParentDcbLinks;
//
// Point back to our parent dcb
//
Dcb->ParentDcb = ParentDcb;
//
// Set the Vcb
//
Dcb->Vcb = Vcb;
//
// Set the dirent offset within the directory
//
Dcb->LfnOffsetWithinDirectory = LfnOffsetWithinDirectory;
Dcb->DirentOffsetWithinDirectory = DirentOffsetWithinDirectory;
//
// Set the DirentFatFlags and LastWriteTime
//
Dcb->DirentFatFlags = Dirent->Attributes;
Dcb->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) {
Dcb->LastAccessTime =
FatFatDateToNtTime( IrpContext,
Dirent->LastAccessDate );
} else {
Dcb->LastAccessTime = FatSystemJanOne1980;
}
//
// Only do the really hard work if this field is non-zero.
//
if (((PUSHORT)Dirent)[8] != 0) {
Dcb->CreationTime =
FatFatTimeToNtTime( IrpContext,
Dirent->CreationTime,
Dirent->CreationMSec );
} else {
Dcb->CreationTime = FatSystemJanOne1980;
}
}
//
// Initialize Advanced FCB Header fields
//
ExInitializeFastMutex( &Dcb->NonPaged->AdvancedFcbHeaderMutex );
FsRtlSetupAdvancedHeader( &Dcb->Header,
&Dcb->NonPaged->AdvancedFcbHeaderMutex );
//
// Initialize the Mcb
//
FsRtlInitializeLargeMcb( &Dcb->Mcb, PagedPool );
UnwindMcb = &Dcb->Mcb;
//
// Set the file size, first cluster of file, and allocation size
// based on the information stored in the dirent
//
Dcb->FirstClusterOfFile = (ULONG)Dirent->FirstClusterOfFile;
if ( FatIsFat32(Dcb->Vcb) ) {
Dcb->FirstClusterOfFile += Dirent->FirstClusterOfFileHi << 16;
}
if ( Dcb->FirstClusterOfFile == 0 ) {
Dcb->Header.AllocationSize.QuadPart = 0;
} else {
Dcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
}
// initialize the notify queues, and the parent dcb queue.
//
InitializeListHead( &Dcb->Specific.Dcb.ParentDcbQueue );
//
// Setup the free dirent bitmap buffer. Since we don't know the
// size of the directory, leave it zero for now.
//
RtlInitializeBitMap( &Dcb->Specific.Dcb.FreeDirentBitmap,
NULL,
0 );
//
// 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;
//
// Postpone initializing the cache map until we need to do a read/write
// of the directory file.
//
// set the file names. This must be the last thing we do.
//
FatConstructNamesInFcb( IrpContext,
Dcb,
Dirent,
Lfn );
} finally {
DebugUnwind( FatCreateDcb );
//
// If this is an abnormal termination then undo our work
//
if (AbnormalTermination()) {
ULONG i;
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, "FatCreateDcb -> %08lx\n", Dcb);
}
//
// return and tell the caller
//
DebugTrace(-1, Dbg, "FatCreateDcb -> %08lx\n", Dcb);
return Dcb;
}
VOID
FatDeleteFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB *FcbPtr
)
/*++
Routine Description:
This routine deallocates and removes an FCB, DCB, or ROOT DCB record
from Fat's in-memory data structures. It also will remove all
associated underlings (i.e., Notify irps, and child FCB/DCB records).
Arguments:
Fcb - Supplies the FCB/DCB/ROOT DCB to be removed
Return Value:
None
--*/
{
PFCB Fcb = *FcbPtr;
DebugTrace(+1, Dbg, "FatDeleteFcb, Fcb = %08lx\n", Fcb);
//
// We can only delete this record if the open count is zero.
//
if (Fcb->OpenCount != 0) {
DebugDump("Error deleting Fcb, Still Open\n", 0, Fcb);
FatBugCheck( 0, 0, 0 );
}
//
// Better be an FCB/DCB.
//
if ((Fcb->Header.NodeTypeCode != FAT_NTC_DCB) &&
(Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB) &&
(Fcb->Header.NodeTypeCode != FAT_NTC_FCB)) {
FatBugCheck( 0, 0, 0 );
}
//
// If this is a DCB then remove every Notify record from the two
// notify queues
//
if ((Fcb->Header.NodeTypeCode == FAT_NTC_DCB) ||
(Fcb->Header.NodeTypeCode == FAT_NTC_ROOT_DCB)) {
//
// If we allocated a free dirent bitmap buffer, free it.
//
if ((Fcb->Specific.Dcb.FreeDirentBitmap.Buffer != NULL) &&
(Fcb->Specific.Dcb.FreeDirentBitmap.Buffer !=
&Fcb->Specific.Dcb.FreeDirentBitmapBuffer[0])) {
ExFreePool(Fcb->Specific.Dcb.FreeDirentBitmap.Buffer);
}
ASSERT( Fcb->Specific.Dcb.DirectoryFileOpenCount == 0 );
ASSERT( IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) );
ASSERT( NULL == Fcb->Specific.Dcb.DirectoryFile);
} else {
//
// Uninitialize the byte range file locks and opportunistic locks
//
FsRtlUninitializeFileLock( &Fcb->Specific.Fcb.FileLock );
FsRtlUninitializeOplock( &Fcb->Specific.Fcb.Oplock );
}
//
// Release any Filter Context structures associated with this FCB
//
FsRtlTeardownPerStreamContexts( &Fcb->Header );
//
// Uninitialize the Mcb
//
FsRtlUninitializeLargeMcb( &Fcb->Mcb );
//
// If this is not the root dcb then we need to remove ourselves from
// our parents Dcb queue
//
if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB) {
RemoveEntryList( &(Fcb->ParentDcbLinks) );
}
//
// Remove the entry from the splay table if there is still is one.
//
if (FlagOn( Fcb->FcbState, FCB_STATE_NAMES_IN_SPLAY_TREE )) {
FatRemoveNames( IrpContext, Fcb );
}
//
// Free the file name pool if allocated.
//
if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB) {
//
// If we blew up at inconvenient times, the shortname
// could be null even though you will *never* see this
// normally. Rename is a good example of this case.
//
if (Fcb->ShortName.Name.Oem.Buffer) {
ExFreePool( Fcb->ShortName.Name.Oem.Buffer );
}
if (Fcb->FullFileName.Buffer) {
ExFreePool( Fcb->FullFileName.Buffer );
}
}
if (Fcb->ExactCaseLongName.Buffer) {
ExFreePool(Fcb->ExactCaseLongName.Buffer);
}
#ifdef SYSCACHE_COMPILE
if (Fcb->WriteMask) {
ExFreePool( Fcb->WriteMask );
}
#endif
//
// Finally deallocate the Fcb and non-paged fcb records
//
FatFreeResource( Fcb->Header.Resource );
if (Fcb->Header.PagingIoResource != Fcb->Header.Resource) {
FatFreeResource( Fcb->Header.PagingIoResource );
}
//
// If an Event was allocated, get rid of it.
//
if (Fcb->NonPaged->OutstandingAsyncEvent) {
ExFreePool( Fcb->NonPaged->OutstandingAsyncEvent );
}
FatFreeNonPagedFcb( Fcb->NonPaged );
Fcb->Header.NodeTypeCode = NTC_UNDEFINED;
FatFreeFcb( Fcb );
*FcbPtr = NULL;
//
// and return to our caller
//
DebugTrace(-1, Dbg, "FatDeleteFcb -> VOID\n", 0);
}
PCCB
FatCreateCcb (
IN PIRP_CONTEXT IrpContext
)
/*++
Routine Description:
This routine creates a new CCB record
Arguments:
Return Value:
CCB - returns a pointer to the newly allocate CCB
--*/
{
PCCB Ccb;
DebugTrace(+1, Dbg, "FatCreateCcb\n", 0);
//
// Allocate a new CCB Record
//
Ccb = FatAllocateCcb();
RtlZeroMemory( Ccb, sizeof(CCB) );
//
// Set the proper node type code and node byte size
//
Ccb->NodeTypeCode = FAT_NTC_CCB;
Ccb->NodeByteSize = sizeof(CCB);
//
// return and tell the caller
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -