[wue] fix MSA bypass not being applied unless SB/TPM or RAM/Disk bypass is also selected

* In a manner that defies logic, Microsoft designed Windows setup to parse Autounattend.xml
  for windowsPE tasks in the PE environment, but only carry out the copying of that file
  to %WINDIR%\Panther for subsequent processing with the other passes *IF* there exist an
  actual windowsPE section.
* In short, when using the Autounattend.xml method, Microsoft have made all passes there
  dependent on the existence of a windowsPE pass, regardless of whether that pass has any
  use or not.
* Working around this would be fine and all (just add an empty windowsPE pass so that the
  later passes get executed) if the absence of a windowsPE pass didn't also determine
  whether the user will be presented with the default Windows setup screens that include
  the "Repair your computer" option or a completely different set of screens (c.f. #1971).
* This means that, to keep users happy, we need to add yet another method to carry out
  tasks that should have remained the realm of boot.wim's Autounattend.xml, and instead
  create a \sources\$OEM$\$$\Panther\unattend.xml when there are no windowsPE tasks (on
  account that setup copies anything found under \sources\$OEM$\$$\ to %WINDIR%\).
  Only through this can we have the specialize and oobeSystem tasks actually carried out
  (for bypassing MSA requirements of skipping the data collection screens) while keeping
  the original Windows Setup look and feel.
* Closes #1981
This commit is contained in:
Pete Batard 2022-07-13 18:31:11 +01:00
parent 2b7b81808f
commit 5117a3b4a8
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
4 changed files with 70 additions and 30 deletions

View File

@ -1498,8 +1498,9 @@ static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp)
/*
* Add unattend.xml to 'sources\boot.wim' (install) or 'Windows\Panther\' (Windows To Go)
* NB: Work with a copy of unattend_xml_selection as a paremeter since we will modify it.
*/
BOOL ApplyWindowsCustomization(char drive_letter, BOOL windows_to_go)
BOOL ApplyWindowsCustomization(char drive_letter, int unattend_selection)
{
BOOL r = FALSE, is_hive_mounted = FALSE;
int i;
@ -1515,7 +1516,7 @@ BOOL ApplyWindowsCustomization(char drive_letter, BOOL windows_to_go)
assert(unattend_xml_path != NULL);
uprintf("Applying Windows customization:");
if (windows_to_go) {
if (unattend_selection & UNATTEND_WINDOWS_TO_GO) {
static_sprintf(path, "%c:\\Windows\\Panther", drive_letter);
if (!CreateDirectoryA(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
uprintf("Could not create '%s' : %s", path, WindowsErrorString());
@ -1529,7 +1530,7 @@ BOOL ApplyWindowsCustomization(char drive_letter, BOOL windows_to_go)
uprintf("Added '%s'", path);
} else {
boot_wim_path[0] = drive_letter;
if (unattend_xml_selection & UNATTEND_WINPE_SETUP_MASK) {
if (unattend_selection & UNATTEND_WINPE_SETUP_MASK) {
// Create a backup of sources\appraiserres.dll and then create an empty file to
// allow in-place upgrades without TPM/SB. Note that we need to create an empty,
// appraiserres.dll otherwise setup.exe extracts its own.
@ -1544,12 +1545,16 @@ BOOL ApplyWindowsCustomization(char drive_letter, BOOL windows_to_go)
}
UpdateProgressWithInfoForce(OP_PATCH, MSG_325, 0, PATCH_PROGRESS_TOTAL);
uprintf("Mounting '%s'...", boot_wim_path);
mount_path = WimMountImage(boot_wim_path, wim_index);
if (mount_path == NULL)
goto out;
// We only need to mount boot.wim if we have windowsPE data to deal with. If
// not, we can just copy our unattend.xml in \sources\$OEM$\$$\Panther\.
if (unattend_selection & UNATTEND_WINPE_SETUP_MASK) {
uprintf("Mounting '%s'...", boot_wim_path);
mount_path = WimMountImage(boot_wim_path, wim_index);
if (mount_path == NULL)
goto out;
}
if (unattend_xml_selection & UNATTEND_WINPE_SETUP_MASK) {
if (unattend_selection & (UNATTEND_SECUREBOOT_TPM_MASK | UNATTEND_MINRAM_MINDISK_MASK)) {
// Try to create the registry keys directly, and fallback to using unattend
// if that fails (which the Windows Store version is expected to do).
static_sprintf(path, "%s\\Windows\\System32\\config\\SYSTEM", mount_path);
@ -1577,7 +1582,7 @@ BOOL ApplyWindowsCustomization(char drive_letter, BOOL windows_to_go)
}
for (i = 0; i < ARRAYSIZE(bypass_name); i++) {
if (!(unattend_xml_selection & (1 << (i / 2))))
if (!(unattend_selection & (1 << (i / 2))))
continue;
status = RegSetValueExA(hSubKey, bypass_name[i], 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD));
if (status != ERROR_SUCCESS) {
@ -1590,18 +1595,52 @@ BOOL ApplyWindowsCustomization(char drive_letter, BOOL windows_to_go)
}
// We were successfull in creating the keys so disable the windowsPE section from unattend.xml
// We do this by replacing '<settings pass="windowsPE">' with '<settings pass="disabled">'
if (replace_in_token_data(unattend_xml_path, "<settings", "windowsPE", "disabled", FALSE) == NULL)
uprintf("Warning: Could not disable 'windowsPE' pass from unattend.xml");
// (provided that the registry key creation was the only item for this pass)
if ((unattend_selection & UNATTEND_WINPE_SETUP_MASK) == (UNATTEND_SECUREBOOT_TPM_MASK | UNATTEND_MINRAM_MINDISK_MASK)) {
if (replace_in_token_data(unattend_xml_path, "<settings", "windowsPE", "disabled", FALSE) == NULL)
uprintf("Warning: Could not disable 'windowsPE' pass from unattend.xml");
// Remove the flags, since we accomplished the registry creation outside of unattend.
unattend_selection &= ~(UNATTEND_SECUREBOOT_TPM_MASK | UNATTEND_MINRAM_MINDISK_MASK);
} else {
// TODO: If we add other tasks besides LabConfig reg keys, we'll need to figure out how
// to comment out the <RunSynchronous> entries from windowsPE (and only windowsPE).
assert(FALSE);
}
UpdateProgressWithInfoForce(OP_PATCH, MSG_325, 102, PATCH_PROGRESS_TOTAL);
}
copy_unattend:
static_sprintf(path, "%s\\Autounattend.xml", mount_path);
if (!CopyFileU(unattend_xml_path, path, TRUE)) {
uprintf("Could not create boot.wim 'Autounattend.xml': %s", WindowsErrorString());
goto out;
if (unattend_selection & UNATTEND_WINPE_SETUP_MASK) {
// If we have a windowsPE section, copy the answer files to the root of boot.wim as
// Autounattend.xml. This also results in that file being automatically copied over
// to %WINDIR%\Panther\unattend.xml for later passes processing.
assert(mount_path != NULL);
static_sprintf(path, "%s\\Autounattend.xml", mount_path);
if (!CopyFileU(unattend_xml_path, path, TRUE)) {
uprintf("Could not create boot.wim 'Autounattend.xml': %s", WindowsErrorString());
goto out;
}
uprintf("Added 'Autounattend.xml' to '%s'", boot_wim_path);
} else {
// If there is no windowsPE section in our unattend, then copying it as Autounattend.xml on
// the root of boot.wim will not work as Windows Setup does *NOT* carry Autounattend.xml into
// %WINDIR%\Panther\unattend.xml then (See: https://github.com/pbatard/rufus/issues/1981).
// So instead, copy it to \sources\$OEM$\$$\Panther\unattend.xml on the media, as the content
// of \sources\$OEM$\$$\* will get copied into %WINDIR%\ during the file copy phase.
static_sprintf(path, "%c:\\sources\\$OEM$\\$$\\Panther", drive_letter);
i = SHCreateDirectoryExA(NULL, path, NULL);
if (i != ERROR_SUCCESS) {
SetLastError(i);
uprintf("Error: Could not create directory '%s': %s", path, WindowsErrorString());
goto out;
}
static_sprintf(path, "%c:\\sources\\$OEM$\\$$\\Panther\\unattend.xml", drive_letter);
if (!CopyFileU(unattend_xml_path, path, TRUE)) {
uprintf("Could not create '%s': %s", path, WindowsErrorString());
goto out;
}
uprintf("Created '%s'", path);
}
uprintf("Added 'Autounattend.xml' to '%s'", boot_wim_path);
UpdateProgressWithInfoForce(OP_PATCH, MSG_325, 103, PATCH_PROGRESS_TOTAL);
}
r = TRUE;
@ -2413,7 +2452,7 @@ DWORD WINAPI FormatThread(void* param)
goto out;
}
if (unattend_xml_path != NULL) {
if (!ApplyWindowsCustomization(drive_name[0], TRUE))
if (!ApplyWindowsCustomization(drive_name[0], unattend_xml_selection | UNATTEND_WINDOWS_TO_GO))
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_PATCH);
}
} else {
@ -2455,7 +2494,7 @@ DWORD WINAPI FormatThread(void* param)
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH);
}
if (unattend_xml_path != NULL) {
if (!ApplyWindowsCustomization(drive_name[0], FALSE))
if (!ApplyWindowsCustomization(drive_name[0], unattend_xml_selection))
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_PATCH);
}
}

View File

@ -1283,7 +1283,7 @@ static char* CreateUnattendXml(int arch, int mask)
// WinPE will complain if we don't provide a product key. *Any* product key. This is soooo idiotic...
fprintf(fd, " <UserData>\n");
fprintf(fd, " <ProductKey>\n");
fprintf(fd, " <Key>xxxxx-xxxxx-xxxxx-xxxxx-xxxxx</Key>\n");
fprintf(fd, " <Key />\n");
fprintf(fd, " </ProductKey>\n");
fprintf(fd, " </UserData>\n");
fprintf(fd, " <RunSynchronous>\n");

View File

@ -499,12 +499,13 @@ enum ArchType {
};
// Windows User Experience (unattend.xml) options
#define UNATTEND_SECUREBOOT_TPM_MASK 0x01
#define UNATTEND_MINRAM_MINDISK_MASK 0x02
#define UNATTEND_NO_ONLINE_ACCOUNT_MASK 0x04
#define UNATTEND_NO_DATA_COLLECTION_MASK 0x08
#define UNATTEND_OFFLINE_INTERNAL_DRIVES 0x10
#define UNATTEND_DEFAULT_MASK 0x1F
#define UNATTEND_SECUREBOOT_TPM_MASK 0x00001
#define UNATTEND_MINRAM_MINDISK_MASK 0x00002
#define UNATTEND_NO_ONLINE_ACCOUNT_MASK 0x00004
#define UNATTEND_NO_DATA_COLLECTION_MASK 0x00008
#define UNATTEND_OFFLINE_INTERNAL_DRIVES 0x00010
#define UNATTEND_DEFAULT_MASK 0x0001F
#define UNATTEND_WINDOWS_TO_GO 0x10000 // Special flag for Windows To Go
#define UNATTEND_WINPE_SETUP_MASK (UNATTEND_SECUREBOOT_TPM_MASK | UNATTEND_MINRAM_MINDISK_MASK)
#define UNATTEND_SPECIALIZE_DEPLOYMENT_MASK (UNATTEND_NO_ONLINE_ACCOUNT_MASK)

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.20.1918"
CAPTION "Rufus 3.20.1919"
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,1918,0
PRODUCTVERSION 3,20,1918,0
FILEVERSION 3,20,1919,0
PRODUCTVERSION 3,20,1919,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.1918"
VALUE "FileVersion", "3.20.1919"
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.1918"
VALUE "ProductVersion", "3.20.1919"
END
END
BLOCK "VarFileInfo"