diff --git a/.vs/rufus.vcxproj b/.vs/rufus.vcxproj
index 11b65194..15e92970 100644
--- a/.vs/rufus.vcxproj
+++ b/.vs/rufus.vcxproj
@@ -405,6 +405,7 @@
+
diff --git a/.vs/rufus.vcxproj.filters b/.vs/rufus.vcxproj.filters
index d42d2867..2e10c9d3 100644
--- a/.vs/rufus.vcxproj.filters
+++ b/.vs/rufus.vcxproj.filters
@@ -188,6 +188,9 @@
Header Files
+
+ Header Files
+
diff --git a/configure b/configure
index 299b4470..62786484 100755
--- a/configure
+++ b/configure
@@ -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"
diff --git a/configure.ac b/configure.ac
index 9cecadb7..c5624f67 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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])
diff --git a/src/format.c b/src/format.c
index c2383a37..155390bf 100644
--- a/src/format.c
+++ b/src/format.c
@@ -44,6 +44,7 @@
#include "localization.h"
#include "br.h"
+#include "vhd.h"
#include "wue.h"
#include "fat16.h"
#include "fat32.h"
diff --git a/src/rufus.c b/src/rufus.c
index 71e77450..d95fc9f9 100755
--- a/src/rufus.c
+++ b/src/rufus.c
@@ -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
diff --git a/src/rufus.h b/src/rufus.h
index 63f1d42b..c96f8c9d 100644
--- a/src/rufus.h
+++ b/src/rufus.h
@@ -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);
diff --git a/src/rufus.rc b/src/rufus.rc
index e9a00350..3496684e 100644
--- a/src/rufus.rc
+++ b/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"
diff --git a/src/vhd.c b/src/vhd.c
index c6410191..ab41746b 100644
--- a/src/vhd.c
+++ b/src/vhd.c
@@ -23,6 +23,7 @@
#include
#include
+#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)) );
}
+///
+/// Find if a specific index belongs to a WIM image.
+///
+/// The path to the WIM file.
+/// The (non-zero) value of the index to check.
+/// TRUE if the index was found in the image, FALSE otherwise.
+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
diff --git a/src/vhd.h b/src/vhd.h
new file mode 100644
index 00000000..e5f1f86f
--- /dev/null
+++ b/src/vhd.h
@@ -0,0 +1,141 @@
+/*
+ * Rufus: The Reliable USB Formatting Utility
+ * Virtual Disk Handling definitions and prototypes
+ * Copyright © 2022 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
+#include
+
+#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);
diff --git a/src/wue.c b/src/wue.c
index 1f19abfc..5eb51d98 100644
--- a/src/wue.c
+++ b/src/wue.c
@@ -24,6 +24,7 @@
#include
#include "rufus.h"
+#include "vhd.h"
#include "drive.h"
#include "format.h"
#include "missing.h"
@@ -359,7 +360,7 @@ out:
/// -2 on user cancel, -1 on other error, >=0 on success.
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;