mirror of
https://github.com/reactos/reactos.git
synced 2025-06-27 18:00:49 +00:00
[fastfat_new]
- Implement all infrastructue for constructing filenames in FCBs, and use it to build full file names. Every FCB has four names: a short upcased name in ANSI, a long upcased name in Unicode, a name in exact case in Unicode, and finally a full file name including all path up to the root. - FatiQueryFileNameInformation now returns correct file name, and other places relying on presence of a correct name work now. svn path=/trunk/; revision=43390
This commit is contained in:
parent
ab802377c7
commit
388ffabace
5 changed files with 212 additions and 7 deletions
|
@ -376,7 +376,8 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
/* Ensure the name is set */
|
/* Ensure the name is set */
|
||||||
if (!ParentDcb->FullFileName.Buffer)
|
if (!ParentDcb->FullFileName.Buffer)
|
||||||
{
|
{
|
||||||
DPRINT1("ParentDcb->FullFileName.Buffer is NULL\n");
|
/* Set it if it's missing */
|
||||||
|
FatSetFullFileNameInFcb(IrpContext, ParentDcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check max path length */
|
/* Check max path length */
|
||||||
|
|
|
@ -306,6 +306,10 @@ VOID NTAPI
|
||||||
FatSetFullNameInFcb(PFCB Fcb,
|
FatSetFullNameInFcb(PFCB Fcb,
|
||||||
PUNICODE_STRING Name);
|
PUNICODE_STRING Name);
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
FatSetFullFileNameInFcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
|
IN PFCB Fcb);
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
|
FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
IN PFCB Fcb);
|
IN PFCB Fcb);
|
||||||
|
|
|
@ -281,6 +281,8 @@ typedef struct _FCB
|
||||||
UNICODE_STRING FullFileName;
|
UNICODE_STRING FullFileName;
|
||||||
/* Long name with exact case */
|
/* Long name with exact case */
|
||||||
UNICODE_STRING ExactCaseLongName;
|
UNICODE_STRING ExactCaseLongName;
|
||||||
|
/* Hint for the filename length */
|
||||||
|
ULONG FileNameLength;
|
||||||
/* A copy of fat attribute byte */
|
/* A copy of fat attribute byte */
|
||||||
UCHAR DirentFatFlags;
|
UCHAR DirentFatFlags;
|
||||||
/* File basic info */
|
/* File basic info */
|
||||||
|
|
|
@ -172,6 +172,84 @@ FatCreateCcb()
|
||||||
return Ccb;
|
return Ccb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
FatGetFcbUnicodeName(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
|
IN PFCB Fcb,
|
||||||
|
OUT PUNICODE_STRING LongName)
|
||||||
|
{
|
||||||
|
FF_DIRENT DirEnt;
|
||||||
|
FF_ERROR Err;
|
||||||
|
OEM_STRING ShortName;
|
||||||
|
CHAR ShortNameBuf[13];
|
||||||
|
UCHAR EntryBuffer[32];
|
||||||
|
UCHAR NumLFNs;
|
||||||
|
OEM_STRING LongNameOem;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* We support only files now, not directories */
|
||||||
|
if (Fcb->Header.NodeTypeCode != FAT_NTC_FCB)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the dir entry */
|
||||||
|
Err = FF_GetEntry(Fcb->Vcb->Ioman,
|
||||||
|
Fcb->FatHandle->DirEntry,
|
||||||
|
Fcb->FatHandle->DirCluster,
|
||||||
|
&DirEnt);
|
||||||
|
|
||||||
|
if (Err != FF_ERR_NONE)
|
||||||
|
{
|
||||||
|
DPRINT1("Error %d getting dirent of a file\n", Err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the dirent to fetch the raw short name */
|
||||||
|
FF_FetchEntry(Fcb->Vcb->Ioman,
|
||||||
|
Fcb->FatHandle->DirCluster,
|
||||||
|
Fcb->FatHandle->DirEntry,
|
||||||
|
EntryBuffer);
|
||||||
|
NumLFNs = (UCHAR)(EntryBuffer[0] & ~0x40);
|
||||||
|
|
||||||
|
/* Check if we only have a short name.
|
||||||
|
Convert it to unicode and return if that's the case */
|
||||||
|
if (NumLFNs == 0)
|
||||||
|
{
|
||||||
|
/* Initialize short name string */
|
||||||
|
ShortName.Buffer = ShortNameBuf;
|
||||||
|
ShortName.Length = 0;
|
||||||
|
ShortName.MaximumLength = 12;
|
||||||
|
|
||||||
|
/* Convert raw short name to a proper string */
|
||||||
|
Fati8dot3ToString((PCHAR)EntryBuffer, FALSE, &ShortName);
|
||||||
|
|
||||||
|
/* Convert it to unicode */
|
||||||
|
Status = RtlOemStringToCountedUnicodeString(LongName,
|
||||||
|
&ShortName,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
/* Ensure conversion was successful */
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
/* Exit */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert LFN from OEM to unicode and return */
|
||||||
|
LongNameOem.Buffer = DirEnt.FileName;
|
||||||
|
LongNameOem.MaximumLength = FF_MAX_FILENAME;
|
||||||
|
LongNameOem.Length = strlen(DirEnt.FileName);
|
||||||
|
|
||||||
|
/* Convert it to unicode */
|
||||||
|
Status = RtlOemStringToUnicodeString(LongName, &LongNameOem, FALSE);
|
||||||
|
|
||||||
|
/* Ensure conversion was successful */
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
FatSetFullNameInFcb(PFCB Fcb,
|
FatSetFullNameInFcb(PFCB Fcb,
|
||||||
|
@ -244,6 +322,99 @@ FatSetFullNameInFcb(PFCB Fcb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
FatSetFullFileNameInFcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
|
IN PFCB Fcb)
|
||||||
|
{
|
||||||
|
UNICODE_STRING LongName;
|
||||||
|
PFCB CurFcb = Fcb;
|
||||||
|
PFCB StopFcb;
|
||||||
|
PWCHAR TmpBuffer;
|
||||||
|
ULONG PathLength = 0;
|
||||||
|
|
||||||
|
/* Do nothing if it's already set */
|
||||||
|
if (Fcb->FullFileName.Buffer) return;
|
||||||
|
|
||||||
|
/* Allocate a temporary buffer */
|
||||||
|
LongName.Length = 0;
|
||||||
|
LongName.MaximumLength = FF_MAX_FILENAME * sizeof(WCHAR);
|
||||||
|
LongName.Buffer =
|
||||||
|
FsRtlAllocatePoolWithTag(PagedPool,
|
||||||
|
FF_MAX_FILENAME * sizeof(WCHAR),
|
||||||
|
TAG_FILENAME);
|
||||||
|
|
||||||
|
/* Go through all parents to calculate needed length */
|
||||||
|
while (CurFcb != Fcb->Vcb->RootDcb)
|
||||||
|
{
|
||||||
|
/* Does current FCB have FullFileName set? */
|
||||||
|
if (CurFcb != Fcb &&
|
||||||
|
CurFcb->FullFileName.Buffer)
|
||||||
|
{
|
||||||
|
/* Yes, just use it! */
|
||||||
|
PathLength += CurFcb->FullFileName.Length;
|
||||||
|
|
||||||
|
Fcb->FullFileName.Buffer =
|
||||||
|
FsRtlAllocatePoolWithTag(PagedPool,
|
||||||
|
PathLength,
|
||||||
|
TAG_FILENAME);
|
||||||
|
|
||||||
|
RtlCopyMemory(Fcb->FullFileName.Buffer,
|
||||||
|
CurFcb->FullFileName.Buffer,
|
||||||
|
CurFcb->FullFileName.Length);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sum up length of a current item */
|
||||||
|
PathLength += CurFcb->FileNameLength + sizeof(WCHAR);
|
||||||
|
|
||||||
|
/* Go to the parent */
|
||||||
|
CurFcb = CurFcb->ParentFcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate FullFileName if it wasn't already allocated above */
|
||||||
|
if (!Fcb->FullFileName.Buffer)
|
||||||
|
{
|
||||||
|
Fcb->FullFileName.Buffer =
|
||||||
|
FsRtlAllocatePoolWithTag(PagedPool,
|
||||||
|
PathLength,
|
||||||
|
TAG_FILENAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
StopFcb = CurFcb;
|
||||||
|
|
||||||
|
CurFcb = Fcb;
|
||||||
|
TmpBuffer = Fcb->FullFileName.Buffer + PathLength / sizeof(WCHAR);
|
||||||
|
|
||||||
|
/* Set lengths */
|
||||||
|
Fcb->FullFileName.Length = PathLength;
|
||||||
|
Fcb->FullFileName.MaximumLength = PathLength;
|
||||||
|
|
||||||
|
while (CurFcb != StopFcb)
|
||||||
|
{
|
||||||
|
/* Get its unicode name */
|
||||||
|
FatGetFcbUnicodeName(IrpContext,
|
||||||
|
CurFcb,
|
||||||
|
&LongName);
|
||||||
|
|
||||||
|
/* Copy it */
|
||||||
|
TmpBuffer -= LongName.Length / sizeof(WCHAR);
|
||||||
|
RtlCopyMemory(TmpBuffer, LongName.Buffer, LongName.Length);
|
||||||
|
|
||||||
|
/* Append with a backslash */
|
||||||
|
TmpBuffer -= 1;
|
||||||
|
*TmpBuffer = L'\\';
|
||||||
|
|
||||||
|
/* Go to the parent */
|
||||||
|
CurFcb = CurFcb->ParentFcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the temp buffer */
|
||||||
|
ExFreePool(LongName.Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
|
FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
|
@ -313,6 +484,21 @@ FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set its length */
|
||||||
|
Fcb->FileNameLength = UnicodeName->Length;
|
||||||
|
|
||||||
|
/* Save case-preserved copy */
|
||||||
|
Fcb->ExactCaseLongName.Length = UnicodeName->Length;
|
||||||
|
Fcb->ExactCaseLongName.MaximumLength = UnicodeName->Length;
|
||||||
|
Fcb->ExactCaseLongName.Buffer =
|
||||||
|
FsRtlAllocatePoolWithTag(PagedPool, UnicodeName->Length, TAG_FILENAME);
|
||||||
|
|
||||||
|
RtlCopyMemory(Fcb->ExactCaseLongName.Buffer,
|
||||||
|
UnicodeName->Buffer,
|
||||||
|
UnicodeName->Length);
|
||||||
|
|
||||||
|
/* Perform a trick which is done by MS's FASTFAT driver to monocase
|
||||||
|
the filename */
|
||||||
RtlDowncaseUnicodeString(UnicodeName, UnicodeName, FALSE);
|
RtlDowncaseUnicodeString(UnicodeName, UnicodeName, FALSE);
|
||||||
RtlUpcaseUnicodeString(UnicodeName, UnicodeName, FALSE);
|
RtlUpcaseUnicodeString(UnicodeName, UnicodeName, FALSE);
|
||||||
|
|
||||||
|
@ -325,6 +511,15 @@ FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
/* Indicate that this FCB has a unicode long name */
|
/* Indicate that this FCB has a unicode long name */
|
||||||
SetFlag(Fcb->State, FCB_STATE_HAS_UNICODE_NAME);
|
SetFlag(Fcb->State, FCB_STATE_HAS_UNICODE_NAME);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No LFN, set exact case name to 0 length */
|
||||||
|
Fcb->ExactCaseLongName.Length = 0;
|
||||||
|
Fcb->ExactCaseLongName.MaximumLength = 0;
|
||||||
|
|
||||||
|
/* Set the length based on the short name */
|
||||||
|
Fcb->FileNameLength = RtlOemStringToCountedUnicodeSize(ShortName);
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark the fact that names were added to splay trees*/
|
/* Mark the fact that names were added to splay trees*/
|
||||||
SetFlag(Fcb->State, FCB_STATE_HAS_NAMES);
|
SetFlag(Fcb->State, FCB_STATE_HAS_NAMES);
|
||||||
|
|
|
@ -59,10 +59,10 @@ FatiQueryInternalInformation(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
FatiQueryNameInformation(IN PFAT_IRP_CONTEXT IrpContext,
|
FatiQueryNameInformation(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
IN PFCB Fcb,
|
IN PFCB Fcb,
|
||||||
IN PFILE_OBJECT FileObject,
|
IN PFILE_OBJECT FileObject,
|
||||||
IN OUT PFILE_NAME_INFORMATION Buffer,
|
IN OUT PFILE_NAME_INFORMATION Buffer,
|
||||||
IN OUT PLONG Length)
|
IN OUT PLONG Length)
|
||||||
{
|
{
|
||||||
ULONG ByteSize;
|
ULONG ByteSize;
|
||||||
ULONG Trim = 0;
|
ULONG Trim = 0;
|
||||||
|
@ -71,8 +71,11 @@ FatiQueryNameInformation(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
/* Deduct the minimum written length */
|
/* Deduct the minimum written length */
|
||||||
*Length -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
|
*Length -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
|
||||||
|
|
||||||
// Build full name if needed
|
/* Build full name if needed */
|
||||||
//if (!Fcb->FullFileName.Buffer)
|
if (!Fcb->FullFileName.Buffer)
|
||||||
|
{
|
||||||
|
FatSetFullFileNameInFcb(IrpContext, Fcb);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT1("FullFileName %wZ\n", &Fcb->FullFileName);
|
DPRINT1("FullFileName %wZ\n", &Fcb->FullFileName);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue