diff options
author | John Ankarström <john@ankarstrom.se> | 2022-07-19 17:26:24 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2022-07-19 17:26:24 +0200 |
commit | ff53b8efce55f5668af61f13b656fdb54dee7755 (patch) | |
tree | 3b5802f9a1ac2b5bc7b32578528659a70c4c1b4c | |
parent | 0635058400597e43d698c87caf3d3ca4f802e0bd (diff) | |
download | EpisodeBrowser-ff53b8efce55f5668af61f13b656fdb54dee7755.tar.gz |
Check Windows API calls for errors more consistently.
Some of the checks are likely redundant, but the Windows API
documentation rarely makes it clear WHICH errors may be returned (and
under which circumstances) rather than simply WHETHER errors may be
returned (under any circumstances, including those that do not apply
in the given case).
-rw-r--r-- | c/common.cpp | 8 | ||||
-rw-r--r-- | c/common.h | 24 | ||||
-rw-r--r-- | c/episodelistview.cpp | 6 | ||||
-rw-r--r-- | c/listview.cpp | 5 | ||||
-rw-r--r-- | c/main.cpp | 58 |
5 files changed, 60 insertions, 41 deletions
diff --git a/c/common.cpp b/c/common.cpp index ba6593b..b85be49 100644 --- a/c/common.cpp +++ b/c/common.cpp @@ -61,7 +61,7 @@ Library::~Library() } /* Move message box to center of main window. */ -static LRESULT CALLBACK CBTProc(const int nCode, const WPARAM wParam, const LPARAM lParam) +static LRESULT CALLBACK CBTProc(const int nCode, const WPARAM wParam, const LPARAM lParam) noexcept { extern HWND g_hWnd; if (!g_hWnd || nCode < 0 || nCode != HCBT_ACTIVATE) @@ -87,10 +87,8 @@ static LRESULT CALLBACK CBTProc(const int nCode, const WPARAM wParam, const LPAR int EBMessageBox(const TCHAR* const tszText, const TCHAR* const tszCaption, const unsigned uType) { extern HWND g_hWnd; - HHOOK hHook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId()); - if (!hHook) return 0; + HHOOK hHook = throw_nil<SetWindowsHookEx>(WH_CBT, CBTProc, (HINSTANCE)NULL, GetCurrentThreadId()); int r = MessageBox(g_hWnd, tszText, tszCaption, uType); - UnhookWindowsHookEx(hHook); - if (!hHook) throw Win32Error(GetLastError()); + throw_nil<UnhookWindowsHookEx>(hHook); return r; } @@ -44,7 +44,7 @@ T* Library::GetProcAddress(const char* const szProc) * return nothing. The returned value must be checked before being * used, as dereferencing is undefined if the value is empty. */ template <class C, typename ...T> -std::optional<C> try_make(T ...args) +std::optional<C> maybe_make(T ...args) { try { return C(args...); @@ -53,6 +53,28 @@ std::optional<C> try_make(T ...args) } } +/* Call Windows API function and throw error if NULL is returned. */ +template <auto f, typename ...T> +inline auto throw_nil(T ...args) +{ + auto r = f(args...); + if (!r) throw Win32Error(GetLastError()); + return r; +} + +/* Call Windows API function and show a warning if NULL is returned. */ +template <auto f, typename ...T> +inline auto warn_nil(T ...args) +{ + decltype(f(args...)) r; + try { + r = throw_nil<f>(args...); + } catch (Win32Error& e) { + EBMessageBox(e.twhat(), TEXT("System Error"), MB_ICONWARNING); + } + return r; +} + /* Return integer scaled for current DPI. */ inline int Dpi(const int i) { diff --git a/c/episodelistview.cpp b/c/episodelistview.cpp index c08e6f8..e70cc06 100644 --- a/c/episodelistview.cpp +++ b/c/episodelistview.cpp @@ -90,7 +90,7 @@ LRESULT EpisodeListView::HandleNotify(const LPARAM lParam) { extern HFONT g_hfBold; if (!Pl("track_episodes","watched",pLvCd->nmcd.lItemlParam)) { - SelectObject(pLvCd->nmcd.hdc, g_hfBold); + throw_nil<SelectObject>(pLvCd->nmcd.hdc, g_hfBold); return CDRF_NEWFONT; } break; @@ -125,9 +125,9 @@ LRESULT EpisodeListView::HandleNotify(const LPARAM lParam) { extern HMENU g_hPopupMenu; const DWORD dwPos = GetMessagePos(); - TrackPopupMenu(g_hPopupMenu, TPM_RIGHTBUTTON, + throw_nil<TrackPopupMenu>(g_hPopupMenu, TPM_RIGHTBUTTON, LOWORD(dwPos), HIWORD(dwPos), 0, - m_hWndParent, NULL); + m_hWndParent, (const RECT*)NULL); break; } } diff --git a/c/listview.cpp b/c/listview.cpp index 8f5da65..fa99793 100644 --- a/c/listview.cpp +++ b/c/listview.cpp @@ -13,16 +13,15 @@ ListView::ListView(const HWND hWndParent, const HMENU hMenu, const DWORD dwStyle { m_hWndParent = hWndParent; m_bHeader = !(dwStyle & LVS_NOCOLUMNHEADER); - hWnd = CreateWindowEx( + hWnd = throw_nil<CreateWindowEx>( WS_EX_CLIENTEDGE, WC_LISTVIEW, TEXT(""), dwStyle|WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP|LVS_REPORT|LVS_SHOWSELALWAYS, 0, 0, 0, 0, m_hWndParent, hMenu, GetModuleHandle(NULL), this); - if (!hWnd) throw Win32Error(GetLastError()); - if (SetProp(hWnd, TEXT("this"), (HANDLE)this)) + if (throw_nil<SetProp>(hWnd, TEXT("this"), (HANDLE)this)) m_prevProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)::WndProc); @@ -45,7 +45,7 @@ static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); static void UpdateTheme(); -void OnTerminate() +void OnTerminate() noexcept { try { std::rethrow_exception(std::current_exception()); @@ -89,10 +89,10 @@ 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 Win32Error(GetLastError()); + throw_nil<InitCommonControlsEx>(&icc); - g_hPopupMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_POPUPMENU)); - g_hPopupMenu = GetSubMenu(g_hPopupMenu, 0); + g_hPopupMenu = throw_nil<LoadMenu>((HINSTANCE)NULL, MAKEINTRESOURCE(IDR_POPUPMENU)); + g_hPopupMenu = throw_nil<GetSubMenu>(g_hPopupMenu, 0); WNDCLASSEX wc; memset(&wc, 0, sizeof(WNDCLASSEX)); @@ -105,31 +105,29 @@ 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 Win32Error(GetLastError()); + throw_nil<RegisterClassEx>(&wc); /* 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 correctly. */ - const HHOOK hHook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId()); - if (!hHook) throw Win32Error(GetLastError()); - const HWND hWnd = CreateWindowEx( + const HHOOK hHook = throw_nil<SetWindowsHookEx>(WH_CBT, CBTProc, + (HINSTANCE)NULL, GetCurrentThreadId()); + const HWND hWnd = throw_nil<CreateWindowEx>( 0, TEXT("Episode Browser"), TEXT("Episode Browser"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, - NULL, NULL, hInstance, NULL); - if (!hHook) throw Win32Error(GetLastError()); - if (!hWnd) throw Win32Error(GetLastError()); - UnhookWindowsHookEx(hHook); + (HWND)NULL, (HMENU)NULL, hInstance, (void*)NULL); + throw_nil<UnhookWindowsHookEx>(hHook); - g_hWndStatus = CreateWindowEx( + g_hWndStatus = throw_nil<CreateWindowEx>( 0, STATUSCLASSNAME, (const TCHAR*)NULL, WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP, 0, 0, 0, 0, - hWnd, (HMENU)ID_STATUS, hInstance, NULL); + hWnd, (HMENU)ID_STATUS, hInstance, (void*)NULL); ShowWindow(hWnd, nCmdShow); @@ -161,27 +159,29 @@ static LRESULT CALLBACK CBTProc(const int nCode, const WPARAM wParam, const LPAR g_hWnd = (HWND)wParam; /* Look up constants. */ - if (auto opLib = try_make<Library>(TEXT("User32.dll"))) + if (auto opLib = maybe_make<Library>(TEXT("User32.dll"))) if (auto GetDpiForWindow = opLib->GetProcAddress<UINT(HWND)>("GetDpiForWindow")) g_iDPI = GetDpiForWindow(g_hWnd); - if (auto opLib = try_make<Library>(TEXT("uxtheme.dll"))) + if (auto opLib = maybe_make<Library>(TEXT("uxtheme.dll"))) if (opLib->GetProcAddress<void>("SetWindowTheme")) g_bThemes = 1; - LOGFONT lf; - if (auto opLib = try_make<Library>(TEXT("User32.dll"))) { + if (auto opLib = maybe_make<Library>(TEXT("User32.dll"))) { if (opLib->GetProcAddress<void>("SystemParametersInfo" WA)) { NONCLIENTMETRICS m; m.cbSize = sizeof(NONCLIENTMETRICS); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &m, 0); - g_hfNormal = CreateFontIndirect(&m.lfMessageFont); + throw_nil<SystemParametersInfo>(SPI_GETNONCLIENTMETRICS, + sizeof(NONCLIENTMETRICS), &m, 0); + g_hfNormal = throw_nil<CreateFontIndirect>(&m.lfMessageFont); } } else - g_hfNormal = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)); - GetObject(g_hfNormal, sizeof(LOGFONT), &lf); + g_hfNormal = static_cast<HFONT>(throw_nil<GetStockObject>(DEFAULT_GUI_FONT)); + + LOGFONT lf; + throw_nil<GetObject>(g_hfNormal, sizeof(LOGFONT), &lf); lf.lfWeight = FW_BOLD; - g_hfBold = CreateFontIndirect(&lf); + g_hfBold = throw_nil<CreateFontIndirect>(&lf); /* Create child windows. */ g_pDlv = new DataListView(g_hWnd); @@ -237,7 +237,7 @@ LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, { const RECT* const lpr = (RECT*)lParam; g_iDPI = HIWORD(wParam); - SetWindowPos(hWnd, NULL, + warn_nil<SetWindowPos>(hWnd, (HWND)NULL, lpr->left, lpr->top, lpr->right-lpr->left, lpr->bottom-lpr->top, @@ -280,7 +280,7 @@ LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, TEXT(""))); } else { i = 0; - KillTimer(hWnd, IDT_TIMER); + warn_nil<KillTimer>(hWnd, IDT_TIMER); g_pElv->Update(); } break; @@ -302,8 +302,8 @@ LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, case IDM_FILE_FETCH_SCREENWRITERS: if (g_bThread) break; Pl("episode_data","thread_create","update_screenwriters",&g_aThread); - t: KillTimer(hWnd, IDT_TIMER); - SetTimer(hWnd, IDT_TIMER, 500, NULL); + t: warn_nil<KillTimer>(hWnd, IDT_TIMER); + if (!SetTimer(hWnd, IDT_TIMER, 500, (TIMERPROC)NULL)) break; SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)TEXT(".")); g_bThread = 1; break; @@ -514,14 +514,14 @@ void UpdateLayout() /* Resize data list view. */ cyDlv = rc.bottom-yStatus-g_pDlv->Height(); - MoveWindow(g_pDlv->hWnd, 0, cyDlv, rc.right, rc.bottom-yStatus-cyDlv, TRUE); + throw_nil<MoveWindow>(g_pDlv->hWnd, 0, cyDlv, rc.right, rc.bottom-yStatus-cyDlv, TRUE); ListView_SetColumnWidth(g_pDlv->hWnd, DLVSIKEY, LVSCW_AUTOSIZE); cxColumn = ListView_GetColumnWidth(g_pDlv->hWnd, 0)+4; ListView_SetColumnWidth(g_pDlv->hWnd, DLVSIKEY, cxColumn); ListView_SetColumnWidth(g_pDlv->hWnd, DLVSIVALUE, rc.right-cxColumn-cxVScroll-4); /* Resize episode list view. */ - MoveWindow(g_pElv->hWnd, 0, 0, rc.right, cyDlv+1, TRUE); + throw_nil<MoveWindow>(g_pElv->hWnd, 0, 0, rc.right, cyDlv+1, TRUE); ListView_SetColumnWidth(g_pElv->hWnd, ELVSIEPISODE, LVSCW_AUTOSIZE); cxColumn = ListView_GetColumnWidth(g_pElv->hWnd, ELVSIEPISODE)+4; ListView_SetColumnWidth(g_pElv->hWnd, ELVSIEPISODE, cxColumn); |