[CONSOLE.CPL] Rewrite the BuildCodePageList() registry enumeration loop and use far less stack space.

Any valid code page value name in System\CurrentControlSet\Control\Nls\CodePage
is a string representation of its corresponding decimal value, that
cannot be larger than MAXUSHORT == 65535, i.e. longer than 5+1
characters.

Noticed with the analyser warning
dll\cpl\console\options.c(74): warning C6262: Function uses '32808' bytes
of stack: exceeds /analyze:stacksize '16384'. Consider moving some data to heap.

Make the enumeration loop actually stop when ERROR_NO_MORE_ITEMS is
returned. If we got another error, e.g. because the value name was
too long (and thus, an invalid code page), just ignore and continue
looping.
This commit is contained in:
Hermès Bélusca-Maïto 2022-01-29 18:42:23 +01:00
parent 13b3425369
commit 2a5536c540
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0

View file

@ -76,17 +76,23 @@ BuildCodePageList(
IN UINT CurrentCodePage)
{
LIST_CTL ListCtl;
LRESULT lResult;
HKEY hKey;
DWORD dwIndex, dwSize, dwType;
DWORD dwIndex, dwType;
DWORD cchValueName;
UINT CodePage;
WCHAR szValueName[MAX_VALUE_NAME];
// #define REGSTR_PATH_CODEPAGE TEXT("System\\CurrentControlSet\\Control\\Nls\\CodePage")
/* Valid code page value names are string representations
* of their corresponding decimal values, that are not larger
* than MAXUSHORT == 65535. */
WCHAR szValueName[sizeof("65535")];
/* Open the Nls\CodePage key */
// #define REGSTR_PATH_CODEPAGE TEXT("System\\CurrentControlSet\\Control\\Nls\\CodePage")
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"System\\CurrentControlSet\\Control\\Nls\\CodePage",
0,
KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
KEY_QUERY_VALUE,
&hKey) != ERROR_SUCCESS)
{
return;
@ -97,16 +103,26 @@ BuildCodePageList(
ListCtl.GetData = List_GetData;
/* Enumerate all the available code pages on the system */
dwSize = ARRAYSIZE(szValueName);
dwIndex = 0;
while (RegEnumValueW(hKey, dwIndex, szValueName, &dwSize,
NULL, &dwType, NULL, NULL) == ERROR_SUCCESS) // != ERROR_NO_MORE_ITEMS
for (dwIndex = 0, cchValueName = ARRAYSIZE(szValueName);
(lResult = RegEnumValueW(hKey, dwIndex,
szValueName, &cchValueName,
NULL, &dwType,
NULL, NULL)) != ERROR_NO_MORE_ITEMS;
++dwIndex, cchValueName = ARRAYSIZE(szValueName))
{
/* Ignore these parameters, prepare for next iteration */
dwSize = ARRAYSIZE(szValueName);
++dwIndex;
/* Ignore if we failed for another reason, e.g. because
* the value name is too long (and thus, invalid). */
if (lResult != ERROR_SUCCESS)
continue;
/* Check the value type validity */
/* Validate the value name (exclude the unnamed value) */
if (!cchValueName || (*szValueName == UNICODE_NULL))
continue;
/* Too large value names have already been handled with ERROR_MORE_DATA */
ASSERT((cchValueName < ARRAYSIZE(szValueName)) &&
(szValueName[cchValueName] == UNICODE_NULL));
/* Validate the value type */
if (dwType != REG_SZ)
continue;