/*
* ReactOS kernel
- * Copyright (C) 2002 ReactOS Team
+ * Copyright (C) 2002, 2014 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* PROJECT: ReactOS kernel
* FILE: drivers/filesystem/ntfs/fcb.c
* PURPOSE: NTFS filesystem driver
- * PROGRAMMER: Eric Kohl
+ * PROGRAMMERS: Eric Kohl
+ * Pierre Schweitzer (pierre@reactos.org)
+ * Hervé Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include <debug.h>
-/* GLOBALS *****************************************************************/
-
-
-
/* MACROS *******************************************************************/
#define TAG_FCB 'BCFI'
-
-
/* FUNCTIONS ****************************************************************/
-static PWCHAR
+static
+PWCHAR
NtfsGetNextPathElement(PWCHAR FileName)
{
- if (*FileName == L'\0')
- {
- return(NULL);
- }
+ if (*FileName == L'\0')
+ {
+ return NULL;
+ }
- while (*FileName != L'\0' && *FileName != L'\\')
- {
- FileName++;
- }
+ while (*FileName != L'\0' && *FileName != L'\\')
+ {
+ FileName++;
+ }
- return(FileName);
+ return FileName;
}
-static VOID
-NtfsWSubString(PWCHAR pTarget, const PWCHAR pSource, size_t pLength)
+static
+VOID
+NtfsWSubString(PWCHAR pTarget,
+ const PWCHAR pSource,
+ size_t pLength)
{
- wcsncpy (pTarget, pSource, pLength);
- pTarget [pLength] = L'\0';
+ wcsncpy(pTarget, pSource, pLength);
+ pTarget[pLength] = L'\0';
}
PNTFS_FCB
-NtfsCreateFCB(PCWSTR FileName, PNTFS_VCB Vcb)
+NtfsCreateFCB(PCWSTR FileName,
+ PNTFS_VCB Vcb)
{
- PNTFS_FCB Fcb;
+ PNTFS_FCB Fcb;
- ASSERT(Vcb);
- ASSERT(Vcb->Identifier.Type == NTFS_TYPE_VCB);
+ ASSERT(Vcb);
+ ASSERT(Vcb->Identifier.Type == NTFS_TYPE_VCB);
- Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_FCB), TAG_FCB);
- RtlZeroMemory(Fcb, sizeof(NTFS_FCB));
+ Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_FCB), TAG_FCB);
+ RtlZeroMemory(Fcb, sizeof(NTFS_FCB));
- Fcb->Identifier.Type = NTFS_TYPE_FCB;
- Fcb->Identifier.Size = sizeof(NTFS_TYPE_FCB);
-
- Fcb->Vcb = Vcb;
+ Fcb->Identifier.Type = NTFS_TYPE_FCB;
+ Fcb->Identifier.Size = sizeof(NTFS_TYPE_FCB);
- if (FileName)
- {
- wcscpy(Fcb->PathName, FileName);
- if (wcsrchr(Fcb->PathName, '\\') != 0)
- {
- Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\');
- }
- else
+ Fcb->Vcb = Vcb;
+
+ if (FileName)
{
- Fcb->ObjectName = Fcb->PathName;
+ wcscpy(Fcb->PathName, FileName);
+ if (wcsrchr(Fcb->PathName, '\\') != 0)
+ {
+ Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\');
+ }
+ else
+ {
+ Fcb->ObjectName = Fcb->PathName;
+ }
}
- }
- ExInitializeResourceLite(&Fcb->MainResource);
-
- Fcb->RFCB.Resource = &(Fcb->MainResource);
+ ExInitializeResourceLite(&Fcb->MainResource);
+
+ Fcb->RFCB.Resource = &(Fcb->MainResource);
- return(Fcb);
+ return Fcb;
}
VOID
NtfsDestroyFCB(PNTFS_FCB Fcb)
{
- ASSERT(Fcb);
- ASSERT(Fcb->Identifier.Type == NTFS_TYPE_FCB);
+ ASSERT(Fcb);
+ ASSERT(Fcb->Identifier.Type == NTFS_TYPE_FCB);
- ExDeleteResourceLite(&Fcb->MainResource);
+ ExDeleteResourceLite(&Fcb->MainResource);
- ExFreePool(Fcb);
+ ExFreePool(Fcb);
}
BOOLEAN
NtfsFCBIsDirectory(PNTFS_FCB Fcb)
{
-// return(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY);
-// return(Fcb->Entry.FileFlags & 0x02);
- return(TRUE);
+ return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_DIRECTORY) == NTFS_FILE_TYPE_DIRECTORY);
}
BOOLEAN
NtfsFCBIsRoot(PNTFS_FCB Fcb)
{
- return(wcscmp(Fcb->PathName, L"\\") == 0);
+ return (wcscmp(Fcb->PathName, L"\\") == 0);
}
NtfsGrabFCB(PNTFS_VCB Vcb,
PNTFS_FCB Fcb)
{
- KIRQL oldIrql;
+ KIRQL oldIrql;
- DPRINT("grabbing FCB at %p: %S, refCount:%d\n",
- Fcb,
- Fcb->PathName,
- Fcb->RefCount);
+ DPRINT("grabbing FCB at %p: %S, refCount:%d\n",
+ Fcb,
+ Fcb->PathName,
+ Fcb->RefCount);
- KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
- Fcb->RefCount++;
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+ KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
+ Fcb->RefCount++;
+ KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
}
NtfsReleaseFCB(PNTFS_VCB Vcb,
PNTFS_FCB Fcb)
{
- KIRQL oldIrql;
-
- DPRINT("releasing FCB at %p: %S, refCount:%d\n",
- Fcb,
- Fcb->PathName,
- Fcb->RefCount);
-
- KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
- Fcb->RefCount--;
- if (Fcb->RefCount <= 0 && !NtfsFCBIsDirectory(Fcb))
- {
- RemoveEntryList(&Fcb->FcbListEntry);
- CcUninitializeCacheMap(Fcb->FileObject, NULL, NULL);
- NtfsDestroyFCB(Fcb);
- }
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+ KIRQL oldIrql;
+
+ DPRINT("releasing FCB at %p: %S, refCount:%d\n",
+ Fcb,
+ Fcb->PathName,
+ Fcb->RefCount);
+
+ KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
+ Fcb->RefCount--;
+ if (Fcb->RefCount <= 0 && !NtfsFCBIsDirectory(Fcb))
+ {
+ RemoveEntryList(&Fcb->FcbListEntry);
+ KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+ CcUninitializeCacheMap(Fcb->FileObject, NULL, NULL);
+ NtfsDestroyFCB(Fcb);
+ }
+ else
+ {
+ KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+ }
}
NtfsAddFCBToTable(PNTFS_VCB Vcb,
PNTFS_FCB Fcb)
{
- KIRQL oldIrql;
+ KIRQL oldIrql;
- KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
- Fcb->Vcb = Vcb;
- InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry);
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+ KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
+ Fcb->Vcb = Vcb;
+ InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry);
+ KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
}
NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
PCWSTR FileName)
{
- KIRQL oldIrql;
- PNTFS_FCB Fcb;
- PLIST_ENTRY current_entry;
-
- KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
-
- if (FileName == NULL || *FileName == 0)
- {
- DPRINT("Return FCB for stream file object\n");
- Fcb = Vcb->StreamFileObject->FsContext;
- Fcb->RefCount++;
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
- return(Fcb);
- }
+ KIRQL oldIrql;
+ PNTFS_FCB Fcb;
+ PLIST_ENTRY current_entry;
- current_entry = Vcb->FcbListHead.Flink;
- while (current_entry != &Vcb->FcbListHead)
- {
- Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
+ KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
- DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
- if (_wcsicmp(FileName, Fcb->PathName) == 0)
+ if (FileName == NULL || *FileName == 0)
{
- Fcb->RefCount++;
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
- return(Fcb);
+ DPRINT("Return FCB for stream file object\n");
+ Fcb = Vcb->StreamFileObject->FsContext;
+ Fcb->RefCount++;
+ KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+ return Fcb;
}
- //FIXME: need to compare against short name in FCB here
+ current_entry = Vcb->FcbListHead.Flink;
+ while (current_entry != &Vcb->FcbListHead)
+ {
+ Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
- current_entry = current_entry->Flink;
- }
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+ DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
+ if (_wcsicmp(FileName, Fcb->PathName) == 0)
+ {
+ Fcb->RefCount++;
+ KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+ return Fcb;
+ }
- return(NULL);
+ //FIXME: need to compare against short name in FCB here
+
+ current_entry = current_entry->Flink;
+ }
+
+ KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+
+ return NULL;
}
NtfsFCBInitializeCache(PNTFS_VCB Vcb,
PNTFS_FCB Fcb)
{
- PFILE_OBJECT FileObject;
- NTSTATUS Status;
- PNTFS_CCB newCCB;
-
- FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice);
-
- newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB);
- if (newCCB == NULL)
- {
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
- RtlZeroMemory(newCCB, sizeof(NTFS_CCB));
-
- newCCB->Identifier.Type = NTFS_TYPE_CCB;
- newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB);
-
- FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
- FileObject->FsContext = Fcb;
- FileObject->FsContext2 = newCCB;
- newCCB->PtrFileObject = FileObject;
- Fcb->FileObject = FileObject;
- Fcb->Vcb = Vcb;
-
- Status = STATUS_SUCCESS;
- CcInitializeCacheMap(FileObject,
- (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
- FALSE,
- &(NtfsGlobalData->CacheMgrCallbacks),
- Fcb);
-
- ObDereferenceObject(FileObject);
- Fcb->Flags |= FCB_CACHE_INITIALIZED;
-
- return(Status);
+ PFILE_OBJECT FileObject;
+ NTSTATUS Status;
+ PNTFS_CCB newCCB;
+
+ FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice);
+
+ newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB);
+ if (newCCB == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(newCCB, sizeof(NTFS_CCB));
+
+ newCCB->Identifier.Type = NTFS_TYPE_CCB;
+ newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB);
+
+ FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
+ FileObject->FsContext = Fcb;
+ FileObject->FsContext2 = newCCB;
+ newCCB->PtrFileObject = FileObject;
+ Fcb->FileObject = FileObject;
+ Fcb->Vcb = Vcb;
+
+ Status = STATUS_SUCCESS;
+ CcInitializeCacheMap(FileObject,
+ (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
+ FALSE,
+ &(NtfsGlobalData->CacheMgrCallbacks),
+ Fcb);
+
+ ObDereferenceObject(FileObject);
+ Fcb->Flags |= FCB_CACHE_INITIALIZED;
+
+ return Status;
}
PNTFS_FCB
NtfsMakeRootFCB(PNTFS_VCB Vcb)
{
- PNTFS_FCB Fcb;
+ PNTFS_FCB Fcb;
+ PFILE_RECORD_HEADER MftRecord;
+ PFILENAME_ATTRIBUTE FileName;
+
+ MftRecord = ExAllocatePoolWithTag(NonPagedPool,
+ Vcb->NtfsInfo.BytesPerFileRecord,
+ TAG_NTFS);
+ if (MftRecord == NULL)
+ {
+ return NULL;
+ }
+
+ if (!NT_SUCCESS(ReadFileRecord(Vcb, NTFS_FILE_ROOT, MftRecord)))
+ {
+ ExFreePoolWithTag(MftRecord, TAG_NTFS);
+ return NULL;
+ }
- Fcb = NtfsCreateFCB(L"\\", Vcb);
+ FileName = GetFileNameFromRecord(MftRecord, NTFS_FILE_NAME_WIN32);
+ if (!FileName)
+ {
+ ExFreePoolWithTag(MftRecord, TAG_NTFS);
+ return NULL;
+ }
-// memset(Fcb->entry.Filename, ' ', 11);
+ Fcb = NtfsCreateFCB(L"\\", Vcb);
+ if (!Fcb)
+ {
+ ExFreePoolWithTag(MftRecord, TAG_NTFS);
+ return NULL;
+ }
-// Fcb->Entry.DataLengthL = Vcb->CdInfo.RootSize;
-// Fcb->Entry.ExtentLocationL = Vcb->CdInfo.RootStart;
-// Fcb->Entry.FileFlags = 0x02; // FILE_ATTRIBUTE_DIRECTORY;
- Fcb->RefCount = 1;
- Fcb->DirIndex = 0;
- Fcb->RFCB.FileSize.QuadPart = PAGE_SIZE;//Vcb->CdInfo.RootSize;
- Fcb->RFCB.ValidDataLength.QuadPart = PAGE_SIZE;//Vcb->CdInfo.RootSize;
- Fcb->RFCB.AllocationSize.QuadPart = PAGE_SIZE;//Vcb->CdInfo.RootSize;
+ memcpy(&Fcb->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength));
+ Fcb->Entry.NameType = FileName->NameType;
+ Fcb->Entry.NameLength = 0;
+ Fcb->Entry.Name[0] = UNICODE_NULL;
+ Fcb->RefCount = 1;
+ Fcb->DirIndex = 0;
+ Fcb->RFCB.FileSize.QuadPart = FileName->DataSize;
+ Fcb->RFCB.ValidDataLength.QuadPart = FileName->DataSize;
+ Fcb->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize;
+ Fcb->MFTIndex = NTFS_FILE_ROOT;
- NtfsFCBInitializeCache(Vcb, Fcb);
- NtfsAddFCBToTable(Vcb, Fcb);
- NtfsGrabFCB(Vcb, Fcb);
+ NtfsFCBInitializeCache(Vcb, Fcb);
+ NtfsAddFCBToTable(Vcb, Fcb);
+ NtfsGrabFCB(Vcb, Fcb);
- return(Fcb);
+ ExFreePoolWithTag(MftRecord, TAG_NTFS);
+
+ return Fcb;
}
PNTFS_FCB
NtfsOpenRootFCB(PNTFS_VCB Vcb)
{
- PNTFS_FCB Fcb;
+ PNTFS_FCB Fcb;
- Fcb = NtfsGrabFCBFromTable(Vcb, L"\\");
- if (Fcb == NULL)
- {
- Fcb = NtfsMakeRootFCB(Vcb);
- }
+ Fcb = NtfsGrabFCBFromTable(Vcb, L"\\");
+ if (Fcb == NULL)
+ {
+ Fcb = NtfsMakeRootFCB(Vcb);
+ }
- return(Fcb);
+ return Fcb;
}
DPRINT("Name '%S'\n", Name);
}
+#endif
NTSTATUS
-NtfsMakeFCBFromDirEntry(PVCB Vcb,
- PFCB DirectoryFCB,
- PWSTR Name,
- PDIR_RECORD Record,
- PFCB * fileFCB)
+NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb,
+ PNTFS_FCB DirectoryFCB,
+ PUNICODE_STRING Name,
+ PFILE_RECORD_HEADER Record,
+ ULONGLONG MFTIndex,
+ PNTFS_FCB * fileFCB)
{
- WCHAR pathName[MAX_PATH];
- PFCB rcFCB;
- ULONG Size;
+ WCHAR pathName[MAX_PATH];
+ PFILENAME_ATTRIBUTE FileName;
+ PNTFS_FCB rcFCB;
+
+ DPRINT1("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p)\n", Vcb, DirectoryFCB, Name, Record, fileFCB);
- if (Name [0] != 0 && wcslen (DirectoryFCB->PathName) +
- sizeof(WCHAR) + wcslen (Name) > MAX_PATH)
+ FileName = GetBestFileNameFromRecord(Record);
+ if (!FileName)
{
- return(STATUS_OBJECT_NAME_INVALID);
+ return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here
}
- wcscpy(pathName, DirectoryFCB->PathName);
- if (!NtfsFCBIsRoot(DirectoryFCB))
+ if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) +
+ sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH)
{
- wcscat(pathName, L"\\");
+ return STATUS_OBJECT_NAME_INVALID;
}
- if (Name[0] != 0)
+ wcscpy(pathName, DirectoryFCB->PathName);
+ if (!NtfsFCBIsRoot(DirectoryFCB))
{
- wcscat(pathName, Name);
+ wcscat(pathName, L"\\");
}
- else
- {
- WCHAR entryName[MAX_PATH];
+ wcscat(pathName, Name->Buffer);
- NtfsGetDirEntryName(Vcb, Record, entryName);
- wcscat(pathName, entryName);
+ rcFCB = NtfsCreateFCB(pathName, Vcb);
+ if (!rcFCB)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- rcFCB = NtfsCreateFCB(pathName, Vcb);
- memcpy(&rcFCB->Entry, Record, sizeof(DIR_RECORD));
-
- Size = rcFCB->Entry.DataLengthL;
+ memcpy(&rcFCB->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength));
+ rcFCB->Entry.NameType = FileName->NameType;
+ rcFCB->RFCB.FileSize.QuadPart = FileName->DataSize;
+ rcFCB->RFCB.ValidDataLength.QuadPart = FileName->DataSize;
+ rcFCB->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize;
- rcFCB->RFCB.FileSize.QuadPart = Size;
- rcFCB->RFCB.ValidDataLength.QuadPart = Size;
- rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, BLOCKSIZE);
-// DPRINT1("%S %d %d\n", longName, Size, (ULONG)rcFCB->RFCB.AllocationSize.QuadPart);
- NtfsFCBInitializeCache(Vcb, rcFCB);
- rcFCB->RefCount++;
- NtfsAddFCBToTable(Vcb, rcFCB);
- *fileFCB = rcFCB;
+ NtfsFCBInitializeCache(Vcb, rcFCB);
+ rcFCB->RefCount = 1;
+ rcFCB->MFTIndex = MFTIndex;
+ NtfsAddFCBToTable(Vcb, rcFCB);
+ *fileFCB = rcFCB;
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
}
-#endif
NTSTATUS
PNTFS_FCB Fcb,
PFILE_OBJECT FileObject)
{
- PNTFS_CCB newCCB;
-
- newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB);
- if (newCCB == NULL)
- {
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
- RtlZeroMemory(newCCB, sizeof(NTFS_CCB));
-
- newCCB->Identifier.Type = NTFS_TYPE_CCB;
- newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB);
-
- FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
- FileObject->FsContext = Fcb;
- FileObject->FsContext2 = newCCB;
- newCCB->PtrFileObject = FileObject;
- Fcb->Vcb = Vcb;
-
- if (!(Fcb->Flags & FCB_CACHE_INITIALIZED))
- {
- CcInitializeCacheMap(FileObject,
- (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
- FALSE,
- NULL,
- NULL);
+ PNTFS_CCB newCCB;
- Fcb->Flags |= FCB_CACHE_INITIALIZED;
- }
+ newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB);
+ if (newCCB == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(newCCB, sizeof(NTFS_CCB));
- //DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL);
+ newCCB->Identifier.Type = NTFS_TYPE_CCB;
+ newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB);
- return(STATUS_SUCCESS);
+ FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
+ FileObject->FsContext = Fcb;
+ FileObject->FsContext2 = newCCB;
+ newCCB->PtrFileObject = FileObject;
+ Fcb->Vcb = Vcb;
+
+ if (!(Fcb->Flags & FCB_CACHE_INITIALIZED))
+ {
+ CcInitializeCacheMap(FileObject,
+ (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
+ FALSE,
+ NULL,
+ NULL);
+
+ Fcb->Flags |= FCB_CACHE_INITIALIZED;
+ }
+
+ //DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL);
+
+ return STATUS_SUCCESS;
}
PWSTR FileToFind,
PNTFS_FCB *FoundFCB)
{
-#if 0
- WCHAR TempName[2];
- WCHAR Name[256];
- PVOID Block;
- ULONG FirstSector;
- ULONG DirSize;
- PDIR_RECORD Record;
- ULONG Offset;
- ULONG BlockOffset;
- NTSTATUS Status;
-
- LARGE_INTEGER StreamOffset;
- PVOID Context;
-
- ASSERT(DeviceExt);
- ASSERT(DirectoryFcb);
- ASSERT(FileToFind);
-
- DPRINT("NtfsDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n",
- DeviceExt,
- DirectoryFcb,
- FileToFind);
- DPRINT("Dir Path:%S\n", DirectoryFcb->PathName);
-
- /* default to '.' if no filename specified */
- if (wcslen(FileToFind) == 0)
- {
- TempName[0] = L'.';
- TempName[1] = 0;
- FileToFind = TempName;
- }
+ NTSTATUS Status;
+ ULONGLONG CurrentDir;
+ UNICODE_STRING File;
+ PFILE_RECORD_HEADER FileRecord;
+ PNTFS_ATTR_CONTEXT DataContext;
+ ULONGLONG MFTIndex;
- DirSize = DirectoryFcb->Entry.DataLengthL;
- StreamOffset.QuadPart = (LONGLONG)DirectoryFcb->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
+ DPRINT1("NtfsDirFindFile(%p, %p, %S, %p)\n", Vcb, DirectoryFcb, FileToFind, FoundFCB);
- if(!CcMapData(DeviceExt->StreamFileObject, &StreamOffset,
- BLOCKSIZE, TRUE, &Context, &Block))
- {
- DPRINT("CcMapData() failed\n");
- return(STATUS_UNSUCCESSFUL);
- }
+ *FoundFCB = NULL;
+ RtlInitUnicodeString(&File, FileToFind);
+ CurrentDir = DirectoryFcb->MFTIndex;
- Offset = 0;
- BlockOffset = 0;
- Record = (PDIR_RECORD)Block;
- while(TRUE)
+ Status = NtfsLookupFileAt(Vcb, &File, &FileRecord, &DataContext, &MFTIndex, CurrentDir);
+ if (!NT_SUCCESS(Status))
{
- if (Record->RecordLength == 0)
- {
- DPRINT("RecordLength == 0 Stopped!\n");
- break;
- }
-
- DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n",
- Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
-
- NtfsGetDirEntryName(DeviceExt, Record, Name);
- DPRINT("Name '%S'\n", Name);
-
- if (wstrcmpjoki(Name, FileToFind))
- {
- DPRINT("Match found, %S\n", Name);
- Status = NtfsMakeFCBFromDirEntry(DeviceExt,
- DirectoryFcb,
- Name,
- Record,
- FoundFCB);
-
- CcUnpinData(Context);
-
- return(Status);
- }
-
- Offset += Record->RecordLength;
- BlockOffset += 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 >= DirSize)
- break;
+ return Status;
}
- CcUnpinData(Context);
-#endif
- return(STATUS_OBJECT_NAME_NOT_FOUND);
+ Status = NtfsMakeFCBFromDirEntry(Vcb, DirectoryFcb, &File, FileRecord, MFTIndex, FoundFCB);
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+
+ return Status;
}
PNTFS_FCB *pFCB,
const PWSTR pFileName)
{
- NTSTATUS Status;
- WCHAR pathName [MAX_PATH];
- WCHAR elementName [MAX_PATH];
- PWCHAR currentElement;
- PNTFS_FCB FCB;
- PNTFS_FCB parentFCB;
-
- DPRINT("NtfsGetFCBForFile(%p, %p, %p, '%S')\n",
- Vcb,
- pParentFCB,
- pFCB,
- pFileName);
-
- /* Dummy code */
+ NTSTATUS Status;
+ WCHAR pathName [MAX_PATH];
+ WCHAR elementName [MAX_PATH];
+ PWCHAR currentElement;
+ PNTFS_FCB FCB;
+ PNTFS_FCB parentFCB;
+
+ DPRINT("NtfsGetFCBForFile(%p, %p, %p, '%S')\n",
+ Vcb,
+ pParentFCB,
+ pFCB,
+ pFileName);
+
+ /* Dummy code */
// FCB = NtfsOpenRootFCB(Vcb);
// *pFCB = FCB;
// *pParentFCB = NULL;
#if 1
- /* Trivial case, open of the root directory on volume */
- if (pFileName [0] == L'\0' || wcscmp(pFileName, L"\\") == 0)
- {
- DPRINT("returning root FCB\n");
+ /* Trivial case, open of the root directory on volume */
+ if (pFileName [0] == L'\0' || wcscmp(pFileName, L"\\") == 0)
+ {
+ DPRINT("returning root FCB\n");
- FCB = NtfsOpenRootFCB(Vcb);
- *pFCB = FCB;
- *pParentFCB = NULL;
+ FCB = NtfsOpenRootFCB(Vcb);
+ *pFCB = FCB;
+ *pParentFCB = NULL;
- return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND);
- }
- else
- {
- currentElement = pFileName + 1;
- wcscpy (pathName, L"\\");
- FCB = NtfsOpenRootFCB (Vcb);
- }
- parentFCB = NULL;
-
- /* Parse filename and check each path element for existance and access */
- while (NtfsGetNextPathElement(currentElement) != 0)
- {
- /* Skip blank directory levels */
- if ((NtfsGetNextPathElement(currentElement) - currentElement) == 0)
+ return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ else
{
- currentElement++;
- continue;
+ currentElement = pFileName + 1;
+ wcscpy (pathName, L"\\");
+ FCB = NtfsOpenRootFCB (Vcb);
}
- DPRINT("Parsing, currentElement:%S\n", currentElement);
- DPRINT(" parentFCB:%p FCB:%p\n", parentFCB, FCB);
+ parentFCB = NULL;
- /* Descend to next directory level */
- if (parentFCB)
+ /* Parse filename and check each path element for existance and access */
+ while (NtfsGetNextPathElement(currentElement) != 0)
{
- NtfsReleaseFCB(Vcb, parentFCB);
- parentFCB = NULL;
- }
+ /* Skip blank directory levels */
+ if ((NtfsGetNextPathElement(currentElement) - currentElement) == 0)
+ {
+ currentElement++;
+ continue;
+ }
- /* fail if element in FCB is not a directory */
- if (!NtfsFCBIsDirectory(FCB))
- {
- DPRINT("Element in requested path is not a directory\n");
+ DPRINT("Parsing, currentElement:%S\n", currentElement);
+ DPRINT(" parentFCB:%p FCB:%p\n", parentFCB, FCB);
- NtfsReleaseFCB(Vcb, FCB);
- FCB = 0;
- *pParentFCB = NULL;
- *pFCB = NULL;
+ /* Descend to next directory level */
+ if (parentFCB)
+ {
+ NtfsReleaseFCB(Vcb, parentFCB);
+ parentFCB = NULL;
+ }
- return(STATUS_OBJECT_PATH_NOT_FOUND);
- }
- parentFCB = FCB;
+ /* fail if element in FCB is not a directory */
+ if (!NtfsFCBIsDirectory(FCB))
+ {
+ DPRINT("Element in requested path is not a directory\n");
- /* Extract next directory level into dirName */
- NtfsWSubString(pathName,
- pFileName,
- NtfsGetNextPathElement(currentElement) - pFileName);
- DPRINT(" pathName:%S\n", pathName);
+ NtfsReleaseFCB(Vcb, FCB);
+ FCB = 0;
+ *pParentFCB = NULL;
+ *pFCB = NULL;
- FCB = NtfsGrabFCBFromTable(Vcb, pathName);
- if (FCB == NULL)
- {
- NtfsWSubString(elementName,
- currentElement,
- NtfsGetNextPathElement(currentElement) - currentElement);
- DPRINT(" elementName:%S\n", elementName);
-
- Status = NtfsDirFindFile(Vcb, parentFCB, elementName, &FCB);
- if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
- {
- *pParentFCB = parentFCB;
- *pFCB = NULL;
- currentElement = NtfsGetNextPathElement(currentElement);
- if (*currentElement == L'\0' || NtfsGetNextPathElement(currentElement + 1) == 0)
- {
- return(STATUS_OBJECT_NAME_NOT_FOUND);
+ return STATUS_OBJECT_PATH_NOT_FOUND;
}
- else
+
+ parentFCB = FCB;
+
+ /* Extract next directory level into dirName */
+ NtfsWSubString(pathName,
+ pFileName,
+ NtfsGetNextPathElement(currentElement) - pFileName);
+ DPRINT(" pathName:%S\n", pathName);
+
+ FCB = NtfsGrabFCBFromTable(Vcb, pathName);
+ if (FCB == NULL)
{
- return(STATUS_OBJECT_PATH_NOT_FOUND);
+ NtfsWSubString(elementName,
+ currentElement,
+ NtfsGetNextPathElement(currentElement) - currentElement);
+ DPRINT(" elementName:%S\n", elementName);
+
+ Status = NtfsDirFindFile(Vcb, parentFCB, elementName, &FCB);
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ *pParentFCB = parentFCB;
+ *pFCB = NULL;
+ currentElement = NtfsGetNextPathElement(currentElement);
+ if (*currentElement == L'\0' || NtfsGetNextPathElement(currentElement + 1) == 0)
+ {
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ else
+ {
+ return STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ NtfsReleaseFCB(Vcb, parentFCB);
+ *pParentFCB = NULL;
+ *pFCB = NULL;
+
+ return Status;
+ }
}
- }
- else if (!NT_SUCCESS(Status))
- {
- NtfsReleaseFCB(Vcb, parentFCB);
- *pParentFCB = NULL;
- *pFCB = NULL;
- return(Status);
- }
+ currentElement = NtfsGetNextPathElement(currentElement);
}
- currentElement = NtfsGetNextPathElement(currentElement);
- }
- *pParentFCB = parentFCB;
- *pFCB = FCB;
+ *pParentFCB = parentFCB;
+ *pFCB = FCB;
#endif
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
}
/* EOF */