📄 ea.c
字号:
DebugTrace(0, Dbg, "FatCommonSetEa: Next Ea name -> %Z\n",
&EaName);
//
// Make sure the ea name is valid
//
if (!FatIsEaNameValid( IrpContext,EaName )) {
Irp->IoStatus.Information = (PUCHAR)FullEa - Buffer;
Status = STATUS_INVALID_EA_NAME;
try_return( Status );
}
//
// Check that no invalid ea flags are set.
//
//
// TEMPCODE We are returning STATUS_INVALID_EA_NAME
// until a more appropriate error code exists.
//
if (FullEa->Flags != 0
&& FullEa->Flags != FILE_NEED_EA) {
Irp->IoStatus.Information = (PUCHAR)FullEa - (PUCHAR)Buffer;
try_return( Status = STATUS_INVALID_EA_NAME );
}
//
// See if we can locate the ea name in the ea set
//
if (FatLocateEaByName( IrpContext,
(PPACKED_EA) EaSetHeader->PackedEas,
PackedEasLength,
&EaName,
&Offset )) {
DebugTrace(0, Dbg, "FatCommonSetEa: Found Ea name\n", 0);
//
// We found the ea name so now delete the current entry,
// and if the new ea value length is not zero then we
// replace if with the new ea
//
FatDeletePackedEa( IrpContext,
EaSetHeader,
&PackedEasLength,
Offset );
}
if (FullEa->EaValueLength != 0) {
FatAppendPackedEa( IrpContext,
&EaSetHeader,
&PackedEasLength,
&AllocationLength,
FullEa,
BytesPerCluster );
}
}
//
// If there are any ea's not removed, we
// call 'AddEaSet' to insert them into the Fat chain.
//
if (PackedEasLength != 0) {
LARGE_INTEGER EaOffset;
EaOffset.HighPart = 0;
//
// If the packed eas length (plus 4 bytes) is greater
// than the maximum allowed ea size, we return an error.
//
if (PackedEasLength + 4 > MAXIMUM_EA_SIZE) {
DebugTrace( 0, Dbg, "Ea length is greater than maximum\n", 0 );
try_return( Status = STATUS_EA_TOO_LARGE );
}
//
// We need to now read the ea file if we haven't already.
//
if (EaDirent == NULL) {
FatGetEaFile( IrpContext,
Vcb,
&EaDirent,
&EaBcb,
TRUE,
TRUE );
AcquiredEaFcb = TRUE;
}
FatGetDirentFromFcbOrDcb( IrpContext, Fcb, &Dirent, &Bcb );
RtlZeroMemory( &EaSetRange, sizeof( EA_RANGE ));
FatAddEaSet( IrpContext,
Vcb,
PackedEasLength + SIZE_OF_EA_SET_HEADER,
EaBcb,
EaDirent,
&EaHandle,
&EaSetRange );
NewEaSetHeader = (PEA_SET_HEADER) EaSetRange.Data;
DebugTrace(0, Dbg, "FatCommonSetEa: Adding an ea set\n", 0);
//
// Store the length of the new Ea's into the EaSetHeader.
// This is the PackedEasLength + 4.
//
PackedEasLength += 4;
CopyU4char( EaSetHeader->cbList, &PackedEasLength );
//
// Copy all but the first four bytes of EaSetHeader into
// NewEaSetHeader. The signature and index fields have
// already been filled in.
//
RtlCopyMemory( &NewEaSetHeader->NeedEaCount,
&EaSetHeader->NeedEaCount,
PackedEasLength + SIZE_OF_EA_SET_HEADER - 8 );
FatMarkEaRangeDirty( IrpContext, Vcb->VirtualEaFile, &EaSetRange );
FatUnpinEaRange( IrpContext, &EaSetRange );
CcFlushCache( Vcb->VirtualEaFile->SectionObjectPointer, NULL, 0, NULL );
} else {
FatGetDirentFromFcbOrDcb( IrpContext, Fcb, &Dirent, &Bcb );
EaHandle = 0;
}
//
// Now we do a wholesale replacement of the ea for the file
//
if (PreviousEas) {
FatDeleteEaSet( IrpContext,
Vcb,
EaBcb,
EaDirent,
ExtendedAttributes,
&Fcb->ShortName.Name.Oem );
CcFlushCache( Vcb->VirtualEaFile->SectionObjectPointer, NULL, 0, NULL );
}
if (PackedEasLength != 0 ) {
Fcb->EaModificationCount++;
}
//
// Mark the dirent with the new ea's
//
Dirent->ExtendedAttributes = EaHandle;
FatSetDirtyBcb( IrpContext, Bcb, Vcb, TRUE );
//
// We call the notify package to report that the ea's were
// modified.
//
FatNotifyReportChange( IrpContext,
Vcb,
Fcb,
FILE_NOTIFY_CHANGE_EA,
FILE_ACTION_MODIFIED );
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
try_exit: NOTHING;
//
// Unpin the dirents for the Fcb and EaFcb if necessary.
//
FatUnpinBcb( IrpContext, Bcb );
FatUnpinBcb( IrpContext, EaBcb );
FatUnpinRepinnedBcbs( IrpContext );
} finally {
DebugUnwind( FatCommonSetEa );
//
// If this is an abnormal termination, we need to clean up
// any locked resources.
//
if (AbnormalTermination()) {
//
// Unpin the dirents for the Fcb, EaFcb and EaSetFcb if necessary.
//
FatUnpinBcb( IrpContext, Bcb );
FatUnpinBcb( IrpContext, EaBcb );
FatUnpinEaRange( IrpContext, &EaSetRange );
}
//
// Release the Fcbs/Vcb acquired.
//
if (AcquiredEaFcb) {
FatReleaseFcb( IrpContext, Vcb->EaFcb );
}
if (AcquiredFcb) {
FatReleaseFcb( IrpContext, Fcb );
}
if (AcquiredParentDcb) {
FatReleaseFcb( IrpContext, Fcb->ParentDcb );
}
if (AcquiredRootDcb) {
FatReleaseFcb( IrpContext, Fcb->Vcb->RootDcb );
}
if (AcquiredVcb) {
FatReleaseVcb( IrpContext, Fcb->Vcb );
}
//
// Deallocate our Ea buffer.
//
if (EaSetHeader != NULL) {
ExFreePool( EaSetHeader );
}
//
// Complete the irp.
//
if (!AbnormalTermination()) {
FatCompleteRequest( IrpContext, Irp, Status );
}
DebugTrace(-1, Dbg, "FatCommonSetEa -> %08lx\n", Status);
}
//
// And return to our caller
//
return Status;
#endif
}
#if 0
//
// Local Support Routine
//
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
)
/*++
Routine Description:
This routine is the work routine for querying EAs given an ea index
Arguments:
Ccb - Supplies the Ccb for the query
FirstPackedEa - Supplies the first ea for the file being queried
PackedEasLength - Supplies the length of the ea data
UserBuffer - Supplies the buffer to receive the full eas
UserBufferLength - Supplies the length, in bytes, of the user buffer
UserEaList - Supplies the user specified ea name list
UserEaListLength - Supplies the length, in bytes, of the user ea list
ReturnSingleEntry - Indicates if we are to return a single entry or not
Return Value:
IO_STATUS_BLOCK - Receives the completion status for the operation
--*/
{
IO_STATUS_BLOCK Iosb;
ULONG Offset;
ULONG RemainingUserBufferLength;
PPACKED_EA PackedEa;
ULONG PackedEaSize;
PFILE_FULL_EA_INFORMATION LastFullEa = NULL;
ULONG LastFullEaSize;
PFILE_FULL_EA_INFORMATION NextFullEa;
PFILE_GET_EA_INFORMATION GetEa;
BOOLEAN Overflow;
DebugTrace(+1, Dbg, "FatQueryEaUserEaList...\n", 0);
LastFullEa = NULL;
NextFullEa = (PFILE_FULL_EA_INFORMATION) UserBuffer;
RemainingUserBufferLength = UserBufferLength;
Overflow = FALSE;
for (GetEa = (PFILE_GET_EA_INFORMATION) &UserEaList[0];
GetEa < (PFILE_GET_EA_INFORMATION) ((PUCHAR) UserEaList
+ UserEaListLength);
GetEa = (GetEa->NextEntryOffset == 0
? (PFILE_GET_EA_INFORMATION) MAXUINT_PTR
: (PFILE_GET_EA_INFORMATION) ((PUCHAR) GetEa
+ GetEa->NextEntryOffset))) {
OEM_STRING Str;
OEM_STRING OutputEaName;
DebugTrace(0, Dbg, "Top of loop, GetEa = %08lx\n", GetEa);
DebugTrace(0, Dbg, "LastFullEa = %08lx\n", LastFullEa);
DebugTrace(0, Dbg, "NextFullEa = %08lx\n", NextFullEa);
DebugTrace(0, Dbg, "RemainingUserBufferLength = %08lx\n", RemainingUserBufferLength);
//
// Make a string reference to the GetEa and see if we can
// locate the ea by name
//
Str.MaximumLength = Str.Length = GetEa->EaNameLength;
Str.Buffer = &GetEa->EaName[0];
//
// Check for a valid name.
//
if (!FatIsEaNameValid( IrpContext, Str )) {
DebugTrace(-1, Dbg,
"FatQueryEaUserEaList: Invalid Ea Name -> %Z\n",
&Str);
Iosb.Information = (PUCHAR)GetEa - UserEaList;
Iosb.Status = STATUS_INVALID_EA_NAME;
return Iosb;
}
//
// If this is a duplicate name, we skip to the next.
//
if (FatIsDuplicateEaName( IrpContext, GetEa, UserEaList )) {
DebugTrace(0, Dbg, "FatQueryEaUserEaList: Duplicate name\n", 0);
continue;
}
if (!FatLocateEaByName( IrpContext,
FirstPackedEa,
PackedEasLength,
&Str,
&Offset )) {
Offset = 0xffffffff;
DebugTrace(0, Dbg, "Need to dummy up an ea\n", 0);
//
// We were not able to locate the name therefore we must
// dummy up a entry for the query. The needed Ea size is
// the size of the name + 4 (next entry offset) + 1 (flags)
// + 1 (name length) + 2 (value length) + the name length +
// 1 (null byte).
//
if ((ULONG)(4+1+1+2+GetEa->EaNameLength+1)
> RemainingUserBufferLength) {
Overflow = TRUE;
break;
}
//
// Everything is going to work fine, so copy over the name,
// set the name length and zero out the rest of the ea.
//
NextFullEa->NextEntryOffset = 0;
NextFullEa->Flags = 0;
NextFullEa->EaNameLength = GetEa->EaNameLength;
NextFullEa->EaValueLength = 0;
RtlCopyMemory( &NextFullEa->EaName[0],
&GetEa->EaName[0],
GetEa->EaNameLength );
//
// Upcase the name in the buffer.
//
OutputEaName.MaximumLength = OutputEaName.Length = Str.Length;
OutputEaName.Buffer = NextFullEa->EaName;
FatUpcaseEaName( IrpContext, &OutputEaName, &OutputEaName );
NextFullEa->EaName[GetEa->EaNameLength] = 0;
} else {
DebugTrace(0, Dbg, "Located the ea, Offset = %08lx\n", Offset);
//
// We were able to locate the packed ea
// Reference the packed ea
//
PackedEa = (PPACKED_EA) ((PUCHAR) FirstPackedEa + Offset);
SizeOfPackedEa( PackedEa, &PackedEaSize );
DebugTrace(0, Dbg, "PackedEaSize = %08lx\n", PackedEaSize);
//
// We know that the packed ea is 4 bytes smaller than its
// equivalent full ea so we need to check the remaining
// user buffer length against the computed full ea size.
//
if (PackedEaSize + 4 > RemainingUserBufferLength) {
Overflow = TRUE;
break;
}
//
// Everything is going to work fine, so copy over the packed
// ea to the full ea and zero out the next entry offset field.
//
RtlCopyMemory( &NextFullEa->Flags,
&PackedEa->Flags,
PackedEaSize );
NextFullEa->NextEntryOffset = 0;
}
//
// At this point we've copied a new full ea into the next full ea
// location. So now go back and set the set full eas entry offset
// field to be the difference between out two pointers.
//
if (LastFullEa != NULL) {
LastFullEa->NextEntryOffset = (ULONG)((PUCHAR) NextFullEa
- (PUCHAR) LastFullEa);
}
//
// Set the last full ea to the next full ea, compute
// where the next full should be, and decrement the remaining user
// buffer length appropriately
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -