[CONUTILS] Implement ConSetThreadUILanguage() as a wrapper for kernel32!SetThreadUILanguage().

CORE-17601

Dynamically load SetThreadUILanguage(), so as to support systems where this API is not present.

Hopefully implemented in a thread-safe manner.
This commit is contained in:
Hermès Bélusca-Maïto 2021-05-26 00:12:10 +02:00
parent 35f499e52f
commit 7c3aabc088
No known key found for this signature in database
GPG Key ID: 3B2539C65E7B93D0
2 changed files with 59 additions and 4 deletions

View File

@ -3,8 +3,8 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Base set of functions for loading string resources
* and message strings, and handle type identification.
* COPYRIGHT: Copyright 2017-2018 ReactOS Team
* Copyright 2017-2018 Hermes Belusca-Maito
* COPYRIGHT: Copyright 2017-2021 ReactOS Team
* Copyright 2017-2021 Hermes Belusca-Maito
*/
/**
@ -320,6 +320,57 @@ FormatMessageSafeW(
return dwLength;
}
/**
* @name ConSetThreadUILanguage
* Sets the current thread's user interface language.
* Mostly used by console applications for selecting a
* language identifier that best supports the NT Console.
* This function dynamically loads and calls kernel32!SetThreadUILanguage()
* so as to be able to work on older environments where this
* API is not supported.
* The FormatMessage() API also bases itself on the thread's
* current language for its default behaviour (unless an explicit
* language identifier has been provided).
*
* @param[in,opt] LangId
* (Vista+) A non-zero language identifier that specifies the
* current thread's user interface language to set.
* (XP/2003) Set the language identifier to 0 for selecting a
* language identifier that best supports the NT Console.
*
* @return
* Returns LangId in case of success, or 0 in case of failure.
* If LangId was set to 0, the function always succeeds and returns
* the language identifier that best supports the NT Console.
*
* @remark
* This function is thread-safe.
*
* @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-setthreaduilanguage">SetThreadUILanguage() (on MSDN)</a>
**/
LANGID
ConSetThreadUILanguage(
IN LANGID LangId OPTIONAL)
{
/* The function pointer is shared amongst all threads */
static volatile LANGID (WINAPI *pfnSetThreadUILanguage)(LANGID) = NULL;
if (!pfnSetThreadUILanguage)
{
/* Load the API from kernel32 */
PVOID pFunc = (PVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetThreadUILanguage");
if (!pFunc)
{
/* Fail since the API is not available */
return 0;
}
/* Set the function pointer in case it hasn't been already set by another thread */
InterlockedCompareExchangePointer((PVOID*)&pfnSetThreadUILanguage, pFunc, NULL);
// ASSERT(pfnSetThreadUILanguage);
}
return pfnSetThreadUILanguage(LangId);
}
/**
* @name IsTTYHandle
* Checks whether a handle refers to a valid TTY object.

View File

@ -3,8 +3,8 @@
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Base set of functions for loading string resources
* and message strings, and handle type identification.
* COPYRIGHT: Copyright 2017-2018 ReactOS Team
* Copyright 2017-2018 Hermes Belusca-Maito
* COPYRIGHT: Copyright 2017-2021 ReactOS Team
* Copyright 2017-2021 Hermes Belusca-Maito
*/
/**
@ -56,6 +56,10 @@ FormatMessageSafeW(
IN DWORD nSize,
IN va_list *Arguments OPTIONAL);
LANGID
ConSetThreadUILanguage(
IN LANGID LangId OPTIONAL);
BOOL
IsTTYHandle(IN HANDLE hHandle);