Index: source/Utility/Status.cpp =================================================================== --- source/Utility/Status.cpp +++ source/Utility/Status.cpp @@ -27,6 +27,9 @@ #include #endif +#ifdef _WIN32 +#include +#endif #include // for uint32_t namespace llvm { @@ -87,7 +90,8 @@ 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(AsCString(), llvm::inconvertibleErrorCode()); } @@ -106,6 +110,23 @@ 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 @@ m_string = llvm::sys::StrError(m_code); break; + case eErrorTypeWin32: +#if defined(_WIN32) + m_string = RetrieveWin32ErrorString(m_code); +#endif + break; + default: break; } Index: unittests/Utility/StatusTest.cpp =================================================================== --- unittests/Utility/StatusTest.cpp +++ unittests/Utility/StatusTest.cpp @@ -10,6 +10,10 @@ #include "lldb/Utility/Status.h" #include "gtest/gtest.h" +#ifdef _WIN32 +#include +#endif + using namespace lldb_private; using namespace lldb; @@ -51,3 +55,22 @@ 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