From a1c91f4695e208d5a8f80dc37b1818169b7829ff Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:24:59 +0200 Subject: 5.17 --- zen/com_error.h | 85 ++++++++++++++++++++++++--------------------------------- 1 file changed, 36 insertions(+), 49 deletions(-) (limited to 'zen/com_error.h') diff --git a/zen/com_error.h b/zen/com_error.h index 0e0448a7..5eb7611d 100644 --- a/zen/com_error.h +++ b/zen/com_error.h @@ -4,31 +4,19 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef COM_ERROR_HEADER -#define COM_ERROR_HEADER +#ifndef COM_ERROR_HEADER_88425703425254 +#define COM_ERROR_HEADER_88425703425254 -#include #include -#include "win.h" //includes "windows.h" +#include "sys_error.h" namespace zen { -std::wstring generateErrorMsg(const std::wstring& input, HRESULT hr); -std::wstring formatWin32Msg(DWORD dwMessageId); //return empty string on error - -class ComError -{ -public: - explicit ComError(const std::wstring& msg, HRESULT hr = S_OK) : msg_(hr == S_OK ? msg : generateErrorMsg(msg, hr)) {} - const std::wstring& toString() const { return msg_; } - -private: - std::wstring msg_; -}; +std::wstring formatComError(const std::wstring& msg, HRESULT hr); //Convenience Macros checking for COM errors: -#define ZEN_COM_CHECK(func) ZEN_COM_CHECK_IMPL(func, #func) //throw ComError +#define ZEN_COM_CHECK(func) ZEN_COM_CHECK_IMPL(func, #func) //throw SysError /* Example: ZEN_COM_CHECK(backupComp->InitializeForBackup()); @@ -36,17 +24,17 @@ Equivalent to: { HRESULT hrInternal = backupComp->InitializeForBackup(); if (FAILED(hrInternal)) - throw ComError(L"Error calling \"backupComp->InitializeForBackup()\".", hrInternal); + throw SysError(formatComError(L"Error calling \"backupComp->InitializeForBackup()\".", hrInternal)); } */ -#define ZEN_COM_ASSERT(obj) ZEN_COM_ASSERT_IMPL(obj, #obj) //throw ComError +#define ZEN_COM_ASSERT(obj) ZEN_COM_ASSERT_IMPL(obj, #obj) //throw SysError /* Example: ZEN_COM_ASSERT(obj); Equivalent to: if (!obj) - throw ComError(L"Assertion failed: \"obj\".", E_FAIL); + throw SysError(formatComError(L"Assertion failed: \"obj\".", E_FAIL)); */ @@ -54,32 +42,35 @@ Equivalent to: - - - - - - - //################# implementation ##################### -std::wstring formatWin32Msg(DWORD dwMessageId) //return empty string on error +namespace impl +{ +inline +std::wstring formatWin32Message(DWORD dwMessageId) //return empty string on error { - std::wstring output; LPWSTR buffer = nullptr; if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_IGNORE_INSERTS | //important: without this flag ::FormatMessage() will fail if message contains placeholders FORMAT_MESSAGE_ALLOCATE_BUFFER, nullptr, dwMessageId, 0, reinterpret_cast(&buffer), 0, nullptr) != 0) - { if (buffer) //just to be sure { - output = buffer; - ::LocalFree(buffer); + ZEN_ON_SCOPE_EXIT(::LocalFree(buffer)); + return buffer; } - } - return output; + return std::wstring(); +} + + +inline +std::wstring numberToHexString(long number) +{ + wchar_t buffer[100] = {}; + const int charsWritten = ::swprintf(buffer, 100, L"0x%08x", static_cast(number)); + return charsWritten > 0 ? std::wstring(buffer, charsWritten) : std::wstring(); } + namespace { std::wstring formatFacility(HRESULT hr) @@ -199,28 +190,24 @@ std::wstring formatFacility(HRESULT hr) } } } - -inline -std::wstring numberToHexString(long number) -{ - wchar_t result[100]; - ::swprintf(result, 100, L"0x%08x", static_cast(number)); - return std::wstring(result); } +std::wstring formatComError(const std::wstring& msg, long long hr); //not implemented! intentional overload ambiguity to catch usage errors with HRESULT! + + inline -std::wstring generateErrorMsg(const std::wstring& input, HRESULT hr) +std::wstring formatComError(const std::wstring& msg, HRESULT hr) { - std::wstring output(input); + std::wstring output(msg); output += L"\n"; //don't use _com_error(hr).ErrorMessage(): internally this is nothing more than a call to ::FormatMessage() - std::wstring win32Msg = formatWin32Msg(hr); + std::wstring win32Msg = impl::formatWin32Message(hr); if (!win32Msg.empty()) //empty string on error - output += win32Msg + L"\n" + L"HRESULT: " + numberToHexString(hr); + output += win32Msg + L"\n" + L"HRESULT: " + impl::numberToHexString(hr); else - output += L"HRESULT: " + numberToHexString(hr) + L", " + L"Facility: " + formatFacility(hr); + output += L"HRESULT: " + impl::numberToHexString(hr) + L", " + L"Facility: " + impl::formatFacility(hr); //don't bluntly interpret as Win32 error code HRESULT_CODE(hr), too often misleading! //http://blogs.msdn.com/b/oldnewthing/archive/2006/11/03/942851.aspx @@ -232,9 +219,9 @@ std::wstring generateErrorMsg(const std::wstring& input, HRESULT hr) { \ HRESULT hrInternal = func; \ if (FAILED(hrInternal)) \ - throw zen::ComError(std::wstring(L"Error calling \"") + L ## txt + L"\".", hrInternal); \ + throw zen::SysError(formatComError(std::wstring(L"Error calling \"") + L ## txt + L"\".", hrInternal)); \ } -#define ZEN_COM_ASSERT_IMPL(obj, txt) if (!(obj)) throw zen::ComError(std::wstring(L"Assertion failed: \"") + L ## txt + L"\".", E_FAIL); +#define ZEN_COM_ASSERT_IMPL(obj, txt) if (!(obj)) throw zen::SysError(formatComError(std::wstring(L"Assertion failed: \"") + L ## txt + L"\".", E_FAIL)); } -#endif //COM_ERROR_HEADER +#endif //COM_ERROR_HEADER_88425703425254 -- cgit