mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	Compare commits
	
		
			3 commits
		
	
	
		
			c717c7789b
			...
			d4c9f2dfa1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d4c9f2dfa1 | ||
|  | 1476e9cd8b | ||
|  | c47ee4c435 | 
					 20 changed files with 400 additions and 357 deletions
				
			
		|  | @ -3,3 +3,5 @@ EXPORTS | ||||||
|   GetVirtualDiskPhysicalPath@12 |   GetVirtualDiskPhysicalPath@12 | ||||||
|   DetachVirtualDisk@12 |   DetachVirtualDisk@12 | ||||||
|   OpenVirtualDisk@24 |   OpenVirtualDisk@24 | ||||||
|  |   CreateVirtualDisk@36 | ||||||
|  |   GetVirtualDiskOperationProgress@12 | ||||||
|  |  | ||||||
|  | @ -603,6 +603,8 @@ t MSG_339 "Rufus detected that the ISO you have selected contains a UEFI bootloa | ||||||
| 	"- If you obtained it from a trusted source, you should try to locate a more up to date version, that will not produce this warning." | 	"- If you obtained it from a trusted source, you should try to locate a more up to date version, that will not produce this warning." | ||||||
| t MSG_340 "a \"Security Violation\" screen" | t MSG_340 "a \"Security Violation\" screen" | ||||||
| t MSG_341 "a Windows Recovery Screen (BSOD) with '%s'" | t MSG_341 "a Windows Recovery Screen (BSOD) with '%s'" | ||||||
|  | t MSG_342 "Compressed VHDX Image" | ||||||
|  | t MSG_343 "Uncompressed VHD Image" | ||||||
| # The following messages are for the Windows Store listing only and are not used by the application | # The following messages are for the Windows Store listing only and are not used by the application | ||||||
| t MSG_900 "Rufus is a utility that helps format and create bootable USB flash drives, such as USB keys/pendrives, memory sticks, etc." | t MSG_900 "Rufus is a utility that helps format and create bootable USB flash drives, such as USB keys/pendrives, memory sticks, etc." | ||||||
| t MSG_901 "Official site: %s" | t MSG_901 "Official site: %s" | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ jmp_buf bb_error_jmp; | ||||||
| char* bb_virtual_buf = NULL; | char* bb_virtual_buf = NULL; | ||||||
| size_t bb_virtual_len = 0, bb_virtual_pos = 0; | size_t bb_virtual_len = 0, bb_virtual_pos = 0; | ||||||
| int bb_virtual_fd = -1; | int bb_virtual_fd = -1; | ||||||
|  | uint32_t BB_BUFSIZE = 0x10000; | ||||||
| 
 | 
 | ||||||
| static long long int unpack_none(transformer_state_t *xstate) | static long long int unpack_none(transformer_state_t *xstate) | ||||||
| { | { | ||||||
|  | @ -265,7 +266,8 @@ int64_t bled_uncompress_from_buffer_to_buffer(const char* src, const size_t src_ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Initialize the library.
 | /* Initialize the library.
 | ||||||
|  * When the parameters are not NULL you can: |  * When the parameters are not NULL or zero you can: | ||||||
|  |  * - specify the buffer size to use (must be larger than 64KB and a power of two) | ||||||
|  * - specify the printf-like function you want to use to output message |  * - specify the printf-like function you want to use to output message | ||||||
|  *   void print_function(const char* format, ...); |  *   void print_function(const char* format, ...); | ||||||
|  * - specify the read/write functions you want to use; |  * - specify the read/write functions you want to use; | ||||||
|  | @ -275,18 +277,25 @@ int64_t bled_uncompress_from_buffer_to_buffer(const char* src, const size_t src_ | ||||||
|  *   void switch_function(const char* filename, const uint64_t filesize); |  *   void switch_function(const char* filename, const uint64_t filesize); | ||||||
|  * - point to an unsigned long variable, to be used to cancel operations when set to non zero |  * - point to an unsigned long variable, to be used to cancel operations when set to non zero | ||||||
|  */ |  */ | ||||||
| int bled_init(printf_t print_function, read_t read_function, write_t write_function,  | int bled_init(uint32_t buffer_size, printf_t print_function, read_t read_function, write_t write_function, | ||||||
| 	progress_t progress_function, switch_t switch_function, unsigned long* cancel_request) | 	progress_t progress_function, switch_t switch_function, unsigned long* cancel_request) | ||||||
| { | { | ||||||
| 	if (bled_initialized) | 	if (bled_initialized) | ||||||
| 		return -1; | 		return -1; | ||||||
| 	bled_initialized = true; | 	BB_BUFSIZE = buffer_size; | ||||||
|  | 	/* buffer_size must be larger than 64 KB and a power of two */ | ||||||
|  | 	if (buffer_size < 0x10000 || (buffer_size & (buffer_size - 1)) != 0) { | ||||||
|  | 		if (buffer_size != 0 && print_function != NULL) | ||||||
|  | 			print_function("bled_init: invalid buffer_size, defaulting to 64 KB"); | ||||||
|  | 		BB_BUFSIZE = 0x10000; | ||||||
|  | 	} | ||||||
| 	bled_printf = print_function; | 	bled_printf = print_function; | ||||||
| 	bled_read = read_function; | 	bled_read = read_function; | ||||||
| 	bled_write = write_function; | 	bled_write = write_function; | ||||||
| 	bled_progress = progress_function; | 	bled_progress = progress_function; | ||||||
| 	bled_switch = switch_function; | 	bled_switch = switch_function; | ||||||
| 	bled_cancel_request = cancel_request; | 	bled_cancel_request = cancel_request; | ||||||
|  | 	bled_initialized = true; | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -50,7 +50,8 @@ int64_t bled_uncompress_to_dir(const char* src, const char* dir, int type); | ||||||
| int64_t bled_uncompress_from_buffer_to_buffer(const char* src, const size_t src_len, char* dst, size_t dst_len, int type); | int64_t bled_uncompress_from_buffer_to_buffer(const char* src, const size_t src_len, char* dst, size_t dst_len, int type); | ||||||
| 
 | 
 | ||||||
| /* Initialize the library.
 | /* Initialize the library.
 | ||||||
|  * When the parameters are not NULL you can: |  * When the parameters are not NULL or zero you can: | ||||||
|  |  * - specify the buffer size to use (must be larger than 64KB and a power of two) | ||||||
|  * - specify the printf-like function you want to use to output message |  * - specify the printf-like function you want to use to output message | ||||||
|  *   void print_function(const char* format, ...); |  *   void print_function(const char* format, ...); | ||||||
|  * - specify the read/write functions you want to use; |  * - specify the read/write functions you want to use; | ||||||
|  | @ -60,7 +61,7 @@ int64_t bled_uncompress_from_buffer_to_buffer(const char* src, const size_t src_ | ||||||
|  *   void switch_function(const char* filename, const uint64_t filesize); |  *   void switch_function(const char* filename, const uint64_t filesize); | ||||||
|  * - point to an unsigned long variable, to be used to cancel operations when set to non zero |  * - point to an unsigned long variable, to be used to cancel operations when set to non zero | ||||||
|  */ |  */ | ||||||
| int bled_init(printf_t print_function, read_t read_function, write_t write_function, | int bled_init(uint32_t buffer_size, printf_t print_function, read_t read_function, write_t write_function, | ||||||
|     progress_t progress_function, switch_t switch_function, unsigned long* cancel_request); |     progress_t progress_function, switch_t switch_function, unsigned long* cancel_request); | ||||||
| 
 | 
 | ||||||
| /* This call frees any resource used by the library */ | /* This call frees any resource used by the library */ | ||||||
|  |  | ||||||
|  | @ -45,10 +45,11 @@ typedef struct huft_t { | ||||||
| 	} v; | 	} v; | ||||||
| } huft_t; | } huft_t; | ||||||
| 
 | 
 | ||||||
| enum { | /* gunzip_window size--must be a power of two, and
 | ||||||
| 	/* gunzip_window size--must be a power of two, and
 |  | ||||||
|  * at least 32K for zip's deflate method */ |  * at least 32K for zip's deflate method */ | ||||||
| 	GUNZIP_WSIZE = BB_BUFSIZE, | #define GUNZIP_WSIZE BB_BUFSIZE | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
| 	/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ | 	/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ | ||||||
| 	BMAX = 16,	/* maximum bit length of any code (16 for explode) */ | 	BMAX = 16,	/* maximum bit length of any code (16 for explode) */ | ||||||
| 	N_MAX = 288,	/* maximum number of codes in any set */ | 	N_MAX = 288,	/* maximum number of codes in any set */ | ||||||
|  |  | ||||||
|  | @ -27,10 +27,10 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Default input buffer size */ | /* Default input buffer size */ | ||||||
| #define IBUFSIZ         BB_BUFSIZE | #define IBUFSIZ         ((int)BB_BUFSIZE) | ||||||
| 
 | 
 | ||||||
| /* Default output buffer size */ | /* Default output buffer size */ | ||||||
| #define OBUFSIZ         BB_BUFSIZE | #define OBUFSIZ         ((int)BB_BUFSIZE) | ||||||
| 
 | 
 | ||||||
| /* Defines for third byte of header */ | /* Defines for third byte of header */ | ||||||
| #define BIT_MASK        0x1f    /* Mask for 'number of compresssion bits'       */ | #define BIT_MASK        0x1f    /* Mask for 'number of compresssion bits'       */ | ||||||
|  |  | ||||||
|  | @ -209,7 +209,7 @@ do { if (BB_BIG_ENDIAN) { \ | ||||||
| 	(c64).fmt.cdf_offset = SWAP_LE64((c64).fmt.cdf_offset); \ | 	(c64).fmt.cdf_offset = SWAP_LE64((c64).fmt.cdf_offset); \ | ||||||
| }} while (0) | }} while (0) | ||||||
| 
 | 
 | ||||||
| inline void BUG() { | inline void BUG(void) { | ||||||
| 	/* Check the offset of the last element, not the length.  This leniency
 | 	/* Check the offset of the last element, not the length.  This leniency
 | ||||||
| 	 * allows for poor packing, whereby the overall struct may be too long, | 	 * allows for poor packing, whereby the overall struct may be too long, | ||||||
| 	 * even though the elements are all in the right place. | 	 * even though the elements are all in the right place. | ||||||
|  |  | ||||||
|  | @ -39,7 +39,6 @@ | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <io.h> | #include <io.h> | ||||||
| 
 | 
 | ||||||
| #define BB_BUFSIZE                  0x40000 |  | ||||||
| #define ONE_TB                      1099511627776ULL | #define ONE_TB                      1099511627776ULL | ||||||
| 
 | 
 | ||||||
| #define ENABLE_DESKTOP              1 | #define ENABLE_DESKTOP              1 | ||||||
|  | @ -105,6 +104,7 @@ typedef unsigned int uid_t; | ||||||
| #define get_le16(ptr) (*(const uint16_t *)(ptr)) | #define get_le16(ptr) (*(const uint16_t *)(ptr)) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | extern uint32_t BB_BUFSIZE; | ||||||
| extern smallint bb_got_signal; | extern smallint bb_got_signal; | ||||||
| extern uint32_t *global_crc32_table; | extern uint32_t *global_crc32_table; | ||||||
| extern jmp_buf bb_error_jmp; | extern jmp_buf bb_error_jmp; | ||||||
|  |  | ||||||
							
								
								
									
										125
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										125
									
								
								src/format.c
									
										
									
									
									
								
							|  | @ -1290,7 +1290,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive) | ||||||
| 		} | 		} | ||||||
| 		assert((uintptr_t)sec_buf % SelectedDrive.SectorSize == 0); | 		assert((uintptr_t)sec_buf % SelectedDrive.SectorSize == 0); | ||||||
| 		sec_buf_pos = 0; | 		sec_buf_pos = 0; | ||||||
| 		bled_init(uprintf, NULL, sector_write, update_progress, NULL, &FormatStatus); | 		bled_init(256 * KB, uprintf, NULL, sector_write, update_progress, NULL, &FormatStatus); | ||||||
| 		bled_ret = bled_uncompress_with_handles(hSourceImage, hPhysicalDrive, img_report.compression_type); | 		bled_ret = bled_uncompress_with_handles(hSourceImage, hPhysicalDrive, img_report.compression_type); | ||||||
| 		bled_exit(); | 		bled_exit(); | ||||||
| 		uprintfs("\r\n"); | 		uprintfs("\r\n"); | ||||||
|  | @ -1977,126 +1977,3 @@ out: | ||||||
| 	PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)TRUE, 0); | 	PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)TRUE, 0); | ||||||
| 	ExitThread(0); | 	ExitThread(0); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| DWORD WINAPI SaveImageThread(void* param) |  | ||||||
| { |  | ||||||
| 	BOOL s; |  | ||||||
| 	DWORD rSize, wSize; |  | ||||||
| 	IMG_SAVE *img_save = (IMG_SAVE*)param; |  | ||||||
| 	HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE; |  | ||||||
| 	HANDLE hDestImage = INVALID_HANDLE_VALUE; |  | ||||||
| 	LARGE_INTEGER li; |  | ||||||
| 	uint8_t *buffer = NULL; |  | ||||||
| 	uint64_t wb; |  | ||||||
| 	int i; |  | ||||||
| 
 |  | ||||||
| 	PrintInfoDebug(0, MSG_225); |  | ||||||
| 	switch (img_save->Type) { |  | ||||||
| 	case IMG_SAVE_TYPE_VHD: |  | ||||||
| 		hPhysicalDrive = GetPhysicalHandle(img_save->DeviceNum, TRUE, FALSE, FALSE); |  | ||||||
| 		break; |  | ||||||
| 	case IMG_SAVE_TYPE_ISO: |  | ||||||
| 		hPhysicalDrive = CreateFileA(img_save->DevicePath, GENERIC_READ, FILE_SHARE_READ, |  | ||||||
| 			NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		uprintf("Invalid image type"); |  | ||||||
| 	} |  | ||||||
| 	if (hPhysicalDrive == INVALID_HANDLE_VALUE) { |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Write an image file
 |  | ||||||
| 	// We may have poked the MBR and other stuff, so need to rewind
 |  | ||||||
| 	li.QuadPart = 0; |  | ||||||
| 	if (!SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN)) |  | ||||||
| 		uprintf("Warning: Unable to rewind device position - wrong data might be copied!"); |  | ||||||
| 	hDestImage = CreateFileU(img_save->ImagePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, |  | ||||||
| 		CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |  | ||||||
| 	if (hDestImage == INVALID_HANDLE_VALUE) { |  | ||||||
| 		uprintf("Could not open image '%s': %s", img_save->ImagePath, WindowsErrorString()); |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	buffer = (uint8_t*)_mm_malloc(img_save->BufSize, 16); |  | ||||||
| 	if (buffer == NULL) { |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY; |  | ||||||
| 		uprintf("could not allocate buffer"); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	uprintf("Will use a buffer size of %s", SizeToHumanReadable(img_save->BufSize, FALSE, FALSE)); |  | ||||||
| 	uprintf("Saving to image '%s'...", img_save->ImagePath); |  | ||||||
| 
 |  | ||||||
| 	// Don't bother trying for something clever, using double buffering overlapped and whatnot:
 |  | ||||||
| 	// With Windows' default optimizations, sync read + sync write for sequential operations
 |  | ||||||
| 	// will be as fast, if not faster, than whatever async scheme you can come up with.
 |  | ||||||
| 	UpdateProgressWithInfoInit(NULL, FALSE); |  | ||||||
| 	for (wb = 0; ; wb += wSize) { |  | ||||||
| 		if (img_save->Type == IMG_SAVE_TYPE_ISO) { |  | ||||||
| 			// Optical drives do not appear to increment the sectors to read automatically
 |  | ||||||
| 			li.QuadPart = wb; |  | ||||||
| 			if (!SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN)) |  | ||||||
| 				uprintf("Warning: Unable to set device position - wrong data might be copied!"); |  | ||||||
| 		} |  | ||||||
| 		s = ReadFile(hPhysicalDrive, buffer, |  | ||||||
| 			(DWORD)MIN(img_save->BufSize, img_save->DeviceSize - wb), &rSize, NULL); |  | ||||||
| 		if (!s) { |  | ||||||
| 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; |  | ||||||
| 			uprintf("Read error: %s", WindowsErrorString()); |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 		if (rSize == 0) |  | ||||||
| 			break; |  | ||||||
| 		UpdateProgressWithInfo(OP_FORMAT, MSG_261, wb, img_save->DeviceSize); |  | ||||||
| 		for (i = 1; i <= WRITE_RETRIES; i++) { |  | ||||||
| 			CHECK_FOR_USER_CANCEL; |  | ||||||
| 			s = WriteFile(hDestImage, buffer, rSize, &wSize, NULL); |  | ||||||
| 			if ((s) && (wSize == rSize)) |  | ||||||
| 				break; |  | ||||||
| 			if (s) |  | ||||||
| 				uprintf("Write error: Wrote %d bytes, expected %d bytes", wSize, rSize); |  | ||||||
| 			else |  | ||||||
| 				uprintf("Write error: %s", WindowsErrorString()); |  | ||||||
| 			if (i < WRITE_RETRIES) { |  | ||||||
| 				li.QuadPart = wb; |  | ||||||
| 				uprintf("Retrying in %d seconds...", WRITE_TIMEOUT / 1000); |  | ||||||
| 				Sleep(WRITE_TIMEOUT); |  | ||||||
| 				if (!SetFilePointerEx(hDestImage, li, NULL, FILE_BEGIN)) { |  | ||||||
| 					uprintf("Write error: Could not reset position - %s", WindowsErrorString()); |  | ||||||
| 					goto out; |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; |  | ||||||
| 				goto out; |  | ||||||
| 			} |  | ||||||
| 			Sleep(200); |  | ||||||
| 		} |  | ||||||
| 		if (i > WRITE_RETRIES) |  | ||||||
| 			goto out; |  | ||||||
| 	} |  | ||||||
| 	if (wb != img_save->DeviceSize) { |  | ||||||
| 		uprintf("Error: wrote %s, expected %s", SizeToHumanReadable(wb, FALSE, FALSE), |  | ||||||
| 			SizeToHumanReadable(img_save->DeviceSize, FALSE, FALSE)); |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 	if (img_save->Type == IMG_SAVE_TYPE_VHD) { |  | ||||||
| 		uprintf("Appending VHD footer..."); |  | ||||||
| 		if (!AppendVHDFooter(img_save->ImagePath)) { |  | ||||||
| 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	uprintf("Operation complete (Wrote %s).", SizeToHumanReadable(wb, FALSE, FALSE)); |  | ||||||
| 
 |  | ||||||
| out: |  | ||||||
| 	safe_free(img_save->ImagePath); |  | ||||||
| 	safe_mm_free(buffer); |  | ||||||
| 	safe_closehandle(hDestImage); |  | ||||||
| 	safe_unlockclose(hPhysicalDrive); |  | ||||||
| 	PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)TRUE, 0); |  | ||||||
| 	ExitThread(0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
							
								
								
									
										158
									
								
								src/iso.c
									
										
									
									
									
								
							
							
						
						
									
										158
									
								
								src/iso.c
									
										
									
									
									
								
							|  | @ -43,6 +43,8 @@ | ||||||
| #include <cdio/udf.h> | #include <cdio/udf.h> | ||||||
| 
 | 
 | ||||||
| #include "rufus.h" | #include "rufus.h" | ||||||
|  | #include "ui.h" | ||||||
|  | #include "drive.h" | ||||||
| #include "libfat.h" | #include "libfat.h" | ||||||
| #include "missing.h" | #include "missing.h" | ||||||
| #include "resource.h" | #include "resource.h" | ||||||
|  | @ -82,6 +84,7 @@ RUFUS_IMG_REPORT img_report; | ||||||
| int64_t iso_blocking_status = -1; | int64_t iso_blocking_status = -1; | ||||||
| extern BOOL preserve_timestamps, enable_ntfs_compression; | extern BOOL preserve_timestamps, enable_ntfs_compression; | ||||||
| extern char* archive_path; | extern char* archive_path; | ||||||
|  | extern HANDLE format_thread; | ||||||
| BOOL enable_iso = TRUE, enable_joliet = TRUE, enable_rockridge = TRUE, has_ldlinux_c32; | BOOL enable_iso = TRUE, enable_joliet = TRUE, enable_rockridge = TRUE, has_ldlinux_c32; | ||||||
| #define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0) | #define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0) | ||||||
| static const char* psz_extract_dir; | static const char* psz_extract_dir; | ||||||
|  | @ -1283,7 +1286,7 @@ out: | ||||||
| 		update_md5sum(); | 		update_md5sum(); | ||||||
| 		if (archive_path != NULL) { | 		if (archive_path != NULL) { | ||||||
| 			uprintf("● Adding files from %s", archive_path); | 			uprintf("● Adding files from %s", archive_path); | ||||||
| 			bled_init(NULL, NULL, NULL, NULL, alt_print_extracted_file, NULL); | 			bled_init(256 * KB, NULL, NULL, NULL, NULL, alt_print_extracted_file, NULL); | ||||||
| 			bled_uncompress_to_dir(archive_path, dest_dir, BLED_COMPRESSION_ZIP); | 			bled_uncompress_to_dir(archive_path, dest_dir, BLED_COMPRESSION_ZIP); | ||||||
| 			bled_exit(); | 			bled_exit(); | ||||||
| 		} | 		} | ||||||
|  | @ -1713,7 +1716,7 @@ static HANDLE mounted_handle = INVALID_HANDLE_VALUE; | ||||||
| char* MountISO(const char* path) | char* MountISO(const char* path) | ||||||
| { | { | ||||||
| 	VIRTUAL_STORAGE_TYPE vtype = { 1, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT }; | 	VIRTUAL_STORAGE_TYPE vtype = { 1, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT }; | ||||||
| 	ATTACH_VIRTUAL_DISK_PARAMETERS vparams = {0}; | 	ATTACH_VIRTUAL_DISK_PARAMETERS vparams = { 0 }; | ||||||
| 	DWORD r; | 	DWORD r; | ||||||
| 	wchar_t wtmp[128]; | 	wchar_t wtmp[128]; | ||||||
| 	ULONG size = ARRAYSIZE(wtmp); | 	ULONG size = ARRAYSIZE(wtmp); | ||||||
|  | @ -1766,3 +1769,154 @@ void UnMountISO(void) | ||||||
| out: | out: | ||||||
| 	physical_path[0] = 0; | 	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) | ||||||
|  | { | ||||||
|  | 	BOOL s; | ||||||
|  | 	DWORD rSize, wSize; | ||||||
|  | 	IMG_SAVE* img_save = (IMG_SAVE*)param; | ||||||
|  | 	HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE; | ||||||
|  | 	HANDLE hDestImage = INVALID_HANDLE_VALUE; | ||||||
|  | 	LARGE_INTEGER li; | ||||||
|  | 	uint8_t* buffer = NULL; | ||||||
|  | 	uint64_t wb; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	assert(img_save->Type == VIRTUAL_STORAGE_TYPE_DEVICE_ISO); | ||||||
|  | 
 | ||||||
|  | 	PrintInfoDebug(0, MSG_225); | ||||||
|  | 	hPhysicalDrive = CreateFileA(img_save->DevicePath, GENERIC_READ, FILE_SHARE_READ, | ||||||
|  | 		NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); | ||||||
|  | 	if (hPhysicalDrive == INVALID_HANDLE_VALUE) { | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// In case someone poked the disc before us
 | ||||||
|  | 	li.QuadPart = 0; | ||||||
|  | 	if (!SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN)) | ||||||
|  | 		uprintf("Warning: Unable to rewind device position - wrong data might be copied!"); | ||||||
|  | 	hDestImage = CreateFileU(img_save->ImagePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, | ||||||
|  | 		CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | ||||||
|  | 	if (hDestImage == INVALID_HANDLE_VALUE) { | ||||||
|  | 		uprintf("Could not open image '%s': %s", img_save->ImagePath, WindowsErrorString()); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	buffer = (uint8_t*)_mm_malloc(img_save->BufSize, 16); | ||||||
|  | 	if (buffer == NULL) { | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_NOT_ENOUGH_MEMORY; | ||||||
|  | 		uprintf("Could not allocate buffer"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	uprintf("Will use a buffer size of %s", SizeToHumanReadable(img_save->BufSize, FALSE, FALSE)); | ||||||
|  | 	uprintf("Saving to image '%s'...", img_save->ImagePath); | ||||||
|  | 
 | ||||||
|  | 	// Don't bother trying for something clever, using double buffering overlapped and whatnot:
 | ||||||
|  | 	// With Windows' default optimizations, sync read + sync write for sequential operations
 | ||||||
|  | 	// will be as fast, if not faster, than whatever async scheme you can come up with.
 | ||||||
|  | 	UpdateProgressWithInfoInit(NULL, FALSE); | ||||||
|  | 	for (wb = 0; ; wb += wSize) { | ||||||
|  | 		// Optical drives do not appear to increment the sectors to read automatically
 | ||||||
|  | 		li.QuadPart = wb; | ||||||
|  | 		if (!SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN)) | ||||||
|  | 			uprintf("Warning: Unable to set device position - wrong data might be copied!"); | ||||||
|  | 		s = ReadFile(hPhysicalDrive, buffer, | ||||||
|  | 			(DWORD)MIN(img_save->BufSize, img_save->DeviceSize - wb), &rSize, NULL); | ||||||
|  | 		if (!s) { | ||||||
|  | 			FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_READ_FAULT; | ||||||
|  | 			uprintf("Read error: %s", WindowsErrorString()); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 		if (rSize == 0) | ||||||
|  | 			break; | ||||||
|  | 		UpdateProgressWithInfo(OP_FORMAT, MSG_261, wb, img_save->DeviceSize); | ||||||
|  | 		for (i = 1; i <= WRITE_RETRIES; i++) { | ||||||
|  | 			CHECK_FOR_USER_CANCEL; | ||||||
|  | 			s = WriteFile(hDestImage, buffer, rSize, &wSize, NULL); | ||||||
|  | 			if ((s) && (wSize == rSize)) | ||||||
|  | 				break; | ||||||
|  | 			if (s) | ||||||
|  | 				uprintf("Write error: Wrote %d bytes, expected %d bytes", wSize, rSize); | ||||||
|  | 			else | ||||||
|  | 				uprintf("Write error: %s", WindowsErrorString()); | ||||||
|  | 			if (i < WRITE_RETRIES) { | ||||||
|  | 				li.QuadPart = wb; | ||||||
|  | 				uprintf("Retrying in %d seconds...", WRITE_TIMEOUT / 1000); | ||||||
|  | 				Sleep(WRITE_TIMEOUT); | ||||||
|  | 				if (!SetFilePointerEx(hDestImage, li, NULL, FILE_BEGIN)) { | ||||||
|  | 					uprintf("Write error: Could not reset position - %s", WindowsErrorString()); | ||||||
|  | 					goto out; | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_WRITE_FAULT; | ||||||
|  | 				goto out; | ||||||
|  | 			} | ||||||
|  | 			Sleep(200); | ||||||
|  | 		} | ||||||
|  | 		if (i > WRITE_RETRIES) | ||||||
|  | 			goto out; | ||||||
|  | 	} | ||||||
|  | 	if (wb != img_save->DeviceSize) { | ||||||
|  | 		uprintf("Error: wrote %s, expected %s", SizeToHumanReadable(wb, FALSE, FALSE), | ||||||
|  | 			SizeToHumanReadable(img_save->DeviceSize, FALSE, FALSE)); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_WRITE_FAULT; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	uprintf("Operation complete (Wrote %s).", SizeToHumanReadable(wb, FALSE, FALSE)); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	safe_free(img_save->ImagePath); | ||||||
|  | 	safe_mm_free(buffer); | ||||||
|  | 	safe_closehandle(hDestImage); | ||||||
|  | 	safe_unlockclose(hPhysicalDrive); | ||||||
|  | 	PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)TRUE, 0); | ||||||
|  | 	ExitThread(0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SaveISO(void) | ||||||
|  | { | ||||||
|  | 	static IMG_SAVE img_save = { 0 }; | ||||||
|  | 	char filename[33] = "disc_image.iso"; | ||||||
|  | 	EXT_DECL(img_ext, filename, __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036))); | ||||||
|  | 
 | ||||||
|  | 	if (op_in_progress || (format_thread != NULL)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_ISO; | ||||||
|  | 	if (!GetOpticalMedia(&img_save)) { | ||||||
|  | 		uprintf("No dumpable optical media found."); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	// Adjust the buffer size according to the disc size so that we get a decent speed.
 | ||||||
|  | 	for (img_save.BufSize = 32 * MB; | ||||||
|  | 		(img_save.BufSize > 8 * MB) && (img_save.DeviceSize <= img_save.BufSize * 64); | ||||||
|  | 		img_save.BufSize /= 2); | ||||||
|  | 	if ((img_save.Label != NULL) && (img_save.Label[0] != 0)) | ||||||
|  | 		static_sprintf(filename, "%s.iso", img_save.Label); | ||||||
|  | 
 | ||||||
|  | 	img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); | ||||||
|  | 	if (img_save.ImagePath == NULL) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	uprintf("ISO media size %s", SizeToHumanReadable(img_save.DeviceSize, FALSE, FALSE)); | ||||||
|  | 	SendMessage(hMainDialog, UM_PROGRESS_INIT, 0, 0); | ||||||
|  | 	FormatStatus = 0; | ||||||
|  | 	// Disable all controls except cancel
 | ||||||
|  | 	EnableControls(FALSE, FALSE); | ||||||
|  | 	InitProgress(TRUE); | ||||||
|  | 	format_thread = CreateThread(NULL, 0, SaveISOThread, &img_save, 0, NULL); | ||||||
|  | 	if (format_thread != NULL) { | ||||||
|  | 		uprintf("\r\nSave to ISO operation started"); | ||||||
|  | 		PrintInfo(0, -1); | ||||||
|  | 		SendMessage(hMainDialog, UM_TIMER_START, 0, 0); | ||||||
|  | 	} else { | ||||||
|  | 		uprintf("Unable to start ISO save thread"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD); | ||||||
|  | 		safe_free(img_save.ImagePath); | ||||||
|  | 		PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -185,10 +185,6 @@ static __inline uint16_t remap16(uint16_t src, uint16_t* map, const BOOL reverse | ||||||
| #define ERROR_OFFSET_ALIGNMENT_VIOLATION        327 | #define ERROR_OFFSET_ALIGNMENT_VIOLATION        327 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| /* The following is used for native ISO mounting in Windows 8 or later */ |  | ||||||
| #define VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT \ |  | ||||||
| 	{ 0xEC984AECL, 0xA0F9, 0x47e9, { 0x90, 0x1F, 0x71, 0x41, 0x5A, 0x66, 0x34, 0x5B } } |  | ||||||
| 
 |  | ||||||
| /* RISC-V is still bleeding edge */ | /* RISC-V is still bleeding edge */ | ||||||
| #ifndef IMAGE_FILE_MACHINE_RISCV32 | #ifndef IMAGE_FILE_MACHINE_RISCV32 | ||||||
| #define IMAGE_FILE_MACHINE_RISCV32 0x5032 | #define IMAGE_FILE_MACHINE_RISCV32 0x5032 | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <inttypes.h> | #include <inttypes.h> | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
|  | #include <virtdisk.h> | ||||||
| 
 | 
 | ||||||
| #include "rufus.h" | #include "rufus.h" | ||||||
| #include "missing.h" | #include "missing.h" | ||||||
|  | @ -948,7 +949,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) | ||||||
| 		free(sig); | 		free(sig); | ||||||
| 		uprintf("Download signature is valid ✓"); | 		uprintf("Download signature is valid ✓"); | ||||||
| 		uncompressed_size = *((uint64_t*)&compressed[5]); | 		uncompressed_size = *((uint64_t*)&compressed[5]); | ||||||
| 		if ((uncompressed_size < 1 * MB) && (bled_init(uprintf, NULL, NULL, NULL, NULL, &FormatStatus) >= 0)) { | 		if ((uncompressed_size < 1 * MB) && (bled_init(0, uprintf, NULL, NULL, NULL, NULL, &FormatStatus) >= 0)) { | ||||||
| 			fido_script = malloc((size_t)uncompressed_size); | 			fido_script = malloc((size_t)uncompressed_size); | ||||||
| 			size = bled_uncompress_from_buffer_to_buffer(compressed, dwCompressedSize, fido_script, (size_t)uncompressed_size, BLED_COMPRESSION_LZMA); | 			size = bled_uncompress_from_buffer_to_buffer(compressed, dwCompressedSize, fido_script, (size_t)uncompressed_size, BLED_COMPRESSION_LZMA); | ||||||
| 			bled_exit(); | 			bled_exit(); | ||||||
|  | @ -1038,7 +1039,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) | ||||||
| #pragma warning(default: 6386) | #pragma warning(default: 6386) | ||||||
| #endif | #endif | ||||||
| 			EXT_DECL(img_ext, GetShortName(url), __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036))); | 			EXT_DECL(img_ext, GetShortName(url), __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036))); | ||||||
| 			img_save.Type = IMG_SAVE_TYPE_ISO; | 			img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_ISO; | ||||||
| 			img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); | 			img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); | ||||||
| 			if (img_save.ImagePath == NULL) { | 			if (img_save.ImagePath == NULL) { | ||||||
| 				goto out; | 				goto out; | ||||||
|  |  | ||||||
|  | @ -812,7 +812,8 @@ BOOL ParseSKUSiPolicy(void) | ||||||
| 
 | 
 | ||||||
| 	pe256ssp_size = 0; | 	pe256ssp_size = 0; | ||||||
| 	safe_free(pe256ssp); | 	safe_free(pe256ssp); | ||||||
| 	static_sprintf(path, "%s\\SecureBootUpdates\\SKUSiPolicy.p7b", system_dir); | 	// Must use sysnative for WOW
 | ||||||
|  | 	static_sprintf(path, "%s\\SecureBootUpdates\\SKUSiPolicy.p7b", sysnative_dir); | ||||||
| 	wpath = utf8_to_wchar(path); | 	wpath = utf8_to_wchar(path); | ||||||
| 	if (wpath == NULL) | 	if (wpath == NULL) | ||||||
| 		goto out; | 		goto out; | ||||||
|  |  | ||||||
							
								
								
									
										104
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										104
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -87,7 +87,6 @@ static int selected_pt = -1, selected_fs = FS_UNKNOWN, preselected_fs = FS_UNKNO | ||||||
| static int image_index = 0, select_index = 0; | static int image_index = 0, select_index = 0; | ||||||
| static RECT relaunch_rc = { -65536, -65536, 0, 0}; | static RECT relaunch_rc = { -65536, -65536, 0, 0}; | ||||||
| static UINT uMBRChecked = BST_UNCHECKED; | static UINT uMBRChecked = BST_UNCHECKED; | ||||||
| static HANDLE format_thread = NULL; |  | ||||||
| static HWND hSelectImage = NULL, hStart = NULL; | static HWND hSelectImage = NULL, hStart = NULL; | ||||||
| static char szTimer[12] = "00:00:00"; | static char szTimer[12] = "00:00:00"; | ||||||
| static unsigned int timer; | static unsigned int timer; | ||||||
|  | @ -121,7 +120,7 @@ WORD selected_langid = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); | ||||||
| DWORD MainThreadId; | DWORD MainThreadId; | ||||||
| HWND hDeviceList, hPartitionScheme, hTargetSystem, hFileSystem, hClusterSize, hLabel, hBootType, hNBPasses, hLog = NULL; | HWND hDeviceList, hPartitionScheme, hTargetSystem, hFileSystem, hClusterSize, hLabel, hBootType, hNBPasses, hLog = NULL; | ||||||
| HWND hImageOption, hLogDialog = NULL, hProgress = NULL, hDiskID; | HWND hImageOption, hLogDialog = NULL, hProgress = NULL, hDiskID; | ||||||
| HANDLE dialog_handle = NULL; | HANDLE dialog_handle = NULL, format_thread = NULL; | ||||||
| BOOL is_x86_64, use_own_c32[NB_OLD_C32] = { FALSE, FALSE }, mbr_selected_by_user = FALSE, lock_drive = TRUE; | BOOL is_x86_64, use_own_c32[NB_OLD_C32] = { FALSE, FALSE }, mbr_selected_by_user = FALSE, lock_drive = TRUE; | ||||||
| BOOL op_in_progress = TRUE, right_to_left_mode = FALSE, has_uefi_csm = FALSE, its_a_me_mario = FALSE; | BOOL op_in_progress = TRUE, right_to_left_mode = FALSE, has_uefi_csm = FALSE, its_a_me_mario = FALSE; | ||||||
| BOOL enable_HDDs = FALSE, enable_VHDs = TRUE, enable_ntfs_compression = FALSE, no_confirmation_on_cancel = FALSE; | BOOL enable_HDDs = FALSE, enable_VHDs = TRUE, enable_ntfs_compression = FALSE, no_confirmation_on_cancel = FALSE; | ||||||
|  | @ -862,7 +861,7 @@ static void EnableBootOptions(BOOL enable, BOOL remove_checkboxes) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Toggle controls according to operation
 | // Toggle controls according to operation
 | ||||||
| static void EnableControls(BOOL enable, BOOL remove_checkboxes) | void EnableControls(BOOL enable, BOOL remove_checkboxes) | ||||||
| { | { | ||||||
| 	op_in_progress = !enable; | 	op_in_progress = !enable; | ||||||
| 
 | 
 | ||||||
|  | @ -2161,104 +2160,6 @@ static void PrintStatusTimeout(const char* str, BOOL val) | ||||||
| 	PrintStatus(STATUS_MSG_TIMEOUT, (val)?MSG_250:MSG_251, str); | 	PrintStatus(STATUS_MSG_TIMEOUT, (val)?MSG_250:MSG_251, str); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void SaveVHD(void) |  | ||||||
| { |  | ||||||
| 	static IMG_SAVE img_save = { 0 }; |  | ||||||
| 	char filename[128]; |  | ||||||
| 	char path[MAX_PATH]; |  | ||||||
| 	int DriveIndex = ComboBox_GetCurSel(hDeviceList); |  | ||||||
| 	EXT_DECL(img_ext, filename, __VA_GROUP__("*.vhd"), __VA_GROUP__(lmprintf(MSG_095))); |  | ||||||
| 	ULARGE_INTEGER free_space; |  | ||||||
| 
 |  | ||||||
| 	if ((DriveIndex < 0) || (format_thread != NULL)) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	static_sprintf(filename, "%s.vhd", rufus_drive[DriveIndex].label); |  | ||||||
| 	img_save.Type = IMG_SAVE_TYPE_VHD; |  | ||||||
| 	img_save.DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, DriveIndex); |  | ||||||
| 	img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); |  | ||||||
| 	img_save.BufSize = DD_BUFFER_SIZE; |  | ||||||
| 	img_save.DeviceSize = SelectedDrive.DiskSize; |  | ||||||
| 	if (img_save.ImagePath != NULL) { |  | ||||||
| 		// Reset all progress bars
 |  | ||||||
| 		SendMessage(hMainDialog, UM_PROGRESS_INIT, 0, 0); |  | ||||||
| 		FormatStatus = 0; |  | ||||||
| 		free_space.QuadPart = 0; |  | ||||||
| 		if ((GetVolumePathNameA(img_save.ImagePath, path, sizeof(path))) |  | ||||||
| 			&& (GetDiskFreeSpaceExA(path, &free_space, NULL, NULL)) |  | ||||||
| 			&& ((LONGLONG)free_space.QuadPart > (SelectedDrive.DiskSize + 512))) { |  | ||||||
| 			// Disable all controls except cancel
 |  | ||||||
| 			EnableControls(FALSE, FALSE); |  | ||||||
| 			FormatStatus = 0; |  | ||||||
| 			InitProgress(TRUE); |  | ||||||
| 			format_thread = CreateThread(NULL, 0, SaveImageThread, &img_save, 0, NULL); |  | ||||||
| 			if (format_thread != NULL) { |  | ||||||
| 				uprintf("\r\nSave to VHD operation started"); |  | ||||||
| 				PrintInfo(0, -1); |  | ||||||
| 				SendMessage(hMainDialog, UM_TIMER_START, 0, 0); |  | ||||||
| 			} else { |  | ||||||
| 				uprintf("Unable to start VHD save thread"); |  | ||||||
| 				FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD); |  | ||||||
| 				safe_free(img_save.ImagePath); |  | ||||||
| 				PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0); |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			if (free_space.QuadPart == 0) { |  | ||||||
| 				uprintf("Unable to isolate drive name for VHD save"); |  | ||||||
| 				FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_PATH_NOT_FOUND; |  | ||||||
| 			} else { |  | ||||||
| 				uprintf("The VHD size is too large for the target drive"); |  | ||||||
| 				FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_FILE_TOO_LARGE; |  | ||||||
| 			} |  | ||||||
| 			safe_free(img_save.ImagePath); |  | ||||||
| 			PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void SaveISO(void) |  | ||||||
| { |  | ||||||
| 	static IMG_SAVE img_save = { 0 }; |  | ||||||
| 	char filename[33] = "disc_image.iso"; |  | ||||||
| 	EXT_DECL(img_ext, filename, __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036))); |  | ||||||
| 
 |  | ||||||
| 	if (op_in_progress || (format_thread != NULL)) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	img_save.Type = IMG_SAVE_TYPE_ISO; |  | ||||||
| 	if (!GetOpticalMedia(&img_save)) { |  | ||||||
| 		uprintf("No dumpable optical media found."); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 	// Adjust the buffer size according to the disc size so that we get a decent speed.
 |  | ||||||
| 	for (img_save.BufSize = 32 * MB; |  | ||||||
| 		(img_save.BufSize > 8 * MB) && (img_save.DeviceSize <= img_save.BufSize * 64); |  | ||||||
| 		img_save.BufSize /= 2); |  | ||||||
| 	if ((img_save.Label != NULL) && (img_save.Label[0] != 0)) |  | ||||||
| 		static_sprintf(filename, "%s.iso", img_save.Label); |  | ||||||
| 	uprintf("ISO media size %s", SizeToHumanReadable(img_save.DeviceSize, FALSE, FALSE)); |  | ||||||
| 
 |  | ||||||
| 	img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); |  | ||||||
| 	if (img_save.ImagePath == NULL) |  | ||||||
| 		return; |  | ||||||
| 	SendMessage(hMainDialog, UM_PROGRESS_INIT, 0, 0); |  | ||||||
| 	FormatStatus = 0; |  | ||||||
| 	// Disable all controls except cancel
 |  | ||||||
| 	EnableControls(FALSE, FALSE); |  | ||||||
| 	InitProgress(TRUE); |  | ||||||
| 	format_thread = CreateThread(NULL, 0, SaveImageThread, &img_save, 0, NULL); |  | ||||||
| 	if (format_thread != NULL) { |  | ||||||
| 		uprintf("\r\nSave to ISO operation started"); |  | ||||||
| 		PrintInfo(0, -1); |  | ||||||
| 		SendMessage(hMainDialog, UM_TIMER_START, 0, 0); |  | ||||||
| 	} else { |  | ||||||
| 		uprintf("Unable to start ISO save thread"); |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD); |  | ||||||
| 		safe_free(img_save.ImagePath); |  | ||||||
| 		PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Check for conflicting processes accessing the drive.
 | // Check for conflicting processes accessing the drive.
 | ||||||
| // If bPrompt is true, ask the user whether they want to proceed.
 | // If bPrompt is true, ask the user whether they want to proceed.
 | ||||||
| // dwTimeOut is the maximum amount of time we allow for this call to execute (in ms)
 | // dwTimeOut is the maximum amount of time we allow for this call to execute (in ms)
 | ||||||
|  | @ -2764,6 +2665,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 			MyDialogBox(hMainInstance, IDD_UPDATE_POLICY, hDlg, UpdateCallback); | 			MyDialogBox(hMainInstance, IDD_UPDATE_POLICY, hDlg, UpdateCallback); | ||||||
| 			break; | 			break; | ||||||
| 		case IDC_HASH: | 		case IDC_HASH: | ||||||
|  | 			// TODO: Move this as a fn call in hash.c?
 | ||||||
| 			if ((format_thread == NULL) && (image_path != NULL)) { | 			if ((format_thread == NULL) && (image_path != NULL)) { | ||||||
| 				FormatStatus = 0; | 				FormatStatus = 0; | ||||||
| 				no_confirmation_on_cancel = TRUE; | 				no_confirmation_on_cancel = TRUE; | ||||||
|  |  | ||||||
|  | @ -71,6 +71,7 @@ | ||||||
| #define PATCH_PROGRESS_TOTAL        207 | #define PATCH_PROGRESS_TOTAL        207 | ||||||
| #define MAX_LOG_SIZE                0x7FFFFFFE | #define MAX_LOG_SIZE                0x7FFFFFFE | ||||||
| #define MAX_REFRESH                 25			// How long we should wait to refresh UI elements (in ms)
 | #define MAX_REFRESH                 25			// How long we should wait to refresh UI elements (in ms)
 | ||||||
|  | #define MARQUEE_TIMER_REFRESH       10			// Time between progress bar marquee refreshes, in ms
 | ||||||
| #define MAX_GUID_STRING_LENGTH      40 | #define MAX_GUID_STRING_LENGTH      40 | ||||||
| #define MAX_PARTITIONS              16			// Maximum number of partitions we handle
 | #define MAX_PARTITIONS              16			// Maximum number of partitions we handle
 | ||||||
| #define MAX_ESP_TOGGLE              8			// Maximum number of entries we record to toggle GPT ESP back and forth
 | #define MAX_ESP_TOGGLE              8			// Maximum number of entries we record to toggle GPT ESP back and forth
 | ||||||
|  | @ -88,7 +89,6 @@ | ||||||
| #define WRITE_TIMEOUT               5000		// How long we should wait between write retries (in ms)
 | #define WRITE_TIMEOUT               5000		// How long we should wait between write retries (in ms)
 | ||||||
| #define SEARCH_PROCESS_TIMEOUT      10000		// How long we should search for conflicting processes before giving up (in ms)
 | #define SEARCH_PROCESS_TIMEOUT      10000		// How long we should search for conflicting processes before giving up (in ms)
 | ||||||
| #define NET_SESSION_TIMEOUT         3500		// How long we should wait to connect, send or receive internet data
 | #define NET_SESSION_TIMEOUT         3500		// How long we should wait to connect, send or receive internet data
 | ||||||
| #define MARQUEE_TIMER_REFRESH       10			// Time between progress bar marquee refreshes, in ms
 |  | ||||||
| #define FS_DEFAULT                  FS_FAT32 | #define FS_DEFAULT                  FS_FAT32 | ||||||
| #define SINGLE_CLUSTERSIZE_DEFAULT  0x00000100 | #define SINGLE_CLUSTERSIZE_DEFAULT  0x00000100 | ||||||
| #define BADLOCKS_PATTERN_TYPES      5 | #define BADLOCKS_PATTERN_TYPES      5 | ||||||
|  | @ -433,9 +433,6 @@ typedef struct { | ||||||
| 	char* release_notes; | 	char* release_notes; | ||||||
| } RUFUS_UPDATE; | } RUFUS_UPDATE; | ||||||
| 
 | 
 | ||||||
| #define IMG_SAVE_TYPE_VHD 1 |  | ||||||
| #define IMG_SAVE_TYPE_ISO 2 |  | ||||||
| 
 |  | ||||||
| typedef struct { | typedef struct { | ||||||
| 	DWORD Type; | 	DWORD Type; | ||||||
| 	DWORD DeviceNum; | 	DWORD DeviceNum; | ||||||
|  | @ -726,7 +723,6 @@ extern HANDLE CreatePreallocatedFile(const char* lpFileName, DWORD dwDesiredAcce | ||||||
| 	DWORD dwFlagsAndAttributes, LONGLONG fileSize); | 	DWORD dwFlagsAndAttributes, LONGLONG fileSize); | ||||||
| #define GetTextWidth(hDlg, id) GetTextSize(GetDlgItem(hDlg, id), NULL).cx | #define GetTextWidth(hDlg, id) GetTextSize(GetDlgItem(hDlg, id), NULL).cx | ||||||
| 
 | 
 | ||||||
| DWORD WINAPI SaveImageThread(void* param); |  | ||||||
| DWORD WINAPI HashThread(void* param); | DWORD WINAPI HashThread(void* param); | ||||||
| 
 | 
 | ||||||
| /* Hash tables */ | /* Hash tables */ | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | ||||||
| IDD_DIALOG DIALOGEX 12, 12, 232, 326 | IDD_DIALOG DIALOGEX 12, 12, 232, 326 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_ACCEPTFILES | EXSTYLE WS_EX_ACCEPTFILES | ||||||
| CAPTION "Rufus 4.2.2057" | CAPTION "Rufus 4.2.2060" | ||||||
| FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | ||||||
| BEGIN | BEGIN | ||||||
|     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP |     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP | ||||||
|  | @ -392,8 +392,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 4,2,2057,0 |  FILEVERSION 4,2,2060,0 | ||||||
|  PRODUCTVERSION 4,2,2057,0 |  PRODUCTVERSION 4,2,2060,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -411,13 +411,13 @@ BEGIN | ||||||
|             VALUE "Comments", "https://rufus.ie" |             VALUE "Comments", "https://rufus.ie" | ||||||
|             VALUE "CompanyName", "Akeo Consulting" |             VALUE "CompanyName", "Akeo Consulting" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "4.2.2057" |             VALUE "FileVersion", "4.2.2060" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" |             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" | ||||||
|             VALUE "OriginalFilename", "rufus-4.2.exe" |             VALUE "OriginalFilename", "rufus-4.2.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "4.2.2057" |             VALUE "ProductVersion", "4.2.2060" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								src/stdlg.c
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								src/stdlg.c
									
										
									
									
									
								
							|  | @ -103,7 +103,7 @@ char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options) | ||||||
| 	IFileDialog *pfd = NULL; | 	IFileDialog *pfd = NULL; | ||||||
| 	IShellItem *psiResult; | 	IShellItem *psiResult; | ||||||
| 	COMDLG_FILTERSPEC* filter_spec = NULL; | 	COMDLG_FILTERSPEC* filter_spec = NULL; | ||||||
| 	wchar_t *wpath = NULL, *wfilename = NULL; | 	wchar_t *wpath = NULL, *wfilename = NULL, *wext = NULL; | ||||||
| 	IShellItem *si_path = NULL;	// Automatically freed
 | 	IShellItem *si_path = NULL;	// Automatically freed
 | ||||||
| 
 | 
 | ||||||
| 	if ((ext == NULL) || (ext->count == 0) || (ext->extension == NULL) || (ext->description == NULL)) | 	if ((ext == NULL) || (ext->count == 0) || (ext->extension == NULL) || (ext->description == NULL)) | ||||||
|  | @ -162,11 +162,20 @@ char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options) | ||||||
| 		if (wfilename != NULL) { | 		if (wfilename != NULL) { | ||||||
| 			IFileDialog_SetFileName(pfd, wfilename); | 			IFileDialog_SetFileName(pfd, wfilename); | ||||||
| 		} | 		} | ||||||
|  | 		// Set a default extension so that when the user switches filters it gets
 | ||||||
|  | 		// automatically updated. Note that the IFileDialog::SetDefaultExtension()
 | ||||||
|  | 		// doc says the extension shouldn't be prefixed with unwanted characters
 | ||||||
|  | 		// but it appears to work regardless so we don't bother cleaning it.
 | ||||||
|  | 		wext = utf8_to_wchar((ext->extension == NULL) ? "" : ext->extension[0]); | ||||||
|  | 		if (wext != NULL) { | ||||||
|  | 			IFileDialog_SetDefaultExtension(pfd, wext); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		// Display the dialog
 | 		// Display the dialog
 | ||||||
| 		hr = IFileDialog_Show(pfd, hMainDialog); | 		hr = IFileDialog_Show(pfd, hMainDialog); | ||||||
| 
 | 
 | ||||||
| 		// Cleanup
 | 		// Cleanup
 | ||||||
|  | 		safe_free(wext); | ||||||
| 		safe_free(wfilename); | 		safe_free(wfilename); | ||||||
| 		for (i = 0; i < ext->count; i++) { | 		for (i = 0; i < ext->count; i++) { | ||||||
| 			safe_free(filter_spec[i].pszSpec); | 			safe_free(filter_spec[i].pszSpec); | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								src/ui.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								src/ui.h
									
										
									
									
									
								
							|  | @ -20,6 +20,7 @@ | ||||||
| #include <windows.h> | #include <windows.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include "resource.h" | #include "resource.h" | ||||||
|  | #include "localization.h" | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | @ -99,6 +100,7 @@ extern void ToggleAdvancedFormatOptions(BOOL enable); | ||||||
| extern void ToggleImageOptions(void); | extern void ToggleImageOptions(void); | ||||||
| extern void CreateSmallButtons(HWND hDlg); | extern void CreateSmallButtons(HWND hDlg); | ||||||
| extern void CreateAdditionalControls(HWND hDlg); | extern void CreateAdditionalControls(HWND hDlg); | ||||||
|  | extern void EnableControls(BOOL enable, BOOL remove_checkboxes); | ||||||
| extern void InitProgress(BOOL bOnlyFormat); | extern void InitProgress(BOOL bOnlyFormat); | ||||||
| extern void ShowLanguageMenu(RECT rcExclude); | extern void ShowLanguageMenu(RECT rcExclude); | ||||||
| extern void SetPassesTooltip(void); | extern void SetPassesTooltip(void); | ||||||
|  |  | ||||||
							
								
								
									
										243
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										243
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -18,13 +18,15 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <windows.h> | #include <windows.h> | ||||||
|  | #include <windowsx.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <io.h> | #include <io.h> | ||||||
| #include <rpc.h> | #include <rpc.h> | ||||||
| #include <time.h> | #include <time.h> | ||||||
| 
 | 
 | ||||||
| #include "vhd.h" |  | ||||||
| #include "rufus.h" | #include "rufus.h" | ||||||
|  | #include "ui.h" | ||||||
|  | #include "vhd.h" | ||||||
| #include "missing.h" | #include "missing.h" | ||||||
| #include "resource.h" | #include "resource.h" | ||||||
| #include "msapi_utf8.h" | #include "msapi_utf8.h" | ||||||
|  | @ -45,7 +47,6 @@ PF_TYPE_DECL(WINAPI, BOOL, WIMGetImageInformation, (HANDLE, PVOID, PDWORD)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMCloseHandle, (HANDLE)); | PF_TYPE_DECL(WINAPI, BOOL, WIMCloseHandle, (HANDLE)); | ||||||
| PF_TYPE_DECL(WINAPI, DWORD, WIMRegisterMessageCallback, (HANDLE, FARPROC, PVOID)); | PF_TYPE_DECL(WINAPI, DWORD, WIMRegisterMessageCallback, (HANDLE, FARPROC, PVOID)); | ||||||
| PF_TYPE_DECL(WINAPI, DWORD, WIMUnregisterMessageCallback, (HANDLE, FARPROC)); | PF_TYPE_DECL(WINAPI, DWORD, WIMUnregisterMessageCallback, (HANDLE, FARPROC)); | ||||||
| PF_TYPE_DECL(RPC_ENTRY, RPC_STATUS, UuidCreate, (UUID __RPC_FAR*)); |  | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
| 	int index; | 	int index; | ||||||
|  | @ -58,6 +59,8 @@ uint32_t wim_nb_files, wim_proc_files, wim_extra_files; | ||||||
| HANDLE wim_thread = NULL; | HANDLE wim_thread = NULL; | ||||||
| extern int default_thread_priority; | extern int default_thread_priority; | ||||||
| extern BOOL ignore_boot_marker; | extern BOOL ignore_boot_marker; | ||||||
|  | extern RUFUS_DRIVE rufus_drive[MAX_DRIVES]; | ||||||
|  | extern HANDLE format_thread; | ||||||
| 
 | 
 | ||||||
| static uint8_t wim_flags = 0; | static uint8_t wim_flags = 0; | ||||||
| static uint32_t progress_report_mask; | static uint32_t progress_report_mask; | ||||||
|  | @ -78,102 +81,6 @@ static BOOL Get7ZipPath(void) | ||||||
| 	return FALSE; | 	return FALSE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOL AppendVHDFooter(const char* vhd_path) |  | ||||||
| { |  | ||||||
| 	const char creator_os[4] = VHD_FOOTER_CREATOR_HOST_OS_WINDOWS; |  | ||||||
| 	const char creator_app[4] = { 'r', 'u', 'f', 's' }; |  | ||||||
| 	BOOL r = FALSE; |  | ||||||
| 	DWORD size; |  | ||||||
| 	LARGE_INTEGER li; |  | ||||||
| 	HANDLE handle = INVALID_HANDLE_VALUE; |  | ||||||
| 	vhd_footer* footer = NULL; |  | ||||||
| 	uint64_t totalSectors; |  | ||||||
| 	uint16_t cylinders = 0; |  | ||||||
| 	uint8_t heads, sectorsPerTrack; |  | ||||||
| 	uint32_t cylinderTimesHeads; |  | ||||||
| 	uint32_t checksum; |  | ||||||
| 	size_t i; |  | ||||||
| 
 |  | ||||||
| 	PF_INIT(UuidCreate, Rpcrt4); |  | ||||||
| 	handle = CreateFileU(vhd_path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, |  | ||||||
| 		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |  | ||||||
| 	li.QuadPart = 0; |  | ||||||
| 	if ((handle == INVALID_HANDLE_VALUE) || (!SetFilePointerEx(handle, li, &li, FILE_END))) { |  | ||||||
| 		uprintf("Could not open image '%s': %s", vhd_path, WindowsErrorString()); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 	footer = (vhd_footer*)calloc(1, sizeof(vhd_footer)); |  | ||||||
| 	if (footer == NULL) { |  | ||||||
| 		uprintf("Could not allocate VHD footer"); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	memcpy(footer->cookie, conectix_str, sizeof(footer->cookie)); |  | ||||||
| 	footer->features = bswap_uint32(VHD_FOOTER_FEATURES_RESERVED); |  | ||||||
| 	footer->file_format_version = bswap_uint32(VHD_FOOTER_FILE_FORMAT_V1_0); |  | ||||||
| 	footer->data_offset = bswap_uint64(VHD_FOOTER_DATA_OFFSET_FIXED_DISK); |  | ||||||
| 	footer->timestamp = bswap_uint32((uint32_t)(_time64(NULL) - SECONDS_SINCE_JAN_1ST_2000)); |  | ||||||
| 	memcpy(footer->creator_app, creator_app, sizeof(creator_app)); |  | ||||||
| 	footer->creator_version = bswap_uint32((rufus_version[0]<<16)|rufus_version[1]); |  | ||||||
| 	memcpy(footer->creator_host_os, creator_os, sizeof(creator_os)); |  | ||||||
| 	footer->original_size = bswap_uint64(li.QuadPart); |  | ||||||
| 	footer->current_size = footer->original_size; |  | ||||||
| 	footer->disk_type = bswap_uint32(VHD_FOOTER_TYPE_FIXED_HARD_DISK); |  | ||||||
| 	if ((pfUuidCreate == NULL) || (pfUuidCreate(&footer->unique_id) != RPC_S_OK)) |  | ||||||
| 		uprintf("Warning: could not set VHD UUID"); |  | ||||||
| 
 |  | ||||||
| 	// Compute CHS, as per the VHD specs
 |  | ||||||
| 	totalSectors = li.QuadPart / 512; |  | ||||||
| 	if (totalSectors > 65535 * 16 * 255) { |  | ||||||
| 		totalSectors = 65535 * 16 * 255; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (totalSectors >= 65535 * 16 * 63) { |  | ||||||
| 		sectorsPerTrack = 255; |  | ||||||
| 		heads = 16; |  | ||||||
| 		cylinderTimesHeads = (uint32_t)(totalSectors / sectorsPerTrack); |  | ||||||
| 	} else { |  | ||||||
| 		sectorsPerTrack = 17; |  | ||||||
| 		cylinderTimesHeads = (uint32_t)(totalSectors / sectorsPerTrack); |  | ||||||
| 
 |  | ||||||
| 		heads = (cylinderTimesHeads + 1023) / 1024; |  | ||||||
| 
 |  | ||||||
| 		if (heads < 4) { |  | ||||||
| 			heads = 4; |  | ||||||
| 		} |  | ||||||
| 		if (cylinderTimesHeads >= ((uint32_t)heads * 1024) || heads > 16) { |  | ||||||
| 			sectorsPerTrack = 31; |  | ||||||
| 			heads = 16; |  | ||||||
| 			cylinderTimesHeads = (uint32_t)(totalSectors / sectorsPerTrack); |  | ||||||
| 		} |  | ||||||
| 		if (cylinderTimesHeads >= ((uint32_t)heads * 1024)) { |  | ||||||
| 			sectorsPerTrack = 63; |  | ||||||
| 			heads = 16; |  | ||||||
| 			cylinderTimesHeads = (uint32_t)(totalSectors / sectorsPerTrack); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	cylinders = cylinderTimesHeads / heads; |  | ||||||
| 	footer->disk_geometry.chs.cylinders = bswap_uint16(cylinders); |  | ||||||
| 	footer->disk_geometry.chs.heads = heads; |  | ||||||
| 	footer->disk_geometry.chs.sectors = sectorsPerTrack; |  | ||||||
| 
 |  | ||||||
| 	// Compute the VHD footer checksum
 |  | ||||||
| 	for (checksum=0, i=0; i<sizeof(vhd_footer); i++) |  | ||||||
| 		checksum += ((uint8_t*)footer)[i]; |  | ||||||
| 	footer->checksum = bswap_uint32(~checksum); |  | ||||||
| 
 |  | ||||||
| 	if (!WriteFileWithRetry(handle, footer, sizeof(vhd_footer), &size, WRITE_RETRIES)) { |  | ||||||
| 		uprintf("Could not write VHD footer: %s", WindowsErrorString()); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 	r = TRUE; |  | ||||||
| 
 |  | ||||||
| out: |  | ||||||
| 	safe_free(footer); |  | ||||||
| 	safe_closehandle(handle); |  | ||||||
| 	return r; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| typedef struct { | typedef struct { | ||||||
| 	const char* ext; | 	const char* ext; | ||||||
| 	bled_compression_type type; | 	bled_compression_type type; | ||||||
|  | @ -211,7 +118,7 @@ static BOOL IsCompressedBootableImage(const char* path) | ||||||
| 			if (buf == NULL) | 			if (buf == NULL) | ||||||
| 				return FALSE; | 				return FALSE; | ||||||
| 			FormatStatus = 0; | 			FormatStatus = 0; | ||||||
| 			bled_init(uprintf, NULL, NULL, NULL, NULL, &FormatStatus); | 			bled_init(0, uprintf, NULL, NULL, NULL, NULL, &FormatStatus); | ||||||
| 			dc = bled_uncompress_to_buffer(path, (char*)buf, MBR_SIZE, file_assoc[i].type); | 			dc = bled_uncompress_to_buffer(path, (char*)buf, MBR_SIZE, file_assoc[i].type); | ||||||
| 			bled_exit(); | 			bled_exit(); | ||||||
| 			if (dc != MBR_SIZE) { | 			if (dc != MBR_SIZE) { | ||||||
|  | @ -977,3 +884,141 @@ BOOL WimApplyImage(const char* image, int index, const char* dst) | ||||||
| 	wim_thread = NULL; | 	wim_thread = NULL; | ||||||
| 	return dw; | 	return dw; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // 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 SaveImageThread(void* param) | ||||||
|  | { | ||||||
|  | 	IMG_SAVE* img_save = (IMG_SAVE*)param; | ||||||
|  | 	HANDLE handle = INVALID_HANDLE_VALUE; | ||||||
|  | 	WCHAR* wDst = utf8_to_wchar(img_save->ImagePath); | ||||||
|  | 	WCHAR* wSrc = utf8_to_wchar(GetPhysicalName(img_save->DeviceNum)); | ||||||
|  | 	VIRTUAL_STORAGE_TYPE vtype = { img_save->Type, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT }; | ||||||
|  | 	STOPGAP_CREATE_VIRTUAL_DISK_PARAMETERS vparams = { 0 }; | ||||||
|  | 	VIRTUAL_DISK_PROGRESS vprogress = { 0 }; | ||||||
|  | 	OVERLAPPED overlapped = { 0 }; | ||||||
|  | 	DWORD result, flags; | ||||||
|  | 
 | ||||||
|  | 	assert(img_save->Type == VIRTUAL_STORAGE_TYPE_DEVICE_VHD || | ||||||
|  | 		img_save->Type == VIRTUAL_STORAGE_TYPE_DEVICE_VHDX); | ||||||
|  | 
 | ||||||
|  | 	UpdateProgressWithInfoInit(NULL, FALSE); | ||||||
|  | 
 | ||||||
|  | 	vparams.Version = CREATE_VIRTUAL_DISK_VERSION_2; | ||||||
|  | 	vparams.Version2.UniqueId = GUID_NULL; | ||||||
|  | 	vparams.Version2.BlockSizeInBytes = CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_BLOCK_SIZE; | ||||||
|  | 	vparams.Version2.SectorSizeInBytes = CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_SECTOR_SIZE; | ||||||
|  | 	vparams.Version2.PhysicalSectorSizeInBytes = SelectedDrive.SectorSize; | ||||||
|  | 	vparams.Version2.SourcePath = wSrc; | ||||||
|  | 
 | ||||||
|  | 	// When CREATE_VIRTUAL_DISK_FLAG_CREATE_BACKING_STORAGE is specified with
 | ||||||
|  | 	// a source path, CreateVirtualDisk() automatically clones the source to
 | ||||||
|  | 	// the virtual disk.
 | ||||||
|  | 	flags = CREATE_VIRTUAL_DISK_FLAG_CREATE_BACKING_STORAGE; | ||||||
|  | 	// The following ensures that VHD images are stored uncompressed and can
 | ||||||
|  | 	// be used as DD images.
 | ||||||
|  | 	if (img_save->Type != VIRTUAL_STORAGE_TYPE_DEVICE_VHDX) | ||||||
|  | 		flags |= CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION; | ||||||
|  | 	// TODO: Use CREATE_VIRTUAL_DISK_FLAG_PREVENT_WRITES_TO_SOURCE_DISK?
 | ||||||
|  | 
 | ||||||
|  | 	overlapped.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); | ||||||
|  | 
 | ||||||
|  | 	// CreateVirtualDisk() does not have an overwrite flag...
 | ||||||
|  | 	DeleteFileW(wDst); | ||||||
|  | 
 | ||||||
|  | 	result = CreateVirtualDisk(&vtype, wDst, VIRTUAL_DISK_ACCESS_NONE, NULL, | ||||||
|  | 		flags, 0, (PCREATE_VIRTUAL_DISK_PARAMETERS)&vparams, &overlapped, &handle); | ||||||
|  | 	if (result != ERROR_SUCCESS && result != ERROR_IO_PENDING) { | ||||||
|  | 		SetLastError(result); | ||||||
|  | 		uprintf("Could not create virtual disk: %s", WindowsErrorString()); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (result == ERROR_IO_PENDING) { | ||||||
|  | 		while ((result = WaitForSingleObject(overlapped.hEvent, 100)) == WAIT_TIMEOUT) { | ||||||
|  | 			if (IS_ERROR(FormatStatus) && (SCODE_CODE(FormatStatus) == ERROR_CANCELLED)) { | ||||||
|  | 				CancelIoEx(handle, &overlapped); | ||||||
|  | 				goto out; | ||||||
|  | 			} | ||||||
|  | 			if (GetVirtualDiskOperationProgress(handle, &overlapped, &vprogress) == ERROR_SUCCESS) { | ||||||
|  | 				if (vprogress.OperationStatus == ERROR_IO_PENDING) | ||||||
|  | 					UpdateProgressWithInfo(OP_FORMAT, MSG_261, vprogress.CurrentValue, vprogress.CompletionValue); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (result != WAIT_OBJECT_0) { | ||||||
|  | 			uprintf("Could not save virtual disk: %s", WindowsErrorString()); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	UpdateProgressWithInfo(OP_FORMAT, MSG_261, SelectedDrive.DiskSize, SelectedDrive.DiskSize); | ||||||
|  | 	uprintf("Operation complete."); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	safe_closehandle(handle); | ||||||
|  | 	safe_closehandle(overlapped.hEvent); | ||||||
|  | 	safe_free(wDst); | ||||||
|  | 	safe_free(wSrc); | ||||||
|  | 	safe_free(img_save->ImagePath); | ||||||
|  | 	PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)TRUE, 0); | ||||||
|  | 	ExitThread(0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SaveVHD(void) | ||||||
|  | { | ||||||
|  | 	static IMG_SAVE img_save = { 0 }; | ||||||
|  | 	char filename[128]; | ||||||
|  | 	char path[MAX_PATH]; | ||||||
|  | 	int DriveIndex = ComboBox_GetCurSel(hDeviceList); | ||||||
|  | 	EXT_DECL(img_ext, filename, __VA_GROUP__("*.vhdx", "*.vhd"), __VA_GROUP__(lmprintf(MSG_342), lmprintf(MSG_343))); | ||||||
|  | 	ULARGE_INTEGER free_space; | ||||||
|  | 
 | ||||||
|  | 	if ((DriveIndex < 0) || (format_thread != NULL)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	static_sprintf(filename, "%s.vhdx", rufus_drive[DriveIndex].label); | ||||||
|  | 	img_save.DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, DriveIndex); | ||||||
|  | 	img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); | ||||||
|  | 	img_save.Type = safe_strstr(img_save.ImagePath, ".vhdx") != NULL ? | ||||||
|  | 		VIRTUAL_STORAGE_TYPE_DEVICE_VHDX : VIRTUAL_STORAGE_TYPE_DEVICE_VHD; | ||||||
|  | 	img_save.BufSize = DD_BUFFER_SIZE; | ||||||
|  | 	img_save.DeviceSize = SelectedDrive.DiskSize; | ||||||
|  | 	if (img_save.ImagePath != NULL) { | ||||||
|  | 		// Reset all progress bars
 | ||||||
|  | 		SendMessage(hMainDialog, UM_PROGRESS_INIT, 0, 0); | ||||||
|  | 		FormatStatus = 0; | ||||||
|  | 		free_space.QuadPart = 0; | ||||||
|  | 		if ((GetVolumePathNameA(img_save.ImagePath, path, sizeof(path))) | ||||||
|  | 			&& (GetDiskFreeSpaceExA(path, &free_space, NULL, NULL)) | ||||||
|  | 			&& ((LONGLONG)free_space.QuadPart > (SelectedDrive.DiskSize + 512))) { | ||||||
|  | 			// Disable all controls except cancel
 | ||||||
|  | 			EnableControls(FALSE, FALSE); | ||||||
|  | 			FormatStatus = 0; | ||||||
|  | 			InitProgress(TRUE); | ||||||
|  | 			format_thread = CreateThread(NULL, 0, SaveImageThread, &img_save, 0, NULL); | ||||||
|  | 			if (format_thread != NULL) { | ||||||
|  | 				uprintf("\r\nSave to VHD operation started"); | ||||||
|  | 				PrintInfo(0, -1); | ||||||
|  | 				SendMessage(hMainDialog, UM_TIMER_START, 0, 0); | ||||||
|  | 			} else { | ||||||
|  | 				uprintf("Unable to start VHD save thread"); | ||||||
|  | 				FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD); | ||||||
|  | 				safe_free(img_save.ImagePath); | ||||||
|  | 				PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0); | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			if (free_space.QuadPart == 0) { | ||||||
|  | 				uprintf("Unable to isolate drive name for VHD save"); | ||||||
|  | 				FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_PATH_NOT_FOUND; | ||||||
|  | 			} else { | ||||||
|  | 				// TODO: Might be salvageable for compressed VHDX
 | ||||||
|  | 				uprintf("The VHD size is too large for the target drive"); | ||||||
|  | 				FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_FILE_TOO_LARGE; | ||||||
|  | 			} | ||||||
|  | 			safe_free(img_save.ImagePath); | ||||||
|  | 			PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										47
									
								
								src/vhd.h
									
										
									
									
									
								
							
							
						
						
									
										47
									
								
								src/vhd.h
									
										
									
									
									
								
							|  | @ -19,6 +19,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <windows.h> | #include <windows.h> | ||||||
|  | #include <virtdisk.h> | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | @ -70,6 +71,49 @@ | ||||||
| 
 | 
 | ||||||
| #define MBR_SIZE							512	// Might need to review this once we see bootable 4k systems
 | #define MBR_SIZE							512	// Might need to review this once we see bootable 4k systems
 | ||||||
| 
 | 
 | ||||||
|  | // TODO: Remove this once MinGW has been updated
 | ||||||
|  | #define VIRTUAL_STORAGE_TYPE_DEVICE_VHDX                    3 | ||||||
|  | #define CREATE_VIRTUAL_DISK_VERSION_2                       2 | ||||||
|  | #define CREATE_VIRTUAL_DISK_FLAG_CREATE_BACKING_STORAGE     8 | ||||||
|  | 
 | ||||||
|  | #ifndef CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_BLOCK_SIZE | ||||||
|  | #define CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_BLOCK_SIZE   0 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifndef CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_SECTOR_SIZE | ||||||
|  | #define CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_SECTOR_SIZE  0 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  | 	CREATE_VIRTUAL_DISK_VERSION Version; | ||||||
|  | 	union | ||||||
|  | 	{ | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			GUID                  UniqueId; | ||||||
|  | 			ULONGLONG             MaximumSize; | ||||||
|  | 			ULONG                 BlockSizeInBytes; | ||||||
|  | 			ULONG                 SectorSizeInBytes; | ||||||
|  | 			PCWSTR                ParentPath; | ||||||
|  | 			PCWSTR                SourcePath; | ||||||
|  | 		} Version1; | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			GUID                   UniqueId; | ||||||
|  | 			ULONGLONG              MaximumSize; | ||||||
|  | 			ULONG                  BlockSizeInBytes; | ||||||
|  | 			ULONG                  SectorSizeInBytes; | ||||||
|  | 			ULONG                  PhysicalSectorSizeInBytes; | ||||||
|  | 			PCWSTR                 ParentPath; | ||||||
|  | 			PCWSTR                 SourcePath; | ||||||
|  | 			OPEN_VIRTUAL_DISK_FLAG OpenFlags; | ||||||
|  | 			VIRTUAL_STORAGE_TYPE   ParentVirtualStorageType; | ||||||
|  | 			VIRTUAL_STORAGE_TYPE   SourceVirtualStorageType; | ||||||
|  | 			GUID                   ResiliencyGuid; | ||||||
|  | 		} Version2; | ||||||
|  | 	}; | ||||||
|  | } STOPGAP_CREATE_VIRTUAL_DISK_PARAMETERS; | ||||||
| 
 | 
 | ||||||
| // From https://docs.microsoft.com/en-us/previous-versions/msdn10/dd834960(v=msdn.10)
 | // From https://docs.microsoft.com/en-us/previous-versions/msdn10/dd834960(v=msdn.10)
 | ||||||
| // as well as https://msfn.org/board/topic/150700-wimgapi-wimmountimage-progressbar/
 | // as well as https://msfn.org/board/topic/150700-wimgapi-wimmountimage-progressbar/
 | ||||||
|  | @ -139,4 +183,5 @@ extern BOOL WimUnmountImage(const char* image, int index, BOOL commit); | ||||||
| extern char* GetExistingMountPoint(const char* image, int index); | extern char* GetExistingMountPoint(const char* image, int index); | ||||||
| extern BOOL WimIsValidIndex(const char* image, int index); | extern BOOL WimIsValidIndex(const char* image, int index); | ||||||
| extern int8_t IsBootableImage(const char* path); | extern int8_t IsBootableImage(const char* path); | ||||||
| extern BOOL AppendVHDFooter(const char* vhd_path); | extern void SaveVHD(void); | ||||||
|  | extern void SaveISO(void); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue