Browse Source

Delete Commands.ps1

pull/378/head
Dmitry Nefedov 2 years ago
committed by GitHub
parent
commit
95c6983069
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 815
      Sophia Script/Sophia Script for Windows 10 PowerShell 7/bin/PolicyFileEdit/Commands.ps1

815
Sophia Script/Sophia Script for Windows 10 PowerShell 7/bin/PolicyFileEdit/Commands.ps1

@ -1,815 +0,0 @@
#requires -Version 2.0
. "$PSScriptRoot\Common.ps1"
<#
.SYNOPSIS
Creates or modifies a value in a .pol file
.DESCRIPTION
Creates or modifies a value in a .pol file. By default, also updates the version number in the policy's GPT.ini file
.PARAMETER Path
Path to the .pol file that is to be modified
.PARAMETER Key
The registry key inside the .pol file that you want to modify.
.PARAMETER ValueName
The name of the registry value. May be set to an empty string to modify the default value of a key
.PARAMETER Data
The new value to assign to the registry key / value. Cannot be $null, but can be set to an empty string or empty array
.PARAMETER Type
The type of registry value to set in the policy file. Cannot be set to Unknown or None, but all other values of the RegistryValueKind enum are legal
.PARAMETER NoGptIniUpdate
When this switch is used, the command will not attempt to update the version number in the GPT.ini file
.EXAMPLE
Set-PolicyFileEntry -Path $env:SystemRoot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue -Data 'Hello, World!' -Type String
Assigns a value of 'Hello, World!' to the String value Software\Policies\Something\SomeValue in the local computer Machine GPO. Updates the Machine version counter in $env:SystemRoot\system32\GroupPolicy\GPT.ini
.EXAMPLE
Set-PolicyFileEntry -Path $env:SystemRoot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue -Data 'Hello, World!' -Type String -NoGptIniUpdate
Same as example 1, except this one does not update GPT.ini right away. This can be useful if you want to set multiple values in the policy file and only trigger a single Group Policy refresh
.EXAMPLE
Set-PolicyFileEntry -Path $env:SystemRoot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue -Data '0x12345' -Type DWord
Example demonstrating that strings with valid numeric data (including hexadecimal strings beginning with 0x) can be assigned to the numeric types DWord, QWord and Binary
.EXAMPLE
$entries = @(
New-Object psobject -Property @{ValueName = 'MaxXResolution'; Data = 1680}
New-Object psobject -Property @{ValueName = 'MaxYResolution'; Data = 1050}
)
$entries | Set-PolicyFileEntry -Path $env:SystemRoot\system32\GroupPolicy\Machine\registry.pol -Key 'SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Type DWord
Example of using pipeline input to set multiple values at once. The advantage to this approach is that the .pol file on disk (and the GPT.ini file) will be updated if _any_ of the specified settings had to be modified,
and will be left alone if the file already contained all of the correct values.
The Key and Type properties could have also been specified via the pipeline objects instead of on the command line, but since both values shared the same Key and Type, this example shows that you can pass the values in either way.
.INPUTS
The Key, ValueName, Data, and Type properties may be bound via the pipeline by property name
.OUTPUTS
None. This command does not generate output
.NOTES
If the specified policy file already contains the correct value, the file will not be modified, and the GPT.ini file will not be updated
.LINK
Get-PolicyFileEntry
.LINK
Remove-PolicyFileEntry
.LINK
Update-GptIniVersion
.LINK
about_RegistryValuesForAdminTemplates
#>
function Set-PolicyFileEntry
{
[CmdletBinding(SupportsShouldProcess = $true)]
param
(
[Parameter(
Mandatory = $true,
Position = 0
)]
[string]
$Path,
[Parameter(
Mandatory = $true,
Position = 1,
ValueFromPipelineByPropertyName = $true
)]
[string]
$Key,
[Parameter(
Mandatory = $true,
Position = 2,
ValueFromPipelineByPropertyName = $true
)]
[AllowEmptyString()]
[string]
$ValueName,
[Parameter(
Mandatory = $true,
Position = 3,
ValueFromPipelineByPropertyName = $true
)]
[AllowEmptyString()]
[AllowEmptyCollection()]
[object]
$Data,
[Parameter(ValueFromPipelineByPropertyName = $true)]
[ValidateScript({
if ($_ -eq [Microsoft.Win32.RegistryValueKind]::Unknown)
{
throw 'Unknown is not a valid value for the Type parameter'
}
if ($_ -eq [Microsoft.Win32.RegistryValueKind]::None)
{
throw 'None is not a valid value for the Type parameter'
}
return $true
})]
[Microsoft.Win32.RegistryValueKind]
$Type = [Microsoft.Win32.RegistryValueKind]::String,
[switch]
$NoGptIniUpdate
)
begin
{
if (Get-Command [G]et-CallerPreference -CommandType Function -Module PreferenceVariables)
{
Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
}
$dirty = $false
try
{
$policyFile = OpenPolicyFile -Path $Path -ErrorAction Stop
}
catch
{
$PSCmdlet.ThrowTerminatingError($_)
}
}
process
{
$existingEntry = $policyFile.GetValue($Key, $ValueName)
if (($null -ne $existingEntry) -and ($Type -eq (PolEntryTypeToRegistryValueKind $existingEntry.Type)))
{
$existingData = GetEntryData -Entry $existingEntry -Type $Type
if (DataIsEqual $Data $existingData -Type $Type)
{
Write-Verbose "Policy setting '$Key\$ValueName' is already set to '$Data' of type '$Type'."
return
}
}
Write-Verbose "Configuring '$Key\$ValueName' to value '$Data' of type '$Type'."
try
{
switch ($Type)
{
([Microsoft.Win32.RegistryValueKind]::Binary)
{
$bytes = $Data -as [byte[]]
if ($null -eq $bytes)
{
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to Binary, -Data must be passed a Byte[] array.'
$PSCmdlet.ThrowTerminatingError($errorRecord)
}
else
{
$policyFile.SetBinaryValue($Key, $ValueName, $bytes)
}
break
}
([Microsoft.Win32.RegistryValueKind]::String)
{
$array = @($Data)
if ($array.Count -ne 1)
{
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to String, -Data must be passed a scalar value or single-element array.'
$PSCmdlet.ThrowTerminatingError($errorRecord)
}
else
{
$policyFile.SetStringValue($Key, $ValueName, $array[0].ToString())
}
break
}
([Microsoft.Win32.RegistryValueKind]::ExpandString)
{
$array = @($Data)
if ($array.Count -ne 1)
{
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to ExpandString, -Data must be passed a scalar value or single-element array.'
$PSCmdlet.ThrowTerminatingError($errorRecord)
}
else
{
$policyFile.SetStringValue($Key, $ValueName, $array[0].ToString(), $true)
}
break
}
([Microsoft.Win32.RegistryValueKind]::DWord)
{
$array = @($Data)
$dword = ($array | Select-Object -First 1) -as [UInt32]
if ($null -eq $dword -or $array.Count -ne 1)
{
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to DWord, -Data must be passed a valid UInt32 value.'
$PSCmdlet.ThrowTerminatingError($errorRecord)
}
else
{
$policyFile.SetDWORDValue($key, $ValueName, $dword)
}
break
}
([Microsoft.Win32.RegistryValueKind]::QWord)
{
$array = @($Data)
$qword = ($array | Select-Object -First 1) -as [UInt64]
if ($null -eq $qword -or $array.Count -ne 1)
{
$errorRecord = InvalidDataTypeCombinationErrorRecord -Message 'When -Type is set to QWord, -Data must be passed a valid UInt64 value.'
$PSCmdlet.ThrowTerminatingError($errorRecord)
}
else
{
$policyFile.SetQWORDValue($key, $ValueName, $qword)
}
break
}
([Microsoft.Win32.RegistryValueKind]::MultiString)
{
$strings = [string[]] @(
foreach ($item in @($Data))
{
$item.ToString()
}
)
$policyFile.SetMultiStringValue($Key, $ValueName, $strings)
break
}
} # switch ($Type)
$dirty = $true
}
catch
{
throw
}
}
end
{
if ($dirty)
{
$doUpdateGptIni = -not $NoGptIniUpdate
try
{
# SavePolicyFile contains the calls to $PSCmdlet.ShouldProcess, and will inherit our
# WhatIfPreference / ConfirmPreference values from here.
SavePolicyFile -PolicyFile $policyFile -UpdateGptIni:$doUpdateGptIni -ErrorAction Stop
}
catch
{
$PSCmdlet.ThrowTerminatingError($_)
}
}
}
}
<#
.SYNOPSIS
Retrieves the current setting(s) from a .pol file
.DESCRIPTION
Retrieves the current setting(s) from a .pol file
.PARAMETER Path
Path to the .pol file that is to be read
.PARAMETER Key
The registry key inside the .pol file that you want to read
.PARAMETER ValueName
The name of the registry value. May be set to an empty string to read the default value of a key
.PARAMETER All
Switch indicating that all entries from the specified .pol file should be output, instead of searching for a specific key / ValueName pair
.EXAMPLE
Get-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue
Reads the value of Software\Policies\Something\SomeValue from the Machine admin templates of the local GPO.
Either returns an object with the data and type of this registry value (if present), or returns nothing, if not found.
.EXAMPLE
Get-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -All
Outputs all of the registry values from the local machine Administrative Templates
.INPUTS
None. This command does not accept pipeline input.
.OUTPUTS
If the specified registry value is found, the function outputs a PSCustomObject with the following properties:
ValueName: The same value that was passed to the -ValueName parameter
Key: The same value that was passed to the -Key parameter
Data: The current value assigned to the specified Key / ValueName in the .pol file.
Type: The RegistryValueKind type of the specified Key / ValueName in the .pol file.
If the specified registry value is not found in the .pol file, the command returns nothing. No error is produced.
.LINK
Set-PolicyFileEntry
.LINK
Remove-PolicyFileEntry
.LINK
Update-GptIniVersion
.LINK
about_RegistryValuesForAdminTemplates
#>
function Get-PolicyFileEntry
{
[CmdletBinding(DefaultParameterSetName = 'ByKeyAndValue')]
param (
[Parameter(
Mandatory = $true,
Position = 0
)]
[string]
$Path,
[Parameter(
Mandatory = $true,
Position = 1,
ParameterSetName = 'ByKeyAndValue'
)]
[string]
$Key,
[Parameter(
Mandatory = $true,
Position = 2,
ParameterSetName = 'ByKeyAndValue'
)]
[string]
$ValueName,
[Parameter(
Mandatory = $true,
ParameterSetName = 'All'
)]
[switch]
$All
)
if (Get-Command [G]et-CallerPreference -CommandType Function -Module PreferenceVariables)
{
Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
}
try
{
$policyFile = OpenPolicyFile -Path $Path -ErrorAction Stop
}
catch
{
$PSCmdlet.ThrowTerminatingError($_)
}
if ($PSCmdlet.ParameterSetName -eq 'ByKeyAndValue')
{
$entry = $policyFile.GetValue($Key, $ValueName)
if ($null -ne $entry)
{
PolEntryToPsObject -PolEntry $entry
}
}
else
{
foreach ($entry in $policyFile.Entries)
{
PolEntryToPsObject -PolEntry $entry
}
}
}
<#
.SYNOPSIS
Removes a value from a .pol file
.DESCRIPTION
Removes a value from a .pol file. By default, also updates the version number in the policy's GPT.ini file
.PARAMETER Path
Path to the .pol file that is to be modified
.PARAMETER Key
The registry key inside the .pol file from which you want to remove a value
.PARAMETER ValueName
The name of the registry value to be removed. May be set to an empty string to remove the default value of a key
.PARAMETER NoGptIniUpdate
When this switch is used, the command will not attempt to update the version number in the GPT.ini fil
.EXAMPLE
Remove-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key Software\Policies\Something -ValueName SomeValue
Removes the value Software\Policies\Something\SomeValue from the local computer Machine GPO, if present. Updates the Machine version counter in $env:systemroot\system32\GroupPolicy\GPT.ini
.EXAMPLE
$entries = @(
New-Object -TypeName PSObject -Property @{ValueName = 'MaxXResolution'; Data = 1680}
New-Object -TypeName PSObject -Property @{ValueName = 'MaxYResolution'; Data = 1050}
)
$entries | Remove-PolicyFileEntry -Path $env:SystemRoot\system32\GroupPolicy\Machine\registry.pol -Key 'SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services'
Example of using pipeline input to remove multiple values at once. The advantage to this approach is that the .pol file on disk (and the GPT.ini file) will be updated if _any_ of the specified settings had to be removed,
and will be left alone if the file already did not contain any of those values.
The Key property could have also been specified via the pipeline objects instead of on the command line, but
since both values shared the same Key, this example shows that you can pass the value in either way.
.INPUTS
The Key and ValueName properties may be bound via the pipeline by property name
.OUTPUTS
None. This command does not generate output
.NOTES
If the specified policy file is already not present in the .pol file, the file will not be modified, and the GPT.ini file will not be updated
.LINK
Get-PolicyFileEntry
.LINK
Set-PolicyFileEntry
.LINK
Update-GptIniVersion
.LINK
about_RegistryValuesForAdminTemplates
#>
function Remove-PolicyFileEntry
{
[CmdletBinding(SupportsShouldProcess = $true)]
param (
[Parameter(
Mandatory = $true,
Position = 0
)]
[string]
$Path,
[Parameter(
Mandatory = $true,
Position = 1,
ValueFromPipelineByPropertyName = $true
)]
[string]
$Key,
[Parameter(
Mandatory = $true,
Position = 2,
ValueFromPipelineByPropertyName = $true
)]
[string]
$ValueName,
[switch]
$NoGptIniUpdate
)
begin
{
if (Get-Command [G]et-CallerPreference -CommandType Function -Module PreferenceVariables)
{
Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
}
$dirty = $false
try
{
$policyFile = OpenPolicyFile -Path $Path -ErrorAction Stop
}
catch
{
$PSCmdlet.ThrowTerminatingError($_)
}
}
process
{
$entry = $policyFile.GetValue($Key, $ValueName)
if ($null -eq $entry)
{
Write-Verbose "Entry '$Key\$ValueName' is already not present in file '$Path'."
return
}
Write-Verbose "Removing entry '$Key\$ValueName' from file '$Path'"
$policyFile.DeleteValue($Key, $ValueName)
$dirty = $true
}
end
{
if ($dirty)
{
$doUpdateGptIni = -not $NoGptIniUpdate
try
{
# SavePolicyFile contains the calls to $PSCmdlet.ShouldProcess, and will inherit our
# WhatIfPreference / ConfirmPreference values from here.
SavePolicyFile -PolicyFile $policyFile -UpdateGptIni:$doUpdateGptIni -ErrorAction Stop
}
catch
{
$PSCmdlet.ThrowTerminatingError($_)
}
}
}
}
<#
.SYNOPSIS
Increments the version counter in a GPT.ini file
.DESCRIPTION
Increments the version counter in a GPT.ini file
.PARAMETER Path
Path to the GPT.ini file that is to be modified
.PARAMETER PolicyType
Can be set to either 'Machine', 'User', or both. This affects how the value of the Version number in the ini file is changed
.EXAMPLE
Update-GptIniVersion -Path $env:SystemRoot\system32\GroupPolicy\GPT.ini -PolicyType Machine
Increments the Machine version counter of the local GPO
.EXAMPLE
Update-GptIniVersion -Path $env:SystemRoot\system32\GroupPolicy\GPT.ini -PolicyType User
Increments the User version counter of the local GPO
.EXAMPLE
Update-GptIniVersion -Path $env:SystemRoot\system32\GroupPolicy\GPT.ini -PolicyType Machine, User
Increments both the Machine and User version counters of the local GPO
.INPUTS
None. This command does not accept pipeline input.
.OUTPUTS
None. This command does not generate output
.NOTES
A GPT.ini file contains only a single Version value. However, this represents two separate counters, for machine and user versions.
The high 16 bits of the value are the User counter, and the low 16 bits are the Machine counter. For example (on PowerShell 3.0and later),
the Version value when the Machine counter is set to 3 and the User counter is set to 5 can be found by evaluating this expression:
(5 -shl 16) -bor 3 , which will show up as decimal value 327683 in the INI file.
.LINK
Set-PolicyFileEntry
.LINK
about_RegistryValuesForAdminTemplates
#>
function Update-GptIniVersion
{
[CmdletBinding(SupportsShouldProcess = $true)]
param (
[Parameter(Mandatory = $true)]
[ValidateScript({
if (Test-Path -LiteralPath $_ -PathType Leaf)
{
return $true
}
throw "Path '$_' does not exist."
})]
[string]
$Path,
[Parameter(Mandatory = $true)]
[ValidateSet('Machine', 'User')]
[string[]]
$PolicyType
)
if (Get-Command [G]et-CallerPreference -CommandType Function -Module PreferenceVariables)
{
Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
}
try
{
IncrementGptIniVersion @PSBoundParameters
}
catch
{
$PSCmdlet.ThrowTerminatingError($_)
}
}
# SIG # Begin signature block
# MIIgTAYJKoZIhvcNAQcCoIIgPTCCIDkCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAWcBLp5Go0Yq2e
# WARWCHEIvOxdE5WCmcYIoSD6N4yxq6CCG1YwggO3MIICn6ADAgECAhAM5+DlF9hG
# /o/lYPwb8DA5MA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBa
# Fw0zMTExMTAwMDAwMDBaMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lD
# ZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
# AQoCggEBAK0OFc7kQ4BcsYfzt2D5cRKlrtwmlIiq9M71IDkoWGAM+IDaqRWVMmE8
# tbEohIqK3J8KDIMXeo+QrIrneVNcMYQq9g+YMjZ2zN7dPKii72r7IfJSYd+fINcf
# 4rHZ/hhk0hJbX/lYGDW8R82hNvlrf9SwOD7BG8OMM9nYLxj+KA+zp4PWw25EwGE1
# lhb+WZyLdm3X8aJLDSv/C3LanmDQjpA1xnhVhyChz+VtCshJfDGYM2wi6YfQMlqi
# uhOCEe05F52ZOnKh5vqk2dUXMXWuhX0irj8BRob2KHnIsdrkVxfEfhwOsLSSplaz
# vbKX7aqn8LfFqD+VFtD/oZbrCF8Yd08CAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGG
# MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEXroq/0ksuCMS1Ri6enIZ3zbcgP
# MB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBBQUA
# A4IBAQCiDrzf4u3w43JzemSUv/dyZtgy5EJ1Yq6H6/LV2d5Ws5/MzhQouQ2XYFwS
# TFjk0z2DSUVYlzVpGqhH6lbGeasS2GeBhN9/CTyU5rgmLCC9PbMoifdf/yLil4Qf
# 6WXvh+DfwWdJs13rsgkq6ybteL59PyvztyY1bV+JAbZJW58BBZurPSXBzLZ/wvFv
# hsb6ZGjrgS2U60K3+owe3WLxvlBnt2y98/Efaww2BxZ/N3ypW2168RJGYIPXJwS+
# S86XvsNnKmgR34DnDDNmvxMNFG7zfx9jEB76jRslbWyPpbdhAbHSoyahEHGdreLD
# +cOZUbcrBwjOLuZQsqf6CkUvovDyMIIFJDCCBAygAwIBAgIQCRrHC94asIH2W7lu
# /i1eITANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln
# aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhE
# aWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTE3MDYy
# MTAwMDAwMFoXDTE4MDgyOTEyMDAwMFowYTELMAkGA1UEBhMCQ0ExCzAJBgNVBAgT
# Ak9OMREwDwYDVQQHEwhCcmFtcHRvbjEYMBYGA1UEChMPRGF2aWQgTGVlIFd5YXR0
# MRgwFgYDVQQDEw9EYXZpZCBMZWUgV3lhdHQwggEiMA0GCSqGSIb3DQEBAQUAA4IB
# DwAwggEKAoIBAQDA/6cBpCOYJk6IY2cPgY23dVjs3xYcJKeSDIvnfvBl/SFqvEYX
# tJkfbETnjp2XkZ9UFk2j5b5JpRg25GpkTo4a0MYMAUyn7tfotxG64sjxsNLXrrYN
# nx3q2QUt4dpRjG11giMyFSjAFPjPO1JbM9976GN96ldiOUX3yH+UM4Ow6zS+0iGq
# MSnd88iPs/CqphaVTDBN+ZmU864hnzGhjiMBlyjw4z/aLtJeopeLmuk8wyxN+N3v
# P/wsFwmPpycxSU3hPlqa2GDDswYtiMuf5NOdG3CfEEX9Ntrd2NxpjXOPGDt6Ko0C
# 0mYSd9qgzznxuweJPXXg4GR6jeVZrq4pQZFlAgMBAAGjggHFMIIBwTAfBgNVHSME
# GDAWgBRaxLl7KgqjpepxA8Bg+S32ZXUOWDAdBgNVHQ4EFgQUDkf1juW1Z6Tp40ck
# YDz0SxGZDn8wDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcG
# A1UdHwRwMG4wNaAzoDGGL2h0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFz
# c3VyZWQtY3MtZzEuY3JsMDWgM6Axhi9odHRwOi8vY3JsNC5kaWdpY2VydC5jb20v
# c2hhMi1hc3N1cmVkLWNzLWcxLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwDATAq
# MCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeB
# DAEEATCBhAYIKwYBBQUHAQEEeDB2MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5k
# aWdpY2VydC5jb20wTgYIKwYBBQUHMAKGQmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0
# LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURDb2RlU2lnbmluZ0NBLmNydDAMBgNV
# HRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAqho5skBHIeG738khh3muTynOW
# TWwHZ4fJI0oWgAVLK/g1VNHKCWY+fqoxdXZcRZt6jZtklmuYAPx3q86XtOniVqYk
# EFIcJgBFJtBuAQDeYFyKyMWoidqGVQ4wIrzArUEWg6q/ba36S+u1TqnZr3GJ3+y0
# G9iNbc1nEzKoUPARo3rgWEirgARMjNCPSufDLHNsjPHCXwUNxbRtq+kiUxBgOIF7
# Rn4ADci9pCalNeby/V7I2poj5nQ22f2P7nwIMuIFszOsV7BBfI2ni9GzPhKBCwLy
# K6s3wzPQyuUewKiG84dQcnOIZO9f/8aB30BVu6FSnNvMdMjyLIRtlPP0txxvMIIF
# MDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1b5VQCDANBgkqhkiG9w0BAQsFADBlMQsw
# CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
# ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
# Q0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgxMDIyMTIwMDAwWjByMQswCQYDVQQGEwJV
# UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
# Y29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWdu
# aW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+NOzHH8OEa9n
# dwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLXcep2nQUut4/6kkPApfmJ1DcZ17aq8JyG
# pdglrA55KDp+6dFn08b7KSfH03sjlOSRI5aQd4L5oYQjZhJUM1B0sSgmuyRpwsJS
# 8hRniolF1C2ho+mILCCVrhxKhwjfDPXiTWAYvqrEsq5wMWYzcT6scKKrzn/pfMuS
# oeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5Ng2Q7+S1TqSp6moKq4TzrGdOtcT3jNEg
# JSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8vYWxYoNzQYIH5DiLanMg0A9kczyen6Yz
# qf0Z3yWT0QIDAQABo4IBzTCCAckwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8B
# Af8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMweQYIKwYBBQUHAQEEbTBrMCQG
# CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKG
# N2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJv
# b3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0
# LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9j
# cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwTwYD
# VR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3
# LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYEFFrEuXsqCqOl
# 6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0G
# CSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPzItEVyCx8JSl2qB1dHC06GsTvMGHXfgtg
# /cM9D8Svi/3vKt8gVTew4fbRknUPUbRupY5a4l4kgU4QpO4/cY5jDhNLrddfRHnz
# NhQGivecRk5c/5CxGwcOkRX7uq+1UcKNJK4kxscnKqEpKBo6cSgCPC6Ro8AlEeKc
# FEehemhor5unXCBc2XGxDI+7qPjFEmifz0DLQESlE/DmZAwlCEIysjaKJAL+L3J+
# HNdJRZboWR3p+nRka7LrZkPas7CM1ekN3fYBIM6ZMWM9CBoYs4GbT8aTEAb8B4H6
# i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKyZqHnGKSaZFHvMIIGajCCBVKgAwIBAgIQ
# AwGaAjr/WLFr1tXq5hfwZjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzEV
# MBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t
# MSEwHwYDVQQDExhEaWdpQ2VydCBBc3N1cmVkIElEIENBLTEwHhcNMTQxMDIyMDAw
# MDAwWhcNMjQxMDIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGln
# aUNlcnQxJTAjBgNVBAMTHERpZ2lDZXJ0IFRpbWVzdGFtcCBSZXNwb25kZXIwggEi
# MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjZF38fLPggjXg4PbGKuZJdTvM
# buBTqZ8fZFnmfGt/a4ydVfiS457VWmNbAklQ2YPOb2bu3cuF6V+l+dSHdIhEOxnJ
# 5fWRn8YUOawk6qhLLJGJzF4o9GS2ULf1ErNzlgpno75hn67z/RJ4dQ6mWxT9RSOO
# hkRVfRiGBYxVh3lIRvfKDo2n3k5f4qi2LVkCYYhhchhoubh87ubnNC8xd4EwH7s2
# AY3vJ+P3mvBMMWSN4+v6GYeofs/sjAw2W3rBerh4x8kGLkYQyI3oBGDbvHN0+k7Y
# /qpA8bLOcEaD6dpAoVk62RUJV5lWMJPzyWHM0AjMa+xiQpGsAsDvpPCJEY93AgMB
# AAGjggM1MIIDMTAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUB
# Af8EDDAKBggrBgEFBQcDCDCCAb8GA1UdIASCAbYwggGyMIIBoQYJYIZIAYb9bAcB
# MIIBkjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCC
# AWQGCCsGAQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABp
# AHMAIABDAGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABl
# AHMAIABhAGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBp
# AEMAZQByAHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5
# AGkAbgBnACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBj
# AGgAIABsAGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQBy
# AGUAIABpAG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5
# ACAAcgBlAGYAZQByAGUAbgBjAGUALjALBglghkgBhv1sAxUwHwYDVR0jBBgwFoAU
# FQASKxOYspkH7R7for5XDStnAs0wHQYDVR0OBBYEFGFaTSS2STKdSip5GoNL9B6J
# wcp9MH0GA1UdHwR2MHQwOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydEFzc3VyZWRJRENBLTEuY3JsMDigNqA0hjJodHRwOi8vY3JsNC5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURDQS0xLmNybDB3BggrBgEFBQcBAQRr
# MGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEF
# BQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl
# ZElEQ0EtMS5jcnQwDQYJKoZIhvcNAQEFBQADggEBAJ0lfhszTbImgVybhs4jIA+A
# h+WI//+x1GosMe06FxlxF82pG7xaFjkAneNshORaQPveBgGMN/qbsZ0kfv4gpFet
# W7easGAm6mlXIV00Lx9xsIOUGQVrNZAQoHuXx/Y/5+IRQaa9YtnwJz04HShvOlIJ
# 8OxwYtNiS7Dgc6aSwNOOMdgv420XEwbu5AO2FKvzj0OncZ0h3RTKFV2SQdr5D4HR
# mXQNJsQOfxu19aDxxncGKBXp2JPlVRbwuwqrHNtcSCdmyKOLChzlldquxC5ZoGHd
# 2vNtomHpigtt7BIYvfdVVEADkitrwlHCCkivsNRu4PQUCjob4489yq9qjXvc2EQw
# ggbNMIIFtaADAgECAhAG/fkDlgOt6gAK6z8nu7obMA0GCSqGSIb3DQEBBQUAMGUx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9v
# dCBDQTAeFw0wNjExMTAwMDAwMDBaFw0yMTExMTAwMDAwMDBaMGIxCzAJBgNVBAYT
# AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy
# dC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IEFzc3VyZWQgSUQgQ0EtMTCCASIwDQYJ
# KoZIhvcNAQEBBQADggEPADCCAQoCggEBAOiCLZn5ysJClaWAc0Bw0p5WVFypxNJB
# Bo/JM/xNRZFcgZ/tLJz4FlnfnrUkFcKYubR3SdyJxArar8tea+2tsHEx6886QAxG
# TZPsi3o2CAOrDDT+GEmC/sfHMUiAfB6iD5IOUMnGh+s2P9gww/+m9/uizW9zI/6s
# VgWQ8DIhFonGcIj5BZd9o8dD3QLoOz3tsUGj7T++25VIxO4es/K8DCuZ0MZdEkKB
# 4YNugnM/JksUkK5ZZgrEjb7SzgaurYRvSISbT0C58Uzyr5j79s5AXVz2qPEvr+yJ
# IvJrGGWxwXOt1/HYzx4KdFxCuGh+t9V3CidWfA9ipD8yFGCV/QcEogkCAwEAAaOC
# A3owggN2MA4GA1UdDwEB/wQEAwIBhjA7BgNVHSUENDAyBggrBgEFBQcDAQYIKwYB
# BQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwgwggHSBgNVHSAEggHJ
# MIIBxTCCAbQGCmCGSAGG/WwAAQQwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
# LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
# AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
# AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
# AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
# AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
# AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
# AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
# AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
# AHIAZQBuAGMAZQAuMAsGCWCGSAGG/WwDFTASBgNVHRMBAf8ECDAGAQH/AgEAMHkG
# CCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu
# Y29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln
# aUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRw
# Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3Js
# MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVk
# SURSb290Q0EuY3JsMB0GA1UdDgQWBBQVABIrE5iymQftHt+ivlcNK2cCzTAfBgNV
# HSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEA
# RlA+ybcoJKc4HbZbKa9Sz1LpMUerVlx71Q0LQbPv7HUfdDjyslxhopyVw1Dkgrkj
# 0bo6hnKtOHisdV0XFzRyR4WUVtHruzaEd8wkpfMEGVWp5+Pnq2LN+4stkMLA0rWU
# vV5PsQXSDj0aqRRbpoYxYqioM+SbOafE9c4deHaUJXPkKqvPnHZL7V/CSxbkS3BM
# AIke/MV5vEwSV/5f4R68Al2o/vsHOE8Nxl2RuQ9nRc3Wg+3nkg2NsWmMT/tZ4CMP
# 0qquAHzunEIOz5HXJ7cW7g/DvXwKoO4sCFWFIrjrGBpN/CohrUkxg0eVd3HcsRtL
# SxwQnHcUwZ1PL1qVCCkQJjGCBEwwggRIAgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUw
# EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
# MTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcg
# Q0ECEAkaxwveGrCB9lu5bv4tXiEwDQYJYIZIAWUDBAIBBQCggYQwGAYKKwYBBAGC
# NwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgeDlioT2f
# GHcGNTfuRsD0IKaxlXd1hWdfaxBVWx50HuMwDQYJKoZIhvcNAQEBBQAEggEAUPAK
# q7M3j9NMUPZulEA4Xw5ihJ034qItL2ZaAwGQ6ITLEXwqQp4o9sI5RJ4or9zCwKuI
# CSz9OUPEnYj2hIVVJY7Qd4+4J4u5thFJzWqj4nDJV/IVSpR7j+QWc+M4774mNQv3
# kjTaHWaI4ZGSN7QGXSqJiagS8cnq7s8puJu0eS2tvCjHPbAZ01pgMWckCqXpnKhw
# +cuSLQ69CFhAp9xL5oOWva0qrW/aL829MGfrmt3HtIOonLIip+p7E1pG/3L8N8oq
# sWG9LmyXR147VVev4pa/pzI+gjEG4yLNaSiC4IeF9uuyJ+DI7d0fVeJVQUROkzx1
# ertJoAoGC4g9/s2ATaGCAg8wggILBgkqhkiG9w0BCQYxggH8MIIB+AIBATB2MGIx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IEFzc3VyZWQgSUQgQ0Et
# MQIQAwGaAjr/WLFr1tXq5hfwZjAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsG
# CSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTgwMjEyMjExOTQzWjAjBgkqhkiG
# 9w0BCQQxFgQUHWtK+HMhOICqm+NK2ov+B+/Ica8wDQYJKoZIhvcNAQEBBQAEggEA
# lkoWbQS5N7Oi6fFD39t6V/wGuLkTj1a6MK4lLTcGu4KUTQeSGQpkWn8oeL2JdvgX
# 23jgLe9D7kn6W7GP5xgYgwFF3LN+8sgt5mzjOYBkGoUkGzwRSJcHsxIaT5P8B8pC
# ttYX/gD86GOT5OxT+DybiY6g6ejYy+a7qoAlawm9Vmth/Nx4MC85FFxgOFs6YJXy
# IShe2CmmIZxUmlgWRoxpx19wCOgY0O34CgnkNVSuVPDJMjdmxdlr3rhHDwwyp7C4
# n0DTzclyQs/g3DqnMGyj1/fgnHk+p4kqpJAHaWFom/V1vxK4KgWl7fT0OibEQBoQ
# q6k346yfNir+/qcW3OacgA==
# SIG # End signature block
Loading…
Cancel
Save