mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[vhd] add write support for .vhdx and .ffu images
* Also move VHD mounting function calls from iso.c to vhd.c and remove unused VHD footer elements.
This commit is contained in:
parent
f411d526d6
commit
5bbcba8534
10 changed files with 226 additions and 223 deletions
40
src/format.c
40
src/format.c
|
@ -36,6 +36,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "rufus.h"
|
#include "rufus.h"
|
||||||
|
#include "format.h"
|
||||||
#include "missing.h"
|
#include "missing.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -73,7 +74,7 @@ extern const int nb_steps[FS_MAX];
|
||||||
extern uint32_t dur_mins, dur_secs;
|
extern uint32_t dur_mins, dur_secs;
|
||||||
extern uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
|
extern uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
|
||||||
extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, fast_zeroing, enable_file_indexing;
|
extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, fast_zeroing, enable_file_indexing;
|
||||||
extern BOOL write_as_image, use_vds, write_as_esp, is_vds_available;
|
extern BOOL write_as_image, use_vds, write_as_esp, is_vds_available, has_ffu_support;
|
||||||
uint8_t *grub2_buf = NULL, *sec_buf = NULL;
|
uint8_t *grub2_buf = NULL, *sec_buf = NULL;
|
||||||
long grub2_len;
|
long grub2_len;
|
||||||
|
|
||||||
|
@ -1154,6 +1155,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive)
|
||||||
int64_t bled_ret;
|
int64_t bled_ret;
|
||||||
uint8_t* buffer = NULL;
|
uint8_t* buffer = NULL;
|
||||||
uint32_t zero_data, *cmp_buffer = NULL;
|
uint32_t zero_data, *cmp_buffer = NULL;
|
||||||
|
char* vhd_path = NULL;
|
||||||
int throttle_fast_zeroing = 0, read_bufnum = 0, proc_bufnum = 1;
|
int throttle_fast_zeroing = 0, read_bufnum = 0, proc_bufnum = 1;
|
||||||
|
|
||||||
if (SelectedDrive.SectorSize < 512) {
|
if (SelectedDrive.SectorSize < 512) {
|
||||||
|
@ -1273,7 +1275,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive)
|
||||||
if (i > WRITE_RETRIES)
|
if (i > WRITE_RETRIES)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else if (img_report.compression_type != BLED_COMPRESSION_NONE) {
|
} else if (img_report.compression_type != BLED_COMPRESSION_NONE && img_report.compression_type < BLED_COMPRESSION_MAX) {
|
||||||
uprintf("Writing compressed image:");
|
uprintf("Writing compressed image:");
|
||||||
hSourceImage = CreateFileU(image_path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
hSourceImage = CreateFileU(image_path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
|
@ -1310,8 +1312,17 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hSourceImage = CreateFileAsync(image_path, GENERIC_READ, FILE_SHARE_READ,
|
assert(img_report.compression_type != IMG_COMPRESSION_FFU);
|
||||||
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN);
|
// VHD/VHDX require mounting the image first
|
||||||
|
if (img_report.compression_type == IMG_COMPRESSION_VHD ||
|
||||||
|
img_report.compression_type == IMG_COMPRESSION_VHDX) {
|
||||||
|
vhd_path = VhdMountImage(image_path);
|
||||||
|
if (vhd_path == NULL)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
hSourceImage = CreateFileAsync(vhd_path != NULL ? vhd_path : image_path, GENERIC_READ,
|
||||||
|
FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN);
|
||||||
if (hSourceImage == NULL) {
|
if (hSourceImage == NULL) {
|
||||||
uprintf("Could not open image '%s': %s", image_path, WindowsErrorString());
|
uprintf("Could not open image '%s': %s", image_path, WindowsErrorString());
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED;
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED;
|
||||||
|
@ -1397,10 +1408,12 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive)
|
||||||
RefreshDriveLayout(hPhysicalDrive);
|
RefreshDriveLayout(hPhysicalDrive);
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
out:
|
out:
|
||||||
if (img_report.compression_type != BLED_COMPRESSION_NONE)
|
if (img_report.compression_type != BLED_COMPRESSION_NONE && img_report.compression_type < BLED_COMPRESSION_MAX)
|
||||||
safe_closehandle(hSourceImage);
|
safe_closehandle(hSourceImage);
|
||||||
else
|
else
|
||||||
CloseFileAsync(hSourceImage);
|
CloseFileAsync(hSourceImage);
|
||||||
|
if (vhd_path != NULL)
|
||||||
|
VhdUnmountImage();
|
||||||
safe_mm_free(buffer);
|
safe_mm_free(buffer);
|
||||||
safe_mm_free(cmp_buffer);
|
safe_mm_free(cmp_buffer);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1627,7 +1640,24 @@ DWORD WINAPI FormatThread(void* param)
|
||||||
|
|
||||||
// Write an image file
|
// Write an image file
|
||||||
if ((boot_type == BT_IMAGE) && write_as_image) {
|
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;
|
||||||
|
// 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);
|
||||||
|
uprintf("Running command: '%s", cmd);
|
||||||
|
cr = RunCommandWithProgress(cmd, sysnative_dir, TRUE, MSG_261);
|
||||||
|
if (cr != 0 && !IS_ERROR(FormatStatus)) {
|
||||||
|
SetLastError(cr);
|
||||||
|
uprintf("Failed to apply FFU image: %s", WindowsErrorString());
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_WINDOWS) | SCODE_CODE(cr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
WriteDrive(hPhysicalDrive, FALSE);
|
WriteDrive(hPhysicalDrive, FALSE);
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Rufus: The Reliable USB Formatting Utility
|
* Rufus: The Reliable USB Formatting Utility
|
||||||
* Formatting function calls
|
* Formatting function calls
|
||||||
* Copyright © 2011-2020 Pete Batard <pete@akeo.ie>
|
* Copyright © 2011-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
|
||||||
|
@ -111,6 +111,10 @@ typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)(
|
||||||
ULONG CompressionFlags // FILE_SYSTEM_PROP_FLAG
|
ULONG CompressionFlags // FILE_SYSTEM_PROP_FLAG
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#define IMG_COMPRESSION_FFU (BLED_COMPRESSION_MAX)
|
||||||
|
#define IMG_COMPRESSION_VHD (BLED_COMPRESSION_MAX + 1)
|
||||||
|
#define IMG_COMPRESSION_VHDX (BLED_COMPRESSION_MAX + 2)
|
||||||
|
|
||||||
BOOL WritePBR(HANDLE hLogicalDrive);
|
BOOL WritePBR(HANDLE hLogicalDrive);
|
||||||
BOOL FormatLargeFAT32(DWORD DriveIndex, uint64_t PartitionOffset, DWORD ClusterSize, LPCSTR FSName, LPCSTR Label, DWORD Flags);
|
BOOL FormatLargeFAT32(DWORD DriveIndex, uint64_t PartitionOffset, DWORD ClusterSize, LPCSTR FSName, LPCSTR Label, DWORD Flags);
|
||||||
BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LPCSTR FSName, LPCSTR Label, DWORD Flags);
|
BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LPCSTR FSName, LPCSTR Label, DWORD Flags);
|
||||||
|
|
81
src/iso.c
81
src/iso.c
|
@ -1726,83 +1726,8 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VirtDisk API Prototypes since we can't use delay-loading because of MinGW
|
|
||||||
// See https://github.com/pbatard/rufus/issues/2272#issuecomment-1615976013
|
|
||||||
PF_TYPE_DECL(WINAPI, DWORD, OpenVirtualDisk, (PVIRTUAL_STORAGE_TYPE, PCWSTR,
|
|
||||||
VIRTUAL_DISK_ACCESS_MASK, OPEN_VIRTUAL_DISK_FLAG, POPEN_VIRTUAL_DISK_PARAMETERS, PHANDLE));
|
|
||||||
PF_TYPE_DECL(WINAPI, DWORD, AttachVirtualDisk, (HANDLE, PSECURITY_DESCRIPTOR,
|
|
||||||
ATTACH_VIRTUAL_DISK_FLAG, ULONG, PATTACH_VIRTUAL_DISK_PARAMETERS, LPOVERLAPPED));
|
|
||||||
PF_TYPE_DECL(WINAPI, DWORD, DetachVirtualDisk, (HANDLE, DETACH_VIRTUAL_DISK_FLAG, ULONG));
|
|
||||||
PF_TYPE_DECL(WINAPI, DWORD, GetVirtualDiskPhysicalPath, (HANDLE, PULONG, PWSTR));
|
|
||||||
|
|
||||||
static char physical_path[128] = "";
|
|
||||||
static HANDLE mounted_handle = INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
char* MountISO(const char* path)
|
|
||||||
{
|
|
||||||
VIRTUAL_STORAGE_TYPE vtype = { VIRTUAL_STORAGE_TYPE_DEVICE_ISO, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT };
|
|
||||||
ATTACH_VIRTUAL_DISK_PARAMETERS vparams = { 0 };
|
|
||||||
DWORD r;
|
|
||||||
wchar_t wtmp[128];
|
|
||||||
ULONG size = ARRAYSIZE(wtmp);
|
|
||||||
wconvert(path);
|
|
||||||
char* ret = NULL;
|
|
||||||
|
|
||||||
PF_INIT_OR_OUT(OpenVirtualDisk, VirtDisk);
|
|
||||||
PF_INIT_OR_OUT(AttachVirtualDisk, VirtDisk);
|
|
||||||
PF_INIT_OR_OUT(GetVirtualDiskPhysicalPath, VirtDisk);
|
|
||||||
|
|
||||||
if ((mounted_handle != NULL) && (mounted_handle != INVALID_HANDLE_VALUE))
|
|
||||||
UnMountISO();
|
|
||||||
|
|
||||||
r = pfOpenVirtualDisk(&vtype, wpath, VIRTUAL_DISK_ACCESS_READ | VIRTUAL_DISK_ACCESS_GET_INFO,
|
|
||||||
OPEN_VIRTUAL_DISK_FLAG_NONE, NULL, &mounted_handle);
|
|
||||||
if (r != ERROR_SUCCESS) {
|
|
||||||
SetLastError(r);
|
|
||||||
uprintf("Could not open ISO '%s': %s", path, WindowsErrorString());
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
vparams.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
|
|
||||||
r = pfAttachVirtualDisk(mounted_handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY |
|
|
||||||
ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER, 0, &vparams, NULL);
|
|
||||||
if (r != ERROR_SUCCESS) {
|
|
||||||
SetLastError(r);
|
|
||||||
uprintf("Could not mount ISO '%s': %s", path, WindowsErrorString());
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = pfGetVirtualDiskPhysicalPath(mounted_handle, &size, wtmp);
|
|
||||||
if (r != ERROR_SUCCESS) {
|
|
||||||
SetLastError(r);
|
|
||||||
uprintf("Could not obtain physical path for mounted ISO '%s': %s", path, WindowsErrorString());
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
wchar_to_utf8_no_alloc(wtmp, physical_path, sizeof(physical_path));
|
|
||||||
ret = physical_path;
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (ret == NULL)
|
|
||||||
UnMountISO();
|
|
||||||
wfree(path);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnMountISO(void)
|
|
||||||
{
|
|
||||||
PF_INIT_OR_OUT(DetachVirtualDisk, VirtDisk);
|
|
||||||
|
|
||||||
if ((mounted_handle == NULL) || (mounted_handle == INVALID_HANDLE_VALUE))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
pfDetachVirtualDisk(mounted_handle, DETACH_VIRTUAL_DISK_FLAG_NONE, 0);
|
|
||||||
safe_closehandle(mounted_handle);
|
|
||||||
out:
|
|
||||||
physical_path[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: If we can't get save to ISO from virtdisk, we might as well drop this
|
// TODO: If we can't get save to ISO from virtdisk, we might as well drop this
|
||||||
static DWORD WINAPI SaveISOThread(void* param)
|
static DWORD WINAPI IsoSaveImageThread(void* param)
|
||||||
{
|
{
|
||||||
BOOL s;
|
BOOL s;
|
||||||
DWORD rSize, wSize;
|
DWORD rSize, wSize;
|
||||||
|
@ -1908,7 +1833,7 @@ out:
|
||||||
ExitThread(0);
|
ExitThread(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveISO(void)
|
void IsoSaveImage(void)
|
||||||
{
|
{
|
||||||
static IMG_SAVE img_save = { 0 };
|
static IMG_SAVE img_save = { 0 };
|
||||||
char filename[33] = "disc_image.iso";
|
char filename[33] = "disc_image.iso";
|
||||||
|
@ -1939,7 +1864,7 @@ void SaveISO(void)
|
||||||
// Disable all controls except cancel
|
// Disable all controls except cancel
|
||||||
EnableControls(FALSE, FALSE);
|
EnableControls(FALSE, FALSE);
|
||||||
InitProgress(TRUE);
|
InitProgress(TRUE);
|
||||||
format_thread = CreateThread(NULL, 0, SaveISOThread, &img_save, 0, NULL);
|
format_thread = CreateThread(NULL, 0, IsoSaveImageThread, &img_save, 0, NULL);
|
||||||
if (format_thread != NULL) {
|
if (format_thread != NULL) {
|
||||||
uprintf("\r\nSave to ISO operation started");
|
uprintf("\r\nSave to ISO operation started");
|
||||||
PrintInfo(0, -1);
|
PrintInfo(0, -1);
|
||||||
|
|
14
src/rufus.c
14
src/rufus.c
|
@ -128,7 +128,7 @@ BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fa
|
||||||
BOOL usb_debug, use_fake_units, preserve_timestamps = FALSE, fast_zeroing = FALSE, app_changed_size = FALSE;
|
BOOL usb_debug, use_fake_units, preserve_timestamps = FALSE, fast_zeroing = FALSE, app_changed_size = FALSE;
|
||||||
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE;
|
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE;
|
||||||
BOOL write_as_image = FALSE, write_as_esp = FALSE, use_vds = FALSE, ignore_boot_marker = FALSE;
|
BOOL write_as_image = FALSE, write_as_esp = FALSE, use_vds = FALSE, ignore_boot_marker = FALSE;
|
||||||
BOOL appstore_version = FALSE, is_vds_available = TRUE, persistent_log = FALSE;
|
BOOL appstore_version = FALSE, is_vds_available = TRUE, persistent_log = FALSE, has_ffu_support = FALSE;
|
||||||
float fScale = 1.0f;
|
float fScale = 1.0f;
|
||||||
int dialog_showing = 0, selection_default = BT_IMAGE, persistence_unit_selection = -1, imop_win_sel = 0;
|
int dialog_showing = 0, selection_default = BT_IMAGE, persistence_unit_selection = -1, imop_win_sel = 0;
|
||||||
int default_fs, fs_type, boot_type, partition_type, target_type;
|
int default_fs, fs_type, boot_type, partition_type, target_type;
|
||||||
|
@ -2588,8 +2588,11 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
img_provided = FALSE; // One off thing...
|
img_provided = FALSE; // One off thing...
|
||||||
} else {
|
} else {
|
||||||
char* old_image_path = image_path;
|
char* old_image_path = image_path;
|
||||||
|
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_036) would be called on each message...
|
||||||
EXT_DECL(img_ext, NULL, __VA_GROUP__("*.iso;*.img;*.vhd;*.usb;*.bz2;*.bzip2;*.gz;*.lzma;*.xz;*.Z;*.zip;*.wim;*.esd;*.vtsi"),
|
EXT_DECL(img_ext, NULL, __VA_GROUP__(extensions),
|
||||||
__VA_GROUP__(lmprintf(MSG_036)));
|
__VA_GROUP__(lmprintf(MSG_036)));
|
||||||
image_path = FileDialog(FALSE, NULL, &img_ext, 0);
|
image_path = FileDialog(FALSE, NULL, &img_ext, 0);
|
||||||
if (image_path == NULL) {
|
if (image_path == NULL) {
|
||||||
|
@ -2684,7 +2687,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDC_SAVE:
|
case IDC_SAVE:
|
||||||
SaveVHD();
|
VhdSaveImage();
|
||||||
break;
|
break;
|
||||||
case IDM_SELECT:
|
case IDM_SELECT:
|
||||||
case IDM_DOWNLOAD:
|
case IDM_DOWNLOAD:
|
||||||
|
@ -3695,6 +3698,9 @@ skip_args_processing:
|
||||||
// Detect CPU acceleration for SHA-1/SHA-256
|
// Detect CPU acceleration for SHA-1/SHA-256
|
||||||
cpu_has_sha1_accel = DetectSHA1Acceleration();
|
cpu_has_sha1_accel = DetectSHA1Acceleration();
|
||||||
cpu_has_sha256_accel = DetectSHA256Acceleration();
|
cpu_has_sha256_accel = DetectSHA256Acceleration();
|
||||||
|
// FFU support started with Windows 10 1709 (through FfuProvider.dll)
|
||||||
|
static_sprintf(tmp_path, "%s\\dism\\FfuProvider.dll", sysnative_dir);
|
||||||
|
has_ffu_support = (_accessU(tmp_path, 0) == 0);
|
||||||
|
|
||||||
relaunch:
|
relaunch:
|
||||||
ubprintf("Localization set to '%s'", selected_locale->txt[0]);
|
ubprintf("Localization set to '%s'", selected_locale->txt[0]);
|
||||||
|
@ -3964,7 +3970,7 @@ extern int TestHashes(void);
|
||||||
}
|
}
|
||||||
// Alt-O => Save from Optical drive to ISO
|
// Alt-O => Save from Optical drive to ISO
|
||||||
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'O')) {
|
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'O')) {
|
||||||
SaveISO();
|
IsoSaveImage();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Alt-P => Toggle GPT ESP to and from Basic Data type (Windows 10 or later)
|
// Alt-P => Toggle GPT ESP to and from Basic Data type (Windows 10 or later)
|
||||||
|
|
|
@ -652,8 +652,6 @@ extern int64_t ExtractISOFile(const char* iso, const char* iso_file, const char*
|
||||||
extern BOOL CopySKUSiPolicy(const char* drive_name);
|
extern BOOL CopySKUSiPolicy(const char* drive_name);
|
||||||
extern BOOL HasEfiImgBootLoaders(void);
|
extern BOOL HasEfiImgBootLoaders(void);
|
||||||
extern BOOL DumpFatDir(const char* path, int32_t cluster);
|
extern BOOL DumpFatDir(const char* path, int32_t cluster);
|
||||||
extern char* MountISO(const char* path);
|
|
||||||
extern void UnMountISO(void);
|
|
||||||
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);
|
||||||
|
|
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.2067"
|
CAPTION "Rufus 4.2.2068"
|
||||||
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,2067,0
|
FILEVERSION 4,2,2068,0
|
||||||
PRODUCTVERSION 4,2,2067,0
|
PRODUCTVERSION 4,2,2068,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.2067"
|
VALUE "FileVersion", "4.2.2068"
|
||||||
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.2067"
|
VALUE "ProductVersion", "4.2.2068"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -1235,7 +1235,7 @@ uint32_t ResolveDllAddress(dll_resolver_t* resolver)
|
||||||
// Check settings to see if we have existing data for these DLL calls.
|
// Check settings to see if we have existing data for these DLL calls.
|
||||||
for (i = 0; i < resolver->count; i++) {
|
for (i = 0; i < resolver->count; i++) {
|
||||||
static_sprintf(saved_id, "%s@%s%x:%s", _filenameU(resolver->path),
|
static_sprintf(saved_id, "%s@%s%x:%s", _filenameU(resolver->path),
|
||||||
GuidToString(&info->Guid, FALSE), info->Age, resolver->name[i]);
|
GuidToString(&info->Guid, FALSE), (int)info->Age, resolver->name[i]);
|
||||||
resolver->address[i] = ReadSetting32(saved_id);
|
resolver->address[i] = ReadSetting32(saved_id);
|
||||||
if (resolver->address[i] == 0)
|
if (resolver->address[i] == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -1253,7 +1253,7 @@ uint32_t ResolveDllAddress(dll_resolver_t* resolver)
|
||||||
goto out;
|
goto out;
|
||||||
static_sprintf(path, "%s\\%s", temp_dir, info->PdbName);
|
static_sprintf(path, "%s\\%s", temp_dir, info->PdbName);
|
||||||
static_sprintf(url, "http://msdl.microsoft.com/download/symbols/%s/%s%x/%s",
|
static_sprintf(url, "http://msdl.microsoft.com/download/symbols/%s/%s%x/%s",
|
||||||
info->PdbName, GuidToString(&info->Guid, FALSE), info->Age, info->PdbName);
|
info->PdbName, GuidToString(&info->Guid, FALSE), (int)info->Age, info->PdbName);
|
||||||
if (DownloadToFileOrBufferEx(url, path, SYMBOL_SERVER_USER_AGENT, NULL, hMainDialog, FALSE) < 200 * KB)
|
if (DownloadToFileOrBufferEx(url, path, SYMBOL_SERVER_USER_AGENT, NULL, hMainDialog, FALSE) < 200 * KB)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1280,7 +1280,7 @@ uint32_t ResolveDllAddress(dll_resolver_t* resolver)
|
||||||
r = 0;
|
r = 0;
|
||||||
for (i = 0; i < resolver->count; i++) {
|
for (i = 0; i < resolver->count; i++) {
|
||||||
static_sprintf(saved_id, "%s@%s%x:%s", _filenameU(resolver->path),
|
static_sprintf(saved_id, "%s@%s%x:%s", _filenameU(resolver->path),
|
||||||
GuidToString(&info->Guid, FALSE), info->Age, resolver->name[i]);
|
GuidToString(&info->Guid, FALSE), (int)info->Age, resolver->name[i]);
|
||||||
if (resolver->address[i] != 0) {
|
if (resolver->address[i] != 0) {
|
||||||
WriteSetting32(saved_id, resolver->address[i]);
|
WriteSetting32(saved_id, resolver->address[i]);
|
||||||
r++;
|
r++;
|
||||||
|
|
207
src/vhd.c
207
src/vhd.c
|
@ -58,7 +58,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 BOOL ignore_boot_marker;
|
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;
|
||||||
|
|
||||||
|
@ -67,7 +67,6 @@ static uint32_t progress_report_mask;
|
||||||
static uint64_t progress_offset = 0, progress_total = 100;
|
static uint64_t progress_offset = 0, progress_total = 100;
|
||||||
static wchar_t wmount_path[MAX_PATH] = { 0 }, wmount_track[MAX_PATH] = { 0 };
|
static wchar_t wmount_path[MAX_PATH] = { 0 }, wmount_track[MAX_PATH] = { 0 };
|
||||||
static char sevenzip_path[MAX_PATH];
|
static char sevenzip_path[MAX_PATH];
|
||||||
static const char conectix_str[] = VHD_FOOTER_COOKIE;
|
|
||||||
static BOOL count_files;
|
static BOOL count_files;
|
||||||
static int progress_op = OP_FILE_COPY, progress_msg = MSG_267;
|
static int progress_op = OP_FILE_COPY, progress_msg = MSG_267;
|
||||||
|
|
||||||
|
@ -83,7 +82,7 @@ static BOOL Get7ZipPath(void)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* ext;
|
const char* ext;
|
||||||
bled_compression_type type;
|
uint8_t type;
|
||||||
} comp_assoc;
|
} comp_assoc;
|
||||||
|
|
||||||
static comp_assoc file_assoc[] = {
|
static comp_assoc file_assoc[] = {
|
||||||
|
@ -94,33 +93,75 @@ static comp_assoc file_assoc[] = {
|
||||||
{ ".bz2", BLED_COMPRESSION_BZIP2 },
|
{ ".bz2", BLED_COMPRESSION_BZIP2 },
|
||||||
{ ".xz", BLED_COMPRESSION_XZ },
|
{ ".xz", BLED_COMPRESSION_XZ },
|
||||||
{ ".vtsi", BLED_COMPRESSION_VTSI },
|
{ ".vtsi", BLED_COMPRESSION_VTSI },
|
||||||
|
{ ".ffu", BLED_COMPRESSION_MAX },
|
||||||
|
{ ".vhd", BLED_COMPRESSION_MAX + 1 },
|
||||||
|
{ ".vhdx", BLED_COMPRESSION_MAX + 2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
// For now we consider that an image that matches a known extension is bootable
|
// Look for a boot marker in the MBR area of the image
|
||||||
static BOOL IsCompressedBootableImage(const char* path)
|
static BOOL IsCompressedBootableImage(const char* path)
|
||||||
{
|
{
|
||||||
char *p;
|
char *ext = NULL, *physical_disk = NULL;
|
||||||
unsigned char *buf = NULL;
|
unsigned char *buf = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
FILE* fd = NULL;
|
||||||
BOOL r = FALSE;
|
BOOL r = FALSE;
|
||||||
int64_t dc;
|
int64_t dc = 0;
|
||||||
|
|
||||||
img_report.compression_type = BLED_COMPRESSION_NONE;
|
img_report.compression_type = BLED_COMPRESSION_NONE;
|
||||||
for (p = (char*)&path[strlen(path)-1]; (*p != '.') && (p != path); p--);
|
if (safe_strlen(path) > 4)
|
||||||
|
for (ext = (char*)&path[safe_strlen(path) - 1]; (*ext != '.') && (ext != path); ext--);
|
||||||
if (p == path)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAYSIZE(file_assoc); i++) {
|
for (i = 0; i < ARRAYSIZE(file_assoc); i++) {
|
||||||
if (strcmp(p, file_assoc[i].ext) == 0) {
|
if (safe_stricmp(ext, file_assoc[i].ext) == 0) {
|
||||||
img_report.compression_type = file_assoc[i].type;
|
img_report.compression_type = file_assoc[i].type;
|
||||||
buf = malloc(MBR_SIZE);
|
buf = malloc(MBR_SIZE);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
FormatStatus = 0;
|
FormatStatus = 0;
|
||||||
|
if (img_report.compression_type < BLED_COMPRESSION_MAX) {
|
||||||
bled_init(0, uprintf, NULL, NULL, NULL, NULL, &FormatStatus);
|
bled_init(0, uprintf, NULL, NULL, NULL, NULL, &FormatStatus);
|
||||||
dc = bled_uncompress_to_buffer(path, (char*)buf, MBR_SIZE, file_assoc[i].type);
|
dc = bled_uncompress_to_buffer(path, (char*)buf, MBR_SIZE, file_assoc[i].type);
|
||||||
bled_exit();
|
bled_exit();
|
||||||
|
} else if (img_report.compression_type == BLED_COMPRESSION_MAX) {
|
||||||
|
// Dism, through FfuProvider.dll, can mount a .ffu as a physicaldrive, which we
|
||||||
|
// could then use to poke the MBR as we do for VHD... Except Microsoft did design
|
||||||
|
// dism to FAIL AND EXIT, after mounting the ffu as a virtual drive, if it doesn't
|
||||||
|
// find something that looks like Windows at the specified image index... which it
|
||||||
|
// usually won't in our case. So, curse Microsoft and their incredible short-
|
||||||
|
// sightedness (or, most likely in this case, intentional malice, by BREACHING the
|
||||||
|
// OS contract to keep useful disk APIs for their usage, and their usage only).
|
||||||
|
// Then again, considering that .ffu's are GPT based, the marker should always be
|
||||||
|
// present, so just check for the FFU signature and pretend there's a marker then.
|
||||||
|
if (has_ffu_support) {
|
||||||
|
fd = fopenU(path, "rb");
|
||||||
|
if (fd != NULL) {
|
||||||
|
dc = fread(buf, 1, MBR_SIZE, fd);
|
||||||
|
fclose(fd);
|
||||||
|
// The signature may not be constant, but since the only game in town to
|
||||||
|
// create FFU is dism, and dism appears to use "SignedImage " always,.we
|
||||||
|
// might as well use this to our advantage.
|
||||||
|
if (strncmp(&buf[4], "SignedImage ", 12) == 0) {
|
||||||
|
// At this stage, the buffer is only used for marker validation.
|
||||||
|
buf[0x1FE] = 0x55;
|
||||||
|
buf[0x1FF] = 0xAA;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
uprintf("Could not open %s: %d", path, errno);
|
||||||
|
} else {
|
||||||
|
uprintf(" An FFU image was selected, but this system does not have FFU support!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
physical_disk = VhdMountImage(path);
|
||||||
|
if (physical_disk != NULL) {
|
||||||
|
fd = fopenU(physical_disk, "rb");
|
||||||
|
if (fd != NULL) {
|
||||||
|
dc = fread(buf, 1, MBR_SIZE, fd);
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VhdUnmountImage();
|
||||||
|
}
|
||||||
if (dc != MBR_SIZE) {
|
if (dc != MBR_SIZE) {
|
||||||
free(buf);
|
free(buf);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -139,10 +180,7 @@ int8_t IsBootableImage(const char* path)
|
||||||
{
|
{
|
||||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||||
LARGE_INTEGER liImageSize;
|
LARGE_INTEGER liImageSize;
|
||||||
vhd_footer* footer = NULL;
|
|
||||||
DWORD size;
|
DWORD size;
|
||||||
size_t i;
|
|
||||||
uint32_t checksum, old_checksum;
|
|
||||||
uint64_t wim_magic = 0;
|
uint64_t wim_magic = 0;
|
||||||
LARGE_INTEGER ptr = { 0 };
|
LARGE_INTEGER ptr = { 0 };
|
||||||
int8_t is_bootable_img;
|
int8_t is_bootable_img;
|
||||||
|
@ -171,40 +209,7 @@ int8_t IsBootableImage(const char* path)
|
||||||
if (img_report.is_windows_img)
|
if (img_report.is_windows_img)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
size = sizeof(vhd_footer);
|
|
||||||
if ((img_report.compression_type == BLED_COMPRESSION_NONE) && (img_report.image_size >= (512 + size))) {
|
|
||||||
footer = (vhd_footer*)malloc(size);
|
|
||||||
ptr.QuadPart = img_report.image_size - size;
|
|
||||||
if ( (footer == NULL) || (!SetFilePointerEx(handle, ptr, NULL, FILE_BEGIN)) ||
|
|
||||||
(!ReadFile(handle, footer, size, &size, NULL)) || (size != sizeof(vhd_footer)) ) {
|
|
||||||
uprintf(" Could not read VHD footer");
|
|
||||||
is_bootable_img = -3;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (memcmp(footer->cookie, conectix_str, sizeof(footer->cookie)) == 0) {
|
|
||||||
img_report.image_size -= sizeof(vhd_footer);
|
|
||||||
if ( (bswap_uint32(footer->file_format_version) != VHD_FOOTER_FILE_FORMAT_V1_0)
|
|
||||||
|| (bswap_uint32(footer->disk_type) != VHD_FOOTER_TYPE_FIXED_HARD_DISK)) {
|
|
||||||
uprintf(" Unsupported type of VHD image");
|
|
||||||
is_bootable_img = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
// Might as well validate the checksum while we're at it
|
|
||||||
old_checksum = bswap_uint32(footer->checksum);
|
|
||||||
footer->checksum = 0;
|
|
||||||
for (checksum = 0, i = 0; i < sizeof(vhd_footer); i++)
|
|
||||||
checksum += ((uint8_t*)footer)[i];
|
|
||||||
checksum = ~checksum;
|
|
||||||
if (checksum != old_checksum)
|
|
||||||
uprintf(" Warning: VHD footer seems corrupted (checksum: %04X, expected: %04X)", old_checksum, checksum);
|
|
||||||
// Need to remove the footer from our payload
|
|
||||||
uprintf(" Image is a Fixed Hard Disk VHD file");
|
|
||||||
img_report.is_vhd = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
safe_free(footer);
|
|
||||||
safe_closehandle(handle);
|
safe_closehandle(handle);
|
||||||
return is_bootable_img;
|
return is_bootable_img;
|
||||||
}
|
}
|
||||||
|
@ -405,7 +410,7 @@ char* WimMountImage(const char* image, int index)
|
||||||
mp.index = index;
|
mp.index = index;
|
||||||
|
|
||||||
// Try to unmount an existing stale image, if there is any
|
// Try to unmount an existing stale image, if there is any
|
||||||
mount_path = GetExistingMountPoint(image, index);
|
mount_path = WimGetExistingMountPoint(image, index);
|
||||||
if (mount_path != NULL) {
|
if (mount_path != NULL) {
|
||||||
uprintf("WARNING: Found stale '%s [%d]' image mounted on '%s' - Attempting to unmount it...",
|
uprintf("WARNING: Found stale '%s [%d]' image mounted on '%s' - Attempting to unmount it...",
|
||||||
image, index, mount_path);
|
image, index, mount_path);
|
||||||
|
@ -499,7 +504,7 @@ BOOL WimUnmountImage(const char* image, int index, BOOL commit)
|
||||||
// This basically parses HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WIMMount\Mounted Images
|
// This basically parses HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WIMMount\Mounted Images
|
||||||
// to see if an instance exists with the image/index passed as parameter and returns
|
// to see if an instance exists with the image/index passed as parameter and returns
|
||||||
// the mount point of this image if found, or NULL otherwise.
|
// the mount point of this image if found, or NULL otherwise.
|
||||||
char* GetExistingMountPoint(const char* image, int index)
|
char* WimGetExistingMountPoint(const char* image, int index)
|
||||||
{
|
{
|
||||||
static char path[MAX_PATH];
|
static char path[MAX_PATH];
|
||||||
char class[MAX_PATH] = "", guid[40], key_name[MAX_PATH];
|
char class[MAX_PATH] = "", guid[40], key_name[MAX_PATH];
|
||||||
|
@ -886,17 +891,102 @@ BOOL WimApplyImage(const char* image, int index, const char* dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VirtDisk API Prototypes since we can't use delay-loading because of MinGW
|
// VirtDisk API Prototypes since we can't use delay-loading because of MinGW
|
||||||
|
// See https://github.com/pbatard/rufus/issues/2272#issuecomment-1615976013
|
||||||
PF_TYPE_DECL(WINAPI, DWORD, CreateVirtualDisk, (PVIRTUAL_STORAGE_TYPE, PCWSTR,
|
PF_TYPE_DECL(WINAPI, DWORD, CreateVirtualDisk, (PVIRTUAL_STORAGE_TYPE, PCWSTR,
|
||||||
VIRTUAL_DISK_ACCESS_MASK, PSECURITY_DESCRIPTOR, CREATE_VIRTUAL_DISK_FLAG, ULONG,
|
VIRTUAL_DISK_ACCESS_MASK, PSECURITY_DESCRIPTOR, CREATE_VIRTUAL_DISK_FLAG, ULONG,
|
||||||
PCREATE_VIRTUAL_DISK_PARAMETERS, LPOVERLAPPED, PHANDLE));
|
PCREATE_VIRTUAL_DISK_PARAMETERS, LPOVERLAPPED, PHANDLE));
|
||||||
|
PF_TYPE_DECL(WINAPI, DWORD, OpenVirtualDisk, (PVIRTUAL_STORAGE_TYPE, PCWSTR,
|
||||||
|
VIRTUAL_DISK_ACCESS_MASK, OPEN_VIRTUAL_DISK_FLAG, POPEN_VIRTUAL_DISK_PARAMETERS, PHANDLE));
|
||||||
|
PF_TYPE_DECL(WINAPI, DWORD, AttachVirtualDisk, (HANDLE, PSECURITY_DESCRIPTOR,
|
||||||
|
ATTACH_VIRTUAL_DISK_FLAG, ULONG, PATTACH_VIRTUAL_DISK_PARAMETERS, LPOVERLAPPED));
|
||||||
|
PF_TYPE_DECL(WINAPI, DWORD, DetachVirtualDisk, (HANDLE, DETACH_VIRTUAL_DISK_FLAG, ULONG));
|
||||||
|
PF_TYPE_DECL(WINAPI, DWORD, GetVirtualDiskPhysicalPath, (HANDLE, PULONG, PWSTR));
|
||||||
PF_TYPE_DECL(WINAPI, DWORD, GetVirtualDiskOperationProgress, (HANDLE, LPOVERLAPPED,
|
PF_TYPE_DECL(WINAPI, DWORD, GetVirtualDiskOperationProgress, (HANDLE, LPOVERLAPPED,
|
||||||
PVIRTUAL_DISK_PROGRESS));
|
PVIRTUAL_DISK_PROGRESS));
|
||||||
|
|
||||||
|
static char physical_path[128] = "";
|
||||||
|
static HANDLE mounted_handle = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
// Mount an ISO or a VHD/VHDX image
|
||||||
|
// Returns the physical path of the mounted image or NULL on error.
|
||||||
|
char* VhdMountImage(const char* path)
|
||||||
|
{
|
||||||
|
VIRTUAL_STORAGE_TYPE vtype = { VIRTUAL_STORAGE_TYPE_DEVICE_ISO, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT };
|
||||||
|
ATTACH_VIRTUAL_DISK_PARAMETERS vparams = { 0 };
|
||||||
|
DWORD r;
|
||||||
|
wchar_t wtmp[128];
|
||||||
|
ULONG size = ARRAYSIZE(wtmp);
|
||||||
|
wconvert(path);
|
||||||
|
char *ret = NULL, *ext = NULL;
|
||||||
|
|
||||||
|
PF_INIT_OR_OUT(OpenVirtualDisk, VirtDisk);
|
||||||
|
PF_INIT_OR_OUT(AttachVirtualDisk, VirtDisk);
|
||||||
|
PF_INIT_OR_OUT(GetVirtualDiskPhysicalPath, VirtDisk);
|
||||||
|
|
||||||
|
if (wpath == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((mounted_handle != NULL) && (mounted_handle != INVALID_HANDLE_VALUE))
|
||||||
|
VhdUnmountImage();
|
||||||
|
|
||||||
|
if (safe_strlen(path) > 4)
|
||||||
|
for (ext = (char*)&path[safe_strlen(path) - 1]; (*ext != '.') && (ext != path); ext--);
|
||||||
|
if (safe_stricmp(ext, ".vhdx") == 0)
|
||||||
|
vtype.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_VHDX;
|
||||||
|
else if (safe_stricmp(ext, ".vhdx") == 0)
|
||||||
|
vtype.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
|
||||||
|
|
||||||
|
r = pfOpenVirtualDisk(&vtype, wpath, VIRTUAL_DISK_ACCESS_READ | VIRTUAL_DISK_ACCESS_GET_INFO,
|
||||||
|
OPEN_VIRTUAL_DISK_FLAG_NONE, NULL, &mounted_handle);
|
||||||
|
if (r != ERROR_SUCCESS) {
|
||||||
|
SetLastError(r);
|
||||||
|
uprintf("Could not open image '%s': %s", path, WindowsErrorString());
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
vparams.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
|
||||||
|
r = pfAttachVirtualDisk(mounted_handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY |
|
||||||
|
ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER, 0, &vparams, NULL);
|
||||||
|
if (r != ERROR_SUCCESS) {
|
||||||
|
SetLastError(r);
|
||||||
|
uprintf("Could not mount image '%s': %s", path, WindowsErrorString());
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = pfGetVirtualDiskPhysicalPath(mounted_handle, &size, wtmp);
|
||||||
|
if (r != ERROR_SUCCESS) {
|
||||||
|
SetLastError(r);
|
||||||
|
uprintf("Could not obtain physical path for mounted image '%s': %s", path, WindowsErrorString());
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
wchar_to_utf8_no_alloc(wtmp, physical_path, sizeof(physical_path));
|
||||||
|
ret = physical_path;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (ret == NULL)
|
||||||
|
VhdUnmountImage();
|
||||||
|
wfree(path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VhdUnmountImage(void)
|
||||||
|
{
|
||||||
|
PF_INIT_OR_OUT(DetachVirtualDisk, VirtDisk);
|
||||||
|
|
||||||
|
if ((mounted_handle == NULL) || (mounted_handle == INVALID_HANDLE_VALUE))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
pfDetachVirtualDisk(mounted_handle, DETACH_VIRTUAL_DISK_FLAG_NONE, 0);
|
||||||
|
safe_closehandle(mounted_handle);
|
||||||
|
out:
|
||||||
|
physical_path[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Since we no longer have to deal with Windows 7, we can call on CreateVirtualDisk()
|
// Since we no longer have to deal with Windows 7, we can call on CreateVirtualDisk()
|
||||||
// to backup a physical disk to VHD/VHDX. Now if this could also be used to create an
|
// to backup a physical disk to VHD/VHDX. Now if this could also be used to create an
|
||||||
// ISO from optical media that would be swell, but no matter what I tried, it didn't
|
// ISO from optical media that would be swell, but no matter what I tried, it didn't
|
||||||
// seem possible...
|
// seem possible...
|
||||||
static DWORD WINAPI SaveVHDThread(void* param)
|
static DWORD WINAPI VhdSaveImageThread(void* param)
|
||||||
{
|
{
|
||||||
IMG_SAVE* img_save = (IMG_SAVE*)param;
|
IMG_SAVE* img_save = (IMG_SAVE*)param;
|
||||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||||
|
@ -984,21 +1074,21 @@ out:
|
||||||
// calls, as well as how to properly hook into the DLL for every arch/every release
|
// calls, as well as how to properly hook into the DLL for every arch/every release
|
||||||
// of Windows, would be a massive timesink, we just take a shortcut by calling dism
|
// of Windows, would be a massive timesink, we just take a shortcut by calling dism
|
||||||
// directly, as imperfect as such a solution might be...
|
// directly, as imperfect as such a solution might be...
|
||||||
static DWORD WINAPI SaveFFUThread(void* param)
|
static DWORD WINAPI FfuSaveImageThread(void* param)
|
||||||
{
|
{
|
||||||
DWORD r;
|
DWORD r;
|
||||||
IMG_SAVE* img_save = (IMG_SAVE*)param;
|
IMG_SAVE* img_save = (IMG_SAVE*)param;
|
||||||
char cmd[MAX_PATH + 128], *letter = "", *label;
|
char cmd[MAX_PATH + 128], *letter = "", *label;
|
||||||
|
|
||||||
GetDriveLabel(SelectedDrive.DeviceNumber, letter, &label, TRUE);
|
GetDriveLabel(SelectedDrive.DeviceNumber, letter, &label, TRUE);
|
||||||
static_sprintf(cmd, "dism /capture-ffu /capturedrive=%s /imagefile=\"%s\" "
|
static_sprintf(cmd, "dism /Capture-Ffu /CaptureDrive:%s /ImageFile:\"%s\" "
|
||||||
"/name:\"%s\" /description:\"Created by %s (%s)\"",
|
"/Name:\"%s\" /Description:\"Created by %s (%s)\"",
|
||||||
img_save->DevicePath, img_save->ImagePath, label, APPLICATION_NAME, RUFUS_URL);
|
img_save->DevicePath, img_save->ImagePath, label, APPLICATION_NAME, RUFUS_URL);
|
||||||
uprintf("Running command: '%s", cmd);
|
uprintf("Running command: '%s", cmd);
|
||||||
r = RunCommandWithProgress(cmd, sysnative_dir, TRUE, MSG_261);
|
r = RunCommandWithProgress(cmd, sysnative_dir, TRUE, MSG_261);
|
||||||
if (r != 0 && !IS_ERROR(FormatStatus)) {
|
if (r != 0 && !IS_ERROR(FormatStatus)) {
|
||||||
SetLastError(r);
|
SetLastError(r);
|
||||||
uprintf("Failed to create FFU image: %s", WindowsErrorString());
|
uprintf("Failed to capture FFU image: %s", WindowsErrorString());
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_WINDOWS) | SCODE_CODE(r);
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_WINDOWS) | SCODE_CODE(r);
|
||||||
}
|
}
|
||||||
safe_free(img_save->DevicePath);
|
safe_free(img_save->DevicePath);
|
||||||
|
@ -1007,7 +1097,7 @@ static DWORD WINAPI SaveFFUThread(void* param)
|
||||||
ExitThread(r);
|
ExitThread(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveVHD(void)
|
void VhdSaveImage(void)
|
||||||
{
|
{
|
||||||
static IMG_SAVE img_save = { 0 };
|
static IMG_SAVE img_save = { 0 };
|
||||||
char filename[128];
|
char filename[128];
|
||||||
|
@ -1023,9 +1113,8 @@ void SaveVHD(void)
|
||||||
static_sprintf(filename, "%s.vhdx", rufus_drive[DriveIndex].label);
|
static_sprintf(filename, "%s.vhdx", 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 started with Windows 10 1709 (through FfuProvider.dll) and requires GPT
|
// FFU support requires GPT
|
||||||
static_sprintf(path, "%s\\dism\\FfuProvider.dll", sysnative_dir);
|
if (!has_ffu_support || SelectedDrive.PartitionStyle != PARTITION_STYLE_GPT)
|
||||||
if ((_accessU(path, 0) != 0) || SelectedDrive.PartitionStyle != PARTITION_STYLE_GPT)
|
|
||||||
img_ext.count = 2;
|
img_ext.count = 2;
|
||||||
img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0);
|
img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0);
|
||||||
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
|
img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
|
||||||
|
@ -1048,7 +1137,7 @@ void SaveVHD(void)
|
||||||
FormatStatus = 0;
|
FormatStatus = 0;
|
||||||
InitProgress(TRUE);
|
InitProgress(TRUE);
|
||||||
format_thread = CreateThread(NULL, 0, img_save.Type == VIRTUAL_STORAGE_TYPE_DEVICE_FFU ?
|
format_thread = CreateThread(NULL, 0, img_save.Type == VIRTUAL_STORAGE_TYPE_DEVICE_FFU ?
|
||||||
SaveFFUThread : SaveVHDThread, &img_save, 0, NULL);
|
FfuSaveImageThread : VhdSaveImageThread, &img_save, 0, NULL);
|
||||||
if (format_thread != NULL) {
|
if (format_thread != NULL) {
|
||||||
uprintf("\r\nSave to VHD operation started");
|
uprintf("\r\nSave to VHD operation started");
|
||||||
PrintInfo(0, -1);
|
PrintInfo(0, -1);
|
||||||
|
|
59
src/vhd.h
59
src/vhd.h
|
@ -23,23 +23,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VHD_FOOTER_COOKIE { 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x' }
|
|
||||||
|
|
||||||
#define VHD_FOOTER_FEATURES_NONE 0x00000000
|
|
||||||
#define VHD_FOOTER_FEATURES_TEMPORARY 0x00000001
|
|
||||||
#define VHD_FOOTER_FEATURES_RESERVED 0x00000002
|
|
||||||
|
|
||||||
#define VHD_FOOTER_FILE_FORMAT_V1_0 0x00010000
|
|
||||||
|
|
||||||
#define VHD_FOOTER_DATA_OFFSET_FIXED_DISK 0xFFFFFFFFFFFFFFFFULL
|
|
||||||
|
|
||||||
#define VHD_FOOTER_CREATOR_HOST_OS_WINDOWS { 'W', 'i', '2', 'k' }
|
|
||||||
#define VHD_FOOTER_CREATOR_HOST_OS_MAC { 'M', 'a', 'c', ' ' }
|
|
||||||
|
|
||||||
#define VHD_FOOTER_TYPE_FIXED_HARD_DISK 0x00000002
|
|
||||||
#define VHD_FOOTER_TYPE_DYNAMIC_HARD_DISK 0x00000003
|
|
||||||
#define VHD_FOOTER_TYPE_DIFFER_HARD_DISK 0x00000004
|
|
||||||
|
|
||||||
#define WIM_MAGIC 0x0000004D4957534DULL // "MSWIM\0\0\0"
|
#define WIM_MAGIC 0x0000004D4957534DULL // "MSWIM\0\0\0"
|
||||||
#define WIM_HAS_API_EXTRACT 1
|
#define WIM_HAS_API_EXTRACT 1
|
||||||
#define WIM_HAS_7Z_EXTRACT 2
|
#define WIM_HAS_7Z_EXTRACT 2
|
||||||
|
@ -142,40 +125,6 @@ enum WIMMessage {
|
||||||
WIM_MSG_ABORT_IMAGE = -1
|
WIM_MSG_ABORT_IMAGE = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* VHD Fixed HD footer (Big Endian)
|
|
||||||
* http://download.microsoft.com/download/f/f/e/ffef50a5-07dd-4cf8-aaa3-442c0673a029/Virtual%20Hard%20Disk%20Format%20Spec_10_18_06.doc
|
|
||||||
* NB: If a dymamic implementation is needed, check the GPL v3 compatible C++ implementation from:
|
|
||||||
* https://sourceforge.net/p/urbackup/backend/ci/master/tree/fsimageplugin/
|
|
||||||
*/
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
typedef struct vhd_footer {
|
|
||||||
char cookie[8];
|
|
||||||
uint32_t features;
|
|
||||||
uint32_t file_format_version;
|
|
||||||
uint64_t data_offset;
|
|
||||||
uint32_t timestamp;
|
|
||||||
char creator_app[4];
|
|
||||||
uint32_t creator_version;
|
|
||||||
char creator_host_os[4];
|
|
||||||
uint64_t original_size;
|
|
||||||
uint64_t current_size;
|
|
||||||
union {
|
|
||||||
uint32_t geometry;
|
|
||||||
struct {
|
|
||||||
uint16_t cylinders;
|
|
||||||
uint8_t heads;
|
|
||||||
uint8_t sectors;
|
|
||||||
} chs;
|
|
||||||
} disk_geometry;
|
|
||||||
uint32_t disk_type;
|
|
||||||
uint32_t checksum;
|
|
||||||
uuid_t unique_id;
|
|
||||||
uint8_t saved_state;
|
|
||||||
uint8_t reserved[427];
|
|
||||||
} vhd_footer;
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
extern uint8_t WimExtractCheck(BOOL bSilent);
|
extern uint8_t WimExtractCheck(BOOL bSilent);
|
||||||
extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst, BOOL bSilent);
|
extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst, BOOL bSilent);
|
||||||
extern BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst, BOOL bSilent);
|
extern BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst, BOOL bSilent);
|
||||||
|
@ -183,8 +132,10 @@ extern BOOL WimExtractFile_7z(const char* image, int index, const char* src, con
|
||||||
extern BOOL WimApplyImage(const char* image, int index, const char* dst);
|
extern BOOL WimApplyImage(const char* image, int index, const char* dst);
|
||||||
extern char* WimMountImage(const char* image, int index);
|
extern char* WimMountImage(const char* image, int index);
|
||||||
extern BOOL WimUnmountImage(const char* image, int index, BOOL commit);
|
extern BOOL WimUnmountImage(const char* image, int index, BOOL commit);
|
||||||
extern char* GetExistingMountPoint(const char* image, int index);
|
extern char* WimGetExistingMountPoint(const char* image, int index);
|
||||||
extern BOOL WimIsValidIndex(const char* image, int index);
|
extern BOOL WimIsValidIndex(const char* image, int index);
|
||||||
extern int8_t IsBootableImage(const char* path);
|
extern int8_t IsBootableImage(const char* path);
|
||||||
extern void SaveVHD(void);
|
extern char* VhdMountImage(const char* path);
|
||||||
extern void SaveISO(void);
|
extern void VhdUnmountImage(void);
|
||||||
|
extern void VhdSaveImage(void);
|
||||||
|
extern void IsoSaveImage(void);
|
||||||
|
|
14
src/wue.c
14
src/wue.c
|
@ -440,7 +440,7 @@ BOOL PopulateWindowsVersion(void)
|
||||||
|
|
||||||
// If we're not using a straight install.wim, we need to mount the ISO to access it
|
// If we're not using a straight install.wim, we need to mount the ISO to access it
|
||||||
if (!img_report.is_windows_img) {
|
if (!img_report.is_windows_img) {
|
||||||
mounted_iso = MountISO(image_path);
|
mounted_iso = VhdMountImage(image_path);
|
||||||
if (mounted_iso == NULL) {
|
if (mounted_iso == NULL) {
|
||||||
uprintf("Could not mount Windows ISO for build number detection");
|
uprintf("Could not mount Windows ISO for build number detection");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -468,7 +468,7 @@ BOOL PopulateWindowsVersion(void)
|
||||||
out:
|
out:
|
||||||
DeleteFileU(xml_file);
|
DeleteFileU(xml_file);
|
||||||
if (!img_report.is_windows_img)
|
if (!img_report.is_windows_img)
|
||||||
UnMountISO();
|
VhdUnmountImage();
|
||||||
|
|
||||||
return ((img_report.win_version.major != 0) && (img_report.win_version.build != 0));
|
return ((img_report.win_version.major != 0) && (img_report.win_version.build != 0));
|
||||||
}
|
}
|
||||||
|
@ -532,7 +532,7 @@ int SetWinToGoIndex(void)
|
||||||
|
|
||||||
// If we're not using a straight install.wim, we need to mount the ISO to access it
|
// If we're not using a straight install.wim, we need to mount the ISO to access it
|
||||||
if (!img_report.is_windows_img) {
|
if (!img_report.is_windows_img) {
|
||||||
mounted_iso = MountISO(image_path);
|
mounted_iso = VhdMountImage(image_path);
|
||||||
if (mounted_iso == NULL) {
|
if (mounted_iso == NULL) {
|
||||||
uprintf("Could not mount ISO for Windows To Go selection");
|
uprintf("Could not mount ISO for Windows To Go selection");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -613,7 +613,7 @@ int SetWinToGoIndex(void)
|
||||||
out:
|
out:
|
||||||
DeleteFileU(xml_file);
|
DeleteFileU(xml_file);
|
||||||
if (!img_report.is_windows_img)
|
if (!img_report.is_windows_img)
|
||||||
UnMountISO();
|
VhdUnmountImage();
|
||||||
return wintogo_index;
|
return wintogo_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,7 +640,7 @@ BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!img_report.is_windows_img) {
|
if (!img_report.is_windows_img) {
|
||||||
mounted_iso = MountISO(image_path);
|
mounted_iso = VhdMountImage(image_path);
|
||||||
if (mounted_iso == NULL) {
|
if (mounted_iso == NULL) {
|
||||||
uprintf("Could not mount ISO for Windows To Go installation");
|
uprintf("Could not mount ISO for Windows To Go installation");
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_ISO_EXTRACT);
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_ISO_EXTRACT);
|
||||||
|
@ -656,11 +656,11 @@ BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp)
|
||||||
if (!IS_ERROR(FormatStatus))
|
if (!IS_ERROR(FormatStatus))
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_ISO_EXTRACT);
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_ISO_EXTRACT);
|
||||||
if (!img_report.is_windows_img)
|
if (!img_report.is_windows_img)
|
||||||
UnMountISO();
|
VhdUnmountImage();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!img_report.is_windows_img)
|
if (!img_report.is_windows_img)
|
||||||
UnMountISO();
|
VhdUnmountImage();
|
||||||
|
|
||||||
if (use_esp) {
|
if (use_esp) {
|
||||||
uprintf("Setting up EFI System Partition");
|
uprintf("Setting up EFI System Partition");
|
||||||
|
|
Loading…
Reference in a new issue