-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<system_error>: FormatMessageA needs be used in a different way #2451
Comments
The behavior previously to #457 called FormatMessageW with no explicit locale, then converted using CP_ACP, so I wouldn't be opposed to pass the system language ID to FormatMessageA. This might throw off people expecting the user language ID to be used, but that was always a broken/poorly supported scenario (since the issue you raised was present even before #457). |
Why the ANSI version of FormatMessage was preferred? I'm trying to understand which encoding std::string should use. For example, if you pass such a string to fputs or std::cout. Based on my test, it should be in system ACP, not user ACP. And it would be better if we can totally avoid using non-unicode functions. Because some languages even don't have a code page. |
If So you end up calling |
I tested with System Language: Russian and User Language - Chinese. So is this a debugger visualizer issue? |
I reached the point by setting Windows display language to Chinese for the current user. This setting is per user. If I click the "Administrative Language Settings" at the bottom, it will pop up a traditional dialog Most Windows users are very familiar with the later one. Most important, as the dialog shows the system level local is still "English (US)". The mismatch will cause problems for who uses ANSI APIs. Because these APIs do not have user-level locale information, they use the system-level locale setting. But the FormatMessage function is different. It has a "dwLanguageId" parameter for such a purpose. If you pass in zero, it will prefer user language settings to system language settings. See: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage |
If we update this function to use the user locale, then it becomes the "odd one out". Every other standard function that takes So I think the best course of action here is to explicitly pass the system locale ID (which we can obtain by calling GetSystemDefaultLangID) to FormatMessage instead of 0. |
yes, but not always. When I had had such settings: (User Interface- Russian, Region: China), I had System Language: Russian and User Language - Chinese, and FormatMessageA still preferred System Language. Anyway I think explicitly pass GetSystemDefaultLangID is correct. |
Describe the bug
Windows settings have “user language id” and “system language id”. They can be different. std::system_category().message() returns "???" when they are different.
By default FormatMessage returns a string in “user language”. The Unicode version of FormatMessage works good in all cases. But the ANSI version, like all other ANSI version Windows APIs, would try to convert the result string to a multibyte string based on “system language id”. It goes wrong when the two ids are different. For example, If your user language is Chinese but the system language is English, it can only returns “????”, because you can’t encode a Chinese string in ISO-8859-1.
So if you need to return the error message in std::string type, there are two solutions:
Command-line test case
To compile it:
C:\Temp>cl /EHsc .\repro.cpp
To reproduce the error:
I assume you have a clean Windows installation. Then please create a new user without Administrator privilege. Then login to the user, go to settings and change the display language to something different. Like, Chinese. In such a case, you only changed the user's locale, not the system. Because the user doesn't have the privilege to change system level settings.
Then run the code, use your debugger to inspect the binary content of the error message. Do not print it out. Printing is a different problem. Just look the raw bytes.
Expected behavior
The error message should contain useful information.
STL version
VS 2022 17.0.3
Additional context
Add any other context about the problem here.
The text was updated successfully, but these errors were encountered: