Windows365LanguagesInstaller.ps1


<#PSScriptInfo
 
.VERSION 1.0.0.0
 
.GUID afa48b3c-60c5-42a6-9ae7-a8b8b59a3000
 
.AUTHOR Microsoft Corporation
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
#>
 







<#
 
.DESCRIPTION
This script installs additional 38 languages based on user selection.
 
#>
 

Param()


##########################################################################
## Add additional languages to Windows 365 custom images for IT Pro##
##########################################################################

$downloadPath = "$env:SystemDrive\Users\$env:UserName\Downloads\"

$languages = @("ar-SA", "bg-BG", "cs-CZ", "da-DK","de-DE", "el-GR", "en-GB","en-US","es-ES",
"es-MX","et-EE","fi-FI","fr-CA","fr-FR","he-IL","hr-HR","hu-HU","it-IT","ja-JP","ko-KR","lt-LT",
"lv-LV","nb-NO","nl-NL","pl-PL","pt-BR","pt-PT","ro-RO","ru-RU","sk-SK","sl-SI","sr-Cyrl-CS",
"sv-SE","th-TH","tr-TR","uk-UA","zh-CN","zh-TW")

$languagesDescription = @("Arabic (Saudi Arabia)","Bulgarian (Bulgaria)","Czech (Czech Republic)","Danish (Denmark)","German (Germany)","Greek (Greece)","English (United Kingdom)","English (United States)","Spanish (Spain)",
"Spanish (Mexico)","Estonian (Estonia)","Finnish (Finland)","French (Canada)","French (France)","Hebrew (Israel)","Croatian (Croatia)","Hungarian (Hungary)","Italian (Italy)","Japanese (Japan)","Korean (Korea)","Lithuanian (Lithuania)",
"Latvian (Latvia)","Norwegian (Bokmål) (Norway)","Dutch (Netherlands)","Polish (Poland)","Portuguese (Brazil)","Portuguese (Portugal)","Romanian (Romania)","Russian (Russia)","Slovak (Slovakia)","Slovenian (Slovenia)","Serbian (Latin, Serbia)",
"Swedish (Sweden)","Thai (Thailand)","Turkish (Turkey)","Ukrainian (Ukraine)","Chinese (Mainland)","Chinese (Taiwan)")

function ListSupportedLanguages(){
    foreach($num in 1..$languages.Count){
        Write-Host "`n[$num] $($languagesDescription[$num-1])"
    }
}

$1903Files = @{
    'LanguagePack' = "https://software-download.microsoft.com/download/pr/18362.1.190318-1202.19h1_release_CLIENTLANGPACKDVD_OEM_MULTI.iso"
    'FOD'          = "https://software-download.microsoft.com/download/pr/18362.1.190318-1202.19h1_release_amd64fre_FOD-PACKAGES_OEM_PT1_amd64fre_MULTI.iso"
    'InboxApps'    = "https://software-download.microsoft.com/download/pr/18362.1.190318-1202.19h1_release_amd64fre_InboxApps.iso"
}

$1909Files = @{
    'LanguagePack' = 'https://software-download.microsoft.com/download/pr/18362.1.190318-1202.19h1_release_CLIENTLANGPACKDVD_OEM_MULTI.iso'
    'FOD'          = 'https://software-download.microsoft.com/download/pr/18362.1.190318-1202.19h1_release_amd64fre_FOD-PACKAGES_OEM_PT1_amd64fre_MULTI.iso'
    'InboxApps'    = 'https://software-download.microsoft.com/download/pr/18362.1.190318-1202.19h1_release_amd64fre_InboxApps.iso'
}

$2004Files = @{
    'LanguagePack' = 'https://software-download.microsoft.com/download/pr/19041.1.191206-1406.vb_release_CLIENTLANGPACKDVD_OEM_MULTI.iso'
    'FOD'          = 'https://software-download.microsoft.com/download/pr/19041.1.191206-1406.vb_release_amd64fre_FOD-PACKAGES_OEM_PT1_amd64fre_MULTI.iso'
    'InboxApps'    = 'https://software-download.microsoft.com/download/pr/19041.1.191206-1406.vb_release_amd64fre_InboxApps.iso'
}

$20H2Files = @{
    'LanguagePack' = 'https://software-download.microsoft.com/download/pr/19041.1.191206-1406.vb_release_CLIENTLANGPACKDVD_OEM_MULTI.iso'
    'FOD'          = 'https://software-download.microsoft.com/download/pr/19041.1.191206-1406.vb_release_amd64fre_FOD-PACKAGES_OEM_PT1_amd64fre_MULTI.iso'
    'InboxApps'    = 'https://software-download.microsoft.com/download/pr/19041.508.200905-1327.vb_release_svc_prod1_amd64fre_InboxApps.iso'
}

$21H1Files = @{
    'LanguagePack' = 'https://software-download.microsoft.com/download/pr/19041.1.191206-1406.vb_release_CLIENTLANGPACKDVD_OEM_MULTI.iso'
    'FOD'          = 'https://software-download.microsoft.com/download/pr/19041.1.191206-1406.vb_release_amd64fre_FOD-PACKAGES_OEM_PT1_amd64fre_MULTI.iso'
    'InboxApps'    = 'https://software-download.microsoft.com/download/sg/19041.928.210407-2138.vb_release_svc_prod1_amd64fre_InboxApps.iso'
}

$languageFiles = @{
    '1903' = $1903Files
    '1909' = $1909Files
    '2004' = $2004Files
    '20H2' = $20H2Files
    '21H1' = $21H1Files
}

function DownloadFile($fileName, $url, $outFile) {
    Write-Output "Downloading $fileName file..." 
    $ProgressPreference = 'SilentlyContinue'
    Invoke-WebRequest -Uri $url -OutFile $outFile
}

function DownloadLanguageFiles() {
    $files = $languageFiles[$winver]

    $space = 20
    foreach ($fileName in $files.Keys) {
        $fileUrl = $files[$fileName]
        $outFile = $downloadPath + $fileUrl.Split("/")[-1]
        if (Test-Path $outFile) {
            $space -= 5
        }
    }
    
    $CDrive = GWMI Win32_LogicalDisk -Filter "DeviceID='C:'"
    if ([Math]::Round($CDrive.FreeSpace / 1GB) -lt $space) {
        Write-Output "Not enough space. Install additional languages require $space GB free space, please try again after cleaning the disk."
        Break Script
    }

    foreach ($fileName in $files.Keys) {
        $fileUrl = $files[$fileName]
        $outFile = $downloadPath + $fileUrl.Split("/")[-1]

        if (!(Test-Path $outFile)) {
            DownloadFile $fileName $fileUrl $outFile
        }
    }
}

function GetOutputFilePath($fileName) {
    return $downloadPath + $languageFiles[$winver][$fileName].Split("/")[-1]
}

function MountFile($filePath) {
    $result = Mount-DiskImage -ImagePath $filePath -PassThru
    return ($result | Get-Volume).Driveletter
}

function DismountFile($filePath) {
    Dismount-DiskImage -ImagePath $filePath | Out-Null
}

function CleanupLanguageFiles() {
    Remove-Item (GetOutputFilePath 'LanguagePack')
    Remove-Item (GetOutputFilePath 'FOD')
    Remove-Item (GetOutputFilePath 'InboxApps')
}

function InstallLanguagePackage($languageCode, $driveletter) {
    Write-Output "Installing $languageCode language pack"

    $LIPContent = $driveLetter + ":"

    $lowerLanguageCode = $languageCode.ToLower()
    $packagePath = "$LIPContent\LocalExperiencePack\$lowerLanguageCode\LanguageExperiencePack.$languageCode.Neutral.appx"
    $licensePath = "$LIPContent\LocalExperiencePack\$lowerLanguageCode\License.xml"

    Add-AppProvisionedPackage -Online -PackagePath $packagePath -LicensePath $licensePath
    Add-WindowsPackage -Online -PackagePath $LIPContent\x64\langpacks\Microsoft-Windows-Client-Language-Pack_x64_$lowerLanguageCode.cab
}

function AddWindowsPackageIfExists ($filePath) {
    if (Test-Path $filePath) {
        Write-Output "Installing $filePath"
        Add-WindowsPackage -Online -PackagePath $filePath
    }
}

function InstallFOD($languageCode, $driveLetter) {
    Write-Output "Installing $languageCode FOD"

    $LIPContent = $driveLetter + ":"

    if ($languageCode -eq "zh-CN") {
        AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-LanguageFeatures-Fonts-Hans-Package~31bf3856ad364e35~amd64~~.cab
    }

    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-LanguageFeatures-Basic-$languagecode-Package~31bf3856ad364e35~amd64~~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-LanguageFeatures-Handwriting-$languagecode-Package~31bf3856ad364e35~amd64~~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-LanguageFeatures-OCR-$languagecode-Package~31bf3856ad364e35~amd64~~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-LanguageFeatures-Speech-$languagecode-Package~31bf3856ad364e35~amd64~~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-LanguageFeatures-TextToSpeech-$languagecode-Package~31bf3856ad364e35~amd64~~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-NetFx3-OnDemand-Package~31bf3856ad364e35~amd64~$languagecode~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-InternetExplorer-Optional-Package~31bf3856ad364e35~amd64~$languagecode~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-MSPaint-FoD-Package~31bf3856ad364e35~amd64~$languagecode~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-Notepad-FoD-Package~31bf3856ad364e35~amd64~$languagecode~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-PowerShell-ISE-FOD-Package~31bf3856ad364e35~amd64~$languagecode~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-Printing-WFS-FoD-Package~31bf3856ad364e35~amd64~$languagecode~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-StepsRecorder-Package~31bf3856ad364e35~amd64~$languagecode~.cab
    AddWindowsPackageIfExists $LIPContent\Microsoft-Windows-WordPad-FoD-Package~31bf3856ad364e35~amd64~$languagecode~.cab
}

function UpdateLanguageList($languageCode) {
    Write-Output "Adding $languageCode to LanguageList"

    $LanguageList = Get-WinUserLanguageList
    $LanguageList.Add($languageCode)
    Set-WinUserLanguageList $LanguageList -force
}

###################################
## Update inbox apps for language##
###################################
function InstallInboxApps() {
    Write-Output "Installing InboxApps"

    $file = GetOutputFilePath 'InboxApps'
    $driveletter = MountFile $file

    $AppsContent = $driveletter + ":\amd64fre"
    foreach ($App in (Get-AppxProvisionedPackage -Online)) {
        $AppPath = $AppsContent + $App.DisplayName + '_' + $App.PublisherId
        Write-Output "Handling $AppPath"
        $licFile = Get-Item $AppPath*.xml
        if ($licFile.Count) {
            $lic = $true
            $licFilePath = $licFile.FullName
        }
        else {
            $lic = $false
        }
        $appxFile = Get-Item $AppPath*.appx*
        if ($appxFile.Count) {
            $appxFilePath = $appxFile.FullName
            if ($lic) {
                Add-AppxProvisionedPackage -Online -PackagePath $appxFilePath -LicensePath $licFilePath 
            }
            else {
                Add-AppxProvisionedPackage -Online -PackagePath $appxFilePath -skiplicense
            }
        }
    }

    DismountFile $file
}

function InstallLanguageFiles($languageCode) { 
    $languagePackDriveLetter = MountFile (GetOutputFilePath 'LanguagePack')
    $fodDriveLetter = MountFile (GetOutputFilePath 'FOD')

    InstallLanguagePackage $languageCode $languagePackDriveLetter
    InstallFOD $languageCode $fodDriveLetter
    UpdateLanguageList $languageCode

    DismountFile (GetOutputFilePath 'LanguagePack')
    DismountFile (GetOutputFilePath 'FOD')

    InstallInboxApps
}

function Install() {

    ListSupportedLanguages
    $languageNumber = Read-Host "Select number to install language"

    if (!($languageNumber -in 1..$languages.Count))
    {
        Write-Host "Invalid language number." -ForegroundColor red
        break
    }

    $languageCode = $languages[$languageNumber - 1]

    DownloadLanguageFiles 
    InstallLanguageFiles $languageCode
    CleanupLanguageFiles
}

If (!(test-path $downloadPath)) {
    New-Item -ItemType Directory -Force -Path $downloadPath
}

$currentWindowsIdentity = [Security.Principal.WindowsIdentity]::GetCurrent()
$currentWindowsPrincipal = [Security.Principal.WindowsPrincipal]$currentWindowsIdentity
 
if( -not $currentWindowsPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)){
    Write-Host "Script needs to be run as Administrator." -ForegroundColor red
    Break Script
}

$winver = (Get-Item "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue('DisplayVersion')
if (!$winver) {
    $winver = (Get-Item "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue('ReleaseId')
}

if (!$languageFiles[$winver]){
    Write-Host "Languages installer is not supportd Windows $winver." -ForegroundColor red
    Break Script
}

##Disable language pack cleanup##
Disable-ScheduledTask -TaskPath "\Microsoft\Windows\AppxDeploymentClient\" -TaskName "Pre-staged app cleanup"

Write-Output "Install Windows $winver languages:" 
Install
# SIG # Begin signature block
# MIInLAYJKoZIhvcNAQcCoIInHTCCJxkCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBvUJ5Ce82TNuBx
# ivNPej/1K0x9IVak5Y90UV1XMl3cmaCCEWUwggh3MIIHX6ADAgECAhM2AAABOXjG
# OfXldyfqAAEAAAE5MA0GCSqGSIb3DQEBCwUAMEExEzARBgoJkiaJk/IsZAEZFgNH
# QkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFNRSBDUyBDQSAwMTAe
# Fw0yMDEwMjEyMDM5MDZaFw0yMTA5MTUyMTQzMDNaMCQxIjAgBgNVBAMTGU1pY3Jv
# c29mdCBBenVyZSBDb2RlIFNpZ24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
# AoIBAQCvtf6RG9X1bFXLQOzLuA06k5gBhizLWQ3/m6nIKOwoNsu9N+s9yt+ZGRpb
# ZbDtBmtAeoi3c2XK9vf0x3sq32GWPPv+px6a7u55tQ9lq4evX6QNxPhrH++ltlUt
# siiVmV934/+F5B/71sJ1Nxr89OsExV1b5Ey7LiKkEwxpTRxlOyUXf4OiQvTDzG0I
# 7AseJ4RxOy23tLnh8268pkucY2PbSLFYoRIG1ZGNgchcprL+uiRLuCz4vZXfidQo
# Wus3ThY8+mYulD8AaQ5ZtnuwzSHtzxYm/g6OeSDsf4xFep0DYLA3zNiKO4CvmzNR
# jJbcg1Bm7OpDe/CSLSWG5aoqW+X5AgMBAAGjggWDMIIFfzApBgkrBgEEAYI3FQoE
# HDAaMAwGCisGAQQBgjdbAQEwCgYIKwYBBQUHAwMwPQYJKwYBBAGCNxUHBDAwLgYm
# KwYBBAGCNxUIhpDjDYTVtHiE8Ys+hZvdFs6dEoFgg93NZoaUjDICAWQCAQwwggJ2
# BggrBgEFBQcBAQSCAmgwggJkMGIGCCsGAQUFBzAChlZodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F
# JTIwQ1MlMjBDQSUyMDAxKDEpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDEu
# YW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUy
# MDAxKDEpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDIuYW1lLmdibC9haWEv
# QlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDEpLmNydDBS
# BggrBgEFBQcwAoZGaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAx
# LkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDEpLmNydDBSBggrBgEFBQcwAoZG
# aHR0cDovL2NybDQuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F
# JTIwQ1MlMjBDQSUyMDAxKDEpLmNydDCBrQYIKwYBBQUHMAKGgaBsZGFwOi8vL0NO
# PUFNRSUyMENTJTIwQ0ElMjAwMSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2Vy
# dmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1BTUUsREM9R0JM
# P2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0
# aG9yaXR5MB0GA1UdDgQWBBRQasfWFuGWZ4TjHj7E0G+JYLldgzAOBgNVHQ8BAf8E
# BAMCB4AwUAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRp
# b25zIFB1ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzYxNjcrNDYyNTE2MIIB1AYDVR0f
# BIIByzCCAccwggHDoIIBv6CCAbuGPGh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9w
# a2lpbmZyYS9DUkwvQU1FJTIwQ1MlMjBDQSUyMDAxLmNybIYuaHR0cDovL2NybDEu
# YW1lLmdibC9jcmwvQU1FJTIwQ1MlMjBDQSUyMDAxLmNybIYuaHR0cDovL2NybDIu
# YW1lLmdibC9jcmwvQU1FJTIwQ1MlMjBDQSUyMDAxLmNybIYuaHR0cDovL2NybDMu
# YW1lLmdibC9jcmwvQU1FJTIwQ1MlMjBDQSUyMDAxLmNybIYuaHR0cDovL2NybDQu
# YW1lLmdibC9jcmwvQU1FJTIwQ1MlMjBDQSUyMDAxLmNybIaBumxkYXA6Ly8vQ049
# QU1FJTIwQ1MlMjBDQSUyMDAxLENOPUJZMlBLSUNTQ0EwMSxDTj1DRFAsQ049UHVi
# bGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlv
# bixEQz1BTUUsREM9R0JMP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9v
# YmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2ludDAfBgNVHSMEGDAWgBQbZqIZ
# /JvrpdqEjxiY6RCkw3uSvTAfBgNVHSUEGDAWBgorBgEEAYI3WwEBBggrBgEFBQcD
# AzANBgkqhkiG9w0BAQsFAAOCAQEArFNMfAJStrd/3V4hInTdjEo/CLYAY8YX/foG
# Amyk6NrjEx3uFN0sJmR3qR0iBggS3SBiUi4oZ+Xk8+DjVnnJFn9Fhmu/kB2wT4ZK
# jjjZeWROPcTsUnRgs1+OhKTWbX2Eng8oH3Cq0qR9LaOT/ES5Ejd98S1jq6WZ8B8K
# dNHg0d+VGAtwts+E3uu8MkUM5rUukmPHW7BC8ttmgKeXZiIiLV4T1KzxBMMNg0lY
# 7iFbQ5fkj5hLa1E0WvsGMcMGOMwRUVwVwl6F8OL8aUY5i7tpAuz54XVS4W1grPyT
# JDae1qB19H5JvqTwPPNm30JrFGpR/X/SGQhROsoD4V1tvCJ8tDCCCOYwggbOoAMC
# AQICEx8AAAAUtMUfxvKAvnEAAAAAABQwDQYJKoZIhvcNAQELBQAwPDETMBEGCgmS
# JomT8ixkARkWA0dCTDETMBEGCgmSJomT8ixkARkWA0FNRTEQMA4GA1UEAxMHYW1l
# cm9vdDAeFw0xNjA5MTUyMTMzMDNaFw0yMTA5MTUyMTQzMDNaMEExEzARBgoJkiaJ
# k/IsZAEZFgNHQkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFNRSBD
# UyBDQSAwMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANVXgQLW+frQ
# 9xuAud03zSTcZmH84YlyrSkM0hsbmr+utG00tVRHgw40pxYbJp5W+hpDwnmJgicF
# oGRrPt6FifMmnd//1aD/fW1xvGs80yZk9jxTNcisVF1CYIuyPctwuJZfwE3wcGxh
# kVw/tj3ZHZVacSls3jRD1cGwrcVo1IR6+hHMvUejtt4/tv0UmUoH82HLQ8w1oTX9
# D7xj35Zt9T0pOPqM3Gt9+/zs7tPp2gyoOYv8xR4X0iWZKuXTzxugvMA63YsB4ehu
# SBqzHdkF55rxH47aT6hPhvDHlm7M2lsZcRI0CUAujwcJ/vELeFapXNGpt2d3wcPJ
# M0bpzrPDJ/8CAwEAAaOCBNowggTWMBAGCSsGAQQBgjcVAQQDAgEBMCMGCSsGAQQB
# gjcVAgQWBBSR/DPOQp72k+bifVTXCBi7uNdxZTAdBgNVHQ4EFgQUG2aiGfyb66Xa
# hI8YmOkQpMN7kr0wggEEBgNVHSUEgfwwgfkGBysGAQUCAwUGCCsGAQUFBwMBBggr
# BgEFBQcDAgYKKwYBBAGCNxQCAQYJKwYBBAGCNxUGBgorBgEEAYI3CgMMBgkrBgEE
# AYI3FQYGCCsGAQUFBwMJBggrBgEFBQgCAgYKKwYBBAGCN0ABAQYLKwYBBAGCNwoD
# BAEGCisGAQQBgjcKAwQGCSsGAQQBgjcVBQYKKwYBBAGCNxQCAgYKKwYBBAGCNxQC
# AwYIKwYBBQUHAwMGCisGAQQBgjdbAQEGCisGAQQBgjdbAgEGCisGAQQBgjdbAwEG
# CisGAQQBgjdbBQEGCisGAQQBgjdbBAEGCisGAQQBgjdbBAIwGQYJKwYBBAGCNxQC
# BAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw
# HwYDVR0jBBgwFoAUKV5RXmSuNLnrrJwNp4x1AdEJCygwggFoBgNVHR8EggFfMIIB
# WzCCAVegggFToIIBT4YjaHR0cDovL2NybDEuYW1lLmdibC9jcmwvYW1lcm9vdC5j
# cmyGMWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2lpbmZyYS9jcmwvYW1lcm9v
# dC5jcmyGI2h0dHA6Ly9jcmwyLmFtZS5nYmwvY3JsL2FtZXJvb3QuY3JshiNodHRw
# Oi8vY3JsMy5hbWUuZ2JsL2NybC9hbWVyb290LmNybIaBqmxkYXA6Ly8vQ049YW1l
# cm9vdCxDTj1BTUVST09ULENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNl
# cyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPUFNRSxEQz1HQkw/Y2Vy
# dGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3Ry
# aWJ1dGlvblBvaW50MIIBqwYIKwYBBQUHAQEEggGdMIIBmTA3BggrBgEFBQcwAoYr
# aHR0cDovL2NybDEuYW1lLmdibC9haWEvQU1FUk9PVF9hbWVyb290LmNydDBHBggr
# BgEFBQcwAoY7aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL2NlcnRz
# L0FNRVJPT1RfYW1lcm9vdC5jcnQwNwYIKwYBBQUHMAKGK2h0dHA6Ly9jcmwyLmFt
# ZS5nYmwvYWlhL0FNRVJPT1RfYW1lcm9vdC5jcnQwNwYIKwYBBQUHMAKGK2h0dHA6
# Ly9jcmwzLmFtZS5nYmwvYWlhL0FNRVJPT1RfYW1lcm9vdC5jcnQwgaIGCCsGAQUF
# BzAChoGVbGRhcDovLy9DTj1hbWVyb290LENOPUFJQSxDTj1QdWJsaWMlMjBLZXkl
# MjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPUFNRSxE
# Qz1HQkw/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNlcnRpZmljYXRp
# b25BdXRob3JpdHkwDQYJKoZIhvcNAQELBQADggIBACi3Soaajx+kAWjNwgDqkIvK
# AOFkHmS1t0DlzZlpu1ANNfA0BGtck6hEG7g+TpUdVrvxdvPQ5lzU3bGTOBkyhGmX
# oSIlWjKC7xCbbuYegk8n1qj3rTcjiakdbBqqHdF8J+fxv83E2EsZ+StzfCnZXA62
# QCMn6t8mhCWBxpwPXif39Ua32yYHqP0QISAnLTjjcH6bAV3IIk7k5pQ/5NA6qIL8
# yYD6vRjpCMl/3cZOyJD81/5+POLNMx0eCClOfFNxtaD0kJmeThwL4B2hAEpHTeRN
# tB8ib+cze3bvkGNPHyPlSHIuqWoC31x2Gk192SfzFDPV1PqFOcuKjC8049SSBtC1
# X7hyvMqAe4dop8k3u25+odhvDcWdNmimdMWvp/yZ6FyjbGlTxtUqE7iLTLF1eaUL
# SEobAap16hY2N2yTJTISKHzHI4rjsEQlvqa2fj6GLxNj/jC+4LNy+uRmfQXShd30
# lt075qTroz0Nt680pXvVhsRSdNnzW2hfQu2xuOLg8zKGVOD/rr0GgeyhODjKgL2G
# Hxctbb9XaVSDf6ocdB//aDYjiabmWd/WYmy7fQ127KuasMh5nSV2orMcAed8CbIV
# I3NYu+sahT1DRm/BGUN2hSpdsPQeO73wYvp1N7DdLaZyz7XsOCx1quCwQ+bojWVQ
# TmKLGegSoUpZNfmP9MtSMYIVHTCCFRkCAQEwWDBBMRMwEQYKCZImiZPyLGQBGRYD
# R0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRUwEwYDVQQDEwxBTUUgQ1MgQ0EgMDEC
# EzYAAAE5eMY59eV3J+oAAQAAATkwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcN
# AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw
# LwYJKoZIhvcNAQkEMSIEIFQ4TukGfWCUAxJ3OxwhHbcEdNSYIhveqqStgB+l3F7o
# MEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEAQBoDPBku0EC5
# /r6oweFpA0cZxDSApLa2+DepgedA0jbWmJdYlIC4i4N+8B2pYxMO5sbH5f/zKBWQ
# 6k8mO2FcivhTm24CdSLUSmOM9mTlPNgnyH5me94rQ8Fdx+5m7pjHp2GG6bl+pAcF
# 0cFpxmkSZ/C3pt8VFLjgFQLQ85niBL6j9RVTEYaYGf1FK5jKYhISl1ls4y20cqgQ
# VDYO9ZrUGAXatxif6gih/HRIm68uzv4zYQNRXf0gpIC4pZOzRW3cYJJv19ZArbNQ
# mT11dg7AOS5iwUYSjCP1+348WZeK0ACj3pQK10su9iF4QzfLqf1xgqcv4IzTHZKT
# UsUoiYO7gKGCEuUwghLhBgorBgEEAYI3AwMBMYIS0TCCEs0GCSqGSIb3DQEHAqCC
# Er4wghK6AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFRBgsqhkiG9w0BCRABBKCCAUAE
# ggE8MIIBOAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCCu8GrnpXd7
# lagyjM/ivf63rJKDOTUB3dOCkcqcNym7hwIGYR6oAKb0GBMyMDIxMDkwNjA4MDA0
# My4zMzFaMASAAgH0oIHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z
# MSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo3QkYxLUUzRUEtQjgwODElMCMGA1UE
# AxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCDjwwggTxMIID2aADAgEC
# AhMzAAABUcNQ51lsqsanAAAAAAFRMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBU
# aW1lLVN0YW1wIFBDQSAyMDEwMB4XDTIwMTExMjE4MjYwNFoXDTIyMDIxMTE4MjYw
# NFowgcoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH
# EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNV
# BAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxl
# cyBUU1MgRVNOOjdCRjEtRTNFQS1CODA4MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt
# ZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
# n9KH76qErjvvOIkjWbHptMkYDjmG+JEmzguyr/VxjZgZ/ig8Mk47jqSJP5RxH/sD
# yqhYu7jPSO86siZh8u7DBX9L8I+AB+8fPPvD4uoLKD22BpoFl4B8Fw5K7Suibvbx
# GN7adL1/zW+sWXlVvpDhEPIKDICvEdNjGTLhktfftjefg9lumBMUBJ2G4/g4ad0d
# DvRNmKiMZXXe/Ll4Qg/oPSzXCUEYoSSqa5D+5MRimVe5/YTLj0jVr8iF45V0hT7V
# H8OJO4YImcnZhq6Dw1G+w6ACRGePFmOWqW8tEZ13SMmOquJrTkwyy8zyNtVttJAX
# 7diFLbR0SvMlbJZWK0KHdwIDAQABo4IBGzCCARcwHQYDVR0OBBYEFMV3/+NoUGKT
# NGg6OMyE6fN1ROptMB8GA1UdIwQYMBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYG
# A1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3Js
# L3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8yMDEwLTA3LTAxLmNybDBaBggrBgEFBQcB
# AQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kv
# Y2VydHMvTWljVGltU3RhUENBXzIwMTAtMDctMDEuY3J0MAwGA1UdEwEB/wQCMAAw
# EwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZIhvcNAQELBQADggEBACv99cAVg5nx
# 0SqjvLfQzmugMj5cJ9NE60duSH1LpxHYim9Ls3UfiYd7t0JvyEw/rRTEKHbznV6L
# FLlX++lHJMGKzZnHtTe2OI6ZHFnNiFhtgyWuYDJrm7KQykNi1G1LbuVie9MehmoK
# +hBiZnnrcfZSnBSokrvO2QEWHC1xnZ5wM82UEjprFYOkchU+6RcoCjjmIFGfgSzN
# j1MIbf4lcJ5FoV1Mg6FwF45CijOXHVXrzkisMZ9puDpFjjEV6TAY6INgMkhLev/A
# Vow0sF8MfQztJIlFYdFEkZ5NF/IyzoC2Yb9iw4bCKdBrdD3As6mvoGSNjCC6lOdz
# 6EerJK3NhFgwggZxMIIEWaADAgECAgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUA
# MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQD
# EylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0x
# MDA3MDEyMTM2NTVaFw0yNTA3MDEyMTQ2NTVaMHwxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFBDQSAyMDEwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcR
# ijog7PwTl/X6f2mUa3RUENWlCgCChfvtfGhLLF/Fw+Vhwna3PmYrW/AVUycEMR9B
# GxqVHc4JE458YTBZsTBED/FgiIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HN
# vyRgMlhgRvJYR4YyhB50YWeRX4FUsc+TTJLBxKZd0WETbijGGvmGgLvfYfxGwScd
# JGcSchohiq9LZIlQYrFd/XcfPfBXday9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u
# 5ZrKsajyeioKMfDaTgaRtogINeh4HLDpmc085y9Euqf03GS9pAHBIAmTeM38vMDJ
# RF1eFpwBBU8iTQIDAQABo4IB5jCCAeIwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0O
# BBYEFNVjOlyKMZDzQ3t8RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIA
# QwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2
# VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwu
# bWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEw
# LTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93
# d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYt
# MjMuY3J0MIGgBgNVHSABAf8EgZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEF
# BQcCARYxaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL1BLSS9kb2NzL0NQUy9kZWZh
# dWx0Lmh0bTBABggrBgEFBQcCAjA0HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMA
# eQBfAFMAdABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0BAQsFAAOCAgEAB+aI
# UQ3ixuCYP4FxAz2do6Ehb7Prpsz1Mb7PBeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ie
# JeP5vO1rVFcIK1GCRBL7uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZLdO9CEMiv
# v3/Gf/I3fVo/HPKZeUqRUgCvOA8X9S95gWXZqbVr5MfO9sp6AG9LMEQkIjzP7QOl
# lo9ZKby2/QThcJ8ySif9Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoLkSbi
# OewZSnFjnXshbcOco6I8+n99lmqQeKZt0uGc+R38ONiU9MalCpaGpL2eGq4EQoO4
# tYCbIjggtSXlZOz39L9+Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ
# 732D8OE7cQnfXXSYIghh2rBQHm+98eEA3+cxB6STOvdlR3jo+KhIq/fecn5ha293
# qYHLpwmsObvsxsvYgrRyzR30uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAz
# LhIp9cAvVCch98isTtoouLGp25ayp0Kiyc8ZQU3ghvkqmqMRZjDTu3QyS99je/WZ
# ii8bxyGvWbWu3EQ8l1Bx16HSxVXjad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gF
# Lu8NoFA12u8JJxzVs341Hgi62jbb01+P3nSISRKhggLOMIICNwIBATCB+KGB0KSB
# zTCByjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UE
# CxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVz
# IFRTUyBFU046N0JGMS1FM0VBLUI4MDgxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1l
# LVN0YW1wIFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVAKCir3PxP6RCCyVMJSAVoMV6
# 1yNeoIGDMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwDQYJKoZI
# hvcNAQEFBQACBQDk4Dg8MCIYDzIwMjEwOTA2MTQ0ODI4WhgPMjAyMTA5MDcxNDQ4
# MjhaMHcwPQYKKwYBBAGEWQoEATEvMC0wCgIFAOTgODwCAQAwCgIBAAICDgICAf8w
# BwIBAAICEtUwCgIFAOThibwCAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGE
# WQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQBN
# Ocs4hwCgKmxb7Dong8N1T49zCWLRwJzYKukxmxPTKRNGlOtZjJpEeloj2QwdWZoE
# uY8uQewGMitHh3ocQQL8KDa+Z8dDSxOM5H4P1zGXZVEsHlHiKtxcCssbskFUerfu
# nZDZ2O4eNZH1B8TYo6Ue06hFeDySKb8c4FWfc5sU8TGCAw0wggMJAgEBMIGTMHwx
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABUcNQ51lsqsanAAAAAAFR
# MA0GCWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQw
# LwYJKoZIhvcNAQkEMSIEIGI5u7CzwDmPZduFulmDgQoHs1q/ngMzzBE6Q6xkJwyf
# MIH6BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgLs1cmYj41sFZBwCmFvv9ScP5
# tuuUhxsv/t0B9XF65UEwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg
# MjAxMAITMwAAAVHDUOdZbKrGpwAAAAABUTAiBCBQ3T+4xu4/dPxPQcVsnj+SvIQz
# W1ZYfOB7Qhp/EFZo7zANBgkqhkiG9w0BAQsFAASCAQBfyoH49n9MJZqlqcaiNO4h
# 1u3fmn5aeRQPs0aEDie1NfNKkqZv7VTNT3eu6p/49/5ECGlMmLf46caV8fut+Mcz
# vUZXONGx+owQwwuCheUPIrFfexKL0aeWGLhUO2oAODfyoFWnpgojeGAVVvKuEJG1
# KuhDsdOux5LGyCaIBseZ2NbIavUUK2qdXTsiSpf/U3dN7Ie32Ppgp/6fX1OD3Wjf
# wurjzldRcuMVYORfK3JWkDMhnyHvvoVQHQ+4twB+OGXysOjVf0L+qIYdv8wE52uK
# NfZwojKY7j1zRNXcifSCQeJpkJFYZepZhUFATRynCQi3yn3dZVsTDaExikxmW/1D
# SIG # End signature block