From f9370e002e078e557ffcdb96ba4e7e63913b8d5f Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sun, 2 Jul 2023 13:15:51 +0100 Subject: [PATCH] [iso] fix a crash when parsing Windows ISOs with MinGW x86_32 * MinGW32's delay loading functionality is not yet up to par with MSVC's and especially, for some libraries (wininet, virtdisk) attempting to delay load them simply crashes the runtime. * This results in the MinGW32 version of the app crashing when selecting a Windows ISO, as we will then try to mount the ISO using virtdisk to poke the build version. Note that this crash does not happen with the MinGW64 version or with MSVC. * Closes #2272. * Also fix a Coverity warning in SaveImageThread() and improve the VHD saving code. --- .mingw/Makefile.am | 2 +- .mingw/Makefile.in | 2 +- .mingw/virtdisk.def | 7 ------- .vs/rufus.vcxproj | 32 ++++++++++++++++---------------- src/Makefile.am | 5 ++++- src/Makefile.in | 5 ++++- src/iso.c | 23 +++++++++++++++++++---- src/rufus.rc | 10 +++++----- src/vhd.c | 30 ++++++++++++++++++++++-------- 9 files changed, 72 insertions(+), 44 deletions(-) delete mode 100644 .mingw/virtdisk.def diff --git a/.mingw/Makefile.am b/.mingw/Makefile.am index 32c0b48b..eb979f9f 100644 --- a/.mingw/Makefile.am +++ b/.mingw/Makefile.am @@ -19,7 +19,7 @@ TARGET := $(word 1,$(subst -, ,$(TUPLE))) DEF_SUFFIX := $(if $(TARGET:x86_64=),.def,.def64) .PHONY: all -all: dwmapi-delaylib.lib virtdisk-delaylib.lib wintrust-delaylib.lib +all: dwmapi-delaylib.lib wintrust-delaylib.lib %.def64: %.def $(AM_V_SED) "s/@.*//" $< >$@ diff --git a/.mingw/Makefile.in b/.mingw/Makefile.in index fbdc2ce6..0af7e49c 100644 --- a/.mingw/Makefile.in +++ b/.mingw/Makefile.in @@ -367,7 +367,7 @@ uninstall-am: .PHONY: all -all: dwmapi-delaylib.lib virtdisk-delaylib.lib wintrust-delaylib.lib +all: dwmapi-delaylib.lib wintrust-delaylib.lib %.def64: %.def $(AM_V_SED) "s/@.*//" $< >$@ diff --git a/.mingw/virtdisk.def b/.mingw/virtdisk.def deleted file mode 100644 index 4476016c..00000000 --- a/.mingw/virtdisk.def +++ /dev/null @@ -1,7 +0,0 @@ -EXPORTS - AttachVirtualDisk@24 - GetVirtualDiskPhysicalPath@12 - DetachVirtualDisk@12 - OpenVirtualDisk@24 - CreateVirtualDisk@36 - GetVirtualDiskOperationProgress@12 diff --git a/.vs/rufus.vcxproj b/.vs/rufus.vcxproj index a4128ac7..6693b2f2 100644 --- a/.vs/rufus.vcxproj +++ b/.vs/rufus.vcxproj @@ -133,12 +133,12 @@ /utf-8 $(ExternalCompilerOptions) %(AdditionalOptions) - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;virtdisk.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies) RequireAdministrator true Windows MachineX86 - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;virtdisk.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -162,12 +162,12 @@ /utf-8 $(ExternalCompilerOptions) %(AdditionalOptions) - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;virtdisk.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) RequireAdministrator true Windows C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;virtdisk.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -193,12 +193,12 @@ /utf-8 $(ExternalCompilerOptions) %(AdditionalOptions) - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;virtdisk.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) RequireAdministrator true Windows C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64 - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;virtdisk.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -229,12 +229,12 @@ /utf-8 $(ExternalCompilerOptions) %(AdditionalOptions) - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;virtdisk.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies) RequireAdministrator true Windows MachineX64 - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;virtdisk.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -260,13 +260,13 @@ true - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;virtdisk.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies) RequireAdministrator false Windows MachineX86 /BREPRO %(AdditionalOptions) - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;virtdisk.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -292,13 +292,13 @@ true - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;virtdisk.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) RequireAdministrator false Windows C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm /BREPRO %(AdditionalOptions) - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;virtdisk.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -326,13 +326,13 @@ true - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;virtdisk.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) RequireAdministrator false Windows C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64 /BREPRO %(AdditionalOptions) - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;virtdisk.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -363,13 +363,13 @@ true - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;virtdisk.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies) RequireAdministrator false Windows MachineX64 /BREPRO %(AdditionalOptions) - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;virtdisk.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;%(PreprocessorDefinitions) diff --git a/src/Makefile.am b/src/Makefile.am index ef95f391..59dfabd3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,10 @@ SUBDIRS = ../.mingw bled ext2fs ms-sys syslinux/libfat syslinux/libinstaller sys # As far as I can tell, the following libraries are *not* vulnerable to side-loading, so we link using their regular version: NONVULNERABLE_LIBS = -lsetupapi -lole32 -lgdi32 -lshlwapi -lcrypt32 -lcomdlg32 -lcomctl32 -luuid # The following libraries are vulnerable (or have an unknown vulnerability status), so we link using our delay-loaded replacement: -VULNERABLE_LIBS = -ldwmapi-delaylib -lvirtdisk-delaylib -lwintrust-delaylib +# Ideally there would also be virtdisk and wininet as delaylib's below, but the MinGW folks haven't quite sorted out delay-loading +# for x86_32 so as soon as you try to call APIs from these, the application will crash! +# See https://github.com/pbatard/rufus/issues/1877#issuecomment-1109683039 as well as https://github.com/pbatard/rufus/issues/2272 +VULNERABLE_LIBS = -ldwmapi-delaylib -lwintrust-delaylib noinst_PROGRAMS = rufus diff --git a/src/Makefile.in b/src/Makefile.in index e83fd54a..0fe9fa5a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -277,7 +277,10 @@ SUBDIRS = ../.mingw bled ext2fs ms-sys syslinux/libfat syslinux/libinstaller sys # As far as I can tell, the following libraries are *not* vulnerable to side-loading, so we link using their regular version: NONVULNERABLE_LIBS = -lsetupapi -lole32 -lgdi32 -lshlwapi -lcrypt32 -lcomdlg32 -lcomctl32 -luuid # The following libraries are vulnerable (or have an unknown vulnerability status), so we link using our delay-loaded replacement: -VULNERABLE_LIBS = -ldwmapi-delaylib -lvirtdisk-delaylib -lwintrust-delaylib +# Ideally there would also be virtdisk and wininet as delaylib's below, but the MinGW folks haven't quite sorted out delay-loading +# for x86_32 so as soon as you try to call APIs from these, the application will crash! +# See https://github.com/pbatard/rufus/issues/1877#issuecomment-1109683039 as well as https://github.com/pbatard/rufus/issues/2272 +VULNERABLE_LIBS = -ldwmapi-delaylib -lwintrust-delaylib AM_V_WINDRES_0 = @echo " RC $@";$(WINDRES) AM_V_WINDRES_1 = $(WINDRES) AM_V_WINDRES_ = $(AM_V_WINDRES_$(AM_DEFAULT_VERBOSITY)) diff --git a/src/iso.c b/src/iso.c index 4372a249..a8db0e68 100644 --- a/src/iso.c +++ b/src/iso.c @@ -1710,6 +1710,15 @@ out: 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; @@ -1723,10 +1732,14 @@ char* MountISO(const char* path) 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 = OpenVirtualDisk(&vtype, wpath, VIRTUAL_DISK_ACCESS_READ | VIRTUAL_DISK_ACCESS_GET_INFO, + 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); @@ -1735,7 +1748,7 @@ char* MountISO(const char* path) } vparams.Version = ATTACH_VIRTUAL_DISK_VERSION_1; - r = AttachVirtualDisk(mounted_handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | + 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); @@ -1743,7 +1756,7 @@ char* MountISO(const char* path) goto out; } - r = GetVirtualDiskPhysicalPath(mounted_handle, &size, wtmp); + 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()); @@ -1761,10 +1774,12 @@ out: void UnMountISO(void) { + PF_INIT_OR_OUT(DetachVirtualDisk, VirtDisk); + if ((mounted_handle == NULL) || (mounted_handle == INVALID_HANDLE_VALUE)) goto out; - DetachVirtualDisk(mounted_handle, DETACH_VIRTUAL_DISK_FLAG_NONE, 0); + pfDetachVirtualDisk(mounted_handle, DETACH_VIRTUAL_DISK_FLAG_NONE, 0); safe_closehandle(mounted_handle); out: physical_path[0] = 0; diff --git a/src/rufus.rc b/src/rufus.rc index 60c3802b..1c81b27e 100644 --- a/src/rufus.rc +++ b/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.2060" +CAPTION "Rufus 4.2.2061" 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,2060,0 - PRODUCTVERSION 4,2,2060,0 + FILEVERSION 4,2,2061,0 + PRODUCTVERSION 4,2,2061,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.2060" + VALUE "FileVersion", "4.2.2061" 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.2060" + VALUE "ProductVersion", "4.2.2061" END END BLOCK "VarFileInfo" diff --git a/src/vhd.c b/src/vhd.c index 94c63188..9ef94647 100644 --- a/src/vhd.c +++ b/src/vhd.c @@ -885,6 +885,13 @@ BOOL WimApplyImage(const char* image, int index, const char* dst) return dw; } +// VirtDisk API Prototypes since we can't use delay-loading because of MinGW +PF_TYPE_DECL(WINAPI, DWORD, CreateVirtualDisk, (PVIRTUAL_STORAGE_TYPE, PCWSTR, + VIRTUAL_DISK_ACCESS_MASK, PSECURITY_DESCRIPTOR, CREATE_VIRTUAL_DISK_FLAG, ULONG, + PCREATE_VIRTUAL_DISK_PARAMETERS, LPOVERLAPPED, PHANDLE)); +PF_TYPE_DECL(WINAPI, DWORD, GetVirtualDiskOperationProgress, (HANDLE, LPOVERLAPPED, + PVIRTUAL_DISK_PROGRESS)); + // 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 // ISO from optical media that would be swell, but no matter what I tried, it didn't @@ -893,14 +900,17 @@ static DWORD WINAPI SaveImageThread(void* param) { IMG_SAVE* img_save = (IMG_SAVE*)param; HANDLE handle = INVALID_HANDLE_VALUE; + WCHAR* wSrc = utf8_to_wchar(img_save->DevicePath); WCHAR* wDst = utf8_to_wchar(img_save->ImagePath); - WCHAR* wSrc = utf8_to_wchar(GetPhysicalName(img_save->DeviceNum)); VIRTUAL_STORAGE_TYPE vtype = { img_save->Type, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT }; STOPGAP_CREATE_VIRTUAL_DISK_PARAMETERS vparams = { 0 }; VIRTUAL_DISK_PROGRESS vprogress = { 0 }; OVERLAPPED overlapped = { 0 }; DWORD result, flags; + PF_INIT_OR_OUT(CreateVirtualDisk, VirtDisk); + PF_INIT_OR_OUT(GetVirtualDiskOperationProgress, VirtDisk); + assert(img_save->Type == VIRTUAL_STORAGE_TYPE_DEVICE_VHD || img_save->Type == VIRTUAL_STORAGE_TYPE_DEVICE_VHDX); @@ -919,7 +929,7 @@ static DWORD WINAPI SaveImageThread(void* param) flags = CREATE_VIRTUAL_DISK_FLAG_CREATE_BACKING_STORAGE; // The following ensures that VHD images are stored uncompressed and can // be used as DD images. - if (img_save->Type != VIRTUAL_STORAGE_TYPE_DEVICE_VHDX) + if (img_save->Type == VIRTUAL_STORAGE_TYPE_DEVICE_VHD) flags |= CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION; // TODO: Use CREATE_VIRTUAL_DISK_FLAG_PREVENT_WRITES_TO_SOURCE_DISK? @@ -928,7 +938,7 @@ static DWORD WINAPI SaveImageThread(void* param) // CreateVirtualDisk() does not have an overwrite flag... DeleteFileW(wDst); - result = CreateVirtualDisk(&vtype, wDst, VIRTUAL_DISK_ACCESS_NONE, NULL, + result = pfCreateVirtualDisk(&vtype, wDst, VIRTUAL_DISK_ACCESS_NONE, NULL, flags, 0, (PCREATE_VIRTUAL_DISK_PARAMETERS)&vparams, &overlapped, &handle); if (result != ERROR_SUCCESS && result != ERROR_IO_PENDING) { SetLastError(result); @@ -942,7 +952,7 @@ static DWORD WINAPI SaveImageThread(void* param) CancelIoEx(handle, &overlapped); goto out; } - if (GetVirtualDiskOperationProgress(handle, &overlapped, &vprogress) == ERROR_SUCCESS) { + if (pfGetVirtualDiskOperationProgress(handle, &overlapped, &vprogress) == ERROR_SUCCESS) { if (vprogress.OperationStatus == ERROR_IO_PENDING) UpdateProgressWithInfo(OP_FORMAT, MSG_261, vprogress.CurrentValue, vprogress.CompletionValue); } @@ -957,10 +967,11 @@ static DWORD WINAPI SaveImageThread(void* param) uprintf("Operation complete."); out: - safe_closehandle(handle); safe_closehandle(overlapped.hEvent); - safe_free(wDst); + safe_closehandle(handle); safe_free(wSrc); + safe_free(wDst); + safe_free(img_save->DevicePath); safe_free(img_save->ImagePath); PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)TRUE, 0); ExitThread(0); @@ -980,12 +991,13 @@ void SaveVHD(void) static_sprintf(filename, "%s.vhdx", rufus_drive[DriveIndex].label); img_save.DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, DriveIndex); + img_save.DevicePath = GetPhysicalName(img_save.DeviceNum); img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); img_save.Type = safe_strstr(img_save.ImagePath, ".vhdx") != NULL ? VIRTUAL_STORAGE_TYPE_DEVICE_VHDX : VIRTUAL_STORAGE_TYPE_DEVICE_VHD; img_save.BufSize = DD_BUFFER_SIZE; img_save.DeviceSize = SelectedDrive.DiskSize; - if (img_save.ImagePath != NULL) { + if (img_save.DevicePath != NULL && img_save.ImagePath != NULL) { // Reset all progress bars SendMessage(hMainDialog, UM_PROGRESS_INIT, 0, 0); FormatStatus = 0; @@ -993,7 +1005,7 @@ void SaveVHD(void) 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 + // Disable all controls except Cancel EnableControls(FALSE, FALSE); FormatStatus = 0; InitProgress(TRUE); @@ -1005,6 +1017,7 @@ void SaveVHD(void) } 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); } @@ -1017,6 +1030,7 @@ void SaveVHD(void) uprintf("The VHD size is too large for the target drive"); FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_FILE_TOO_LARGE; } + safe_free(img_save.DevicePath); safe_free(img_save.ImagePath); PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0); }