mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-29 05:55:30 -04: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
179
src/vhd.c
179
src/vhd.c
|
@ -23,6 +23,7 @@
|
|||
#include <rpc.h>
|
||||
#include <time.h>
|
||||
|
||||
#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)) );
|
||||
}
|
||||
|
||||
/// <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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue