📄 easup.c
字号:
/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
EaSup.c
Abstract:
This module implements the cluster operations on the EA file for Fat.
--*/
#include "FatProcs.h"
//
// Local debug trace level
//
#define Dbg (DEBUG_TRACE_EA)
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatAddEaSet)
#pragma alloc_text(PAGE, FatAppendPackedEa)
#pragma alloc_text(PAGE, FatCreateEa)
#pragma alloc_text(PAGE, FatDeleteEa)
#pragma alloc_text(PAGE, FatDeleteEaSet)
#pragma alloc_text(PAGE, FatDeletePackedEa)
#pragma alloc_text(PAGE, FatGetEaFile)
#pragma alloc_text(PAGE, FatGetEaLength)
#pragma alloc_text(PAGE, FatGetNeedEaCount)
#pragma alloc_text(PAGE, FatIsEaNameValid)
#pragma alloc_text(PAGE, FatLocateEaByName)
#pragma alloc_text(PAGE, FatLocateNextEa)
#pragma alloc_text(PAGE, FatReadEaSet)
#pragma alloc_text(PAGE, FatPinEaRange)
#pragma alloc_text(PAGE, FatMarkEaRangeDirty)
#pragma alloc_text(PAGE, FatUnpinEaRange)
#endif
#define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))
//
// Any access to the Ea file must recognize when a section boundary is being
// crossed.
//
#define EA_SECTION_SIZE (0x00040000)
VOID
FatGetEaLength (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDIRENT Dirent,
OUT PULONG EaLength
)
/*++
Routine Description:
This routine looks up the Ea length for the Eas of the file. This
length is the length of the packed eas, including the 4 bytes which
contain the Ea length.
This routine pins down the Ea set for the desired file and copies
this field from the Ea set header.
Arguments:
Vcb - Vcb for the volume containing the Eas.
Dirent - Supplies a pointer to the dirent for the file in question.
EaLength - Supplies the address to store the length of the Eas.
Return Value:
None
--*/
{
PBCB EaBcb;
BOOLEAN LockedEaFcb;
EA_RANGE EaSetRange;
DebugTrace(+1, Dbg, "FatGetEaLength ...\n", 0);
//
// If this is Fat32 volume, or if the handle is 0 then the Ea length is 0.
//
if (FatIsFat32( Vcb ) ||
Dirent->ExtendedAttributes == 0) {
*EaLength = 0;
DebugTrace(-1, Dbg, "FatGetEaLength -> %08lx\n", TRUE);
return;
}
RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
//
// Use a try to facilitate cleanup.
//
try {
PDIRENT EaDirent;
OEM_STRING ThisFilename;
UCHAR Buffer[12];
PEA_SET_HEADER EaSetHeader;
//
// Initial the local values.
//
EaBcb = NULL;
LockedEaFcb = FALSE;
//
// Try to get the Ea file object. Return FALSE on failure.
//
FatGetEaFile( IrpContext,
Vcb,
&EaDirent,
&EaBcb,
FALSE,
FALSE );
LockedEaFcb = TRUE;
//
// If we didn't get the file because it doesn't exist, then the
// disk is corrupted.
//
if (Vcb->VirtualEaFile == NULL) {
DebugTrace(0, Dbg, "FatGetEaLength: Ea file doesn't exist\n", 0);
FatRaiseStatus( IrpContext, STATUS_NO_EAS_ON_FILE );
}
//
// Try to pin down the Ea set header for the index in the
// dirent. If the operation doesn't complete, return FALSE
// from this routine.
//
ThisFilename.Buffer = Buffer;
Fat8dot3ToString( IrpContext, Dirent, FALSE, &ThisFilename );
FatReadEaSet( IrpContext,
Vcb,
Dirent->ExtendedAttributes,
&ThisFilename,
FALSE,
&EaSetRange );
EaSetHeader = (PEA_SET_HEADER) EaSetRange.Data;
//
// We now have the Ea set header for this file. We simply copy
// the Ea length field.
//
CopyUchar4( EaLength, EaSetHeader->cbList );
DebugTrace(0, Dbg, "FatGetEaLength: Length of Ea is -> %08lx\n",
*EaLength);
} finally {
DebugUnwind( FatGetEaLength );
//
// Unpin the EaDirent and the EaSetHeader if pinned.
//
FatUnpinBcb( IrpContext, EaBcb );
FatUnpinEaRange( IrpContext, &EaSetRange );
//
// Release the Fcb for the Ea file if locked.
//
if (LockedEaFcb) {
FatReleaseFcb( IrpContext, Vcb->EaFcb );
}
DebugTrace(-1, Dbg, "FatGetEaLength: Ea length -> %08lx\n", *EaLength);
}
return;
}
VOID
FatGetNeedEaCount (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDIRENT Dirent,
OUT PULONG NeedEaCount
)
/*++
Routine Description:
This routine looks up the Need Ea count for the file. The value is the
in the ea header for the file.
Arguments:
Vcb - Vcb for the volume containing the Eas.
Dirent - Supplies a pointer to the dirent for the file in question.
NeedEaCount - Supplies the address to store the Need Ea count.
Return Value:
None
--*/
{
PBCB EaBcb;
BOOLEAN LockedEaFcb;
EA_RANGE EaSetRange;
DebugTrace(+1, Dbg, "FatGetNeedEaCount ...\n", 0);
//
// If the handle is 0 then the Need Ea count is 0.
//
if (Dirent->ExtendedAttributes == 0) {
*NeedEaCount = 0;
DebugTrace(-1, Dbg, "FatGetNeedEaCount -> %08lx\n", TRUE);
return;
}
RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
//
// Use a try to facilitate cleanup.
//
try {
PDIRENT EaDirent;
OEM_STRING ThisFilename;
UCHAR Buffer[12];
PEA_SET_HEADER EaSetHeader;
//
// Initial the local values.
//
EaBcb = NULL;
LockedEaFcb = FALSE;
//
// Try to get the Ea file object. Return FALSE on failure.
//
FatGetEaFile( IrpContext,
Vcb,
&EaDirent,
&EaBcb,
FALSE,
FALSE );
LockedEaFcb = TRUE;
//
// If we didn't get the file because it doesn't exist, then the
// disk is corrupted.
//
if (Vcb->VirtualEaFile == NULL) {
DebugTrace(0, Dbg, "FatGetNeedEaCount: Ea file doesn't exist\n", 0);
FatRaiseStatus( IrpContext, STATUS_NO_EAS_ON_FILE );
}
//
// Try to pin down the Ea set header for the index in the
// dirent. If the operation doesn't complete, return FALSE
// from this routine.
//
ThisFilename.Buffer = Buffer;
Fat8dot3ToString( IrpContext, Dirent, FALSE, &ThisFilename );
FatReadEaSet( IrpContext,
Vcb,
Dirent->ExtendedAttributes,
&ThisFilename,
FALSE,
&EaSetRange );
EaSetHeader = (PEA_SET_HEADER) EaSetRange.Data;
//
// We now have the Ea set header for this file. We simply copy
// the Need Ea field.
//
*NeedEaCount = EaSetHeader->NeedEaCount;
} finally {
DebugUnwind( FatGetNeedEaCount );
//
// Unpin the EaDirent and the EaSetHeader if pinned.
//
FatUnpinBcb( IrpContext, EaBcb );
FatUnpinEaRange( IrpContext, &EaSetRange );
//
// Release the Fcb for the Ea file if locked.
//
if (LockedEaFcb) {
FatReleaseFcb( IrpContext, Vcb->EaFcb );
}
DebugTrace(-1, Dbg, "FatGetNeedEaCount: NeedEaCount -> %08lx\n", *NeedEaCount);
}
return;
}
VOID
FatCreateEa (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PUCHAR Buffer,
IN ULONG Length,
IN POEM_STRING FileName,
OUT PUSHORT EaHandle
)
/*++
Routine Description:
This routine adds an entire ea set to the Ea file. The owning file
is specified in 'FileName'. This is used to replace the Ea set attached
to an existing file during a supersede operation.
NOTE: This routine may block, it should not be called unless the
thread is waitable.
Arguments:
Vcb - Supplies the Vcb for the volume.
Buffer - Buffer with the Ea list to add.
Length - Length of the buffer.
FileName - The Ea's will be attached to this file.
EaHandle - The new ea handle will be assigned to this address.
Return Value:
None
--*/
{
PBCB EaBcb;
BOOLEAN LockedEaFcb;
PEA_SET_HEADER EaSetHeader;
EA_RANGE EaSetRange;
DebugTrace(+1, Dbg, "FatCreateEa...\n", 0);
EaBcb = NULL;
LockedEaFcb = FALSE;
RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
//
// Use 'try' to facilitate cleanup.
//
try {
PDIRENT EaDirent;
ULONG PackedEasLength;
ULONG AllocationLength;
ULONG BytesPerCluster;
PFILE_FULL_EA_INFORMATION FullEa;
//
// We will allocate a buffer and copy the Ea list from the user's
// buffer to a FAT packed Ea list. Initial allocation is one
// cluster, our starting offset into the packed Ea list is 0.
//
PackedEasLength = 0;
BytesPerCluster = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;
AllocationLength = (PackedEasLength
+ SIZE_OF_EA_SET_HEADER
+ BytesPerCluster - 1)
& ~(BytesPerCluster - 1);
//
// Allocate the memory and store the file name into it.
//
EaSetHeader = FsRtlAllocatePoolWithTag( PagedPool,
AllocationLength,
TAG_EA_SET_HEADER );
RtlZeroMemory( EaSetHeader, AllocationLength );
RtlCopyMemory( EaSetHeader->OwnerFileName,
FileName->Buffer,
FileName->Length );
AllocationLength -= SIZE_OF_EA_SET_HEADER;
//
// Loop through the user's Ea list. Catch any error for invalid
// name or non-existent Ea value.
//
for ( FullEa = (PFILE_FULL_EA_INFORMATION) Buffer;
FullEa < (PFILE_FULL_EA_INFORMATION) &Buffer[Length];
FullEa = (PFILE_FULL_EA_INFORMATION) (FullEa->NextEntryOffset == 0 ?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -