Author: pschweitzer
Date: Sun Sep 27 20:54:20 2015
New Revision: 69389
URL:
http://svn.reactos.org/svn/reactos?rev=69389&view=rev
Log:
[RTL]
Major bugfixing session for RtlGenerate8dot3Name()... Up to know, AllowExtendedCharacters
was totally ignored and any upcased char, as long as it was not in the forbidden list was
accepted. This was bringing numerous problems (cf: apitest :-)).
So, now, the following fixes were brought:
- AllowExtendedCharacters isn't ignored any longer. If it's given, the unicode
char is upcased, if it's not, as previously, the ansi char is upcased
- Be more strict in the allowed chars in name: only allow "graph" chars. This
avoids generating broken names that aren't allowed in FAT
- In case no char could be added in the name, then, for the generation of the name
checksum and use it as shortname
- When writing the checksum, don't use reversed order, but direct order, to match
Windows behavior (as exposed with tests)
- When writing the checksum, use when possible bit operations instead of numerical
operations for performances reasons (NFC)
- Rewrite RtlpGetCheckSum() with an algorithm that produces the exact same checksums than
Windows 2003.
This whole commit fixes all apitests related (direct visible effect). As a bonus, it also
fixes short names generation in FAT: we no longer produce broken volumes with
international file names.
This also fixes less visible issues: we were producing unicode strings with null char in
their middle (as exposed in tests), not sure about how all functions could handle this:
likely not that good, this could have lead to various memory issues & corruptions.
CORE-10223 #resolve #comment Fixed with r69389
Modified:
trunk/reactos/lib/rtl/dos8dot3.c
Modified: trunk/reactos/lib/rtl/dos8dot3.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/dos8dot3.c?rev=693…
==============================================================================
--- trunk/reactos/lib/rtl/dos8dot3.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/dos8dot3.c [iso-8859-1] Sun Sep 27 20:54:20 2015
@@ -30,17 +30,42 @@
static USHORT
RtlpGetCheckSum(PUNICODE_STRING Name)
{
- USHORT Hash = 0;
- ULONG Length;
- PWCHAR c;
-
- Length = Name->Length / sizeof(WCHAR);
- c = Name->Buffer;
- while(Length--)
- {
- Hash = (Hash + (*c << 4) + (*c >> 4)) * 11;
- c++;
- }
+ USHORT Hash, Saved;
+ WCHAR * CurChar;
+ USHORT Len;
+
+ if (Name->Length == 0)
+ {
+ return 0;
+ }
+
+ if (Name->Length == sizeof(WCHAR))
+ {
+ return Name->Buffer[0];
+ }
+
+ CurChar = Name->Buffer;
+ Hash = (*CurChar << 8) + *(CurChar + 1);
+ if (Name->Length == 2 * sizeof(WCHAR))
+ {
+ 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;
}
@@ -78,7 +103,7 @@
ULONG IndexLength;
ULONG CurrentIndex;
USHORT Checksum;
- CHAR c;
+ WCHAR c;
StrLength = Name->Length / sizeof(WCHAR);
DPRINT("StrLength: %lu\n", StrLength);
@@ -98,15 +123,27 @@
/* 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 != ' ')
- {
- NameBuffer[NameLength++] = (WCHAR)c;
+ else if (c != L'.' && c != L' ')
+ {
+ if (isgraph(c) || (AllowExtendedCharacters && iswgraph(c)))
+ {
+ NameBuffer[NameLength++] = c;
+ }
}
}
@@ -118,15 +155,27 @@
{
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;
+ }
}
}
}
@@ -171,7 +220,15 @@
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);
@@ -192,12 +249,11 @@
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;
}