#include #include #include #include #include "err.h" #include "util.h" #include "win32.h" /* Strip trailing punctuation. */ static void Strip(wchar_t* s, DWORD* len) { int i; for (i = *len-1; i >= 0; i--) if (s[i] == '\r' || s[i] == '\n' || s[i] == '.') s[i] = 0; *len = i+1; } Err::Err(ErrType t, Buf msg) { const wchar_t fmt[] = L"%s: %s."; switch (t) { case GENERIC: what = std::wstring(Len(msg)+2, 0); Swprintf(what, L"%s.", msg.data); break; case WINDOWS: { wchar_t* err; DWORD lenErr = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, GetLastError(), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (wchar_t*)&err, 0, nullptr); Strip(err, &lenErr); what = std::wstring(Len(fmt)+Len(msg)+lenErr, 0); Swprintf(what, fmt, msg.data, err); HeapFree(GetProcessHeap(), 0, err); break; } case WININET: { DWORD code = GetLastError(); if (code == ERROR_INTERNET_EXTENDED_ERROR) { DWORD lenErr; InternetGetLastResponseInfo(&code, nullptr, &lenErr); std::wstring err(lenErr, 0); if (InternetGetLastResponseInfoW(&code, err.data(), &lenErr)) { Strip(err.data(), &lenErr); what = std::wstring(Len(fmt)+Len(msg)+lenErr, 0); Swprintf(what, fmt, msg.data, err.c_str()); } else what = Err(WINDOWS, msg).what; } else { wchar_t* err; DWORD lenErr = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_FROM_HMODULE |FORMAT_MESSAGE_IGNORE_INSERTS, GetModuleHandle(L"wininet.dll"), code, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (wchar_t*)&err, 0, nullptr); Strip(err, &lenErr); what = std::wstring(Len(fmt)+Len(msg)+lenErr, 0); Swprintf(what, fmt, msg.data, err); HeapFree(GetProcessHeap(), 0, err); } break; } case LIBXML2: { std::wstring err = WideFromNarrow(xmlGetLastError()->message); what = std::wstring(Len(fmt)+Len(msg)+err.size(), 0); Swprintf(what, fmt, msg.data, err.c_str()); break; } } } std::wstring What(std::exception_ptr ex) { try { std::rethrow_exception(ex); } catch (const Err& e) { return e.what; } catch (const std::exception& e) { return WideFromNarrow(e.what()); } catch (...) { return L"Unknown exception"; } } void OnTerminate() { EBMessageBox(What(), L"Fatal Error", MB_ICONERROR); }