📄 ea.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
Ea.c
Abstract:
This module implements the EA routines for Fat called by
the dispatch driver.
--*/
#include "FatProcs.h"
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_EA)
//
// Local procedure prototypes
//
IO_STATUS_BLOCK
FatQueryEaUserEaList (
IN PIRP_CONTEXT IrpContext,
OUT PCCB Ccb,
IN PPACKED_EA FirstPackedEa,
IN ULONG PackedEasLength,
OUT PUCHAR UserBuffer,
IN ULONG UserBufferLength,
IN PUCHAR UserEaList,
IN ULONG UserEaListLength,
IN BOOLEAN ReturnSingleEntry
);
IO_STATUS_BLOCK
FatQueryEaIndexSpecified (
IN PIRP_CONTEXT IrpContext,
OUT PCCB Ccb,
IN PPACKED_EA FirstPackedEa,
IN ULONG PackedEasLength,
OUT PUCHAR UserBuffer,
IN ULONG UserBufferLength,
IN ULONG UserEaIndex,
IN BOOLEAN ReturnSingleEntry
);
IO_STATUS_BLOCK
FatQueryEaSimpleScan (
IN PIRP_CONTEXT IrpContext,
OUT PCCB Ccb,
IN PPACKED_EA FirstPackedEa,
IN ULONG PackedEasLength,
OUT PUCHAR UserBuffer,
IN ULONG UserBufferLength,
IN BOOLEAN ReturnSingleEntry,
ULONG StartOffset
);
BOOLEAN
FatIsDuplicateEaName (
IN PIRP_CONTEXT IrpContext,
IN PFILE_GET_EA_INFORMATION GetEa,
IN PUCHAR UserBuffer
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatCommonQueryEa)
#pragma alloc_text(PAGE, FatCommonSetEa)
#pragma alloc_text(PAGE, FatFsdQueryEa)
#pragma alloc_text(PAGE, FatFsdSetEa)
#if 0
#pragma alloc_text(PAGE, FatIsDuplicateEaName)
#pragma alloc_text(PAGE, FatQueryEaIndexSpecified)
#pragma alloc_text(PAGE, FatQueryEaSimpleScan)
#pragma alloc_text(PAGE, FatQueryEaUserEaList)
#endif
#endif
NTSTATUS
FatFsdQueryEa (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the Fsd part of the NtQueryEa API
call.
Arguments:
VolumeDeviceObject - Supplies the volume device object where the file
being queried exists.
Irp - Supplies the Irp being processed.
Return Value:
NTSTATUS - The FSD status for the Irp.
--*/
{
NTSTATUS Status;
PIRP_CONTEXT IrpContext = NULL;
BOOLEAN TopLevel;
DebugTrace(+1, Dbg, "FatFsdQueryEa\n", 0);
//
// Call the common query routine, with blocking allowed if synchronous
//
FsRtlEnterFileSystem();
TopLevel = FatIsIrpTopLevel( Irp );
try {
IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
Status = FatCommonQueryEa( IrpContext, Irp );
} except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with
// the error status that we get back from the
// execption code
//
Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
}
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
FsRtlExitFileSystem();
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatFsdQueryEa -> %08lx\n", Status);
UNREFERENCED_PARAMETER( VolumeDeviceObject );
return Status;
}
NTSTATUS
FatFsdSetEa (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the FSD part of the NtSetEa API
call.
Arguments:
VolumeDeviceObject - Supplies the volume device object where the file
being set exists.
Irp - Supplies the Irp being processed.
Return Value:
NTSTATUS - The FSD status for the Irp.
--*/
{
NTSTATUS Status;
PIRP_CONTEXT IrpContext = NULL;
BOOLEAN TopLevel;
DebugTrace(+1, Dbg, "FatFsdSetEa\n", 0);
//
// Call the common set routine, with blocking allowed if synchronous
//
FsRtlEnterFileSystem();
TopLevel = FatIsIrpTopLevel( Irp );
try {
IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
Status = FatCommonSetEa( IrpContext, Irp );
} except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with
// the error status that we get back from the
// execption code
//
Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
}
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
FsRtlExitFileSystem();
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatFsdSetEa -> %08lx\n", Status);
UNREFERENCED_PARAMETER( VolumeDeviceObject );
return Status;
}
NTSTATUS
FatCommonQueryEa (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for querying File ea called by both
the fsd and fsp threads.
Arguments:
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The return status for the operation
--*/
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
PUCHAR Buffer;
ULONG UserBufferLength;
PUCHAR UserEaList;
ULONG UserEaListLength;
ULONG UserEaIndex;
BOOLEAN RestartScan;
BOOLEAN ReturnSingleEntry;
BOOLEAN IndexSpecified;
PVCB Vcb;
PCCB Ccb;
PFCB Fcb;
PDIRENT Dirent;
PBCB Bcb;
PDIRENT EaDirent;
PBCB EaBcb;
BOOLEAN LockedEaFcb;
PEA_SET_HEADER EaSetHeader;
EA_RANGE EaSetRange;
USHORT ExtendedAttributes;
FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST);
return STATUS_INVALID_DEVICE_REQUEST;
#if 0
//
// Get the current Irp stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "FatCommonQueryEa...\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.QueryEa.Length );
DebugTrace( 0, Dbg, " ->EaList = %08lx\n", IrpSp->Parameters.QueryEa.EaList );
DebugTrace( 0, Dbg, " ->EaListLength = %08lx\n", IrpSp->Parameters.QueryEa.EaListLength );
DebugTrace( 0, Dbg, " ->EaIndex = %08lx\n", IrpSp->Parameters.QueryEa.EaIndex );
DebugTrace( 0, Dbg, " ->RestartScan = %08lx\n", FlagOn(IrpSp->Flags, SL_RESTART_SCAN));
DebugTrace( 0, Dbg, " ->ReturnSingleEntry = %08lx\n", FlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY));
DebugTrace( 0, Dbg, " ->IndexSpecified = %08lx\n", FlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// Check that the file object is associated with either a user file
// or directory open. We don't allow Ea operations on the root
// directory.
//
{
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,
"FatCommonQueryEa -> %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,
"FatCommonQueryEa -> %08lx\n",
STATUS_EAS_NOT_SUPPORTED);
return STATUS_EAS_NOT_SUPPORTED;
}
//
// Acquire shared access to the Fcb and enqueue the Irp if we didn't
// get access.
//
if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
DebugTrace(0, Dbg, "FatCommonQueryEa: Thread can't wait\n", 0);
Status = FatFsdPostRequest( IrpContext, Irp );
DebugTrace(-1, Dbg, "FatCommonQueryEa -> %08lx\n", Status );
return Status;
}
FatAcquireSharedFcb( IrpContext, Fcb );
//
// Reference our input parameters to make things easier
//
UserBufferLength = IrpSp->Parameters.QueryEa.Length;
UserEaList = IrpSp->Parameters.QueryEa.EaList;
UserEaListLength = IrpSp->Parameters.QueryEa.EaListLength;
UserEaIndex = IrpSp->Parameters.QueryEa.EaIndex;
RestartScan = BooleanFlagOn(IrpSp->Flags, SL_RESTART_SCAN);
ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
IndexSpecified = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED);
//
// Initialize our local values.
//
LockedEaFcb = FALSE;
Bcb = NULL;
EaBcb = NULL;
Status = STATUS_SUCCESS;
RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
try {
PPACKED_EA FirstPackedEa;
ULONG PackedEasLength;
Buffer = FatMapUserBuffer( IrpContext, Irp );
//
// 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 );
//
// Verify that the Ea file is in a consistant state. If the
// Ea modification count in the Fcb doesn't match that in
// the CCB, then the Ea file has been changed from under
// us. If we are not starting the search from the beginning
// of the Ea set, we return an error.
//
if (UserEaList == NULL
&& Ccb->OffsetOfNextEaToReturn != 0
&& !IndexSpecified
&& !RestartScan
&& Fcb->EaModificationCount != Ccb->EaModificationCount) {
DebugTrace(0, Dbg,
"FatCommonQueryEa: Ea file in unknown state\n", 0);
Status = STATUS_EA_CORRUPT_ERROR;
try_return( Status );
}
//
// Show that the Ea's for this file are consistant for this
// file handle.
//
Ccb->EaModificationCount = Fcb->EaModificationCount;
//
// If the handle value is 0, then the file has no Eas. We dummy up
// an ea list to use below.
//
ExtendedAttributes = Dirent->ExtendedAttributes;
FatUnpinBcb( IrpContext, Bcb );
if (ExtendedAttributes == 0) {
DebugTrace(0, Dbg,
"FatCommonQueryEa: Zero handle, no Ea's for this file\n", 0);
FirstPackedEa = (PPACKED_EA) NULL;
PackedEasLength = 0;
} else {
//
// We need to get the Ea file for this volume. If the
// operation doesn't complete due to blocking, then queue the
// Irp to the Fsp.
//
FatGetEaFile( IrpContext,
Vcb,
&EaDirent,
&EaBcb,
FALSE,
FALSE );
LockedEaFcb = TRUE;
//
// If the above operation completed and the Ea file did not exist,
// the disk has been corrupted. There is an existing Ea handle
// without any Ea data.
//
if (Vcb->VirtualEaFile == NULL) {
DebugTrace(0, Dbg,
"FatCommonQueryEa: No Ea file found when expected\n", 0);
Status = STATUS_NO_EAS_ON_FILE;
try_return( Status );
}
//
// We need to try to get the Ea set for the desired file. If
// blocking is necessary then we'll post the request to the Fsp.
//
FatReadEaSet( IrpContext,
Vcb,
ExtendedAttributes,
&Fcb->ShortName.Name.Oem,
TRUE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -