mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
745d047762
Summary: This resolves a dependency cycle introduced in D23037325 (f4f159537f
) and D23480435 (34821976e0
) Reviewed By: xavierd Differential Revision: D23735176 fbshipit-source-id: a4849d512e4181afbb007d7e850aadf092c6eb90
97 lines
2.6 KiB
C++
97 lines
2.6 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This software may be used and distributed according to the terms of the
|
|
* GNU General Public License version 2.
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
#include "eden/fs/utils/WinError.h"
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <sstream>
|
|
namespace facebook {
|
|
namespace eden {
|
|
|
|
std::string win32ErrorToString(uint32_t error) {
|
|
struct LocalDeleter {
|
|
void operator()(HLOCAL p) noexcept {
|
|
::LocalFree(p);
|
|
}
|
|
};
|
|
|
|
LPSTR messageBufferRaw = nullptr;
|
|
// By default, FormatMessageA will terminate the string with "\r\n",
|
|
// and the mis-named (and mis-documented) FORMAT_MESSAGE_MAX_WIDTH_MASK flag
|
|
// will remove these (but add a whitespace instead).
|
|
size_t size = FormatMessageA(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
|
nullptr,
|
|
error,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPSTR)&messageBufferRaw,
|
|
0,
|
|
nullptr);
|
|
// Get a unique_ptr to the raw buffer, so it's released in case of an
|
|
// exception.
|
|
std::unique_ptr<char, LocalDeleter> messageBuffer{messageBufferRaw};
|
|
|
|
std::stringstream stream;
|
|
if ((size > 0) && (messageBuffer)) {
|
|
stream << "Error (0x" << std::hex << error << ") " << messageBuffer.get();
|
|
} else {
|
|
stream << "Error (0x" << std::hex << error << ") Unknown Error";
|
|
}
|
|
return stream.str();
|
|
}
|
|
|
|
const char* Win32ErrorCategory::name() const noexcept {
|
|
return "Win32 Error";
|
|
}
|
|
|
|
std::string Win32ErrorCategory::message(int error) const {
|
|
return win32ErrorToString(error);
|
|
}
|
|
|
|
const std::error_category& Win32ErrorCategory::get() noexcept {
|
|
static class Win32ErrorCategory cat;
|
|
return cat;
|
|
}
|
|
|
|
const char* HResultErrorCategory::name() const noexcept {
|
|
return "HRESULT Error";
|
|
}
|
|
|
|
std::string HResultErrorCategory::message(int error) const {
|
|
return win32ErrorToString(error);
|
|
}
|
|
|
|
const std::error_category& HResultErrorCategory::get() noexcept {
|
|
static class HResultErrorCategory cat;
|
|
return cat;
|
|
}
|
|
|
|
HRESULT exceptionToHResult(const std::exception& ex) noexcept {
|
|
if (auto e = dynamic_cast<const std::system_error*>(&ex)) {
|
|
auto code = e->code();
|
|
XLOG(ERR) << e->what() << ": " << code;
|
|
if (code.category() == HResultErrorCategory::get()) {
|
|
return code.value();
|
|
}
|
|
if (code.category() == Win32ErrorCategory::get()) {
|
|
return HRESULT_FROM_WIN32(code.value());
|
|
}
|
|
return ERROR_ERRORS_ENCOUNTERED;
|
|
} else if (auto e = dynamic_cast<const std::bad_alloc*>(&ex)) {
|
|
return E_OUTOFMEMORY;
|
|
} else {
|
|
XLOG(ERR) << ex.what();
|
|
return ERROR_ERRORS_ENCOUNTERED;
|
|
}
|
|
}
|
|
|
|
} // namespace eden
|
|
} // namespace facebook
|
|
#endif
|