VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/Dlgcode.c
diff options
context:
space:
mode:
authorMounir IDRASSI <mounir.idrassi@idrix.fr>2023-09-03 23:42:41 +0200
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2023-09-03 23:42:41 +0200
commit2a6726b00ed51430590e01950a5c0f67ede9e8a9 (patch)
tree924ff4a717bbe41686f105ad4dd03fe47ae85af7 /src/Common/Dlgcode.c
parent201d09ff5aa69db61643659726b36810d5ac00d4 (diff)
downloadVeraCrypt-2a6726b00ed51430590e01950a5c0f67ede9e8a9.tar.gz
VeraCrypt-2a6726b00ed51430590e01950a5c0f67ede9e8a9.zip
Windows: Replace legacy file/dir selection APIs with modern IFileDialog interface
We remove usage of GetOpenFileNameW/GetSaveFileNameW/SHBrowseForFolderW which are deprecated by Microsoft
Diffstat (limited to 'src/Common/Dlgcode.c')
-rw-r--r--src/Common/Dlgcode.c413
1 files changed, 240 insertions, 173 deletions
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index c9c9752a..2c9b3599 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -4964,144 +4964,139 @@ void ResetCurrentDirectory ()
}
-BOOL BrowseFiles (HWND hwndDlg, char *stringId, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter)
+BOOL BrowseFiles (HWND hwndDlg, char *stringId, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode)
{
- return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, browseFilter);
+ return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, NULL);
}
-
-BOOL BrowseFilesInDir (HWND hwndDlg, char *stringId, wchar_t *initialDir, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter, const wchar_t *initialFileName, const wchar_t *defaultExtension)
+BOOL BrowseFilesInDir(HWND hwndDlg, char *stringId, wchar_t *initialDir, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter, const wchar_t *initialFileName, const wchar_t *defaultExtension)
{
- OPENFILENAMEW ofn;
- wchar_t file[TC_MAX_PATH] = { 0 };
+ IFileDialog *pfd = NULL;
+ HRESULT hr;
wchar_t filter[1024];
BOOL status = FALSE;
- CoInitialize (NULL);
-
- ZeroMemory (&ofn, sizeof (ofn));
- *lpszFileName = 0;
-
- if (initialDir)
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (FAILED(hr))
{
- ofn.lpstrInitialDir = initialDir;
+ return FALSE;
}
- if (initialFileName)
- StringCchCopyW (file, array_capacity (file), initialFileName);
-
- ofn.lStructSize = sizeof (ofn);
- ofn.hwndOwner = hwndDlg;
-
- StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c",
- GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0);
- ofn.lpstrFilter = browseFilter ? browseFilter : filter;
- ofn.nFilterIndex = 1;
- ofn.lpstrFile = file;
- ofn.nMaxFile = sizeof (file) / sizeof (file[0]);
- ofn.lpstrTitle = GetString (stringId);
- ofn.lpstrDefExt = defaultExtension;
- ofn.Flags = OFN_HIDEREADONLY
- | OFN_PATHMUSTEXIST
- | (keepHistory ? 0 : OFN_DONTADDTORECENT)
- | (saveMode ? OFN_OVERWRITEPROMPT : 0);
-
- if (!keepHistory)
- CleanLastVisitedMRU ();
-
- SystemFileSelectorCallerThreadId = GetCurrentThreadId();
- SystemFileSelectorCallPending = TRUE;
-
- if (!saveMode)
+ // Choose between the File Open or File Save dialog depending on the saveMode.
+ if (saveMode)
{
- if (!GetOpenFileNameW (&ofn))
- goto ret;
+ hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
}
else
{
- if (!GetSaveFileNameW (&ofn))
- goto ret;
+ hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
}
- SystemFileSelectorCallPending = FALSE;
+ if (SUCCEEDED(hr))
+ {
+ // Set the options for the dialog.
+ DWORD dwFlags;
+ hr = pfd->GetOptions(&dwFlags);
+ if (SUCCEEDED(hr))
+ {
+ dwFlags |= FOS_NOCHANGEDIR | FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE;
+ if (!keepHistory)
+ dwFlags |= FOS_DONTADDTORECENT;
+ if (saveMode)
+ dwFlags |= FOS_NOTESTFILECREATE | FOS_OVERWRITEPROMPT | FOS_DEFAULTNOMINIMODE;
+ hr = pfd->SetOptions(dwFlags);
+ }
- StringCchCopyW (lpszFileName, MAX_PATH, file);
+ // Set the initial directory, if provided.
+ if (initialDir)
+ {
+ IShellItem *psi;
+ hr = SHCreateItemFromParsingName(initialDir, NULL, IID_PPV_ARGS(&psi));
+ if (SUCCEEDED(hr))
+ {
+ pfd->SetFolder(psi);
+ psi->Release();
+ }
+ }
- if (!keepHistory)
- CleanLastVisitedMRU ();
+ // Set the initial file name, if provided.
+ if (initialFileName)
+ {
+ pfd->SetFileName(initialFileName);
+ }
- status = TRUE;
+ // Set the title.
+ pfd->SetTitle(GetString(stringId));
-ret:
- SystemFileSelectorCallPending = FALSE;
- ResetCurrentDirectory();
- CoUninitialize();
+ // Set the default extension.
+ if (defaultExtension)
+ {
+ pfd->SetDefaultExtension(defaultExtension);
+ }
- return status;
-}
+ // Prepare the filter
+ COMDLG_FILTERSPEC filterSpec[5];
+ UINT cfilterSpec = 0;
+ if (!browseFilter)
+ {
+ StringCbPrintfW(filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c",
+ GetString("ALL_FILES"), 0, 0, GetString("TC_VOLUMES"), 0, 0, 0);
+ browseFilter = filter;
+ }
-static wchar_t SelectMultipleFilesPath[131072];
-static int SelectMultipleFilesOffset;
+ // Assume browseFilter is a formatted wide string like L"Text Files (*.txt)\0*.txt\0"
+ // loop over all the filters in the string and add them to filterSpec array
+ while (*browseFilter)
+ {
+ filterSpec[cfilterSpec].pszName = browseFilter;
+ browseFilter += wcslen(browseFilter) + 1;
+ filterSpec[cfilterSpec].pszSpec = browseFilter;
+ browseFilter += wcslen(browseFilter) + 1;
+ cfilterSpec++;
-BOOL SelectMultipleFiles (HWND hwndDlg, const char *stringId, wchar_t *lpszFileName, size_t cbFileName,BOOL keepHistory)
-{
- OPENFILENAMEW ofn;
- wchar_t filter[1024];
- BOOL status = FALSE;
+ if (cfilterSpec >= ARRAYSIZE(filterSpec))
+ break;
+ }
- CoInitialize (NULL);
+ // Set the file types filter.
+ hr = pfd->SetFileTypes(cfilterSpec, filterSpec);
+ hr = pfd->SetFileTypeIndex(1);
- ZeroMemory (&ofn, sizeof (ofn));
-
- SelectMultipleFilesPath[0] = 0;
- *lpszFileName = 0;
- ofn.lStructSize = sizeof (ofn);
- ofn.hwndOwner = hwndDlg;
- StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c",
- GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0);
- ofn.lpstrFilter = filter;
- ofn.nFilterIndex = 1;
- ofn.lpstrFile = SelectMultipleFilesPath;
- ofn.nMaxFile = 0xffff * 2; // The size must not exceed 0xffff*2 due to a bug in Windows 2000 and XP SP1
- ofn.lpstrTitle = GetString (stringId);
- ofn.Flags = OFN_HIDEREADONLY
- | OFN_EXPLORER
- | OFN_PATHMUSTEXIST
- | OFN_ALLOWMULTISELECT
- | (keepHistory ? 0 : OFN_DONTADDTORECENT);
-
- if (!keepHistory)
- CleanLastVisitedMRU ();
+ if (!keepHistory)
+ CleanLastVisitedMRU();
- SystemFileSelectorCallerThreadId = GetCurrentThreadId();
- SystemFileSelectorCallPending = TRUE;
+ SystemFileSelectorCallerThreadId = GetCurrentThreadId();
+ SystemFileSelectorCallPending = TRUE;
- if (!GetOpenFileNameW (&ofn))
- goto ret;
+ // Show the dialog.
+ hr = pfd->Show(hwndDlg);
- SystemFileSelectorCallPending = FALSE;
+ // Obtain the result if the user clicked the "OK" button.
+ if (SUCCEEDED(hr))
+ {
+ IShellItem *pItem;
+ hr = pfd->GetResult(&pItem);
+ if (SUCCEEDED(hr))
+ {
+ PWSTR pszFilePath;
+ hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
+ if (SUCCEEDED(hr))
+ {
+ StringCchCopyW(lpszFileName, MAX_PATH, pszFilePath);
+ CoTaskMemFree(pszFilePath);
+ status = TRUE;
+ }
+ pItem->Release();
+ }
+ }
- if (SelectMultipleFilesPath[ofn.nFileOffset - 1] != 0)
- {
- // Single file selected
- StringCbCopyW (lpszFileName, cbFileName, SelectMultipleFilesPath);
- SelectMultipleFilesOffset = 0;
- SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath));
- }
- else
- {
- // Multiple files selected
- SelectMultipleFilesOffset = ofn.nFileOffset;
- SelectMultipleFilesNext (lpszFileName, cbFileName);
- }
+ pfd->Release();
- if (!keepHistory)
- CleanLastVisitedMRU ();
+ if (!keepHistory)
+ CleanLastVisitedMRU();
+ }
- status = TRUE;
-
-ret:
SystemFileSelectorCallPending = FALSE;
ResetCurrentDirectory();
CoUninitialize();
@@ -5109,101 +5104,173 @@ ret:
return status;
}
-
-BOOL SelectMultipleFilesNext (wchar_t *lpszFileName, size_t cbFileName)
+BOOL SelectMultipleFiles(HWND hwndDlg, const char *stringId, BOOL keepHistory, std::vector<std::wstring> &filesList)
{
- if (SelectMultipleFilesOffset == 0)
+ IFileOpenDialog *pfd = NULL;
+ HRESULT hr;
+ BOOL status = FALSE;
+
+ filesList.clear();
+
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (FAILED(hr))
+ {
return FALSE;
+ }
- StringCbCopyW (lpszFileName, cbFileName,SelectMultipleFilesPath);
- lpszFileName[TC_MAX_PATH - 1] = 0;
+ // Create the File Open Dialog object.
+ hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
+ if (SUCCEEDED(hr))
+ {
+ DWORD dwFlags;
+ hr = pfd->GetOptions(&dwFlags);
+ if (SUCCEEDED(hr))
+ {
+ dwFlags |= FOS_ALLOWMULTISELECT | FOS_NOCHANGEDIR | FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE;
+ if (!keepHistory)
+ dwFlags |= FOS_DONTADDTORECENT;
- if (lpszFileName[wcslen (lpszFileName) - 1] != L'\\')
- StringCbCatW (lpszFileName, cbFileName,L"\\");
+ hr = pfd->SetOptions(dwFlags);
+ }
- StringCbCatW (lpszFileName, cbFileName,SelectMultipleFilesPath + SelectMultipleFilesOffset);
+ // Set the title and filter
+ pfd->SetTitle(GetString(stringId));
- SelectMultipleFilesOffset += (int) wcslen (SelectMultipleFilesPath + SelectMultipleFilesOffset) + 1;
- if (SelectMultipleFilesPath[SelectMultipleFilesOffset] == 0)
- {
- SelectMultipleFilesOffset = 0;
- SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath));
- }
+ wchar_t allFilesfilter[512];
+ wchar_t volumesfilter[512];
- return TRUE;
-}
+ StringCbPrintfW(allFilesfilter, sizeof(allFilesfilter), L"%ls (*.*)", GetString("ALL_FILES"));
+ StringCbPrintfW(volumesfilter, sizeof(volumesfilter), L"%ls (*.hc)", GetString("TC_VOLUMES"));
+ COMDLG_FILTERSPEC rgSpec[] =
+ {
+ {allFilesfilter, L"*.*"},
+ {volumesfilter, L"*.hc"}};
+ hr = pfd->SetFileTypes(ARRAYSIZE(rgSpec), rgSpec);
-static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData)
-{
- switch(uMsg) {
- case BFFM_INITIALIZED:
- {
- /* WParam is TRUE since we are passing a path.
- It would be FALSE if we were passing a pidl. */
- SendMessageW (hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)pData);
- break;
- }
+ if (!keepHistory)
+ CleanLastVisitedMRU();
- case BFFM_SELCHANGED:
- {
- wchar_t szDir[TC_MAX_PATH];
+ // Show the dialog
+ hr = pfd->Show(hwndDlg);
+ if (SUCCEEDED(hr))
+ {
+ IShellItemArray *psiaResults;
+ hr = pfd->GetResults(&psiaResults);
+ if (SUCCEEDED(hr))
+ {
+ DWORD count;
+ hr = psiaResults->GetCount(&count);
+ if (SUCCEEDED(hr))
+ {
+ for (DWORD i = 0; i < count; ++i)
+ {
+ IShellItem *psi;
+ hr = psiaResults->GetItemAt(i, &psi);
+ if (SUCCEEDED(hr))
+ {
+ PWSTR pszFilePath;
+ hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
+ if (SUCCEEDED(hr))
+ {
+ filesList.push_back(pszFilePath);
+ CoTaskMemFree(pszFilePath);
+ }
+ psi->Release();
+ }
+ }
- /* Set the status window to the currently selected path. */
- if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir))
- {
- SendMessage (hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
- }
- break;
- }
+ status = TRUE;
+ }
+ psiaResults->Release();
+ }
+ }
- default:
- break;
+ if (!keepHistory)
+ CleanLastVisitedMRU();
+
+ pfd->Release();
}
- return 0;
+ CoUninitialize();
+ return status;
}
-
-BOOL BrowseDirectories (HWND hwndDlg, char *lpszTitle, wchar_t *dirName)
+BOOL BrowseDirectories(HWND hwndDlg, char *lpszTitle, wchar_t *dirName, const wchar_t *initialDir)
{
- BROWSEINFOW bi;
- LPITEMIDLIST pidl;
- LPMALLOC pMalloc;
- BOOL bOK = FALSE;
+ IFileDialog *pfd = NULL;
+ HRESULT hr;
+ BOOL bOK = FALSE;
- CoInitialize (NULL);
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (FAILED(hr))
+ {
+ return FALSE;
+ }
- if (SUCCEEDED (SHGetMalloc (&pMalloc)))
+ hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
+ if (SUCCEEDED(hr))
{
- ZeroMemory (&bi, sizeof(bi));
- bi.hwndOwner = hwndDlg;
- bi.pszDisplayName = 0;
- bi.lpszTitle = GetString (lpszTitle);
- bi.pidlRoot = 0;
- bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
- bi.lpfn = BrowseCallbackProc;
- bi.lParam = (LPARAM)dirName;
+ // Set the options on the dialog.
+ DWORD dwFlags;
+ hr = pfd->GetOptions(&dwFlags);
+ if (SUCCEEDED(hr))
+ {
+ dwFlags |= FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM | FOS_NOCHANGEDIR; // Important to enable folder-picking mode
+ hr = pfd->SetOptions(dwFlags);
+ }
+
+ // Set the title.
+ if (lpszTitle)
+ {
+ pfd->SetTitle(GetString(lpszTitle));
+ }
- pidl = SHBrowseForFolderW (&bi);
- if (pidl != NULL)
+ IShellItem *psi;
+ if (initialDir)
{
- if (SHGetPathFromIDList(pidl, dirName))
+ // Set the initial directory, if provided.
+ hr = SHCreateItemFromParsingName(initialDir, NULL, IID_PPV_ARGS(&psi));
+ }
+ else
+ {
+ // set folder to "This PC" shel item
+ hr = SHCreateItemInKnownFolder(FOLDERID_ComputerFolder, 0, NULL, IID_PPV_ARGS(&psi));
+ }
+ if (SUCCEEDED(hr))
+ {
+ pfd->SetFolder(psi);
+ psi->Release();
+ }
+
+ // Show the dialog.
+ hr = pfd->Show(hwndDlg);
+ if (SUCCEEDED(hr))
+ {
+ // Obtain the result when the user clicks the "OK" button.
+ // The result is an IShellItem object.
+ IShellItem *pItem;
+ hr = pfd->GetResult(&pItem);
+ if (SUCCEEDED(hr))
{
- bOK = TRUE;
+ PWSTR pszFolderPath;
+ hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFolderPath);
+ if (SUCCEEDED(hr))
+ {
+ StringCchCopyW(dirName, MAX_PATH, pszFolderPath);
+ CoTaskMemFree(pszFolderPath);
+ bOK = TRUE;
+ }
+ pItem->Release();
}
-
- pMalloc->Free (pidl);
- pMalloc->Release();
}
+ pfd->Release();
}
CoUninitialize();
-
return bOK;
}
-
std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg)
{
WCHAR szTmp[8192];
@@ -6891,7 +6958,7 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
fileExtensionPtr = wcsrchr(szFileBaseName, L'.');
/* Select directory */
- if (!BrowseDirectories (hwndDlg, "SELECT_KEYFILE_GENERATION_DIRECTORY", szDirName))
+ if (!BrowseDirectories (hwndDlg, "SELECT_KEYFILE_GENERATION_DIRECTORY", szDirName, NULL))
return 1;
if (szDirName[wcslen(szDirName) - 1] != L'\\' && szDirName[wcslen(szDirName) - 1] != L'/')
@@ -11899,7 +11966,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
{
wchar_t keyfilePath[TC_MAX_PATH];
- if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE, NULL))
+ if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE))
{
DWORD keyfileSize;
byte *keyfileData = (byte *) LoadFile (keyfilePath, &keyfileSize);
@@ -11962,7 +12029,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
{
wchar_t keyfilePath[TC_MAX_PATH];
- if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE, NULL))
+ if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE))
break;
{