From 9c271a637d36c2a9e4f6f369e725f87f2989b9c8 Mon Sep 17 00:00:00 2001 From: Anders Date: Thu, 14 Apr 2022 19:43:45 +0200 Subject: [PATCH] Improve Windows open dialog handling - Correctly handle OleUninitialize - Don't leak LPITEMIDLIST if SHGetPathFromIDListW fails - Use correct nMaxFile size - Use string alloc helper function - Hide read-only checkbox --- OpenDialog/windows.c | 64 ++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/OpenDialog/windows.c b/OpenDialog/windows.c index e711032..edc654a 100644 --- a/OpenDialog/windows.c +++ b/OpenDialog/windows.c @@ -2,56 +2,62 @@ #include #include "open_dialog.h" +static char *wc_to_utf8_alloc(const wchar_t *wide) +{ + unsigned int cb = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL); + if (cb) { + char *buffer = (char*) malloc(cb); + if (buffer) { + WideCharToMultiByte(CP_UTF8, 0, wide, -1, buffer, cb, NULL, NULL); + return buffer; + } + } + return NULL; +} + char *do_open_rom_dialog(void) { OPENFILENAMEW dialog; - static wchar_t filename[MAX_PATH] = {0}; - + wchar_t filename[MAX_PATH]; + + filename[0] = '\0'; memset(&dialog, 0, sizeof(dialog)); dialog.lStructSize = sizeof(dialog); dialog.lpstrFile = filename; - dialog.nMaxFile = sizeof(filename); + dialog.nMaxFile = MAX_PATH; dialog.lpstrFilter = L"Game Boy ROMs\0*.gb;*.gbc;*.sgb;*.isx\0All files\0*.*\0\0"; dialog.nFilterIndex = 1; dialog.lpstrFileTitle = NULL; dialog.nMaxFileTitle = 0; dialog.lpstrInitialDir = NULL; - dialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - - if (GetOpenFileNameW(&dialog) == TRUE) { - char *ret = malloc(MAX_PATH * 4); - WideCharToMultiByte(CP_UTF8, 0, filename, sizeof(filename), ret, MAX_PATH * 4, NULL, NULL); - return ret; + dialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + + if (GetOpenFileNameW(&dialog) == TRUE) { + return wc_to_utf8_alloc(filename); } - + return NULL; } char *do_open_folder_dialog(void) { - + char *ret = NULL; BROWSEINFOW dialog; - memset(&dialog, 0, sizeof(dialog)); - - dialog.ulFlags = BIF_USENEWUI; - dialog.lpszTitle = L"Select Boot ROMs Folder"; - - OleInitialize(NULL); - - LPITEMIDLIST list = SHBrowseForFolderW(&dialog); - static wchar_t filename[MAX_PATH] = {0}; + memset(&dialog, 0, sizeof(dialog)); + dialog.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS; + dialog.lpszTitle = L"Select Boot ROMs Folder"; + + HRESULT hrOleInit = OleInitialize(NULL); + LPITEMIDLIST list = SHBrowseForFolderW(&dialog); if (list) { - if (!SHGetPathFromIDListW(list, filename)) { - OleUninitialize(); - return NULL; + wchar_t filename[MAX_PATH]; + if (SHGetPathFromIDListW(list, filename)) { + ret = wc_to_utf8_alloc(filename); } - char *ret = malloc(MAX_PATH * 4); - WideCharToMultiByte(CP_UTF8, 0, filename, sizeof(filename), ret, MAX_PATH * 4, NULL, NULL); CoTaskMemFree(list); - OleUninitialize(); - return ret; } - OleUninitialize(); - return NULL; + + if (SUCCEEDED(hrOleInit)) OleUninitialize(); + return ret; }