📄 namesup.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
NameSup.c
Abstract:
This module implements the Fat Name support routines
--*/
#include "FatProcs.h"
#define Dbg (DEBUG_TRACE_NAMESUP)
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Fat8dot3ToString)
#pragma alloc_text(PAGE, FatIsNameInExpression)
#pragma alloc_text(PAGE, FatStringTo8dot3)
#pragma alloc_text(PAGE, FatSetFullFileNameInFcb)
#pragma alloc_text(PAGE, FatGetUnicodeNameFromFcb)
#pragma alloc_text(PAGE, FatUnicodeToUpcaseOem)
#pragma alloc_text(PAGE, FatSelectNames)
#pragma alloc_text(PAGE, FatEvaluateNameCase)
#pragma alloc_text(PAGE, FatSpaceInName)
#endif
BOOLEAN
FatIsNameInExpression (
IN PIRP_CONTEXT IrpContext,
IN OEM_STRING Expression,
IN OEM_STRING Name
)
/*++
Routine Description:
This routine compare a name and an expression and tells the caller if
the name is equal to or not equal to the expression. The input name
cannot contain wildcards, while the expression may contain wildcards.
Arguments:
Expression - Supplies the input expression to check against
The caller must have already upcased the Expression.
Name - Supplies the input name to check for. The caller must have
already upcased the name.
Return Value:
BOOLEAN - TRUE if Name is an element in the set of strings denoted
by the input Expression and FALSE otherwise.
--*/
{
//
// Call the appropriate FsRtl routine do to the real work
//
return FsRtlIsDbcsInExpression( &Expression,
&Name );
UNREFERENCED_PARAMETER( IrpContext );
}
VOID
FatStringTo8dot3 (
IN PIRP_CONTEXT IrpContext,
IN OEM_STRING InputString,
OUT PFAT8DOT3 Output8dot3
)
/*++
Routine Description:
Convert a string into fat 8.3 format. The string must not contain
any wildcards.
Arguments:
InputString - Supplies the input string to convert
Output8dot3 - Receives the converted string, the memory must be supplied
by the caller.
Return Value:
None.
--*/
{
ULONG i;
ULONG j;
DebugTrace(+1, Dbg, "FatStringTo8dot3\n", 0);
DebugTrace( 0, Dbg, "InputString = %Z\n", &InputString);
ASSERT( InputString.Length <= 12 );
//
// Make the output name all blanks
//
RtlFillMemory( Output8dot3, 11, UCHAR_SP );
//
// Copy over the first part of the file name. Stop when we get to
// the end of the input string or a dot.
//
for (i = 0;
(i < (ULONG)InputString.Length) && (InputString.Buffer[i] != '.');
i += 1) {
(*Output8dot3)[i] = InputString.Buffer[i];
}
//
// Check if we need to process an extension
//
if (i < (ULONG)InputString.Length) {
//
// Make sure we have a dot and then skip over it.
//
ASSERT( (InputString.Length - i) <= 4 );
ASSERT( InputString.Buffer[i] == '.' );
i += 1;
//
// Copy over the extension. Stop when we get to the
// end of the input string.
//
for (j = 8; (i < (ULONG)InputString.Length); j += 1, i += 1) {
(*Output8dot3)[j] = InputString.Buffer[i];
}
}
//
// Before we return check if we should translate the first character
// from 0xe5 to 0x5.
//
if ((*Output8dot3)[0] == 0xe5) {
(*Output8dot3)[0] = FAT_DIRENT_REALLY_0E5;
}
DebugTrace(-1, Dbg, "FatStringTo8dot3 -> (VOID)\n", 0);
UNREFERENCED_PARAMETER( IrpContext );
return;
}
VOID
Fat8dot3ToString (
IN PIRP_CONTEXT IrpContext,
IN PDIRENT Dirent,
IN BOOLEAN RestoreCase,
OUT POEM_STRING OutputString
)
/*++
Routine Description:
Convert fat 8.3 format into a string. The 8.3 name must be well formed.
Arguments:
Dirent - Supplies the input 8.3 name to convert
RestoreCase - If TRUE, then the magic reserved bits are used to restore
the original case.
OutputString - Receives the converted name, the memory must be supplied
by the caller.
Return Value:
None
--*/
{
ULONG DirentIndex, StringIndex;
ULONG BaseLength, ExtensionLength;
DebugTrace(+1, Dbg, "Fat8dot3ToString\n", 0);
//
// First, find the length of the base component.
//
for (BaseLength = 8; BaseLength > 0; BaseLength -= 1) {
if (Dirent->FileName[BaseLength - 1] != UCHAR_SP) {
break;
}
}
//
// Now find the length of the extension.
//
for (ExtensionLength = 3; ExtensionLength > 0; ExtensionLength -= 1) {
if (Dirent->FileName[8 + ExtensionLength - 1] != UCHAR_SP) {
break;
}
}
//
// If there was a base part, copy it and check the case. Don't forget
// if the first character needs to be changed from 0x05 to 0xe5.
//
if (BaseLength != 0) {
RtlCopyMemory( OutputString->Buffer, Dirent->FileName, BaseLength );
if (OutputString->Buffer[0] == FAT_DIRENT_REALLY_0E5) {
OutputString->Buffer[0] = (CHAR)0xe5;
}
//
// Now if we are to restore case, look for A-Z
//
if (FatData.ChicagoMode &&
RestoreCase &&
FlagOn(Dirent->NtByte, FAT_DIRENT_NT_BYTE_8_LOWER_CASE)) {
for (StringIndex = 0; StringIndex < BaseLength; StringIndex += 1) {
//
// Depending on whether the media was built in a system that was
// running with "code page invariance" (see FatEvaluateNameCase),
// there could be double-byte OEM characters lying in wait here.
// Gotta skip them.
//
if (FsRtlIsLeadDbcsCharacter(OutputString->Buffer[StringIndex])) {
StringIndex += 1;
continue;
}
if ((OutputString->Buffer[StringIndex] >= 'A') &&
(OutputString->Buffer[StringIndex] <= 'Z')) {
OutputString->Buffer[StringIndex] += 'a' - 'A';
}
}
}
}
//
// If there was an extension, copy that over. Else we now know the
// size of the string.
//
if (ExtensionLength != 0) {
PUCHAR o, d;
//
// Now add the dot
//
OutputString->Buffer[BaseLength++] = '.';
//
// Copy over the extension into the output buffer.
//
o = &OutputString->Buffer[BaseLength];
d = &Dirent->FileName[8];
switch (ExtensionLength) {
case 3:
*o++ = *d++;
case 2:
*o++ = *d++;
case 1:
*o++ = *d++;
}
//
// Set the output string length
//
OutputString->Length = (USHORT)(BaseLength + ExtensionLength);
//
// Now if we are to restore case, look for A-Z
//
if (FatData.ChicagoMode &&
RestoreCase &&
FlagOn(Dirent->NtByte, FAT_DIRENT_NT_BYTE_3_LOWER_CASE)) {
for (StringIndex = BaseLength;
StringIndex < OutputString->Length;
StringIndex++ ) {
//
// Depending on whether the media was built in a system that was
// running with "code page invariance" (see FatEvaluateNameCase),
// there could be double-byte OEM characters lying in wait here.
// Gotta skip them.
//
if (FsRtlIsLeadDbcsCharacter(OutputString->Buffer[StringIndex])) {
StringIndex += 1;
continue;
}
if ((OutputString->Buffer[StringIndex] >= 'A') &&
(OutputString->Buffer[StringIndex] <= 'Z')) {
OutputString->Buffer[StringIndex] += 'a' - 'A';
}
}
}
} else {
//
// Set the output string length
//
OutputString->Length = (USHORT)BaseLength;
}
//
// And return to our caller
//
DebugTrace(-1, Dbg, "Fat8dot3ToString, OutputString = \"%Z\" -> VOID\n", OutputString);
UNREFERENCED_PARAMETER( IrpContext );
return;
}
VOID
FatGetUnicodeNameFromFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN OUT PUNICODE_STRING Lfn
)
/*++
Routine Description:
This routine will return the unicode name for a given Fcb. If the
file has an LFN, it will return this. Otherwise it will return
the UNICODE conversion of the Oem name, properly cased.
Arguments:
Fcb - Supplies the Fcb to query.
Lfn - Supplies a string that already has enough storage for the
full unicode name.
Return Value:
None
--*/
{
PDIRENT Dirent;
PBCB DirentBcb = NULL;
ULONG DirentByteOffset;
CCB LocalCcb;
ASSERT((MAX_LFN_CHARACTERS * sizeof( WCHAR)) == Lfn->MaximumLength);
//
// We'll start by locating the dirent for the name.
//
FatStringTo8dot3( IrpContext,
Fcb->ShortName.Name.Oem,
&LocalCcb.OemQueryTemplate.Constant );
LocalCcb.Flags = 0;
LocalCcb.UnicodeQueryTemplate.Length = 0;
LocalCcb.ContainsWildCards = FALSE;
FatLocateDirent( IrpContext,
Fcb->ParentDcb,
&LocalCcb,
Fcb->LfnOffsetWithinDirectory,
&Dirent,
&DirentBcb,
&DirentByteOffset,
NULL,
Lfn);
try {
//
// If we didn't find the Dirent, something is terribly wrong.
//
if ((DirentBcb == NULL) ||
(DirentByteOffset != Fcb->DirentOffsetWithinDirectory)) {
FatRaiseStatus( IrpContext, STATUS_FILE_INVALID );
}
//
// Check for the easy case.
//
if (Lfn->Length == 0) {
NTSTATUS Status;
OEM_STRING ShortName;
UCHAR ShortNameBuffer[12];
//
// If we thought that there was an LFN here and didn't find one,
// we're as dead. This shouldn't happen in normal operation, but
// if someone scrambles a directory by hand ...
//
ASSERT( Fcb->LfnOffsetWithinDirectory == Fcb->DirentOffsetWithinDirectory );
if (Fcb->LfnOffsetWithinDirectory != Fcb->DirentOffsetWithinDirectory) {
FatRaiseStatus( IrpContext, STATUS_FILE_INVALID );
}
//
// There is no LFN, so manufacture a UNICODE name.
//
ShortName.Length = 0;
ShortName.MaximumLength = 12;
ShortName.Buffer = ShortNameBuffer;
Fat8dot3ToString( IrpContext, Dirent, TRUE, &ShortName );
//
// OK, now convert this string to UNICODE
//
Status = RtlOemStringToCountedUnicodeString( Lfn,
&ShortName,
FALSE );
ASSERT( Status == STATUS_SUCCESS );
}
} finally {
FatUnpinBcb( IrpContext, DirentBcb );
}
}
VOID
FatSetFullFileNameInFcb (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb
)
/*++
Routine Description:
If the FullFileName field in the Fcb has not yet been filled in, we
proceed to do so.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -