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
#include <shlobj.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)
{
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;
+ dialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
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;
+ return wc_to_utf8_alloc(filename);
}
return NULL;
@@ -29,29 +41,23 @@ char *do_open_rom_dialog(void)
char *do_open_folder_dialog(void)
{
-
+ char *ret = NULL;
BROWSEINFOW dialog;
- memset(&dialog, 0, sizeof(dialog));
- dialog.ulFlags = BIF_USENEWUI;
+ memset(&dialog, 0, sizeof(dialog));
+ dialog.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
dialog.lpszTitle = L"Select Boot ROMs Folder";
- OleInitialize(NULL);
-
+ HRESULT hrOleInit = OleInitialize(NULL);
LPITEMIDLIST list = SHBrowseForFolderW(&dialog);
- static wchar_t filename[MAX_PATH] = {0};
-
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;
}
