📄 ea.c
字号:
//
LastFullEa = NextFullEa;
LastFullEaSize = LongAlign( SizeOfFullEa( LastFullEa ));
RemainingUserBufferLength -= LastFullEaSize;
NextFullEa = (PFILE_FULL_EA_INFORMATION) ((PUCHAR) NextFullEa
+ LastFullEaSize);
//
// Remember the offset of the next ea in case we're asked to
// resume the iteration
//
Ccb->OffsetOfNextEaToReturn = FatLocateNextEa( IrpContext,
FirstPackedEa,
PackedEasLength,
Offset );
//
// If we were to return a single entry then break out of our loop
// now
//
if (ReturnSingleEntry) {
break;
}
}
//
// Now we've iterated all that can and we've exited the preceding loop
// with either all, some or no information stored in the return buffer.
// We can decide if we got everything to fit by checking the local
// Overflow variable
//
if (Overflow) {
Iosb.Information = 0;
Iosb.Status = STATUS_BUFFER_OVERFLOW;
} else {
//
// Otherwise we've been successful in returing at least one
// ea so we'll compute the number of bytes used to store the
// full ea information. The number of bytes used is the difference
// between the LastFullEa and the start of the buffer, and the
// non-aligned size of the last full ea.
//
Iosb.Information = ((PUCHAR) LastFullEa - UserBuffer)
+ SizeOfFullEa(LastFullEa);
Iosb.Status = STATUS_SUCCESS;
}
DebugTrace(-1, Dbg, "FatQueryEaUserEaList -> Iosb.Status = %08lx\n",
Iosb.Status);
return Iosb;
}
//
// Local Support Routine
//
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
)
/*++
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
UserEaIndex - Supplies the index of the first ea to return.
RestartScan - Indicates if the first item to return is at the
beginning of the packed ea list or if we should resume our
previous iteration
Return Value:
IO_STATUS_BLOCK - Receives the completion status for the operation
--*/
{
IO_STATUS_BLOCK Iosb;
ULONG i;
ULONG Offset;
DebugTrace(+1, Dbg, "FatQueryEaIndexSpecified...\n", 0);
//
// Zero out the information field of the iosb
//
Iosb.Information = 0;
//
// If the index value is zero or there are no Eas on the file, then
// the specified index can't be returned.
//
if (UserEaIndex == 0
|| PackedEasLength == 0) {
DebugTrace( -1, Dbg, "FatQueryEaIndexSpecified: Non-existant entry\n", 0 );
Iosb.Status = STATUS_NONEXISTENT_EA_ENTRY;
return Iosb;
}
//
// Iterate the eas until we find the index we're after.
//
for (i = 1, Offset = 0;
(i < UserEaIndex) && (Offset < PackedEasLength);
i += 1, Offset = FatLocateNextEa( IrpContext,
FirstPackedEa,
PackedEasLength, Offset )) {
NOTHING;
}
//
// Make sure the offset we're given to the ea is a real offset otherwise
// the ea doesn't exist
//
if (Offset >= PackedEasLength) {
//
// If we just passed the last Ea, we will return STATUS_NO_MORE_EAS.
// This is for the caller who may be enumerating the Eas.
//
if (i == UserEaIndex) {
Iosb.Status = STATUS_NO_MORE_EAS;
//
// Otherwise we report that this is a bad ea index.
//
} else {
Iosb.Status = STATUS_NONEXISTENT_EA_ENTRY;
}
DebugTrace(-1, Dbg, "FatQueryEaIndexSpecified -> %08lx\n", Iosb.Status);
return Iosb;
}
//
// We now have the offset of the first Ea to return to the user.
// We simply call our EaSimpleScan routine to do the actual work.
//
Iosb = FatQueryEaSimpleScan( IrpContext,
Ccb,
FirstPackedEa,
PackedEasLength,
UserBuffer,
UserBufferLength,
ReturnSingleEntry,
Offset );
DebugTrace(-1, Dbg, "FatQueryEaIndexSpecified -> %08lx\n", Iosb.Status);
return Iosb;
}
//
// Local Support Routine
//
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
)
/*++
Routine Description:
This routine is the work routine for querying EAs from the beginning of
the ea list.
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
ReturnSingleEntry - Indicates if we are to return a single entry or not
StartOffset - Indicates the offset within the Ea data to return the
first block of data.
Return Value:
IO_STATUS_BLOCK - Receives the completion status for the operation
--*/
{
IO_STATUS_BLOCK Iosb;
ULONG RemainingUserBufferLength;
PPACKED_EA PackedEa;
ULONG PackedEaSize;
PFILE_FULL_EA_INFORMATION LastFullEa;
ULONG LastFullEaSize;
PFILE_FULL_EA_INFORMATION NextFullEa;
BOOLEAN BufferOverflow = FALSE;
DebugTrace(+1, Dbg, "FatQueryEaSimpleScan...\n", 0);
//
// Zero out the information field in the Iosb
//
Iosb.Information = 0;
LastFullEa = NULL;
NextFullEa = (PFILE_FULL_EA_INFORMATION) UserBuffer;
RemainingUserBufferLength = UserBufferLength;
while (StartOffset < PackedEasLength) {
DebugTrace(0, Dbg, "Top of loop, Offset = %08lx\n", StartOffset);
DebugTrace(0, Dbg, "LastFullEa = %08lx\n", LastFullEa);
DebugTrace(0, Dbg, "NextFullEa = %08lx\n", NextFullEa);
DebugTrace(0, Dbg, "RemainingUserBufferLength = %08lx\n", RemainingUserBufferLength);
//
// Reference the packed ea of interest.
//
PackedEa = (PPACKED_EA) ((PUCHAR) FirstPackedEa + StartOffset);
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) {
BufferOverflow = 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.
// Then go back and set the last full eas entry offset field
// to be the difference between the two pointers.
//
RtlCopyMemory( &NextFullEa->Flags, &PackedEa->Flags, PackedEaSize );
NextFullEa->NextEntryOffset = 0;
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
//
LastFullEa = NextFullEa;
LastFullEaSize = LongAlign( SizeOfFullEa( LastFullEa ));
RemainingUserBufferLength -= LastFullEaSize;
NextFullEa = (PFILE_FULL_EA_INFORMATION) ((PUCHAR) NextFullEa
+ LastFullEaSize);
//
// Remember the offset of the next ea in case we're asked to
// resume the teration
//
StartOffset = FatLocateNextEa( IrpContext,
FirstPackedEa,
PackedEasLength,
StartOffset );
Ccb->OffsetOfNextEaToReturn = StartOffset;
//
// If we were to return a single entry then break out of our loop
// now
//
if (ReturnSingleEntry) {
break;
}
}
//
// Now we've iterated all that can and we've exited the preceding loop
// with either some or no information stored in the return buffer.
// We can decide which it is by checking if the last full ea is null
//
if (LastFullEa == NULL) {
Iosb.Information = 0;
//
// We were not able to return a single ea entry, now we need to find
// out if it is because we didn't have an entry to return or the
// buffer is too small. If the Offset variable is less than
// PackedEaList->UsedSize then the user buffer is too small
//
if (PackedEasLength == 0) {
Iosb.Status = STATUS_NO_EAS_ON_FILE;
} else if (StartOffset >= PackedEasLength) {
Iosb.Status = STATUS_NO_MORE_EAS;
} else {
Iosb.Status = STATUS_BUFFER_TOO_SMALL;
}
} else {
//
// Otherwise we've been successful in returing at least one
// ea so we'll compute the number of bytes used to store the
// full ea information. The number of bytes used is the difference
// between the LastFullEa and the start of the buffer, and the
// non-aligned size of the last full ea.
//
Iosb.Information = ((PUCHAR) LastFullEa - UserBuffer)
+ SizeOfFullEa( LastFullEa );
//
// If there are more to return, report the buffer was too small.
// Otherwise return STATUS_SUCCESS.
//
if (BufferOverflow) {
Iosb.Status = STATUS_BUFFER_OVERFLOW;
} else {
Iosb.Status = STATUS_SUCCESS;
}
}
DebugTrace(-1, Dbg, "FatQueryEaSimpleScan -> Iosb.Status = %08lx\n",
Iosb.Status);
return Iosb;
}
//
// Local Support Routine
//
BOOLEAN
FatIsDuplicateEaName (
IN PIRP_CONTEXT IrpContext,
IN PFILE_GET_EA_INFORMATION GetEa,
IN PUCHAR UserBuffer
)
/*++
Routine Description:
This routine walks through a list of ea names to find a duplicate name.
'GetEa' is an actual position in the list. We are only interested in
previous matching ea names, as the ea information for that ea name
would have been returned with the previous instance.
Arguments:
GetEa - Supplies the Ea name structure for the ea name to match.
UserBuffer - Supplies a pointer to the user buffer with the list
of ea names to search for.
Return Value:
BOOLEAN - TRUE if a previous match is found, FALSE otherwise.
--*/
{
PFILE_GET_EA_INFORMATION ThisGetEa;
BOOLEAN DuplicateFound;
OEM_STRING EaString;
DebugTrace(+1, Dbg, "FatIsDuplicateEaName...\n", 0);
EaString.MaximumLength = EaString.Length = GetEa->EaNameLength;
EaString.Buffer = &GetEa->EaName[0];
FatUpcaseEaName( IrpContext, &EaString, &EaString );
DuplicateFound = FALSE;
for (ThisGetEa = (PFILE_GET_EA_INFORMATION) &UserBuffer[0];
ThisGetEa < GetEa
&& ThisGetEa->NextEntryOffset != 0;
ThisGetEa = (PFILE_GET_EA_INFORMATION) ((PUCHAR) ThisGetEa
+ ThisGetEa->NextEntryOffset)) {
OEM_STRING Str;
DebugTrace(0, Dbg, "Top of loop, ThisGetEa = %08lx\n", ThisGetEa);
//
// Make a string reference to the GetEa and see if we can
// locate the ea by name
//
Str.MaximumLength = Str.Length = ThisGetEa->EaNameLength;
Str.Buffer = &ThisGetEa->EaName[0];
DebugTrace(0, Dbg, "FatIsDuplicateEaName: Next Name -> %Z\n", &Str);
if ( FatAreNamesEqual(IrpContext, Str, EaString) ) {
DebugTrace(0, Dbg, "FatIsDuplicateEaName: Duplicate found\n", 0);
DuplicateFound = TRUE;
break;
}
}
DebugTrace(-1, Dbg, "FatIsDuplicateEaName: Exit -> %04x\n", DuplicateFound);
return DuplicateFound;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -