[fastfat_new]
authorAleksey Bragin <aleksey@reactos.org>
Tue, 29 Sep 2009 13:09:16 +0000 (13:09 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Tue, 29 Sep 2009 13:09:16 +0000 (13:09 +0000)
- Add directory path parsing which tries to find existing FCBs for path names.
- Add a framework for creating DCBs during path dissection. Currently just prints out path names.
- Cleanup fcb.c, Alexey Vlasov's version was great, but it is a bit different from what I want to implement now.

svn path=/trunk/; revision=43225

reactos/drivers/filesystems/fastfat_new/create.c
reactos/drivers/filesystems/fastfat_new/fastfat.h
reactos/drivers/filesystems/fastfat_new/fatstruc.h
reactos/drivers/filesystems/fastfat_new/fcb.c

index 090e5ee..6530750 100644 (file)
 #define NDEBUG
 #include "fastfat.h"
 
 #define NDEBUG
 #include "fastfat.h"
 
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlUpcaseUnicodeStringToCountedOemString(
+    IN OUT POEM_STRING DestinationString,
+    IN PCUNICODE_STRING SourceString,
+    IN BOOLEAN AllocateDestinationString
+);
+
+
 /* FUNCTIONS *****************************************************************/
 
 IO_STATUS_BLOCK
 /* FUNCTIONS *****************************************************************/
 
 IO_STATUS_BLOCK
@@ -52,7 +62,7 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
 
     /* Control blocks */
     PVCB Vcb, DecodedVcb;
 
     /* Control blocks */
     PVCB Vcb, DecodedVcb;
-    PFCB Fcb;
+    PFCB Fcb, NextFcb;
     PCCB Ccb;
     PFCB ParentDcb;
 
     PCCB Ccb;
     PFCB ParentDcb;
 
@@ -72,6 +82,11 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
     NTSTATUS Status;
     IO_STATUS_BLOCK Iosb;
     PIO_STACK_LOCATION IrpSp;
     NTSTATUS Status;
     IO_STATUS_BLOCK Iosb;
     PIO_STACK_LOCATION IrpSp;
+    BOOLEAN EndBackslash = FALSE, OpenedAsDos;
+    UNICODE_STRING RemainingPart, FirstName, NextName;
+    OEM_STRING AnsiFirstName;
+
+    Iosb.Status = STATUS_SUCCESS;
 
     /* Get current IRP stack location */
     IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
     /* Get current IRP stack location */
     IrpSp = IoGetCurrentIrpStackLocation(Irp);
@@ -266,10 +281,178 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
             ParentDcb = Vcb->RootDcb;
             DPRINT1("ParentDcb %p\n", ParentDcb);
         }
             ParentDcb = Vcb->RootDcb;
             DPRINT1("ParentDcb %p\n", ParentDcb);
         }
+
+        /* Check for backslash at the end */
+        if (FileName.Length &&
+            FileName.Buffer[FileName.Length / sizeof(WCHAR) - 1] == L'\\')
+        {
+            /* Cut it out */
+            FileName.Length -= sizeof(WCHAR);
+
+            /* Remember we cut it */
+            EndBackslash = TRUE;
+        }
+
+        /* Ensure the name is set */
+        if (!ParentDcb->FullFileName.Buffer)
+        {
+            DPRINT1("ParentDcb->FullFileName.Buffer is NULL\n");
+        }
+
+        /* Check max path length */
+        if (ParentDcb->FullFileName.Length + FileName.Length + sizeof(WCHAR) <= FileName.Length)
+        {
+            DPRINT1("Max length is way off\n");
+            Iosb.Status = STATUS_OBJECT_NAME_INVALID;
+            ASSERT(FALSE);
+        }
+
+        /* Loop through FCBs to find a good one */
+        while (TRUE)
+        {
+            Fcb = ParentDcb;
+
+            /* Dissect the name */
+            RemainingPart = FileName;
+            while (RemainingPart.Length)
+            {
+                FsRtlDissectName(RemainingPart, &FirstName, &NextName);
+
+                /* Check for validity */
+                if ((NextName.Length && NextName.Buffer[0] == L'\\') ||
+                    (NextName.Length > 255 * sizeof(WCHAR)))
+                {
+                    /* The name is invalid */
+                    DPRINT1("Invalid name found\n");
+                    Iosb.Status = STATUS_OBJECT_NAME_INVALID;
+                    ASSERT(FALSE);
+                }
+
+                /* Convert the name to ANSI */
+                AnsiFirstName.Buffer = ExAllocatePool(PagedPool, FirstName.Length);
+                AnsiFirstName.Length = 0;
+                AnsiFirstName.MaximumLength = FirstName.Length;
+                Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName, &FirstName, FALSE);
+
+                if (!NT_SUCCESS(Status))
+                {
+                    DPRINT1("RtlUpcaseUnicodeStringToCountedOemString() failed with 0x%08x\n", Status);
+                    ASSERT(FALSE);
+                    NextFcb = NULL;
+                    AnsiFirstName.Length = 0;
+                }
+                else
+                {
+                    /* Find the coresponding FCB */
+                    NextFcb = FatFindFcb(IrpContext,
+                                         &Fcb->Dcb.SplayLinksAnsi,
+                                        (PSTRING)&AnsiFirstName,
+                                         &OpenedAsDos);
+                }
+
+                /* Check if we found anything */
+                if (!NextFcb && Fcb->Dcb.SplayLinksUnicode)
+                {
+                    ASSERT(FALSE);
+                }
+
+                /* Move to the next FCB */
+                if (NextFcb)
+                {
+                    Fcb = NextFcb;
+                    RemainingPart = NextName;
+                }
+
+                /* Break out of this loop if nothing can be found */
+                if (!NextFcb ||
+                    NextName.Length == 0 ||
+                    FatNodeType(NextFcb) == FAT_NTC_FCB)
+                {
+                    break;
+                }
+            }
+
+            /* Ensure remaining name doesn't start from a backslash */
+            if (RemainingPart.Length &&
+                RemainingPart.Buffer[0] == L'\\')
+            {
+                /* Cut it */
+                RemainingPart.Buffer++;
+                RemainingPart.Length -= sizeof(WCHAR);
+            }
+
+            if (Fcb->Condition == FcbGood)
+            {
+                /* Good FCB, break out of the loop */
+                break;
+            }
+            else
+            {
+                ASSERT(FALSE);
+            }
+        }
+
+        /* We have a valid FCB now */
+        if (!RemainingPart.Length)
+        {
+            DPRINT1("It's possible to open an existing FCB\n");
+            ASSERT(FALSE);
+        }
+
+        /* During parsing we encountered a part which has no attached FCB/DCB.
+           Check that the parent is really DCB and not FCB */
+        if (FatNodeType(Fcb) != FAT_NTC_ROOT_DCB &&
+            FatNodeType(Fcb) != FAT_NTC_DCB)
+        {
+            DPRINT1("Weird FCB node type %x, expected DCB or root DCB\n", FatNodeType(Fcb));
+            ASSERT(FALSE);
+        }
+
+        /* Create additional DCBs for all path items */
+        ParentDcb = Fcb;
+        while (TRUE)
+        {
+            FsRtlDissectName(RemainingPart, &FirstName, &RemainingPart);
+
+            /* Check for validity */
+            if ((RemainingPart.Length && RemainingPart.Buffer[0] == L'\\') ||
+                (NextName.Length > 255 * sizeof(WCHAR)))
+            {
+                /* The name is invalid */
+                DPRINT1("Invalid name found\n");
+                Iosb.Status = STATUS_OBJECT_NAME_INVALID;
+                ASSERT(FALSE);
+            }
+
+            /* Convert the name to ANSI */
+            AnsiFirstName.Buffer = ExAllocatePool(PagedPool, FirstName.Length);
+            AnsiFirstName.Length = 0;
+            AnsiFirstName.MaximumLength = FirstName.Length;
+            Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName, &FirstName, FALSE);
+
+            if (!NT_SUCCESS(Status))
+            {
+                ASSERT(FALSE);
+            }
+
+            DPRINT1("FirstName %wZ, RemainingPart %wZ\n", &FirstName, &RemainingPart);
+
+            /* Break if came to the end */
+            if (!RemainingPart.Length) break;
+
+            // TODO: Create a DCB for this entry
+        }
+
+        // Simulate that we opened the file
+        //Iosb.Information = FILE_OPENED;
+        Irp->IoStatus.Information = FILE_OPENED;
+        FileObject->SectionObjectPointer = (PSECTION_OBJECT_POINTERS)0x1;
     }
 
     }
 
-    //return Iosb.Status;
-    return STATUS_SUCCESS;
+    /* Complete the request */
+    FatCompleteRequest(IrpContext, Irp, Iosb.Status);
+
+    return Iosb.Status;
 }
 
 NTSTATUS
 }
 
 NTSTATUS
index 7833e4d..349f3b8 100644 (file)
@@ -153,6 +153,14 @@ FatDecodeFileObject(IN PFILE_OBJECT FileObject,
                     OUT PFCB *FcbOrDcb,
                     OUT PCCB *Ccb);
 
                     OUT PFCB *FcbOrDcb,
                     OUT PCCB *Ccb);
 
+/* --------------------------------------------------------- fcb.c */
+
+PFCB NTAPI
+FatFindFcb(PFAT_IRP_CONTEXT IrpContext,
+           PRTL_SPLAY_LINKS *RootNode,
+           PSTRING AnsiName,
+           PBOOLEAN IsDosName);
+
 /* --------------------------------------------------------- fullfat.c */
 
 FF_T_SINT32
 /* --------------------------------------------------------- fullfat.c */
 
 FF_T_SINT32
index 290bb3a..6382f44 100644 (file)
@@ -221,13 +221,14 @@ enum _FCB_NAME_TYPE {
 } FCB_NAME_TYPE;
 
 typedef struct _FCB_NAME_LINK {
 } FCB_NAME_TYPE;
 
 typedef struct _FCB_NAME_LINK {
+    struct _FCB *Fcb;
     RTL_SPLAY_LINKS Links;
     union
     {
         OEM_STRING Ansi;
         UNICODE_STRING String;
     } Name;
     RTL_SPLAY_LINKS Links;
     union
     {
         OEM_STRING Ansi;
         UNICODE_STRING String;
     } Name;
-    UCHAR Type;
+    BOOLEAN IsDosName;
 } FCB_NAME_LINK, *PFCB_NAME_LINK;
 
 typedef enum _FCB_CONDITION
 } FCB_NAME_LINK, *PFCB_NAME_LINK;
 
 typedef enum _FCB_CONDITION
@@ -287,7 +288,9 @@ typedef struct _FCB
             PFILE_OBJECT StreamFileObject;
             /* Bitmap to search for free dirents. */
             RTL_BITMAP FreeBitmap;
             PFILE_OBJECT StreamFileObject;
             /* Bitmap to search for free dirents. */
             RTL_BITMAP FreeBitmap;
-            PRTL_SPLAY_LINKS SplayLinks;
+            /* Names */
+            PRTL_SPLAY_LINKS SplayLinksAnsi;
+            PRTL_SPLAY_LINKS SplayLinksUnicode;
         } Dcb;
     };
 } FCB, *PFCB;
         } Dcb;
     };
 } FCB, *PFCB;
index c52d152..21e2938 100644 (file)
@@ -3,7 +3,7 @@
  * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            drivers/filesystems/fastfat/fcb.c
  * PURPOSE:         FCB manipulation routines.
  * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            drivers/filesystems/fastfat/fcb.c
  * PURPOSE:         FCB manipulation routines.
- * PROGRAMMERS:     Alexey Vlasov
+ * PROGRAMMERS:     Aleksey Bragin <aleksey@reactos.org>
  */
 
 /* INCLUDES *****************************************************************/
  */
 
 /* INCLUDES *****************************************************************/
 #include "fastfat.h"
 
 /* FUNCTIONS ****************************************************************/
 #include "fastfat.h"
 
 /* FUNCTIONS ****************************************************************/
-#if 0
-/**
- * Locates FCB by the supplied name in the cache trie of fcbs.
- *
- * @param ParentFcb
- * Supplies a pointer to the parent FCB
- *
- * @param Name
- * Supplied a name of the FCB to be located in cache.
- *
- * @return
- * Pointer to the found FCB or NULL.
- */
-PFCB
-FatLookupFcbByName(
-       IN PFCB ParentFcb,
-       IN PUNICODE_STRING Name)
-{
-    PFCB_NAME_LINK Node;
-       PRTL_SPLAY_LINKS Links;
-
-    /* Get sub-trie root node from the parent FCB */
-       Links = ParentFcb->Dcb.SplayLinks;
-       while (Links != NULL)
-       {
-               LONG Comparison;
-
-               Node = CONTAINING_RECORD(Links, FCB_NAME_LINK, Links);
 
 
-       /*
-        * Compare the name stored in the node
-        * and determine the direction to walk.
-        */
-               Comparison = RtlCompareUnicodeString(&Node->String, Name, TRUE);
-               if (Comparison > 0) {
-            /* Left child */
-                       Links = RtlLeftChild(&Node->Links);
-               }
-               else if (Comparison < 0)
-               {
-            /* Right child */
-                       Links = RtlRightChild(&Node->Links);
-               }
-               else
-               {
-            /* Strings are equal, we have found the node! */
-                       break;
-               }
-       }
-
-    /* The case when nothing was found. */
-       if (Links == NULL)
-               return NULL;
-
-    /* Cast node to the FCB structure. */
-       return CONTAINING_RECORD(Links, FCB, FileName[Node->Type]);
-}
-
-/**
- * Inserts FCB into FCBs cache trie.
- *
- * @param ParentFcb
- * Supplies a pointer to the parent FCB
- *
- * @param Fcb
- * Supplied a pointer to the being inserted FCB.
- *
- * @return
- * TRUE if the FCB was successfully inserted,
- * FASLE in the case of name collision.
- */
-BOOLEAN
-FatLinkFcbNames(
-       IN PFCB ParentFcb,
-       IN PFCB Fcb)
+FSRTL_COMPARISON_RESULT
+NTAPI
+FatiCompareNames(PSTRING NameA,
+                 PSTRING NameB)
 {
 {
-    PFCB_NAME_LINK Name;
-       PRTL_SPLAY_LINKS Links;
-       
-    /* None of the parameters can be NULL */
-       ASSERT(ParentFcb != NULL && Fcb != NULL);
+    ULONG MinimumLen, i;
 
 
-    /* Get root links of the parent FCB. */
-       Links = ParentFcb->Dcb.SplayLinks;
+    /* Calc the minimum length */
+    MinimumLen = NameA->Length < NameB->Length ? NameA->Length :
+                                                NameB->Length;
 
 
-   /*
-    * Get first file name
-    * (short name for FAT because it's always there.
-    */
-       Name = Fcb->FileName;
-
-   /*
-    * Check if ParentDcb links are initialized,
-    * at least one child FCB is cached.
-    */
-       if (Links == NULL)
-       {
-               ParentFcb->Dcb.SplayLinks = Links = &Name->Links;
-               RtlInitializeSplayLinks(Links);
-
-        /* Check if we have more names to cache. */
-               if ((++Name)->String.Length == 0)
-                       return TRUE;
-       }
-    /* Lookup for the insertion point in the trie. */
-       do
-       {
-               LONG Comparison;
-               PFCB_NAME_LINK Node;
-               PRTL_SPLAY_LINKS PrevLinks;
-
-               PrevLinks = Links;
-               Node = CONTAINING_RECORD(Links, FCB_NAME_LINK, Links);
-               Comparison = RtlCompareUnicodeString(&Node->String, &Name->String, TRUE);
-               if (Comparison > 0) {
-                       Links = RtlLeftChild(&Node->Links);
-                       if (Links == NULL)
-                       {
-                               RtlInsertAsLeftChild(PrevLinks, &Name->Links);
-                               break;
-                       }
-               }
-               else if (Comparison < 0)
-               {
-                       Links = RtlRightChild(&Node->Links);
-                       if (Links == NULL)
-                       {
-                               RtlInsertAsRightChild(PrevLinks, &Name->Links);
-                               break;
-                       }
-               }
-               else
-               {
-                       return FALSE;
-               }
-
-        /* Possibly switch to the second (lfn) name and cache that. */
-       } while (Name == Fcb->FileName && (++Name)->String.Length > 0);
-       return TRUE;
-}
-
-/**
- * Unlinks FCB from the FCBs cache trie.
- *
- * @param ParentFcb
- * Supplies a pointer to the parent FCB
- *
- * @param Fcb
- * Supplied a pointer to the being unlinked FCB.
- *
- * @return
- * VOID
- */
-VOID
-FatUnlinkFcbNames(
-       IN PFCB ParentFcb,
-       IN PFCB Fcb)
-{
-    /* See if there is an lfn and unlink that. */
-       if (Fcb->FileName[FcbLongName].String.Length > 0)
-               ParentFcb->Dcb.SplayLinks =
-                       RtlDelete(&Fcb->FileName[FcbLongName].Links);
-
-    /* See if there is a short name and unlink that. */
-       if (Fcb->FileName[FcbShortName].String.Length > 0)
-               ParentFcb->Dcb.SplayLinks =
-                       RtlDelete(&Fcb->FileName[FcbShortName].Links);
-}
+    /* Actually compare them */
+    i = (ULONG)RtlCompareMemory( NameA->Buffer, NameB->Buffer, MinimumLen );
 
 
-NTSTATUS
-FatCreateFcb(
-    OUT PFCB* CreatedFcb,
-    IN PFAT_IRP_CONTEXT IrpContext,
-    IN PFCB ParentFcb,
-       IN PDIR_ENTRY Dirent,
-    IN PUNICODE_STRING FileName,
-       IN PUNICODE_STRING LongFileName OPTIONAL)
-{
-       NTSTATUS Status;
-       PFCB Fcb;
-
-    /* Allocate FCB structure. */
-       Fcb = (PFCB) ExAllocateFromNPagedLookasideList(&FatGlobalData.NonPagedFcbList);
-       if (Fcb == NULL)
-               return STATUS_INSUFFICIENT_RESOURCES;
-       RtlZeroMemory(Fcb, sizeof(FCB));
-
-    /* Setup FCB Advanced Header. */
-       Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
-       Fcb->Header.NodeByteSize = sizeof(*Fcb);
-       ExInitializeResourceLite(&Fcb->Resource);
-       Fcb->Header.Resource = &Fcb->Resource;
-       ExInitializeResourceLite(&Fcb->PagingIoResource);
-       Fcb->Header.PagingIoResource = &Fcb->PagingIoResource;
-       ExInitializeFastMutex(&Fcb->HeaderMutex);
-       FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
-       Fcb->Header.FileSize.QuadPart = Dirent->FileSize;
-       Fcb->Header.ValidDataLength.QuadPart = Dirent->FileSize;
-       Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
-
-    /* Setup main fields. */
-       FsRtlInitializeFileLock(&Fcb->Lock, NULL, NULL);
-       FsRtlInitializeLargeMcb(&Fcb->Mcb, PagedPool);
-       Fcb->Vcb = IrpContext->Vcb;
-       Fcb->ParentFcb = ParentFcb;
-       Fcb->FirstCluster = Dirent->FirstCluster
-               | (Dirent->FirstClusterOfFileHi << 0x10);
-
-    /* Setup basic info. */
-    Fcb->BasicInfo.FileAttributes = Dirent->Attributes;
-    FatQueryFileTimes(&Fcb->BasicInfo.CreationTime, Dirent);
-
-    /* Setup short name since always present in FAT. */
-       Fcb->FileName[FcbShortName].Type = FcbShortName;
-       Fcb->FileName[FcbShortName].String.Buffer = Fcb->ShortNameBuffer;
-       Fcb->FileName[FcbShortName].String.MaximumLength = 0x0c;
-       Fcb->FileName[FcbShortName].String.Length = FileName->Length;
-    RtlCopyMemory(Fcb->ShortNameBuffer, FileName->Buffer, FileName->Length);
-
-    /* Just swap optional lfn. */
-       if (ARGUMENT_PRESENT(LongFileName) && LongFileName->Length > 0)
-       {
-               Fcb->FileName[FcbLongName].Type = FcbLongName;
-        Fcb->FileName[FcbLongName].String = *LongFileName;
-        RtlZeroMemory(LongFileName, sizeof(UNICODE_STRING));
-       }
-
-    /* Put FCB into cache trie. */
-       if (!FatLinkFcbNames(ParentFcb, Fcb))
-       {
-               Status = STATUS_OBJECT_NAME_COLLISION;
-               goto FsdFatCreateFcbCleanup;
-       }
-    *CreatedFcb = Fcb;
-
-    /* We are done! */
-       return STATUS_SUCCESS;
-
-FsdFatCreateFcbCleanup:
-    if (ARGUMENT_PRESENT(LongFileName) &&
-        Fcb->FileName[FcbLongName].String.Buffer != NULL)
+    if (i < MinimumLen)
     {
     {
-        /* Swap lfn back to the input parameter */
-        *LongFileName = Fcb->FileName[FcbLongName].String;
+        /* Compare prefixes */
+        if (NameA->Buffer[i] < NameB->Buffer[i])
+            return LessThan;
+        else
+            return GreaterThan;
     }
     }
-    ExFreeToNPagedLookasideList(&FatGlobalData.NonPagedFcbList, Fcb);
-       return Status;
+
+    /* Final comparison */
+    if (NameA->Length < NameB->Length)
+        return LessThan;
+    else if (NameA->Length > NameB->Length)
+        return GreaterThan;
+    else
+        return EqualTo;
 }
 
 }
 
-NTSTATUS
-FatOpenFcb(
-    OUT PFCB* Fcb,
-    IN PFAT_IRP_CONTEXT IrpContext,
-    IN PFCB ParentFcb,
-    IN PUNICODE_STRING FileName)
+PFCB
+NTAPI
+FatFindFcb(PFAT_IRP_CONTEXT IrpContext,
+           PRTL_SPLAY_LINKS *RootNode,
+           PSTRING AnsiName,
+           PBOOLEAN IsDosName)
 {
 {
-    FAT_FIND_DIRENT_CONTEXT Context;
-    UNICODE_STRING LongFileName;
-    PDIR_ENTRY Dirent;
-    NTSTATUS Status;
-
-    // TODO: _SEH_TRY {
-    if (ParentFcb->Dcb.StreamFileObject == NULL)
-    {
-        PFILE_OBJECT FileObject;
-        PVPB Vpb;
-    
-        Vpb = IrpContext->Vcb->Vpb;
-
-        /* Create stream file object */
-        FileObject = IoCreateStreamFileObject(NULL, Vpb->RealDevice);
-        FileObject->Vpb = Vpb;
-        FileObject->SectionObjectPointer = &ParentFcb->SectionObjectPointers;
-        FileObject->FsContext = ParentFcb;
-        FileObject->FsContext2 = NULL;
-
-        /* Store it in parent fcb */
-        ParentFcb->Dcb.StreamFileObject = FileObject;
+    PFCB_NAME_LINK Node;
+    FSRTL_COMPARISON_RESULT Comparison;
+    PRTL_SPLAY_LINKS Links;
 
 
-    }
+    Links = *RootNode;
 
 
-    /* Check if cache is initialized. */
-    if (ParentFcb->Dcb.StreamFileObject->PrivateCacheMap == NULL )
+    while (Links)
     {
     {
-        CcInitializeCacheMap(ParentFcb->Dcb.StreamFileObject,
-            (PCC_FILE_SIZES) &ParentFcb->Header.AllocationSize,
-            TRUE,
-            &FatGlobalData.CacheMgrNoopCallbacks,
-            ParentFcb);
+        Node = CONTAINING_RECORD(Links, FCB_NAME_LINK, Links);
+
+        /* Compare the prefix */
+        if (*(PUCHAR)Node->Name.Ansi.Buffer != *(PUCHAR)AnsiName->Buffer)
+        {
+            if (*(PUCHAR)Node->Name.Ansi.Buffer < *(PUCHAR)AnsiName->Buffer)
+                Comparison = LessThan;
+            else
+                Comparison = GreaterThan;
+        }
+        else
+        {
+            /* Perform real comparison */
+            Comparison = FatiCompareNames(&Node->Name.Ansi, AnsiName);
+        }
+
+        /* Do they match? */
+        if (Comparison == GreaterThan)
+        {
+            /* No, it's greater, go to the left child */
+            Links = RtlLeftChild(Links);
+        }
+        else if (Comparison == LessThan)
+        {
+            /* No, it's lesser, go to the right child */
+            Links = RtlRightChild(Links);
+        }
+        else
+        {
+            /* Exact match, balance the tree */
+            *RootNode = RtlSplay(Links);
+
+            /* Save type of the name, if needed */
+            if (IsDosName)
+                *IsDosName = Node->IsDosName;
+
+            /* Return the found fcb */
+            return Node->Fcb;
+        }
     }
 
     }
 
-    /* Page context */
-    Context.Page.FileObject = ParentFcb->Dcb.StreamFileObject;
-    Context.Page.EndOfData = ParentFcb->Header.FileSize;
-    Context.Page.Offset.QuadPart = -1LL;
-    Context.Page.Bcb = NULL;
-    Context.Page.CanWait = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT);
-    Context.Page.EndOfData = ParentFcb->Header.FileSize;
+    /* Nothing found */
+    return NULL;
+}
 
 
-    /* Search context */
-    Context.ShortName.Length = 0;
-    Context.ShortName.Buffer = Context.ShortNameBuffer;
-    Context.ShortName.MaximumLength = sizeof(Context.ShortNameBuffer);
-    Context.FileName = FileName;
-    Context.Valid8dot3Name = RtlIsNameLegalDOS8Dot3(FileName, NULL, NULL);
 
 
-    /* Locate the dirent */
-    FatFindDirent(&Context, &Dirent, &LongFileName);
-    Status = FatCreateFcb(Fcb, IrpContext, ParentFcb, Dirent,
-        &Context.ShortName, &LongFileName);
-    return Status;
-}
-#endif
 /* EOF */
 /* EOF */