Fix registry ownership/ACL and hang bugs in tiny11maker.ps1, plus build/setup script updates

Fixes several offline-hive build failures: TrustedInstaller-owned keys
(WindowsRuntime\ActivatableClassId, Explorer\Advanced, System\GameConfigStore, Search
SystemIndex) denying writes even to admin-owned processes, a PowerShell 5.1 quirk that drops
empty-string reg.exe arguments and can hang the build on a silent overwrite prompt, a
registry-handle leak that left hives locked and cascaded into DISM cleanup failures, and
relaxed the post-ResetBase health gate to accept 'Repairable' (only abort on
'NonRepairable') since ResetBase makes full repair impossible anyway - documented that
repairing the installed OS needs the original stock ISO, not the tweaked output. Also
rolls in in-progress updates to the other maker scripts and OEM setup/first-boot scripts.
This commit is contained in:
2026-07-31 06:09:58 -07:00
parent 26c397fb95
commit d38cd32b82
16 changed files with 1477 additions and 220 deletions
@@ -50,7 +50,13 @@ function Get-RemotePackage {
if (-not (Test-Path $dest)) {
Write-Host "Downloading $fileName..." -ForegroundColor Cyan
Invoke-WebRequest -Uri $Url -OutFile $dest -UseBasicParsing
try {
Invoke-WebRequest -Uri $Url -OutFile $dest -UseBasicParsing -TimeoutSec 15
}
catch {
Write-Host "Download failed or timed out for $Url : $($_.Exception.Message)" -ForegroundColor Red
return $null
}
}
return $dest
@@ -290,6 +296,9 @@ else {
}
$mainAppPath = Get-RemotePackage $selectedFile.url
if (-not $mainAppPath) {
continue
}
}
default {
@@ -17,7 +17,7 @@ if (-not (Test-Path -Path $logPath)) {
function Get-ContentFromUrl {
param([string]$url)
(Invoke-WebRequest -Uri $url -UseBasicParsing -ErrorAction Stop).Content
(Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 15 -ErrorAction Stop).Content
}
# =========================
@@ -0,0 +1,37 @@
# Check PowerShell version for use in path
if ($PSVersionTable.PSVersion.Major -ge 3) {
$currentDir = $PSScriptRoot
}
else {
$currentDir = (Get-Item .).FullName
}
# Only run if the maker script flagged this build with -IgnoreSecBoot
$labConfigPath = "HKLM:\SYSTEM\Setup\LabConfig"
$flag = Get-ItemProperty -Path $labConfigPath -Name "IgnoreSecBootBootRes" -ErrorAction SilentlyContinue
if (-not $flag -or $flag.IgnoreSecBootBootRes -ne 1) {
return
}
Write-Output "IgnoreSecBootBootRes flag set - checking Secure Boot state before touching BCD..."
# Confirm-SecureBootUEFI throws on legacy BIOS / non-UEFI firmware - no Secure Boot to worry about there
$secureBootOn = $false
try {
$secureBootOn = Confirm-SecureBootUEFI
}
catch {
Write-Output "Confirm-SecureBootUEFI unavailable (legacy BIOS/non-UEFI) - Secure Boot not applicable, proceeding."
$secureBootOn = $false
}
if ($secureBootOn) {
Write-Warning "Secure Boot is ENABLED - skipping testsigning/nointegritychecks. Windows ignores both settings while Secure Boot is on, and forcing them here would do nothing but risk an inconsistent BCD. Disable Secure Boot in UEFI firmware, then re-run this script (`"$PSCommandPath`") manually to apply the settings - it only runs automatically once, during setup."
return
}
& bcdedit /set '{current}' testsigning on | Out-Null
& bcdedit /set '{current}' nointegritychecks on | Out-Null
Write-Output "testsigning/nointegritychecks enabled - Secure Boot was off, so this should take effect on next reboot."
@@ -93,4 +93,8 @@ Write-Output "Installing UWP UI Components for all users..."
#### Install Normal Apps (Machine wide) ####
Start-Process -FilePath "$windowsDrive\Windows\OEM\MultiStaller.exe" -ArgumentList "--config", "$windowsDrive\Windows\OEM\setup\apps-machine-wide.yml" -WindowStyle Maximized -Wait
Start-Process -FilePath "$windowsDrive\Windows\OEM\ChromeMassInstaller.exe" -ArgumentList "--no_pref" -Wait
Start-Process -FilePath "$windowsDrive\Windows\OEM\ChromeMassInstaller.exe" -ArgumentList "--no_pref" -Wait
# Install other miscellaneous applications (mostly for user convenience)
Start-Process -FilePath "msiexec.exe" -ArgumentList "/i `"$windowsDrive\Windows\OEM\apps\other\Monitarian-4.14.0.msi`" /quiet /norestart" -Wait -PassThru
Start-Process -FilePath "$windowsDrive\Windows\OEM\apps\other\ShareX-19.0.2-setup.exe" -ArgumentList "/S" -Wait
@@ -1,20 +1,35 @@
# Check PowerShell version for use in path
if ($PSVersionTable.PSVersion.Major -ge 3) {
# Use new variable syntax in PowerShell 3 and above
$currentDir = $PSScriptRoot
try {
Start-Transcript -Path "$env:WINDIR\OEM\setup\scripts\setup-user.log" -Append
}
else {
# Use old variable syntax in Windows PowerShell 3 and below
$currentDir = (Get-Item .).FullName
catch {
# Transcript failing to start must not block the rest of setup
}
# Import script-helper.ps1
. "$currentDir\..\..\scripts\script-helper.ps1"
try {
# Check PowerShell version for use in path
if ($PSVersionTable.PSVersion.Major -ge 3) {
# Use new variable syntax in PowerShell 3 and above
$currentDir = $PSScriptRoot
}
else {
# Use old variable syntax in Windows PowerShell 3 and below
$currentDir = (Get-Item .).FullName
}
# Before doing ANYTHING, check if windwos is activated
if ((Get-WindowsVersionDetails).LicenseStatus -ne "Licensed") {
& ([ScriptBlock]::Create((Invoke-RestMethod https://get.activated.win))) /HWID /HWID-NoEditionChange
}
# Import script-helper.ps1
. "$currentDir\..\..\scripts\script-helper.ps1"
# Before doing ANYTHING, check if windows is activated
try {
if ((Get-WindowsVersionDetails).LicenseStatus -ne "Licensed") {
Write-Output "Windows not licensed - fetching activation script from get.activated.win..."
$activationScript = Invoke-RestMethod -Uri "https://get.activated.win" -TimeoutSec 15 -UseBasicParsing
& ([ScriptBlock]::Create($activationScript)) /HWID /HWID-NoEditionChange
}
}
catch {
Write-Warning "Activation step failed or timed out, continuing setup without activation: $($_.Exception.Message)"
}
#### Set cursor theme to Posys Cursor ####
$cursorkey = "HKCU:\Control Panel\Cursors"
@@ -88,4 +103,21 @@ if (-not (Get-Process -Name explorer -ErrorAction SilentlyContinue)) {
& "$windowsDrive\Windows\OEM\setup\scripts\install-apps-user.ps1"
## Install apps (modern windows apps, such as: store apps, winget, appx, msix, etc [appx/msix/others can be downloaded from url])
& "$windowsDrive\Windows\OEM\scripts\install-win-apps.ps1"
& "$windowsDrive\Windows\OEM\scripts\install-win-apps.ps1"
}
catch {
Write-Error "setup-user.ps1 failed: $($_.Exception.Message)"
Write-Output $_.ScriptStackTrace
}
finally {
try {
Stop-Transcript
}
catch {
# Nothing to stop, ignore
}
}
# Always exit 0 - a failure here must be logged and diagnosed via setup-user.log,
# not surfaced as an OOBE error dialog or left to hang FirstLogonCommands.
exit 0
@@ -22,6 +22,9 @@ if ($appsRoot -and (Test-Path $bootcampPath)) {
& $bootcampPath
}
#### Apply custom bootres.dll Secure Boot compatibility settings (only runs if flagged at build time) ####
& "$currentDir\enable-custom-bootres.ps1"
#### Install oxmc-servers Root Certificate (required for system apps) ####
Write-Output "Installing oxmc-servers root certificate..."
& "$windowsDrive\Windows\OEM\scripts\install-certs.ps1" -Silent
+1 -1
View File
@@ -1,6 +1,6 @@
[MRU List]
MRU1=C:\Users\oxmc\Documents\Github\CustomTiny11\working\tiny11\sources\spwizimg.dll
MRU2=C:\Users\oxmc\Documents\Github\CustomTiny11\working\tiny10\sources\spwizimg.dll
MRU2=
MRU3=
MRU4=
MRU5=
+28 -3
View File
@@ -16,8 +16,10 @@ param(
[Parameter(Mandatory = $false)]
[string]$PfxPassword = "",
[switch]$UseLegacySizes
[switch]$UseLegacySizes,
[switch]$IgnoreSecBoot
)
#Requires -RunAsAdministrator
@@ -253,6 +255,14 @@ function Sign-FileWithCertificate {
}
}
# Function to create a throwaway self-signed code-signing cert (IgnoreSecBoot path only)
function New-ThrowawaySigningCert {
$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=CustomTiny11 IgnoreSecBoot" `
-CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeyUsage DigitalSignature `
-NotAfter (Get-Date).AddYears(5)
return $cert
}
# Function to resize bitmap
function Resize-Bitmap {
param(
@@ -412,6 +422,12 @@ try {
$signed = Sign-FileWithCertificate -FilePath $outputDll -SignToolPath $signToolPath `
-CertificateThumbprint $CertificateThumbprint -PfxPath $PfxPath -PfxPassword $PfxPassword
}
elseif ($IgnoreSecBoot) {
Write-Log "IgnoreSecBoot set and no certificate given - generating throwaway self-signed cert..." -Color "Yellow"
$throwawayCert = New-ThrowawaySigningCert
$signed = Sign-FileWithCertificate -FilePath $outputDll -SignToolPath $signToolPath `
-CertificateThumbprint $throwawayCert.Thumbprint
}
else {
Write-Log "No certificate specified. Skipping code signing." -Color "Yellow"
}
@@ -439,7 +455,16 @@ try {
Write-Host "[!] File is NOT signed" -ForegroundColor Yellow
Write-Host " Requires Test Signing mode or Secure Boot disabled" -ForegroundColor Gray
}
if ($IgnoreSecBoot) {
Write-Host ""
Write-Host "[IgnoreSecBoot] Signed with throwaway cert (not Microsoft-trusted)." -ForegroundColor Yellow
Write-Host " Build the image with -IgnoreSecBoot on the maker script too - it flags first boot" -ForegroundColor Gray
Write-Host " to run 'bcdedit /set testsigning on' and 'bcdedit /set nointegritychecks on'." -ForegroundColor Gray
Write-Host " Those settings are IGNORED by Windows while Secure Boot is on in firmware." -ForegroundColor Gray
Write-Host " Secure Boot must be disabled manually in UEFI setup for this to boot." -ForegroundColor Gray
}
# Copy final DLL to script directory
$FinallDLL = Join-Path $PSScriptRoot "bootres_modified.dll"
Copy-Item -Path $outputDll -Destination $FinallDLL -Force
+49 -6
View File
@@ -6,6 +6,36 @@ param(
$projectRoot = (Resolve-Path "$PSScriptRoot\..\..")
# Detect Windows 10 vs 11 from install.wim/install.esd so the right autounattend variant gets injected
function Get-WindowsVersionFromMedia {
param([string]$MediaRoot)
$srcBase = $MediaRoot
if (-not (Test-Path "$srcBase\sources\install.wim") -and -not (Test-Path "$srcBase\sources\install.esd") -and (Test-Path "$srcBase\x64\sources")) {
$srcBase = "$srcBase\x64"
}
$imagePath = if (Test-Path "$srcBase\sources\install.wim") { "$srcBase\sources\install.wim" }
elseif (Test-Path "$srcBase\sources\install.esd") { "$srcBase\sources\install.esd" }
else { $null }
if (-not $imagePath) { return $null }
try {
$imgInfo = Get-WindowsImage -ImagePath $imagePath -Index 1
$parts = $imgInfo.Version.Split('.')
if ($parts.Count -ge 3) {
$build = [int]$parts[2]
if ($build -ge 22000) { return "11" }
elseif ($build -ge 10240) { return "10" }
}
}
catch {
Write-Warning "Could not read Windows version from media: $($_.Exception.Message)"
}
return $null
}
if (-not (Test-Path $IsoPath)) {
Write-Error "ISO not found: $IsoPath"
exit 1
@@ -81,18 +111,31 @@ try {
}
}
# Replace autounattend.xml
$newXml = "$projectRoot\includes\autounattend-win10.xml"
# Detect Windows version so we inject the matching autounattend variant
Write-Host "Detecting Windows version from media..."
$detectedVersion = Get-WindowsVersionFromMedia -MediaRoot $tempDir
if (-not $detectedVersion) {
Write-Host "Could not automatically detect Windows version from media."
do {
$detectedVersion = Read-Host "Enter Windows version (10 or 11)"
} while ($detectedVersion -notin @("10", "11"))
}
else {
Write-Host "Detected Windows $detectedVersion media."
}
# Replace autounattend.xml with the version-matched variant
$newXml = "$projectRoot\includes\autounattend-win$detectedVersion.xml"
if (-not (Test-Path $newXml)) {
Write-Error "autounattend-win10.xml not found at: $newXml"
Write-Error "autounattend-win$detectedVersion.xml not found at: $newXml"
exit 1
}
Write-Host "Replacing autounattend.xml..."
Write-Host "Replacing autounattend.xml with autounattend-win$detectedVersion.xml..."
Copy-Item -Path $newXml -Destination "$tempDir\autounattend.xml" -Force
# Detect label from ISO filename
# Detect label from ISO filename, tagged with the detected version
$isoName = [System.IO.Path]::GetFileNameWithoutExtension($IsoPath)
$label = if ($isoName -match 'x86') { "Tiny10_x86" } else { "Tiny10_x64" }
$label = if ($isoName -match 'x86') { "Tiny${detectedVersion}_x86" } else { "Tiny${detectedVersion}_x64" }
$bootEtfs = "$tempDir\boot\etfsboot.com"
$bootEfi = "$tempDir\efi\microsoft\boot\efisys.bin"