diff --git a/sdk/lib/conutils/utils.c b/sdk/lib/conutils/utils.c index 31fe8951092..35f7f6b92d6 100644 --- a/sdk/lib/conutils/utils.c +++ b/sdk/lib/conutils/utils.c @@ -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 SetThreadUILanguage() (on MSDN) + **/ +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. diff --git a/sdk/lib/conutils/utils.h b/sdk/lib/conutils/utils.h index 798548056e9..7d613d996fd 100644 --- a/sdk/lib/conutils/utils.h +++ b/sdk/lib/conutils/utils.h @@ -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);