/* FUNCTIONS ****************************************************************/
-#if 0
-static NTSTATUS
-CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt,
- PVOID *Context,
- PVOID *Block,
- PLARGE_INTEGER StreamOffset,
- ULONG DirLength,
- PVOID *Ptr,
- PWSTR Name,
- PULONG pIndex,
- PULONG pIndex2)
-/*
- * FUNCTION: Retrieves the file name, be it in short or long file name format
- */
+ULONGLONG
+NtfsGetFileSize(PDEVICE_EXTENSION DeviceExt,
+ PFILE_RECORD_HEADER FileRecord,
+ PCWSTR Stream,
+ ULONG StreamLength,
+ PULONGLONG AllocatedSize)
{
- PDIR_RECORD Record;
- NTSTATUS Status;
- ULONG Index = 0;
- ULONG Offset = 0;
- ULONG BlockOffset = 0;
-
- Record = (PDIR_RECORD)*Block;
- while(Index < *pIndex)
- {
- BlockOffset += Record->RecordLength;
- Offset += Record->RecordLength;
-
- Record = (PDIR_RECORD)(*Block + BlockOffset);
- if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0)
- {
- DPRINT("Map next sector\n");
- CcUnpinData(*Context);
- StreamOffset->QuadPart += BLOCKSIZE;
- Offset = ROUND_UP(Offset, BLOCKSIZE);
- BlockOffset = 0;
-
- if (!CcMapData(DeviceExt->StreamFileObject,
- StreamOffset,
- BLOCKSIZE, TRUE,
- Context, Block))
- {
- DPRINT("CcMapData() failed\n");
- return(STATUS_UNSUCCESSFUL);
- }
- Record = (PDIR_RECORD)(*Block + BlockOffset);
- }
-
- if (Offset >= DirLength)
- return(STATUS_NO_MORE_ENTRIES);
-
- Index++;
- }
-
- DPRINT("Index %lu RecordLength %lu Offset %lu\n",
- Index, Record->RecordLength, Offset);
+ ULONGLONG Size = 0ULL;
+ ULONGLONG Allocated = 0ULL;
+ NTSTATUS Status;
+ PNTFS_ATTR_CONTEXT DataContext;
- if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
- {
- wcscpy(Name, L".");
- }
- else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
- {
- wcscpy(Name, L"..");
- }
- else
+ Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Stream, StreamLength, &DataContext, NULL);
+ if (NT_SUCCESS(Status))
{
- if (DeviceExt->CdInfo.JolietLevel == 0)
- {
- ULONG i;
-
- for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
- Name[i] = (WCHAR)Record->FileId[i];
- Name[i] = 0;
- }
- else
- {
- CdfsSwapString(Name, Record->FileId, Record->FileIdLength);
- }
+ Size = AttributeDataLength(DataContext->pRecord);
+ Allocated = AttributeAllocatedLength(DataContext->pRecord);
+ ReleaseAttributeContext(DataContext);
}
- DPRINT("Name '%S'\n", Name);
+ if (AllocatedSize != NULL) *AllocatedSize = Allocated;
- *Ptr = Record;
+ return Size;
+}
- *pIndex = Index;
- return(STATUS_SUCCESS);
-}
-#endif
+#define ULONG_ROUND_UP(x) ROUND_UP((x), (sizeof(ULONG)))
static NTSTATUS
-NtfsGetNameInformation(PDEVICE_EXTENSION DeviceExt,
- PFILE_RECORD_HEADER FileRecord,
- PNTFS_ATTR_CONTEXT DataContext,
- 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 = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_POSIX);
+ FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
if (FileName == NULL)
{
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
- if (FileName == NULL)
- {
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
- }
+ DPRINT1("No name information for file ID: %#I64x\n", MFTIndex);
+ NtfsDumpFileAttributes(DeviceExt, FileRecord);
+ return STATUS_OBJECT_NAME_NOT_FOUND;
}
- ASSERT(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;
- Info->FileNameLength = Length;
- Info->NextEntryOffset =
- ROUND_UP(sizeof(FILE_NAMES_INFORMATION) + Length, sizeof(ULONG));
- RtlCopyMemory(Info->FileName, FileName->Name, 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;
- return(STATUS_SUCCESS);
+ if (BytesToCopy == Length)
+ {
+ Info->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_NAMES_INFORMATION) +
+ BytesToCopy);
+ Status = STATUS_SUCCESS;
+ }
+ }
+ }
+
+ return Status;
}
static NTSTATUS
NtfsGetDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
PFILE_RECORD_HEADER FileRecord,
- PNTFS_ATTR_CONTEXT DataContext,
+ 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");
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_POSIX);
+ *Written = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ if (FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName) > BufferLength)
+ {
+ return Status;
+ }
+
+ FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
if (FileName == NULL)
{
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
- if (FileName == NULL)
- {
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
- }
+ DPRINT1("No name information for file ID: %#I64x\n", MFTIndex);
+ NtfsDumpFileAttributes(DeviceExt, FileRecord);
+ return STATUS_OBJECT_NAME_NOT_FOUND;
}
- ASSERT(FileName != NULL);
+
+ StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord);
+ 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;
+
+ *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;
- Info->FileNameLength = Length;
- Info->NextEntryOffset =
- ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) + Length, sizeof(ULONG));
- RtlCopyMemory(Info->FileName, FileName->Name, Length);
+ 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, &Info->FileAttributes);
+ /* Convert file flags */
+ NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
- Info->EndOfFile.QuadPart = FileName->AllocatedSize;
- Info->AllocationSize.QuadPart = ROUND_UP(FileName->AllocatedSize, DeviceExt->NtfsInfo.BytesPerCluster);
+ Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
-// Info->FileIndex=;
+ Info->FileIndex = MFTIndex;
+ }
- return STATUS_SUCCESS;
+ return Status;
}
static NTSTATUS
NtfsGetFullDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
PFILE_RECORD_HEADER FileRecord,
- PNTFS_ATTR_CONTEXT DataContext,
+ 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");
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_POSIX);
+ *Written = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ if (FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName) > BufferLength)
+ {
+ return Status;
+ }
+
+ FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
if (FileName == NULL)
{
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
- if (FileName == NULL)
- {
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
- }
+ DPRINT1("No name information for file ID: %#I64x\n", MFTIndex);
+ NtfsDumpFileAttributes(DeviceExt, FileRecord);
+ return STATUS_OBJECT_NAME_NOT_FOUND;
}
- ASSERT(FileName != NULL);
+
+ StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord);
+ 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, &Info->FileAttributes);
+ /* Convert file flags */
+ NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
- Info->EndOfFile.QuadPart = FileName->AllocatedSize;
- Info->AllocationSize.QuadPart = ROUND_UP(FileName->AllocatedSize, DeviceExt->NtfsInfo.BytesPerCluster);
+ Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
-// Info->FileIndex=;
- Info->EaSize = 0;
+ Info->FileIndex = MFTIndex;
+ Info->EaSize = 0;
+ }
- return STATUS_SUCCESS;
+ return Status;
}
static NTSTATUS
NtfsGetBothDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
PFILE_RECORD_HEADER FileRecord,
- PNTFS_ATTR_CONTEXT DataContext,
+ 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");
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_POSIX);
+ *Written = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ if (FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName) > BufferLength)
+ {
+ return Status;
+ }
+
+ FileName = GetBestFileNameFromRecord(DeviceExt, FileRecord);
if (FileName == NULL)
{
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_WIN32);
- if (FileName == NULL)
- {
- FileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
- }
+ DPRINT1("No name information for file ID: %#I64x\n", MFTIndex);
+ NtfsDumpFileAttributes(DeviceExt, FileRecord);
+ return STATUS_OBJECT_NAME_NOT_FOUND;
}
- ASSERT(FileName != NULL);
- ShortFileName = GetFileNameFromRecord(FileRecord, NTFS_FILE_NAME_DOS);
+ ShortFileName = GetFileNameFromRecord(DeviceExt, FileRecord, NTFS_FILE_NAME_DOS);
+
+ StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord);
+ 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;
+
+ *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;
- Info->FileNameLength = Length;
- Info->NextEntryOffset =
- ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, sizeof(ULONG));
- RtlCopyMemory(Info->FileName, FileName->Name, Length);
+ 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;
- }
+ 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, &Info->FileAttributes);
+ /* Convert file flags */
+ NtfsFileFlagsToAttributes(FileName->FileAttributes | StdInfo->FileAttribute, &Info->FileAttributes);
- Info->EndOfFile.QuadPart = FileName->AllocatedSize;
- Info->AllocationSize.QuadPart = ROUND_UP(FileName->AllocatedSize, DeviceExt->NtfsInfo.BytesPerCluster);
+ Info->EndOfFile.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, (PULONGLONG)&Info->AllocationSize.QuadPart);
-// Info->FileIndex=;
- Info->EaSize = 0;
+ Info->FileIndex = MFTIndex;
+ Info->EaSize = 0;
+ }
- return STATUS_SUCCESS;
+ return Status;
}
PFILE_OBJECT FileObject;
NTSTATUS Status = STATUS_SUCCESS;
PFILE_RECORD_HEADER FileRecord;
- PNTFS_ATTR_CONTEXT DataContext;
ULONGLONG MFTRecord, OldMFTRecord = 0;
UNICODE_STRING Pattern;
+ ULONG Written;
DPRINT1("NtfsQueryDirectory() called\n");
FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass;
FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
+ if (NtfsFCBIsCompressed(Fcb))
+ {
+ DPRINT1("Compressed directory!\n");
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ if (!ExAcquireResourceSharedLite(&Fcb->MainResource,
+ BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
+ {
+ return STATUS_PENDING;
+ }
+
if (SearchPattern != NULL)
{
if (!Ccb->DirectorySearchPattern)
ExAllocatePoolWithTag(NonPagedPool, Pattern.MaximumLength, TAG_NTFS);
if (!Ccb->DirectorySearchPattern)
{
+ ExReleaseResourceLite(&Fcb->MainResource);
return STATUS_INSUFFICIENT_RESOURCES;
}
- Status = RtlUpcaseUnicodeString(&Pattern, SearchPattern, FALSE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("RtlUpcaseUnicodeString('%wZ') failed with status 0x%08lx\n", &Pattern, Status);
- ExFreePoolWithTag(Ccb->DirectorySearchPattern, TAG_NTFS);
- Ccb->DirectorySearchPattern = NULL;
- return Status;
- }
+ memcpy(Ccb->DirectorySearchPattern, SearchPattern->Buffer, SearchPattern->Length);
Ccb->DirectorySearchPattern[SearchPattern->Length / sizeof(WCHAR)] = 0;
}
}
Ccb->DirectorySearchPattern = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), TAG_NTFS);
if (!Ccb->DirectorySearchPattern)
{
+ ExReleaseResourceLite(&Fcb->MainResource);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* 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))
{
Ccb->Entry = 0;
}
- /* Determine Buffer for result */
- if (Irp->MdlAddress)
- {
- Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
- }
- else
- {
- Buffer = Irp->UserBuffer;
- }
+ /* Get Buffer for result */
+ Buffer = NtfsGetUserBuffer(Irp, FALSE);
DPRINT("Buffer=%p tofind=%S\n", Buffer, Ccb->DirectorySearchPattern);
+ if (!ExAcquireResourceExclusiveLite(&DeviceExtension->DirResource,
+ BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
+ {
+ ExReleaseResourceLite(&Fcb->MainResource);
+ return STATUS_PENDING;
+ }
+
+ Written = 0;
while (Status == STATUS_SUCCESS && BufferLength > 0)
{
Status = NtfsFindFileAt(DeviceExtension,
&Pattern,
&Ccb->Entry,
&FileRecord,
- &DataContext,
&MFTRecord,
- Fcb->MFTIndex);
+ Fcb->MFTIndex,
+ BooleanFlagOn(Stack->Flags, SL_CASE_SENSITIVE));
if (NT_SUCCESS(Status))
{
*/
if (MFTRecord == OldMFTRecord)
{
- DPRINT("Ignoring duplicate MFT entry 0x%x\n", MFTRecord);
+ 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,
- DataContext,
- (PFILE_NAMES_INFORMATION)Buffer,
- BufferLength);
+ case FileNamesInformation:
+ Status = NtfsGetNamesInformation(DeviceExtension,
+ FileRecord,
+ MFTRecord,
+ (PFILE_NAMES_INFORMATION)Buffer,
+ BufferLength,
+ &Written,
+ Buffer0 == NULL);
break;
case FileDirectoryInformation:
Status = NtfsGetDirectoryInformation(DeviceExtension,
FileRecord,
- DataContext,
+ MFTRecord,
(PFILE_DIRECTORY_INFORMATION)Buffer,
- BufferLength);
+ BufferLength,
+ &Written,
+ Buffer0 == NULL);
break;
case FileFullDirectoryInformation:
Status = NtfsGetFullDirectoryInformation(DeviceExtension,
FileRecord,
- DataContext,
+ MFTRecord,
(PFILE_FULL_DIRECTORY_INFORMATION)Buffer,
- BufferLength);
+ BufferLength,
+ &Written,
+ Buffer0 == NULL);
break;
case FileBothDirectoryInformation:
Status = NtfsGetBothDirectoryInformation(DeviceExtension,
FileRecord,
- DataContext,
+ 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;
}
-
- if (FileIndex > 0)
+ else
{
- Status = STATUS_SUCCESS;
+ ASSERT(Status != STATUS_SUCCESS || BufferLength == 0);
+ ASSERT(Written <= Stack->Parameters.QueryDirectory.Length);
+ IrpContext->Irp->IoStatus.Information = Written;
}
+ ExReleaseResourceLite(&DeviceExtension->DirResource);
+ ExReleaseResourceLite(&Fcb->MainResource);
+
return Status;
}
NTSTATUS
-NTAPI
-NtfsFsdDirectoryControl(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+NtfsDirectoryControl(PNTFS_IRP_CONTEXT IrpContext)
{
- PNTFS_IRP_CONTEXT IrpContext = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
DPRINT1("NtfsDirectoryControl() called\n");
- FsRtlEnterFileSystem();
- ASSERT(DeviceObject);
- ASSERT(Irp);
-
- NtfsIsIrpTopLevel(Irp);
-
- IrpContext = NtfsAllocateIrpContext(DeviceObject, Irp);
- if (IrpContext)
+ switch (IrpContext->MinorFunction)
{
- switch (IrpContext->MinorFunction)
- {
- case IRP_MN_QUERY_DIRECTORY:
- Status = NtfsQueryDirectory(IrpContext);
- break;
+ case IRP_MN_QUERY_DIRECTORY:
+ Status = NtfsQueryDirectory(IrpContext);
+ break;
- case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
- DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+ case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
+ DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
- default:
- Status = STATUS_INVALID_DEVICE_REQUEST;
- break;
- }
+ default:
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
}
- else
- Status = STATUS_INSUFFICIENT_RESOURCES;
- Irp->IoStatus.Status = Status;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ if (Status == STATUS_PENDING && IrpContext->Flags & IRPCONTEXT_COMPLETE)
+ {
+ return NtfsMarkIrpContextForQueue(IrpContext);
+ }
- if (IrpContext)
- ExFreePoolWithTag(IrpContext, 'PRIN');
+ IrpContext->Irp->IoStatus.Information = 0;
- IoSetTopLevelIrp(NULL);
- FsRtlExitFileSystem();
return Status;
}