From 41745326d8440340a87b5179139b2915efe3715d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Mon, 18 Jul 2022 03:03:56 +0200 Subject: Add Unicode support to Win32Error. --- c/common.cpp | 44 ++++++++++++++++++++++++++++++++------------ c/common.h | 4 +++- c/listview.cpp | 2 ++ c/main.cpp | 18 +++++++++--------- 4 files changed, 46 insertions(+), 22 deletions(-) (limited to 'c') diff --git a/c/common.cpp b/c/common.cpp index f0b5d34..a5b7316 100644 --- a/c/common.cpp +++ b/c/common.cpp @@ -2,30 +2,50 @@ #include "common.h" -Win32Error::Win32Error(const DWORD dwErr) -{ - m_dwErr = dwErr; - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - m_dwErr, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (char*)&m_szMsg, - 0, NULL - ); -} +Win32Error::Win32Error(const DWORD dwErr) : m_dwErr(dwErr) {} Win32Error::~Win32Error() { if (m_szMsg) HeapFree(GetProcessHeap(), 0, m_szMsg); + if (m_wszMsg) + HeapFree(GetProcessHeap(), 0, m_wszMsg); } const char* Win32Error::what() const noexcept { + if (!m_szMsg) + FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + m_dwErr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char*)&m_szMsg, + 0, NULL + ); return m_szMsg; } +const TCHAR* Win32Error::twhat() const noexcept +{ +#ifdef UNICODE +#define M m_wszMsg +#else +#define M m_szMsg +#endif + if (!M) + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + m_dwErr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (TCHAR*)&M, + 0, NULL + ); + return M; +#undef M +} + Library::Library(const TCHAR* const tszLibrary) { m_hModule = LoadLibrary(tszLibrary); diff --git a/c/common.h b/c/common.h index 515c75c..2b3c331 100644 --- a/c/common.h +++ b/c/common.h @@ -16,9 +16,11 @@ struct Win32Error : public std::exception Win32Error(DWORD dwErr); ~Win32Error(); virtual const char* what() const noexcept override; + virtual const TCHAR* twhat() const noexcept; private: DWORD m_dwErr; - char* const m_szMsg = NULL; + char* m_szMsg = NULL; + wchar_t* m_wszMsg = NULL; }; struct Library diff --git a/c/listview.cpp b/c/listview.cpp index 6c0185d..27dc7ac 100644 --- a/c/listview.cpp +++ b/c/listview.cpp @@ -21,6 +21,8 @@ ListView::ListView(const HWND hWndParent, const HMENU hMenu, const DWORD dwStyle 0, 0, 0, 0, m_hWndParent, hMenu, GetModuleHandle(NULL), this ); + if (!hWnd) throw Win32Error(GetLastError()); + if (SetProp(hWnd, TEXT("this"), (HANDLE)this)) m_prevProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)::WndProc); diff --git a/c/main.cpp b/c/main.cpp index 951770a..4b42317 100644 --- a/c/main.cpp +++ b/c/main.cpp @@ -59,6 +59,10 @@ void OnTerminate() } else MessageBoxA(NULL, "The program was terminated due to a Prolog exception.", "Fatal Error", MB_ICONERROR); + } catch (Win32Error& e) { + std::basic_string tstr = TEXT("The program was terminated due to a Windows error: "); + tstr += e.twhat(); + MessageBox(NULL, tstr.c_str(), TEXT("Fatal Error"), MB_ICONERROR); } catch (std::exception& e) { std::string str = "The program was terminated due to an exception: "; str += e.what(); @@ -86,8 +90,7 @@ int WINAPI WinMain(const HINSTANCE hInstance, const HINSTANCE, char* const, cons INITCOMMONCONTROLSEX icc; icc.dwSize = sizeof(icc); icc.dwICC = ICC_WIN95_CLASSES; - if (!InitCommonControlsEx(&icc)) - throw std::runtime_error("Could not initialize common controls."); + if (!InitCommonControlsEx(&icc)) throw Win32Error(GetLastError()); g_hPopupMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_POPUPMENU)); g_hPopupMenu = GetSubMenu(g_hPopupMenu, 0); @@ -103,14 +106,11 @@ int WINAPI WinMain(const HINSTANCE hInstance, const HINSTANCE, char* const, cons wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); wc.lpszClassName = TEXT("Episode Browser"); wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); - if (!RegisterClassEx(&wc)) - throw std::runtime_error("Could not register window class."); + if (!RegisterClassEx(&wc)) throw Win32Error(GetLastError()); /* Create window. A CBT hook is used to initialize important * global variables before any messages are sent to the new - * window. It is vital that the hook is set up and torn down - * correctly. Note that if the unhook fails, it is useless to - * try to show an error dialog. */ + * window. It is vital that the hook is set up correctly. */ const HHOOK hHook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId()); if (!hHook) throw Win32Error(GetLastError()); const HWND hWnd = CreateWindowEx( @@ -121,9 +121,9 @@ int WINAPI WinMain(const HINSTANCE hInstance, const HINSTANCE, char* const, cons CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, hInstance, NULL ); + if (!hHook) throw Win32Error(GetLastError()); + if (!hWnd) throw Win32Error(GetLastError()); UnhookWindowsHookEx(hHook); - if (!hHook) _Exit(1); - if (!hWnd) throw std::runtime_error("Could not create main window."); g_hWndStatus = CreateStatusBar(hWnd, hInstance); ShowWindow(hWnd, nCmdShow); -- cgit v1.2.3