fix(toolchain): pin WU disabled across the DISM /ResetBase window

The disk-cleanup function stopped wuauserv before DISM /StartComponentCleanup
/ResetBase but only re-enforced Start=4 AFTER it. /ResetBase drives heavy CBS
servicing (TiWorker); during that window WaaSMedicSvc woke, flipped wuauserv
Start back to Manual, and a "Schedule Scan" task started it. If the pass was
interrupted there (reboot/crash), the template was left with WU running and
Manual startup — a half-prepared state where Windows Update keeps firing on a
supposedly-locked-down build template.

Move the lockdown ahead of DISM: set wuauserv Start=4, apply the
WaaSMedicSvc registry write-deny ACL (the only reliable lever — the service
is protected and cannot itself be disabled), and disable the WindowsUpdate /
UpdateOrchestrator scan tasks, all BEFORE /ResetBase rather than only after.
The post-DISM re-enforce stays as a belt-and-suspenders check.

Applied identically to the WinBuild2025 and WinBuild2022 toolchains.
This commit is contained in:
2026-06-10 00:48:00 +02:00
parent 43ad5afd09
commit fb5de6f59f
2 changed files with 70 additions and 0 deletions
@@ -253,6 +253,41 @@ function Invoke-DiskCleanup {
foreach ($svc in 'wuauserv', 'UsoSvc', 'bits', 'dosvc', 'TrustedInstaller') {
Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue
}
# Pin Windows Update down for the WHOLE DISM /ResetBase window below. /ResetBase
# drives heavy CBS servicing (TiWorker); with wuauserv merely *stopped* and no
# ACL yet, WaaSMedicSvc wakes, flips wuauserv Start back to Manual, and a
# "Schedule Scan" task starts it mid-cleanup — so an interruption here leaves WU
# running (exactly the half-prepared state seen on stuck templates). Force
# Start=4, deny WaaSMedicSvc the registry write, and disable the scan tasks
# BEFORE DISM, not only in the re-enforce after it.
Set-Service -Name wuauserv -StartupType Disabled -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv' `
-Name Start -Value 4 -Type DWord -Force -ErrorAction SilentlyContinue
try {
$svcRegPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv'
$acl = Get-Acl $svcRegPath
$denyRule = New-Object System.Security.AccessControl.RegistryAccessRule(
([System.Security.Principal.NTAccount]'NT SERVICE\WaaSMedicSvc'),
[System.Security.AccessControl.RegistryRights]'SetValue,CreateSubKey,WriteKey',
[System.Security.AccessControl.InheritanceFlags]::None,
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Deny
)
$acl.AddAccessRule($denyRule)
Set-Acl $svcRegPath $acl
Write-Host "wuauserv: WaaSMedicSvc write-deny ACL applied (pre-DISM)."
} catch {
Write-Warning "wuauserv pre-DISM ACL deny skipped (non-fatal): $_"
}
foreach ($t in @(
'\Microsoft\Windows\WindowsUpdate\Scheduled Start',
'\Microsoft\Windows\UpdateOrchestrator\Schedule Scan',
'\Microsoft\Windows\UpdateOrchestrator\Schedule Scan Static Task'
)) {
schtasks /Change /TN $t /Disable 2>&1 | Out-Null
}
$sdDownload = 'C:\Windows\SoftwareDistribution\Download'
Remove-Item $sdDownload -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path $sdDownload -Force | Out-Null
@@ -254,6 +254,41 @@ function Invoke-DiskCleanup {
foreach ($svc in 'wuauserv', 'UsoSvc', 'bits', 'dosvc', 'TrustedInstaller') {
Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue
}
# Pin Windows Update down for the WHOLE DISM /ResetBase window below. /ResetBase
# drives heavy CBS servicing (TiWorker); with wuauserv merely *stopped* and no
# ACL yet, WaaSMedicSvc wakes, flips wuauserv Start back to Manual, and a
# "Schedule Scan" task starts it mid-cleanup — so an interruption here leaves WU
# running (exactly the half-prepared state seen on stuck templates). Force
# Start=4, deny WaaSMedicSvc the registry write, and disable the scan tasks
# BEFORE DISM, not only in the re-enforce after it.
Set-Service -Name wuauserv -StartupType Disabled -ErrorAction SilentlyContinue
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv' `
-Name Start -Value 4 -Type DWord -Force -ErrorAction SilentlyContinue
try {
$svcRegPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv'
$acl = Get-Acl $svcRegPath
$denyRule = New-Object System.Security.AccessControl.RegistryAccessRule(
([System.Security.Principal.NTAccount]'NT SERVICE\WaaSMedicSvc'),
[System.Security.AccessControl.RegistryRights]'SetValue,CreateSubKey,WriteKey',
[System.Security.AccessControl.InheritanceFlags]::None,
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Deny
)
$acl.AddAccessRule($denyRule)
Set-Acl $svcRegPath $acl
Write-Host "wuauserv: WaaSMedicSvc write-deny ACL applied (pre-DISM)."
} catch {
Write-Warning "wuauserv pre-DISM ACL deny skipped (non-fatal): $_"
}
foreach ($t in @(
'\Microsoft\Windows\WindowsUpdate\Scheduled Start',
'\Microsoft\Windows\UpdateOrchestrator\Schedule Scan',
'\Microsoft\Windows\UpdateOrchestrator\Schedule Scan Static Task'
)) {
schtasks /Change /TN $t /Disable 2>&1 | Out-Null
}
$sdDownload = 'C:\Windows\SoftwareDistribution\Download'
Remove-Item $sdDownload -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path $sdDownload -Force | Out-Null