1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2024-08-14 23:57:05 +00:00

[core] add option to bypass TPM 2.0/Secure Boot/RAM requirements for Windows 11 ISOs

* If 'Extended Windows 11 Installation' mode is selected, the system registry hive of
  'sources\boot.wim' is patched to add the Setup\LabConfig registry keys that bypass
  the TPM 2.0/Secure Boot/8GB+ RAM Windows 11 system requirements.
This commit is contained in:
Pete Batard 2021-10-08 19:22:33 +01:00
parent a10b8e8c54
commit b043db33e6
No known key found for this signature in database
GPG key ID: 38E0CF5E69EDD671
11 changed files with 334 additions and 68 deletions

View file

@ -5,8 +5,9 @@ o Version 3.16 (2021.10.??)
Fix log not being saved on exit
Add UEFI Shell ISO downloads
Add support for Intel NUC card readers
Improve Windows version reporting
Add Windows 11 extended installation support (disables TPM or Secure Boot requirement)
Improve Windows 11 support
Improve Windows version reporting
Speed up clearing of MBR/GPT
o Version 3.15 (2021.08.03)

View file

@ -11,7 +11,7 @@
<Identity
Name="19453.net.Rufus"
Publisher="CN=7AC86D13-3E5A-491A-ADD5-80095C212740"
Version="3.16.1831.0" />
Version="3.16.1832.0" />
<Properties>
<DisplayName>Rufus</DisplayName>

View file

@ -559,8 +559,9 @@ t MSG_301 "Show application settings"
t MSG_302 "Show information about this application"
t MSG_303 "Show the log"
t MSG_304 "Create a disk image of the selected device"
t MSG_305 "Use this option to indicate whether you want to use this device to install Windows on another disk, "
"or if you want to run Windows directly from this drive (Windows To Go)."
t MSG_305 "Use this option to indicate if you want to run Windows directly from this drive (Windows To Go) or if you "
"want to install Windows to a different disk.\r\nIn 'Extended Windows 11 Installation' mode, Rufus patches the "
"media so that Windows 11 can be installed on platforms that don't meet the TPM 2.0 or Secure Boot requirements."
# You can see this status message by pressing <Ctrl>-<Alt>-<Z> and then selecting START.
# It's the same as MSG_286 but with a process that *may* be faster, hence the name.
t MSG_306 "Fast-zeroing drive: %s"
@ -582,6 +583,9 @@ t MSG_319 "Ignore Boot Marker"
t MSG_320 "Refreshing partition layout (%s)..."
t MSG_321 "The image you have selected is an ISOHybrid, but its creators have not made it compatible with ISO/File "
"copy mode.\nAs a result, DD image writing mode will be enforced."
t MSG_322 "Standard Windows 11 Installation (TPM 2.0 / Secure Boot / 8GB+ RAM)"
t MSG_323 "Extended Windows 11 Installation (no TPM / no Secure Boot / 8GB- RAM)"
t MSG_324 "Removing Windows 11 installation restrictions (%s)"
#########################################################################
l "ar-SA" "Arabic (العربية)" 0x0401, 0x0801, 0x0c01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001

View file

@ -1417,7 +1417,7 @@ static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp)
UpdateProgressWithInfo(OP_FILE_COPY, MSG_267, wim_proc_files + 2 * wim_extra_files, wim_nb_files);
uprintf("Disable the use of the Windows Recovery Environment using command:");
uprintf("Disabling use of the Windows Recovery Environment using command:");
static_sprintf(cmd, "%s\\bcdedit.exe /store %s\\EFI\\Microsoft\\Boot\\BCD /set {default} recoveryenabled no",
sysnative_dir, (use_esp) ? ms_efi : drive_name);
uprintf(cmd);
@ -1433,6 +1433,80 @@ static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp)
return TRUE;
}
/*
* Edit sources/boot.wim registry to remove Windows 11 install restrictions
*/
BOOL RemoveWindows11Restrictions(char drive_letter)
{
BOOL r = FALSE, is_hive_mounted = FALSE;
int i;
const int wim_index = 2;
const char* offline_hive_name = "RUFUS_OFFLINE_HIVE";
const char* key_name[] = { "BypassTPMCheck", "BypassSecureBootCheck", "BypassRAMCheck" };
char boot_wim_path[] = "#:\\sources\\boot.wim", key_path[64];
char* mount_path = NULL;
char path[MAX_PATH];
HKEY hKey = NULL, hSubKey = NULL;
LSTATUS status;
DWORD dwDisp, dwVal = 1;
boot_wim_path[0] = drive_letter;
PrintInfo(0, MSG_324, lmprintf(MSG_307));
uprintf("Mounting '%s'...", boot_wim_path);
mount_path = WimMountImage(boot_wim_path, wim_index);
if (mount_path == NULL)
goto out;
static_sprintf(path, "%s\\Windows\\System32\\config\\SYSTEM", mount_path);
if (!MountRegistryHive(HKEY_LOCAL_MACHINE, offline_hive_name, path))
goto out;
is_hive_mounted = TRUE;
static_sprintf(key_path, "%s\\Setup", offline_hive_name);
status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, key_path, 0, KEY_READ | KEY_CREATE_SUB_KEY, &hKey);
if (status != ERROR_SUCCESS) {
SetLastError(status);
uprintf("Could not open 'HKLM\\SYSTEM\\Setup' registry key: %s", WindowsErrorString());
goto out;
}
status = RegCreateKeyExA(hKey, "LabConfig", 0, NULL, 0,
KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hSubKey, &dwDisp);
if (status != ERROR_SUCCESS) {
SetLastError(status);
uprintf("Could not create 'HKLM\\SYSTEM\\Setup\\LabConfig' registry key: %s", WindowsErrorString());
goto out;
}
for (i = 0; i < ARRAYSIZE(key_name); i++) {
status = RegSetValueExA(hSubKey, key_name[i], 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD));
if (status != ERROR_SUCCESS) {
SetLastError(status);
uprintf("Could not set 'HKLM\\SYSTEM\\Setup\\LabConfig\\%s' registry key: %s",
key_name[i], WindowsErrorString());
goto out;
}
uprintf("Created 'HKLM\\SYSTEM\\Setup\\LabConfig\\%s' registry key", key_name[i]);
}
r = TRUE;
out:
if (hSubKey != NULL)
RegCloseKey(hSubKey);
if (hKey != NULL)
RegCloseKey(hKey);
if (is_hive_mounted)
UnmountRegistryHive(HKEY_LOCAL_MACHINE, offline_hive_name);
if (mount_path) {
uprintf("Unmounting '%s'...", boot_wim_path, wim_index);
WimUnmountImage(boot_wim_path, wim_index);
}
free(mount_path);
return r;
}
static void update_progress(const uint64_t processed_bytes)
{
// NB: We don't really care about resetting this value to UINT64_MAX for a new pass.
@ -1792,7 +1866,7 @@ DWORD WINAPI FormatThread(void* param)
use_large_fat32 = (fs_type == FS_FAT32) && ((SelectedDrive.DiskSize > LARGE_FAT32_SIZE) || (force_large_fat32));
windows_to_go = (image_options & IMOP_WINTOGO) && (boot_type == BT_IMAGE) && HAS_WINTOGO(img_report) &&
ComboBox_GetCurItemData(hImageOption);
(ComboBox_GetCurItemData(hImageOption) == IMOP_WIN_TO_GO);
large_drive = (SelectedDrive.DiskSize > (1*TB));
if (large_drive)
uprintf("Notice: Large drive detected (may produce short writes)");
@ -2256,10 +2330,14 @@ DWORD WINAPI FormatThread(void* param)
}
}
if ( (target_type == TT_BIOS) && HAS_WINPE(img_report) ) {
// Apply WinPe fixup
// Apply WinPE fixup
if (!SetupWinPE(drive_name[0]))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH);
}
if (ComboBox_GetCurItemData(hImageOption) == IMOP_WIN_EXTENDED) {
if (!RemoveWindows11Restrictions(drive_name[0]))
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_PATCH);
}
}
}
UpdateProgress(OP_FINALIZE, -1.0f);

View file

@ -86,7 +86,7 @@ static char szTimer[12] = "00:00:00";
static unsigned int timer;
static char uppercase_select[2][64], uppercase_start[64], uppercase_close[64], uppercase_cancel[64];
extern HANDLE update_check_thread, apply_wim_thread;
extern HANDLE update_check_thread, wim_thread;
extern BOOL enable_iso, enable_joliet, enable_rockridge, enable_extra_hashes;
extern BYTE* fido_script;
extern HWND hFidoDlg;
@ -121,9 +121,9 @@ BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fa
BOOL use_fake_units, preserve_timestamps = FALSE, fast_zeroing = FALSE, app_changed_size = FALSE;
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE;
BOOL write_as_image = FALSE, write_as_esp = FALSE, installed_uefi_ntfs = FALSE, use_vds = FALSE, ignore_boot_marker = FALSE;
BOOL windows_to_go_selected = FALSE, appstore_version = FALSE, is_vds_available = TRUE;
BOOL appstore_version = FALSE, is_vds_available = TRUE;
float fScale = 1.0f;
int dialog_showing = 0, selection_default = BT_IMAGE, persistence_unit_selection = -1;
int dialog_showing = 0, selection_default = BT_IMAGE, persistence_unit_selection = -1, imop_win_sel = 0;
int default_fs, fs_type, boot_type, partition_type, target_type; // file system, boot type, partition type, target type
int force_update = 0, default_thread_priority = THREAD_PRIORITY_ABOVE_NORMAL;
char szFolderPath[MAX_PATH], app_dir[MAX_PATH], system_dir[MAX_PATH], temp_dir[MAX_PATH], sysnative_dir[MAX_PATH];
@ -179,7 +179,7 @@ static void SetAllowedFileSystems(void)
if ((image_path != NULL) && (img_report.has_4GB_file))
break;
if (!HAS_WINDOWS(img_report) || (target_type != TT_BIOS) || allow_dual_uefi_bios) {
if (!HAS_WINTOGO(img_report) || (!ComboBox_GetCurItemData(hImageOption))) {
if (!HAS_WINTOGO(img_report) || (ComboBox_GetCurItemData(hImageOption) != IMOP_WIN_TO_GO)) {
allowed_filesystem[FS_FAT16] = TRUE;
allowed_filesystem[FS_FAT32] = TRUE;
}
@ -258,7 +258,7 @@ static void SetPartitionSchemeAndTargetSystem(BOOL only_target)
boot_type = (int)ComboBox_GetCurItemData(hBootType);
is_windows_to_go_selected = (boot_type == BT_IMAGE) && (image_path != NULL) && HAS_WINTOGO(img_report) &&
ComboBox_GetCurItemData(hImageOption);
(ComboBox_GetCurItemData(hImageOption) == IMOP_WIN_TO_GO);
// If no device is selected, don't populate anything
if (ComboBox_GetCurSel(hDeviceList) < 0)
return;
@ -589,7 +589,7 @@ static void SetFSFromISO(void)
int i, fs_tmp, preferred_fs = FS_UNKNOWN;
uint32_t fs_mask = FS_FAT32 | FS_NTFS;
BOOL windows_to_go = (image_options & IMOP_WINTOGO) && (boot_type == BT_IMAGE) &&
HAS_WINTOGO(img_report) && ComboBox_GetCurItemData(hImageOption);
HAS_WINTOGO(img_report) && (ComboBox_GetCurItemData(hImageOption) == IMOP_WIN_TO_GO);
if (image_path == NULL)
return;
@ -649,7 +649,7 @@ static void SetMBRProps(void)
fs_type = (int)ComboBox_GetCurItemData(hFileSystem);
if ((!mbr_selected_by_user) && ((image_path == NULL) || (boot_type != BT_IMAGE) || (fs_type != FS_NTFS) || HAS_GRUB(img_report) ||
((image_options & IMOP_WINTOGO) && ComboBox_GetCurItemData(hImageOption)) )) {
((image_options & IMOP_WINTOGO) && (ComboBox_GetCurItemData(hImageOption) == IMOP_WIN_TO_GO)) )) {
CheckDlgButton(hMainDialog, IDC_RUFUS_MBR, BST_UNCHECKED);
IGNORE_RETVAL(ComboBox_SetCurSel(hDiskID, 0));
return;
@ -1129,10 +1129,17 @@ static void UpdateImage(BOOL update_image_option_only)
}
ComboBox_ResetContent(hImageOption);
if (!img_report.is_windows_img)
IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_117)), FALSE));
IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_118)), TRUE));
IGNORE_RETVAL(ComboBox_SetCurSel(hImageOption, (img_report.is_windows_img || !windows_to_go_selected) ? 0 : 1));
if (!img_report.is_windows_img) { // Straight install.wim/install.esd only have Windows To Go option
if (img_report.win_version.major == 11) {
IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_322)), IMOP_WIN_STANDARD));
IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_323)), IMOP_WIN_EXTENDED));
} else {
IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_117)), IMOP_WIN_STANDARD));
}
}
IGNORE_RETVAL(ComboBox_SetItemData(hImageOption, ComboBox_AddStringU(hImageOption, lmprintf(MSG_118)), IMOP_WIN_TO_GO));
IGNORE_RETVAL(ComboBox_SetCurSel(hImageOption, imop_win_sel));
}
static uint8_t FindArch(const char* filename)
@ -1226,6 +1233,7 @@ DWORD WINAPI ImageScanThread(LPVOID param)
img_report.is_iso = (BOOLEAN)ExtractISO(image_path, "", TRUE);
img_report.is_bootable_img = IsBootableImage(image_path);
ComboBox_ResetContent(hImageOption);
imop_win_sel = 0;
if ((FormatStatus == (ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_CANCELLED)) ||
(img_report.image_size == 0) ||
@ -1409,7 +1417,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
goto out;
}
if ((image_options & IMOP_WINTOGO) && ComboBox_GetCurItemData(hImageOption)) {
if ((image_options & IMOP_WINTOGO) && (ComboBox_GetCurItemData(hImageOption) == IMOP_WIN_TO_GO)) {
if (fs_type != FS_NTFS) {
// Windows To Go only works for NTFS
MessageBoxExU(hMainDialog, lmprintf(MSG_097, "Windows To Go"), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
@ -2119,6 +2127,24 @@ out:
return ret;
}
#ifdef RUFUS_TEST
extern BOOL RemoveWindows11Restrictions(char drive_letter);
static DWORD WINAPI TestThread(LPVOID param)
{
static BOOL processing = FALSE;
if (processing) {
uprintf("Test thread is already in progress!");
ExitThread(1);
}
processing = TRUE;
RemoveWindows11Restrictions('B');
processing = FALSE;
ExitThread(0);
}
#endif
/*
* Main dialog callback
*/
@ -2155,8 +2181,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
case WM_COMMAND:
#ifdef RUFUS_TEST
if (LOWORD(wParam) == IDC_TEST) {
DWORD DriveIndex = (DWORD)ComboBox_GetItemData(hDeviceList, ComboBox_GetCurSel(hDeviceList));
uprintf("label = '%s'", GetExtFsLabel(DriveIndex, 1));
CreateThread(NULL, 0, TestThread, NULL, 0, NULL);
break;
}
#endif
@ -2333,7 +2358,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
if (HIWORD(wParam) != CBN_SELCHANGE)
break;
SetFileSystemAndClusterSize(NULL);
windows_to_go_selected = (BOOL)ComboBox_GetCurItemData(hImageOption);
imop_win_sel = ComboBox_GetCurSel(hImageOption);
break;
case IDC_PERSISTENCE_SIZE:
if (HIWORD(wParam) == EN_CHANGE) {
@ -3624,8 +3649,8 @@ relaunch:
WriteSetting32(SETTING_DEFAULT_THREAD_PRIORITY, default_thread_priority - THREAD_PRIORITY_ABOVE_NORMAL);
if (format_thread != NULL)
SetThreadPriority(format_thread, default_thread_priority);
if (apply_wim_thread != NULL)
SetThreadPriority(apply_wim_thread, default_thread_priority);
if (wim_thread != NULL)
SetThreadPriority(wim_thread, default_thread_priority);
}
PrintStatus(STATUS_MSG_TIMEOUT, MSG_318, default_thread_priority);
continue;

View file

@ -292,6 +292,13 @@ enum target_type {
// For the partition types we'll use Microsoft's PARTITION_STYLE_### constants
#define PARTITION_STYLE_SFD PARTITION_STYLE_RAW
enum image_option_type {
IMOP_WIN_STANDARD = 0,
IMOP_WIN_EXTENDED,
IMOP_WIN_TO_GO,
IMOP_MAX
};
enum checksum_type {
CHECKSUM_MD5 = 0,
CHECKSUM_SHA1,
@ -552,6 +559,8 @@ extern unsigned char* GetResource(HMODULE module, char* name, char* type, const
extern DWORD GetResourceSize(HMODULE module, char* name, char* type, const char* desc);
extern DWORD RunCommand(const char* cmdline, const char* dir, BOOL log);
extern BOOL CompareGUID(const GUID *guid1, const GUID *guid2);
extern BOOL MountRegistryHive(const HKEY key, const char* pszHiveName, const char* pszHivePath);
extern BOOL UnmountRegistryHive(const HKEY key, const char* pszHiveName);
extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue);
extern LONG GetEntryWidth(HWND hDropDown, const char* entry);
extern uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** buffer, HWND hProgressDialog, BOOL bTaskBarProgress);
@ -581,6 +590,8 @@ extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, co
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 uint8_t IsBootableImage(const char* path);
extern BOOL AppendVHDFooter(const char* vhd_path);
extern int SetWinToGoIndex(void);
@ -594,7 +605,7 @@ extern BOOL WriteFileWithRetry(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBy
LPDWORD lpNumberOfBytesWritten, DWORD nNumRetries);
extern BOOL SetThreadAffinity(DWORD_PTR* thread_affinity, size_t num_threads);
extern BOOL HashFile(const unsigned type, const char* path, uint8_t* sum);
extern BOOL HashBuffer(const unsigned type, const unsigned char* buf, const size_t len, uint8_t* sum);
extern BOOL HashBuffer(const unsigned type, const uint8_t* buf, const size_t len, uint8_t* sum);
extern BOOL IsFileInDB(const char* path);
extern BOOL IsBufferInDB(const unsigned char* buf, const size_t len);
#define printbits(x) _printbits(sizeof(x), &x, 0)

View file

@ -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.16.1831"
CAPTION "Rufus 3.16.1832"
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,16,1831,0
PRODUCTVERSION 3,16,1831,0
FILEVERSION 3,16,1832,0
PRODUCTVERSION 3,16,1832,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.16.1831"
VALUE "FileVersion", "3.16.1832"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2021 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-3.16.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.16.1831"
VALUE "ProductVersion", "3.16.1832"
END
END
BLOCK "VarFileInfo"

View file

@ -24,6 +24,7 @@
#include <windows.h>
#include <sddl.h>
#include <gpedit.h>
#include <assert.h>
#include "rufus.h"
#include "missing.h"
@ -997,3 +998,87 @@ char* GetCurrentMUI(void)
}
return mui_str;
}
/*
* From: https://stackoverflow.com/a/40390858/1069307
*/
BOOL SetPrivilege(HANDLE hToken, LPCWSTR pwzPrivilegeName, BOOL bEnable)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValue(NULL, pwzPrivilegeName, &luid)) {
uprintf("Could not lookup '%S' privilege: %s", pwzPrivilegeName, WindowsErrorString());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
uprintf("Could not %s '%S' privilege: %s",
bEnable ? "enable" : "disable", pwzPrivilegeName, WindowsErrorString());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
uprintf("Error assigning privileges: %s", WindowsErrorString());
return FALSE;
}
return TRUE;
}
/*
* Mount an offline registry hive located at <pszHivePath> into <key>\<pszHiveName>.
* <key> should be HKEY_LOCAL_MACHINE or HKEY_USERS.
*/
BOOL MountRegistryHive(const HKEY key, const char* pszHiveName, const char* pszHivePath)
{
LSTATUS status;
HANDLE token = INVALID_HANDLE_VALUE;
assert((key == HKEY_LOCAL_MACHINE) || (key == HKEY_USERS));
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) {
uprintf("Could not get current process token: %s", WindowsErrorString());
return FALSE;
}
// Ignore errors on those in case we can proceed without...
SetPrivilege(token, SE_RESTORE_NAME, TRUE);
SetPrivilege(token, SE_BACKUP_NAME, TRUE);
status = RegLoadKeyA(key, pszHiveName, pszHivePath);
if (status != ERROR_SUCCESS) {
SetLastError(status);
uprintf("Could not mount offline registry hive '%s': %s", pszHivePath, WindowsErrorString());
} else
uprintf("Mounted offline registry hive '%s' to '%s\\%s'",
pszHivePath, (key == HKEY_LOCAL_MACHINE) ? "HKLM" : "HKCU", pszHiveName);
safe_closehandle(token);
return (status == ERROR_SUCCESS);
}
/*
* Unmount an offline registry hive.
* <key> should be HKEY_LOCAL_MACHINE or HKEY_USERS.
*/
BOOL UnmountRegistryHive(const HKEY key, const char* pszHiveName)
{
LSTATUS status;
assert((key == HKEY_LOCAL_MACHINE) || (key == HKEY_USERS));
status = RegUnLoadKeyA(key, pszHiveName);
if (status != ERROR_SUCCESS) {
SetLastError(status);
uprintf("Could not unmount offline registry hive: %s", WindowsErrorString());
} else
uprintf("Unmounted offline registry hive '%s\\%s'",
(key == HKEY_LOCAL_MACHINE) ? "HKLM" : "HKCU", pszHiveName);
return (status == ERROR_SUCCESS);
}

View file

@ -45,6 +45,7 @@
UINT_PTR UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU;
HIMAGELIST hUpImageList, hDownImageList;
extern BOOL use_vds, appstore_version;
extern int imop_win_sel;
int update_progress_type = UPT_PERCENT;
int advanced_device_section_height, advanced_format_section_height;
// (empty) check box width, (empty) drop down width, button height (for and without dropdown match)
@ -273,6 +274,8 @@ void GetFullWidth(HWND hDlg)
// Go through the Image Options for Windows To Go
fw = max(fw, GetTextSize(hImageOption, lmprintf(MSG_117)).cx);
fw = max(fw, GetTextSize(hImageOption, lmprintf(MSG_118)).cx);
fw = max(fw, GetTextSize(hImageOption, lmprintf(MSG_322)).cx);
fw = max(fw, GetTextSize(hImageOption, lmprintf(MSG_323)).cx);
// Now deal with full length checkbox lines
for (i = 0; i<ARRAYSIZE(full_width_checkboxes); i++)
@ -790,7 +793,7 @@ void ToggleImageOptions(void)
image_options ^= IMOP_WINTOGO;
if (image_options & IMOP_WINTOGO) {
// Set the Windows To Go selection in the dropdown
IGNORE_RETVAL(ComboBox_SetCurSel(hImageOption, (img_report.is_windows_img || !windows_to_go_selected) ? 0 : 1));
IGNORE_RETVAL(ComboBox_SetCurSel(hImageOption, imop_win_sel));
}
}

View file

@ -74,7 +74,7 @@ enum update_progress_type {
extern HWND hMultiToolbar, hSaveToolbar, hHashToolbar, hAdvancedDeviceToolbar, hAdvancedFormatToolbar;
extern HFONT hInfoFont;
extern UINT_PTR UM_LANGUAGE_MENU_MAX;
extern BOOL advanced_mode_device, advanced_mode_format, force_large_fat32, app_changed_size, windows_to_go_selected;
extern BOOL advanced_mode_device, advanced_mode_format, force_large_fat32, app_changed_size;
extern loc_cmd* selected_locale;
extern uint64_t persistence_size;
extern const char *sfd_name, *flash_type[BADLOCKS_PATTERN_TYPES];

127
src/vhd.c
View file

@ -109,15 +109,18 @@ PF_TYPE_DECL(WINAPI, DWORD, WIMUnregisterMessageCallback, (HANDLE, FARPROC));
PF_TYPE_DECL(RPC_ENTRY, RPC_STATUS, UuidCreate, (UUID __RPC_FAR*));
uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
HANDLE apply_wim_thread = NULL;
HANDLE wim_thread = NULL;
extern int default_thread_priority;
extern BOOL ignore_boot_marker;
static uint8_t wim_flags = 0;
static wchar_t wmount_path[MAX_PATH] = { 0 };
static wchar_t wmount_path[MAX_PATH] = { 0 }, wmount_track[MAX_PATH] = { 0 };
static char sevenzip_path[MAX_PATH];
static const char conectix_str[] = VHD_FOOTER_COOKIE;
static BOOL count_files;
// Apply/Mount image functionality
static const char *_image, *_dst;
static int _index;
static BOOL Get7ZipPath(void)
{
@ -381,55 +384,115 @@ uint8_t WimExtractCheck(BOOL bSilent)
return wim_flags;
}
// Looks like Microsoft's idea of "mount" for WIM images is to just *extract* all
// files to a mounpoint and pretend it is "mounted", even if you do specify that
// you're not planning to change the content. So, yeah, this is both super slow
// and super wasteful of space... These calls are a complete waste of time.
BOOL WimMountImage(char* pszWimFileName, DWORD dwImageIndex)
// Looks like Microsoft's idea of "mount" for WIM images involves the creation
// of a as many virtual junctions as there exist directories on the image...
// So, yeah, this is both very slow and wasteful of space.
static DWORD WINAPI WimMountImageThread(LPVOID param)
{
BOOL r = FALSE;
wconvert(temp_dir);
wconvert(pszWimFileName);
wchar_t* wimage = utf8_to_wchar(_image);
PF_INIT_OR_OUT(WIMMountImage, Wimgapi);
if (wmount_path[0] != 0) {
uprintf("WimMountImage: An image is already mounted");
goto out;
}
if (GetTempFileNameW(wtemp_dir, L"Rufus", 0, wmount_path) == 0) {
uprintf("WimMountImage: Can not create mount directory");
if (GetTempFileNameW(wtemp_dir, L"Ruf", 0, wmount_path) == 0) {
uprintf("WimMountImage: Can not generate mount directory: %s", WindowsErrorString());
goto out;
}
DeleteFileW(wmount_path);
if (!CreateDirectoryW(wmount_path, 0)) {
uprintf("WimMountImage: Can not create mount directory");
uprintf("WimMountImage: Can not create mount directory '%S': %s", wmount_path, WindowsErrorString());
goto out;
}
if (GetTempFileNameW(wtemp_dir, L"Ruf", 0, wmount_track) == 0) {
uprintf("WimMountImage: Can not generate tracking directory: %s", WindowsErrorString());
goto out;
}
DeleteFileW(wmount_track);
if (!CreateDirectoryW(wmount_track, 0)) {
uprintf("WimMountImage: Can not create tracking directory '%S': %s", wmount_track, WindowsErrorString());
goto out;
}
r = pfWIMMountImage(wmount_path, wpszWimFileName, dwImageIndex, NULL);
if (!r)
uprintf("Could not mount %S on %S: %s", wpszWimFileName, wmount_path, WindowsErrorString());
r = pfWIMMountImage(wmount_path, wimage, _index, wmount_track);
if (!r) {
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);
out:
wfree(temp_dir);
wfree(pszWimFileName);
return r;
safe_free(wimage);
ExitThread((DWORD)r);
}
BOOL WimUnmountImage(void)
// Returns the temporary mount path on success, NULL on error.
// Returned path must be freed by the caller.
char* WimMountImage(const char* image, int index)
{
DWORD dw = 0;
_image = image;
_index = index;
wim_thread = CreateThread(NULL, 0, WimMountImageThread, NULL, 0, NULL);
if (wim_thread == NULL) {
uprintf("Unable to start mount-image thread");
return NULL;
}
SetThreadPriority(wim_thread, default_thread_priority);
WaitForSingleObject(wim_thread, INFINITE);
if (!GetExitCodeThread(wim_thread, &dw))
dw = 0;
wim_thread = NULL;
return (dw) ? wchar_to_utf8(wmount_path) : NULL;
}
static DWORD WINAPI WimUnmountImageThread(LPVOID param)
{
BOOL r = FALSE;
wchar_t* wimage = utf8_to_wchar(_image);
PF_INIT_OR_OUT(WIMUnmountImage, Wimgapi);
if (wmount_path[0] == 0) {
uprintf("WimUnmountImage: No image is mounted");
goto out;
}
r = pfWIMUnmountImage(wmount_path, NULL, 0, FALSE);
if (!r)
uprintf("Could not unmount %S: %s", wmount_path, WindowsErrorString());
r = pfWIMUnmountImage(wmount_path, wimage, _index, TRUE);
if (!r) {
uprintf("Could not unmount '%S': %s", wmount_path, WindowsErrorString());
goto out;
}
uprintf("Unmounted '%S [%d]'", wmount_path, _index);
RemoveDirectoryW(wmount_path);
wmount_path[0] = 0;
RemoveDirectoryW(wmount_track);
wmount_track[0] = 0;
out:
return r;
safe_free(wimage);
ExitThread((DWORD)r);
}
BOOL WimUnmountImage(const char* image, int index)
{
DWORD dw = 0;
_image = image;
_index = index;
wim_thread = CreateThread(NULL, 0, WimUnmountImageThread, NULL, 0, NULL);
if (wim_thread == NULL) {
uprintf("Unable to start unmount-image thread");
return FALSE;
}
SetThreadPriority(wim_thread, default_thread_priority);
WaitForSingleObject(wim_thread, INFINITE);
if (!GetExitCodeThread(wim_thread, &dw))
dw = 0;
wim_thread = NULL;
return dw;
}
// Extract a file from a WIM image using wimgapi.dll (Windows 7 or later)
@ -589,12 +652,8 @@ 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)) );
}
// Apply image functionality
static const char *_image, *_dst;
static int _index;
// From http://msdn.microsoft.com/en-us/library/windows/desktop/dd834960.aspx
// as well as http://www.msfn.org/board/topic/150700-wimgapi-wimmountimage-progressbar/
// 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,
@ -700,7 +759,7 @@ DWORD WINAPI WimProgressCallback(DWORD dwMsgId, WPARAM wParam, LPARAM lParam, PV
}
// Apply a WIM image using wimgapi.dll (Windows 7 or later)
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd851944.aspx
// 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
static DWORD WINAPI WimApplyImageThread(LPVOID param)
{
@ -800,15 +859,15 @@ BOOL WimApplyImage(const char* image, int index, const char* dst)
_index = index;
_dst = dst;
apply_wim_thread = CreateThread(NULL, 0, WimApplyImageThread, NULL, 0, NULL);
if (apply_wim_thread == NULL) {
wim_thread = CreateThread(NULL, 0, WimApplyImageThread, NULL, 0, NULL);
if (wim_thread == NULL) {
uprintf("Unable to start apply-image thread");
return FALSE;
}
SetThreadPriority(apply_wim_thread, default_thread_priority);
WaitForSingleObject(apply_wim_thread, INFINITE);
if (!GetExitCodeThread(apply_wim_thread, &dw))
SetThreadPriority(wim_thread, default_thread_priority);
WaitForSingleObject(wim_thread, INFINITE);
if (!GetExitCodeThread(wim_thread, &dw))
dw = 0;
apply_wim_thread = NULL;
wim_thread = NULL;
return dw;
}