Host/Host.ps1

#region Copyright & License

# Copyright © 2012 - 2021 François Chabot
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#endregion

Set-StrictMode -Version Latest

enum HostType {
    InProcess = [Microsoft.BizTalk.ExplorerOM.HostType]::InProcess
    Isolated = [Microsoft.BizTalk.ExplorerOM.HostType]::Isolated
}

<#
.SYNOPSIS
    Asserts the existence of a Microsoft BizTalk Server Host of a given type.
.DESCRIPTION
    This command will throw if the Microsoft BizTalk Server Host does not exist and will silently complete otherwise.
    The asserted check can be narrowed down to a particular Type of Microsoft BizTalk Server Host, i.e. either
    InProcess or Isolated.
.PARAMETER Name
    The name of the Microsoft BizTalk Server Host.
.PARAMETER BizTalkHost
    The Microsoft BizTalk Server Host object.
.PARAMETER Type
    The type of the Microsoft BizTalk Server Host.
.EXAMPLE
    PS> Get-BizTalkHost | Assert-BizTalkHost -Type Isolated
.EXAMPLE
    PS> Assert-BizTalkHost -Host @(Get-BizTalkHost) -Type Isolated
.EXAMPLE
    PS> Assert-BizTalkHost -Name 'Transmit Host'
.EXAMPLE
    PS> Assert-BizTalkHost -Name 'Transmit Host' -Verbose
.NOTES
    © 2021 be.stateless.
#>

function Assert-BizTalkHost {
    [CmdletBinding(DefaultParameterSetName = 'by-filter')]
    [OutputType([void])]
    param(
        [Parameter(Mandatory = $true, ParameterSetName = 'by-filter')]
        [ArgumentCompleter( { Get-BizTalkHost | Select-Object -ExpandProperty Name } )]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $Name,

        [Parameter(Mandatory = $true, ParameterSetName = 'by-object', ValueFromPipeline = $true)]
        [Alias('Host')]
        [AllowEmptyCollection()]
        [object[]]
        $BizTalkHost,

        [Parameter(Mandatory = $false, ParameterSetName = 'by-filter')]
        [Parameter(Mandatory = $false, ParameterSetName = 'by-object')]
        [HostType]
        $Type
    )
    Begin {
        Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
        if ($PSCmdlet.ParameterSetName -eq 'by-filter') { $BizTalkHost = @(Enumerate-BizTalkHost -Name $Name -UserBoundParameters $PSBoundParameters -ErrorAction Stop -WarningAction SilentlyContinue) }
        $arguments = @{ }
        if ($PSBoundParameters.ContainsKey('Type')) { $arguments.Type = $Type }
    }
    Process {
        $BizTalkHost | Where-Object -FilterScript { $_ } -PipelineVariable currentHost | ForEach-Object -Process {
            $arguments.BizTalkHost = $currentHost
            if (-not(Test-BizTalkHost @arguments)) { throw ($hostMessages.Error_Type -f $currentHost.Name) }
        }
    }
}

<#
.SYNOPSIS
    Gets information about the Microsoft BizTalk Server Hosts.
.DESCRIPTION
    Gets either summary or detailed information about the Microsoft BizTalk Server Hosts.
.PARAMETER Name
    The name of the Microsoft BizTalk Server Host.
.PARAMETER Detailed
    To get detailed, instead of summary, information about the Microsoft BizTalk Server Hosts.
.OUTPUTS
    Returns information about the Microsoft BizTalk Server Hosts.
.EXAMPLE
    PS> Get-BizTalkHost
.EXAMPLE
    PS> Get-BizTalkHost | Where-Object { $_ | Test-BizTalkHost -Type InProcess }
.EXAMPLE
    PS> Get-BizTalkHost -Type InProcess
.EXAMPLE
    PS> Get-BizTalkHost -Name 'Transmit Host'
.EXAMPLE
    PS> Get-BizTalkHost -Name 'Transmit Host' -Detailed
.NOTES
    © 2021 be.stateless.
#>

function Get-BizTalkHost {
    [CmdletBinding()]
    [OutputType([PSCustomObject[]])]
    param(
        [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $Name,

        [Parameter(Mandatory = $false)]
        [switch]
        $Detailed,

        [Parameter(Mandatory = $false)]
        [HostType]
        $Type
    )
    Begin {
        Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
    }
    Process {
        Enumerate-BizTalkHost -Name $Name -Detailed:$Detailed -UserBoundParameters $PSBoundParameters -ErrorAction SilentlyContinue -WarningAction SilentlyContinue |
            Where-Object -FilterScript { [bool]$_ -and (-not $PSBoundParameters.ContainsKey('Type') -or $_.HostType -eq $Type) }
    }
}

<#
.SYNOPSIS
    Creates a new Microsoft BizTalk Server Host.
.DESCRIPTION
    Creates and configures a new Microsoft BizTalk Server Host.
.PARAMETER Name
    The name of the Microsoft BizTalk Server Host.
.PARAMETER Type
    The type of the Microsoft BizTalk Server Host, either InProcess or Isolated.
.PARAMETER Group
    The Windows Domain Group used to control access of this host.
.PARAMETER x86
    Whether instances of this host will be 32-bit only processes.
.PARAMETER Default
    Whether this host is to be the default host in the Microsoft BizTalk Server Group or not.
.PARAMETER Tracking
    Wheter to enable the Microsoft BizTalk Server Tracking component for this host or not.
.PARAMETER Trusted
    Whether Microsoft BizTalk Server should trust this host or not.
.EXAMPLE
    PS> New-BizTalkHost -Name 'Transmit Host' -Type InProcess -Group 'BizTalk Application Users'
.EXAMPLE
    PS> New-BizTalkHost -Name 'Transmit Host' -Type InProcess -Group 'BizTalk Application Users' -x86
.EXAMPLE
    PS> New-BizTalkHost -Name 'Transmit Host' -Type InProcess -Group 'BizTalk Application Users' -x86:$false
.EXAMPLE
    PS> New-BizTalkHost -Name 'Transmit Host' -Type InProcess -Group 'BizTalk Application Users' -Verbose
.EXAMPLE
    PS> New-BizTalkHost -Name 'Transmit Host' -Type InProcess -Group 'BizTalk Application Users' -WhatIf
.LINK
    https://msdn.microsoft.com/en-us/library/aa560467.aspx, Creating, Updating, and Deleting a Host Instance Using WMI
.NOTES
    © 2021 be.stateless.
#>

function New-BizTalkHost {
    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([void])]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,

        [Parameter(Mandatory = $true)]
        [HostType]
        $Type,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Group,

        [Parameter(Mandatory = $false)]
        [switch]
        $x86,

        [Parameter(Mandatory = $false)]
        [switch]
        $Default,

        [Parameter(Mandatory = $false)]
        [switch]
        $Tracking,

        [Parameter(Mandatory = $false)]
        [switch]
        $Trusted
    )
    Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
    if (Test-BizTalkHost -Name $Name -Type $Type) {
        Write-Information -MessageData ($hostMessages.Info_Existing -f $Type, $Name)
    } elseif (Test-BizTalkHost -Name $Name) {
        Write-Warning -Message ($hostMessages.Warn_Existing_Different_Type -f $Name)
    } elseif ($PsCmdlet.ShouldProcess($globalMessages.Should_Target, ($hostMessages.Should_Create -f $Type, $Name))) {
        Write-Information -MessageData ($hostMessages.Info_Creating -f $Type, $Name)
        $instanceClass = Get-CimClass -ErrorAction Stop -Namespace root/MicrosoftBizTalkServer -ClassName MSBTS_HostSetting
        $instance = New-CimInstance -ErrorAction Stop -CimClass $instanceClass -Property @{
            Name            = $Name
            HostType        = [Uint32]$Type
            NTGroupName     = $Group
            IsHost32BitOnly = [bool]$x86
            IsDefault       = [bool]$Default
            HostTracking    = [bool]$Tracking
            AuthTrusted     = [bool]$Trusted
        }
        Set-CimInstance -ErrorAction Stop -InputObject $instance
        Write-Information -MessageData ($hostMessages.Info_Created -f $Type, $Name)
    }
}

<#
.SYNOPSIS
    Removes a Microsoft BizTalk Server Host.
.DESCRIPTION
    Removes a Microsoft BizTalk Server Host.
.PARAMETER Name
    The name of the Microsoft BizTalk Server Host.
.PARAMETER BizTalkHost
    The Microsoft BizTalk Server Host object.
.EXAMPLE
    PS> Get-BizTalkHost | Remove-BizTalkHost
.EXAMPLE
    PS> Remove-BizTalkHost -Host @(Get-BizTalkHost)
.EXAMPLE
    PS> Remove-BizTalkHost -Name 'Transmit Host'
.NOTES
    © 2021 be.stateless.
#>

function Remove-BizTalkHost {
    [CmdletBinding(DefaultParameterSetName = 'by-filter', SupportsShouldProcess = $true)]
    [OutputType([void])]
    param(
        [Parameter(Mandatory = $true, ParameterSetName = 'by-filter')]
        [ArgumentCompleter( { Get-BizTalkHost | Select-Object -ExpandProperty Name } )]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $Name,

        [Parameter(Mandatory = $true, ParameterSetName = 'by-object', ValueFromPipeline = $true)]
        [Alias('Host')]
        [AllowEmptyCollection()]
        [object[]]
        $BizTalkHost
    )
    Begin {
        Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
        if ($PSCmdlet.ParameterSetName -eq 'by-filter') { $BizTalkHost = @(Enumerate-BizTalkHost -Name $Name -UserBoundParameters $PSBoundParameters -ErrorAction SilentlyContinue -WarningAction Continue) }
    }
    Process {
        $BizTalkHost | Where-Object -FilterScript { $_ } -PipelineVariable currentHost | ForEach-Object -Process {
            if ($PsCmdlet.ShouldProcess($globalMessages.Should_Target, ($hostMessages.Should_Remove -f $currentHost.Name))) {
                Write-Information -MessageData ($hostMessages.Info_Removing -f $currentHost.Name)
                Remove-CimInstance -ErrorAction Stop -InputObject $currentHost
                Write-Information -MessageData ($hostMessages.Info_Removed -f $currentHost.Name)
            }
        }
    }
}

<#
.SYNOPSIS
    Returns whether a Microsoft BizTalk Server Host of a given type exists.
.DESCRIPTION
    This command will return $true if the Microsoft BizTalk Server Host exists; $false otherwise. The existence test
    can be narrowed down to a particular Type of Microsoft BizTalk Server Host, i.e. either InProcess or Isolated.
.PARAMETER Name
    The name of the Microsoft BizTalk Server Host.
.PARAMETER BizTalkHost
    The Microsoft BizTalk Server Host object.
.PARAMETER Type
    The type of the Microsoft BizTalk Server Host.
.OUTPUTS
    $true if the Microsoft BizTalk Server Host exists and is of the given Type; $false otherwise.
.EXAMPLE
    PS> Get-BizTalkHost | Test-BizTalkHost -Type Isolated
.EXAMPLE
    PS> Test-BizTalkHost -Host @(Get-BizTalkHost) -Type Isolated
.EXAMPLE
    PS> Test-BizTalkHost -Name 'Transmit Host'
.EXAMPLE
    PS> Test-BizTalkHost -Name 'Transmit Host' -Type Isolated
.NOTES
    © 2021 be.stateless.
#>

function Test-BizTalkHost {
    [CmdletBinding(DefaultParameterSetName = 'by-filter')]
    [OutputType([bool[]])]
    param(
        [Parameter(Mandatory = $true, ParameterSetName = 'by-filter')]
        [ArgumentCompleter( { Get-BizTalkHost | Select-Object -ExpandProperty Name } )]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $Name,

        [Parameter(Mandatory = $true, ParameterSetName = 'by-object', ValueFromPipeline = $true)]
        [Alias('Host')]
        [AllowEmptyCollection()]
        [object[]]
        $BizTalkHost,

        [Parameter(Mandatory = $false, ParameterSetName = 'by-filter')]
        [Parameter(Mandatory = $false, ParameterSetName = 'by-object')]
        [HostType]
        $Type
    )
    Begin {
        Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
        if ($PSCmdlet.ParameterSetName -eq 'by-filter') { $BizTalkHost = @(Enumerate-BizTalkHost -Name $Name -UserBoundParameters $PSBoundParameters -ErrorAction SilentlyContinue -WarningAction SilentlyContinue) }
    }
    Process {
        $BizTalkHost | ForEach-Object -Process { $_ } -PipelineVariable currentHost | ForEach-Object -Process {
            [bool]$currentHost -and (-not $PSBoundParameters.ContainsKey('Type') -or $currentHost.HostType -eq $Type)
        }
    }
}

<#
.SYNOPSIS
    Updates the configuration settings of a Microsoft BizTalk Server Host.
.DESCRIPTION
    Updates the configuration settings of a Microsoft BizTalk Server Host.
.PARAMETER Name
    The name of the Microsoft BizTalk Server Host.
.PARAMETER BizTalkHost
    The Microsoft BizTalk Server Host object.
.PARAMETER x86
    Whether instances of this host will be 32-bit only processes.
.PARAMETER Default
    Whether this host is to be the default host in the Microsoft BizTalk Server group or not.
.PARAMETER Tracking
    Wheter to enable the Microsoft BizTalk Server Tracking component for this host or not.
.PARAMETER Trusted
    Whether Microsoft BizTalk Server should trust this host or not.
.EXAMPLE
    PS> Get-BizTalkHost | Update-BizTalkHost -x86
.EXAMPLE
    PS> Update-BizTalkHost -Host @(Get-BizTalkHost) -x86
.EXAMPLE
    PS> Update-BizTalkHost -Name 'Transmit Host' -x86 -Verbose
    With the -Verbose switch, this command will confirm this process is 32 bit.
.EXAMPLE
    PS> Update-BizTalkHost -Name 'Transmit Host' -x86 -Verbose -WhatIf
.EXAMPLE
    PS> Update-BizTalkHost -Name 'Transmit Host' -x86:$false -Verbose
    With the -Verbose switch, this command will confirm this process is not 32 bit.
.NOTES
    © 2021 be.stateless.
#>

function Update-BizTalkHost {
    [CmdletBinding(DefaultParameterSetName = 'by-filter', SupportsShouldProcess = $true)]
    [OutputType([void])]
    param(
        [Parameter(Mandatory = $true, ParameterSetName = 'by-filter')]
        [ArgumentCompleter( { Get-BizTalkHost | Select-Object -ExpandProperty Name } )]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $Name,

        [Parameter(Mandatory = $true, ParameterSetName = 'by-object', ValueFromPipeline = $true)]
        [Alias('Host')]
        [AllowEmptyCollection()]
        [object[]]
        $BizTalkHost,

        [Parameter(Mandatory = $false, ParameterSetName = 'by-filter')]
        [Parameter(Mandatory = $false, ParameterSetName = 'by-object')]
        [switch]
        $x86,

        [Parameter(Mandatory = $false, ParameterSetName = 'by-filter')]
        [Parameter(Mandatory = $false, ParameterSetName = 'by-object')]
        [switch]
        $Default,

        [Parameter(Mandatory = $false, ParameterSetName = 'by-filter')]
        [Parameter(Mandatory = $false, ParameterSetName = 'by-object')]
        [switch]
        $Tracking,

        [Parameter(Mandatory = $false, ParameterSetName = 'by-filter')]
        [Parameter(Mandatory = $false, ParameterSetName = 'by-object')]
        [switch]
        $Trusted
    )
    Begin {
        Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
        if ($PSCmdlet.ParameterSetName -eq 'by-filter') { $BizTalkHost = @(Enumerate-BizTalkHost -Name $Name -Detailed -UserBoundParameters $PSBoundParameters -ErrorAction SilentlyContinue -WarningAction Continue) }
    }
    Process {
        function Set-BizTalkHostProperty {
            [CmdletBinding(SupportsShouldProcess = $true)]
            [OutputType([void])]
            param(
                [Parameter(Mandatory = $true)]
                [object]
                $BizTalkHost,

                [Parameter(Mandatory = $true)]
                [string]
                $Property,

                [Parameter(Mandatory = $true)]
                [object]
                $Value,

                [Parameter(Mandatory = $true)]
                [string]
                $ActionToPerform,

                [Parameter(Mandatory = $true)]
                [string]
                $PerformedAction
            )
            if ($BizTalkHost.$Property -ne $value -and $PsCmdlet.ShouldProcess($globalMessages.Should_Target, $ActionToPerform)) {
                Write-Information -MessageData "`t $ActionToPerform..."
                $BizTalkHost.$Property = $Value
                Set-CimInstance -ErrorAction Stop -InputObject $BizTalkHost
                Write-Information -MessageData "`t $PerformedAction."
            }
        }

        $BizTalkHost | Where-Object -FilterScript { $_ } -PipelineVariable currentHost | ForEach-Object -Process {
            if (Get-Member -InputObject $currentHost -Name IsHost32BitOnly -ErrorAction Ignore | Test-None) { $currentHost = Get-BizTalkHost -Name $currentHost.Name -Detailed }
            if ($x86.IsPresent) {
                $subject = "'$($currentHost.Name)' host's 32-bit only restriction"
                Set-BizTalkHostProperty -BizTalkHost $currentHost -Property IsHost32BitOnly -Value $x86 `
                    -ActionToPerform ('{1} {0}' -f $Subject, (@('Enabling', 'Disabling')[!$x86])) `
                    -PerformedAction ('{0} has been {1}' -f $Subject, (@('enabled', 'disabled')[!$x86]))
            }

            if ($Default.IsPresent -and -not $currentHost.IsDefault) {
                Set-BizTalkHostProperty -BizTalkHost $currentHost -Property IsDefault -Value $Default `
                    -ActionToPerform "Defining '$($currentHost.Name)' host as default Microsoft BizTalk Server Group host" `
                    -PerformedAction "'$($currentHost.Name)' host has been defined as default Microsoft BizTalk Server Group host"
            }

            if ($Tracking.IsPresent) {
                $subject = "'$($currentHost.Name)' host's Tracking capability"
                Set-BizTalkHostProperty -BizTalkHost $currentHost -Property HostTracking -Value $Tracking `
                    -ActionToPerform ('{1} {0}' -f $Subject, (@('Enabling', 'Disabling')[!$Tracking])) `
                    -PerformedAction ('{0} has been {1}' -f $Subject, (@('enabled', 'disabled')[!$Tracking]))
            }

            if ($Trusted.IsPresent) {
                $subject = "'$($currentHost.Name)' host's Trusted Authentication"
                Set-BizTalkHostProperty -BizTalkHost $currentHost -Property AuthTrusted -Value $Trusted `
                    -ActionToPerform ('{1} {0}' -f $Subject, (@('Enabling', 'Disabling')[!$Trusted])) `
                    -PerformedAction ('{0} has been {1}' -f $Subject, (@('enabled', 'disabled')[!$Trusted]))
            }
        }
    }
}

function Enumerate-BizTalkHost {
    [Diagnostics.CodeAnalysis.SuppressMessage('PSUseApprovedVerbs', '', Justification = 'Non-public function.')]
    [CmdletBinding()]
    [OutputType([PSCustomObject[]])]
    param(
        [Parameter(Mandatory = $false)]
        [AllowEmptyString()]
        [AllowEmptyCollection()]
        [AllowNull()]
        [string[]]
        $Name,

        [Parameter(Mandatory = $false)]
        [switch]
        $Detailed,

        [Parameter(Mandatory = $true)]
        [HashTable]
        $UserBoundParameters
    )
    function Enumerate-BizTalkHostCore {
        [CmdletBinding()]
        [OutputType([PSCustomObject[]])]
        param(
            [Parameter(Mandatory = $false)]
            [AllowEmptyString()]
            [AllowEmptyCollection()]
            [AllowNull()]
            [string[]]
            $Name = '', # default value ensures its pipeline will run

            [Parameter(Mandatory = $false)]
            [switch]
            $Detailed
        )
        $className = if ($Detailed) { 'MSBTS_HostSetting' } else { 'MSBTS_Host' }
        $Name | ForEach-Object -Process { $_ } -PipelineVariable currentName | ForEach-Object -Process {
            $filter, $message = if (![string]::IsNullOrWhiteSpace($Name)) {
                "Name='$currentName'"
                $hostMessages.Error_Not_Found -f $currentName
            } else {
                $null
                $hostMessages.Error_None_Found
            }
            $instance = Get-CimInstance -ErrorAction Stop -Namespace root/MicrosoftBizTalkServer -ClassName $className -Filter $filter
            if ($null -eq $instance) {
                Write-Error -Message $message
                Write-Warning -Message $message
                $null
            } else {
                $instance
            }
        }
    }
    $arguments = @{ } + $PSBoundParameters
    $arguments.Remove('UserBoundParameters') | Out-Null
    if ($UserBoundParameters.ContainsKey('ErrorAction')) { $arguments.ErrorAction = $UserBoundParameters.ErrorAction }
    if ($UserBoundParameters.ContainsKey('WarningAction')) { $arguments.WarningAction = $UserBoundParameters.WarningAction }
    Enumerate-BizTalkHostCore @arguments
}

Import-LocalizedData -BindingVariable hostMessages -FileName Host.Messages.psd1

# SIG # Begin signature block
# MIII0QYJKoZIhvcNAQcCoIIIwjCCCL4CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUx+7WGvguEf4HOVPwSzDAUnKG
# JOmgggVMMIIFSDCCAzCgAwIBAgIJAJkr3mJdTBkUMA0GCSqGSIb3DQEBCwUAMEEx
# PzA9BgNVBAMeNgBpAGMAcgBhAGYAdABzAG8AZgB0AHcAYQByAGUAQABzAHQAYQB0
# AGUAbABlAHMAcwAuAGIAZTAeFw0yMTA2MjUxNDEyMjNaFw00MTA2MjAxNDEyMjNa
# MEExPzA9BgNVBAMeNgBpAGMAcgBhAGYAdABzAG8AZgB0AHcAYQByAGUAQABzAHQA
# YQB0AGUAbABlAHMAcwAuAGIAZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAOeqdUHBv7sxSeX3aj6yPKj7PAvs8izpVXjyEBl5aR8mQneVcXuF53AH7EW1
# 6E5p4+Az5pJPGUD5c3tXhiGMF7vgLhQjO6hlaVBRIqiIYHikNLwMNy6YBMc/QQYM
# rPhqHEFsZ53dkBIIj3M8e3kFcTFA09n25yDtTPDab4nd9yUhc9Qc8+nfpIzfYsoP
# 1pZ3nCzhw6hN2/44v1dkQrG3dRYwt+px65p6NPNZWEJpt4VCJjIFh+lBYJdxm9d4
# X/rAnlHIkbv7liOavWDzgHVabS3hdAWtcDmynm+7+FcZDFqPWNCl3e4SS7xe4s/R
# CKFKA0IsfKkSk9YJlLgeSQIEXUOOWXJAGaLqnRD8xWLZsc4Oi9GZg7XV1mv/S88c
# oztXnwtAN3OOlRKBh2QbomMgxeMO0GvsLE/cq5Q/YKAoz+KGr/7LcZq9jzQ8IPus
# ZvWLeDXmxPiwJjpZc1koLgfGIEX2NStQTT3QmacWr9thrWcKvI+4uBmI4exS9B4a
# R3nV91w5EY+2RoYsHqej9LWwNamO96+jMX9pxprTX+EkLUuMAikw/po8sBC9MUUn
# 5pMWmUv7DCtQOLGGBDDMMMkn4ZcjpCEEdPGHRKfqNnD27ssGtDjiNzfQrsm67toU
# bBwUF+gyJq/YckWquYJhA9ZOFWEADuIwGnsOzsoRvuQyY+p9AgMBAAGjQzBBMA4G
# A1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAzAXBgNVHREEEDAO
# ggxzdGF0ZWxlc3MuYmUwDQYJKoZIhvcNAQELBQADggIBACithYM3qckZRc9+Xbfu
# a6gWr3HwjrW+FHKgjfrcOm8ZnLVapb9xFqsqrRQqd3RXWQDINEGrtI2rSfrzyfoK
# UiTgldIfQNP1ZcGY229d++90t3hdo2mlt05hjYlbMENloJHpsEP0vQZmwOcEimCT
# ex1pymYM+P9pj3j8UD1PT1eIZot6or8fBRl63UybyDSrM7L4UOkkAOniKxWy5pW6
# 6duS8SR+SZpr3Bv44NyXPj0Nv+MIpLmsLrd7XPBFmnGxzY01ZO9vzi9KEhM2wT5i
# jPqHDNOvfPiADtAa+EyUBzdJiqy9heCz/TMZQgMWGwtfqJNxWZmsHcha2anW4Qt+
# mzrLO4GojWoVog9uVSAq+l0a+YQsd1u1kUmm4vgZCFyUA+lEp4LkI7ca2VBHkLPD
# w+u2DoDMRiqFPZjO7BCKjGc0jj9B/qGR3JVt+tqDdB621xXf2YGF2oFvxZQ/keGt
# 0ujfJ+JwN3nCulDAA4773q6KUnfykyrvAgITNbRJL6TngeRKtw9VIJBPxzqMzLpV
# 5ggXNituwLaD1CCBJ1oo9DZHpL9gplXp1wGrelJOTiJhh+pdNsPtRH7CrranWa5h
# LFLuigqin0eewQ5giJ1VaiBVEseOmiZog+27UpFIv40aDzgGL3YxB/Mu0ojwrQtp
# WLmqJCmWnR5qxOm0yK+zNWe0MYIC7zCCAusCAQEwTjBBMT8wPQYDVQQDHjYAaQBj
# AHIAYQBmAHQAcwBvAGYAdAB3AGEAcgBlAEAAcwB0AGEAdABlAGwAZQBzAHMALgBi
# AGUCCQCZK95iXUwZFDAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAA
# oQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4w
# DAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQU4Nw9QyykZj0Hl7l+g6JLtynX
# 2P0wDQYJKoZIhvcNAQEBBQAEggIAG9QMadxdvK9aK65bGJ+4spKxEkbMtgMI0/sZ
# y66D5BBIKRvRotFGJ04gGNLftMD0pefKY7OUR9jqNLC/MO1rVSEAll7iT6yhl0Wh
# YKjnTSWe9ThWd8jLZHL8z1sTbBJSfdLkUUDCnNClo4t8YZvTxj9n+w3gmK5h74e+
# dfe/cH2oJ583eaEvKtEB4VCkDiRV9cyw3CUMArf8ETIRR9qq7qSPL7TNujsnz2Bb
# JcFocbfoJdec86GgYYem7jO2Bn6XkOOLQLf7Jt9PfkailXaTU4et3e3dDyzwIYXx
# r4zLXUCwF9NzYlHJTB6FZB7FucVcwdMKK8KezhjFvshJibZVQpdh54uZmuLvqlG0
# qBVPnx8kBEJEU0ok5XttE6eodzt9TSOcuOArxJf/XybUgdizVWj90UEiVhku9UCK
# /eT72Y6v5Eb9Qpgn9Pu8E7KMeeAjNhWZc9JSFu9Yn/XFxlk0BklLaUnroT7x4ZFx
# 88Bbbt4TCp5wRX/G/t9zflcjxCY4sxv/YjBcblp4dSFhnTdtx+xuD0YCv65egX+x
# o8PVPnps1WLfP0eIF75s2fTJSYDhpOy8SEM0UdaY9o0o5sg5cZLYV5lYkQo5hcw5
# FeoJCpRJp4dqjEpCMhWTjWOAvUQ40UeHHqrsFy/Y2hWLLmSlTc2L7JUPZrdDizNW
# 3Kmr1c8=
# SIG # End signature block