Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / reactos / drivers / filesystems / fastfat / fcb.c
diff --git a/reactos/drivers/filesystems/fastfat/fcb.c b/reactos/drivers/filesystems/fastfat/fcb.c
deleted file mode 100644 (file)
index 4a103b0..0000000
+++ /dev/null
@@ -1,1055 +0,0 @@
-/*
-* FILE:             drivers/filesystems/fastfat/fcb.c
-* PURPOSE:          Routines to manipulate FCBs.
-* COPYRIGHT:        See COPYING in the top level directory
-* PROJECT:          ReactOS kernel
-* PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
-*                   Rex Jolliff (rex@lvcablemodem.com)
-*                   Herve Poussineau (reactos@poussine.freesurf.fr)
-*                   Pierre Schweitzer (pierre@reactos.org)
-*/
-
-/*  -------------------------------------------------------  INCLUDES  */
-
-#include "vfat.h"
-
-#define NDEBUG
-#include <debug.h>
-
-#ifdef __GNUC__
-#include <wctype.h> /* towlower prototype */
-#endif
-
-/*  --------------------------------------------------------  DEFINES  */
-
-#define TAG_FCB 'BCFV'
-
-/*  --------------------------------------------------------  PUBLICS  */
-
-static
-ULONG
-vfatNameHash(
-    ULONG hash,
-    PUNICODE_STRING NameU)
-{
-    PWCHAR last;
-    PWCHAR curr;
-    register WCHAR c;
-
-    // LFN could start from "."
-    //ASSERT(NameU->Buffer[0] != L'.');
-    curr = NameU->Buffer;
-    last = NameU->Buffer + NameU->Length / sizeof(WCHAR);
-
-    while(curr < last)
-    {
-        c = towlower(*curr++);
-        hash = (hash + (c << 4) + (c >> 4)) * 11;
-    }
-    return hash;
-}
-
-VOID
-vfatSplitPathName(
-    PUNICODE_STRING PathNameU,
-    PUNICODE_STRING DirNameU,
-    PUNICODE_STRING FileNameU)
-{
-    PWCHAR pName;
-    USHORT Length = 0;
-    pName = PathNameU->Buffer + PathNameU->Length / sizeof(WCHAR) - 1;
-    while (*pName != L'\\' && pName >= PathNameU->Buffer)
-    {
-        pName--;
-        Length++;
-    }
-    ASSERT(*pName == L'\\' || pName < PathNameU->Buffer);
-    if (FileNameU)
-    {
-        FileNameU->Buffer = pName + 1;
-        FileNameU->Length = FileNameU->MaximumLength = Length * sizeof(WCHAR);
-    }
-    if (DirNameU)
-    {
-        DirNameU->Buffer = PathNameU->Buffer;
-        DirNameU->Length = (pName + 1 - PathNameU->Buffer) * sizeof(WCHAR);
-        DirNameU->MaximumLength = DirNameU->Length;
-    }
-}
-
-static
-VOID
-vfatInitFcb(
-    PVFATFCB Fcb,
-    PUNICODE_STRING NameU)
-{
-    USHORT PathNameBufferLength;
-
-    if (NameU)
-        PathNameBufferLength = NameU->Length + sizeof(WCHAR);
-    else
-        PathNameBufferLength = 0;
-
-    Fcb->PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameBufferLength, TAG_FCB);
-    if (!Fcb->PathNameBuffer)
-    {
-        /* FIXME: what to do if no more memory? */
-        DPRINT1("Unable to initialize FCB for filename '%wZ'\n", NameU);
-        KeBugCheckEx(FAT_FILE_SYSTEM, (ULONG_PTR)Fcb, (ULONG_PTR)NameU, 0, 0);
-    }
-
-    Fcb->PathNameU.Length = 0;
-    Fcb->PathNameU.Buffer = Fcb->PathNameBuffer;
-    Fcb->PathNameU.MaximumLength = PathNameBufferLength;
-    Fcb->ShortNameU.Length = 0;
-    Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer;
-    Fcb->ShortNameU.MaximumLength = sizeof(Fcb->ShortNameBuffer);
-    Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
-    if (NameU && NameU->Length)
-    {
-        RtlCopyUnicodeString(&Fcb->PathNameU, NameU);
-        vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
-    }
-    else
-    {
-        Fcb->DirNameU.Buffer = Fcb->LongNameU.Buffer = NULL;
-        Fcb->DirNameU.MaximumLength = Fcb->DirNameU.Length = 0;
-        Fcb->LongNameU.MaximumLength = Fcb->LongNameU.Length = 0;
-    }
-    RtlZeroMemory(&Fcb->FCBShareAccess, sizeof(SHARE_ACCESS));
-    Fcb->OpenHandleCount = 0;
-}
-
-PVFATFCB
-vfatNewFCB(
-    PDEVICE_EXTENSION pVCB,
-    PUNICODE_STRING pFileNameU)
-{
-    PVFATFCB  rcFCB;
-
-    DPRINT("'%wZ'\n", pFileNameU);
-
-    rcFCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->FcbLookasideList);
-    if (rcFCB == NULL)
-    {
-        return NULL;
-    }
-    RtlZeroMemory(rcFCB, sizeof(VFATFCB));
-    vfatInitFcb(rcFCB, pFileNameU);
-    if (vfatVolumeIsFatX(pVCB))
-        rcFCB->Attributes = &rcFCB->entry.FatX.Attrib;
-    else
-        rcFCB->Attributes = &rcFCB->entry.Fat.Attrib;
-    rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU);
-    rcFCB->Hash.self = rcFCB;
-    rcFCB->ShortHash.self = rcFCB;
-    ExInitializeResourceLite(&rcFCB->PagingIoResource);
-    ExInitializeResourceLite(&rcFCB->MainResource);
-    FsRtlInitializeFileLock(&rcFCB->FileLock, NULL, NULL);
-    ExInitializeFastMutex(&rcFCB->LastMutex);
-    rcFCB->RFCB.PagingIoResource = &rcFCB->PagingIoResource;
-    rcFCB->RFCB.Resource = &rcFCB->MainResource;
-    rcFCB->RFCB.IsFastIoPossible = FastIoIsNotPossible;
-    InitializeListHead(&rcFCB->ParentListHead);
-
-    return  rcFCB;
-}
-
-static
-VOID
-vfatDelFCBFromTable(
-    PDEVICE_EXTENSION pVCB,
-    PVFATFCB pFCB)
-{
-    ULONG Index;
-    ULONG ShortIndex;
-    HASHENTRY* entry;
-
-    Index = pFCB->Hash.Hash % pVCB->HashTableSize;
-    ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
-
-    if (pFCB->Hash.Hash != pFCB->ShortHash.Hash)
-    {
-        entry = pVCB->FcbHashTable[ShortIndex];
-        if (entry->self == pFCB)
-        {
-            pVCB->FcbHashTable[ShortIndex] = entry->next;
-        }
-        else
-        {
-            while (entry->next->self != pFCB)
-            {
-                entry = entry->next;
-            }
-            entry->next = pFCB->ShortHash.next;
-        }
-    }
-    entry = pVCB->FcbHashTable[Index];
-    if (entry->self == pFCB)
-    {
-        pVCB->FcbHashTable[Index] = entry->next;
-    }
-    else
-    {
-        while (entry->next->self != pFCB)
-        {
-            entry = entry->next;
-        }
-        entry->next = pFCB->Hash.next;
-    }
-
-    RemoveEntryList(&pFCB->FcbListEntry);
-}
-
-static
-NTSTATUS
-vfatMakeFullName(
-    PVFATFCB directoryFCB,
-    PUNICODE_STRING LongNameU,
-    PUNICODE_STRING ShortNameU,
-    PUNICODE_STRING NameU)
-{
-    PWCHAR PathNameBuffer;
-    USHORT PathNameLength;
-
-    PathNameLength = directoryFCB->PathNameU.Length + max(LongNameU->Length, ShortNameU->Length);
-    if (!vfatFCBIsRoot(directoryFCB))
-    {
-        PathNameLength += sizeof(WCHAR);
-    }
-
-    if (PathNameLength > LONGNAME_MAX_LENGTH * sizeof(WCHAR))
-    {
-        return  STATUS_OBJECT_NAME_INVALID;
-    }
-    PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameLength + sizeof(WCHAR), TAG_FCB);
-    if (!PathNameBuffer)
-    {
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-    NameU->Buffer = PathNameBuffer;
-    NameU->Length = 0;
-    NameU->MaximumLength = PathNameLength;
-
-    RtlCopyUnicodeString(NameU, &directoryFCB->PathNameU);
-    if (!vfatFCBIsRoot(directoryFCB))
-    {
-        RtlAppendUnicodeToString(NameU, L"\\");
-    }
-    if (LongNameU->Length > 0)
-    {
-        RtlAppendUnicodeStringToString(NameU, LongNameU);
-    }
-    else
-    {
-        RtlAppendUnicodeStringToString(NameU, ShortNameU);
-    }
-    NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
-
-    return STATUS_SUCCESS;
-}
-
-VOID
-vfatDestroyCCB(
-    PVFATCCB pCcb)
-{
-    if (pCcb->SearchPattern.Buffer)
-    {
-        ExFreePoolWithTag(pCcb->SearchPattern.Buffer, TAG_VFAT);
-    }
-    ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, pCcb);
-}
-
-VOID
-vfatDestroyFCB(
-    PVFATFCB pFCB)
-{
-    FsRtlUninitializeFileLock(&pFCB->FileLock);
-    if (!vfatFCBIsRoot(pFCB) &&
-        !BooleanFlagOn(pFCB->Flags, FCB_IS_FAT) && !BooleanFlagOn(pFCB->Flags, FCB_IS_VOLUME))
-    {
-        RemoveEntryList(&pFCB->ParentListEntry);
-    }
-    ExFreePool(pFCB->PathNameBuffer);
-    ExDeleteResourceLite(&pFCB->PagingIoResource);
-    ExDeleteResourceLite(&pFCB->MainResource);
-    ASSERT(IsListEmpty(&pFCB->ParentListHead));
-    ExFreeToNPagedLookasideList(&VfatGlobalData->FcbLookasideList, pFCB);
-}
-
-BOOLEAN
-vfatFCBIsRoot(
-    PVFATFCB FCB)
-{
-    return FCB->PathNameU.Length == sizeof(WCHAR) && FCB->PathNameU.Buffer[0] == L'\\' ? TRUE : FALSE;
-}
-
-VOID
-vfatGrabFCB(
-    PDEVICE_EXTENSION pVCB,
-    PVFATFCB pFCB)
-{
-    ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
-
-    ASSERT(pFCB != pVCB->VolumeFcb);
-    ASSERT(pFCB->RefCount > 0);
-    ++pFCB->RefCount;
-}
-
-VOID
-vfatReleaseFCB(
-    PDEVICE_EXTENSION pVCB,
-    PVFATFCB pFCB)
-{
-    PVFATFCB tmpFcb;
-
-    DPRINT("releasing FCB at %p: %wZ, refCount:%d\n",
-           pFCB, &pFCB->PathNameU, pFCB->RefCount);
-
-    ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
-
-    while (pFCB)
-    {
-        ASSERT(pFCB != pVCB->VolumeFcb);
-        ASSERT(pFCB->RefCount > 0);
-        pFCB->RefCount--;
-        if (pFCB->RefCount == 0)
-        {
-            ASSERT(pFCB->OpenHandleCount == 0);
-            tmpFcb = pFCB->parentFcb;
-            vfatDelFCBFromTable(pVCB, pFCB);
-            vfatDestroyFCB(pFCB);
-        }
-        else
-        {
-            tmpFcb = NULL;
-        }
-        pFCB = tmpFcb;
-    }
-}
-
-static
-VOID
-vfatAddFCBToTable(
-    PDEVICE_EXTENSION pVCB,
-    PVFATFCB pFCB)
-{
-    ULONG Index;
-    ULONG ShortIndex;
-
-    ASSERT(pFCB->Hash.Hash == vfatNameHash(0, &pFCB->PathNameU));
-    Index = pFCB->Hash.Hash % pVCB->HashTableSize;
-    ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
-
-    InsertTailList(&pVCB->FcbListHead, &pFCB->FcbListEntry);
-
-    pFCB->Hash.next = pVCB->FcbHashTable[Index];
-    pVCB->FcbHashTable[Index] = &pFCB->Hash;
-    if (pFCB->Hash.Hash != pFCB->ShortHash.Hash)
-    {
-        pFCB->ShortHash.next = pVCB->FcbHashTable[ShortIndex];
-        pVCB->FcbHashTable[ShortIndex] = &pFCB->ShortHash;
-    }
-    if (pFCB->parentFcb)
-    {
-        vfatGrabFCB(pVCB, pFCB->parentFcb);
-    }
-}
-
-static
-VOID
-vfatInitFCBFromDirEntry(
-    PDEVICE_EXTENSION Vcb,
-    PVFATFCB Fcb,
-    PVFAT_DIRENTRY_CONTEXT DirContext)
-{
-    ULONG Size;
-
-    RtlCopyMemory(&Fcb->entry, &DirContext->DirEntry, sizeof (DIR_ENTRY));
-    RtlCopyUnicodeString(&Fcb->ShortNameU, &DirContext->ShortNameU);
-    Fcb->Hash.Hash = vfatNameHash(0, &Fcb->PathNameU);
-    if (vfatVolumeIsFatX(Vcb))
-    {
-        Fcb->ShortHash.Hash = Fcb->Hash.Hash;
-    }
-    else
-    {
-        Fcb->ShortHash.Hash = vfatNameHash(0, &Fcb->DirNameU);
-        Fcb->ShortHash.Hash = vfatNameHash(Fcb->ShortHash.Hash, &Fcb->ShortNameU);
-    }
-
-    if (vfatFCBIsDirectory(Fcb))
-    {
-        ULONG FirstCluster, CurrentCluster;
-        NTSTATUS Status = STATUS_SUCCESS;
-        Size = 0;
-        FirstCluster = vfatDirEntryGetFirstCluster(Vcb, &Fcb->entry);
-        if (FirstCluster == 1)
-        {
-            Size = Vcb->FatInfo.rootDirectorySectors * Vcb->FatInfo.BytesPerSector;
-        }
-        else if (FirstCluster != 0)
-        {
-            CurrentCluster = FirstCluster;
-            while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
-            {
-                Size += Vcb->FatInfo.BytesPerCluster;
-                Status = NextCluster(Vcb, FirstCluster, &CurrentCluster, FALSE);
-            }
-        }
-    }
-    else if (vfatVolumeIsFatX(Vcb))
-    {
-        Size = Fcb->entry.FatX.FileSize;
-    }
-    else
-    {
-        Size = Fcb->entry.Fat.FileSize;
-    }
-    Fcb->dirIndex = DirContext->DirIndex;
-    Fcb->startIndex = DirContext->StartIndex;
-    if (vfatVolumeIsFatX(Vcb) && !vfatFCBIsRoot(Fcb))
-    {
-        ASSERT(DirContext->DirIndex >= 2 && DirContext->StartIndex >= 2);
-        Fcb->dirIndex = DirContext->DirIndex-2;
-        Fcb->startIndex = DirContext->StartIndex-2;
-    }
-    Fcb->RFCB.FileSize.QuadPart = Size;
-    Fcb->RFCB.ValidDataLength.QuadPart = Size;
-    Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP_64(Size, Vcb->FatInfo.BytesPerCluster);
-}
-
-NTSTATUS
-vfatSetFCBNewDirName(
-    PDEVICE_EXTENSION pVCB,
-    PVFATFCB Fcb,
-    PVFATFCB ParentFcb)
-{
-    NTSTATUS Status;
-    UNICODE_STRING NewNameU;
-
-    /* Get full path name */
-    Status = vfatMakeFullName(ParentFcb, &Fcb->LongNameU, &Fcb->ShortNameU, &NewNameU);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    /* Delete old name */
-    if (Fcb->PathNameBuffer)
-    {
-        ExFreePoolWithTag(Fcb->PathNameBuffer, TAG_FCB);
-    }
-    Fcb->PathNameU = NewNameU;
-
-    /* Delete from table */
-    vfatDelFCBFromTable(pVCB, Fcb);
-
-    /* Split it properly */
-    Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
-    Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
-    vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
-    Fcb->Hash.Hash = vfatNameHash(0, &Fcb->PathNameU);
-    if (vfatVolumeIsFatX(pVCB))
-    {
-        Fcb->ShortHash.Hash = Fcb->Hash.Hash;
-    }
-    else
-    {
-        Fcb->ShortHash.Hash = vfatNameHash(0, &Fcb->DirNameU);
-        Fcb->ShortHash.Hash = vfatNameHash(Fcb->ShortHash.Hash, &Fcb->ShortNameU);
-    }
-
-    vfatAddFCBToTable(pVCB, Fcb);
-    vfatReleaseFCB(pVCB, ParentFcb);
-
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-vfatUpdateFCB(
-    PDEVICE_EXTENSION pVCB,
-    PVFATFCB Fcb,
-    PVFAT_DIRENTRY_CONTEXT DirContext,
-    PVFATFCB ParentFcb)
-{
-    NTSTATUS Status;
-    PVFATFCB OldParent;
-
-    DPRINT("vfatUpdateFCB(%p, %p, %p, %p)\n", pVCB, Fcb, DirContext, ParentFcb);
-
-    /* Get full path name */
-    Status = vfatMakeFullName(ParentFcb, &DirContext->LongNameU, &DirContext->ShortNameU, &Fcb->PathNameU);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    /* Delete old name */
-    if (Fcb->PathNameBuffer)
-    {
-        ExFreePoolWithTag(Fcb->PathNameBuffer, TAG_FCB);
-    }
-
-    /* Delete from table */
-    vfatDelFCBFromTable(pVCB, Fcb);
-
-    /* Split it properly */
-    Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
-    Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
-    vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
-
-    /* Save old parent */
-    OldParent = Fcb->parentFcb;
-    RemoveEntryList(&Fcb->ParentListEntry);
-
-    /* Reinit FCB */
-    vfatInitFCBFromDirEntry(pVCB, Fcb, DirContext);
-
-    if (vfatFCBIsDirectory(Fcb))
-    {
-        CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
-    }
-    Fcb->parentFcb = ParentFcb;
-    InsertTailList(&ParentFcb->ParentListHead, &Fcb->ParentListEntry);
-    vfatAddFCBToTable(pVCB, Fcb);
-
-    /* If we moved across directories, dereference our old parent
-     * We also dereference in case we're just renaming since AddFCBToTable references it
-     */
-    vfatReleaseFCB(pVCB, OldParent);
-
-    return STATUS_SUCCESS;
-}
-
-PVFATFCB
-vfatGrabFCBFromTable(
-    PDEVICE_EXTENSION pVCB,
-    PUNICODE_STRING PathNameU)
-{
-    PVFATFCB  rcFCB;
-    ULONG Hash;
-    UNICODE_STRING DirNameU;
-    UNICODE_STRING FileNameU;
-    PUNICODE_STRING FcbNameU;
-
-    HASHENTRY* entry;
-
-    DPRINT("'%wZ'\n", PathNameU);
-
-    ASSERT(PathNameU->Length >= sizeof(WCHAR) && PathNameU->Buffer[0] == L'\\');
-    Hash = vfatNameHash(0, PathNameU);
-
-    entry = pVCB->FcbHashTable[Hash % pVCB->HashTableSize];
-    if (entry)
-    {
-        vfatSplitPathName(PathNameU, &DirNameU, &FileNameU);
-    }
-
-    while (entry)
-    {
-        if (entry->Hash == Hash)
-        {
-            rcFCB = entry->self;
-            DPRINT("'%wZ' '%wZ'\n", &DirNameU, &rcFCB->DirNameU);
-            if (RtlEqualUnicodeString(&DirNameU, &rcFCB->DirNameU, TRUE))
-            {
-                if (rcFCB->Hash.Hash == Hash)
-                {
-                    FcbNameU = &rcFCB->LongNameU;
-                }
-                else
-                {
-                    FcbNameU = &rcFCB->ShortNameU;
-                }
-                /* compare the file name */
-                DPRINT("'%wZ' '%wZ'\n", &FileNameU, FcbNameU);
-                if (RtlEqualUnicodeString(&FileNameU, FcbNameU, TRUE))
-                {
-                    vfatGrabFCB(pVCB, rcFCB);
-                    return rcFCB;
-                }
-            }
-        }
-        entry = entry->next;
-    }
-    return NULL;
-}
-
-static
-NTSTATUS
-vfatFCBInitializeCacheFromVolume(
-    PVCB vcb,
-    PVFATFCB fcb)
-{
-    PFILE_OBJECT fileObject;
-    PVFATCCB newCCB;
-    NTSTATUS status;
-
-    fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
-
-    newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
-    if (newCCB == NULL)
-    {
-        ObDereferenceObject(fileObject);
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-    RtlZeroMemory(newCCB, sizeof (VFATCCB));
-
-    fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
-    fileObject->FsContext = fcb;
-    fileObject->FsContext2 = newCCB;
-    fcb->FileObject = fileObject;
-
-    _SEH2_TRY
-    {
-        CcInitializeCacheMap(fileObject,
-                             (PCC_FILE_SIZES)(&fcb->RFCB.AllocationSize),
-                             TRUE,
-                             &VfatGlobalData->CacheMgrCallbacks,
-                             fcb);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        status = _SEH2_GetExceptionCode();
-        fcb->FileObject = NULL;
-        ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, newCCB);
-        ObDereferenceObject(fileObject);
-        return status;
-    }
-    _SEH2_END;
-
-    vfatGrabFCB(vcb, fcb);
-    fcb->Flags |= FCB_CACHE_INITIALIZED;
-    return STATUS_SUCCESS;
-}
-
-PVFATFCB
-vfatMakeRootFCB(
-    PDEVICE_EXTENSION pVCB)
-{
-    PVFATFCB FCB;
-    ULONG FirstCluster, CurrentCluster, Size = 0;
-    NTSTATUS Status = STATUS_SUCCESS;
-    UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\");
-
-    FCB = vfatNewFCB(pVCB, &NameU);
-    if (vfatVolumeIsFatX(pVCB))
-    {
-        memset(FCB->entry.FatX.Filename, ' ', 42);
-        FCB->entry.FatX.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
-        FCB->entry.FatX.Attrib = FILE_ATTRIBUTE_DIRECTORY;
-        FCB->entry.FatX.FirstCluster = 1;
-        Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
-    }
-    else
-    {
-        memset(FCB->entry.Fat.ShortName, ' ', 11);
-        FCB->entry.Fat.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
-        FCB->entry.Fat.Attrib = FILE_ATTRIBUTE_DIRECTORY;
-        if (pVCB->FatInfo.FatType == FAT32)
-        {
-            CurrentCluster = FirstCluster = pVCB->FatInfo.RootCluster;
-            FCB->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0xffff);
-            FCB->entry.Fat.FirstClusterHigh = (unsigned short)(FirstCluster >> 16);
-
-            while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
-            {
-                Size += pVCB->FatInfo.BytesPerCluster;
-                Status = NextCluster (pVCB, FirstCluster, &CurrentCluster, FALSE);
-            }
-        }
-        else
-        {
-            FCB->entry.Fat.FirstCluster = 1;
-            Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
-        }
-    }
-    FCB->ShortHash.Hash = FCB->Hash.Hash;
-    FCB->RefCount = 2;
-    FCB->dirIndex = 0;
-    FCB->RFCB.FileSize.QuadPart = Size;
-    FCB->RFCB.ValidDataLength.QuadPart = Size;
-    FCB->RFCB.AllocationSize.QuadPart = Size;
-    FCB->RFCB.IsFastIoPossible = FastIoIsNotPossible;
-
-    vfatFCBInitializeCacheFromVolume(pVCB, FCB);
-    vfatAddFCBToTable(pVCB, FCB);
-
-    return FCB;
-}
-
-PVFATFCB
-vfatOpenRootFCB(
-    PDEVICE_EXTENSION pVCB)
-{
-    PVFATFCB FCB;
-    UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\");
-
-    FCB = vfatGrabFCBFromTable(pVCB, &NameU);
-    if (FCB == NULL)
-    {
-        FCB = vfatMakeRootFCB(pVCB);
-    }
-
-    return FCB;
-}
-
-NTSTATUS
-vfatMakeFCBFromDirEntry(
-    PVCB vcb,
-    PVFATFCB directoryFCB,
-    PVFAT_DIRENTRY_CONTEXT DirContext,
-    PVFATFCB *fileFCB)
-{
-    PVFATFCB rcFCB;
-    UNICODE_STRING NameU;
-    NTSTATUS Status;
-
-    Status = vfatMakeFullName(directoryFCB, &DirContext->LongNameU, &DirContext->ShortNameU, &NameU);
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    rcFCB = vfatNewFCB(vcb, &NameU);
-    vfatInitFCBFromDirEntry(vcb, rcFCB, DirContext);
-
-    rcFCB->RefCount = 1;
-    if (vfatFCBIsDirectory(rcFCB))
-    {
-        Status = vfatFCBInitializeCacheFromVolume(vcb, rcFCB);
-        if (!NT_SUCCESS(Status))
-        {
-            vfatReleaseFCB(vcb, rcFCB);
-            ExFreePoolWithTag(NameU.Buffer, TAG_FCB);
-            return Status;
-        }
-    }
-    rcFCB->parentFcb = directoryFCB;
-    InsertTailList(&directoryFCB->ParentListHead, &rcFCB->ParentListEntry);
-    vfatAddFCBToTable(vcb, rcFCB);
-    *fileFCB = rcFCB;
-
-    ExFreePoolWithTag(NameU.Buffer, TAG_FCB);
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-vfatAttachFCBToFileObject(
-    PDEVICE_EXTENSION vcb,
-    PVFATFCB fcb,
-    PFILE_OBJECT fileObject)
-{
-    PVFATCCB newCCB;
-
-    UNREFERENCED_PARAMETER(vcb);
-
-    newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
-    if (newCCB == NULL)
-    {
-        return  STATUS_INSUFFICIENT_RESOURCES;
-    }
-    RtlZeroMemory(newCCB, sizeof (VFATCCB));
-
-    fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
-    fileObject->FsContext = fcb;
-    fileObject->FsContext2 = newCCB;
-    DPRINT("file open: fcb:%p PathName:%wZ\n", fcb, &fcb->PathNameU);
-
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-vfatDirFindFile(
-    PDEVICE_EXTENSION pDeviceExt,
-    PVFATFCB pDirectoryFCB,
-    PUNICODE_STRING FileToFindU,
-    PVFATFCB *pFoundFCB)
-{
-    NTSTATUS status;
-    PVOID Context = NULL;
-    PVOID Page = NULL;
-    BOOLEAN First = TRUE;
-    VFAT_DIRENTRY_CONTEXT DirContext;
-    /* This buffer must have a size of 260 characters, because
-    vfatMakeFCBFromDirEntry can copy 20 name entries with 13 characters. */
-    WCHAR LongNameBuffer[260];
-    WCHAR ShortNameBuffer[13];
-    BOOLEAN FoundLong = FALSE;
-    BOOLEAN FoundShort = FALSE;
-    BOOLEAN IsFatX = vfatVolumeIsFatX(pDeviceExt);
-
-    ASSERT(pDeviceExt);
-    ASSERT(pDirectoryFCB);
-    ASSERT(FileToFindU);
-
-    DPRINT("vfatDirFindFile(VCB:%p, dirFCB:%p, File:%wZ)\n",
-           pDeviceExt, pDirectoryFCB, FileToFindU);
-    DPRINT("Dir Path:%wZ\n", &pDirectoryFCB->PathNameU);
-
-    DirContext.DirIndex = 0;
-    DirContext.LongNameU.Buffer = LongNameBuffer;
-    DirContext.LongNameU.Length = 0;
-    DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
-    DirContext.ShortNameU.Buffer = ShortNameBuffer;
-    DirContext.ShortNameU.Length = 0;
-    DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
-
-    while (TRUE)
-    {
-        status = VfatGetNextDirEntry(pDeviceExt,
-            &Context,
-            &Page,
-            pDirectoryFCB,
-            &DirContext,
-            First);
-        First = FALSE;
-        if (status == STATUS_NO_MORE_ENTRIES)
-        {
-            return STATUS_OBJECT_NAME_NOT_FOUND;
-        }
-        if (!NT_SUCCESS(status))
-        {
-            return status;
-        }
-
-        DPRINT("  Index:%u  longName:%wZ\n",
-               DirContext.DirIndex, &DirContext.LongNameU);
-
-        if (!ENTRY_VOLUME(IsFatX, &DirContext.DirEntry))
-        {
-            if (DirContext.LongNameU.Length == 0 ||
-                DirContext.ShortNameU.Length == 0)
-            {
-                DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
-                if (VfatGlobalData->Flags & VFAT_BREAK_ON_CORRUPTION)
-                {
-                    ASSERT(DirContext.LongNameU.Length != 0 &&
-                           DirContext.ShortNameU.Length != 0);
-                }
-                DirContext.DirIndex++;
-                continue;
-            }
-            FoundLong = RtlEqualUnicodeString(FileToFindU, &DirContext.LongNameU, TRUE);
-            if (FoundLong == FALSE)
-            {
-                FoundShort = RtlEqualUnicodeString(FileToFindU, &DirContext.ShortNameU, TRUE);
-            }
-            if (FoundLong || FoundShort)
-            {
-                status = vfatMakeFCBFromDirEntry(pDeviceExt,
-                    pDirectoryFCB,
-                    &DirContext,
-                    pFoundFCB);
-                CcUnpinData(Context);
-                return status;
-            }
-        }
-        DirContext.DirIndex++;
-    }
-
-    return STATUS_OBJECT_NAME_NOT_FOUND;
-}
-
-NTSTATUS
-vfatGetFCBForFile(
-    PDEVICE_EXTENSION pVCB,
-    PVFATFCB *pParentFCB,
-    PVFATFCB *pFCB,
-    PUNICODE_STRING pFileNameU)
-{
-    NTSTATUS status;
-    PVFATFCB FCB = NULL;
-    PVFATFCB parentFCB;
-    UNICODE_STRING NameU;
-    UNICODE_STRING RootNameU = RTL_CONSTANT_STRING(L"\\");
-    UNICODE_STRING FileNameU;
-    WCHAR NameBuffer[260];
-    PWCHAR curr, prev, last;
-    ULONG Length;
-
-    DPRINT("vfatGetFCBForFile (%p,%p,%p,%wZ)\n",
-           pVCB, pParentFCB, pFCB, pFileNameU);
-
-    RtlInitEmptyUnicodeString(&FileNameU, NameBuffer, sizeof(NameBuffer));
-
-    parentFCB = *pParentFCB;
-
-    if (parentFCB == NULL)
-    {
-        /* Passed-in name is the full name */
-        RtlCopyUnicodeString(&FileNameU, pFileNameU);
-
-        //  Trivial case, open of the root directory on volume
-        if (RtlEqualUnicodeString(&FileNameU, &RootNameU, FALSE))
-        {
-            DPRINT("returning root FCB\n");
-
-            FCB = vfatOpenRootFCB(pVCB);
-            *pFCB = FCB;
-            *pParentFCB = NULL;
-
-            return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
-        }
-
-        /* Check for an existing FCB */
-        FCB = vfatGrabFCBFromTable(pVCB, &FileNameU);
-        if (FCB)
-        {
-            *pFCB = FCB;
-            *pParentFCB = FCB->parentFcb;
-            vfatGrabFCB(pVCB, *pParentFCB);
-            return STATUS_SUCCESS;
-        }
-
-        last = curr = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
-        while (*curr != L'\\' && curr > FileNameU.Buffer)
-        {
-            curr--;
-        }
-
-        if (curr > FileNameU.Buffer)
-        {
-            NameU.Buffer = FileNameU.Buffer;
-            NameU.MaximumLength = NameU.Length = (curr - FileNameU.Buffer) * sizeof(WCHAR);
-            FCB = vfatGrabFCBFromTable(pVCB, &NameU);
-            if (FCB)
-            {
-                Length = (curr - FileNameU.Buffer) * sizeof(WCHAR);
-                if (Length != FCB->PathNameU.Length)
-                {
-                    if (FileNameU.Length + FCB->PathNameU.Length - Length > FileNameU.MaximumLength)
-                    {
-                        vfatReleaseFCB(pVCB, FCB);
-                        return STATUS_OBJECT_NAME_INVALID;
-                    }
-                    RtlMoveMemory(FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR),
-                        curr, FileNameU.Length - Length);
-                    FileNameU.Length += (USHORT)(FCB->PathNameU.Length - Length);
-                    curr = FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR);
-                    last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
-                }
-                RtlCopyMemory(FileNameU.Buffer, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
-            }
-        }
-        else
-        {
-            FCB = NULL;
-        }
-
-        if (FCB == NULL)
-        {
-            FCB = vfatOpenRootFCB(pVCB);
-            curr = FileNameU.Buffer;
-        }
-
-        parentFCB = NULL;
-        prev = curr;
-    }
-    else
-    {
-        /* Make absolute path */
-        RtlCopyUnicodeString(&FileNameU, &parentFCB->PathNameU);
-        curr = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
-        if (*curr != L'\\')
-        {
-            RtlAppendUnicodeToString(&FileNameU, L"\\");
-            curr++;
-        }
-        ASSERT(*curr == L'\\');
-        RtlAppendUnicodeStringToString(&FileNameU, pFileNameU);
-
-        FCB = parentFCB;
-        parentFCB = NULL;
-        prev = curr;
-        last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
-    }
-
-    while (curr <= last)
-    {
-        if (parentFCB)
-        {
-            vfatReleaseFCB(pVCB, parentFCB);
-            parentFCB = NULL;
-        }
-        //  fail if element in FCB is not a directory
-        if (!vfatFCBIsDirectory(FCB))
-        {
-            DPRINT ("Element in requested path is not a directory\n");
-
-            vfatReleaseFCB(pVCB, FCB);
-            FCB = NULL;
-            *pParentFCB = NULL;
-            *pFCB = NULL;
-
-            return  STATUS_OBJECT_PATH_NOT_FOUND;
-        }
-        parentFCB = FCB;
-        if (prev < curr)
-        {
-            Length = (curr - prev) * sizeof(WCHAR);
-            if (Length != parentFCB->LongNameU.Length)
-            {
-                if (FileNameU.Length + parentFCB->LongNameU.Length - Length > FileNameU.MaximumLength)
-                {
-                    vfatReleaseFCB(pVCB, parentFCB);
-                    *pParentFCB = NULL;
-                    *pFCB = NULL;
-                    return STATUS_OBJECT_NAME_INVALID;
-                }
-                RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr,
-                    FileNameU.Length - (curr - FileNameU.Buffer) * sizeof(WCHAR));
-                FileNameU.Length += (USHORT)(parentFCB->LongNameU.Length - Length);
-                curr = prev + parentFCB->LongNameU.Length / sizeof(WCHAR);
-                last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
-            }
-            RtlCopyMemory(prev, parentFCB->LongNameU.Buffer, parentFCB->LongNameU.Length);
-        }
-        curr++;
-        prev = curr;
-        while (*curr != L'\\' && curr <= last)
-        {
-            curr++;
-        }
-        NameU.Buffer = FileNameU.Buffer;
-        NameU.Length = (curr - NameU.Buffer) * sizeof(WCHAR);
-        NameU.MaximumLength = FileNameU.MaximumLength;
-        DPRINT("%wZ\n", &NameU);
-        FCB = vfatGrabFCBFromTable(pVCB, &NameU);
-        if (FCB == NULL)
-        {
-            NameU.Buffer = prev;
-            NameU.MaximumLength = NameU.Length = (curr - prev) * sizeof(WCHAR);
-            status = vfatDirFindFile(pVCB, parentFCB, &NameU, &FCB);
-            if (status == STATUS_OBJECT_NAME_NOT_FOUND)
-            {
-                *pFCB = NULL;
-                if (curr > last)
-                {
-                    *pParentFCB = parentFCB;
-                    return STATUS_OBJECT_NAME_NOT_FOUND;
-                }
-                else
-                {
-                    vfatReleaseFCB(pVCB, parentFCB);
-                    *pParentFCB = NULL;
-                    return STATUS_OBJECT_PATH_NOT_FOUND;
-                }
-            }
-            else if (!NT_SUCCESS(status))
-            {
-                vfatReleaseFCB(pVCB, parentFCB);
-                *pParentFCB = NULL;
-                *pFCB = NULL;
-
-                return status;
-            }
-        }
-    }
-
-    *pParentFCB = parentFCB;
-    *pFCB = FCB;
-
-    return STATUS_SUCCESS;
-}