1+ [CmdletBinding ()]
2+ param ([Parameter (Mandatory  =  $true )]
3+     [string ]$buildNumber )
4+ 
5+ #  Ensure the error action preference is set to the default for PowerShell3, 'Stop'
6+ $ErrorActionPreference  =  ' Stop' 
7+ 
8+ #  Constants
9+ $WindowsSDKOptions  =  @ (" OptionId.UWPCpp" 
10+ $WindowsSDKRegPath  =  " HKLM:\Software\Microsoft\Windows Kits\Installed Roots" 
11+ $WindowsSDKRegRootKey  =  " KitsRoot10" 
12+ $WindowsSDKVersion  =  " 10.0.$buildNumber .0" 
13+ $WindowsSDKInstalledRegPath  =  " $WindowsSDKRegPath \$WindowsSDKVersion \Installed Options" 
14+ $StrongNameRegPath  =  " HKLM:\SOFTWARE\Microsoft\StrongName\Verification" 
15+ $PublicKeyTokens  =  @ (" 31bf3856ad364e35" 
16+ 
17+ function  Download-File  {
18+     param  ([string ] $outDir , 
19+         [string ] $downloadUrl , 
20+         [string ] $downloadName )
21+ 
22+     $downloadPath  =  Join-Path  $outDir  " $downloadName .download" 
23+     $downloadDest  =  Join-Path  $outDir  $downloadName 
24+     $downloadDestTemp  =  Join-Path  $outDir  " $downloadName .tmp" 
25+ 
26+     Write-Host  - NoNewline " Downloading $downloadName ..." 
27+ 
28+     try  {
29+         $webclient  =  new-object  System.Net.WebClient
30+         $webclient.DownloadFile  ($downloadUrl ,  $downloadPath )
31+     }
32+     catch  [System.Net.WebException ] {
33+         Write-Host 
34+         Write-Warning  " Failed to fetch updated file from $downloadUrl " 
35+         if  (! (Test-Path  $downloadDest )) {
36+             throw  " $downloadName  was not found at $downloadDest " 
37+         }
38+         else  {
39+             Write-Warning  " $downloadName  may be out of date" 
40+         }
41+     }
42+ 
43+     Unblock-File  $downloadPath 
44+ 
45+     $downloadDestTemp  =  $downloadPath ;
46+ 
47+     #  Delete and rename to final dest
48+     if  (Test-Path  - PathType Container $downloadDest ) {
49+         [System.IO.Directory ]::Delete($downloadDest ,  $true )
50+     }
51+ 
52+     Move-Item  - Force $downloadDestTemp  $downloadDest 
53+     Write-Host  " Done" 
54+ 
55+     return  $downloadDest 
56+ }
57+ 
58+ function  Get-ISODriveLetter  {
59+     param  ([string ] $isoPath )
60+ 
61+     $diskImage  =  Get-DiskImage  - ImagePath $isoPath 
62+     if  ($diskImage ) {
63+         $volume  =  Get-Volume  - DiskImage $diskImage 
64+ 
65+         if  ($volume ) {
66+             $driveLetter  =  $volume.DriveLetter  
67+             if  ($driveLetter ) {
68+                 $driveLetter  +=  " :" 
69+                 return  $driveLetter 
70+             }
71+         }
72+     }
73+ 
74+     return  $null 
75+ }
76+ 
77+ function  Mount-ISO  {
78+     param  ([string ] $isoPath )
79+ 
80+     #  Check if image is already mounted
81+     $isoDrive  =  Get-ISODriveLetter  $isoPath 
82+ 
83+     if  (! $isoDrive ) {
84+         Mount-DiskImage  - ImagePath $isoPath  - StorageType ISO |  Out-Null 
85+     }
86+ 
87+     $isoDrive  =  Get-ISODriveLetter  $isoPath 
88+     Write-Verbose  " $isoPath  mounted to ${isoDrive} :" 
89+ }
90+ 
91+ function  Dismount-ISO  {
92+     param  ([string ] $isoPath )
93+ 
94+     $isoDrive  =  (Get-DiskImage  - ImagePath $isoPath  |  Get-Volume ).DriveLetter
95+ 
96+     if  ($isoDrive ) {
97+         Write-Verbose  " $isoPath  dismounted" 
98+         Dismount-DiskImage  - ImagePath $isoPath  |  Out-Null 
99+     }
100+ }
101+ 
102+ function  Disable-StrongName  {
103+     param  ([string ] $publicKeyToken  =  " *" 
104+ 
105+     reg ADD " HKLM\SOFTWARE\Microsoft\StrongName\Verification\*,$publicKeyToken " / f |  Out-Null 
106+     if  ($env: PROCESSOR_ARCHITECTURE  -eq  " AMD64" 
107+         reg ADD " HKLM\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\*,$publicKeyToken " / f |  Out-Null 
108+     }
109+ }
110+ 
111+ function  Test-Admin  {
112+     $identity  =  [Security.Principal.WindowsIdentity ]::GetCurrent()
113+     $principal  =  New-Object  Security.Principal.WindowsPrincipal $identity 
114+     $principal.IsInRole  ([Security.Principal.WindowsBuiltInRole ]::Administrator)
115+ }
116+ 
117+ function  Test-RegistryPathAndValue  {
118+     param  (
119+         [parameter (Mandatory  =  $true )]
120+         [ValidateNotNullOrEmpty ()]
121+         [string ] $path , 
122+         [parameter (Mandatory  =  $true )]
123+         [ValidateNotNullOrEmpty ()]
124+         [string ] $value )
125+ 
126+     try  {
127+         if  (Test-Path  $path ) {
128+             Get-ItemProperty  - Path $path  |  Select-Object  - ExpandProperty $value  - ErrorAction Stop |  Out-Null 
129+             return  $true 
130+         }
131+     }
132+     catch  {
133+     }
134+ 
135+     return  $false 
136+ }
137+ 
138+ function  Test-InstallWindowsSDK  {
139+     $retval  =  $true 
140+ 
141+     if  (Test-RegistryPathAndValue  - Path $WindowsSDKRegPath  - Value $WindowsSDKRegRootKey ) {
142+         #  A Windows SDK is installed
143+         #  Is an SDK of our version installed with the options we need?
144+         if  (Test-RegistryPathAndValue  - Path $WindowsSDKInstalledRegPath  - Value " $WindowsSDKOptions " 
145+             #  It appears we have what we need. Double check the disk
146+             $sdkRoot  =  Get-ItemProperty  - Path $WindowsSDKRegPath  |  Select-Object  - ExpandProperty $WindowsSDKRegRootKey 
147+             if  ($sdkRoot ) {
148+                 if  (Test-Path  $sdkRoot ) {
149+                     $refPath  =  Join-Path  $sdkRoot  " References\$WindowsSDKVersion " 
150+                     if  (Test-Path  $refPath ) {
151+                         $umdPath  =  Join-Path  $sdkRoot  " UnionMetadata\$WindowsSDKVersion " 
152+                         if  (Test-Path  $umdPath ) {
153+                             #  Pretty sure we have what we need
154+                             $retval  =  $false 
155+                         }
156+                     }
157+                 }
158+             }
159+         }
160+     }
161+ 
162+     return  $retval 
163+ }
164+ 
165+ function  Test-InstallStrongNameHijack  {
166+     foreach  ($publicKeyToken  in  $PublicKeyTokens ) {
167+         $key  =  " $StrongNameRegPath \*,$publicKeyToken " 
168+         if  (! (Test-Path  $key )) {
169+             return  $true 
170+         }
171+     }
172+ 
173+     return  $false 
174+ }
175+ 
176+ Write-Host  - NoNewline " Checking for installed Windows SDK $WindowsSDKVersion ..." 
177+ $InstallWindowsSDK  =  Test-InstallWindowsSDK 
178+ if  ($InstallWindowsSDK ) {
179+     Write-Host  " Installation required" 
180+ }
181+ else  {
182+     Write-Host  " INSTALLED" 
183+ }
184+ 
185+ $StrongNameHijack  =  Test-InstallStrongNameHijack 
186+ Write-Host  - NoNewline " Checking if StrongName bypass required..." 
187+ 
188+ if  ($StrongNameHijack ) {
189+     Write-Host  " REQUIRED" 
190+ }
191+ else  {
192+     Write-Host  " Done" 
193+ }
194+ 
195+ if  ($StrongNameHijack  -or  $InstallWindowsSDK ) {
196+     if  (! (Test-Admin )) {
197+         Write-Host 
198+         throw  " ERROR: Elevation required" 
199+     }
200+ }
201+ 
202+ if  ($InstallWindowsSDK ) {
203+     #  Static(ish) link for Windows SDK
204+     #  Note: there is a delay from Windows SDK announcements to availability via the static link
205+     $uri  =  " https://software-download.microsoft.com/download/sg/Windows_InsiderPreview_SDK_en-us_$ ( $buildNumber ) _1.iso" 
206+ 
207+     if  ($null  -eq  $env: TEMP ) {
208+         $env: TEMP  =  Join-Path  $env: SystemDrive  ' temp' 
209+     }
210+ 
211+     $winsdkTempDir  =  Join-Path  $env: TEMP  " WindowsSDK" 
212+ 
213+     if  (! [System.IO.Directory ]::Exists($winsdkTempDir )) {
214+         [void ][System.IO.Directory ]::CreateDirectory($winsdkTempDir )
215+     }
216+ 
217+     $file  =  " winsdk_$buildNumber .iso" 
218+ 
219+     Write-Verbose  " Getting WinSDK from $uri " 
220+     $downloadFile  =  Download- File $winsdkTempDir  $uri  $file 
221+ 
222+     #  TODO Check if zip, exe, iso, etc.
223+     try  {
224+         Write-Host  - NoNewline " Mounting ISO $file ..." 
225+         Mount-ISO  $downloadFile 
226+         Write-Host  " Done" 
227+ 
228+         $isoDrive  =  Get-ISODriveLetter  $downloadFile 
229+ 
230+         if  (Test-Path  $isoDrive ) {
231+             Write-Host  - NoNewLine " Installing WinSDK..." 
232+ 
233+             $setupPath  =  Join-Path  " $isoDrive " " WinSDKSetup.exe" 
234+             Start-Process  - Wait $setupPath  " /features $WindowsSDKOptions  /q" 
235+             Write-Host  " Done" 
236+         }
237+         else  {
238+             throw  " Could not find mounted ISO at ${isoDrive} " 
239+         }
240+     }
241+     finally  {
242+         Write-Host  - NoNewline " Dismounting ISO $file ..." 
243+         #  Dismount-ISO $downloadFile
244+         Write-Host  " Done" 
245+     }
246+ }
247+ 
248+ if  ($StrongNameHijack ) {
249+     Write-Host  - NoNewline " Disabling StrongName for Windows SDK..." 
250+ 
251+     foreach  ($key  in  $PublicKeyTokens ) {
252+         Disable-StrongName  $key 
253+     }
254+ 
255+     Write-Host  " Done" 
256+ }
0 commit comments