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; Fcb = pFileObject->FsContext;
ASSERT(Fcb); 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 /* verify related object is a directory and target name
don't start with \. */ don't start with \. */
if (NtfsFCBIsDirectory(Fcb) == FALSE || 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 * FUNCTION: Opens a file
*/ */
@ -80,7 +152,6 @@ NTSTATUS
NtfsOpenFile(PDEVICE_EXTENSION DeviceExt, NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject, PFILE_OBJECT FileObject,
PWSTR FileName, PWSTR FileName,
BOOLEAN OpenById,
PNTFS_FCB * FoundFCB) PNTFS_FCB * FoundFCB)
{ {
PNTFS_FCB ParentFcb; PNTFS_FCB ParentFcb;
@ -88,81 +159,53 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
NTSTATUS Status; NTSTATUS Status;
PWSTR AbsFileName = NULL; 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; *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); Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
FileName,
Fcb = NtfsGrabFCBFromTableById(DeviceExt, &AbsFileName);
Id); if (AbsFileName) FileName = AbsFileName;
if (Fcb == NULL) if (!NT_SUCCESS(Status))
{ {
Status = NtfsGetFCBForFileById(DeviceExt, return Status;
&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
//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"); NtfsReleaseFCB(DeviceExt,
ParentFcb);
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) if (!NT_SUCCESS (Status))
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"); DPRINT("Could not make a new FCB, status: %x\n", Status);
Status = NtfsGetFCBForFile(DeviceExt,
&ParentFcb,
&Fcb,
FileName);
if (ParentFcb != NULL)
{
NtfsReleaseFCB(DeviceExt,
ParentFcb);
}
if (!NT_SUCCESS (Status)) if (AbsFileName)
{ ExFreePool(AbsFileName);
DPRINT("Could not make a new FCB, status: %x\n", Status);
if (AbsFileName) return Status;
ExFreePool(AbsFileName);
return Status;
}
} }
} }
@ -196,6 +239,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
PNTFS_FCB Fcb; PNTFS_FCB Fcb;
// PWSTR FileName; // PWSTR FileName;
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING FullPath;
DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, Irp); DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, Irp);
@ -213,12 +257,6 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
FileObject = Stack->FileObject; FileObject = Stack->FileObject;
if (RequestedDisposition == FILE_CREATE || if (RequestedDisposition == FILE_CREATE ||
@ -228,10 +266,18 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
} }
if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID && if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID)
FileObject->FileName.Length != sizeof(ULONGLONG))
{ {
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 */ /* This a open operation for the volume itself */
@ -258,10 +304,14 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
Status = NtfsOpenFile(DeviceExt, Status = NtfsOpenFile(DeviceExt,
FileObject, FileObject,
FileObject->FileName.Buffer, ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer),
((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID),
&Fcb); &Fcb);
if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
{
ExFreePoolWithTag(FullPath.Buffer, TAG_NTFS);
}
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
if (RequestedDisposition == FILE_CREATE) if (RequestedDisposition == FILE_CREATE)

View file

@ -220,8 +220,7 @@ NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry); Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName); DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
if ((Fcb->Flags & FCB_IS_OPEN_BY_ID) != FCB_IS_OPEN_BY_ID && if (_wcsicmp(FileName, Fcb->PathName) == 0)
_wcsicmp(FileName, Fcb->PathName) == 0)
{ {
Fcb->RefCount++; Fcb->RefCount++;
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 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 NTSTATUS
NtfsFCBInitializeCache(PNTFS_VCB Vcb, NtfsFCBInitializeCache(PNTFS_VCB Vcb,
PNTFS_FCB Fcb) 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 NTSTATUS
NtfsReadFCBAttribute(PNTFS_VCB Vcb, NtfsReadFCBAttribute(PNTFS_VCB Vcb,
PNTFS_FCB pFCB, PNTFS_FCB pFCB,

View file

@ -416,7 +416,6 @@ typedef struct _NTFS_ATTR_CONTEXT
#define FCB_CACHE_INITIALIZED 0x0001 #define FCB_CACHE_INITIALIZED 0x0001
#define FCB_IS_VOLUME_STREAM 0x0002 #define FCB_IS_VOLUME_STREAM 0x0002
#define FCB_IS_VOLUME 0x0004 #define FCB_IS_VOLUME 0x0004
#define FCB_IS_OPEN_BY_ID 0x0008
#define MAX_PATH 260 #define MAX_PATH 260
typedef struct _FCB typedef struct _FCB
@ -601,10 +600,6 @@ PNTFS_FCB
NtfsGrabFCBFromTable(PNTFS_VCB Vcb, NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
PCWSTR FileName); PCWSTR FileName);
PNTFS_FCB
NtfsGrabFCBFromTableById(PNTFS_VCB Vcb,
ULONGLONG Id);
NTSTATUS NTSTATUS
NtfsFCBInitializeCache(PNTFS_VCB Vcb, NtfsFCBInitializeCache(PNTFS_VCB Vcb,
PNTFS_FCB Fcb); PNTFS_FCB Fcb);
@ -626,11 +621,6 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
PNTFS_FCB *pFCB, PNTFS_FCB *pFCB,
const PWSTR pFileName); const PWSTR pFileName);
NTSTATUS
NtfsGetFCBForFileById(PNTFS_VCB Vcb,
PNTFS_FCB *pFCB,
ULONGLONG Id);
NTSTATUS NTSTATUS
NtfsReadFCBAttribute(PNTFS_VCB Vcb, NtfsReadFCBAttribute(PNTFS_VCB Vcb,
PNTFS_FCB pFCB, PNTFS_FCB pFCB,