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
This commit is contained in:
Anders 2022-04-14 19:43:45 +02:00 committed by GitHub
parent 76b881c2e1
commit 9c271a637d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2,56 +2,62 @@
#include <shlobj.h> #include <shlobj.h>
#include "open_dialog.h" #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) char *do_open_rom_dialog(void)
{ {
OPENFILENAMEW dialog; OPENFILENAMEW dialog;
static wchar_t filename[MAX_PATH] = {0}; wchar_t filename[MAX_PATH];
filename[0] = '\0';
memset(&dialog, 0, sizeof(dialog)); memset(&dialog, 0, sizeof(dialog));
dialog.lStructSize = sizeof(dialog); dialog.lStructSize = sizeof(dialog);
dialog.lpstrFile = filename; 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.lpstrFilter = L"Game Boy ROMs\0*.gb;*.gbc;*.sgb;*.isx\0All files\0*.*\0\0";
dialog.nFilterIndex = 1; dialog.nFilterIndex = 1;
dialog.lpstrFileTitle = NULL; dialog.lpstrFileTitle = NULL;
dialog.nMaxFileTitle = 0; dialog.nMaxFileTitle = 0;
dialog.lpstrInitialDir = NULL; dialog.lpstrInitialDir = NULL;
dialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; dialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
if (GetOpenFileNameW(&dialog) == TRUE) { if (GetOpenFileNameW(&dialog) == TRUE) {
char *ret = malloc(MAX_PATH * 4); return wc_to_utf8_alloc(filename);
WideCharToMultiByte(CP_UTF8, 0, filename, sizeof(filename), ret, MAX_PATH * 4, NULL, NULL);
return ret;
} }
return NULL; return NULL;
} }
char *do_open_folder_dialog(void) char *do_open_folder_dialog(void)
{ {
char *ret = NULL;
BROWSEINFOW dialog; 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 (list) {
if (!SHGetPathFromIDListW(list, filename)) { wchar_t filename[MAX_PATH];
OleUninitialize(); if (SHGetPathFromIDListW(list, filename)) {
return NULL; 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); CoTaskMemFree(list);
OleUninitialize();
return ret;
} }
OleUninitialize();
return NULL; if (SUCCEEDED(hrOleInit)) OleUninitialize();
return ret;
} }