📄 ea.c
字号:
&EaSetRange );
EaSetHeader = (PEA_SET_HEADER) EaSetRange.Data;
//
// Find the start and length of the Eas.
//
FirstPackedEa = (PPACKED_EA) EaSetHeader->PackedEas;
PackedEasLength = GetcbList( EaSetHeader ) - 4;
}
//
// Protect our access to the user buffer since IO dosn't do this
// for us in this path unless we had specified that our driver
// requires buffering for these large requests. We don't, so ...
//
try {
//
// Let's clear the output buffer.
//
RtlZeroMemory( Buffer, UserBufferLength );
//
// We now satisfy the user's request depending on whether he
// specified an Ea name list, an Ea index or restarting the
// search.
//
//
// The user has supplied a list of Ea names.
//
if (UserEaList != NULL) {
Irp->IoStatus = FatQueryEaUserEaList( IrpContext,
Ccb,
FirstPackedEa,
PackedEasLength,
Buffer,
UserBufferLength,
UserEaList,
UserEaListLength,
ReturnSingleEntry );
//
// The user supplied an index into the Ea list.
//
} else if (IndexSpecified) {
Irp->IoStatus = FatQueryEaIndexSpecified( IrpContext,
Ccb,
FirstPackedEa,
PackedEasLength,
Buffer,
UserBufferLength,
UserEaIndex,
ReturnSingleEntry );
//
// Else perform a simple scan, taking into account the restart
// flag and the position of the next Ea stored in the Ccb.
//
} else {
Irp->IoStatus = FatQueryEaSimpleScan( IrpContext,
Ccb,
FirstPackedEa,
PackedEasLength,
Buffer,
UserBufferLength,
ReturnSingleEntry,
RestartScan
? 0
: Ccb->OffsetOfNextEaToReturn );
}
} except (!FsRtlIsNtstatusExpected(GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
//
// We must have had a problem filling in the user's buffer, so fail.
//
Irp->IoStatus.Status = GetExceptionCode();
Irp->IoStatus.Information = 0;
}
Status = Irp->IoStatus.Status;
try_exit: NOTHING;
} finally {
DebugUnwind( FatCommonQueryEa );
//
// Release the Fcb for the file object, and the Ea Fcb if
// successfully locked.
//
FatReleaseFcb( IrpContext, Fcb );
if (LockedEaFcb) {
FatReleaseFcb( IrpContext, Vcb->EaFcb );
}
//
// Unpin the dirents for the Fcb, EaFcb and EaSetFcb if necessary.
//
FatUnpinBcb( IrpContext, Bcb );
FatUnpinBcb( IrpContext, EaBcb );
FatUnpinEaRange( IrpContext, &EaSetRange );
if (!AbnormalTermination()) {
FatCompleteRequest( IrpContext, Irp, Status );
}
DebugTrace(-1, Dbg, "FatCommonQueryEa -> %08lx\n", Status);
}
return Status;
#endif
}
NTSTATUS
FatCommonSetEa (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the common Set Ea File Api called by the
the Fsd and Fsp threads
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The appropriate status for the Irp
--*/
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
USHORT ExtendedAttributes;
PUCHAR Buffer;
ULONG UserBufferLength;
PVCB Vcb;
PCCB Ccb;
PFCB Fcb;
PDIRENT Dirent;
PBCB Bcb = NULL;
PDIRENT EaDirent = NULL;
PBCB EaBcb = NULL;
PEA_SET_HEADER EaSetHeader = NULL;
PEA_SET_HEADER PrevEaSetHeader;
PEA_SET_HEADER NewEaSetHeader;
EA_RANGE EaSetRange;
BOOLEAN AcquiredVcb = FALSE;
BOOLEAN AcquiredFcb = FALSE;
BOOLEAN AcquiredParentDcb = FALSE;
BOOLEAN AcquiredRootDcb = FALSE;
BOOLEAN AcquiredEaFcb = FALSE;
FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST);
return STATUS_INVALID_DEVICE_REQUEST;
#if 0
//
// The following booleans are used in the unwind process.
//
//
// Get the current Irp stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "FatCommonSetEa...\n", 0);
DebugTrace( 0, Dbg, " Wait = %08lx\n", FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
DebugTrace( 0, Dbg, " Irp = %08lx\n", Irp );
DebugTrace( 0, Dbg, " ->SystemBuffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer );
DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.SetEa.Length );
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// Check that the file object is associated with either a user file
// or directory open.
//
{
TYPE_OF_OPEN OpenType;
if (((OpenType = FatDecodeFileObject( IrpSp->FileObject,
&Vcb,
&Fcb,
&Ccb )) != UserFileOpen
&& OpenType != UserDirectoryOpen) ||
(NodeType( Fcb )) == FAT_NTC_ROOT_DCB) {
FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
DebugTrace(-1, Dbg,
"FatCommonSetEa -> %08lx\n",
STATUS_INVALID_PARAMETER);
return STATUS_INVALID_PARAMETER;
}
}
//
// Fat32 does not support ea's.
//
if (FatIsFat32(Vcb)) {
FatCompleteRequest( IrpContext, Irp, STATUS_EAS_NOT_SUPPORTED );
DebugTrace(-1, Dbg,
"FatCommonSetEa -> %08lx\n",
STATUS_EAS_NOT_SUPPORTED);
return STATUS_EAS_NOT_SUPPORTED;
}
//
// Reference our input parameters to make things easier
//
UserBufferLength = IrpSp->Parameters.SetEa.Length;
//
// Since we ask for no outside help (direct or buffered IO), it
// is our responsibility to insulate ourselves from the
// deviousness of the user above. Now, buffer and validate the
// contents.
//
Buffer = FatBufferUserBuffer( IrpContext, Irp, UserBufferLength );
//
// Check the validity of the buffer with the new eas. We really
// need to do this always since we don't know, if it was already
// buffered, that we buffered and checked it or some overlying
// filter buffered without checking.
//
Status = IoCheckEaBufferValidity( (PFILE_FULL_EA_INFORMATION) Buffer,
UserBufferLength,
(PULONG)&Irp->IoStatus.Information );
if (!NT_SUCCESS( Status )) {
FatCompleteRequest( IrpContext, Irp, Status );
DebugTrace(-1, Dbg,
"FatCommonSetEa -> %08lx\n",
Status);
return Status;
}
//
// Acquire exclusive access to the Fcb. If this is a write-through operation
// we will need to pick up the other possible streams that can be modified in
// this operation so that the locking order is preserved - the root directory
// (dirent addition if EA database doesn't already exist) and the parent
// directory (addition of the EA handle to the object's dirent).
//
// We are primarily synchronizing with directory enumeration here.
//
// If we cannot wait need to send things off to the fsp.
//
if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {
DebugTrace(0, Dbg, "FatCommonSetEa: Set Ea must be waitable\n", 0);
Status = FatFsdPostRequest( IrpContext, Irp );
DebugTrace(-1, Dbg, "FatCommonSetEa -> %08lx\n", Status );
return Status;
}
//
// Set this handle as having modified the file
//
IrpSp->FileObject->Flags |= FO_FILE_MODIFIED;
RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
try {
ULONG PackedEasLength;
BOOLEAN PreviousEas;
ULONG AllocationLength;
ULONG BytesPerCluster;
USHORT EaHandle;
PFILE_FULL_EA_INFORMATION FullEa;
//
// Now go pick up everything
//
FatAcquireSharedVcb( IrpContext, Fcb->Vcb );
AcquiredVcb = TRUE;
FatAcquireExclusiveFcb( IrpContext, Fcb );
AcquiredFcb = TRUE;
if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) {
if (Fcb->ParentDcb) {
FatAcquireExclusiveFcb( IrpContext, Fcb->ParentDcb );
AcquiredParentDcb = TRUE;
}
FatAcquireExclusiveFcb( IrpContext, Fcb->Vcb->RootDcb );
AcquiredRootDcb = TRUE;
}
//
// We verify that the Fcb is still valid.
//
FatVerifyFcb( IrpContext, Fcb );
//
// We need to get the dirent for the Fcb to recover the Ea handle.
//
FatGetDirentFromFcbOrDcb( IrpContext, Fcb, &Dirent, &Bcb );
DebugTrace(0, Dbg, "FatCommonSetEa: Dirent Address -> %08lx\n",
Dirent );
DebugTrace(0, Dbg, "FatCommonSetEa: Dirent Bcb -> %08lx\n",
Bcb);
//
// If the handle value is 0, then the file has no Eas. In that
// case we allocate memory to hold the Eas to be added. If there
// are existing Eas for the file, then we must read from the
// file and copy the Eas.
//
ExtendedAttributes = Dirent->ExtendedAttributes;
FatUnpinBcb( IrpContext, Bcb );
if (ExtendedAttributes == 0) {
PreviousEas = FALSE;
DebugTrace(0, Dbg,
"FatCommonSetEa: File has no current Eas\n", 0 );
} else {
PreviousEas = TRUE;
DebugTrace(0, Dbg, "FatCommonSetEa: File has previous Eas\n", 0 );
FatGetEaFile( IrpContext,
Vcb,
&EaDirent,
&EaBcb,
FALSE,
TRUE );
AcquiredEaFcb = TRUE;
//
// If we didn't get the file then there is an error on
// the disk.
//
if (Vcb->VirtualEaFile == NULL) {
Status = STATUS_NO_EAS_ON_FILE;
try_return( Status );
}
}
DebugTrace(0, Dbg, "FatCommonSetEa: EaBcb -> %08lx\n", EaBcb);
DebugTrace(0, Dbg, "FatCommonSetEa: EaDirent -> %08lx\n", EaDirent);
//
// If the file has existing ea's, we need to read them to
// determine the size of the buffer allocation.
//
if (PreviousEas) {
//
// We need to try to get the Ea set for the desired file.
//
FatReadEaSet( IrpContext,
Vcb,
ExtendedAttributes,
&Fcb->ShortName.Name.Oem,
TRUE,
&EaSetRange );
PrevEaSetHeader = (PEA_SET_HEADER) EaSetRange.Data;
//
// We now must allocate pool memory for our copy of the
// EaSetHeader and then copy the Ea data into it. At that
// time we can unpin the EaSet.
//
PackedEasLength = GetcbList( PrevEaSetHeader ) - 4;
//
// Else we will create a dummy EaSetHeader.
//
} else {
PackedEasLength = 0;
}
BytesPerCluster = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;
AllocationLength = (PackedEasLength
+ SIZE_OF_EA_SET_HEADER
+ BytesPerCluster - 1)
& ~(BytesPerCluster - 1);
EaSetHeader = FsRtlAllocatePoolWithTag( PagedPool,
AllocationLength,
TAG_EA_SET_HEADER );
//
// Copy the existing Eas over to pool memory.
//
if (PreviousEas) {
RtlCopyMemory( EaSetHeader, PrevEaSetHeader, AllocationLength );
FatUnpinEaRange( IrpContext, &EaSetRange );
} else {
RtlZeroMemory( EaSetHeader, AllocationLength );
RtlCopyMemory( EaSetHeader->OwnerFileName,
Fcb->ShortName.Name.Oem.Buffer,
Fcb->ShortName.Name.Oem.Length );
}
AllocationLength -= SIZE_OF_EA_SET_HEADER;
DebugTrace(0, Dbg, "FatCommonSetEa: Initial Ea set -> %08lx\n",
EaSetHeader);
//
// At this point we have either read in the current eas for the file
// or we have initialized a new empty buffer for the eas. Now for
// each full ea in the input user buffer we do the specified operation
// on the ea
//
for (FullEa = (PFILE_FULL_EA_INFORMATION) Buffer;
FullEa < (PFILE_FULL_EA_INFORMATION) &Buffer[UserBufferLength];
FullEa = (PFILE_FULL_EA_INFORMATION) (FullEa->NextEntryOffset == 0 ?
&Buffer[UserBufferLength] :
(PUCHAR) FullEa + FullEa->NextEntryOffset)) {
OEM_STRING EaName;
ULONG Offset;
EaName.MaximumLength = EaName.Length = FullEa->EaNameLength;
EaName.Buffer = &FullEa->EaName[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -