From 4a632280f0e52304d3efdbba7cd5240d9fe0c531 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sun, 31 May 2015 21:28:52 +0000 Subject: [PATCH] [NTFS] Directly implement NtfsOpenFileById() for special files from the MFT where we cannot moonwalk there path. It concerns any file with ID < 0x10. This function can only cope with file which ID is < 0xc. Windows Internals reports that 0xc - 0xf entries are unused. It would be interesting to double check returrned status in case of error, and also what Windows returns when attempting weird opening of suchs entries (overwrite, create for unused, etc). svn path=/trunk/; revision=67983 --- reactos/drivers/filesystems/ntfs/create.c | 110 +++++++++++++++++++--- reactos/drivers/filesystems/ntfs/ntfs.h | 8 ++ 2 files changed, 106 insertions(+), 12 deletions(-) diff --git a/reactos/drivers/filesystems/ntfs/create.c b/reactos/drivers/filesystems/ntfs/create.c index a71c5072796..4d2c9fc4af0 100644 --- a/reactos/drivers/filesystems/ntfs/create.c +++ b/reactos/drivers/filesystems/ntfs/create.c @@ -31,6 +31,21 @@ #define NDEBUG #include +static PCWSTR MftIdToName[] = { + L"$MFT", + L"$MFTMirr", + L"$LogFile", + L"$Volume", + L"AttrDef", + L".", + L"$Bitmap", + L"$Boot", + L"$BadClus", + L"$Quota", + L"$UpCase", + L"$Extended", +}; + /* FUNCTIONS ****************************************************************/ static @@ -157,6 +172,72 @@ NtfsMoonWalkID(PDEVICE_EXTENSION DeviceExt, return Status; } +static +NTSTATUS +NtfsOpenFileById(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + ULONGLONG MftId, + PNTFS_FCB * FoundFCB) +{ + NTSTATUS Status; + PNTFS_FCB FCB; + PFILE_RECORD_HEADER MftRecord; + + DPRINT1("NtfsOpenFileById(%p, %p, %I64x, %p)\n", DeviceExt, FileObject, MftId, FoundFCB); + + ASSERT(MftId < 0x10); + if (MftId > 0xb) /* No entries are used yet beyond this */ + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + MftRecord = ExAllocatePoolWithTag(NonPagedPool, + DeviceExt->NtfsInfo.BytesPerFileRecord, + TAG_NTFS); + if (MftRecord == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = ReadFileRecord(DeviceExt, MftId, MftRecord); + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(MftRecord, TAG_NTFS); + return Status; + } + + if (!(MftRecord->Flags & FRH_IN_USE)) + { + ExFreePoolWithTag(MftRecord, TAG_NTFS); + return STATUS_OBJECT_PATH_NOT_FOUND; + } + + FCB = NtfsGrabFCBFromTable(DeviceExt, MftIdToName[MftId]); + if (FCB == NULL) + { + UNICODE_STRING Name; + + RtlInitUnicodeString(&Name, MftIdToName[MftId]); + Status = NtfsMakeFCBFromDirEntry(DeviceExt, NULL, &Name, MftRecord, MftId, &FCB); + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(MftRecord, TAG_NTFS); + return Status; + } + } + + ASSERT(FCB != NULL); + + ExFreePoolWithTag(MftRecord, TAG_NTFS); + + Status = NtfsAttachFCBToFileObject(DeviceExt, + FCB, + FileObject); + *FoundFCB = FCB; + + return Status; +} + /* * FUNCTION: Opens a file */ @@ -249,7 +330,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject; ULONG RequestedDisposition; ULONG RequestedOptions; - PNTFS_FCB Fcb; + PNTFS_FCB Fcb = NULL; // PWSTR FileName; NTSTATUS Status; UNICODE_STRING FullPath; @@ -287,13 +368,15 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject, return STATUS_INVALID_PARAMETER; MFTId = (*(PULONGLONG)FileObject->FileName.Buffer) & NTFS_MFT_MASK; - if (MFTId < 0xf) + if (MFTId < 0x10) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + Status = NtfsOpenFileById(DeviceExt, FileObject, MFTId, &Fcb); + } + else + { + Status = NtfsMoonWalkID(DeviceExt, MFTId, &FullPath); } - Status = NtfsMoonWalkID(DeviceExt, MFTId, &FullPath); if (!NT_SUCCESS(Status)) { return Status; @@ -324,14 +407,17 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject, return STATUS_SUCCESS; } - Status = NtfsOpenFile(DeviceExt, - FileObject, - ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer), - &Fcb); - - if (RequestedOptions & FILE_OPEN_BY_FILE_ID) + if (Fcb == NULL) { - ExFreePoolWithTag(FullPath.Buffer, TAG_NTFS); + Status = NtfsOpenFile(DeviceExt, + FileObject, + ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer), + &Fcb); + + if (RequestedOptions & FILE_OPEN_BY_FILE_ID) + { + ExFreePoolWithTag(FullPath.Buffer, TAG_NTFS); + } } if (NT_SUCCESS(Status)) diff --git a/reactos/drivers/filesystems/ntfs/ntfs.h b/reactos/drivers/filesystems/ntfs/ntfs.h index a18fbdc89e2..1da9e07abf9 100644 --- a/reactos/drivers/filesystems/ntfs/ntfs.h +++ b/reactos/drivers/filesystems/ntfs/ntfs.h @@ -643,6 +643,14 @@ NtfsReadFCBAttribute(PNTFS_VCB Vcb, ULONG NameLength, PVOID * Data); +NTSTATUS +NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb, + PNTFS_FCB DirectoryFCB, + PUNICODE_STRING Name, + PFILE_RECORD_HEADER Record, + ULONGLONG MFTIndex, + PNTFS_FCB * fileFCB); + /* finfo.c */