Author: pschweitzer
Date: Sun Dec 14 21:18:47 2014
New Revision: 65652
URL:
http://svn.reactos.org/svn/reactos?rev=65652&view=rev
Log:
[NTFS]
- Implement NtfsGrabFCBFromTableById() and NtfsGetFCBForFileById(). These two are
responsible for opening and retrieving a file open by ID.
- Modified NtfsMakeFCBFromDirEntry() so that it supports openings by ID which come with
less information than normal openings.
- Modified NtfsGrabFCBFromTable() so that it doesn't return a FCB which would have
been opened by ID.
- Modified NtfsOpenFile() so that it allows opening a file by ID using the two FCB helpers
functions defined upper.
- Modified NtfsCreateFile() so that it can validate input in case of opening by ID.
To make it short, all this implements file opening by ID in NTFS driver. I made the choice
to separate FCB which are coming from "normal" opening and these from ID
opening.
The reason is that a file opening with ID has less information than a normal opening, and
may fail on these information retreival. This is due to the fact that if opening by ID can
virtual open all the files, because it ignores authorizations, traverses checks, in the
end for retrieving the information, such checks can be done and fail.
I also left all this disabled so far, because it appears to regress NFI. I will
investigate this.
CORE-8725
Modified:
trunk/reactos/drivers/filesystems/ntfs/create.c
trunk/reactos/drivers/filesystems/ntfs/fcb.c
trunk/reactos/drivers/filesystems/ntfs/ntfs.h
Modified: trunk/reactos/drivers/filesystems/ntfs/create.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/c…
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/create.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/create.c [iso-8859-1] Sun Dec 14 21:18:47 2014
@@ -80,6 +80,7 @@
NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PWSTR FileName,
+ BOOLEAN OpenById,
PNTFS_FCB * FoundFCB)
{
PNTFS_FCB ParentFcb;
@@ -87,55 +88,81 @@
NTSTATUS Status;
PWSTR AbsFileName = NULL;
- DPRINT1("NtfsOpenFile(%p, %p, %S, %p)\n", DeviceExt, FileObject, FileName,
FoundFCB);
+ DPRINT1("NtfsOpenFile(%p, %p, %S, %u, %p)\n", DeviceExt, FileObject,
(!OpenById ? FileName : NULL), OpenById, FoundFCB);
*FoundFCB = NULL;
- if (FileObject->RelatedFileObject)
- {
- DPRINT("Converting relative filename to absolute filename\n");
-
- Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
- FileName,
- &AbsFileName);
- FileName = AbsFileName;
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- return STATUS_UNSUCCESSFUL;
- }
-
- //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
-
- DPRINT("PathName to open: %S\n", FileName);
-
- /* try first to find an existing FCB in memory */
- DPRINT("Checking for existing FCB in memory\n");
- Fcb = NtfsGrabFCBFromTable(DeviceExt,
- FileName);
- if (Fcb == NULL)
- {
- DPRINT("No existing FCB found, making a new one if file exists.\n");
- Status = NtfsGetFCBForFile(DeviceExt,
- &ParentFcb,
- &Fcb,
+ if (OpenById)
+ {
+ ULONGLONG Id = (*(PULONGLONG)FileName) & NTFS_MFT_MASK;
+
+ DPRINT1("Will attempt to open by id: %I64x\n", Id);
+
+ Fcb = NtfsGrabFCBFromTableById(DeviceExt,
+ Id);
+ if (Fcb == NULL)
+ {
+ Status = NtfsGetFCBForFileById(DeviceExt,
+ &Fcb,
+ Id);
+ if (!NT_SUCCESS (Status))
+ {
+ DPRINT("Could not make a new FCB, status: %x\n", Status);
+
+ return Status;
+ }
+
+ Fcb->Flags |= FCB_IS_OPEN_BY_ID;
+ }
+ }
+ else
+ {
+ if (FileObject->RelatedFileObject)
+ {
+ DPRINT("Converting relative filename to absolute filename\n");
+
+ Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
+ FileName,
+ &AbsFileName);
+ FileName = AbsFileName;
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //FIXME: Get cannonical path name (remove .'s, ..'s and extra
separators)
+
+ DPRINT("PathName to open: %S\n", FileName);
+
+ /* try first to find an existing FCB in memory */
+ DPRINT("Checking for existing FCB in memory\n");
+ Fcb = NtfsGrabFCBFromTable(DeviceExt,
FileName);
- if (ParentFcb != NULL)
- {
- NtfsReleaseFCB(DeviceExt,
- ParentFcb);
- }
-
- if (!NT_SUCCESS (Status))
- {
- DPRINT("Could not make a new FCB, status: %x\n", Status);
-
- if (AbsFileName)
- ExFreePool(AbsFileName);
-
- return Status;
+ if (Fcb == NULL)
+ {
+ DPRINT("No existing FCB found, making a new one if file
exists.\n");
+ Status = NtfsGetFCBForFile(DeviceExt,
+ &ParentFcb,
+ &Fcb,
+ FileName);
+ if (ParentFcb != NULL)
+ {
+ NtfsReleaseFCB(DeviceExt,
+ ParentFcb);
+ }
+
+ if (!NT_SUCCESS (Status))
+ {
+ DPRINT("Could not make a new FCB, status: %x\n", Status);
+
+ if (AbsFileName)
+ ExFreePool(AbsFileName);
+
+ return Status;
+ }
}
}
@@ -201,6 +228,12 @@
return STATUS_ACCESS_DENIED;
}
+ if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID &&
+ FileObject->FileName.Length != sizeof(ULONGLONG))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
/* This a open operation for the volume itself */
if (FileObject->FileName.Length == 0 &&
(FileObject->RelatedFileObject == NULL ||
FileObject->RelatedFileObject->FsContext2 != NULL))
@@ -226,6 +259,7 @@
Status = NtfsOpenFile(DeviceExt,
FileObject,
FileObject->FileName.Buffer,
+ ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ==
FILE_OPEN_BY_FILE_ID),
&Fcb);
if (NT_SUCCESS(Status))
Modified: trunk/reactos/drivers/filesystems/ntfs/fcb.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/f…
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/fcb.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/fcb.c [iso-8859-1] Sun Dec 14 21:18:47 2014
@@ -220,7 +220,8 @@
Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
DPRINT("Comparing '%S' and '%S'\n", FileName,
Fcb->PathName);
- if (_wcsicmp(FileName, Fcb->PathName) == 0)
+ if ((Fcb->Flags & FCB_IS_OPEN_BY_ID) != FCB_IS_OPEN_BY_ID &&
+ _wcsicmp(FileName, Fcb->PathName) == 0)
{
Fcb->RefCount++;
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
@@ -228,6 +229,38 @@
}
//FIXME: need to compare against short name in FCB here
+
+ current_entry = current_entry->Flink;
+ }
+
+ KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+
+ return NULL;
+}
+
+
+PNTFS_FCB
+NtfsGrabFCBFromTableById(PNTFS_VCB Vcb,
+ ULONGLONG Id)
+{
+ KIRQL oldIrql;
+ PNTFS_FCB Fcb;
+ PLIST_ENTRY current_entry;
+
+ KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
+
+ current_entry = Vcb->FcbListHead.Flink;
+ while (current_entry != &Vcb->FcbListHead)
+ {
+ Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
+
+ if ((Fcb->Flags & FCB_IS_OPEN_BY_ID) == FCB_IS_OPEN_BY_ID &&
+ Fcb->MFTIndex == Id)
+ {
+ Fcb->RefCount++;
+ KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+ return Fcb;
+ }
current_entry = current_entry->Flink;
}
@@ -410,18 +443,26 @@
return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here
}
- if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) +
- sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH)
- {
- return STATUS_OBJECT_NAME_INVALID;
- }
-
- wcscpy(pathName, DirectoryFCB->PathName);
- if (!NtfsFCBIsRoot(DirectoryFCB))
- {
- wcscat(pathName, L"\\");
- }
- wcscat(pathName, Name->Buffer);
+ if (DirectoryFCB && Name)
+ {
+ if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) +
+ sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH)
+ {
+ return STATUS_OBJECT_NAME_INVALID;
+ }
+
+ wcscpy(pathName, DirectoryFCB->PathName);
+ if (!NtfsFCBIsRoot(DirectoryFCB))
+ {
+ wcscat(pathName, L"\\");
+ }
+ wcscat(pathName, Name->Buffer);
+ }
+ else
+ {
+ RtlCopyMemory(pathName, FileName->Name, FileName->NameLength * sizeof
(WCHAR));
+ pathName[FileName->NameLength] = UNICODE_NULL;
+ }
rcFCB = NtfsCreateFCB(pathName, Vcb);
if (!rcFCB)
@@ -655,6 +696,42 @@
NTSTATUS
+NtfsGetFCBForFileById(PNTFS_VCB Vcb,
+ PNTFS_FCB *pFCB,
+ ULONGLONG Id)
+{
+ NTSTATUS Status;
+ PFILE_RECORD_HEADER FileRecord;
+
+ FileRecord = ExAllocatePoolWithTag(NonPagedPool,
+ Vcb->NtfsInfo.BytesPerFileRecord,
+ TAG_NTFS);
+ if (FileRecord == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Status = ReadFileRecord(Vcb, Id, FileRecord);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+ return Status;
+ }
+
+ if ((FileRecord->Flags & FRH_IN_USE) != FRH_IN_USE)
+ {
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = NtfsMakeFCBFromDirEntry(Vcb, NULL, NULL, FileRecord, Id, pFCB);
+
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+
+ return Status;
+}
+
+NTSTATUS
NtfsReadFCBAttribute(PNTFS_VCB Vcb,
PNTFS_FCB pFCB,
ULONG Type,
Modified: trunk/reactos/drivers/filesystems/ntfs/ntfs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/n…
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/ntfs.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/ntfs.h [iso-8859-1] Sun Dec 14 21:18:47 2014
@@ -416,6 +416,7 @@
#define FCB_CACHE_INITIALIZED 0x0001
#define FCB_IS_VOLUME_STREAM 0x0002
#define FCB_IS_VOLUME 0x0004
+#define FCB_IS_OPEN_BY_ID 0x0008
#define MAX_PATH 260
typedef struct _FCB
@@ -599,6 +600,10 @@
NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
PCWSTR FileName);
+PNTFS_FCB
+NtfsGrabFCBFromTableById(PNTFS_VCB Vcb,
+ ULONGLONG Id);
+
NTSTATUS
NtfsFCBInitializeCache(PNTFS_VCB Vcb,
PNTFS_FCB Fcb);
@@ -619,6 +624,11 @@
PNTFS_FCB *pParentFCB,
PNTFS_FCB *pFCB,
const PWSTR pFileName);
+
+NTSTATUS
+NtfsGetFCBForFileById(PNTFS_VCB Vcb,
+ PNTFS_FCB *pFCB,
+ ULONGLONG Id);
NTSTATUS
NtfsReadFCBAttribute(PNTFS_VCB Vcb,