mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "d4c9f2dfa15e0abd87c57dbe0740b985a00ba3a7" and "c717c7789b4f79a4cb500f9287f5d355fed591a4" have entirely different histories.
		
	
	
		
			d4c9f2dfa1
			...
			c717c7789b
		
	
		
					 20 changed files with 357 additions and 400 deletions
				
			
		|  | @ -3,5 +3,3 @@ EXPORTS | |||
|   GetVirtualDiskPhysicalPath@12 | ||||
|   DetachVirtualDisk@12 | ||||
|   OpenVirtualDisk@24 | ||||
|   CreateVirtualDisk@36 | ||||
|   GetVirtualDiskOperationProgress@12 | ||||
|  |  | |||
|  | @ -603,8 +603,6 @@ 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." | ||||
| t MSG_340 "a \"Security Violation\" screen" | ||||
| 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 | ||||
| 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" | ||||
|  |  | |||
|  | @ -31,7 +31,6 @@ jmp_buf bb_error_jmp; | |||
| char* bb_virtual_buf = NULL; | ||||
| size_t bb_virtual_len = 0, bb_virtual_pos = 0; | ||||
| int bb_virtual_fd = -1; | ||||
| uint32_t BB_BUFSIZE = 0x10000; | ||||
| 
 | ||||
| static long long int unpack_none(transformer_state_t *xstate) | ||||
| { | ||||
|  | @ -266,8 +265,7 @@ int64_t bled_uncompress_from_buffer_to_buffer(const char* src, const size_t src_ | |||
| } | ||||
| 
 | ||||
| /* Initialize the library.
 | ||||
|  * 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) | ||||
|  * When the parameters are not NULL you can: | ||||
|  * - specify the printf-like function you want to use to output message | ||||
|  *   void print_function(const char* format, ...); | ||||
|  * - specify the read/write functions you want to use; | ||||
|  | @ -277,25 +275,18 @@ 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); | ||||
|  * - point to an unsigned long variable, to be used to cancel operations when set to non zero | ||||
|  */ | ||||
| int bled_init(uint32_t buffer_size, printf_t print_function, read_t read_function, write_t write_function, | ||||
| int bled_init(printf_t print_function, read_t read_function, write_t write_function,  | ||||
| 	progress_t progress_function, switch_t switch_function, unsigned long* cancel_request) | ||||
| { | ||||
| 	if (bled_initialized) | ||||
| 		return -1; | ||||
| 	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_initialized = true; | ||||
| 	bled_printf = print_function; | ||||
| 	bled_read = read_function; | ||||
| 	bled_write = write_function; | ||||
| 	bled_progress = progress_function; | ||||
| 	bled_switch = switch_function; | ||||
| 	bled_cancel_request = cancel_request; | ||||
| 	bled_initialized = true; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,8 +50,7 @@ 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); | ||||
| 
 | ||||
| /* Initialize the library.
 | ||||
|  * 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) | ||||
|  * When the parameters are not NULL you can: | ||||
|  * - specify the printf-like function you want to use to output message | ||||
|  *   void print_function(const char* format, ...); | ||||
|  * - specify the read/write functions you want to use; | ||||
|  | @ -61,7 +60,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); | ||||
|  * - point to an unsigned long variable, to be used to cancel operations when set to non zero | ||||
|  */ | ||||
| int bled_init(uint32_t buffer_size, printf_t print_function, read_t read_function, write_t write_function, | ||||
| int bled_init(printf_t print_function, read_t read_function, write_t write_function, | ||||
|     progress_t progress_function, switch_t switch_function, unsigned long* cancel_request); | ||||
| 
 | ||||
| /* This call frees any resource used by the library */ | ||||
|  |  | |||
|  | @ -45,11 +45,10 @@ typedef struct huft_t { | |||
| 	} v; | ||||
| } huft_t; | ||||
| 
 | ||||
| enum { | ||||
| 	/* gunzip_window size--must be a power of two, and
 | ||||
| 	 * at least 32K for zip's deflate method */ | ||||
| #define GUNZIP_WSIZE BB_BUFSIZE | ||||
| 
 | ||||
| enum { | ||||
| 	GUNZIP_WSIZE = BB_BUFSIZE, | ||||
| 	/* 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) */ | ||||
| 	N_MAX = 288,	/* maximum number of codes in any set */ | ||||
|  |  | |||
|  | @ -27,10 +27,10 @@ | |||
| 
 | ||||
| 
 | ||||
| /* Default input buffer size */ | ||||
| #define IBUFSIZ         ((int)BB_BUFSIZE) | ||||
| #define IBUFSIZ         BB_BUFSIZE | ||||
| 
 | ||||
| /* Default output buffer size */ | ||||
| #define OBUFSIZ         ((int)BB_BUFSIZE) | ||||
| #define OBUFSIZ         BB_BUFSIZE | ||||
| 
 | ||||
| /* Defines for third byte of header */ | ||||
| #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); \ | ||||
| }} while (0) | ||||
| 
 | ||||
| inline void BUG(void) { | ||||
| inline void BUG() { | ||||
| 	/* Check the offset of the last element, not the length.  This leniency
 | ||||
| 	 * allows for poor packing, whereby the overall struct may be too long, | ||||
| 	 * even though the elements are all in the right place. | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ | |||
| #include <sys/types.h> | ||||
| #include <io.h> | ||||
| 
 | ||||
| #define BB_BUFSIZE                  0x40000 | ||||
| #define ONE_TB                      1099511627776ULL | ||||
| 
 | ||||
| #define ENABLE_DESKTOP              1 | ||||
|  | @ -104,7 +105,6 @@ typedef unsigned int uid_t; | |||
| #define get_le16(ptr) (*(const uint16_t *)(ptr)) | ||||
| #endif | ||||
| 
 | ||||
| extern uint32_t BB_BUFSIZE; | ||||
| extern smallint bb_got_signal; | ||||
| extern uint32_t *global_crc32_table; | ||||
| 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); | ||||
| 		sec_buf_pos = 0; | ||||
| 		bled_init(256 * KB, uprintf, NULL, sector_write, update_progress, NULL, &FormatStatus); | ||||
| 		bled_init(uprintf, NULL, sector_write, update_progress, NULL, &FormatStatus); | ||||
| 		bled_ret = bled_uncompress_with_handles(hSourceImage, hPhysicalDrive, img_report.compression_type); | ||||
| 		bled_exit(); | ||||
| 		uprintfs("\r\n"); | ||||
|  | @ -1977,3 +1977,126 @@ out: | |||
| 	PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)TRUE, 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); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										156
									
								
								src/iso.c
									
										
									
									
									
								
							
							
						
						
									
										156
									
								
								src/iso.c
									
										
									
									
									
								
							|  | @ -43,8 +43,6 @@ | |||
| #include <cdio/udf.h> | ||||
| 
 | ||||
| #include "rufus.h" | ||||
| #include "ui.h" | ||||
| #include "drive.h" | ||||
| #include "libfat.h" | ||||
| #include "missing.h" | ||||
| #include "resource.h" | ||||
|  | @ -84,7 +82,6 @@ RUFUS_IMG_REPORT img_report; | |||
| int64_t iso_blocking_status = -1; | ||||
| extern BOOL preserve_timestamps, enable_ntfs_compression; | ||||
| extern char* archive_path; | ||||
| extern HANDLE format_thread; | ||||
| BOOL enable_iso = TRUE, enable_joliet = TRUE, enable_rockridge = TRUE, has_ldlinux_c32; | ||||
| #define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0) | ||||
| static const char* psz_extract_dir; | ||||
|  | @ -1286,7 +1283,7 @@ out: | |||
| 		update_md5sum(); | ||||
| 		if (archive_path != NULL) { | ||||
| 			uprintf("● Adding files from %s", archive_path); | ||||
| 			bled_init(256 * KB, NULL, NULL, NULL, NULL, alt_print_extracted_file, NULL); | ||||
| 			bled_init(NULL, NULL, NULL, NULL, alt_print_extracted_file, NULL); | ||||
| 			bled_uncompress_to_dir(archive_path, dest_dir, BLED_COMPRESSION_ZIP); | ||||
| 			bled_exit(); | ||||
| 		} | ||||
|  | @ -1769,154 +1766,3 @@ void UnMountISO(void) | |||
| out: | ||||
| 	physical_path[0] = 0; | ||||
| } | ||||
| 
 | ||||
| // TODO: If we can't get save to ISO from virtdisk, we might as well drop this
 | ||||
| static DWORD WINAPI SaveISOThread(void* param) | ||||
| { | ||||
| 	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,6 +185,10 @@ static __inline uint16_t remap16(uint16_t src, uint16_t* map, const BOOL reverse | |||
| #define ERROR_OFFSET_ALIGNMENT_VIOLATION        327 | ||||
| #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 */ | ||||
| #ifndef IMAGE_FILE_MACHINE_RISCV32 | ||||
| #define IMAGE_FILE_MACHINE_RISCV32 0x5032 | ||||
|  |  | |||
|  | @ -31,7 +31,6 @@ | |||
| #include <string.h> | ||||
| #include <inttypes.h> | ||||
| #include <assert.h> | ||||
| #include <virtdisk.h> | ||||
| 
 | ||||
| #include "rufus.h" | ||||
| #include "missing.h" | ||||
|  | @ -949,7 +948,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) | |||
| 		free(sig); | ||||
| 		uprintf("Download signature is valid ✓"); | ||||
| 		uncompressed_size = *((uint64_t*)&compressed[5]); | ||||
| 		if ((uncompressed_size < 1 * MB) && (bled_init(0, uprintf, NULL, NULL, NULL, NULL, &FormatStatus) >= 0)) { | ||||
| 		if ((uncompressed_size < 1 * MB) && (bled_init(uprintf, NULL, NULL, NULL, NULL, &FormatStatus) >= 0)) { | ||||
| 			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); | ||||
| 			bled_exit(); | ||||
|  | @ -1039,7 +1038,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) | |||
| #pragma warning(default: 6386) | ||||
| #endif | ||||
| 			EXT_DECL(img_ext, GetShortName(url), __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036))); | ||||
| 			img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_ISO; | ||||
| 			img_save.Type = IMG_SAVE_TYPE_ISO; | ||||
| 			img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); | ||||
| 			if (img_save.ImagePath == NULL) { | ||||
| 				goto out; | ||||
|  |  | |||
|  | @ -812,8 +812,7 @@ BOOL ParseSKUSiPolicy(void) | |||
| 
 | ||||
| 	pe256ssp_size = 0; | ||||
| 	safe_free(pe256ssp); | ||||
| 	// Must use sysnative for WOW
 | ||||
| 	static_sprintf(path, "%s\\SecureBootUpdates\\SKUSiPolicy.p7b", sysnative_dir); | ||||
| 	static_sprintf(path, "%s\\SecureBootUpdates\\SKUSiPolicy.p7b", system_dir); | ||||
| 	wpath = utf8_to_wchar(path); | ||||
| 	if (wpath == NULL) | ||||
| 		goto out; | ||||
|  |  | |||
							
								
								
									
										104
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										104
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -87,6 +87,7 @@ static int selected_pt = -1, selected_fs = FS_UNKNOWN, preselected_fs = FS_UNKNO | |||
| static int image_index = 0, select_index = 0; | ||||
| static RECT relaunch_rc = { -65536, -65536, 0, 0}; | ||||
| static UINT uMBRChecked = BST_UNCHECKED; | ||||
| static HANDLE format_thread = NULL; | ||||
| static HWND hSelectImage = NULL, hStart = NULL; | ||||
| static char szTimer[12] = "00:00:00"; | ||||
| static unsigned int timer; | ||||
|  | @ -120,7 +121,7 @@ WORD selected_langid = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); | |||
| DWORD MainThreadId; | ||||
| HWND hDeviceList, hPartitionScheme, hTargetSystem, hFileSystem, hClusterSize, hLabel, hBootType, hNBPasses, hLog = NULL; | ||||
| HWND hImageOption, hLogDialog = NULL, hProgress = NULL, hDiskID; | ||||
| HANDLE dialog_handle = NULL, format_thread = NULL; | ||||
| HANDLE dialog_handle = NULL; | ||||
| 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 enable_HDDs = FALSE, enable_VHDs = TRUE, enable_ntfs_compression = FALSE, no_confirmation_on_cancel = FALSE; | ||||
|  | @ -861,7 +862,7 @@ static void EnableBootOptions(BOOL enable, BOOL remove_checkboxes) | |||
| } | ||||
| 
 | ||||
| // Toggle controls according to operation
 | ||||
| void EnableControls(BOOL enable, BOOL remove_checkboxes) | ||||
| static void EnableControls(BOOL enable, BOOL remove_checkboxes) | ||||
| { | ||||
| 	op_in_progress = !enable; | ||||
| 
 | ||||
|  | @ -2160,6 +2161,104 @@ static void PrintStatusTimeout(const char* str, BOOL val) | |||
| 	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.
 | ||||
| // 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)
 | ||||
|  | @ -2665,7 +2764,6 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 			MyDialogBox(hMainInstance, IDD_UPDATE_POLICY, hDlg, UpdateCallback); | ||||
| 			break; | ||||
| 		case IDC_HASH: | ||||
| 			// TODO: Move this as a fn call in hash.c?
 | ||||
| 			if ((format_thread == NULL) && (image_path != NULL)) { | ||||
| 				FormatStatus = 0; | ||||
| 				no_confirmation_on_cancel = TRUE; | ||||
|  |  | |||
|  | @ -71,7 +71,6 @@ | |||
| #define PATCH_PROGRESS_TOTAL        207 | ||||
| #define MAX_LOG_SIZE                0x7FFFFFFE | ||||
| #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_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
 | ||||
|  | @ -89,6 +88,7 @@ | |||
| #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 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 SINGLE_CLUSTERSIZE_DEFAULT  0x00000100 | ||||
| #define BADLOCKS_PATTERN_TYPES      5 | ||||
|  | @ -433,6 +433,9 @@ typedef struct { | |||
| 	char* release_notes; | ||||
| } RUFUS_UPDATE; | ||||
| 
 | ||||
| #define IMG_SAVE_TYPE_VHD 1 | ||||
| #define IMG_SAVE_TYPE_ISO 2 | ||||
| 
 | ||||
| typedef struct { | ||||
| 	DWORD Type; | ||||
| 	DWORD DeviceNum; | ||||
|  | @ -723,6 +726,7 @@ extern HANDLE CreatePreallocatedFile(const char* lpFileName, DWORD dwDesiredAcce | |||
| 	DWORD dwFlagsAndAttributes, LONGLONG fileSize); | ||||
| #define GetTextWidth(hDlg, id) GetTextSize(GetDlgItem(hDlg, id), NULL).cx | ||||
| 
 | ||||
| DWORD WINAPI SaveImageThread(void* param); | ||||
| DWORD WINAPI HashThread(void* param); | ||||
| 
 | ||||
| /* 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 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_ACCEPTFILES | ||||
| CAPTION "Rufus 4.2.2060" | ||||
| CAPTION "Rufus 4.2.2057" | ||||
| FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | ||||
| BEGIN | ||||
|     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP | ||||
|  | @ -392,8 +392,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 4,2,2060,0 | ||||
|  PRODUCTVERSION 4,2,2060,0 | ||||
|  FILEVERSION 4,2,2057,0 | ||||
|  PRODUCTVERSION 4,2,2057,0 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -411,13 +411,13 @@ BEGIN | |||
|             VALUE "Comments", "https://rufus.ie" | ||||
|             VALUE "CompanyName", "Akeo Consulting" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "4.2.2060" | ||||
|             VALUE "FileVersion", "4.2.2057" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" | ||||
|             VALUE "OriginalFilename", "rufus-4.2.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "4.2.2060" | ||||
|             VALUE "ProductVersion", "4.2.2057" | ||||
|         END | ||||
|     END | ||||
|     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; | ||||
| 	IShellItem *psiResult; | ||||
| 	COMDLG_FILTERSPEC* filter_spec = NULL; | ||||
| 	wchar_t *wpath = NULL, *wfilename = NULL, *wext = NULL; | ||||
| 	wchar_t *wpath = NULL, *wfilename = NULL; | ||||
| 	IShellItem *si_path = NULL;	// Automatically freed
 | ||||
| 
 | ||||
| 	if ((ext == NULL) || (ext->count == 0) || (ext->extension == NULL) || (ext->description == NULL)) | ||||
|  | @ -162,20 +162,11 @@ char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options) | |||
| 		if (wfilename != NULL) { | ||||
| 			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
 | ||||
| 		hr = IFileDialog_Show(pfd, hMainDialog); | ||||
| 
 | ||||
| 		// Cleanup
 | ||||
| 		safe_free(wext); | ||||
| 		safe_free(wfilename); | ||||
| 		for (i = 0; i < ext->count; i++) { | ||||
| 			safe_free(filter_spec[i].pszSpec); | ||||
|  |  | |||
							
								
								
									
										2
									
								
								src/ui.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								src/ui.h
									
										
									
									
									
								
							|  | @ -20,7 +20,6 @@ | |||
| #include <windows.h> | ||||
| #include <stdint.h> | ||||
| #include "resource.h" | ||||
| #include "localization.h" | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
|  | @ -100,7 +99,6 @@ extern void ToggleAdvancedFormatOptions(BOOL enable); | |||
| extern void ToggleImageOptions(void); | ||||
| extern void CreateSmallButtons(HWND hDlg); | ||||
| extern void CreateAdditionalControls(HWND hDlg); | ||||
| extern void EnableControls(BOOL enable, BOOL remove_checkboxes); | ||||
| extern void InitProgress(BOOL bOnlyFormat); | ||||
| extern void ShowLanguageMenu(RECT rcExclude); | ||||
| extern void SetPassesTooltip(void); | ||||
|  |  | |||
							
								
								
									
										243
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										243
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -18,15 +18,13 @@ | |||
|  */ | ||||
| 
 | ||||
| #include <windows.h> | ||||
| #include <windowsx.h> | ||||
| #include <stdlib.h> | ||||
| #include <io.h> | ||||
| #include <rpc.h> | ||||
| #include <time.h> | ||||
| 
 | ||||
| #include "rufus.h" | ||||
| #include "ui.h" | ||||
| #include "vhd.h" | ||||
| #include "rufus.h" | ||||
| #include "missing.h" | ||||
| #include "resource.h" | ||||
| #include "msapi_utf8.h" | ||||
|  | @ -47,6 +45,7 @@ PF_TYPE_DECL(WINAPI, BOOL, WIMGetImageInformation, (HANDLE, PVOID, PDWORD)); | |||
| PF_TYPE_DECL(WINAPI, BOOL, WIMCloseHandle, (HANDLE)); | ||||
| PF_TYPE_DECL(WINAPI, DWORD, WIMRegisterMessageCallback, (HANDLE, FARPROC, PVOID)); | ||||
| PF_TYPE_DECL(WINAPI, DWORD, WIMUnregisterMessageCallback, (HANDLE, FARPROC)); | ||||
| PF_TYPE_DECL(RPC_ENTRY, RPC_STATUS, UuidCreate, (UUID __RPC_FAR*)); | ||||
| 
 | ||||
| typedef struct { | ||||
| 	int index; | ||||
|  | @ -59,8 +58,6 @@ uint32_t wim_nb_files, wim_proc_files, wim_extra_files; | |||
| HANDLE wim_thread = NULL; | ||||
| extern int default_thread_priority; | ||||
| extern BOOL ignore_boot_marker; | ||||
| extern RUFUS_DRIVE rufus_drive[MAX_DRIVES]; | ||||
| extern HANDLE format_thread; | ||||
| 
 | ||||
| static uint8_t wim_flags = 0; | ||||
| static uint32_t progress_report_mask; | ||||
|  | @ -81,6 +78,102 @@ static BOOL Get7ZipPath(void) | |||
| 	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 { | ||||
| 	const char* ext; | ||||
| 	bled_compression_type type; | ||||
|  | @ -118,7 +211,7 @@ static BOOL IsCompressedBootableImage(const char* path) | |||
| 			if (buf == NULL) | ||||
| 				return FALSE; | ||||
| 			FormatStatus = 0; | ||||
| 			bled_init(0, uprintf, NULL, NULL, NULL, NULL, &FormatStatus); | ||||
| 			bled_init(uprintf, NULL, NULL, NULL, NULL, &FormatStatus); | ||||
| 			dc = bled_uncompress_to_buffer(path, (char*)buf, MBR_SIZE, file_assoc[i].type); | ||||
| 			bled_exit(); | ||||
| 			if (dc != MBR_SIZE) { | ||||
|  | @ -884,141 +977,3 @@ BOOL WimApplyImage(const char* image, int index, const char* dst) | |||
| 	wim_thread = NULL; | ||||
| 	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,7 +19,6 @@ | |||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <windows.h> | ||||
| #include <virtdisk.h> | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
|  | @ -71,49 +70,6 @@ | |||
| 
 | ||||
| #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)
 | ||||
| // as well as https://msfn.org/board/topic/150700-wimgapi-wimmountimage-progressbar/
 | ||||
|  | @ -183,5 +139,4 @@ extern BOOL WimUnmountImage(const char* image, int index, BOOL commit); | |||
| extern char* GetExistingMountPoint(const char* image, int index); | ||||
| extern BOOL WimIsValidIndex(const char* image, int index); | ||||
| extern int8_t IsBootableImage(const char* path); | ||||
| extern void SaveVHD(void); | ||||
| extern void SaveISO(void); | ||||
| extern BOOL AppendVHDFooter(const char* vhd_path); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue