📄 cachesup.c
字号:
/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
Cache.c
Abstract:
This module implements the cache management routines for the Cdfs
FSD and FSP, by calling the Common Cache Manager.
--*/
#include "CdProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_CACHESUP)
//
// Local debug trace level
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCompleteMdl)
#pragma alloc_text(PAGE, CdCreateInternalStream)
#pragma alloc_text(PAGE, CdDeleteInternalStream)
#pragma alloc_text(PAGE, CdPurgeVolume)
#endif
VOID
CdCreateInternalStream (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFCB Fcb,
IN OPTIONAL PUNICODE_STRING Name
)
/*++
Routine Description:
This function creates an internal stream file for interaction
with the cache manager. The Fcb here can be for either a
directory stream or for a path table stream.
Arguments:
Vcb - Vcb for this volume.
Fcb - Points to the Fcb for this file. It is either an Index or
Path Table Fcb.
Return Value:
None.
--*/
{
PFILE_OBJECT StreamFile = NULL;
BOOLEAN DecrementReference = FALSE;
BOOLEAN CleanupDirContext = FALSE;
BOOLEAN UpdateFcbSizes = FALSE;
DIRENT Dirent;
DIRENT_ENUM_CONTEXT DirContext;
PAGED_CODE();
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_FCB( Fcb );
//
// We may only have the Fcb shared. Lock the Fcb and do a
// safe test to see if we need to really create the file object.
//
CdLockFcb( IrpContext, Fcb );
if (Fcb->FileObject != NULL) {
CdUnlockFcb( IrpContext, Fcb );
return;
}
//
// Use a try-finally to facilitate cleanup.
//
try {
//
// Create the internal stream. The Vpb should be pointing at our volume
// device object at this point.
//
StreamFile = IoCreateStreamFileObject( NULL, Vcb->Vpb->RealDevice );
if (StreamFile == NULL) {
CdRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
}
//
// Initialize the fields of the file object.
//
StreamFile->ReadAccess = TRUE;
StreamFile->WriteAccess = FALSE;
StreamFile->DeleteAccess = FALSE;
StreamFile->SectionObjectPointer = &Fcb->FcbNonpaged->SegmentObject;
//
// Set the file object type and increment the Vcb counts.
//
CdSetFileObject( IrpContext,
StreamFile,
StreamFileOpen,
Fcb,
NULL );
//
// We'll give stream file objects a name to aid IO profiling etc. We
// NULL this in CdDeleteInternalStream before OB deletes the file object,
// and before CdRemovePrefix is called (which frees Fcb names).
//
StreamFile->FileName = *Name;
//
// We will reference the current Fcb twice to keep it from going
// away in the error path. Otherwise if we dereference it
// below in the finally clause a close could cause the Fcb to
// be deallocated.
//
CdLockVcb( IrpContext, Vcb );
CdIncrementReferenceCounts( IrpContext, Fcb, 2, 0 );
CdUnlockVcb( IrpContext, Vcb );
DecrementReference = TRUE;
//
// Initialize the cache map for the file.
//
CcInitializeCacheMap( StreamFile,
(PCC_FILE_SIZES)&Fcb->AllocationSize,
TRUE,
&CdData.CacheManagerCallbacks,
Fcb );
//
// Go ahead and store the stream file into the Fcb.
//
Fcb->FileObject = StreamFile;
StreamFile = NULL;
//
// If this is the first file object for a directory then we need to
// read the self entry for this directory and update the sizes
// in the Fcb. We know that the Fcb has been initialized so
// that we have a least one sector available to read.
//
if (!FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED )) {
ULONG NewDataLength;
//
// Initialize the search structures.
//
CdInitializeDirContext( IrpContext, &DirContext );
CdInitializeDirent( IrpContext, &Dirent );
CleanupDirContext = TRUE;
//
// Read the dirent from disk and transfer the data to the
// in-memory dirent.
//
CdLookupDirent( IrpContext,
Fcb,
Fcb->StreamOffset,
&DirContext );
CdUpdateDirentFromRawDirent( IrpContext, Fcb, &DirContext, &Dirent );
//
// Verify that this really for the self entry. We do this by
// updating the name in the dirent and then checking that it matches
// one of the hard coded names.
//
CdUpdateDirentName( IrpContext, &Dirent, FALSE );
if (Dirent.CdFileName.FileName.Buffer != CdUnicodeSelfArray) {
CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// If the data sizes are different then update the header
// and Mcb for this Fcb.
//
NewDataLength = BlockAlign( Vcb, Dirent.DataLength + Fcb->StreamOffset );
if (NewDataLength == 0) {
CdRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
if (NewDataLength != Fcb->FileSize.QuadPart) {
Fcb->AllocationSize.QuadPart =
Fcb->FileSize.QuadPart =
Fcb->ValidDataLength.QuadPart = NewDataLength;
CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize );
CdTruncateAllocation( IrpContext, Fcb, 0 );
CdAddInitialAllocation( IrpContext,
Fcb,
Dirent.StartingOffset,
NewDataLength );
UpdateFcbSizes = TRUE;
}
//
// Check for the existence flag and transform to hidden.
//
if (FlagOn( Dirent.DirentFlags, CD_ATTRIBUTE_HIDDEN )) {
SetFlag( Fcb->FileAttributes, FILE_ATTRIBUTE_HIDDEN );
}
//
// Convert the time to NT time.
//
CdConvertCdTimeToNtTime( IrpContext,
Dirent.CdTime,
(PLARGE_INTEGER) &Fcb->CreationTime );
//
// Update the Fcb flags to indicate we have read the
// self entry.
//
SetFlag( Fcb->FcbState, FCB_STATE_INITIALIZED );
//
// If we updated the sizes then we want to purge the file. Go
// ahead and unpin and then purge the first page.
//
CdCleanupDirContext( IrpContext, &DirContext );
CdCleanupDirent( IrpContext, &Dirent );
CleanupDirContext = FALSE;
if (UpdateFcbSizes) {
CcPurgeCacheSection( &Fcb->FcbNonpaged->SegmentObject,
NULL,
0,
FALSE );
}
}
} finally {
//
// Cleanup any dirent structures we may have used.
//
if (CleanupDirContext) {
CdCleanupDirContext( IrpContext, &DirContext );
CdCleanupDirent( IrpContext, &Dirent );
}
//
// If we raised then we need to dereference the file object.
//
if (StreamFile != NULL) {
ObDereferenceObject( StreamFile );
Fcb->FileObject = NULL;
}
//
// Dereference and unlock the Fcb.
//
if (DecrementReference) {
CdLockVcb( IrpContext, Vcb );
CdDecrementReferenceCounts( IrpContext, Fcb, 1, 0 );
CdUnlockVcb( IrpContext, Vcb );
}
CdUnlockFcb( IrpContext, Fcb );
}
return;
}
VOID
CdDeleteInternalStream (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
)
/*++
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -