mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[wue] add fallback to index 1 if boot.wim index 2 is not available
* Some "unofficial" Windows ISOs use a custom boot.wim that only includes the Setup image at index 1, rather than at index 2, after the PE image, for official ISOs. * Also refactor to add a long needed vhd.h header. * Also fix a MinGW warning.
This commit is contained in:
		
							parent
							
								
									eda1f59a38
								
							
						
					
					
						commit
						fbad63666e
					
				
					 11 changed files with 243 additions and 134 deletions
				
			
		|  | @ -405,6 +405,7 @@ | |||
|     <ClInclude Include="..\src\dev.h" /> | ||||
|     <ClInclude Include="..\src\ui.h" /> | ||||
|     <ClInclude Include="..\src\ui_data.h" /> | ||||
|     <ClInclude Include="..\src\vhd.h" /> | ||||
|     <ClInclude Include="..\src\winio.h" /> | ||||
|     <ClInclude Include="..\src\wue.h" /> | ||||
|   </ItemGroup> | ||||
|  |  | |||
|  | @ -188,6 +188,9 @@ | |||
|     <ClInclude Include="..\src\wue.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\src\vhd.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="..\res\rufus.ico"> | ||||
|  |  | |||
							
								
								
									
										2
									
								
								configure
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								configure
									
										
									
									
										vendored
									
									
								
							|  | @ -4726,7 +4726,7 @@ fi | |||
| rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext | ||||
| CFLAGS="${saved_CFLAGS}" | ||||
| 
 | ||||
| AM_CFLAGS="$AM_CFLAGS -DUNICODE -D_UNICODE -UNDEBUG -DCOBJMACROS -D__USE_MINGW_ANSI_STDIO=0 -std=gnu99 -Wshadow -Wall -Wformat-security -Wundef -Wunused -Wstrict-prototypes -Wno-restrict -Werror-implicit-function-declaration -Wbidi-chars=none $nopointersign_cflags" | ||||
| AM_CFLAGS="$AM_CFLAGS -DUNICODE -D_UNICODE -UNDEBUG -DCOBJMACROS -D__USE_MINGW_ANSI_STDIO=0 -std=gnu99 -Wshadow -Wall -Wformat-security -Wundef -Wunused -Wstrict-prototypes -Wno-restrict -Wno-array-bounds -Werror-implicit-function-declaration -Wbidi-chars=none $nopointersign_cflags" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -64,7 +64,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], | |||
| 	[nopointersign_cflags="-Wno-pointer-sign"], [nopointersign_cflags=""]) | ||||
| CFLAGS="${saved_CFLAGS}" | ||||
| 
 | ||||
| AM_CFLAGS="$AM_CFLAGS -DUNICODE -D_UNICODE -UNDEBUG -DCOBJMACROS -D__USE_MINGW_ANSI_STDIO=0 -std=gnu99 -Wshadow -Wall -Wformat-security -Wundef -Wunused -Wstrict-prototypes -Wno-restrict -Werror-implicit-function-declaration -Wbidi-chars=none $nopointersign_cflags" | ||||
| AM_CFLAGS="$AM_CFLAGS -DUNICODE -D_UNICODE -UNDEBUG -DCOBJMACROS -D__USE_MINGW_ANSI_STDIO=0 -std=gnu99 -Wshadow -Wall -Wformat-security -Wundef -Wunused -Wstrict-prototypes -Wno-restrict -Wno-array-bounds -Werror-implicit-function-declaration -Wbidi-chars=none $nopointersign_cflags" | ||||
| 
 | ||||
| AC_SUBST([VISIBILITY_CFLAGS]) | ||||
| AC_SUBST([AM_CFLAGS]) | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ | |||
| #include "localization.h" | ||||
| 
 | ||||
| #include "br.h" | ||||
| #include "vhd.h" | ||||
| #include "wue.h" | ||||
| #include "fat16.h" | ||||
| #include "fat32.h" | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ | |||
| 
 | ||||
| #include "ui.h" | ||||
| #include "re.h" | ||||
| #include "vhd.h" | ||||
| #include "wue.h" | ||||
| #include "drive.h" | ||||
| #include "settings.h" | ||||
|  | @ -3770,9 +3771,8 @@ relaunch: | |||
| 		// Ctrl-T => Alternate Test mode that doesn't require a full rebuild
 | ||||
| 		if ((ctrl_without_focus || ((GetKeyState(VK_CONTROL) & 0x8000) && (msg.message == WM_KEYDOWN))) | ||||
| 			&& (msg.wParam == 'T')) { | ||||
| 			//extern int TestChecksum(void);
 | ||||
| 			//TestChecksum();
 | ||||
| 			ListVdsVolumes(FALSE); | ||||
| 			int index = 2; | ||||
| 			uprintf("Index %d is %s", index, WimIsValidIndex("C:\\tmp\\boot1.wim", index) ? "valid" : "invalid"); | ||||
| 			continue; | ||||
| 		} | ||||
| #endif | ||||
|  |  | |||
|  | @ -629,15 +629,6 @@ extern char* replace_in_token_data(const char* filename, const char* token, cons | |||
| extern char* replace_char(const char* src, const char c, const char* rep); | ||||
| extern void parse_update(char* buf, size_t len); | ||||
| extern void* get_data_from_asn1(const uint8_t* buf, size_t buf_len, const char* oid_str, uint8_t asn1_type, size_t* data_len); | ||||
| extern uint8_t WimExtractCheck(BOOL bSilent); | ||||
| extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst, BOOL bSilent); | ||||
| extern BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst, BOOL bSilent); | ||||
| extern BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst, BOOL bSilent); | ||||
| extern BOOL WimApplyImage(const char* image, int index, const char* dst); | ||||
| extern char* WimMountImage(const char* image, int index); | ||||
| extern BOOL WimUnmountImage(const char* image, int index); | ||||
| extern int8_t IsBootableImage(const char* path); | ||||
| extern BOOL AppendVHDFooter(const char* vhd_path); | ||||
| extern int IsHDD(DWORD DriveIndex, uint16_t vid, uint16_t pid, const char* strid); | ||||
| extern char* GetSignatureName(const char* path, const char* country_code, BOOL bSilent); | ||||
| extern uint64_t GetSignatureTimeStamp(const char* path); | ||||
|  |  | |||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | |||
| IDD_DIALOG DIALOGEX 12, 12, 232, 326 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_ACCEPTFILES | ||||
| CAPTION "Rufus 3.20.1927" | ||||
| CAPTION "Rufus 3.20.1928" | ||||
| FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | ||||
| BEGIN | ||||
|     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP | ||||
|  | @ -395,8 +395,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 3,20,1927,0 | ||||
|  PRODUCTVERSION 3,20,1927,0 | ||||
|  FILEVERSION 3,20,1928,0 | ||||
|  PRODUCTVERSION 3,20,1928,0 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -414,13 +414,13 @@ BEGIN | |||
|             VALUE "Comments", "https://rufus.ie" | ||||
|             VALUE "CompanyName", "Akeo Consulting" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "3.20.1927" | ||||
|             VALUE "FileVersion", "3.20.1928" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2022 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" | ||||
|             VALUE "OriginalFilename", "rufus-3.20.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "3.20.1927" | ||||
|             VALUE "ProductVersion", "3.20.1928" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
							
								
								
									
										179
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										179
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -23,6 +23,7 @@ | |||
| #include <rpc.h> | ||||
| #include <time.h> | ||||
| 
 | ||||
| #include "vhd.h" | ||||
| #include "rufus.h" | ||||
| #include "missing.h" | ||||
| #include "resource.h" | ||||
|  | @ -32,110 +33,7 @@ | |||
| #include "registry.h" | ||||
| #include "bled/bled.h" | ||||
| 
 | ||||
| #define VHD_FOOTER_COOKIE					{ 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x' } | ||||
| 
 | ||||
| #define VHD_FOOTER_FEATURES_NONE			0x00000000 | ||||
| #define VHD_FOOTER_FEATURES_TEMPORARY		0x00000001 | ||||
| #define VHD_FOOTER_FEATURES_RESERVED		0x00000002 | ||||
| 
 | ||||
| #define VHD_FOOTER_FILE_FORMAT_V1_0			0x00010000 | ||||
| 
 | ||||
| #define VHD_FOOTER_DATA_OFFSET_FIXED_DISK	0xFFFFFFFFFFFFFFFFULL | ||||
| 
 | ||||
| #define VHD_FOOTER_CREATOR_HOST_OS_WINDOWS	{ 'W', 'i', '2', 'k' } | ||||
| #define VHD_FOOTER_CREATOR_HOST_OS_MAC		{ 'M', 'a', 'c', ' ' } | ||||
| 
 | ||||
| #define VHD_FOOTER_TYPE_FIXED_HARD_DISK		0x00000002 | ||||
| #define VHD_FOOTER_TYPE_DYNAMIC_HARD_DISK	0x00000003 | ||||
| #define VHD_FOOTER_TYPE_DIFFER_HARD_DISK	0x00000004 | ||||
| 
 | ||||
| #define WIM_MAGIC							0x0000004D4957534DULL	// "MSWIM\0\0\0"
 | ||||
| #define WIM_HAS_API_EXTRACT					1 | ||||
| #define WIM_HAS_7Z_EXTRACT					2 | ||||
| #define WIM_HAS_API_APPLY					4 | ||||
| #define WIM_HAS_EXTRACT(r)					(r & (WIM_HAS_API_EXTRACT|WIM_HAS_7Z_EXTRACT)) | ||||
| 
 | ||||
| #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) | ||||
|  * http://download.microsoft.com/download/f/f/e/ffef50a5-07dd-4cf8-aaa3-442c0673a029/Virtual%20Hard%20Disk%20Format%20Spec_10_18_06.doc
 | ||||
|  * NB: If a dymamic implementation is needed, check the GPL v3 compatible C++ implementation from: | ||||
|  * https://sourceforge.net/p/urbackup/backend/ci/master/tree/fsimageplugin/
 | ||||
|  */ | ||||
| #pragma pack(push, 1) | ||||
| typedef struct vhd_footer { | ||||
| 	char		cookie[8]; | ||||
| 	uint32_t	features; | ||||
| 	uint32_t	file_format_version; | ||||
| 	uint64_t	data_offset; | ||||
| 	uint32_t	timestamp; | ||||
| 	char		creator_app[4]; | ||||
| 	uint32_t	creator_version; | ||||
| 	char		creator_host_os[4]; | ||||
| 	uint64_t	original_size; | ||||
| 	uint64_t	current_size; | ||||
| 	union { | ||||
| 		uint32_t	geometry; | ||||
| 		struct { | ||||
| 			uint16_t	cylinders; | ||||
| 			uint8_t		heads; | ||||
| 			uint8_t		sectors; | ||||
| 		} chs; | ||||
| 	} disk_geometry; | ||||
| 	uint32_t	disk_type; | ||||
| 	uint32_t	checksum; | ||||
| 	uuid_t		unique_id; | ||||
| 	uint8_t		saved_state; | ||||
| 	uint8_t		reserved[427]; | ||||
| } vhd_footer; | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
| // WIM API Prototypes
 | ||||
| #define WIM_GENERIC_READ            GENERIC_READ | ||||
| #define WIM_OPEN_EXISTING           OPEN_EXISTING | ||||
| #define WIM_UNDOCUMENTED_BULLSHIT   0x20000000 | ||||
| PF_TYPE_DECL(WINAPI, HANDLE, WIMCreateFile, (PWSTR, DWORD, DWORD, DWORD, DWORD, PDWORD)); | ||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMSetTemporaryPath, (HANDLE, PWSTR)); | ||||
| PF_TYPE_DECL(WINAPI, HANDLE, WIMLoadImage, (HANDLE, DWORD)); | ||||
|  | @ -287,8 +185,7 @@ static comp_assoc file_assoc[] = { | |||
| }; | ||||
| 
 | ||||
| // For now we consider that an image that matches a known extension is bootable
 | ||||
| #define MBR_SIZE 512	// Might need to review this once we see bootable 4k systems
 | ||||
| BOOL IsCompressedBootableImage(const char* path) | ||||
| static BOOL IsCompressedBootableImage(const char* path) | ||||
| { | ||||
| 	char *p; | ||||
| 	unsigned char *buf = NULL; | ||||
|  | @ -566,7 +463,7 @@ static DWORD WINAPI WimMountImageThread(LPVOID param) | |||
| 		uprintf("Could not mount '%S [%d]' on '%S': %s", wimage, _index, wmount_path, WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	uprintf("mounted '%S [%d]' on '%S'", wimage, _index, wmount_path); | ||||
| 	uprintf("Mounted '%S [%d]' on '%S'", wimage, _index, wmount_path); | ||||
| 
 | ||||
| out: | ||||
| 	if (!r) { | ||||
|  | @ -677,11 +574,11 @@ BOOL WimExtractFile_API(const char* image, int index, const char* src, const cha | |||
| 	HANDLE hWim = 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* wsrc = utf8_to_wchar(src); | ||||
| 	wchar_t* wdst = utf8_to_wchar(dst); | ||||
| 	char* wim_info; | ||||
| 	wchar_t* wim_info; | ||||
| 
 | ||||
| 	PF_INIT_OR_OUT(WIMCreateFile, Wimgapi); | ||||
| 	PF_INIT_OR_OUT(WIMSetTemporaryPath, Wimgapi); | ||||
|  | @ -713,7 +610,7 @@ BOOL WimExtractFile_API(const char* image, int index, const char* src, const cha | |||
| 
 | ||||
| 	suprintf("Extracting: %s (From %s)", dst, src); | ||||
| 	if (safe_strcmp(src, index_name) == 0) { | ||||
| 		if (!pfWIMGetImageInformation(hWim, &wim_info, &dw)) { | ||||
| 		if (!pfWIMGetImageInformation(hWim, &wim_info, &dw) || (dw == 0)) { | ||||
| 			uprintf("  Could not access WIM info: %s", WindowsErrorString()); | ||||
| 			goto out; | ||||
| 		} | ||||
|  | @ -823,6 +720,70 @@ 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)) ); | ||||
| } | ||||
| 
 | ||||
| /// <summary>
 | ||||
| /// Find if a specific index belongs to a WIM image.
 | ||||
| /// </summary>
 | ||||
| /// <param name="image">The path to the WIM file.</param>
 | ||||
| /// <param name="index">The (non-zero) value of the index to check.</param>
 | ||||
| /// <returns>TRUE if the index was found in the image, FALSE otherwise.</returns>
 | ||||
| BOOL WimIsValidIndex(const char* image, int index) | ||||
| { | ||||
| 	int i = 1; | ||||
| 	BOOL r = FALSE; | ||||
| 	DWORD dw = 0; | ||||
| 	HANDLE hWim = NULL; | ||||
| 	HANDLE hFile = NULL; | ||||
| 	char xml_file[MAX_PATH] = { 0 }; | ||||
| 	char* str; | ||||
| 	wchar_t* wimage = utf8_to_wchar(image); | ||||
| 	wchar_t* wim_info; | ||||
| 
 | ||||
| 	PF_INIT_OR_OUT(WIMCreateFile, Wimgapi); | ||||
| 	PF_INIT_OR_OUT(WIMGetImageInformation, Wimgapi); | ||||
| 	PF_INIT_OR_OUT(WIMCloseHandle, Wimgapi); | ||||
| 
 | ||||
| 	// Zero indexes are invalid
 | ||||
| 	if (index == 0) | ||||
| 		return FALSE; | ||||
| 
 | ||||
| 	hWim = pfWIMCreateFile(wimage, WIM_GENERIC_READ, WIM_OPEN_EXISTING, | ||||
| 		(img_report.wininst_version >= SPECIAL_WIM_VERSION) ? WIM_UNDOCUMENTED_BULLSHIT : 0, 0, NULL); | ||||
| 	if (hWim == NULL) { | ||||
| 		uprintf("  Could not access image: %s", WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!pfWIMGetImageInformation(hWim, &wim_info, &dw) || (dw == 0)) { | ||||
| 		uprintf("  Could not access WIM info: %s", WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	if ((GetTempFileNameU(temp_dir, APPLICATION_NAME, 0, xml_file) == 0) || (xml_file[0] == 0)) | ||||
| 		static_strcpy(xml_file, ".\\RufVXml.tmp"); | ||||
| 	DeleteFileU(xml_file); | ||||
| 	hFile = CreateFileU(xml_file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, | ||||
| 		NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | ||||
| 	if ((hFile == INVALID_HANDLE_VALUE) || (!WriteFile(hFile, wim_info, dw, &dw, NULL))) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	while ((str = get_token_data_file_indexed("IMAGE INDEX", xml_file, i)) != NULL) { | ||||
| 		if (atoi(str) == index) { | ||||
| 			r = TRUE; | ||||
| 			break; | ||||
| 		} | ||||
| 		i++; | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	if (hWim != NULL) | ||||
| 		pfWIMCloseHandle(hWim); | ||||
| 	safe_closehandle(hFile); | ||||
| 	if (xml_file[0] != 0) | ||||
| 		DeleteFileU(xml_file); | ||||
| 	safe_free(wimage); | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| // Apply a WIM image using wimgapi.dll (Windows 7 or later)
 | ||||
| // 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
 | ||||
|  |  | |||
							
								
								
									
										141
									
								
								src/vhd.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/vhd.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,141 @@ | |||
| /*
 | ||||
|  * Rufus: The Reliable USB Formatting Utility | ||||
|  * Virtual Disk Handling definitions and prototypes | ||||
|  * Copyright © 2022 Pete Batard <pete@akeo.ie> | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <windows.h> | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #define VHD_FOOTER_COOKIE					{ 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x' } | ||||
| 
 | ||||
| #define VHD_FOOTER_FEATURES_NONE			0x00000000 | ||||
| #define VHD_FOOTER_FEATURES_TEMPORARY		0x00000001 | ||||
| #define VHD_FOOTER_FEATURES_RESERVED		0x00000002 | ||||
| 
 | ||||
| #define VHD_FOOTER_FILE_FORMAT_V1_0			0x00010000 | ||||
| 
 | ||||
| #define VHD_FOOTER_DATA_OFFSET_FIXED_DISK	0xFFFFFFFFFFFFFFFFULL | ||||
| 
 | ||||
| #define VHD_FOOTER_CREATOR_HOST_OS_WINDOWS	{ 'W', 'i', '2', 'k' } | ||||
| #define VHD_FOOTER_CREATOR_HOST_OS_MAC		{ 'M', 'a', 'c', ' ' } | ||||
| 
 | ||||
| #define VHD_FOOTER_TYPE_FIXED_HARD_DISK		0x00000002 | ||||
| #define VHD_FOOTER_TYPE_DYNAMIC_HARD_DISK	0x00000003 | ||||
| #define VHD_FOOTER_TYPE_DIFFER_HARD_DISK	0x00000004 | ||||
| 
 | ||||
| #define WIM_MAGIC							0x0000004D4957534DULL	// "MSWIM\0\0\0"
 | ||||
| #define WIM_HAS_API_EXTRACT					1 | ||||
| #define WIM_HAS_7Z_EXTRACT					2 | ||||
| #define WIM_HAS_API_APPLY					4 | ||||
| #define WIM_HAS_EXTRACT(r)					(r & (WIM_HAS_API_EXTRACT|WIM_HAS_7Z_EXTRACT)) | ||||
| 
 | ||||
| #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 | ||||
| 
 | ||||
| #define WIM_GENERIC_READ					GENERIC_READ | ||||
| #define WIM_OPEN_EXISTING					OPEN_EXISTING | ||||
| #define WIM_UNDOCUMENTED_BULLSHIT			0x20000000 | ||||
| 
 | ||||
| #define MBR_SIZE							512	// Might need to review this once we see bootable 4k systems
 | ||||
| 
 | ||||
| 
 | ||||
| // 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) | ||||
|  * http://download.microsoft.com/download/f/f/e/ffef50a5-07dd-4cf8-aaa3-442c0673a029/Virtual%20Hard%20Disk%20Format%20Spec_10_18_06.doc
 | ||||
|  * NB: If a dymamic implementation is needed, check the GPL v3 compatible C++ implementation from: | ||||
|  * https://sourceforge.net/p/urbackup/backend/ci/master/tree/fsimageplugin/
 | ||||
|  */ | ||||
| #pragma pack(push, 1) | ||||
| typedef struct vhd_footer { | ||||
| 	char		cookie[8]; | ||||
| 	uint32_t	features; | ||||
| 	uint32_t	file_format_version; | ||||
| 	uint64_t	data_offset; | ||||
| 	uint32_t	timestamp; | ||||
| 	char		creator_app[4]; | ||||
| 	uint32_t	creator_version; | ||||
| 	char		creator_host_os[4]; | ||||
| 	uint64_t	original_size; | ||||
| 	uint64_t	current_size; | ||||
| 	union { | ||||
| 		uint32_t	geometry; | ||||
| 		struct { | ||||
| 			uint16_t	cylinders; | ||||
| 			uint8_t		heads; | ||||
| 			uint8_t		sectors; | ||||
| 		} chs; | ||||
| 	} disk_geometry; | ||||
| 	uint32_t	disk_type; | ||||
| 	uint32_t	checksum; | ||||
| 	uuid_t		unique_id; | ||||
| 	uint8_t		saved_state; | ||||
| 	uint8_t		reserved[427]; | ||||
| } vhd_footer; | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
| extern uint8_t WimExtractCheck(BOOL bSilent); | ||||
| extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst, BOOL bSilent); | ||||
| extern BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst, BOOL bSilent); | ||||
| extern BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst, BOOL bSilent); | ||||
| extern BOOL WimApplyImage(const char* image, int index, const char* dst); | ||||
| extern char* WimMountImage(const char* image, int index); | ||||
| extern BOOL WimUnmountImage(const char* image, int index); | ||||
| extern BOOL WimIsValidIndex(const char* image, int index); | ||||
| extern int8_t IsBootableImage(const char* path); | ||||
| extern BOOL AppendVHDFooter(const char* vhd_path); | ||||
							
								
								
									
										23
									
								
								src/wue.c
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								src/wue.c
									
										
									
									
									
								
							|  | @ -24,6 +24,7 @@ | |||
| #include <assert.h> | ||||
| 
 | ||||
| #include "rufus.h" | ||||
| #include "vhd.h" | ||||
| #include "drive.h" | ||||
| #include "format.h" | ||||
| #include "missing.h" | ||||
|  | @ -359,7 +360,7 @@ out: | |||
| /// <returns>-2 on user cancel, -1 on other error, >=0 on success.</returns>
 | ||||
| int SetWinToGoIndex(void) | ||||
| { | ||||
| 	char* mounted_iso, * val, mounted_image_path[128]; | ||||
| 	char* mounted_iso, *val, mounted_image_path[128]; | ||||
| 	char xml_file[MAX_PATH] = ""; | ||||
| 	char* install_names[MAX_WININST]; | ||||
| 	StrArray version_name, version_index; | ||||
|  | @ -619,8 +620,7 @@ BOOL ApplyWindowsCustomization(char drive_letter, int flags) | |||
| // NB: Work with a copy of unattend_xml_flags as a paremeter since we will modify it.
 | ||||
| { | ||||
| 	BOOL r = FALSE, is_hive_mounted = FALSE; | ||||
| 	int i; | ||||
| 	const int wim_index = 2; | ||||
| 	int i, wim_index = 2; | ||||
| 	const char* offline_hive_name = "RUFUS_OFFLINE_HIVE"; | ||||
| 	char boot_wim_path[] = "?:\\sources\\boot.wim", key_path[64]; | ||||
| 	char appraiserres_dll_src[] = "?:\\sources\\appraiserres.dll"; | ||||
|  | @ -653,12 +653,16 @@ BOOL ApplyWindowsCustomization(char drive_letter, int flags) | |||
| 			// appraiserres.dll otherwise setup.exe extracts its own.
 | ||||
| 			appraiserres_dll_src[0] = drive_letter; | ||||
| 			appraiserres_dll_dst[0] = drive_letter; | ||||
| 			if (!MoveFileExU(appraiserres_dll_src, appraiserres_dll_dst, MOVEFILE_REPLACE_EXISTING)) | ||||
| 			if (!MoveFileExU(appraiserres_dll_src, appraiserres_dll_dst, MOVEFILE_REPLACE_EXISTING) | ||||
| 				&& GetLastError() != ERROR_FILE_NOT_FOUND) { | ||||
| 				uprintf("Could not rename '%s': %s", appraiserres_dll_src, WindowsErrorString()); | ||||
| 			else | ||||
| 			} else { | ||||
| 				if (GetLastError() == ERROR_SUCCESS) | ||||
| 					uprintf("Renamed '%s' → '%s'", appraiserres_dll_src, appraiserres_dll_dst); | ||||
| 				CloseHandle(CreateFileU(appraiserres_dll_src, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, | ||||
| 					NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); | ||||
| 			uprintf("Renamed '%s' → '%s'", appraiserres_dll_src, appraiserres_dll_dst); | ||||
| 				uprintf("Created '%s' placeholder", appraiserres_dll_src); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		UpdateProgressWithInfoForce(OP_PATCH, MSG_325, 0, PATCH_PROGRESS_TOTAL); | ||||
|  | @ -666,6 +670,13 @@ BOOL ApplyWindowsCustomization(char drive_letter, int flags) | |||
| 		// not, we can just copy our unattend.xml in \sources\$OEM$\$$\Panther\.
 | ||||
| 		if (flags & UNATTEND_WINPE_SETUP_MASK) { | ||||
| 			uprintf("Mounting '%s'...", boot_wim_path); | ||||
| 			// Some "unofficial" ISOs have a modified boot.wim that doesn't have Windows Setup at index 2...
 | ||||
| 			if (!WimIsValidIndex(boot_wim_path, wim_index)) { | ||||
| 				uprintf("WARNING: This image appears to be an UNOFFICIAL Windows ISO!"); | ||||
| 				uprintf("Rufus recommends that you only use OFFICIAL retail Microsoft Windows images, such as"); | ||||
| 				uprintf("the ones that can be downloaded through the download facility of this application."); | ||||
| 				wim_index = 1; | ||||
| 			} | ||||
| 			mount_path = WimMountImage(boot_wim_path, wim_index); | ||||
| 			if (mount_path == NULL) | ||||
| 				goto out; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue