From f61e83d936ebab185b09682f922aa58734153761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Fri, 15 Jul 2022 16:40:49 +0200 Subject: Add Win32Error exception class. --- c/common.cpp | 26 +++++++++++++++++++++++++- c/defs.h | 14 ++++++++++++-- c/main.cpp | 52 ++++++++++++++++++++++++---------------------------- 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/c/common.cpp b/c/common.cpp index dd84742..3a99769 100644 --- a/c/common.cpp +++ b/c/common.cpp @@ -29,11 +29,35 @@ TCHAR *TszFromSz(const char *sz, int iCp) return tsz; } +Win32Error::Win32Error(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), + (LPSTR)&m_szMsg, + 0, NULL + ); +} + +Win32Error::~Win32Error() +{ + if (m_szMsg) + HeapFree(GetProcessHeap(), 0, m_szMsg); +} + +const char *Win32Error::what(void) const noexcept +{ + return m_szMsg; +} + Library::Library(const TCHAR *tszLibrary) { m_hModule = LoadLibrary(tszLibrary); if (!m_hModule) - throw std::invalid_argument("Library not found."); + throw Win32Error(GetLastError()); } Library::~Library() diff --git a/c/defs.h b/c/defs.h index 5a6a25a..102dce2 100644 --- a/c/defs.h +++ b/c/defs.h @@ -3,16 +3,26 @@ #include #include +#include #include #include #include /* common.cpp */ TCHAR *TszFromSz(const char *, int); +struct Win32Error : public std::exception +{ + Win32Error(DWORD); + ~Win32Error(void); + virtual const char *what(void) const noexcept override; +private: + DWORD m_dwErr; + char *m_szMsg = NULL; +}; struct Library { Library(const TCHAR *); - ~Library(); + ~Library(void); FARPROC GetProcAddress(const char *); private: HMODULE m_hModule; @@ -70,7 +80,7 @@ int Plx(const char *, const char *); struct Query { Query(module_t ctx, predicate_t p, term_t t0); - ~Query(); + ~Query(void); int Cut(); int Close(); int NextSolution(); diff --git a/c/main.cpp b/c/main.cpp index 90f828d..82c95ba 100644 --- a/c/main.cpp +++ b/c/main.cpp @@ -33,21 +33,18 @@ static void UpdateTheme(void); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) { - LPTSTR tszErr; - /* Exit gracefully on uncaught exception. */ std::set_terminate(OnTerminate); /* Set constant values. */ - if (auto upLib = try_make(TEXT("uxtheme.dll"))) - if (upLib->GetProcAddress("SetWindowTheme")) { + if (auto opLib = try_make(TEXT("uxtheme.dll"))) + if (opLib->GetProcAddress("SetWindowTheme")) g_bThemes = 1; - } g_cxVScroll = GetSystemMetrics(SM_CXVSCROLL); /* Setup fonts. */ - if (auto upLib = try_make(TEXT("User32.dll"))) { - if (upLib->GetProcAddress("SystemParametersInfo" WA)) { + if (auto opLib = try_make(TEXT("User32.dll"))) { + if (opLib->GetProcAddress("SystemParametersInfo" WA)) { NONCLIENTMETRICS m; m.cbSize = sizeof(NONCLIENTMETRICS); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &m, 0); @@ -63,18 +60,17 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, /* Initialize Prolog. */ char *argv[] = { (char *)"EpisodeBrowser", NULL }; - tszErr = TEXT("Could not initialize Prolog."); - if (!PL_initialise(1, argv)) goto f; - tszErr = TEXT("Could not attach databases."); - if (!Pl("track_episodes","attach")) goto f; - if (!Pl("episode_data","attach")) goto f; + if (!PL_initialise(1, argv)) + throw std::runtime_error("Could not initialize Prolog."); + if (!Pl("track_episodes","attach") || !Pl("episode_data","attach")) + throw std::runtime_error("Could not attach databases."); /* Initialize common controls, load menu and register window class. */ INITCOMMONCONTROLSEX icc; icc.dwSize = sizeof(icc); icc.dwICC = ICC_WIN95_CLASSES; - tszErr = TEXT("Could not initialize common controls."); - if (!InitCommonControlsEx(&icc)) goto f; + if (!InitCommonControlsEx(&icc)) + throw std::runtime_error("Could not initialize common controls."); g_hPopupMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_POPUPMENU)); g_hPopupMenu = GetSubMenu(g_hPopupMenu, 0); @@ -90,8 +86,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); wc.lpszClassName = TEXT("Episode Browser"); wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); - tszErr = TEXT("Could not register window class."); - if (!RegisterClassEx(&wc)) goto f; + if (!RegisterClassEx(&wc)) + throw std::runtime_error("Could not register window class."); /* Create window. Note that a CBT hook is used to initialize * important global variables before any messages are sent to @@ -108,8 +104,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, NULL, NULL, hInstance, NULL ); UnhookWindowsHookEx(hHook); - tszErr = TEXT("Could not create main window."); - if (!hWnd) goto f; + if (!hWnd) throw std::runtime_error("Could not create main window."); g_hWndStatus = CreateStatusBar(hWnd, hInstance); ShowWindow(hWnd, nCmdShow); @@ -127,9 +122,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PL_halt(0); return 0; -f: MessageBox(NULL, tszErr, TEXT("Fatal Error"), MB_ICONERROR); - PL_halt(1); - return 1; } void OnTerminate() @@ -139,14 +131,18 @@ void OnTerminate() } catch (term_t &t) { char *sz; TCHAR *tsz; - if (PL_get_chars(t, &sz, CVT_WRITE)) /* TODO: PL_get_wchars */ - tsz = TszFromSz(sz, CP_UTF8); - else - tsz = TEXT("The program was terminated due to an exception."); - MessageBox(NULL, tsz, TEXT("Fatal Error"), MB_ICONERROR); + /* TODO: PL_get_wchars */ + if (PL_get_chars(t, &sz, CVT_WRITE) && (tsz = TszFromSz(sz, CP_UTF8))) { + MessageBox(NULL, tsz, TEXT("Fatal Error"), MB_ICONERROR); + free(tsz); + } else + MessageBoxA(NULL, "The program was terminated due to a Prolog exception.", + "Fatal Error", MB_ICONERROR); + } catch (std::exception &e) { + MessageBoxA(NULL, e.what(), "Fatal Error", MB_ICONERROR); } catch (...) { - MessageBox(NULL, TEXT("The program was terminated due to an exception."), - TEXT("Fatal Error"), MB_ICONERROR); + MessageBoxA(NULL, "The program was terminated due to an exception.", + "Fatal Error", MB_ICONERROR); } std::_Exit(1); } -- cgit v1.2.3