mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[efi] add support for Windows 7 UEFI boot
* Add WIM file handling in vhd.c to extract bootx64.efi * x64 only, since Microsoft does not provide Win7 x86 EFI support
This commit is contained in:
		
							parent
							
								
									997c0a0f28
								
							
						
					
					
						commit
						84e4aecfcd
					
				
					 11 changed files with 186 additions and 21 deletions
				
			
		|  | @ -175,6 +175,7 @@ | |||
|     <ClCompile Include="..\stdio.c" /> | ||||
|     <ClCompile Include="..\stdlg.c" /> | ||||
|     <ClCompile Include="..\syslinux.c" /> | ||||
|     <ClCompile Include="..\vhd.c" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="..\badblocks.h" /> | ||||
|  |  | |||
|  | @ -54,6 +54,9 @@ | |||
|     <ClCompile Include="..\net.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\vhd.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="..\rufus.h"> | ||||
|  |  | |||
|  | @ -41,4 +41,5 @@ SOURCES=rufus.c          \ | |||
|         badblocks.c      \ | ||||
|         drive.c          \ | ||||
|         syslinux.c       \ | ||||
|         vhd.c            \ | ||||
|         rufus.rc | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ pkg_v_rc_0 = @echo "  RC     $@"; | |||
| %_rc.o: %.rc | ||||
| 	$(pkg_v_rc)$(WINDRES) $(AM_RCFLAGS) -i $< -o $@ | ||||
| 
 | ||||
| rufus_SOURCES = drive.c icon.c parser.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c | ||||
| rufus_SOURCES = drive.c icon.c parser.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c vhd.c format.c stdio.c stdlg.c rufus.c | ||||
| rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) | ||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | ||||
| rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \ | ||||
|  |  | |||
|  | @ -47,8 +47,9 @@ am_rufus_OBJECTS = rufus-drive.$(OBJEXT) rufus-icon.$(OBJEXT) \ | |||
| 	rufus-parser.$(OBJEXT) rufus-iso.$(OBJEXT) rufus-net.$(OBJEXT) \
 | ||||
| 	rufus-dos.$(OBJEXT) rufus-dos_locale.$(OBJEXT) \
 | ||||
| 	rufus-badblocks.$(OBJEXT) rufus-syslinux.$(OBJEXT) \
 | ||||
| 	rufus-format.$(OBJEXT) rufus-stdio.$(OBJEXT) \
 | ||||
| 	rufus-stdlg.$(OBJEXT) rufus-rufus.$(OBJEXT) | ||||
| 	rufus-vhd.$(OBJEXT) rufus-format.$(OBJEXT) \
 | ||||
| 	rufus-stdio.$(OBJEXT) rufus-stdlg.$(OBJEXT) \
 | ||||
| 	rufus-rufus.$(OBJEXT) | ||||
| rufus_OBJECTS = $(am_rufus_OBJECTS) | ||||
| rufus_DEPENDENCIES = rufus_rc.o ms-sys/libmssys.a \
 | ||||
| 	syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
 | ||||
|  | @ -183,7 +184,7 @@ SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/u | |||
| pkg_v_rc = $(pkg_v_rc_$(V)) | ||||
| pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY)) | ||||
| pkg_v_rc_0 = @echo "  RC     $@"; | ||||
| rufus_SOURCES = drive.c icon.c parser.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c | ||||
| rufus_SOURCES = drive.c icon.c parser.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c vhd.c format.c stdio.c stdlg.c rufus.c | ||||
| rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) | ||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | ||||
| rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
 | ||||
|  | @ -316,6 +317,14 @@ rufus-syslinux.obj: syslinux.c | |||
| 	$(AM_V_CC) @AM_BACKSLASH@ | ||||
| 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-syslinux.obj `if test -f 'syslinux.c'; then $(CYGPATH_W) 'syslinux.c'; else $(CYGPATH_W) '$(srcdir)/syslinux.c'; fi` | ||||
| 
 | ||||
| rufus-vhd.o: vhd.c | ||||
| 	$(AM_V_CC) @AM_BACKSLASH@ | ||||
| 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-vhd.o `test -f 'vhd.c' || echo '$(srcdir)/'`vhd.c | ||||
| 
 | ||||
| rufus-vhd.obj: vhd.c | ||||
| 	$(AM_V_CC) @AM_BACKSLASH@ | ||||
| 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-vhd.obj `if test -f 'vhd.c'; then $(CYGPATH_W) 'vhd.c'; else $(CYGPATH_W) '$(srcdir)/vhd.c'; fi` | ||||
| 
 | ||||
| rufus-format.o: format.c | ||||
| 	$(AM_V_CC) @AM_BACKSLASH@ | ||||
| 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-format.o `test -f 'format.c' || echo '$(srcdir)/'`format.c | ||||
|  |  | |||
							
								
								
									
										21
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										21
									
								
								src/format.c
									
										
									
									
									
								
							|  | @ -1122,6 +1122,8 @@ DWORD WINAPI FormatThread(LPVOID param) | |||
| 	char drive_name[] = "?:\\"; | ||||
| 	char bb_msg[512]; | ||||
| 	char logfile[MAX_PATH], *userdir; | ||||
| 	char wim_image[] = "?:\\sources\\install.wim"; | ||||
| 	char efi_dst[] = "?:\\efi\\boot\\bootx64.efi"; | ||||
| 	FILE* log_fd; | ||||
| 
 | ||||
| 	hPhysicalDrive = GetDriveHandle(num, NULL, TRUE, TRUE); | ||||
|  | @ -1250,7 +1252,7 @@ DWORD WINAPI FormatThread(LPVOID param) | |||
| 	if (IsChecked(IDC_DOS)) { | ||||
| 		if (pt == PT_GPT) { | ||||
| 			// For once, no need to do anything - just check our sanity
 | ||||
| 			if ( (dt != DT_ISO) || (!iso_report.has_efi) || (fs > FS_FAT32) ) { | ||||
| 			if ( (dt != DT_ISO) || (!IS_EFI(iso_report)) || (fs > FS_FAT32) ) { | ||||
| 				uprintf("Spock gone crazy error!\n"); | ||||
| 				FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE; | ||||
| 				goto out; | ||||
|  | @ -1310,6 +1312,23 @@ DWORD WINAPI FormatThread(LPVOID param) | |||
| 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; | ||||
| 					goto out; | ||||
| 				} | ||||
| 				if ((pt == PT_GPT) && (!iso_report.has_efi) && (iso_report.has_win7_efi)) { | ||||
| 					// TODO: progress
 | ||||
| 					PrintStatus(0, TRUE, "Win7 EFI boot setup (this may take a while)..."); | ||||
| 					wim_image[0] = drive_name[0]; | ||||
| 					efi_dst[0] = drive_name[0]; | ||||
| 					efi_dst[sizeof(efi_dst) - sizeof("\\bootx64.efi")] = 0; | ||||
| 					if (!CreateDirectoryA(efi_dst, 0)) { | ||||
| 						uprintf("Could not create directory '%s': %s\n", WindowsErrorString()); | ||||
| 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH); | ||||
| 					} else { | ||||
| 						efi_dst[sizeof(efi_dst) - sizeof("\\bootx64.efi")] = '\\'; | ||||
| 						if (!WIMExtractFile(wim_image, 1, "Windows\\Boot\\EFI\\bootmgfw.efi", efi_dst)) { | ||||
| 							uprintf("Failed to setup Win7 EFI boot\n"); | ||||
| 							FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if ( (pt == PT_MBR) && (IS_WINPE(iso_report.winpe)) ) { | ||||
| 				// Apply WinPe fixup
 | ||||
|  |  | |||
							
								
								
									
										11
									
								
								src/iso.c
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								src/iso.c
									
										
									
									
									
								
							|  | @ -55,7 +55,7 @@ RUFUS_ISO_REPORT iso_report; | |||
| int64_t iso_blocking_status = -1; | ||||
| #define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0) | ||||
| static const char* psz_extract_dir; | ||||
| static const char* bootmgr_name = "bootmgr"; | ||||
| static const char* bootmgr_efi_name = "bootmgr.efi"; | ||||
| static const char* ldlinux_name = "ldlinux.sys"; | ||||
| static const char* efi_dirname = "/efi/boot"; | ||||
| static const char* isolinux_name[] = { "isolinux.cfg", "syslinux.cfg", "extlinux.conf"}; | ||||
|  | @ -123,9 +123,14 @@ static __inline BOOL check_iso_props(const char* psz_dirname, BOOL* is_syslinux_ | |||
| 	} | ||||
| 
 | ||||
| 	if (scan_only) { | ||||
| 		// Check for a "bootmgr" file in root (psz_path = "")
 | ||||
| 		if ((*psz_dirname == 0) && (safe_stricmp(psz_basename, bootmgr_name) == 0)) | ||||
| 		// Check for a "bootmgr(.efi)" file in root (psz_path = "")
 | ||||
| 		if (*psz_dirname == 0) { | ||||
| 			if (safe_strnicmp(psz_basename, bootmgr_efi_name, sizeof(bootmgr_efi_name)-4) == 0) | ||||
| 				iso_report.has_bootmgr = TRUE; | ||||
| 			if (safe_stricmp(psz_basename, bootmgr_efi_name) == 0) { | ||||
| 				iso_report.has_win7_efi = TRUE; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// Check for the EFI boot directory
 | ||||
| 		if (safe_stricmp(psz_dirname, efi_dirname) == 0) | ||||
|  |  | |||
							
								
								
									
										16
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -491,7 +491,7 @@ static void SetFSFromISO(void) | |||
| 	} | ||||
| 
 | ||||
| 	// Syslinux and EFI have precedence over bootmgr
 | ||||
| 	if ((iso_report.has_isolinux) || (iso_report.has_efi)) { | ||||
| 	if ((iso_report.has_isolinux) || (IS_EFI(iso_report))) { | ||||
| 		if (fs_mask & (1<<FS_FAT32)) { | ||||
| 			selected_fs = FS_FAT32; | ||||
| 		} else if (fs_mask & (1<<FS_FAT16)) { | ||||
|  | @ -633,7 +633,7 @@ const GUID PARTITION_BASIC_DATA_GUID = { 0xebd0a0a2, 0xb9e5, 0x4433, {0x87, 0xc0 | |||
| #endif | ||||
| BOOL CreatePartition(HANDLE hDrive) | ||||
| { | ||||
| 	CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {0}}; | ||||
| 	CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {{0}}}; | ||||
| 	DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0}; | ||||
| 	BOOL r; | ||||
| 	DWORD size; | ||||
|  | @ -1354,8 +1354,10 @@ DWORD WINAPI ISOScanThread(LPVOID param) | |||
| 		safe_free(iso_path); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	uprintf("ISO label: '%s'\r\n  Size: %lld bytes\r\n  Has a >4GB file: %s\r\n  Uses EFI: %s\r\n  Uses Bootmgr: %s\r\n  Uses WinPE: %s%s\r\n  Uses isolinux: %s\n", | ||||
| 		iso_report.label, iso_report.projected_size, iso_report.has_4GB_file?"Yes":"No",  iso_report.has_efi?"Yes":"No", iso_report.has_bootmgr?"Yes":"No", | ||||
| 	// TODO: 4GB and UEFI = BAD!!!
 | ||||
| 	uprintf("ISO label: '%s'\r\n  Size: %lld bytes\r\n  Has a >4GB file: %s\r\n  Uses EFI: %s%s\r\n  Uses Bootmgr: %s\r\n  Uses WinPE: %s%s\r\n  Uses isolinux: %s\n", | ||||
| 		iso_report.label, iso_report.projected_size, iso_report.has_4GB_file?"Yes":"No", (iso_report.has_efi || iso_report.has_win7_efi)?"Yes":"No",  | ||||
| 		(iso_report.has_win7_efi && (!iso_report.has_efi))?" (win7_x64)":"", iso_report.has_bootmgr?"Yes":"No", | ||||
| 		IS_WINPE(iso_report.winpe)?"Yes":"No", (iso_report.uses_minint)?" (with /minint)":"", iso_report.has_isolinux?"Yes":"No"); | ||||
| 	if (iso_report.has_isolinux) { | ||||
| 		for (i=0; i<NB_OLD_C32; i++) { | ||||
|  | @ -1922,7 +1924,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 						} | ||||
| 						fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); | ||||
| 						pt = (int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme)); | ||||
| 						if ((pt == PT_GPT) && ((!iso_report.has_efi) || ((fs > FS_FAT32)))) { | ||||
| 						if ((pt == PT_GPT) && ((!IS_EFI(iso_report)) || ((fs > FS_FAT32)))) { | ||||
| 							MessageBoxA(hMainDialog, "When using GPT, only EFI bootable ISOs are supported. " | ||||
| 								"Please select an EFI bootable ISO or change the Partition Scheme to MBR.", "Unsupported GPT ISO...", MB_OK|MB_ICONERROR); | ||||
| 							break; | ||||
|  | @ -1937,8 +1939,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 							} | ||||
| 							break; | ||||
| 						} else if (((fs == FS_FAT16)||(fs == FS_FAT32)) && ((!iso_report.has_isolinux) && (pt != PT_GPT))) { | ||||
| 							MessageBoxA(hMainDialog, "Only 'isolinux' based ISO " | ||||
| 								"images can currently be used with FAT.", "Unsupported ISO...", MB_OK|MB_ICONERROR); | ||||
| 							MessageBoxA(hMainDialog, "Only isolinux or EFI based ISO " | ||||
| 								"images can currently be used with FAT/FAT32.", "Unsupported ISO...", MB_OK|MB_ICONERROR); | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
|  |  | |||
|  | @ -181,6 +181,7 @@ typedef struct { | |||
| #define WINPE_MININT    0x2A | ||||
| #define WINPE_I386      0x15 | ||||
| #define IS_WINPE(r)     (((r&WINPE_MININT) == WINPE_MININT)||((r&WINPE_I386) == WINPE_I386)) | ||||
| #define IS_EFI(r)       ((r.has_efi) || (r.has_win7_efi)) | ||||
| 
 | ||||
| typedef struct { | ||||
| 	char label[192];		/* 3*64 to account for UTF-8 */ | ||||
|  | @ -191,6 +192,7 @@ typedef struct { | |||
| 	BOOL has_4GB_file; | ||||
| 	BOOL has_bootmgr; | ||||
| 	BOOL has_efi; | ||||
| 	BOOL has_win7_efi; | ||||
| 	BOOL has_isolinux; | ||||
| 	BOOL has_autorun; | ||||
| 	BOOL has_old_c32[NB_OLD_C32]; | ||||
|  | @ -296,6 +298,7 @@ extern char* get_token_data_buffer(const char* token, unsigned int n, const char | |||
| extern char* insert_section_data(const char* filename, const char* section, const char* data, BOOL dos2unix); | ||||
| extern char* replace_in_token_data(const char* filename, const char* token, const char* src, const char* rep, BOOL dos2unix); | ||||
| extern void parse_update(char* buf, size_t len); | ||||
| extern BOOL WIMExtractFile(const char* wim_image, int index, const char* src, const char* dst); | ||||
| 
 | ||||
| __inline static BOOL UnlockDrive(HANDLE hDrive) | ||||
| { | ||||
|  |  | |||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL | |||
| IDD_DIALOG DIALOGEX 12, 12, 206, 316 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_APPWINDOW | ||||
| CAPTION "Rufus v1.3.1.223" | ||||
| CAPTION "Rufus v1.3.1.224" | ||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||
| BEGIN | ||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,278,50,14 | ||||
|  | @ -274,8 +274,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 1,3,1,223 | ||||
|  PRODUCTVERSION 1,3,1,223 | ||||
|  FILEVERSION 1,3,1,224 | ||||
|  PRODUCTVERSION 1,3,1,224 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -292,13 +292,13 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "1.3.1.223" | ||||
|             VALUE "FileVersion", "1.3.1.224" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "(c) 2011-2012 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||
|             VALUE "OriginalFilename", "rufus.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "1.3.1.223" | ||||
|             VALUE "ProductVersion", "1.3.1.224" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
							
								
								
									
										122
									
								
								src/vhd.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/vhd.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,122 @@ | |||
| /*
 | ||||
|  * Rufus: The Reliable USB Formatting Utility | ||||
|  * Virtual Disk Handling functions | ||||
|  * Copyright (c) 2013 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 "rufus.h" | ||||
| #include "msapi_utf8.h" | ||||
| 
 | ||||
| #define WIM_GENERIC_READ	GENERIC_READ | ||||
| #define WIM_OPEN_EXISTING	OPEN_EXISTING | ||||
| 
 | ||||
| typedef HANDLE (WINAPI *WIMCreateFile_t)( | ||||
| 	PWSTR   pszWimPath, | ||||
| 	DWORD   dwDesiredAccess, | ||||
| 	DWORD   dwCreationDisposition, | ||||
| 	DWORD   dwFlagsAndAttributes, | ||||
| 	DWORD   dwCompressionType, | ||||
| 	PDWORD  pdwCreationResult | ||||
| ); | ||||
| 
 | ||||
| typedef BOOL (WINAPI *WIMSetTemporaryPath_t)( | ||||
| 	HANDLE  hWim, | ||||
| 	PWSTR   pszPath | ||||
| ); | ||||
| 
 | ||||
| typedef HANDLE (WINAPI *WIMLoadImage_t)( | ||||
| 	HANDLE  hWim, | ||||
| 	DWORD   dwImageIndex | ||||
| ); | ||||
| 
 | ||||
| typedef BOOL (WINAPI *WIMExtractImagePath_t)( | ||||
| 	HANDLE  hImage, | ||||
| 	PWSTR   pszImagePath, | ||||
| 	PWSTR   pszDestinationPath, | ||||
| 	DWORD   dwExtractFlags | ||||
| ); | ||||
| 
 | ||||
| typedef BOOL (WINAPI *WIMCloseHandle_t)( | ||||
| 	HANDLE  hObj | ||||
| ); | ||||
| 
 | ||||
| // Extract a file from a WIM image
 | ||||
| // NB: Don't bother trying to get progress from a WIM callback - it doesn't work!
 | ||||
| BOOL WIMExtractFile(const char* image, int index, const char* src, const char* dst) | ||||
| { | ||||
| 	BOOL r = FALSE; | ||||
| 	DWORD dw = 0; | ||||
| 	HANDLE hWim = NULL; | ||||
| 	HANDLE hImage = NULL; | ||||
| 	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); | ||||
| 	PF_DECL(WIMCreateFile); | ||||
| 	PF_DECL(WIMSetTemporaryPath); | ||||
| 	PF_DECL(WIMLoadImage); | ||||
| 	PF_DECL(WIMExtractImagePath); | ||||
| 	PF_DECL(WIMCloseHandle); | ||||
| 
 | ||||
| 	PF_INIT_OR_OUT(WIMCreateFile, wimgapi); | ||||
| 	PF_INIT_OR_OUT(WIMSetTemporaryPath, wimgapi); | ||||
| 	PF_INIT_OR_OUT(WIMLoadImage, wimgapi); | ||||
| 	PF_INIT_OR_OUT(WIMExtractImagePath, wimgapi); | ||||
| 	PF_INIT_OR_OUT(WIMCloseHandle, wimgapi); | ||||
| 
 | ||||
| 	// TODO: check for NULL and missing wimgapi.dll
 | ||||
| 
 | ||||
| 	if (GetTempPathW(ARRAYSIZE(wtemp), wtemp) == 0) { | ||||
| 		uprintf("Could not fetch temp path: %s\n", WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	uprintf("Opening: %s (index #%d)\n", image, index); | ||||
| 	hWim = pfWIMCreateFile(wimage, WIM_GENERIC_READ, WIM_OPEN_EXISTING, 0, 0, &dw); | ||||
| 	if (hWim == NULL) { | ||||
| 		uprintf("  Error: '%s': %s\n", WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!pfWIMSetTemporaryPath(hWim, wtemp)) { | ||||
| 		uprintf("  Error setting temp path: %s\n", WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	hImage = pfWIMLoadImage(hWim, (DWORD)index); | ||||
| 	if (hImage == NULL) { | ||||
| 		uprintf("  Error setting index: %s.\n", WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	uprintf("Extracting: %s (From \\%s)\n", dst, src); | ||||
| 	if (!pfWIMExtractImagePath(hImage, wsrc, wdst, 0)) { | ||||
| 		uprintf("  Could not extract file: %s.\n", WindowsErrorString()); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	r = TRUE; | ||||
| 
 | ||||
| out: | ||||
| 	if ((hImage != NULL) || (hWim != NULL)) { | ||||
| 		uprintf("Closing: %s\n", image); | ||||
| 	} | ||||
| 	if (hImage != NULL) pfWIMCloseHandle(hImage); | ||||
| 	if (hWim != NULL) pfWIMCloseHandle(hWim); | ||||
| 	safe_free(wimage); | ||||
| 	safe_free(wsrc); | ||||
| 	safe_free(wdst); | ||||
| 	return r; | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue