diff --git a/src/.msvc/rufus.vcxproj b/src/.msvc/rufus.vcxproj
index 84a30fc7..b9027638 100644
--- a/src/.msvc/rufus.vcxproj
+++ b/src/.msvc/rufus.vcxproj
@@ -175,6 +175,7 @@
+
diff --git a/src/.msvc/rufus.vcxproj.filters b/src/.msvc/rufus.vcxproj.filters
index 53302d1c..068f5682 100644
--- a/src/.msvc/rufus.vcxproj.filters
+++ b/src/.msvc/rufus.vcxproj.filters
@@ -54,6 +54,9 @@
Source Files
+
+ Source Files
+
diff --git a/src/.msvc/rufus_sources b/src/.msvc/rufus_sources
index 78a4486d..59dbaf1a 100644
--- a/src/.msvc/rufus_sources
+++ b/src/.msvc/rufus_sources
@@ -41,4 +41,5 @@ SOURCES=rufus.c \
badblocks.c \
drive.c \
syslinux.c \
+ vhd.c \
rufus.rc
diff --git a/src/Makefile.am b/src/Makefile.am
index cf181606..1aa6f424 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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 \
diff --git a/src/Makefile.in b/src/Makefile.in
index af1bdff2..87a9faaa 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -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
diff --git a/src/format.c b/src/format.c
index 943567cc..9a580107 100644
--- a/src/format.c
+++ b/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
diff --git a/src/iso.c b/src/iso.c
index 4737cf44..60861257 100644
--- a/src/iso.c
+++ b/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))
- iso_report.has_bootmgr = TRUE;
+ // 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)
diff --git a/src/rufus.c b/src/rufus.c
index 8ef7a2e9..4215e223 100644
--- a/src/rufus.c
+++ b/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<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 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;
}
}
diff --git a/src/rufus.h b/src/rufus.h
index ab463bc5..f6d830c1 100644
--- a/src/rufus.h
+++ b/src/rufus.h
@@ -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)
{
diff --git a/src/rufus.rc b/src/rufus.rc
index 3a878dd5..df2c0b27 100644
--- a/src/rufus.rc
+++ b/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"
diff --git a/src/vhd.c b/src/vhd.c
new file mode 100644
index 00000000..db8aca5c
--- /dev/null
+++ b/src/vhd.c
@@ -0,0 +1,122 @@
+/*
+ * Rufus: The Reliable USB Formatting Utility
+ * Virtual Disk Handling functions
+ * Copyright (c) 2013 Pete Batard
+ *
+ * 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 .
+ */
+
+#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;
+}