mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[core] Add VHD source image support
* As part of #321 * Also improve FileDialog so that it can support multiple extensions * Also fix a typo in rufus.loc
This commit is contained in:
		
							parent
							
								
									36d226e101
								
							
						
					
					
						commit
						bfa1656488
					
				
					 7 changed files with 207 additions and 99 deletions
				
			
		|  | @ -264,7 +264,7 @@ t MSG_096 "Only FAT/FAT32 is supported for this type of ISO. Please select FAT/F | |||
| t MSG_097 "Only 'bootmgr' or 'WinPE' based ISO images can currently be used with NTFS." | ||||
| t MSG_098 "FAT/FAT32 can only be used for isolinux based ISO images or when the Target Type is UEFI." | ||||
| t MSG_099 "Filesystem limitation" | ||||
| t MSG_100 "This ISO image contains a file larger than 4GB file, which is more than the " | ||||
| t MSG_100 "This ISO image contains a file larger than 4GB, which is more than the " | ||||
| 	"maximum size allowed for a FAT or FAT32 file system." | ||||
| t MSG_101 "Missing WIM support" | ||||
| t MSG_102 "Your platform cannot extract files from WIM archives. WIM extraction " | ||||
|  |  | |||
							
								
								
									
										19
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								src/format.c
									
										
									
									
									
								
							|  | @ -1360,12 +1360,13 @@ DWORD WINAPI FormatThread(void* param) | |||
| 
 | ||||
| 	// Write an image file
 | ||||
| 	if (dt == DT_IMG) { | ||||
| 		// We poked the MBR, so we need to rewind
 | ||||
| 		// We poked the MBR and other stuff, so we need to rewind
 | ||||
| 		li.QuadPart = 0; | ||||
| 		SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN); | ||||
| 		hSourceImage = CreateFileU(iso_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); | ||||
| 		if (!SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN)) | ||||
| 			uprintf("Warning: Unable to rewind image position - wrong data might be copied!"); | ||||
| 		hSourceImage = CreateFileU(image_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); | ||||
| 		if (hSourceImage == INVALID_HANDLE_VALUE) { | ||||
| 			uprintf("Could not open image '%s': %s", iso_path, WindowsErrorString()); | ||||
| 			uprintf("Could not open image '%s': %s", image_path, WindowsErrorString()); | ||||
| 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | ||||
| 			goto out; | ||||
| 		} | ||||
|  | @ -1397,6 +1398,10 @@ DWORD WINAPI FormatThread(void* param) | |||
| 				UpdateProgress(OP_FORMAT, format_percent); | ||||
| 			} | ||||
| 			CHECK_FOR_USER_CANCEL; | ||||
| 			// Don't overflow our projected size (mostly for VHDs)
 | ||||
| 			if (wb + rSize > iso_report.projected_size) { | ||||
| 				rSize = (DWORD)(iso_report.projected_size - wb); | ||||
| 			} | ||||
| 			for (i=0; i<WRITE_RETRIES; i++) { | ||||
| 				s = WriteFile(hPhysicalDrive, buffer, rSize, &wSize, NULL); | ||||
| 				if ((s) && (wSize == rSize)) | ||||
|  | @ -1549,11 +1554,11 @@ DWORD WINAPI FormatThread(void* param) | |||
| 				goto out; | ||||
| 			} | ||||
| 		} else if (dt == DT_ISO) { | ||||
| 			if (iso_path != NULL) { | ||||
| 			if (image_path != NULL) { | ||||
| 				UpdateProgress(OP_DOS, 0.0f); | ||||
| 				PrintStatus(0, TRUE, MSG_231); | ||||
| 				drive_name[2] = 0; | ||||
| 				if (!ExtractISO(iso_path, drive_name, FALSE)) { | ||||
| 				if (!ExtractISO(image_path, drive_name, FALSE)) { | ||||
| 					if (!IS_ERROR(FormatStatus)) | ||||
| 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; | ||||
| 					goto out; | ||||
|  | @ -1561,7 +1566,7 @@ DWORD WINAPI FormatThread(void* param) | |||
| 				if (iso_report.has_kolibrios) { | ||||
| 					kolibri_dst[0] = drive_name[0]; | ||||
| 					uprintf("Installing: %s (KolibriOS loader)\n", kolibri_dst); | ||||
| 					if (ExtractISOFile(iso_path, "HD_Load/USB_Boot/MTLD_F32", kolibri_dst, | ||||
| 					if (ExtractISOFile(image_path, "HD_Load/USB_Boot/MTLD_F32", kolibri_dst, | ||||
| 						FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM) == 0) { | ||||
| 						uprintf("Warning: loader installation failed - KolibriOS will not boot!\n"); | ||||
| 					} | ||||
|  |  | |||
							
								
								
									
										87
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										87
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -113,7 +113,7 @@ OPENED_LIBRARIES_VARS; | |||
| HINSTANCE hMainInstance; | ||||
| HWND hMainDialog; | ||||
| char szFolderPath[MAX_PATH], app_dir[MAX_PATH]; | ||||
| char* iso_path = NULL; | ||||
| char* image_path = NULL; | ||||
| float fScale = 1.0f; | ||||
| int default_fs; | ||||
| uint32_t dur_mins, dur_secs; | ||||
|  | @ -438,7 +438,7 @@ static void SetFSFromISO(void) | |||
| 	uint32_t fs_mask = 0; | ||||
| 	int bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme))); | ||||
| 
 | ||||
| 	if (iso_path == NULL) | ||||
| 	if (image_path == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	// Create a mask of all the FS's available
 | ||||
|  | @ -477,7 +477,7 @@ static void SetMBRProps(void) | |||
| 	int dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); | ||||
| 	BOOL needs_masquerading = (IS_WINPE(iso_report.winpe) && (!iso_report.uses_minint)); | ||||
| 
 | ||||
| 	if ((!mbr_selected_by_user) && ((iso_path == NULL) || (dt != DT_ISO) || (fs != FS_NTFS))) { | ||||
| 	if ((!mbr_selected_by_user) && ((image_path == NULL) || (dt != DT_ISO) || (fs != FS_NTFS))) { | ||||
| 		CheckDlgButton(hMainDialog, IDC_RUFUS_MBR, BST_UNCHECKED); | ||||
| 		IGNORE_RETVAL(ComboBox_SetCurSel(hDiskID, 0)); | ||||
| 		return; | ||||
|  | @ -593,7 +593,7 @@ static BOOL PopulateProperties(int ComboIndex) | |||
| 	} | ||||
| 
 | ||||
| 	// If no existing label is available and no ISO is selected, propose one according to the size (eg: "256MB", "8GB")
 | ||||
| 	if ((iso_path == NULL) || (iso_report.label[0] == 0)) { | ||||
| 	if ((image_path == NULL) || (iso_report.label[0] == 0)) { | ||||
| 		if ( (safe_stricmp(no_label, DriveLabel.String[ComboIndex]) == 0) | ||||
| 		  || (safe_stricmp(lmprintf(MSG_207), DriveLabel.String[ComboIndex]) == 0) ) { | ||||
| 			SetWindowTextU(hLabel, SelectedDrive.proposed_label); | ||||
|  | @ -766,6 +766,9 @@ BOOL CALLBACK LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) | |||
| 	long lfHeight; | ||||
| 	DWORD log_size; | ||||
| 	char *log_buffer = NULL, *filepath; | ||||
| 	const char* log_x[] = { "*.log" }; | ||||
| 	const char* log_d[] = { lmprintf(MSG_108) }; | ||||
| 	ext_t log_ext = {ARRAYSIZE(log_x), "rufus.log", log_x, log_d }; | ||||
| 
 | ||||
| 	switch (message) { | ||||
| 	case WM_INITDIALOG: | ||||
|  | @ -799,7 +802,7 @@ BOOL CALLBACK LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) | |||
| 				log_size = GetDlgItemTextU(hDlg, IDC_LOG_EDIT, log_buffer, log_size); | ||||
| 				if (log_size != 0) { | ||||
| 					log_size--;	// remove NUL terminator
 | ||||
| 					filepath =  FileDialog(TRUE, app_dir, "rufus.log", "log", lmprintf(MSG_108), 0); | ||||
| 					filepath =  FileDialog(TRUE, app_dir, &log_ext, 0); | ||||
| 					if (filepath != NULL) { | ||||
| 						FileIO(TRUE, filepath, &log_buffer, &log_size); | ||||
| 					} | ||||
|  | @ -905,34 +908,6 @@ BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) | |||
| 	return FALSE; | ||||
| } | ||||
| 
 | ||||
| BOOL IsImage(const char* src_img) | ||||
| { | ||||
| 	HANDLE handle = INVALID_HANDLE_VALUE; | ||||
| 	LARGE_INTEGER liImageSize; | ||||
| 
 | ||||
| 	handle = CreateFileU(src_img, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); | ||||
| 	if (handle == INVALID_HANDLE_VALUE) { | ||||
| 		uprintf("Could not open image '%s'", src_img); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	iso_report.is_bootable_img = AnalyzeMBR(handle, "Image"); | ||||
| 
 | ||||
| 	if (!GetFileSizeEx(handle, &liImageSize)) { | ||||
| 		uprintf("Could not get image size: %s", WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	iso_report.projected_size = (uint64_t)liImageSize.QuadPart; | ||||
| 
 | ||||
| 	if (iso_report.is_bootable_img) { | ||||
| 		uprintf("Using bootable disk image: '%s'", src_img); | ||||
| 		selection_default = DT_IMG; | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	safe_closehandle(handle); | ||||
| 	return iso_report.is_bootable_img; | ||||
| } | ||||
| 
 | ||||
| // The scanning process can be blocking for message processing => use a thread
 | ||||
| DWORD WINAPI ISOScanThread(LPVOID param) | ||||
| { | ||||
|  | @ -940,21 +915,24 @@ DWORD WINAPI ISOScanThread(LPVOID param) | |||
| 	BOOL r; | ||||
| 	char isolinux_str[16] = "No"; | ||||
| 
 | ||||
| 	if (iso_path == NULL) | ||||
| 	if (image_path == NULL) | ||||
| 		goto out; | ||||
| 	PrintStatus(0, TRUE, MSG_202); | ||||
| 	user_notified = FALSE; | ||||
| 	EnableControls(FALSE); | ||||
| 	r = ExtractISO(iso_path, "", TRUE) || IsImage(iso_path); | ||||
| 	r = ExtractISO(image_path, "", TRUE) || IsHDImage(image_path); | ||||
| 	EnableControls(TRUE); | ||||
| 	if (!r) { | ||||
| 		SendMessage(hISOProgressDlg, UM_PROGRESS_EXIT, 0, 0); | ||||
| 		PrintStatus(0, TRUE, MSG_203); | ||||
| 		safe_free(iso_path); | ||||
| 		safe_free(image_path); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!iso_report.is_bootable_img) { | ||||
| 	if (iso_report.is_bootable_img) { | ||||
| 		uprintf("Using bootable %s image: '%s'", iso_report.is_vhd?"VHD":"disk", image_path); | ||||
| 		selection_default = DT_IMG; | ||||
| 	} else { | ||||
| 		if (HAS_SYSLINUX(iso_report)) { | ||||
| 			safe_sprintf(isolinux_str, sizeof(isolinux_str), "Yes (%s)", iso_report.sl_version_str); | ||||
| 		} | ||||
|  | @ -974,7 +952,7 @@ DWORD WINAPI ISOScanThread(LPVOID param) | |||
| 	if ( (!iso_report.has_bootmgr) && (!HAS_SYSLINUX(iso_report)) && (!IS_WINPE(iso_report.winpe))  | ||||
| 		&& (!iso_report.has_efi) && (!IS_REACTOS(iso_report) && (!iso_report.has_kolibrios) && (!iso_report.is_bootable_img)) ) { | ||||
| 		MessageBoxU(hMainDialog, lmprintf(MSG_082), lmprintf(MSG_081), MB_OK|MB_ICONINFORMATION|MB_IS_RTL); | ||||
| 		safe_free(iso_path); | ||||
| 		safe_free(image_path); | ||||
| 		SetMBRProps(); | ||||
| 	} else { | ||||
| 		// Enable bootable and set Target System and FS accordingly
 | ||||
|  | @ -992,8 +970,8 @@ DWORD WINAPI ISOScanThread(LPVOID param) | |||
| 			SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_FILESYSTEM, | ||||
| 				ComboBox_GetCurSel(hFileSystem)); | ||||
| 		} | ||||
| 		for (i=(int)safe_strlen(iso_path); (i>0)&&(iso_path[i]!='\\'); i--); | ||||
| 		PrintStatus(0, TRUE, MSG_205, &iso_path[i+1]); | ||||
| 		for (i=(int)safe_strlen(image_path); (i>0)&&(image_path[i]!='\\'); i--); | ||||
| 		PrintStatus(0, TRUE, MSG_205, &image_path[i+1]); | ||||
| 		// Lose the focus on the select ISO (but place it on Close)
 | ||||
| 		SendMessage(hMainDialog, WM_NEXTDLGCTL,  (WPARAM)FALSE, 0); | ||||
| 		// Lose the focus from Close and set it back to Start
 | ||||
|  | @ -1100,7 +1078,7 @@ static BOOL BootCheck(void) | |||
| 	syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0; | ||||
| 	dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); | ||||
| 	if ((dt == DT_ISO) || (dt == DT_IMG)) { | ||||
| 		if (iso_path == NULL) { | ||||
| 		if (image_path == NULL) { | ||||
| 			// Please click on the disc button to select a bootable ISO
 | ||||
| 			MessageBoxU(hMainDialog, lmprintf(MSG_087), lmprintf(MSG_086), MB_OK|MB_ICONERROR|MB_IS_RTL); | ||||
| 			return FALSE; | ||||
|  | @ -1530,6 +1508,13 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 	static LPITEMIDLIST pidlDesktop = NULL; | ||||
| 	static MY_SHChangeNotifyEntry NotifyEntry; | ||||
| 	loc_cmd* lcmd = NULL; | ||||
| 	// TODO: Add "*.img;*.vhd" / "All Supported Images" to the list below and use a generic "%s Image" in the .loc
 | ||||
| 	const char* img_x[] = { "*.img", "*.vhd" }; | ||||
| 	const char* img_d[] = { lmprintf(MSG_095), "VHD Image" }; | ||||
| 	ext_t img_ext = {ARRAYSIZE(img_x), NULL, img_x, img_d}; | ||||
| 	const char* iso_x[] = { "*.iso" }; | ||||
| 	const char* iso_d[] = { lmprintf(MSG_036) }; | ||||
| 	ext_t iso_ext = {ARRAYSIZE(iso_x), NULL, iso_x, iso_d }; | ||||
| 
 | ||||
| 	switch (message) { | ||||
| 
 | ||||
|  | @ -1809,7 +1794,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 			EnableAdvancedBootOptions(TRUE, TRUE); | ||||
| 			ToggleImage(!IsChecked(IDC_BOOT) || (selection_default != DT_IMG)); | ||||
| 			if ((selection_default == DT_ISO) || (selection_default == DT_IMG)) { | ||||
| 				if ((iso_path == NULL) || (iso_report.label[0] == 0)) { | ||||
| 				if ((image_path == NULL) || (iso_report.label[0] == 0)) { | ||||
| 					// Set focus to the Select ISO button
 | ||||
| 					SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)FALSE, 0); | ||||
| 					SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)hSelectISO, TRUE); | ||||
|  | @ -1830,21 +1815,21 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 			return (INT_PTR)TRUE; | ||||
| 		case IDC_SELECT_ISO: | ||||
| 			if (iso_provided) { | ||||
| 				uprintf("Image provided: '%s'\n", iso_path); | ||||
| 				uprintf("Image provided: '%s'\n", image_path); | ||||
| 				iso_provided = FALSE;	// One off thing...
 | ||||
| 			} else { | ||||
| 				safe_free(iso_path); | ||||
| 				safe_free(image_path); | ||||
| 				if (selection_default == DT_IMG) | ||||
| 					iso_path = FileDialog(FALSE, NULL, "*.img", "img", "DD Image", 0); | ||||
| 					image_path = FileDialog(FALSE, NULL, &img_ext, 0); | ||||
| 				else | ||||
| 					iso_path = FileDialog(FALSE, NULL, "*.iso", "iso", lmprintf(MSG_036), 0); | ||||
| 				if (iso_path == NULL) { | ||||
| 					image_path = FileDialog(FALSE, NULL, &iso_ext, 0); | ||||
| 				if (image_path == NULL) { | ||||
| 					CreateTooltip(hSelectISO, lmprintf(MSG_173), -1); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			selection_default = DT_ISO; | ||||
| 			CreateTooltip(hSelectISO, iso_path, -1); | ||||
| 			CreateTooltip(hSelectISO, image_path, -1); | ||||
| 			FormatStatus = 0; | ||||
| 			if (CreateThread(NULL, 0, ISOScanThread, NULL, 0, NULL) == NULL) { | ||||
| 				uprintf("Unable to start ISO scanning thread"); | ||||
|  | @ -2095,7 +2080,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | |||
| 				break; | ||||
| 			case 'i': | ||||
| 				if (_access(optarg, 0) != -1) { | ||||
| 					iso_path = safe_strdup(optarg); | ||||
| 					image_path = safe_strdup(optarg); | ||||
| 					iso_provided = TRUE; | ||||
| 				} else { | ||||
| 					printf("Could not find ISO image '%s'\n", optarg); | ||||
|  | @ -2282,7 +2267,7 @@ relaunch: | |||
| 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'I')) { | ||||
| 				enable_iso = !enable_iso; | ||||
| 				PrintStatus2000(lmprintf(MSG_262), enable_iso); | ||||
| 				if (iso_path != NULL) { | ||||
| 				if (image_path != NULL) { | ||||
| 					iso_provided = TRUE; | ||||
| 					PostMessage(hDlg, WM_COMMAND, IDC_SELECT_ISO, 0); | ||||
| 				} | ||||
|  | @ -2354,7 +2339,7 @@ out: | |||
| 		DeleteFileU(loc_file); | ||||
| 	DestroyAllTooltips(); | ||||
| 	exit_localization(); | ||||
| 	safe_free(iso_path); | ||||
| 	safe_free(image_path); | ||||
| 	safe_free(locale_name); | ||||
| 	safe_free(update.download_url); | ||||
| 	safe_free(update.release_notes); | ||||
|  |  | |||
							
								
								
									
										15
									
								
								src/rufus.h
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/rufus.h
									
										
									
									
									
								
							|  | @ -247,6 +247,7 @@ typedef struct { | |||
| 	BOOL has_kolibrios; | ||||
| 	BOOL uses_minint; | ||||
| 	BOOL is_bootable_img; | ||||
| 	BOOL is_vhd; | ||||
| 	uint16_t sl_version;	// Syslinux/Isolinux version
 | ||||
| 	char sl_version_str[12]; | ||||
| } RUFUS_ISO_REPORT; | ||||
|  | @ -285,6 +286,15 @@ enum WindowsVersion { | |||
| 	WINDOWS_MAX | ||||
| }; | ||||
| 
 | ||||
| /* Extensions structure used by FileDialog() */ | ||||
| typedef struct ext_t { | ||||
| 	const size_t count; | ||||
| 	const char* filename; | ||||
| 	const char** extension; | ||||
| 	const char** description; | ||||
| } ext_t; | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Globals | ||||
|  */ | ||||
|  | @ -294,7 +304,7 @@ extern HWND hPartitionScheme, hFileSystem, hClusterSize, hLabel, hBootType, hNBP | |||
| extern HWND hISOProgressDlg, hISOProgressBar, hISOFileName, hDiskID; | ||||
| extern float fScale; | ||||
| extern char szFolderPath[MAX_PATH], app_dir[MAX_PATH]; | ||||
| extern char* iso_path; | ||||
| extern char* image_path; | ||||
| extern DWORD FormatStatus; | ||||
| extern DWORD syslinux_ldlinux_len[2]; | ||||
| extern RUFUS_DRIVE_INFO SelectedDrive; | ||||
|  | @ -342,7 +352,7 @@ extern BOOL InstallSyslinux(DWORD drive_index, char drive_letter); | |||
| DWORD WINAPI FormatThread(void* param); | ||||
| extern BOOL CreateProgress(void); | ||||
| extern BOOL SetAutorun(const char* path); | ||||
| extern char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc, DWORD options); | ||||
| extern char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options); | ||||
| extern BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size); | ||||
| extern unsigned char* GetResource(HMODULE module, char* name, char* type, const char* desc, DWORD* len, BOOL duplicate); | ||||
| extern BOOL GetUSBDevices(DWORD devnum); | ||||
|  | @ -362,6 +372,7 @@ extern char* replace_in_token_data(const char* filename, const char* token, cons | |||
| extern void parse_update(char* buf, size_t len); | ||||
| extern BOOL WimExtractCheck(void); | ||||
| extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst); | ||||
| extern BOOL IsHDImage(const char* path); | ||||
| extern int IsHDD(DWORD DriveIndex, uint16_t vid, uint16_t pid, const char* strid); | ||||
| 
 | ||||
| static __inline BOOL UnlockDrive(HANDLE hDrive) | ||||
|  |  | |||
							
								
								
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | |||
| 
 | ||||
| IDD_DIALOG DIALOGEX 12, 12, 206, 329 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| CAPTION "Rufus 1.4.8.479" | ||||
| CAPTION "Rufus 1.4.8.480" | ||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||
| BEGIN | ||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 | ||||
|  | @ -165,7 +165,7 @@ END | |||
| RTL_IDD_DIALOG DIALOGEX 12, 12, 206, 329 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL | ||||
| CAPTION "Rufus 1.4.8.479" | ||||
| CAPTION "Rufus 1.4.8.480" | ||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||
| BEGIN | ||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 | ||||
|  | @ -427,8 +427,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 1,4,8,479 | ||||
|  PRODUCTVERSION 1,4,8,479 | ||||
|  FILEVERSION 1,4,8,480 | ||||
|  PRODUCTVERSION 1,4,8,480 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -445,13 +445,13 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "1.4.8.479" | ||||
|             VALUE "FileVersion", "1.4.8.480" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||
|             VALUE "OriginalFilename", "rufus.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "1.4.8.479" | ||||
|             VALUE "ProductVersion", "1.4.8.480" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
							
								
								
									
										70
									
								
								src/stdlg.c
									
										
									
									
									
								
							
							
						
						
									
										70
									
								
								src/stdlg.c
									
										
									
									
									
								
							|  | @ -237,13 +237,13 @@ fallback: | |||
|  * CoInitializeEx() for *EACH* thread you invoke FileDialog from, as | ||||
|  * GetDisplayName() will return error 0x8001010E otherwise. | ||||
|  */ | ||||
| char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc, DWORD options) | ||||
| char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options) | ||||
| { | ||||
| 	DWORD tmp; | ||||
| 	OPENFILENAMEA ofn; | ||||
| 	char selected_name[MAX_PATH]; | ||||
| 	char *ext_string = NULL, *all_files = NULL; | ||||
| 	size_t i, ext_strlen; | ||||
| 	size_t i, j, ext_strlen; | ||||
| 	BOOL r; | ||||
| 	char* filepath = NULL; | ||||
| 
 | ||||
|  | @ -251,25 +251,26 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des | |||
| 	HRESULT hr = FALSE; | ||||
| 	IFileDialog *pfd = NULL; | ||||
| 	IShellItem *psiResult; | ||||
| 	COMDLG_FILTERSPEC filter_spec[2]; | ||||
| 	char* ext_filter; | ||||
| 	COMDLG_FILTERSPEC* filter_spec; | ||||
| 	wchar_t *wpath = NULL, *wfilename = NULL; | ||||
| 	IShellItem *si_path = NULL;	// Automatically freed
 | ||||
| #endif | ||||
| 
 | ||||
| 	if ((ext == NULL) || (ext->count == 0) || (ext->extension == NULL) || (ext->description == NULL)) | ||||
| 		return NULL; | ||||
| 	dialog_showing++; | ||||
| 	memset(filter_spec, 0, sizeof(filter_spec)); | ||||
| 
 | ||||
| #if (_WIN32_WINNT >= 0x0600)	// Vista and later
 | ||||
| 	INIT_VISTA_SHELL32; | ||||
| 	if (IS_VISTA_SHELL32_AVAILABLE) { | ||||
| 	filter_spec = (COMDLG_FILTERSPEC*)calloc(ext->count + 1, sizeof(COMDLG_FILTERSPEC)); | ||||
| 	if ((IS_VISTA_SHELL32_AVAILABLE) && (filter_spec != NULL)) { | ||||
| 		// Setup the file extension filter table
 | ||||
| 		ext_filter = (char*)malloc(safe_strlen(ext)+3); | ||||
| 		if (ext_filter != NULL) { | ||||
| 			safe_sprintf(ext_filter, safe_strlen(ext)+3, "*.%s", ext); | ||||
| 			filter_spec[0].pszSpec = utf8_to_wchar(ext_filter); | ||||
| 			safe_free(ext_filter); | ||||
| 			filter_spec[0].pszName = utf8_to_wchar(ext_desc); | ||||
| 			filter_spec[1].pszSpec = L"*.*"; | ||||
| 			filter_spec[1].pszName = utf8_to_wchar(lmprintf(MSG_107)); | ||||
| 		for (i=0; i<ext->count; i++) { | ||||
| 			filter_spec[i].pszSpec = utf8_to_wchar(ext->extension[i]); | ||||
| 			filter_spec[i].pszName = utf8_to_wchar(ext->description[i]); | ||||
| 		} | ||||
| 		filter_spec[i].pszSpec = L"*.*"; | ||||
| 		filter_spec[i].pszName = utf8_to_wchar(lmprintf(MSG_107)); | ||||
| 
 | ||||
| 		hr = CoCreateInstance(save?&CLSID_FileSaveDialog:&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC, | ||||
| 			&IID_IFileDialog, (LPVOID)&pfd); | ||||
|  | @ -282,7 +283,7 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des | |||
| 		} | ||||
| 
 | ||||
| 		// Set the file extension filters
 | ||||
| 		pfd->lpVtbl->SetFileTypes(pfd, 2, filter_spec); | ||||
| 		pfd->lpVtbl->SetFileTypes(pfd, ext->count+1, filter_spec); | ||||
| 
 | ||||
| 		// Set the default directory
 | ||||
| 		wpath = utf8_to_wchar(path); | ||||
|  | @ -293,7 +294,7 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des | |||
| 		safe_free(wpath); | ||||
| 
 | ||||
| 		// Set the default filename
 | ||||
| 		wfilename = utf8_to_wchar(filename); | ||||
| 		wfilename = utf8_to_wchar((ext->filename == NULL)?ext->extension[0]:ext->filename); | ||||
| 		if (wfilename != NULL) { | ||||
| 			pfd->lpVtbl->SetFileName(pfd, wfilename); | ||||
| 		} | ||||
|  | @ -303,9 +304,12 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des | |||
| 
 | ||||
| 		// Cleanup
 | ||||
| 		safe_free(wfilename); | ||||
| 		safe_free(filter_spec[0].pszSpec); | ||||
| 		safe_free(filter_spec[0].pszName); | ||||
| 		safe_free(filter_spec[1].pszName); | ||||
| 		for (i=0; i<ext->count; i++) { | ||||
| 			safe_free(filter_spec[i].pszSpec); | ||||
| 			safe_free(filter_spec[i].pszName); | ||||
| 		} | ||||
| 		safe_free(filter_spec[i].pszName); | ||||
| 		safe_free(filter_spec); | ||||
| 
 | ||||
| 		if (SUCCEEDED(hr)) { | ||||
| 			// Obtain the result of the user's interaction with the dialog.
 | ||||
|  | @ -336,24 +340,30 @@ fallback: | |||
| 	if (pfd != NULL) { | ||||
| 		pfd->lpVtbl->Release(pfd); | ||||
| 	} | ||||
| #else | ||||
| 	dialog_showing++; | ||||
| #endif | ||||
| 
 | ||||
| 	memset(&ofn, 0, sizeof(ofn)); | ||||
| 	ofn.lStructSize = sizeof(ofn); | ||||
| 	ofn.hwndOwner = hMainDialog; | ||||
| 	// File name
 | ||||
| 	safe_strcpy(selected_name, MAX_PATH, filename); | ||||
| 	// Selected File name
 | ||||
| 	static_sprintf(selected_name, "%s", (ext->filename == NULL)?ext->extension[0]:ext->filename); | ||||
| 	ofn.lpstrFile = selected_name; | ||||
| 	ofn.nMaxFile = MAX_PATH; | ||||
| 	// Set the file extension filters
 | ||||
| 	all_files = lmprintf(MSG_107); | ||||
| 	ext_strlen = safe_strlen(ext_desc) + 2*safe_strlen(ext) + sizeof(" (*.)\0*.\0 (*.*)\0*.*\0\0") + safe_strlen(all_files); | ||||
| 	ext_string = (char*)malloc(ext_strlen); | ||||
| 	ext_strlen = 0; | ||||
| 	for (i=0; i<ext->count; i++) { | ||||
| 		ext_strlen += safe_strlen(ext->description[i]) + 2*safe_strlen(ext->extension[i]) + sizeof(" ()\r\r"); | ||||
| 	} | ||||
| 	ext_strlen += safe_strlen(all_files) + sizeof(" (*.*)\r*.*\r"); | ||||
| 	ext_string = (char*)malloc(ext_strlen+1); | ||||
| 	ext_string[0] = 0; | ||||
| 	if (ext_string == NULL) | ||||
| 		return NULL; | ||||
| 	safe_sprintf(ext_string, ext_strlen, "%s (*.%s)\r*.%s\r%s (*.*)\r*.*\r\0", ext_desc, ext, ext, all_files); | ||||
| 	for (i=0, j=0; i<ext->count; i++) { | ||||
| 		j += _snprintf(&ext_string[j], ext_strlen-j, "%s (%s)\r%s\r", ext->description[i], ext->extension[i], ext->extension[i]); | ||||
| 	} | ||||
| 	j = _snprintf(&ext_string[j], ext_strlen-j, "%s (*.*)\r*.*\r", all_files); | ||||
| 	// Microsoft could really have picked a better delimiter!
 | ||||
| 	for (i=0; i<ext_strlen; i++) { | ||||
| 		if (ext_string[i] == '\r') { | ||||
|  | @ -361,7 +371,7 @@ fallback: | |||
| 		} | ||||
| 	} | ||||
| 	ofn.lpstrFilter = ext_string; | ||||
| 	// Initial dir
 | ||||
| 	ofn.nFilterIndex = 1; | ||||
| 	ofn.lpstrInitialDir = path; | ||||
| 	ofn.Flags = OFN_OVERWRITEPROMPT | options; | ||||
| 	// Show Dialog
 | ||||
|  | @ -1177,6 +1187,9 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR | |||
| 	STARTUPINFOA si; | ||||
| 	PROCESS_INFORMATION pi; | ||||
| 	HFONT hyperlink_font = NULL; | ||||
| 	const char* dl_x[] = { "*.exe" }; | ||||
| 	const char* dl_d[] = { lmprintf(MSG_037) }; | ||||
| 	ext_t dl_ext = { ARRAYSIZE(dl_x), "rufus.log", dl_x, dl_d }; | ||||
| 
 | ||||
| 	switch (message) { | ||||
| 	case WM_INITDIALOG: | ||||
|  | @ -1245,7 +1258,8 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR | |||
| 					break; | ||||
| 				} | ||||
| 				for (i=(int)strlen(update.download_url); (i>0)&&(update.download_url[i]!='/'); i--); | ||||
| 				filepath = FileDialog(TRUE, app_dir, (char*)&update.download_url[i+1], "exe", lmprintf(MSG_037), OFN_NOCHANGEDIR); | ||||
| 				dl_ext.filename = &update.download_url[i+1]; | ||||
| 				filepath = FileDialog(TRUE, app_dir, &dl_ext, OFN_NOCHANGEDIR); | ||||
| 				if (filepath == NULL) { | ||||
| 					uprintf("Could not get save path\n"); | ||||
| 					break; | ||||
|  |  | |||
							
								
								
									
										101
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										101
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -18,17 +18,56 @@ | |||
|  */ | ||||
| 
 | ||||
| #include <windows.h> | ||||
| #include <stdlib.h> | ||||
| #include <io.h> | ||||
| 
 | ||||
| #include "rufus.h" | ||||
| #include "msapi_utf8.h" | ||||
| #include "drive.h" | ||||
| #include "registry.h" | ||||
| 
 | ||||
| static BOOL has_wimgapi = FALSE, has_7z = FALSE; | ||||
| static char sevenzip_path[MAX_PATH]; | ||||
| #if defined(_MSC_VER) | ||||
| #define bswap_uint64 _byteswap_uint64 | ||||
| #define bswap_uint32 _byteswap_ulong | ||||
| #define bswap_uint16 _byteswap_ushort | ||||
| #else | ||||
| #define bswap_uint64 __builtin_bswap64 | ||||
| #define bswap_uint32 __builtin_bswap32 | ||||
| #define bswap_uint16 __builtin_bswap16 | ||||
| #endif | ||||
| 
 | ||||
| // TODO: Add a call to generate a Fixed Hard Disk VHD footer, This would allow the saving of an existing USB to VHD. See VHD specs at:
 | ||||
| // http://download.microsoft.com/download/f/f/e/ffef50a5-07dd-4cf8-aaa3-442c0673a029/Virtual%20Hard%20Disk%20Format%20Spec_10_18_06.doc
 | ||||
| #define VHD_FOOTER_COOKIE					{ 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x' } | ||||
| 
 | ||||
| #define VHD_FOOTER_FILE_FORMAT_V1_0			0x00010000 | ||||
| 
 | ||||
| #define VHD_FOOTER_TYPE_FIXED_HARD_DISK		0x00000002 | ||||
| #define VHD_FOOTER_TYPE_DYNAMIC_HARD_DISK	0x00000003 | ||||
| #define VHD_FOOTER_TYPE_DIFFER_HARD_DISK	0x00000004 | ||||
| 
 | ||||
| /*
 | ||||
|  * VHD Fixed HD footer (Big Endian) | ||||
|  * http://download.microsoft.com/download/f/f/e/ffef50a5-07dd-4cf8-aaa3-442c0673a029/Virtual%20Hard%20Disk%20Format%20Spec_10_18_06.doc
 | ||||
|  */ | ||||
| #pragma pack(push, 1) | ||||
| typedef struct vhd_footer { | ||||
| 	char		cookie[8]; | ||||
| 	uint32_t	features; | ||||
| 	uint32_t	file_format_version; | ||||
| 	uint64_t	data_offset; | ||||
| 	uint32_t	timestamp; | ||||
| 	uint32_t	creator_app; | ||||
| 	uint32_t	creator_version; | ||||
| 	uint32_t	creator_host_os; | ||||
| 	uint64_t	original_size; | ||||
| 	uint64_t	current_size; | ||||
| 	uint32_t	disk_geometry; | ||||
| 	uint32_t	disk_type; | ||||
| 	uint32_t	checksum; | ||||
| 	uuid_t		unique_id; | ||||
| 	uint8_t		saved_state; | ||||
| 	uint8_t		reserved[427]; | ||||
| } vhd_footer; | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
| // WIM API Prototypes
 | ||||
| #define WIM_GENERIC_READ	GENERIC_READ | ||||
|  | @ -39,6 +78,9 @@ PF_TYPE_DECL(WINAPI, HANDLE, WIMLoadImage, (HANDLE, DWORD)); | |||
| PF_TYPE_DECL(WINAPI, BOOL, WIMExtractImagePath, (HANDLE, PWSTR, PWSTR, DWORD)); | ||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMCloseHandle, (HANDLE)); | ||||
| 
 | ||||
| static BOOL has_wimgapi = FALSE, has_7z = FALSE; | ||||
| static char sevenzip_path[MAX_PATH]; | ||||
| 
 | ||||
| static BOOL Get7ZipPath(void) | ||||
| { | ||||
| 	if ( (GetRegistryKeyStr(REGKEY_HKCU, "7-Zip\\Path", sevenzip_path, sizeof(sevenzip_path))) | ||||
|  | @ -49,6 +91,57 @@ static BOOL Get7ZipPath(void) | |||
| 	return FALSE; | ||||
| } | ||||
| 
 | ||||
| BOOL IsHDImage(const char* path) | ||||
| { | ||||
| 	const char conectix_str[] = VHD_FOOTER_COOKIE; | ||||
| 	HANDLE handle = INVALID_HANDLE_VALUE; | ||||
| 	LARGE_INTEGER liImageSize; | ||||
| 	vhd_footer* footer = NULL; | ||||
| 	DWORD size; | ||||
| 	LARGE_INTEGER ptr; | ||||
| 
 | ||||
| 	handle = CreateFileU(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); | ||||
| 	if (handle == INVALID_HANDLE_VALUE) { | ||||
| 		uprintf("Could not open image '%s'", path); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	iso_report.is_bootable_img = AnalyzeMBR(handle, "Image"); | ||||
| 
 | ||||
| 	if (!GetFileSizeEx(handle, &liImageSize)) { | ||||
| 		uprintf("Could not get image size: %s", WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	iso_report.projected_size = (uint64_t)liImageSize.QuadPart; | ||||
| 
 | ||||
| 	size = sizeof(vhd_footer); | ||||
| 	if (iso_report.projected_size >= (512 + size)) { | ||||
| 		footer = (vhd_footer*)malloc(size); | ||||
| 		ptr.QuadPart = iso_report.projected_size - size; | ||||
| 		if ( (footer == NULL) || (!SetFilePointerEx(handle, ptr, NULL, FILE_BEGIN)) || | ||||
| 			 (!ReadFile(handle, footer, size, &size, NULL)) || (size != sizeof(vhd_footer)) ) { | ||||
| 			uprintf("Could not read VHD footer"); | ||||
| 			goto out; | ||||
| 		} | ||||
| 		if (memcmp(footer->cookie, conectix_str, sizeof(footer->cookie)) == 0) { | ||||
| 			iso_report.projected_size -= sizeof(vhd_footer); | ||||
| 			if ( (bswap_uint32(footer->file_format_version) != VHD_FOOTER_FILE_FORMAT_V1_0) | ||||
| 			  || (bswap_uint32(footer->disk_type) != VHD_FOOTER_TYPE_FIXED_HARD_DISK)) { | ||||
| 				uprintf("Unsupported type of VHD image"); | ||||
| 				iso_report.is_bootable_img = FALSE; | ||||
| 				goto out; | ||||
| 			} | ||||
| 			// Need to remove the footer from our payload
 | ||||
| 			uprintf("Image is a Fixed Hard Disk VHD file"); | ||||
| 			iso_report.is_vhd = TRUE; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	safe_free(footer); | ||||
| 	safe_closehandle(handle); | ||||
| 	return iso_report.is_bootable_img; | ||||
| } | ||||
| 
 | ||||
| // Find out if we have any way to extract WIM files on this platform
 | ||||
| BOOL WimExtractCheck(void) | ||||
| { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue