mirror of
https://github.com/reactos/reactos.git
synced 2024-09-08 19:59:49 +00:00
[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 svn path=/trunk/; revision=69389
This commit is contained in:
parent
df8ea25b31
commit
1ab5b38172
|
@ -30,17 +30,42 @@ RtlpIsShortIllegal(CHAR Char)
|
||||||
static USHORT
|
static USHORT
|
||||||
RtlpGetCheckSum(PUNICODE_STRING Name)
|
RtlpGetCheckSum(PUNICODE_STRING Name)
|
||||||
{
|
{
|
||||||
USHORT Hash = 0;
|
USHORT Hash, Saved;
|
||||||
ULONG Length;
|
WCHAR * CurChar;
|
||||||
PWCHAR c;
|
USHORT Len;
|
||||||
|
|
||||||
Length = Name->Length / sizeof(WCHAR);
|
if (Name->Length == 0)
|
||||||
c = Name->Buffer;
|
|
||||||
while(Length--)
|
|
||||||
{
|
{
|
||||||
Hash = (Hash + (*c << 4) + (*c >> 4)) * 11;
|
return 0;
|
||||||
c++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
return Hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +103,7 @@ RtlGenerate8dot3Name(IN PUNICODE_STRING Name,
|
||||||
ULONG IndexLength;
|
ULONG IndexLength;
|
||||||
ULONG CurrentIndex;
|
ULONG CurrentIndex;
|
||||||
USHORT Checksum;
|
USHORT Checksum;
|
||||||
CHAR c;
|
WCHAR c;
|
||||||
|
|
||||||
StrLength = Name->Length / sizeof(WCHAR);
|
StrLength = Name->Length / sizeof(WCHAR);
|
||||||
DPRINT("StrLength: %lu\n", StrLength);
|
DPRINT("StrLength: %lu\n", StrLength);
|
||||||
|
@ -98,15 +123,27 @@ RtlGenerate8dot3Name(IN PUNICODE_STRING Name,
|
||||||
/* Copy name (6 valid characters max) */
|
/* Copy name (6 valid characters max) */
|
||||||
for (i = 0, NameLength = 0; NameLength < 6 && i < DotPos; i++)
|
for (i = 0, NameLength = 0; NameLength < 6 && i < DotPos; i++)
|
||||||
{
|
{
|
||||||
c = 0;
|
c = UNICODE_NULL;
|
||||||
RtlUpcaseUnicodeToOemN(&c, sizeof(CHAR), &Count, &Name->Buffer[i], sizeof(WCHAR));
|
if (AllowExtendedCharacters)
|
||||||
if (Count != 1 || c == 0 || RtlpIsShortIllegal(c))
|
{
|
||||||
|
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'_';
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,15 +155,27 @@ RtlGenerate8dot3Name(IN PUNICODE_STRING Name,
|
||||||
{
|
{
|
||||||
for (i = DotPos, ExtLength = 0; ExtLength < 4 && i < StrLength; i++)
|
for (i = DotPos, ExtLength = 0; ExtLength < 4 && i < StrLength; i++)
|
||||||
{
|
{
|
||||||
c = 0;
|
c = UNICODE_NULL;
|
||||||
RtlUpcaseUnicodeToOemN(&c, sizeof(CHAR), &Count, &Name->Buffer[i], sizeof(WCHAR));
|
if (AllowExtendedCharacters)
|
||||||
if (Count != 1 || c == 0 || RtlpIsShortIllegal(c))
|
{
|
||||||
|
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'_';
|
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 @@ RtlGenerate8dot3Name(IN PUNICODE_STRING Name,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Context->LastIndexValue = 1;
|
Context->LastIndexValue = 1;
|
||||||
Context->CheckSumInserted = FALSE;
|
if (NameLength == 0)
|
||||||
|
{
|
||||||
|
Context->CheckSumInserted = TRUE;
|
||||||
|
Context->Checksum = RtlpGetCheckSum(Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Context->CheckSumInserted = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexLength = RtlpGetIndexLength(Context->LastIndexValue);
|
IndexLength = RtlpGetIndexLength(Context->LastIndexValue);
|
||||||
|
@ -192,12 +249,11 @@ RtlGenerate8dot3Name(IN PUNICODE_STRING Name,
|
||||||
j = CopyLength;
|
j = CopyLength;
|
||||||
if (Context->CheckSumInserted)
|
if (Context->CheckSumInserted)
|
||||||
{
|
{
|
||||||
j += 3;
|
|
||||||
Checksum = Context->Checksum;
|
Checksum = Context->Checksum;
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
Name8dot3->Buffer[j--] = (Checksum % 16) > 9 ? (Checksum % 16) + L'A' - 10 : (Checksum % 16) + L'0';
|
Name8dot3->Buffer[j++] = (Checksum & 0xF) > 9 ? (Checksum & 0xF) + L'A' - 10 : (Checksum & 0xF) + L'0';
|
||||||
Checksum /= 16;
|
Checksum >>= 4;
|
||||||
}
|
}
|
||||||
j = CopyLength + 4;
|
j = CopyLength + 4;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue