[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:
Aleksey Bragin 2009-10-12 09:30:41 +00:00
parent ab802377c7
commit 388ffabace
5 changed files with 212 additions and 7 deletions

View file

@ -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 */

View file

@ -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);

View file

@ -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 */

View file

@ -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);

View file

@ -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);