mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-28 05:34:15 -04:00
use IFileDialog when running on Vista or later
* When compiled with MinGW, this was always disabled due to forcing XP as the lowest common denominator and using #ifdefs * This should also help with OFN_NOCHANGEDIR seemingly being ignored * Sadly, this change also adds ~20KB to our *compressed* size... :(
This commit is contained in:
parent
cbf1a60365
commit
2c90a06668
5 changed files with 454 additions and 156 deletions
292
src/stdlg.c
292
src/stdlg.c
|
@ -44,9 +44,7 @@
|
|||
#include "settings.h"
|
||||
#include "license.h"
|
||||
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
PF_TYPE_DECL(WINAPI, HRESULT, SHCreateItemFromParsingName, (PCWSTR, IBindCtx*, REFIID, void **));
|
||||
#endif
|
||||
PF_TYPE_DECL(WINAPI, LPITEMIDLIST, SHSimpleIDListFromPath, (PCWSTR pszPath));
|
||||
#define INIT_VISTA_SHELL32 PF_INIT(SHCreateItemFromParsingName, Shell32)
|
||||
#define INIT_XP_SHELL32 PF_INIT(SHSimpleIDListFromPath, Shell32)
|
||||
|
@ -135,8 +133,6 @@ void BrowseForFolder(void) {
|
|||
|
||||
BROWSEINFOW bi;
|
||||
LPITEMIDLIST pidl;
|
||||
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
WCHAR *wpath;
|
||||
size_t i;
|
||||
HRESULT hr;
|
||||
|
@ -147,79 +143,79 @@ void BrowseForFolder(void) {
|
|||
char* tmp_path = NULL;
|
||||
|
||||
dialog_showing++;
|
||||
// Even if we have Vista support with the compiler,
|
||||
// it does not mean we have the Vista API available
|
||||
INIT_VISTA_SHELL32;
|
||||
if (IS_VISTA_SHELL32_AVAILABLE) {
|
||||
hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC,
|
||||
&IID_IFileOpenDialog, (LPVOID)&pfod);
|
||||
if (FAILED(hr)) {
|
||||
uprintf("CoCreateInstance for FileOpenDialog failed: error %X\n", hr);
|
||||
pfod = NULL; // Just in case
|
||||
goto fallback;
|
||||
}
|
||||
hr = pfod->lpVtbl->SetOptions(pfod, FOS_PICKFOLDERS);
|
||||
if (FAILED(hr)) {
|
||||
uprintf("Failed to set folder option for FileOpenDialog: error %X\n", hr);
|
||||
goto fallback;
|
||||
}
|
||||
// Set the initial folder (if the path is invalid, will simply use last)
|
||||
wpath = utf8_to_wchar(szFolderPath);
|
||||
// The new IFileOpenDialog makes us split the path
|
||||
fname = NULL;
|
||||
if ((wpath != NULL) && (wcslen(wpath) >= 1)) {
|
||||
for (i=wcslen(wpath)-1; i!=0; i--) {
|
||||
if (wpath[i] == L'\\') {
|
||||
wpath[i] = 0;
|
||||
fname = &wpath[i+1];
|
||||
break;
|
||||
}
|
||||
#ifndef DDKBUILD // WDK being uncooperative yet again...
|
||||
if (nWindowsVersion >= WINDOWS_VISTA) {
|
||||
INIT_VISTA_SHELL32;
|
||||
if (IS_VISTA_SHELL32_AVAILABLE) {
|
||||
hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC,
|
||||
&IID_IFileOpenDialog, (LPVOID)&pfod);
|
||||
if (FAILED(hr)) {
|
||||
uprintf("CoCreateInstance for FileOpenDialog failed: error %X\n", hr);
|
||||
pfod = NULL; // Just in case
|
||||
goto fallback;
|
||||
}
|
||||
}
|
||||
|
||||
hr = (*pfSHCreateItemFromParsingName)(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (wpath != NULL) {
|
||||
hr = pfod->lpVtbl->SetFolder(pfod, si_path);
|
||||
}
|
||||
if (fname != NULL) {
|
||||
hr = pfod->lpVtbl->SetFileName(pfod, fname);
|
||||
}
|
||||
}
|
||||
safe_free(wpath);
|
||||
|
||||
hr = pfod->lpVtbl->Show(pfod, hMainDialog);
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = pfod->lpVtbl->GetResult(pfod, &psi);
|
||||
if (SUCCEEDED(hr)) {
|
||||
psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &wpath);
|
||||
tmp_path = wchar_to_utf8(wpath);
|
||||
CoTaskMemFree(wpath);
|
||||
if (tmp_path == NULL) {
|
||||
uprintf("Could not convert path\n");
|
||||
} else {
|
||||
safe_strcpy(szFolderPath, MAX_PATH, tmp_path);
|
||||
safe_free(tmp_path);
|
||||
}
|
||||
} else {
|
||||
hr = pfod->lpVtbl->SetOptions(pfod, FOS_PICKFOLDERS);
|
||||
if (FAILED(hr)) {
|
||||
uprintf("Failed to set folder option for FileOpenDialog: error %X\n", hr);
|
||||
goto fallback;
|
||||
}
|
||||
} else if ((hr & 0xFFFF) != ERROR_CANCELLED) {
|
||||
// If it's not a user cancel, assume the dialog didn't show and fallback
|
||||
uprintf("Could not show FileOpenDialog: error %X\n", hr);
|
||||
goto fallback;
|
||||
// Set the initial folder (if the path is invalid, will simply use last)
|
||||
wpath = utf8_to_wchar(szFolderPath);
|
||||
// The new IFileOpenDialog makes us split the path
|
||||
fname = NULL;
|
||||
if ((wpath != NULL) && (wcslen(wpath) >= 1)) {
|
||||
for (i = wcslen(wpath) - 1; i != 0; i--) {
|
||||
if (wpath[i] == L'\\') {
|
||||
wpath[i] = 0;
|
||||
fname = &wpath[i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hr = (*pfSHCreateItemFromParsingName)(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (wpath != NULL) {
|
||||
hr = pfod->lpVtbl->SetFolder(pfod, si_path);
|
||||
}
|
||||
if (fname != NULL) {
|
||||
hr = pfod->lpVtbl->SetFileName(pfod, fname);
|
||||
}
|
||||
}
|
||||
safe_free(wpath);
|
||||
|
||||
hr = pfod->lpVtbl->Show(pfod, hMainDialog);
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = pfod->lpVtbl->GetResult(pfod, &psi);
|
||||
if (SUCCEEDED(hr)) {
|
||||
psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &wpath);
|
||||
tmp_path = wchar_to_utf8(wpath);
|
||||
CoTaskMemFree(wpath);
|
||||
if (tmp_path == NULL) {
|
||||
uprintf("Could not convert path\n");
|
||||
} else {
|
||||
safe_strcpy(szFolderPath, MAX_PATH, tmp_path);
|
||||
safe_free(tmp_path);
|
||||
}
|
||||
} else {
|
||||
uprintf("Failed to set folder option for FileOpenDialog: error %X\n", hr);
|
||||
}
|
||||
} else if ((hr & 0xFFFF) != ERROR_CANCELLED) {
|
||||
// If it's not a user cancel, assume the dialog didn't show and fallback
|
||||
uprintf("Could not show FileOpenDialog: error %X\n", hr);
|
||||
goto fallback;
|
||||
}
|
||||
pfod->lpVtbl->Release(pfod);
|
||||
dialog_showing--;
|
||||
return;
|
||||
}
|
||||
pfod->lpVtbl->Release(pfod);
|
||||
dialog_showing--;
|
||||
return;
|
||||
}
|
||||
fallback:
|
||||
if (pfod != NULL) {
|
||||
pfod->lpVtbl->Release(pfod);
|
||||
if (pfod != NULL) {
|
||||
pfod->lpVtbl->Release(pfod);
|
||||
}
|
||||
}
|
||||
#else
|
||||
dialog_showing++;
|
||||
#endif
|
||||
|
||||
INIT_XP_SHELL32;
|
||||
memset(&bi, 0, sizeof(BROWSEINFOW));
|
||||
bi.hwndOwner = hMainDialog;
|
||||
|
@ -253,99 +249,97 @@ char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options)
|
|||
size_t i, j, ext_strlen;
|
||||
BOOL r;
|
||||
char* filepath = NULL;
|
||||
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
HRESULT hr = FALSE;
|
||||
IFileDialog *pfd = NULL;
|
||||
IShellItem *psiResult;
|
||||
COMDLG_FILTERSPEC* filter_spec;
|
||||
wchar_t *wpath = NULL, *wfilename = NULL;
|
||||
IShellItem *si_path = NULL; // Automatically freed
|
||||
#endif
|
||||
|
||||
if ((ext == NULL) || (ext->count == 0) || (ext->extension == NULL) || (ext->description == NULL))
|
||||
return NULL;
|
||||
dialog_showing++;
|
||||
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
INIT_VISTA_SHELL32;
|
||||
filter_spec = (COMDLG_FILTERSPEC*)calloc(ext->count + 1, sizeof(COMDLG_FILTERSPEC));
|
||||
if ((IS_VISTA_SHELL32_AVAILABLE) && (filter_spec != NULL)) {
|
||||
// Setup the file extension filter table
|
||||
for (i=0; i<ext->count; i++) {
|
||||
filter_spec[i].pszSpec = utf8_to_wchar(ext->extension[i]);
|
||||
filter_spec[i].pszName = utf8_to_wchar(ext->description[i]);
|
||||
}
|
||||
filter_spec[i].pszSpec = L"*.*";
|
||||
filter_spec[i].pszName = utf8_to_wchar(lmprintf(MSG_107));
|
||||
|
||||
hr = CoCreateInstance(save?&CLSID_FileSaveDialog:&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC,
|
||||
&IID_IFileDialog, (LPVOID)&pfd);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
SetLastError(hr);
|
||||
uprintf("CoCreateInstance for FileOpenDialog failed: %s\n", WindowsErrorString());
|
||||
pfd = NULL; // Just in case
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
// Set the file extension filters
|
||||
pfd->lpVtbl->SetFileTypes(pfd, (UINT)ext->count+1, filter_spec);
|
||||
|
||||
// Set the default directory
|
||||
wpath = utf8_to_wchar(path);
|
||||
hr = (*pfSHCreateItemFromParsingName)(wpath, NULL, &IID_IShellItem, (LPVOID) &si_path);
|
||||
if (SUCCEEDED(hr)) {
|
||||
pfd->lpVtbl->SetFolder(pfd, si_path);
|
||||
}
|
||||
safe_free(wpath);
|
||||
|
||||
// Set the default filename
|
||||
wfilename = utf8_to_wchar((ext->filename == NULL)?"":ext->filename);
|
||||
if (wfilename != NULL) {
|
||||
pfd->lpVtbl->SetFileName(pfd, wfilename);
|
||||
}
|
||||
|
||||
// Display the dialog
|
||||
hr = pfd->lpVtbl->Show(pfd, hMainDialog);
|
||||
|
||||
// Cleanup
|
||||
safe_free(wfilename);
|
||||
for (i=0; i<ext->count; i++) {
|
||||
safe_free(filter_spec[i].pszSpec);
|
||||
safe_free(filter_spec[i].pszName);
|
||||
}
|
||||
safe_free(filter_spec[i].pszName);
|
||||
safe_free(filter_spec);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Obtain the result of the user's interaction with the dialog.
|
||||
hr = pfd->lpVtbl->GetResult(pfd, &psiResult);
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = psiResult->lpVtbl->GetDisplayName(psiResult, SIGDN_FILESYSPATH, &wpath);
|
||||
if (SUCCEEDED(hr)) {
|
||||
filepath = wchar_to_utf8(wpath);
|
||||
CoTaskMemFree(wpath);
|
||||
} else {
|
||||
SetLastError(hr);
|
||||
uprintf("Unable to access file path: %s\n", WindowsErrorString());
|
||||
}
|
||||
psiResult->lpVtbl->Release(psiResult);
|
||||
#ifndef DDKBUILD
|
||||
if (nWindowsVersion >= WINDOWS_VISTA) {
|
||||
INIT_VISTA_SHELL32;
|
||||
filter_spec = (COMDLG_FILTERSPEC*)calloc(ext->count + 1, sizeof(COMDLG_FILTERSPEC));
|
||||
if ((IS_VISTA_SHELL32_AVAILABLE) && (filter_spec != NULL)) {
|
||||
// Setup the file extension filter table
|
||||
for (i = 0; i < ext->count; i++) {
|
||||
filter_spec[i].pszSpec = utf8_to_wchar(ext->extension[i]);
|
||||
filter_spec[i].pszName = utf8_to_wchar(ext->description[i]);
|
||||
}
|
||||
} else if ((hr & 0xFFFF) != ERROR_CANCELLED) {
|
||||
// If it's not a user cancel, assume the dialog didn't show and fallback
|
||||
SetLastError(hr);
|
||||
uprintf("Could not show FileOpenDialog: %s\n", WindowsErrorString());
|
||||
goto fallback;
|
||||
}
|
||||
pfd->lpVtbl->Release(pfd);
|
||||
dialog_showing--;
|
||||
return filepath;
|
||||
}
|
||||
filter_spec[i].pszSpec = L"*.*";
|
||||
filter_spec[i].pszName = utf8_to_wchar(lmprintf(MSG_107));
|
||||
|
||||
hr = CoCreateInstance(save ? &CLSID_FileSaveDialog : &CLSID_FileOpenDialog, NULL, CLSCTX_INPROC,
|
||||
&IID_IFileDialog, (LPVOID)&pfd);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
SetLastError(hr);
|
||||
uprintf("CoCreateInstance for FileOpenDialog failed: %s\n", WindowsErrorString());
|
||||
pfd = NULL; // Just in case
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
// Set the file extension filters
|
||||
pfd->lpVtbl->SetFileTypes(pfd, (UINT)ext->count + 1, filter_spec);
|
||||
|
||||
// Set the default directory
|
||||
wpath = utf8_to_wchar(path);
|
||||
hr = (*pfSHCreateItemFromParsingName)(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path);
|
||||
if (SUCCEEDED(hr)) {
|
||||
pfd->lpVtbl->SetFolder(pfd, si_path);
|
||||
}
|
||||
safe_free(wpath);
|
||||
|
||||
// Set the default filename
|
||||
wfilename = utf8_to_wchar((ext->filename == NULL) ? "" : ext->filename);
|
||||
if (wfilename != NULL) {
|
||||
pfd->lpVtbl->SetFileName(pfd, wfilename);
|
||||
}
|
||||
|
||||
// Display the dialog
|
||||
hr = pfd->lpVtbl->Show(pfd, hMainDialog);
|
||||
|
||||
// Cleanup
|
||||
safe_free(wfilename);
|
||||
for (i = 0; i < ext->count; i++) {
|
||||
safe_free(filter_spec[i].pszSpec);
|
||||
safe_free(filter_spec[i].pszName);
|
||||
}
|
||||
safe_free(filter_spec[i].pszName);
|
||||
safe_free(filter_spec);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Obtain the result of the user's interaction with the dialog.
|
||||
hr = pfd->lpVtbl->GetResult(pfd, &psiResult);
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = psiResult->lpVtbl->GetDisplayName(psiResult, SIGDN_FILESYSPATH, &wpath);
|
||||
if (SUCCEEDED(hr)) {
|
||||
filepath = wchar_to_utf8(wpath);
|
||||
CoTaskMemFree(wpath);
|
||||
} else {
|
||||
SetLastError(hr);
|
||||
uprintf("Unable to access file path: %s\n", WindowsErrorString());
|
||||
}
|
||||
psiResult->lpVtbl->Release(psiResult);
|
||||
}
|
||||
} else if ((hr & 0xFFFF) != ERROR_CANCELLED) {
|
||||
// If it's not a user cancel, assume the dialog didn't show and fallback
|
||||
SetLastError(hr);
|
||||
uprintf("Could not show FileOpenDialog: %s\n", WindowsErrorString());
|
||||
goto fallback;
|
||||
}
|
||||
pfd->lpVtbl->Release(pfd);
|
||||
dialog_showing--;
|
||||
return filepath;
|
||||
}
|
||||
fallback:
|
||||
if (pfd != NULL) {
|
||||
pfd->lpVtbl->Release(pfd);
|
||||
if (pfd != NULL) {
|
||||
pfd->lpVtbl->Release(pfd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue