Description
- Version: 8.9.3 (from Electron 2.0.10)
- Platform: windows
- Subsystem: core
I'm writing a native extension and trying to throw exceptions using WinapiErrnoException but the error messages I get are truncated to only the first letter (so instead of "Access Denied" the error message is "A")
I believe I have tracked the error to https://github.com/nodejs/node/blob/master/src/exceptions.cc where it uses FormatMessage to generate a localised error message from an error code like this:
char* errmsg = nullptr;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr);
Now FormatMessage is just a macro that resolves to FormatMessageA on ansi builds and FormatMessageW on wide character/unicode builds. LPTSTR is also a macro that resolves to "char*" on ansi builds and "wchar_t*" on wide character builds.
So I can't be sure but I assume node is built with unicode support so the cast of char* to LPTSTR is invalid as the buffer produced by FormatMessage will be UTF-16 encoded.
This would explain why I get only the first character, as in an english text utf-16 encoded every second byte would be 0x00.
The simplest solution would be to swap FormatMessage for FormatMessageA to explicitly use the ansi variant but the correct solution (for proper localization) would be to change the function to actually use char*/wchar_t* appropriately and then convert to utf-8.
Now I will admit I feel a bit stupid writing this because I can't believe I'd be the first person to notice this if it was true so I'm sure someone will tell me how that's not it and the code actually works as intended - but I don't see how. At the very least the use of the cast from char* to LPTSTR is technically incorrect.