public/New-AppVentiXRegistryUserSetting.ps1
|
<#
.SYNOPSIS Creates an AppVentiX UserSetting XML file for a registry configuration. .DESCRIPTION Builds and saves an AppVentiX UserSetting XML file that defines a set of registry entries. Supports two input modes: - RegistryEntries mode: accepts a flat array of hashtables, each describing a single registry entry. - InputObject mode: accepts a pre-structured object (for example from an Ivanti export pipeline) that already contains the FriendlyName, Description and RegistryEntries. Each registry entry is normalized (root key, value type and delete flag) before it is written to the XML. .PARAMETER FriendlyName Display name for the AppVentiX UserSetting. .PARAMETER Description Optional description for the UserSetting. .PARAMETER ExecutionOrder Execution order for the UserSetting. Defaults to 0. .PARAMETER ProcessAtLogin Whether the setting is applied at login. Defaults to $true. .PARAMETER ProcessAtRefresh Whether the setting is applied at refresh. Defaults to $true. .PARAMETER ProcessAtReconnectAndUnlock Whether the setting is applied at reconnect and unlock. Defaults to $false. .PARAMETER MachineGroupFriendlyName One or more machine group friendly names to apply the setting to. Defaults to 'All Machine Groups'. .PARAMETER RegistryEntries Array of hashtables describing registry entries. Each entry must contain: RootKey, KeyPath. Optional keys: ValueName, ValueData, ValueType, Action, DeleteKey. .PARAMETER InputObject A pre-structured object containing the FriendlyName, Description and RegistryEntries to import. When supplied, its values are used instead of the individual parameters. .PARAMETER ConfigShare Specifies the path to the AppVentiX configuration share. You can omit this parameter if the configuration store was already set with Set-AppVentiXConfigShare, or when it can be detected automatically (for example on a machine where AppVentiX Central View is installed and configured). .EXAMPLE New-AppVentiXRegistryUserSetting -FriendlyName 'Disable First Run' -RegistryEntries @( @{ RootKey = 'HKCU'; KeyPath = 'Software\Contoso\App'; ValueName = 'FirstRun'; ValueData = '0'; ValueType = 'DWord' } ) Creates a registry User Setting with a single registry value. .LINK Get-AppVentiXUserSettings .LINK New-AppVentiXDriveMappingUserSetting .LINK New-AppVentiXEnvironmentVariableUserSetting .LINK New-AppVentiXGroupPolicyUserSetting .LINK New-AppVentiXPrinterMappingUserSetting .LINK New-AppVentiXShortcutUserSetting .LINK Set-AppVentiXUserSettingFolder .LINK Set-AppVentiXUserSettingsAssignment .NOTES Function : New-AppVentiXRegistryUserSetting Author : John Billekens Copyright : (c) John Billekens Consultancy & AppVentiX Version : 2026.312.2000 #> function New-AppVentiXRegistryUserSetting { [CmdletBinding()] [Alias("New-AppVentiXRegistry")] param ( [Parameter(Mandatory = $true, ParameterSetName = "RegistryEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [string]$FriendlyName, [Parameter(Mandatory = $false, ParameterSetName = "RegistryEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [string]$Description, [Parameter(Mandatory = $false, ParameterSetName = "RegistryEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [int]$ExecutionOrder = 0, [Parameter(Mandatory = $false, ParameterSetName = "RegistryEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [bool]$ProcessAtLogin = $true, [Parameter(Mandatory = $false, ParameterSetName = "RegistryEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [bool]$ProcessAtRefresh = $true, [Parameter(Mandatory = $false, ParameterSetName = "RegistryEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [bool]$ProcessAtReconnectAndUnlock = $false, [Parameter(Mandatory = $false, ParameterSetName = "RegistryEntries")] [Parameter(Mandatory = $false, ParameterSetName = "InputObject")] [string[]]$MachineGroupFriendlyName = @("All Machine Groups"), [Parameter(Mandatory = $true, ParameterSetName = "RegistryEntries")] [hashtable[]]$RegistryEntries = @(), [Parameter(Mandatory = $true, ParameterSetName = "InputObject")] [PSCustomObject]$InputObject, [Parameter(DontShow)] [ValidateNotNullOrEmpty()] [string]$ConfigShare = $Script:AppVentix.ConfigShare ) #region functions function New-RegistryUserSettingXml { <# .SYNOPSIS Builds and returns the UserSetting XML document object. .NOTES Function : New-RegistryUserSettingXml Author : John Billekens Copyright : Copyright (c) John Billekens Consultancy Version : 2026.0227.1200 #> [CmdletBinding()] param () $XmlDoc = New-Object System.Xml.XmlDocument # Root element $Root = $XmlDoc.CreateElement("UserSetting") [void]$XmlDoc.AppendChild($Root) # Helper: append a simple text element function Add-TextElement { param ( [System.Xml.XmlElement]$Parent, [string]$Name, [string]$Text ) $Element = $XmlDoc.CreateElement($Name) $Element.InnerText = $Text [void]$Parent.AppendChild($Element) return $Element } # Basic metadata [void](Add-TextElement -Parent $Root -Name "Id" -Text $SettingId) [void](Add-TextElement -Parent $Root -Name "FriendlyName" -Text $FriendlyName) [void](Add-TextElement -Parent $Root -Name "Description" -Text $Description) [void](Add-TextElement -Parent $Root -Name "Type" -Text $Type) [void](Add-TextElement -Parent $Root -Name "ExecutionOrder" -Text $ExecutionOrder) [void](Add-TextElement -Parent $Root -Name "CreatedDate" -Text $CreatedDate) [void](Add-TextElement -Parent $Root -Name "LastModifiedDate" -Text $LastModifiedDate) [void](Add-TextElement -Parent $Root -Name "ProcessAtLogin" -Text (ConvertTo-BooleanString -Value $ProcessAtLogin)) [void](Add-TextElement -Parent $Root -Name "ProcessAtRefresh" -Text (ConvertTo-BooleanString -Value $ProcessAtRefresh)) [void](Add-TextElement -Parent $Root -Name "ProcessAtReconnectAndUnlock" -Text (ConvertTo-BooleanString -Value $ProcessAtReconnectAndUnlock)) $MachineGroupsElement = $XmlDoc.CreateElement("MachineGroups") foreach ($Group in $MachineGroups) { [void](Add-TextElement -Parent $MachineGroupsElement -Name "MachineGroup" -Text $Group) } [void]$Root.AppendChild($MachineGroupsElement) $MachineGroupFriendlyNamesElement = $XmlDoc.CreateElement("MachineGroupFriendlyNames") foreach ($GroupFriendlyName in $MachineGroupFriendlyNames) { [void](Add-TextElement -Parent $MachineGroupFriendlyNamesElement -Name "FriendlyName" -Text $GroupFriendlyName) } [void]$Root.AppendChild($MachineGroupFriendlyNamesElement) $RegistryEntriesElement = $XmlDoc.CreateElement("RegistryEntries") foreach ($EntryData in $NewRegistryEntries) { $RegistryEntryElement = $XmlDoc.CreateElement("RegistryEntry") [void](Add-TextElement -Parent $RegistryEntryElement -Name "RootKey" -Text $EntryData.RootKey) [void](Add-TextElement -Parent $RegistryEntryElement -Name "KeyPath" -Text $EntryData.KeyPath) [void](Add-TextElement -Parent $RegistryEntryElement -Name "ValueName" -Text $EntryData.ValueName) [void](Add-TextElement -Parent $RegistryEntryElement -Name "ValueData" -Text $EntryData.ValueData) [void](Add-TextElement -Parent $RegistryEntryElement -Name "ValueType" -Text $EntryData.ValueType) [void](Add-TextElement -Parent $RegistryEntryElement -Name "Action" -Text $EntryData.Action) [void](Add-TextElement -Parent $RegistryEntryElement -Name "DeleteKey" -Text (ConvertTo-BooleanString -Value ([bool]$EntryData.DeleteKey))) [void]$RegistryEntriesElement.AppendChild($RegistryEntryElement) } [void]$Root.AppendChild($RegistryEntriesElement) return $XmlDoc } #endregion functions if (Test-AppVentiXIsLicensed -ConfigShare $ConfigShare) { # region Basics $SettingId = [guid]::NewGuid().ToString() $Type = "RegistrySettings" # endregion Basics $userSettingsPath = Join-Path -Path $ConfigShare -ChildPath $Script:AppVentix.UserSettingsPath #Process the inputObject if provided if ($PSBoundParameters.ContainsKey("InputObject")) { Write-Verbose "Processing InputObject parameter..." if (-not [string]::IsNullOrEmpty($InputObject.FriendlyName)) { $FriendlyName = $InputObject.FriendlyName } if (-not [string]::IsNullOrEmpty($InputObject.Description)) { $Description = $InputObject.Description } $FriendlyName = $InputObject.FriendlyName $Description = $InputObject.Description $RegistryEntries = @($InputObject.RegistryEntries | ConvertTo-HashTable) } # Only first MachineGroup is used if ($MachineGroupFriendlyName.Count -gt 0) { if ($MachineGroup -notcontains "All Machine Groups" -and $MachineGroup -notcontains "All" -and $MachineGroup.Count -gt 0) { $AvailableGroups = Get-AppVentiXMachineGroup $MachineGroups = @() $MachineGroupFriendlyNames = @() foreach ($Group in $MachineGroupFriendlyName) { $selectedGroup = $AvailableGroups | Where-Object { $_.FriendlyName -ieq $Group } if ($selectedGroup) { $MachineGroups += $selectedGroup.GroupName.ToString() $MachineGroupFriendlyNames += $selectedGroup.FriendlyName.ToString() } } } else { $MachineGroups = @("All") $MachineGroupFriendlyNames = @("All Machine Groups") } } else { $MachineGroups = @("All") $MachineGroupFriendlyNames = @("All Machine Groups") } #region --- Build $NewRegistryEntries --- #Check That the $RegistryEntries parameter is an array of hashtables with the required keys $NewRegistryEntries = @() foreach ($entry in $RegistryEntries) { if (-not ($entry.ContainsKey("RootKey") -and $entry.ContainsKey("KeyPath"))) { Write-Error "Each registry entry must be a hashtable containing at least the keys: RootKey, KeyPath" return } $NewRegistryEntry = [ordered]@{ RootKey = "$($entry.RootKey)" KeyPath = "$($entry.KeyPath)" ValueName = "$($entry.ValueName)" ValueData = "$($entry.ValueData)" ValueType = "$($entry.ValueType)" Action = "$($entry.Action)" DeleteKey = $($entry.DeleteKey) } if ([string]::IsNullOrEmpty($NewRegistryEntry.Action)) { $NewRegistryEntry.Action = "Set" } if ([string]::IsNullOrEmpty($NewRegistryEntry.DeleteKey)) { $NewRegistryEntry.DeleteKey = $false } #check and normalize the rootkey values Write-Verbose "Checking RootKey value: $($NewRegistryEntry.RootKey)" switch -CaseSensitive ($NewRegistryEntry.RootKey) { "HKLM" { $NewRegistryEntry.RootKey = "HKEY_LOCAL_MACHINE" } "HKCU" { $NewRegistryEntry.RootKey = "HKEY_CURRENT_USER" } "Machine" { $NewRegistryEntry.RootKey = "HKEY_LOCAL_MACHINE" } "User" { $NewRegistryEntry.RootKey = "HKEY_CURRENT_USER" } "HKEY_LOCAL_MACHINE" { } "HKEY_CURRENT_USER" { } default { Write-Error "Invalid RootKey value: $($NewRegistryEntry.RootKey). Valid values are: HKEY_LOCAL_MACHINE (alias: HKLM, Machine), HKEY_CURRENT_USER (alias: HKCU, User)" return } } $NewRegistryEntry.RootKey = $NewRegistryEntry.RootKey.ToUpper() if ($NewRegistryEntry.RootKey -notin @("HKEY_LOCAL_MACHINE", "HKEY_CURRENT_USER")) { Write-Error "Invalid RootKey value: $($NewRegistryEntry.RootKey). Valid values are: HKEY_LOCAL_MACHINE (alias: HKLM, Machine), HKEY_CURRENT_USER (alias: HKCU, User)" return } Write-Verbose "Continuing with normalized RootKey: $($NewRegistryEntry.RootKey)" Write-Verbose "Checking ValueType value: $($NewRegistryEntry.ValueType)" switch ($NewRegistryEntry.ValueType) { "String" { $NewRegistryEntry.ValueType = "REG_SZ" } "DWord" { $NewRegistryEntry.ValueType = "REG_DWORD" } "Binary" { $NewRegistryEntry.ValueType = "REG_BINARY" } "MultiString" { $NewRegistryEntry.ValueType = "REG_MULTI_SZ" } "ExpandString" { $NewRegistryEntry.ValueType = "REG_EXPAND_SZ" } } $NewRegistryEntry.ValueType = $NewRegistryEntry.ValueType.ToUpper() if ([string]::IsNullOrEmpty($NewRegistryEntry.ValueType)) { $NewRegistryEntry.ValueType = "REG_SZ" Write-Verbose "ValueType not specified. Defaulting to REG_SZ." } if ($NewRegistryEntry.ValueType -notin @("REG_SZ", "REG_DWORD", "REG_BINARY", "REG_MULTI_SZ", "REG_EXPAND_SZ")) { Write-Error "Invalid ValueType: $($NewRegistryEntry.ValueType). Valid values are: REG_SZ (alias: String), REG_DWORD (alias: DWord), REG_BINARY (alias: Binary), REG_MULTI_SZ (alias: MultiString), REG_EXPAND_SZ (alias: ExpandString)" return } Write-Verbose "Continuing with normalized ValueType: $($NewRegistryEntry.ValueType)" Write-Verbose "Checking DeleteKey value: $($NewRegistryEntry.DeleteKey)" $deleteKey = $false switch ($($NewRegistryEntry.DeleteKey)) { "True" { $deleteKey = $true } "False" { $deleteKey = $false } "1" { $deleteKey = $true } "0" { $deleteKey = $false } $true { $deleteKey = $true } $false { $deleteKey = $false } default { Write-Error "Invalid DeleteKey value: $($NewRegistryEntry.DeleteKey). Valid values are: True (alias: 1), False (alias: 0)" return } } $NewRegistryEntry.DeleteKey = $deleteKey if ($NewRegistryEntry.Action -ieq "Remove" -and [string]::IsNullOrEmpty($NewRegistryEntry.ValueName)) { $NewRegistryEntry.DeleteKey = $true Write-Verbose "Action is Remove and ValueName is empty. Setting DeleteKey to True." } Write-Verbose "Continuing with normalized DeleteKey: $($NewRegistryEntry.DeleteKey)" $NewRegistryEntries += $NewRegistryEntry } #endregion --- Build $NewRegistryEntries --- $policyFilename = "$($Type)-$($SettingId).xml" $policyFullname = Join-Path -Path $userSettingsPath -ChildPath $policyFilename $CreatedDate = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") $LastModifiedDate = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") #region --- Main --- if ([string]::IsNullOrEmpty($FriendlyName)) { Write-Error "FriendlyName is required. Please provide a value for the FriendlyName parameter or include it in the InputObject." return } try { Write-Verbose "Building UserSetting XML..." $XmlDocument = New-RegistryUserSettingXml $XmlWriterSettings = New-Object System.Xml.XmlWriterSettings $XmlWriterSettings.Indent = $true $XmlWriterSettings.IndentChars = " " $XmlWriterSettings.Encoding = [System.Text.Encoding]::UTF8 $XmlWriterSettings.OmitXmlDeclaration = $true Write-Verbose "Saving UserSetting XML to $policyFullname" $XmlWriter = [System.Xml.XmlWriter]::Create($policyFullname, $XmlWriterSettings) $XmlDocument.Save($XmlWriter) Write-AppVentiXLogEntry -Feature UserSettings -Action $($MyInvocation.MyCommand.Name) -Details "New Registry User Setting '$FriendlyName' added with $($NewRegistryEntries.Count) setting(s)." $XmlWriter.Close() Write-Output ( [PSCustomObject]@{ Id = $SettingId FriendlyName = $FriendlyName FileName = $policyFilename } ) } catch { Write-Error "Failed to generate XML: $($_.Exception.Message)" } } else { Write-Warning 'AppVentiX is not licensed!' } } # SIG # Begin signature block # MIInigYJKoZIhvcNAQcCoIInezCCJ3cCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA8mhbxbE1NM6PV # 0lMabhUR4fqtfqtDQU5tZm7ZD1vE1qCCIR0wggZFMIIELaADAgECAhAIMk+dt9qR # b2Pk8qM8Xl1RMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQK # ExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2Rl # IFNpZ25pbmcgMjAyMSBDQTAeFw0yNDA0MDQxNDA0MjRaFw0yNzA0MDQxNDA0MjNa # MGsxCzAJBgNVBAYTAk5MMRIwEAYDVQQHDAlTY2hpam5kZWwxIzAhBgNVBAoMGkpv # aG4gQmlsbGVrZW5zIENvbnN1bHRhbmN5MSMwIQYDVQQDDBpKb2huIEJpbGxla2Vu # cyBDb25zdWx0YW5jeTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMsl # ntDbSQwHZXwFhmibivbnd0Qfn6sqe/6fos3pKzKxEsR907RkDMet2x6RRg3eJkiI # r3TFPwqBooyXXgK3zxxpyhGOcuIqyM9J28DVf4kUyZHsjGO/8HFjrr3K1hABNUsz # P0o7H3o6J31eqV1UmCXYhQlNoW9FOmRC1amlquBmh7w4EKYEytqdmdOBavAD5Xq4 # vLPxNP6kyA+B2YTtk/xM27TghtbwFGKnu9Vwnm7dFcpLxans4ONt2OxDQOMA5Nwg # cUv/YTpjhq9qoz6ivG55NRJGNvUXsM3w2o7dR6Xh4MuEGrTSrOWGg2A5EcLH1XqQ # tkF5cZnAPM8W/9HUp8ggornWnFVQ9/6Mga+ermy5wy5XrmQpN+x3u6tit7xlHk1H # c+4XY4a4ie3BPXG2PhJhmZAn4ebNSBwNHh8z7WTT9X9OFERepGSytZVeEP7hgypt # SLcuhpwWeR4QdBb7dV++4p3PsAUQVHFpwkSbrRTv4EiJ0Lcz9P1HPGFoHiFAQQID # AQABo4IBeDCCAXQwDAYDVR0TAQH/BAIwADA9BgNVHR8ENjA0MDKgMKAuhixodHRw # Oi8vY2NzY2EyMDIxLmNybC5jZXJ0dW0ucGwvY2NzY2EyMDIxLmNybDBzBggrBgEF # BQcBAQRnMGUwLAYIKwYBBQUHMAGGIGh0dHA6Ly9jY3NjYTIwMjEub2NzcC1jZXJ0 # dW0uY29tMDUGCCsGAQUFBzAChilodHRwOi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwv # Y2NzY2EyMDIxLmNlcjAfBgNVHSMEGDAWgBTddF1MANt7n6B0yrFu9zzAMsBwzTAd # BgNVHQ4EFgQUO6KtBpOBgmrlANVAnyiQC6W6lJwwSwYDVR0gBEQwQjAIBgZngQwB # BAEwNgYLKoRoAYb2dwIFAQQwJzAlBggrBgEFBQcCARYZaHR0cHM6Ly93d3cuY2Vy # dHVtLnBsL0NQUzATBgNVHSUEDDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8EBAMCB4Aw # DQYJKoZIhvcNAQELBQADggIBAEQsN8wgPMdWVkwHPPTN+jKpdns5AKVFjcn00psf # 2NGVVgWWNQBIQc9lEuTBWb54IK6Ga3hxQRZfnPNo5HGl73YLmFgdFQrFzZ1lnaMd # Icyh8LTWv6+XNWfoyCM9wCp4zMIDPOs8LKSMQqA/wRgqiACWnOS4a6fyd5GUIAm4 # CuaptpFYr90l4Dn/wAdXOdY32UhgzmSuxpUbhD8gVJUaBNVmQaRqeU8y49MxiVrU # KJXde1BCrtR9awXbqembc7Nqvmi60tYKlD27hlpKtj6eGPjkht0hHEsgzU0Fxw7Z # JghYG2wXfpF2ziN893ak9Mi/1dmCNmorGOnybKYfT6ff6YTCDDNkod4egcMZdOSv # +/Qv+HAeIgEvrxE9QsGlzTwbRtbm6gwYYcVBs/SsVUdBn/TSB35MMxRhHE5iC3aU # TkDbceo/XP3uFhVL4g2JZHpFfCSu2TQrrzRn2sn07jfMvzeHArCOJgBW1gPqR3Wr # J4hUxL06Rbg1gs9tU5HGGz9KNQMfQFQ70Wz7UIhezGcFcRfkIfSkMmQYYpsc7rfz # j+z0ThfDVzzJr2dMOFsMlfj1T6l22GBq9XQx0A4lcc5Fl9pRxbOuHHWFqIBD/BCE # hwniOCySzqENd2N+oz8znKooSISStnkNaYXt6xblJF2dx9Dn89FK7d1IquNxOwt0 # tI5dMIIGgjCCBGqgAwIBAgIQNsKwvXwbOuejs902y8l1aDANBgkqhkiG9w0BAQwF # ADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcT # C0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAs # BgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcN # MjEwMzIyMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjBXMQswCQYDVQQGEwJHQjEYMBYG # A1UEChMPU2VjdGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVTZWN0aWdvIFB1YmxpYyBU # aW1lIFN0YW1waW5nIFJvb3QgUjQ2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAiJ3YuUVnnR3d6LkmgZpUVMB8SQWbzFoVD9mUEES0QUCBdxSZqdTkdizI # CFNeINCSJS+lV1ipnW5ihkQyC0cRLWXUJzodqpnMRs46npiJPHrfLBOifjfhpdXJ # 2aHHsPHggGsCi7uE0awqKggE/LkYw3sqaBia67h/3awoqNvGqiFRJ+OTWYmUCO2G # AXsePHi+/JUNAax3kpqstbl3vcTdOGhtKShvZIvjwulRH87rbukNyHGWX5tNK/WA # BKf+Gnoi4cmisS7oSimgHUI0Wn/4elNd40BFdSZ1EwpuddZ+Wr7+Dfo0lcHflm/F # DDrOJ3rWqauUP8hsokDoI7D/yUVI9DAE/WK3Jl3C4LKwIpn1mNzMyptRwsXKrop0 # 6m7NUNHdlTDEMovXAIDGAvYynPt5lutv8lZeI5w3MOlCybAZDpK3Dy1MKo+6aEtE # 9vtiTMzz/o2dYfdP0KWZwZIXbYsTIlg1YIetCpi5s14qiXOpRsKqFKqav9R1R5vj # 3NgevsAsvxsAnI8Oa5s2oy25qhsoBIGo/zi6GpxFj+mOdh35Xn91y72J4RGOJEoq # zEIbW3q0b2iPuWLA911cRxgY5SJYubvjay3nSMbBPPFsyl6mY4/WYucmyS9lo3l7 # jk27MAe145GWxK4O3m3gEFEIkv7kRmefDR7Oe2T1HxAnICQvr9sCAwEAAaOCARYw # ggESMB8GA1UdIwQYMBaAFFN5v1qqK0rPVIDh2JvAnfKyA2bLMB0GA1UdDgQWBBT2 # d2rdP/0BE/8WoWyCAi/QCj0UJTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw # AwEB/zATBgNVHSUEDDAKBggrBgEFBQcDCDARBgNVHSAECjAIMAYGBFUdIAAwUAYD # VR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJUcnVz # dFJTQUNlcnRpZmljYXRpb25BdXRob3JpdHkuY3JsMDUGCCsGAQUFBwEBBCkwJzAl # BggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0B # AQwFAAOCAgEADr5lQe1oRLjlocXUEYfktzsljOt+2sgXke3Y8UPEooU5y39rAARa # AdAxUeiX1ktLJ3+lgxtoLQhn5cFb3GF2SSZRX8ptQ6IvuD3wz/LNHKpQ5nX8hjsD # LRhsyeIiJsms9yAWnvdYOdEMq1W61KE9JlBkB20XBee6JaXx4UBErc+YuoSb1SxV # f7nkNtUjPfcxuFtrQdRMRi/fInV/AobE8Gw/8yBMQKKaHt5eia8ybT8Y/Ffa6HAJ # yz9gvEOcF1VWXG8OMeM7Vy7Bs6mSIkYeYtddU1ux1dQLbEGur18ut97wgGwDiGin # CwKPyFO7ApcmVJOtlw9FVJxw/mL1TbyBns4zOgkaXFnnfzg4qbSvnrwyj1NiurMp # 4pmAWjR+Pb/SIduPnmFzbSN/G8reZCL4fvGlvPFk4Uab/JVCSmj59+/mB2Gn6G/U # YOy8k60mKcmaAZsEVkhOFuoj4we8CYyaR9vd9PGZKSinaZIkvVjbH/3nlLb0a7SB # IkiRzfPfS9T+JesylbHa1LtRV9U/7m0q7Ma2CQ/t392ioOssXW7oKLdOmMBl14su # VFBmbzrt5V5cQPnwtd3UOTpS9oCG+ZZheiIvPgkDmA8FzPsnfXW5qHELB43ET7HH # FHeRPRYrMBKjkb8/IN7Po0d0hQoF4TeMM+zYAJzoKQnVKOLg8pZVPT8wgganMIIE # j6ADAgECAhEAkKwIciD9xafEa1zHDfc9BjANBgkqhkiG9w0BAQwFADBXMQswCQYD # VQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVTZWN0 # aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIFJvb3QgUjQ2MB4XDTI2MDMyNTAwMDAw # MFoXDTQxMDMyNDIzNTk1OVowVTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3Rp # Z28gTGltaXRlZDEsMCoGA1UEAxMjU2VjdGlnbyBQdWJsaWMgVGltZSBTdGFtcGlu # ZyBDQSBSNDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCu5EqiAa2C # HGL5Zi1bmgPM8NUXwYZJ+BtQqHps43GLTC+sjVLypsBh+8uv+TLkgtVGD//vSmA0 # qrzELf9YRCh2MTAA/aGaQZKGg0BRCmziR3pbCnvgWjtGXBDUyn3j3K2lZAO8KxgF # tlxwOYEAkL+CCqK4v9zzTl8ZwzDpPMiDIFa5THk8an1ieF5I09cXNrPQw+1ER1li # ThaG0z6FrOpqwxZWmPRZQBw2E32878UB1bL0Zp91vuWZgsMpNNiPCoBj0/1F+LE8 # +NRokfqacFI0F2tftrRB2W7HQClLR9zjxFbWb5be2rceIfNyHUUfKGIvMI2NzoxS # lxXnFqUG887D8W1Cj8DFok688JKxWvHR/9aQykSbd+9Vutj36ij2sgq/125wTpUZ # /AgC0ph50bRs7gFrUyaXE9wSsOqMvCCC+sEm7vd/BemSG0TSHNXSmyCba+FCzeke # WX03TRIcF3Laqd0Rw24OH7jpei4zaGhcI7nfdhBA4c8RScxNY6jeHLHHmSMMTk9W # qn7H4dLhUBP5YEwbgbN4uv1i9ltTnHli8t1xHV0StX9BFgrnmunTX19kUXY1H5OR # JbRZyZDdvm1oZyteDj0SnMozr+YSmdIleDUTXdfoY7b2taz8s2+QbOxLxcahEIYG # Wzqu6h955tKwcANHcZ4gTmAhT3btuOiQsQIDAQABo4IBbjCCAWowHwYDVR0jBBgw # FoAU9ndq3T/9ARP/FqFsggIv0Ao9FCUwHQYDVR0OBBYEFDp0pQxnxkJQwv21/Me7 # KTSC9Hq5MA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBMGA1Ud # JQQMMAoGCCsGAQUFBwMIMCMGA1UdIAQcMBowCAYGZ4EMAQQCMA4GDCsGAQQBsjEB # AgEDCDBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLnNlY3RpZ28uY29tL1Nl # Y3RpZ29QdWJsaWNUaW1lU3RhbXBpbmdSb290UjQ2LmNybDB8BggrBgEFBQcBAQRw # MG4wRwYIKwYBBQUHMAKGO2h0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1 # YmxpY1RpbWVTdGFtcGluZ1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8v # b2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAMt5SR2bxngNm+N8o # c6Gq76Gx1c235fkX7jw8Ho9MAkJGADerHE7dhsBXttqmzgr/7ZZahZSykGRPhPY1 # crj028kB8KzO0dKC2qQBAwtfgqMLKkkX/6bYq2uT33eD6ByAp2/XKD0LcmZh0kKe # cvSBr6ln9ajX6u1dnx2fA7xEKy1M3qBhfQSUWLtjs2nFt0ELVLptzTlX9ID0cL+i # OPfdboZ3CelT+JXKVKR2Sge0d4YiFAtPZkfSo8z1Z1x7y/Z9mwMIlBAnyuWXs4Ys # NuxdrYIt/QxE31PDOJ9DesS4Bc7H9OTORlEV/AvfiF/VepKZpira1MzLYuCw+uoL # Zn/pkpvd+CvNTS+mEHjBJNa6WK1j8qXFu+jIq+sG9QILHiyB6p/xpHrkJu8zkw39 # 3+VqF9eKlTY2VjRxdycZLrVemZ4Yp3wi33b+W58CllH3HqjmowlZ7SOrgmx8YwYO # kgrHsXOQHyBp6O4FRb8In0+FzjT7ElGie9V7CfhL3IlVFZ4zjuKsZtH1iU3fGu4z # /JnOGT6sCb0BbTqe/uhvpFCQBdH5xPGIA/LrbQUXjU2tWJgHhTIqnN/HvHyOHi5t # M4zP3nhgh2rJ6Kqq2xsHBeNYs/R18xQ8DeIg+c90Eoaeh0YlN1KU8AyYol3K9M+q # Y5ez8syd/7ZlrRnoVewgH3P1pcswgga5MIIEoaADAgECAhEAmaOACiZVO2Wr3G6E # prPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVu # aXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZp # Y2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y # ayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIxOFowVjELMAkGA1UE # BhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEkMCIGA1UE # AxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjANBgkqhkiG9w0BAQEF # AAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5cTbq96y34vuTmflN4 # mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7VS5+djSoMcbvIKck # 6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1PH9ud0IF+njvMk2xq # bNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOouu9Tj1yHIohzuC8KN # qfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv8aGUsRdaCtVD2bSl # bfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtMLK+Wo837Q4QOZgYq # VWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9lDV2nT8mFSkcSkAE # xzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/JHuurfTI5XDYO962 # WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkKbWpQ5boufUnq1UiY # PIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADaCi2JSplKShBSND36 # E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAWd18Jx5n858JSqPEC # AwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFN10XUwA23uf # oHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8+tT4HKbROg79MA4G # A1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAwBgNVHR8EKTAnMCWg # I6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3JsMGwGCCsGAQUFBwEB # BGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3AtY2VydHVtLmNvbTAy # BggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2N0bmNhMi5j # ZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEWGGh0dHA6Ly93d3cu # Y2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhYD+WPUCiaU58Q7EP8 # 9DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUStJl490L94C9LGF3v # jzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChDUyuQy6rGDxLUUAsO # 0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiRsWrhWM2f8pXdd3x2 # mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7bWRLDm0CdY9rNLqyA # 3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mATwZWwSD+B7eMcZNhp # n8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3/bFAEloMU+vUBfSo # uCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESYkOh1/w1tVxTpV2Na # 3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR+x+zPF/2DaGgK2W1 # eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C+xN4YaNjt2ywzOr+ # tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qwt4HOUBCrW602NCmv # O1nm+/80nLy5r0AZvCQxaQ4wggbiMIIEyqADAgECAhEA507yVbBQT/rbpt/3/Iuj # FTANBgkqhkiG9w0BAQwFADBVMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGln # byBMaW1pdGVkMSwwKgYDVQQDEyNTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5n # IENBIFI0MTAeFw0yNjAzMjUwMDAwMDBaFw0zNzA2MjQyMzU5NTlaMHIxCzAJBgNV # BAYTAkdCMRcwFQYDVQQIEw5HcmVhdGVyIExvbmRvbjEYMBYGA1UEChMPU2VjdGln # byBMaW1pdGVkMTAwLgYDVQQDEydTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5n # IFNpZ25lciBSMzcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCy/8Nt # S9xQ2UUtBRF32bj7VK3n4m50Uqjk/zTciSziYV40H1LKah0/oEklYG42E4VCP3Dv # sBUB6DmpCkDZ0jCnZBPIEevaH15ZJOQwFWP2ZXr5YjlJpb68Nlbs+ElNvKx32/1Y # Hde3qqUSLybjulxPLz6T85+HOIqK7M1Bep8LspyhEP/q6nw5kGxTSrGvufmeH+JF # 8CnVBcVMFA40FlIYh0cDJVFhhfTfdWgLy/vWuLMQoKkf3s/FvByf16r0rtbyHm/i # emwxSioJL9zyZDDKUNAbHXl0dhXo2VxUV2NcPXWXuoKsjL+6cfk6Vm2DHnxAlFdF # saBDIF1JOkSnC6PeLlBznZn2buF3vIIYJcq6N/zeFRCk4/HXDz7zgRsRRMdUB+rh # yk5FoZaBjw0nLq3GZ3fClLUx5es5pUAxzNODMBn7JkFYip2BAGBPER5eV0ROhk6t # GTG+fUiMiV+vgjg1YnP5FvnYWyEtWeQD/B2hp3vz0RvtdkM0p3igyadzrfpOBq5p # pVk/YsuhTQkP99ivneHAGfi5e7lmxJ+meoBPrRLuzMmb81rzzbESjJHMsn5RVtc6 # Ucs7rcMqQC13PUIO7BbGBETV2ufCmV6lPTp3P7XJOvmnUCRTPbVvMTpxP/z+SOHg # 4/OCBhiqs4FA9+4oQvlkk9w32NGASli9GWrm5wIDAQABo4IBjjCCAYowHwYDVR0j # BBgwFoAUOnSlDGfGQlDC/bX8x7spNIL0erkwHQYDVR0OBBYEFGEQ6XoSr1HEhdTy # z6R0D1DNIK/4MA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB # /wQMMAoGCCsGAQUFBwMIMEoGA1UdIARDMEEwCAYGZ4EMAQQCMDUGDCsGAQQBsjEB # AgEDCDAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQUzBKBgNV # HR8EQzBBMD+gPaA7hjlodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJs # aWNUaW1lU3RhbXBpbmdDQVI0MS5jcmwwegYIKwYBBQUHAQEEbjBsMEUGCCsGAQUF # BzAChjlodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNUaW1lU3Rh # bXBpbmdDQVI0MS5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28u # Y29tMA0GCSqGSIb3DQEBDAUAA4ICAQAD6j2N0azN+hl6k6bKB5/U6VuSOs93ZBb3 # Pczy9VtBIKu4947Z5GwL0aFngIxl+GSuLFrJgPruBCRvKJEJsm7kv+LQ1COVCEG9 # tZ+IRtr4ocUoa53lgdFaENlS0N4wgkZkbQEPv+x+1lSjYh+T4JeL9mUznT7Erc6S # p5dWLka5sMP/m3GZi6oJPdPcsCKWagH7m2H2xDGIyHJC5PdH9phvi/KmhkktiSVT # NNqVeV5bWdX2zhRE6UTfz0IcMoCL996lFIydXxOCE4MNDHDM0as4lnTiT/KHMccO # 6l8c9TnUVgmpci9ar1IABZ2U1XUkYjGGSn9MC3EHDP9V39VuBVvZ33/BEV/EWSRr # f07T7jFplKX+gQr/UOqPGMlE7ZJ72UaUkNJy7bVl3bcLKzdpjIHzLkf/4MVa1V7w # 8wqCv5W4gOnRGTlud5UMARbRM8BPxR/CXYXoMmIOD8pmTk2axgRL4LG8XtuchISd # CHRmtacAmLGq5XSYSVTHTXADlO48iDKh3HM2r98LSF6f0sG12d8V9Jn7C3wDUieO # xuKj4MdWrW+hiJU2kF87v6eH00HgCFFc2V0+CvfOCMn7juzS41jLaINcBlKWQ/fK # b/uDLfWOW73z1I2lFY7Xj8tQ1XYtK5eREjWItM8jpl1cbQOc88btR+0XS2TmboE/ # 141+va2PWzGCBcMwggW/AgEBMGowVjELMAkGA1UEBhMCUEwxITAfBgNVBAoTGEFz # c2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEkMCIGA1UEAxMbQ2VydHVtIENvZGUgU2ln # bmluZyAyMDIxIENBAhAIMk+dt9qRb2Pk8qM8Xl1RMA0GCWCGSAFlAwQCAQUAoIGE # MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQB # gjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkE # MSIEIEcoFxhzK8PpR7fXvXOfLxQuT1d1XYGxwu5RNU7dG8ouMA0GCSqGSIb3DQEB # AQUABIIBgCsnCPh3kHwx+ZnFsy50H2NPrF4kbTqc+aIGh8QQKoPnWc0FJIyzgqy3 # l42cF79+XAzWQHN6qXuU0c7TR/w6TyCFdtgAcS6UT486RdhNDZjQ32Qm00MyJNWB # 7NwNllH6gI9fOZACVQlaXPG3me8oC0KI7bse+qu/HjylirDPRz/Af8Gklg4lcO04 # KmIKHLSx2gVlZ4wrJODfNx3eu35YW4nNeoUvzeDZJhczN8+4n1ZYVUAZdgFcOFQt # cGkVN+z4MOWUZfEQVJSV7mREXILaUk5dCq+vrzqglknpa21GNB9yazZP8I7y6+Uf # +lXTM7Xw9ICgIN6JOgrfQJGDcnDVZeqTbDRynZfrFp1RtoqG/h3PtvVCQtGOEI2k # ycQuBZ6wl1Hb7qzLtR2tv9l5zJKTIqUSGtSZjJuFNMOFvajM3/JXiZf63xYOaFYo # jl6L7S8e4FFkTzlp5vNQGr+a/kQ8p+1R8JkumpINDG35c+wEVdL5WvtJsrMknOQ/ # dghzgAEizKGCAyMwggMfBgkqhkiG9w0BCQYxggMQMIIDDAIBATBqMFUxCzAJBgNV # BAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxLDAqBgNVBAMTI1NlY3Rp # Z28gUHVibGljIFRpbWUgU3RhbXBpbmcgQ0EgUjQxAhEA507yVbBQT/rbpt/3/Iuj # FTANBglghkgBZQMEAgIFAKB5MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJ # KoZIhvcNAQkFMQ8XDTI2MDcwNzE1Mjc0OFowPwYJKoZIhvcNAQkEMTIEMJuoxETQ # eRQLANFWKXajxnFkuxn+vqfpYUPHpv7T9MoesDftmZnBQmBuZ8/181cPUjANBgkq # hkiG9w0BAQEFAASCAgAgXr6Bow/XCngVeRKlDiRxO/PleOV3/bxiL1xGQ8S/ojoQ # gB0kwPqSSSulgTYPDwNZKB7QU4dz4OtOppimsyDxZRLIj/vNxl9diApXu86eaDQB # EVQFI69IMld9u3zSqJucHP4l0WZuMq7/PxkRcNZBu/3BIVzU7vs5p1G+Lvd0M0Ni # 1quOrD5d+aVFryTBzLZ5v+GCxDmruSOujxNwAK2orxdXD9OamCWX5gcmnJD/RIZl # JyRzS0RKaUJqlC1ioCdgioI1/JBwVmcNlBaZIO5UpTtA9iIAU4g1TB6xZ4f0GsrV # Ju938ATVyBVK0wPEZp85Ubz0CFD5TGm4YmzxGDCEtdTnZX7NM/9Hs0IEk5Mh6rcM # ZmsPXBK5NWNsPr4EnewY6uaACx9c41fxcV8uPF7lSeFWpfuJFXKtKuRPigcDN10b # /rh9N+Z6LNF2A+M8IPpdeIdBcPcU70TRdE8z73ZGjSWo4yNQTYkYj4QrnwrtTKHy # ThkNIoe68Z+SDTQMFAhg6ic/zYug6EqmyQGmtav4EzeUir7gvAUGvfWXBZjuxbmm # IG6zVgzybeXtNejV3TYUAc/YR2o+vEp7UPQ/D5SeUTmuYF5hhSnR2I1F4OjyuZAo # c/YooNI6Fx69qhDsF0CaBwp59PHykpCnEtmDp7h9FQ+c51eZrL7hgLgykyVzSg== # SIG # End signature block |