From 467af44edb8449809f8863faf87a2c1385ec860d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 28 Jan 2023 12:21:34 +0530 Subject: [PATCH] Niceties for getting the last error on windows --- src/calibre/utils/windows/common.h | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/calibre/utils/windows/common.h b/src/calibre/utils/windows/common.h index e37feafaa6..98fae364b5 100644 --- a/src/calibre/utils/windows/common.h +++ b/src/calibre/utils/windows/common.h @@ -5,12 +5,15 @@ */ #pragma once +#include #define PY_SSIZE_T_CLEAN #define UNICODE #define _UNICODE #include #include +#include #include +#include #include "../cpp_binding.h" static inline PyObject* @@ -24,6 +27,46 @@ set_error_from_hresult(PyObject *exc_type, const char *file, const int line, con } #define error_from_hresult(hr, ...) set_error_from_hresult(PyExc_OSError, __FILE__, __LINE__, hr, __VA_ARGS__) +// trim from end (in place) +template +static inline void +rtrim(std::basic_string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](T ch) { + switch (ch) { case ' ': case '\t': case '\n': case '\r': case '\v': case '\f': return false; } + return true; + }).base(), s.end()); +} + +static inline std::wstring +get_last_error(std::wstring const & prefix = L"") { + auto ec = GetLastError(); + LPWSTR buf; + DWORD n; + + if ((n = FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + ec, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&buf), + 0, NULL)) == 0) { + auto error_code{ ::GetLastError() }; + throw std::system_error(error_code, std::system_category(), "Failed to retrieve error message string."); + } + auto deleter = [](void* p) { ::LocalFree(p); }; + std::unique_ptr ptrBuffer(buf, deleter); + auto msg = std::wstring(buf, n); + std::wstring ans = prefix; + if (prefix.size() > 0) { + ans += L": "; + } + rtrim(msg); + ans += L"Code: " + std::to_wstring(ec) + L" Message: " + msg; + return ans; +} + class scoped_com_initializer { // {{{ public: scoped_com_initializer() : m_succeded(false), hr(0) { @@ -67,6 +110,7 @@ typedef generic_raii mapping_raii; static inline HANDLE invalid_handle_value_getter(void) { return INVALID_HANDLE_VALUE; } static inline void close_handle(HANDLE x) { CloseHandle(x); } typedef generic_raii handle_raii; +typedef generic_raii handle_raii_null; struct prop_variant : PROPVARIANT { prop_variant(VARTYPE vt=VT_EMPTY) noexcept : PROPVARIANT{} { PropVariantInit(this); this->vt = vt; }