1 # Copyright (c) 2015-2016 The Khronos Group Inc. 2 # Copyright (c) 2015-2016 Valve Corporation 3 # Copyright (c) 2015-2016 LunarG, Inc. 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and/or associated documentation files (the "Materials"), to 7 # deal in the Materials without restriction, including without limitation the 8 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 # sell copies of the Materials, and to permit persons to whom the Materials are 10 # furnished to do so, subject to the following conditions: 11 # 12 # The above copyright notice(s) and this permission notice shall be included in 13 # all copies or substantial portions of the Materials. 14 # 15 # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 # 19 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 22 # USE OR OTHER DEALINGS IN THE MATERIALS. 23 # 24 # Author: David Pinedo <david (a] LunarG.com> 25 # Author: Mark Young <mark (a] LunarG.com> 26 # 27 28 29 # This Powershell script is used by the Vulkan Run Time Installer/Uninstaller to: 30 # - Copy the most recent vulkan-<majorabi>-*.dll in C:\Windows\System32 31 # to vulkan-<majorabi>.dll 32 # - Copy the most recent version of vulkaninfo-<abimajor>-*.exe in 33 # C:\Windows\System32 to vulkaninfo.exe 34 # - The same thing is done for those files in C:\Windows\SysWOW64 on a 64-bit 35 # target. 36 # - Set the layer registry entries to point to the layer json files 37 # in the Vulkan SDK associated with the most recent vulkan*dll. 38 # 39 # This script takes the following parameters: 40 # $majorabi : a single string number specifying the major abi version. 41 # $ossize : an integer indicating if the target is a 64 (64) or 32 (32) bit OS. 42 # 43 44 Param( 45 [string]$majorabi, 46 [int]$ossize 47 ) 48 49 $vulkandll = "vulkan-"+$majorabi+".dll" 50 $windrive = $env:SYSTEMDRIVE 51 $winfolder = $env:SYSTEMROOT 52 $script:VulkanDllList=@() 53 54 function notNumeric ($x) { 55 try { 56 0 + $x | Out-Null 57 return $false 58 } catch { 59 return $true 60 } 61 } 62 63 # The name of the versioned vulkan dll file is one of the following: 64 # 65 # vulkan-<majorabi>-<major>-<minor>-<patch>-<buildno>-<prerelease>-<prebuildno> 66 # vulkan-<majorabi>-<major>-<minor>-<patch>-<buildno>-<prerelease> 67 # vulkan-<majorabi>-<major>-<minor>-<patch>-<buildno>-<prebuildno> 68 # vulkan-<majorabi>-<major>-<minor>-<patch>-<buildno>.dll 69 # 70 # <major>, <minor>, <patch>, <buildno> and <prebuildno> are 1 to 10 numeric digits. 71 # <prerelease> is any combination of alpha and numeric characters. 72 # If <prerelease> and/or <prebuildno> are present, this identifies a prerelease, 73 # and the vulkan dll file will be considered less recent than one with the same 74 # <major>, <minor>, <patch>, <buildno> numbers without the <prerelease> and/or 75 # <prebuildno>. 76 77 78 # We first create an array, with one array element for each vulkan-*dll in 79 # C:\Windows\System32 (and C:\Windows\SysWOW64 on 64-bit systems), with each element 80 # containing: 81 # <major>=<minor>=<patch>=<buildno>=<prerelease>=<prebuildno>= 82 # filename 83 # @<major>@<minor>@<patch>@<buildno>@<prerelease>@<prebuildno>@ 84 # [Note that the above three lines are one element in the array.] 85 # The build identifiers separated by "=" are suitable for sorting, i.e. 86 # expanded to 10 digits with leading 0s. If <prerelease> or <prebuildno> are 87 # not specified, "zzzzzzzzzz" is substituted for them, so that they sort 88 # to a position after those that do specify them. 89 # The build identifiers separated by "@" are the original values extracted 90 # from the file name. They are used later to find the path to the SDK 91 # install directory for the given filename. 92 93 94 function UpdateVulkanSysFolder([string]$dir, [int]$writeSdkName) 95 { 96 # Push the current path on the stack and go to $dir 97 Push-Location -Path $dir 98 99 # Create a list for all the DLLs in the folder. 100 # First Initialize the list to empty 101 $script:VulkanDllList = @() 102 103 # Find all DLL objects in this directory 104 dir -name vulkan-$majorabi-*.dll | 105 ForEach-Object { 106 if ($_ -match "=" -or 107 $_ -match "@" -or 108 $_ -match " " -or 109 ($_.Split('-').count -lt 6) -or 110 ($_.Split('-').count -gt 8)) 111 { 112 # If a file name contains "=", "@", or " ", or it contains less then 5 dashes or more than 113 # 7 dashes, it wasn't installed by the Vulkan Run Time. 114 # Note that we need to use return inside of ForEach-Object is to continue with iteration. 115 return 116 } 117 $major=$_.Split('-')[2] 118 $majorOrig=$major 119 $minor=$_.Split('-')[3] 120 $minorOrig=$minor 121 $patch=$_.Split('-')[4] 122 $patchOrig=$patch 123 $buildno=$_.Split('-')[5] 124 125 if ($buildno -match ".dll") { 126 # prerelease and prebuildno are not in the name 127 # Extract buildno, and set prerelease and prebuildno to "z"s 128 $buildno=$buildno -replace ".dll","" 129 $buildnoOrig=$buildno 130 $prerelease="z"*10 131 $prereleaseOrig="" 132 $prebuildno="z"*10 133 $prebuildnoOrig="" 134 } else { 135 # Extract buildno, prerelease, and prebuildno 136 $f=$_ -replace ".dll","" 137 $buildno=$f.Split('-')[5] 138 $buildnoOrig=$buildno 139 $prerelease=$f.Split('-')[6] 140 $prebuildno=$f.Split('-')[7] 141 if ($prebuildno.Length -eq 0) { 142 if ($prerelease -match "^[0-9]") { 143 # prerelease starts with a digit, it must be the prebuildno 144 $prebuildno=$prerelease 145 $prerelease="" 146 } 147 } 148 $prereleaseOrig=$prerelease 149 $prebuildnoOrig=$prebuildno 150 151 if ($prerelease.Length -eq 0) { 152 $prerelease="z"*10 153 } 154 if ($prebuildno.Length -eq 0) { 155 $prebuildno="z"*10 156 } 157 } 158 159 # Make sure fields that are supposed to be numbers are numbers 160 if (notNumeric($major)) {return} 161 if (notNumeric($minor)) {return} 162 if (notNumeric($patch)) {return} 163 if (notNumeric($buildno)) {return} 164 if (notNumeric($prebuildno)) { 165 if ($prebuildno -ne "z"*10) {return} 166 } 167 168 $major = $major.padleft(10,'0') 169 $minor = $minor.padleft(10,'0') 170 $patch = $patch.padleft(10,'0') 171 $buildno = $buildno.padleft(10,'0') 172 $prerelease = $prerelease.padleft(10,'0') 173 $prebuildno = $prebuildno.padleft(10,'0') 174 175 # Add a new element to the $VulkanDllList array 176 $script:VulkanDllList+="$major=$minor=$patch=$buildno=$prerelease=$prebuildno= $_ @$majorOrig@$minorOrig@$patchOrig@$buildnoOrig@$prereleaseOrig@$prebuildnoOrig@" 177 } 178 179 # If $VulkanDllList contains at least one element, there's at least one vulkan*.dll file. 180 # Copy the most recent vulkan*.dll (named in the last element of $VulkanDllList) to vulkan-$majorabi.dll. 181 182 if ($script:VulkanDllList.Length -gt 0) { 183 184 # Sort the list. The most recent vulkan-*.dll will be in the last element of the list. 185 [array]::sort($script:VulkanDllList) 186 187 # Put the name of the most recent vulkan-*.dll in $mrVulkanDLL. 188 # The most recent vulkanDLL is the second word in the last element of the 189 # sorted $VulkanDllList. Copy it to $vulkandll. 190 $mrVulkanDll=$script:VulkanDllList[-1].Split(' ')[1] 191 copy $mrVulkanDll $vulkandll 192 193 # Copy the most recent version of vulkaninfo-<abimajor>-*.exe to vulkaninfo.exe. 194 # We create the source file name for the copy from $mrVulkanDll. 195 $mrVulkaninfo=$mrVulkanDll -replace ".dll",".exe" 196 $mrVulkaninfo=$mrVulkaninfo -replace "vulkan","vulkaninfo" 197 copy $mrVulkaninfo vulkaninfo.exe 198 199 # Create the name used in the registry for the SDK associated with $mrVulkanDll. 200 $major=$script:VulkanDllList[-1].Split('@')[1] 201 $minor=$script:VulkanDllList[-1].Split('@')[2] 202 $patch=$script:VulkanDllList[-1].Split('@')[3] 203 $buildno=$script:VulkanDllList[-1].Split('@')[4] 204 $prerelease=$script:VulkanDllList[-1].Split('@')[5] 205 $prebuildno=$script:VulkanDllList[-1].Split('@')[6] 206 207 $sdktempname="VulkanSDK"+$major + "." + $minor + "." + $patch + "." + $buildno 208 if ($prerelease -ne "") { 209 $sdktempname=$sdktempname + "." + $prerelease 210 } 211 if ($prebuildno -ne "") { 212 $sdktempname=$sdktempname + "." + $prebuildno 213 } 214 } 215 216 # Return to our previous folder 217 Pop-Location 218 219 # Only update the overall script-scope SDK name if we're told to 220 if ($writeSdkName -ne 0) { 221 $script:sdkname = $sdktempname 222 } 223 224 return 225 } 226 227 # We only care about SYSWOW64 if we're targeting a 64-bit OS 228 if ($ossize -eq 64) { 229 # Update the SYSWOW64 Vulkan DLLS/EXEs 230 UpdateVulkanSysFolder $winfolder\SYSWOW64 0 231 } 232 233 # Update the SYSTEM32 Vulkan DLLS/EXEs 234 UpdateVulkanSysFolder $winfolder\SYSTEM32 1 235 236 # Create an array of vulkan sdk install dirs 237 238 $mrVulkanDllInstallDir="" 239 $VulkanSdkDirs=@() 240 Get-ChildItem -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | 241 ForEach-Object { 242 $regkey=$_ -replace ".*\\","" 243 if ($_ -match "\\VulkanSDK") { 244 # Get the install path from UninstallString 245 $tmp=Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$regkey -Name UninstallString 246 $tmp=$tmp -replace "\\Uninstall.exe.*","" 247 $tmp=$tmp -replace ".*=.","" 248 $VulkanSdkDirs+=$tmp 249 if ($regkey -eq $script:sdkname) { 250 # Save away the sdk install dir for the the most recent vulkandll 251 $mrVulkanDllInstallDir=$tmp 252 } 253 } 254 } 255 256 257 # Search list of sdk install dirs for an sdk compatible with $script:sdkname. 258 # We go backwards through VulkanDllList to generate SDK names, because we want the most recent SDK. 259 if ($mrVulkanDllInstallDir -eq "") { 260 ForEach ($idx in ($script:VulkanDllList.Length-1)..0) { 261 $vulkanDllMajor=$script:VulkanDllList[$idx].Split('@')[1] 262 $vulkanDllMinor=$script:VulkanDllList[$idx].Split('@')[2] 263 $vulkanDllPatch=$script:VulkanDllList[$idx].Split('@')[3] 264 $vulkanDllBuildno=$script:VulkanDllList[$idx].Split('@')[4] 265 $vulkanDllPrerelease=$script:VulkanDllList[$idx].Split('@')[5] 266 $vulkanDllPrebuildno=$script:VulkanDllList[$idx].Split('@')[6] 267 $regEntry="VulkanSDK"+$vulkanDllMajor+"."+$vulkanDllMinor+"."+$vulkanDllPatch+"."+$vulkanDllBuildno 268 if ($vulkanDllPrerelease) { 269 $regEntry=$regEntry+"."+$vulkanDllPrerelease 270 } 271 if ($vulkanDllPrebuildno) { 272 $regEntry=$regEntry+"."+$vulkanDllPrebuildno 273 } 274 $rval=Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$regEntry -ErrorAction SilentlyContinue 275 $instDir=$rval 276 $instDir=$instDir -replace "\\Uninstall.exe.*","" 277 $instDir=$instDir -replace ".*=.","" 278 if ($rval) { 279 $rval=$rval -replace ".* DisplayVersion=","" 280 $rval=$rval -replace ";.*","" 281 $reMajor=$rval.Split('.')[0] 282 $reMinor=$rval.Split('.')[1] 283 $rePatch=$rval.Split('.')[2] 284 if ($reMajor+$reMinor+$rePatch -eq $vulkanDllMajor+$vulkanDllMinor+$vulkanDllPatch) { 285 $mrVulkanDllInstallDir=$instDir 286 break 287 } 288 } 289 } 290 } 291 292 # Add C:\Vulkan\SDK\0.9.3 to list of SDK install dirs. 293 # We do this because there is in a bug in SDK 0.9.3 in which layer 294 # reg entries were not removed on uninstall. So we'll try to clean up 295 # and remove them now. 296 # This works only if 0.9.3 was installed to the default location. 297 # If it was not installed to the default location, those entries will 298 # need to be cleaned up manually. 299 300 $VulkanSdkDirs+="C:\VulkanSDK\0.9.3" 301 $VulkanSdkDirs+="$windrive\VulkanSDK\0.9.3" 302 303 # Remove layer registry entries associated with all installed Vulkan SDKs. 304 # Note that we remove only those entries created by Vulkan SDKs. If other 305 # layers were installed that are not from an SDK, we don't mess with them. 306 307 Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\ExplicitLayers | Select-Object -ExpandProperty Property | 308 ForEach-Object { 309 $regval=$_ 310 ForEach ($sdkdir in $VulkanSdkDirs) { 311 if ($regval -like "$sdkdir\*.json") { 312 Remove-ItemProperty -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers -name $regval 313 } 314 } 315 } 316 # Remove 32-bit layer registry entries if we're targeting a 64-bit OS 317 if ($ossize -eq 64) { 318 Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers | Select-Object -ExpandProperty Property | 319 ForEach-Object { 320 $regval=$_ 321 ForEach ($sdkdir in $VulkanSdkDirs) { 322 if ($regval -like "$sdkdir\*.json") { 323 Remove-ItemProperty -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers -name $regval 324 } 325 } 326 } 327 } 328 329 330 # Create layer registry entries associated with Vulkan SDK from which $mrVulkanDll is from 331 332 if ($mrVulkanDllInstallDir -ne "") { 333 if ($ossize -eq 64) { 334 335 # Create registry entires in normal registry location for 64-bit items on a 64-bit OS 336 New-Item -Force -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers | out-null 337 Get-ChildItem $mrVulkanDllInstallDir\Bin -Filter VkLayer*json | 338 ForEach-Object { 339 New-ItemProperty -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers -Name $mrVulkanDllInstallDir\Bin\$_ -PropertyType DWord -Value 0 | out-null 340 } 341 342 # Create registry entires for the WOW6432Node registry location for 32-bit items on a 64-bit OS 343 New-Item -Force -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers | out-null 344 Get-ChildItem $mrVulkanDllInstallDir\Bin32 -Filter VkLayer*json | 345 ForEach-Object { 346 New-ItemProperty -Path HKLM:\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers -Name $mrVulkanDllInstallDir\Bin32\$_ -PropertyType DWord -Value 0 | out-null 347 } 348 349 } else { 350 351 # Create registry entires in normal registry location for 32-bit items on a 32-bit OS 352 New-Item -Force -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers | out-null 353 Get-ChildItem $mrVulkanDllInstallDir\Bin32 -Filter VkLayer*json | 354 ForEach-Object { 355 New-ItemProperty -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers -Name $mrVulkanDllInstallDir\Bin32\$_ -PropertyType DWord -Value 0 | out-null 356 } 357 358 } 359 } 360 361 # SIG # Begin signature block 362 # MIIcZgYJKoZIhvcNAQcCoIIcVzCCHFMCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB 363 # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR 364 # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUdeZMvyfevbCm2d9Sn02g0L39 365 # 6EKggheVMIIFHjCCBAagAwIBAgIQDmYEpPtQ2iBY4vC2AGq6uzANBgkqhkiG9w0B 366 # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD 367 # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz 368 # c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTE1MDQzMDAwMDAwMFoXDTE2MDcw 369 # NjEyMDAwMFowZTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMRUwEwYD 370 # VQQHEwxGb3J0IENvbGxpbnMxFTATBgNVBAoTDEx1bmFyRywgSW5jLjEVMBMGA1UE 371 # AxMMTHVuYXJHLCBJbmMuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 372 # jaLJm/Joxsn/IeopiGY3XPeSZeIhjSjSlQUkDyIyDGcBG7CvfiSsXIw3EgdGkjQg 373 # yBcW5YsPz9bPGPUjo5go7CwZaRkhW7/LmSkAlx0UAv8EMLuJrAZ3jBNZvpPPqfWd 374 # zgi/Rkm2gWQ6eSKouy7IjcLk+EwkeBbB+UBnYfMp0BfCPzR3mPgGAJH6efAmEaqQ 375 # FBCrX97joYgDqp3v8u42jALLl/Ict/GNMHLxP+QWagIHIICCRgS6s02OsildLF6R 376 # nqJOOG/43f2qUD4Cab65kzlI+0+uQyOl1UlxNxp0XareghGTqECsYA03j64Esxyo 377 # 2xrNbV2LJm9crTX6QthxywIDAQABo4IBuzCCAbcwHwYDVR0jBBgwFoAUWsS5eyoK 378 # o6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYEFOSdVsqodGWApfCjHtAcn8sAzLBGMA4G 379 # A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWg 380 # M6Axhi9odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcx 381 # LmNybDA1oDOgMYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJl 382 # ZC1jcy1nMS5jcmwwQgYDVR0gBDswOTA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcC 383 # ARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCBhAYIKwYBBQUHAQEEeDB2 384 # MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTgYIKwYBBQUH 385 # MAKGQmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1 386 # cmVkSURDb2RlU2lnbmluZ0NBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEB 387 # CwUAA4IBAQCIt1S8zfvzMQEVmdAssjrwqBaq78xhtGPLjkNF06EvtWoV6VMLI/A6 388 # 45KoULsaXeYuszLxNI+OT/b4HfD0e2LxImaTDZRmCLeIs+2pMLSlWDSV4okm8Vk2 389 # rObLBlgiI1x0PiMa1le9D832COWM4EJcH7pxM+9JfiHYMLlZbcfNEVgv6Dhhl4MG 390 # mOTMTl7vQNNQaJ1coNVf9m5Bez1DV9Iu2Cgd8BHp1oLVCQCHjVv0Ifj48RIPi4SQ 391 # khzalrnrf+L/BWRDhpLnxYasazdV5WfrMHurPuBvYUiLQNkU9SqKgRk9XrzDAfMe 392 # gPbGybMr0kqtbE/A/cDcTVnvRuTZnhXSMIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1 393 # U0O1b5VQCDANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM 394 # RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQD 395 # ExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcN 396 # MjgxMDIyMTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg 397 # SW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2Vy 398 # dCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0B 399 # AQEFAAOCAQ8AMIIBCgKCAQEA+NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid 400 # 2zLXcep2nQUut4/6kkPApfmJ1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sj 401 # lOSRI5aQd4L5oYQjZhJUM1B0sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjf 402 # DPXiTWAYvqrEsq5wMWYzcT6scKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzL 403 # fnQ5Ng2Q7+S1TqSp6moKq4TzrGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR 404 # 93O8vYWxYoNzQYIH5DiLanMg0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckw 405 # EgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYI 406 # KwYBBQUHAwMweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz 407 # cC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2lj 408 # ZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgw 409 # OqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJ 410 # RFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp 411 # Q2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIE 412 # MCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYI 413 # YIZIAYb9bAMwHQYDVR0OBBYEFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQY 414 # MBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1a 415 # JLPzItEVyCx8JSl2qB1dHC06GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUP 416 # UbRupY5a4l4kgU4QpO4/cY5jDhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1 417 # UcKNJK4kxscnKqEpKBo6cSgCPC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjF 418 # Emifz0DLQESlE/DmZAwlCEIysjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM 419 # 1ekN3fYBIM6ZMWM9CBoYs4GbT8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhs 420 # RDKyZqHnGKSaZFHvMIIGajCCBVKgAwIBAgIQAwGaAjr/WLFr1tXq5hfwZjANBgkq 421 # hkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j 422 # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBB 423 # c3N1cmVkIElEIENBLTEwHhcNMTQxMDIyMDAwMDAwWhcNMjQxMDIyMDAwMDAwWjBH 424 # MQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNlcnQxJTAjBgNVBAMTHERpZ2lD 425 # ZXJ0IFRpbWVzdGFtcCBSZXNwb25kZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 426 # ggEKAoIBAQCjZF38fLPggjXg4PbGKuZJdTvMbuBTqZ8fZFnmfGt/a4ydVfiS457V 427 # WmNbAklQ2YPOb2bu3cuF6V+l+dSHdIhEOxnJ5fWRn8YUOawk6qhLLJGJzF4o9GS2 428 # ULf1ErNzlgpno75hn67z/RJ4dQ6mWxT9RSOOhkRVfRiGBYxVh3lIRvfKDo2n3k5f 429 # 4qi2LVkCYYhhchhoubh87ubnNC8xd4EwH7s2AY3vJ+P3mvBMMWSN4+v6GYeofs/s 430 # jAw2W3rBerh4x8kGLkYQyI3oBGDbvHN0+k7Y/qpA8bLOcEaD6dpAoVk62RUJV5lW 431 # MJPzyWHM0AjMa+xiQpGsAsDvpPCJEY93AgMBAAGjggM1MIIDMTAOBgNVHQ8BAf8E 432 # BAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDCCAb8G 433 # A1UdIASCAbYwggGyMIIBoQYJYIZIAYb9bAcBMIIBkjAoBggrBgEFBQcCARYcaHR0 434 # cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCCAWQGCCsGAQUFBwICMIIBVh6CAVIA 435 # QQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABDAGUAcgB0AGkAZgBpAGMA 436 # YQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABhAGMAYwBlAHAAdABhAG4A 437 # YwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQByAHQAIABDAFAALwBDAFAA 438 # UwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBnACAAUABhAHIAdAB5ACAA 439 # QQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABsAGkAbQBpAHQAIABsAGkA 440 # YQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABpAG4AYwBvAHIAcABvAHIA 441 # YQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBlAGYAZQByAGUAbgBjAGUA 442 # LjALBglghkgBhv1sAxUwHwYDVR0jBBgwFoAUFQASKxOYspkH7R7for5XDStnAs0w 443 # HQYDVR0OBBYEFGFaTSS2STKdSip5GoNL9B6Jwcp9MH0GA1UdHwR2MHQwOKA2oDSG 444 # Mmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENBLTEu 445 # Y3JsMDigNqA0hjJodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1 446 # cmVkSURDQS0xLmNybDB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6 447 # Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMu 448 # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEQ0EtMS5jcnQwDQYJKoZIhvcN 449 # AQEFBQADggEBAJ0lfhszTbImgVybhs4jIA+Ah+WI//+x1GosMe06FxlxF82pG7xa 450 # FjkAneNshORaQPveBgGMN/qbsZ0kfv4gpFetW7easGAm6mlXIV00Lx9xsIOUGQVr 451 # NZAQoHuXx/Y/5+IRQaa9YtnwJz04HShvOlIJ8OxwYtNiS7Dgc6aSwNOOMdgv420X 452 # Ewbu5AO2FKvzj0OncZ0h3RTKFV2SQdr5D4HRmXQNJsQOfxu19aDxxncGKBXp2JPl 453 # VRbwuwqrHNtcSCdmyKOLChzlldquxC5ZoGHd2vNtomHpigtt7BIYvfdVVEADkitr 454 # wlHCCkivsNRu4PQUCjob4489yq9qjXvc2EQwggbNMIIFtaADAgECAhAG/fkDlgOt 455 # 6gAK6z8nu7obMA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK 456 # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV 457 # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBa 458 # Fw0yMTExMTAwMDAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy 459 # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD 460 # ZXJ0IEFzc3VyZWQgSUQgQ0EtMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 461 # ggEBAOiCLZn5ysJClaWAc0Bw0p5WVFypxNJBBo/JM/xNRZFcgZ/tLJz4FlnfnrUk 462 # FcKYubR3SdyJxArar8tea+2tsHEx6886QAxGTZPsi3o2CAOrDDT+GEmC/sfHMUiA 463 # fB6iD5IOUMnGh+s2P9gww/+m9/uizW9zI/6sVgWQ8DIhFonGcIj5BZd9o8dD3QLo 464 # Oz3tsUGj7T++25VIxO4es/K8DCuZ0MZdEkKB4YNugnM/JksUkK5ZZgrEjb7Szgau 465 # rYRvSISbT0C58Uzyr5j79s5AXVz2qPEvr+yJIvJrGGWxwXOt1/HYzx4KdFxCuGh+ 466 # t9V3CidWfA9ipD8yFGCV/QcEogkCAwEAAaOCA3owggN2MA4GA1UdDwEB/wQEAwIB 467 # hjA7BgNVHSUENDAyBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEF 468 # BQcDBAYIKwYBBQUHAwgwggHSBgNVHSAEggHJMIIBxTCCAbQGCmCGSAGG/WwAAQQw 469 # ggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9zc2wtY3Bz 470 # LXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4AeQAgAHUA 471 # cwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQAZQAgAGMA 472 # bwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUAIABvAGYA 473 # IAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAAYQBuAGQA 474 # IAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcAcgBlAGUA 475 # bQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIAaQBsAGkA 476 # dAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkACAA 477 # aABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMAsGCWCGSAGG 478 # /WwDFTASBgNVHRMBAf8ECDAGAQH/AgEAMHkGCCsGAQUFBwEBBG0wazAkBggrBgEF 479 # BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRw 480 # Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0Eu 481 # Y3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20v 482 # RGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsNC5k 483 # aWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMB0GA1UdDgQW 484 # BBQVABIrE5iymQftHt+ivlcNK2cCzTAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun 485 # pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEARlA+ybcoJKc4HbZbKa9Sz1LpMUer 486 # Vlx71Q0LQbPv7HUfdDjyslxhopyVw1Dkgrkj0bo6hnKtOHisdV0XFzRyR4WUVtHr 487 # uzaEd8wkpfMEGVWp5+Pnq2LN+4stkMLA0rWUvV5PsQXSDj0aqRRbpoYxYqioM+Sb 488 # OafE9c4deHaUJXPkKqvPnHZL7V/CSxbkS3BMAIke/MV5vEwSV/5f4R68Al2o/vsH 489 # OE8Nxl2RuQ9nRc3Wg+3nkg2NsWmMT/tZ4CMP0qquAHzunEIOz5HXJ7cW7g/DvXwK 490 # oO4sCFWFIrjrGBpN/CohrUkxg0eVd3HcsRtLSxwQnHcUwZ1PL1qVCCkQJjGCBDsw 491 # ggQ3AgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx 492 # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNI 493 # QTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0ECEA5mBKT7UNogWOLwtgBqursw 494 # CQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcN 495 # AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw 496 # IwYJKoZIhvcNAQkEMRYEFCQBfl/Xm3/R6yW/EO6kbSmkdowDMA0GCSqGSIb3DQEB 497 # AQUABIIBADCbC3HqswOLfqwjX9+TM0hW9sG02WMHPbz0fFBTH5J/tck4wZECl9ct 498 # DK0pUzHoJBY9EuBnH9OD46MiVCIYwYHQ9w/xiaypUNRbfXYEwSVL9EXCIcYkkqAN 499 # pSpDrQJu0TzmGyvN1fSvYj/qahvIVKz/cxbzzQbYl4NqNXRfiD26Pa5JOdNABP8g 500 # WL5Ruk/MPvMJE0dIW3em40hoanGKQhP0xgQ/BGJygumYrZsigENfhQkRVngH/aUP 501 # f5k78VKL3DFoCMmneIxAfIwspTC37izb/AjlqDNUbqEmfBBIsbLgu6teZVIyPBI/ 502 # nktk5kwOOhzuyeQxLAcn0z+8ToF5frKhggIPMIICCwYJKoZIhvcNAQkGMYIB/DCC 503 # AfgCAQEwdjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkw 504 # FwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBBc3N1 505 # cmVkIElEIENBLTECEAMBmgI6/1ixa9bV6uYX8GYwCQYFKw4DAhoFAKBdMBgGCSqG 506 # SIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE2MDMyMjIwMjM0 507 # N1owIwYJKoZIhvcNAQkEMRYEFM6NeSjPd00j7j25copMrjENL7GXMA0GCSqGSIb3 508 # DQEBAQUABIIBAHJbUlt2mxIX5hbiigRw3kIoug57G5sDYWQK8rcTjHUif6PAdEqj 509 # 5c1UhxQHJxEasddUAqbEtCsG8qiz1lq76KKiwaWxffSRQ2JwjYEvnYQ2TK9rtnMs 510 # zeYnQajrIUP44z7ysqoikB0bEgup0QVDScm4SSa1SmqQzHMsUX5rCygsM3PlpF5K 511 # dH2u3eSK4zDhGiye6/SQkcddvsI2lLFRcxQIyfUD4+W9oFdXuYkKhNBGPLUlOH9V 512 # DEDQG9zH6CAzvla/r1iYnX8RZ4rz7yacdrMBq5g92HAEcuXFTBQfaeAZSGQBhNSn 513 # p1rVWgLb0T3a/5zlOtZvp+bLyDRbms+w8BY= 514 # SIG # End signature block 515