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) {
|
||||
// Special case for FFU images
|
||||
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
|
||||
assert(has_ffu_support);
|
||||
safe_unlockclose(hPhysicalDrive);
|
||||
physical = GetPhysicalName(SelectedDrive.DeviceNumber);
|
||||
static_sprintf(cmd, "dism /Apply-Ffu /ApplyDrive:%s /ImageFile:\"%s\"", physical, image_path);
|
||||
safe_free(physical);
|
||||
uprintf("Running command: '%s", cmd);
|
||||
cr = RunCommandWithProgress(cmd, sysnative_dir, TRUE, MSG_261);
|
||||
if (cr != 0 && !IS_ERROR(FormatStatus)) {
|
||||
|
|
|
@ -1040,7 +1040,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param)
|
|||
#endif
|
||||
EXT_DECL(img_ext, GetShortName(url), __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036)));
|
||||
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) {
|
||||
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 ClusterSizeLabel[MAX_CLUSTER_SIZES][64];
|
||||
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;
|
||||
// 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 };
|
||||
|
@ -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);
|
||||
if (log_size != 0) {
|
||||
log_size--; // remove NUL terminator
|
||||
filepath = FileDialog(TRUE, user_dir, &log_ext, 0);
|
||||
filepath = FileDialog(TRUE, user_dir, &log_ext, NULL);
|
||||
if (filepath != NULL)
|
||||
FileIO(FILE_IO_WRITE, filepath, &log_buffer, &log_size);
|
||||
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)));
|
||||
if (image_path == NULL)
|
||||
break;
|
||||
archive_path = FileDialog(FALSE, NULL, &arch_ext, 0);
|
||||
archive_path = FileDialog(FALSE, NULL, &arch_ext, NULL);
|
||||
if (archive_path != NULL) {
|
||||
struct __stat64 stat64 = { 0 };
|
||||
_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";
|
||||
if (has_ffu_support)
|
||||
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),
|
||||
__VA_GROUP__(lmprintf(MSG_036)));
|
||||
image_path = FileDialog(FALSE, NULL, &img_ext, 0);
|
||||
__VA_GROUP__(lmprintf(MSG_280)));
|
||||
image_path = FileDialog(FALSE, NULL, &img_ext, NULL);
|
||||
if (image_path == NULL) {
|
||||
if (old_image_path != NULL) {
|
||||
// Reselect previous image
|
||||
|
@ -3556,6 +3556,7 @@ skip_args_processing:
|
|||
enable_extra_hashes = ReadSettingBool(SETTING_ENABLE_EXTRA_HASHES);
|
||||
ignore_boot_marker = ReadSettingBool(SETTING_IGNORE_BOOT_MARKER);
|
||||
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
|
||||
// settings, and is designed to work even if we add new options later.
|
||||
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 uint16_t GetSyslinuxVersion(char* buf, size_t buf_size, char** ext);
|
||||
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 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);
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 4.2.2068"
|
||||
CAPTION "Rufus 4.2.2069"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -392,8 +392,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,2,2068,0
|
||||
PRODUCTVERSION 4,2,2068,0
|
||||
FILEVERSION 4,2,2069,0
|
||||
PRODUCTVERSION 4,2,2069,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -411,13 +411,13 @@ BEGIN
|
|||
VALUE "Comments", "https://rufus.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "4.2.2068"
|
||||
VALUE "FileVersion", "4.2.2069"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
VALUE "OriginalFilename", "rufus-4.2.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "4.2.2068"
|
||||
VALUE "ProductVersion", "4.2.2069"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Rufus: The Reliable USB Formatting Utility
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -19,6 +19,7 @@
|
|||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include "rufus.h"
|
||||
#include "msapi_utf8.h"
|
||||
#include "registry.h"
|
||||
|
||||
#pragma once
|
||||
|
@ -52,6 +53,7 @@ extern char* ini_file;
|
|||
#define SETTING_USE_UDF_VERSION "UseUdfVersion"
|
||||
#define SETTING_USE_VDS "UseVds"
|
||||
#define SETTING_PERSISTENT_LOG "PersistentLog"
|
||||
#define SETTING_PREFERRED_SAVE_IMAGE_TYPE "PreferredSaveImageType"
|
||||
#define SETTING_PRESERVE_TIMESTAMPS "PreserveTimestamps"
|
||||
#define SETTING_VERBOSE_UPDATES "VerboseUpdateCheck"
|
||||
#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
|
||||
* 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;
|
||||
OPENFILENAMEA ofn;
|
||||
char selected_name[MAX_PATH];
|
||||
char *ext_string = NULL, *all_files = NULL;
|
||||
size_t i, j, ext_strlen;
|
||||
BOOL r;
|
||||
size_t i;
|
||||
char* filepath = NULL;
|
||||
HRESULT hr = FALSE;
|
||||
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))
|
||||
return NULL;
|
||||
dialog_showing++;
|
||||
|
||||
filter_spec = (COMDLG_FILTERSPEC*)calloc(ext->count + 1, sizeof(COMDLG_FILTERSPEC));
|
||||
if (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));
|
||||
if (filter_spec == NULL)
|
||||
return NULL;
|
||||
|
||||
hr = CoCreateInstance(save ? &CLSID_FileSaveDialog : &CLSID_FileOpenDialog, NULL, CLSCTX_INPROC,
|
||||
&IID_IFileDialog, (LPVOID)&pfd);
|
||||
dialog_showing++;
|
||||
|
||||
if (FAILED(hr)) {
|
||||
SetLastError(hr);
|
||||
uprintf("CoCreateInstance for FileOpenDialog failed: %s\n", WindowsErrorString());
|
||||
if (pfd != NULL) {
|
||||
IFileDialog_Release(pfd);
|
||||
pfd = NULL; // Just in case
|
||||
}
|
||||
goto fallback;
|
||||
}
|
||||
// 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));
|
||||
|
||||
// Set the file extension filters
|
||||
IFileDialog_SetFileTypes(pfd, (UINT)ext->count + 1, filter_spec);
|
||||
hr = CoCreateInstance(save ? &CLSID_FileSaveDialog : &CLSID_FileOpenDialog, NULL, CLSCTX_INPROC,
|
||||
&IID_IFileDialog, (LPVOID)&pfd);
|
||||
|
||||
if (path == NULL) {
|
||||
// Try to use the "Downloads" folder as the initial default directory
|
||||
const GUID download_dir_guid =
|
||||
{ 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);
|
||||
if (SUCCEEDED(hr)) {
|
||||
IFileDialog_SetDefaultFolder(pfd, si_path);
|
||||
}
|
||||
CoTaskMemFree(wpath);
|
||||
}
|
||||
} else {
|
||||
wpath = utf8_to_wchar(path);
|
||||
if (FAILED(hr)) {
|
||||
SetLastError(hr);
|
||||
uprintf("CoCreateInstance for FileOpenDialog failed: %s\n", WindowsErrorString());
|
||||
if (pfd != NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Set the file extension filters
|
||||
IFileDialog_SetFileTypes(pfd, (UINT)ext->count + 1, filter_spec);
|
||||
|
||||
if (path == NULL) {
|
||||
// Try to use the "Downloads" folder as the initial default directory
|
||||
const GUID download_dir_guid =
|
||||
{ 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);
|
||||
if (SUCCEEDED(hr)) {
|
||||
IFileDialog_SetFolder(pfd, si_path);
|
||||
IFileDialog_SetDefaultFolder(pfd, si_path);
|
||||
}
|
||||
safe_free(wpath);
|
||||
CoTaskMemFree(wpath);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
} else {
|
||||
wpath = utf8_to_wchar(path);
|
||||
hr = SHCreateItemFromParsingName(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path);
|
||||
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\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_SetFolder(pfd, si_path);
|
||||
}
|
||||
IFileDialog_Release(pfd);
|
||||
dialog_showing--;
|
||||
return filepath;
|
||||
safe_free(wpath);
|
||||
}
|
||||
|
||||
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);
|
||||
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));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = hMainDialog;
|
||||
// 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);
|
||||
out:
|
||||
if (pfd != NULL)
|
||||
IFileDialog_Release(pfd);
|
||||
dialog_showing--;
|
||||
return filepath;
|
||||
}
|
||||
|
@ -1700,7 +1635,7 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
|
|||
break;
|
||||
}
|
||||
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) {
|
||||
uprintf("Could not get save path");
|
||||
break;
|
||||
|
|
87
src/vhd.c
87
src/vhd.c
|
@ -29,6 +29,7 @@
|
|||
#include "vhd.h"
|
||||
#include "missing.h"
|
||||
#include "resource.h"
|
||||
#include "settings.h"
|
||||
#include "msapi_utf8.h"
|
||||
|
||||
#include "drive.h"
|
||||
|
@ -58,6 +59,7 @@ typedef struct {
|
|||
uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
|
||||
HANDLE wim_thread = NULL;
|
||||
extern int default_thread_priority;
|
||||
extern char* save_image_type;
|
||||
extern BOOL ignore_boot_marker, has_ffu_support;
|
||||
extern RUFUS_DRIVE rufus_drive[MAX_DRIVES];
|
||||
extern HANDLE format_thread;
|
||||
|
@ -1099,68 +1101,79 @@ static DWORD WINAPI FfuSaveImageThread(void* param)
|
|||
|
||||
void VhdSaveImage(void)
|
||||
{
|
||||
static IMG_SAVE img_save = { 0 };
|
||||
UINT i;
|
||||
static IMG_SAVE img_save;
|
||||
char filename[128];
|
||||
char path[MAX_PATH];
|
||||
int DriveIndex = ComboBox_GetCurSel(hDeviceList);
|
||||
EXT_DECL(img_ext, filename, __VA_GROUP__("*.vhdx", "*.vhd", "*.ffu"),
|
||||
__VA_GROUP__(lmprintf(MSG_342), lmprintf(MSG_343), lmprintf(MSG_344)));
|
||||
static EXT_DECL(img_ext, filename, __VA_GROUP__("*.vhd", "*.vhdx", "*.ffu"),
|
||||
__VA_GROUP__(lmprintf(MSG_343), lmprintf(MSG_342), lmprintf(MSG_344)));
|
||||
ULARGE_INTEGER free_space;
|
||||
|
||||
memset(&img_save, 0, sizeof(IMG_SAVE));
|
||||
if ((DriveIndex < 0) || (format_thread != NULL))
|
||||
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.DevicePath = GetPhysicalName(img_save.DeviceNum);
|
||||
// FFU support requires GPT
|
||||
if (!has_ffu_support || SelectedDrive.PartitionStyle != PARTITION_STYLE_GPT)
|
||||
img_ext.count = 2;
|
||||
img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0);
|
||||
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
|
||||
if (safe_strstr(img_save.ImagePath, ".vhdx") != NULL)
|
||||
for (i = 1; i <= (UINT)img_ext.count && (safe_strcmp(&_img_ext_x[i - 1][2], save_image_type) != 0); i++);
|
||||
if (i > (UINT)img_ext.count)
|
||||
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;
|
||||
else if (safe_strstr(img_save.ImagePath, ".ffu") != NULL)
|
||||
break;
|
||||
case 3:
|
||||
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.DeviceSize = SelectedDrive.DiskSize;
|
||||
if (img_save.DevicePath != NULL && img_save.ImagePath != NULL) {
|
||||
// Reset all progress bars
|
||||
SendMessage(hMainDialog, UM_PROGRESS_INIT, 0, 0);
|
||||
FormatStatus = 0;
|
||||
free_space.QuadPart = 0;
|
||||
if ((GetVolumePathNameA(img_save.ImagePath, path, sizeof(path)))
|
||||
&& (GetDiskFreeSpaceExA(path, &free_space, NULL, NULL))
|
||||
&& ((LONGLONG)free_space.QuadPart > (SelectedDrive.DiskSize + 512))) {
|
||||
// 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);
|
||||
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
|
||||
if (img_save.Type == VIRTUAL_STORAGE_TYPE_DEVICE_VHD) {
|
||||
free_space.QuadPart = 0;
|
||||
if ((GetVolumePathNameA(img_save.ImagePath, path, sizeof(path)))
|
||||
&& (GetDiskFreeSpaceExA(path, &free_space, NULL, NULL))
|
||||
&& ((LONGLONG)free_space.QuadPart < (SelectedDrive.DiskSize + 512))) {
|
||||
uprintf("The VHD size is too large for the target drive");
|
||||
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);
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (format_thread == NULL) {
|
||||
safe_free(img_save.DevicePath);
|
||||
safe_free(img_save.ImagePath);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue