/* 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
- */
+/**
+* @name NtfsAddFilenameToDirectory
+* @implemented
+*
+* Adds a $FILE_NAME attribute to a given directory index.
+*
+* @param DeviceExt
+* Points to the target disk's DEVICE_EXTENSION.
+*
+* @param DirectoryMftIndex
+* Mft index of the parent directory which will receive the file.
+*
+* @param FileReferenceNumber
+* File reference of the file to be added to the directory. This is a combination of the
+* Mft index and sequence number.
+*
+* @param FilenameAttribute
+* Pointer to the FILENAME_ATTRIBUTE of the file being added to the directory.
+*
+* @return
+* STATUS_SUCCESS on success.
+* STATUS_INSUFFICIENT_RESOURCES if an allocation fails.
+* STATUS_NOT_IMPLEMENTED if target address isn't at the end of the given file record.
+*
+* @remarks
+* WIP - Can only support an empty directory.
+* One FILENAME_ATTRIBUTE is added to the directory's index for each link to that file. So, each
+* file which contains one FILENAME_ATTRIBUTE for a long name and another for the 8.3 name, will
+* get both attributes added to its parent directory.
+*/
+NTSTATUS
+NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
+ ULONGLONG DirectoryMftIndex,
+ ULONGLONG FileReferenceNumber,
+ PFILENAME_ATTRIBUTE FilenameAttribute)
{
- PDIR_RECORD Record;
- NTSTATUS Status;
- ULONG Index = 0;
- ULONG Offset = 0;
- ULONG BlockOffset = 0;
-
- Record = (PDIR_RECORD)*Block;
- while(Index < *pIndex)
+ NTSTATUS Status = STATUS_SUCCESS;
+ PFILE_RECORD_HEADER ParentFileRecord;
+ PNTFS_ATTR_CONTEXT IndexRootContext;
+ PINDEX_ROOT_ATTRIBUTE I30IndexRoot;
+ ULONG IndexRootOffset;
+ ULONGLONG I30IndexRootLength;
+ PINDEX_ENTRY_ATTRIBUTE IndexNodeEntry;
+ ULONG LengthWritten;
+ PNTFS_ATTR_RECORD DestinationAttribute;
+ PINDEX_ROOT_ATTRIBUTE NewIndexRoot;
+ ULONG AttributeLength;
+ PNTFS_ATTR_RECORD NextAttribute;
+
+ // Allocate memory for the parent directory
+ ParentFileRecord = ExAllocatePoolWithTag(NonPagedPool,
+ DeviceExt->NtfsInfo.BytesPerFileRecord,
+ TAG_NTFS);
+ if (!ParentFileRecord)
{
- 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++;
+ DPRINT1("ERROR: Couldn't allocate memory for file record!\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- DPRINT("Index %lu RecordLength %lu Offset %lu\n",
- Index, Record->RecordLength, Offset);
+ // Open the parent directory
+ Status = ReadFileRecord(DeviceExt, DirectoryMftIndex, ParentFileRecord);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+ DPRINT1("ERROR: Couldn't read parent directory with index %I64u\n",
+ DirectoryMftIndex);
+ return Status;
+ }
- if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
+ DPRINT1("Dumping old parent file record:\n");
+ NtfsDumpFileRecord(DeviceExt, ParentFileRecord);
+
+ // Find the index root attribute for the directory
+ Status = FindAttribute(DeviceExt,
+ ParentFileRecord,
+ AttributeIndexRoot,
+ L"$I30",
+ 4,
+ &IndexRootContext,
+ &IndexRootOffset);
+ if (!NT_SUCCESS(Status))
{
- wcscpy(Name, L".");
+ DPRINT1("ERROR: Couldn't find $I30 $INDEX_ROOT attribute for parent directory with MFT #: %I64u!\n",
+ DirectoryMftIndex);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+ return Status;
}
- else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
+
+ I30IndexRootLength = AttributeDataLength(&IndexRootContext->Record);
+
+ // Allocate memory for the index root data
+ I30IndexRoot = (PINDEX_ROOT_ATTRIBUTE)ExAllocatePoolWithTag(NonPagedPool, I30IndexRootLength, TAG_NTFS);
+ if (!I30IndexRoot)
{
- wcscpy(Name, L"..");
+ DPRINT1("ERROR: Couldn't allocate memory for index root attribute!\n");
+ ReleaseAttributeContext(IndexRootContext);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
}
- else
+
+ // Read the Index Root
+ Status = ReadAttribute(DeviceExt, IndexRootContext, 0, (PCHAR)I30IndexRoot, I30IndexRootLength);
+ 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);
- }
+ DPRINT1("ERROR: Couln't read index root attribute for Mft index #%I64u\n", DirectoryMftIndex);
+ ReleaseAttributeContext(IndexRootContext);
+ ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+ return Status;
}
- DPRINT("Name '%S'\n", Name);
+ // Make sure it's empty (temporarily)
+ IndexNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)I30IndexRoot + I30IndexRoot->Header.FirstEntryOffset + 0x10);
+ if (IndexNodeEntry->Data.Directory.IndexedFile != 0 || IndexNodeEntry->Flags != 2)
+ {
+ DPRINT1("FIXME: File-creation is only supported in empty directories right now! Be patient! :)\n");
+ ReleaseAttributeContext(IndexRootContext);
+ ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ // Now we need to setup a new index root attribute to replace the old one
+ NewIndexRoot = ExAllocatePoolWithTag(NonPagedPool, DeviceExt->NtfsInfo.BytesPerIndexRecord, TAG_NTFS);
+ if (!NewIndexRoot)
+ {
+ DPRINT1("ERROR: Unable to allocate memory for new index root attribute!\n");
+ ReleaseAttributeContext(IndexRootContext);
+ ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ // Setup the new index record
+ RtlZeroMemory(NewIndexRoot, DeviceExt->NtfsInfo.BytesPerIndexRecord); // shouldn't be necessary but aids in debugging
+
+ NewIndexRoot->AttributeType = AttributeFileName;
+ NewIndexRoot->CollationRule = COLLATION_FILE_NAME;
+ NewIndexRoot->SizeOfEntry = DeviceExt->NtfsInfo.BytesPerIndexRecord;
+ // If Bytes per index record is less than cluster size, clusters per index record becomes sectors per index
+ if(NewIndexRoot->SizeOfEntry < DeviceExt->NtfsInfo.BytesPerCluster)
+ NewIndexRoot->ClustersPerIndexRecord = NewIndexRoot->SizeOfEntry / DeviceExt->NtfsInfo.BytesPerSector;
+ else
+ NewIndexRoot->ClustersPerIndexRecord = NewIndexRoot->SizeOfEntry / DeviceExt->NtfsInfo.BytesPerCluster;
+
+ // Setup the Index node header
+ NewIndexRoot->Header.FirstEntryOffset = 0x10;
+ NewIndexRoot->Header.Flags = INDEX_ROOT_SMALL;
+ // still need to calculate sizes
+
+ // The first index node entry will be for the filename we're adding
+ IndexNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)NewIndexRoot + NewIndexRoot->Header.FirstEntryOffset + 0x10);
+ IndexNodeEntry->Data.Directory.IndexedFile = FileReferenceNumber;
+ IndexNodeEntry->Flags = INDEX_ROOT_SMALL;
+ IndexNodeEntry->KeyLength = FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + (2 * FilenameAttribute->NameLength);
+ IndexNodeEntry->Length = ALIGN_UP_BY(IndexNodeEntry->KeyLength, 8) + FIELD_OFFSET(INDEX_ENTRY_ATTRIBUTE, FileName);
+
+ // Now we can calculate the Node length (temp logic)
+ NewIndexRoot->Header.TotalSizeOfEntries = NewIndexRoot->Header.FirstEntryOffset + IndexNodeEntry->Length + 0x10;
+ NewIndexRoot->Header.AllocatedSize = NewIndexRoot->Header.TotalSizeOfEntries;
+
+ DPRINT1("New Index Node Entry Stream Length: %u\nNew Inde Node Entry Length: %u\n",
+ IndexNodeEntry->KeyLength,
+ IndexNodeEntry->Length);
+
+ // copy over the attribute proper
+ RtlCopyMemory(&IndexNodeEntry->FileName, FilenameAttribute, IndexNodeEntry->KeyLength);
+
+ // Now setup the dummy key
+ IndexNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexNodeEntry + IndexNodeEntry->Length);
+
+ IndexNodeEntry->Data.Directory.IndexedFile = 0;
+ IndexNodeEntry->Length = 0x10;
+ IndexNodeEntry->KeyLength = 0;
+ IndexNodeEntry->Flags = NTFS_INDEX_ENTRY_END;
+
+ // This is when we'd normally setup the length (already done above)
+
+ // Write back the new index root attribute to the parent directory file record
+
+ // First, we need to make sure the attribute is large enough.
+ // We can't set the size as we normally would, because if we extend past the file record,
+ // we must create an index allocation and index bitmap (TODO). Also TODO: support file records with
+ // $ATTRIBUTE_LIST's.
+ AttributeLength = NewIndexRoot->Header.AllocatedSize + FIELD_OFFSET(INDEX_ROOT_ATTRIBUTE, Header);
+ DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)ParentFileRecord + IndexRootOffset);
+
+ NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)DestinationAttribute + DestinationAttribute->Length);
+ if (NextAttribute->Type != AttributeEnd)
+ {
+ DPRINT1("FIXME: For now, only resizing index root at the end of a file record is supported!\n");
+ ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
+ ReleaseAttributeContext(IndexRootContext);
+ ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ // Update the length of the attribute in the file record of the parent directory
+ InternalSetResidentAttributeLength(IndexRootContext,
+ ParentFileRecord,
+ IndexRootOffset,
+ AttributeLength);
+
+ Status = UpdateFileRecord(DeviceExt, DirectoryMftIndex, ParentFileRecord);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ERROR: Failed to update file record of directory with index: %llx\n", DirectoryMftIndex);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+ ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
+ ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
+ return Status;
+ }
- *Ptr = Record;
+ // Update the parent directory with the new index root
+ Status = WriteAttribute(DeviceExt,
+ IndexRootContext,
+ 0,
+ (PUCHAR)NewIndexRoot,
+ AttributeLength,
+ &LengthWritten);
+ if (!NT_SUCCESS(Status) )
+ {
+ DPRINT1("ERROR: Unable to write new index root attribute to parent directory!\n");
+ ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
+ ReleaseAttributeContext(IndexRootContext);
+ ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+ return Status;
+ }
+
+ // re-read the parent file record, so we can dump it
+ Status = ReadFileRecord(DeviceExt, DirectoryMftIndex, ParentFileRecord);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ERROR: Couldn't read parent directory after messing with it!\n");
+ }
+ else
+ {
+ DPRINT1("Dumping new parent file record:\n");
+ NtfsDumpFileRecord(DeviceExt, ParentFileRecord);
+ }
- *pIndex = Index;
+ // Cleanup
+ ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
+ ReleaseAttributeContext(IndexRootContext);
+ ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
+ ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
- return(STATUS_SUCCESS);
+ return Status;
+}
+
+ULONGLONG
+NtfsGetFileSize(PDEVICE_EXTENSION DeviceExt,
+ PFILE_RECORD_HEADER FileRecord,
+ PCWSTR Stream,
+ ULONG StreamLength,
+ PULONGLONG AllocatedSize)
+{
+ ULONGLONG Size = 0ULL;
+ ULONGLONG Allocated = 0ULL;
+ NTSTATUS Status;
+ PNTFS_ATTR_CONTEXT DataContext;
+
+ Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Stream, StreamLength, &DataContext, NULL);
+ if (NT_SUCCESS(Status))
+ {
+ Size = AttributeDataLength(&DataContext->Record);
+ Allocated = AttributeAllocatedLength(&DataContext->Record);
+ ReleaseAttributeContext(DataContext);
+ }
+
+ if (AllocatedSize != NULL) *AllocatedSize = Allocated;
+
+ return Size;
}
-#endif
static NTSTATUS
NtfsGetNameInformation(PDEVICE_EXTENSION DeviceExt,
PFILE_RECORD_HEADER FileRecord,
- PNTFS_ATTR_CONTEXT DataContext,
+ ULONGLONG MFTIndex,
PFILE_NAMES_INFORMATION Info,
ULONG BufferLength)
{
DPRINT("NtfsGetNameInformation() called\n");
- 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)
static NTSTATUS
NtfsGetDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
PFILE_RECORD_HEADER FileRecord,
- PNTFS_ATTR_CONTEXT DataContext,
+ ULONGLONG MFTIndex,
PFILE_DIRECTORY_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
PFILENAME_ATTRIBUTE FileName;
+ PSTANDARD_INFORMATION StdInfo;
DPRINT("NtfsGetDirectoryInformation() called\n");
- 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);
+
+ StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord);
+ ASSERT(StdInfo != NULL);
Length = FileName->NameLength * sizeof (WCHAR);
if ((sizeof(FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
Info->ChangeTime.QuadPart = FileName->ChangeTime;
/* Convert file flags */
- NtfsFileFlagsToAttributes(FileName->FileAttributes, &Info->FileAttributes);
+ 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;
}
static NTSTATUS
NtfsGetFullDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
PFILE_RECORD_HEADER FileRecord,
- PNTFS_ATTR_CONTEXT DataContext,
+ ULONGLONG MFTIndex,
PFILE_FULL_DIRECTORY_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
PFILENAME_ATTRIBUTE FileName;
+ PSTANDARD_INFORMATION StdInfo;
DPRINT("NtfsGetFullDirectoryInformation() called\n");
- 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);
+
+ StdInfo = GetStandardInformationFromRecord(DeviceExt, FileRecord);
+ ASSERT(StdInfo != NULL);
Length = FileName->NameLength * sizeof (WCHAR);
if ((sizeof(FILE_FULL_DIRECTORY_INFORMATION) + Length) > BufferLength)
Info->ChangeTime.QuadPart = FileName->ChangeTime;
/* Convert file flags */
- NtfsFileFlagsToAttributes(FileName->FileAttributes, &Info->FileAttributes);
+ 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;
Info->EaSize = 0;
return STATUS_SUCCESS;
static NTSTATUS
NtfsGetBothDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
PFILE_RECORD_HEADER FileRecord,
- PNTFS_ATTR_CONTEXT DataContext,
+ ULONGLONG MFTIndex,
PFILE_BOTH_DIR_INFORMATION Info,
ULONG BufferLength)
{
ULONG Length;
PFILENAME_ATTRIBUTE FileName, ShortFileName;
+ PSTANDARD_INFORMATION StdInfo;
DPRINT("NtfsGetBothDirectoryInformation() called\n");
- 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);
- 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)
Info->ChangeTime.QuadPart = FileName->ChangeTime;
/* Convert file flags */
- NtfsFileFlagsToAttributes(FileName->FileAttributes, &Info->FileAttributes);
+ 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;
Info->EaSize = 0;
return STATUS_SUCCESS;
PFILE_OBJECT FileObject;
NTSTATUS Status = STATUS_SUCCESS;
PFILE_RECORD_HEADER FileRecord;
- PNTFS_ATTR_CONTEXT DataContext;
ULONGLONG MFTRecord, OldMFTRecord = 0;
UNICODE_STRING Pattern;
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;
}
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;
+ }
+
while (Status == STATUS_SUCCESS && BufferLength > 0)
{
Status = NtfsFindFileAt(DeviceExtension,
&Pattern,
&Ccb->Entry,
&FileRecord,
- &DataContext,
&MFTRecord,
- Fcb->MFTIndex);
+ Fcb->MFTIndex,
+ (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);
continue;
case FileNameInformation:
Status = NtfsGetNameInformation(DeviceExtension,
FileRecord,
- DataContext,
+ MFTRecord,
(PFILE_NAMES_INFORMATION)Buffer,
BufferLength);
break;
case FileDirectoryInformation:
Status = NtfsGetDirectoryInformation(DeviceExtension,
FileRecord,
- DataContext,
+ MFTRecord,
(PFILE_DIRECTORY_INFORMATION)Buffer,
BufferLength);
break;
case FileFullDirectoryInformation:
Status = NtfsGetFullDirectoryInformation(DeviceExtension,
FileRecord,
- DataContext,
+ MFTRecord,
(PFILE_FULL_DIRECTORY_INFORMATION)Buffer,
BufferLength);
break;
case FileBothDirectoryInformation:
Status = NtfsGetBothDirectoryInformation(DeviceExtension,
FileRecord,
- DataContext,
+ MFTRecord,
(PFILE_BOTH_DIR_INFORMATION)Buffer,
BufferLength);
break;
Buffer0->NextEntryOffset = 0;
}
+ ExReleaseResourceLite(&DeviceExtension->DirResource);
+ ExReleaseResourceLite(&Fcb->MainResource);
+
if (FileIndex > 0)
{
Status = STATUS_SUCCESS;
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;
}