[lldb] Add support in Status::AsCString to retrieve win32 system error strings
authorAaron Smith <aaron.smith@microsoft.com>
Fri, 19 Oct 2018 18:58:24 +0000 (18:58 +0000)
committerAaron Smith <aaron.smith@microsoft.com>
Fri, 19 Oct 2018 18:58:24 +0000 (18:58 +0000)
Reviewers: rnk, zturner, aleksandr.urakov

Subscribers: lldb-commits

Differential Revision: https://reviews.llvm.org/D53092

llvm-svn: 344798

lldb/source/Utility/Status.cpp
lldb/unittests/Utility/StatusTest.cpp

index f6dc228..5caecc6 100644 (file)
@@ -27,6 +27,9 @@
 #include <mach/mach.h>
 #endif
 
+#ifdef _WIN32
+#include <windows.h>
+#endif
 #include <stdint.h> // for uint32_t
 
 namespace llvm {
@@ -87,7 +90,8 @@ llvm::Error Status::ToError() const {
   if (Success())
     return llvm::Error::success();
   if (m_type == ErrorType::eErrorTypePOSIX)
-    return llvm::errorCodeToError(std::error_code(m_code, std::generic_category()));
+    return llvm::errorCodeToError(
+        std::error_code(m_code, std::generic_category()));
   return llvm::make_error<llvm::StringError>(AsCString(),
                                              llvm::inconvertibleErrorCode());
 }
@@ -106,6 +110,23 @@ const Status &Status::operator=(const Status &rhs) {
 
 Status::~Status() = default;
 
+#ifdef _WIN32
+static std::string RetrieveWin32ErrorString(uint32_t error_code) {
+  char *buffer = nullptr;
+  std::string message;
+  // Retrieve win32 system error.
+  if (::FormatMessageA(
+          FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+              FORMAT_MESSAGE_MAX_WIDTH_MASK,
+          NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+          (LPSTR)&buffer, 0, NULL)) {
+    message.assign(buffer);
+    ::LocalFree(buffer);
+  }
+  return message;
+}
+#endif
+
 //----------------------------------------------------------------------
 // Get the error value as a NULL C string. The error string will be fetched and
 // cached on demand. The cached error string value will remain until the error
@@ -128,6 +149,12 @@ const char *Status::AsCString(const char *default_error_str) const {
       m_string = llvm::sys::StrError(m_code);
       break;
 
+    case eErrorTypeWin32:
+#if defined(_WIN32)
+      m_string = RetrieveWin32ErrorString(m_code);
+#endif
+      break;
+
     default:
       break;
     }
index b3f5182..4e0cfb9 100644 (file)
 #include "lldb/Utility/Status.h"
 #include "gtest/gtest.h"
 
+#ifdef _WIN32
+#include <winerror.h>
+#endif
+
 using namespace lldb_private;
 using namespace lldb;
 
@@ -51,3 +55,22 @@ TEST(StatusTest, ErrorConversion) {
   EXPECT_TRUE(bool(foo));
   EXPECT_EQ("foo", llvm::toString(std::move(foo)));
 }
+
+#ifdef _WIN32
+TEST(StatusTest, ErrorWin32) {
+  auto success = Status(NO_ERROR, ErrorType::eErrorTypeWin32);
+  EXPECT_STREQ(NULL, success.AsCString());
+  EXPECT_FALSE(success.ToError());
+  EXPECT_TRUE(success.Success());
+
+  auto s = Status(ERROR_ACCESS_DENIED, ErrorType::eErrorTypeWin32);
+  EXPECT_TRUE(s.Fail());
+  EXPECT_STREQ("Access is denied. ", s.AsCString());
+
+  s.SetError(ERROR_IPSEC_IKE_TIMED_OUT, ErrorType::eErrorTypeWin32);
+  EXPECT_STREQ("Negotiation timed out ", s.AsCString());
+
+  s.SetError(16000, ErrorType::eErrorTypeWin32);
+  EXPECT_STREQ("unknown error", s.AsCString());
+}
+#endif