mirror of
https://github.com/pbatard/Fido.git
synced 2025-09-16 14:18:02 +02:00

* Gotta really praise Microsoft for having designed their download servers to handle multiple archs for the same Windows SKUs... and then completely throw that out of the window to instead make Windows 11 ARM64 a different SKU. * Now, because we don't want to be *AS MORONIC AS MICROSOFT*, we go the extra mile (and issue multiple requests, using multiple session IDs) to make the ARM64 *ARCHITECTURE* fall into the fold of where it belongs, i.e. as a user selectable property of a single Windows 11 release. * Closes #97.
1348 lines
53 KiB
PowerShell
1348 lines
53 KiB
PowerShell
#
|
||
# Fido v1.61 - Feature ISO Downloader, for retail Windows images and UEFI Shell
|
||
# Copyright © 2019-2024 Pete Batard <pete@akeo.ie>
|
||
# Command line support: Copyright © 2021 flx5
|
||
# ConvertTo-ImageSource: Copyright © 2016 Chris Carter
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#
|
||
|
||
# NB: You must have a BOM on your .ps1 if you want Powershell to actually
|
||
# realise it should use Unicode for the UI rather than ISO-8859-1.
|
||
|
||
#region Parameters
|
||
param(
|
||
# (Optional) The title to display on the application window.
|
||
[string]$AppTitle = "Fido - Feature ISO Downloader",
|
||
# (Optional) '|' separated UI localization strings.
|
||
[string]$LocData,
|
||
# (Optional) Forced locale
|
||
[string]$Locale = "en-US",
|
||
# (Optional) Path to a file that should be used for the UI icon.
|
||
[string]$Icon,
|
||
# (Optional) Name of a pipe the download URL should be sent to.
|
||
# If not provided, a browser window is opened instead.
|
||
[string]$PipeName,
|
||
# (Optional) Specify Windows version (e.g. "Windows 10") [Toggles commandline mode]
|
||
[string]$Win,
|
||
# (Optional) Specify Windows release (e.g. "21H1") [Toggles commandline mode]
|
||
[string]$Rel,
|
||
# (Optional) Specify Windows edition (e.g. "Pro") [Toggles commandline mode]
|
||
[string]$Ed,
|
||
# (Optional) Specify Windows language [Toggles commandline mode]
|
||
[string]$Lang,
|
||
# (Optional) Specify Windows architecture [Toggles commandline mode]
|
||
[string]$Arch,
|
||
# (Optional) Only display the download URL [Toggles commandline mode]
|
||
[switch]$GetUrl = $false,
|
||
# (Optional) Increase verbosity
|
||
[switch]$Verbose = $false,
|
||
# (Optional) Produce debugging information
|
||
[switch]$Debug = $false
|
||
)
|
||
#endregion
|
||
|
||
try {
|
||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||
} catch {}
|
||
|
||
$Cmd = $false
|
||
if ($Win -or $Rel -or $Ed -or $Lang -or $Arch -or $GetUrl) {
|
||
$Cmd = $true
|
||
}
|
||
|
||
# Return a decimal Windows version that we can then check for platform support.
|
||
# Note that because we don't want to have to support this script on anything
|
||
# other than Windows, this call returns 0.0 for PowerShell running on Linux/Mac.
|
||
function Get-Platform-Version()
|
||
{
|
||
$version = 0.0
|
||
$platform = [string][System.Environment]::OSVersion.Platform
|
||
# This will filter out non Windows platforms
|
||
if ($platform.StartsWith("Win")) {
|
||
# Craft a decimal numeric version of Windows
|
||
$version = [System.Environment]::OSVersion.Version.Major * 1.0 + [System.Environment]::OSVersion.Version.Minor * 0.1
|
||
}
|
||
return $version
|
||
}
|
||
|
||
$winver = Get-Platform-Version
|
||
|
||
# The default TLS for Windows 8.x doesn't work with Microsoft's servers so we must force it
|
||
if ($winver -lt 10.0) {
|
||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
|
||
}
|
||
|
||
#region Assembly Types
|
||
$Drawing_Assembly = "System.Drawing"
|
||
# PowerShell 7 altered the name of the Drawing assembly...
|
||
if ($host.version -ge "7.0") {
|
||
$Drawing_Assembly += ".Common"
|
||
}
|
||
|
||
$Signature = @{
|
||
Namespace = "WinAPI"
|
||
Name = "Utils"
|
||
Language = "CSharp"
|
||
UsingNamespace = "System.Runtime", "System.IO", "System.Text", "System.Drawing", "System.Globalization"
|
||
ReferencedAssemblies = $Drawing_Assembly
|
||
ErrorAction = "Stop"
|
||
WarningAction = "Ignore"
|
||
IgnoreWarnings = $true
|
||
MemberDefinition = @"
|
||
[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||
internal static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons);
|
||
|
||
[DllImport("user32.dll")]
|
||
public static extern bool ShowWindow(IntPtr handle, int state);
|
||
// Extract an icon from a DLL
|
||
public static Icon ExtractIcon(string file, int number, bool largeIcon) {
|
||
IntPtr large, small;
|
||
ExtractIconEx(file, number, out large, out small, 1);
|
||
try {
|
||
return Icon.FromHandle(largeIcon ? large : small);
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
"@
|
||
}
|
||
|
||
if (!$Cmd) {
|
||
Write-Host Please Wait...
|
||
|
||
if (!("WinAPI.Utils" -as [type]))
|
||
{
|
||
Add-Type @Signature
|
||
}
|
||
Add-Type -AssemblyName PresentationFramework
|
||
|
||
# Hide the powershell window: https://stackoverflow.com/a/27992426/1069307
|
||
[WinAPI.Utils]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0) | Out-Null
|
||
}
|
||
#endregion
|
||
|
||
#region Data
|
||
$WindowsVersions = @(
|
||
@(
|
||
@("Windows 11", "windows11"),
|
||
@(
|
||
"24H2 (Build 26100.1742 - 2024.10)",
|
||
# Thanks to Microsoft's hare-brained decision not to treat ARM64 as a CPU arch,
|
||
# like they did for x86 and x64, we have to handle multiple IDs for each release...
|
||
@("Windows 11 Home/Pro/Edu", @(3113, 3131)),
|
||
@("Windows 11 Home China ", @(3115, 3132)),
|
||
@("Windows 11 Pro China ", @(3114, 3133))
|
||
)
|
||
),
|
||
@(
|
||
@("Windows 10", "Windows10ISO"),
|
||
@(
|
||
"22H2 v1 (Build 19045.2965 - 2023.05)",
|
||
@("Windows 10 Home/Pro/Edu", 2618),
|
||
@("Windows 10 Home China ", 2378)
|
||
)
|
||
)
|
||
@(
|
||
@("UEFI Shell 2.2", "UEFI_SHELL 2.2"),
|
||
@(
|
||
"24H1 (edk2-stable202405)",
|
||
@("Release", 0),
|
||
@("Debug", 1)
|
||
),
|
||
@(
|
||
"23H2 (edk2-stable202311)",
|
||
@("Release", 0),
|
||
@("Debug", 1)
|
||
),
|
||
@(
|
||
"23H1 (edk2-stable202305)",
|
||
@("Release", 0),
|
||
@("Debug", 1)
|
||
),
|
||
@(
|
||
"22H2 (edk2-stable202211)",
|
||
@("Release", 0),
|
||
@("Debug", 1)
|
||
),
|
||
@(
|
||
"22H1 (edk2-stable202205)",
|
||
@("Release", 0),
|
||
@("Debug", 1)
|
||
),
|
||
@(
|
||
"21H2 (edk2-stable202108)",
|
||
@("Release", 0),
|
||
@("Debug", 1)
|
||
),
|
||
@(
|
||
"21H1 (edk2-stable202105)",
|
||
@("Release", 0),
|
||
@("Debug", 1)
|
||
),
|
||
@(
|
||
"20H2 (edk2-stable202011)",
|
||
@("Release", 0),
|
||
@("Debug", 1)
|
||
)
|
||
),
|
||
@(
|
||
@("UEFI Shell 2.0", "UEFI_SHELL 2.0"),
|
||
@(
|
||
"4.632 [20100426]",
|
||
@("Release", 0)
|
||
)
|
||
)
|
||
)
|
||
#endregion
|
||
|
||
#region Functions
|
||
function Select-Language([string]$LangName)
|
||
{
|
||
# Use the system locale to try select the most appropriate language
|
||
[string]$SysLocale = [System.Globalization.CultureInfo]::CurrentUICulture.Name
|
||
if (($SysLocale.StartsWith("ar") -and $LangName -like "*Arabic*") -or `
|
||
($SysLocale -eq "pt-BR" -and $LangName -like "*Brazil*") -or `
|
||
($SysLocale.StartsWith("ar") -and $LangName -like "*Bulgar*") -or `
|
||
($SysLocale -eq "zh-CN" -and $LangName -like "*Chinese*" -and $LangName -like "*simp*") -or `
|
||
($SysLocale -eq "zh-TW" -and $LangName -like "*Chinese*" -and $LangName -like "*trad*") -or `
|
||
($SysLocale.StartsWith("hr") -and $LangName -like "*Croat*") -or `
|
||
($SysLocale.StartsWith("cz") -and $LangName -like "*Czech*") -or `
|
||
($SysLocale.StartsWith("da") -and $LangName -like "*Danish*") -or `
|
||
($SysLocale.StartsWith("nl") -and $LangName -like "*Dutch*") -or `
|
||
($SysLocale -eq "en-US" -and $LangName -eq "English") -or `
|
||
($SysLocale.StartsWith("en") -and $LangName -like "*English*" -and ($LangName -like "*inter*" -or $LangName -like "*ingdom*")) -or `
|
||
($SysLocale.StartsWith("et") -and $LangName -like "*Eston*") -or `
|
||
($SysLocale.StartsWith("fi") -and $LangName -like "*Finn*") -or `
|
||
($SysLocale -eq "fr-CA" -and $LangName -like "*French*" -and $LangName -like "*Canad*") -or `
|
||
($SysLocale.StartsWith("fr") -and $LangName -eq "French") -or `
|
||
($SysLocale.StartsWith("de") -and $LangName -like "*German*") -or `
|
||
($SysLocale.StartsWith("el") -and $LangName -like "*Greek*") -or `
|
||
($SysLocale.StartsWith("he") -and $LangName -like "*Hebrew*") -or `
|
||
($SysLocale.StartsWith("hu") -and $LangName -like "*Hungar*") -or `
|
||
($SysLocale.StartsWith("id") -and $LangName -like "*Indones*") -or `
|
||
($SysLocale.StartsWith("it") -and $LangName -like "*Italia*") -or `
|
||
($SysLocale.StartsWith("ja") -and $LangName -like "*Japan*") -or `
|
||
($SysLocale.StartsWith("ko") -and $LangName -like "*Korea*") -or `
|
||
($SysLocale.StartsWith("lv") -and $LangName -like "*Latvia*") -or `
|
||
($SysLocale.StartsWith("lt") -and $LangName -like "*Lithuania*") -or `
|
||
($SysLocale.StartsWith("ms") -and $LangName -like "*Malay*") -or `
|
||
($SysLocale.StartsWith("nb") -and $LangName -like "*Norw*") -or `
|
||
($SysLocale.StartsWith("fa") -and $LangName -like "*Persia*") -or `
|
||
($SysLocale.StartsWith("pl") -and $LangName -like "*Polish*") -or `
|
||
($SysLocale -eq "pt-PT" -and $LangName -eq "Portuguese") -or `
|
||
($SysLocale.StartsWith("ro") -and $LangName -like "*Romania*") -or `
|
||
($SysLocale.StartsWith("ru") -and $LangName -like "*Russia*") -or `
|
||
($SysLocale.StartsWith("sr") -and $LangName -like "*Serbia*") -or `
|
||
($SysLocale.StartsWith("sk") -and $LangName -like "*Slovak*") -or `
|
||
($SysLocale.StartsWith("sl") -and $LangName -like "*Slovenia*") -or `
|
||
($SysLocale -eq "es-ES" -and $LangName -eq "Spanish") -or `
|
||
($SysLocale.StartsWith("es") -and $Locale -ne "es-ES" -and $LangName -like "*Spanish*") -or `
|
||
($SysLocale.StartsWith("sv") -and $LangName -like "*Swed*") -or `
|
||
($SysLocale.StartsWith("th") -and $LangName -like "*Thai*") -or `
|
||
($SysLocale.StartsWith("tr") -and $LangName -like "*Turk*") -or `
|
||
($SysLocale.StartsWith("uk") -and $LangName -like "*Ukrain*") -or `
|
||
($SysLocale.StartsWith("vi") -and $LangName -like "*Vietnam*")) {
|
||
return $true
|
||
}
|
||
return $false
|
||
}
|
||
|
||
function Add-Entry([int]$pos, [string]$Name, [array]$Items, [string]$DisplayName)
|
||
{
|
||
$Title = New-Object System.Windows.Controls.TextBlock
|
||
$Title.FontSize = $WindowsVersionTitle.FontSize
|
||
$Title.Height = $WindowsVersionTitle.Height;
|
||
$Title.Width = $WindowsVersionTitle.Width;
|
||
$Title.HorizontalAlignment = "Left"
|
||
$Title.VerticalAlignment = "Top"
|
||
$Margin = $WindowsVersionTitle.Margin
|
||
$Margin.Top += $pos * $dh
|
||
$Title.Margin = $Margin
|
||
$Title.Text = Get-Translation($Name)
|
||
$XMLGrid.Children.Insert(2 * $Stage + 2, $Title)
|
||
|
||
$Combo = New-Object System.Windows.Controls.ComboBox
|
||
$Combo.FontSize = $WindowsVersion.FontSize
|
||
$Combo.Height = $WindowsVersion.Height;
|
||
$Combo.Width = $WindowsVersion.Width;
|
||
$Combo.HorizontalAlignment = "Left"
|
||
$Combo.VerticalAlignment = "Top"
|
||
$Margin = $WindowsVersion.Margin
|
||
$Margin.Top += $pos * $script:dh
|
||
$Combo.Margin = $Margin
|
||
$Combo.SelectedIndex = 0
|
||
if ($Items) {
|
||
$Combo.ItemsSource = $Items
|
||
if ($DisplayName) {
|
||
$Combo.DisplayMemberPath = $DisplayName
|
||
} else {
|
||
$Combo.DisplayMemberPath = $Name
|
||
}
|
||
}
|
||
$XMLGrid.Children.Insert(2 * $Stage + 3, $Combo)
|
||
|
||
$XMLForm.Height += $dh;
|
||
$Margin = $Continue.Margin
|
||
$Margin.Top += $dh
|
||
$Continue.Margin = $Margin
|
||
$Margin = $Back.Margin
|
||
$Margin.Top += $dh
|
||
$Back.Margin = $Margin
|
||
|
||
return $Combo
|
||
}
|
||
|
||
function Refresh-Control([object]$Control)
|
||
{
|
||
$Control.Dispatcher.Invoke("Render", [Windows.Input.InputEventHandler] { $Continue.UpdateLayout() }, $null, $null) | Out-Null
|
||
}
|
||
|
||
function Send-Message([string]$PipeName, [string]$Message)
|
||
{
|
||
[System.Text.Encoding]$Encoding = [System.Text.Encoding]::UTF8
|
||
$Pipe = New-Object -TypeName System.IO.Pipes.NamedPipeClientStream -ArgumentList ".", $PipeName, ([System.IO.Pipes.PipeDirection]::Out), ([System.IO.Pipes.PipeOptions]::None), ([System.Security.Principal.TokenImpersonationLevel]::Impersonation)
|
||
try {
|
||
$Pipe.Connect(1000)
|
||
} catch {
|
||
Write-Host $_.Exception.Message
|
||
}
|
||
$bRequest = $Encoding.GetBytes($Message)
|
||
$cbRequest = $bRequest.Length;
|
||
$Pipe.Write($bRequest, 0, $cbRequest);
|
||
$Pipe.Dispose()
|
||
}
|
||
|
||
# From https://www.powershellgallery.com/packages/IconForGUI/1.5.2
|
||
# Copyright © 2016 Chris Carter. All rights reserved.
|
||
# License: https://creativecommons.org/licenses/by-sa/4.0/
|
||
function ConvertTo-ImageSource
|
||
{
|
||
[CmdletBinding()]
|
||
Param(
|
||
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
|
||
[System.Drawing.Icon]$Icon
|
||
)
|
||
|
||
Process {
|
||
foreach ($i in $Icon) {
|
||
[System.Windows.Interop.Imaging]::CreateBitmapSourceFromHIcon(
|
||
$i.Handle,
|
||
(New-Object System.Windows.Int32Rect -Args 0,0,$i.Width, $i.Height),
|
||
[System.Windows.Media.Imaging.BitmapSizeOptions]::FromEmptyOptions()
|
||
)
|
||
}
|
||
}
|
||
}
|
||
|
||
function Throw-Error([object]$Req, [string]$Alt)
|
||
{
|
||
$Err = $(GetElementById -Request $Req -Id "errorModalMessage").innerText -replace "<[^>]+>" -replace "\s+", " "
|
||
if (!$Err) {
|
||
$Err = $Alt
|
||
} else {
|
||
$Err = [System.Text.Encoding]::UTF8.GetString([byte[]][char[]]$Err)
|
||
}
|
||
throw $Err
|
||
}
|
||
|
||
# Translate a message string
|
||
function Get-Translation([string]$Text)
|
||
{
|
||
if (!($English -contains $Text)) {
|
||
Write-Host "Error: '$Text' is not a translatable string"
|
||
return "(Untranslated)"
|
||
}
|
||
if ($Localized) {
|
||
if ($Localized.Length -ne $English.Length) {
|
||
Write-Host "Error: '$Text' is not a translatable string"
|
||
}
|
||
for ($i = 0; $i -lt $English.Length; $i++) {
|
||
if ($English[$i] -eq $Text) {
|
||
if ($Localized[$i]) {
|
||
return $Localized[$i]
|
||
} else {
|
||
return $Text
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return $Text
|
||
}
|
||
|
||
# Get the underlying *native* CPU architecture
|
||
function Get-Arch
|
||
{
|
||
$Arch = Get-CimInstance -ClassName Win32_Processor | Select-Object -ExpandProperty Architecture
|
||
switch($Arch) {
|
||
0 { return "x86" }
|
||
1 { return "MIPS" }
|
||
2 { return "Alpha" }
|
||
3 { return "PowerPC" }
|
||
5 { return "ARM32" }
|
||
6 { return "IA64" }
|
||
9 { return "x64" }
|
||
12 { return "ARM64" }
|
||
default { return "Unknown"}
|
||
}
|
||
}
|
||
|
||
# Some PowerShells don't have Microsoft.mshtml assembly (comes with MS Office?)
|
||
# so we can't use ParsedHtml or IHTMLDocument[2|3] features there...
|
||
function GetElementById([object]$Request, [string]$Id)
|
||
{
|
||
try {
|
||
return $Request.ParsedHtml.IHTMLDocument3_GetElementByID($Id)
|
||
} catch {
|
||
return $Request.AllElements | ? {$_.id -eq $Id}
|
||
}
|
||
}
|
||
|
||
function Error([string]$ErrorMessage)
|
||
{
|
||
Write-Host Error: $ErrorMessage
|
||
if (!$Cmd) {
|
||
$XMLForm.Title = $(Get-Translation("Error")) + ": " + $ErrorMessage
|
||
Refresh-Control($XMLForm)
|
||
$XMLGrid.Children[2 * $script:Stage + 1].IsEnabled = $true
|
||
$UserInput = [System.Windows.MessageBox]::Show($XMLForm.Title, $(Get-Translation("Error")), "OK", "Error")
|
||
$script:ExitCode = $script:Stage--
|
||
} else {
|
||
$script:ExitCode = 2
|
||
}
|
||
}
|
||
|
||
function Get-RandomDate()
|
||
{
|
||
[DateTime]$Min = "1/1/2008"
|
||
[DateTime]$Max = [DateTime]::Now
|
||
|
||
$RandomGen = new-object random
|
||
$RandomTicks = [Convert]::ToInt64( ($Max.ticks * 1.0 - $Min.Ticks * 1.0 ) * $RandomGen.NextDouble() + $Min.Ticks * 1.0 )
|
||
$Date = new-object DateTime($RandomTicks)
|
||
return $Date.ToString("yyyyMMdd")
|
||
}
|
||
#endregion
|
||
|
||
#region Form
|
||
[xml]$XAML = @"
|
||
<Window xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" Height = "162" Width = "384" ResizeMode = "NoResize">
|
||
<Grid Name = "XMLGrid">
|
||
<Button Name = "Continue" FontSize = "16" Height = "26" Width = "160" HorizontalAlignment = "Left" VerticalAlignment = "Top" Margin = "14,78,0,0"/>
|
||
<Button Name = "Back" FontSize = "16" Height = "26" Width = "160" HorizontalAlignment = "Left" VerticalAlignment = "Top" Margin = "194,78,0,0"/>
|
||
<TextBlock Name = "WindowsVersionTitle" FontSize = "16" Width="340" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="16,8,0,0"/>
|
||
<ComboBox Name = "WindowsVersion" FontSize = "14" Height = "24" Width = "340" HorizontalAlignment = "Left" VerticalAlignment="Top" Margin = "14,34,0,0" SelectedIndex = "0"/>
|
||
<CheckBox Name = "Check" FontSize = "14" Width = "340" HorizontalAlignment = "Left" VerticalAlignment="Top" Margin = "14,0,0,0" Visibility="Collapsed" />
|
||
</Grid>
|
||
</Window>
|
||
"@
|
||
#endregion
|
||
|
||
#region Globals
|
||
$ErrorActionPreference = "Stop"
|
||
$DefaultTimeout = 30
|
||
$dh = 58
|
||
$Stage = 0
|
||
$SelectedIndex = 0
|
||
$ltrm = ""
|
||
if ($Cmd) {
|
||
$ltrm = ""
|
||
}
|
||
$MaxStage = 4
|
||
# Can't reuse the same sessionId for x64 and ARM64. The Microsoft servers
|
||
# are purposefully designed to ever process one specific download request
|
||
# that matches the last SKUs retrieved.
|
||
$SessionId = @($null) * 2
|
||
$ExitCode = 100
|
||
$Locale = $Locale
|
||
$RequestData = @{}
|
||
# This GUID applies to all visitors, regardless of their locale
|
||
$RequestData["GetLangs"] = @("a8f8f489-4c7f-463a-9ca6-5cff94d8d041", "getskuinformationbyproductedition" )
|
||
# This GUID applies to visitors of the en-US download page. Other locales may get a different GUID.
|
||
$RequestData["GetLinks"] = @("6e2a1789-ef16-4f27-a296-74ef7ef5d96b", "GetProductDownloadLinksBySku" )
|
||
# Create a semi-random Linux User-Agent string
|
||
$FirefoxVersion = Get-Random -Minimum 110 -Maximum 135
|
||
$FirefoxDate = Get-RandomDate
|
||
$UserAgent = "Mozilla/5.0 (X11; Linux i586; rv:$FirefoxVersion.0) Gecko/$FirefoxDate Firefox/$FirefoxVersion.0"
|
||
$Verbosity = 1
|
||
if ($Debug) {
|
||
$Verbosity = 5
|
||
} elseif ($Verbose) {
|
||
$Verbosity = 2
|
||
} elseif ($Cmd -and $GetUrl) {
|
||
$Verbosity = 0
|
||
}
|
||
$PlatformArch = Get-Arch
|
||
#endregion
|
||
|
||
# Localization
|
||
$EnglishMessages = "en-US|Version|Release|Edition|Language|Architecture|Download|Continue|Back|Close|Cancel|Error|Please wait...|" +
|
||
"Download using a browser|Download of Windows ISOs is unavailable due to Microsoft having altered their website to prevent it.|" +
|
||
"PowerShell 3.0 or later is required to run this script.|Do you want to go online and download it?|" +
|
||
"This feature is not available on this platform."
|
||
[string[]]$English = $EnglishMessages.Split('|')
|
||
[string[]]$Localized = $null
|
||
if ($LocData -and !$LocData.StartsWith("en-US")) {
|
||
$Localized = $LocData.Split('|')
|
||
# Adjust the $Localized array if we have more or fewer strings than in $EnglishMessages
|
||
if ($Localized.Length -lt $English.Length) {
|
||
while ($Localized.Length -ne $English.Length) {
|
||
$Localized += $English[$Localized.Length]
|
||
}
|
||
} elseif ($Localized.Length -gt $English.Length) {
|
||
$Localized = $LocData.Split('|')[0..($English.Length - 1)]
|
||
}
|
||
$Locale = $Localized[0]
|
||
}
|
||
$QueryLocale = $Locale
|
||
|
||
# Convert a size in bytes to a human readable string
|
||
function Size-To-Human-Readable([uint64]$size)
|
||
{
|
||
$suffix = "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
|
||
$i = 0
|
||
while ($size -gt 1kb) {
|
||
$size = $size / 1kb
|
||
$i++
|
||
}
|
||
"{0:N1} {1}" -f $size, $suffix[$i]
|
||
}
|
||
|
||
# Check if the locale we want is available - Fall back to en-US otherwise
|
||
function Check-Locale
|
||
{
|
||
try {
|
||
$url = "https://www.microsoft.com/" + $QueryLocale + "/software-download/"
|
||
if ($Verbosity -ge 2) {
|
||
Write-Host Querying $url
|
||
}
|
||
# Looks Microsoft are filtering our script according to the first query it performs with the spoofed user agent.
|
||
# So, to continue this pointless cat and mouse game, we simply add an extra first query with the default user agent.
|
||
# Also: "Hi Microsoft. You sure have A LOT OF RESOURCES TO WASTE to have assigned folks of yours to cripple scripts
|
||
# that merely exist because you have chosen to make the user experience from your download website utterly subpar.
|
||
# And while I am glad senpai noticed me (UwU), I feel compelled to ask: Don't you guys have better things to do?"
|
||
Invoke-WebRequest -UseBasicParsing -TimeoutSec $DefaultTimeout -MaximumRedirection 0 $url | Out-Null
|
||
Invoke-WebRequest -UseBasicParsing -TimeoutSec $DefaultTimeout -MaximumRedirection 0 -UserAgent $UserAgent $url | Out-Null
|
||
} catch {
|
||
# Of course PowerShell 7 had to BREAK $_.Exception.Status on timeouts...
|
||
if ($_.Exception.Status -eq "Timeout" -or $_.Exception.GetType().Name -eq "TaskCanceledException") {
|
||
Write-Host Operation Timed out
|
||
}
|
||
$script:QueryLocale = "en-US"
|
||
}
|
||
}
|
||
|
||
# Return an array of releases (e.g. 20H2, 21H1, ...) for the selected Windows version
|
||
function Get-Windows-Releases([int]$SelectedVersion)
|
||
{
|
||
$i = 0
|
||
$releases = @()
|
||
foreach ($version in $WindowsVersions[$SelectedVersion]) {
|
||
if (($i -ne 0) -and ($version -is [array])) {
|
||
$releases += @(New-Object PsObject -Property @{ Release = $ltrm + $version[0].Replace(")", ")" + $ltrm); Index = $i })
|
||
}
|
||
$i++
|
||
}
|
||
return $releases
|
||
}
|
||
|
||
# Return an array of editions (e.g. Home, Pro, etc) for the selected Windows release
|
||
function Get-Windows-Editions([int]$SelectedVersion, [int]$SelectedRelease)
|
||
{
|
||
$editions = @()
|
||
foreach ($release in $WindowsVersions[$SelectedVersion][$SelectedRelease])
|
||
{
|
||
if ($release -is [array]) {
|
||
if (!($release[0].Contains("China")) -or ($Locale.StartsWith("zh"))) {
|
||
$editions += @(New-Object PsObject -Property @{ Edition = $release[0]; Id = $release[1] })
|
||
}
|
||
}
|
||
}
|
||
return $editions
|
||
}
|
||
|
||
# Return an array of languages for the selected edition
|
||
function Get-Windows-Languages([int]$SelectedVersion, [object]$SelectedEdition)
|
||
{
|
||
$langs = @()
|
||
if ($WindowsVersions[$SelectedVersion][0][1].StartsWith("UEFI_SHELL")) {
|
||
$langs += @(New-Object PsObject -Property @{ DisplayName = "English (US)"; Name = "en-us"; Data = @($null) })
|
||
} else {
|
||
$languages = [ordered]@{}
|
||
$SessionIndex = 0
|
||
foreach ($EditionId in $SelectedEdition) {
|
||
$SessionId[$SessionIndex] = [guid]::NewGuid()
|
||
# Microsoft download protection now requires the sessionId to be whitelisted through vlscppe.microsoft.com/tags
|
||
$url = "https://vlscppe.microsoft.com/tags?org_id=y6jn8c31&session_id=" + $SessionId[$SessionIndex]
|
||
if ($Verbosity -ge 2) {
|
||
Write-Host Querying $url
|
||
}
|
||
try {
|
||
Invoke-WebRequest -UseBasicParsing -TimeoutSec $DefaultTimeout -MaximumRedirection 0 -UserAgent $UserAgent $url | Out-Null
|
||
} catch {
|
||
Error($_.Exception.Message)
|
||
return @()
|
||
}
|
||
$url = "https://www.microsoft.com/" + $QueryLocale + "/api/controls/contentinclude/html"
|
||
$url += "?pageId=" + $RequestData["GetLangs"][0]
|
||
$url += "&host=www.microsoft.com"
|
||
$url += "&segments=software-download," + $WindowsVersions[$SelectedVersion][0][1]
|
||
$url += "&query=&action=" + $RequestData["GetLangs"][1]
|
||
$url += "&sessionId=" + $SessionId[$SessionIndex]
|
||
$url += "&productEditionId=" + $EditionId
|
||
$url += "&sdVersion=2"
|
||
if ($Verbosity -ge 2) {
|
||
Write-Host Querying $url
|
||
}
|
||
try {
|
||
$r = Invoke-WebRequest -Method Post -UseBasicParsing -TimeoutSec $DefaultTimeout -UserAgent $UserAgent -SessionVariable "Session" $url
|
||
if ($Verbosity -ge 5) {
|
||
Write-Host "=============================================================================="
|
||
Write-Host $r
|
||
Write-Host "=============================================================================="
|
||
}
|
||
if ($r -match "errorModalMessage") {
|
||
Throw-Error -Req $r -Alt "Could not retrieve languages from server"
|
||
}
|
||
$r = $r -replace "`n" -replace "`r"
|
||
$pattern = '.*<select id="product-languages"[^>]*>(.*)</select>.*'
|
||
$html = [regex]::Match($r, $pattern).Groups[1].Value
|
||
# Go through an XML conversion to keep all PowerShells happy...
|
||
$html = $html.Replace("selected value", "value")
|
||
$html = "<options>" + $html + "</options>"
|
||
$xml = [xml]$html
|
||
foreach ($var in $xml.options.option) {
|
||
$json = $var.value | ConvertFrom-Json;
|
||
if ($json) {
|
||
if (!$languages.Contains($json.language)) {
|
||
$languages[$json.language] = @{ DisplayName = $var.InnerText; Data = @() }
|
||
}
|
||
$languages[$json.language].Data += @{ SessionIndex = $SessionIndex; SkuId = $json.id }
|
||
}
|
||
}
|
||
if ($languages.Length -eq 0) {
|
||
Throw-Error -Req $r -Alt "Could not parse languages"
|
||
}
|
||
} catch {
|
||
Error($_.Exception.Message)
|
||
return @()
|
||
}
|
||
$SessionIndex++
|
||
}
|
||
# Need to convert to an array since PowerShell treats them differently from hashtable
|
||
$i = 0
|
||
$script:SelectedIndex = 0
|
||
foreach($language in $languages.Keys) {
|
||
$langs += @(New-Object PsObject -Property @{ DisplayName = $languages[$language].DisplayName; Name = $language; Data = $languages[$language].Data })
|
||
if (Select-Language($language)) {
|
||
$script:SelectedIndex = $i
|
||
}
|
||
$i++
|
||
}
|
||
}
|
||
return $langs
|
||
}
|
||
|
||
# Return an array of download links for each supported arch
|
||
function Get-Windows-Download-Links([int]$SelectedVersion, [int]$SelectedRelease, [object]$SelectedEdition, [PSCustomObject]$SelectedLanguage)
|
||
{
|
||
$links = @()
|
||
if ($WindowsVersions[$SelectedVersion][0][1].StartsWith("UEFI_SHELL")) {
|
||
$tag = $WindowsVersions[$SelectedVersion][$SelectedRelease][0].Split(' ')[0]
|
||
$shell_version = $WindowsVersions[$SelectedVersion][0][1].Split(' ')[1]
|
||
$url = "https://github.com/pbatard/UEFI-Shell/releases/download/" + $tag
|
||
$link = $url + "/UEFI-Shell-" + $shell_version + "-" + $tag
|
||
if ($SelectedEdition -eq 0) {
|
||
$link += "-RELEASE.iso"
|
||
} else {
|
||
$link += "-DEBUG.iso"
|
||
}
|
||
try {
|
||
# Read the supported archs from the release URL
|
||
$url += "/Version.xml"
|
||
$xml = New-Object System.Xml.XmlDocument
|
||
if ($Verbosity -ge 2) {
|
||
Write-Host Querying $url
|
||
}
|
||
$xml.Load($url)
|
||
$sep = ""
|
||
$archs = ""
|
||
foreach($arch in $xml.release.supported_archs.arch) {
|
||
$archs += $sep + $arch
|
||
$sep = ", "
|
||
}
|
||
$links += @(New-Object PsObject -Property @{ Type = $archs; Url = $link })
|
||
} catch {
|
||
Error($_.Exception.Message)
|
||
return @()
|
||
}
|
||
} else {
|
||
foreach ($Entry in $SelectedLanguage.Data) {
|
||
$url = "https://www.microsoft.com/" + $QueryLocale + "/api/controls/contentinclude/html"
|
||
$url += "?pageId=" + $RequestData["GetLinks"][0]
|
||
$url += "&host=www.microsoft.com"
|
||
$url += "&segments=software-download," + $WindowsVersions[$SelectedVersion][0][1]
|
||
$url += "&query=&action=" + $RequestData["GetLinks"][1]
|
||
$url += "&sessionId=" + $SessionId[$Entry.SessionIndex]
|
||
$url += "&skuId=" + $Entry.SkuId
|
||
$url += "&language=" + $SelectedLanguage.Name
|
||
$url += "&sdVersion=2"
|
||
if ($Verbosity -ge 2) {
|
||
Write-Host Querying $url
|
||
}
|
||
|
||
try {
|
||
# Must add a referer for this request, else Microsoft's servers will deny it
|
||
$ref = "https://www.microsoft.com/software-download/windows11"
|
||
$r = Invoke-WebRequest -Method Post -Headers @{ "Referer" = $ref } -UseBasicParsing -TimeoutSec $DefaultTimeout -UserAgent $UserAgent -WebSession $Session $url
|
||
if ($Verbosity -ge 5) {
|
||
Write-Host "=============================================================================="
|
||
Write-Host $r
|
||
Write-Host "=============================================================================="
|
||
}
|
||
if ($r -match "errorModalMessage") {
|
||
$Alt = [regex]::Match($r.Content, '<p id="errorModalMessage">(.+?)<\/p>').Groups[1].Value -replace "<[^>]+>" -replace "\s+", " " -replace "\?\?\?", "-"
|
||
$Alt = [System.Text.Encoding]::UTF8.GetString([byte[]][char[]]$Alt)
|
||
if (!$Alt) {
|
||
$Alt = "Could not retrieve architectures from server"
|
||
} elseif ($Alt -match "715-123130") {
|
||
$Alt += " " + $SessionId[$Entry.SessionIndex] + "."
|
||
}
|
||
Throw-Error -Req $r -Alt $Alt
|
||
}
|
||
$pattern = '(?s)(<input.*?></input>)'
|
||
ForEach-Object { [regex]::Matches($r, $pattern) } | ForEach-Object { $html += $_.Groups[1].value }
|
||
# Need to fix the HTML and JSON data so that it is well-formed
|
||
$html = $html.Replace("class=product-download-hidden", "")
|
||
$html = $html.Replace("type=hidden", "")
|
||
$html = $html.Replace(" ", " ")
|
||
$html = $html.Replace("IsoX86", ""x86"")
|
||
$html = $html.Replace("IsoX64", ""x64"")
|
||
# As usual Microsoft's left hand is completely uncoordinated with right hand
|
||
$html = $html.Replace("Unknown", ""ARM64"")
|
||
$html = "<inputs>" + $html + "</inputs>"
|
||
$xml = [xml]$html
|
||
foreach ($var in $xml.inputs.input) {
|
||
$json = $var.value | ConvertFrom-Json;
|
||
if ($json) {
|
||
$links += @(New-Object PsObject -Property @{ Type = $json.DownloadType; Url = $json.Uri })
|
||
}
|
||
}
|
||
if ($links.Length -eq 0) {
|
||
Throw-Error -Req $r -Alt "Could not retrieve ISO download links"
|
||
}
|
||
} catch {
|
||
Error($_.Exception.Message)
|
||
return @()
|
||
}
|
||
$SessionIndex++
|
||
}
|
||
$i = 0
|
||
$script:SelectedIndex = 0
|
||
foreach($link in $links) {
|
||
if ($link.Type -eq $PlatformArch) {
|
||
$script:SelectedIndex = $i
|
||
}
|
||
$i++
|
||
}
|
||
}
|
||
return $links
|
||
}
|
||
|
||
# Process the download URL by either sending it through the pipe or by opening the browser
|
||
function Process-Download-Link([string]$Url)
|
||
{
|
||
try {
|
||
if ($PipeName -and !$Check.IsChecked) {
|
||
Send-Message -PipeName $PipeName -Message $Url
|
||
} else {
|
||
if ($Cmd) {
|
||
$pattern = '.*\/(.*\.iso).*'
|
||
$File = [regex]::Match($Url, $pattern).Groups[1].Value
|
||
# PowerShell implicit conversions are iffy, so we need to force them...
|
||
$str_size = (Invoke-WebRequest -UseBasicParsing -TimeoutSec $DefaultTimeout -Uri $Url -Method Head).Headers.'Content-Length'
|
||
$tmp_size = [uint64]::Parse($str_size)
|
||
$Size = Size-To-Human-Readable $tmp_size
|
||
Write-Host "Downloading '$File' ($Size)..."
|
||
Start-BitsTransfer -Source $Url -Destination $File
|
||
} else {
|
||
Write-Host Download Link: $Url
|
||
Start-Process -FilePath $Url
|
||
}
|
||
}
|
||
} catch {
|
||
Error($_.Exception.Message)
|
||
return 404
|
||
}
|
||
return 0
|
||
}
|
||
|
||
if ($Cmd) {
|
||
$winVersionId = $null
|
||
$winReleaseId = $null
|
||
$winEditionId = $null
|
||
$winLanguageId = $null
|
||
$winLanguageName = $null
|
||
$winLink = $null
|
||
|
||
# Windows 7 and non Windows platforms are too much of a liability
|
||
if ($winver -le 6.1) {
|
||
Error(Get-Translation("This feature is not available on this platform."))
|
||
exit 403
|
||
}
|
||
|
||
$i = 0
|
||
$Selected = ""
|
||
if ($Win -eq "List") {
|
||
Write-Host "Please select a Windows Version (-Win):"
|
||
}
|
||
foreach($version in $WindowsVersions) {
|
||
if ($Win -eq "List") {
|
||
Write-Host " -" $version[0][0]
|
||
} elseif ($version[0][0] -match $Win) {
|
||
$Selected += $version[0][0]
|
||
$winVersionId = $i
|
||
break;
|
||
}
|
||
$i++
|
||
}
|
||
if ($winVersionId -eq $null) {
|
||
if ($Win -ne "List") {
|
||
Write-Host "Invalid Windows version provided."
|
||
Write-Host "Use '-Win List' for a list of available Windows versions."
|
||
}
|
||
exit 1
|
||
}
|
||
|
||
# Windows Version selection
|
||
$releases = Get-Windows-Releases $winVersionId
|
||
if ($Rel -eq "List") {
|
||
Write-Host "Please select a Windows Release (-Rel) for ${Selected} (or use 'Latest' for most recent):"
|
||
}
|
||
foreach ($release in $releases) {
|
||
if ($Rel -eq "List") {
|
||
Write-Host " -" $release.Release
|
||
} elseif (!$Rel -or $release.Release.StartsWith($Rel) -or $Rel -eq "Latest") {
|
||
if (!$Rel -and $Verbosity -ge 1) {
|
||
Write-Host "No release specified (-Rel). Defaulting to '$($release.Release)'."
|
||
}
|
||
$Selected += " " + $release.Release
|
||
$winReleaseId = $release.Index
|
||
break;
|
||
}
|
||
}
|
||
if ($winReleaseId -eq $null) {
|
||
if ($Rel -ne "List") {
|
||
Write-Host "Invalid Windows release provided."
|
||
Write-Host "Use '-Rel List' for a list of available $Selected releases or '-Rel Latest' for latest."
|
||
}
|
||
exit 1
|
||
}
|
||
|
||
# Windows Release selection => Populate Product Edition
|
||
$editions = Get-Windows-Editions $winVersionId $winReleaseId
|
||
if ($Ed -eq "List") {
|
||
Write-Host "Please select a Windows Edition (-Ed) for ${Selected}:"
|
||
}
|
||
foreach($edition in $editions) {
|
||
if ($Ed -eq "List") {
|
||
Write-Host " -" $edition.Edition
|
||
} elseif (!$Ed -or $edition.Edition -match $Ed) {
|
||
if (!$Ed -and $Verbosity -ge 1) {
|
||
Write-Host "No edition specified (-Ed). Defaulting to '$($edition.Edition)'."
|
||
}
|
||
$Selected += "," + $edition.Edition -replace "Windows [0-9\.]*"
|
||
$winEditionId = $edition.Id
|
||
break;
|
||
}
|
||
}
|
||
if ($winEditionId -eq $null) {
|
||
if ($Ed -ne "List") {
|
||
Write-Host "Invalid Windows edition provided."
|
||
Write-Host "Use '-Ed List' for a list of available editions or remove the -Ed parameter to use default."
|
||
}
|
||
exit 1
|
||
}
|
||
|
||
# Product Edition selection => Request and populate Languages
|
||
$languages = Get-Windows-Languages $winVersionId $winEditionId
|
||
if (!$languages) {
|
||
exit 3
|
||
}
|
||
if ($Lang -eq "List") {
|
||
Write-Host "Please select a Language (-Lang) for ${Selected}:"
|
||
} elseif ($Lang) {
|
||
# Escape parentheses so that they aren't interpreted as regex
|
||
$Lang = $Lang.replace('(', '\(')
|
||
$Lang = $Lang.replace(')', '\)')
|
||
}
|
||
$i = 0
|
||
$winLanguage = $null
|
||
foreach ($language in $languages) {
|
||
if ($Lang -eq "List") {
|
||
Write-Host " -" $language.Name
|
||
} elseif ((!$Lang -and $script:SelectedIndex -eq $i) -or ($Lang -and $language.Name -match $Lang)) {
|
||
if (!$Lang -and $Verbosity -ge 1) {
|
||
Write-Host "No language specified (-Lang). Defaulting to '$($language.Name)'."
|
||
}
|
||
$Selected += ", " + $language.Name
|
||
$winLanguage = $language
|
||
break;
|
||
}
|
||
$i++
|
||
}
|
||
if ($winLanguage -eq $null) {
|
||
if ($Lang -ne "List") {
|
||
Write-Host "Invalid Windows language provided."
|
||
Write-Host "Use '-Lang List' for a list of available languages or remove the option to use system default."
|
||
}
|
||
exit 1
|
||
}
|
||
|
||
# Language selection => Request and populate Arch download links
|
||
$links = Get-Windows-Download-Links $winVersionId $winReleaseId $winEditionId $winLanguage
|
||
if (!$links) {
|
||
exit 3
|
||
}
|
||
if ($Arch -eq "List") {
|
||
Write-Host "Please select an Architecture (-Arch) for ${Selected}:"
|
||
}
|
||
$i = 0
|
||
foreach ($link in $links) {
|
||
if ($Arch -eq "List") {
|
||
Write-Host " -" $link.Type
|
||
} elseif ((!$Arch -and $script:SelectedIndex -eq $i) -or ($Arch -and $link.Type -match $Arch)) {
|
||
if (!$Arch -and $Verbosity -ge 1) {
|
||
Write-Host "No architecture specified (-Arch). Defaulting to '$($link.Type)'."
|
||
}
|
||
$Selected += ", [" + $link.Type + "]"
|
||
$winLink = $link
|
||
break;
|
||
}
|
||
$i++
|
||
}
|
||
if ($winLink -eq $null) {
|
||
if ($Arch -ne "List") {
|
||
Write-Host "Invalid Windows architecture provided."
|
||
Write-Host "Use '-Arch List' for a list of available architectures or remove the option to use system default."
|
||
}
|
||
exit 1
|
||
}
|
||
|
||
# Arch selection => Return selected download link
|
||
if ($GetUrl) {
|
||
return $winLink.Url
|
||
$ExitCode = 0
|
||
} else {
|
||
Write-Host "Selected: $Selected"
|
||
$ExitCode = Process-Download-Link $winLink.Url
|
||
}
|
||
|
||
# Clean up & exit
|
||
exit $ExitCode
|
||
}
|
||
|
||
# Form creation
|
||
$XMLForm = [Windows.Markup.XamlReader]::Load((New-Object System.Xml.XmlNodeReader $XAML))
|
||
$XAML.SelectNodes("//*[@Name]") | ForEach-Object { Set-Variable -Name ($_.Name) -Value $XMLForm.FindName($_.Name) -Scope Script }
|
||
$XMLForm.Title = $AppTitle
|
||
if ($Icon) {
|
||
$XMLForm.Icon = $Icon
|
||
} else {
|
||
$XMLForm.Icon = [WinAPI.Utils]::ExtractIcon("imageres.dll", -5205, $true) | ConvertTo-ImageSource
|
||
}
|
||
if ($Locale.StartsWith("ar") -or $Locale.StartsWith("fa") -or $Locale.StartsWith("he")) {
|
||
$XMLForm.FlowDirection = "RightToLeft"
|
||
}
|
||
$WindowsVersionTitle.Text = Get-Translation("Version")
|
||
$Continue.Content = Get-Translation("Continue")
|
||
$Back.Content = Get-Translation("Close")
|
||
|
||
# Windows 7 and non Windows platforms are too much of a liability
|
||
if ($winver -le 6.1) {
|
||
Error(Get-Translation("This feature is not available on this platform."))
|
||
exit 403
|
||
}
|
||
|
||
# Populate the Windows versions
|
||
$i = 0
|
||
$versions = @()
|
||
foreach($version in $WindowsVersions) {
|
||
$versions += @(New-Object PsObject -Property @{ Version = $version[0][0]; PageType = $version[0][1]; Index = $i })
|
||
$i++
|
||
}
|
||
$WindowsVersion.ItemsSource = $versions
|
||
$WindowsVersion.DisplayMemberPath = "Version"
|
||
|
||
# Button Action
|
||
$Continue.add_click({
|
||
$script:Stage++
|
||
$XMLGrid.Children[2 * $Stage + 1].IsEnabled = $false
|
||
$Continue.IsEnabled = $false
|
||
$Back.IsEnabled = $false
|
||
Refresh-Control($Continue)
|
||
Refresh-Control($Back)
|
||
|
||
switch ($Stage) {
|
||
|
||
1 { # Windows Version selection
|
||
$XMLForm.Title = Get-Translation($English[12])
|
||
Refresh-Control($XMLForm)
|
||
if ($WindowsVersion.SelectedValue.Version.StartsWith("Windows")) {
|
||
Check-Locale
|
||
}
|
||
$releases = Get-Windows-Releases $WindowsVersion.SelectedValue.Index
|
||
$script:WindowsRelease = Add-Entry $Stage "Release" $releases
|
||
$Back.Content = Get-Translation($English[8])
|
||
$XMLForm.Title = $AppTitle
|
||
}
|
||
|
||
2 { # Windows Release selection => Populate Product Edition
|
||
$editions = Get-Windows-Editions $WindowsVersion.SelectedValue.Index $WindowsRelease.SelectedValue.Index
|
||
$script:ProductEdition = Add-Entry $Stage "Edition" $editions
|
||
}
|
||
|
||
3 { # Product Edition selection => Request and populate languages
|
||
$XMLForm.Title = Get-Translation($English[12])
|
||
Refresh-Control($XMLForm)
|
||
$languages = Get-Windows-Languages $WindowsVersion.SelectedValue.Index $ProductEdition.SelectedValue.Id
|
||
if ($languages.Length -eq 0) {
|
||
break
|
||
}
|
||
$script:Language = Add-Entry $Stage "Language" $languages "DisplayName"
|
||
$Language.SelectedIndex = $script:SelectedIndex
|
||
$XMLForm.Title = $AppTitle
|
||
}
|
||
|
||
4 { # Language selection => Request and populate Arch download links
|
||
$XMLForm.Title = Get-Translation($English[12])
|
||
Refresh-Control($XMLForm)
|
||
$links = Get-Windows-Download-Links $WindowsVersion.SelectedValue.Index $WindowsRelease.SelectedValue.Index $ProductEdition.SelectedValue.Id $Language.SelectedValue
|
||
if ($links.Length -eq 0) {
|
||
break
|
||
}
|
||
$script:Architecture = Add-Entry $Stage "Architecture" $links "Type"
|
||
if ($PipeName) {
|
||
$XMLForm.Height += $dh / 2;
|
||
$Margin = $Continue.Margin
|
||
$top = $Margin.Top
|
||
$Margin.Top += $dh /2
|
||
$Continue.Margin = $Margin
|
||
$Margin = $Back.Margin
|
||
$Margin.Top += $dh / 2
|
||
$Back.Margin = $Margin
|
||
$Margin = $Check.Margin
|
||
$Margin.Top = $top - 2
|
||
$Check.Margin = $Margin
|
||
$Check.Content = Get-Translation($English[13])
|
||
$Check.Visibility = "Visible"
|
||
}
|
||
$Architecture.SelectedIndex = $script:SelectedIndex
|
||
$Continue.Content = Get-Translation("Download")
|
||
$XMLForm.Title = $AppTitle
|
||
}
|
||
|
||
5 { # Arch selection => Return selected download link
|
||
$script:ExitCode = Process-Download-Link $Architecture.SelectedValue.Url
|
||
$XMLForm.Close()
|
||
}
|
||
}
|
||
$Continue.IsEnabled = $true
|
||
if ($Stage -ge 0) {
|
||
$Back.IsEnabled = $true
|
||
}
|
||
})
|
||
|
||
$Back.add_click({
|
||
if ($Stage -eq 0) {
|
||
$XMLForm.Close()
|
||
} else {
|
||
$XMLGrid.Children.RemoveAt(2 * $Stage + 3)
|
||
$XMLGrid.Children.RemoveAt(2 * $Stage + 2)
|
||
$XMLGrid.Children[2 * $Stage + 1].IsEnabled = $true
|
||
$dh2 = $dh
|
||
if ($Stage -eq 4 -and $PipeName) {
|
||
$Check.Visibility = "Collapsed"
|
||
$dh2 += $dh / 2
|
||
}
|
||
$XMLForm.Height -= $dh2;
|
||
$Margin = $Continue.Margin
|
||
$Margin.Top -= $dh2
|
||
$Continue.Margin = $Margin
|
||
$Margin = $Back.Margin
|
||
$Margin.Top -= $dh2
|
||
$Back.Margin = $Margin
|
||
$script:Stage = $Stage - 1
|
||
$XMLForm.Title = $AppTitle
|
||
if ($Stage -eq 0) {
|
||
$Back.Content = Get-Translation("Close")
|
||
} else {
|
||
$Continue.Content = Get-Translation("Continue")
|
||
Refresh-Control($Continue)
|
||
}
|
||
}
|
||
})
|
||
|
||
# Display the dialog
|
||
$XMLForm.Add_Loaded({$XMLForm.Activate()})
|
||
$XMLForm.ShowDialog() | Out-Null
|
||
|
||
# Clean up & exit
|
||
exit $ExitCode
|
||
|
||
# SIG # Begin signature block
|
||
# MIItPAYJKoZIhvcNAQcCoIItLTCCLSkCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
||
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDFXTWq2lpU/6fR
|
||
# Ct1W7yWDg6b1THz8JSMDTQ5AW7weJ6CCEkAwggVvMIIEV6ADAgECAhBI/JO0YFWU
|
||
# jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI
|
||
# DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM
|
||
# EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy
|
||
# dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG
|
||
# EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv
|
||
# IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA
|
||
# A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s
|
||
# hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD
|
||
# J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7
|
||
# P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme
|
||
# me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz
|
||
# T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q
|
||
# RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz
|
||
# mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc
|
||
# QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T
|
||
# OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/
|
||
# AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID
|
||
# AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD
|
||
# VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV
|
||
# HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE
|
||
# VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v
|
||
# ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE
|
||
# KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI
|
||
# hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF
|
||
# OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC
|
||
# J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ
|
||
# pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl
|
||
# d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH
|
||
# +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggYcMIIEBKADAgECAhAz1wio
|
||
# kUBTGeKlu9M5ua1uMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYD
|
||
# VQQKEw9TZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENv
|
||
# ZGUgU2lnbmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5
|
||
# NTlaMFcxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxLjAs
|
||
# BgNVBAMTJVNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBFViBSMzYwggGi
|
||
# MA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC70f4et0JbePWQp64sg/GNIdMw
|
||
# hoV739PN2RZLrIXFuwHP4owoEXIEdiyBxasSekBKxRDogRQ5G19PB/YwMDB/NSXl
|
||
# wHM9QAmU6Kj46zkLVdW2DIseJ/jePiLBv+9l7nPuZd0o3bsffZsyf7eZVReqskmo
|
||
# PBBqOsMhspmoQ9c7gqgZYbU+alpduLyeE9AKnvVbj2k4aOqlH1vKI+4L7bzQHkND
|
||
# brBTjMJzKkQxbr6PuMYC9ruCBBV5DFIg6JgncWHvL+T4AvszWbX0w1Xn3/YIIq62
|
||
# 0QlZ7AGfc4m3Q0/V8tm9VlkJ3bcX9sR0gLqHRqwG29sEDdVOuu6MCTQZlRvmcBME
|
||
# Jd+PuNeEM4xspgzraLqVT3xE6NRpjSV5wyHxNXf4T7YSVZXQVugYAtXueciGoWnx
|
||
# G06UE2oHYvDQa5mll1CeHDOhHu5hiwVoHI717iaQg9b+cYWnmvINFD42tRKtd3V6
|
||
# zOdGNmqQU8vGlHHeBzoh+dYyZ+CcblSGoGSgg8sCAwEAAaOCAWMwggFfMB8GA1Ud
|
||
# IwQYMBaAFDLrkpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBSBMpJBKyjNRsjE
|
||
# osYqORLsSKk/FDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAT
|
||
# BgNVHSUEDDAKBggrBgEFBQcDAzAaBgNVHSAEEzARMAYGBFUdIAAwBwYFZ4EMAQMw
|
||
# SwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdv
|
||
# UHVibGljQ29kZVNpZ25pbmdSb290UjQ2LmNybDB7BggrBgEFBQcBAQRvMG0wRgYI
|
||
# KwYBBQUHMAKGOmh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0Nv
|
||
# ZGVTaWduaW5nUm9vdFI0Ni5wN2MwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNl
|
||
# Y3RpZ28uY29tMA0GCSqGSIb3DQEBDAUAA4ICAQBfNqz7+fZyWhS38Asd3tj9lwHS
|
||
# /QHumS2G6Pa38Dn/1oFKWqdCSgotFZ3mlP3FaUqy10vxFhJM9r6QZmWLLXTUqwj3
|
||
# ahEDCHd8vmnhsNufJIkD1t5cpOCy1rTP4zjVuW3MJ9bOZBHoEHJ20/ng6SyJ6UnT
|
||
# s5eWBgrh9grIQZqRXYHYNneYyoBBl6j4kT9jn6rNVFRLgOr1F2bTlHH9nv1HMePp
|
||
# GoYd074g0j+xUl+yk72MlQmYco+VAfSYQ6VK+xQmqp02v3Kw/Ny9hA3s7TSoXpUr
|
||
# OBZjBXXZ9jEuFWvilLIq0nQ1tZiao/74Ky+2F0snbFrmuXZe2obdq2TWauqDGIgb
|
||
# MYL1iLOUJcAhLwhpAuNMu0wqETDrgXkG4UGVKtQg9guT5Hx2DJ0dJmtfhAH2KpnN
|
||
# r97H8OQYok6bLyoMZqaSdSa+2UA1E2+upjcaeuitHFFjBypWBmztfhj24+xkc6Zt
|
||
# CDaLrw+ZrnVrFyvCTWrDUUZBVumPwo3/E3Gb2u2e05+r5UWmEsUUWlJBl6MGAAjF
|
||
# 5hzqJ4I8O9vmRsTvLQA1E802fZ3lqicIBczOwDYOSxlP0GOabb/FKVMxItt1UHeG
|
||
# 0PL4au5rBhs+hSMrl8h+eplBDN1Yfw6owxI9OjWb4J0sjBeBVESoeh2YnZZ/WVim
|
||
# VGX/UUIL+Efrz/jlvzCCBqkwggURoAMCAQICEDfFCjwdoANxxw3HxiaQL+UwDQYJ
|
||
# KoZIhvcNAQELBQAwVzELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGlt
|
||
# aXRlZDEuMCwGA1UEAxMlU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIEVW
|
||
# IFIzNjAeFw0yNDA4MjgwMDAwMDBaFw0yNzA4MjgyMzU5NTlaMIGTMQ8wDQYDVQQF
|
||
# EwY0MDc5NTAxEzARBgsrBgEEAYI3PAIBAxMCSUUxGDAWBgNVBA8TD0J1c2luZXNz
|
||
# IEVudGl0eTELMAkGA1UEBhMCSUUxEDAOBgNVBAgMB0RvbmVnYWwxGDAWBgNVBAoM
|
||
# D0FrZW8gQ29uc3VsdGluZzEYMBYGA1UEAwwPQWtlbyBDb25zdWx0aW5nMIICIjAN
|
||
# BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqpN7vevPy6Ir46imPS9uMM86vroQ
|
||
# e9gcAMNYKW+RXzSJfi79vZOzABoVPZ72rSwODApd89w95Z5FqGjwhaIu04lCHt6H
|
||
# mOL+TR9xdo2WWFWXGh7yC5jmvMofk54A6h7klEd2u3f4aTjy9sVr1uUmjA9KA1o8
|
||
# HBgid5+HL57I9XprTRXGtTHAzHJyX1FEEGGKv9CtxEUaIr1/mIFpsNLZN2NfOoIu
|
||
# PPpxMypcXISDecJApvKxhqBte5SMhKa5zlI5omyizesQJZoRGjVfe83Ntb7kykFS
|
||
# Du1hmJMbtV0mM8yrhoUy+QAKp2ZhctkbPmWDNVLDK51GnfOgfmgaMQvm9RZQeh1N
|
||
# OT+fbUxHakG14kdARprNWJbBsJX5kLvzzTL4xbz+hPRT4jUkRZgQ9eDz1+a5Qa4Q
|
||
# FJtosRbwaJNuX9YQyrda1Jy2yJEVXanaRS8R0WM6wcYL47KMmxhz37HGr5zek9I+
|
||
# rfQ+/Qt+imZ/q1cYEuvx9owSVbpZAV1/g5z3AwH4ue+msMlY3bxwBfeEPHFnNdxh
|
||
# Dg7jlggohX79KL5e85FQs3iQpwXvGDlUjvS6KG+Rv3DokvZS9WSWB4REHmC/Cywu
|
||
# LQh3VF1Ezko3HMOG+nQptBNJ2Vk9JRq8mh317Tzv9dsoVWS6Vv1O2nyGbWZfjkn3
|
||
# ayT+S5SopUo/PcECAwEAAaOCAbIwggGuMB8GA1UdIwQYMBaAFIEykkErKM1GyMSi
|
||
# xio5EuxIqT8UMB0GA1UdDgQWBBRU0FFbeE+nxVuayZAwm7BZrYKDHzAOBgNVHQ8B
|
||
# Af8EBAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzBJBgNV
|
||
# HSAEQjBAMDUGDCsGAQQBsjEBAgEGATAlMCMGCCsGAQUFBwIBFhdodHRwczovL3Nl
|
||
# Y3RpZ28uY29tL0NQUzAHBgVngQwBAzBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8v
|
||
# Y3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBRVZSMzYu
|
||
# Y3JsMHsGCCsGAQUFBwEBBG8wbTBGBggrBgEFBQcwAoY6aHR0cDovL2NydC5zZWN0
|
||
# aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQUVWUjM2LmNydDAjBggr
|
||
# BgEFBQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wJAYDVR0RBB0wG6AZBggr
|
||
# BgEFBQcIA6ANMAsMCUlFLTQwNzk1MDANBgkqhkiG9w0BAQsFAAOCAYEAs2WyIJRC
|
||
# l+lgha7wuLYXCdbZbx4K02SyteLCXXRYuQ/+o7kX2P3BQuqNZXBQ4y+xbuOTqNOY
|
||
# R6VK7QrLvYaiMJky5qZY3lQfdsvuGkZmg1XvY1BPXre6B1/HkatGmnqtFUcBBeW4
|
||
# wtHOglq96eLHXzXCvS+1xO9wvv7GGB53i+7ePq7ROr717p/V1OUntl5y8nzxyhRI
|
||
# ucs6gBX0gbBQljLC16DwZ20NlNhYfi1SF7pSfnWZH/bojOPta3fCmIx7r8tjDu5m
|
||
# 4a6KRpYwLMYE9/ZBEBP7JpfiMt42q+QF6fyS8xauGiOGBOZW4ch7Wh+GBoe3JZUu
|
||
# UPC4wZDC9LeRKz/otodtloaTEnW9YE9gPmfRttMWaNsQTg6y5sc74qLoVY0RSqcW
|
||
# B2KScXAjuVHVkJJcOoPSuLoTjOhK3Ug4XbQmRypdteoizdTSnONGmW84RJyXquzi
|
||
# rIjw9CnLTggrZiYi9EZTo7URWNaARqLbSFpu0VMkdOBpWdXq5F6x6jslMYIaUjCC
|
||
# Gk4CAQEwazBXMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVk
|
||
# MS4wLAYDVQQDEyVTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgRVYgUjM2
|
||
# AhA3xQo8HaADcccNx8YmkC/lMA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIB
|
||
# DDECMAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
|
||
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIJOGS5HWMc2rDXvPKvX2nFz6
|
||
# Kgz3N3nMaspPXtcMKTojMA0GCSqGSIb3DQEBAQUABIICAJ74B4pGm7vaEYuhs3NT
|
||
# DVwFMiBWnu7mul6K6Van7Itz0bECfra3r9wpUvcsAoOKEqZ9VX1AmJ/zoIQhQgq3
|
||
# gPMhbPLeJuIwnjExCLHSwaJ9tXbETIMX50vMBOt6aLsVgnzT2VJTC5UTzvwcW/Lm
|
||
# Gaucxnm1bFMNmTMdeOZFLPZBB+WPaJ3dT2lgNU/usB0DyF+i5ilFPFUzesrMDzcV
|
||
# x+ijkEOz1jxNxXGbTotPvXjMPkUnBIaYsTmeKhrzn085p8O5l0eUAqjEnYPvAq/n
|
||
# WSvpohmXZa3V7pWRum5XPZ2fe4cs6GjMYmdmD+8ovW4G6KVbNkf75JFKJZ82Y9lq
|
||
# qn4VO0r5vV4ffD0erFF/KGTavhvz/VlG2par1O/jfa6ue9yPaLLpWiynThz9/lGI
|
||
# zbvmAGJuIxCjRcA/Dp/QRkl1a8+VvXtaopd3hQTwgHhlXhnOLKzDKuLoJd9CsDPL
|
||
# 0krYSqps1PD7sAdpr4rx4Gkv+iT9vLJYD+N9KSpfW8BmrHKaKp2BnK79ERxo4fQm
|
||
# bagOlVCX/FBmSYU+HW52fb2b9fwS7xVupOoruHiIksjTy7YWNgck3CW4WVKxp35y
|
||
# i6SEO4u+1ivx9uhIYQnDJ4mEcezLU1QBFoc5UG6IW1QgbnYVbBwhlrp/poF90NHp
|
||
# TC2UDXb1m+JfMPdjaOBZdothoYIXOjCCFzYGCisGAQQBgjcDAwExghcmMIIXIgYJ
|
||
# KoZIhvcNAQcCoIIXEzCCFw8CAQMxDzANBglghkgBZQMEAgEFADB4BgsqhkiG9w0B
|
||
# CRABBKBpBGcwZQIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIBw/qIiW
|
||
# ZirjZAJAqvzJLoq2PiAMMR2U/b8N3B7swhynAhEArbB7KWdDox91SH7wp5yr5hgP
|
||
# MjAyNDExMTgwMTQzNDFaoIITAzCCBrwwggSkoAMCAQICEAuuZrxaun+Vh8b56QTj
|
||
# MwQwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD
|
||
# ZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYg
|
||
# U0hBMjU2IFRpbWVTdGFtcGluZyBDQTAeFw0yNDA5MjYwMDAwMDBaFw0zNTExMjUy
|
||
# MzU5NTlaMEIxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhEaWdpQ2VydDEgMB4GA1UE
|
||
# AxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjQwggIiMA0GCSqGSIb3DQEBAQUAA4IC
|
||
# DwAwggIKAoICAQC+anOf9pUhq5Ywultt5lmjtej9kR8YxIg7apnjpcH9CjAgQxK+
|
||
# CMR0Rne/i+utMeV5bUlYYSuuM4vQngvQepVHVzNLO9RDnEXvPghCaft0djvKKO+h
|
||
# Du6ObS7rJcXa/UKvNminKQPTv/1+kBPgHGlP28mgmoCw/xi6FG9+Un1h4eN6zh92
|
||
# 6SxMe6We2r1Z6VFZj75MU/HNmtsgtFjKfITLutLWUdAoWle+jYZ49+wxGE1/UXjW
|
||
# fISDmHuI5e/6+NfQrxGFSKx+rDdNMsePW6FLrphfYtk/FLihp/feun0eV+pIF496
|
||
# OVh4R1TvjQYpAztJpVIfdNsEvxHofBf1BWkadc+Up0Th8EifkEEWdX4rA/FE1Q0r
|
||
# qViTbLVZIqi6viEk3RIySho1XyHLIAOJfXG5PEppc3XYeBH7xa6VTZ3rOHNeiYnY
|
||
# +V4j1XbJ+Z9dI8ZhqcaDHOoj5KGg4YuiYx3eYm33aebsyF6eD9MF5IDbPgjvwmnA
|
||
# alNEeJPvIeoGJXaeBQjIK13SlnzODdLtuThALhGtyconcVuPI8AaiCaiJnfdzUcb
|
||
# 3dWnqUnjXkRFwLtsVAxFvGqsxUA2Jq/WTjbnNjIUzIs3ITVC6VBKAOlb2u29Vwgf
|
||
# ta8b2ypi6n2PzP0nVepsFk8nlcuWfyZLzBaZ0MucEdeBiXL+nUOGhCjl+QIDAQAB
|
||
# o4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/
|
||
# BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcB
|
||
# MB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBSfVywD
|
||
# dw4oFZBmpWNe7k+SH3agWzBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5k
|
||
# aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0
|
||
# YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0
|
||
# cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0
|
||
# cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGlt
|
||
# ZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQA9rR4fdplb4ziEEkfZ
|
||
# Q5H2EdubTggd0ShPz9Pce4FLJl6reNKLkZd5Y/vEIqFWKt4oKcKz7wZmXa5VgW9B
|
||
# 76k9NJxUl4JlKwyjUkKhk3aYx7D8vi2mpU1tKlY71AYXB8wTLrQeh83pXnWwwsxc
|
||
# 1Mt+FWqz57yFq6laICtKjPICYYf/qgxACHTvypGHrC8k1TqCeHk6u4I/VBQC9VK7
|
||
# iSpU5wlWjNlHlFFv/M93748YTeoXU/fFa9hWJQkuzG2+B7+bMDvmgF8VlJt1qQcl
|
||
# 7YFUMYgZU1WM6nyw23vT6QSgwX5Pq2m0xQ2V6FJHu8z4LXe/371k5QrN9FQBhLLI
|
||
# SZi2yemW0P8ZZfx4zvSWzVXpAb9k4Hpvpi6bUe8iK6WonUSV6yPlMwerwJZP/Gtb
|
||
# u3CKldMnn+LmmRTkTXpFIEB06nXZrDwhCGED+8RsWQSIXZpuG4WLFQOhtloDRWGo
|
||
# Cwwc6ZpPddOFkM2LlTbMcqFSzm4cd0boGhBq7vkqI1uHRz6Fq1IX7TaRQuR+0BGO
|
||
# zISkcqwXu7nMpFu3mgrlgbAW+BzikRVQ3K2YHcGkiKjA4gi4OA/kz1YCsdhIBHXq
|
||
# BzR0/Zd2QwQ/l4Gxftt/8wY3grcc/nS//TVkej9nmUYu83BDtccHHXKibMs/yXHh
|
||
# DXNkoPIdynhVAku7aRZOwqw6pDCCBq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYq
|
||
# XlswDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD
|
||
# ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGln
|
||
# aUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIz
|
||
# NTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTsw
|
||
# OQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVT
|
||
# dGFtcGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJ
|
||
# s8E9cklRVcclA8TykTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJ
|
||
# C3+dH54PMx9QEwsmc5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+
|
||
# QtxnjupRPfDWVtTnKC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3
|
||
# eZ9drMvohGS0UvJ2R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbF
|
||
# Hc02DVzV5huowWR0QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71
|
||
# h6aPTnYVVSZwmCZ/oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseS
|
||
# v6De4z6ic/rnH1pslPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj
|
||
# 1QPgv/CiPMpC3BhIfxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2L
|
||
# INIsVzV5K6jzRWC8I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJ
|
||
# jAw7W4oiqMEmCPkUEBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAO
|
||
# hFTuzuldyF4wEr1GnrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMB
|
||
# Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNV
|
||
# HSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYD
|
||
# VR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhho
|
||
# dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNl
|
||
# cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1Ud
|
||
# HwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRy
|
||
# dXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwH
|
||
# ATANBgkqhkiG9w0BAQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88w
|
||
# U86/GPvHUF3iSyn7cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZv
|
||
# xFBMYh0MCIKoFr2pVs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+R
|
||
# Zp4snuCKrOX9jLxkJodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM
|
||
# 8HKjI/rAJ4JErpknG6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/E
|
||
# x8HBanHZxhOACcS2n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd
|
||
# /yVjmScsPT9rp/Fmw0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFP
|
||
# vT87eK1MrfvElXvtCl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHics
|
||
# JttvFXseGYs2uJPU5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2V
|
||
# Qbc61RWYMbRiCQ8KvYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ
|
||
# 8GV2QqYphwlHK+Z/GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr
|
||
# 9u3WfPwwggWNMIIEdaADAgECAhAOmxiO+dAt5+/bUOIIQBhaMA0GCSqGSIb3DQEB
|
||
# DAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNV
|
||
# BAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQg
|
||
# SUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBaFw0zMTExMDkyMzU5NTlaMGIxCzAJ
|
||
# BgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
|
||
# aWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDCC
|
||
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8MCIwaTPs
|
||
# wqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauyefLKEdLk
|
||
# X9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34LzB4TmdDtt
|
||
# ceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+xembud8hI
|
||
# qGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhAkHnDeMe2
|
||
# scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1LyuGwN1XXhm
|
||
# 2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2PVldQnaH
|
||
# iZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37AlLTSYW3r
|
||
# M9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD76GSmM9GJ
|
||
# B+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ybzTQRES
|
||
# W+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXAj6Kxfgom
|
||
# mfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIBNjAPBgNVHRMBAf8EBTADAQH/MB0G
|
||
# A1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF66Kv9JLL
|
||
# gjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMCAYYweQYIKwYBBQUHAQEEbTBrMCQG
|
||
# CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKG
|
||
# N2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJv
|
||
# b3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQu
|
||
# Y29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDARBgNVHSAECjAIMAYGBFUd
|
||
# IAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0NcVec4X6CjdBs9thbX979XB72arKGH
|
||
# LOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnovLbc47/T/gLn4offyct4kvFIDyE7Q
|
||
# Kt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65ZyoUi0mcudT6cGAxN3J0TU53/oWajw
|
||
# vy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFWjuyk1T3osdz9HNj0d1pcVIxv76FQ
|
||
# Pfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPFmCLBsln1VWvPJ6tsds5vIy30fnFq
|
||
# I2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9ztwGpn1eqXijiuZQxggN2MIIDcgIB
|
||
# ATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkG
|
||
# A1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3Rh
|
||
# bXBpbmcgQ0ECEAuuZrxaun+Vh8b56QTjMwQwDQYJYIZIAWUDBAIBBQCggdEwGgYJ
|
||
# KoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNDExMTgw
|
||
# MTQzNDFaMCsGCyqGSIb3DQEJEAIMMRwwGjAYMBYEFNvThe5i29I+e+T2cUhQhyTV
|
||
# hltFMC8GCSqGSIb3DQEJBDEiBCCLPWAm+aNyc4DrqvDwqzC7ow3BipFMugVd26EO
|
||
# cUUgxTA3BgsqhkiG9w0BCRACLzEoMCYwJDAiBCB2dp+o8mMvH0MLOiMwrtZWdf7X
|
||
# c9sF1mW5BZOYQ4+a2zANBgkqhkiG9w0BAQEFAASCAgA1D9F+ChwLLlPfrnjVN7y8
|
||
# Raa08Q1yJoUiIPZw/m4rknXNCjyL768gux2rys7Y0ofhaTL8qB2U5605DNmkuDAw
|
||
# NwDXME2bka4xBxDJrI43XFVtu3SpKRbNcv5ujZs0jF4gA3GQykM9UahyusmaxwtQ
|
||
# DILavBxCuVye9HX86Z1Bdac1wCWY6hvbtoT4ffm+/Uondgh8VzEWd36ImGOpAXQM
|
||
# +UOR8t4JG5777yIBTv51W3qnEx7e4bazezEXIgC7DdXFSq18ypjJuCkLMrb2bWgp
|
||
# /CxGT2ff4itbsv8Z++oJI2oOewhlLiA5tVMkbB0lVGQbkeEP4nqUKwAvOt7g1i7f
|
||
# uSxGdoNbaesSNefScqii1OTXHsLSjNciRQQJZMxJI44F15X7LOVdaaIbvgoLfIWy
|
||
# T9s+OgUxmAvDdZKpRcHO//tW6JqFCoi+gdW04mUSvME+MRx6RFZe1cjZNPpJEnwh
|
||
# kmKGhndTmaBjg1nJH0okrfmR87jjIhulemrdJsUZtcdzCBxT1gW5AaHFOMUuHBkR
|
||
# P9h0VG3f12fejgEotaDyTmPYBazFlwSrXtrr1uFmS0SDw681z5xGjK92279MlUpo
|
||
# 8RBOupy5LSPC59Oi1j7SSeW+xyBfS+0aiyKEAYfk1qO0f3Eql9kTQBZjaizDdKmq
|
||
# ubbhLFZ/dE5qax8nkz2Rxw==
|
||
# SIG # End signature block
|