From 9d071d2a2cec9a7662a02669488569a017f0ea35 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Mon, 13 Feb 2017 21:25:04 -0700 Subject: 8.9 --- zen/sys_error.h | 266 ++++++++++++++++++++++---------------------------------- 1 file changed, 105 insertions(+), 161 deletions(-) mode change 100644 => 100755 zen/sys_error.h (limited to 'zen/sys_error.h') diff --git a/zen/sys_error.h b/zen/sys_error.h old mode 100644 new mode 100755 index 4798b959..a19409ab --- a/zen/sys_error.h +++ b/zen/sys_error.h @@ -1,161 +1,105 @@ -// ***************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 * -// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved * -// ***************************************************************************** - -#ifndef SYS_ERROR_H_3284791347018951324534 -#define SYS_ERROR_H_3284791347018951324534 - -#include -#include "utf.h" -#include "i18n.h" -#include "scope_guard.h" - -#ifdef ZEN_WIN - #include "win.h" //tame WinINet.h include - #include -#elif defined ZEN_LINUX || defined ZEN_MAC - #include - #include -#endif - - -namespace zen -{ -//evaluate GetLastError()/errno and assemble specific error message -#ifdef ZEN_WIN - using ErrorCode = DWORD; -#elif defined ZEN_LINUX || defined ZEN_MAC - using ErrorCode = int; -#endif - -ErrorCode getLastError(); - -std::wstring formatSystemError(const std::wstring& functionName, ErrorCode ec); -std::wstring formatSystemError(const std::wstring& functionName, const std::wstring& errorCode, const std::wstring& errorMsg); - -//A low-level exception class giving (non-translated) detail information only - same conceptional level like "GetLastError()"! -class SysError -{ -public: - explicit SysError(const std::wstring& msg) : msg_(msg) {} - const std::wstring& toString() const { return msg_; } - -private: - std::wstring msg_; -}; - -#define DEFINE_NEW_SYS_ERROR(X) struct X : public SysError { X(const std::wstring& msg) : SysError(msg) {} }; - - - -#ifdef _MSC_VER -#define THROW_LAST_SYS_ERROR(functionName) \ - do \ - { \ - const ErrorCode ecInternal = getLastError(); \ - throw SysError(formatSystemError(functionName, ecInternal)); \ - \ - __pragma(warning(suppress: 4127)) /*"conditional expression is constant"*/ \ - } while (false) - -#else //same thing witout "__pragma": -#define THROW_LAST_SYS_ERROR(functionName) \ - do { const ErrorCode ecInternal = getLastError(); throw SysError(formatSystemError(functionName, ecInternal)); } while (false) -#endif - - - - - - -//######################## implementation ######################## -inline -ErrorCode getLastError() -{ -#ifdef ZEN_WIN - return ::GetLastError(); -#elif defined ZEN_LINUX || defined ZEN_MAC - return errno; //don't use "::", errno is a macro! -#endif -} - - -std::wstring formatSystemErrorRaw(long long) = delete; //intentional overload ambiguity to catch usage errors - -inline -std::wstring formatSystemErrorRaw(ErrorCode ec) //return empty string on error -{ - const ErrorCode currentError = getLastError(); //not necessarily == lastError - - std::wstring errorMsg; -#ifdef ZEN_WIN - ZEN_ON_SCOPE_EXIT(::SetLastError(currentError)); //this function must not change active system error variable! - - LPWSTR buffer = nullptr; - const DWORD rv = [&] - { - if (INTERNET_ERROR_BASE <= ec && ec <= INTERNET_ERROR_LAST) - return ::FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | - FORMAT_MESSAGE_MAX_WIDTH_MASK | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_ALLOCATE_BUFFER, ::GetModuleHandle(L"WinINet.dll"), ec, 0, reinterpret_cast(&buffer), 0, nullptr); - else - return ::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, //_In_ DWORD dwFlags, - nullptr, //_In_opt_ LPCVOID lpSource, - ec, //_In_ DWORD dwMessageId, - 0, //_In_ DWORD dwLanguageId, - reinterpret_cast(&buffer), //_Out_ LPTSTR lpBuffer, - 0, //_In_ DWORD nSize, - nullptr); //_In_opt_ va_list *Arguments - }(); - if (rv != 0) - if (buffer) //"don't trust nobody" - { - ZEN_ON_SCOPE_EXIT(::LocalFree(buffer)); - errorMsg = buffer; - } - -#elif defined ZEN_LINUX || defined ZEN_MAC - ZEN_ON_SCOPE_EXIT(errno = currentError); - - errorMsg = utfCvrtTo(::strerror(ec)); -#endif - trim(errorMsg); //Windows messages seem to end with a blank... - - return errorMsg; -} - - -std::wstring formatSystemError(const std::wstring& functionName, long long lastError) = delete; //intentional overload ambiguity to catch usage errors with HRESULT! - -inline -std::wstring formatSystemError(const std::wstring& functionName, ErrorCode ec) -{ - return formatSystemError(functionName, numberTo(ec), formatSystemErrorRaw(ec)); -} - - -inline -std::wstring formatSystemError(const std::wstring& functionName, const std::wstring& errorCode, const std::wstring& errorMsg) -{ - std::wstring output = replaceCpy(_("Error Code %x:"), L"%x", errorCode); - - if (!errorMsg.empty()) - { - output += L" "; - output += errorMsg; - } - - output += L" (" + functionName + L")"; - - return output; -} - -} - -#endif //SYS_ERROR_H_3284791347018951324534 +// ***************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 * +// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved * +// ***************************************************************************** + +#ifndef SYS_ERROR_H_3284791347018951324534 +#define SYS_ERROR_H_3284791347018951324534 + +#include +#include "utf.h" +#include "i18n.h" +#include "scope_guard.h" + + #include + #include + + +namespace zen +{ +//evaluate GetLastError()/errno and assemble specific error message + using ErrorCode = int; + +ErrorCode getLastError(); + +std::wstring formatSystemError(const std::wstring& functionName, ErrorCode ec); +std::wstring formatSystemError(const std::wstring& functionName, const std::wstring& errorCode, const std::wstring& errorMsg); + +//A low-level exception class giving (non-translated) detail information only - same conceptional level like "GetLastError()"! +class SysError +{ +public: + explicit SysError(const std::wstring& msg) : msg_(msg) {} + const std::wstring& toString() const { return msg_; } + +private: + std::wstring msg_; +}; + +#define DEFINE_NEW_SYS_ERROR(X) struct X : public SysError { X(const std::wstring& msg) : SysError(msg) {} }; + + + +#define THROW_LAST_SYS_ERROR(functionName) \ + do { const ErrorCode ecInternal = getLastError(); throw SysError(formatSystemError(functionName, ecInternal)); } while (false) + + + + + + +//######################## implementation ######################## +inline +ErrorCode getLastError() +{ + return errno; //don't use "::", errno is a macro! +} + + +std::wstring formatSystemErrorRaw(long long) = delete; //intentional overload ambiguity to catch usage errors + +inline +std::wstring formatSystemErrorRaw(ErrorCode ec) //return empty string on error +{ + const ErrorCode currentError = getLastError(); //not necessarily == lastError + + std::wstring errorMsg; + ZEN_ON_SCOPE_EXIT(errno = currentError); + + errorMsg = utfCvrtTo(::strerror(ec)); + trim(errorMsg); //Windows messages seem to end with a blank... + + return errorMsg; +} + + +std::wstring formatSystemError(const std::wstring& functionName, long long lastError) = delete; //intentional overload ambiguity to catch usage errors with HRESULT! + +inline +std::wstring formatSystemError(const std::wstring& functionName, ErrorCode ec) +{ + return formatSystemError(functionName, replaceCpy(_("Error Code %x"), L"%x", numberTo(ec)), formatSystemErrorRaw(ec)); +} + + +inline +std::wstring formatSystemError(const std::wstring& functionName, const std::wstring& errorCode, const std::wstring& errorMsg) +{ + std::wstring output = errorCode + L":"; + + const std::wstring errorMsgFmt = trimCpy(errorMsg); + if (!errorMsgFmt.empty()) + { + output += L" "; + output += errorMsgFmt; + } + + output += L" [" + functionName + L"]"; + + return output; +} + +} + +#endif //SYS_ERROR_H_3284791347018951324534 -- cgit