mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[core] enable the direct provision of install.wim/install.esd for Windows To Go
* Also remove the use of 'unattend.xml' to disable the recovery environment (use bcdedit instead) * Also some code cleanup and refactoring
This commit is contained in:
		
							parent
							
								
									4617f91e3b
								
							
						
					
					
						commit
						34b1d8a3ca
					
				
					 12 changed files with 316 additions and 194 deletions
				
			
		|  | @ -1,11 +0,0 @@ | ||||||
| <?xml version='1.0' encoding='utf-8' standalone='yes'?> |  | ||||||
| <unattend xmlns="urn:schemas-microsoft-com:unattend"> |  | ||||||
| 	<settings pass="offlineServicing"> |  | ||||||
| 		<component name="Microsoft-Windows-PartitionManager" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |  | ||||||
| 			<SanPolicy>4</SanPolicy> |  | ||||||
| 		</component> |  | ||||||
| 		<component name="Microsoft-Windows-PartitionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |  | ||||||
| 			<SanPolicy>4</SanPolicy> |  | ||||||
| 		</component> |  | ||||||
| 	</settings> |  | ||||||
| </unattend> |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| <?xml version="1.0" encoding="utf-8"?> |  | ||||||
| <unattend xmlns="urn:schemas-microsoft-com:unattend"> |  | ||||||
| 	<settings pass="oobeSystem"> |  | ||||||
| 		<component name="Microsoft-Windows-WinRE-RecoveryAgent" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |  | ||||||
| 			<UninstallWindowsRE>true</UninstallWindowsRE> |  | ||||||
| 		</component> |  | ||||||
| 		<component name="Microsoft-Windows-WinRE-RecoveryAgent" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |  | ||||||
| 			<UninstallWindowsRE>true</UninstallWindowsRE> |  | ||||||
| 		</component> |  | ||||||
| 	</settings> |  | ||||||
| </unattend> |  | ||||||
							
								
								
									
										99
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										99
									
								
								src/format.c
									
										
									
									
									
								
							|  | @ -1220,8 +1220,8 @@ out: | ||||||
| // Returns -2 on user cancel, -1 on other error, >=0 on success.
 | // Returns -2 on user cancel, -1 on other error, >=0 on success.
 | ||||||
| int SetWinToGoIndex(void) | int SetWinToGoIndex(void) | ||||||
| { | { | ||||||
| 	char *mounted_iso, *build, image[128]; | 	char *mounted_iso, *build, mounted_image_path[128]; | ||||||
| 	char tmp_path[MAX_PATH] = "", xml_file[MAX_PATH] = ""; | 	char xml_file[MAX_PATH] = ""; | ||||||
| 	char *install_names[MAX_WININST]; | 	char *install_names[MAX_WININST]; | ||||||
| 	StrArray version_name, version_index; | 	StrArray version_name, version_index; | ||||||
| 	int i, build_nr = 0; | 	int i, build_nr = 0; | ||||||
|  | @ -1230,7 +1230,7 @@ int SetWinToGoIndex(void) | ||||||
| 	// Sanity checks
 | 	// Sanity checks
 | ||||||
| 	wintogo_index = -1; | 	wintogo_index = -1; | ||||||
| 	wininst_index = 0; | 	wininst_index = 0; | ||||||
| 	if ((nWindowsVersion < WINDOWS_8) || ((WimExtractCheck() & 4) == 0) || | 	if ((nWindowsVersion < WINDOWS_8) || ((WimExtractCheck(FALSE) & 4) == 0) || | ||||||
| 		(ComboBox_GetCurItemData(hFileSystem) != FS_NTFS)) { | 		(ComboBox_GetCurItemData(hFileSystem) != FS_NTFS)) { | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  | @ -1247,18 +1247,18 @@ int SetWinToGoIndex(void) | ||||||
| 			wininst_index = 0; | 			wininst_index = 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Mount the install.wim image, that resides on the ISO
 | 	// If we're not using a straigth install.wim, we need to mount the ISO to access it
 | ||||||
|  | 	if (!img_report.is_windows_img) { | ||||||
| 		mounted_iso = MountISO(image_path); | 		mounted_iso = MountISO(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 FALSE; | 			return FALSE; | ||||||
| 		} | 		} | ||||||
| 	static_sprintf(image, "%s%s", mounted_iso, &img_report.wininst_path[wininst_index][2]); | 		static_sprintf(mounted_image_path, "%s%s", mounted_iso, &img_report.wininst_path[wininst_index][2]); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	// Now take a look at the XML file in install.wim to list our versions
 | 	// Now take a look at the XML file in install.wim to list our versions
 | ||||||
| 	if ((GetTempPathU(sizeof(tmp_path), tmp_path) == 0) | 	if ((GetTempFileNameU(temp_dir, APPLICATION_NAME, 0, xml_file) == 0) || (xml_file[0] == 0)) { | ||||||
| 		|| (GetTempFileNameU(tmp_path, APPLICATION_NAME, 0, xml_file) == 0) |  | ||||||
| 		|| (xml_file[0] == 0)) { |  | ||||||
| 		// Last ditch effort to get a tmp file - just extract it to the current directory
 | 		// Last ditch effort to get a tmp file - just extract it to the current directory
 | ||||||
| 		static_strcpy(xml_file, ".\\RufVXml.tmp"); | 		static_strcpy(xml_file, ".\\RufVXml.tmp"); | ||||||
| 	} | 	} | ||||||
|  | @ -1266,7 +1266,8 @@ int SetWinToGoIndex(void) | ||||||
| 	DeleteFileU(xml_file); | 	DeleteFileU(xml_file); | ||||||
| 
 | 
 | ||||||
| 	// Must use the Windows WIM API as 7z messes up the XML
 | 	// Must use the Windows WIM API as 7z messes up the XML
 | ||||||
| 	if (!WimExtractFile_API(image, 0, "[1].xml", xml_file)) { | 	if (!WimExtractFile_API(img_report.is_windows_img ? image_path : mounted_image_path, | ||||||
|  | 		0, "[1].xml", xml_file, FALSE)) { | ||||||
| 		uprintf("Could not acquire WIM index"); | 		uprintf("Could not acquire WIM index"); | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
|  | @ -1328,25 +1329,19 @@ int SetWinToGoIndex(void) | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	DeleteFileU(xml_file); | 	DeleteFileU(xml_file); | ||||||
|  | 	if (!img_report.is_windows_img) | ||||||
| 		UnMountISO(); | 		UnMountISO(); | ||||||
| 	return wintogo_index; | 	return wintogo_index; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // http://technet.microsoft.com/en-ie/library/jj721578.aspx
 | // http://technet.microsoft.com/en-ie/library/jj721578.aspx
 | ||||||
| // As opposed to the technet guide above, we no longer set internal drives offline,
 | // As opposed to the technet guide above, we don't set internal drives offline,
 | ||||||
| // due to people wondering why they can't see them by default.
 | // due to people wondering why they can't see them by default and we also use
 | ||||||
| //#define SET_INTERNAL_DRIVES_OFFLINE
 | // bcdedit rather than 'unattend.xml' to disable the recovery environment.
 | ||||||
| static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp) | static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp) | ||||||
| { | { | ||||||
| #ifdef SET_INTERNAL_DRIVES_OFFLINE | 	char *mounted_iso, *ms_efi = NULL, mounted_image_path[128], cmd[MAX_PATH]; | ||||||
| 	static char san_policy_path[] = "?:\\san_policy.xml"; |  | ||||||
| #endif |  | ||||||
| 	static char unattend_path[] = "?:\\Windows\\System32\\sysprep\\unattend.xml"; |  | ||||||
| 	char *mounted_iso, *ms_efi = NULL, image[128], cmd[MAX_PATH]; |  | ||||||
| 	unsigned char *buffer; |  | ||||||
| 	DWORD bufsize; |  | ||||||
| 	ULONG cluster_size; | 	ULONG cluster_size; | ||||||
| 	FILE* fd; |  | ||||||
| 
 | 
 | ||||||
| 	uprintf("Windows To Go mode selected"); | 	uprintf("Windows To Go mode selected"); | ||||||
| 	// Additional sanity checks
 | 	// Additional sanity checks
 | ||||||
|  | @ -1355,24 +1350,27 @@ static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// First, we need to access the install.wim image, that resides on the ISO
 | 	if (!img_report.is_windows_img) { | ||||||
| 		mounted_iso = MountISO(image_path); | 		mounted_iso = MountISO(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); | ||||||
| 			return FALSE; | 			return FALSE; | ||||||
| 		} | 		} | ||||||
| 	static_sprintf(image, "%s%s", mounted_iso, &img_report.wininst_path[wininst_index][2]); | 		static_sprintf(mounted_image_path, "%s%s", mounted_iso, &img_report.wininst_path[wininst_index][2]); | ||||||
| 		uprintf("Mounted ISO as '%s'", mounted_iso); | 		uprintf("Mounted ISO as '%s'", mounted_iso); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	// Now we use the WIM API to apply that image
 | 	// Now we use the WIM API to apply that image
 | ||||||
| 	if (!WimApplyImage(image, wintogo_index, drive_name)) { | 	if (!WimApplyImage(img_report.is_windows_img ? image_path : mounted_image_path, wintogo_index, drive_name)) { | ||||||
| 		uprintf("Failed to apply Windows To Go image"); | 		uprintf("Failed to apply Windows To Go image"); | ||||||
| 		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) | ||||||
| 			UnMountISO(); | 			UnMountISO(); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
|  | 	if (!img_report.is_windows_img) | ||||||
| 		UnMountISO(); | 		UnMountISO(); | ||||||
| 
 | 
 | ||||||
| 	if (use_esp) { | 	if (use_esp) { | ||||||
|  | @ -1406,59 +1404,35 @@ static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// We invoke the 'bcdboot' command from the host, as the one from the drive produces problems (#558)
 | 	// We invoke the 'bcdboot' command from the host, as the one from the drive produces problems (#558)
 | ||||||
|  | 	// and of course, we couldn't invoke an ARM64 'bcdboot' binary on an x86 host anyway...
 | ||||||
| 	// Also, since Rufus should (usually) be running as a 32 bit app, on 64 bit systems, we need to use
 | 	// Also, since Rufus should (usually) be running as a 32 bit app, on 64 bit systems, we need to use
 | ||||||
| 	// 'C:\Windows\Sysnative' and not 'C:\Windows\System32' to invoke bcdboot, as 'C:\Windows\System32'
 | 	// 'C:\Windows\Sysnative' and not 'C:\Windows\System32' to invoke bcdboot, as 'C:\Windows\System32'
 | ||||||
| 	// will get converted to 'C:\Windows\SysWOW64' behind the scenes, and there is no bcdboot.exe there.
 | 	// will get converted to 'C:\Windows\SysWOW64' behind the scenes, and there is no bcdboot.exe there.
 | ||||||
|  | 	uprintf("Enabling boot using command:"); | ||||||
| 	static_sprintf(cmd, "%s\\bcdboot.exe %s\\Windows /v /f %s /s %s", sysnative_dir, drive_name, | 	static_sprintf(cmd, "%s\\bcdboot.exe %s\\Windows /v /f %s /s %s", sysnative_dir, drive_name, | ||||||
| 		HAS_BOOTMGR_BIOS(img_report) ? (HAS_BOOTMGR_EFI(img_report) ? "ALL" : "BIOS") : "UEFI", | 		HAS_BOOTMGR_BIOS(img_report) ? (HAS_BOOTMGR_EFI(img_report) ? "ALL" : "BIOS") : "UEFI", | ||||||
| 		(use_esp)?ms_efi:drive_name); | 		(use_esp)?ms_efi:drive_name); | ||||||
| 	uprintf("Enabling boot using command '%s'", cmd); | 	uprintf(cmd); | ||||||
| 	if (RunCommand(cmd, sysnative_dir, usb_debug) != 0) { | 	if (RunCommand(cmd, sysnative_dir, usb_debug) != 0) { | ||||||
| 		// Try to continue... but report a failure
 | 		// Try to continue... but report a failure
 | ||||||
| 		uprintf("Failed to enable boot"); | 		uprintf("Failed to enable boot"); | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_ISO_EXTRACT); | 		FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_ISO_EXTRACT); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	UpdateProgressWithInfo(OP_FILE_COPY, MSG_267, wim_proc_files + 2 * wim_extra_files, wim_nb_files); | ||||||
|  | 
 | ||||||
|  | 	uprintf("Disable the use of the Windows Recovery Environment using command:"); | ||||||
|  | 	static_sprintf(cmd, "%s\\bcdedit.exe /store %s\\EFI\\Microsoft\\Boot\\BCD /set {default} recoveryenabled no", | ||||||
|  | 		sysnative_dir, (use_esp) ? ms_efi : drive_name); | ||||||
|  | 	uprintf(cmd); | ||||||
|  | 	RunCommand(cmd, sysnative_dir, usb_debug); | ||||||
|  | 
 | ||||||
|  | 	UpdateProgressWithInfo(OP_FILE_COPY, MSG_267, wim_nb_files, wim_nb_files); | ||||||
|  | 
 | ||||||
| 	if (use_esp) { | 	if (use_esp) { | ||||||
| 		Sleep(200); | 		Sleep(200); | ||||||
| 		AltUnmountVolume(ms_efi, FALSE); | 		AltUnmountVolume(ms_efi, FALSE); | ||||||
| 	} | 	} | ||||||
| 	UpdateProgressWithInfo(OP_FILE_COPY, MSG_267, wim_proc_files + 2 * wim_extra_files, wim_nb_files); |  | ||||||
| 
 |  | ||||||
| 	// The following are non fatal if they fail
 |  | ||||||
| 
 |  | ||||||
| #ifdef SET_INTERNAL_DRIVES_OFFLINE |  | ||||||
| 	uprintf("Applying 'san_policy.xml', to set the target's internal drives offline..."); |  | ||||||
| 	buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_TOGO_SAN_POLICY_XML), |  | ||||||
| 		_RT_RCDATA, "san_policy.xml", &bufsize, FALSE); |  | ||||||
| 	san_policy_path[0] = drive_name[0]; |  | ||||||
| 	fd = fopenU(san_policy_path, "wb"); |  | ||||||
| 	if ((fd == NULL) || (fwrite(buffer, 1, bufsize, fd) != bufsize)) { |  | ||||||
| 		uprintf("Could not write '%s'\n", san_policy_path); |  | ||||||
| 		if (fd) |  | ||||||
| 			fclose(fd); |  | ||||||
| 	} else { |  | ||||||
| 		fclose(fd); |  | ||||||
| 		// Can't use the one from the USB (at least for Windows 10 preview), as you'll get
 |  | ||||||
| 		// "Error: 0x800401f0  An error occurred while initializing COM security".
 |  | ||||||
| 		// On the other hand, using Windows 8.1 dism against Windows 10 doesn't work either
 |  | ||||||
| 		// (you get a message about needing to upgrade to latest AIK)...
 |  | ||||||
| 		static_sprintf(cmd, "dism /Image:%s\\ /Apply-Unattend:%s", drive_name, san_policy_path); |  | ||||||
| 		if (RunCommand(cmd, NULL, TRUE) != 0) |  | ||||||
| 			uprintf("Command '%s' failed to run", cmd); |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 	uprintf("Copying 'unattend.xml', to disable the use of the Windows Recovery Environment..."); |  | ||||||
| 	buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_TOGO_UNATTEND_XML), |  | ||||||
| 		_RT_RCDATA, "unattend.xml", &bufsize, FALSE); |  | ||||||
| 	unattend_path[0] = drive_name[0]; |  | ||||||
| 	fd = fopenU(unattend_path, "wb"); |  | ||||||
| 	if ((fd == NULL) || (fwrite(buffer, 1, bufsize, fd) != bufsize)) |  | ||||||
| 		uprintf("Could not write '%s'", unattend_path); |  | ||||||
| 	if (fd != NULL) |  | ||||||
| 		fclose(fd); |  | ||||||
| 	UpdateProgressWithInfo(OP_FILE_COPY, MSG_267, wim_nb_files, wim_nb_files); |  | ||||||
| 
 | 
 | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
|  | @ -2145,7 +2119,7 @@ DWORD WINAPI FormatThread(void* param) | ||||||
| 				IsFileInDB(FILES_DIR "\\grub4dos-" GRUB4DOS_VERSION "\\grldr")?"✓":"✗"); | 				IsFileInDB(FILES_DIR "\\grub4dos-" GRUB4DOS_VERSION "\\grldr")?"✓":"✗"); | ||||||
| 			if (!CopyFileU(FILES_DIR "\\grub4dos-" GRUB4DOS_VERSION "\\grldr", grub4dos_dst, FALSE)) | 			if (!CopyFileU(FILES_DIR "\\grub4dos-" GRUB4DOS_VERSION "\\grldr", grub4dos_dst, FALSE)) | ||||||
| 				uprintf("Failed to copy file: %s", WindowsErrorString()); | 				uprintf("Failed to copy file: %s", WindowsErrorString()); | ||||||
| 		} else if ((boot_type == BT_IMAGE) && (image_path != NULL) && (img_report.is_iso)) { | 		} else if ((boot_type == BT_IMAGE) && (image_path != NULL) && (img_report.is_iso || img_report.is_windows_img)) { | ||||||
| 			UpdateProgress(OP_FILE_COPY, 0.0f); | 			UpdateProgress(OP_FILE_COPY, 0.0f); | ||||||
| 			drive_name[2] = 0;	// Ensure our drive is something like 'D:'
 | 			drive_name[2] = 0;	// Ensure our drive is something like 'D:'
 | ||||||
| 			if (windows_to_go) { | 			if (windows_to_go) { | ||||||
|  | @ -2156,6 +2130,7 @@ DWORD WINAPI FormatThread(void* param) | ||||||
| 					goto out; | 					goto out; | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
|  | 				assert(!img_report.is_windows_img); | ||||||
| 				if (!ExtractISO(image_path, drive_name, FALSE)) { | 				if (!ExtractISO(image_path, drive_name, FALSE)) { | ||||||
| 					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); | ||||||
|  | @ -2180,7 +2155,7 @@ DWORD WINAPI FormatThread(void* param) | ||||||
| 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH); | 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH); | ||||||
| 					} else { | 					} else { | ||||||
| 						efi_dst[sizeof(efi_dst) - sizeof("\\bootx64.efi")] = '\\'; | 						efi_dst[sizeof(efi_dst) - sizeof("\\bootx64.efi")] = '\\'; | ||||||
| 						if (!WimExtractFile(img_report.wininst_path[0], 1, "Windows\\Boot\\EFI\\bootmgfw.efi", efi_dst)) { | 						if (!WimExtractFile(img_report.wininst_path[0], 1, "Windows\\Boot\\EFI\\bootmgfw.efi", efi_dst, FALSE)) { | ||||||
| 							uprintf("Failed to setup Win7 EFI boot"); | 							uprintf("Failed to setup Win7 EFI boot"); | ||||||
| 							FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH); | 							FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH); | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
|  | @ -89,7 +89,8 @@ static const char* ldlinux_c32 = "ldlinux.c32"; | ||||||
| static const char* md5sum_name[] = { "MD5SUMS", "md5sum.txt" }; | static const char* md5sum_name[] = { "MD5SUMS", "md5sum.txt" }; | ||||||
| static const char* casper_dirname = "/casper"; | static const char* casper_dirname = "/casper"; | ||||||
| static const char* efi_dirname = "/efi/boot"; | static const char* efi_dirname = "/efi/boot"; | ||||||
| static const char* efi_bootname[] = { "bootia32.efi", "bootia64.efi", "bootx64.efi", "bootarm.efi", "bootaa64.efi", "bootebc.efi" }; | static const char* efi_bootname[MAX_ARCHS] = | ||||||
|  | 	{ "bootia32.efi", "bootia64.efi", "bootx64.efi", "bootarm.efi", "bootaa64.efi", "bootebc.efi" }; | ||||||
| static const char* sources_str = "/sources"; | static const char* sources_str = "/sources"; | ||||||
| static const char* wininst_name[] = { "install.wim", "install.esd", "install.swm" }; | static const char* wininst_name[] = { "install.wim", "install.esd", "install.swm" }; | ||||||
| // We only support GRUB/BIOS (x86) that uses a standard config dir (/boot/grub/i386-pc/)
 | // We only support GRUB/BIOS (x86) that uses a standard config dir (/boot/grub/i386-pc/)
 | ||||||
|  | @ -1044,7 +1045,7 @@ out: | ||||||
| 		if (img_report.has_grub2) { | 		if (img_report.has_grub2) { | ||||||
| 			// In case we have a GRUB2 based iso, we extract boot/grub/i386-pc/normal.mod to parse its version
 | 			// In case we have a GRUB2 based iso, we extract boot/grub/i386-pc/normal.mod to parse its version
 | ||||||
| 			img_report.grub2_version[0] = 0; | 			img_report.grub2_version[0] = 0; | ||||||
| 			if ((GetTempPathU(sizeof(path), path) != 0) && (GetTempFileNameU(path, APPLICATION_NAME, 0, path) != 0)) { | 			if (GetTempFileNameU(temp_dir, APPLICATION_NAME, 0, path) != 0) { | ||||||
| 				size = (size_t)ExtractISOFile(src_iso, "boot/grub/i386-pc/normal.mod", path, FILE_ATTRIBUTE_NORMAL); | 				size = (size_t)ExtractISOFile(src_iso, "boot/grub/i386-pc/normal.mod", path, FILE_ATTRIBUTE_NORMAL); | ||||||
| 				buf = (char*)calloc(size, 1); | 				buf = (char*)calloc(size, 1); | ||||||
| 				fd = fopen(path, "rb"); | 				fd = fopen(path, "rb"); | ||||||
|  |  | ||||||
|  | @ -1130,6 +1130,26 @@ static __inline int _rmdirU(const char* dirname) | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static __inline BOOL MoveFileU(const char* lpExistingFileName, const char* lpNewFileName) | ||||||
|  | { | ||||||
|  | 	wconvert(lpExistingFileName); | ||||||
|  | 	wconvert(lpNewFileName); | ||||||
|  | 	BOOL ret = MoveFileW(wlpExistingFileName, wlpNewFileName); | ||||||
|  | 	wfree(lpNewFileName); | ||||||
|  | 	wfree(lpExistingFileName); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static __inline BOOL MoveFileExU(const char* lpExistingFileName, const char* lpNewFileName, DWORD dwFlags) | ||||||
|  | { | ||||||
|  | 	wconvert(lpExistingFileName); | ||||||
|  | 	wconvert(lpNewFileName); | ||||||
|  | 	BOOL ret = MoveFileExW(wlpExistingFileName, wlpNewFileName, dwFlags); | ||||||
|  | 	wfree(lpNewFileName); | ||||||
|  | 	wfree(lpExistingFileName); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // The following expects PropertyBuffer to contain a single Unicode string
 | // The following expects PropertyBuffer to contain a single Unicode string
 | ||||||
| static __inline BOOL SetupDiGetDeviceRegistryPropertyU(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, | static __inline BOOL SetupDiGetDeviceRegistryPropertyU(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, | ||||||
| 	DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize) | 	DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize) | ||||||
|  |  | ||||||
|  | @ -90,8 +90,6 @@ | ||||||
| #define IDR_LC_RUFUS_LOC                500 | #define IDR_LC_RUFUS_LOC                500 | ||||||
| #define IDR_XT_HOGGER                   501 | #define IDR_XT_HOGGER                   501 | ||||||
| #define IDR_UEFI_NTFS                   502 | #define IDR_UEFI_NTFS                   502 | ||||||
| #define IDR_TOGO_SAN_POLICY_XML         503 |  | ||||||
| #define IDR_TOGO_UNATTEND_XML           504 |  | ||||||
| #define IDM_SELECT                      901 | #define IDM_SELECT                      901 | ||||||
| #define IDM_DOWNLOAD                    902 | #define IDM_DOWNLOAD                    902 | ||||||
| #define IDC_DEVICE                      1001 | #define IDC_DEVICE                      1001 | ||||||
|  |  | ||||||
							
								
								
									
										149
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										149
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -62,10 +62,11 @@ enum bootcheck_return { | ||||||
| static const char* cmdline_hogger = "rufus.com"; | static const char* cmdline_hogger = "rufus.com"; | ||||||
| static const char* ep_reg = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"; | static const char* ep_reg = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"; | ||||||
| static const char* vs_reg = "Software\\Microsoft\\VisualStudio"; | static const char* vs_reg = "Software\\Microsoft\\VisualStudio"; | ||||||
|  | static const char* arch_name[MAX_ARCHS] = { "x86_32", "Itanic", "x86_64", "ARM", "ARM64", "EBC" }; | ||||||
| static BOOL existing_key = FALSE;	// For LGP set/restore
 | static BOOL existing_key = FALSE;	// For LGP set/restore
 | ||||||
| static BOOL size_check = TRUE; | static BOOL size_check = TRUE; | ||||||
| static BOOL log_displayed = FALSE; | static BOOL log_displayed = FALSE; | ||||||
| static BOOL iso_provided = FALSE; | static BOOL img_provided = FALSE; | ||||||
| static BOOL user_notified = FALSE; | static BOOL user_notified = FALSE; | ||||||
| static BOOL relaunch = FALSE; | static BOOL relaunch = FALSE; | ||||||
| static BOOL dont_display_image_name = FALSE; | static BOOL dont_display_image_name = FALSE; | ||||||
|  | @ -118,8 +119,9 @@ BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fa | ||||||
| BOOL use_fake_units, preserve_timestamps = FALSE, fast_zeroing = FALSE, app_changed_size = FALSE; | BOOL 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, installed_uefi_ntfs = FALSE, use_vds = FALSE; | BOOL write_as_image = FALSE, write_as_esp = FALSE, installed_uefi_ntfs = FALSE, use_vds = FALSE; | ||||||
|  | BOOL windows_to_go_selected = FALSE; | ||||||
| float fScale = 1.0f; | float fScale = 1.0f; | ||||||
| int dialog_showing = 0, selection_default = BT_IMAGE, windows_to_go_selection = 0, persistence_unit_selection = -1; | int dialog_showing = 0, selection_default = BT_IMAGE, persistence_unit_selection = -1; | ||||||
| int default_fs, fs_type, boot_type, partition_type, target_type; // file system, boot type, partition type, target type
 | int default_fs, fs_type, boot_type, partition_type, target_type; // file system, boot type, partition type, target type
 | ||||||
| int force_update = 0, default_thread_priority = THREAD_PRIORITY_ABOVE_NORMAL; | int force_update = 0, default_thread_priority = THREAD_PRIORITY_ABOVE_NORMAL; | ||||||
| char szFolderPath[MAX_PATH], app_dir[MAX_PATH], system_dir[MAX_PATH], temp_dir[MAX_PATH], sysnative_dir[MAX_PATH]; | char szFolderPath[MAX_PATH], app_dir[MAX_PATH], system_dir[MAX_PATH], temp_dir[MAX_PATH], sysnative_dir[MAX_PATH]; | ||||||
|  | @ -315,7 +317,7 @@ static void SetPartitionSchemeAndTargetSystem(BOOL only_target) | ||||||
| 			preferred_pt = (selected_pt >= 0) ? selected_pt : PARTITION_STYLE_MBR; | 			preferred_pt = (selected_pt >= 0) ? selected_pt : PARTITION_STYLE_MBR; | ||||||
| 		else if (boot_type == BT_UEFI_NTFS) | 		else if (boot_type == BT_UEFI_NTFS) | ||||||
| 			preferred_pt = (selected_pt >= 0) ? selected_pt : PARTITION_STYLE_GPT; | 			preferred_pt = (selected_pt >= 0) ? selected_pt : PARTITION_STYLE_GPT; | ||||||
| 		else if ((boot_type == BT_IMAGE) && (image_path != NULL) && (img_report.is_iso)) { | 		else if ((boot_type == BT_IMAGE) && (image_path != NULL) && (img_report.is_iso || img_report.is_windows_img)) { | ||||||
| 			if (HAS_WINDOWS(img_report) && img_report.has_efi) | 			if (HAS_WINDOWS(img_report) && img_report.has_efi) | ||||||
| 				preferred_pt = allow_dual_uefi_bios? PARTITION_STYLE_MBR : | 				preferred_pt = allow_dual_uefi_bios? PARTITION_STYLE_MBR : | ||||||
| 					((selected_pt >= 0) ? selected_pt : PARTITION_STYLE_GPT); | 					((selected_pt >= 0) ? selected_pt : PARTITION_STYLE_GPT); | ||||||
|  | @ -849,7 +851,8 @@ static void EnableControls(BOOL enable, BOOL remove_checkboxes) | ||||||
| 	EnableBootOptions(enable, remove_checkboxes); | 	EnableBootOptions(enable, remove_checkboxes); | ||||||
| 
 | 
 | ||||||
| 	// Finally, only enable the half-size dropdowns if we aren't dealing with a pure DD image
 | 	// Finally, only enable the half-size dropdowns if we aren't dealing with a pure DD image
 | ||||||
| 	enable = ((boot_type == BT_IMAGE) && (image_path != NULL) && (!img_report.is_iso)) ? FALSE : enable; | 	enable = ((boot_type == BT_IMAGE) && (image_path != NULL) && | ||||||
|  | 		(!(img_report.is_iso || img_report.is_windows_img))) ? FALSE : enable; | ||||||
| 	EnableWindow(hPartitionScheme, enable); | 	EnableWindow(hPartitionScheme, enable); | ||||||
| 	EnableWindow(hTargetSystem, enable); | 	EnableWindow(hTargetSystem, enable); | ||||||
| 	EnableWindow(GetDlgItem(hMainDialog, IDS_CSM_HELP_TXT), enable); | 	EnableWindow(GetDlgItem(hMainDialog, IDS_CSM_HELP_TXT), enable); | ||||||
|  | @ -1086,11 +1089,12 @@ static void DisplayISOProps(void) | ||||||
| 		"  Because of this, the size required for the target media may be much larger than size of the ISO..."); | 		"  Because of this, the size required for the target media may be much larger than size of the ISO..."); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Insert the image name into the Boot selection dropdown
 | // Insert the image name into the Boot selection dropdown and (re)populate the Image option dropdown
 | ||||||
| static void UpdateImage(void) | static void UpdateImage(BOOL update_image_option_only) | ||||||
| { | { | ||||||
| 	assert(image_index != 0); | 	assert(image_index != 0); | ||||||
| 
 | 
 | ||||||
|  | 	if (!update_image_option_only) { | ||||||
| 		if (ComboBox_GetItemData(hBootType, image_index) == BT_IMAGE) | 		if (ComboBox_GetItemData(hBootType, image_index) == BT_IMAGE) | ||||||
| 			ComboBox_DeleteString(hBootType, image_index); | 			ComboBox_DeleteString(hBootType, image_index); | ||||||
| 		ComboBox_InsertStringU(hBootType, image_index, | 		ComboBox_InsertStringU(hBootType, image_index, | ||||||
|  | @ -1101,10 +1105,85 @@ static void UpdateImage(void) | ||||||
| 		SetBootTypeDropdownWidth(); | 		SetBootTypeDropdownWidth(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	ComboBox_ResetContent(hImageOption); | ||||||
|  | 	if (!img_report.is_windows_img) | ||||||
|  | 		IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_117)), FALSE)); | ||||||
|  | 	IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_118)), TRUE)); | ||||||
|  | 	IGNORE_RETVAL(ComboBox_SetCurSel(hImageOption, (img_report.is_windows_img || !windows_to_go_selected) ? 0 : 1)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static uint8_t FindArch(const char* filename) | ||||||
|  | { | ||||||
|  | 	uint8_t ret = 0; | ||||||
|  | 	HANDLE hFile = NULL, hFileMapping = NULL; | ||||||
|  | 	PIMAGE_DOS_HEADER pImageDOSHeader = NULL; | ||||||
|  | 	// NB: The field we are after is at the same location for 32 and 64-bit
 | ||||||
|  | 	// PE headers, so we don't need to care about using PIMAGE_NT_HEADERS[32|64]
 | ||||||
|  | 	PIMAGE_NT_HEADERS pImageNTHeader = NULL; | ||||||
|  | 
 | ||||||
|  | 	hFile = CreateFileU(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | ||||||
|  | 	if (hFile == NULL) { | ||||||
|  | 		uprintf("FindArch: Could not open file '%s': %s", filename, WindowsErrorString()); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); | ||||||
|  | 	if (hFileMapping == NULL) { | ||||||
|  | 		uprintf("FindArch: Could not create file mapping: %s", WindowsErrorString()); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pImageDOSHeader = (PIMAGE_DOS_HEADER)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); | ||||||
|  | 	if (pImageDOSHeader == NULL) { | ||||||
|  | 		uprintf("FindArch: Could not get mapped view address: %s", WindowsErrorString()); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	if (pImageDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) { | ||||||
|  | 		uprintf("FindArch: DOS header not found"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	pImageNTHeader = (PIMAGE_NT_HEADERS)((uintptr_t)pImageDOSHeader + pImageDOSHeader->e_lfanew); | ||||||
|  | 	if (pImageNTHeader->Signature != IMAGE_NT_SIGNATURE) { | ||||||
|  | 		uprintf("FindArch: NT header not found"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch (pImageNTHeader->FileHeader.Machine) { | ||||||
|  | 	case IMAGE_FILE_MACHINE_I386: | ||||||
|  | 		ret = 1; | ||||||
|  | 		break; | ||||||
|  | 	case IMAGE_FILE_MACHINE_IA64: | ||||||
|  | 		ret = 2; | ||||||
|  | 		break; | ||||||
|  | 	case IMAGE_FILE_MACHINE_AMD64: | ||||||
|  | 		ret = 3; | ||||||
|  | 		break; | ||||||
|  | 	case IMAGE_FILE_MACHINE_ARM: | ||||||
|  | 		ret = 4; | ||||||
|  | 		break; | ||||||
|  | 	case IMAGE_FILE_MACHINE_ARM64: | ||||||
|  | 		ret = 5; | ||||||
|  | 		break; | ||||||
|  | 	case IMAGE_FILE_MACHINE_EBC: | ||||||
|  | 		ret = 6; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	if (pImageDOSHeader != NULL) | ||||||
|  | 		UnmapViewOfFile(pImageDOSHeader); | ||||||
|  | 	safe_closehandle(hFileMapping); | ||||||
|  | 	safe_closehandle(hFile); | ||||||
|  | 	assert(ret <= MAX_ARCHS); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // The scanning process can be blocking for message processing => use a thread
 | // The scanning process can be blocking for message processing => use a thread
 | ||||||
| DWORD WINAPI ISOScanThread(LPVOID param) | DWORD WINAPI ImageScanThread(LPVOID param) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
|  | 	uint8_t arch; | ||||||
|  | 	char tmp_path[MAX_PATH]; | ||||||
| 
 | 
 | ||||||
| 	if (image_path == NULL) | 	if (image_path == NULL) | ||||||
| 		goto out; | 		goto out; | ||||||
|  | @ -1114,13 +1193,15 @@ DWORD WINAPI ISOScanThread(LPVOID param) | ||||||
| 	memset(&img_report, 0, sizeof(img_report)); | 	memset(&img_report, 0, sizeof(img_report)); | ||||||
| 	img_report.is_iso = (BOOLEAN)ExtractISO(image_path, "", TRUE); | 	img_report.is_iso = (BOOLEAN)ExtractISO(image_path, "", TRUE); | ||||||
| 	img_report.is_bootable_img = (BOOLEAN)IsBootableImage(image_path); | 	img_report.is_bootable_img = (BOOLEAN)IsBootableImage(image_path); | ||||||
|  | 	ComboBox_ResetContent(hImageOption); | ||||||
| 
 | 
 | ||||||
| 	if ((FormatStatus == (ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_CANCELLED)) || | 	if ((FormatStatus == (ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_CANCELLED)) || | ||||||
| 		(img_report.image_size == 0) || (!img_report.is_iso && !img_report.is_bootable_img)) { | 		(img_report.image_size == 0) || | ||||||
|  | 		(!img_report.is_iso && !img_report.is_bootable_img && !img_report.is_windows_img)) { | ||||||
| 		// Failed to scan image
 | 		// Failed to scan image
 | ||||||
| 		SendMessage(hMainDialog, UM_PROGRESS_EXIT, 0, 0); | 		SendMessage(hMainDialog, UM_PROGRESS_EXIT, 0, 0); | ||||||
| 		safe_free(image_path); | 		safe_free(image_path); | ||||||
| 		UpdateImage(); | 		UpdateImage(FALSE); | ||||||
| 		SetMBRProps(); | 		SetMBRProps(); | ||||||
| 		PopulateProperties(); | 		PopulateProperties(); | ||||||
| 		PrintInfoDebug(0, MSG_203); | 		PrintInfoDebug(0, MSG_203); | ||||||
|  | @ -1129,7 +1210,25 @@ DWORD WINAPI ISOScanThread(LPVOID param) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (img_report.is_bootable_img) { | 	if (img_report.is_windows_img) { | ||||||
|  | 		selection_default = BT_IMAGE; | ||||||
|  | 		if (GetTempFileNameU(temp_dir, APPLICATION_NAME, 0, tmp_path) != 0) { | ||||||
|  | 			// Only look at index 1 for now. If people complain, we may look for more.
 | ||||||
|  | 			if (WimExtractFile(image_path, 1, "Windows\\Boot\\EFI\\bootmgr.efi", tmp_path, TRUE)) { | ||||||
|  | 				arch = FindArch(tmp_path); | ||||||
|  | 				if (arch != 0) { | ||||||
|  | 					uprintf("  Image contains an %s EFI boot manager", arch_name[arch - 1]); | ||||||
|  | 					img_report.has_efi = 1 | (1 << arch); | ||||||
|  | 					img_report.has_bootmgr_efi = TRUE; | ||||||
|  | 					img_report.wininst_index = 1; | ||||||
|  | 				} else { | ||||||
|  | 					uprintf("  Image does not contain an EFI boot manager"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			DeleteFileU(tmp_path); | ||||||
|  | 		} | ||||||
|  | 		uprintf("  Image is %sa UEFI bootable Windows installation image", img_report.has_efi ? "" : "NOT "); | ||||||
|  | 	} else if (img_report.is_bootable_img) { | ||||||
| 		uprintf("  Image is a %sbootable %s image", | 		uprintf("  Image is a %sbootable %s image", | ||||||
| 			(img_report.compression_type != BLED_COMPRESSION_NONE) ? "compressed " : "", img_report.is_vhd ? "VHD" : "disk"); | 			(img_report.compression_type != BLED_COMPRESSION_NONE) ? "compressed " : "", img_report.is_vhd ? "VHD" : "disk"); | ||||||
| 		selection_default = BT_IMAGE; | 		selection_default = BT_IMAGE; | ||||||
|  | @ -1160,13 +1259,13 @@ DWORD WINAPI ISOScanThread(LPVOID param) | ||||||
| 				i++; | 				i++; | ||||||
| 			short_image_path = &image_path[i]; | 			short_image_path = &image_path[i]; | ||||||
| 			PrintStatus(0, MSG_205, short_image_path); | 			PrintStatus(0, MSG_205, short_image_path); | ||||||
| 			UpdateImage(); |  | ||||||
| 			uprintf("Using image: %s (%s)", short_image_path, SizeToHumanReadable(img_report.image_size, FALSE, FALSE)); | 			uprintf("Using image: %s (%s)", short_image_path, SizeToHumanReadable(img_report.image_size, FALSE, FALSE)); | ||||||
| 		} | 		} | ||||||
|  | 		UpdateImage(dont_display_image_name); | ||||||
| 		ToggleImageOptions(); | 		ToggleImageOptions(); | ||||||
| 		EnableControls(TRUE, FALSE); | 		EnableControls(TRUE, FALSE); | ||||||
| 		// Set Target and FS accordingly
 | 		// Set Target and FS accordingly
 | ||||||
| 		if (img_report.is_iso) { | 		if (img_report.is_iso || img_report.is_windows_img) { | ||||||
| 			IGNORE_RETVAL(ComboBox_SetCurSel(hBootType, image_index)); | 			IGNORE_RETVAL(ComboBox_SetCurSel(hBootType, image_index)); | ||||||
| 			SetPartitionSchemeAndTargetSystem(FALSE); | 			SetPartitionSchemeAndTargetSystem(FALSE); | ||||||
| 			SetFileSystemAndClusterSize(NULL); | 			SetFileSystemAndClusterSize(NULL); | ||||||
|  | @ -1266,7 +1365,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) | ||||||
| 				MessageBoxExU(hMainDialog, lmprintf(MSG_091), lmprintf(MSG_090), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); | 				MessageBoxExU(hMainDialog, lmprintf(MSG_091), lmprintf(MSG_090), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); | ||||||
| 				goto out; | 				goto out; | ||||||
| 			} | 			} | ||||||
| 			if (HAS_WIN7_EFI(img_report) && (!WimExtractCheck())) { | 			if (HAS_WIN7_EFI(img_report) && (!WimExtractCheck(FALSE))) { | ||||||
| 				// Your platform cannot extract files from WIM archives => download 7-zip?
 | 				// Your platform cannot extract files from WIM archives => download 7-zip?
 | ||||||
| 				if (MessageBoxExU(hMainDialog, lmprintf(MSG_102), lmprintf(MSG_101), MB_YESNO|MB_ICONERROR|MB_IS_RTL, selected_langid) == IDYES) | 				if (MessageBoxExU(hMainDialog, lmprintf(MSG_102), lmprintf(MSG_101), MB_YESNO|MB_ICONERROR|MB_IS_RTL, selected_langid) == IDYES) | ||||||
| 					ShellExecuteA(hMainDialog, "open", SEVENZIP_URL, NULL, NULL, SW_SHOWNORMAL); | 					ShellExecuteA(hMainDialog, "open", SEVENZIP_URL, NULL, NULL, SW_SHOWNORMAL); | ||||||
|  | @ -1680,10 +1779,6 @@ static void InitDialog(HWND hDlg) | ||||||
| 	// Fill up the boot options dropdown
 | 	// Fill up the boot options dropdown
 | ||||||
| 	SetBootOptions(); | 	SetBootOptions(); | ||||||
| 
 | 
 | ||||||
| 	// Fill up the Image Options Windows To Go dropdown
 |  | ||||||
| 	IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_117)), FALSE)); |  | ||||||
| 	IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_118)), TRUE)); |  | ||||||
| 
 |  | ||||||
| 	// Fill up the MBR masqueraded disk IDs ("8 disks should be enough for anybody")
 | 	// Fill up the MBR masqueraded disk IDs ("8 disks should be enough for anybody")
 | ||||||
| 	IGNORE_RETVAL(ComboBox_SetItemData(hDiskID, ComboBox_AddStringU(hDiskID, lmprintf(MSG_030, LEFT_TO_RIGHT_EMBEDDING "0x80" POP_DIRECTIONAL_FORMATTING)), 0x80)); | 	IGNORE_RETVAL(ComboBox_SetItemData(hDiskID, ComboBox_AddStringU(hDiskID, lmprintf(MSG_030, LEFT_TO_RIGHT_EMBEDDING "0x80" POP_DIRECTIONAL_FORMATTING)), 0x80)); | ||||||
| 	for (i=1; i<=7; i++) { | 	for (i=1; i<=7; i++) { | ||||||
|  | @ -1744,7 +1839,7 @@ static void InitDialog(HWND hDlg) | ||||||
| 	ToggleImageOptions(); | 	ToggleImageOptions(); | ||||||
| 
 | 
 | ||||||
| 	// Process commandline parameters
 | 	// Process commandline parameters
 | ||||||
| 	if (iso_provided) { | 	if (img_provided) { | ||||||
| 		// Simulate a button click for image selection
 | 		// Simulate a button click for image selection
 | ||||||
| 		PostMessage(hDlg, WM_COMMAND, IDC_SELECT, 0); | 		PostMessage(hDlg, WM_COMMAND, IDC_SELECT, 0); | ||||||
| 	} | 	} | ||||||
|  | @ -2134,7 +2229,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 			if (HIWORD(wParam) != CBN_SELCHANGE) | 			if (HIWORD(wParam) != CBN_SELCHANGE) | ||||||
| 				break; | 				break; | ||||||
| 			SetFileSystemAndClusterSize(NULL); | 			SetFileSystemAndClusterSize(NULL); | ||||||
| 			windows_to_go_selection = ComboBox_GetCurSel(hImageOption); | 			windows_to_go_selected = (BOOL)ComboBox_GetCurItemData(hImageOption); | ||||||
| 			break; | 			break; | ||||||
| 		case IDC_PERSISTENCE_SIZE: | 		case IDC_PERSISTENCE_SIZE: | ||||||
| 			if (HIWORD(wParam) == EN_CHANGE) { | 			if (HIWORD(wParam) == EN_CHANGE) { | ||||||
|  | @ -2260,13 +2355,13 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 				EnableControls(FALSE, FALSE); | 				EnableControls(FALSE, FALSE); | ||||||
| 				DownloadISO(); | 				DownloadISO(); | ||||||
| 			} else { | 			} else { | ||||||
| 				if (iso_provided) { | 				if (img_provided) { | ||||||
| 					uprintf("\r\nImage provided: '%s'", image_path); | 					uprintf("\r\nImage provided: '%s'", image_path); | ||||||
| 					iso_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; | ||||||
| 					// 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"), | 					EXT_DECL(img_ext, NULL, __VA_GROUP__("*.iso;*.img;*.vhd;*.usb;*.bz2;*.bzip2;*.gz;*.lzma;*.xz;*.Z;*.zip;*.wim;*.esd"), | ||||||
| 						__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) { | ||||||
|  | @ -2284,7 +2379,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				FormatStatus = 0; | 				FormatStatus = 0; | ||||||
| 				if (CreateThread(NULL, 0, ISOScanThread, NULL, 0, NULL) == NULL) { | 				if (CreateThread(NULL, 0, ImageScanThread, NULL, 0, NULL) == NULL) { | ||||||
| 					uprintf("Unable to start ISO scanning thread"); | 					uprintf("Unable to start ISO scanning thread"); | ||||||
| 					FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD); | 					FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD); | ||||||
| 				} | 				} | ||||||
|  | @ -2402,7 +2497,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 		break; | 		break; | ||||||
| 	case UM_SELECT_ISO: | 	case UM_SELECT_ISO: | ||||||
| 		select_index = 0; | 		select_index = 0; | ||||||
| 		iso_provided = TRUE; | 		img_provided = TRUE; | ||||||
| 		SetWindowTextU(GetDlgItem(hDlg, IDC_SELECT), uppercase_select[0]); | 		SetWindowTextU(GetDlgItem(hDlg, IDC_SELECT), uppercase_select[0]); | ||||||
| 		SendMessage(hDlg, WM_COMMAND, IDC_SELECT, 0); | 		SendMessage(hDlg, WM_COMMAND, IDC_SELECT, 0); | ||||||
| 		break; | 		break; | ||||||
|  | @ -2606,7 +2701,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 		safe_free(wbuffer); | 		safe_free(wbuffer); | ||||||
| 
 | 
 | ||||||
| 		if (image_path != NULL) { | 		if (image_path != NULL) { | ||||||
| 			iso_provided = TRUE; | 			img_provided = TRUE; | ||||||
| 			// Simulate image selection click
 | 			// Simulate image selection click
 | ||||||
| 			SendMessage(hDlg, WM_COMMAND, IDC_SELECT, 0); | 			SendMessage(hDlg, WM_COMMAND, IDC_SELECT, 0); | ||||||
| 		} | 		} | ||||||
|  | @ -3065,7 +3160,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| 					if (_access(optarg, 0) != -1) { | 					if (_access(optarg, 0) != -1) { | ||||||
| 						safe_free(image_path); | 						safe_free(image_path); | ||||||
| 						image_path = safe_strdup(optarg); | 						image_path = safe_strdup(optarg); | ||||||
| 						iso_provided = TRUE; | 						img_provided = TRUE; | ||||||
| 					} | 					} | ||||||
| 					else { | 					else { | ||||||
| 						printf("Could not find ISO image '%s'\n", optarg); | 						printf("Could not find ISO image '%s'\n", optarg); | ||||||
|  | @ -3490,7 +3585,7 @@ relaunch: | ||||||
| 				enable_iso = !enable_iso; | 				enable_iso = !enable_iso; | ||||||
| 				PrintStatusTimeout(lmprintf(MSG_262), enable_iso); | 				PrintStatusTimeout(lmprintf(MSG_262), enable_iso); | ||||||
| 				if (image_path != NULL) { | 				if (image_path != NULL) { | ||||||
| 					iso_provided = TRUE; | 					img_provided = TRUE; | ||||||
| 					dont_display_image_name = TRUE; | 					dont_display_image_name = TRUE; | ||||||
| 					SendMessage(hDlg, WM_COMMAND, IDC_SELECT, 0); | 					SendMessage(hDlg, WM_COMMAND, IDC_SELECT, 0); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.h
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.h
									
										
									
									
									
								
							|  | @ -62,6 +62,7 @@ | ||||||
| #define DRIVE_INDEX_MAX             0x000000C0 | #define DRIVE_INDEX_MAX             0x000000C0 | ||||||
| #define MIN_DRIVE_SIZE              8			// Minimum size a drive must have, to be formattable (in MB)
 | #define MIN_DRIVE_SIZE              8			// Minimum size a drive must have, to be formattable (in MB)
 | ||||||
| #define MIN_EXTRA_PART_SIZE         (1024*1024)	// Minimum size of the extra partition, in bytes
 | #define MIN_EXTRA_PART_SIZE         (1024*1024)	// Minimum size of the extra partition, in bytes
 | ||||||
|  | #define MAX_ARCHS                   6			// Number of arhitectures we recognize
 | ||||||
| #define MAX_DRIVES                  (DRIVE_INDEX_MAX - DRIVE_INDEX_MIN) | #define MAX_DRIVES                  (DRIVE_INDEX_MAX - DRIVE_INDEX_MIN) | ||||||
| #define MAX_TOOLTIPS                128 | #define MAX_TOOLTIPS                128 | ||||||
| #define MAX_SIZE_SUFFIXES           6			// bytes, KB, MB, GB, TB, PB
 | #define MAX_SIZE_SUFFIXES           6			// bytes, KB, MB, GB, TB, PB
 | ||||||
|  | @ -338,6 +339,7 @@ typedef struct { | ||||||
| 	BOOLEAN is_iso; | 	BOOLEAN is_iso; | ||||||
| 	BOOLEAN is_bootable_img; | 	BOOLEAN is_bootable_img; | ||||||
| 	BOOLEAN is_vhd; | 	BOOLEAN is_vhd; | ||||||
|  | 	BOOLEAN is_windows_img; | ||||||
| 	BOOLEAN disable_iso; | 	BOOLEAN disable_iso; | ||||||
| 	uint16_t winpe; | 	uint16_t winpe; | ||||||
| 	uint8_t has_efi; | 	uint8_t has_efi; | ||||||
|  | @ -555,10 +557,10 @@ extern char* replace_in_token_data(const char* filename, const char* token, cons | ||||||
| extern char* replace_char(const char* src, const char c, const char* rep); | extern char* replace_char(const char* src, const char c, const char* rep); | ||||||
| extern void parse_update(char* buf, size_t len); | extern void parse_update(char* buf, size_t len); | ||||||
| extern void* get_data_from_asn1(const uint8_t* buf, size_t buf_len, const char* oid_str, uint8_t asn1_type, size_t* data_len); | extern void* get_data_from_asn1(const uint8_t* buf, size_t buf_len, const char* oid_str, uint8_t asn1_type, size_t* data_len); | ||||||
| extern uint8_t WimExtractCheck(void); | extern uint8_t WimExtractCheck(BOOL bSilent); | ||||||
| extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst); | 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); | extern BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst, BOOL bSilent); | ||||||
| extern BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst); | extern BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst, BOOL bSilent); | ||||||
| extern BOOL WimApplyImage(const char* image, int index, const char* dst); | extern BOOL WimApplyImage(const char* image, int index, const char* dst); | ||||||
| extern BOOL IsBootableImage(const char* path); | extern BOOL IsBootableImage(const char* path); | ||||||
| extern BOOL AppendVHDFooter(const char* vhd_path); | extern BOOL AppendVHDFooter(const char* vhd_path); | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								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 3.12.1690" | CAPTION "Rufus 3.12.1691" | ||||||
| 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 | ||||||
|  | @ -308,8 +308,6 @@ BEGIN | ||||||
|     "IDR_FD_EGA18_CPX        RCDATA                  ""../res/freedos/EGA18.CPX""\r\n" |     "IDR_FD_EGA18_CPX        RCDATA                  ""../res/freedos/EGA18.CPX""\r\n" | ||||||
|     "IDR_XT_HOGGER           RCDATA                  ""../res/hogger/hogger.exe""\r\n" |     "IDR_XT_HOGGER           RCDATA                  ""../res/hogger/hogger.exe""\r\n" | ||||||
|     "IDR_UEFI_NTFS           RCDATA                  ""../res/uefi/uefi-ntfs.img""\r\n" |     "IDR_UEFI_NTFS           RCDATA                  ""../res/uefi/uefi-ntfs.img""\r\n" | ||||||
|     "IDR_TOGO_SAN_POLICY_XML RCDATA                  ""../res/togo/san_policy.xml""\r\n" |  | ||||||
|     "IDR_TOGO_UNATTEND_XML   RCDATA                  ""../res/togo/unattend.xml""\r\n" |  | ||||||
|     "IDI_LANG_16             RCDATA                  ""../res/icons/lang-16.png""\r\n" |     "IDI_LANG_16             RCDATA                  ""../res/icons/lang-16.png""\r\n" | ||||||
|     "IDI_INFO_16             RCDATA                  ""../res/icons/info-16.png""\r\n" |     "IDI_INFO_16             RCDATA                  ""../res/icons/info-16.png""\r\n" | ||||||
|     "IDI_SETTINGS_16         RCDATA                  ""../res/icons/settings-16.png""\r\n" |     "IDI_SETTINGS_16         RCDATA                  ""../res/icons/settings-16.png""\r\n" | ||||||
|  | @ -397,8 +395,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 3,12,1690,0 |  FILEVERSION 3,12,1691,0 | ||||||
|  PRODUCTVERSION 3,12,1690,0 |  PRODUCTVERSION 3,12,1691,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -416,13 +414,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", "3.12.1690" |             VALUE "FileVersion", "3.12.1691" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2020 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2020 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-3.12.exe" |             VALUE "OriginalFilename", "rufus-3.12.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "3.12.1690" |             VALUE "ProductVersion", "3.12.1691" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  | @ -494,8 +492,6 @@ IDR_FD_EGA17_CPX        RCDATA                  "../res/freedos/EGA17.CPX" | ||||||
| IDR_FD_EGA18_CPX        RCDATA                  "../res/freedos/EGA18.CPX" | IDR_FD_EGA18_CPX        RCDATA                  "../res/freedos/EGA18.CPX" | ||||||
| IDR_XT_HOGGER           RCDATA                  "../res/hogger/hogger.exe" | IDR_XT_HOGGER           RCDATA                  "../res/hogger/hogger.exe" | ||||||
| IDR_UEFI_NTFS           RCDATA                  "../res/uefi/uefi-ntfs.img" | IDR_UEFI_NTFS           RCDATA                  "../res/uefi/uefi-ntfs.img" | ||||||
| IDR_TOGO_SAN_POLICY_XML RCDATA                  "../res/togo/san_policy.xml" |  | ||||||
| IDR_TOGO_UNATTEND_XML   RCDATA                  "../res/togo/unattend.xml" |  | ||||||
| IDI_LANG_16             RCDATA                  "../res/icons/lang-16.png" | IDI_LANG_16             RCDATA                  "../res/icons/lang-16.png" | ||||||
| IDI_INFO_16             RCDATA                  "../res/icons/info-16.png" | IDI_INFO_16             RCDATA                  "../res/icons/info-16.png" | ||||||
| IDI_SETTINGS_16         RCDATA                  "../res/icons/settings-16.png" | IDI_SETTINGS_16         RCDATA                  "../res/icons/settings-16.png" | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								src/ui.c
									
										
									
									
									
								
							
							
						
						
									
										25
									
								
								src/ui.c
									
										
									
									
									
								
							|  | @ -772,7 +772,8 @@ void ToggleImageOptions(void) | ||||||
| 	uint8_t entry_image_options = image_options; | 	uint8_t entry_image_options = image_options; | ||||||
| 	int i, shift = rh; | 	int i, shift = rh; | ||||||
| 
 | 
 | ||||||
| 	has_wintogo = ((boot_type == BT_IMAGE) && (image_path != NULL) && (img_report.is_iso) && (nWindowsVersion >= WINDOWS_8) && (HAS_WINTOGO(img_report))); | 	has_wintogo = ((boot_type == BT_IMAGE) && (image_path != NULL) && (img_report.is_iso || img_report.is_windows_img) && | ||||||
|  | 		(nWindowsVersion >= WINDOWS_8) && (HAS_WINTOGO(img_report))); | ||||||
| 	has_persistence = ((boot_type == BT_IMAGE) && (image_path != NULL) && (img_report.is_iso) && (HAS_PERSISTENCE(img_report))); | 	has_persistence = ((boot_type == BT_IMAGE) && (image_path != NULL) && (img_report.is_iso) && (HAS_PERSISTENCE(img_report))); | ||||||
| 
 | 
 | ||||||
| 	assert(popcnt8(image_options) <= 1); | 	assert(popcnt8(image_options) <= 1); | ||||||
|  | @ -784,13 +785,20 @@ void ToggleImageOptions(void) | ||||||
| 	if ( ((has_wintogo) && !(image_options & IMOP_WINTOGO)) || | 	if ( ((has_wintogo) && !(image_options & IMOP_WINTOGO)) || | ||||||
| 		 ((!has_wintogo) && (image_options & IMOP_WINTOGO)) ) { | 		 ((!has_wintogo) && (image_options & IMOP_WINTOGO)) ) { | ||||||
| 		image_options ^= IMOP_WINTOGO; | 		image_options ^= IMOP_WINTOGO; | ||||||
|  | 		if (image_options & IMOP_WINTOGO) { | ||||||
| 			// Set the Windows To Go selection in the dropdown
 | 			// Set the Windows To Go selection in the dropdown
 | ||||||
| 		IGNORE_RETVAL(ComboBox_SetCurSel(hImageOption, windows_to_go_selection)); | 			IGNORE_RETVAL(ComboBox_SetCurSel(hImageOption, (img_report.is_windows_img || !windows_to_go_selected) ? 0 : 1)); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (((has_persistence) && !(image_options & IMOP_PERSISTENCE)) || | 	if (((has_persistence) && !(image_options & IMOP_PERSISTENCE)) || | ||||||
| 		((!has_persistence) && (image_options & IMOP_PERSISTENCE))) { | 		((!has_persistence) && (image_options & IMOP_PERSISTENCE))) { | ||||||
| 		image_options ^= IMOP_PERSISTENCE; | 		image_options ^= IMOP_PERSISTENCE; | ||||||
|  | 		if (image_options & IMOP_PERSISTENCE) { | ||||||
|  | 			SetWindowTextU(GetDlgItem(hMainDialog, IDS_IMAGE_OPTION_TXT), lmprintf(MSG_123)); | ||||||
|  | 			TogglePersistenceControls(persistence_size != 0); | ||||||
|  | 			SetPersistenceSize(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if ( ((entry_image_options != 0) && (has_wintogo || has_persistence)) || | 	if ( ((entry_image_options != 0) && (has_wintogo || has_persistence)) || | ||||||
|  | @ -815,15 +823,6 @@ void ToggleImageOptions(void) | ||||||
| 		ShowWindow(GetDlgItem(hMainDialog, image_option_toggle_ids[i][0]), | 		ShowWindow(GetDlgItem(hMainDialog, image_option_toggle_ids[i][0]), | ||||||
| 			(image_options & image_option_toggle_ids[i][1]) ? SW_SHOW : SW_HIDE); | 			(image_options & image_option_toggle_ids[i][1]) ? SW_SHOW : SW_HIDE); | ||||||
| 	} | 	} | ||||||
| 	// Set the dropdown default selection
 |  | ||||||
| 	if (image_options & IMOP_WINTOGO) { |  | ||||||
| 		SetWindowTextU(GetDlgItem(hMainDialog, IDS_IMAGE_OPTION_TXT), image_option_txt); |  | ||||||
| 		IGNORE_RETVAL(ComboBox_SetCurSel(hImageOption, windows_to_go_selection)); |  | ||||||
| 	} else if (image_options & IMOP_PERSISTENCE) { |  | ||||||
| 		SetWindowTextU(GetDlgItem(hMainDialog, IDS_IMAGE_OPTION_TXT), lmprintf(MSG_123)); |  | ||||||
| 		TogglePersistenceControls(persistence_size != 0); |  | ||||||
| 		SetPersistenceSize(); |  | ||||||
| 	} |  | ||||||
| 	// If you don't force a redraw here, all kind of bad UI artifacts happen...
 | 	// If you don't force a redraw here, all kind of bad UI artifacts happen...
 | ||||||
| 	InvalidateRect(hMainDialog, NULL, TRUE); | 	InvalidateRect(hMainDialog, NULL, TRUE); | ||||||
| } | } | ||||||
|  | @ -1180,14 +1179,14 @@ void InitProgress(BOOL bOnlyFormat) | ||||||
| 				nb_slots[OP_FILE_COPY] = 5 + 1; | 				nb_slots[OP_FILE_COPY] = 5 + 1; | ||||||
| 				break; | 				break; | ||||||
| 			case BT_IMAGE: | 			case BT_IMAGE: | ||||||
| 				nb_slots[OP_FILE_COPY] = img_report.is_iso ? -1 : 0; | 				nb_slots[OP_FILE_COPY] = (img_report.is_iso || img_report.is_windows_img) ? -1 : 0; | ||||||
| 				break; | 				break; | ||||||
| 			default: | 			default: | ||||||
| 				nb_slots[OP_FILE_COPY] = 2 + 1; | 				nb_slots[OP_FILE_COPY] = 2 + 1; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (selection_default == BT_IMAGE && !img_report.is_iso) { | 		if (selection_default == BT_IMAGE && !(img_report.is_iso || img_report.is_windows_img)) { | ||||||
| 			nb_slots[OP_FORMAT] = -1; | 			nb_slots[OP_FORMAT] = -1; | ||||||
| 		} else { | 		} else { | ||||||
| 			nb_slots[OP_ZERO_MBR] = 1; | 			nb_slots[OP_ZERO_MBR] = 1; | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								src/ui.h
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								src/ui.h
									
										
									
									
									
								
							|  | @ -74,13 +74,12 @@ enum update_progress_type { | ||||||
| extern HWND hMultiToolbar, hSaveToolbar, hHashToolbar, hAdvancedDeviceToolbar, hAdvancedFormatToolbar; | extern HWND hMultiToolbar, hSaveToolbar, hHashToolbar, hAdvancedDeviceToolbar, hAdvancedFormatToolbar; | ||||||
| extern HFONT hInfoFont; | extern HFONT hInfoFont; | ||||||
| extern UINT_PTR UM_LANGUAGE_MENU_MAX; | extern UINT_PTR UM_LANGUAGE_MENU_MAX; | ||||||
| extern BOOL advanced_mode_device, advanced_mode_format, force_large_fat32, app_changed_size; | extern BOOL advanced_mode_device, advanced_mode_format, force_large_fat32, app_changed_size, windows_to_go_selected; | ||||||
| extern loc_cmd* selected_locale; | extern loc_cmd* selected_locale; | ||||||
| extern uint64_t persistence_size; | extern uint64_t persistence_size; | ||||||
| extern const char *sfd_name, *flash_type[BADLOCKS_PATTERN_TYPES]; | extern const char *sfd_name, *flash_type[BADLOCKS_PATTERN_TYPES]; | ||||||
| extern char *short_image_path, image_option_txt[128]; | extern char *short_image_path, image_option_txt[128]; | ||||||
| extern int advanced_device_section_height, advanced_format_section_height; | extern int advanced_device_section_height, advanced_format_section_height, persistence_unit_selection; | ||||||
| extern int windows_to_go_selection, persistence_unit_selection; |  | ||||||
| extern int selection_default, cbw, ddw, ddbh, bh, update_progress_type; | extern int selection_default, cbw, ddw, ddbh, bh, update_progress_type; | ||||||
| 
 | 
 | ||||||
| extern void SetAccessibleName(HWND hCtrl, const char* name); | extern void SetAccessibleName(HWND hCtrl, const char* name); | ||||||
|  |  | ||||||
							
								
								
									
										111
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										111
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -49,6 +49,12 @@ | ||||||
| #define VHD_FOOTER_TYPE_DYNAMIC_HARD_DISK	0x00000003 | #define VHD_FOOTER_TYPE_DYNAMIC_HARD_DISK	0x00000003 | ||||||
| #define VHD_FOOTER_TYPE_DIFFER_HARD_DISK	0x00000004 | #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 | ||||||
|  | #define WIM_HAS_API_APPLY					4 | ||||||
|  | #define WIM_HAS_EXTRACT(r)					(r & (WIM_HAS_API_EXTRACT|WIM_HAS_7Z_EXTRACT)) | ||||||
|  | 
 | ||||||
| #define SECONDS_SINCE_JAN_1ST_2000			946684800 | #define SECONDS_SINCE_JAN_1ST_2000			946684800 | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -92,6 +98,8 @@ typedef struct vhd_footer { | ||||||
| PF_TYPE_DECL(WINAPI, HANDLE, WIMCreateFile, (PWSTR, DWORD, DWORD, DWORD, DWORD, PDWORD)); | PF_TYPE_DECL(WINAPI, HANDLE, WIMCreateFile, (PWSTR, DWORD, DWORD, DWORD, DWORD, PDWORD)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMSetTemporaryPath, (HANDLE, PWSTR)); | PF_TYPE_DECL(WINAPI, BOOL, WIMSetTemporaryPath, (HANDLE, PWSTR)); | ||||||
| PF_TYPE_DECL(WINAPI, HANDLE, WIMLoadImage, (HANDLE, DWORD)); | PF_TYPE_DECL(WINAPI, HANDLE, WIMLoadImage, (HANDLE, DWORD)); | ||||||
|  | PF_TYPE_DECL(WINAPI, BOOL, WIMMountImage, (PCWSTR, PCWSTR, DWORD, PCWSTR)); | ||||||
|  | PF_TYPE_DECL(WINAPI, BOOL, WIMUnmountImage, (PCWSTR, PCWSTR, DWORD, BOOL)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMApplyImage, (HANDLE, PCWSTR, DWORD)); | PF_TYPE_DECL(WINAPI, BOOL, WIMApplyImage, (HANDLE, PCWSTR, DWORD)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMExtractImagePath, (HANDLE, PWSTR, PWSTR, DWORD)); | PF_TYPE_DECL(WINAPI, BOOL, WIMExtractImagePath, (HANDLE, PWSTR, PWSTR, DWORD)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMGetImageInformation, (HANDLE, PVOID, PDWORD)); | PF_TYPE_DECL(WINAPI, BOOL, WIMGetImageInformation, (HANDLE, PVOID, PDWORD)); | ||||||
|  | @ -105,6 +113,7 @@ HANDLE apply_wim_thread = NULL; | ||||||
| extern int default_thread_priority; | extern int default_thread_priority; | ||||||
| 
 | 
 | ||||||
| static uint8_t wim_flags = 0; | static uint8_t wim_flags = 0; | ||||||
|  | static wchar_t wmount_path[MAX_PATH] = { 0 }; | ||||||
| static char sevenzip_path[MAX_PATH]; | static char sevenzip_path[MAX_PATH]; | ||||||
| static const char conectix_str[] = VHD_FOOTER_COOKIE; | static const char conectix_str[] = VHD_FOOTER_COOKIE; | ||||||
| static BOOL count_files; | static BOOL count_files; | ||||||
|  | @ -268,7 +277,6 @@ BOOL IsCompressedBootableImage(const char* path) | ||||||
| 	return FALSE; | 	return FALSE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| BOOL IsBootableImage(const char* path) | BOOL IsBootableImage(const char* path) | ||||||
| { | { | ||||||
| 	HANDLE handle = INVALID_HANDLE_VALUE; | 	HANDLE handle = INVALID_HANDLE_VALUE; | ||||||
|  | @ -277,7 +285,8 @@ BOOL IsBootableImage(const char* path) | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
| 	size_t i; | 	size_t i; | ||||||
| 	uint32_t checksum, old_checksum; | 	uint32_t checksum, old_checksum; | ||||||
| 	LARGE_INTEGER ptr; | 	uint64_t wim_magic = 0; | ||||||
|  | 	LARGE_INTEGER ptr = { 0 }; | ||||||
| 	BOOL is_bootable_img = FALSE; | 	BOOL is_bootable_img = FALSE; | ||||||
| 
 | 
 | ||||||
| 	uprintf("Disk image analysis:"); | 	uprintf("Disk image analysis:"); | ||||||
|  | @ -297,6 +306,11 @@ BOOL IsBootableImage(const char* path) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 	img_report.image_size = (uint64_t)liImageSize.QuadPart; | 	img_report.image_size = (uint64_t)liImageSize.QuadPart; | ||||||
|  | 	size = sizeof(wim_magic); | ||||||
|  | 	SetFilePointerEx(handle, ptr, NULL, FILE_BEGIN); | ||||||
|  | 	img_report.is_windows_img = ReadFile(handle, &wim_magic, size, &size, NULL) && (wim_magic == WIM_MAGIC); | ||||||
|  | 	if (img_report.is_windows_img) | ||||||
|  | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	size = sizeof(vhd_footer); | 	size = sizeof(vhd_footer); | ||||||
| 	if ((img_report.compression_type == BLED_COMPRESSION_NONE) && (img_report.image_size >= (512 + size))) { | 	if ((img_report.compression_type == BLED_COMPRESSION_NONE) && (img_report.image_size >= (512 + size))) { | ||||||
|  | @ -335,14 +349,9 @@ out: | ||||||
| 	return is_bootable_img; | 	return is_bootable_img; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define WIM_HAS_API_EXTRACT 1 |  | ||||||
| #define WIM_HAS_7Z_EXTRACT  2 |  | ||||||
| #define WIM_HAS_API_APPLY   4 |  | ||||||
| #define WIM_HAS_EXTRACT(r) (r & (WIM_HAS_API_EXTRACT|WIM_HAS_7Z_EXTRACT)) |  | ||||||
| 
 |  | ||||||
| // Find out if we have any way to extract/apply WIM files on this platform
 | // Find out if we have any way to extract/apply WIM files on this platform
 | ||||||
| // Returns a bitfield of the methods we can use (1 = Extract using wimgapi, 2 = Extract using 7-Zip, 4 = Apply using wimgapi)
 | // Returns a bitfield of the methods we can use (1 = Extract using wimgapi, 2 = Extract using 7-Zip, 4 = Apply using wimgapi)
 | ||||||
| uint8_t WimExtractCheck(void) | uint8_t WimExtractCheck(BOOL bSilent) | ||||||
| { | { | ||||||
| 	PF_INIT(WIMCreateFile, Wimgapi); | 	PF_INIT(WIMCreateFile, Wimgapi); | ||||||
| 	PF_INIT(WIMSetTemporaryPath, Wimgapi); | 	PF_INIT(WIMSetTemporaryPath, Wimgapi); | ||||||
|  | @ -361,19 +370,69 @@ uint8_t WimExtractCheck(void) | ||||||
| 	if ((wim_flags & WIM_HAS_API_EXTRACT) && pfWIMApplyImage && pfWIMRegisterMessageCallback && pfWIMUnregisterMessageCallback) | 	if ((wim_flags & WIM_HAS_API_EXTRACT) && pfWIMApplyImage && pfWIMRegisterMessageCallback && pfWIMUnregisterMessageCallback) | ||||||
| 		wim_flags |= WIM_HAS_API_APPLY; | 		wim_flags |= WIM_HAS_API_APPLY; | ||||||
| 
 | 
 | ||||||
| 	uprintf("WIM extraction method(s) supported: %s%s%s", (wim_flags & WIM_HAS_7Z_EXTRACT)?"7-Zip": | 	suprintf("WIM extraction method(s) supported: %s%s%s", (wim_flags & WIM_HAS_7Z_EXTRACT)?"7-Zip": | ||||||
| 		((wim_flags & WIM_HAS_API_EXTRACT)?"":"NONE"), | 		((wim_flags & WIM_HAS_API_EXTRACT)?"":"NONE"), | ||||||
| 		(WIM_HAS_EXTRACT(wim_flags) == (WIM_HAS_API_EXTRACT|WIM_HAS_7Z_EXTRACT))?", ": | 		(WIM_HAS_EXTRACT(wim_flags) == (WIM_HAS_API_EXTRACT|WIM_HAS_7Z_EXTRACT))?", ": | ||||||
| 		"", (wim_flags & WIM_HAS_API_EXTRACT)?"wimgapi.dll":""); | 		"", (wim_flags & WIM_HAS_API_EXTRACT)?"wimgapi.dll":""); | ||||||
| 	uprintf("WIM apply method supported: %s", (wim_flags & WIM_HAS_API_APPLY)?"wimgapi.dll":"NONE"); | 	suprintf("WIM apply method supported: %s", (wim_flags & WIM_HAS_API_APPLY)?"wimgapi.dll":"NONE"); | ||||||
| 	return wim_flags; | 	return wim_flags; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Looks like Microsoft's idea of "mount" for WIM images is to just *extract* all
 | ||||||
|  | // files to a mounpoint and pretend it is "mounted", even if you do specify that
 | ||||||
|  | // you're not planning to change the content. So, yeah, this is both super slow
 | ||||||
|  | // and super wasteful of space... These calls are a complete waste of time.
 | ||||||
|  | BOOL WimMountImage(char* pszWimFileName, DWORD dwImageIndex) | ||||||
|  | { | ||||||
|  | 	BOOL r = FALSE; | ||||||
|  | 	wconvert(temp_dir); | ||||||
|  | 	wconvert(pszWimFileName); | ||||||
|  | 	PF_INIT_OR_OUT(WIMMountImage, Wimgapi); | ||||||
|  | 
 | ||||||
|  | 	if (wmount_path[0] != 0) { | ||||||
|  | 		uprintf("WimMountImage: An image is already mounted"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	if (GetTempFileNameW(wtemp_dir, L"Rufus", 0, wmount_path) == 0) { | ||||||
|  | 		uprintf("WimMountImage: Can not create mount directory"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	DeleteFileW(wmount_path); | ||||||
|  | 	if (!CreateDirectoryW(wmount_path, 0)) { | ||||||
|  | 		uprintf("WimMountImage: Can not create mount directory"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	r = pfWIMMountImage(wmount_path, wpszWimFileName, dwImageIndex, NULL); | ||||||
|  | 	if (!r) | ||||||
|  | 		uprintf("Could not mount %S on %S: %s", wpszWimFileName, wmount_path, WindowsErrorString()); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	wfree(temp_dir); | ||||||
|  | 	wfree(pszWimFileName); | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOL WimUnmountImage(void) | ||||||
|  | { | ||||||
|  | 	BOOL r = FALSE; | ||||||
|  | 	PF_INIT_OR_OUT(WIMUnmountImage, Wimgapi); | ||||||
|  | 	if (wmount_path[0] == 0) { | ||||||
|  | 		uprintf("WimUnmountImage: No image is mounted"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	r = pfWIMUnmountImage(wmount_path, NULL, 0, FALSE); | ||||||
|  | 	if (!r) | ||||||
|  | 		uprintf("Could not unmount %S: %s", wmount_path, WindowsErrorString()); | ||||||
|  | 	wmount_path[0] = 0; | ||||||
|  | out: | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| // Extract a file from a WIM image using wimgapi.dll (Windows 7 or later)
 | // Extract a file from a WIM image using wimgapi.dll (Windows 7 or later)
 | ||||||
| // NB: if you want progress from a WIM callback, you must run the WIM API call in its own thread
 | // NB: if you want progress from a WIM callback, you must run the WIM API call in its own thread
 | ||||||
| // (which we don't do here) as it won't work otherwise. Thanks go to Erwan for figuring this out!
 | // (which we don't do here) as it won't work otherwise. Thanks go to Erwan for figuring this out!
 | ||||||
| BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst) | BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst, BOOL bSilent) | ||||||
| { | { | ||||||
| 	static char* index_name = "[1].xml"; | 	static char* index_name = "[1].xml"; | ||||||
| 	BOOL r = FALSE; | 	BOOL r = FALSE; | ||||||
|  | @ -393,7 +452,7 @@ BOOL WimExtractFile_API(const char* image, int index, const char* src, const cha | ||||||
| 	PF_INIT_OR_OUT(WIMExtractImagePath, Wimgapi); | 	PF_INIT_OR_OUT(WIMExtractImagePath, Wimgapi); | ||||||
| 	PF_INIT_OR_OUT(WIMCloseHandle, Wimgapi); | 	PF_INIT_OR_OUT(WIMCloseHandle, Wimgapi); | ||||||
| 
 | 
 | ||||||
| 	uprintf("Opening: %s:[%d] (API)", image, index); | 	suprintf("Opening: %s:[%d] (API)", image, index); | ||||||
| 	if (GetTempPathW(ARRAYSIZE(wtemp), wtemp) == 0) { | 	if (GetTempPathW(ARRAYSIZE(wtemp), wtemp) == 0) { | ||||||
| 		uprintf("  Could not fetch temp path: %s", WindowsErrorString()); | 		uprintf("  Could not fetch temp path: %s", WindowsErrorString()); | ||||||
| 		goto out; | 		goto out; | ||||||
|  | @ -415,7 +474,7 @@ BOOL WimExtractFile_API(const char* image, int index, const char* src, const cha | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	uprintf("Extracting: %s (From %s)", dst, src); | 	suprintf("Extracting: %s (From %s)", dst, src); | ||||||
| 	if (safe_strcmp(src, index_name) == 0) { | 	if (safe_strcmp(src, index_name) == 0) { | ||||||
| 		if (!pfWIMGetImageInformation(hWim, &wim_info, &dw)) { | 		if (!pfWIMGetImageInformation(hWim, &wim_info, &dw)) { | ||||||
| 			uprintf("  Could not access WIM info: %s", WindowsErrorString()); | 			uprintf("  Could not access WIM info: %s", WindowsErrorString()); | ||||||
|  | @ -424,7 +483,7 @@ BOOL WimExtractFile_API(const char* image, int index, const char* src, const cha | ||||||
| 		hFile = CreateFileW(wdst, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, | 		hFile = CreateFileW(wdst, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, | ||||||
| 			NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | 			NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | ||||||
| 		if ((hFile == INVALID_HANDLE_VALUE) || (!WriteFile(hFile, wim_info, dw, &dw, NULL))) { | 		if ((hFile == INVALID_HANDLE_VALUE) || (!WriteFile(hFile, wim_info, dw, &dw, NULL))) { | ||||||
| 			uprintf("  Could not extract file: %s", WindowsErrorString()); | 			suprintf("  Could not extract file: %s", WindowsErrorString()); | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -434,7 +493,7 @@ BOOL WimExtractFile_API(const char* image, int index, const char* src, const cha | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 		if (!pfWIMExtractImagePath(hImage, wsrc, wdst, 0)) { | 		if (!pfWIMExtractImagePath(hImage, wsrc, wdst, 0)) { | ||||||
| 			uprintf("  Could not extract file: %s", WindowsErrorString()); | 			suprintf("  Could not extract file: %s", WindowsErrorString()); | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -442,7 +501,7 @@ BOOL WimExtractFile_API(const char* image, int index, const char* src, const cha | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	if ((hImage != NULL) || (hWim != NULL)) { | 	if ((hImage != NULL) || (hWim != NULL)) { | ||||||
| 		uprintf("Closing: %s", image); | 		suprintf("Closing: %s", image); | ||||||
| 		if (hImage != NULL) pfWIMCloseHandle(hImage); | 		if (hImage != NULL) pfWIMCloseHandle(hImage); | ||||||
| 		if (hWim != NULL) pfWIMCloseHandle(hWim); | 		if (hWim != NULL) pfWIMCloseHandle(hWim); | ||||||
| 	} | 	} | ||||||
|  | @ -454,7 +513,7 @@ out: | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Extract a file from a WIM image using 7-Zip
 | // Extract a file from a WIM image using 7-Zip
 | ||||||
| BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst) | BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst, BOOL bSilent) | ||||||
| { | { | ||||||
| 	int n; | 	int n; | ||||||
| 	size_t i; | 	size_t i; | ||||||
|  | @ -462,7 +521,7 @@ BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char | ||||||
| 	char tmpdst[MAX_PATH]; | 	char tmpdst[MAX_PATH]; | ||||||
| 	char index_prefix[] = "#\\"; | 	char index_prefix[] = "#\\"; | ||||||
| 
 | 
 | ||||||
| 	uprintf("Opening: %s:[%d] (7-Zip)", image, index); | 	suprintf("Opening: %s:[%d] (7-Zip)", image, index); | ||||||
| 
 | 
 | ||||||
| 	if ((image == NULL) || (src == NULL) || (dst == NULL)) | 	if ((image == NULL) || (src == NULL) || (dst == NULL)) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
|  | @ -471,7 +530,7 @@ BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char | ||||||
| 	// that this breaks!
 | 	// that this breaks!
 | ||||||
| 	index_prefix[0] = '0' + index; | 	index_prefix[0] = '0' + index; | ||||||
| 
 | 
 | ||||||
| 	uprintf("Extracting: %s (From %s)", dst, src); | 	suprintf("Extracting: %s (From %s)", dst, src); | ||||||
| 
 | 
 | ||||||
| 	// 7z has a quirk where the image index MUST be specified if a
 | 	// 7z has a quirk where the image index MUST be specified if a
 | ||||||
| 	// WIM has multiple indexes, but it MUST be removed if there is
 | 	// WIM has multiple indexes, but it MUST be removed if there is
 | ||||||
|  | @ -500,13 +559,13 @@ BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (n >= 2) { | 	if (n >= 2) { | ||||||
| 		uprintf("  7z.exe did not extract %s", tmpdst); | 		suprintf("  7z.exe did not extract %s", tmpdst); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// coverity[toctou]
 | 	// coverity[toctou]
 | ||||||
| 	if (rename(tmpdst, dst) != 0) { | 	if (!MoveFileExU(tmpdst, dst, MOVEFILE_REPLACE_EXISTING)) { | ||||||
| 		uprintf("  Could not rename %s to %s: errno %d", tmpdst, dst, errno); | 		uprintf("  Could not rename %s to %s: %s", tmpdst, dst, WindowsErrorString()); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -514,17 +573,17 @@ BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Extract a file from a WIM image
 | // Extract a file from a WIM image
 | ||||||
| BOOL WimExtractFile(const char* image, int index, const char* src, const char* dst) | BOOL WimExtractFile(const char* image, int index, const char* src, const char* dst, BOOL bSilent) | ||||||
| { | { | ||||||
| 	if ((wim_flags == 0) && (!WIM_HAS_EXTRACT(WimExtractCheck()))) | 	if ((wim_flags == 0) && (!WIM_HAS_EXTRACT(WimExtractCheck(TRUE)))) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	if ((image == NULL) || (src == NULL) || (dst == NULL)) | 	if ((image == NULL) || (src == NULL) || (dst == NULL)) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 
 | 
 | ||||||
| 	// Prefer 7-Zip as, unsurprisingly, it's faster than the Microsoft way,
 | 	// Prefer 7-Zip as, unsurprisingly, it's faster than the Microsoft way,
 | ||||||
| 	// but allow fallback if 7-Zip doesn't succeed
 | 	// but allow fallback if 7-Zip doesn't succeed
 | ||||||
| 	return ( ((wim_flags & WIM_HAS_7Z_EXTRACT) && WimExtractFile_7z(image, index, src, dst)) | 	return ( ((wim_flags & WIM_HAS_7Z_EXTRACT) && WimExtractFile_7z(image, index, src, dst, bSilent)) | ||||||
| 		  || ((wim_flags & WIM_HAS_API_EXTRACT) && WimExtractFile_API(image, index, src, dst)) ); | 		  || ((wim_flags & WIM_HAS_API_EXTRACT) && WimExtractFile_API(image, index, src, dst, bSilent)) ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Apply image functionality
 | // Apply image functionality
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue