From 30198dbcee79d3241f2b906a50fca00cc335ee47 Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Mon, 25 Mar 2019 09:35:04 -0400
Subject: [PATCH] DynamicLoader: fix error reporting on Windows

Windows was reporting errors in `wchar_t` which was not reinterpreted as
UTF-8 which is expected from kwsys errors. This basically made error
messages appear as truncated since the UCS-2 byte array had embedded
byte NUL characters.
---
 DynamicLoader.cxx | 40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/DynamicLoader.cxx b/DynamicLoader.cxx
index a85690f7..17432f3c 100644
--- a/DynamicLoader.cxx
+++ b/DynamicLoader.cxx
@@ -247,24 +247,38 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
 #  endif
 }
 
+#  define DYNLOAD_ERROR_BUFFER_SIZE 1024
+
 const char* DynamicLoader::LastError()
 {
-  LPVOID lpMsgBuf = NULL;
-
-  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-                NULL, GetLastError(),
-                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
-                (LPTSTR)&lpMsgBuf, 0, NULL);
+  wchar_t lpMsgBuf[DYNLOAD_ERROR_BUFFER_SIZE + 1];
+
+  DWORD error = GetLastError();
+  DWORD length = FormatMessageW(
+    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
+    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+    lpMsgBuf, DYNLOAD_ERROR_BUFFER_SIZE, NULL);
+
+  static char str[DYNLOAD_ERROR_BUFFER_SIZE + 1];
+
+  if (length < 1) {
+    /* FormatMessage failed.  Use a default message.  */
+    _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
+              "DynamicLoader encountered error 0x%X.  "
+              "FormatMessage failed with error 0x%X",
+              error, GetLastError());
+    return str;
+  }
 
-  if (!lpMsgBuf) {
-    return NULL;
+  if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, str,
+                           DYNLOAD_ERROR_BUFFER_SIZE, NULL, NULL)) {
+    /* WideCharToMultiByte failed.  Use a default message.  */
+    _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
+              "DynamicLoader encountered error 0x%X.  "
+              "WideCharToMultiByte failed with error 0x%X",
+              error, GetLastError());
   }
 
-  static char* str = 0;
-  delete[] str;
-  str = strcpy(new char[strlen((char*)lpMsgBuf) + 1], (char*)lpMsgBuf);
-  // Free the buffer.
-  LocalFree(lpMsgBuf);
   return str;
 }
 
-- 
GitLab