mirror of
https://github.com/reactos/reactos.git
synced 2026-06-01 08:50:24 +08:00
[RTL] Fix searching resource names
Resource names are sorted with '_' being higher than any alphabetic characters. This means _wcsicmp cannot be used to search, because it lowercases the characters before comparison, which would make '_' lower than lowercase alphabetic characters. Implement a custom compare function instead. See CORE-20401, CORE-20408
This commit is contained in:
@@ -121,6 +121,53 @@ IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function performs a case-insensitive comparison of a
|
||||
* null-terminated wide string with a resource string.
|
||||
* Unlike _wcsicmp, which lowercases the characters before comparison,
|
||||
* this function uppercases them, because that is how resource strings
|
||||
* are sorted (e.g. '_' comes after 'z' / 'Z').
|
||||
*/
|
||||
static
|
||||
int
|
||||
CompareResourceString(
|
||||
const wchar_t *SearchString,
|
||||
const IMAGE_RESOURCE_DIR_STRING_U *ResourceString)
|
||||
{
|
||||
wchar_t const* p1 = SearchString;
|
||||
wchar_t const* p2 = ResourceString->NameString;
|
||||
size_t remaining = ResourceString->Length;
|
||||
wchar_t chr1, chr2;
|
||||
|
||||
while (remaining-- != 0)
|
||||
{
|
||||
chr1 = *p1++;
|
||||
chr2 = *p2++;
|
||||
|
||||
/* Quick direct comparison first */
|
||||
if (chr1 != chr2)
|
||||
{
|
||||
/* No direct match, upcase both characters */
|
||||
if ((chr1 >= 'a') && (chr1 <= 'z'))
|
||||
chr1 -= ('a' - 'A');
|
||||
if ((chr2 >= 'a') && (chr2 <= 'z'))
|
||||
chr2 -= ('a' - 'A');
|
||||
|
||||
/* Compare again, if they don't match, return the difference */
|
||||
if (chr1 != chr2)
|
||||
return chr1 - chr2;
|
||||
}
|
||||
}
|
||||
|
||||
/* All characters matched, check if the search string ends here */
|
||||
if (*p1 != 0)
|
||||
{
|
||||
/* The search string is longer, return a positive result */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* find_entry_by_name
|
||||
@@ -134,19 +181,17 @@ IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
|
||||
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
|
||||
const IMAGE_RESOURCE_DIR_STRING_U *str;
|
||||
int min, max, res, pos;
|
||||
size_t namelen;
|
||||
|
||||
if (!((ULONG_PTR)name & 0xFFFF0000)) return find_entry_by_id( dir, (ULONG_PTR)name & 0xFFFF, root, want_dir );
|
||||
entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
|
||||
namelen = wcslen(name);
|
||||
min = 0;
|
||||
max = dir->NumberOfNamedEntries - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
pos = (min + max) / 2;
|
||||
str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const char *)root + entry[pos].NameOffset);
|
||||
res = _wcsnicmp( name, str->NameString, str->Length );
|
||||
if (!res && namelen == str->Length)
|
||||
res = CompareResourceString(name, str);
|
||||
if (!res)
|
||||
{
|
||||
if (!entry[pos].DataIsDirectory == !want_dir)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user