Simplify the implementation of the "Open by ID" feature of our driver.
Instead of creating singleton FCB not linked to the rest of FS tree, just walk the whole path down, to recreate it.

This doesn't make nfi work properly though. Will investigate more.

CORE-8725

svn path=/trunk/; revision=66264
This commit is contained in:
Pierre Schweitzer 2015-02-14 15:35:35 +00:00
parent e713b40c77
commit 483c6f32a5
3 changed files with 123 additions and 152 deletions

View file

@ -46,6 +46,18 @@ NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject,
Fcb = pFileObject->FsContext;
ASSERT(Fcb);
if (Fcb->Flags & FCB_IS_VOLUME)
{
/* This is likely to be an opening by ID, return ourselves */
if (pRelativeFileName[0] == L'\\')
{
*pAbsoluteFilename = NULL;
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}
/* verify related object is a directory and target name
don't start with \. */
if (NtfsFCBIsDirectory(Fcb) == FALSE ||
@ -72,6 +84,66 @@ NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject,
}
static
NTSTATUS
NtfsMoonWalkID(PDEVICE_EXTENSION DeviceExt,
ULONGLONG Id,
PUNICODE_STRING OutPath)
{
NTSTATUS Status;
PFILE_RECORD_HEADER MftRecord;
PFILENAME_ATTRIBUTE FileName;
WCHAR FullPath[MAX_PATH];
ULONG WritePosition = MAX_PATH - 1;
DPRINT1("NtfsMoonWalkID(%p, %I64x, %p)\n", DeviceExt, Id, OutPath);
Id = Id & NTFS_MFT_MASK;
RtlZeroMemory(FullPath, sizeof(FullPath));
MftRecord = ExAllocatePoolWithTag(NonPagedPool,
DeviceExt->NtfsInfo.BytesPerFileRecord,
TAG_NTFS);
if (MftRecord == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
while (TRUE)
{
Status = ReadFileRecord(DeviceExt, Id, MftRecord);
if (!NT_SUCCESS(Status))
break;
ASSERT(MftRecord->Ntfs.Type == NRH_FILE_TYPE);
FileName = GetBestFileNameFromRecord(MftRecord);
WritePosition -= FileName->NameLength;
ASSERT(WritePosition < MAX_PATH);
RtlCopyMemory(FullPath + WritePosition, FileName->Name, FileName->NameLength * sizeof(WCHAR));
WritePosition -= 1;
ASSERT(WritePosition < MAX_PATH);
FullPath[WritePosition] = L'\\';
Id = FileName->DirectoryFileReferenceNumber & NTFS_MFT_MASK;
if (Id == NTFS_FILE_ROOT)
break;
}
ExFreePoolWithTag(MftRecord, TAG_NTFS);
OutPath->Length = (MAX_PATH - WritePosition - 1) * sizeof(WCHAR);
OutPath->MaximumLength = (MAX_PATH - WritePosition) * sizeof(WCHAR);
OutPath->Buffer = ExAllocatePoolWithTag(NonPagedPool, OutPath->MaximumLength, TAG_NTFS);
if (OutPath->Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(OutPath->Buffer, FullPath + WritePosition, OutPath->MaximumLength);
return Status;
}
/*
* FUNCTION: Opens a file
*/
@ -80,7 +152,6 @@ NTSTATUS
NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PWSTR FileName,
BOOLEAN OpenById,
PNTFS_FCB * FoundFCB)
{
PNTFS_FCB ParentFcb;
@ -88,81 +159,53 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
NTSTATUS Status;
PWSTR AbsFileName = NULL;
DPRINT1("NtfsOpenFile(%p, %p, %S, %u, %p)\n", DeviceExt, FileObject, (!OpenById ? FileName : NULL), OpenById, FoundFCB);
DPRINT1("NtfsOpenFile(%p, %p, %S, %p)\n", DeviceExt, FileObject, FileName, FoundFCB);
*FoundFCB = NULL;
if (OpenById)
if (FileObject->RelatedFileObject)
{
ULONGLONG Id = (*(PULONGLONG)FileName) & NTFS_MFT_MASK;
DPRINT("Converting relative filename to absolute filename\n");
DPRINT1("Will attempt to open by id: %I64x\n", Id);
Fcb = NtfsGrabFCBFromTableById(DeviceExt,
Id);
if (Fcb == NULL)
Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
FileName,
&AbsFileName);
if (AbsFileName) FileName = AbsFileName;
if (!NT_SUCCESS(Status))
{
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;
return Status;
}
}
else
//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)
{
if (FileObject->RelatedFileObject)
DPRINT("No existing FCB found, making a new one if file exists.\n");
Status = NtfsGetFCBForFile(DeviceExt,
&ParentFcb,
&Fcb,
FileName);
if (ParentFcb != NULL)
{
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;
NtfsReleaseFCB(DeviceExt,
ParentFcb);
}
//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)
if (!NT_SUCCESS (Status))
{
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);
}
DPRINT("Could not make a new FCB, status: %x\n", Status);
if (!NT_SUCCESS (Status))
{
DPRINT("Could not make a new FCB, status: %x\n", Status);
if (AbsFileName)
ExFreePool(AbsFileName);
if (AbsFileName)
ExFreePool(AbsFileName);
return Status;
}
return Status;
}
}
@ -196,6 +239,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
PNTFS_FCB Fcb;
// PWSTR FileName;
NTSTATUS Status;
UNICODE_STRING FullPath;
DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, Irp);
@ -213,12 +257,6 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
return STATUS_INVALID_PARAMETER;
}
if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
FileObject = Stack->FileObject;
if (RequestedDisposition == FILE_CREATE ||
@ -228,10 +266,18 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
return STATUS_ACCESS_DENIED;
}
if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID &&
FileObject->FileName.Length != sizeof(ULONGLONG))
if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID)
{
return STATUS_INVALID_PARAMETER;
if (FileObject->FileName.Length != sizeof(ULONGLONG))
return STATUS_INVALID_PARAMETER;
Status = NtfsMoonWalkID(DeviceExt, (*(PULONGLONG)FileObject->FileName.Buffer), &FullPath);
if (!NT_SUCCESS(Status))
{
return Status;
}
DPRINT1("Open by ID: %I64x -> %wZ\n", (*(PULONGLONG)FileObject->FileName.Buffer) & NTFS_MFT_MASK, &FullPath);
}
/* This a open operation for the volume itself */
@ -258,10 +304,14 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
Status = NtfsOpenFile(DeviceExt,
FileObject,
FileObject->FileName.Buffer,
((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID),
((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))
{
if (RequestedDisposition == FILE_CREATE)

View file

@ -220,8 +220,7 @@ NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
if ((Fcb->Flags & FCB_IS_OPEN_BY_ID) != FCB_IS_OPEN_BY_ID &&
_wcsicmp(FileName, Fcb->PathName) == 0)
if (_wcsicmp(FileName, Fcb->PathName) == 0)
{
Fcb->RefCount++;
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
@ -239,38 +238,6 @@ NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
}
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;
}
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
return NULL;
}
NTSTATUS
NtfsFCBInitializeCache(PNTFS_VCB Vcb,
PNTFS_FCB Fcb)
@ -697,42 +664,6 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
}
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,

View file

@ -416,7 +416,6 @@ typedef struct _NTFS_ATTR_CONTEXT
#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
@ -601,10 +600,6 @@ PNTFS_FCB
NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
PCWSTR FileName);
PNTFS_FCB
NtfsGrabFCBFromTableById(PNTFS_VCB Vcb,
ULONGLONG Id);
NTSTATUS
NtfsFCBInitializeCache(PNTFS_VCB Vcb,
PNTFS_FCB Fcb);
@ -626,11 +621,6 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
PNTFS_FCB *pFCB,
const PWSTR pFileName);
NTSTATUS
NtfsGetFCBForFileById(PNTFS_VCB Vcb,
PNTFS_FCB *pFCB,
ULONGLONG Id);
NTSTATUS
NtfsReadFCBAttribute(PNTFS_VCB Vcb,
PNTFS_FCB pFCB,