-/* COPYRIGHT: See COPYING in the top level directory
+/*
+ * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/rtl/dos8dot3.c
* PURPOSE: Short name (8.3 name) functions
static USHORT
RtlpGetCheckSum(PUNICODE_STRING Name)
{
- USHORT Hash = 0;
- ULONG Length;
- PWCHAR c;
+ USHORT Hash, Saved;
+ WCHAR * CurChar;
+ USHORT Len;
+
+ if (Name->Length == 0)
+ {
+ return 0;
+ }
+
+ if (Name->Length == sizeof(WCHAR))
+ {
+ return Name->Buffer[0];
+ }
- Length = Name->Length / sizeof(WCHAR);
- c = Name->Buffer;
- while(Length--)
+ CurChar = Name->Buffer;
+ Hash = (*CurChar << 8) + *(CurChar + 1);
+ if (Name->Length == 2 * sizeof(WCHAR))
{
- Hash = (Hash + (*c << 4) + (*c >> 4)) * 11;
- c++;
+ return Hash;
}
+
+ Saved = Hash;
+ Len = 2;
+ do
+ {
+ CurChar = CurChar + 2;
+ Hash = (Hash << 7) + *CurChar;
+ Hash = (Saved >> 1) + (Hash << 8);
+ if (Len + 1 < Name->Length / sizeof(WCHAR))
+ {
+ Hash += *(CurChar + 1);
+ }
+ Saved = Hash;
+ Len += 2;
+ } while (Len < Name->Length / sizeof(WCHAR));
+
return Hash;
}
ULONG IndexLength;
ULONG CurrentIndex;
USHORT Checksum;
- CHAR c;
+ WCHAR c;
StrLength = Name->Length / sizeof(WCHAR);
DPRINT("StrLength: %lu\n", StrLength);
/* Copy name (6 valid characters max) */
for (i = 0, NameLength = 0; NameLength < 6 && i < DotPos; i++)
{
- c = 0;
- RtlUpcaseUnicodeToOemN(&c, sizeof(CHAR), &Count, &Name->Buffer[i], sizeof(WCHAR));
- if (Count != 1 || c == 0 || RtlpIsShortIllegal(c))
+ c = UNICODE_NULL;
+ if (AllowExtendedCharacters)
+ {
+ c = RtlUpcaseUnicodeChar(Name->Buffer[i]);
+ Count = 1;
+ }
+ else
+ {
+ RtlUpcaseUnicodeToOemN((CHAR *)&c, sizeof(CHAR), &Count, &Name->Buffer[i], sizeof(WCHAR));
+ }
+
+ if (Count != 1 || c == UNICODE_NULL || RtlpIsShortIllegal(c))
{
NameBuffer[NameLength++] = L'_';
}
- else if (c != '.' && c != ' ')
+ else if (c != L'.' && c != L' ')
{
- NameBuffer[NameLength++] = (WCHAR)c;
+ if (isgraph(c) || (AllowExtendedCharacters && iswgraph(c)))
+ {
+ NameBuffer[NameLength++] = c;
+ }
}
}
{
for (i = DotPos, ExtLength = 0; ExtLength < 4 && i < StrLength; i++)
{
- c = 0;
- RtlUpcaseUnicodeToOemN(&c, sizeof(CHAR), &Count, &Name->Buffer[i], sizeof(WCHAR));
- if (Count != 1 || c == 0 || RtlpIsShortIllegal(c))
+ c = UNICODE_NULL;
+ if (AllowExtendedCharacters)
+ {
+ c = RtlUpcaseUnicodeChar(Name->Buffer[i]);
+ Count = 1;
+ }
+ else
+ {
+ RtlUpcaseUnicodeToOemN((CHAR *)&c, sizeof(CHAR), &Count, &Name->Buffer[i], sizeof(WCHAR));
+ }
+
+ if (Count != 1 || c == UNICODE_NULL || RtlpIsShortIllegal(c))
{
ExtBuffer[ExtLength++] = L'_';
}
- else if (c != ' ')
+ else if (c != L' ')
{
- ExtBuffer[ExtLength++] = c;
+ if (isgraph(c) || c == L'.' || (AllowExtendedCharacters && iswgraph(c)))
+ {
+ ExtBuffer[ExtLength++] = c;
+ }
}
}
}
else
{
Context->LastIndexValue = 1;
- Context->CheckSumInserted = FALSE;
+ if (NameLength == 0)
+ {
+ Context->CheckSumInserted = TRUE;
+ Context->Checksum = RtlpGetCheckSum(Name);
+ }
+ else
+ {
+ Context->CheckSumInserted = FALSE;
+ }
}
IndexLength = RtlpGetIndexLength(Context->LastIndexValue);
j = CopyLength;
if (Context->CheckSumInserted)
{
- j += 3;
Checksum = Context->Checksum;
for (i = 0; i < 4; i++)
{
- Name8dot3->Buffer[j--] = (Checksum % 16) > 9 ? (Checksum % 16) + L'A' - 10 : (Checksum % 16) + L'0';
- Checksum /= 16;
+ Name8dot3->Buffer[j++] = (Checksum & 0xF) > 9 ? (Checksum & 0xF) + L'A' - 10 : (Checksum & 0xF) + L'0';
+ Checksum >>= 4;
}
j = CopyLength + 4;
}
/*
* @implemented
+ * Note: the function does not conform to the annotations.
+ * SpacesFound is not always set!
*/
+_IRQL_requires_max_(PASSIVE_LEVEL)
+_Must_inspect_result_
+NTSYSAPI
BOOLEAN
NTAPI
-RtlIsNameLegalDOS8Dot3(IN PCUNICODE_STRING UnicodeName,
- IN OUT POEM_STRING AnsiName OPTIONAL,
- IN OUT PBOOLEAN SpacesFound OPTIONAL)
+RtlIsNameLegalDOS8Dot3 (
+ _In_ PCUNICODE_STRING Name,
+ _Inout_opt_ POEM_STRING OemName,
+ _Out_opt_ PBOOLEAN NameContainsSpaces)
{
static const char Illegal[] = "*?<>|\"+=,;[]:/\\\345";
int Dot = -1;
char Buffer[12];
OEM_STRING OemString;
BOOLEAN GotSpace = FALSE;
+ NTSTATUS Status;
- if (!AnsiName)
+ if (!OemName)
{
OemString.Length = sizeof(Buffer);
OemString.MaximumLength = sizeof(Buffer);
OemString.Buffer = Buffer;
- AnsiName = &OemString;
+ OemName = &OemString;
}
- if (RtlUpcaseUnicodeStringToCountedOemString( AnsiName, UnicodeName, FALSE ) != STATUS_SUCCESS)
+
+ Status = RtlUpcaseUnicodeStringToCountedOemString(OemName, Name, FALSE);
+ if (!NT_SUCCESS(Status))
return FALSE;
- if ((AnsiName->Length > 12) || (AnsiName->Buffer == NULL)) return FALSE;
+ if ((OemName->Length > 12) || (OemName->Buffer == NULL)) return FALSE;
/* a starting . is invalid, except for . and .. */
- if (AnsiName->Buffer[0] == '.')
+ if (OemName->Buffer[0] == '.')
{
- if (AnsiName->Length != 1 && (AnsiName->Length != 2 || AnsiName->Buffer[1] != '.')) return FALSE;
- if (SpacesFound) *SpacesFound = FALSE;
+ if (OemName->Length != 1 && (OemName->Length != 2 || OemName->Buffer[1] != '.')) return FALSE;
+ if (NameContainsSpaces) *NameContainsSpaces = FALSE;
return TRUE;
}
- for (i = 0; i < AnsiName->Length; i++)
+ for (i = 0; i < OemName->Length; i++)
{
- switch (AnsiName->Buffer[i])
+ switch (OemName->Buffer[i])
{
case ' ':
/* leading/trailing spaces not allowed */
- if (!i || i == AnsiName->Length-1 || AnsiName->Buffer[i+1] == '.') return FALSE;
+ if (!i || i == OemName->Length-1 || OemName->Buffer[i+1] == '.') return FALSE;
GotSpace = TRUE;
break;
case '.':
Dot = i;
break;
default:
- if (strchr(Illegal, AnsiName->Buffer[i])) return FALSE;
+ if (strchr(Illegal, OemName->Buffer[i])) return FALSE;
break;
}
}
*/
if (Dot == -1)
{
- if (AnsiName->Length > 8) return FALSE;
+ if (OemName->Length > 8) return FALSE;
}
else
{
- if (Dot > 8 || (AnsiName->Length - Dot > 4) || Dot == AnsiName->Length - 1) return FALSE;
+ if (Dot > 8 || (OemName->Length - Dot > 4) || Dot == OemName->Length - 1) return FALSE;
}
- if (SpacesFound) *SpacesFound = GotSpace;
+ if (NameContainsSpaces) *NameContainsSpaces = GotSpace;
return TRUE;
}