📄 easup.c
字号:
//
// Verify that the virtual Ea file is large enough for us to read
// the EaOffet table for this index.
//
EaOffsetVbo = sizeof( EA_FILE_HEADER ) + ((EaHandle >> 7) << 8);
//
// Zero the Ea range structures.
//
RtlZeroMemory( &EaHeaderRange, sizeof( EA_RANGE ));
RtlZeroMemory( &EaOffsetRange, sizeof( EA_RANGE ));
//
// Use a try statement to clean up on exit.
//
try {
//
// Pin down the EA file header.
//
FatPinEaRange( IrpContext,
Vcb->VirtualEaFile,
Vcb->EaFcb,
&EaHeaderRange,
0,
sizeof( EA_FILE_HEADER ),
STATUS_NONEXISTENT_EA_ENTRY );
EaHeader = (PEA_FILE_HEADER) EaHeaderRange.Data;
//
// Pin down the Ea offset table for the particular index.
//
FatPinEaRange( IrpContext,
Vcb->VirtualEaFile,
Vcb->EaFcb,
&EaOffsetRange,
EaOffsetVbo,
sizeof( EA_OFF_TABLE ),
STATUS_NONEXISTENT_EA_ENTRY );
//
// Check if the specifific handle is currently being used.
//
EaOffsetCluster = *((PUSHORT) EaOffsetRange.Data
+ (EaHandle & (MAX_EA_OFFSET_INDEX - 1)));
if (EaOffsetCluster == UNUSED_EA_HANDLE) {
DebugTrace(0, Dbg, "FatReadEaSet: Ea handle is unused\n", 0);
FatRaiseStatus( IrpContext, STATUS_NONEXISTENT_EA_ENTRY );
}
//
// Compute the file offset for the Ea data.
//
EaSetVbo = (EaHeader->EaBaseTable[EaHandle >> 7] + EaOffsetCluster)
<< Vcb->AllocationSupport.LogOfBytesPerCluster;
//
// Unpin the file header and offset table.
//
FatUnpinEaRange( IrpContext, &EaHeaderRange );
FatUnpinEaRange( IrpContext, &EaOffsetRange );
//
// Pin the ea set.
//
FatPinEaRange( IrpContext,
Vcb->VirtualEaFile,
Vcb->EaFcb,
EaSetRange,
EaSetVbo,
BytesPerCluster,
STATUS_DATA_ERROR );
//
// Verify that the Ea set is valid and belongs to this index.
// Raise STATUS_DATA_ERROR if there is a data conflict.
//
EaSet = (PEA_SET_HEADER) EaSetRange->Data;
if (EaSet->Signature != EA_SET_SIGNATURE
|| EaSet->OwnEaHandle != EaHandle ) {
DebugTrace(0, Dbg, "FatReadEaSet: Ea set header is corrupt\n", 0);
FatRaiseStatus( IrpContext, STATUS_DATA_ERROR );
}
//
// At this point we have pinned a single cluster of Ea data. If
// this represents the entire Ea data for the Ea index, we are
// done. Otherwise we need to check on the entire size of
// of the Ea set header and whether it is contained in the allocated
// size of the Ea virtual file. At that point we can unpin
// the partial Ea set header and repin the entire header.
//
CbList = GetcbList( EaSet );
if (ReturnEntireSet
&& CbList > BytesPerCluster ) {
//
// Round up to the cluster size.
//
CbList = (CbList + EA_CBLIST_OFFSET + BytesPerCluster - 1)
& ~(BytesPerCluster - 1);
FatUnpinEaRange( IrpContext, EaSetRange );
RtlZeroMemory( EaSetRange, sizeof( EA_RANGE ));
FatPinEaRange( IrpContext,
Vcb->VirtualEaFile,
Vcb->EaFcb,
EaSetRange,
EaSetVbo,
CbList,
STATUS_DATA_ERROR );
}
} finally {
DebugUnwind( FatReadEaSet );
//
// Unpin the Ea base and offset tables if locked down.
//
FatUnpinEaRange( IrpContext, &EaHeaderRange );
FatUnpinEaRange( IrpContext, &EaOffsetRange );
DebugTrace(-1, Dbg, "FatReadEaSet: Exit\n", 0);
}
return;
}
VOID
FatDeleteEaSet (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PBCB EaBcb,
OUT PDIRENT EaDirent,
IN USHORT EaHandle,
IN POEM_STRING FileName
)
/*++
Routine Description:
This routines clips the Ea set for a particular index out of the
Ea file for a volume. The index is verified as belonging to a valid
handle. The clusters are removed and the Ea stream file along with
the Ea base and offset files are updated.
The caller of this function will have verified that the Ea file
exists and that the Vcb field points to an initialized cache file.
The caller will already have gained exclusive access to the
EaFcb.
Arguments:
Vcb - Supplies the Vcb for the volume.
VirtualEeFile - Pointer to the file object for the virtual Ea file.
EaFcb - Supplies the pointer to the Fcb for the Ea file.
EaBcb - Supplies a pointer to the Bcb for the Ea dirent.
EaDirent - Supplies a pointer to the dirent for the Ea file.
EaHandle - Supplies the handle for the Ea's to read.
FileName - Name of the file whose Ea's are being read.
Return Value:
None.
--*/
{
ULONG BytesPerCluster = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;
ULONG CbList;
LARGE_INTEGER FileOffset;
LARGE_MCB DataMcb;
BOOLEAN UnwindInitializeDataMcb = FALSE;
BOOLEAN UnwindSplitData = FALSE;
LARGE_MCB TailMcb;
BOOLEAN UnwindInitializeTailMcb = FALSE;
BOOLEAN UnwindSplitTail = FALSE;
BOOLEAN UnwindMergeTail = FALSE;
BOOLEAN UnwindModifiedEaHeader = FALSE;
BOOLEAN UnwindCacheValues = FALSE;
ULONG UnwindPrevFileSize = 0;
ULONG EaOffsetVbo;
USHORT EaOffsetIndex;
EA_RANGE EaOffsetRange;
USHORT EaOffsetCluster;
PFILE_OBJECT VirtualEaFile = Vcb->VirtualEaFile;
PFCB EaFcb = Vcb->EaFcb;
EA_RANGE EaHeaderRange;
PEA_FILE_HEADER EaHeader;
USHORT EaHeaderBaseIndex;
ULONG EaSetVbo;
ULONG EaSetLength;
EA_RANGE EaSetRange;
PEA_SET_HEADER EaSet;
USHORT EaSetClusterCount;
//
// Verify that the Ea index has a legal value. Raise status
// STATUS_INVALID_HANDLE if illegal.
//
if (EaHandle < MIN_EA_HANDLE
|| EaHandle > MAX_EA_HANDLE) {
DebugTrace(-1, Dbg, "FatDeleteEaSet: Illegal handle value\n", 0);
FatRaiseStatus( IrpContext, STATUS_NONEXISTENT_EA_ENTRY );
}
//
// Verify that the virtual Ea file is large enough for us to read
// the EaOffet table for this index.
//
EaOffsetVbo = sizeof( EA_FILE_HEADER ) + ((EaHandle >> 7) << 8);
//
// Zero the Ea range structures.
//
RtlZeroMemory( &EaHeaderRange, sizeof( EA_RANGE ));
RtlZeroMemory( &EaOffsetRange, sizeof( EA_RANGE ));
RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
//
// Use a try to facilitate cleanup.
//
try {
//
// Pin down the EA file header.
//
FatPinEaRange( IrpContext,
VirtualEaFile,
EaFcb,
&EaHeaderRange,
0,
sizeof( EA_FILE_HEADER ),
STATUS_NONEXISTENT_EA_ENTRY );
EaHeader = (PEA_FILE_HEADER) EaHeaderRange.Data;
//
// Pin down the Ea offset table for the particular index.
//
FatPinEaRange( IrpContext,
VirtualEaFile,
EaFcb,
&EaOffsetRange,
EaOffsetVbo,
sizeof( EA_OFF_TABLE ),
STATUS_NONEXISTENT_EA_ENTRY );
//
// Check if the specifific handle is currently being used.
//
EaOffsetIndex = EaHandle & (MAX_EA_OFFSET_INDEX - 1);
EaOffsetCluster = *((PUSHORT) EaOffsetRange.Data + EaOffsetIndex);
if (EaOffsetCluster == UNUSED_EA_HANDLE) {
DebugTrace(0, Dbg, "FatReadEaSet: Ea handle is unused\n", 0);
FatRaiseStatus( IrpContext, STATUS_NONEXISTENT_EA_ENTRY );
}
//
// Compute the file offset for the Ea data.
//
EaHeaderBaseIndex = EaHandle >> 7;
EaSetVbo = (EaHeader->EaBaseTable[EaHeaderBaseIndex] + EaOffsetCluster)
<< Vcb->AllocationSupport.LogOfBytesPerCluster;
//
// Unpin the file header and offset table.
//
FatUnpinEaRange( IrpContext, &EaHeaderRange );
FatUnpinEaRange( IrpContext, &EaOffsetRange );
//
// Try to pin the requested Ea set.
//
FatPinEaRange( IrpContext,
VirtualEaFile,
EaFcb,
&EaSetRange,
EaSetVbo,
BytesPerCluster,
STATUS_DATA_ERROR );
EaSet = (PEA_SET_HEADER) EaSetRange.Data;
if (EaSet->Signature != EA_SET_SIGNATURE
|| EaSet->OwnEaHandle != EaHandle ) {
DebugTrace(0, Dbg, "FatReadEaSet: Ea set header is corrupt\n", 0);
FatRaiseStatus( IrpContext, STATUS_DATA_ERROR );
}
//
// At this point we have pinned a single cluster of Ea data. If
// this represents the entire Ea data for the Ea index, we know
// the number of clusters to remove. Otherwise we need to check
// on the entire size of the Ea set header and whether it is
// contained in the allocated size of the Ea virtual file. At
// that point we unpin the partial Ea set header and remember the
// starting cluster offset and number of clusters in both cluster
// and Vbo formats.
//
// At that point the following variables have the described
// values.
//
// EaSetVbo - Vbo to start splice at.
// EaSetLength - Number of bytes to splice.
// EaSetClusterCount - Number of clusters to splice.
//
CbList = GetcbList( EaSet );
EaSetClusterCount = (USHORT) ((CbList + EA_CBLIST_OFFSET + BytesPerCluster - 1)
>> Vcb->AllocationSupport.LogOfBytesPerCluster);
EaSetLength = EaSetClusterCount << Vcb->AllocationSupport.LogOfBytesPerCluster;
if (EaSetLength > BytesPerCluster) {
if (EaFcb->Header.FileSize.LowPart - EaSetVbo < EaSetLength) {
DebugTrace(0, Dbg, "FatDeleteEaSet: Full Ea set not contained in file\n", 0);
FatRaiseStatus( IrpContext, STATUS_DATA_ERROR );
}
}
FatUnpinEaRange( IrpContext, &EaSetRange );
//
// Update the cache manager for this file. This is done by
// truncating to the point where the data was spliced and
// reinitializing with the modified size of the file.
//
// NOTE: Even if the all the EA's are removed the Ea file will
// always exist and the header area will never shrink.
//
FileOffset.LowPart = EaSetVbo;
FileOffset.HighPart = 0;
//
// Round the cache map down to a system page boundary.
//
FileOffset.LowPart &= ~(PAGE_SIZE - 1);
//
// Make sure all the data gets out to the disk.
//
{
IO_STATUS_BLOCK Iosb;
ULONG PurgeCount = 5;
while (--PurgeCount) {
Iosb.Status = STATUS_SUCCESS;
CcFlushCache( VirtualEaFile->SectionObjectPointer,
NULL,
0,
&Iosb );
ASSERT( Iosb.Status == STATUS_SUCCESS );
//
// We do not have to worry about a lazy writer firing in parallel
// with our CcFlushCache since we have the EaFcb exclusive. Thus
// we know all data is out.
//
//
// We throw the unwanted pages out of the cache and then
// truncate the Ea File for the new size.
//
if (CcPurgeCacheSection( VirtualEaFile->SectionObjectPointer,
&FileOffset,
0,
FALSE )) {
break;
}
}
if (!PurgeCount) {
FatRaiseStatus( IrpContext, STATUS_UNABLE_TO_DELETE_SECTION );
}
}
FileOffset.LowPart = EaFcb->Header.FileSize.LowPart - EaSetLength;
//
// Perform the splice operation on the FAT chain. This is done
// by splitting the target clusters out and merging the remaining
// clusters around them. We can ignore the return value from
// the merge and splice functions because we are guaranteed
// to be able to block.
//
{
FsRtlInitializeLargeMcb( &DataMcb, PagedPool );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -