aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/error.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/error.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/error.cpp b/src/error.cpp
new file mode 100644
index 0000000..ff755b6
--- /dev/null
+++ b/src/error.cpp
@@ -0,0 +1,67 @@
+// Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
+// This file is part of the "winapi-common" project.
+// For details, see https://github.com/egor-tensin/winapi-common.
+// Distributed under the MIT License.
+
+#include <winapi/error.hpp>
+#include <winapi/utf8.hpp>
+
+#include <windows.h>
+
+#include <sstream>
+#include <string>
+#include <system_error>
+
+namespace winapi {
+namespace error {
+namespace {
+
+std::wstring trim_trailing_newline(const std::wstring& s) {
+ const auto last_pos = s.find_last_not_of(L"\r\n");
+ if (std::wstring::npos == last_pos)
+ return {};
+ return s.substr(0, last_pos + 1);
+}
+
+std::string build_what(DWORD code, const char* function) {
+ std::ostringstream what;
+ what << "Function " << function << " failed with error code " << code;
+ return what.str();
+}
+
+std::string format_message(int code) {
+ wchar_t* buf;
+
+ const auto len = ::FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ code,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ reinterpret_cast<wchar_t*>(&buf),
+ 0,
+ NULL);
+
+ if (0 == len) {
+ ::LocalFree(buf);
+ return "Couldn't format the error message";
+ }
+
+ std::wstring msg{buf, len};
+ ::LocalFree(buf);
+ return narrow(trim_trailing_newline(msg));
+}
+
+} // namespace
+
+std::string CategoryWindows::message(int code) const {
+ return format_message(code);
+}
+
+std::system_error windows(DWORD code, const char* function) {
+ static_assert(sizeof(DWORD) == sizeof(int), "Aren't DWORDs the same size as ints?");
+ return std::system_error{
+ static_cast<int>(code), category_windows(), build_what(code, function)};
+}
+
+} // namespace error
+} // namespace winapi