/* FUNCTIONS ****************************************************************/
-
ULONGLONG
NtfsGetFileSize(PDEVICE_EXTENSION DeviceExt,
PFILE_RECORD_HEADER FileRecord,
NTSTATUS Status;
PNTFS_ATTR_CONTEXT DataContext;
- Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Stream, StreamLength, &DataContext);
+ Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Stream, StreamLength, &DataContext, NULL);
if (NT_SUCCESS(Status))
{
- Size = AttributeDataLength(&DataContext->Record);
- Allocated = AttributeAllocatedLength(&DataContext->Record);
+ Size = AttributeDataLength(DataContext->pRecord);
+ Allocated = AttributeAllocatedLength(DataContext->pRecord);
ReleaseAttributeContext(DataContext);
}
}
+#define ULONG_ROUND_UP(x) ROUND_UP((x), (sizeof(ULONG)))
+
+
static NTSTATUS
-NtfsGetNameInformation(PDEVICE_EXTENSION DeviceExt,
- PFILE_RECORD_HEADER FileRecord,
- ULONGLONG MFTIndex,
- PFILE_NAMES_INFORMATION Info,
- ULONG BufferLength)
+NtfsGetNamesInformation(PDEVICE_EXTENSION DeviceExt,
+ PFILE_RECORD_HEADER FileRecord,
+ ULONGLONG MFTIndex,
+ PFILE_NAMES_INFORMATION Info,
+ ULONG BufferLength,
+ PULONG Written,
+ BOOLEAN First)
{
ULONG Length;
+ NTSTATUS Status;
+ ULONG BytesToCopy = 0;
PFILENAME_ATTRIBUTE FileName;
- DPRINT("NtfsGetNameInformation() called\n");
+ DPRINT("NtfsGetNamesInformation() called\n");
+
+ *Written = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ if (FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName) > BufferLength)
+ {
+ return Status;
+ }
FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
if (FileName == NULL)
}
Length = FileName->NameLength * sizeof (WCHAR);
- if ((sizeof(FILE_NAMES_INFORMATION) + Length) > BufferLength)
- return(STATUS_BUFFER_OVERFLOW);
+ if (First || (BufferLength >= FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName) + Length))
+ {
+ Info->FileNameLength = Length;
+
+ *Written = FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName);
+ Info->NextEntryOffset = 0;
+ if (BufferLength > FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName))
+ {
+ BytesToCopy = min(Length, BufferLength - FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName));
+ RtlCopyMemory(Info->FileName, FileName->Name, BytesToCopy);
+ *Written += BytesToCopy;
- Info->FileNameLength = Length;
- Info->NextEntryOffset =
- ROUND_UP(sizeof(FILE_NAMES_INFORMATION) + Length, sizeof(ULONG));
- RtlCopyMemory(Info->FileName, FileName->Name, Length);
+ if (BytesToCopy == Length)
+ {
+ Info->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_NAMES_INFORMATION) +
+ BytesToCopy);
+ Status = STATUS_SUCCESS;
+ }
+ }
+ }
- return(STATUS_SUCCESS);
+ return Status;
}
PFILE_RECORD_HEADER FileRecord,
ULONGLONG MFTIndex,
PFILE_DIRECTORY_INFORMATION Info,
- ULONG BufferLength)
+ ULONG BufferLength,
+ PULONG Written,
+ BOOLEAN First)
{
ULONG Length;
+ NTSTATUS Status;
+ ULONG BytesToCopy = 0;
PFILENAME_ATTRIBUTE FileName;
PSTANDARD_INFORMATION StdInfo;
DPRINT("NtfsGetDirectoryInformation() called\n");
+ *Written = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ if (FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName) > BufferLength)
+ {
+ return Status;
+ }
+
FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
if (FileName == NULL)
{
ASSERT(StdInfo != NULL);
Length = FileName->NameLength * sizeof (WCHAR);
- if ((sizeof(FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
- return(STATUS_BUFFER_OVERFLOW);
+ if (First || (BufferLength >= FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName) + Length))
+ {
+ Info->FileNameLength = Length;
- Info->FileNameLength = Length;
- Info->NextEntryOffset =
- ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) + Length, sizeof(ULONG));
- RtlCopyMemory(Info->FileName, FileName->Name, Length);
+ *Written = FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName);
+ Info->NextEntryOffset = 0;
+ if (BufferLength > FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName))
+ {
+ BytesToCopy = min(Length, BufferLength - FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName));
+ RtlCopyMemory(Info->FileName, FileName->Name, BytesToCopy);
+ *Written += BytesToCopy;
+
+ if (BytesToCopy == Length)
+ {
+ Info->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) +
+ BytesToCopy);
+ Status = STATUS_SUCCESS;
+ }
+ }
- Info->CreationTime.QuadPart = FileName->CreationTime;
- Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
- Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
- Info->ChangeTime.QuadPart = FileName->ChangeTime;
+ Info->CreationTime.QuadPart = FileName->CreationTime;
+ Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
+ Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
+ Info->ChangeTime.QuadPart = FileName->ChangeTime;
- /* Convert file flags */
- NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
+ /* Convert file flags */
+ NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
- Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
+ Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
- Info->FileIndex = MFTIndex;
+ Info->FileIndex = MFTIndex;
+ }
- return STATUS_SUCCESS;
+ return Status;
}
PFILE_RECORD_HEADER FileRecord,
ULONGLONG MFTIndex,
PFILE_FULL_DIRECTORY_INFORMATION Info,
- ULONG BufferLength)
+ ULONG BufferLength,
+ PULONG Written,
+ BOOLEAN First)
{
ULONG Length;
+ NTSTATUS Status;
+ ULONG BytesToCopy = 0;
PFILENAME_ATTRIBUTE FileName;
PSTANDARD_INFORMATION StdInfo;
DPRINT("NtfsGetFullDirectoryInformation() called\n");
+ *Written = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ if (FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName) > BufferLength)
+ {
+ return Status;
+ }
+
FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
if (FileName == NULL)
{
ASSERT(StdInfo != NULL);
Length = FileName->NameLength * sizeof (WCHAR);
- if ((sizeof(FILE_FULL_DIRECTORY_INFORMATION) + Length) > BufferLength)
- return(STATUS_BUFFER_OVERFLOW);
+ if (First || (BufferLength >= FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName) + Length))
+ {
+ Info->FileNameLength = Length;
- Info->FileNameLength = Length;
- Info->NextEntryOffset =
- ROUND_UP(sizeof(FILE_FULL_DIRECTORY_INFORMATION) + Length, sizeof(ULONG));
- RtlCopyMemory(Info->FileName, FileName->Name, Length);
+ *Written = FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName);
+ Info->NextEntryOffset = 0;
+ if (BufferLength > FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName))
+ {
+ BytesToCopy = min(Length, BufferLength - FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName));
+ RtlCopyMemory(Info->FileName, FileName->Name, BytesToCopy);
+ *Written += BytesToCopy;
+
+ if (BytesToCopy == Length)
+ {
+ Info->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION) +
+ BytesToCopy);
+ Status = STATUS_SUCCESS;
+ }
+ }
- Info->CreationTime.QuadPart = FileName->CreationTime;
- Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
- Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
- Info->ChangeTime.QuadPart = FileName->ChangeTime;
+ Info->CreationTime.QuadPart = FileName->CreationTime;
+ Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
+ Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
+ Info->ChangeTime.QuadPart = FileName->ChangeTime;
- /* Convert file flags */
- NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
+ /* Convert file flags */
+ NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
- Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
+ Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
- Info->FileIndex = MFTIndex;
- Info->EaSize = 0;
+ Info->FileIndex = MFTIndex;
+ Info->EaSize = 0;
+ }
- return STATUS_SUCCESS;
+ return Status;
}
PFILE_RECORD_HEADER FileRecord,
ULONGLONG MFTIndex,
PFILE_BOTH_DIR_INFORMATION Info,
- ULONG BufferLength)
+ ULONG BufferLength,
+ PULONG Written,
+ BOOLEAN First)
{
ULONG Length;
+ NTSTATUS Status;
+ ULONG BytesToCopy = 0;
PFILENAME_ATTRIBUTE FileName, ShortFileName;
PSTANDARD_INFORMATION StdInfo;
DPRINT("NtfsGetBothDirectoryInformation() called\n");
+ *Written = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ if (FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName) > BufferLength)
+ {
+ return Status;
+ }
+
FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
if (FileName == NULL)
{
ASSERT(StdInfo != NULL);
Length = FileName->NameLength * sizeof (WCHAR);
- if ((sizeof(FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength)
- return(STATUS_BUFFER_OVERFLOW);
+ if (First || (BufferLength >= FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName) + Length))
+ {
+ Info->FileNameLength = Length;
- Info->FileNameLength = Length;
- Info->NextEntryOffset =
- ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, sizeof(ULONG));
- RtlCopyMemory(Info->FileName, FileName->Name, Length);
+ *Written = FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName);
+ Info->NextEntryOffset = 0;
+ if (BufferLength > FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName))
+ {
+ BytesToCopy = min(Length, BufferLength - FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName));
+ RtlCopyMemory(Info->FileName, FileName->Name, BytesToCopy);
+ *Written += BytesToCopy;
- if (ShortFileName)
- {
- /* Should we upcase the filename? */
- ASSERT(ShortFileName->NameLength <= ARRAYSIZE(Info->ShortName));
- Info->ShortNameLength = ShortFileName->NameLength * sizeof(WCHAR);
- RtlCopyMemory(Info->ShortName, ShortFileName->Name, Info->ShortNameLength);
- }
- else
- {
- Info->ShortName[0] = 0;
- Info->ShortNameLength = 0;
- }
+ if (BytesToCopy == Length)
+ {
+ Info->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) +
+ BytesToCopy);
+ Status = STATUS_SUCCESS;
+ }
+ }
+
+ if (ShortFileName)
+ {
+ /* Should we upcase the filename? */
+ ASSERT(ShortFileName->NameLength <= ARRAYSIZE(Info->ShortName));
+ Info->ShortNameLength = ShortFileName->NameLength * sizeof(WCHAR);
+ RtlCopyMemory(Info->ShortName, ShortFileName->Name, Info->ShortNameLength);
+ }
+ else
+ {
+ Info->ShortName[0] = 0;
+ Info->ShortNameLength = 0;
+ }
- Info->CreationTime.QuadPart = FileName->CreationTime;
- Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
- Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
- Info->ChangeTime.QuadPart = FileName->ChangeTime;
+ Info->CreationTime.QuadPart = FileName->CreationTime;
+ Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
+ Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
+ Info->ChangeTime.QuadPart = FileName->ChangeTime;
- /* Convert file flags */
- NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
+ /* Convert file flags */
+ NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
- Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
+ Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
- Info->FileIndex = MFTIndex;
- Info->EaSize = 0;
+ Info->FileIndex = MFTIndex;
+ Info->EaSize = 0;
+ }
- return STATUS_SUCCESS;
+ return Status;
}
PFILE_RECORD_HEADER FileRecord;
ULONGLONG MFTRecord, OldMFTRecord = 0;
UNICODE_STRING Pattern;
+ ULONG Written;
DPRINT1("NtfsQueryDirectory() called\n");
/* Determine directory index */
if (Stack->Flags & SL_INDEX_SPECIFIED)
{
- Ccb->Entry = Ccb->CurrentByteOffset.u.LowPart;
+ Ccb->Entry = FileIndex;
}
else if (First || (Stack->Flags & SL_RESTART_SCAN))
{
return STATUS_PENDING;
}
+ Written = 0;
while (Status == STATUS_SUCCESS && BufferLength > 0)
{
Status = NtfsFindFileAt(DeviceExtension,
&Ccb->Entry,
&FileRecord,
&MFTRecord,
- Fcb->MFTIndex);
+ Fcb->MFTIndex,
+ BooleanFlagOn(Stack->Flags, SL_CASE_SENSITIVE));
if (NT_SUCCESS(Status))
{
{
DPRINT1("Ignoring duplicate MFT entry 0x%x\n", MFTRecord);
Ccb->Entry++;
- ExFreePoolWithTag(FileRecord, TAG_NTFS);
+ ExFreeToNPagedLookasideList(&DeviceExtension->FileRecLookasideList, FileRecord);
continue;
}
OldMFTRecord = MFTRecord;
switch (FileInformationClass)
{
- case FileNameInformation:
- Status = NtfsGetNameInformation(DeviceExtension,
- FileRecord,
- MFTRecord,
- (PFILE_NAMES_INFORMATION)Buffer,
- BufferLength);
+ case FileNamesInformation:
+ Status = NtfsGetNamesInformation(DeviceExtension,
+ FileRecord,
+ MFTRecord,
+ (PFILE_NAMES_INFORMATION)Buffer,
+ BufferLength,
+ &Written,
+ Buffer0 == NULL);
break;
case FileDirectoryInformation:
FileRecord,
MFTRecord,
(PFILE_DIRECTORY_INFORMATION)Buffer,
- BufferLength);
+ BufferLength,
+ &Written,
+ Buffer0 == NULL);
break;
case FileFullDirectoryInformation:
FileRecord,
MFTRecord,
(PFILE_FULL_DIRECTORY_INFORMATION)Buffer,
- BufferLength);
+ BufferLength,
+ &Written,
+ Buffer0 == NULL);
break;
case FileBothDirectoryInformation:
FileRecord,
MFTRecord,
(PFILE_BOTH_DIR_INFORMATION)Buffer,
- BufferLength);
+ BufferLength,
+ &Written,
+ Buffer0 == NULL);
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
}
- if (Status == STATUS_BUFFER_OVERFLOW)
+ if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_INVALID_INFO_CLASS)
{
- if (Buffer0)
- {
- Buffer0->NextEntryOffset = 0;
- }
break;
}
}
else
{
- if (Buffer0)
- {
- Buffer0->NextEntryOffset = 0;
- }
-
- if (First)
- {
- Status = STATUS_NO_SUCH_FILE;
- }
- else
- {
- Status = STATUS_NO_MORE_FILES;
- }
+ Status = (First ? STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES);
break;
}
Buffer0 = (PFILE_NAMES_INFORMATION)Buffer;
Buffer0->FileIndex = FileIndex++;
Ccb->Entry++;
+ BufferLength -= Buffer0->NextEntryOffset;
+
+ ExFreeToNPagedLookasideList(&DeviceExtension->FileRecLookasideList, FileRecord);
if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
{
break;
}
- BufferLength -= Buffer0->NextEntryOffset;
+
Buffer += Buffer0->NextEntryOffset;
- ExFreePoolWithTag(FileRecord, TAG_NTFS);
}
if (Buffer0)
{
Buffer0->NextEntryOffset = 0;
+ Status = STATUS_SUCCESS;
+ IrpContext->Irp->IoStatus.Information = Stack->Parameters.QueryDirectory.Length - BufferLength;
+ }
+ else
+ {
+ ASSERT(Status != STATUS_SUCCESS || BufferLength == 0);
+ ASSERT(Written <= Stack->Parameters.QueryDirectory.Length);
+ IrpContext->Irp->IoStatus.Information = Written;
}
ExReleaseResourceLite(&DeviceExtension->DirResource);
ExReleaseResourceLite(&Fcb->MainResource);
- if (FileIndex > 0)
- {
- Status = STATUS_SUCCESS;
- }
-
return Status;
}