Use FormatMessageA instead of th FormatMessage macro.

 Add FORMAT_MESSAGE_IGNORE_INSERTS flag to FormatMessageA avoids
 ERROR_INVALID_PARAMETER (error code 87), which is recommended in:
 https://devblogs.microsoft.com/oldnewthing/20071128-00/?p=24353

 To ensure that the trailing "\r\n" is correctly removed when using other
 periods (other than U+002E, such as Idengraphic FullStop(U+3002))
 at the end of error message.

 Before testing std::system_category().message(int), set the thread preferred
 language to en-US so that the returned string can meet expectations in
 various language environments.

 libstdc++-v3/ChangeLog:

        * src/c++11/system_error.cc (system_error_category) [_WIN32]:
        Fix typo in __MINGW32__ macro name.
        Fix behavioral issus in some situations.
        * testsuite/19_diagnostics/error_category/system_category.cc:
        Adujust for behaviour on Windows.
---
 libstdc++-v3/src/c++11/system_error.cc        | 21 ++++++++++---------
 .../error_category/system_category.cc         | 18 +++++++++++++---
 2 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/src/c++11/system_error.cc 
b/libstdc++-v3/src/c++11/system_error.cc
index b9a0b2c158f..dec65081b8e 100644
--- a/libstdc++-v3/src/c++11/system_error.cc
+++ b/libstdc++-v3/src/c++11/system_error.cc
@@ -161,22 +161,23 @@ namespace
 #if defined(_WIN32) && !defined(__CYGWIN__)
       char* buf = nullptr;
       auto len
-       = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
-                       | FORMAT_MESSAGE_ALLOCATE_BUFFER,
-                       nullptr,
-                       i,
-                       LANG_USER_DEFAULT,
-                       reinterpret_cast<LPTSTR>(&buf),
-                       0,
-                       nullptr);
+       = FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM
+                         | FORMAT_MESSAGE_ALLOCATE_BUFFER
+                         | FORMAT_MESSAGE_IGNORE_INSERTS,
+                         nullptr,
+                         i,
+                         LANG_USER_DEFAULT,
+                         reinterpret_cast<LPTSTR>(&buf),
+                         0,
+                         nullptr);
       if (len > 0)
       {
        struct deleter {
          void operator()(void* p) const { ::LocalFree(p); }
        };
        std::unique_ptr<char[], deleter> guard(buf);
-       if (len > 3 && !__builtin_memcmp(buf + len - 3, ".\r\n", 3)) [[likely]]
-         len -= 3;
+       if (len > 2 && !__builtin_memcmp (buf + len - 2, "\r\n", 2)) [[likely]]
+         len -= 2 + (buf[len - 3] == '.');
        return string(buf, len);
       }
       return string("Unknown error code");
diff --git 
a/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc 
b/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
index 196a15347a6..6c90f0f730c 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc
@@ -21,6 +21,11 @@
 #include <locale>
 #include <testsuite_hooks.h>
 
+#if defined __MINGW32__ || defined __MINGW64__
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
 void
 test01()
 {
@@ -34,7 +39,7 @@ test02()
   const std::error_category& cat = std::system_category();
   std::error_condition cond;
 
-#if defined __MING32__ || defined __MINGW64__
+#if defined __MINGW32__ || defined __MINGW64__
   cond = cat.default_error_condition(8); // ERROR_NOT_ENOUGH_MEMORY
   VERIFY( cond.value() == ENOMEM );
   VERIFY( cond.category() == std::generic_category() );
@@ -112,9 +117,16 @@ test03()
   // set "C" locale to get expected message
   auto loc = std::locale::global(std::locale::classic());
 
-#if defined __MING32__ || defined __MINGW64__
+#if defined __MINGW32__ || defined __MINGW64__
+  // On Windows, set thread preferred UI languages to "en-US"
+  // to get expected message
+  ULONG num_langs = 1;
+  SetThreadPreferredUILanguages(MUI_LANGUAGE_NAME, L"en-US\0", &num_langs);
+
   std::string msg = std::system_category().message(5); // ERROR_ACCESS_DENIED
-  VERIFY(msg == "Access denied");
+  VERIFY( msg == "Access is denied" );
+
+  SetThreadPreferredUILanguages(MUI_RESET_FILTERS, nullptr, nullptr);
 #else
   std::string msg = std::system_category().message(EBADF);
   VERIFY( msg.find("file") != std::string::npos );
-- 
2.52.0

Reply via email to