# This powershell script is part of WVDAdmin and Project Hydra - see https://blog.itprocloud.de/Windows-Virtual-Desktop-Admin/ for more information # Current Version of this script: 4.7 param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [ValidateSet('Generalize','JoinDomain','DataPartition','RDAgentBootloader','RestartBootloader','StartBootloader','CleanFirstStart', 'RenameComputer')] [string] $Mode, [string] $StrongGeneralize='0', [string] $ComputerNewname='', #Only for SecureBoot process (workaround, normaly not used) [string] $LocalAdminName='localAdmin', #Only for SecureBoot process (workaround, normaly not used) [string] $LocalAdminPassword='', [string] $DomainJoinUserName='', [string] $DomainJoinUserPassword='', [string] $LocalAdminName64='bG9jYWxBZG1pbg==', #Base64-coding is used if not empty - providing the older parameters to be compatible [string] $LocalAdminPassword64='', [string] $DomainJoinUserName64='', [string] $DomainJoinUserPassword64='', [string] $DomainJoinOU='', [string] $AadOnly='0', [string] $JoinMem='0', [string] $MovePagefileToC='0', [string] $DomainFqdn='', [string] $WvdRegistrationKey='', [string] $LogDir="$env:windir\system32\logfiles", [string] $HydraAgentUri='', #Only used by Hydra [string] $HydraAgentSecret='', #Only used by Hydra [string] $DownloadNewestAgent='0' #Download the newes agent, event if a local agent exist ) function LogWriter($message) { $message="$(Get-Date ([datetime]::UtcNow) -Format "o") $message" write-host($message) if ([System.IO.Directory]::Exists($LogDir)) {try {write-output($message) | Out-File $LogFile -Append} catch {}} } function ShowDrives() { $drives = Get-WmiObject -Class win32_volume -Filter "DriveType = 3" LogWriter("Drives:") foreach ($drive in $drives) { LogWriter("Name: '$($drive.Name)', Letter: '$($drive.DriveLetter)', Label: '$($drive.Label)'") } } function ShowPageFiles() { $pageFiles = Get-WmiObject -Class Win32_PageFileSetting LogWriter("Pagefiles:") foreach ($pageFile in $pageFiles) { LogWriter("Name: '$($pageFile.Name)', Maximum size: '$($pageFile.MaximumSize)'") } } function RedirectPageFileToC() { $CurrentPageFile = Get-WmiObject -Query 'select * from Win32_PageFileSetting' LogWriter("Pagefile name: '$($CurrentPageFile.Name)', max size: $($CurrentPageFile.MaximumSize)") $CurrentPageFile.delete() LogWriter("Pagefile deleted") $CurrentPageFile = Get-WmiObject -Query 'select * from Win32_PageFileSetting' if ($null -eq $CurrentPageFile) { LogWriter("Pagefile deletion successful") } else { LogWriter("Pagefile deletion failed") } Set-WMIInstance -Class Win32_PageFileSetting -Arguments @{name='c:\pagefile.sys';InitialSize = 0; MaximumSize = 0} $CurrentPageFile = Get-WmiObject -Query 'select * from Win32_PageFileSetting' if ($null -eq $CurrentPageFile) { LogWriter("Pagefile not found") } else { LogWriter("New pagefile name: '$($CurrentPageFile.Name)', max size: $($CurrentPageFile.MaximumSize)") } } function UnzipFile ($zipfile, $outdir) { # Based on https://gist.github.com/nachivpn/3e53dd36120877d70aee Add-Type -AssemblyName System.IO.Compression.FileSystem $files = [System.IO.Compression.ZipFile]::OpenRead($zipfile) foreach ($entry in $files.Entries) { $targetPath = [System.IO.Path]::Combine($outdir, $entry.FullName) $directory = [System.IO.Path]::GetDirectoryName($targetPath) if(!(Test-Path $directory )){ New-Item -ItemType Directory -Path $directory | Out-Null } if(!$targetPath.EndsWith("/")){ [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $targetPath, $true); } } } function DownloadFile ( $url, $outFile) { $i=3 $ok=$false; do { try { LogWriter("Try to download file") Invoke-WebRequest -Uri $url -OutFile $outFile -UseBasicParsing $ok=$true } catch { $i--; if ($i -le 0) { throw } LogWriter("Re-trying download after 10 seconds") Start-Sleep -Seconds 10 } } while (!$ok) } # Define static variables $LocalConfig="C:\ITPC-WVD-PostCustomizing" $unattend="PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0ndXRmLTgnPz48dW5hdHRlbmQgeG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206dW5hdHRlbmQiPjxzZXR0aW5ncyBwYXNzPSJvb2JlU3lzdGVtIj48Y29tcG9uZW50IG5hbWU9Ik1pY3Jvc29mdC1XaW5kb3dzLVNoZWxsLVNldHVwIiBwcm9jZXNzb3JBcmNoaXRlY3R1cmU9ImFtZDY0IiBwdWJsaWNLZXlUb2tlbj0iMzFiZjM4NTZhZDM2NGUzNSIgbGFuZ3VhZ2U9Im5ldXRyYWwiIHZlcnNpb25TY29wZT0ibm9uU3hTIiB4bWxuczp3Y209Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vV01JQ29uZmlnLzIwMDIvU3RhdGUiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiPjxPT0JFPjxTa2lwTWFjaGluZU9PQkU+dHJ1ZTwvU2tpcE1hY2hpbmVPT0JFPjxTa2lwVXNlck9PQkU+dHJ1ZTwvU2tpcFVzZXJPT0JFPjwvT09CRT48L2NvbXBvbmVudD48L3NldHRpbmdzPjwvdW5hdHRlbmQ+" # Define logfile $LogFile=$LogDir+"\AVD.Customizing.log" # Main LogWriter("Starting ITPC-WVD-Image-Processing in mode ${Mode}") # Generating variables from Base64-coding if ($LocalAdminName64) {$LocalAdminName=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($LocalAdminName64))} if ($LocalAdminPassword64) {$LocalAdminPassword=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($LocalAdminPassword64))} if ($DomainJoinUserName64) {$DomainJoinUserName=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($DomainJoinUserName64))} if ($DomainJoinUserPassword64) {$DomainJoinUserPassword=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($DomainJoinUserPassword64))} # check for the existend of the helper scripts if ((Test-Path ($LocalConfig+"\ITPC-WVD-Image-Processing.ps1")) -eq $false) { # Create local directory for script(s) and copy files (including the RD agent and boot loader - rename it to the specified name) LogWriter("Copy files to local session host or downloading files from Microsoft") new-item $LocalConfig -ItemType Directory -ErrorAction Ignore try {(Get-Item $LocalConfig -ErrorAction Ignore).attributes="Hidden"} catch {} if ((Test-Path ("${PSScriptRoot}\ITPC-WVD-Image-Processing.ps1")) -eq $false) { LogWriter("Creating ITPC-WVD-Image-Processing.ps1") Copy-Item "$($MyInvocation.InvocationName)" -Destination ($LocalConfig+"\ITPC-WVD-Image-Processing.ps1") } else {Copy-Item "${PSScriptRoot}\ITPC-WVD-Image-Processing.ps1" -Destination ($LocalConfig+"\")} } if ($ComputerNewname -eq "" -or $DownloadNewestAgent -eq "1") { if ((Test-Path ($LocalConfig+"\Microsoft.RDInfra.RDAgent.msi")) -eq $false -or $DownloadNewestAgent -eq "1") { if ((Test-Path ($ScriptRoot+"\Microsoft.RDInfra.RDAgent.msi")) -eq $false -or $DownloadNewestAgent -eq "1") { LogWriter("Downloading RDAgent") DownloadFile "https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RWrmXv" ($LocalConfig+"\Microsoft.RDInfra.RDAgent.msi") #Invoke-WebRequest -Uri "https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RWrmXv" -OutFile ($LocalConfig+"\Microsoft.RDInfra.RDAgent.msi") } else {Copy-Item "${PSScriptRoot}\Microsoft.RDInfra.RDAgent.msi" -Destination ($LocalConfig+"\")} } if ((Test-Path ($LocalConfig+"\Microsoft.RDInfra.RDAgentBootLoader.msi")) -eq $false -or $DownloadNewestAgent -eq "1") { if ((Test-Path ($ScriptRoot+"\Microsoft.RDInfra.RDAgentBootLoader.msi ")) -eq $false -or $DownloadNewestAgent -eq "1") { LogWriter("Downloading RDBootloader") DownloadFile "https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RWrxrH" ($LocalConfig+"\Microsoft.RDInfra.RDAgentBootLoader.msi") #Invoke-WebRequest -Uri "https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RWrxrH" -OutFile ($LocalConfig+"\Microsoft.RDInfra.RDAgentBootLoader.msi") } else {Copy-Item "${PSScriptRoot}\Microsoft.RDInfra.RDAgentBootLoader.msi" -Destination ($LocalConfig+"\")} } } # updating local script (from maybe an older version from the last image process) Copy-Item "$($MyInvocation.InvocationName)" -Destination ($LocalConfig+"\ITPC-WVD-Image-Processing.ps1") -Force -ErrorAction SilentlyContinue # check, if secure boot is enabled (used by the snapshot workaround) $isSecureBoot=$false try { $isSecureBoot=Confirm-SecureBootUEFI } catch {} # Start script by mode if ($mode -eq "Generalize") { LogWriter("Removing existing Remote Desktop Agent Boot Loader") Uninstall-Package -Name "Remote Desktop Agent Boot Loader" -AllVersions -Force -ErrorAction SilentlyContinue LogWriter("Removing existing Remote Desktop Services Infrastructure Agent") Uninstall-Package -Name "Remote Desktop Services Infrastructure Agent" -AllVersions -Force -ErrorAction SilentlyContinue Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\RDMonitoringAgent" -Force -ErrorAction Ignore LogWriter("Disabling ITPC-LogAnalyticAgent and MySmartScale if exist") Disable-ScheduledTask -TaskName "ITPC-LogAnalyticAgent for RDS and Citrix" -ErrorAction Ignore Disable-ScheduledTask -TaskName "ITPC-MySmartScaleAgent" -ErrorAction Ignore LogWriter("Cleaning up reliability messages") $key="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Reliability" Remove-ItemProperty -Path $key -Name "DirtyShutdown" -ErrorAction Ignore Remove-ItemProperty -Path $key -Name "DirtyShutdownTime" -ErrorAction Ignore Remove-ItemProperty -Path $key -Name "LastAliveStamp" -ErrorAction Ignore Remove-ItemProperty -Path $key -Name "TimeStampInterval" -ErrorAction Ignore # Triggering dotnet to execute queued items $dotnetRoot="$env:windir\Microsoft.NET\Framework" Get-ChildItem -Path $dotnetRoot -Directory | foreach { if (Test-Path "$($_.FullName)\ngen.exe") { LogWriter("Triggering dotnet to execute queued items in: $($_.FullName)") Start-Process -FilePath "$($_.FullName)\ngen.exe" -Wait -ArgumentList "ExecuteQueuedItems" -ErrorAction SilentlyContinue } } # Read property from registry (force imaging, like dism) $force=$StrongGeneralize -eq "1" if (Test-Path -Path "HKLM:\SOFTWARE\ITProCloud\WVD.Force") { $force=$true } # DISM cleanup if ($force -and (Test-Path "$env:windir\system32\Dism.exe")) { LogWriter("DISM cleanup") Start-Process -FilePath "$env:windir\system32\Dism.exe" -Wait -ArgumentList "/online /cleanup-image /startcomponentcleanup /resetbase" -ErrorAction SilentlyContinue } LogWriter("Modifying sysprep to avoid issues with AppXPackages - Start") $sysPrepActionPath="$env:windir\System32\Sysprep\ActionFiles" $sysPrepActionFile="Generalize.xml" $sysPrepActionPathItem = Get-Item $sysPrepActionPath.Replace("C:\","\\localhost\\c$\") -ErrorAction Ignore $acl = $sysPrepActionPathItem.GetAccessControl() $acl.SetOwner((New-Object System.Security.Principal.NTAccount("SYSTEM"))) $sysPrepActionPathItem.SetAccessControl($acl) $aclSystemFull = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM","FullControl","Allow") $acl.AddAccessRule($aclSystemFull) $sysPrepActionPathItem.SetAccessControl($acl) [xml]$xml = Get-Content -Path "$sysPrepActionPath\$sysPrepActionFile" $xmlNode=$xml.sysprepInformation.imaging | where {$_.sysprepModule.moduleName -match "AppxSysprep.dll"} if ($xmlNode -ne $null) { $xmlNode.ParentNode.RemoveChild($xmlNode) $xml.sysprepInformation.imaging.Count $xml.Save("$sysPrepActionPath\$sysPrepActionFile.new") Remove-Item "$sysPrepActionPath\$sysPrepActionFile.old" -Force -ErrorAction Ignore Move-Item "$sysPrepActionPath\$sysPrepActionFile" "$sysPrepActionPath\$sysPrepActionFile.old" Move-Item "$sysPrepActionPath\$sysPrepActionFile.new" "$sysPrepActionPath\$sysPrepActionFile" LogWriter("Modifying sysprep to avoid issues with AppXPackages - Done") } # Preparation for the snapshot workaround if ($isSecureBoot -and $LocalAdminName -ne "" -and $LocalAdminPassword -ne "") { LogWriter("Creating administrator $LocalAdminName") New-LocalUser "$LocalAdminName" -Password (ConvertTo-SecureString $LocalAdminPassword -AsPlainText -Force) -FullName "$LocalAdminName" -Description "Local Administrator" -ErrorAction SilentlyContinue Add-LocalGroupMember -Group "Administrators" -Member "$LocalAdminName" -ErrorAction SilentlyContinue } LogWriter("Removing an older Sysprep state") Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\Sysprep" -Name "SysprepCorrupt" -ErrorAction Ignore New-ItemProperty -Path "HKLM:\SYSTEM\Setup\Status\SysprepStatus" -Name "State" -Value 2 -force New-ItemProperty -Path "HKLM:\SYSTEM\Setup\Status\SysprepStatus" -Name "GeneralizationState" -Value 7 -force New-Item -Path "HKLM:\Software\Microsoft\DesiredStateConfiguration" -ErrorAction Ignore New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\DesiredStateConfiguration" -Name "AgentId" -Value "" -force -ErrorAction Ignore LogWriter("Saving time zone info for re-deploy") $timeZone=(Get-TimeZone).Id LogWriter("Current time zone is: "+$timeZone) New-Item -Path "HKLM:\SOFTWARE" -Name "ITProCloud" -ErrorAction Ignore New-Item -Path "HKLM:\SOFTWARE\ITProCloud" -Name "WVD.Runtime" -ErrorAction Ignore New-ItemProperty -Path "HKLM:\SOFTWARE\ITProCloud\WVD.Runtime" -Name "TimeZone.Origin" -Value $timeZone -force LogWriter("Removing existing Azure Monitoring Certificates") Get-ChildItem "Cert:\LocalMachine\Microsoft Monitoring Agent" -ErrorAction Ignore | Remove-Item # Check, if the optimization script exist (Hydra: use a script inside Hydra) if ([System.IO.File]::Exists("C:\ProgramData\Optimize\Win10_VirtualDesktop_Optimize.ps1")) { LogWriter("Running VDI Optimization script") Start-Process -wait -FilePath PowerShell.exe -WorkingDirectory "C:\ProgramData\Optimize" -ArgumentList '-ExecutionPolicy Bypass -File "C:\ProgramData\Optimize\Win10_VirtualDesktop_Optimize.ps1 -AcceptEULA -Optimizations WindowsMediaPlayer,AppxPackages,ScheduledTasks,DefaultUserSettings,Autologgers,Services,NetworkOptimizations"' -RedirectStandardOutput "$($LogDir)\VirtualDesktop_Optimize.Stage1.Out.txt" -RedirectStandardError "$($LogDir)\VirtualDesktop_Optimize.Stage1.Warning.txt" } # prepare cleanup task for new deployed VMs - solve an issue with the runcommand api giving older log data LogWriter("Preparing CleanFirstStart task") $action = New-ScheduledTaskAction -Execute "$env:windir\System32\WindowsPowerShell\v1.0\Powershell.exe" -Argument "-executionPolicy Unrestricted -File `"$LocalConfig\ITPC-WVD-Image-Processing.ps1`" -Mode `"CleanFirstStart`"" $trigger = New-ScheduledTaskTrigger -AtStartup $principal = New-ScheduledTaskPrincipal 'NT Authority\SYSTEM' -RunLevel Highest $settingsSet = New-ScheduledTaskSettingsSet $task = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settingsSet Register-ScheduledTask -TaskName 'ITPC-AVD-CleanFirstStart-Helper' -InputObject $task -ErrorAction Ignore Enable-ScheduledTask -TaskName 'ITPC-AVD-CleanFirstStart-Helper' LogWriter("Added new startup task to run the CleanFirstStart") # check if D:-drive not the temporary storage and having three drives $modifyDrives=$false $disks=Get-WmiObject -Class win32_volume | Where-Object { $_.DriveLetter -ne $null -and $_.DriveType -eq 3 } foreach ($disk in $disks) {if ($disk.Name -ne 'D:\' -and $disk.Label -eq 'Temporary Storage') {$modifyDrives=$true}} if ($disks.Count -eq 3 -and $modifyDrives) { LogWriter("VM with 3 drives so prepare change of drive letters of temp and data after deployment") New-ItemProperty -Path "HKLM:\SOFTWARE\ITProCloud\WVD.Runtime" -Name "ChangeDrives" -Value 1 -force # check if default value 'automatic manage pagefile size for all devices' is activated if ($null -eq (Get-WmiObject Win32_Pagefile) ) { # disable 'automatic manage pagefile size for all devices' $sys = Get-WmiObject Win32_Computersystem -EnableAllPrivileges $sys.AutomaticManagedPagefile = $false $sys.put() LogWriter("Automatic manage pagefile size for all devices deactivated") } else { LogWriter("Automatic manage pagefile size for all devices not activated") } # redirect pagefile to C: to rename data partition after deployment RedirectPageFileToC } LogWriter("Starting sysprep to generalize session host") if ([System.Environment]::OSVersion.Version.Major -le 6) { #Windows 7 LogWriter("Enabling RDP8 on Windows 7") New-Item -Path "HKLM:\SOFTWARE" -Name "Policies" -ErrorAction Ignore New-Item -Path "HKLM:\SOFTWARE\Policies" -Name "Microsoft" -ErrorAction Ignore New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft" -Name "Windows NT" -ErrorAction Ignore New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT" -Name "Terminal Services" -ErrorAction Ignore New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" -Name "fServerEnableRDP8" -Value 1 -force Start-Process -FilePath "$env:windir\System32\Sysprep\sysprep" -ArgumentList "/generalize /oobe /shutdown" } else { if ($isSecureBoot) { LogWriter("Secure boot is enabled") write-output([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($unattend))) | Out-File "$LocalConfig\unattend.xml" -Encoding ASCII write-output([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($unattend))) | Out-File "$env:windir\panther\unattend.xml" -Encoding ASCII Start-Process -FilePath "$env:windir\System32\Sysprep\sysprep" -ArgumentList "/generalize /oobe /shutdown /mode:vm /unattend:$LocalConfig\unattend.xml" } else { Start-Process -FilePath "$env:windir\System32\Sysprep\sysprep" -ArgumentList "/generalize /oobe /shutdown /mode:vm" } } } elseif ($mode -eq "RenameComputer") { # Used for the snapshot workaround LogWriter("Renaming computer to: "+$readComputerNewname) Rename-Computer -NewName $ComputerNewname -Force -ErrorAction SilentlyContinue } elseif ($mode -eq "JoinDomain") { # Removing existing agent if exist LogWriter("Removing existing Remote Desktop Agent Boot Loader") Uninstall-Package -Name "Remote Desktop Agent Boot Loader" -AllVersions -Force -ErrorAction SilentlyContinue LogWriter("Removing existing Remote Desktop Services Infrastructure Agent") Uninstall-Package -Name "Remote Desktop Services Infrastructure Agent" -AllVersions -Force -ErrorAction SilentlyContinue Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\RDMonitoringAgent" -Force -ErrorAction Ignore # Storing AadOnly to registry LogWriter("Storing AadOnly to registry: "+$AadOnly) New-Item -Path "HKLM:\SOFTWARE" -Name "ITProCloud" -ErrorAction Ignore New-Item -Path "HKLM:\SOFTWARE\ITProCloud" -Name "WVD.Runtime" -ErrorAction Ignore New-ItemProperty -Path "HKLM:\SOFTWARE\ITProCloud\WVD.Runtime" -Name "AadOnly" -Value $AadOnly -force # Checking for a saved time zone information if (Test-Path -Path "HKLM:\SOFTWARE\ITProCloud\WVD.Runtime") { $timeZone=(Get-ItemProperty -Path "HKLM:\SOFTWARE\ITProCloud\WVD.Runtime" -ErrorAction Ignore)."TimeZone.Origin" if ($timeZone -ne "" -and $timeZone -ne $null) { LogWriter("Setting time zone to: "+$timeZone) Set-TimeZone -Id $timeZone } } # AD / AAD handling LogWriter("Cleaning up previous AADLoginExtension / AAD join") Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows Azure\CurrentVersion\AADLoginForWindowsExtension" -Force -ErrorAction Ignore if (Test-Path -Path "$($env:WinDir)\system32\Dsregcmd.exe") { Start-Process -wait -FilePath "$($env:WinDir)\system32\Dsregcmd.exe" -ArgumentList "/leave" -ErrorAction SilentlyContinue } if ($DomainJoinUserName -ne "" -and $AadOnly -ne "1") { LogWriter("Joining AD domain") $psc = New-Object System.Management.Automation.PSCredential($DomainJoinUserName, (ConvertTo-SecureString $DomainJoinUserPassword -AsPlainText -Force)) $retry=3 $ok=$false do{ try { if ($DomainJoinOU -eq "") { Add-Computer -DomainName $DomainFqdn -Credential $psc -Force -ErrorAction Stop $ok=$true LogWriter("Domain joined successfully") } else { Add-Computer -DomainName $DomainFqdn -OUPath $DomainJoinOU -Credential $psc -Force -ErrorAction Stop $ok=$true LogWriter("Domain joined successfully") } } catch { if ($retry -eq 0) {throw $_} $retry-- LogWriter("Retry domain join because of an error: $_") Start-Sleep -Seconds 10 } } while($ok -ne $true) } else { LogWriter("AAD only is selected. Skipping joining to a native AD, joining AAD") $aadPath=@(Get-ChildItem -Directory "C:\Packages\Plugins\Microsoft.Azure.ActiveDirectory.AADLoginForWindows")[@(Get-ChildItem -Directory "C:\Packages\Plugins\Microsoft.Azure.ActiveDirectory.AADLoginForWindows").count-1].fullname Start-Process -wait -FilePath "$aadPath\AADLoginForWindowsHandler.exe" -WorkingDirectory $aadPath -ArgumentList 'enable' -RedirectStandardOutput "$($LogDir)\Avd.AadJoin.Out.txt" -RedirectStandardError "$($LogDir)\Avd.AadJoin.Warning.txt" if ($JoinMem -eq "1") { LogWriter("Joining Microsoft Endpoint Manamgement is selected. Try to register to MEM") Start-Process -wait -FilePath "$($env:WinDir)\system32\Dsregcmd.exe" -ArgumentList "/AzureSecureVMJoin /debug /MdmId 0000000a-0000-0000-c000-000000000000" -RedirectStandardOutput "$($LogDir)\Avd.MemJoin.Out.txt" -RedirectStandardError "$($LogDir)\Avd.MemJoin.Warning.txt" } try { if ($AadOnly) { $timeOut=(Get-Date).AddSeconds(5*60) do { LogWriter("Waiting for the domain join") Start-Sleep -Seconds 3#AzureAdJoined : YES } while ((Get-Date) -le $timeOut -and (Select-String -InputObject (&dsregcmd /status) -pattern "AzureAdJoined : YES").length -eq 0) } } catch {} } # check for disk handling $modifyDrives=$false if (Test-Path -Path "HKLM:\SOFTWARE\ITProCloud\WVD.Runtime") { if ((Get-ItemProperty -Path "HKLM:\SOFTWARE\ITProCloud\WVD.Runtime").ChangeDrives -eq 1) { $disks=Get-WmiObject -Class win32_volume | Where-Object { $_.DriveLetter -ne $null -and $_.DriveType -eq 3 } foreach ($disk in $disks) {if ($disk.Name -eq 'D:\' -and $disk.Label -eq 'Temporary Storage') {$modifyDrives=$true}} if ($modifyDrives -and $disks.Count -eq 3) { # change drive letters of temp and data drive for VMs with 3 drives LogWriter("VM with 3 drives so delete old pagefile and install runonce key") # create scheduled task executed at startup for next phase $action = New-ScheduledTaskAction -Execute "$env:windir\System32\WindowsPowerShell\v1.0\Powershell.exe" -Argument "-executionPolicy Unrestricted -File `"$LocalConfig\ITPC-WVD-Image-Processing.ps1`" -Mode `"DataPartition`"" $trigger = New-ScheduledTaskTrigger -AtStartup $principal = New-ScheduledTaskPrincipal 'NT Authority\SYSTEM' -RunLevel Highest $settingsSet = New-ScheduledTaskSettingsSet $task = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settingsSet Register-ScheduledTask -TaskName 'ITPC-AVD-Disk-Mover-Helper' -InputObject $task -ErrorAction Ignore Enable-ScheduledTask -TaskName 'ITPC-AVD-Disk-Mover-Helper' LogWriter("Added new startup task for the disk handling") # change c:\pagefile.sys to e:\pagefile.sys ShowPageFiles $CurrentPageFile = Get-WmiObject -Query 'select * from Win32_PageFileSetting' if ($null -eq $CurrentPageFile) { LogWriter("No pagefile found") } else { if ($CurrentPageFile.Name.tolower().contains('d:')) { $CurrentPageFile.delete() LogWriter("Old pagefile deleted") Set-WMIInstance -Class Win32_PageFileSetting -Arguments @{name='c:\pagefile.sys';InitialSize = 0; MaximumSize = 0} LogWriter("Set pagefile to c:\pagefile.sys") ShowPageFiles } } ShowPageFiles } } } # check to move pagefile finally to C if ($MovePagefileToC -eq "1") { RedirectPageFileToC } # install Hydra Agent (Hydra only) if ($HydraAgentUri -ne "") { $uri=$HydraAgentUri $secret=$HydraAgentSecret $DownloadAdress="https://$($uri)/Download/HydraAgent" try { if ((Test-Path ("$env:ProgramFiles\ITProCloud.de")) -eq $false) { new-item "$env:ProgramFiles\ITProCloud.de" -ItemType Directory -ErrorAction Ignore } if ((Test-Path ("$env:ProgramFiles\ITProCloud.de\HydraAgent")) -eq $false) { new-item "$env:ProgramFiles\ITProCloud.de\HydraAgent" -ItemType Directory -ErrorAction Ignore } Remove-Item -Path "$env:ProgramFiles\ITProCloud.de\HydraAgent\HydraAgent.zip" -Force -ErrorAction Ignore LogWriter("Downloading HydraAgent.zip from $DownloadAdress") DownloadFile $DownloadAdress "$env:ProgramFiles\ITProCloud.de\HydraAgent\HydraAgent.zip" #Invoke-WebRequest -Uri $DownloadAdress -OutFile "$env:ProgramFiles\ITProCloud.de\HydraAgent\HydraAgent.zip" -UseBasicParsing # Stop a running instance LogWriter("Stop a running instance") Stop-ScheduledTask -TaskName 'ITPC-AVD-Hydra-Helper' -ErrorAction Ignore Stop-Process -Name HydraAgent -Force -ErrorAction Ignore Start-Sleep -Seconds 6 UnzipFile "$env:ProgramFiles\ITProCloud.de\HydraAgent\HydraAgent.zip" "$env:ProgramFiles\ITProCloud.de\HydraAgent" # Configuring the agent LogWriter("Configuring the agent") cd "$env:ProgramFiles\ITProCloud.de\HydraAgent" . "$env:ProgramFiles\ITProCloud.de\HydraAgent\HydraAgent.exe" -i -u "wss://$($uri)/wsx" -s $secret } catch { LogWriter("An error occurred while installing Hydra Agent: $_") } } # install AVD Agent if a registration key given if ($WvdRegistrationKey -ne "") { if ([System.Environment]::OSVersion.Version.Major -gt 6) { LogWriter("Installing AVD agent") Start-Process -wait -FilePath "${LocalConfig}\Microsoft.RDInfra.RDAgent.msi" -ArgumentList "/quiet /qn /norestart /passive RegistrationToken=${WvdRegistrationKey}" if ($false) { LogWriter("Installing AVD boot loader - current path is ${LocalConfig}") Start-Process -wait -FilePath "${LocalConfig}\Microsoft.RDInfra.RDAgentBootLoader.msi" -ArgumentList "/quiet /qn /norestart /passive" LogWriter("Waiting for the service RDAgentBootLoader") $bootloaderServiceName = "RDAgentBootLoader" $retryCount = 0 while ( -not (Get-Service "RDAgentBootLoader" -ErrorAction SilentlyContinue)) { $retry = ($retryCount -lt 6) LogWriter("Service RDAgentBootLoader was not found") if ($retry) { LogWriter("Retrying again in 30 seconds, this will be retry $retryCount") } else { LogWriter("Retry limit exceeded" ) throw "RDAgentBootLoader didn't become available after 6 retries" } $retryCount++ Start-Sleep -Seconds 30 } } else { LogWriter("Preparing AVD boot loader task") $action = New-ScheduledTaskAction -Execute "$env:windir\System32\WindowsPowerShell\v1.0\Powershell.exe" -Argument "-executionPolicy Unrestricted -File `"$LocalConfig\ITPC-WVD-Image-Processing.ps1`" -Mode `"RDAgentBootloader`"" $trigger = New-ScheduledTaskTrigger -AtStartup $principal = New-ScheduledTaskPrincipal 'NT Authority\SYSTEM' -RunLevel Highest $settingsSet = New-ScheduledTaskSettingsSet $task = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settingsSet Register-ScheduledTask -TaskName 'ITPC-AVD-RDAgentBootloader-Helper' -InputObject $task -ErrorAction Ignore Enable-ScheduledTask -TaskName 'ITPC-AVD-RDAgentBootloader-Helper' LogWriter("Added new startup task to run the RDAgentBootloader") $class = cimclass MSFT_TaskEventTrigger root/Microsoft/Windows/TaskScheduler $triggerM = $class | New-CimInstance -ClientOnly $triggerM.Enabled = $true $triggerM.Subscription='' $actionM = New-ScheduledTaskAction -Execute "$env:windir\System32\WindowsPowerShell\v1.0\Powershell.exe" -Argument "-executionPolicy Unrestricted -File `"$LocalConfig\ITPC-WVD-Image-Processing.ps1`" -Mode `"RestartBootloader`"" $settingsM = New-ScheduledTaskSettingsSet $taskM = New-ScheduledTask -Action $actionM -Principal $principal -Trigger $triggerM -Settings $settingsM -Description "Restarts the bootloader in case of an known issue (timeout, download error) while installing the RDagent" Register-ScheduledTask -TaskName 'ITPC-AVD-RDAgentBootloader-Monitor-1' -InputObject $taskM -ErrorAction Ignore Enable-ScheduledTask -TaskName 'ITPC-AVD-RDAgentBootloader-Monitor-1' -ErrorAction Ignore LogWriter("Added new task to monitor the RDAgentBootloader") } } else { if ((Test-Path "${LocalConfig}\Microsoft.RDInfra.WVDAgent.msi") -eq $false) { LogWriter("Downloading Microsoft.RDInfra.WVDAgent.msi") DownloadFile "https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE3JZCm" "${LocalConfig}\Microsoft.RDInfra.WVDAgent.msi" #Invoke-WebRequest -Uri 'https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE3JZCm' -OutFile "${LocalConfig}\Microsoft.RDInfra.WVDAgent.msi" -UseBasicParsing } if ((Test-Path "${LocalConfig}\Microsoft.RDInfra.WVDAgentManager.msi") -eq $false) { LogWriter("Downloading Microsoft.RDInfra.WVDAgentManager.msi") DownloadFile "https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE3K2e3" "${LocalConfig}\Microsoft.RDInfra.WVDAgentManager.msi" #nvoke-WebRequest -Uri 'https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE3K2e3' -OutFile "${LocalConfig}\Microsoft.RDInfra.WVDAgentManager.msi" -UseBasicParsing } LogWriter("Installing AVDAgent") Start-Process -wait -FilePath "${LocalConfig}\Microsoft.RDInfra.WVDAgent.msi" -ArgumentList "/q RegistrationToken=${WvdRegistrationKey}" LogWriter("Installing AVDAgentManager") Start-Process -wait -FilePath "${LocalConfig}\Microsoft.RDInfra.WVDAgentManager.msi" -ArgumentList '/q' } } LogWriter("Enabling ITPC-LogAnalyticAgent and MySmartScale if exist") Enable-ScheduledTask -TaskName "ITPC-LogAnalyticAgent for RDS and Citrix" -ErrorAction Ignore Enable-ScheduledTask -TaskName "ITPC-MySmartScaleAgent" -ErrorAction Ignore if ([System.IO.File]::Exists("C:\ProgramData\Optimize\Win10_VirtualDesktop_Optimize.ps1")) { LogWriter("Running VDI Optimization script") Start-Process -wait -FilePath PowerShell.exe -WorkingDirectory "C:\ProgramData\Optimize" -ArgumentList '-ExecutionPolicy Bypass -File "C:\ProgramData\Optimize\Win10_VirtualDesktop_Optimize.ps1 -AcceptEULA -Optimizations WindowsMediaPlayer,AppxPackages,ScheduledTasks,DefaultUserSettings,Autologgers,Services,NetworkOptimizations"' -RedirectStandardOutput "$($LogDir)\VirtualDesktop_Optimize.Stage2.Out.txt" -RedirectStandardError "$($LogDir)\VirtualDesktop_Optimize.Stage2.Warning.txt" } # Final reboot LogWriter("Finally restarting session host") Restart-Computer -Force -ErrorAction SilentlyContinue } elseif ($Mode -eq "DataPartition") { if ((Get-WmiObject -Class win32_volume | Where-Object { $_.DriveLetter -ne $null -and $_.DriveType -eq 3 }).Count -eq 3) { # change drive letters of temp and data drive for VMs with 3 drives LogWriter("VM with 3 drives so change drive letters of temp and data") ShowDrives # change c:\pagefile.sys to e:\pagefile.sys ShowPageFiles $CurrentPageFile = Get-WmiObject -Query 'select * from Win32_PageFileSetting' if ($null -eq $CurrentPageFile) { LogWriter("No pagefile found") } else { if ($CurrentPageFile.Name.tolower().contains('c:')) { ShowDrives # change temp drive to Z: $drive = Get-WmiObject -Class win32_volume -Filter "DriveLetter = 'd:'" if ($null -ne $drive) { LogWriter("d: drive: $($drive.Label)") Set-WmiInstance -input $drive -Arguments @{ DriveLetter='z:' } LogWriter("changed drive letter to z:") ShowDrives } else { LogWriter("Drive D: not found") } # change data drive to D: $drive = Get-WmiObject -Class win32_volume -Filter "DriveLetter = 'e:'" if ($null -ne $drive) { LogWriter("e: drive: $($drive.Label)") Set-WmiInstance -input $drive -Arguments @{ DriveLetter='D:' } LogWriter("changed drive letter to D:") ShowDrives } else { LogWriter("Drive E: not found") } # change temp drive back to E: $drive = Get-WmiObject -Class win32_volume -Filter "DriveLetter = 'z:'" if ($null -ne $drive) { LogWriter("z: drive: $($drive.Label)") Set-WmiInstance -input $drive -Arguments @{ DriveLetter='E:' } LogWriter("changed drive letter to E:") ShowDrives } else { LogWriter("Drive Z: not found") } # change c:\pagefile.sys to e:\pagefile.sys ShowPageFiles $CurrentPageFile = Get-WmiObject -Query 'select * from Win32_PageFileSetting' if ($null -eq $CurrentPageFile) { LogWriter("No pagefile found") } else { $CurrentPageFile.delete() LogWriter("Old pagefile deleted") } ShowPageFiles Set-WMIInstance -Class Win32_PageFileSetting -Arguments @{name='e:\pagefile.sys';InitialSize = 0; MaximumSize = 0} LogWriter("set pagefile to e:\pagefile.sys") ShowPageFiles # reboot to activate pagefile LogWriter("Finally restarting session host") Restart-Computer -Force LogWriter("After Finally restarting session host") } } } LogWriter("Disable scheduled task") try { # disable startup scheduled task Disable-ScheduledTask -TaskName 'ITPC-AVD-Disk-Mover-Helper' } catch { LogWriter("Disabling scheduled task failed: " + $_.Exception.Message) } } elseif ($Mode -eq "RDAgentBootloader") { LogWriter("Installing AVD boot loader - current path is ${LocalConfig}") Start-Process -wait -FilePath "${LocalConfig}\Microsoft.RDInfra.RDAgentBootLoader.msi" -ArgumentList "/quiet /qn /norestart /passive" LogWriter("Waiting for the service RDAgentBootLoader") $bootloaderServiceName = "RDAgentBootLoader" $retryCount = 0 while ( -not (Get-Service "RDAgentBootLoader" -ErrorAction SilentlyContinue)) { $retry = ($retryCount -lt 6) LogWriter("Service RDAgentBootLoader was not found") if ($retry) { LogWriter("Retrying again in 30 seconds, this will be retry $retryCount") } else { LogWriter("Retry limit exceeded" ) throw "RDAgentBootLoader didn't become available after 6 retries" } $retryCount++ Start-Sleep -Seconds 30 } LogWriter("Disable scheduled task") try { # disable startup scheduled task Disable-ScheduledTask -TaskName 'ITPC-AVD-RDAgentBootloader-Helper' } catch { LogWriter("Disabling scheduled task failed: " + $_.Exception.Message) } } elseif ($Mode -eq "CleanFirstStart") { LogWriter("Cleaning up Azure Agent logs - current path is ${LocalConfig}") Remove-Item -Path "C:\Packages\Plugins\Microsoft.CPlat.Core.RunCommandWindows\*" -Include *.status -Recurse -Force -ErrorAction SilentlyContinue LogWriter("Disable scheduled task") try { # disable startup scheduled task Disable-ScheduledTask -TaskName 'ITPC-AVD-CleanFirstStart-Helper' } catch { LogWriter("Disabling scheduled task failed: " + $_.Exception.Message) } } elseif ($mode -eq "RestartBootloader") { $LogFile=$LogDir+"\AVD.AgentBootloaderErrorHandling.log" LogWriter "Stopping service" Stop-Service -Name "RDAgentBootLoader" LogWriter "Starting service" Start-Service -Name "RDAgentBootLoader" } elseif ($mode -eq "StartBootloader") { $LogFile=$LogDir+"\AVD.AgentBootloaderErrorHandling.log" LogWriter "Start service was triggered by an event" LogWriter "Waiting for 5 seconds" Start-Sleep -Seconds 5 LogWriter "Starting service" Start-Service -Name "RDAgentBootLoader" LogWriter "Waiting for 60 seconds" Start-Sleep -Seconds 60 LogWriter "Starting service (if not running)" Start-Service -Name "RDAgentBootLoader" LogWriter "Waiting for 60 seconds" Start-Sleep -Seconds 60 LogWriter "Starting service (if not running)" Start-Service -Name "RDAgentBootLoader" } # SIG # Begin signature block # MIIoqAYJKoZIhvcNAQcCoIIomTCCKJUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU4qJrUnQJN2ErhFHujsk5VW1I # XQyggiHbMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGtDCCBJyg # AwIBAgIQDcesVwX/IZkuQEMiDDpJhjANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQG # EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl # cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjUw # NTA3MDAwMDAwWhcNMzgwMTE0MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UE # ChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQg # VGltZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUgQ0ExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAtHgx0wqYQXK+PEbAHKx126NGaHS0URedTa2N # DZS1mZaDLFTtQ2oRjzUXMmxCqvkbsDpz4aH+qbxeLho8I6jY3xL1IusLopuW2qft # JYJaDNs1+JH7Z+QdSKWM06qchUP+AbdJgMQB3h2DZ0Mal5kYp77jYMVQXSZH++0t # rj6Ao+xh/AS7sQRuQL37QXbDhAktVJMQbzIBHYJBYgzWIjk8eDrYhXDEpKk7RdoX # 0M980EpLtlrNyHw0Xm+nt5pnYJU3Gmq6bNMI1I7Gb5IBZK4ivbVCiZv7PNBYqHEp # NVWC2ZQ8BbfnFRQVESYOszFI2Wv82wnJRfN20VRS3hpLgIR4hjzL0hpoYGk81coW # J+KdPvMvaB0WkE/2qHxJ0ucS638ZxqU14lDnki7CcoKCz6eum5A19WZQHkqUJfdk # DjHkccpL6uoG8pbF0LJAQQZxst7VvwDDjAmSFTUms+wV/FbWBqi7fTJnjq3hj0Xb # Qcd8hjj/q8d6ylgxCZSKi17yVp2NL+cnT6Toy+rN+nM8M7LnLqCrO2JP3oW//1sf # uZDKiDEb1AQ8es9Xr/u6bDTnYCTKIsDq1BtmXUqEG1NqzJKS4kOmxkYp2WyODi7v # QTCBZtVFJfVZ3j7OgWmnhFr4yUozZtqgPrHRVHhGNKlYzyjlroPxul+bgIspzOwb # tmsgY1MCAwEAAaOCAV0wggFZMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE # FO9vU0rp5AZ8esrikFb2L9RJ7MtOMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/n # upiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB3Bggr # BgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNv # bTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lD # ZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2Ny # bDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0g # BBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQAX # zvsWgBz+Bz0RdnEwvb4LyLU0pn/N0IfFiBowf0/Dm1wGc/Do7oVMY2mhXZXjDNJQ # a8j00DNqhCT3t+s8G0iP5kvN2n7Jd2E4/iEIUBO41P5F448rSYJ59Ib61eoalhnd # 6ywFLerycvZTAz40y8S4F3/a+Z1jEMK/DMm/axFSgoR8n6c3nuZB9BfBwAQYK9FH # aoq2e26MHvVY9gCDA/JYsq7pGdogP8HRtrYfctSLANEBfHU16r3J05qX3kId+ZOc # zgj5kjatVB+NdADVZKON/gnZruMvNYY2o1f4MXRJDMdTSlOLh0HCn2cQLwQCqjFb # qrXuvTPSegOOzr4EWj7PtspIHBldNE2K9i697cvaiIo2p61Ed2p8xMJb82Yosn0z # 4y25xUbI7GIN/TpVfHIqQ6Ku/qjTY6hc3hsXMrS+U0yy+GWqAXam4ToWd2UQ1KYT # 70kZjE4YtL8Pbzg0c1ugMZyZZd/BdHLiRu7hAWE6bTEm4XYRkA6Tl4KSFLFk43es # aUeqGkH/wyW4N7OigizwJWeukcyIPbAvjSabnf7+Pu0VrFgoiovRDiyx3zEdmcif # /sYQsfch28bZeUz2rtY/9TCA6TD8dC3JE3rYkrhLULy7Dc90G6e8BlqmyIjlgp2+ # VqsS9/wQD7yFylIz0scmbKvFoW2jNrbM1pD2T7m3XDCCBugwggTQoAMCAQICEHe9 # DgW3WQu2HUdhUx4/de0wDQYJKoZIhvcNAQELBQAwUzELMAkGA1UEBhMCQkUxGTAX # BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExKTAnBgNVBAMTIEdsb2JhbFNpZ24gQ29k # ZSBTaWduaW5nIFJvb3QgUjQ1MB4XDTIwMDcyODAwMDAwMFoXDTMwMDcyODAwMDAw # MFowXDELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExMjAw # BgNVBAMTKUdsb2JhbFNpZ24gR0NDIFI0NSBFViBDb2RlU2lnbmluZyBDQSAyMDIw # MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyyDvlx65ATJDoFupiiP9 # IF6uOBKLyizU/0HYGlXUGVO3/aMX53o5XMD3zhGj+aXtAfq1upPvr5Pc+OKzGUyD # sEpEUAR4hBBqpNaWkI6B+HyrL7WjVzPSWHuUDm0PpZEmKrODT3KxintkktDwtFVf # lgsR5Zq1LLIRzyUbfVErmB9Jo1/4E541uAMC2qQTL4VK78QvcA7B1MwzEuy9QJXT # EcrmzbMFnMhT61LXeExRAZKC3hPzB450uoSAn9KkFQ7or+v3ifbfcfDRvqeyQTMg # dcyx1e0dBxnE6yZ38qttF5NJqbfmw5CcxrjszMl7ml7FxSSTY29+EIthz5hVoySi # iDby+Z++ky6yBp8mwAwBVhLhsoqfDh7cmIsuz9riiTSmHyagqK54beyhiBU8wuru # t9itYaWvcDaieY7cDXPA8eQsq5TsWAY5NkjWO1roIs50Dq8s8RXa0bSV6KzVSW3l # r92ba2MgXY5+O7JD2GI6lOXNtJizNxkkEnJzqwSwCdyF5tQiBO9AKh0ubcdp0263 # AWwN4JenFuYmi4j3A0SGX2JnTLWnN6hV3AM2jG7PbTYm8Q6PsD1xwOEyp4LktjIC # MjB8tZPIIf08iOZpY/judcmLwqvvujr96V6/thHxvvA9yjI+bn3eD36blcQSh+ca # uE7uLMHfoWXoJIPJKsL9uVMCAwEAAaOCAa0wggGpMA4GA1UdDwEB/wQEAwIBhjAT # BgNVHSUEDDAKBggrBgEFBQcDAzASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW # BBQlndD8WQmGY8Xs87ETO1ccA5I2ETAfBgNVHSMEGDAWgBQfAL9GgAr8eDm3pbRD # 2VZQu86WOzCBkwYIKwYBBQUHAQEEgYYwgYMwOQYIKwYBBQUHMAGGLWh0dHA6Ly9v # Y3NwLmdsb2JhbHNpZ24uY29tL2NvZGVzaWduaW5ncm9vdHI0NTBGBggrBgEFBQcw # AoY6aHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNvbS9jYWNlcnQvY29kZXNpZ25p # bmdyb290cjQ1LmNydDBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8vY3JsLmdsb2Jh # bHNpZ24uY29tL2NvZGVzaWduaW5ncm9vdHI0NS5jcmwwVQYDVR0gBE4wTDBBBgkr # BgEEAaAyAQIwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5j # b20vcmVwb3NpdG9yeS8wBwYFZ4EMAQMwDQYJKoZIhvcNAQELBQADggIBACV1oAnJ # Obq3oTmJLxifq9brHUvolHwNB2ibHJ3vcbYXamsCT7M/hkWHzGWbTONYBgIiZtVh # AsVjj9Si8bZeJQt3lunNcUAziCns7vOibbxNtT4GS8lzM8oIFC09TOiwunWmdC2k # WDpsE0n4pRUKFJaFsWpoNCVCr5ZW9BD6JH3xK3LBFuFr6+apmMc+WvTQGJ39dJeG # d0YqPSN9KHOKru8rG5q/bFOnFJ48h3HAXo7I+9MqkjPqV01eB17KwRisgS0aIfpu # z5dhe99xejrKY/fVMEQ3Mv67Q4XcuvymyjMZK3dt28sF8H5fdS6itr81qjZjyc5k # 2b38vCzzSVYAyBIrxie7N69X78TPHinE9OItziphz1ft9QpA4vUY1h7pkC/K04df # k4pIGhEd5TeFny5mYppegU6VrFVXQ9xTiyV+PGEPigu69T+m1473BFZeIbuf12px # gL+W3nID2NgiK/MnFk846FFADK6S7749ffeAxkw2V4SVp4QVSDAOUicIjY6ivSLH # Gcmmyg6oejbbarphXxEklaTijmjuGalJmV7QtDS91vlAxxCXMVI5NSkRhyTTxPup # Y8t3SNX6Yvwk4AR6TtDkbt7OnjhQJvQhcWXXCSXUyQcAerjH83foxdTiVdDTHvZ/ # UuJJjbkRcgyIRCYzZgFE3+QzDiHeYolIB9r1MIIG7TCCBNWgAwIBAgIQCoDvGEuN # 8QWC0cR2p5V0aDANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJVUzEXMBUGA1UE # ChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQg # VGltZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUgQ0ExMB4XDTI1MDYwNDAw # MDAwMFoXDTM2MDkwMzIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRp # Z2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBTSEEyNTYgUlNBNDA5NiBU # aW1lc3RhbXAgUmVzcG9uZGVyIDIwMjUgMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP # ADCCAgoCggIBANBGrC0Sxp7Q6q5gVrMrV7pvUf+GcAoB38o3zBlCMGMyqJnfFNZx # +wvA69HFTBdwbHwBSOeLpvPnZ8ZN+vo8dE2/pPvOx/Vj8TchTySA2R4QKpVD7dvN # Zh6wW2R6kSu9RJt/4QhguSssp3qome7MrxVyfQO9sMx6ZAWjFDYOzDi8SOhPUWlL # nh00Cll8pjrUcCV3K3E0zz09ldQ//nBZZREr4h/GI6Dxb2UoyrN0ijtUDVHRXdmn # cOOMA3CoB/iUSROUINDT98oksouTMYFOnHoRh6+86Ltc5zjPKHW5KqCvpSduSwhw # UmotuQhcg9tw2YD3w6ySSSu+3qU8DD+nigNJFmt6LAHvH3KSuNLoZLc1Hf2JNMVL # 4Q1OpbybpMe46YceNA0LfNsnqcnpJeItK/DhKbPxTTuGoX7wJNdoRORVbPR1VVnD # uSeHVZlc4seAO+6d2sC26/PQPdP51ho1zBp+xUIZkpSFA8vWdoUoHLWnqWU3dCCy # FG1roSrgHjSHlq8xymLnjCbSLZ49kPmk8iyyizNDIXj//cOgrY7rlRyTlaCCfw7a # SUROwnu7zER6EaJ+AliL7ojTdS5PWPsWeupWs7NpChUk555K096V1hE0yZIXe+gi # AwW00aHzrDchIc2bQhpp0IoKRR7YufAkprxMiXAJQ1XCmnCfgPf8+3mnAgMBAAGj # ggGVMIIBkTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTkO/zyMe39/dfzkXFjGVBD # z2GM6DAfBgNVHSMEGDAWgBTvb1NK6eQGfHrK4pBW9i/USezLTjAOBgNVHQ8BAf8E # BAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwgZUGCCsGAQUFBwEBBIGIMIGF # MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXQYIKwYBBQUH # MAKGUWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRH # NFRpbWVTdGFtcGluZ1JTQTQwOTZTSEEyNTYyMDI1Q0ExLmNydDBfBgNVHR8EWDBW # MFSgUqBQhk5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVk # RzRUaW1lU3RhbXBpbmdSU0E0MDk2U0hBMjU2MjAyNUNBMS5jcmwwIAYDVR0gBBkw # FzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQBlKq3x # HCcEua5gQezRCESeY0ByIfjk9iJP2zWLpQq1b4URGnwWBdEZD9gBq9fNaNmFj6Eh # 8/YmRDfxT7C0k8FUFqNh+tshgb4O6Lgjg8K8elC4+oWCqnU/ML9lFfim8/9yJmZS # e2F8AQ/UdKFOtj7YMTmqPO9mzskgiC3QYIUP2S3HQvHG1FDu+WUqW4daIqToXFE/ # JQ/EABgfZXLWU0ziTN6R3ygQBHMUBaB5bdrPbF6MRYs03h4obEMnxYOX8VBRKe1u # NnzQVTeLni2nHkX/QqvXnNb+YkDFkxUGtMTaiLR9wjxUxu2hECZpqyU1d0IbX6Wq # 8/gVutDojBIFeRlqAcuEVT0cKsb+zJNEsuEB7O7/cuvTQasnM9AWcIQfVjnzrvwi # CZ85EE8LUkqRhoS3Y50OHgaY7T/lwd6UArb+BOVAkg2oOvol/DJgddJ35XTxfUlQ # +8Hggt8l2Yv7roancJIFcbojBcxlRcGG0LIhp6GvReQGgMgYxQbV1S3CrWqZzBt1 # R9xJgKf47CdxVRd/ndUlQ05oxYy2zRWVFjF7mcr4C34Mj3ocCVccAvlKV9jEnstr # niLvUxxVZE/rptb7IRE2lskKPIJgbaP5t2nGj/ULLi49xTcBZU8atufk+EMF/cWu # iC7POGT75qaL6vdCvHlshtjdNXOCIUjsarfNZzCCB7EwggWZoAMCAQICDCuwyvrK # 7n8JSCSsTjANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQ # R2xvYmFsU2lnbiBudi1zYTEyMDAGA1UEAxMpR2xvYmFsU2lnbiBHQ0MgUjQ1IEVW # IENvZGVTaWduaW5nIENBIDIwMjAwHhcNMjMxMjE0MTY1MDE0WhcNMjYxMjE0MTY1 # MDE0WjCCARUxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYDVQQF # EwpIUkIgMTA3MjA3MRMwEQYLKwYBBAGCNzwCAQMTAkRFMSQwIgYLKwYBBAGCNzwC # AQITE05vcmRyaGVpbi1XZXN0ZmFsZW4xFjAUBgsrBgEEAYI3PAIBARMFS29lbG4x # CzAJBgNVBAYTAkRFMRwwGgYDVQQIExNOb3JkcmhlaW4tV2VzdGZhbGVuMREwDwYD # VQQHEwhPZGVudGhhbDEaMBgGA1UECRMRRWljaGhvbHplciBXZWcgMzUxGDAWBgNV # BAoTD0lUUHJvQ2xvdWQgR21iSDEYMBYGA1UEAxMPSVRQcm9DbG91ZCBHbWJIMIIC # IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1DRPH5Dgw4RFR2wU1JQPbblF # YvIrFFHGRtnyUi+62FCwYXf76lJ9P5grlY3Q5Fv/L5abhdcyoNvR2SpDyLz86y+L # gLWUhS24AXscYOGeAhMwEbxCgtUfT+RCtOaSiT/Mt50JjTldiPYmH4gEZFTEypGH # EYkGw2K0YRN6KPbtH/wQ+wa5/uJnICgCNFaXVt1AzclOTahPhvz/MGuqijT/ptFE # WQeimGXi3kTvEhArXjMPdWht6woQQDg8eVGCBEAWtMoPBAgtkFVcOFl8pAFglLxi # rL/gIo9MYWZvkyxJxXc+krAFaXiNXwf40uMefDC246DKXb5b6Vgikev9hmXAAZ0i # A7Q/KjhK+GEOgJztN7t7UBpAzxqWAi0Ddf+wkVlMIEKOBMZ0S0TyJUxOdexJlojL # nwlagu4wSLQ4Ca0/6TeQIEE41Fl1u4KZyKKVZ0z+hdicUxxpgdCGGjvSM5xbnyLU # Q1kiKfbttJzi405Ovax1Nwuk+6DyyCjbQciql5Bbpt5TAf3MxIH1qLgmk73IhlxG # KTuXGI5Aw/1NAJJrCNCqIK+qkQYvpuf5T6/RUBpCYyU5uhfgNyvs7oA5YtLq5/WR # pqFOfyODIxY6rlrKpiXx79FgzUICfAcI7IbdGIHLWMVlWt8FELQTVPwE/bpeqXXH # AqNqz+b5PZFEgvSCHssCAwEAAaOCAbYwggGyMA4GA1UdDwEB/wQEAwIHgDCBnwYI # KwYBBQUHAQEEgZIwgY8wTAYIKwYBBQUHMAKGQGh0dHA6Ly9zZWN1cmUuZ2xvYmFs # c2lnbi5jb20vY2FjZXJ0L2dzZ2NjcjQ1ZXZjb2Rlc2lnbmNhMjAyMC5jcnQwPwYI # KwYBBQUHMAGGM2h0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29tL2dzZ2NjcjQ1ZXZj # b2Rlc2lnbmNhMjAyMDBVBgNVHSAETjBMMEEGCSsGAQQBoDIBAjA0MDIGCCsGAQUF # BwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAHBgVn # gQwBAzAJBgNVHRMEAjAAMEcGA1UdHwRAMD4wPKA6oDiGNmh0dHA6Ly9jcmwuZ2xv # YmFsc2lnbi5jb20vZ3NnY2NyNDVldmNvZGVzaWduY2EyMDIwLmNybDATBgNVHSUE # DDAKBggrBgEFBQcDAzAfBgNVHSMEGDAWgBQlndD8WQmGY8Xs87ETO1ccA5I2ETAd # BgNVHQ4EFgQUjh4VAhP/4XwUsx0JssK4+EHy1XYwDQYJKoZIhvcNAQELBQADggIB # AMfjOH5vftWP/M433873bkokhhQf5uRjgKEuTX/TJZHwyIRqxi23dAlsEniQuWpX # E/oWDRnOKLm0WsNO6RZGWO1Cq4TNyEJNnMPs63wj3/IytOYoqK6mT8aL6ODHYNv0 # IvYzegjf/PwPduQ+9Q4hghnBSXmqEAesHnb9AdFMoTO53RK06Gxz6macj12C2bQ6 # KAkSj9mTpzNRtgoGQfEUPrFnL8Kb8p0Wk9ItVkdAqpvXdst6EbOKhR4ElGHdHTvN # Yhgzujr2MRARQ/awMq5x/TJuRnSyDpD6QrZ6IJncnGESfgL2StksAx2dnSOg0H5m # b2FzTuAE3LfvgM54Ky0vQGmYNzauyX02SptUExLrHLQLw3gNX1fdxjlqj/2FB6EO # xKwaLQL7AwXWvn6THKKIu+B5voUtXq6Age2JYhKLO2zw1pXHKFzKIRli+LIl+XsU # Pgur2IuS89hAm7vRw1iFZ8I+vRpc8U8nVgliVibPUSoSPLdf/TT5bHfb55Ny9PRK # pxu9ClTMU0cQSw+xuO3ZEnQtUBn1k8KiJfKmjR6qSCKyYJgX49Zye/rrC70XaHlu # y9vTSbjRD7/HjfzBtdXA2avrmbi84exhoc6bmsfY2qOyFHYJhTV8O8mbOimwR/9Y # DkwR58X6y4j5TLpNyxCvNCsZzbefLu8wPZnq9yzscTCZMYIGNzCCBjMCAQEwbDBc # MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEyMDAGA1UE # AxMpR2xvYmFsU2lnbiBHQ0MgUjQ1IEVWIENvZGVTaWduaW5nIENBIDIwMjACDCuw # yvrK7n8JSCSsTjAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKA # ADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYK # KwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQU9eeb6SzZ/8wr7lCRfzqDfWfZr2Yw # DQYJKoZIhvcNAQEBBQAEggIAJ6n9tdS3Y92qSmKTJkhqW7r185lGR6cHvs2QbTjv # vj8j0L+PAYazjmcaTJM16Q1SQbIOuhdliCwaufHZ9iz5Pj1Ih6T+3ait6Vz+fiqV # 1FxzP4iRcIEozQJyjNNbMTlIAVgOHeDBEAKXad3ZHS2wqYoQPQ+Mh3LBINVSwCwG # c7Sa9R0ISPN6xrMluXofeOiJHg9CzvbRPrR3zH+2743hMvh6H0VT1lQD0P6MSilZ # byxu/43g8MFmAy12OcQIbeF2EQ+c2AqoFkYKbswciKACexDGSBOyRznW0tMZ6Z38 # 1RhywZVb60DUeF1gODzuJs638RtldE1pQOLLMq2QO67KfNhRTSAVamLh3olhTuc/ # KNwysO/ERjtclwrb8FBpV4dqHJw+TLA/dPbxGO1cqXKsuB0jDBhuRtm+gFY35HpD # 2bi6qoNpWX/8qqMa2Tn2xYFd1KNuh1lCpxU8Nis+LEzjr5zYT+lnvvJi3Edx60wG # Q5U1jISCBwv6VhMGgIWhW5dvESzHAcN17mTstdHvKXmq/N12N5zHVKqc1CMBRjkW # xmNfFVrxl385UsKVWft07MtqJ7Jd4n8WKxlRQciu2+P6AM3JDJqVOXz4Rl/JK7LX # /eSDmm5AD64ZMF1QD3dJieByPDFMlt+SG8mGoP3wjnhGuHyTw67tfJYkRuU/iwe7 # S3ehggMmMIIDIgYJKoZIhvcNAQkGMYIDEzCCAw8CAQEwfTBpMQswCQYDVQQGEwJV # UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRy # dXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUgQ0ExAhAK # gO8YS43xBYLRxHanlXRoMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsG # CSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjUwNzE1MDgwMTQwWjAvBgkqhkiG # 9w0BCQQxIgQgbpqzLAq4FWBF6DcU8oZ8DPxe+6e52fi7M/tffRjP2oAwDQYJKoZI # hvcNAQEBBQAEggIAochW5/r9cZ4s5ky9GPy0c6Bi9Ec3U/j/9OJG9H6IR1eyGnui # 8Bw08DwkQfDU+u89NOGh6tKpt5RMjHcm+BzYEFXPz4G8C0rQpO9H7beNP9Fz3sov # eMN8jC6GKCmy+pr9rozzlNUN0tTEU7UawLGErRs4j35HfTaT2q5s91k2bkgThIMp # uzQxTxEDRmfceTi+WFDIJr7aerDmCPhJ/bDcwg4Q3DjB2XlA1fnoIvHS5V2gVhl+ # 5yo/21V/8syi9zGBxcSe8m0WEBncphO63+dSG7G6CU/6HhZfYhLpzygATbYIWtUw # eHBKZwxvE5b4xXvPPHW54R0chOyyqyNx8KJzy52ZqFWN0jmDbrzW29Yc1VqkPlw0 # Z2EOhvPwHUPg9IxFpAXIPMm3asg0a0F1twD9ozcEGp0JbfH/on8efaAr5mod/QaN # SbHWjObtrRX2muO1HV2tlpcj4J0J8RExri4W98832tOztez7mlQB1caJN0M4f6zh # jIDUx/FzuDu9TrLruvJtKi3IrJywcvGqTQ3OFeYAo94PSY5n+u6bhZBS1HEEFfc8 # BFz83YGmv9cbljwhG6M2+4qodcTHL+l7q+MfyqC3b0LSxay1r3MQkwqLOueLPhIG # 7tnbrCJhx10ZyqdzAgXfEvy5WmYM+WE+g9YnKc9PNQZOfLIW2b8Rofbf6M0= # SIG # End signature block