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 | ||||
| 
 | ||||
| #include "rufus.h" | ||||
| #include "format.h" | ||||
| #include "missing.h" | ||||
| #include "resource.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 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 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; | ||||
| long grub2_len; | ||||
| 
 | ||||
|  | @ -1154,6 +1155,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive) | |||
| 	int64_t bled_ret; | ||||
| 	uint8_t* buffer = NULL; | ||||
| 	uint32_t zero_data, *cmp_buffer = NULL; | ||||
| 	char* vhd_path = NULL; | ||||
| 	int throttle_fast_zeroing = 0, read_bufnum = 0, proc_bufnum = 1; | ||||
| 
 | ||||
| 	if (SelectedDrive.SectorSize < 512) { | ||||
|  | @ -1273,7 +1275,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive) | |||
| 			if (i > WRITE_RETRIES) | ||||
| 				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:"); | ||||
| 		hSourceImage = CreateFileU(image_path, GENERIC_READ, FILE_SHARE_READ, NULL, | ||||
| 			OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); | ||||
|  | @ -1310,8 +1312,17 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive) | |||
| 			goto out; | ||||
| 		} | ||||
| 	} else { | ||||
| 		hSourceImage = CreateFileAsync(image_path, GENERIC_READ, FILE_SHARE_READ, | ||||
| 			OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN); | ||||
| 		assert(img_report.compression_type != IMG_COMPRESSION_FFU); | ||||
| 		// 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) { | ||||
| 			uprintf("Could not open image '%s': %s", image_path, WindowsErrorString()); | ||||
| 			FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED; | ||||
|  | @ -1397,10 +1408,12 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive) | |||
| 	RefreshDriveLayout(hPhysicalDrive); | ||||
| 	ret = TRUE; | ||||
| 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); | ||||
| 	else | ||||
| 		CloseFileAsync(hSourceImage); | ||||
| 	if (vhd_path != NULL) | ||||
| 		VhdUnmountImage(); | ||||
| 	safe_mm_free(buffer); | ||||
| 	safe_mm_free(cmp_buffer); | ||||
| 	return ret; | ||||
|  | @ -1627,7 +1640,24 @@ DWORD WINAPI FormatThread(void* param) | |||
| 
 | ||||
| 	// Write an image file
 | ||||
| 	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); | ||||
| 		} | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| /*
 | ||||
|  * Rufus: The Reliable USB Formatting Utility | ||||
|  * 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 | ||||
|  * 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
 | ||||
| ); | ||||
| 
 | ||||
| #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 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); | ||||
|  |  | |||
							
								
								
									
										81
									
								
								src/iso.c
									
										
									
									
									
								
							
							
						
						
									
										81
									
								
								src/iso.c
									
										
									
									
									
								
							|  | @ -1726,83 +1726,8 @@ 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; | ||||
| 
 | ||||
| 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
 | ||||
| static DWORD WINAPI SaveISOThread(void* param) | ||||
| static DWORD WINAPI IsoSaveImageThread(void* param) | ||||
| { | ||||
| 	BOOL s; | ||||
| 	DWORD rSize, wSize; | ||||
|  | @ -1908,7 +1833,7 @@ out: | |||
| 	ExitThread(0); | ||||
| } | ||||
| 
 | ||||
| void SaveISO(void) | ||||
| void IsoSaveImage(void) | ||||
| { | ||||
| 	static IMG_SAVE img_save = { 0 }; | ||||
| 	char filename[33] = "disc_image.iso"; | ||||
|  | @ -1939,7 +1864,7 @@ void SaveISO(void) | |||
| 	// Disable all controls except cancel
 | ||||
| 	EnableControls(FALSE, FALSE); | ||||
| 	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) { | ||||
| 		uprintf("\r\nSave to ISO operation started"); | ||||
| 		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 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 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; | ||||
| 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; | ||||
|  | @ -2588,8 +2588,11 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 					img_provided = FALSE;	// One off thing...
 | ||||
| 				} else { | ||||
| 					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...
 | ||||
| 					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))); | ||||
| 					image_path = FileDialog(FALSE, NULL, &img_ext, 0); | ||||
| 					if (image_path == NULL) { | ||||
|  | @ -2684,7 +2687,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 			} | ||||
| 			break; | ||||
| 		case IDC_SAVE: | ||||
| 			SaveVHD(); | ||||
| 			VhdSaveImage(); | ||||
| 			break; | ||||
| 		case IDM_SELECT: | ||||
| 		case IDM_DOWNLOAD: | ||||
|  | @ -3695,6 +3698,9 @@ skip_args_processing: | |||
| 	// Detect CPU acceleration for SHA-1/SHA-256
 | ||||
| 	cpu_has_sha1_accel = DetectSHA1Acceleration(); | ||||
| 	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: | ||||
| 	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
 | ||||
| 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'O')) { | ||||
| 				SaveISO(); | ||||
| 				IsoSaveImage(); | ||||
| 				continue; | ||||
| 			} | ||||
| 			// 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 HasEfiImgBootLoaders(void); | ||||
| 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 uint16_t GetSyslinuxVersion(char* buf, size_t buf_size, char** ext); | ||||
| 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 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_ACCEPTFILES | ||||
| CAPTION "Rufus 4.2.2067" | ||||
| CAPTION "Rufus 4.2.2068" | ||||
| 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,2067,0 | ||||
|  PRODUCTVERSION 4,2,2067,0 | ||||
|  FILEVERSION 4,2,2068,0 | ||||
|  PRODUCTVERSION 4,2,2068,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.2067" | ||||
|             VALUE "FileVersion", "4.2.2068" | ||||
|             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.2067" | ||||
|             VALUE "ProductVersion", "4.2.2068" | ||||
|         END | ||||
|     END | ||||
|     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.
 | ||||
| 	for (i = 0; i < resolver->count; i++) { | ||||
| 		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); | ||||
| 		if (resolver->address[i] == 0) | ||||
| 			break; | ||||
|  | @ -1253,7 +1253,7 @@ uint32_t ResolveDllAddress(dll_resolver_t* resolver) | |||
| 		goto out; | ||||
| 	static_sprintf(path, "%s\\%s", temp_dir, info->PdbName); | ||||
| 	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) | ||||
| 		goto out; | ||||
| 
 | ||||
|  | @ -1280,7 +1280,7 @@ uint32_t ResolveDllAddress(dll_resolver_t* resolver) | |||
| 	r = 0; | ||||
| 	for (i = 0; i < resolver->count; i++) { | ||||
| 		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) { | ||||
| 			WriteSetting32(saved_id, resolver->address[i]); | ||||
| 			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; | ||||
| HANDLE wim_thread = NULL; | ||||
| 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 HANDLE format_thread; | ||||
| 
 | ||||
|  | @ -67,7 +67,6 @@ static uint32_t progress_report_mask; | |||
| static uint64_t progress_offset = 0, progress_total = 100; | ||||
| static wchar_t wmount_path[MAX_PATH] = { 0 }, wmount_track[MAX_PATH] = { 0 }; | ||||
| static char sevenzip_path[MAX_PATH]; | ||||
| static const char conectix_str[] = VHD_FOOTER_COOKIE; | ||||
| static BOOL count_files; | ||||
| static int progress_op = OP_FILE_COPY, progress_msg = MSG_267; | ||||
| 
 | ||||
|  | @ -83,7 +82,7 @@ static BOOL Get7ZipPath(void) | |||
| 
 | ||||
| typedef struct { | ||||
| 	const char* ext; | ||||
| 	bled_compression_type type; | ||||
| 	uint8_t type; | ||||
| } comp_assoc; | ||||
| 
 | ||||
| static comp_assoc file_assoc[] = { | ||||
|  | @ -94,33 +93,75 @@ static comp_assoc file_assoc[] = { | |||
| 	{ ".bz2", BLED_COMPRESSION_BZIP2 }, | ||||
| 	{ ".xz", BLED_COMPRESSION_XZ }, | ||||
| 	{ ".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) | ||||
| { | ||||
| 	char *p; | ||||
| 	char *ext = NULL, *physical_disk = NULL; | ||||
| 	unsigned char *buf = NULL; | ||||
| 	int i; | ||||
| 	FILE* fd = NULL; | ||||
| 	BOOL r = FALSE; | ||||
| 	int64_t dc; | ||||
| 	int64_t dc = 0; | ||||
| 
 | ||||
| 	img_report.compression_type = BLED_COMPRESSION_NONE; | ||||
| 	for (p = (char*)&path[strlen(path)-1]; (*p != '.') && (p != path); p--); | ||||
| 
 | ||||
| 	if (p == path) | ||||
| 		return FALSE; | ||||
| 	if (safe_strlen(path) > 4) | ||||
| 		for (ext = (char*)&path[safe_strlen(path) - 1]; (*ext != '.') && (ext != path); ext--); | ||||
| 
 | ||||
| 	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; | ||||
| 			buf = malloc(MBR_SIZE); | ||||
| 			if (buf == NULL) | ||||
| 				return FALSE; | ||||
| 			FormatStatus = 0; | ||||
| 			if (img_report.compression_type < BLED_COMPRESSION_MAX) { | ||||
| 				bled_init(0, uprintf, NULL, NULL, NULL, NULL, &FormatStatus); | ||||
| 				dc = bled_uncompress_to_buffer(path, (char*)buf, MBR_SIZE, file_assoc[i].type); | ||||
| 				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) { | ||||
| 				free(buf); | ||||
| 				return FALSE; | ||||
|  | @ -139,10 +180,7 @@ int8_t IsBootableImage(const char* path) | |||
| { | ||||
| 	HANDLE handle = INVALID_HANDLE_VALUE; | ||||
| 	LARGE_INTEGER liImageSize; | ||||
| 	vhd_footer* footer = NULL; | ||||
| 	DWORD size; | ||||
| 	size_t i; | ||||
| 	uint32_t checksum, old_checksum; | ||||
| 	uint64_t wim_magic = 0; | ||||
| 	LARGE_INTEGER ptr = { 0 }; | ||||
| 	int8_t is_bootable_img; | ||||
|  | @ -171,40 +209,7 @@ int8_t IsBootableImage(const char* path) | |||
| 	if (img_report.is_windows_img) | ||||
| 		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: | ||||
| 	safe_free(footer); | ||||
| 	safe_closehandle(handle); | ||||
| 	return is_bootable_img; | ||||
| } | ||||
|  | @ -405,7 +410,7 @@ char* WimMountImage(const char* image, int index) | |||
| 	mp.index = index; | ||||
| 
 | ||||
| 	// 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) { | ||||
| 		uprintf("WARNING: Found stale '%s [%d]' image mounted on '%s' - Attempting to unmount it...", | ||||
| 			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
 | ||||
| // 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.
 | ||||
| char* GetExistingMountPoint(const char* image, int index) | ||||
| char* WimGetExistingMountPoint(const char* image, int index) | ||||
| { | ||||
| 	static char path[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
 | ||||
| // See https://github.com/pbatard/rufus/issues/2272#issuecomment-1615976013
 | ||||
| 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, 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, | ||||
| 	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()
 | ||||
| // 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
 | ||||
| // seem possible...
 | ||||
| static DWORD WINAPI SaveVHDThread(void* param) | ||||
| static DWORD WINAPI VhdSaveImageThread(void* param) | ||||
| { | ||||
| 	IMG_SAVE* img_save = (IMG_SAVE*)param; | ||||
| 	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
 | ||||
| // of Windows, would be a massive timesink, we just take a shortcut by calling dism
 | ||||
| // directly, as imperfect as such a solution might be...
 | ||||
| static DWORD WINAPI SaveFFUThread(void* param) | ||||
| static DWORD WINAPI FfuSaveImageThread(void* param) | ||||
| { | ||||
| 	DWORD r; | ||||
| 	IMG_SAVE* img_save = (IMG_SAVE*)param; | ||||
| 	char cmd[MAX_PATH + 128], *letter = "", *label; | ||||
| 
 | ||||
| 	GetDriveLabel(SelectedDrive.DeviceNumber, letter, &label, TRUE); | ||||
| 	static_sprintf(cmd, "dism /capture-ffu /capturedrive=%s /imagefile=\"%s\" " | ||||
| 		"/name:\"%s\" /description:\"Created by %s (%s)\"", | ||||
| 	static_sprintf(cmd, "dism /Capture-Ffu /CaptureDrive:%s /ImageFile:\"%s\" " | ||||
| 		"/Name:\"%s\" /Description:\"Created by %s (%s)\"", | ||||
| 		img_save->DevicePath, img_save->ImagePath, label, APPLICATION_NAME, RUFUS_URL); | ||||
| 	uprintf("Running command: '%s", cmd); | ||||
| 	r = RunCommandWithProgress(cmd, sysnative_dir, TRUE, MSG_261); | ||||
| 	if (r != 0 && !IS_ERROR(FormatStatus)) { | ||||
| 		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); | ||||
| 	} | ||||
| 	safe_free(img_save->DevicePath); | ||||
|  | @ -1007,7 +1097,7 @@ static DWORD WINAPI SaveFFUThread(void* param) | |||
| 	ExitThread(r); | ||||
| } | ||||
| 
 | ||||
| void SaveVHD(void) | ||||
| void VhdSaveImage(void) | ||||
| { | ||||
| 	static IMG_SAVE img_save = { 0 }; | ||||
| 	char filename[128]; | ||||
|  | @ -1023,9 +1113,8 @@ 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); | ||||
| 	// FFU support started with Windows 10 1709 (through FfuProvider.dll) and requires GPT
 | ||||
| 	static_sprintf(path, "%s\\dism\\FfuProvider.dll", sysnative_dir); | ||||
| 	if ((_accessU(path, 0) != 0) || SelectedDrive.PartitionStyle != PARTITION_STYLE_GPT) | ||||
| 	// 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; | ||||
|  | @ -1048,7 +1137,7 @@ void SaveVHD(void) | |||
| 			FormatStatus = 0; | ||||
| 			InitProgress(TRUE); | ||||
| 			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) { | ||||
| 				uprintf("\r\nSave to VHD operation started"); | ||||
| 				PrintInfo(0, -1); | ||||
|  |  | |||
							
								
								
									
										59
									
								
								src/vhd.h
									
										
									
									
									
								
							
							
						
						
									
										59
									
								
								src/vhd.h
									
										
									
									
									
								
							|  | @ -23,23 +23,6 @@ | |||
| 
 | ||||
| #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_HAS_API_EXTRACT					1 | ||||
| #define WIM_HAS_7Z_EXTRACT					2 | ||||
|  | @ -142,40 +125,6 @@ enum WIMMessage { | |||
| 	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 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); | ||||
|  | @ -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 char* WimMountImage(const char* image, int index); | ||||
| 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 int8_t IsBootableImage(const char* path); | ||||
| extern void SaveVHD(void); | ||||
| extern void SaveISO(void); | ||||
| extern char* VhdMountImage(const char* path); | ||||
| 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 (!img_report.is_windows_img) { | ||||
| 		mounted_iso = MountISO(image_path); | ||||
| 		mounted_iso = VhdMountImage(image_path); | ||||
| 		if (mounted_iso == NULL) { | ||||
| 			uprintf("Could not mount Windows ISO for build number detection"); | ||||
| 			return FALSE; | ||||
|  | @ -468,7 +468,7 @@ BOOL PopulateWindowsVersion(void) | |||
| out: | ||||
| 	DeleteFileU(xml_file); | ||||
| 	if (!img_report.is_windows_img) | ||||
| 		UnMountISO(); | ||||
| 		VhdUnmountImage(); | ||||
| 
 | ||||
| 	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 (!img_report.is_windows_img) { | ||||
| 		mounted_iso = MountISO(image_path); | ||||
| 		mounted_iso = VhdMountImage(image_path); | ||||
| 		if (mounted_iso == NULL) { | ||||
| 			uprintf("Could not mount ISO for Windows To Go selection"); | ||||
| 			return -1; | ||||
|  | @ -613,7 +613,7 @@ int SetWinToGoIndex(void) | |||
| out: | ||||
| 	DeleteFileU(xml_file); | ||||
| 	if (!img_report.is_windows_img) | ||||
| 		UnMountISO(); | ||||
| 		VhdUnmountImage(); | ||||
| 	return wintogo_index; | ||||
| } | ||||
| 
 | ||||
|  | @ -640,7 +640,7 @@ BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp) | |||
| 	} | ||||
| 
 | ||||
| 	if (!img_report.is_windows_img) { | ||||
| 		mounted_iso = MountISO(image_path); | ||||
| 		mounted_iso = VhdMountImage(image_path); | ||||
| 		if (mounted_iso == NULL) { | ||||
| 			uprintf("Could not mount ISO for Windows To Go installation"); | ||||
| 			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)) | ||||
| 			FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_ISO_EXTRACT); | ||||
| 		if (!img_report.is_windows_img) | ||||
| 			UnMountISO(); | ||||
| 			VhdUnmountImage(); | ||||
| 		return FALSE; | ||||
| 	} | ||||
| 	if (!img_report.is_windows_img) | ||||
| 		UnMountISO(); | ||||
| 		VhdUnmountImage(); | ||||
| 
 | ||||
| 	if (use_esp) { | ||||
| 		uprintf("Setting up EFI System Partition"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue