mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[ui] improve progress report when disabling Windows 11 installation restrictions
* Also fix Image Options content being lost when switching language.
This commit is contained in:
		
							parent
							
								
									b043db33e6
								
							
						
					
					
						commit
						957ec183c9
					
				
					 11 changed files with 221 additions and 133 deletions
				
			
		|  | @ -3,9 +3,9 @@ o Version 3.16 (2021.10.??) | ||||||
|     Fix BIOS boot support for Arch derivatives |     Fix BIOS boot support for Arch derivatives | ||||||
|     Fix removal of some boot entries for Ubuntu derivatives |     Fix removal of some boot entries for Ubuntu derivatives | ||||||
|     Fix log not being saved on exit |     Fix log not being saved on exit | ||||||
|  |     Add Windows 11 "Extended" installation support (Disables TPM/Secure Boot/RAM requirements) | ||||||
|     Add UEFI Shell ISO downloads |     Add UEFI Shell ISO downloads | ||||||
|     Add support for Intel NUC card readers |     Add support for Intel NUC card readers | ||||||
|     Add Windows 11 extended installation support (disables TPM or Secure Boot requirement) |  | ||||||
|     Improve Windows 11 support |     Improve Windows 11 support | ||||||
|     Improve Windows version reporting |     Improve Windows version reporting | ||||||
|     Speed up clearing of MBR/GPT |     Speed up clearing of MBR/GPT | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ | ||||||
|   <Identity |   <Identity | ||||||
|     Name="19453.net.Rufus" |     Name="19453.net.Rufus" | ||||||
|     Publisher="CN=7AC86D13-3E5A-491A-ADD5-80095C212740" |     Publisher="CN=7AC86D13-3E5A-491A-ADD5-80095C212740" | ||||||
|     Version="3.16.1832.0" /> |     Version="3.16.1833.0" /> | ||||||
| 
 | 
 | ||||||
|   <Properties> |   <Properties> | ||||||
|     <DisplayName>Rufus</DisplayName> |     <DisplayName>Rufus</DisplayName> | ||||||
|  |  | ||||||
|  | @ -5,6 +5,12 @@ To edit a translation, please make sure to follow: | ||||||
| https://github.com/pbatard/rufus/wiki/Localization#Editing_an_existing_translation | https://github.com/pbatard/rufus/wiki/Localization#Editing_an_existing_translation | ||||||
| Or simply download https://rufus-web.akeo.ie/locale/pollock.exe and follow its directions. | Or simply download https://rufus-web.akeo.ie/locale/pollock.exe and follow its directions. | ||||||
| 
 | 
 | ||||||
|  | o v3.?? (????.??.??) | ||||||
|  |   - *UPDATED*  MSG_305 Reworked the message to mention the new Windows 11 Extended option | ||||||
|  |   - *NEW*      MSG_322 "Standard Windows 11 Installation (TPM 2.0, Secure Boot, 8GB+ RAM)" | ||||||
|  |   - *NEW*      MSG_323 "Extended Windows 11 Installation (no TPM/no Secure Boot/8GB- RAM)" | ||||||
|  |   - *NEW*      MSG_324 "Removing Windows 11 installation restrictions: %s" | ||||||
|  | 
 | ||||||
| o v3.14 (2021.03.31) | o v3.14 (2021.03.31) | ||||||
|   - *UPDATED*  MSG_068 "Error while partitioning drive." -> "Could not partition drive." |   - *UPDATED*  MSG_068 "Error while partitioning drive." -> "Could not partition drive." | ||||||
|   - *UPDATED*  MSG_274 "IsoHybrid image detected" -> "%s image detected" |   - *UPDATED*  MSG_274 "IsoHybrid image detected" -> "%s image detected" | ||||||
|  |  | ||||||
|  | @ -559,9 +559,10 @@ t MSG_301 "Show application settings" | ||||||
| t MSG_302 "Show information about this application" | t MSG_302 "Show information about this application" | ||||||
| t MSG_303 "Show the log" | t MSG_303 "Show the log" | ||||||
| t MSG_304 "Create a disk image of the selected device" | t MSG_304 "Create a disk image of the selected device" | ||||||
| t MSG_305 "Use this option to indicate if you want to run Windows directly from this drive (Windows To Go) or if you " | t MSG_305 "Use this option to indicate if you plan to install Windows to a different disk, or if you want to run Windows " | ||||||
| 	"want to install Windows to a different disk.\r\nIn 'Extended Windows 11 Installation' mode, Rufus patches the " | 	"directly from this drive (Windows To Go).\r\nIn 'Extended Windows 11 Installation' mode, Rufus will patch the " | ||||||
| 	"media so that Windows 11 can be installed on platforms that don't meet the TPM 2.0 or Secure Boot requirements." | 	"media so that Windows 11 can be installed on platforms that don't meet the TPM 2.0, Secure Boot or minimum RAM " | ||||||
|  | 	"requirements." | ||||||
| # You can see this status message by pressing <Ctrl>-<Alt>-<Z> and then selecting START. | # You can see this status message by pressing <Ctrl>-<Alt>-<Z> and then selecting START. | ||||||
| # It's the same as MSG_286 but with a process that *may* be faster, hence the name. | # It's the same as MSG_286 but with a process that *may* be faster, hence the name. | ||||||
| t MSG_306 "Fast-zeroing drive: %s" | t MSG_306 "Fast-zeroing drive: %s" | ||||||
|  | @ -583,9 +584,9 @@ t MSG_319 "Ignore Boot Marker" | ||||||
| t MSG_320 "Refreshing partition layout (%s)..." | t MSG_320 "Refreshing partition layout (%s)..." | ||||||
| t MSG_321 "The image you have selected is an ISOHybrid, but its creators have not made it compatible with ISO/File " | t MSG_321 "The image you have selected is an ISOHybrid, but its creators have not made it compatible with ISO/File " | ||||||
| 	"copy mode.\nAs a result, DD image writing mode will be enforced." | 	"copy mode.\nAs a result, DD image writing mode will be enforced." | ||||||
| t MSG_322 "Standard Windows 11 Installation (TPM 2.0 / Secure Boot / 8GB+ RAM)" | t MSG_322 "Standard Windows 11 Installation (TPM 2.0, Secure Boot, 8GB+ RAM)" | ||||||
| t MSG_323 "Extended Windows 11 Installation (no TPM/no Secure Boot/8GB- RAM)" | t MSG_323 "Extended Windows 11 Installation (no TPM/no Secure Boot/8GB- RAM)" | ||||||
| t MSG_324 "Removing Windows 11 installation restrictions (%s)" | t MSG_324 "Removing Windows 11 installation restrictions: %s" | ||||||
| 
 | 
 | ||||||
| ######################################################################### | ######################################################################### | ||||||
| l "ar-SA" "Arabic (العربية)" 0x0401, 0x0801, 0x0c01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001 | l "ar-SA" "Arabic (العربية)" 0x0401, 0x0801, 0x0c01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001 | ||||||
|  |  | ||||||
|  | @ -1452,7 +1452,7 @@ BOOL RemoveWindows11Restrictions(char drive_letter) | ||||||
| 
 | 
 | ||||||
| 	boot_wim_path[0] = drive_letter; | 	boot_wim_path[0] = drive_letter; | ||||||
| 
 | 
 | ||||||
| 	PrintInfo(0, MSG_324, lmprintf(MSG_307)); | 	UpdateProgressWithInfoForce(OP_PATCH, MSG_324, 0, PATCH_PROGRESS_TOTAL); | ||||||
| 	uprintf("Mounting '%s'...", boot_wim_path); | 	uprintf("Mounting '%s'...", boot_wim_path); | ||||||
| 
 | 
 | ||||||
| 	mount_path = WimMountImage(boot_wim_path, wim_index); | 	mount_path = WimMountImage(boot_wim_path, wim_index); | ||||||
|  | @ -1462,6 +1462,7 @@ BOOL RemoveWindows11Restrictions(char drive_letter) | ||||||
| 	static_sprintf(path, "%s\\Windows\\System32\\config\\SYSTEM", mount_path); | 	static_sprintf(path, "%s\\Windows\\System32\\config\\SYSTEM", mount_path); | ||||||
| 	if (!MountRegistryHive(HKEY_LOCAL_MACHINE, offline_hive_name, path)) | 	if (!MountRegistryHive(HKEY_LOCAL_MACHINE, offline_hive_name, path)) | ||||||
| 		goto out; | 		goto out; | ||||||
|  | 	UpdateProgressWithInfoForce(OP_PATCH, MSG_324, 102, PATCH_PROGRESS_TOTAL); | ||||||
| 	is_hive_mounted = TRUE; | 	is_hive_mounted = TRUE; | ||||||
| 
 | 
 | ||||||
| 	static_sprintf(key_path, "%s\\Setup", offline_hive_name); | 	static_sprintf(key_path, "%s\\Setup", offline_hive_name); | ||||||
|  | @ -1490,6 +1491,7 @@ BOOL RemoveWindows11Restrictions(char drive_letter) | ||||||
| 		} | 		} | ||||||
| 		uprintf("Created 'HKLM\\SYSTEM\\Setup\\LabConfig\\%s' registry key", key_name[i]); | 		uprintf("Created 'HKLM\\SYSTEM\\Setup\\LabConfig\\%s' registry key", key_name[i]); | ||||||
| 	} | 	} | ||||||
|  | 	UpdateProgressWithInfoForce(OP_PATCH, MSG_324, 103, PATCH_PROGRESS_TOTAL); | ||||||
| 	r = TRUE; | 	r = TRUE; | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
|  | @ -1497,12 +1499,15 @@ out: | ||||||
| 		RegCloseKey(hSubKey); | 		RegCloseKey(hSubKey); | ||||||
| 	if (hKey != NULL) | 	if (hKey != NULL) | ||||||
| 		RegCloseKey(hKey); | 		RegCloseKey(hKey); | ||||||
| 	if (is_hive_mounted) | 	if (is_hive_mounted) { | ||||||
| 		UnmountRegistryHive(HKEY_LOCAL_MACHINE, offline_hive_name); | 		UnmountRegistryHive(HKEY_LOCAL_MACHINE, offline_hive_name); | ||||||
|  | 		UpdateProgressWithInfoForce(OP_PATCH, MSG_324, 104, PATCH_PROGRESS_TOTAL); | ||||||
|  | 	} | ||||||
| 	if (mount_path) { | 	if (mount_path) { | ||||||
| 		uprintf("Unmounting '%s'...", boot_wim_path, wim_index); | 		uprintf("Unmounting '%s'...", boot_wim_path, wim_index); | ||||||
| 		WimUnmountImage(boot_wim_path, wim_index); | 		WimUnmountImage(boot_wim_path, wim_index); | ||||||
| 	} | 	} | ||||||
|  | 	UpdateProgressWithInfo(OP_PATCH, MSG_324, PATCH_PROGRESS_TOTAL, PATCH_PROGRESS_TOTAL); | ||||||
| 	free(mount_path); | 	free(mount_path); | ||||||
| 	return r; | 	return r; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2707,6 +2707,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 		InitDialog(hDlg); | 		InitDialog(hDlg); | ||||||
| 		GetDevices(0); | 		GetDevices(0); | ||||||
| 		EnableControls(TRUE, FALSE); | 		EnableControls(TRUE, FALSE); | ||||||
|  | 		UpdateImage(FALSE); | ||||||
| 		// The AppStore version does not need the internal check for updates
 | 		// The AppStore version does not need the internal check for updates
 | ||||||
| 		if (!appstore_version) | 		if (!appstore_version) | ||||||
| 			CheckForUpdates(FALSE); | 			CheckForUpdates(FALSE); | ||||||
|  |  | ||||||
|  | @ -69,6 +69,7 @@ | ||||||
| #define MAX_SIZE_SUFFIXES           6			// bytes, KB, MB, GB, TB, PB
 | #define MAX_SIZE_SUFFIXES           6			// bytes, KB, MB, GB, TB, PB
 | ||||||
| #define MAX_CLUSTER_SIZES           18 | #define MAX_CLUSTER_SIZES           18 | ||||||
| #define MAX_PROGRESS                0xFFFF | #define MAX_PROGRESS                0xFFFF | ||||||
|  | #define PATCH_PROGRESS_TOTAL        207 | ||||||
| #define MAX_LOG_SIZE                0x7FFFFFFE | #define MAX_LOG_SIZE                0x7FFFFFFE | ||||||
| #define MAX_REFRESH                 25			// How long we should wait to refresh UI elements (in ms)
 | #define MAX_REFRESH                 25			// How long we should wait to refresh UI elements (in ms)
 | ||||||
| #define MAX_GUID_STRING_LENGTH      40 | #define MAX_GUID_STRING_LENGTH      40 | ||||||
|  | @ -251,6 +252,7 @@ enum action_type { | ||||||
| 	OP_CREATE_FS, | 	OP_CREATE_FS, | ||||||
| 	OP_FIX_MBR, | 	OP_FIX_MBR, | ||||||
| 	OP_FILE_COPY, | 	OP_FILE_COPY, | ||||||
|  | 	OP_PATCH, | ||||||
| 	OP_FINALIZE, | 	OP_FINALIZE, | ||||||
| 	OP_MAX | 	OP_MAX | ||||||
| }; | }; | ||||||
|  | @ -516,7 +518,9 @@ extern void PrintStatusInfo(BOOL info, BOOL debug, unsigned int duration, int ms | ||||||
| #define PrintInfo(...) PrintStatusInfo(TRUE, FALSE, __VA_ARGS__) | #define PrintInfo(...) PrintStatusInfo(TRUE, FALSE, __VA_ARGS__) | ||||||
| #define PrintInfoDebug(...) PrintStatusInfo(TRUE, TRUE, __VA_ARGS__) | #define PrintInfoDebug(...) PrintStatusInfo(TRUE, TRUE, __VA_ARGS__) | ||||||
| extern void UpdateProgress(int op, float percent); | extern void UpdateProgress(int op, float percent); | ||||||
| extern void UpdateProgressWithInfo(int op, int msg, uint64_t processed, uint64_t total); | extern void _UpdateProgressWithInfo(int op, int msg, uint64_t processed, uint64_t total, BOOL force); | ||||||
|  | #define UpdateProgressWithInfo(op, msg, processed, total) _UpdateProgressWithInfo(op, msg, processed, total, FALSE) | ||||||
|  | #define UpdateProgressWithInfoForce(op, msg, processed, total) _UpdateProgressWithInfo(op, msg, processed, total, TRUE) | ||||||
| #define UpdateProgressWithInfoInit(hProgressDialog, bNoAltMode) UpdateProgressWithInfo(OP_INIT, (int)bNoAltMode, (uint64_t)(uintptr_t)hProgressDialog, 0); | #define UpdateProgressWithInfoInit(hProgressDialog, bNoAltMode) UpdateProgressWithInfo(OP_INIT, (int)bNoAltMode, (uint64_t)(uintptr_t)hProgressDialog, 0); | ||||||
| extern const char* StrError(DWORD error_code, BOOL use_default_locale); | extern const char* StrError(DWORD error_code, BOOL use_default_locale); | ||||||
| extern char* GuidToString(const GUID* guid); | extern char* GuidToString(const GUID* guid); | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | ||||||
| IDD_DIALOG DIALOGEX 12, 12, 232, 326 | IDD_DIALOG DIALOGEX 12, 12, 232, 326 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_ACCEPTFILES | EXSTYLE WS_EX_ACCEPTFILES | ||||||
| CAPTION "Rufus 3.16.1832" | CAPTION "Rufus 3.16.1833" | ||||||
| FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | ||||||
| BEGIN | BEGIN | ||||||
|     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP |     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP | ||||||
|  | @ -395,8 +395,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 3,16,1832,0 |  FILEVERSION 3,16,1833,0 | ||||||
|  PRODUCTVERSION 3,16,1832,0 |  PRODUCTVERSION 3,16,1833,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -414,13 +414,13 @@ BEGIN | ||||||
|             VALUE "Comments", "https://rufus.ie" |             VALUE "Comments", "https://rufus.ie" | ||||||
|             VALUE "CompanyName", "Akeo Consulting" |             VALUE "CompanyName", "Akeo Consulting" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "3.16.1832" |             VALUE "FileVersion", "3.16.1833" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2021 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2021 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" |             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" | ||||||
|             VALUE "OriginalFilename", "rufus-3.16.exe" |             VALUE "OriginalFilename", "rufus-3.16.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "3.16.1832" |             VALUE "ProductVersion", "3.16.1833" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								src/stdio.c
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								src/stdio.c
									
										
									
									
									
								
							|  | @ -37,6 +37,8 @@ | ||||||
| #include "msapi_utf8.h" | #include "msapi_utf8.h" | ||||||
| #include "localization.h" | #include "localization.h" | ||||||
| 
 | 
 | ||||||
|  | #define FACILITY_WIM 322 | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Globals |  * Globals | ||||||
|  */ |  */ | ||||||
|  | @ -627,6 +629,16 @@ static const char *GetVdsError(DWORD error_code) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const char* GetVimError(DWORD error_code) | ||||||
|  | { | ||||||
|  | 	switch (error_code) { | ||||||
|  | 	case 0xC1420127: | ||||||
|  | 		return "The specified image in the specified wim is already mounted for read and write access."; | ||||||
|  | 	default: | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Convert a windows error to human readable string
 | // Convert a windows error to human readable string
 | ||||||
| const char *WindowsErrorString(void) | const char *WindowsErrorString(void) | ||||||
| { | { | ||||||
|  | @ -637,11 +649,14 @@ const char *WindowsErrorString(void) | ||||||
| 
 | 
 | ||||||
| 	error_code = GetLastError(); | 	error_code = GetLastError(); | ||||||
| 	// Check for VDS error codes
 | 	// Check for VDS error codes
 | ||||||
| 	if ((SCODE_FACILITY(error_code) == FACILITY_ITF) && (GetVdsError(error_code) != NULL)) { | 	if ((HRESULT_FACILITY(error_code) == FACILITY_ITF) && (GetVdsError(error_code) != NULL)) { | ||||||
| 		static_sprintf(err_string, "[0x%08lX] %s", error_code, GetVdsError(error_code)); | 		static_sprintf(err_string, "[0x%08lX] %s", error_code, GetVdsError(error_code)); | ||||||
| 		return err_string; | 		return err_string; | ||||||
| 	} | 	} | ||||||
| 
 | 	if ((HRESULT_FACILITY(error_code) == FACILITY_WIM) && (GetVimError(error_code) != NULL)) { | ||||||
|  | 		static_sprintf(err_string, "[0x%08lX] %s", error_code, GetVimError(error_code)); | ||||||
|  | 		return err_string; | ||||||
|  | 	} | ||||||
| 	static_sprintf(err_string, "[0x%08lX] ", error_code); | 	static_sprintf(err_string, "[0x%08lX] ", error_code); | ||||||
| 	presize = (DWORD)strlen(err_string); | 	presize = (DWORD)strlen(err_string); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/ui.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/ui.c
									
										
									
									
									
								
							|  | @ -1181,6 +1181,8 @@ void InitProgress(BOOL bOnlyFormat) | ||||||
| 				break; | 				break; | ||||||
| 			case BT_IMAGE: | 			case BT_IMAGE: | ||||||
| 				nb_slots[OP_FILE_COPY] = (img_report.is_iso || img_report.is_windows_img) ? -1 : 0; | 				nb_slots[OP_FILE_COPY] = (img_report.is_iso || img_report.is_windows_img) ? -1 : 0; | ||||||
|  | 				if (HAS_WINDOWS(img_report) && ComboBox_GetCurItemData(hImageOption) == IMOP_WIN_EXTENDED) | ||||||
|  | 					nb_slots[OP_PATCH] = -1; | ||||||
| 				break; | 				break; | ||||||
| 			default: | 			default: | ||||||
| 				nb_slots[OP_FILE_COPY] = 2 + 1; | 				nb_slots[OP_FILE_COPY] = 2 + 1; | ||||||
|  | @ -1387,7 +1389,7 @@ static void bar_update(struct bar_progress* bp, uint64_t howmuch, uint64_t dltim | ||||||
| // display percentage completed, rate of transfer and estimated remaining duration.
 | // display percentage completed, rate of transfer and estimated remaining duration.
 | ||||||
| // During init (op = OP_INIT) an optional HWND can be passed on which to look for
 | // During init (op = OP_INIT) an optional HWND can be passed on which to look for
 | ||||||
| // a progress bar. Part of the code (eta, speed) comes from GNU wget.
 | // a progress bar. Part of the code (eta, speed) comes from GNU wget.
 | ||||||
| void UpdateProgressWithInfo(int op, int msg, uint64_t processed, uint64_t total) | void _UpdateProgressWithInfo(int op, int msg, uint64_t processed, uint64_t total, BOOL force) | ||||||
| { | { | ||||||
| 	static int last_update_progress_type = UPT_PERCENT; | 	static int last_update_progress_type = UPT_PERCENT; | ||||||
| 	static struct bar_progress bp = { 0 }; | 	static struct bar_progress bp = { 0 }; | ||||||
|  | @ -1486,7 +1488,7 @@ void UpdateProgressWithInfo(int op, int msg, uint64_t processed, uint64_t total) | ||||||
| 			static_sprintf(msg_data, "%0.1f%%", percent); | 			static_sprintf(msg_data, "%0.1f%%", percent); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		if ((bp.count == bp.total_length) || (current_time > last_refresh + MAX_REFRESH)) { | 		if ((force) || (bp.count == bp.total_length) || (current_time > last_refresh + MAX_REFRESH)) { | ||||||
| 			if (op < 0) { | 			if (op < 0) { | ||||||
| 				SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS * percent / 100.0f), 0); | 				SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS * percent / 100.0f), 0); | ||||||
| 				if (op == OP_NOOP_WITH_TASKBAR) | 				if (op == OP_NOOP_WITH_TASKBAR) | ||||||
|  | @ -1494,8 +1496,8 @@ void UpdateProgressWithInfo(int op, int msg, uint64_t processed, uint64_t total) | ||||||
| 			} else { | 			} else { | ||||||
| 				UpdateProgress(op, (float)percent); | 				UpdateProgress(op, (float)percent); | ||||||
| 			} | 			} | ||||||
| 			if ((msg >= 0) && ((current_time > bp.last_screen_update + SCREEN_REFRESH_INTERVAL) || | 			if ((force) || ((msg >= 0) && ((current_time > bp.last_screen_update + SCREEN_REFRESH_INTERVAL) || | ||||||
| 				(last_update_progress_type != update_progress_type) || (bp.count == bp.total_length))) { | 				(last_update_progress_type != update_progress_type) || (bp.count == bp.total_length)))) { | ||||||
| 				PrintInfo(0, msg, msg_data); | 				PrintInfo(0, msg, msg_data); | ||||||
| 				bp.last_screen_update = current_time; | 				bp.last_screen_update = current_time; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
							
								
								
									
										276
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										276
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -57,6 +57,47 @@ | ||||||
| 
 | 
 | ||||||
| #define SECONDS_SINCE_JAN_1ST_2000			946684800 | #define SECONDS_SINCE_JAN_1ST_2000			946684800 | ||||||
| 
 | 
 | ||||||
|  | #define INVALID_CALLBACK_VALUE				0xFFFFFFFF | ||||||
|  | 
 | ||||||
|  | #define WIM_FLAG_RESERVED					0x00000001 | ||||||
|  | #define WIM_FLAG_VERIFY						0x00000002 | ||||||
|  | #define WIM_FLAG_INDEX						0x00000004 | ||||||
|  | #define WIM_FLAG_NO_APPLY					0x00000008 | ||||||
|  | #define WIM_FLAG_NO_DIRACL					0x00000010 | ||||||
|  | #define WIM_FLAG_NO_FILEACL					0x00000020 | ||||||
|  | #define WIM_FLAG_SHARE_WRITE				0x00000040 | ||||||
|  | #define WIM_FLAG_FILEINFO					0x00000080 | ||||||
|  | #define WIM_FLAG_NO_RP_FIX					0x00000100 | ||||||
|  | 
 | ||||||
|  | // Bitmask for the kind of progress we want to report in the WIM progress callback
 | ||||||
|  | #define WIM_REPORT_PROGRESS					0x00000001 | ||||||
|  | #define WIM_REPORT_PROCESS					0x00000002 | ||||||
|  | #define WIM_REPORT_FILEINFO					0x00000004 | ||||||
|  | 
 | ||||||
|  | // From https://docs.microsoft.com/en-us/previous-versions/msdn10/dd834960(v=msdn.10)
 | ||||||
|  | // as well as https://msfn.org/board/topic/150700-wimgapi-wimmountimage-progressbar/
 | ||||||
|  | enum WIMMessage { | ||||||
|  | 	WIM_MSG = WM_APP + 0x1476, | ||||||
|  | 	WIM_MSG_TEXT, | ||||||
|  | 	WIM_MSG_PROGRESS,	// Indicates an update in the progress of an image application.
 | ||||||
|  | 	WIM_MSG_PROCESS,	// Enables the caller to prevent a file or a directory from being captured or applied.
 | ||||||
|  | 	WIM_MSG_SCANNING,	// Indicates that volume information is being gathered during an image capture.
 | ||||||
|  | 	WIM_MSG_SETRANGE,	// Indicates the number of files that will be captured or applied.
 | ||||||
|  | 	WIM_MSG_SETPOS,		// Indicates the number of files that have been captured or applied.
 | ||||||
|  | 	WIM_MSG_STEPIT,		// Indicates that a file has been either captured or applied.
 | ||||||
|  | 	WIM_MSG_COMPRESS,	// Enables the caller to prevent a file resource from being compressed during a capture.
 | ||||||
|  | 	WIM_MSG_ERROR,		// Alerts the caller that an error has occurred while capturing or applying an image.
 | ||||||
|  | 	WIM_MSG_ALIGNMENT,	// Enables the caller to align a file resource on a particular alignment boundary.
 | ||||||
|  | 	WIM_MSG_RETRY,		// Sent when the file is being reapplied because of a network timeout.
 | ||||||
|  | 	WIM_MSG_SPLIT,		// Enables the caller to align a file resource on a particular alignment boundary.
 | ||||||
|  | 	WIM_MSG_FILEINFO,	// Used in conjunction with WimApplyImages()'s WIM_FLAG_FILEINFO flag to provide detailed file info.
 | ||||||
|  | 	WIM_MSG_INFO,		// Sent when an info message is available.
 | ||||||
|  | 	WIM_MSG_WARNING,	// Sent when a warning message is available.
 | ||||||
|  | 	WIM_MSG_CHK_PROCESS, | ||||||
|  | 	WIM_MSG_SUCCESS     = 0, | ||||||
|  | 	WIM_MSG_ABORT_IMAGE = -1 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * VHD Fixed HD footer (Big Endian) |  * 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
 |  * http://download.microsoft.com/download/f/f/e/ffef50a5-07dd-4cf8-aaa3-442c0673a029/Virtual%20Hard%20Disk%20Format%20Spec_10_18_06.doc
 | ||||||
|  | @ -114,13 +155,15 @@ extern int default_thread_priority; | ||||||
| extern BOOL ignore_boot_marker; | extern BOOL ignore_boot_marker; | ||||||
| 
 | 
 | ||||||
| static uint8_t wim_flags = 0; | static uint8_t wim_flags = 0; | ||||||
|  | static uint32_t progress_report_mask; | ||||||
|  | static uint64_t progress_offset = 0, progress_total = 100; | ||||||
| static wchar_t wmount_path[MAX_PATH] = { 0 }, wmount_track[MAX_PATH] = { 0 }; | static wchar_t wmount_path[MAX_PATH] = { 0 }, wmount_track[MAX_PATH] = { 0 }; | ||||||
| static char sevenzip_path[MAX_PATH]; | static char sevenzip_path[MAX_PATH]; | ||||||
| static const char conectix_str[] = VHD_FOOTER_COOKIE; | static const char conectix_str[] = VHD_FOOTER_COOKIE; | ||||||
| static BOOL count_files; | static BOOL count_files, use_msg_progress = FALSE; | ||||||
| // Apply/Mount image functionality
 | // Apply/Mount image functionality
 | ||||||
| static const char *_image, *_dst; | static const char *_image, *_dst; | ||||||
| static int _index; | static int _index, progress_op = OP_FILE_COPY, progress_msg = MSG_267; | ||||||
| 
 | 
 | ||||||
| static BOOL Get7ZipPath(void) | static BOOL Get7ZipPath(void) | ||||||
| { | { | ||||||
|  | @ -355,6 +398,79 @@ out: | ||||||
| 	return is_bootable_img; | 	return is_bootable_img; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // WIM operations progress callback
 | ||||||
|  | DWORD WINAPI WimProgressCallback(DWORD dwMsgId, WPARAM wParam, LPARAM lParam, PVOID pvIgnored) | ||||||
|  | { | ||||||
|  | 	PBOOL pbCancel = NULL; | ||||||
|  | 	PWIN32_FIND_DATA pFileData; | ||||||
|  | 	const char* level = NULL; | ||||||
|  | 	uint64_t size; | ||||||
|  | 
 | ||||||
|  | 	switch (dwMsgId) { | ||||||
|  | 	case WIM_MSG_PROGRESS: | ||||||
|  | 		// The default WIM progress is useless for apply (freezes at 95%, which is usually when
 | ||||||
|  | 		// only half the files have been processed), so we only use it for mounting/unmounting.
 | ||||||
|  | 		if (!(progress_report_mask & WIM_REPORT_PROGRESS)) | ||||||
|  | 			break; | ||||||
|  | 		UpdateProgressWithInfo(progress_op, progress_msg, progress_offset + wParam, progress_total); | ||||||
|  | 		break; | ||||||
|  | 	case WIM_MSG_PROCESS: | ||||||
|  | 		if (!(progress_report_mask & WIM_REPORT_PROCESS)) | ||||||
|  | 			break; | ||||||
|  | 		// The amount of files processed is overwhelming (16k+ for a typical image),
 | ||||||
|  | 		// and trying to display it *WILL* slow us down, so we don't.
 | ||||||
|  | #if 0 | ||||||
|  | 		uprintf("%S", (PWSTR)wParam); | ||||||
|  | 		PrintStatus(0, MSG_000, str);	// MSG_000 is "%s"
 | ||||||
|  | #endif | ||||||
|  | 		if (count_files) { | ||||||
|  | 			wim_nb_files++; | ||||||
|  | 		} else { | ||||||
|  | 			// At the end of an actual apply, the WIM API re-lists a bunch of directories it already processed,
 | ||||||
|  | 			// so, even as we try to compensate, we might end up with more entries than counted - ignore those.
 | ||||||
|  | 			if (wim_proc_files < wim_nb_files) | ||||||
|  | 				wim_proc_files++; | ||||||
|  | 			else | ||||||
|  | 				wim_extra_files++; | ||||||
|  | 			UpdateProgressWithInfo(progress_op, progress_msg, wim_proc_files, wim_nb_files); | ||||||
|  | 		} | ||||||
|  | 		// Halt on error
 | ||||||
|  | 		if (IS_ERROR(FormatStatus)) { | ||||||
|  | 			pbCancel = (PBOOL)lParam; | ||||||
|  | 			*pbCancel = TRUE; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case WIM_MSG_FILEINFO: | ||||||
|  | 		if (!(progress_report_mask & WIM_REPORT_FILEINFO)) | ||||||
|  | 			break; | ||||||
|  | 		pFileData = (PWIN32_FIND_DATA)lParam; | ||||||
|  | 		if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { | ||||||
|  | 			uprintf("Creating: %S", (PWSTR)wParam); | ||||||
|  | 		} else { | ||||||
|  | 			size = (((uint64_t)pFileData->nFileSizeHigh) << 32) + pFileData->nFileSizeLow; | ||||||
|  | 			uprintf("Extracting: %S (%s)", (PWSTR)wParam, SizeToHumanReadable(size, FALSE, FALSE)); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case WIM_MSG_RETRY: | ||||||
|  | 		level = "retry"; | ||||||
|  | 		// fall through
 | ||||||
|  | 	case WIM_MSG_INFO: | ||||||
|  | 		if (level == NULL) level = "info"; | ||||||
|  | 		// fall through
 | ||||||
|  | 	case WIM_MSG_WARNING: | ||||||
|  | 		if (level == NULL) level = "warning"; | ||||||
|  | 		// fall through
 | ||||||
|  | 	case WIM_MSG_ERROR: | ||||||
|  | 		if (level == NULL) level = "error"; | ||||||
|  | 		SetLastError((DWORD)lParam); | ||||||
|  | 		uprintf("WIM processing %s: %S [err = %d]\n", level, (PWSTR)wParam, WindowsErrorString()); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return IS_ERROR(FormatStatus) ? WIM_MSG_ABORT_IMAGE : WIM_MSG_SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Find out if we have any way to extract/apply WIM files on this platform
 | // Find out if we have any way to extract/apply WIM files on this platform
 | ||||||
| // Returns a bitfield of the methods we can use (1 = Extract using wimgapi, 2 = Extract using 7-Zip, 4 = Apply using wimgapi)
 | // Returns a bitfield of the methods we can use (1 = Extract using wimgapi, 2 = Extract using 7-Zip, 4 = Apply using wimgapi)
 | ||||||
| uint8_t WimExtractCheck(BOOL bSilent) | uint8_t WimExtractCheck(BOOL bSilent) | ||||||
|  | @ -384,15 +500,26 @@ uint8_t WimExtractCheck(BOOL bSilent) | ||||||
| 	return wim_flags; | 	return wim_flags; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //
 | ||||||
| // Looks like Microsoft's idea of "mount" for WIM images involves the creation
 | // Looks like Microsoft's idea of "mount" for WIM images involves the creation
 | ||||||
| // of a as many virtual junctions as there exist directories on the image...
 | // of a as many virtual junctions as there exist directories on the image...
 | ||||||
| // So, yeah, this is both very slow and wasteful of space.
 | // So, yeah, this is both very slow and wasteful of space.
 | ||||||
|  | //
 | ||||||
|  | // NB: You can see mounted WIMs, along with their mountpoint, by checking:
 | ||||||
|  | // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WIMMount\Mounted Images\ | ||||||
|  | // You can also mount/unmount images from an elevated prompt with something like:
 | ||||||
|  | // dism /mount-image [/readonly] /imagefile:F:\sources\boot.wim /index:2 /mountdir:C:\test\offline
 | ||||||
|  | // dism /unmount-image /discard /mountdir:C:\test\offline
 | ||||||
|  | //
 | ||||||
| static DWORD WINAPI WimMountImageThread(LPVOID param) | static DWORD WINAPI WimMountImageThread(LPVOID param) | ||||||
| { | { | ||||||
| 	BOOL r = FALSE; | 	BOOL r = FALSE; | ||||||
| 	wconvert(temp_dir); | 	wconvert(temp_dir); | ||||||
| 	wchar_t* wimage = utf8_to_wchar(_image); | 	wchar_t* wimage = utf8_to_wchar(_image); | ||||||
|  | 
 | ||||||
|  | 	PF_INIT_OR_OUT(WIMRegisterMessageCallback, Wimgapi); | ||||||
| 	PF_INIT_OR_OUT(WIMMountImage, Wimgapi); | 	PF_INIT_OR_OUT(WIMMountImage, Wimgapi); | ||||||
|  | 	PF_INIT_OR_OUT(WIMUnregisterMessageCallback, Wimgapi); | ||||||
| 
 | 
 | ||||||
| 	if (wmount_path[0] != 0) { | 	if (wmount_path[0] != 0) { | ||||||
| 		uprintf("WimMountImage: An image is already mounted"); | 		uprintf("WimMountImage: An image is already mounted"); | ||||||
|  | @ -417,7 +544,18 @@ static DWORD WINAPI WimMountImageThread(LPVOID param) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	progress_report_mask = WIM_REPORT_PROGRESS; | ||||||
|  | 	progress_op = OP_PATCH; | ||||||
|  | 	progress_msg = MSG_324; | ||||||
|  | 	progress_offset = 1; | ||||||
|  | 	progress_total = PATCH_PROGRESS_TOTAL; | ||||||
|  | 	if (pfWIMRegisterMessageCallback(NULL, (FARPROC)WimProgressCallback, NULL) == INVALID_CALLBACK_VALUE) { | ||||||
|  | 		uprintf("WimMountImage: Could not set progress callback: %s", WindowsErrorString()); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	r = pfWIMMountImage(wmount_path, wimage, _index, wmount_track); | 	r = pfWIMMountImage(wmount_path, wimage, _index, wmount_track); | ||||||
|  | 	pfWIMUnregisterMessageCallback(NULL, (FARPROC)WimProgressCallback); | ||||||
| 	if (!r) { | 	if (!r) { | ||||||
| 		uprintf("Could not mount '%S [%d]' on '%S': %s", wimage, _index, wmount_path, WindowsErrorString()); | 		uprintf("Could not mount '%S [%d]' on '%S': %s", wimage, _index, wmount_path, WindowsErrorString()); | ||||||
| 		goto out; | 		goto out; | ||||||
|  | @ -455,22 +593,39 @@ static DWORD WINAPI WimUnmountImageThread(LPVOID param) | ||||||
| { | { | ||||||
| 	BOOL r = FALSE; | 	BOOL r = FALSE; | ||||||
| 	wchar_t* wimage = utf8_to_wchar(_image); | 	wchar_t* wimage = utf8_to_wchar(_image); | ||||||
|  | 
 | ||||||
|  | 	PF_INIT_OR_OUT(WIMRegisterMessageCallback, Wimgapi); | ||||||
| 	PF_INIT_OR_OUT(WIMUnmountImage, Wimgapi); | 	PF_INIT_OR_OUT(WIMUnmountImage, Wimgapi); | ||||||
|  | 	PF_INIT_OR_OUT(WIMUnregisterMessageCallback, Wimgapi); | ||||||
| 
 | 
 | ||||||
| 	if (wmount_path[0] == 0) { | 	if (wmount_path[0] == 0) { | ||||||
| 		uprintf("WimUnmountImage: No image is mounted"); | 		uprintf("WimUnmountImage: No image is mounted"); | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	progress_report_mask = WIM_REPORT_PROGRESS; | ||||||
|  | 	progress_op = OP_PATCH; | ||||||
|  | 	progress_msg = MSG_324; | ||||||
|  | 	progress_offset = 105; | ||||||
|  | 	progress_total = PATCH_PROGRESS_TOTAL; | ||||||
|  | 	if (pfWIMRegisterMessageCallback(NULL, (FARPROC)WimProgressCallback, NULL) == INVALID_CALLBACK_VALUE) { | ||||||
|  | 		uprintf("WimUnmountImage: Could not set progress callback: %s", WindowsErrorString()); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	r = pfWIMUnmountImage(wmount_path, wimage, _index, TRUE); | 	r = pfWIMUnmountImage(wmount_path, wimage, _index, TRUE); | ||||||
|  | 	pfWIMUnregisterMessageCallback(NULL, (FARPROC)WimProgressCallback); | ||||||
| 	if (!r) { | 	if (!r) { | ||||||
| 		uprintf("Could not unmount '%S': %s", wmount_path, WindowsErrorString()); | 		uprintf("Could not unmount '%S': %s", wmount_path, WindowsErrorString()); | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 	uprintf("Unmounted '%S [%d]'", wmount_path, _index); | 	uprintf("Unmounted '%S [%d]'", wmount_path, _index); | ||||||
| 	RemoveDirectoryW(wmount_path); | 	if (!RemoveDirectoryW(wmount_track)) | ||||||
| 	wmount_path[0] = 0; | 		uprintf("Could not delete '%S' : %s", wmount_track, WindowsErrorString()); | ||||||
| 	RemoveDirectoryW(wmount_track); |  | ||||||
| 	wmount_track[0] = 0; | 	wmount_track[0] = 0; | ||||||
|  | 	if (!RemoveDirectoryW(wmount_path)) | ||||||
|  | 		uprintf("Could not delete '%S' : %s", wmount_path, WindowsErrorString()); | ||||||
|  | 	wmount_path[0] = 0; | ||||||
| out: | out: | ||||||
| 	safe_free(wimage); | 	safe_free(wimage); | ||||||
| 	ExitThread((DWORD)r); | 	ExitThread((DWORD)r); | ||||||
|  | @ -652,112 +807,6 @@ BOOL WimExtractFile(const char* image, int index, const char* src, const char* d | ||||||
| 		  || ((wim_flags & WIM_HAS_API_EXTRACT) && WimExtractFile_API(image, index, src, dst, bSilent)) ); | 		  || ((wim_flags & WIM_HAS_API_EXTRACT) && WimExtractFile_API(image, index, src, dst, bSilent)) ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // From https://docs.microsoft.com/en-us/previous-versions/msdn10/dd834960(v=msdn.10)
 |  | ||||||
| // as well as https://msfn.org/board/topic/150700-wimgapi-wimmountimage-progressbar/
 |  | ||||||
| enum WIMMessage { |  | ||||||
| 	WIM_MSG = WM_APP + 0x1476, |  | ||||||
| 	WIM_MSG_TEXT, |  | ||||||
| 	WIM_MSG_PROGRESS,	// Indicates an update in the progress of an image application.
 |  | ||||||
| 	WIM_MSG_PROCESS,	// Enables the caller to prevent a file or a directory from being captured or applied.
 |  | ||||||
| 	WIM_MSG_SCANNING,	// Indicates that volume information is being gathered during an image capture.
 |  | ||||||
| 	WIM_MSG_SETRANGE,	// Indicates the number of files that will be captured or applied.
 |  | ||||||
| 	WIM_MSG_SETPOS,		// Indicates the number of files that have been captured or applied.
 |  | ||||||
| 	WIM_MSG_STEPIT,		// Indicates that a file has been either captured or applied.
 |  | ||||||
| 	WIM_MSG_COMPRESS,	// Enables the caller to prevent a file resource from being compressed during a capture.
 |  | ||||||
| 	WIM_MSG_ERROR,		// Alerts the caller that an error has occurred while capturing or applying an image.
 |  | ||||||
| 	WIM_MSG_ALIGNMENT,	// Enables the caller to align a file resource on a particular alignment boundary.
 |  | ||||||
| 	WIM_MSG_RETRY,		// Sent when the file is being reapplied because of a network timeout.
 |  | ||||||
| 	WIM_MSG_SPLIT,		// Enables the caller to align a file resource on a particular alignment boundary.
 |  | ||||||
| 	WIM_MSG_FILEINFO,	// Used in conjunction with WimApplyImages()'s WIM_FLAG_FILEINFO flag to provide detailed file info.
 |  | ||||||
| 	WIM_MSG_INFO,		// Sent when an info message is available.
 |  | ||||||
| 	WIM_MSG_WARNING,	// Sent when a warning message is available.
 |  | ||||||
| 	WIM_MSG_CHK_PROCESS, |  | ||||||
| 	WIM_MSG_SUCCESS = 0x00000000, |  | ||||||
| 	WIM_MSG_ABORT_IMAGE = -1 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| #define INVALID_CALLBACK_VALUE 0xFFFFFFFF |  | ||||||
| 
 |  | ||||||
| #define WIM_FLAG_RESERVED      0x00000001 |  | ||||||
| #define WIM_FLAG_VERIFY        0x00000002 |  | ||||||
| #define WIM_FLAG_INDEX         0x00000004 |  | ||||||
| #define WIM_FLAG_NO_APPLY      0x00000008 |  | ||||||
| #define WIM_FLAG_NO_DIRACL     0x00000010 |  | ||||||
| #define WIM_FLAG_NO_FILEACL    0x00000020 |  | ||||||
| #define WIM_FLAG_SHARE_WRITE   0x00000040 |  | ||||||
| #define WIM_FLAG_FILEINFO      0x00000080 |  | ||||||
| #define WIM_FLAG_NO_RP_FIX     0x00000100 |  | ||||||
| 
 |  | ||||||
| // Progress callback
 |  | ||||||
| DWORD WINAPI WimProgressCallback(DWORD dwMsgId, WPARAM wParam, LPARAM lParam, PVOID pvIgnored) |  | ||||||
| { |  | ||||||
| 	PBOOL pbCancel = NULL; |  | ||||||
| 	PWIN32_FIND_DATA pFileData; |  | ||||||
| 	const char* level = NULL; |  | ||||||
| 	uint64_t size; |  | ||||||
| 
 |  | ||||||
| 	switch (dwMsgId) { |  | ||||||
| 	case WIM_MSG_PROGRESS: |  | ||||||
| 		// The default WIM progress is useless (freezes at 95%, which is usually when only half
 |  | ||||||
| 		// the files have been processed), so we don't use it
 |  | ||||||
| #if 0 |  | ||||||
| 		PrintInfo(0, MSG_267, (DWORD)wParam); |  | ||||||
| 		UpdateProgress(OP_FILE_COPY, 0.98f*(DWORD)wParam); |  | ||||||
| #endif |  | ||||||
| 		break; |  | ||||||
| 	case WIM_MSG_PROCESS: |  | ||||||
| 		// The amount of files processed is overwhelming (16k+ for a typical image),
 |  | ||||||
| 		// and trying to display it *WILL* slow us down, so we don't.
 |  | ||||||
| #if 0 |  | ||||||
| 		uprintf("%S", (PWSTR)wParam); |  | ||||||
| 		PrintStatus(0, MSG_000, str);	// MSG_000 is "%s"
 |  | ||||||
| #endif |  | ||||||
| 		if (count_files) { |  | ||||||
| 			wim_nb_files++; |  | ||||||
| 		} else { |  | ||||||
| 			// At the end of an actual apply, the WIM API re-lists a bunch of directories it already processed,
 |  | ||||||
| 			// so, even as we try to compensate, we might end up with more entries than counted - ignore those.
 |  | ||||||
| 			if (wim_proc_files < wim_nb_files) |  | ||||||
| 				wim_proc_files++; |  | ||||||
| 			else |  | ||||||
| 				wim_extra_files++; |  | ||||||
| 			UpdateProgressWithInfo(OP_FILE_COPY, MSG_267, wim_proc_files, wim_nb_files); |  | ||||||
| 		} |  | ||||||
| 		// Halt on error
 |  | ||||||
| 		if (IS_ERROR(FormatStatus)) { |  | ||||||
| 			pbCancel = (PBOOL)lParam; |  | ||||||
| 			*pbCancel = TRUE; |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		break; |  | ||||||
| 	case WIM_MSG_FILEINFO: |  | ||||||
| 		pFileData = (PWIN32_FIND_DATA)lParam; |  | ||||||
| 		if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { |  | ||||||
| 			uprintf("Creating: %S", (PWSTR)wParam); |  | ||||||
| 		} else { |  | ||||||
| 			size = (((uint64_t)pFileData->nFileSizeHigh) << 32) + pFileData->nFileSizeLow; |  | ||||||
| 			uprintf("Extracting: %S (%s)", (PWSTR)wParam, SizeToHumanReadable(size, FALSE, FALSE)); |  | ||||||
| 		} |  | ||||||
| 		break; |  | ||||||
| 	case WIM_MSG_RETRY: |  | ||||||
| 		level = "retry"; |  | ||||||
| 		// fall through
 |  | ||||||
| 	case WIM_MSG_INFO: |  | ||||||
| 		if (level == NULL) level = "info"; |  | ||||||
| 		// fall through
 |  | ||||||
| 	case WIM_MSG_WARNING: |  | ||||||
| 		if (level == NULL) level = "warning"; |  | ||||||
| 		// fall through
 |  | ||||||
| 	case WIM_MSG_ERROR: |  | ||||||
| 		if (level == NULL) level = "error"; |  | ||||||
| 		SetLastError((DWORD)lParam); |  | ||||||
| 		uprintf("Apply %s: %S [err = %d]\n", level, (PWSTR)wParam, WindowsErrorString()); |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return IS_ERROR(FormatStatus)?WIM_MSG_ABORT_IMAGE:WIM_MSG_SUCCESS; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Apply a WIM image using wimgapi.dll (Windows 7 or later)
 | // Apply a WIM image using wimgapi.dll (Windows 7 or later)
 | ||||||
| // https://docs.microsoft.com/en-us/previous-versions/msdn10/dd851944(v=msdn.10)
 | // https://docs.microsoft.com/en-us/previous-versions/msdn10/dd851944(v=msdn.10)
 | ||||||
| // To get progress, we must run this call within its own thread
 | // To get progress, we must run this call within its own thread
 | ||||||
|  | @ -780,6 +829,11 @@ static DWORD WINAPI WimApplyImageThread(LPVOID param) | ||||||
| 
 | 
 | ||||||
| 	uprintf("Opening: %s:[%d]", _image, _index); | 	uprintf("Opening: %s:[%d]", _image, _index); | ||||||
| 
 | 
 | ||||||
|  | 	progress_report_mask = WIM_REPORT_PROCESS | WIM_REPORT_FILEINFO; | ||||||
|  | 	progress_op = OP_FILE_COPY; | ||||||
|  | 	progress_msg = MSG_267; | ||||||
|  | 	progress_offset = 0; | ||||||
|  | 	progress_total = 100; | ||||||
| 	if (pfWIMRegisterMessageCallback(NULL, (FARPROC)WimProgressCallback, NULL) == INVALID_CALLBACK_VALUE) { | 	if (pfWIMRegisterMessageCallback(NULL, (FARPROC)WimProgressCallback, NULL) == INVALID_CALLBACK_VALUE) { | ||||||
| 		uprintf("  Could not set progress callback: %s", WindowsErrorString()); | 		uprintf("  Could not set progress callback: %s", WindowsErrorString()); | ||||||
| 		goto out; | 		goto out; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue