Public/New-ISOImageFile.ps1

function New-ISOImageFile {
    <#
    .SYNOPSIS
        Creates an ISO image from a source directory.

    .DESCRIPTION
        Creates an ISO image file from the contents of a specified source directory.

    .PARAMETER SourcePath
        Path to the source directory to include in the image.

    .PARAMETER DestinationPath
        Path to the ISO file to create.

    .PARAMETER VolumeLabel
        Volume label for the ISO image.

    .PARAMETER IncludeSourceDirectory
        When specified, the source directory itself is added as a subfolder at the ISO root.
        By default only the contents of the source directory are added.

    .PARAMETER Force
        Overwrites an existing ISO file at the destination path.
        Note: when used together with -Confirm, -Force is treated as explicit consent to overwrite the file, so it
        is removed without an additional confirmation prompt.

    .PARAMETER BufferSizeMultiplier
        Number of blocks to read per IStream.Read call; higher values use more memory but may reduce overhead.

    .PARAMETER MediaType
        The media type determines the default file system and free media blocks size for the image.
        Accepts any member of the WritableImapiMediaType enum; non-writable types are excluded.
        The default media type value is 'IMAPI_MEDIA_TYPE_CDR' (which represents CD-R).

        See the following link for currently known media types supported by IMAPI:
        https://learn.microsoft.com/en-us/windows/win32/api/imapi2/ne-imapi2-imapi_media_physical_type

    .EXAMPLE
        New-ISOImageFile -SourcePath 'C:\Files' -DestinationPath 'C:\Output\image.iso'

        Creates an ISO from the contents of C:\Files and writes it to C:\Output\image.iso.

    .EXAMPLE
        New-ISOImageFile -SourcePath 'C:\Files' -DestinationPath 'C:\Output\image.iso' -VolumeLabel 'MYDISC' -Force

        Creates an ISO with the volume label MYDISC, overwriting the destination file if it already exists.

    .EXAMPLE
        New-ISOImageFile -SourcePath 'C:\Files' -DestinationPath 'C:\Output\image.iso' -IncludeSourceDirectory

        Creates an ISO where the 'Files' folder itself appears at the ISO root, rather than only its contents.

    .INPUTS
        None.

    .OUTPUTS
        System.IO.FileInfo
    #>


    [OutputType([System.IO.FileInfo])]
    # h/t to PSScriptAnalyzer
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory)]
        [ValidateScript({Test-Path -LiteralPath $_ -PathType Container })]
        [string]$SourcePath,
        [Parameter(Mandatory)]
        [ValidateScript({Test-Path -LiteralPath (Split-Path -Path $_ -Parent) -PathType Container })]
        [string]$DestinationPath,
        [string]$VolumeLabel = 'cidata',
        [switch]$IncludeSourceDirectory,
        [switch]$Force,
        [int]$BufferSizeMultiplier = 64,
        [WritableImapiMediaType]$MediaType = 'IMAPI_MEDIA_TYPE_CDR'
    )

    $ISOFileExists = Test-Path -LiteralPath $DestinationPath -PathType Leaf

    if ($ISOFileExists) {
        if (-not $Force.IsPresent) {
            $ErrorMessage = 'The ISO file already exists at [{0}]. Use -Force to overwrite.' -f $DestinationPath
            $Exception = [System.IO.IOException]::new($ErrorMessage)
            $ErrorRecord = [System.Management.Automation.ErrorRecord]::new(
                $Exception,
                'ISOFileAlreadyExists',
                [System.Management.Automation.ErrorCategory]::ResourceExists,
                $DestinationPath
            )
            $PSCmdlet.ThrowTerminatingError($ErrorRecord)
        }
        else {
            # ShouldProcess safeguard.
            if ($PSCmdlet.ShouldProcess($DestinationPath, 'Remove existing ISO')) {
                # '-Confirm:false' here is needed to prevent an additional confirmation prompt when -Confirm is
                # specified.
                Remove-Item -LiteralPath $DestinationPath -Force -ErrorAction Stop -Confirm:$false
            }
            else {
                # note: this code block should run only when the -Confirm switch is specified and the user
                # declines the removal of the existing file, hence the $WhatIfPreference check.
                if (-not $WhatIfPreference) {
                    # throw an exception to stop the script execution, as the script cannot proceed without a
                    # valid destination path for the new ISO file.
                    $ErrorMessage = 'Overwrite of existing ISO at [{0}] was declined by the user. No file changes were made.' -f $DestinationPath
                    $Exception = [System.OperationCanceledException]::new($ErrorMessage)
                    $ErrorRecord = [System.Management.Automation.ErrorRecord]::new(
                        $Exception,
                        'ISOOverwriteDeclined',
                        [System.Management.Automation.ErrorCategory]::OperationStopped,
                        $DestinationPath
                    )
                    $PSCmdlet.ThrowTerminatingError($ErrorRecord)
                }
            }
        }
    }

    # ShouldProcess safeguard.
    # if -WhatIf switch is specified, no ISO creation or file system changes will occur; only the emitted messages
    # will indicate the intended actions.
    # if -Confirm is specified, the user will be prompted to confirm the removal of existing ISO file (if any) and
    # the creation of the new ISO file. If the user declines, script will exit without creating the file.
    if ($PSCmdlet.ShouldProcess($DestinationPath, 'Create ISO image')) {

        $ImageObject = $null
        $ResultImage = $null

        try {

            # create an optical disk file system layout object
            $ImageObject = New-Object -ComObject IMAPI2FS.MsftFileSystemImage

            # set its properties
            $ImageObject.VolumeName = $VolumeLabel

            # set the media type (this determines the default file system and free media blocks size)
            $ImageObject.ChooseImageDefaultsForMediaType([int]$MediaType)

            # map the source directory structure into the optical disk file system layout.
            # '$IncludeSourceDirectory' switch controls whether the source directory itself appears as a subfolder
            # at the ISO root ($true) or only its contents are added ($false).
            $ImageObject.Root.AddTree($SourcePath, $IncludeSourceDirectory.IsPresent)

            # generates the burnable image stream from the layout, which is stored in memory as a COM IStream object.
            # the object contains the image stream, block size, and block count.
            $ResultImage = $ImageObject.CreateResultImage()

            # call the Create method of the ISOHelper class to write the ISO file to disk.
            # read the image stream block by block and write it to the output file.
            [ISOHelper]::Create($DestinationPath, $ResultImage.ImageStream, $ResultImage.BlockSize, $ResultImage.TotalBlocks, $BufferSizeMultiplier)

            # check if the file was created successfully and return a FileInfo object for the created ISO file.
            $ISOFileCreated = Test-Path -LiteralPath $DestinationPath -PathType Leaf
            if ($ISOFileCreated) {
                Get-Item -LiteralPath $DestinationPath
            }
            else {
                $ErrorMessage = 'Failed to create the ISO file at [{0}].' -f $DestinationPath
                Write-Error -Message $ErrorMessage
            }
        }
        catch {
            Write-Error -ErrorRecord $_
        }
        finally {
            # release COM objects to free unmanaged resources
            if ($null -ne $ResultImage) {
                $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($ResultImage)
            }
            if ($null -ne $ImageObject) {
                $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($ImageObject)
            }
        }
    }
}

# SIG # Begin signature block
# MIIpJwYJKoZIhvcNAQcCoIIpGDCCKRQCAQExDzANBglghkgBZQMEAgIFADCBiQYK
# KwYBBAGCNwIBBKB7MHkwNAYKKwYBBAGCNwIBHjAmAgMBAAAEEB/MO2BZSwhOtyTS
# xil+81ECAQACAQACAQACAQACAQAwQTANBglghkgBZQMEAgIFAAQwxKVME2Hn3cox
# pH0glhObnwP1gbQ0Ott1gR0t7vtMJKl6rscYi9O3c/zv9Fr2CwvpoIIMXTCCBhow
# ggQCoAMCAQICEGIdbQxSAZ47kHkVIIkhHAowDQYJKoZIhvcNAQEMBQAwVjELMAkG
# A1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEtMCsGA1UEAxMkU2Vj
# dGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIFJvb3QgUjQ2MB4XDTIxMDMyMjAwMDAw
# MFoXDTM2MDMyMTIzNTk1OVowVDELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3Rp
# Z28gTGltaXRlZDErMCkGA1UEAxMiU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5n
# IENBIFIzNjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJsrnVP6NT+O
# YAZDasDP9X/2yFNTGMjO02x+/FgHlRd5ZTMLER4ARkZsQ3hAyAKwktlQqFZOGP/I
# +rLSJJmFeRno+DYDY1UOAWKA4xjMHY4qF2p9YZWhhbeFpPb09JNqFiTCYy/Rv/ze
# dt4QJuIxeFI61tqb7/foXT1/LW2wHyN79FXSYiTxcv+18Irpw+5gcTbXnDOsrSHV
# JYdPE9s+5iRF2Q/TlnCZGZOcA7n9qudjzeN43OE/TpKF2dGq1mVXn37zK/4oiETk
# gsyqA5lgAQ0c1f1IkOb6rGnhWqkHcxX+HnfKXjVodTmmV52L2UIFsf0l4iQ0UgKJ
# Uc2RGarhOnG3B++OxR53LPys3J9AnL9o6zlviz5pzsgfrQH4lrtNUz4Qq/Va5MbB
# wuahTcWk4UxuY+PynPjgw9nV/35gRAhC3L81B3/bIaBb659+Vxn9kT2jUztrkmep
# /aLb+4xJbKZHyvahAEx2XKHafkeKtjiMqcUf/2BG935A591GsllvWwIDAQABo4IB
# ZDCCAWAwHwYDVR0jBBgwFoAUMuuSmv81lkgvKEBCcCA2kVwXheYwHQYDVR0OBBYE
# FA8qyyCHKLjsb0iuK1SmKaoXpM0MMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8E
# CDAGAQH/AgEAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYEVR0g
# ADAIBgZngQwBBAEwSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybC5zZWN0aWdv
# LmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290UjQ2LmNybDB7BggrBgEF
# BQcBAQRvMG0wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2Vj
# dGlnb1B1YmxpY0NvZGVTaWduaW5nUm9vdFI0Ni5wN2MwIwYIKwYBBQUHMAGGF2h0
# dHA6Ly9vY3NwLnNlY3RpZ28uY29tMA0GCSqGSIb3DQEBDAUAA4ICAQAG/4Lhd2M2
# bnuhFSCbE/8E/ph1RGHDVpVx0ZE/haHrQECxyNbgcv2FymQ5PPmNS6Dah66dtgCj
# BsULYAor5wxxcgEPRl05pZOzI3IEGwwsepp+8iGsLKaVpL3z5CmgELIqmk/Q5zFg
# R1TSGmxqoEEhk60FqONzDn7D8p4W89h8sX+V1imaUb693TGqWp3T32IKGfIgy9jk
# d7GM7YCa2xulWfQ6E1xZtYNEX/ewGnp9ZeHPsNwwviJMBZL4xVd40uPWUnOJUoSi
# ugaz0yWLODRtQxs5qU6E58KKmfHwJotl5WZ7nIQuDT0mWjwEx7zSM7fs9Tx6N+Q/
# 3+49qTtUvAQsrEAxwmzOTJ6Jp6uWmHCgrHW4dHM3ITpvG5Ipy62KyqYovk5O6cC+
# 040Si15KJpuQ9VJnbPvqYqfMB9nEKX/d2rd1Q3DiuDexMKCCQdJGpOqUsxLuCOuF
# OoGbO7Uv3RjUpY39jkkp0a+yls6tN85fJe+Y8voTnbPU1knpy24wUFBkfenBa+pR
# FHwCBB1QtS+vGNRhsceP3kSPNrrfN2sRzFYsNfrFaWz8YOdU254qNZQfd9O/VjxZ
# 2Gjr3xgANHtM3HxfzPYF6/pKK8EE4dj66qKKtm2DTL1KFCg/OYJyfrdLJq1q2/HX
# ntgr2GVw+ZWhrWgMTn8v1SjZsLlrgIfZHDCCBjswggSjoAMCAQICEQCOb5nN9RcU
# vOdHUaKd3s+pMA0GCSqGSIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQK
# Ew9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUg
# U2lnbmluZyBDQSBSMzYwHhcNMjQxMDMxMDAwMDAwWhcNMjcxMDMxMjM1OTU5WjBR
# MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxGDAWBgNVBAoMD1NlcnZlcnMu
# Y29tIEluYzEYMBYGA1UEAwwPU2VydmVycy5jb20gSW5jMIICIjANBgkqhkiG9w0B
# AQEFAAOCAg8AMIICCgKCAgEAvp24We3pIGAO3Vgmlu1/s/FmAOPUHB54iVPzo7rt
# 8OnKaNrf6rrACGGmy+/PAhG3S/pVhIcE3dMAMbsKy9OZzvhTOFpu7eNy2nox/NV4
# 3+4ohdhs395u4M884wCGBt34LFL6lAcxjMBiYD4F9eJ4SPzy1z4s7eeWeqmkrVpu
# C5w0J5UC9DcNkz1phxTLD5ZH4XVbBavHMWi2eMWr+SIB80NVrNpk5Zokx3PoHC92
# Ny5fFPE+xQqgVYokVmLA9/IAtw8kyMxS6uy1b7l9y435RTceHUUjCCQJx/DB73bv
# tZ4mLdUVGCMtAdjHrf//ZqzXEJODoYr0Be6GALtWzItEtNgLCwzEs3MbyLZ2o4jS
# aVNOUCZJT0Ybr3jGrjH40HiWtDKJkM5o21vHhXSwEj6FbP59WXZgz1wFwobGpwsy
# 16u0S6MtAErVTrFqjNU1QTBqQRngtN+1dUmzxbnCOOOM/J/EQHCILWuDqSSW+3Xm
# XIBmhOH6JNgRBYefFUOkXOzKHYWhou4e01Ek0iIXnIEevnX0Ot2W/EzPDnpBk0BE
# nroE9eV68lyIJPM6V0v5UTCtU84ueNCyRVwfrgFt/LpDt2k0c5MM913S+4CiX2NV
# 8CAO98ziPcrZKvoQ9Td6CQd1dWXl8WS4Elqdd1XFemVcukMmvbHqNUqKuWzsyVyb
# GN0CAwEAAaOCAYkwggGFMB8GA1UdIwQYMBaAFA8qyyCHKLjsb0iuK1SmKaoXpM0M
# MB0GA1UdDgQWBBSv2va0R2h+vgq1aXEU2nHKmS3m5DAOBgNVHQ8BAf8EBAMCB4Aw
# DAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzBKBgNVHSAEQzBBMDUG
# DCsGAQQBsjEBAgEDAjAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29t
# L0NQUzAIBgZngQwBBAEwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5zZWN0
# aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQVIzNi5jcmwweQYIKwYB
# BQUHAQEEbTBrMEQGCCsGAQUFBzAChjhodHRwOi8vY3J0LnNlY3RpZ28uY29tL1Nl
# Y3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBUjM2LmNydDAjBggrBgEFBQcwAYYXaHR0
# cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggGBAHEbul2S+/ox
# 9Ircz1n8YqKwbk6T6YyCUcIn7Bz91BhIpgJVRd5n5pukFimCo6jWuLdCRkerv8bB
# NYkrjkWeg3tUwI2oT/yxuSbwmkfS5DQZ2WBBg4GEIDCRRfdyipJMQ8fk1/afHM8H
# 38edvzwfcXdqRbDxJODuZyU4ZOU7Witf8wrzOXhXUyg+4hr6gV24EZz8UbCqyKJP
# sxzqmON7TZg61uypGIcA8P0NUBatE3TDD9cJesv5t8+fDkiW/Hym9ziWiYIlw0N+
# 7nkiFUHrIJCtBCv7U4zz+xv9l40LglasVuEIornU0lt02XUOYNKc9vkx9V0wGeBW
# wKNDMln6f9LNZY3GNE+2lmY5UQq7LyMRQZABdkVq5sIEFy2STBmAN33NVoxZbmul
# 5uama9f8+maPbLQBkqPJLpnXT898DYiOl8ndZ9bfVnKFtv1KU5n637cdZNzt+gYz
# 9oV4YVZO0Wuwd5CYSNwmviz0fyLKtK5VsAA6/2W7fsdCePVedw502DGCHA8wghwL
# AgEBMGkwVDELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEr
# MCkGA1UEAxMiU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIFIzNgIRAI5v
# mc31FxS850dRop3ez6kwDQYJYIZIAWUDBAICBQCggYwwEAYKKwYBBAGCNwIBDDEC
# MAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwG
# CisGAQQBgjcCARUwPwYJKoZIhvcNAQkEMTIEMClxN0HTW8+jV/jfgmNQuAOfuhwt
# fTNR/Qk3I5pKagH6UzJ3lIsqFSWeHf7aILeUgDANBgkqhkiG9w0BAQEFAASCAgBJ
# NSffERUFL1RBJyYkAmir9RY6Ow6N4sttv+LfnYdjDbybBZ+tv7vallmO6A0kvghA
# /3ntQjU7651A5HY7VtXtEfBAoyPl9vbMxs4Pklw6vfqJly8ou0aq57FYUMMy5SMO
# eHxSgnp8JxG6+b+EMiiboTs3g6El37IbMeLs/IrzSQiCQJ3WcxHzQ8D9Xec9PvqI
# gXvayu8ZdRs3ZxQ/U19Kky/B6PGS3tW65isUcseevft29xyMTszqDNAZ4n5WcJWF
# ke8CwkGw9UpaCitTD7Z/F+V2m5xB4IrJXuyuzDHgcc/lsUcaoS3xz8XdO5kGeEWz
# zVL5WLqrWcAjMDqmUVzDZp/LXmqK3RBnS2I/tq4Jzqfih0AMI+E1gYcTPrBmL8ea
# hiUpomNg7nIB+ojIu5yS6HSiruNP92TqQNi00c6tcbCs37jTkK6hN6L/c24mVesa
# aaUklfVDZR+n+bos+1Pdlxq4zU9GV+BdZEHasee6geraEVLD/af0+5EDuabRvMwD
# GZBHjC5hfJC5xEeQ1s9S6bWZFRatPrTVQsuE1BjdOduK1cccBS5eclTcdMK1N4n0
# guo+9e66udOzSsfw4P+C5wpECec4eGQ+5AXFK8HhFRqsNogs8gqh1oDi1PBF/eC2
# OtKxCayLPjXMRckNoYpwk8mj4FOLC4NkYGtSov01iqGCGOgwghjkBgorBgEEAYI3
# AwMBMYIY1DCCGNAGCSqGSIb3DQEHAqCCGMEwghi9AgEDMQ8wDQYJYIZIAWUDBAIC
# BQAwggEHBgsqhkiG9w0BCRABBKCB9wSB9DCB8QIBAQYKKwYBBAGyMQIBATBBMA0G
# CWCGSAFlAwQCAgUABDB/Rn7k8XlwcdbP48Khs3VzvuYrBH7lUxyHEKg/YX3sVuy0
# 2muLSM5KsCY4Nse9li8CFCGQ32foPBY6vnkmdkb3w4g15caeGA8yMDI2MDUxMTA5
# MjQwNlqgdqR0MHIxCzAJBgNVBAYTAkdCMRcwFQYDVQQIEw5XZXN0IFlvcmtzaGly
# ZTEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTAwLgYDVQQDEydTZWN0aWdvIFB1
# YmxpYyBUaW1lIFN0YW1waW5nIFNpZ25lciBSMzagghMEMIIGYjCCBMqgAwIBAgIR
# AKQpO24e3denNAiHrXpOtyQwDQYJKoZIhvcNAQEMBQAwVTELMAkGA1UEBhMCR0Ix
# GDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEsMCoGA1UEAxMjU2VjdGlnbyBQdWJs
# aWMgVGltZSBTdGFtcGluZyBDQSBSMzYwHhcNMjUwMzI3MDAwMDAwWhcNMzYwMzIx
# MjM1OTU5WjByMQswCQYDVQQGEwJHQjEXMBUGA1UECBMOV2VzdCBZb3Jrc2hpcmUx
# GDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEwMC4GA1UEAxMnU2VjdGlnbyBQdWJs
# aWMgVGltZSBTdGFtcGluZyBTaWduZXIgUjM2MIICIjANBgkqhkiG9w0BAQEFAAOC
# Ag8AMIICCgKCAgEA04SV9G6kU3jyPRBLeBIHPNyUgVNnYayfsGOyYEXrn3+SkDYT
# Ls1crcw/ol2swE1TzB2aR/5JIjKNf75QBha2Ddj+4NEPKDxHEd4dEn7RTWMcTIfm
# 492TW22I8LfH+A7Ehz0/safc6BbsNBzjHTt7FngNfhfJoYOrkugSaT8F0IzUh6VU
# woHdYDpiln9dh0n0m545d5A5tJD92iFAIbKHQWGbCQNYplqpAFasHBn77OqW37P9
# BhOASdmjp3IijYiFdcA0WQIe60vzvrk0HG+iVcwVZjz+t5OcXGTcxqOAzk1frDNZ
# 1aw8nFhGEvG0ktJQknnJZE3D40GofV7O8WzgaAnZmoUn4PCpvH36vD4XaAF2CjiP
# sJWiY/j2xLsJuqx3JtuI4akH0MmGzlBUylhXvdNVXcjAuIEcEQKtOBR9lU4wXQpI
# SrbOT8ux+96GzBq8TdbhoFcmYaOBZKlwPP7pOp5Mzx/UMhyBA93PQhiCdPfIVOCI
# NsUY4U23p4KJ3F1HqP3H6Slw3lHACnLilGETXRg5X/Fp8G8qlG5Y+M49ZEGUp2bn
# eRLZoyHTyynHvFISpefhBCV0KdRZHPcuSL5OAGWnBjAlRtHvsMBrI3AAA0Tu1oGv
# Pa/4yeeiAyu+9y3SLC98gDVbySnXnkujjhIh+oaatsk/oyf5R2vcxHahajMCAwEA
# AaOCAY4wggGKMB8GA1UdIwQYMBaAFF9Y7UwxeqJhQo1SgLqzYZcZojKbMB0GA1Ud
# DgQWBBSIYYyhKjdkgShgoZsx0Iz9LALOTzAOBgNVHQ8BAf8EBAMCBsAwDAYDVR0T
# AQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDBKBgNVHSAEQzBBMDUGDCsG
# AQQBsjEBAgEDCDAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQ
# UzAIBgZngQwBBAIwSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2NybC5zZWN0aWdv
# LmNvbS9TZWN0aWdvUHVibGljVGltZVN0YW1waW5nQ0FSMzYuY3JsMHoGCCsGAQUF
# BwEBBG4wbDBFBggrBgEFBQcwAoY5aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0
# aWdvUHVibGljVGltZVN0YW1waW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdodHRw
# Oi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAYEAAoE+pIZyUSH5
# ZakuPVKK4eWbzEsTRJOEjbIu6r7vmzXXLpJx4FyGmcqnFZoa1dzx3JrUCrdG5b//
# LfAxOGy9Ph9JtrYChJaVHrusDh9NgYwiGDOhyyJ2zRy3+kdqhwtUlLCdNjFjakTS
# E+hkC9F5ty1uxOoQ2ZkfI5WM4WXA3ZHcNHB4V42zi7Jk3ktEnkSdViVxM6rduXW0
# jmmiu71ZpBFZDh7Kdens+PQXPgMqvzodgQJEkxaION5XRCoBxAwWwiMm2thPDuZT
# zWp/gUFzi7izCmEt4pE3Kf0MOt3ccgwn4Kl2FIcQaV55nkjv1gODcHcD9+ZVjYZo
# yKTVWb4VqMQy/j8Q3aaYd/jOQ66Fhk3NWbg2tYl5jhQCuIsE55Vg4N0DUbEWvXJx
# txQQaVR5xzhEI+BjJKzh3TQ026JxHhr2fuJ0mV68AluFr9qshgwS5SpN5FFtaSEn
# AwqZv3IS+mlG50rK7W3qXbWwi4hmpylUfygtYLEdLQukNEX1jiOKMIIGFDCCA/yg
# AwIBAgIQeiOu2lNplg+RyD5c9MfjPzANBgkqhkiG9w0BAQwFADBXMQswCQYDVQQG
# EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVTZWN0aWdv
# IFB1YmxpYyBUaW1lIFN0YW1waW5nIFJvb3QgUjQ2MB4XDTIxMDMyMjAwMDAwMFoX
# DTM2MDMyMTIzNTk1OVowVTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28g
# TGltaXRlZDEsMCoGA1UEAxMjU2VjdGlnbyBQdWJsaWMgVGltZSBTdGFtcGluZyBD
# QSBSMzYwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDNmNhDQatugivs
# 9jN+JjTkiYzT7yISgFQ+7yavjA6Bg+OiIjPm/N/t3nC7wYUrUlY3mFyI32t2o6Ft
# 3EtxJXCc5MmZQZ8AxCbh5c6WzeJDB9qkQVa46xiYEpc81KnBkAWgsaXnLURoYZzk
# sHIzzCNxtIXnb9njZholGw9djnjkTdAA83abEOHQ4ujOGIaBhPXG2NdV8TNgFWZ9
# BojlAvflxNMCOwkCnzlH4oCw5+4v1nssWeN1y4+RlaOywwRMUi54fr2vFsU5QPrg
# b6tSjvEUh1EC4M29YGy/SIYM8ZpHadmVjbi3Pl8hJiTWw9jiCKv31pcAaeijS9fc
# 6R7DgyyLIGflmdQMwrNRxCulVq8ZpysiSYNi79tw5RHWZUEhnRfs/hsp/fwkXsyn
# u1jcsUX+HuG8FLa2BNheUPtOcgw+vHJcJ8HnJCrcUWhdFczf8O+pDiyGhVYX+bDD
# P3GhGS7TmKmGnbZ9N+MpEhWmbiAVPbgkqykSkzyYVr15OApZYK8CAwEAAaOCAVww
# ggFYMB8GA1UdIwQYMBaAFPZ3at0//QET/xahbIICL9AKPRQlMB0GA1UdDgQWBBRf
# WO1MMXqiYUKNUoC6s2GXGaIymzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgw
# BgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcDCDARBgNVHSAECjAIMAYGBFUdIAAw
# TAYDVR0fBEUwQzBBoD+gPYY7aHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdv
# UHVibGljVGltZVN0YW1waW5nUm9vdFI0Ni5jcmwwfAYIKwYBBQUHAQEEcDBuMEcG
# CCsGAQUFBzAChjtodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNU
# aW1lU3RhbXBpbmdSb290UjQ2LnA3YzAjBggrBgEFBQcwAYYXaHR0cDovL29jc3Au
# c2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIBABLXeyCtDjVYDJ6BHSVY/Uwt
# Z3Svx2ImIfZVVGnGoUaGdltoX4hDskBMZx5NY5L6SCcwDMZhHOmbyMhyOVJDwm1y
# rKYqGDHWzpwVkFJ+996jKKAXyIIaUf5JVKjccev3w16mNIUlNTkpJEor7edVJZiR
# JVCAmWAaHcw9zP0hY3gj+fWp8MbOocI9Zn78xvm9XKGBp6rEs9sEiq/pwzvg2/Kj
# XE2yWUQIkms6+yslCRqNXPjEnBnxuUB1fm6bPAV+Tsr/Qrd+mOCJemo06ldon4pJ
# FbQd0TQVIMLv5koklInHvyaf6vATJP4DfPtKzSBPkKlOtyaFTAjD2Nu+di5hErEV
# VaMqSVbfPzd6kNXOhYm23EWm6N2s2ZHCHVhlUgHaC4ACMRCgXjYfQEDtYEK54dUw
# PJXV7icz0rgCzs9VI29DwsjVZFpO4ZIVR33LwXyPDbYFkLqYmgHjR3tKVkhh9qKV
# 2WCmBuC27pIOx6TYvyqiYbntinmpOqh/QPAnhDgexKG9GX/n1PggkGi9HCapZp8f
# Rwg8RftwS21Ln61euBG0yONM6noD2XQPrFwpm3GcuqJMf0o8LLrFkSLRQNwxPDDk
# WXhW+gZswbaiie5fd/W2ygcto78XCSPfFWveUOSZ5SqK95tBO8aTHmEa4lpJVD7H
# rTEn9jb1EGvxOb1cnn0CMIIGgjCCBGqgAwIBAgIQNsKwvXwbOuejs902y8l1aDAN
# BgkqhkiG9w0BAQwFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJz
# ZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNU
# IE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBB
# dXRob3JpdHkwHhcNMjEwMzIyMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjBXMQswCQYD
# VQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVTZWN0
# aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIFJvb3QgUjQ2MIICIjANBgkqhkiG9w0B
# AQEFAAOCAg8AMIICCgKCAgEAiJ3YuUVnnR3d6LkmgZpUVMB8SQWbzFoVD9mUEES0
# QUCBdxSZqdTkdizICFNeINCSJS+lV1ipnW5ihkQyC0cRLWXUJzodqpnMRs46npiJ
# PHrfLBOifjfhpdXJ2aHHsPHggGsCi7uE0awqKggE/LkYw3sqaBia67h/3awoqNvG
# qiFRJ+OTWYmUCO2GAXsePHi+/JUNAax3kpqstbl3vcTdOGhtKShvZIvjwulRH87r
# bukNyHGWX5tNK/WABKf+Gnoi4cmisS7oSimgHUI0Wn/4elNd40BFdSZ1EwpuddZ+
# Wr7+Dfo0lcHflm/FDDrOJ3rWqauUP8hsokDoI7D/yUVI9DAE/WK3Jl3C4LKwIpn1
# mNzMyptRwsXKrop06m7NUNHdlTDEMovXAIDGAvYynPt5lutv8lZeI5w3MOlCybAZ
# DpK3Dy1MKo+6aEtE9vtiTMzz/o2dYfdP0KWZwZIXbYsTIlg1YIetCpi5s14qiXOp
# RsKqFKqav9R1R5vj3NgevsAsvxsAnI8Oa5s2oy25qhsoBIGo/zi6GpxFj+mOdh35
# Xn91y72J4RGOJEoqzEIbW3q0b2iPuWLA911cRxgY5SJYubvjay3nSMbBPPFsyl6m
# Y4/WYucmyS9lo3l7jk27MAe145GWxK4O3m3gEFEIkv7kRmefDR7Oe2T1HxAnICQv
# r9sCAwEAAaOCARYwggESMB8GA1UdIwQYMBaAFFN5v1qqK0rPVIDh2JvAnfKyA2bL
# MB0GA1UdDgQWBBT2d2rdP/0BE/8WoWyCAi/QCj0UJTAOBgNVHQ8BAf8EBAMCAYYw
# DwYDVR0TAQH/BAUwAwEB/zATBgNVHSUEDDAKBggrBgEFBQcDCDARBgNVHSAECjAI
# MAYGBFUdIAAwUAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC51c2VydHJ1c3Qu
# Y29tL1VTRVJUcnVzdFJTQUNlcnRpZmljYXRpb25BdXRob3JpdHkuY3JsMDUGCCsG
# AQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNv
# bTANBgkqhkiG9w0BAQwFAAOCAgEADr5lQe1oRLjlocXUEYfktzsljOt+2sgXke3Y
# 8UPEooU5y39rAARaAdAxUeiX1ktLJ3+lgxtoLQhn5cFb3GF2SSZRX8ptQ6IvuD3w
# z/LNHKpQ5nX8hjsDLRhsyeIiJsms9yAWnvdYOdEMq1W61KE9JlBkB20XBee6JaXx
# 4UBErc+YuoSb1SxVf7nkNtUjPfcxuFtrQdRMRi/fInV/AobE8Gw/8yBMQKKaHt5e
# ia8ybT8Y/Ffa6HAJyz9gvEOcF1VWXG8OMeM7Vy7Bs6mSIkYeYtddU1ux1dQLbEGu
# r18ut97wgGwDiGinCwKPyFO7ApcmVJOtlw9FVJxw/mL1TbyBns4zOgkaXFnnfzg4
# qbSvnrwyj1NiurMp4pmAWjR+Pb/SIduPnmFzbSN/G8reZCL4fvGlvPFk4Uab/JVC
# Smj59+/mB2Gn6G/UYOy8k60mKcmaAZsEVkhOFuoj4we8CYyaR9vd9PGZKSinaZIk
# vVjbH/3nlLb0a7SBIkiRzfPfS9T+JesylbHa1LtRV9U/7m0q7Ma2CQ/t392ioOss
# XW7oKLdOmMBl14suVFBmbzrt5V5cQPnwtd3UOTpS9oCG+ZZheiIvPgkDmA8FzPsn
# fXW5qHELB43ET7HHFHeRPRYrMBKjkb8/IN7Po0d0hQoF4TeMM+zYAJzoKQnVKOLg
# 8pZVPT8xggSSMIIEjgIBATBqMFUxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0
# aWdvIExpbWl0ZWQxLDAqBgNVBAMTI1NlY3RpZ28gUHVibGljIFRpbWUgU3RhbXBp
# bmcgQ0EgUjM2AhEApCk7bh7d16c0CIetek63JDANBglghkgBZQMEAgIFAKCCAfkw
# GgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNjA1
# MTEwOTI0MDZaMD8GCSqGSIb3DQEJBDEyBDA/0e6metupWdSWA8/PBYbUxUYr4t6U
# 76nwLvX6qNz4PjmV4dwJ2tctKfaFtJhRRYIwggF6BgsqhkiG9w0BCRACDDGCAWkw
# ggFlMIIBYTAWBBQ4yRSBEES03GY+k9R0S4FBhqm1sTCBhwQUxq5U5HiG8Xw9VRJI
# jGnDSnr5wt0wbzBbpFkwVzELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28g
# TGltaXRlZDEuMCwGA1UEAxMlU2VjdGlnbyBQdWJsaWMgVGltZSBTdGFtcGluZyBS
# b290IFI0NgIQeiOu2lNplg+RyD5c9MfjPzCBvAQUhT1jLZOCgmF80JA1xJHeksFC
# 2scwgaMwgY6kgYswgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5
# MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBO
# ZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0
# aG9yaXR5AhA2wrC9fBs656Oz3TbLyXVoMA0GCSqGSIb3DQEBAQUABIICAEbbQptg
# DF+NLfF7qA11lS7qQBeVNnrP5wwjceD7DtjzW04wg7/wZogLcrrhGEbN+s/ARoMk
# XEhWnWOza6Eb1ZH5v3j4xWs4fwkzwzp0rMccithHgoym4Ax09kKFT1+QKu5ByXpF
# 9PjNrs6BeA3LZLMKtG2twIznw2fUYW0WJDgtmEk7WRi/Q5Qg3JkeePVOPbbwENaa
# q9qIn4omp/OKuohWeAehK2PrYJWnzD1OY0xSbnPFruw6mygx99DimDDbnT4MbmYz
# N8pfYtYmgYTUwnfwoVzWCOsWGpo2RmLSZ3Travi6TWr0K1kYCPNDSsaZ9YRNIZy/
# OVk3BwYiCvmHKMeS7Vswj/p2FU8ceAmmJZH47ngNY7Jr6bPCJALvnxfsclAFz/lK
# X6r0LHuSDmnFsKYUBW0hGS2E14X07476oY+Rncf1WygSEqjFzEWAN3fQ36mQ6pDv
# zNtWR3aHtDh6gz3tBVqivfIgzaA03mSikxdA/Z1paWtGuMQHkiVZ8Xj7EunWxu9w
# ZtZXyt74jZigk2pXc8KpaBn2wXRztUDxRzaRoYlrmy6oRD23fK/r9EJ5LZTMeuDh
# FFxDDtHdW739NpbApfvXQluskkrgM4D7HEasKctc9irFJyDOltSYtn5NeNI+dX2T
# y3ROpYRiB5R8QA9RdotnqO9il/iM29LNQLhl
# SIG # End signature block