Skip to content

Commit

Permalink
[wue] add fallback to index 1 if boot.wim index 2 is not available
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
pbatard committed Aug 2, 2022
1 parent eda1f59 commit fbad636
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 134 deletions.
1 change: 1 addition & 0 deletions .vs/rufus.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@
<ClInclude Include="..\src\dev.h" />
<ClInclude Include="..\src\ui.h" />
<ClInclude Include="..\src\ui_data.h" />
<ClInclude Include="..\src\vhd.h" />
<ClInclude Include="..\src\winio.h" />
<ClInclude Include="..\src\wue.h" />
</ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions .vs/rufus.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@
<ClInclude Include="..\src\wue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\vhd.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\res\rufus.ico">
Expand Down
2 changes: 1 addition & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
1 change: 1 addition & 0 deletions src/format.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "localization.h"

#include "br.h"
#include "vhd.h"
#include "wue.h"
#include "fat16.h"
#include "fat32.h"
Expand Down
6 changes: 3 additions & 3 deletions src/rufus.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

#include "ui.h"
#include "re.h"
#include "vhd.h"
#include "wue.h"
#include "drive.h"
#include "settings.h"
Expand Down Expand Up @@ -3770,9 +3771,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// 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
Expand Down
9 changes: 0 additions & 9 deletions src/rufus.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 5 additions & 5 deletions src/rufus.rc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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"
Expand Down
179 changes: 70 additions & 109 deletions src/vhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <rpc.h>
#include <time.h>

#include "vhd.h"
#include "rufus.h"
#include "missing.h"
#include "resource.h"
Expand All @@ -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));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -823,6 +720,70 @@ BOOL WimExtractFile(const char* image, int index, const char* src, const char* d
|| ((wim_flags & WIM_HAS_API_EXTRACT) && WimExtractFile_API(image, index, src, dst, bSilent)) );
}

/// <summary>
/// Find if a specific index belongs to a WIM image.
/// </summary>
/// <param name="image">The path to the WIM file.</param>
/// <param name="index">The (non-zero) value of the index to check.</param>
/// <returns>TRUE if the index was found in the image, FALSE otherwise.</returns>
BOOL WimIsValidIndex(const char* image, int index)
{
int i = 1;
BOOL r = FALSE;
DWORD dw = 0;
HANDLE hWim = NULL;
HANDLE hFile = NULL;
char xml_file[MAX_PATH] = { 0 };
char* str;
wchar_t* wimage = utf8_to_wchar(image);
wchar_t* wim_info;

PF_INIT_OR_OUT(WIMCreateFile, Wimgapi);
PF_INIT_OR_OUT(WIMGetImageInformation, Wimgapi);
PF_INIT_OR_OUT(WIMCloseHandle, Wimgapi);

// Zero indexes are invalid
if (index == 0)
return FALSE;

hWim = pfWIMCreateFile(wimage, WIM_GENERIC_READ, WIM_OPEN_EXISTING,
(img_report.wininst_version >= SPECIAL_WIM_VERSION) ? WIM_UNDOCUMENTED_BULLSHIT : 0, 0, NULL);
if (hWim == NULL) {
uprintf(" Could not access image: %s", WindowsErrorString());
goto out;
}

if (!pfWIMGetImageInformation(hWim, &wim_info, &dw) || (dw == 0)) {
uprintf(" Could not access WIM info: %s", WindowsErrorString());
goto out;
}

if ((GetTempFileNameU(temp_dir, APPLICATION_NAME, 0, xml_file) == 0) || (xml_file[0] == 0))
static_strcpy(xml_file, ".\\RufVXml.tmp");
DeleteFileU(xml_file);
hFile = CreateFileU(xml_file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if ((hFile == INVALID_HANDLE_VALUE) || (!WriteFile(hFile, wim_info, dw, &dw, NULL)))
goto out;

while ((str = get_token_data_file_indexed("IMAGE INDEX", xml_file, i)) != NULL) {
if (atoi(str) == index) {
r = TRUE;
break;
}
i++;
}

out:
if (hWim != NULL)
pfWIMCloseHandle(hWim);
safe_closehandle(hFile);
if (xml_file[0] != 0)
DeleteFileU(xml_file);
safe_free(wimage);
return r;
}

// Apply a WIM image using wimgapi.dll (Windows 7 or later)
// https://docs.microsoft.com/en-us/previous-versions/msdn10/dd851944(v=msdn.10)
// To get progress, we must run this call within its own thread
Expand Down
Loading

0 comments on commit fbad636

Please sign in to comment.