mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[togo] enable selection of Windows version
* Closes #847 * Also set rufus-next to 2.12
This commit is contained in:
		
							parent
							
								
									5113be0a39
								
							
						
					
					
						commit
						7d302d340f
					
				
					 15 changed files with 349 additions and 78 deletions
				
			
		
							
								
								
									
										20
									
								
								configure
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								configure
									
										
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,6 @@ | ||||||
| #! /bin/sh | #! /bin/sh | ||||||
| # Guess values for system-dependent variables and create Makefiles. | # Guess values for system-dependent variables and create Makefiles. | ||||||
| # Generated by GNU Autoconf 2.69 for rufus 2.11. | # Generated by GNU Autoconf 2.69 for rufus 2.12. | ||||||
| # | # | ||||||
| # Report bugs to <https://github.com/pbatard/rufus/issues>. | # Report bugs to <https://github.com/pbatard/rufus/issues>. | ||||||
| # | # | ||||||
|  | @ -580,8 +580,8 @@ MAKEFLAGS= | ||||||
| # Identity of this package. | # Identity of this package. | ||||||
| PACKAGE_NAME='rufus' | PACKAGE_NAME='rufus' | ||||||
| PACKAGE_TARNAME='rufus' | PACKAGE_TARNAME='rufus' | ||||||
| PACKAGE_VERSION='2.11' | PACKAGE_VERSION='2.12' | ||||||
| PACKAGE_STRING='rufus 2.11' | PACKAGE_STRING='rufus 2.12' | ||||||
| PACKAGE_BUGREPORT='https://github.com/pbatard/rufus/issues' | PACKAGE_BUGREPORT='https://github.com/pbatard/rufus/issues' | ||||||
| PACKAGE_URL='http://rufus.akeo.ie' | PACKAGE_URL='http://rufus.akeo.ie' | ||||||
| 
 | 
 | ||||||
|  | @ -1228,7 +1228,7 @@ if test "$ac_init_help" = "long"; then | ||||||
|   # Omit some internal or obsolete options to make the list less imposing. |   # Omit some internal or obsolete options to make the list less imposing. | ||||||
|   # This message is too long to be a string in the A/UX 3.1 sh. |   # This message is too long to be a string in the A/UX 3.1 sh. | ||||||
|   cat <<_ACEOF |   cat <<_ACEOF | ||||||
| \`configure' configures rufus 2.11 to adapt to many kinds of systems. | \`configure' configures rufus 2.12 to adapt to many kinds of systems. | ||||||
| 
 | 
 | ||||||
| Usage: $0 [OPTION]... [VAR=VALUE]... | Usage: $0 [OPTION]... [VAR=VALUE]... | ||||||
| 
 | 
 | ||||||
|  | @ -1294,7 +1294,7 @@ fi | ||||||
| 
 | 
 | ||||||
| if test -n "$ac_init_help"; then | if test -n "$ac_init_help"; then | ||||||
|   case $ac_init_help in |   case $ac_init_help in | ||||||
|      short | recursive ) echo "Configuration of rufus 2.11:";; |      short | recursive ) echo "Configuration of rufus 2.12:";; | ||||||
|    esac |    esac | ||||||
|   cat <<\_ACEOF |   cat <<\_ACEOF | ||||||
| 
 | 
 | ||||||
|  | @ -1385,7 +1385,7 @@ fi | ||||||
| test -n "$ac_init_help" && exit $ac_status | test -n "$ac_init_help" && exit $ac_status | ||||||
| if $ac_init_version; then | if $ac_init_version; then | ||||||
|   cat <<\_ACEOF |   cat <<\_ACEOF | ||||||
| rufus configure 2.11 | rufus configure 2.12 | ||||||
| generated by GNU Autoconf 2.69 | generated by GNU Autoconf 2.69 | ||||||
| 
 | 
 | ||||||
| Copyright (C) 2012 Free Software Foundation, Inc. | Copyright (C) 2012 Free Software Foundation, Inc. | ||||||
|  | @ -1440,7 +1440,7 @@ cat >config.log <<_ACEOF | ||||||
| This file contains any messages produced by compilers while | This file contains any messages produced by compilers while | ||||||
| running configure, to aid debugging if configure makes a mistake. | running configure, to aid debugging if configure makes a mistake. | ||||||
| 
 | 
 | ||||||
| It was created by rufus $as_me 2.11, which was | It was created by rufus $as_me 2.12, which was | ||||||
| generated by GNU Autoconf 2.69.  Invocation command line was | generated by GNU Autoconf 2.69.  Invocation command line was | ||||||
| 
 | 
 | ||||||
|   $ $0 $@ |   $ $0 $@ | ||||||
|  | @ -2303,7 +2303,7 @@ fi | ||||||
| 
 | 
 | ||||||
| # Define the identity of the package. | # Define the identity of the package. | ||||||
|  PACKAGE='rufus' |  PACKAGE='rufus' | ||||||
|  VERSION='2.11' |  VERSION='2.12' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| cat >>confdefs.h <<_ACEOF | cat >>confdefs.h <<_ACEOF | ||||||
|  | @ -4482,7 +4482,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 | ||||||
| # report actual input values of CONFIG_FILES etc. instead of their | # report actual input values of CONFIG_FILES etc. instead of their | ||||||
| # values after options handling. | # values after options handling. | ||||||
| ac_log=" | ac_log=" | ||||||
| This file was extended by rufus $as_me 2.11, which was | This file was extended by rufus $as_me 2.12, which was | ||||||
| generated by GNU Autoconf 2.69.  Invocation command line was | generated by GNU Autoconf 2.69.  Invocation command line was | ||||||
| 
 | 
 | ||||||
|   CONFIG_FILES    = $CONFIG_FILES |   CONFIG_FILES    = $CONFIG_FILES | ||||||
|  | @ -4536,7 +4536,7 @@ _ACEOF | ||||||
| cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 | ||||||
| ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" | ||||||
| ac_cs_version="\\ | ac_cs_version="\\ | ||||||
| rufus config.status 2.11 | rufus config.status 2.12 | ||||||
| configured by $0, generated by GNU Autoconf 2.69, | configured by $0, generated by GNU Autoconf 2.69, | ||||||
|   with options \\"\$ac_cs_config\\" |   with options \\"\$ac_cs_config\\" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| AC_INIT([rufus], [2.11], [https://github.com/pbatard/rufus/issues], [rufus], [http://rufus.akeo.ie]) | AC_INIT([rufus], [2.12], [https://github.com/pbatard/rufus/issues], [rufus], [http://rufus.akeo.ie]) | ||||||
| AM_INIT_AUTOMAKE([-Wno-portability foreign no-dist no-dependencies]) | AM_INIT_AUTOMAKE([-Wno-portability foreign no-dist no-dependencies]) | ||||||
| AC_CONFIG_SRCDIR([src/rufus.c]) | AC_CONFIG_SRCDIR([src/rufus.c]) | ||||||
| AC_CONFIG_MACRO_DIR([m4]) | AC_CONFIG_MACRO_DIR([m4]) | ||||||
|  |  | ||||||
|  | @ -553,6 +553,8 @@ t MSG_287 "Detection of non-USB removable drives" | ||||||
| t MSG_288 "Missing elevated privileges" | t MSG_288 "Missing elevated privileges" | ||||||
| t MSG_289 "This application can only run with elevated privileges" | t MSG_289 "This application can only run with elevated privileges" | ||||||
| t MSG_290 "File Indexing" | t MSG_290 "File Indexing" | ||||||
|  | t MSG_291 "Version selection" | ||||||
|  | t MSG_292 "Please select the version of Windows you want to install:" | ||||||
| 
 | 
 | ||||||
| ################################################################################ | ################################################################################ | ||||||
| ############################# TRANSLATOR END COPY ############################## | ############################# TRANSLATOR END COPY ############################## | ||||||
|  |  | ||||||
|  | @ -313,7 +313,7 @@ BOOL GetDevices(DWORD devnum) | ||||||
| 	StrArrayClear(&DriveLabel); | 	StrArrayClear(&DriveLabel); | ||||||
| 	StrArrayCreate(&dev_if_path, 128); | 	StrArrayCreate(&dev_if_path, 128); | ||||||
| 	// Add a dummy for string index zero, as this is what non matching hashes will point to
 | 	// Add a dummy for string index zero, as this is what non matching hashes will point to
 | ||||||
| 	StrArrayAdd(&dev_if_path, ""); | 	StrArrayAdd(&dev_if_path, "", TRUE); | ||||||
| 
 | 
 | ||||||
| 	device_id = (char*)malloc(MAX_PATH); | 	device_id = (char*)malloc(MAX_PATH); | ||||||
| 	if (device_id == NULL) | 	if (device_id == NULL) | ||||||
|  | @ -340,7 +340,7 @@ BOOL GetDevices(DWORD devnum) | ||||||
| 						// Find the Device IDs for all the children of this hub
 | 						// Find the Device IDs for all the children of this hub
 | ||||||
| 						if (CM_Get_Child(&device_inst, dev_info_data.DevInst, 0) == CR_SUCCESS) { | 						if (CM_Get_Child(&device_inst, dev_info_data.DevInst, 0) == CR_SUCCESS) { | ||||||
| 							device_id[0] = 0; | 							device_id[0] = 0; | ||||||
| 							s = StrArrayAdd(&dev_if_path, devint_detail_data->DevicePath); | 							s = StrArrayAdd(&dev_if_path, devint_detail_data->DevicePath, TRUE); | ||||||
| 							uuprintf("  Hub[%d] = '%s'", s, devint_detail_data->DevicePath); | 							uuprintf("  Hub[%d] = '%s'", s, devint_detail_data->DevicePath); | ||||||
| 							if ((s>= 0) && (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS)) { | 							if ((s>= 0) && (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS)) { | ||||||
| 								if ((k = htab_hash(device_id, &htab_devid)) != 0) { | 								if ((k = htab_hash(device_id, &htab_devid)) != 0) { | ||||||
|  | @ -741,8 +741,8 @@ BOOL GetDevices(DWORD devnum) | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				// Must ensure that the combo box is UNSORTED for indexes to be the same
 | 				// Must ensure that the combo box is UNSORTED for indexes to be the same
 | ||||||
| 				StrArrayAdd(&DriveID, buffer); | 				StrArrayAdd(&DriveID, buffer, TRUE); | ||||||
| 				StrArrayAdd(&DriveLabel, label); | 				StrArrayAdd(&DriveLabel, label, TRUE); | ||||||
| 
 | 
 | ||||||
| 				IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index)); | 				IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index)); | ||||||
| 				maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry)); | 				maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry)); | ||||||
|  |  | ||||||
							
								
								
									
										46
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										46
									
								
								src/format.c
									
										
									
									
									
								
							|  | @ -1277,8 +1277,11 @@ static BOOL SetupWinToGo(const char* drive_name, BOOL use_ms_efi) | ||||||
| 	static char san_policy_path[] = "?:\\san_policy.xml"; | 	static char san_policy_path[] = "?:\\san_policy.xml"; | ||||||
| #endif | #endif | ||||||
| 	static char unattend_path[] = "?:\\Windows\\System32\\sysprep\\unattend.xml"; | 	static char unattend_path[] = "?:\\Windows\\System32\\sysprep\\unattend.xml"; | ||||||
|  | 	StrArray version_name, version_index; | ||||||
| 	char *mounted_iso, *ms_efi = NULL, image[128], cmd[MAX_PATH]; | 	char *mounted_iso, *ms_efi = NULL, image[128], cmd[MAX_PATH]; | ||||||
|  | 	char tmp_path[MAX_PATH] = "", xml_file[MAX_PATH] = ""; | ||||||
| 	unsigned char *buffer; | 	unsigned char *buffer; | ||||||
|  | 	int i, index; | ||||||
| 	wchar_t wVolumeName[] = L"?:"; | 	wchar_t wVolumeName[] = L"?:"; | ||||||
| 	DWORD bufsize; | 	DWORD bufsize; | ||||||
| 	ULONG cluster_size; | 	ULONG cluster_size; | ||||||
|  | @ -1305,11 +1308,50 @@ static BOOL SetupWinToGo(const char* drive_name, BOOL use_ms_efi) | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT); | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
|  | 	static_sprintf(image, "%s%s", mounted_iso, &img_report.install_wim_path[2]); | ||||||
| 	uprintf("Mounted ISO as '%s'", mounted_iso); | 	uprintf("Mounted ISO as '%s'", mounted_iso); | ||||||
| 
 | 
 | ||||||
|  | 	// Then we need to take a look at the XML file in install.wim to allow users
 | ||||||
|  | 	// to select the version they want to extract
 | ||||||
|  | 	if ((GetTempPathU(sizeof(tmp_path), tmp_path) == 0) | ||||||
|  | 		|| (GetTempFileNameU(tmp_path, APPLICATION_NAME, 0, xml_file) == 0) | ||||||
|  | 		|| (xml_file[0] == 0)) { | ||||||
|  | 		// Last ditch effort to get a loc file - just extract it to the current directory
 | ||||||
|  | 		safe_strcpy(xml_file, sizeof(xml_file), ".\\RufVXml.tmp"); | ||||||
|  | 	} | ||||||
|  | 	// GetTempFileName() may leave a file behind
 | ||||||
|  | 	DeleteFileU(xml_file); | ||||||
|  | 
 | ||||||
|  | 	// Must use the Windows WIM API as 7z messes up the XML
 | ||||||
|  | 	if (!WimExtractFile_API(image, 0, "[1].xml", xml_file)) { | ||||||
|  | 		uprintf("Failed to acquire WIM index"); | ||||||
|  | 	} | ||||||
|  | 	StrArrayCreate(&version_name, 16); | ||||||
|  | 	StrArrayCreate(&version_index, 16); | ||||||
|  | 	for (i = 0; (StrArrayAdd(&version_name, get_token_data_file_indexed("DISPLAYNAME", xml_file, i+1), FALSE) >= 0) && | ||||||
|  | 		(StrArrayAdd(&version_index, get_token_data_file_indexed("IMAGE INDEX", xml_file, i+1), FALSE) >= 0); i++); | ||||||
|  | 	DeleteFileU(xml_file); | ||||||
|  | 
 | ||||||
|  | 	if (i > 1) | ||||||
|  | 		i = Selection(lmprintf(MSG_291), lmprintf(MSG_292), version_name.String, i); | ||||||
|  | 	if (i <= 0) { | ||||||
|  | 		uprintf("Cancelled by user"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED; | ||||||
|  | 		UnMountISO(); | ||||||
|  | 		StrArrayDestroy(&version_name); | ||||||
|  | 		StrArrayDestroy(&version_index); | ||||||
|  | 		return FALSE; | ||||||
|  | 	} else if (i == 0) { | ||||||
|  | 		index = 1; | ||||||
|  | 	} else { | ||||||
|  | 		index = atoi(version_index.String[i - 1]); | ||||||
|  | 	} | ||||||
|  | 	uprintf("Selected: '%s' (index %s)", version_name.String[i - 1], version_index.String[i - 1]); | ||||||
|  | 	StrArrayDestroy(&version_name); | ||||||
|  | 	StrArrayDestroy(&version_index); | ||||||
|  | 
 | ||||||
| 	// Now we use the WIM API to apply that image
 | 	// Now we use the WIM API to apply that image
 | ||||||
| 	static_sprintf(image, "%s%s", mounted_iso, &img_report.install_wim_path[2]); | 	if (!WimApplyImage(image, index, drive_name)) { | ||||||
| 	if (!WimApplyImage(image, 1, drive_name)) { |  | ||||||
| 		uprintf("Failed to apply Windows To Go image"); | 		uprintf("Failed to apply Windows To Go image"); | ||||||
| 		if (!IS_ERROR(FormatStatus)) | 		if (!IS_ERROR(FormatStatus)) | ||||||
| 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT); | 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT); | ||||||
|  |  | ||||||
|  | @ -226,12 +226,12 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t i_file_length, cons | ||||||
| 
 | 
 | ||||||
| 		if (props->is_syslinux_cfg) { | 		if (props->is_syslinux_cfg) { | ||||||
| 			// Maintain a list of all the isolinux/syslinux configs identified so far
 | 			// Maintain a list of all the isolinux/syslinux configs identified so far
 | ||||||
| 			StrArrayAdd(&config_path, psz_fullpath); | 			StrArrayAdd(&config_path, psz_fullpath, TRUE); | ||||||
| 		} | 		} | ||||||
| 		for (i=0; i<ARRAYSIZE(isolinux_bin); i++) { | 		for (i=0; i<ARRAYSIZE(isolinux_bin); i++) { | ||||||
| 			if (safe_stricmp(psz_basename, isolinux_bin[i]) == 0) { | 			if (safe_stricmp(psz_basename, isolinux_bin[i]) == 0) { | ||||||
| 				// Maintain a list of all the isolinux.bin files found
 | 				// Maintain a list of all the isolinux.bin files found
 | ||||||
| 				StrArrayAdd(&isolinux_path, psz_fullpath); | 				StrArrayAdd(&isolinux_path, psz_fullpath, TRUE); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -96,6 +96,20 @@ const loc_control_id control_id[] = { | ||||||
| 	LOC_CTRL(IDC_SELECTION_LINE), | 	LOC_CTRL(IDC_SELECTION_LINE), | ||||||
| 	LOC_CTRL(IDC_SELECTION_CHOICE1), | 	LOC_CTRL(IDC_SELECTION_CHOICE1), | ||||||
| 	LOC_CTRL(IDC_SELECTION_CHOICE2), | 	LOC_CTRL(IDC_SELECTION_CHOICE2), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE3), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE4), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE5), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE6), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE7), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE8), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE9), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE10), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE11), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE12), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE13), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE14), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICE15), | ||||||
|  | 	LOC_CTRL(IDC_SELECTION_CHOICEMAX), | ||||||
| 	LOC_CTRL(IDS_DEVICE_TXT), | 	LOC_CTRL(IDS_DEVICE_TXT), | ||||||
| 	LOC_CTRL(IDS_PARTITION_TYPE_TXT), | 	LOC_CTRL(IDS_PARTITION_TYPE_TXT), | ||||||
| 	LOC_CTRL(IDS_FILESYSTEM_TXT), | 	LOC_CTRL(IDS_FILESYSTEM_TXT), | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								src/parser.c
									
										
									
									
									
								
							
							
						
						
									
										25
									
								
								src/parser.c
									
										
									
									
									
								
							|  | @ -571,20 +571,24 @@ out: | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Parse a line of UTF-16 text and return the data if it matches the 'token' |  * Parse a line of UTF-16 text and return the data if it matches the 'token' | ||||||
|  * The parsed line is of the form: [ ]token[ ]=[ ]["]data["][ ] and is |  * The parsed line is of the form: [ ][<][ ]token[ ][=|>][ ]["]data["][ ][<] and is | ||||||
|  * modified by the parser |  * modified by the parser | ||||||
|  */ |  */ | ||||||
| static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline) | static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline) | ||||||
| { | { | ||||||
| 	size_t i, r; | 	size_t i, r; | ||||||
| 	BOOLEAN quoteth = FALSE; | 	BOOLEAN quoteth = FALSE; | ||||||
|  | 	BOOLEAN xml = FALSE; | ||||||
| 
 | 
 | ||||||
| 	if ((wtoken == NULL) || (wline == NULL) || (wline[0] == 0)) | 	if ((wtoken == NULL) || (wline == NULL) || (wline[0] == 0)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	i = 0; | 	i = 0; | ||||||
| 
 | 
 | ||||||
| 	// Skip leading spaces
 | 	// Skip leading spaces and opening '<'
 | ||||||
|  | 	i += wcsspn(&wline[i], wspace); | ||||||
|  | 	if (wline[i] == L'<') | ||||||
|  | 		i++; | ||||||
| 	i += wcsspn(&wline[i], wspace); | 	i += wcsspn(&wline[i], wspace); | ||||||
| 
 | 
 | ||||||
| 	// Our token should begin a line
 | 	// Our token should begin a line
 | ||||||
|  | @ -597,12 +601,14 @@ static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline) | ||||||
| 	// Skip spaces
 | 	// Skip spaces
 | ||||||
| 	i += wcsspn(&wline[i], wspace); | 	i += wcsspn(&wline[i], wspace); | ||||||
| 
 | 
 | ||||||
| 	// Check for an equal sign
 | 	// Check for '=' or '>' sign
 | ||||||
| 	if (wline[i] != L'=') | 	if (wline[i] == L'>') | ||||||
|  | 		xml = TRUE; | ||||||
|  | 	else if (wline[i] != L'=') | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	i++; | 	i++; | ||||||
| 
 | 
 | ||||||
| 	// Skip spaces after equal sign
 | 	// Skip spaces
 | ||||||
| 	i += wcsspn(&wline[i], wspace); | 	i += wcsspn(&wline[i], wspace); | ||||||
| 
 | 
 | ||||||
| 	// eliminate leading quote, if it exists
 | 	// eliminate leading quote, if it exists
 | ||||||
|  | @ -615,7 +621,7 @@ static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline) | ||||||
| 	r = i; | 	r = i; | ||||||
| 
 | 
 | ||||||
| 	// locate end of string or quote
 | 	// locate end of string or quote
 | ||||||
| 	while ( (wline[i] != 0) && ((wline[i] != L'"') || ((wline[i] == L'"') && (!quoteth))) ) | 	while ( (wline[i] != 0) && (((wline[i] != L'"') && (wline[i] != L'<')) || ((wline[i] == L'"') && (!quoteth)) || ((wline[i] == L'<') && (!xml))) ) | ||||||
| 		i++; | 		i++; | ||||||
| 	wline[i--] = 0; | 	wline[i--] = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -627,11 +633,12 @@ static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Parse a file (ANSI or UTF-8 or UTF-16) and return the data for the first occurrence of 'token' |  * Parse a file (ANSI or UTF-8 or UTF-16) and return the data for the 'index'th occurrence of 'token' | ||||||
|  * The returned string is UTF-8 and MUST be freed by the caller |  * The returned string is UTF-8 and MUST be freed by the caller | ||||||
|  */ |  */ | ||||||
| char* get_token_data_file(const char* token, const char* filename) | char* get_token_data_file_indexed(const char* token, const char* filename, int index) | ||||||
| { | { | ||||||
|  | 	int i = 0; | ||||||
| 	wchar_t *wtoken = NULL, *wdata= NULL, *wfilename = NULL; | 	wchar_t *wtoken = NULL, *wdata= NULL, *wfilename = NULL; | ||||||
| 	wchar_t buf[1024]; | 	wchar_t buf[1024]; | ||||||
| 	FILE* fd = NULL; | 	FILE* fd = NULL; | ||||||
|  | @ -659,7 +666,7 @@ char* get_token_data_file(const char* token, const char* filename) | ||||||
| 	// Ideally, we'd check that our buffer fits the line
 | 	// Ideally, we'd check that our buffer fits the line
 | ||||||
| 	while (fgetws(buf, ARRAYSIZE(buf), fd) != NULL) { | 	while (fgetws(buf, ARRAYSIZE(buf), fd) != NULL) { | ||||||
| 		wdata = get_token_data_line(wtoken, buf); | 		wdata = get_token_data_line(wtoken, buf); | ||||||
| 		if (wdata != NULL) { | 		if ((wdata != NULL) && (++i == index)) { | ||||||
| 			ret = wchar_to_utf8(wdata); | 			ret = wchar_to_utf8(wdata); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -134,6 +134,20 @@ | ||||||
| #define IDC_SELECTION_LINE              1076 | #define IDC_SELECTION_LINE              1076 | ||||||
| #define IDC_SELECTION_CHOICE1           1077 | #define IDC_SELECTION_CHOICE1           1077 | ||||||
| #define IDC_SELECTION_CHOICE2           1078 | #define IDC_SELECTION_CHOICE2           1078 | ||||||
|  | #define IDC_SELECTION_CHOICE3           1079 | ||||||
|  | #define IDC_SELECTION_CHOICE4           1080 | ||||||
|  | #define IDC_SELECTION_CHOICE5           1081 | ||||||
|  | #define IDC_SELECTION_CHOICE6           1082 | ||||||
|  | #define IDC_SELECTION_CHOICE7           1083 | ||||||
|  | #define IDC_SELECTION_CHOICE8           1084 | ||||||
|  | #define IDC_SELECTION_CHOICE9           1085 | ||||||
|  | #define IDC_SELECTION_CHOICE10          1086 | ||||||
|  | #define IDC_SELECTION_CHOICE11          1087 | ||||||
|  | #define IDC_SELECTION_CHOICE12          1088 | ||||||
|  | #define IDC_SELECTION_CHOICE13          1089 | ||||||
|  | #define IDC_SELECTION_CHOICE14          1090 | ||||||
|  | #define IDC_SELECTION_CHOICE15          1091 | ||||||
|  | #define IDC_SELECTION_CHOICEMAX         1092 | ||||||
| #define IDS_DEVICE_TXT                  2000 | #define IDS_DEVICE_TXT                  2000 | ||||||
| #define IDS_PARTITION_TYPE_TXT          2001 | #define IDS_PARTITION_TYPE_TXT          2001 | ||||||
| #define IDS_FILESYSTEM_TXT              2002 | #define IDS_FILESYSTEM_TXT              2002 | ||||||
|  |  | ||||||
|  | @ -2108,6 +2108,10 @@ void SaveISO(void) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef RUFUS_TEST | ||||||
|  | 	extern int SelectionDyn(char* title, char* message, char** szChoice, int nChoices); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Main dialog callback |  * Main dialog callback | ||||||
|  */ |  */ | ||||||
|  | @ -2140,6 +2144,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 	case WM_COMMAND: | 	case WM_COMMAND: | ||||||
| #ifdef RUFUS_TEST | #ifdef RUFUS_TEST | ||||||
| 		if (LOWORD(wParam) == IDC_TEST) { | 		if (LOWORD(wParam) == IDC_TEST) { | ||||||
|  | 			char* choices[] = { "Choice 1", "Choice 2", "Choice 3" }; | ||||||
|  | 			SelectionDyn("Test Choice", "Unused", choices, ARRAYSIZE(choices)); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| #endif | #endif | ||||||
|  | @ -2438,8 +2444,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 						(ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)) == BT_ISO)) { | 						(ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)) == BT_ISO)) { | ||||||
| 						char* iso_image = lmprintf(MSG_036); | 						char* iso_image = lmprintf(MSG_036); | ||||||
| 						char* dd_image = lmprintf(MSG_095); | 						char* dd_image = lmprintf(MSG_095); | ||||||
|  | 						char* choices[2] = { lmprintf(MSG_276, iso_image), lmprintf(MSG_277, dd_image) }; | ||||||
| 						i = Selection(lmprintf(MSG_274), lmprintf(MSG_275, iso_image, dd_image, iso_image, dd_image), | 						i = Selection(lmprintf(MSG_274), lmprintf(MSG_275, iso_image, dd_image, iso_image, dd_image), | ||||||
| 							lmprintf(MSG_276, iso_image), lmprintf(MSG_277, dd_image)); | 							choices, 2); | ||||||
| 						if (i < 0) {	// Cancel
 | 						if (i < 0) {	// Cancel
 | ||||||
| 							format_op_in_progress = FALSE; | 							format_op_in_progress = FALSE; | ||||||
| 							PROCESS_QUEUED_EVENTS; | 							PROCESS_QUEUED_EVENTS; | ||||||
|  |  | ||||||
|  | @ -422,7 +422,7 @@ extern BOOL CreateTooltip(HWND hControl, const char* message, int duration); | ||||||
| extern void DestroyTooltip(HWND hWnd); | extern void DestroyTooltip(HWND hWnd); | ||||||
| extern void DestroyAllTooltips(void); | extern void DestroyAllTooltips(void); | ||||||
| extern BOOL Notification(int type, const notification_info* more_info, char* title, char* format, ...); | extern BOOL Notification(int type, const notification_info* more_info, char* title, char* format, ...); | ||||||
| extern int Selection(char* title, char* message, char* selection1, char* selection2); | extern int Selection(char* title, char* message, char** choices, int size); | ||||||
| extern SIZE GetTextSize(HWND hCtrl); | extern SIZE GetTextSize(HWND hCtrl); | ||||||
| extern BOOL ExtractDOS(const char* path); | extern BOOL ExtractDOS(const char* path); | ||||||
| extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan); | extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan); | ||||||
|  | @ -450,7 +450,8 @@ extern BOOL SetUpdateCheck(void); | ||||||
| extern BOOL CheckForUpdates(BOOL force); | extern BOOL CheckForUpdates(BOOL force); | ||||||
| extern void DownloadNewVersion(void); | extern void DownloadNewVersion(void); | ||||||
| extern BOOL IsShown(HWND hDlg); | extern BOOL IsShown(HWND hDlg); | ||||||
| extern char* get_token_data_file(const char* token, const char* filename); | extern char* get_token_data_file_indexed(const char* token, const char* filename, int index); | ||||||
|  | #define get_token_data_file(token, filename) get_token_data_file_indexed(token, filename, 1) | ||||||
| extern char* set_token_data_file(const char* token, const char* data, const char* filename); | extern char* set_token_data_file(const char* token, const char* data, const char* filename); | ||||||
| extern char* get_token_data_buffer(const char* token, unsigned int n, const char* buffer, size_t buffer_size); | extern char* get_token_data_buffer(const char* token, unsigned int n, const char* buffer, size_t buffer_size); | ||||||
| extern char* insert_section_data(const char* filename, const char* section, const char* data, BOOL dos2unix); | extern char* insert_section_data(const char* filename, const char* section, const char* data, BOOL dos2unix); | ||||||
|  | @ -459,6 +460,8 @@ extern char* replace_char(const char* src, const char c, const char* rep); | ||||||
| extern void parse_update(char* buf, size_t len); | extern void parse_update(char* buf, size_t len); | ||||||
| extern uint8_t WimExtractCheck(void); | extern uint8_t 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 WimExtractFile_API(const char* image, int index, const char* src, const char* dst); | ||||||
|  | extern BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst); | ||||||
| extern BOOL WimApplyImage(const char* image, int index, const char* dst); | extern BOOL WimApplyImage(const char* image, int index, const char* dst); | ||||||
| extern BOOL IsBootableImage(const char* path); | extern BOOL IsBootableImage(const char* path); | ||||||
| extern BOOL AppendVHDFooter(const char* vhd_path); | extern BOOL AppendVHDFooter(const char* vhd_path); | ||||||
|  | @ -507,7 +510,7 @@ typedef struct { | ||||||
| 	uint32_t Max;		// Maximum array size
 | 	uint32_t Max;		// Maximum array size
 | ||||||
| } StrArray; | } StrArray; | ||||||
| extern void StrArrayCreate(StrArray* arr, uint32_t initial_size); | extern void StrArrayCreate(StrArray* arr, uint32_t initial_size); | ||||||
| extern int32_t StrArrayAdd(StrArray* arr, const char* str); | extern int32_t StrArrayAdd(StrArray* arr, const char* str, BOOL ); | ||||||
| extern void StrArrayClear(StrArray* arr); | extern void StrArrayClear(StrArray* arr); | ||||||
| extern void StrArrayDestroy(StrArray* arr); | extern void StrArrayDestroy(StrArray* arr); | ||||||
| #define IsStrArrayEmpty(arr) (arr.Index == 0) | #define IsStrArrayEmpty(arr) (arr.Index == 0) | ||||||
|  |  | ||||||
							
								
								
									
										30
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | ||||||
| IDD_DIALOG DIALOGEX 12, 12, 242, 376 | IDD_DIALOG DIALOGEX 12, 12, 242, 376 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_ACCEPTFILES | EXSTYLE WS_EX_ACCEPTFILES | ||||||
| CAPTION "Rufus 2.11.1007" | CAPTION "Rufus 2.12.1008" | ||||||
| FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | ||||||
| BEGIN | BEGIN | ||||||
|     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 |     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 | ||||||
|  | @ -144,10 +144,24 @@ BEGIN | ||||||
|     LTEXT           "",IDC_STATIC,0,0,312,46 |     LTEXT           "",IDC_STATIC,0,0,312,46 | ||||||
|     ICON            IDI_ICON,IDC_SELECTION_ICON,6,6,20,20,0,WS_EX_TRANSPARENT |     ICON            IDI_ICON,IDC_SELECTION_ICON,6,6,20,20,0,WS_EX_TRANSPARENT | ||||||
|     LTEXT           "Message",IDC_SELECTION_TEXT,35,5,269,8 |     LTEXT           "Message",IDC_SELECTION_TEXT,35,5,269,8 | ||||||
|     DEFPUSHBUTTON   "Cancel",IDCANCEL,254,52,50,14 |     DEFPUSHBUTTON   "OK",IDOK,196,52,50,14 | ||||||
|     PUSHBUTTON      "OK",IDOK,196,52,50,14 |     PUSHBUTTON      "Cancel",IDCANCEL,254,52,50,14 | ||||||
|     CONTROL         "Choice 1",IDC_SELECTION_CHOICE1,"Button",BS_AUTORADIOBUTTON,35,18,269,10,WS_EX_TRANSPARENT |     CONTROL         "Choice 1",IDC_SELECTION_CHOICE1,"Button",BS_AUTORADIOBUTTON | WS_GROUP,35,18,269,10,WS_EX_TRANSPARENT | ||||||
|     CONTROL         "Choice 2",IDC_SELECTION_CHOICE2,"Button",BS_AUTORADIOBUTTON,35,31,269,10,WS_EX_TRANSPARENT |     CONTROL         "Choice 2",IDC_SELECTION_CHOICE2,"Button",BS_AUTORADIOBUTTON,35,31,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 3",IDC_SELECTION_CHOICE3,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,44,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 4",IDC_SELECTION_CHOICE4,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,57,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 5",IDC_SELECTION_CHOICE5,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,70,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 6",IDC_SELECTION_CHOICE6,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,83,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 7",IDC_SELECTION_CHOICE7,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,96,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 8",IDC_SELECTION_CHOICE8,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,109,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 9",IDC_SELECTION_CHOICE9,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,122,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 10",IDC_SELECTION_CHOICE10,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,135,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 11",IDC_SELECTION_CHOICE11,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,148,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 12",IDC_SELECTION_CHOICE12,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,161,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 13",IDC_SELECTION_CHOICE13,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,174,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 14",IDC_SELECTION_CHOICE14,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,187,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 15",IDC_SELECTION_CHOICE15,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,200,269,10,WS_EX_TRANSPARENT | ||||||
|  |     CONTROL         "Choice 16",IDC_SELECTION_CHOICEMAX,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,21,269,10,WS_EX_TRANSPARENT | ||||||
| END | END | ||||||
| 
 | 
 | ||||||
| IDD_UPDATE_POLICY DIALOGEX 0, 0, 287, 198 | IDD_UPDATE_POLICY DIALOGEX 0, 0, 287, 198 | ||||||
|  | @ -320,8 +334,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 2,11,1007,0 |  FILEVERSION 2,12,1008,0 | ||||||
|  PRODUCTVERSION 2,11,1007,0 |  PRODUCTVERSION 2,12,1008,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -338,13 +352,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", "2.11.1007" |             VALUE "FileVersion", "2.12.1008" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2016 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", "2.11.1007" |             VALUE "ProductVersion", "2.12.1008" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
|  | @ -348,10 +348,10 @@ void StrArrayCreate(StrArray* arr, uint32_t initial_size) | ||||||
| 		uprintf("Could not allocate string array\n"); | 		uprintf("Could not allocate string array\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t StrArrayAdd(StrArray* arr, const char* str) | int32_t StrArrayAdd(StrArray* arr, const char* str, BOOL duplicate) | ||||||
| { | { | ||||||
| 	char** old_table; | 	char** old_table; | ||||||
| 	if ((arr == NULL) || (arr->String == NULL)) | 	if ((arr == NULL) || (arr->String == NULL) || (str == NULL)) | ||||||
| 		return -1; | 		return -1; | ||||||
| 	if (arr->Index == arr->Max) { | 	if (arr->Index == arr->Max) { | ||||||
| 		arr->Max *= 2; | 		arr->Max *= 2; | ||||||
|  | @ -363,7 +363,7 @@ int32_t StrArrayAdd(StrArray* arr, const char* str) | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	arr->String[arr->Index] = safe_strdup(str); | 	arr->String[arr->Index] = (duplicate)?safe_strdup(str):(char*)str; | ||||||
| 	if (arr->String[arr->Index] == NULL) { | 	if (arr->String[arr->Index] == NULL) { | ||||||
| 		uprintf("Could not store string in array\n"); | 		uprintf("Could not store string in array\n"); | ||||||
| 		return -1; | 		return -1; | ||||||
|  |  | ||||||
							
								
								
									
										185
									
								
								src/stdlg.c
									
										
									
									
									
								
							
							
						
						
									
										185
									
								
								src/stdlg.c
									
										
									
									
									
								
							|  | @ -54,7 +54,8 @@ PF_TYPE_DECL(WINAPI, LPITEMIDLIST, SHSimpleIDListFromPath, (PCWSTR pszPath)); | ||||||
| static HICON hMessageIcon = (HICON)INVALID_HANDLE_VALUE; | static HICON hMessageIcon = (HICON)INVALID_HANDLE_VALUE; | ||||||
| static char* szMessageText = NULL; | static char* szMessageText = NULL; | ||||||
| static char* szMessageTitle = NULL; | static char* szMessageTitle = NULL; | ||||||
| static char *szChoice1, *szChoice2; | static char **szChoice; | ||||||
|  | static int nChoices; | ||||||
| static HWND hBrowseEdit; | static HWND hBrowseEdit; | ||||||
| extern HWND hUpdatesDlg; | extern HWND hUpdatesDlg; | ||||||
| static WNDPROC pOrgBrowseWndproc; | static WNDPROC pOrgBrowseWndproc; | ||||||
|  | @ -68,6 +69,14 @@ static char *fp_title_str = "Microsoft Windows", *fp_button_str = "Format disk"; | ||||||
| 
 | 
 | ||||||
| extern loc_cmd* selected_locale; | extern loc_cmd* selected_locale; | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * https://blogs.msdn.microsoft.com/oldnewthing/20040802-00/?p=38283/
 | ||||||
|  |  */ | ||||||
|  | void SetDialogFocus(HWND hDlg, HWND hCtrl) | ||||||
|  | { | ||||||
|  | 	SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)hCtrl, TRUE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * We need a sub-callback to read the content of the edit box on exit and update |  * We need a sub-callback to read the content of the edit box on exit and update | ||||||
|  * our path, else if what the user typed does match the selection, it is discarded. |  * our path, else if what the user typed does match the selection, it is discarded. | ||||||
|  | @ -99,7 +108,7 @@ INT CALLBACK BrowseInfoCallback(HWND hDlg, UINT message, LPARAM lParam, LPARAM p | ||||||
| 		// Get a handle to the edit control to fix that
 | 		// Get a handle to the edit control to fix that
 | ||||||
| 		hBrowseEdit = FindWindowExA(hDlg, NULL, "Edit", NULL); | 		hBrowseEdit = FindWindowExA(hDlg, NULL, "Edit", NULL); | ||||||
| 		SetWindowTextU(hBrowseEdit, szFolderPath); | 		SetWindowTextU(hBrowseEdit, szFolderPath); | ||||||
| 		SetFocus(hBrowseEdit); | 		SetDialogFocus(hDlg, hBrowseEdit); | ||||||
| 		// On XP, BFFM_SETSELECTION can't be used with a Unicode Path in SendMessageW
 | 		// On XP, BFFM_SETSELECTION can't be used with a Unicode Path in SendMessageW
 | ||||||
| 		// or a pidl (at least with MinGW) => must use SendMessageA
 | 		// or a pidl (at least with MinGW) => must use SendMessageA
 | ||||||
| 		if (nWindowsVersion <= WINDOWS_XP) { | 		if (nWindowsVersion <= WINDOWS_XP) { | ||||||
|  | @ -849,6 +858,13 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA | ||||||
| 
 | 
 | ||||||
| 	switch (message) { | 	switch (message) { | ||||||
| 	case WM_INITDIALOG: | 	case WM_INITDIALOG: | ||||||
|  | 		// Don't overflow our max radio button
 | ||||||
|  | 		if (nChoices > (IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1)) { | ||||||
|  | 			uprintf("WARNING: Too many options requested for Selection (%d vs %d)", | ||||||
|  | 				nChoices, IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1); | ||||||
|  | 			nChoices = IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1; | ||||||
|  | 		} | ||||||
|  | 		// TODO: This shouldn't be needed when using DS_SHELLFONT
 | ||||||
| 		// Get the system message box font. See http://stackoverflow.com/a/6057761
 | 		// Get the system message box font. See http://stackoverflow.com/a/6057761
 | ||||||
| 		ncm.cbSize = sizeof(ncm); | 		ncm.cbSize = sizeof(ncm); | ||||||
| 		// If we're compiling with the Vista SDK or later, the NONCLIENTMETRICS struct
 | 		// If we're compiling with the Vista SDK or later, the NONCLIENTMETRICS struct
 | ||||||
|  | @ -865,8 +881,8 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA | ||||||
| 		// Set the dialog to use the system message box font
 | 		// Set the dialog to use the system message box font
 | ||||||
| 		SendMessage(hDlg, WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | 		SendMessage(hDlg, WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | ||||||
| 		SendMessage(GetDlgItem(hDlg, IDC_SELECTION_TEXT), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | 		SendMessage(GetDlgItem(hDlg, IDC_SELECTION_TEXT), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | ||||||
| 		SendMessage(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | 		for (i = 0; i < nChoices; i++) | ||||||
| 		SendMessage(GetDlgItem(hDlg, IDC_SELECTION_CHOICE2), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | 			SendMessage(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | ||||||
| 		SendMessage(GetDlgItem(hDlg, IDYES), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | 		SendMessage(GetDlgItem(hDlg, IDYES), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | ||||||
| 		SendMessage(GetDlgItem(hDlg, IDNO), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | 		SendMessage(GetDlgItem(hDlg, IDNO), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0)); | ||||||
| 
 | 
 | ||||||
|  | @ -880,9 +896,10 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA | ||||||
| 		SetWindowTextU(hDlg, szMessageTitle); | 		SetWindowTextU(hDlg, szMessageTitle); | ||||||
| 		SetWindowTextU(GetDlgItem(hDlg, IDCANCEL), lmprintf(MSG_007)); | 		SetWindowTextU(GetDlgItem(hDlg, IDCANCEL), lmprintf(MSG_007)); | ||||||
| 		SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_TEXT), szMessageText); | 		SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_TEXT), szMessageText); | ||||||
| 		SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1), szChoice1); | 		for (i = 0; i < nChoices; i++) { | ||||||
| 		SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_CHOICE2), szChoice2); | 			SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), szChoice[i]); | ||||||
| 
 | 			ShowWindow(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), SW_SHOW); | ||||||
|  | 		} | ||||||
| 		// Move/Resize the controls as needed to fit our text
 | 		// Move/Resize the controls as needed to fit our text
 | ||||||
| 		hCtrl = GetDlgItem(hDlg, IDC_SELECTION_TEXT); | 		hCtrl = GetDlgItem(hDlg, IDC_SELECTION_TEXT); | ||||||
| 		hDC = GetDC(hCtrl); | 		hDC = GetDC(hCtrl); | ||||||
|  | @ -893,13 +910,16 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA | ||||||
| 		dh = rect.bottom - rect.top - dh; | 		dh = rect.bottom - rect.top - dh; | ||||||
| 		if (hDC != NULL) | 		if (hDC != NULL) | ||||||
| 			ReleaseDC(hCtrl, hDC); | 			ReleaseDC(hCtrl, hDC); | ||||||
| 
 |  | ||||||
| 		ResizeMoveCtrl(hDlg, hCtrl, 0, 0, 0, dh, 1.0f); | 		ResizeMoveCtrl(hDlg, hCtrl, 0, 0, 0, dh, 1.0f); | ||||||
|  | 		for (i = 0; i < nChoices; i++) | ||||||
|  | 			ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), 0, dh, 0, 0, 1.0f); | ||||||
|  | 		if (nChoices > 2) { | ||||||
|  | 			GetWindowRect(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1), &rect); | ||||||
|  | 			dh += (nChoices - 1) * (rect.bottom - rect.top) - 5; | ||||||
|  | 		} | ||||||
| 		ResizeMoveCtrl(hDlg, hDlg, 0, 0, 0, dh, 1.0f); | 		ResizeMoveCtrl(hDlg, hDlg, 0, 0, 0, dh, 1.0f); | ||||||
| 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, -1), 0, 0, 0, dh, 1.0f);	// IDC_STATIC = -1
 | 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, -1), 0, 0, 0, dh, 1.0f);	// IDC_STATIC = -1
 | ||||||
| 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_LINE), 0, dh, 0, 0, 1.0f); | 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_LINE), 0, dh, 0, 0, 1.0f); | ||||||
| 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_CHOICE1), 0, dh, 0, 0, 1.0f); |  | ||||||
| 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_CHOICE2), 0, dh, 0, 0, 1.0f); |  | ||||||
| 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDOK), 0, dh, 0, 0, 1.0f); | 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDOK), 0, dh, 0, 0, 1.0f); | ||||||
| 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDCANCEL), 0, dh, 0, 0, 1.0f); | 		ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDCANCEL), 0, dh, 0, 0, 1.0f); | ||||||
| 
 | 
 | ||||||
|  | @ -926,10 +946,10 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA | ||||||
| 	case WM_COMMAND: | 	case WM_COMMAND: | ||||||
| 		switch (LOWORD(wParam)) { | 		switch (LOWORD(wParam)) { | ||||||
| 		case IDOK: | 		case IDOK: | ||||||
| 			if (Button_GetCheck(GetDlgItem(hDlg, IDC_SELECTION_CHOICE2)) == BST_CHECKED) | 			for (i = 0; (i < nChoices) && | ||||||
| 				r = 2; | 				(Button_GetCheck(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i)) != BST_CHECKED); i++); | ||||||
| 			else | 			if (i < nChoices) | ||||||
| 				r = 1; | 				r = i + 1; | ||||||
| 			// Fall through
 | 			// Fall through
 | ||||||
| 		case IDNO: | 		case IDNO: | ||||||
| 		case IDCANCEL: | 		case IDCANCEL: | ||||||
|  | @ -944,15 +964,15 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA | ||||||
| /*
 | /*
 | ||||||
| * Display a selection question | * Display a selection question | ||||||
| */ | */ | ||||||
| int Selection(char* title, char* message, char* choice1, char* choice2) | int Selection(char* title, char* message, char** choices, int size) | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	dialog_showing++; | 	dialog_showing++; | ||||||
| 	szMessageTitle = title; | 	szMessageTitle = title; | ||||||
| 	szMessageText = message; | 	szMessageText = message; | ||||||
| 	szChoice1 = choice1; | 	szChoice = choices; | ||||||
| 	szChoice2 = choice2; | 	nChoices = size; | ||||||
| 	ret = (int)MyDialogBox(hMainInstance, IDD_SELECTION, hMainDialog, SelectionCallback); | 	ret = (int)MyDialogBox(hMainInstance, IDD_SELECTION, hMainDialog, SelectionCallback); | ||||||
| 	dialog_showing--; | 	dialog_showing--; | ||||||
| 
 | 
 | ||||||
|  | @ -1819,3 +1839,134 @@ void ClrFormatPromptHook(void) { | ||||||
| 	UnhookWinEvent(fp_weh); | 	UnhookWinEvent(fp_weh); | ||||||
| 	fp_weh = NULL; | 	fp_weh = NULL; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #ifdef RUFUS_TEST | ||||||
|  | static inline LPWORD lpwAlign(LPWORD addr) | ||||||
|  | { | ||||||
|  | 	return (LPWORD)((((uintptr_t)addr) + 3) & (~3)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | INT_PTR CALLBACK SelectionDynCallback(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) | ||||||
|  | { | ||||||
|  | 	int r = -1; | ||||||
|  | 	switch (message) { | ||||||
|  | 	case WM_INITDIALOG: | ||||||
|  | 		return (INT_PTR)TRUE; | ||||||
|  | 
 | ||||||
|  | 	case WM_COMMAND: | ||||||
|  | 		switch (LOWORD(wParam)) { | ||||||
|  | 		case IDOK: | ||||||
|  | 			r = 0; | ||||||
|  | 		case IDCANCEL: | ||||||
|  | 			EndDialog(hwndDlg, r); | ||||||
|  | 			return (INT_PTR)TRUE; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return FALSE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int SelectionDyn(char* title, char* message, char** szChoice, int nChoices) | ||||||
|  | { | ||||||
|  | #define ID_RADIO  12345 | ||||||
|  | 	LPCWSTR lpwszTypeFace = L"MS Shell Dlg"; | ||||||
|  | 	LPDLGTEMPLATEA lpdt; | ||||||
|  | 	LPDLGITEMTEMPLATEA lpdit; | ||||||
|  | 	LPCWSTR lpwszCaption; | ||||||
|  | 	LPWORD lpw; | ||||||
|  | 	LPWSTR lpwsz; | ||||||
|  | 	int i, ret, nchar; | ||||||
|  | 
 | ||||||
|  | 	lpdt = (LPDLGTEMPLATE)calloc(512 + nChoices * 256, 1); | ||||||
|  | 
 | ||||||
|  | 	// Set up a dialog window
 | ||||||
|  | 	lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | DS_MODALFRAME | DS_CENTER | DS_SHELLFONT; | ||||||
|  | 	lpdt->cdit = 2 + nChoices; | ||||||
|  | 	lpdt->x = 10; | ||||||
|  | 	lpdt->y = 10; | ||||||
|  | 	lpdt->cx = 300; | ||||||
|  | 	lpdt->cy = 100; | ||||||
|  | 
 | ||||||
|  | 	// https://msdn.microsoft.com/en-us/library/windows/desktop/ms645394.aspx:
 | ||||||
|  | 	// In a standard template for a dialog box, the DLGTEMPLATE structure is always immediately followed by
 | ||||||
|  | 	// three variable-length arrays that specify the menu, class, and title for the dialog box.
 | ||||||
|  | 	// When the DS_SETFONT style is specified, these arrays are also followed by a 16-bit value specifying
 | ||||||
|  | 	// point size and another variable-length array specifying a typeface name. Each array consists of one
 | ||||||
|  | 	// or more 16-bit elements. The menu, class, title, and font arrays must be aligned on WORD boundaries.
 | ||||||
|  | 	lpw = (LPWORD)(&lpdt[1]); | ||||||
|  | 	*lpw++ = 0;		// No menu
 | ||||||
|  | 	*lpw++ = 0;		// Default dialog class
 | ||||||
|  | 	lpwsz = (LPWSTR)lpw; | ||||||
|  | 	nchar = MultiByteToWideChar(CP_UTF8, 0, title, -1, lpwsz, 50); | ||||||
|  | 	lpw += nchar; | ||||||
|  | 
 | ||||||
|  | 	// Set point size and typeface name if required
 | ||||||
|  | 	if (lpdt->style & (DS_SETFONT | DS_SHELLFONT)) { | ||||||
|  | 		*lpw++ = 8; | ||||||
|  | 		for (lpwsz = (LPWSTR)lpw, lpwszCaption = lpwszTypeFace; (*lpwsz++ = *lpwszCaption++) != 0; ); | ||||||
|  | 		lpw = (LPWORD)lpwsz; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Add an OK button
 | ||||||
|  | 	lpw = lpwAlign(lpw); | ||||||
|  | 	lpdit = (LPDLGITEMTEMPLATE)lpw; | ||||||
|  | 	lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; | ||||||
|  | 	lpdit->x = 10; | ||||||
|  | 	lpdit->y = 70; | ||||||
|  | 	lpdit->cx = 50; | ||||||
|  | 	lpdit->cy = 14; | ||||||
|  | 	lpdit->id = IDOK; | ||||||
|  | 
 | ||||||
|  | 	lpw = (LPWORD)(&lpdit[1]); | ||||||
|  | 	*lpw++ = 0xFFFF; | ||||||
|  | 	*lpw++ = 0x0080;	// Button class
 | ||||||
|  | 
 | ||||||
|  | 	lpwsz = (LPWSTR)lpw; | ||||||
|  | 	nchar = MultiByteToWideChar(CP_UTF8, 0, "OK", -1, lpwsz, 50); | ||||||
|  | 	lpw += nchar; | ||||||
|  | 	*lpw++ = 0;		// No creation data
 | ||||||
|  | 
 | ||||||
|  | 					// Add a Cancel button
 | ||||||
|  | 	lpw = lpwAlign(lpw); | ||||||
|  | 	lpdit = (LPDLGITEMTEMPLATE)lpw; | ||||||
|  | 	lpdit->x = 90; | ||||||
|  | 	lpdit->y = 70; | ||||||
|  | 	lpdit->cx = 50; | ||||||
|  | 	lpdit->cy = 14; | ||||||
|  | 	lpdit->id = IDCANCEL; | ||||||
|  | 	lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON; | ||||||
|  | 
 | ||||||
|  | 	lpw = (LPWORD)(&lpdit[1]); | ||||||
|  | 	*lpw++ = 0xFFFF; | ||||||
|  | 	*lpw++ = 0x0080; | ||||||
|  | 
 | ||||||
|  | 	lpwsz = (LPWSTR)lpw; | ||||||
|  | 	nchar = MultiByteToWideChar(CP_UTF8, 0, lmprintf(MSG_007), -1, lpwsz, 50); | ||||||
|  | 	lpw += nchar; | ||||||
|  | 	*lpw++ = 0; | ||||||
|  | 
 | ||||||
|  | 	// Add radio buttons
 | ||||||
|  | 	for (i = 0; i < nChoices; i++) { | ||||||
|  | 		lpw = lpwAlign(lpw); | ||||||
|  | 		lpdit = (LPDLGITEMTEMPLATE)lpw; | ||||||
|  | 		lpdit->x = 10; | ||||||
|  | 		lpdit->y = 10 + 15 * i; | ||||||
|  | 		lpdit->cx = 40; | ||||||
|  | 		lpdit->cy = 20; | ||||||
|  | 		lpdit->id = ID_RADIO; | ||||||
|  | 		lpdit->style = WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | (i == 0 ? WS_GROUP : 0); | ||||||
|  | 
 | ||||||
|  | 		lpw = (LPWORD)(&lpdit[1]); | ||||||
|  | 		*lpw++ = 0xFFFF; | ||||||
|  | 		*lpw++ = 0x0080; | ||||||
|  | 
 | ||||||
|  | 		lpwsz = (LPWSTR)lpw; | ||||||
|  | 		nchar = MultiByteToWideChar(CP_UTF8, 0, szChoice[i], -1, lpwsz, 150); | ||||||
|  | 		lpw += nchar; | ||||||
|  | 		*lpw++ = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ret = (int)DialogBoxIndirect(hMainInstance, (LPDLGTEMPLATE)lpdt, hMainDialog, (DLGPROC)SelectionDynCallback); | ||||||
|  | 	free(lpdt); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
							
								
								
									
										53
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										53
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -93,6 +93,7 @@ PF_TYPE_DECL(WINAPI, BOOL, WIMSetTemporaryPath, (HANDLE, PWSTR)); | ||||||
| PF_TYPE_DECL(WINAPI, HANDLE, WIMLoadImage, (HANDLE, DWORD)); | PF_TYPE_DECL(WINAPI, HANDLE, WIMLoadImage, (HANDLE, DWORD)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMApplyImage, (HANDLE, PCWSTR, DWORD)); | PF_TYPE_DECL(WINAPI, BOOL, WIMApplyImage, (HANDLE, PCWSTR, DWORD)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMExtractImagePath, (HANDLE, PWSTR, PWSTR, DWORD)); | PF_TYPE_DECL(WINAPI, BOOL, WIMExtractImagePath, (HANDLE, PWSTR, PWSTR, DWORD)); | ||||||
|  | PF_TYPE_DECL(WINAPI, BOOL, WIMGetImageInformation, (HANDLE, PVOID, PDWORD)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMCloseHandle, (HANDLE)); | PF_TYPE_DECL(WINAPI, BOOL, WIMCloseHandle, (HANDLE)); | ||||||
| PF_TYPE_DECL(WINAPI, DWORD, WIMRegisterMessageCallback, (HANDLE, FARPROC, PVOID)); | PF_TYPE_DECL(WINAPI, DWORD, WIMRegisterMessageCallback, (HANDLE, FARPROC, PVOID)); | ||||||
| PF_TYPE_DECL(WINAPI, DWORD, WIMUnregisterMessageCallback, (HANDLE, FARPROC)); | PF_TYPE_DECL(WINAPI, DWORD, WIMUnregisterMessageCallback, (HANDLE, FARPROC)); | ||||||
|  | @ -345,6 +346,7 @@ uint8_t WimExtractCheck(void) | ||||||
| 	PF_INIT(WIMLoadImage, Wimgapi); | 	PF_INIT(WIMLoadImage, Wimgapi); | ||||||
| 	PF_INIT(WIMApplyImage, Wimgapi); | 	PF_INIT(WIMApplyImage, Wimgapi); | ||||||
| 	PF_INIT(WIMExtractImagePath, Wimgapi); | 	PF_INIT(WIMExtractImagePath, Wimgapi); | ||||||
|  | 	PF_INIT(WIMGetImageInformation, Wimgapi); | ||||||
| 	PF_INIT(WIMRegisterMessageCallback, Wimgapi); | 	PF_INIT(WIMRegisterMessageCallback, Wimgapi); | ||||||
| 	PF_INIT(WIMUnregisterMessageCallback, Wimgapi); | 	PF_INIT(WIMUnregisterMessageCallback, Wimgapi); | ||||||
| 	PF_INIT(WIMCloseHandle, Wimgapi); | 	PF_INIT(WIMCloseHandle, Wimgapi); | ||||||
|  | @ -368,16 +370,19 @@ uint8_t WimExtractCheck(void) | ||||||
| // Extract a file from a WIM image using wimgapi.dll (Windows 7 or later)
 | // Extract a file from a WIM image using wimgapi.dll (Windows 7 or later)
 | ||||||
| // NB: if you want progress from a WIM callback, you must run the WIM API call in its own thread
 | // NB: if you want progress from a WIM callback, you must run the WIM API call in its own thread
 | ||||||
| // (which we don't do here) as it won't work otherwise. Thanks go to Erwan for figuring this out!
 | // (which we don't do here) as it won't work otherwise. Thanks go to Erwan for figuring this out!
 | ||||||
| static BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst) | BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst) | ||||||
| { | { | ||||||
|  | 	static char* index_name = "[1].xml"; | ||||||
| 	BOOL r = FALSE; | 	BOOL r = FALSE; | ||||||
| 	DWORD dw = 0; | 	DWORD dw = 0; | ||||||
| 	HANDLE hWim = NULL; | 	HANDLE hWim = NULL; | ||||||
| 	HANDLE hImage = NULL; | 	HANDLE hImage = NULL; | ||||||
|  | 	HANDLE hFile = NULL; | ||||||
| 	wchar_t wtemp[MAX_PATH] = {0}; | 	wchar_t wtemp[MAX_PATH] = {0}; | ||||||
| 	wchar_t* wimage = utf8_to_wchar(image); | 	wchar_t* wimage = utf8_to_wchar(image); | ||||||
| 	wchar_t* wsrc = utf8_to_wchar(src); | 	wchar_t* wsrc = utf8_to_wchar(src); | ||||||
| 	wchar_t* wdst = utf8_to_wchar(dst); | 	wchar_t* wdst = utf8_to_wchar(dst); | ||||||
|  | 	char* wim_info; | ||||||
| 
 | 
 | ||||||
| 	PF_INIT_OR_OUT(WIMCreateFile, Wimgapi); | 	PF_INIT_OR_OUT(WIMCreateFile, Wimgapi); | ||||||
| 	PF_INIT_OR_OUT(WIMSetTemporaryPath, Wimgapi); | 	PF_INIT_OR_OUT(WIMSetTemporaryPath, Wimgapi); | ||||||
|  | @ -402,19 +407,30 @@ static BOOL WimExtractFile_API(const char* image, int index, const char* src, co | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	hImage = pfWIMLoadImage(hWim, (DWORD)index); |  | ||||||
| 	if (hImage == NULL) { |  | ||||||
| 		uprintf("  Could not set index: %s", WindowsErrorString()); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	uprintf("Extracting: %s (From %s)", dst, src); | 	uprintf("Extracting: %s (From %s)", dst, src); | ||||||
| 	if (!pfWIMExtractImagePath(hImage, wsrc, wdst, 0)) { | 	if (safe_strcmp(src, index_name) == 0) { | ||||||
| 		uprintf("  Could not extract file: %s", WindowsErrorString()); | 		if (!pfWIMGetImageInformation(hWim, &wim_info, &dw)) { | ||||||
| 		goto out; | 			uprintf("  Could not access WIM info: %s", WindowsErrorString()); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 		hFile = CreateFileW(wdst, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, | ||||||
|  | 			NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | ||||||
|  | 		if ((hFile == INVALID_HANDLE_VALUE) || (!WriteFile(hFile, wim_info, dw, &dw, NULL))) { | ||||||
|  | 			uprintf("  Could not extract file: %s", WindowsErrorString()); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		hImage = pfWIMLoadImage(hWim, (DWORD)index); | ||||||
|  | 		if (hImage == NULL) { | ||||||
|  | 			uprintf("  Could not set index: %s", WindowsErrorString()); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 		if (!pfWIMExtractImagePath(hImage, wsrc, wdst, 0)) { | ||||||
|  | 			uprintf("  Could not extract file: %s", WindowsErrorString()); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	r = TRUE; | 	r = TRUE; | ||||||
| 	UpdateProgress(OP_FINALIZE, -1.0f); |  | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	if ((hImage != NULL) || (hWim != NULL)) { | 	if ((hImage != NULL) || (hWim != NULL)) { | ||||||
|  | @ -422,6 +438,7 @@ out: | ||||||
| 		if (hImage != NULL) pfWIMCloseHandle(hImage); | 		if (hImage != NULL) pfWIMCloseHandle(hImage); | ||||||
| 		if (hWim != NULL) pfWIMCloseHandle(hWim); | 		if (hWim != NULL) pfWIMCloseHandle(hWim); | ||||||
| 	} | 	} | ||||||
|  | 	safe_closehandle(hFile); | ||||||
| 	safe_free(wimage); | 	safe_free(wimage); | ||||||
| 	safe_free(wsrc); | 	safe_free(wsrc); | ||||||
| 	safe_free(wdst); | 	safe_free(wdst); | ||||||
|  | @ -429,7 +446,7 @@ out: | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Extract a file from a WIM image using 7-Zip
 | // Extract a file from a WIM image using 7-Zip
 | ||||||
| static BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst) | BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst) | ||||||
| { | { | ||||||
| 	int n; | 	int n; | ||||||
| 	size_t i; | 	size_t i; | ||||||
|  | @ -455,10 +472,7 @@ static BOOL WimExtractFile_7z(const char* image, int index, const char* src, con | ||||||
| 	// to issue 2 passes. See github issue #680.
 | 	// to issue 2 passes. See github issue #680.
 | ||||||
| 	for (n = 0; n < 2; n++) { | 	for (n = 0; n < 2; n++) { | ||||||
| 		safe_strcpy(tmpdst, sizeof(tmpdst), dst); | 		safe_strcpy(tmpdst, sizeof(tmpdst), dst); | ||||||
| 		for (i = strlen(tmpdst) - 1; i > 0; i--) { | 		for (i = strlen(tmpdst) - 1; (i > 0) && (tmpdst[i] != '\\') && (tmpdst[i] != '/'); i--); | ||||||
| 			if (tmpdst[i] == '\\') |  | ||||||
| 				break; |  | ||||||
| 		} |  | ||||||
| 		tmpdst[i] = 0; | 		tmpdst[i] = 0; | ||||||
| 
 | 
 | ||||||
| 		safe_sprintf(cmdline, sizeof(cmdline), "\"%s\" -y e \"%s\" %s%s", sevenzip_path, | 		safe_sprintf(cmdline, sizeof(cmdline), "\"%s\" -y e \"%s\" %s%s", sevenzip_path, | ||||||
|  | @ -468,7 +482,10 @@ static BOOL WimExtractFile_7z(const char* image, int index, const char* src, con | ||||||
| 			return FALSE; | 			return FALSE; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		safe_strcat(tmpdst, sizeof(tmpdst), "\\bootmgfw.efi"); | 		for (i = safe_strlen(src); (i > 0) && (src[i] != '\\') && (src[i] != '/'); i--); | ||||||
|  | 		if (i == 0) | ||||||
|  | 			safe_strcat(tmpdst, sizeof(tmpdst), "\\"); | ||||||
|  | 		safe_strcat(tmpdst, sizeof(tmpdst), &src[i]); | ||||||
| 		if (_access(tmpdst, 0) == 0) | 		if (_access(tmpdst, 0) == 0) | ||||||
| 			// File was extracted => move on
 | 			// File was extracted => move on
 | ||||||
| 			break; | 			break; | ||||||
|  | @ -481,7 +498,7 @@ static BOOL WimExtractFile_7z(const char* image, int index, const char* src, con | ||||||
| 
 | 
 | ||||||
| 	// coverity[toctou]
 | 	// coverity[toctou]
 | ||||||
| 	if (rename(tmpdst, dst) != 0) { | 	if (rename(tmpdst, dst) != 0) { | ||||||
| 		uprintf("  Could not rename %s to %s", tmpdst, dst); | 		uprintf("  Could not rename %s to %s: errno %d", tmpdst, dst, errno); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue