mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
[fastfat_new]
- 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
This commit is contained in:
parent
83836038f7
commit
a7532a398b
4 changed files with 281 additions and 307 deletions
|
@ -11,6 +11,16 @@
|
|||
#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
|
||||
|
@ -52,7 +62,7 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
|
|||
|
||||
/* Control blocks */
|
||||
PVCB Vcb, DecodedVcb;
|
||||
PFCB Fcb;
|
||||
PFCB Fcb, NextFcb;
|
||||
PCCB Ccb;
|
||||
PFCB ParentDcb;
|
||||
|
||||
|
@ -72,6 +82,11 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
|
|||
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);
|
||||
|
@ -266,10 +281,178 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
|
|||
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
|
||||
|
|
|
@ -153,6 +153,14 @@ FatDecodeFileObject(IN PFILE_OBJECT FileObject,
|
|||
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
|
||||
|
|
|
@ -221,13 +221,14 @@ enum _FCB_NAME_TYPE {
|
|||
} FCB_NAME_TYPE;
|
||||
|
||||
typedef struct _FCB_NAME_LINK {
|
||||
struct _FCB *Fcb;
|
||||
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
|
||||
|
@ -287,7 +288,9 @@ typedef struct _FCB
|
|||
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;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* 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 *****************************************************************/
|
||||
|
@ -12,318 +12,98 @@
|
|||
#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.
|
||||
*/
|
||||
|
||||
FSRTL_COMPARISON_RESULT
|
||||
NTAPI
|
||||
FatiCompareNames(PSTRING NameA,
|
||||
PSTRING NameB)
|
||||
{
|
||||
ULONG MinimumLen, i;
|
||||
|
||||
/* Calc the minimum length */
|
||||
MinimumLen = NameA->Length < NameB->Length ? NameA->Length :
|
||||
NameB->Length;
|
||||
|
||||
/* Actually compare them */
|
||||
i = (ULONG)RtlCompareMemory( NameA->Buffer, NameB->Buffer, MinimumLen );
|
||||
|
||||
if (i < MinimumLen)
|
||||
{
|
||||
/* Compare prefixes */
|
||||
if (NameA->Buffer[i] < NameB->Buffer[i])
|
||||
return LessThan;
|
||||
else
|
||||
return GreaterThan;
|
||||
}
|
||||
|
||||
/* Final comparison */
|
||||
if (NameA->Length < NameB->Length)
|
||||
return LessThan;
|
||||
else if (NameA->Length > NameB->Length)
|
||||
return GreaterThan;
|
||||
else
|
||||
return EqualTo;
|
||||
}
|
||||
|
||||
PFCB
|
||||
FatLookupFcbByName(
|
||||
IN PFCB ParentFcb,
|
||||
IN PUNICODE_STRING Name)
|
||||
NTAPI
|
||||
FatFindFcb(PFAT_IRP_CONTEXT IrpContext,
|
||||
PRTL_SPLAY_LINKS *RootNode,
|
||||
PSTRING AnsiName,
|
||||
PBOOLEAN IsDosName)
|
||||
{
|
||||
PFCB_NAME_LINK Node;
|
||||
PRTL_SPLAY_LINKS Links;
|
||||
FSRTL_COMPARISON_RESULT Comparison;
|
||||
PRTL_SPLAY_LINKS Links;
|
||||
|
||||
/* Get sub-trie root node from the parent FCB */
|
||||
Links = ParentFcb->Dcb.SplayLinks;
|
||||
while (Links != NULL)
|
||||
{
|
||||
LONG Comparison;
|
||||
Links = *RootNode;
|
||||
|
||||
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)
|
||||
{
|
||||
PFCB_NAME_LINK Name;
|
||||
PRTL_SPLAY_LINKS Links;
|
||||
|
||||
/* None of the parameters can be NULL */
|
||||
ASSERT(ParentFcb != NULL && Fcb != NULL);
|
||||
|
||||
/* Get root links of the parent FCB. */
|
||||
Links = ParentFcb->Dcb.SplayLinks;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
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)
|
||||
while (Links)
|
||||
{
|
||||
/* Swap lfn back to the input parameter */
|
||||
*LongFileName = Fcb->FileName[FcbLongName].String;
|
||||
}
|
||||
ExFreeToNPagedLookasideList(&FatGlobalData.NonPagedFcbList, Fcb);
|
||||
return Status;
|
||||
}
|
||||
Node = CONTAINING_RECORD(Links, FCB_NAME_LINK, Links);
|
||||
|
||||
NTSTATUS
|
||||
FatOpenFcb(
|
||||
OUT PFCB* Fcb,
|
||||
IN PFAT_IRP_CONTEXT IrpContext,
|
||||
IN PFCB ParentFcb,
|
||||
IN PUNICODE_STRING FileName)
|
||||
{
|
||||
FAT_FIND_DIRENT_CONTEXT Context;
|
||||
UNICODE_STRING LongFileName;
|
||||
PDIR_ENTRY Dirent;
|
||||
NTSTATUS Status;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
// TODO: _SEH_TRY {
|
||||
if (ParentFcb->Dcb.StreamFileObject == NULL)
|
||||
{
|
||||
PFILE_OBJECT FileObject;
|
||||
PVPB Vpb;
|
||||
|
||||
Vpb = IrpContext->Vcb->Vpb;
|
||||
/* 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);
|
||||
|
||||
/* 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;
|
||||
/* Save type of the name, if needed */
|
||||
if (IsDosName)
|
||||
*IsDosName = Node->IsDosName;
|
||||
|
||||
/* Return the found fcb */
|
||||
return Node->Fcb;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if cache is initialized. */
|
||||
if (ParentFcb->Dcb.StreamFileObject->PrivateCacheMap == NULL )
|
||||
{
|
||||
CcInitializeCacheMap(ParentFcb->Dcb.StreamFileObject,
|
||||
(PCC_FILE_SIZES) &ParentFcb->Header.AllocationSize,
|
||||
TRUE,
|
||||
&FatGlobalData.CacheMgrNoopCallbacks,
|
||||
ParentFcb);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
/* Nothing found */
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue