@@ -80,6 +80,68 @@ function Invoke-WinUtilISOScript {
8080 }
8181 }
8282
83+ # Returns the full paths of every exported .inf whose online driver class
84+ # matches one of the supplied class names.
85+ function Get-ExportedInfPaths {
86+ param ([string ]$ExportRoot , [string []]$Classes )
87+ Get-WindowsDriver - Online |
88+ Where-Object { $_.ClassName -in $Classes } |
89+ ForEach-Object { [IO.Path ]::GetFileNameWithoutExtension($_.OriginalFileName ) } |
90+ Select-Object - Unique |
91+ ForEach-Object {
92+ Get-ChildItem - Path $ExportRoot - Filter " $_ .inf" - Recurse - ErrorAction SilentlyContinue |
93+ Select-Object - ExpandProperty FullName
94+ }
95+ }
96+
97+ # Injects drivers into a DISM-mounted image. Pass either a list of .inf
98+ # paths via -InfPaths, or a driver folder via -DriverDir (uses /Recurse).
99+ function Add-DriversToImage {
100+ param (
101+ [string ]$MountPath ,
102+ [string []]$InfPaths ,
103+ [string ]$DriverDir ,
104+ [string ]$Label = " image" ,
105+ [scriptblock ]$Logger
106+ )
107+ if ($DriverDir ) {
108+ & dism / English " /image:$MountPath " / Add-Driver " /Driver:$DriverDir " / Recurse 2>&1 |
109+ ForEach-Object { & $Logger " dism[$Label ]: $_ " }
110+ } else {
111+ foreach ($inf in $InfPaths ) {
112+ & dism / English " /image:$MountPath " / Add-Driver " /Driver:$inf " 2>&1 |
113+ ForEach-Object { & $Logger " dism[$Label ]: $_ " }
114+ }
115+ }
116+ }
117+
118+ # Mounts boot.wim index 2, injects drivers, saves, and dismounts.
119+ # Pass either -InfPaths (individual .inf files) or -DriverDir (/Recurse).
120+ function Invoke-BootWimInject {
121+ param (
122+ [string ]$BootWimPath ,
123+ [string []]$InfPaths ,
124+ [string ]$DriverDir ,
125+ [scriptblock ]$Logger
126+ )
127+ Set-ItemProperty - Path $BootWimPath - Name IsReadOnly - Value $false - ErrorAction SilentlyContinue
128+ $mountDir = Join-Path $env: TEMP " WinUtil_BootMount_$ ( Get-Random ) "
129+ New-Item - Path $mountDir - ItemType Directory - Force | Out-Null
130+ try {
131+ & $Logger " Mounting boot.wim (index 2 — Windows Setup) for driver injection..."
132+ Mount-WindowsImage - ImagePath $BootWimPath - Index 2 - Path $mountDir - ErrorAction Stop | Out-Null
133+ Add-DriversToImage - MountPath $mountDir - InfPaths $InfPaths - DriverDir $DriverDir - Label " boot" - Logger $Logger
134+ & $Logger " Saving boot.wim..."
135+ Dismount-WindowsImage - Path $mountDir - Save - ErrorAction Stop | Out-Null
136+ & $Logger " boot.wim driver injection complete."
137+ } catch {
138+ & $Logger " Warning: boot.wim driver injection failed: $_ "
139+ try { Dismount-WindowsImage - Path $mountDir - Discard - ErrorAction SilentlyContinue | Out-Null } catch {}
140+ } finally {
141+ Remove-Item - Path $mountDir - Recurse - Force - ErrorAction SilentlyContinue
142+ }
143+ }
144+
83145 # ═════════════════════════════════════════════════════════════════════════
84146 # 1. Remove provisioned AppX packages
85147 # ═════════════════════════════════════════════════════════════════════════
@@ -145,48 +207,42 @@ function Invoke-WinUtilISOScript {
145207
146208 # ═════════════════════════════════════════════════════════════════════════
147209 # 2. Inject hardware drivers (NVMe / Trackpad / Network)
210+ # Injected into BOTH install.wim (OS) AND boot.wim index 2 (Setup).
211+ # Without storage drivers in boot.wim, Windows Setup cannot see the
212+ # target disk on systems with unsupported NVMe / SATA controllers.
148213 # ═════════════════════════════════════════════════════════════════════════
149214 & $Log " Exporting hardware drivers from running system (NVMe, HID/Trackpad, Network)..."
150215
151216 $driverExportRoot = Join-Path $env: TEMP " WinUtil_DriverExport_$ ( Get-Random ) "
152217 New-Item - Path $driverExportRoot - ItemType Directory - Force | Out-Null
153218
154219 try {
155- # Export every online driver to the temp folder.
156- # Export-WindowsDriver creates one sub-folder per .inf package.
157220 Export-WindowsDriver - Online - Destination $driverExportRoot | Out-Null
158221
159- # Driver classes to inject:
160- # SCSIAdapter - NVMe / AHCI storage controllers
161- # HIDClass - Precision Touchpad and HID devices
162- # Net - Ethernet and Wi-Fi adapters
163- $targetClasses = @ ( ' SCSIAdapter ' , ' HIDClass ' , ' Net ' )
222+ # install.wim: SCSIAdapter + HIDClass + Net
223+ $installInfs = Get-ExportedInfPaths - ExportRoot $driverExportRoot - Classes @ ( ' SCSIAdapter ' , ' HIDClass ' , ' Net ' )
224+ & $Log " Injecting $ ( @ ( $installInfs ).Count ) driver package(s) into install.wim... "
225+ Add-DriversToImage - MountPath $ScratchDir - InfPaths $installInfs - Label " install " - Logger $Log
226+ & $Log " install.wim driver injection complete. "
164227
165- $targetInfBases = Get-WindowsDriver - Online |
166- Where-Object { $_.ClassName -in $targetClasses } |
167- ForEach-Object { [IO.Path ]::GetFileNameWithoutExtension($_.OriginalFileName ) } |
168- Select-Object - Unique
169-
170- $injected = 0
171- foreach ($infBase in $targetInfBases ) {
172- $infFile = Get-ChildItem - Path $driverExportRoot - Filter " $infBase .inf" `
173- - Recurse - ErrorAction SilentlyContinue | Select-Object - First 1
174- if ($infFile ) {
175- & dism / English " /image:$ScratchDir " / Add-Driver " /Driver:$ ( $infFile.FullName ) "
176- $injected ++
228+ # boot.wim: SCSIAdapter + Net only (HID not needed in WinPE)
229+ if ($ISOContentsDir -and (Test-Path $ISOContentsDir )) {
230+ $bootWim = Join-Path $ISOContentsDir " sources\boot.wim"
231+ if (Test-Path $bootWim ) {
232+ $bootInfs = Get-ExportedInfPaths - ExportRoot $driverExportRoot - Classes @ (' SCSIAdapter' , ' Net' )
233+ & $Log " Injecting $ ( @ ($bootInfs ).Count) driver package(s) into boot.wim..."
234+ Invoke-BootWimInject - BootWimPath $bootWim - InfPaths $bootInfs - Logger $Log
177235 } else {
178- & $Log " Warning: exported .inf not found for ' $infBase ' — skipped ."
236+ & $Log " Warning: boot.wim not found — skipping boot.wim driver injection ."
179237 }
180238 }
181-
182- & $Log " Driver injection complete - $injected driver package(s) added."
183239 } catch {
184240 & $Log " Error during driver export/injection: $_ "
185241 } finally {
186242 Remove-Item - Path $driverExportRoot - Recurse - Force - ErrorAction SilentlyContinue
187243 }
188244
189- # ── 2b . Optional: extended Storage & Network drivers from community repo ──
245+ # ── 2c . Optional: extended Storage & Network drivers from community repo ──
190246 $extDriverChoice = [System.Windows.MessageBox ]::Show(
191247 " Would you like to add extended Storage and Network drivers?`n`n " +
192248 " This installs EVERY Storage and Networking device driver " +
@@ -221,10 +277,19 @@ function Invoke-WinUtilISOScript {
221277 $extRepoDir 2>&1 | ForEach-Object { & $Log " git: $_ " }
222278
223279 if (Test-Path $extRepoDir ) {
224- & $Log " Injecting extended drivers into image (this may take several minutes)..."
225- & dism / English " /image:$ScratchDir " / Add-Driver " /Driver:$extRepoDir " / Recurse 2>&1 |
226- ForEach-Object { & $Log " dism: $_ " }
227- & $Log " Extended driver injection complete."
280+ & $Log " Injecting extended drivers into install.wim (this may take several minutes)..."
281+ Add-DriversToImage - MountPath $ScratchDir - DriverDir $extRepoDir - Label " install" - Logger $Log
282+ & $Log " Extended driver injection into install.wim complete."
283+
284+ if ($ISOContentsDir -and (Test-Path $ISOContentsDir )) {
285+ $bootWimExt = Join-Path $ISOContentsDir " sources\boot.wim"
286+ if (Test-Path $bootWimExt ) {
287+ & $Log " Injecting extended drivers into boot.wim..."
288+ Invoke-BootWimInject - BootWimPath $bootWimExt - DriverDir $extRepoDir - Logger $Log
289+ } else {
290+ & $Log " Warning: boot.wim not found — skipping extended driver injection into boot.wim."
291+ }
292+ }
228293 } else {
229294 & $Log " Warning: repository clone directory not found — skipping extended drivers."
230295 }
0 commit comments