Obs/bin/ObsDep/content/Powershell/Roles/Common/MountedImage.psm1

<###################################################
 # #
 # Copyright (c) Microsoft. All rights reserved. #
 # #
 ##################################################>


Import-Module -Name "$PSScriptRoot\..\..\Common\Helpers.psm1"
Import-Module -Name "$PSScriptRoot\RoleHelpers.psm1"
Import-Module -Name Defender

<#
    MountedImage Class provides a standard way of mounting and updating an image.
    The class supports both WIM and VHDx files and can be used to inject Windows updates, drivers and deployment artifacts.
    Any injection of content that is to be done on an offline image should be added to this class.
#>

class MountedImage : System.IDisposable
{
    [string] $MountPath = $null
    [string] $ImagePath
    [string] $imageStatusFolder = "ImageStatus"
    [string] $imageStatusFileName = "ImageStatus.xml"

    # Constructors
    <#
     .SYNOPSIS
     This function mounts a WIM for offline update.
 
     .PARAMETER ImagePath
     Path to the WIM file to be updated.
 
     .PARAMETER ImageIndex
     Index for WIM file. This value should be set to 1 for most WIM files.
    #>

    MountedImage(
        [string] $ImagePath,
        [int] $ImageIndex
    )
    {
        if ($ImagePath -notlike '*.wim')
        {
            throw "$ImagePath is not a WIM."
        }

        $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
        $this.Init($ImagePath)

        # Mount the image
        Trace-Execution "Mount '$ImagePath' to '$($this.MountPath)'."
        Mount-WindowsImageWithRetry -ImagePath $ImagePath -Path $this.mountPath -Index $ImageIndex
    }

    <#
    .SYNOPSIS
    This function mounts VHD image for offline update.
 
    .PARAMETER ImagePath
    Path to the VHD to be updated.
    #>

    MountedImage(
        [string] $ImagePath
    )
    {
        if ($ImagePath -notlike '*.vhd*')
        {
            throw "$ImagePath is not a VHD."
        }

        $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
        $this.Init($ImagePath)

        # Mount the image
        Trace-Execution "Mount '$ImagePath' to '$($this.MountPath)'."

        Mount-WindowsImageWithRetry -ImagePath $ImagePath -Path $this.mountPath -Index 1
    }

    # Initializes the infrastructure pieces needed to mount the image
    [void] Init(
        [string] $ImagePath
    )
    {
        $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop

        $this.ImagePath = $ImagePath
        $this.DiscardPreviousImage()
        $this.MountPath = Join-Path -Path "C:\Temp\" -ChildPath $(Get-Item -Path $([IO.Path]::GetTempFileName())).Name

        # Create the mount path if it does not exist
        if(-not (Test-Path $this.MountPath))
        {
            New-Item -Path $this.MountPath -ItemType Directory
        }

        # Attempt to start defender if not already running
        $service = Get-Service -Name "windefend" -ErrorAction SilentlyContinue
        if ($service -ne $null -and $service.Status -ine "Running")
        {
            $service | Start-Service -ErrorAction SilentlyContinue | Out-Null
        }

        # set exclusion path when windefend is running
        if($service -ne $null -and $service.Status -eq "Running") {
            Trace-Execution "Exclude mount folders $($this.MountPath) from Windows Defender scan to speed up configuration."
            Add-MpPreference -ExclusionPath $this.MountPath -ErrorAction SilentlyContinue
        }
    }

    <#
        Gets the list of all previously mounted images and dismount them.
    #>

    [void] DiscardPreviousImage()
    {
        $mountedImages = Get-WindowsImage -Mounted
        foreach ($mountedImage in $mountedImages)
        {
            if ($mountedImage.ImagePath -eq $this.ImagePath)
            {
                $mountedImage | Dismount-WindowsImage -Discard
            }
        }
    }

    <#
        Gets the build of the mounted image from ntoskrnl.exe.
    #>

    [string] GetBuild()
    {
        $filePath = Join-Path -Path $this.MountPath -ChildPath 'Windows\System32\ntoskrnl.exe'
        Trace-Execution "Getting image build from '$filePath'"
        $fileInfo = Get-Item -Path $filePath
        $build = $fileInfo.VersionInfo.ProductBuildPart
        Trace-Execution "Image build is '$($build.ToString())'"

        return $build.ToString()
    }

    <#
    .SYNOPSIS
     Get version and status information from the image
 
    .DESCRIPTION
     If the image status file is present. The function reads contents of the file and returns it back.
     If the image status file is not present. It return null
    #>

    [xml] GetStatusInfoFromImage()
    {
        $content = $null
        $imageStatusFilePath = "$this.MountPath\$this.ImageStatusFolder\$this.ImageStatusFileName"
        if(Test-Path $imageStatusFilePath)
        {
            # Read the contents of the file
            $content = [xml](Get-Content $imageStatusFilePath)
        }

        return $content
    }

    <#
    .SYNOPSIS
     Updated the image status file with version and status.
 
    .DESCRIPTION
     Takes in version and the status as input. Generates a XML blob and saves it into a predefined location.
 
    .PARAMETER Version
     Version of deployment or update being applied to the stamp.
 
    .PARAMETER Status
    Status value that is to be set in the image
    #>

    UpdateImageStatusFile(
            [string] $Version,
            [string] $Status
    )
    {
        $statusId = $this.GetStatusIdForStatusString($Status)
        Trace-Execution "Updating image status by Setting Version: $Version StatusId: $statusId Status: $Status"
        $imageStatusXML = "<ImageStatus Version=`"$Version`" StatusId=`"$statusId`" Status=`"$Status`" />"

        if( -not (Test-Path "$this.MountPath\$this.ImageStatusFolder") )
        {
            $null = New-Item -Path $this.MountPath -Name $this.ImageStatusFolder -ItemType Directory -Force
        }
        $imageStatusFilePath = (Join-Path $this.MountPath (Join-Path $this.ImageStatusFolder $this.ImageStatusFileName))
        $imageStatusXML | Out-File $imageStatusFilePath -Force
    }

    <#
        Returns an integer value corresponding to the status string
    #>

    [int] GetStatusIdForStatusString(
            [string] $Status
        )
    {
        $statusToIdMap = @{}
        $statusToIdMap.Add("BaseBuildCompleted", 0)
        $statusToIdMap.Add("BuildCompleted", 1)

        return $statusToIdMap[$Status]
    }

    <#
    .SYNOPSIS
     Injects windows updates into the mounted image.
 
    .DESCRIPTION
     Looks for the windows update staging folder and updates inside it.
     If updates are present, it calls into Add-WindowsPackage to inject Windows Updates into the mounted image.
 
    .PARAMETER WindowsUpdateStagingFolder
     Folder containing all the Windows Updates to be applied.
 
    .PARAMETER ScratchDirectory
     Optional Scratch directory for Add-WindowsPackage
    #>

    UpdateImageWithWindowsUpdates(
        [string] $WindowsUpdateStagingFolder
    )
    {
        $this.UpdateImageWithWindowsUpdates($WindowsUpdateStagingFolder, $null, $false)
    }

    UpdateImageWithWindowsUpdates(
        [string] $WindowsUpdateStagingFolder,
        [string] $ScratchDirectory
    )
    {
        $this.UpdateImageWithWindowsUpdates($WindowsUpdateStagingFolder, $ScratchDirectory, $false)
    }

    UpdateImageWithWindowsUpdates(
        [string] $WindowsUpdateStagingFolder,
        [string] $ScratchDirectory,
        [bool] $IgnoreCheck
    )
    {
        $ErrorActionPreference = "Stop"
        Trace-Execution "Performing Windows Update injection for: $($this.ImagePath). WindowsUpdateStagingFolder = '$WindowsUpdateStagingFolder', ScratchDirectory = '$ScratchDirectory'"

        if (Test-Path $WindowsUpdateStagingFolder)
        {
            $versionedFolder = Get-AzSVersionedPath -Path $WindowsUpdateStagingFolder -ErrorAction SilentlyContinue
            if ($versionedFolder -ne $null)
            {
                $WindowsUpdateStagingFolder = $versionedFolder
            }
        }

        Trace-Execution "Found Windows update folder: $WindowsUpdateStagingFolder"

        $subFolders = @("SSU", "LCU")
        foreach ($subFolder in $subFolders)
        {
            $UpdateFolder = Join-Path $WindowsUpdateStagingFolder $subFolder
            if(Test-Path $UpdateFolder)
            {
                $items = @(Get-ChildItem -Path $UpdateFolder -Include @("*.cab", "*.msu") -Recurse)
                if($items.Count -gt 0)
                {
                    Trace-Execution "Injecting windows updates staged at: $UpdateFolder" -Verbose
                    if ($ScratchDirectory)
                    {
                        Trace-Execution "Refreshing PS Drive cache."
                        Get-PSDrive | Out-Null
                        Trace-Execution "Installing updates using ScratchDirectory '$ScratchDirectory'"
                        New-Item -ItemType Directory -Path $ScratchDirectory -Force
                        try
                        {
                            Add-WindowsPackage -PackagePath $UpdateFolder -Path $this.MountPath -ScratchDirectory $ScratchDirectory -IgnoreCheck:$IgnoreCheck
                        }
                        finally
                        {
                            Remove-Item -Force -Recurse -Path $ScratchDirectory -ErrorAction Ignore
                        }
                    }
                    else
                    {
                        Add-WindowsPackage -PackagePath $UpdateFolder -Path $this.MountPath -IgnoreCheck:$IgnoreCheck
                    }
                }
                else
                {
                    Trace-Warning "Windows update folder: $UpdateFolder exists but no updated were found. Skipping windows update injection." -Verbose
                }
            }
            else
            {
                Trace-Warning "Windows update folder: $UpdateFolder not found. Skipping windows update injection." -Verbose
            }
        }
    }

    <#
    .SYNOPSIS
     Adds drivers to the mounted image
 
    .DESCRIPTION
     Adds drivers to the mounted image
 
    .PARAMETER DriverPath
     Location where the drivers will be staged for consumption
 
    .PARAMETER SkipDriverInjection
     Value from the customer config that specifies if the driver injection should be skipped or not.
    #>

    AddDriversToImage(
        [string] $DriverPath,
        [bool] $SkipDriverInjection
    )
    {
        Trace-Execution "Performing driver injection for $($this.ImagePath)"
        # Perform driver injection if needed
        if (-not ($this.TestSkipDriverInjection($DriverPath, $SkipDriverInjection) ))
        {
            Trace-Execution "Adding drivers to the image from: $DriverPath"
            Trace-Execution "Getting existing OEM drivers."
            $existingDrivers = Get-WindowsDriver -Path $this.MountPath

            Trace-Execution "Add Windows drivers from $DriverPath."
            $addDrivers = Add-WindowsDriver -Driver $DriverPath -Path $this.MountPath -Recurse

            if($existingDrivers)
            {
                $addDrivers = $addDrivers | Where-Object {$_.Driver -notin $existingDrivers.Driver}
            }

            foreach($driver in $addDrivers)
            {
                Trace-Execution "$($driver.ProviderName) $(Split-Path -Path $driver.OriginalFileName -Leaf) version $($driver.Version) added as $($driver.Driver)"
            }
        }
        else
        {
            Trace-Execution "Skipping driver injection."
        }
    }

    <#
    .SYNOPSIS
     Adds a directory to the mounted image
 
    .DESCRIPTION
     Adds a directory to the mounted image
 
    .PARAMETER SourcePath
     Location where the directory will be staged for consumption
 
    .PARAMETER Destination
     Destination path of the directory to be added
    #>

    AddDirectoryToImage(
        [string] $SourcePath,
        [string] $Destination
    )
    {
        $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop

        # only copy if the source exists
        if(Test-Path -Path $SourcePath)
        {
            $Directory = Split-Path -Path $SourcePath -Leaf
            $DestinationPath = Join-Path -Path $this.MountPath (Join-Path -Path $Destination -ChildPath $Directory)
            # only copy if the destination doesn't already exist
            if(-not (Test-Path -Path $DestinationPath))
            {
                $TempDestinationPath = "${DestinationPath}_Temp"
                try
                {
                    # create a temporary version of the destination directory
                    if(-not (Test-Path -Path $TempDestinationPath))
                    {
                        Trace-Execution "Creating temporary directory $TempDestinationPath"
                        $null = New-Item -Path $TempDestinationPath -ItemType Directory
                    }
                    # copy each file or directory from the source to the temporary folder
                    foreach($item in (Get-ChildItem -Path $SourcePath))
                    {
                        Trace-Execution "Copying $($item.FullName) to $TempDestinationPath"
                        Copy-Item -Path $item.FullName -Destination $TempDestinationPath  -Recurse
                    }
                }
                finally
                {
                    # rename the temporary folder
                    Trace-Execution "Renaming temporary directory $TempDestinationPath to $Directory"
                    Rename-Item -Path $TempDestinationPath -NewName $Directory
                }
            }
            else
            {
                Trace-Execution "$DestinationPath already exists"
            }
        }
        else
        {
            Trace-Execution "$SourcePath does not exist"
        }
    }

    <#
    .SYNOPSIS
     Adds OEM SLP license to the mounted image
 
    .DESCRIPTION
     Adds OEM SLP license file to the mounted image
 
    .PARAMETER Path
     Source location of the OEM license file
    #>

    AddOemLicense(
        [string] $Path
    )
    {
        $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop

        if(Test-Path -Path $Path)
        {
            $DestinationPath = Join-Path -Path $this.MountPath -ChildPath "\Windows\System32\OEM"
            New-Item -Path $DestinationPath -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
            Trace-Execution "Copying $Path to $DestinationPath"
            Copy-Item -Path $Path -Destination $DestinationPath -Force
        }
        else
        {
            Trace-Execution "$Path does not exist"
        }
    }

    <#
    .SYNOPSIS
     Evaluates if driver injection should be skipped or not
 
    .PARAMETER DriverPath
     Location where the drivers will be staged for consumption
 
    .PARAMETER SkipDriverInjection
     Value from the customer config that specifies if the driver injection should be skipped or not.
    #>

    [bool] TestSkipDriverInjection(
            [string] $DriverPath,
            [bool] $SkipDriverInjection
    )
    {
        $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop

        if ($skipDriverInjection)
        {
            Trace-Warning 'Driver injection will be skipped as instructed by $CloudBuilder.SkipDriverInjection setting.'
        }
        elseif (-not (Test-Path $DriverPath))
        {
            Trace-Execution "Driver injection will be skipped as the driver path '$DriverPath' does not exist."
            $skipDriverInjection = $true
        }
        elseif (-not (Get-ChildItem $DriverPath))
        {
            Trace-Execution "Driver injection will be skipped as the driver path '$DriverPath' does not contain any files."
            $skipDriverInjection = $true
        }
        elseif (-not (Get-ChildItem $DriverPath -Filter *.inf -Recurse))
        {
            Trace-Execution "Driver injection will be skipped as the driver path '$DriverPath' does not contain any drivers (no *.inf files found)."
            $skipDriverInjection = $true
        }

        return $skipDriverInjection
    }

   <#
    .SYNOPSIS
    Expands the deployment artifacts to the destination location.
 
    .DESCRIPTION
    Expands all deployment artifacts into the destination root path.
 
    .EXAMPLE
    ExpandDeploymentArtifacts($Parameters.Configuration.Role.PrivateInfo.DeploymentContent)
 
    .PARAMETER DeploymentContentNode
    The xml node containing the deployment content to deliver to the destination.
    #>

    ExpandDeploymentArtifacts(
        [System.Xml.XmlElement] $DeploymentContentNode,
        [string] $NugetStorePath
        )
    {
        Expand-DeploymentArtifacts -DeploymentContentNode $DeploymentContentNode -DestinationRootPath $this.MountPath -NugetStorePath $NugetStorePath
    }

    <#
    .SYNOPSIS
    Expands the deployment artifacts to the destination location.
 
    .DESCRIPTION
    Expands all deployment artifacts into the destination root path.
 
    .EXAMPLE
    ExpandDeploymentArtifacts($Parameters.Configuration.Role.PrivateInfo.DeploymentContent)
 
    .PARAMETER DeploymentContentNode
    The xml node containing the deployment content to deliver to the destination.
    #>

    ExpandDeploymentArtifacts(
        [System.Xml.XmlElement] $DeploymentContentNode)
    {
        $NugetStorePath = "$env:SystemDrive\CloudDeployment\NuGetStore"
        Expand-DeploymentArtifacts -DeploymentContentNode $DeploymentContentNode -DestinationRootPath $this.MountPath -NugetStorePath $NugetStorePath
    }

    # Dispose methods for the class
    # Invoke this directly if you want the VHD to be unmounted immediately, rather than when the powershell session dies.
    [void]Dispose()
    {
        $this.Dispose($true)
    }

    [void]Dispose(
        [bool]$disposing
        )
    {
        # Dismount the image that was updated
        if ($this.MountPath -ne $null)
        {
            Trace-Execution "Dismount and save mounted image."

            $logFilePath = "C:\Temp\vstor.etl"
            $successlogFilePath = "C:\Temp\vstorGood.etl"
            Copy-Item $PSScriptRoot\vstortrace.wprp C:\Temp -Force
            $logEnabled = $false
            if (-not (Test-Path $logFilePath))
            {
                Trace-Execution "Starting WPR tracing for dismount."
                $logEnabled = $true
                & Wpr.exe -start C:\Temp\vstortrace.wprp!VStorWPP -filemode
            }

            try
            {
                Dismount-WindowsImage -Path $this.mountPath -Save -Verbose:$false
            }
            finally
            {
                if ($logEnabled)
                {
                    Trace-Execution "Stopping WPR tracing for dismount."
                    & Wpr.exe -stop $logFilePath
                }
            }

            if ($logEnabled)
            {
                if (-not (Test-Path $successlogFilePath))
                {
                    Trace-Execution "Keeping the first successful dismount log on this host."
                    Copy-Item $logFilePath $successlogFilePath
                }

                Trace-Execution "Removing WPR log file since dismount is successful."
                Remove-Item $logFilePath -Force -ErrorAction Ignore
            }

            # Attempt to start defender if not already running
            $service = Get-Service -Name "windefend" -ErrorAction SilentlyContinue
            if ($service -ne $null -and $service.Status -ine "Running")
            {
                $service | Start-Service -ErrorAction SilentlyContinue | Out-Null
            }

            if($service -ne $null -and $service.Status -eq "Running") {
                Trace-Execution "Remove Windows Defender exclusions for paths $($this.MountPath)."
                Remove-MpPreference -ExclusionPath $this.MountPath -ErrorAction SilentlyContinue
            }

            $this.MountPath = $null
        }
    }
}
# SIG # Begin signature block
# MIIn0QYJKoZIhvcNAQcCoIInwjCCJ74CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB2YOY0j8mmGx+w
# Lf3bvNI1wujoUg44MT3xbQEX/bMmtKCCDYUwggYDMIID66ADAgECAhMzAAADri01
# UchTj1UdAAAAAAOuMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjMxMTE2MTkwODU5WhcNMjQxMTE0MTkwODU5WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQD0IPymNjfDEKg+YyE6SjDvJwKW1+pieqTjAY0CnOHZ1Nj5irGjNZPMlQ4HfxXG
# yAVCZcEWE4x2sZgam872R1s0+TAelOtbqFmoW4suJHAYoTHhkznNVKpscm5fZ899
# QnReZv5WtWwbD8HAFXbPPStW2JKCqPcZ54Y6wbuWV9bKtKPImqbkMcTejTgEAj82
# 6GQc6/Th66Koka8cUIvz59e/IP04DGrh9wkq2jIFvQ8EDegw1B4KyJTIs76+hmpV
# M5SwBZjRs3liOQrierkNVo11WuujB3kBf2CbPoP9MlOyyezqkMIbTRj4OHeKlamd
# WaSFhwHLJRIQpfc8sLwOSIBBAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhx/vdKmXhwc4WiWXbsf0I53h8T8w
# VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
# dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwMTgzNjAfBgNVHSMEGDAW
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
# AGrJYDUS7s8o0yNprGXRXuAnRcHKxSjFmW4wclcUTYsQZkhnbMwthWM6cAYb/h2W
# 5GNKtlmj/y/CThe3y/o0EH2h+jwfU/9eJ0fK1ZO/2WD0xi777qU+a7l8KjMPdwjY
# 0tk9bYEGEZfYPRHy1AGPQVuZlG4i5ymJDsMrcIcqV8pxzsw/yk/O4y/nlOjHz4oV
# APU0br5t9tgD8E08GSDi3I6H57Ftod9w26h0MlQiOr10Xqhr5iPLS7SlQwj8HW37
# ybqsmjQpKhmWul6xiXSNGGm36GarHy4Q1egYlxhlUnk3ZKSr3QtWIo1GGL03hT57
# xzjL25fKiZQX/q+II8nuG5M0Qmjvl6Egltr4hZ3e3FQRzRHfLoNPq3ELpxbWdH8t
# Nuj0j/x9Crnfwbki8n57mJKI5JVWRWTSLmbTcDDLkTZlJLg9V1BIJwXGY3i2kR9i
# 5HsADL8YlW0gMWVSlKB1eiSlK6LmFi0rVH16dde+j5T/EaQtFz6qngN7d1lvO7uk
# 6rtX+MLKG4LDRsQgBTi6sIYiKntMjoYFHMPvI/OMUip5ljtLitVbkFGfagSqmbxK
# 7rJMhC8wiTzHanBg1Rrbff1niBbnFbbV4UDmYumjs1FIpFCazk6AADXxoKCo5TsO
# zSHqr9gHgGYQC2hMyX9MGLIpowYCURx3L7kUiGbOiMwaMIIHejCCBWKgAwIBAgIK
# YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm
# aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw
# OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD
# VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG
# 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la
# UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc
# 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D
# dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+
# lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk
# kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6
# A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd
# X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL
# 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd
# sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3
# T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS
# 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI
# bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
# BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD
# uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h
# cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA
# YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn
# 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7
# v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b
# pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/
# KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy
# CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp
# mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi
# hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb
# BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS
# oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL
# gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX
# cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGaIwghmeAgEBMIGVMH4x
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
# Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAOuLTVRyFOPVR0AAAAA
# A64wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFbN
# 7YT+y3oIhivuTEAzaagYixjWJoAyB2IvxkC3fHt3MEIGCisGAQQBgjcCAQwxNDAy
# oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20wDQYJKoZIhvcNAQEBBQAEggEAW8OzRyrDk2sHRjN8IfHiGIUq/ttbMQHlhUJd
# 8ws2OVB7gJmd/omXuguCHOgq+PSynTMgE8+N3ealcIRagVmSHPsxzjZk1NiKWiM+
# 5tIpj3ZedOlGgyYmQyy8i1S534OOnZFbJ6Lol0XNmYpkyiN7+bTEl9X5tWxDbLYx
# IPi9zLWkF/CkrP3lcnqyEMdova39jWZtXuHYn1xWOMTd4OTDFTih/Sf8kZqrUlKj
# DKRVMOQBTziV7N8VRJCmQRT7R2Cvcn6XuTliFW9wn2ECft3J/h9GyHr5PMbe5oeR
# C8KYvUYmVU6csvpETJHzaalrWC4HgipE84WUj1e6TPj5A6HONqGCFywwghcoBgor
# BgEEAYI3AwMBMYIXGDCCFxQGCSqGSIb3DQEHAqCCFwUwghcBAgEDMQ8wDQYJYIZI
# AWUDBAIBBQAwggFZBgsqhkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGE
# WQoDATAxMA0GCWCGSAFlAwQCAQUABCAiy1T7m2BopcC1+/NQbuuBl1+wE5fzShP6
# MskDCDpPjwIGZdX+rHJTGBMyMDI0MDMxMTE4MTY1NC40MzJaMASAAgH0oIHYpIHV
# MIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL
# EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsT
# HVRoYWxlcyBUU1MgRVNOOjNCRDQtNEI4MC02OUMzMSUwIwYDVQQDExxNaWNyb3Nv
# ZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIRezCCBycwggUPoAMCAQICEzMAAAHlj2rA
# 8z20C6MAAQAAAeUwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg
# UENBIDIwMTAwHhcNMjMxMDEyMTkwNzM1WhcNMjUwMTEwMTkwNzM1WjCB0jELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9z
# b2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMg
# VFNTIEVTTjozQkQ0LTRCODAtNjlDMzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
# U3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKl7
# 4Drau2O6LLrJO3HyTvO9aXai//eNyP5MLWZrmUGNOJMPwMI08V9zBfRPNcucreIY
# SyJHjkMIUGmuh0rPV5/2+UCLGrN1P77n9fq/mdzXMN1FzqaPHdKElKneJQ8R6cP4
# dru2Gymmt1rrGcNe800CcD6d/Ndoommkd196VqOtjZFA1XWu+GsFBeWHiez/Pllq
# cM/eWntkQMs0lK0zmCfH+Bu7i1h+FDRR8F7WzUr/7M3jhVdPpAfq2zYCA8ZVLNgE
# izY+vFmgx+zDuuU/GChDK7klDcCw+/gVoEuSOl5clQsydWQjJJX7Z2yV+1KC6G1J
# VqpP3dpKPAP/4udNqpR5HIeb8Ta1JfjRUzSv3qSje5y9RYT/AjWNYQ7gsezuDWM/
# 8cZ11kco1JvUyOQ8x/JDkMFqSRwj1v+mc6LKKlj//dWCG/Hw9ppdlWJX6psDesQu
# QR7FV7eCqV/lfajoLpPNx/9zF1dv8yXBdzmWJPeCie2XaQnrAKDqlG3zXux9tNQm
# z2L96TdxnIO2OGmYxBAAZAWoKbmtYI+Ciz4CYyO0Fm5Z3T40a5d7KJuftF6CTocc
# c/Up/jpFfQitLfjd71cS+cLCeoQ+q0n0IALvV+acbENouSOrjv/QtY4FIjHlI5zd
# JzJnGskVJ5ozhji0YRscv1WwJFAuyyCMQvLdmPddAgMBAAGjggFJMIIBRTAdBgNV
# HQ4EFgQU3/+fh7tNczEifEXlCQgFOXgMh6owHwYDVR0jBBgwFoAUn6cVXQBeYl2D
# 9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3Nv
# ZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy
# MDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1l
# LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUB
# Af8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQAD
# ggIBADP6whOFjD1ad8GkEJ9oLBuvfjndMyGQ9R4HgBKSlPt3pa0XVLcimrJlDnKG
# gFBiWwI6XOgw82hdolDiMDBLLWRMTJHWVeUY1gU4XB8OOIxBc9/Q83zb1c0RWEup
# gC48I+b+2x2VNgGJUsQIyPR2PiXQhT5PyerMgag9OSodQjFwpNdGirna2rpV23EU
# wFeO5+3oSX4JeCNZvgyUOzKpyMvqVaubo+Glf/psfW5tIcMjZVt0elswfq0qJNQg
# oYipbaTvv7xmixUJGTbixYifTwAivPcKNdeisZmtts7OHbAM795ZvKLSEqXiRUjD
# YZyeHyAysMEALbIhdXgHEh60KoZyzlBXz3VxEirE7nhucNwM2tViOlwI7EkeU5hu
# dctnXCG55JuMw/wb7c71RKimZA/KXlWpmBvkJkB0BZES8OCGDd+zY/T9BnTp8si3
# 6Tql84VfpYe9iHmy7PqqxqMF2Cn4q2a0mEMnpBruDGE/gR9c8SVJ2ntkARy5Sflu
# uJ/MB61yRvT1mUx3lyppO22ePjBjnwoEvVxbDjT1jhdMNdevOuDeJGzRLK9HNmTD
# C+TdZQlj+VMgIm8ZeEIRNF0oaviF+QZcUZLWzWbYq6yDok8EZKFiRR5otBoGLvaY
# FpxBZUE8mnLKuDlYobjrxh7lnwrxV/fMy0F9fSo2JxFmtLgtMIIHcTCCBVmgAwIB
# AgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0
# IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1
# WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O
# 1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZn
# hUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t
# 1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxq
# D89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmP
# frVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSW
# rAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv
# 231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zb
# r17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYcten
# IPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQc
# xWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17a
# j54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQAB
# MCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQU
# n6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEw
# QTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9E
# b2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQB
# gjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/
# MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJ
# oEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01p
# Y1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYB
# BQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v
# Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3h
# LB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x
# 5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74p
# y27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1A
# oL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbC
# HcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB
# 9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNt
# yo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3
# rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcV
# v7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A24
# 5oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lw
# Y1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAtcwggJAAgEBMIIBAKGB2KSB1TCB
# 0jELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMk
# TWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1U
# aGFsZXMgVFNTIEVTTjozQkQ0LTRCODAtNjlDMzElMCMGA1UEAxMcTWljcm9zb2Z0
# IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUA942iGuYFrsE4wzWD
# d85EpM6RiwqggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN
# BgkqhkiG9w0BAQUFAAIFAOmZhn4wIhgPMjAyNDAzMTEyMTMyNDZaGA8yMDI0MDMx
# MjIxMzI0NlowdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA6ZmGfgIBADAKAgEAAgIA
# rAIB/zAHAgEAAgIRTzAKAgUA6ZrX/gIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgor
# BgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUA
# A4GBAIgAHeCDxKLqK/XLPfgL0M+GuWTuSzdJB6qLPyzZxGCpgCB9mPiGjjOa/RVN
# t/9oszm1E5qBLdvRTY8clHNH71MdmZSUs1beMMGN4tSygaTjKYB4aigZJt3KaIlk
# Cfc3Z1x9lQh7Yp1wPxP018ITd68WtyNaskGHepceY+gQkhqmMYIEDTCCBAkCAQEw
# gZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAHlj2rA8z20C6MA
# AQAAAeUwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0B
# CRABBDAvBgkqhkiG9w0BCQQxIgQgWJ7YAob5YI9fLxndn1LgvlWA2EztyOZ4UxZO
# eY8WB5UwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCAVqdP//qjxGFhe2Ybo
# EXeb8I/pAof01CwhbxUH9U697TCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFBDQSAyMDEwAhMzAAAB5Y9qwPM9tAujAAEAAAHlMCIEIHLeIT3zielfgWew98Co
# TTohktJqX0b2m4aWSu4BtAuGMA0GCSqGSIb3DQEBCwUABIICADJE8WuIgJvurZw7
# 8WS/TnDDLpZ0/bjXnvs0K7KeMDaLjvcSn6xAacWj6ENnnlJhHxzytnbsj4n6kLxx
# ZOD+UtqMnRdK6BWVIb1y0ZktLKQ3U0M1CrJtulwFrxc/MLj6YQ+jbqqELApaj14B
# U1enSOF3NWXBy6fTDpwq3PxTDxe/aVPkI9mKM9vf4TJdICZxmrYnV+ei/8HvHUvg
# FN6DlIfz7Z6lWSbyHQKEEByJj2u3YsjgtlgM3vV1ka4thPrasNP5iZfUrzRFLAn8
# awvRT86d0oYjLMSgH7e21pMrJ3XnfQIA2Zwtj9Wx0lWL4QS60BWYfRyykVqY3Wo6
# tGau1Aeau/2tlkEFzwqf0avfo3El/aUJPQRH6EeX1zdcKagnf7hlkJBQzKHNXwzQ
# 38CsdFy3RJfVXKkrAixzAytpCebuuzgxfcdUpEYMPjUoNmNuQrZnXU5yMBuz37x3
# w79fu9bizkaKlhA5uIYruRhwB0p79zzPHIm93Ea+zCaLw2ny40wS0S4KD7W5t58B
# Pgscg0Fo5I9hxhYe9C9QiOxmkku2UvOF6Ol6cBceKt+l8S9HhLtzUofa5/nChQVh
# F01TUxzmueB9Am6zZEPUVfHdKtxJ5VsG7blYzPfLDjWZnVCrcXW1PQ12++6ubS9A
# jUwe2kbjg9phZBxe/9y/TBzRR2xK
# SIG # End signature block