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_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_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_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." | 	"maximum size allowed for a FAT or FAT32 file system." | ||||||
| t MSG_101 "Missing WIM support" | t MSG_101 "Missing WIM support" | ||||||
| t MSG_102 "Your platform cannot extract files from WIM archives. WIM extraction " | 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
 | 	// Write an image file
 | ||||||
| 	if (dt == DT_IMG) { | 	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; | 		li.QuadPart = 0; | ||||||
| 		SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN); | 		if (!SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN)) | ||||||
| 		hSourceImage = CreateFileU(iso_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); | 			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) { | 		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; | 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | @ -1397,6 +1398,10 @@ DWORD WINAPI FormatThread(void* param) | ||||||
| 				UpdateProgress(OP_FORMAT, format_percent); | 				UpdateProgress(OP_FORMAT, format_percent); | ||||||
| 			} | 			} | ||||||
| 			CHECK_FOR_USER_CANCEL; | 			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++) { | 			for (i=0; i<WRITE_RETRIES; i++) { | ||||||
| 				s = WriteFile(hPhysicalDrive, buffer, rSize, &wSize, NULL); | 				s = WriteFile(hPhysicalDrive, buffer, rSize, &wSize, NULL); | ||||||
| 				if ((s) && (wSize == rSize)) | 				if ((s) && (wSize == rSize)) | ||||||
|  | @ -1549,11 +1554,11 @@ DWORD WINAPI FormatThread(void* param) | ||||||
| 				goto out; | 				goto out; | ||||||
| 			} | 			} | ||||||
| 		} else if (dt == DT_ISO) { | 		} else if (dt == DT_ISO) { | ||||||
| 			if (iso_path != NULL) { | 			if (image_path != NULL) { | ||||||
| 				UpdateProgress(OP_DOS, 0.0f); | 				UpdateProgress(OP_DOS, 0.0f); | ||||||
| 				PrintStatus(0, TRUE, MSG_231); | 				PrintStatus(0, TRUE, MSG_231); | ||||||
| 				drive_name[2] = 0; | 				drive_name[2] = 0; | ||||||
| 				if (!ExtractISO(iso_path, drive_name, FALSE)) { | 				if (!ExtractISO(image_path, drive_name, FALSE)) { | ||||||
| 					if (!IS_ERROR(FormatStatus)) | 					if (!IS_ERROR(FormatStatus)) | ||||||
| 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; | 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; | ||||||
| 					goto out; | 					goto out; | ||||||
|  | @ -1561,7 +1566,7 @@ DWORD WINAPI FormatThread(void* param) | ||||||
| 				if (iso_report.has_kolibrios) { | 				if (iso_report.has_kolibrios) { | ||||||
| 					kolibri_dst[0] = drive_name[0]; | 					kolibri_dst[0] = drive_name[0]; | ||||||
| 					uprintf("Installing: %s (KolibriOS loader)\n", kolibri_dst); | 					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) { | 						FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM) == 0) { | ||||||
| 						uprintf("Warning: loader installation failed - KolibriOS will not boot!\n"); | 						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; | HINSTANCE hMainInstance; | ||||||
| HWND hMainDialog; | HWND hMainDialog; | ||||||
| char szFolderPath[MAX_PATH], app_dir[MAX_PATH]; | char szFolderPath[MAX_PATH], app_dir[MAX_PATH]; | ||||||
| char* iso_path = NULL; | char* image_path = NULL; | ||||||
| float fScale = 1.0f; | float fScale = 1.0f; | ||||||
| int default_fs; | int default_fs; | ||||||
| uint32_t dur_mins, dur_secs; | uint32_t dur_mins, dur_secs; | ||||||
|  | @ -438,7 +438,7 @@ static void SetFSFromISO(void) | ||||||
| 	uint32_t fs_mask = 0; | 	uint32_t fs_mask = 0; | ||||||
| 	int bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme))); | 	int bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme))); | ||||||
| 
 | 
 | ||||||
| 	if (iso_path == NULL) | 	if (image_path == NULL) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	// Create a mask of all the FS's available
 | 	// 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)); | 	int dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); | ||||||
| 	BOOL needs_masquerading = (IS_WINPE(iso_report.winpe) && (!iso_report.uses_minint)); | 	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); | 		CheckDlgButton(hMainDialog, IDC_RUFUS_MBR, BST_UNCHECKED); | ||||||
| 		IGNORE_RETVAL(ComboBox_SetCurSel(hDiskID, 0)); | 		IGNORE_RETVAL(ComboBox_SetCurSel(hDiskID, 0)); | ||||||
| 		return; | 		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 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) | 		if ( (safe_stricmp(no_label, DriveLabel.String[ComboIndex]) == 0) | ||||||
| 		  || (safe_stricmp(lmprintf(MSG_207), DriveLabel.String[ComboIndex]) == 0) ) { | 		  || (safe_stricmp(lmprintf(MSG_207), DriveLabel.String[ComboIndex]) == 0) ) { | ||||||
| 			SetWindowTextU(hLabel, SelectedDrive.proposed_label); | 			SetWindowTextU(hLabel, SelectedDrive.proposed_label); | ||||||
|  | @ -766,6 +766,9 @@ BOOL CALLBACK LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) | ||||||
| 	long lfHeight; | 	long lfHeight; | ||||||
| 	DWORD log_size; | 	DWORD log_size; | ||||||
| 	char *log_buffer = NULL, *filepath; | 	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) { | 	switch (message) { | ||||||
| 	case WM_INITDIALOG: | 	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); | 				log_size = GetDlgItemTextU(hDlg, IDC_LOG_EDIT, log_buffer, log_size); | ||||||
| 				if (log_size != 0) { | 				if (log_size != 0) { | ||||||
| 					log_size--;	// remove NUL terminator
 | 					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) { | 					if (filepath != NULL) { | ||||||
| 						FileIO(TRUE, filepath, &log_buffer, &log_size); | 						FileIO(TRUE, filepath, &log_buffer, &log_size); | ||||||
| 					} | 					} | ||||||
|  | @ -905,34 +908,6 @@ BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) | ||||||
| 	return FALSE; | 	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
 | // The scanning process can be blocking for message processing => use a thread
 | ||||||
| DWORD WINAPI ISOScanThread(LPVOID param) | DWORD WINAPI ISOScanThread(LPVOID param) | ||||||
| { | { | ||||||
|  | @ -940,21 +915,24 @@ DWORD WINAPI ISOScanThread(LPVOID param) | ||||||
| 	BOOL r; | 	BOOL r; | ||||||
| 	char isolinux_str[16] = "No"; | 	char isolinux_str[16] = "No"; | ||||||
| 
 | 
 | ||||||
| 	if (iso_path == NULL) | 	if (image_path == NULL) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	PrintStatus(0, TRUE, MSG_202); | 	PrintStatus(0, TRUE, MSG_202); | ||||||
| 	user_notified = FALSE; | 	user_notified = FALSE; | ||||||
| 	EnableControls(FALSE); | 	EnableControls(FALSE); | ||||||
| 	r = ExtractISO(iso_path, "", TRUE) || IsImage(iso_path); | 	r = ExtractISO(image_path, "", TRUE) || IsHDImage(image_path); | ||||||
| 	EnableControls(TRUE); | 	EnableControls(TRUE); | ||||||
| 	if (!r) { | 	if (!r) { | ||||||
| 		SendMessage(hISOProgressDlg, UM_PROGRESS_EXIT, 0, 0); | 		SendMessage(hISOProgressDlg, UM_PROGRESS_EXIT, 0, 0); | ||||||
| 		PrintStatus(0, TRUE, MSG_203); | 		PrintStatus(0, TRUE, MSG_203); | ||||||
| 		safe_free(iso_path); | 		safe_free(image_path); | ||||||
| 		goto out; | 		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)) { | 		if (HAS_SYSLINUX(iso_report)) { | ||||||
| 			safe_sprintf(isolinux_str, sizeof(isolinux_str), "Yes (%s)", iso_report.sl_version_str); | 			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))  | 	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)) ) { | 		&& (!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); | 		MessageBoxU(hMainDialog, lmprintf(MSG_082), lmprintf(MSG_081), MB_OK|MB_ICONINFORMATION|MB_IS_RTL); | ||||||
| 		safe_free(iso_path); | 		safe_free(image_path); | ||||||
| 		SetMBRProps(); | 		SetMBRProps(); | ||||||
| 	} else { | 	} else { | ||||||
| 		// Enable bootable and set Target System and FS accordingly
 | 		// 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, | 			SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_FILESYSTEM, | ||||||
| 				ComboBox_GetCurSel(hFileSystem)); | 				ComboBox_GetCurSel(hFileSystem)); | ||||||
| 		} | 		} | ||||||
| 		for (i=(int)safe_strlen(iso_path); (i>0)&&(iso_path[i]!='\\'); i--); | 		for (i=(int)safe_strlen(image_path); (i>0)&&(image_path[i]!='\\'); i--); | ||||||
| 		PrintStatus(0, TRUE, MSG_205, &iso_path[i+1]); | 		PrintStatus(0, TRUE, MSG_205, &image_path[i+1]); | ||||||
| 		// Lose the focus on the select ISO (but place it on Close)
 | 		// Lose the focus on the select ISO (but place it on Close)
 | ||||||
| 		SendMessage(hMainDialog, WM_NEXTDLGCTL,  (WPARAM)FALSE, 0); | 		SendMessage(hMainDialog, WM_NEXTDLGCTL,  (WPARAM)FALSE, 0); | ||||||
| 		// Lose the focus from Close and set it back to Start
 | 		// 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; | 	syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0; | ||||||
| 	dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); | 	dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); | ||||||
| 	if ((dt == DT_ISO) || (dt == DT_IMG)) { | 	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
 | 			// 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); | 			MessageBoxU(hMainDialog, lmprintf(MSG_087), lmprintf(MSG_086), MB_OK|MB_ICONERROR|MB_IS_RTL); | ||||||
| 			return FALSE; | 			return FALSE; | ||||||
|  | @ -1530,6 +1508,13 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 	static LPITEMIDLIST pidlDesktop = NULL; | 	static LPITEMIDLIST pidlDesktop = NULL; | ||||||
| 	static MY_SHChangeNotifyEntry NotifyEntry; | 	static MY_SHChangeNotifyEntry NotifyEntry; | ||||||
| 	loc_cmd* lcmd = NULL; | 	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) { | 	switch (message) { | ||||||
| 
 | 
 | ||||||
|  | @ -1809,7 +1794,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 			EnableAdvancedBootOptions(TRUE, TRUE); | 			EnableAdvancedBootOptions(TRUE, TRUE); | ||||||
| 			ToggleImage(!IsChecked(IDC_BOOT) || (selection_default != DT_IMG)); | 			ToggleImage(!IsChecked(IDC_BOOT) || (selection_default != DT_IMG)); | ||||||
| 			if ((selection_default == DT_ISO) || (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
 | 					// Set focus to the Select ISO button
 | ||||||
| 					SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)FALSE, 0); | 					SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)FALSE, 0); | ||||||
| 					SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)hSelectISO, TRUE); | 					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; | 			return (INT_PTR)TRUE; | ||||||
| 		case IDC_SELECT_ISO: | 		case IDC_SELECT_ISO: | ||||||
| 			if (iso_provided) { | 			if (iso_provided) { | ||||||
| 				uprintf("Image provided: '%s'\n", iso_path); | 				uprintf("Image provided: '%s'\n", image_path); | ||||||
| 				iso_provided = FALSE;	// One off thing...
 | 				iso_provided = FALSE;	// One off thing...
 | ||||||
| 			} else { | 			} else { | ||||||
| 				safe_free(iso_path); | 				safe_free(image_path); | ||||||
| 				if (selection_default == DT_IMG) | 				if (selection_default == DT_IMG) | ||||||
| 					iso_path = FileDialog(FALSE, NULL, "*.img", "img", "DD Image", 0); | 					image_path = FileDialog(FALSE, NULL, &img_ext, 0); | ||||||
| 				else | 				else | ||||||
| 					iso_path = FileDialog(FALSE, NULL, "*.iso", "iso", lmprintf(MSG_036), 0); | 					image_path = FileDialog(FALSE, NULL, &iso_ext, 0); | ||||||
| 				if (iso_path == NULL) { | 				if (image_path == NULL) { | ||||||
| 					CreateTooltip(hSelectISO, lmprintf(MSG_173), -1); | 					CreateTooltip(hSelectISO, lmprintf(MSG_173), -1); | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			selection_default = DT_ISO; | 			selection_default = DT_ISO; | ||||||
| 			CreateTooltip(hSelectISO, iso_path, -1); | 			CreateTooltip(hSelectISO, image_path, -1); | ||||||
| 			FormatStatus = 0; | 			FormatStatus = 0; | ||||||
| 			if (CreateThread(NULL, 0, ISOScanThread, NULL, 0, NULL) == NULL) { | 			if (CreateThread(NULL, 0, ISOScanThread, NULL, 0, NULL) == NULL) { | ||||||
| 				uprintf("Unable to start ISO scanning thread"); | 				uprintf("Unable to start ISO scanning thread"); | ||||||
|  | @ -2095,7 +2080,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| 				break; | 				break; | ||||||
| 			case 'i': | 			case 'i': | ||||||
| 				if (_access(optarg, 0) != -1) { | 				if (_access(optarg, 0) != -1) { | ||||||
| 					iso_path = safe_strdup(optarg); | 					image_path = safe_strdup(optarg); | ||||||
| 					iso_provided = TRUE; | 					iso_provided = TRUE; | ||||||
| 				} else { | 				} else { | ||||||
| 					printf("Could not find ISO image '%s'\n", optarg); | 					printf("Could not find ISO image '%s'\n", optarg); | ||||||
|  | @ -2282,7 +2267,7 @@ relaunch: | ||||||
| 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'I')) { | 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'I')) { | ||||||
| 				enable_iso = !enable_iso; | 				enable_iso = !enable_iso; | ||||||
| 				PrintStatus2000(lmprintf(MSG_262), enable_iso); | 				PrintStatus2000(lmprintf(MSG_262), enable_iso); | ||||||
| 				if (iso_path != NULL) { | 				if (image_path != NULL) { | ||||||
| 					iso_provided = TRUE; | 					iso_provided = TRUE; | ||||||
| 					PostMessage(hDlg, WM_COMMAND, IDC_SELECT_ISO, 0); | 					PostMessage(hDlg, WM_COMMAND, IDC_SELECT_ISO, 0); | ||||||
| 				} | 				} | ||||||
|  | @ -2354,7 +2339,7 @@ out: | ||||||
| 		DeleteFileU(loc_file); | 		DeleteFileU(loc_file); | ||||||
| 	DestroyAllTooltips(); | 	DestroyAllTooltips(); | ||||||
| 	exit_localization(); | 	exit_localization(); | ||||||
| 	safe_free(iso_path); | 	safe_free(image_path); | ||||||
| 	safe_free(locale_name); | 	safe_free(locale_name); | ||||||
| 	safe_free(update.download_url); | 	safe_free(update.download_url); | ||||||
| 	safe_free(update.release_notes); | 	safe_free(update.release_notes); | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								src/rufus.h
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/rufus.h
									
										
									
									
									
								
							|  | @ -247,6 +247,7 @@ typedef struct { | ||||||
| 	BOOL has_kolibrios; | 	BOOL has_kolibrios; | ||||||
| 	BOOL uses_minint; | 	BOOL uses_minint; | ||||||
| 	BOOL is_bootable_img; | 	BOOL is_bootable_img; | ||||||
|  | 	BOOL is_vhd; | ||||||
| 	uint16_t sl_version;	// Syslinux/Isolinux version
 | 	uint16_t sl_version;	// Syslinux/Isolinux version
 | ||||||
| 	char sl_version_str[12]; | 	char sl_version_str[12]; | ||||||
| } RUFUS_ISO_REPORT; | } RUFUS_ISO_REPORT; | ||||||
|  | @ -285,6 +286,15 @@ enum WindowsVersion { | ||||||
| 	WINDOWS_MAX | 	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 |  * Globals | ||||||
|  */ |  */ | ||||||
|  | @ -294,7 +304,7 @@ extern HWND hPartitionScheme, hFileSystem, hClusterSize, hLabel, hBootType, hNBP | ||||||
| extern HWND hISOProgressDlg, hISOProgressBar, hISOFileName, hDiskID; | extern HWND hISOProgressDlg, hISOProgressBar, hISOFileName, hDiskID; | ||||||
| extern float fScale; | extern float fScale; | ||||||
| extern char szFolderPath[MAX_PATH], app_dir[MAX_PATH]; | extern char szFolderPath[MAX_PATH], app_dir[MAX_PATH]; | ||||||
| extern char* iso_path; | extern char* image_path; | ||||||
| extern DWORD FormatStatus; | extern DWORD FormatStatus; | ||||||
| extern DWORD syslinux_ldlinux_len[2]; | extern DWORD syslinux_ldlinux_len[2]; | ||||||
| extern RUFUS_DRIVE_INFO SelectedDrive; | extern RUFUS_DRIVE_INFO SelectedDrive; | ||||||
|  | @ -342,7 +352,7 @@ extern BOOL InstallSyslinux(DWORD drive_index, char drive_letter); | ||||||
| DWORD WINAPI FormatThread(void* param); | DWORD WINAPI FormatThread(void* param); | ||||||
| extern BOOL CreateProgress(void); | extern BOOL CreateProgress(void); | ||||||
| extern BOOL SetAutorun(const char* path); | 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 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 unsigned char* GetResource(HMODULE module, char* name, char* type, const char* desc, DWORD* len, BOOL duplicate); | ||||||
| extern BOOL GetUSBDevices(DWORD devnum); | 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 void parse_update(char* buf, size_t len); | ||||||
| extern BOOL WimExtractCheck(void); | extern BOOL WimExtractCheck(void); | ||||||
| extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst); | extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst); | ||||||
|  | extern BOOL IsHDImage(const char* path); | ||||||
| extern int IsHDD(DWORD DriveIndex, uint16_t vid, uint16_t pid, const char* strid); | extern int IsHDD(DWORD DriveIndex, uint16_t vid, uint16_t pid, const char* strid); | ||||||
| 
 | 
 | ||||||
| static __inline BOOL UnlockDrive(HANDLE hDrive) | 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 | IDD_DIALOG DIALOGEX 12, 12, 206, 329 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | 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 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||||
| BEGIN | BEGIN | ||||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 |     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 | ||||||
|  | @ -165,7 +165,7 @@ END | ||||||
| RTL_IDD_DIALOG DIALOGEX 12, 12, 206, 329 | RTL_IDD_DIALOG DIALOGEX 12, 12, 206, 329 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | 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 | 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 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||||
| BEGIN | BEGIN | ||||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 |     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 | ||||||
|  | @ -427,8 +427,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 1,4,8,479 |  FILEVERSION 1,4,8,480 | ||||||
|  PRODUCTVERSION 1,4,8,479 |  PRODUCTVERSION 1,4,8,480 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -445,13 +445,13 @@ BEGIN | ||||||
|         BEGIN |         BEGIN | ||||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" |             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "1.4.8.479" |             VALUE "FileVersion", "1.4.8.480" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" |             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||||
|             VALUE "OriginalFilename", "rufus.exe" |             VALUE "OriginalFilename", "rufus.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "1.4.8.479" |             VALUE "ProductVersion", "1.4.8.480" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
							
								
								
									
										70
									
								
								src/stdlg.c
									
										
									
									
									
								
							
							
						
						
									
										70
									
								
								src/stdlg.c
									
										
									
									
									
								
							|  | @ -237,13 +237,13 @@ fallback: | ||||||
|  * CoInitializeEx() for *EACH* thread you invoke FileDialog from, as |  * CoInitializeEx() for *EACH* thread you invoke FileDialog from, as | ||||||
|  * GetDisplayName() will return error 0x8001010E otherwise. |  * 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; | 	DWORD tmp; | ||||||
| 	OPENFILENAMEA ofn; | 	OPENFILENAMEA ofn; | ||||||
| 	char selected_name[MAX_PATH]; | 	char selected_name[MAX_PATH]; | ||||||
| 	char *ext_string = NULL, *all_files = NULL; | 	char *ext_string = NULL, *all_files = NULL; | ||||||
| 	size_t i, ext_strlen; | 	size_t i, j, ext_strlen; | ||||||
| 	BOOL r; | 	BOOL r; | ||||||
| 	char* filepath = NULL; | 	char* filepath = NULL; | ||||||
| 
 | 
 | ||||||
|  | @ -251,25 +251,26 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des | ||||||
| 	HRESULT hr = FALSE; | 	HRESULT hr = FALSE; | ||||||
| 	IFileDialog *pfd = NULL; | 	IFileDialog *pfd = NULL; | ||||||
| 	IShellItem *psiResult; | 	IShellItem *psiResult; | ||||||
| 	COMDLG_FILTERSPEC filter_spec[2]; | 	COMDLG_FILTERSPEC* filter_spec; | ||||||
| 	char* ext_filter; |  | ||||||
| 	wchar_t *wpath = NULL, *wfilename = NULL; | 	wchar_t *wpath = NULL, *wfilename = NULL; | ||||||
| 	IShellItem *si_path = NULL;	// Automatically freed
 | 	IShellItem *si_path = NULL;	// Automatically freed
 | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|  | 	if ((ext == NULL) || (ext->count == 0) || (ext->extension == NULL) || (ext->description == NULL)) | ||||||
|  | 		return NULL; | ||||||
| 	dialog_showing++; | 	dialog_showing++; | ||||||
| 	memset(filter_spec, 0, sizeof(filter_spec)); | 
 | ||||||
|  | #if (_WIN32_WINNT >= 0x0600)	// Vista and later
 | ||||||
| 	INIT_VISTA_SHELL32; | 	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
 | 		// Setup the file extension filter table
 | ||||||
| 		ext_filter = (char*)malloc(safe_strlen(ext)+3); | 		for (i=0; i<ext->count; i++) { | ||||||
| 		if (ext_filter != NULL) { | 			filter_spec[i].pszSpec = utf8_to_wchar(ext->extension[i]); | ||||||
| 			safe_sprintf(ext_filter, safe_strlen(ext)+3, "*.%s", ext); | 			filter_spec[i].pszName = utf8_to_wchar(ext->description[i]); | ||||||
| 			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)); |  | ||||||
| 		} | 		} | ||||||
|  | 		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, | 		hr = CoCreateInstance(save?&CLSID_FileSaveDialog:&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC, | ||||||
| 			&IID_IFileDialog, (LPVOID)&pfd); | 			&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
 | 		// 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
 | 		// Set the default directory
 | ||||||
| 		wpath = utf8_to_wchar(path); | 		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); | 		safe_free(wpath); | ||||||
| 
 | 
 | ||||||
| 		// Set the default filename
 | 		// Set the default filename
 | ||||||
| 		wfilename = utf8_to_wchar(filename); | 		wfilename = utf8_to_wchar((ext->filename == NULL)?ext->extension[0]:ext->filename); | ||||||
| 		if (wfilename != NULL) { | 		if (wfilename != NULL) { | ||||||
| 			pfd->lpVtbl->SetFileName(pfd, wfilename); | 			pfd->lpVtbl->SetFileName(pfd, wfilename); | ||||||
| 		} | 		} | ||||||
|  | @ -303,9 +304,12 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des | ||||||
| 
 | 
 | ||||||
| 		// Cleanup
 | 		// Cleanup
 | ||||||
| 		safe_free(wfilename); | 		safe_free(wfilename); | ||||||
| 		safe_free(filter_spec[0].pszSpec); | 		for (i=0; i<ext->count; i++) { | ||||||
| 		safe_free(filter_spec[0].pszName); | 			safe_free(filter_spec[i].pszSpec); | ||||||
| 		safe_free(filter_spec[1].pszName); | 			safe_free(filter_spec[i].pszName); | ||||||
|  | 		} | ||||||
|  | 		safe_free(filter_spec[i].pszName); | ||||||
|  | 		safe_free(filter_spec); | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) { | 		if (SUCCEEDED(hr)) { | ||||||
| 			// Obtain the result of the user's interaction with the dialog.
 | 			// Obtain the result of the user's interaction with the dialog.
 | ||||||
|  | @ -336,24 +340,30 @@ fallback: | ||||||
| 	if (pfd != NULL) { | 	if (pfd != NULL) { | ||||||
| 		pfd->lpVtbl->Release(pfd); | 		pfd->lpVtbl->Release(pfd); | ||||||
| 	} | 	} | ||||||
| #else |  | ||||||
| 	dialog_showing++; |  | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	memset(&ofn, 0, sizeof(ofn)); | 	memset(&ofn, 0, sizeof(ofn)); | ||||||
| 	ofn.lStructSize = sizeof(ofn); | 	ofn.lStructSize = sizeof(ofn); | ||||||
| 	ofn.hwndOwner = hMainDialog; | 	ofn.hwndOwner = hMainDialog; | ||||||
| 	// File name
 | 	// Selected File name
 | ||||||
| 	safe_strcpy(selected_name, MAX_PATH, filename); | 	static_sprintf(selected_name, "%s", (ext->filename == NULL)?ext->extension[0]:ext->filename); | ||||||
| 	ofn.lpstrFile = selected_name; | 	ofn.lpstrFile = selected_name; | ||||||
| 	ofn.nMaxFile = MAX_PATH; | 	ofn.nMaxFile = MAX_PATH; | ||||||
| 	// Set the file extension filters
 | 	// Set the file extension filters
 | ||||||
| 	all_files = lmprintf(MSG_107); | 	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_strlen = 0; | ||||||
| 	ext_string = (char*)malloc(ext_strlen); | 	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) | 	if (ext_string == NULL) | ||||||
| 		return 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!
 | 	// Microsoft could really have picked a better delimiter!
 | ||||||
| 	for (i=0; i<ext_strlen; i++) { | 	for (i=0; i<ext_strlen; i++) { | ||||||
| 		if (ext_string[i] == '\r') { | 		if (ext_string[i] == '\r') { | ||||||
|  | @ -361,7 +371,7 @@ fallback: | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	ofn.lpstrFilter = ext_string; | 	ofn.lpstrFilter = ext_string; | ||||||
| 	// Initial dir
 | 	ofn.nFilterIndex = 1; | ||||||
| 	ofn.lpstrInitialDir = path; | 	ofn.lpstrInitialDir = path; | ||||||
| 	ofn.Flags = OFN_OVERWRITEPROMPT | options; | 	ofn.Flags = OFN_OVERWRITEPROMPT | options; | ||||||
| 	// Show Dialog
 | 	// Show Dialog
 | ||||||
|  | @ -1177,6 +1187,9 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR | ||||||
| 	STARTUPINFOA si; | 	STARTUPINFOA si; | ||||||
| 	PROCESS_INFORMATION pi; | 	PROCESS_INFORMATION pi; | ||||||
| 	HFONT hyperlink_font = NULL; | 	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) { | 	switch (message) { | ||||||
| 	case WM_INITDIALOG: | 	case WM_INITDIALOG: | ||||||
|  | @ -1245,7 +1258,8 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
| 				for (i=(int)strlen(update.download_url); (i>0)&&(update.download_url[i]!='/'); i--); | 				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) { | 				if (filepath == NULL) { | ||||||
| 					uprintf("Could not get save path\n"); | 					uprintf("Could not get save path\n"); | ||||||
| 					break; | 					break; | ||||||
|  |  | ||||||
							
								
								
									
										101
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										101
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -18,17 +18,56 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <windows.h> | #include <windows.h> | ||||||
|  | #include <stdlib.h> | ||||||
| #include <io.h> | #include <io.h> | ||||||
| 
 | 
 | ||||||
| #include "rufus.h" | #include "rufus.h" | ||||||
| #include "msapi_utf8.h" | #include "msapi_utf8.h" | ||||||
|  | #include "drive.h" | ||||||
| #include "registry.h" | #include "registry.h" | ||||||
| 
 | 
 | ||||||
| static BOOL has_wimgapi = FALSE, has_7z = FALSE; | #if defined(_MSC_VER) | ||||||
| static char sevenzip_path[MAX_PATH]; | #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:
 | #define VHD_FOOTER_COOKIE					{ 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x' } | ||||||
| // 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_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
 | // WIM API Prototypes
 | ||||||
| #define WIM_GENERIC_READ	GENERIC_READ | #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, WIMExtractImagePath, (HANDLE, PWSTR, PWSTR, DWORD)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMCloseHandle, (HANDLE)); | 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) | static BOOL Get7ZipPath(void) | ||||||
| { | { | ||||||
| 	if ( (GetRegistryKeyStr(REGKEY_HKCU, "7-Zip\\Path", sevenzip_path, sizeof(sevenzip_path))) | 	if ( (GetRegistryKeyStr(REGKEY_HKCU, "7-Zip\\Path", sevenzip_path, sizeof(sevenzip_path))) | ||||||
|  | @ -49,6 +91,57 @@ static BOOL Get7ZipPath(void) | ||||||
| 	return FALSE; | 	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
 | // Find out if we have any way to extract WIM files on this platform
 | ||||||
| BOOL WimExtractCheck(void) | BOOL WimExtractCheck(void) | ||||||
| { | { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue