@@ -40,15 +40,33 @@ extern "C" {
4040 // convert to name of Windows error, return 0 for failure, otherwise return number of chars in buffer
4141 // __std_system_error_deallocate_message should be called even if 0 is returned
4242 // pre: *_Ptr_str == nullptr
43- DWORD _Lang_id;
44- const int _Ret = GetLocaleInfoEx (LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_ILANGUAGE | LOCALE_RETURN_NUMBER,
45- reinterpret_cast <LPWSTR>(&_Lang_id), sizeof (_Lang_id) / sizeof (wchar_t ));
46- if (_Ret == 0 ) {
47- _Lang_id = 0 ;
43+
44+ // We start by requesting US English for system_category() messages. (See GH-2451 and GH-3254 for the history.)
45+ // This is consistent with generic_category(), which uses a table of US English strings in the STL.
46+ // In general, system_error messages aren't directly useful to end-users - they're meant for programmer-users.
47+ // Of course, the programmer-user might not speak US English, but machine translation of the message
48+ // (and the numeric value of the error code) should help them understand the error.
49+
50+ constexpr auto _Flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
51+
52+ DWORD _Lang_id = 0 ;
53+ DWORD _Chars = 0 ;
54+
55+ for (int _Attempt = 0 ; _Attempt < 3 && _Chars == 0 ; ++_Attempt) {
56+ if (_Attempt == 0 ) {
57+ _Lang_id = 0x0409 ; // 1033 decimal, "en-US" locale
58+ } else if (_Attempt == 1 ) {
59+ const int _Ret = GetLocaleInfoEx (LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_ILANGUAGE | LOCALE_RETURN_NUMBER,
60+ reinterpret_cast <LPWSTR>(&_Lang_id), sizeof (_Lang_id) / sizeof (wchar_t ));
61+ if (_Ret == 0 ) {
62+ continue ; // If we can't get the system locale's language ID, skip this attempt
63+ }
64+ } else {
65+ _Lang_id = 0 ;
66+ }
67+
68+ _Chars = FormatMessageA (_Flags, nullptr , _Message_id, _Lang_id, reinterpret_cast <char *>(_Ptr_str), 0 , nullptr );
4869 }
49- const unsigned long _Chars =
50- FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
51- nullptr , _Message_id, _Lang_id, reinterpret_cast <char *>(_Ptr_str), 0 , nullptr );
5270
5371 return _CSTD __std_get_string_size_without_trailing_whitespace (*_Ptr_str, _Chars);
5472}
0 commit comments