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\dev.h" /> | ||||||
|     <ClInclude Include="..\src\ui.h" /> |     <ClInclude Include="..\src\ui.h" /> | ||||||
|     <ClInclude Include="..\src\ui_data.h" /> |     <ClInclude Include="..\src\ui_data.h" /> | ||||||
|  |     <ClInclude Include="..\src\vhd.h" /> | ||||||
|     <ClInclude Include="..\src\winio.h" /> |     <ClInclude Include="..\src\winio.h" /> | ||||||
|     <ClInclude Include="..\src\wue.h" /> |     <ClInclude Include="..\src\wue.h" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|  | @ -188,6 +188,9 @@ | ||||||
|     <ClInclude Include="..\src\wue.h"> |     <ClInclude Include="..\src\wue.h"> | ||||||
|       <Filter>Header Files</Filter> |       <Filter>Header Files</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\src\vhd.h"> | ||||||
|  |       <Filter>Header Files</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="..\res\rufus.ico"> |     <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 | rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext | ||||||
| CFLAGS="${saved_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" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -64,7 +64,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], | ||||||
| 	[nopointersign_cflags="-Wno-pointer-sign"], [nopointersign_cflags=""]) | 	[nopointersign_cflags="-Wno-pointer-sign"], [nopointersign_cflags=""]) | ||||||
| CFLAGS="${saved_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([VISIBILITY_CFLAGS]) | ||||||
| AC_SUBST([AM_CFLAGS]) | AC_SUBST([AM_CFLAGS]) | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ | ||||||
| #include "localization.h" | #include "localization.h" | ||||||
| 
 | 
 | ||||||
| #include "br.h" | #include "br.h" | ||||||
|  | #include "vhd.h" | ||||||
| #include "wue.h" | #include "wue.h" | ||||||
| #include "fat16.h" | #include "fat16.h" | ||||||
| #include "fat32.h" | #include "fat32.h" | ||||||
|  |  | ||||||
|  | @ -47,6 +47,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "ui.h" | #include "ui.h" | ||||||
| #include "re.h" | #include "re.h" | ||||||
|  | #include "vhd.h" | ||||||
| #include "wue.h" | #include "wue.h" | ||||||
| #include "drive.h" | #include "drive.h" | ||||||
| #include "settings.h" | #include "settings.h" | ||||||
|  | @ -3770,9 +3771,8 @@ relaunch: | ||||||
| 		// Ctrl-T => Alternate Test mode that doesn't require a full rebuild
 | 		// Ctrl-T => Alternate Test mode that doesn't require a full rebuild
 | ||||||
| 		if ((ctrl_without_focus || ((GetKeyState(VK_CONTROL) & 0x8000) && (msg.message == WM_KEYDOWN))) | 		if ((ctrl_without_focus || ((GetKeyState(VK_CONTROL) & 0x8000) && (msg.message == WM_KEYDOWN))) | ||||||
| 			&& (msg.wParam == 'T')) { | 			&& (msg.wParam == 'T')) { | ||||||
| 			//extern int TestChecksum(void);
 | 			int index = 2; | ||||||
| 			//TestChecksum();
 | 			uprintf("Index %d is %s", index, WimIsValidIndex("C:\\tmp\\boot1.wim", index) ? "valid" : "invalid"); | ||||||
| 			ListVdsVolumes(FALSE); |  | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| #endif | #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 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 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 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 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 char* GetSignatureName(const char* path, const char* country_code, BOOL bSilent); | ||||||
| extern uint64_t GetSignatureTimeStamp(const char* path); | 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 | 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.20.1927" | CAPTION "Rufus 3.20.1928" | ||||||
| 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,20,1927,0 |  FILEVERSION 3,20,1928,0 | ||||||
|  PRODUCTVERSION 3,20,1927,0 |  PRODUCTVERSION 3,20,1928,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.20.1927" |             VALUE "FileVersion", "3.20.1928" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2022 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2022 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.20.exe" |             VALUE "OriginalFilename", "rufus-3.20.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "3.20.1927" |             VALUE "ProductVersion", "3.20.1928" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
							
								
								
									
										179
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										179
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -23,6 +23,7 @@ | ||||||
| #include <rpc.h> | #include <rpc.h> | ||||||
| #include <time.h> | #include <time.h> | ||||||
| 
 | 
 | ||||||
|  | #include "vhd.h" | ||||||
| #include "rufus.h" | #include "rufus.h" | ||||||
| #include "missing.h" | #include "missing.h" | ||||||
| #include "resource.h" | #include "resource.h" | ||||||
|  | @ -32,110 +33,7 @@ | ||||||
| #include "registry.h" | #include "registry.h" | ||||||
| #include "bled/bled.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
 | // 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, HANDLE, WIMCreateFile, (PWSTR, DWORD, DWORD, DWORD, DWORD, PDWORD)); | ||||||
| PF_TYPE_DECL(WINAPI, BOOL, WIMSetTemporaryPath, (HANDLE, PWSTR)); | PF_TYPE_DECL(WINAPI, BOOL, WIMSetTemporaryPath, (HANDLE, PWSTR)); | ||||||
| PF_TYPE_DECL(WINAPI, HANDLE, WIMLoadImage, (HANDLE, DWORD)); | 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
 | // 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
 | static BOOL IsCompressedBootableImage(const char* path) | ||||||
| BOOL IsCompressedBootableImage(const char* path) |  | ||||||
| { | { | ||||||
| 	char *p; | 	char *p; | ||||||
| 	unsigned char *buf = NULL; | 	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()); | 		uprintf("Could not mount '%S [%d]' on '%S': %s", wimage, _index, wmount_path, WindowsErrorString()); | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 	uprintf("mounted '%S [%d]' on '%S'", wimage, _index, wmount_path); | 	uprintf("Mounted '%S [%d]' on '%S'", wimage, _index, wmount_path); | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	if (!r) { | 	if (!r) { | ||||||
|  | @ -677,11 +574,11 @@ BOOL WimExtractFile_API(const char* image, int index, const char* src, const cha | ||||||
| 	HANDLE hWim = NULL; | 	HANDLE hWim = NULL; | ||||||
| 	HANDLE hImage = NULL; | 	HANDLE hImage = NULL; | ||||||
| 	HANDLE hFile = 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; | 	wchar_t* 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); | ||||||
|  | @ -713,7 +610,7 @@ BOOL WimExtractFile_API(const char* image, int index, const char* src, const cha | ||||||
| 
 | 
 | ||||||
| 	suprintf("Extracting: %s (From %s)", dst, src); | 	suprintf("Extracting: %s (From %s)", dst, src); | ||||||
| 	if (safe_strcmp(src, index_name) == 0) { | 	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()); | 			uprintf("  Could not access WIM info: %s", WindowsErrorString()); | ||||||
| 			goto out; | 			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)) ); | 		  || ((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)
 | // 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
 | ||||||
|  |  | ||||||
							
								
								
									
										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 <assert.h> | ||||||
| 
 | 
 | ||||||
| #include "rufus.h" | #include "rufus.h" | ||||||
|  | #include "vhd.h" | ||||||
| #include "drive.h" | #include "drive.h" | ||||||
| #include "format.h" | #include "format.h" | ||||||
| #include "missing.h" | #include "missing.h" | ||||||
|  | @ -359,7 +360,7 @@ out: | ||||||
| /// <returns>-2 on user cancel, -1 on other error, >=0 on success.</returns>
 | /// <returns>-2 on user cancel, -1 on other error, >=0 on success.</returns>
 | ||||||
| int SetWinToGoIndex(void) | 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 xml_file[MAX_PATH] = ""; | ||||||
| 	char* install_names[MAX_WININST]; | 	char* install_names[MAX_WININST]; | ||||||
| 	StrArray version_name, version_index; | 	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.
 | // NB: Work with a copy of unattend_xml_flags as a paremeter since we will modify it.
 | ||||||
| { | { | ||||||
| 	BOOL r = FALSE, is_hive_mounted = FALSE; | 	BOOL r = FALSE, is_hive_mounted = FALSE; | ||||||
| 	int i; | 	int i, wim_index = 2; | ||||||
| 	const int wim_index = 2; |  | ||||||
| 	const char* offline_hive_name = "RUFUS_OFFLINE_HIVE"; | 	const char* offline_hive_name = "RUFUS_OFFLINE_HIVE"; | ||||||
| 	char boot_wim_path[] = "?:\\sources\\boot.wim", key_path[64]; | 	char boot_wim_path[] = "?:\\sources\\boot.wim", key_path[64]; | ||||||
| 	char appraiserres_dll_src[] = "?:\\sources\\appraiserres.dll"; | 	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 otherwise setup.exe extracts its own.
 | ||||||
| 			appraiserres_dll_src[0] = drive_letter; | 			appraiserres_dll_src[0] = drive_letter; | ||||||
| 			appraiserres_dll_dst[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()); | 				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, | 				CloseHandle(CreateFileU(appraiserres_dll_src, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, | ||||||
| 					NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); | 					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); | 		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\.
 | 		// not, we can just copy our unattend.xml in \sources\$OEM$\$$\Panther\.
 | ||||||
| 		if (flags & UNATTEND_WINPE_SETUP_MASK) { | 		if (flags & UNATTEND_WINPE_SETUP_MASK) { | ||||||
| 			uprintf("Mounting '%s'...", boot_wim_path); | 			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); | 			mount_path = WimMountImage(boot_wim_path, wim_index); | ||||||
| 			if (mount_path == NULL) | 			if (mount_path == NULL) | ||||||
| 				goto out; | 				goto out; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue