Reactos

[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.

+59 -4
+53 -2
sdk/lib/conutils/utils.c
··· 3 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 4 * PURPOSE: Base set of functions for loading string resources 5 5 * and message strings, and handle type identification. 6 - * COPYRIGHT: Copyright 2017-2018 ReactOS Team 7 - * Copyright 2017-2018 Hermes Belusca-Maito 6 + * COPYRIGHT: Copyright 2017-2021 ReactOS Team 7 + * Copyright 2017-2021 Hermes Belusca-Maito 8 8 */ 9 9 10 10 /** ··· 318 318 _SEH2_END; 319 319 320 320 return dwLength; 321 + } 322 + 323 + /** 324 + * @name ConSetThreadUILanguage 325 + * Sets the current thread's user interface language. 326 + * Mostly used by console applications for selecting a 327 + * language identifier that best supports the NT Console. 328 + * This function dynamically loads and calls kernel32!SetThreadUILanguage() 329 + * so as to be able to work on older environments where this 330 + * API is not supported. 331 + * The FormatMessage() API also bases itself on the thread's 332 + * current language for its default behaviour (unless an explicit 333 + * language identifier has been provided). 334 + * 335 + * @param[in,opt] LangId 336 + * (Vista+) A non-zero language identifier that specifies the 337 + * current thread's user interface language to set. 338 + * (XP/2003) Set the language identifier to 0 for selecting a 339 + * language identifier that best supports the NT Console. 340 + * 341 + * @return 342 + * Returns LangId in case of success, or 0 in case of failure. 343 + * If LangId was set to 0, the function always succeeds and returns 344 + * the language identifier that best supports the NT Console. 345 + * 346 + * @remark 347 + * This function is thread-safe. 348 + * 349 + * @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-setthreaduilanguage">SetThreadUILanguage() (on MSDN)</a> 350 + **/ 351 + LANGID 352 + ConSetThreadUILanguage( 353 + IN LANGID LangId OPTIONAL) 354 + { 355 + /* The function pointer is shared amongst all threads */ 356 + static volatile LANGID (WINAPI *pfnSetThreadUILanguage)(LANGID) = NULL; 357 + 358 + if (!pfnSetThreadUILanguage) 359 + { 360 + /* Load the API from kernel32 */ 361 + PVOID pFunc = (PVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetThreadUILanguage"); 362 + if (!pFunc) 363 + { 364 + /* Fail since the API is not available */ 365 + return 0; 366 + } 367 + /* Set the function pointer in case it hasn't been already set by another thread */ 368 + InterlockedCompareExchangePointer((PVOID*)&pfnSetThreadUILanguage, pFunc, NULL); 369 + // ASSERT(pfnSetThreadUILanguage); 370 + } 371 + return pfnSetThreadUILanguage(LangId); 321 372 } 322 373 323 374 /**
+6 -2
sdk/lib/conutils/utils.h
··· 3 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 4 * PURPOSE: Base set of functions for loading string resources 5 5 * and message strings, and handle type identification. 6 - * COPYRIGHT: Copyright 2017-2018 ReactOS Team 7 - * Copyright 2017-2018 Hermes Belusca-Maito 6 + * COPYRIGHT: Copyright 2017-2021 ReactOS Team 7 + * Copyright 2017-2021 Hermes Belusca-Maito 8 8 */ 9 9 10 10 /** ··· 55 55 OUT LPWSTR lpBuffer, 56 56 IN DWORD nSize, 57 57 IN va_list *Arguments OPTIONAL); 58 + 59 + LANGID 60 + ConSetThreadUILanguage( 61 + IN LANGID LangId OPTIONAL); 58 62 59 63 BOOL 60 64 IsTTYHandle(IN HANDLE hHandle);