$_myLocation = (Split-Path (Get-Variable MyInvocation -Scope 0).Value.mycommand.path)
. (Join-Path $_myLocation "CWACLogger.ps1")


<#
    .SYNOPSIS
        Runs an installer in isolation to extract changes it makes to the file system and registry
#>
function Invoke-Sequencer
{
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$True)]
        [string]
        [ValidateNotNullOrEmpty()]
        $ExpandedBaseImage,

        [Parameter(Mandatory=$True)]
        [string]
        [ValidateNotNullOrEmpty()]
        $Installer,

        [Parameter(Mandatory=$True)]
        [string[]]
        [AllowEmptyCollection()]
        [AllowEmptyString()]
        [AllowNull()]
        $InstallerArguments,

        [Parameter(Mandatory=$True)]
        [int[]]
        [AllowEmptyCollection()]
        [AllowNull()]
        $InstallerValidExitCodes,

        [Parameter(Mandatory=$True)]
        [string]
        [ValidateNotNullOrEmpty()]
        $ShareFolder,

        [Parameter(Mandatory=$True)]
        [string]
        [ValidateNotNullOrEmpty()]
        $Destination,

        [Parameter(Mandatory=$True)]
        [string]
        [ValidateNotNullOrEmpty()]
        $DllPath,

        [Parameter(Mandatory=$True)]
        [string]
        [ValidateNotNullOrEmpty()]
        $LogPathToken,

        [Parameter(Mandatory=$True)]
        [CWACLogger]
        [ValidateNotNull()]
        $Logger
    )

    $ErrorActionPreference = "Stop"

    $installerObj = Get-Item $Installer
    $installerPath = $installerObj.FullName
    $installerName = $installerObj.Name

    $isMsi = [io.path]::GetExtension($installerObj) -eq ".msi"
    
    $acceptableExitCodes = $null

    if (!$InstallerValidExitCodes)
    {
        $acceptableExitCodes = @()
        $acceptableExitCodes += 0
        if ($isMsi)
        {
            $acceptableExitCodes += 1641
            $acceptableExitCodes += 3010
        }
        $Logger.LogDiag("No installer valid exit codes specified. Using defaults: $acceptableExitCodes")
    }
    else
    {
        $acceptableExitCodes = $InstallerValidExitCodes
        $Logger.LogDiag("Installer valid exit codes were specified to be: $acceptableExitCodes")
    }

    try
    {
        $sandboxPath = Join-Path $Destination "sandbox"
        $exportPath = Join-Path $Destination "export"

        $isolatedEnvSharedFolder = Join-Path $env:SystemDrive "installer"

        $Logger.LogDiag("Replace any occurence of $LogPathToken in -InstallerArguments with $isolatedEnvSharedLogFolder")
        $isolatedEnvSharedLogFolder = Join-Path $isolatedEnvSharedFolder "logs"
        For ($i = 0; $i -lt ($InstallerArguments | measure).Count; $i++)
        {
            $InstallerArguments[$i] = $InstallerArguments[$i].Replace($LogPathToken, $isolatedEnvSharedLogFolder)
        }

        # create shared log folder host-side, so that it gets shared with the isolated environment
        $hostSharedLogFolder = Join-Path $ShareFolder "logs"
        New-Item -Path $hostSharedLogFolder -ItemType Directory -Force *> $null

        $isolatedEnvInstallerPath = Join-Path $isolatedEnvSharedFolder $installerName
        $logName = "install_" + [System.IO.Path]::ChangeExtension($installerName, ".log")
        $isolatedEnvLogPath = Join-Path $isolatedEnvSharedFolder $logName

        $isolatedEnvInstallCommand = $null
        $isolatedEnvInstallArguments = $null

        if ($isMsi)
        {
            $isolatedEnvInstallCommand = "$env:SystemRoot\system32\msiexec.exe"

            $isolatedEnvInstallArguments = "DISABLEADVTSHORTCUTS=1", "INSTALLSTARTMENUSHORTCUTS=1", "/quiet", "/norestart", "/i", "`"$isolatedEnvInstallerPath`"", "/L*v", "`"$isolatedEnvLogPath`""

            if ($InstallerArguments)
            {
                $Logger.LogWarning("Isolated Install: Warning 4100: msi detected. InstallerArguments: $InstallerArguments will not be used, and were instead replaced with $isolatedEnvInstallArguments")
            }
        }
        else
        {
            $isolatedEnvInstallCommand = $isolatedEnvInstallerPath
            $isolatedEnvInstallArguments = $InstallerArguments
        }

        $commandLine = "`"$isolatedEnvInstallCommand`" $isolatedEnvInstallArguments"

        # Input path can't have a trailing slash.
        $ExpandedBaseImage = $ExpandedBaseImage.TrimEnd("\")

        $Logger.LogDiag("Running installer command in isolated environment:")
        $Logger.LogDiag("Command Line = $commandLine")
        [System.Reflection.Assembly]::LoadFile((Join-Path $DllPath "Microsoft.DesktopAppConverter.IsolationManager.dll")) > $null
        [System.Reflection.Assembly]::LoadFile((Join-Path $DllPath "Microsoft.Windows.ComputeVirtualization.dll")) > $null
        $installerExitCode = [Microsoft.Centennial.Tools.DesktopAppConverter.IsolationManager]::RunIsolatedProcessWithMappedDirectoryAndExport($ExpandedBaseImage, $sandboxPath, $exportPath, $commandLine, $ShareFolder, $isolatedEnvSharedFolder)

        $hostLogPath = (Get-Item $Logger.GetLogFile()).DirectoryName

        if ($isMsi)
        {
            Move-Item (Join-Path $ShareFolder $logName) $hostLogPath
        }

        $Logger.LogDiag("Moving any logs in $hostSharedLogFolder to $hostLogPath")
        Move-Item $hostSharedLogFolder\* $hostLogPath

        $Logger.LogDiag("Output export complete. Moving output from $exportPath to $Destination")
        Move-Item $exportPath\* $Destination
        Remove-Item $exportPath

        $Logger.LogDiag("Checking installer exit code $installerExitCode to ensure it is indicative of success")
        if ($acceptableExitCodes -notcontains $installerExitCode)
        {
            throw "Isolated Install: fatal error 1120: valid exit codes for installer were $acceptableExitCodes, but it returned $installerExitCode."
        }
    }
    catch 
    {
        $lastError = $_
        throw $lastError
    }
}

# SIG # Begin signature block
# MIIkIQYJKoZIhvcNAQcCoIIkEjCCJA4CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAz3EU+Ns1rx8ZF
# D+fJLz6KAM9f8MeickLsaH5MplmgO6CCDZIwggYQMIID+KADAgECAhMzAAAAZEeE
# lIbbQRk4AAAAAABkMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMTUxMDI4MjAzMTQ2WhcNMTcwMTI4MjAzMTQ2WjCBgzEL
# MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
# bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9Q
# UjEeMBwGA1UEAxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMIIBIjANBgkqhkiG9w0B
# AQEFAAOCAQ8AMIIBCgKCAQEAky7a2OY+mNkbD2RfTahYTRQ793qE/DwRMTrvicJK
# LUGlSF3dEp7vq2YoNNV9KlV7TE2K8sDxstNSFYu2swi4i1AL3X/7agmg3GcExPHf
# vHUYIEC+eCyZVt3u9S7dPkL5Wh8wrgEUirCCtVGg4m1l/vcYCo0wbU06p8XzNi3u
# XyygkgCxHEziy/f/JCV/14/A3ZduzrIXtsccRKckyn6B5uYxuRbZXT7RaO6+zUjQ
# hiyu3A4hwcCKw+4bk1kT9sY7gHIYiFP7q78wPqB3vVKIv3rY6LCTraEbjNR+phBQ
# EL7hyBxk+ocu+8RHZhbAhHs2r1+6hURsAg8t4LAOG6I+JQIDAQABo4IBfzCCAXsw
# HwYDVR0lBBgwFgYIKwYBBQUHAwMGCisGAQQBgjdMCAEwHQYDVR0OBBYEFFhWcQTw
# vbsz9YNozOeARvdXr9IiMFEGA1UdEQRKMEikRjBEMQ0wCwYDVQQLEwRNT1BSMTMw
# MQYDVQQFEyozMTY0Mis0OWU4YzNmMy0yMzU5LTQ3ZjYtYTNiZS02YzhjNDc1MWM0
# YjYwHwYDVR0jBBgwFoAUSG5k5VAF04KqFzc3IrVtqMp1ApUwVAYDVR0fBE0wSzBJ
# oEegRYZDaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljQ29k
# U2lnUENBMjAxMV8yMDExLTA3LTA4LmNybDBhBggrBgEFBQcBAQRVMFMwUQYIKwYB
# BQUHMAKGRWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj
# Q29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqG
# SIb3DQEBCwUAA4ICAQCI4gxkQx3dXK6MO4UktZ1A1r1mrFtXNdn06DrARZkQTdu0
# kOTLdlGBCfCzk0309RLkvUgnFKpvLddrg9TGp3n80yUbRsp2AogyrlBU+gP5ggHF
# i7NjGEpj5bH+FDsMw9PygLg8JelgsvBVudw1SgUt625nY7w1vrwk+cDd58TvAyJQ
# FAW1zJ+0ySgB9lu2vwg0NKetOyL7dxe3KoRLaztUcqXoYW5CkI+Mv3m8HOeqlhyf
# FTYxPB5YXyQJPKQJYh8zC9b90JXLT7raM7mQ94ygDuFmlaiZ+QSUR3XVupdEngrm
# ZgUB5jX13M+Pl2Vv7PPFU3xlo3Uhj1wtupNC81epoxGhJ0tRuLdEajD/dCZ0xIni
# esRXCKSC4HCL3BMnSwVXtIoj/QFymFYwD5+sAZuvRSgkKyD1rDA7MPcEI2i/Bh5O
# MAo9App4sR0Gp049oSkXNhvRi/au7QG6NJBTSBbNBGJG8Qp+5QThKoQUk8mj0ugr
# 4yWRsA9JTbmqVw7u9suB5OKYBMUN4hL/yI+aFVsE/KJInvnxSzXJ1YHka45ADYMK
# AMl+fLdIqm3nx6rIN0RkoDAbvTAAXGehUCsIod049A1T3IJyUJXt3OsTd3WabhIB
# XICYfxMg10naaWcyUePgW3+VwP0XLKu4O1+8ZeGyaDSi33GnzmmyYacX3BTqMDCC
# B3owggVioAMCAQICCmEOkNIAAAAAAAMwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNV
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29m
# dCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDExMB4XDTExMDcwODIwNTkw
# OVoXDTI2MDcwODIxMDkwOVowfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAx
# MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKvw+nIQHC6t2G6qghBN
# NLrytlghn0IbKmvpWlCquAY4GgRJun/DDB7dN2vGEtgL8DjCmQawyDnVARQxQtOJ
# DXlkh36UYCRsr55JnOloXtLfm1OyCizDr9mpK656Ca/XllnKYBoF6WZ26DJSJhIv
# 56sIUM+zRLdd2MQuA3WraPPLbfM6XKEW9Ea64DhkrG5kNXimoGMPLdNAk/jj3gcN
# 1Vx5pUkp5w2+oBN3vpQ97/vjK1oQH01WKKJ6cuASOrdJXtjt7UORg9l7snuGG9k+
# sYxd6IlPhBryoS9Z5JA7La4zWMW3Pv4y07MDPbGyr5I4ftKdgCz1TlaRITUlwzlu
# ZH9TupwPrRkjhMv0ugOGjfdf8NBSv4yUh7zAIXQlXxgotswnKDglmDlKNs98sZKu
# HCOnqWbsYR9q4ShJnV+I4iVd0yFLPlLEtVc/JAPw0XpbL9Uj43BdD1FGd7P4AOG8
# rAKCX9vAFbO9G9RVS+c5oQ/pI0m8GLhEfEXkwcNyeuBy5yTfv0aZxe/CHFfbg43s
# TUkwp6uO3+xbn6/83bBm4sGXgXvt1u1L50kppxMopqd9Z4DmimJ4X7IvhNdXnFy/
# dygo8e1twyiPLI9AN0/B4YVEicQJTMXUpUMvdJX3bvh4IFgsE11glZo+TzOE2rCI
# F96eTvSWsLxGoGyY0uDWiIwLAgMBAAGjggHtMIIB6TAQBgkrBgEEAYI3FQEEAwIB
# ADAdBgNVHQ4EFgQUSG5k5VAF04KqFzc3IrVtqMp1ApUwGQYJKwYBBAGCNxQCBAwe
# CgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
# BBgwFoAUci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0
# cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2Vy
# QXV0MjAxMV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAwTgYIKwYBBQUH
# MAKGQmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2Vy
# QXV0MjAxMV8yMDExXzAzXzIyLmNydDCBnwYDVR0gBIGXMIGUMIGRBgkrBgEEAYI3
# LgMwgYMwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv
# cHMvZG9jcy9wcmltYXJ5Y3BzLmh0bTBABggrBgEFBQcCAjA0HjIgHQBMAGUAZwBh
# AGwAXwBwAG8AbABpAGMAeQBfAHMAdABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG
# 9w0BAQsFAAOCAgEAZ/KGpZjgVHkaLtPYdGcimwuWEeFjkplCln3SeQyQwWVfLiw+
# +MNy0W2D/r4/6ArKO79HqaPzadtjvyI1pZddZYSQfYtGUFXYDJJ80hpLHPM8QotS
# 0LD9a+M+By4pm+Y9G6XUtR13lDni6WTJRD14eiPzE32mkHSDjfTLJgJGKsKKELuk
# qQUMm+1o+mgulaAqPyprWEljHwlpblqYluSD9MCP80Yr3vw70L01724lruWvJ+3Q
# 3fMOr5kol5hNDj0L8giJ1h/DMhji8MUtzluetEk5CsYKwsatruWy2dsViFFFWDgy
# cScaf7H0J/jeLDogaZiyWYlobm+nt3TDQAUGpgEqKD6CPxNNZgvAs0314Y9/HG8V
# fUWnduVAKmWjw11SYobDHWM2l4bf2vP48hahmifhzaWX0O5dY0HjWwechz4GdwbR
# BrF1HxS+YWG18NzGGwS+30HHDiju3mUv7Jf2oVyW2ADWoUa9WfOXpQlLSBCZgB/Q
# ACnFsZulP0V3HjXG0qKin3p6IvpIlR+r+0cjgPWe+L9rt0uX4ut1eBrs6jeZeRhL
# /9azI2h15q/6/IvrC4DqaTuv/DDtBEyO3991bWORPdGdVk5Pv4BXIqF4ETIheu9B
# CrE/+6jMpF3BoYibV3FWTkhFwELJm3ZbCoBIa/15n8G9bW1qyVJzEw16UM0xghXl
# MIIV4QIBATCBlTB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ
# MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
# MSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExAhMzAAAA
# ZEeElIbbQRk4AAAAAABkMA0GCWCGSAFlAwQCAQUAoIHWMBkGCSqGSIb3DQEJAzEM
# BgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqG
# SIb3DQEJBDEiBCCJte6oRLPIlV+M013iuuSDbruTnuTSLD0K4RFc49UUNjBqBgor
# BgEEAYI3AgEMMVwwWqAugCwAVwBpAG4AZABvAHcAcwAgAFAAaABvAG4AZQAgAFAA
# YQBjAGsAYQBnAGUAc6EogCZodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vd2luZG93
# c3Bob25lLzANBgkqhkiG9w0BAQEFAASCAQBFziKgxXTMJFnlGD/5RsdifmVfg3lO
# cpTX/Z/HZWbNvbDzILcNf9xFdk43UH57GdFdtDvzDqyd7p5hLMYq6bSmfYuDVFkk
# wWnz/HCMxyDKe4to8Ks08sJw9jiqp5l1QK/ZEqcK4Bfa5ODgkDR7mUZm6j/C58Ts
# mWqo7xL6UNmGGYhb4zTy+oLY8EeF0fqj2uE7OzZ9ZioPW3HBKFdxDkLAspHsYnmy
# BD5fXDzVWmVnu/RKyGGCmvADNbU6+frS+Qm0wjORSpYhYRpvMeq/w1IywX6JQbT4
# C/xBst8ATPrQwQSjnV5Tu0atQaHo1j3AhhOJagtKDutM9sF0yjJfjTLEoYITRzCC
# E0MGCisGAQQBgjcDAwExghMzMIITLwYJKoZIhvcNAQcCoIITIDCCExwCAQMxDzAN
# BglghkgBZQMEAgEFADCCATwGCyqGSIb3DQEJEAEEoIIBKwSCAScwggEjAgEBBgor
# BgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIJT7hViw42GAXjjVweNy6sn0LP1o
# ZXE8KHP+wXfKKD0mAgZW7BuTuWAYEzIwMTYwNDA2MDQxNDA5Ljc4N1owBwIBAYAC
# AfSggbikgbUwgbIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMQ8w
# DQYDVQQHEwZSZWRtb2QxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEN
# MAsGA1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOjMxQzUtMzBC
# QS03QzkxMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIO
# yzCCBnEwggRZoAMCAQICCmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jv
# c29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIx
# MzY1NVoXDTI1MDcwMTIxNDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw
# MTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX
# 9fp/aZRrdFQQ1aUKAIKF++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkT
# jnxhMFmxMEQP8WCIhFRDDNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG
# 8lhHhjKEHnRhZ5FfgVSxz5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGK
# r0tkiVBisV39dx898Fd1rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6
# Kgox8NpOBpG2iAg16HgcsOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEF
# TyJNAgMBAAGjggHmMIIB4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6
# XIoxkPNDe3xGG8UzaFqFbVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYD
# VR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxi
# aNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3Nv
# ZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMu
# Y3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNy
# b3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQw
# gaAGA1UdIAEB/wSBlTCBkjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFo
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRt
# MEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0
# AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/
# gXEDPZ2joSFvs+umzPUxvs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtU
# VwgrUYJEEvu5U4zM9GASinbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9
# Wj8c8pl5SpFSAK84Dxf1L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9
# BOFwnzJKJ/1Vry/+tuWOM7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOd
# eyFtw5yjojz6f32WapB4pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1
# JeVk7Pf0v35jWSUPei45V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4Ttx
# Cd9ddJgiCGHasFAeb73x4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5
# u+zGy9iCtHLNHfS4hQEegPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9U
# JyH3yKxO2ii4sanblrKnQqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Z
# ta7cRDyXUHHXodLFVeNp3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa
# 7wknHNWzfjUeCLraNtvTX4/edIhJEjCCBNkwggPBoAMCAQICEzMAAAB0dMytqT58
# tawAAAAAAHQwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB
# IDIwMTAwHhcNMTUxMDA3MTgxNzM5WhcNMTcwMTA3MTgxNzM5WjCBsjELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xDzANBgNVBAcTBlJlZG1vZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMQ0wCwYDVQQLEwRNT1BSMScwJQYD
# VQQLEx5uQ2lwaGVyIERTRSBFU046MzFDNS0zMEJBLTdDOTExJTAjBgNVBAMTHE1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0GCSqGSIb3DQEBAQUAA4IB
# DwAwggEKAoIBAQCrQ9hj5aNBD+U6BpGjkyCtvSqu2617TahYXzoFCcFLWEIXOiSO
# bajdReSUUjDifvYwFqwgBJF8d3lNtJOevnoTan1oxPFCM9jUZY0ovCdTcpwHAlYE
# iRbio2AHTpY71lPK8RUiOj/ykaDD24nLaeoy/z80RvwZpZIbzIzcrKT3zZWx+WyU
# WPPYoVNoDZcwC5hpFn4joHSv6ETznvmT1ONotWrfljgkXqFl9mfJrbDZ+IB/crdT
# ZiuHAqAICrr7jZkFX9C/jRhNvy8fYzyUsedjXAnG6rSutMkRPMfNyvfeODR2/Ysk
# ETlA+X7qva73xEpewcFTlKFrYLzGRO+xM9rJAgMBAAGjggEbMIIBFzAdBgNVHQ4E
# FgQUNMasUoon09Mel78MA3V3SrrY5DEwHwYDVR0jBBgwFoAU1WM6XIoxkPNDe3xG
# G8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQu
# Y29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGltU3RhUENBXzIwMTAtMDctMDEuY3Js
# MFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3Nv
# ZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQQ0FfMjAxMC0wNy0wMS5jcnQwDAYD
# VR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG9w0BAQsFAAOC
# AQEAWZGMLsOoqIdDRRqOmZPIRG60cJFTSE8ntfhG11xuLIsuTgheIl1kUfXaJonV
# 7hN7jLG46h4B34A2FQKLw9DovWasW5HNLzxIV6ovMUUDCy8MuIxUo0yekudg5XCK
# /hCAUI+KTlBar3EXTvG0hbAyClFScQhw5AysijMGNNPE4zQfjigb4XEDQ+vp20Di
# 1rVJxmCjlhFIEKTVciqxLvdH6uMr27hKuvAjEBq4R0y10qUssUo6xNY/jl8/nveQ
# /43lLOBu99t7cdENKIoTvLJvmibAvIhZm+XPFx1ZiKH+MCoAsw5A0xsHVJ6Zy/pD
# rOxV0JtOzZmz7ByCiNlgO+DoEqGCA3UwggJdAgEBMIHioYG4pIG1MIGyMQswCQYD
# VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEPMA0GA1UEBxMGUmVkbW9kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xDTALBgNVBAsTBE1PUFIxJzAl
# BgNVBAsTHm5DaXBoZXIgRFNFIEVTTjozMUM1LTMwQkEtN0M5MTElMCMGA1UEAxMc
# TWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIlCgEBMAkGBSsOAwIaBQADFQAQ
# dgasogBQhFCmlXN/GcSXThEe+KCBwjCBv6SBvDCBuTELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9QUjEnMCUGA1UECxMebkNp
# cGhlciBOVFMgRVNOOjU3RjYtQzFFMC01NTRDMSswKQYDVQQDEyJNaWNyb3NvZnQg
# VGltZSBTb3VyY2UgTWFzdGVyIENsb2NrMA0GCSqGSIb3DQEBBQUAAgUA2q7V3TAi
# GA8yMDE2MDQwNjAwMjUwMVoYDzIwMTYwNDA3MDAyNTAxWjB0MDoGCisGAQQBhFkK
# BAExLDAqMAoCBQDartXdAgEAMAcCAQACAheuMAcCAQACAhp/MAoCBQDasCddAgEA
# MDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwGgCjAIAgEAAgMW42ChCjAI
# AgEAAgMHoSAwDQYJKoZIhvcNAQEFBQADggEBADlgF2QmmREIN6ZBHprCM210tnNR
# dQrjUTBH8JCqb90loNHufwz+XY+afZOtwYPNd20i9Uj6O5vWyqNLDsXbS0GP1jsX
# TzdXaVzxyb5i3m4/87lQx+bpmRtP2PCWjTIX0v64hn9AWMXO7012M7IIlxkdEmK5
# REZiA3ZQrPRJjYJSAHjokuSVR8/Nb24l26ZSR0a7dMPB66jT1JufHX31dGD3pgcz
# Xima6FfauV54Fd0DXDwqkFn/aT9X4fD33OX2CbYg0LqSKBguFJu+cW9Sc/nUzEju
# Rf92CIRlbty3D93314BXLK9xRs7F9R6hoM3DDBMZapgbED91ccZLvDozHPExggL1
# MIIC8QIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ
# MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
# MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAHR0
# zK2pPny1rAAAAAAAdDANBglghkgBZQMEAgEFAKCCATIwGgYJKoZIhvcNAQkDMQ0G
# CyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCBRgAM8RbvpkXFBFFwsWkT0Z8LV
# EpG1rKs0N96VWR3UnDCB4gYLKoZIhvcNAQkQAgwxgdIwgc8wgcwwgbEEFBB2Bqyi
# AFCEUKaVc38ZxJdOER74MIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB
# IDIwMTACEzMAAAB0dMytqT58tawAAAAAAHQwFgQUObq0eNEndsfP7lSLscWPR0VD
# C/0wDQYJKoZIhvcNAQELBQAEggEAh4h/0l1UX296F/DDMtTI1UCqiUnm+O6oyUXJ
# lMjcIrrLwx2Sut4be/dH9INiKl/EsDP5o7TDBdso1zyN9GKhiBhFmYKwWIlqB8kN
# U7FPJSnlpH1ccJ2osuLQCM6OHetwE13Fdb4M/Esu2OOo6unvpaPE6KGPSfEEAT6U
# VZupphAongSA5fX90qJsN6BkpECj2UZU1dtbEgWPy468ZPxHIc1Rugpz0r1Wy0gx
# u3u3RKVaGZxB63NXXXMu/S21z1B9//rjK2QzKGGgcVoaTvtte5gVxbMuLPxZq5v/
# oNAXX31dVyYoRcSH/V/l9CFSDWo8WIl1/VXYEGvRQ32D5MkV0w==
# SIG # End signature block
