summaryrefslogtreecommitdiff
path: root/zen/sys_error.h
diff options
context:
space:
mode:
Diffstat (limited to 'zen/sys_error.h')
-rw-r--r--zen/sys_error.h48
1 files changed, 40 insertions, 8 deletions
diff --git a/zen/sys_error.h b/zen/sys_error.h
index 5897b413..4798b959 100644
--- a/zen/sys_error.h
+++ b/zen/sys_error.h
@@ -13,8 +13,8 @@
#include "scope_guard.h"
#ifdef ZEN_WIN
- #include "win.h" //includes "windows.h"
-
+ #include "win.h" //tame WinINet.h include
+ #include <WinINet.h>
#elif defined ZEN_LINUX || defined ZEN_MAC
#include <cstring>
#include <cerrno>
@@ -50,6 +50,22 @@ private:
+#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
+
+
@@ -78,10 +94,26 @@ std::wstring formatSystemErrorRaw(ErrorCode ec) //return empty string on error
ZEN_ON_SCOPE_EXIT(::SetLastError(currentError)); //this function must not change active system error variable!
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, ec, 0, reinterpret_cast<LPWSTR>(&buffer), 0, nullptr) != 0)
+ 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<LPWSTR>(&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<LPWSTR>(&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));
@@ -102,9 +134,9 @@ std::wstring formatSystemErrorRaw(ErrorCode ec) //return empty string on error
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)
+std::wstring formatSystemError(const std::wstring& functionName, ErrorCode ec)
{
- return formatSystemError(functionName, numberTo<std::wstring>(ec), formatSystemErrorRaw(ec));
+ return formatSystemError(functionName, numberTo<std::wstring>(ec), formatSystemErrorRaw(ec));
}
bgstack15