mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[ui] keep user preferred image type when saving drive to VHD
* Also fix a Coverity warning and use a better description for SELECT image types.
This commit is contained in:
parent
5bbcba8534
commit
5191c68337
8 changed files with 156 additions and 204 deletions
|
@ -1642,12 +1642,13 @@ DWORD WINAPI FormatThread(void* param)
|
||||||
if ((boot_type == BT_IMAGE) && write_as_image) {
|
if ((boot_type == BT_IMAGE) && write_as_image) {
|
||||||
// Special case for FFU images
|
// Special case for FFU images
|
||||||
if (img_report.compression_type == IMG_COMPRESSION_FFU) {
|
if (img_report.compression_type == IMG_COMPRESSION_FFU) {
|
||||||
char cmd[MAX_PATH + 128], *physical;
|
char cmd[MAX_PATH + 128], *physical = NULL;
|
||||||
// Should have been filtered out beforehand
|
// Should have been filtered out beforehand
|
||||||
assert(has_ffu_support);
|
assert(has_ffu_support);
|
||||||
safe_unlockclose(hPhysicalDrive);
|
safe_unlockclose(hPhysicalDrive);
|
||||||
physical = GetPhysicalName(SelectedDrive.DeviceNumber);
|
physical = GetPhysicalName(SelectedDrive.DeviceNumber);
|
||||||
static_sprintf(cmd, "dism /Apply-Ffu /ApplyDrive:%s /ImageFile:\"%s\"", physical, image_path);
|
static_sprintf(cmd, "dism /Apply-Ffu /ApplyDrive:%s /ImageFile:\"%s\"", physical, image_path);
|
||||||
|
safe_free(physical);
|
||||||
uprintf("Running command: '%s", cmd);
|
uprintf("Running command: '%s", cmd);
|
||||||
cr = RunCommandWithProgress(cmd, sysnative_dir, TRUE, MSG_261);
|
cr = RunCommandWithProgress(cmd, sysnative_dir, TRUE, MSG_261);
|
||||||
if (cr != 0 && !IS_ERROR(FormatStatus)) {
|
if (cr != 0 && !IS_ERROR(FormatStatus)) {
|
||||||
|
|
|
@ -1040,7 +1040,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param)
|
||||||
#endif
|
#endif
|
||||||
EXT_DECL(img_ext, GetShortName(url), __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036)));
|
EXT_DECL(img_ext, GetShortName(url), __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036)));
|
||||||
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_ISO;
|
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_ISO;
|
||||||
img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0);
|
img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, NULL);
|
||||||
if (img_save.ImagePath == NULL) {
|
if (img_save.ImagePath == NULL) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
13
src/rufus.c
13
src/rufus.c
|
@ -139,7 +139,7 @@ char embedded_sl_version_str[2][12] = { "?.??", "?.??" };
|
||||||
char embedded_sl_version_ext[2][32];
|
char embedded_sl_version_ext[2][32];
|
||||||
char ClusterSizeLabel[MAX_CLUSTER_SIZES][64];
|
char ClusterSizeLabel[MAX_CLUSTER_SIZES][64];
|
||||||
char msgbox[1024], msgbox_title[32], *ini_file = NULL, *image_path = NULL, *short_image_path;
|
char msgbox[1024], msgbox_title[32], *ini_file = NULL, *image_path = NULL, *short_image_path;
|
||||||
char *archive_path = NULL, image_option_txt[128], *fido_url = NULL;
|
char *archive_path = NULL, image_option_txt[128], *fido_url = NULL, *save_image_type = NULL;
|
||||||
StrArray BlockingProcess, ImageList;
|
StrArray BlockingProcess, ImageList;
|
||||||
// Number of steps for each FS for FCC_STRUCTURE_PROGRESS
|
// Number of steps for each FS for FCC_STRUCTURE_PROGRESS
|
||||||
const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10, 1, 1, 1, 1 };
|
const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10, 1, 1, 1, 1 };
|
||||||
|
@ -1013,7 +1013,7 @@ BOOL CALLBACK LogCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
log_size = GetDlgItemTextU(hDlg, IDC_LOG_EDIT, log_buffer, log_size);
|
log_size = GetDlgItemTextU(hDlg, IDC_LOG_EDIT, log_buffer, log_size);
|
||||||
if (log_size != 0) {
|
if (log_size != 0) {
|
||||||
log_size--; // remove NUL terminator
|
log_size--; // remove NUL terminator
|
||||||
filepath = FileDialog(TRUE, user_dir, &log_ext, 0);
|
filepath = FileDialog(TRUE, user_dir, &log_ext, NULL);
|
||||||
if (filepath != NULL)
|
if (filepath != NULL)
|
||||||
FileIO(FILE_IO_WRITE, filepath, &log_buffer, &log_size);
|
FileIO(FILE_IO_WRITE, filepath, &log_buffer, &log_size);
|
||||||
safe_free(filepath);
|
safe_free(filepath);
|
||||||
|
@ -2567,7 +2567,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
EXT_DECL(arch_ext, NULL, __VA_GROUP__("*.zip"), __VA_GROUP__(lmprintf(MSG_309)));
|
EXT_DECL(arch_ext, NULL, __VA_GROUP__("*.zip"), __VA_GROUP__(lmprintf(MSG_309)));
|
||||||
if (image_path == NULL)
|
if (image_path == NULL)
|
||||||
break;
|
break;
|
||||||
archive_path = FileDialog(FALSE, NULL, &arch_ext, 0);
|
archive_path = FileDialog(FALSE, NULL, &arch_ext, NULL);
|
||||||
if (archive_path != NULL) {
|
if (archive_path != NULL) {
|
||||||
struct __stat64 stat64 = { 0 };
|
struct __stat64 stat64 = { 0 };
|
||||||
_stat64U(archive_path, &stat64);
|
_stat64U(archive_path, &stat64);
|
||||||
|
@ -2591,10 +2591,10 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
char extensions[128] = "*.iso;*.img;*.vhd;*.vhdx;*.usb;*.bz2;*.bzip2;*.gz;*.lzma;*.xz;*.Z;*.zip;*.wim;*.esd;*.vtsi";
|
char extensions[128] = "*.iso;*.img;*.vhd;*.vhdx;*.usb;*.bz2;*.bzip2;*.gz;*.lzma;*.xz;*.Z;*.zip;*.wim;*.esd;*.vtsi";
|
||||||
if (has_ffu_support)
|
if (has_ffu_support)
|
||||||
strcat(extensions, ";*.ffu");
|
strcat(extensions, ";*.ffu");
|
||||||
// If declared globaly, lmprintf(MSG_036) would be called on each message...
|
// If declared globaly, lmprintf(MSG_280) would be called on each message...
|
||||||
EXT_DECL(img_ext, NULL, __VA_GROUP__(extensions),
|
EXT_DECL(img_ext, NULL, __VA_GROUP__(extensions),
|
||||||
__VA_GROUP__(lmprintf(MSG_036)));
|
__VA_GROUP__(lmprintf(MSG_280)));
|
||||||
image_path = FileDialog(FALSE, NULL, &img_ext, 0);
|
image_path = FileDialog(FALSE, NULL, &img_ext, NULL);
|
||||||
if (image_path == NULL) {
|
if (image_path == NULL) {
|
||||||
if (old_image_path != NULL) {
|
if (old_image_path != NULL) {
|
||||||
// Reselect previous image
|
// Reselect previous image
|
||||||
|
@ -3556,6 +3556,7 @@ skip_args_processing:
|
||||||
enable_extra_hashes = ReadSettingBool(SETTING_ENABLE_EXTRA_HASHES);
|
enable_extra_hashes = ReadSettingBool(SETTING_ENABLE_EXTRA_HASHES);
|
||||||
ignore_boot_marker = ReadSettingBool(SETTING_IGNORE_BOOT_MARKER);
|
ignore_boot_marker = ReadSettingBool(SETTING_IGNORE_BOOT_MARKER);
|
||||||
persistent_log = ReadSettingBool(SETTING_PERSISTENT_LOG);
|
persistent_log = ReadSettingBool(SETTING_PERSISTENT_LOG);
|
||||||
|
save_image_type = ReadSettingStr(SETTING_PREFERRED_SAVE_IMAGE_TYPE);
|
||||||
// This restores the Windows User Experience/unattend.xml mask from the saved user
|
// This restores the Windows User Experience/unattend.xml mask from the saved user
|
||||||
// settings, and is designed to work even if we add new options later.
|
// settings, and is designed to work even if we add new options later.
|
||||||
wue_options = ReadSetting32(SETTING_WUE_OPTIONS);
|
wue_options = ReadSetting32(SETTING_WUE_OPTIONS);
|
||||||
|
|
|
@ -655,7 +655,7 @@ extern BOOL DumpFatDir(const char* path, int32_t cluster);
|
||||||
extern BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs);
|
extern BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs);
|
||||||
extern uint16_t GetSyslinuxVersion(char* buf, size_t buf_size, char** ext);
|
extern uint16_t GetSyslinuxVersion(char* buf, size_t buf_size, char** ext);
|
||||||
extern BOOL SetAutorun(const char* path);
|
extern BOOL SetAutorun(const char* path);
|
||||||
extern char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options);
|
extern char* FileDialog(BOOL save, char* path, const ext_t* ext, UINT* selected_ext);
|
||||||
extern BOOL FileIO(enum file_io_type io_type, char* path, char** buffer, DWORD* size);
|
extern BOOL FileIO(enum file_io_type io_type, char* path, char** buffer, DWORD* size);
|
||||||
extern unsigned char* GetResource(HMODULE module, char* name, char* type, const char* desc, DWORD* len, BOOL duplicate);
|
extern unsigned char* GetResource(HMODULE module, char* name, char* type, const char* desc, DWORD* len, BOOL duplicate);
|
||||||
extern DWORD GetResourceSize(HMODULE module, char* name, char* type, const char* desc);
|
extern DWORD GetResourceSize(HMODULE module, char* name, char* type, const char* desc);
|
||||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
EXSTYLE WS_EX_ACCEPTFILES
|
EXSTYLE WS_EX_ACCEPTFILES
|
||||||
CAPTION "Rufus 4.2.2068"
|
CAPTION "Rufus 4.2.2069"
|
||||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||||
|
@ -392,8 +392,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 4,2,2068,0
|
FILEVERSION 4,2,2069,0
|
||||||
PRODUCTVERSION 4,2,2068,0
|
PRODUCTVERSION 4,2,2069,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -411,13 +411,13 @@ BEGIN
|
||||||
VALUE "Comments", "https://rufus.ie"
|
VALUE "Comments", "https://rufus.ie"
|
||||||
VALUE "CompanyName", "Akeo Consulting"
|
VALUE "CompanyName", "Akeo Consulting"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "4.2.2068"
|
VALUE "FileVersion", "4.2.2069"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
VALUE "OriginalFilename", "rufus-4.2.exe"
|
VALUE "OriginalFilename", "rufus-4.2.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "4.2.2068"
|
VALUE "ProductVersion", "4.2.2069"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Rufus: The Reliable USB Formatting Utility
|
* Rufus: The Reliable USB Formatting Utility
|
||||||
* Settings access, through either registry or INI file
|
* Settings access, through either registry or INI file
|
||||||
* Copyright © 2015-2022 Pete Batard <pete@akeo.ie>
|
* Copyright © 2015-2023 Pete Batard <pete@akeo.ie>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "rufus.h"
|
#include "rufus.h"
|
||||||
|
#include "msapi_utf8.h"
|
||||||
#include "registry.h"
|
#include "registry.h"
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -52,6 +53,7 @@ extern char* ini_file;
|
||||||
#define SETTING_USE_UDF_VERSION "UseUdfVersion"
|
#define SETTING_USE_UDF_VERSION "UseUdfVersion"
|
||||||
#define SETTING_USE_VDS "UseVds"
|
#define SETTING_USE_VDS "UseVds"
|
||||||
#define SETTING_PERSISTENT_LOG "PersistentLog"
|
#define SETTING_PERSISTENT_LOG "PersistentLog"
|
||||||
|
#define SETTING_PREFERRED_SAVE_IMAGE_TYPE "PreferredSaveImageType"
|
||||||
#define SETTING_PRESERVE_TIMESTAMPS "PreserveTimestamps"
|
#define SETTING_PRESERVE_TIMESTAMPS "PreserveTimestamps"
|
||||||
#define SETTING_VERBOSE_UPDATES "VerboseUpdateCheck"
|
#define SETTING_VERBOSE_UPDATES "VerboseUpdateCheck"
|
||||||
#define SETTING_WUE_OPTIONS "WindowsUserExperienceOptions"
|
#define SETTING_WUE_OPTIONS "WindowsUserExperienceOptions"
|
||||||
|
|
239
src/stdlg.c
239
src/stdlg.c
|
@ -90,14 +90,9 @@ void SetDialogFocus(HWND hDlg, HWND hCtrl)
|
||||||
* *EACH* thread you invoke FileDialog from, as GetDisplayName() will
|
* *EACH* thread you invoke FileDialog from, as GetDisplayName() will
|
||||||
* return error 0x8001010E otherwise.
|
* return error 0x8001010E otherwise.
|
||||||
*/
|
*/
|
||||||
char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options)
|
char* FileDialog(BOOL save, char* path, const ext_t* ext, UINT* selected_ext)
|
||||||
{
|
{
|
||||||
DWORD tmp;
|
size_t i;
|
||||||
OPENFILENAMEA ofn;
|
|
||||||
char selected_name[MAX_PATH];
|
|
||||||
char *ext_string = NULL, *all_files = NULL;
|
|
||||||
size_t i, j, ext_strlen;
|
|
||||||
BOOL r;
|
|
||||||
char* filepath = NULL;
|
char* filepath = NULL;
|
||||||
HRESULT hr = FALSE;
|
HRESULT hr = FALSE;
|
||||||
IFileDialog *pfd = NULL;
|
IFileDialog *pfd = NULL;
|
||||||
|
@ -108,167 +103,107 @@ char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options)
|
||||||
|
|
||||||
if ((ext == NULL) || (ext->count == 0) || (ext->extension == NULL) || (ext->description == NULL))
|
if ((ext == NULL) || (ext->count == 0) || (ext->extension == NULL) || (ext->description == NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
dialog_showing++;
|
|
||||||
|
|
||||||
filter_spec = (COMDLG_FILTERSPEC*)calloc(ext->count + 1, sizeof(COMDLG_FILTERSPEC));
|
filter_spec = (COMDLG_FILTERSPEC*)calloc(ext->count + 1, sizeof(COMDLG_FILTERSPEC));
|
||||||
if (filter_spec != NULL) {
|
if (filter_spec == NULL)
|
||||||
// Setup the file extension filter table
|
return NULL;
|
||||||
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,
|
dialog_showing++;
|
||||||
&IID_IFileDialog, (LPVOID)&pfd);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
// Setup the file extension filter table
|
||||||
SetLastError(hr);
|
for (i = 0; i < ext->count; i++) {
|
||||||
uprintf("CoCreateInstance for FileOpenDialog failed: %s\n", WindowsErrorString());
|
filter_spec[i].pszSpec = utf8_to_wchar(ext->extension[i]);
|
||||||
if (pfd != NULL) {
|
filter_spec[i].pszName = utf8_to_wchar(ext->description[i]);
|
||||||
IFileDialog_Release(pfd);
|
}
|
||||||
pfd = NULL; // Just in case
|
filter_spec[i].pszSpec = L"*.*";
|
||||||
}
|
filter_spec[i].pszName = utf8_to_wchar(lmprintf(MSG_107));
|
||||||
goto fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the file extension filters
|
hr = CoCreateInstance(save ? &CLSID_FileSaveDialog : &CLSID_FileOpenDialog, NULL, CLSCTX_INPROC,
|
||||||
IFileDialog_SetFileTypes(pfd, (UINT)ext->count + 1, filter_spec);
|
&IID_IFileDialog, (LPVOID)&pfd);
|
||||||
|
|
||||||
if (path == NULL) {
|
if (FAILED(hr)) {
|
||||||
// Try to use the "Downloads" folder as the initial default directory
|
SetLastError(hr);
|
||||||
const GUID download_dir_guid =
|
uprintf("CoCreateInstance for FileOpenDialog failed: %s\n", WindowsErrorString());
|
||||||
{ 0x374de290, 0x123f, 0x4565, { 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b } };
|
if (pfd != NULL)
|
||||||
hr = SHGetKnownFolderPath(&download_dir_guid, 0, 0, &wpath);
|
goto out;
|
||||||
if (SUCCEEDED(hr)) {
|
}
|
||||||
hr = SHCreateItemFromParsingName(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path);
|
|
||||||
if (SUCCEEDED(hr)) {
|
// Set the file extension filters
|
||||||
IFileDialog_SetDefaultFolder(pfd, si_path);
|
IFileDialog_SetFileTypes(pfd, (UINT)ext->count + 1, filter_spec);
|
||||||
}
|
|
||||||
CoTaskMemFree(wpath);
|
if (path == NULL) {
|
||||||
}
|
// Try to use the "Downloads" folder as the initial default directory
|
||||||
} else {
|
const GUID download_dir_guid =
|
||||||
wpath = utf8_to_wchar(path);
|
{ 0x374de290, 0x123f, 0x4565, { 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b } };
|
||||||
|
hr = SHGetKnownFolderPath(&download_dir_guid, 0, 0, &wpath);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
hr = SHCreateItemFromParsingName(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path);
|
hr = SHCreateItemFromParsingName(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
IFileDialog_SetFolder(pfd, si_path);
|
IFileDialog_SetDefaultFolder(pfd, si_path);
|
||||||
}
|
}
|
||||||
safe_free(wpath);
|
CoTaskMemFree(wpath);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
// Set the default filename
|
wpath = utf8_to_wchar(path);
|
||||||
wfilename = utf8_to_wchar((ext->filename == NULL) ? "" : ext->filename);
|
hr = SHCreateItemFromParsingName(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path);
|
||||||
if (wfilename != NULL) {
|
|
||||||
IFileDialog_SetFileName(pfd, wfilename);
|
|
||||||
}
|
|
||||||
// Set a default extension so that when the user switches filters it gets
|
|
||||||
// automatically updated. Note that the IFileDialog::SetDefaultExtension()
|
|
||||||
// doc says the extension shouldn't be prefixed with unwanted characters
|
|
||||||
// but it appears to work regardless so we don't bother cleaning it.
|
|
||||||
wext = utf8_to_wchar((ext->extension == NULL) ? "" : ext->extension[0]);
|
|
||||||
if (wext != NULL) {
|
|
||||||
IFileDialog_SetDefaultExtension(pfd, wext);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display the dialog
|
|
||||||
hr = IFileDialog_Show(pfd, hMainDialog);
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
safe_free(wext);
|
|
||||||
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)) {
|
if (SUCCEEDED(hr)) {
|
||||||
// Obtain the result of the user's interaction with the dialog.
|
IFileDialog_SetFolder(pfd, si_path);
|
||||||
hr = IFileDialog_GetResult(pfd, &psiResult);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
hr = IShellItem_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());
|
|
||||||
}
|
|
||||||
IShellItem_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;
|
|
||||||
}
|
}
|
||||||
IFileDialog_Release(pfd);
|
safe_free(wpath);
|
||||||
dialog_showing--;
|
|
||||||
return filepath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fallback:
|
// Set the default filename
|
||||||
|
wfilename = utf8_to_wchar((ext->filename == NULL) ? "" : ext->filename);
|
||||||
|
if (wfilename != NULL)
|
||||||
|
IFileDialog_SetFileName(pfd, wfilename);
|
||||||
|
// Set a default extension so that when the user switches filters it gets
|
||||||
|
// automatically updated. Note that the IFileDialog::SetDefaultExtension()
|
||||||
|
// doc says the extension shouldn't be prefixed with unwanted characters
|
||||||
|
// but it appears to work regardless so we don't bother cleaning it.
|
||||||
|
wext = utf8_to_wchar((ext->extension == NULL) ? "" : ext->extension[0]);
|
||||||
|
if (wext != NULL)
|
||||||
|
IFileDialog_SetDefaultExtension(pfd, wext);
|
||||||
|
// Set the current selected extension
|
||||||
|
IFileDialog_SetFileTypeIndex(pfd, selected_ext == NULL ? 0 : *selected_ext);
|
||||||
|
|
||||||
|
// Display the dialog and (optionally) get the selected extension index
|
||||||
|
hr = IFileDialog_Show(pfd, hMainDialog);
|
||||||
|
if (selected_ext != NULL)
|
||||||
|
IFileDialog_GetFileTypeIndex(pfd, selected_ext);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
safe_free(wext);
|
||||||
|
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);
|
safe_free(filter_spec);
|
||||||
if (pfd != NULL) {
|
|
||||||
IFileDialog_Release(pfd);
|
if (SUCCEEDED(hr)) {
|
||||||
|
// Obtain the result of the user's interaction with the dialog.
|
||||||
|
hr = IFileDialog_GetResult(pfd, &psiResult);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = IShellItem_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", WindowsErrorString());
|
||||||
|
}
|
||||||
|
IShellItem_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", WindowsErrorString());
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&ofn, 0, sizeof(ofn));
|
out:
|
||||||
ofn.lStructSize = sizeof(ofn);
|
if (pfd != NULL)
|
||||||
ofn.hwndOwner = hMainDialog;
|
IFileDialog_Release(pfd);
|
||||||
// Selected File name
|
|
||||||
static_sprintf(selected_name, "%s", (ext->filename == NULL)?"":ext->filename);
|
|
||||||
ofn.lpstrFile = selected_name;
|
|
||||||
ofn.nMaxFile = MAX_PATH;
|
|
||||||
// Set the file extension filters
|
|
||||||
all_files = lmprintf(MSG_107);
|
|
||||||
ext_strlen = 0;
|
|
||||||
for (i=0; i<ext->count; i++) {
|
|
||||||
ext_strlen += safe_strlen(ext->description[i]) + 2*safe_strlen(ext->extension[i]) + sizeof(" ()\r\r");
|
|
||||||
}
|
|
||||||
ext_strlen += safe_strlen(all_files) + sizeof(" (*.*)\r*.*\r");
|
|
||||||
ext_string = (char*)malloc(ext_strlen+1);
|
|
||||||
if (ext_string == NULL)
|
|
||||||
return NULL;
|
|
||||||
ext_string[0] = 0;
|
|
||||||
for (i=0, j=0; i<ext->count; i++) {
|
|
||||||
j += _snprintf(&ext_string[j], ext_strlen-j, "%s (%s)\r%s\r", ext->description[i], ext->extension[i], ext->extension[i]);
|
|
||||||
}
|
|
||||||
j = _snprintf(&ext_string[j], ext_strlen-j, "%s (*.*)\r*.*\r", all_files);
|
|
||||||
// Microsoft could really have picked a better delimiter!
|
|
||||||
for (i=0; i<ext_strlen; i++) {
|
|
||||||
// Since the VS Code Analysis tool is dumb...
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma warning(suppress: 6385)
|
|
||||||
#endif
|
|
||||||
if (ext_string[i] == '\r') {
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma warning(suppress: 6386)
|
|
||||||
#endif
|
|
||||||
ext_string[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ofn.lpstrFilter = ext_string;
|
|
||||||
ofn.nFilterIndex = 1;
|
|
||||||
ofn.lpstrInitialDir = path;
|
|
||||||
ofn.Flags = OFN_OVERWRITEPROMPT | options;
|
|
||||||
// Show Dialog
|
|
||||||
if (save) {
|
|
||||||
r = GetSaveFileNameU(&ofn);
|
|
||||||
} else {
|
|
||||||
r = GetOpenFileNameU(&ofn);
|
|
||||||
}
|
|
||||||
if (r) {
|
|
||||||
filepath = safe_strdup(selected_name);
|
|
||||||
} else {
|
|
||||||
tmp = CommDlgExtendedError();
|
|
||||||
if (tmp != 0) {
|
|
||||||
uprintf("Could not select file for %s. Error %X\n", save?"save":"open", tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
safe_free(ext_string);
|
|
||||||
dialog_showing--;
|
dialog_showing--;
|
||||||
return filepath;
|
return filepath;
|
||||||
}
|
}
|
||||||
|
@ -1700,7 +1635,7 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dl_ext.filename = PathFindFileNameU(update.download_url);
|
dl_ext.filename = PathFindFileNameU(update.download_url);
|
||||||
filepath = FileDialog(TRUE, app_dir, &dl_ext, OFN_NOCHANGEDIR);
|
filepath = FileDialog(TRUE, app_dir, &dl_ext, NULL);
|
||||||
if (filepath == NULL) {
|
if (filepath == NULL) {
|
||||||
uprintf("Could not get save path");
|
uprintf("Could not get save path");
|
||||||
break;
|
break;
|
||||||
|
|
87
src/vhd.c
87
src/vhd.c
|
@ -29,6 +29,7 @@
|
||||||
#include "vhd.h"
|
#include "vhd.h"
|
||||||
#include "missing.h"
|
#include "missing.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
#include "settings.h"
|
||||||
#include "msapi_utf8.h"
|
#include "msapi_utf8.h"
|
||||||
|
|
||||||
#include "drive.h"
|
#include "drive.h"
|
||||||
|
@ -58,6 +59,7 @@ typedef struct {
|
||||||
uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
|
uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
|
||||||
HANDLE wim_thread = NULL;
|
HANDLE wim_thread = NULL;
|
||||||
extern int default_thread_priority;
|
extern int default_thread_priority;
|
||||||
|
extern char* save_image_type;
|
||||||
extern BOOL ignore_boot_marker, has_ffu_support;
|
extern BOOL ignore_boot_marker, has_ffu_support;
|
||||||
extern RUFUS_DRIVE rufus_drive[MAX_DRIVES];
|
extern RUFUS_DRIVE rufus_drive[MAX_DRIVES];
|
||||||
extern HANDLE format_thread;
|
extern HANDLE format_thread;
|
||||||
|
@ -1099,68 +1101,79 @@ static DWORD WINAPI FfuSaveImageThread(void* param)
|
||||||
|
|
||||||
void VhdSaveImage(void)
|
void VhdSaveImage(void)
|
||||||
{
|
{
|
||||||
static IMG_SAVE img_save = { 0 };
|
UINT i;
|
||||||
|
static IMG_SAVE img_save;
|
||||||
char filename[128];
|
char filename[128];
|
||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
int DriveIndex = ComboBox_GetCurSel(hDeviceList);
|
int DriveIndex = ComboBox_GetCurSel(hDeviceList);
|
||||||
EXT_DECL(img_ext, filename, __VA_GROUP__("*.vhdx", "*.vhd", "*.ffu"),
|
static EXT_DECL(img_ext, filename, __VA_GROUP__("*.vhd", "*.vhdx", "*.ffu"),
|
||||||
__VA_GROUP__(lmprintf(MSG_342), lmprintf(MSG_343), lmprintf(MSG_344)));
|
__VA_GROUP__(lmprintf(MSG_343), lmprintf(MSG_342), lmprintf(MSG_344)));
|
||||||
ULARGE_INTEGER free_space;
|
ULARGE_INTEGER free_space;
|
||||||
|
|
||||||
|
memset(&img_save, 0, sizeof(IMG_SAVE));
|
||||||
if ((DriveIndex < 0) || (format_thread != NULL))
|
if ((DriveIndex < 0) || (format_thread != NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static_sprintf(filename, "%s.vhdx", rufus_drive[DriveIndex].label);
|
static_sprintf(filename, "%s", rufus_drive[DriveIndex].label);
|
||||||
img_save.DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, DriveIndex);
|
img_save.DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, DriveIndex);
|
||||||
img_save.DevicePath = GetPhysicalName(img_save.DeviceNum);
|
img_save.DevicePath = GetPhysicalName(img_save.DeviceNum);
|
||||||
// FFU support requires GPT
|
// FFU support requires GPT
|
||||||
if (!has_ffu_support || SelectedDrive.PartitionStyle != PARTITION_STYLE_GPT)
|
if (!has_ffu_support || SelectedDrive.PartitionStyle != PARTITION_STYLE_GPT)
|
||||||
img_ext.count = 2;
|
img_ext.count = 2;
|
||||||
img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0);
|
for (i = 1; i <= (UINT)img_ext.count && (safe_strcmp(&_img_ext_x[i - 1][2], save_image_type) != 0); i++);
|
||||||
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
|
if (i > (UINT)img_ext.count)
|
||||||
if (safe_strstr(img_save.ImagePath, ".vhdx") != NULL)
|
i = 2;
|
||||||
|
img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, &i);
|
||||||
|
assert(i > 0 && i <= (UINT)img_ext.count);
|
||||||
|
save_image_type = (char*) &_img_ext_x[i - 1][2];
|
||||||
|
WriteSettingStr(SETTING_PREFERRED_SAVE_IMAGE_TYPE, save_image_type);
|
||||||
|
switch (i) {
|
||||||
|
case 1:
|
||||||
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
|
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
|
||||||
else if (safe_strstr(img_save.ImagePath, ".ffu") != NULL)
|
break;
|
||||||
|
case 3:
|
||||||
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_FFU;
|
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_FFU;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_VHDX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
img_save.BufSize = DD_BUFFER_SIZE;
|
img_save.BufSize = DD_BUFFER_SIZE;
|
||||||
img_save.DeviceSize = SelectedDrive.DiskSize;
|
img_save.DeviceSize = SelectedDrive.DiskSize;
|
||||||
if (img_save.DevicePath != NULL && img_save.ImagePath != NULL) {
|
if (img_save.DevicePath != NULL && img_save.ImagePath != NULL) {
|
||||||
// Reset all progress bars
|
// Reset all progress bars
|
||||||
SendMessage(hMainDialog, UM_PROGRESS_INIT, 0, 0);
|
SendMessage(hMainDialog, UM_PROGRESS_INIT, 0, 0);
|
||||||
FormatStatus = 0;
|
FormatStatus = 0;
|
||||||
free_space.QuadPart = 0;
|
if (img_save.Type == VIRTUAL_STORAGE_TYPE_DEVICE_VHD) {
|
||||||
if ((GetVolumePathNameA(img_save.ImagePath, path, sizeof(path)))
|
free_space.QuadPart = 0;
|
||||||
&& (GetDiskFreeSpaceExA(path, &free_space, NULL, NULL))
|
if ((GetVolumePathNameA(img_save.ImagePath, path, sizeof(path)))
|
||||||
&& ((LONGLONG)free_space.QuadPart > (SelectedDrive.DiskSize + 512))) {
|
&& (GetDiskFreeSpaceExA(path, &free_space, NULL, NULL))
|
||||||
// Disable all controls except Cancel
|
&& ((LONGLONG)free_space.QuadPart < (SelectedDrive.DiskSize + 512))) {
|
||||||
EnableControls(FALSE, FALSE);
|
|
||||||
FormatStatus = 0;
|
|
||||||
InitProgress(TRUE);
|
|
||||||
format_thread = CreateThread(NULL, 0, img_save.Type == VIRTUAL_STORAGE_TYPE_DEVICE_FFU ?
|
|
||||||
FfuSaveImageThread : VhdSaveImageThread, &img_save, 0, NULL);
|
|
||||||
if (format_thread != NULL) {
|
|
||||||
uprintf("\r\nSave to VHD operation started");
|
|
||||||
PrintInfo(0, -1);
|
|
||||||
SendMessage(hMainDialog, UM_TIMER_START, 0, 0);
|
|
||||||
} else {
|
|
||||||
uprintf("Unable to start VHD save thread");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD);
|
|
||||||
safe_free(img_save.DevicePath);
|
|
||||||
safe_free(img_save.ImagePath);
|
|
||||||
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (free_space.QuadPart == 0) {
|
|
||||||
uprintf("Unable to isolate drive name for VHD save");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_PATH_NOT_FOUND;
|
|
||||||
} else {
|
|
||||||
// TODO: Might be salvageable for compressed VHDX
|
|
||||||
uprintf("The VHD size is too large for the target drive");
|
uprintf("The VHD size is too large for the target drive");
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_FILE_TOO_LARGE;
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_FILE_TOO_LARGE;
|
||||||
|
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
safe_free(img_save.DevicePath);
|
}
|
||||||
safe_free(img_save.ImagePath);
|
// Disable all controls except Cancel
|
||||||
|
EnableControls(FALSE, FALSE);
|
||||||
|
FormatStatus = 0;
|
||||||
|
InitProgress(TRUE);
|
||||||
|
format_thread = CreateThread(NULL, 0, img_save.Type == VIRTUAL_STORAGE_TYPE_DEVICE_FFU ?
|
||||||
|
FfuSaveImageThread : VhdSaveImageThread, &img_save, 0, NULL);
|
||||||
|
if (format_thread != NULL) {
|
||||||
|
uprintf("\r\nSave to VHD operation started");
|
||||||
|
PrintInfo(0, -1);
|
||||||
|
SendMessage(hMainDialog, UM_TIMER_START, 0, 0);
|
||||||
|
} else {
|
||||||
|
uprintf("Unable to start VHD save thread");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD);
|
||||||
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0);
|
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
if (format_thread == NULL) {
|
||||||
|
safe_free(img_save.DevicePath);
|
||||||
|
safe_free(img_save.ImagePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue