[NTFS]
[reactos.git] / reactos / drivers / filesystems / ntfs / fcb.c
index d0f3eee..e9b0cc4 100644 (file)
 #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)
 {
+    UNREFERENCED_PARAMETER(Fcb);
 //  return(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY);
 //  return(Fcb->Entry.FileFlags & 0x02);
-  return(TRUE);
+    return TRUE;
 }
 
 
 BOOLEAN
 NtfsFCBIsRoot(PNTFS_FCB Fcb)
 {
-  return(wcscmp(Fcb->PathName, L"\\") == 0);
+    return (wcscmp(Fcb->PathName, L"\\") == 0);
 }
 
 
@@ -136,16 +136,16 @@ VOID
 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);
 }
 
 
@@ -153,22 +153,23 @@ VOID
 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);
+        CcUninitializeCacheMap(Fcb->FileObject, NULL, NULL);
+        NtfsDestroyFCB(Fcb);
+    }
+
+    KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
 }
 
 
@@ -176,12 +177,12 @@ VOID
 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);
 }
 
 
@@ -189,41 +190,42 @@ PNTFS_FCB
 NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
                      PCWSTR FileName)
 {
-  KIRQL  oldIrql;
-  PNTFS_FCB Fcb;
-  PLIST_ENTRY  current_entry;
-
-  KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
+    KIRQL oldIrql;
+    PNTFS_FCB Fcb;
+    PLIST_ENTRY current_entry;
 
-  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);
-  }
+    KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
 
-  current_entry = Vcb->FcbListHead.Flink;
-  while (current_entry != &Vcb->FcbListHead)
-  {
-    Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
-
-    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);
+
+        DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
+        if (_wcsicmp(FileName, Fcb->PathName) == 0)
+        {
+            Fcb->RefCount++;
+            KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+            return Fcb;
+        }
+
+        //FIXME: need to compare against short name in FCB here
+
+        current_entry = current_entry->Flink;
+    }
 
-    current_entry = current_entry->Flink;
-  }
-  KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
+    KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
 
-  return(NULL);
+    return NULL;
 }
 
 
@@ -231,81 +233,107 @@ NTSTATUS
 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;
-
-  Fcb = NtfsCreateFCB(L"\\", Vcb);
+    PNTFS_FCB Fcb;
+    PFILE_RECORD_HEADER MftRecord;
+    PFILENAME_ATTRIBUTE FileName;
+
+    MftRecord = ExAllocatePoolWithTag(NonPagedPool,
+                                      Vcb->NtfsInfo.BytesPerFileRecord,
+                                      TAG_NTFS);
+    if (MftRecord == NULL)
+    {
+        return NULL;
+    }
 
-//  memset(Fcb->entry.Filename, ' ', 11);
+    if (!NT_SUCCESS(ReadFileRecord(Vcb, NTFS_FILE_ROOT, MftRecord)))
+    {
+        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;
+    FileName = GetFileNameFromRecord(MftRecord);
+    if (!FileName)
+    {
+        return NULL;
+    }
 
-  NtfsFCBInitializeCache(Vcb, Fcb);
-  NtfsAddFCBToTable(Vcb, Fcb);
-  NtfsGrabFCB(Vcb, Fcb);
+    Fcb = NtfsCreateFCB(L"\\", Vcb);
+    if (!Fcb)
+    {
+        return NULL;
+    }
 
-  return(Fcb);
+    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);
+
+    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;
 }
 
 
@@ -344,60 +372,62 @@ NtfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt,
 
   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 = GetFileNameFromRecord(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
@@ -405,38 +435,39 @@ NtfsAttachFCBToFileObject(PNTFS_VCB Vcb,
                           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;
 }
 
 
@@ -446,108 +477,29 @@ NtfsDirFindFile(PNTFS_VCB Vcb,
                 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;
 }
 
 
@@ -557,124 +509,127 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
                   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 */