Microsoft.Windows.Setting.Accessibility.psm1
# Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. $ErrorActionPreference = 'Stop' Set-StrictMode -Version Latest enum Ensure { Absent Present } enum TextSize { KeepCurrentValue Small Medium Large ExtraLarge } enum MagnificationValue { KeepCurrentValue None Low Medium High } enum PointerSize { KeepCurrentValue Normal Medium Large ExtraLarge } [Flags()] enum StickyKeysOptions { # https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-stickykeys None = 0x00000000 # 0 Active = 0x00000001 # 1 Available = 0x00000002 # 2 HotkeyActive = 0x00000004 # 4 ConfirmHotkey = 0x00000008 # 8 HotkeySound = 0x00000010# 16 VisualIndicator = 0x00000020 # 32 AudibleFeedback = 0x00000040 # 64 TriState = 0x00000080 # 128 TwoKeysOff = 0x00000100 # 256 } [Flags()] enum ToggleKeysOptions { # https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-togglekeys None = 0x00000000 # 0 Active = 0x00000001 # 1 Available = 0x00000002 # 2 HotkeyActive = 0x00000004 # 4 ConfirmHotkey = 0x00000008 # 8 HotkeySound = 0x00000010# 16 VisualIndicator = 0x00000020 # 32 } [Flags()] enum FilterKeysOptions { # https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-filterkeys None = 0x00000000 # 0 Active = 0x00000001 # 1 Available = 0x00000002 # 2 HotkeyActive = 0x00000004 # 4 ConfirmHotkey = 0x00000008 # 8 HotkeySound = 0x00000010# 16 VisualIndicator = 0x00000020 # 32 AudibleFeedback = 0x00000040 # 64 } if ([string]::IsNullOrEmpty($env:TestRegistryPath)) { $global:AccessibilityRegistryPath = 'HKCU:\Software\Microsoft\Accessibility\' $global:MagnifierRegistryPath = 'HKCU:\Software\Microsoft\ScreenMagnifier\' $global:PointerRegistryPath = 'HKCU:\Control Panel\Cursors\' $global:ControlPanelAccessibilityRegistryPath = 'HKCU:\Control Panel\Accessibility\' $global:AudioRegistryPath = 'HKCU:\Software\Microsoft\Multimedia\Audio\' $global:PersonalizationRegistryPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\' $global:NTAccessibilityRegistryPath = 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Accessibility\' $global:CursorIndicatorAccessibilityRegistryPath = 'HKCU:\Software\Microsoft\Accessibility\CursorIndicator\' $global:ControlPanelDesktopRegistryPath = 'HKCU:\Control Panel\Desktop' $global:StickyKeysRegistryPath = 'HKCU:\Control Panel\Accessibility\StickyKeys' $global:ToggleKeysRegistryPath = 'HKCU:\Control Panel\Accessibility\ToggleKeys' $global:FilterKeysRegistryPath = 'HKCU:\Control Panel\Accessibility\Keyboard Response' $global:EyeControlRegistryPath = 'HKCU:\Software\Microsoft\input\EC\' } else { $global:AccessibilityRegistryPath = $global:MagnifierRegistryPath = $global:PointerRegistryPath = $global:ControlPanelAccessibilityRegistryPath = $global:AudioRegistryPath = $global:PersonalizationRegistryPath = $global:NTAccessibilityRegistryPath = $global:CursorIndicatorAccessibilityRegistryPath = $global:ControlPanelDesktopRegistryPath = $global:StickyKeysRegistryPath = $global:ToggleKeysRegistryPath = $global:FilterKeysRegistryPath = $global:EyeControlRegistryPath = $env:TestRegistryPath } [DSCResource()] class Text { [DscProperty(Key)] [TextSize] $Size = [TextSize]::KeepCurrentValue [DscProperty(NotConfigurable)] [int] $SizeValue hidden [string] $TextScaleFactor = 'TextScaleFactor' [Text] Get() { $currentState = [Text]::new() if (-not(DoesRegistryKeyPropertyExist -Path $global:AccessibilityRegistryPath -Name $this.TextScaleFactor)) { $currentState.Size = [TextSize]::Small $currentState.SizeValue = 96 } else { $currentState.SizeValue = [int](Get-ItemPropertyValue -Path $global:AccessibilityRegistryPath -Name $this.TextScaleFactor) $currentSize = switch ($currentState.sizeValue) { 96 { [TextSize]::Small } 120 { [TextSize]::Medium } 144 { [TextSize]::Large } 256 { [TextSize]::ExtraLarge } } if ($null -ne $currentSize) { $currentState.Size = $currentSize } } return $currentState } [bool] Test() { $currentState = $this.Get() if ($this.Size -ne [TextSize]::KeepCurrentValue -and $this.Size -ne $currentState.Size) { return $false } return $true } [void] Set() { if ($this.Size -ne [TextSize]::KeepCurrentValue) { $desiredSize = switch ([TextSize]($this.Size)) { Small { 96 } Medium { 120 } Large { 144 } ExtraLarge { 256 } } Set-ItemProperty -Path $global:AccessibilityRegistryPath -Name $this.TextScaleFactor -Value $desiredSize -Type DWORD } } } [DSCResource()] class Magnifier { [DscProperty(Key)] [MagnificationValue] $Magnification = [MagnificationValue]::KeepCurrentValue [DscProperty(Mandatory)] [int] $ZoomIncrement = 25 [DscProperty()] [bool] $StartMagnify = $false [DscProperty(NotConfigurable)] [int] $MagnificationLevel [DscProperty(NotConfigurable)] [int] $ZoomIncrementLevel hidden [string] $MagnificationProperty = 'Magnification' hidden [string] $ZoomIncrementProperty = 'ZoomIncrement' [Magnifier] Get() { $currentState = [Magnifier]::new() if (-not(DoesRegistryKeyPropertyExist -Path $global:MagnifierRegistryPath -Name $this.MagnificationProperty)) { $currentState.Magnification = [MagnificationValue]::None $currentState.MagnificationLevel = 0 } else { $currentState.MagnificationLevel = (Get-ItemProperty -Path $global:MagnifierRegistryPath -Name $this.MagnificationProperty).Magnification $currentMagnification = switch ($currentState.MagnificationLevel) { 0 { [MagnificationValue]::None } 100 { [MagnificationValue]::Low } 200 { [MagnificationValue]::Medium } 300 { [MagnificationValue]::High } default { [MagnificationValue]::KeepCurrentValue } } $currentState.Magnification = $currentMagnification } if (-not(DoesRegistryKeyPropertyExist -Path $global:MagnifierRegistryPath -Name $this.ZoomIncrementProperty)) { $currentState.ZoomIncrement = 25 $currentState.ZoomIncrementLevel = 25 } else { $currentState.ZoomIncrementLevel = (Get-ItemProperty -Path $global:MagnifierRegistryPath -Name $this.ZoomIncrementProperty).ZoomIncrement $currentState.ZoomIncrement = $currentState.ZoomIncrementLevel } return $currentState } [bool] Test() { $currentState = $this.Get() if ($this.Magnification -ne [MagnificationValue]::KeepCurrentValue -and $this.Magnification -ne $currentState.Magnification) { return $false } if ($this.ZoomIncrement -ne $currentState.ZoomIncrement) { return $false } return $true } [void] Set() { if ($this.Test()) { return } if (-not (Test-Path -Path $global:MagnifierRegistryPath)) { New-Item -Path $global:MagnifierRegistryPath -Force | Out-Null } if ($this.Magnification -ne [MagnificationValue]::KeepCurrentValue) { $desiredMagnification = switch ([MagnificationValue]($this.Magnification)) { None { 0 } Low { 100 } Medium { 200 } High { 300 } } Set-ItemProperty -Path $global:MagnifierRegistryPath -Name $this.MagnificationProperty -Value $desiredMagnification -Type DWORD } $currentState = $this.Get() if ($this.ZoomIncrement -ne $currentState.ZoomIncrement) { Set-ItemProperty -Path $global:MagnifierRegistryPath -Name $this.ZoomIncrementProperty -Value $this.ZoomIncrement -Type DWORD } if (($this.StartMagnify) -and (($null -eq (Get-Process -Name 'Magnify' -ErrorAction SilentlyContinue)))) { Start-Process 'C:\Windows\System32\Magnify.exe' } } } [DSCResource()] class MousePointer { [DscProperty(Key)] [PointerSize] $PointerSize = [PointerSize]::KeepCurrentValue [DscProperty(NotConfigurable)] [string] $PointerSizeValue hidden [string] $PointerSizeProperty = 'CursorBaseSize' [MousePointer] Get() { $currentState = [MousePointer]::new() if (-not(DoesRegistryKeyPropertyExist -Path $global:PointerRegistryPath -Name $this.PointerSizeProperty)) { $currentState.PointerSize = [PointerSize]::Normal $currentState.PointerSizeValue = '32' } else { $currentState.PointerSizeValue = (Get-ItemProperty -Path $global:PointerRegistryPath -Name $this.PointerSizeProperty).CursorBaseSize $currentSize = switch ($currentState.PointerSizeValue) { '32' { [PointerSize]::Normal } '96' { [PointerSize]::Medium } '144' { [PointerSize]::Large } '256' { [PointerSize]::ExtraLarge } default { [PointerSize]::KeepCurrentValue } } $currentState.PointerSize = $currentSize } return $currentState } [bool] Test() { $currentState = $this.Get() if ($this.PointerSize -ne [PointerSize]::KeepCurrentValue -and $this.PointerSize -ne $currentState.PointerSize) { return $false } return $true } [void] Set() { if ($this.PointerSize -ne [PointerSize]::KeepCurrentValue) { $desiredSize = switch ([PointerSize]($this.PointerSize)) { Normal { '32' } Medium { '96' } Large { '144' } ExtraLarge { '256' } } if (-not (Test-Path -Path $global:PointerRegistryPath)) { New-Item -Path $global:PointerRegistryPath -Force | Out-Null } Set-ItemProperty -Path $global:PointerRegistryPath -Name $this.PointerSizeProperty -Value $desiredSize } } } [DSCResource()] class VisualEffect { # Key required. Do not set. [DscProperty(Key)] [string] $SID [DscProperty()] [nullable[bool]] $AlwaysShowScrollbars [DscProperty()] [nullable[bool]] $TransparencyEffects [DscProperty()] [int] $MessageDurationInSeconds static hidden [string] $DynamicScrollbarsProperty = 'DynamicScrollbars' static hidden [string] $TransparencySettingProperty = 'EnableTransparency' static hidden [string] $MessageDurationProperty = 'MessageDuration' static [bool] GetShowDynamicScrollbarsStatus() { if (-not(DoesRegistryKeyPropertyExist -Path $global:ControlPanelAccessibilityRegistryPath -Name ([VisualEffect]::DynamicScrollbarsProperty))) { return $false } else { $dynamicScrollbarsValue = (Get-ItemProperty -Path $global:ControlPanelAccessibilityRegistryPath -Name ([VisualEffect]::DynamicScrollbarsProperty)).DynamicScrollbars return ($dynamicScrollbarsValue -eq 0) } } static [bool] GetTransparencyStatus() { if (-not(DoesRegistryKeyPropertyExist -Path $global:PersonalizationRegistryPath -Name ([VisualEffect]::TransparencySettingProperty))) { return $false } else { $TransparencySetting = (Get-ItemProperty -Path $global:PersonalizationRegistryPath -Name ([VisualEffect]::TransparencySettingProperty)).EnableTransparency return ($TransparencySetting -eq 0) } } static [int] GetMessageDuration() { if (-not(DoesRegistryKeyPropertyExist -Path $global:ControlPanelAccessibilityRegistryPath -Name ([VisualEffect]::MessageDurationProperty))) { return 5 } else { $MessageDurationSetting = (Get-ItemProperty -Path $global:ControlPanelAccessibilityRegistryPath -Name ([VisualEffect]::MessageDurationProperty)).MessageDuration return $MessageDurationSetting } } [VisualEffect] Get() { $currentState = [VisualEffect]::new() $currentState.AlwaysShowScrollbars = [VisualEffect]::GetShowDynamicScrollbarsStatus() $currentState.TransparencyEffects = [VisualEffect]::GetTransparencyStatus() $currentState.MessageDurationInSeconds = [VisualEffect]::GetMessageDuration() return $currentState } [bool] Test() { $currentState = $this.Get() if (($null -ne $this.AlwaysShowScrollbars) -and ($this.AlwaysShowScrollbars -ne $currentState.AlwaysShowScrollbars)) { return $false } if (($null -ne $this.TransparencyEffects) -and ($this.TransparencyEffects -ne $currentState.TransparencyEffects)) { return $false } if ((0 -ne $this.MessageDurationInSeconds) -and ($this.MessageDurationInSeconds -ne $currentState.MessageDurationInSeconds)) { return $false } return $true } [void] Set() { if (-not $this.Test()) { if (-not (Test-Path -Path $global:ControlPanelAccessibilityRegistryPath)) { New-Item -Path $global:ControlPanelAccessibilityRegistryPath -Force | Out-Null } if ($null -ne $this.AlwaysShowScrollbars) { $dynamicScrollbarValue = if ($this.AlwaysShowScrollbars) { 0 } else { 1 } Set-ItemProperty -Path $global:ControlPanelAccessibilityRegistryPath -Name ([VisualEffect]::DynamicScrollbarsProperty) -Value $dynamicScrollbarValue } if ($null -ne $this.TransparencyEffects) { $transparencyValue = if ($this.TransparencyEffects) { 0 } else { 1 } if (-not (DoesRegistryKeyPropertyExist -Path $global:PersonalizationRegistryPath -Name ([VisualEffect]::TransparencySettingProperty))) { New-ItemProperty -Path $global:PersonalizationRegistryPath -Name ([VisualEffect]::TransparencySettingProperty) -Value $transparencyValue -PropertyType DWord } Set-ItemProperty -Path $global:PersonalizationRegistryPath -Name ([VisualEffect]::TransparencySettingProperty) -Value $transparencyValue } if (0 -ne $this.MessageDurationInSeconds) { $min = 5 $max = 300 if ($this.MessageDurationInSeconds -notin $min..$max) { throw "MessageDurationInSeconds must be between $min and $max. Value $($this.MessageDurationInSeconds) was provided." } Set-ItemProperty -Path $global:ControlPanelAccessibilityRegistryPath -Name ([VisualEffect]::MessageDurationProperty) -Value $this.MessageDurationInSeconds } } } } [DSCResource()] class Audio { # Key required. Do not set. [DscProperty(Key)] [string] $SID [DscProperty()] [bool] $EnableMonoAudio = $false static hidden [string] $EnableMonoAudioProperty = 'AccessibilityMonoMixState' static [bool] GetEnableMonoAudioStatus() { if (-not(DoesRegistryKeyPropertyExist -Path $global:AudioRegistryPath -Name ([Audio]::EnableMonoAudioProperty))) { return $false } else { $AudioMonoSetting = (Get-ItemProperty -Path $global:AudioRegistryPath -Name ([Audio]::EnableMonoAudioProperty)).AccessibilityMonoMixState return ($AudioMonoSetting -eq 0) } } [Audio] Get() { $currentState = [Audio]::new() $currentState.EnableMonoAudio = [Audio]::GetEnableMonoAudioStatus() return $currentState } [bool] Test() { $currentState = $this.Get() if ($this.EnableMonoAudio -ne $currentState.EnableMonoAudio) { return $false } return $true } [void] Set() { if (-not $this.Test()) { if (-not (Test-Path -Path $global:AudioRegistryPath)) { New-Item -Path $global:AudioRegistryPath -Force | Out-Null } $monoAudioValue = if ($this.EnableMonoAudio) { 0 } else { 1 } Set-ItemProperty -Path $global:AudioRegistryPath -Name ([Audio]::EnableMonoAudioProperty) -Value $monoAudioValue } } } [DSCResource()] class TextCursor { # Key required. Do not set. [DscProperty(Key)] [string] $SID [DscProperty()] [nullable[bool]] $IndicatorStatus [DscProperty()] [int] $IndicatorSize [DscProperty()] [int] $IndicatorColor [DscProperty()] [int] $Thickness static hidden [string] $IndicatorStatusProperty = 'Configuration' static hidden [string] $IndicatorStatusValue = 'cursorindicator' static hidden [string] $IndicatorSizeProperty = 'IndicatorType' static hidden [string] $IndicatorColorProperty = 'IndicatorColor' static hidden [string] $ThicknessProperty = 'CaretWidth' static [bool] GetIndicatorStatus() { $indicatorStatusArgs = @{ Path = $global:NTAccessibilityRegistryPath; Name = ([TextCursor]::IndicatorStatusProperty) } if (-not(DoesRegistryKeyPropertyExist @indicatorStatusArgs)) { return $false } else { $textCursorSetting = (Get-ItemProperty @indicatorStatusArgs).Configuration return ($textCursorSetting -eq ([TextCursor]::IndicatorStatusValue)) } } static [int] GetIndicatorSize() { $indicatorSizeArgs = @{ Path = $global:CursorIndicatorAccessibilityRegistryPath; Name = ([TextCursor]::IndicatorSizeProperty) } if (-not(DoesRegistryKeyPropertyExist @indicatorSizeArgs)) { return 1 } else { $textCursorSetting = (Get-ItemProperty @indicatorSizeArgs).IndicatorType return $textCursorSetting } } static [int] GetIndicatorColor() { $indicatorColorArgs = @{ Path = $global:CursorIndicatorAccessibilityRegistryPath; Name = ([TextCursor]::IndicatorColorProperty) } if (-not(DoesRegistryKeyPropertyExist @indicatorColorArgs)) { return $false } else { $textCursorSetting = (Get-ItemProperty @indicatorColorArgs).IndicatorColor return $textCursorSetting } } static [int] GetThickness() { $thicknessArgs = @{ Path = $global:ControlPanelDesktopRegistryPath; Name = ([TextCursor]::ThicknessProperty); } if (-not(DoesRegistryKeyPropertyExist @thicknessArgs)) { return 1 } else { $textCursorSetting = (Get-ItemProperty @thicknessArgs).CaretWidth return $textCursorSetting } } [TextCursor] Get() { $currentState = [TextCursor]::new() $currentState.IndicatorStatus = [TextCursor]::GetIndicatorStatus() $currentState.IndicatorSize = [TextCursor]::GetIndicatorSize() $currentState.IndicatorColor = [TextCursor]::GetIndicatorColor() $currentState.Thickness = [TextCursor]::GetThickness() return $currentState } [bool] Test() { $currentState = $this.Get() if (($null -ne $this.IndicatorStatus) -and ($this.IndicatorStatus -ne $currentState.IndicatorStatus)) { return $false } if ((0 -ne $this.IndicatorSize) -and ($this.IndicatorSize -ne $currentState.IndicatorSize)) { return $false } if ((0 -ne $this.IndicatorColor) -and ($this.IndicatorColor -ne $currentState.IndicatorColor)) { return $false } if ((0 -ne $this.Thickness) -and ($this.Thickness -ne $currentState.Thickness)) { return $false } return $true } [void] Set() { if (-not $this.Test()) { if ($null -ne $this.IndicatorStatus) { $indicatorStatusArgs = @{ Path = $global:NTAccessibilityRegistryPath; Name = ([TextCursor]::IndicatorStatusProperty); } $textCursorValue = if ($this.IndicatorStatus) { ([TextCursor]::IndicatorStatusValue) } else { '' } Set-ItemProperty @indicatorStatusArgs -Value $textCursorValue } if (0 -ne $this.IndicatorSize) { $indicatorSizeArgs = @{ Path = $global:CursorIndicatorAccessibilityRegistryPath; Name = ([TextCursor]::IndicatorSizeProperty) } $min = 1 $max = 20 if ($this.IndicatorSize -notin $min..$max) { throw "IndicatorSize must be between $min and $max. Value $($this.IndicatorSize) was provided." } if (-not (DoesRegistryKeyPropertyExist @indicatorSizeArgs)) { New-ItemProperty @indicatorSizeArgs -Value $this.IndicatorSize -PropertyType DWord } Set-ItemProperty @indicatorSizeArgs -Value $this.IndicatorSize } if (0 -ne $this.IndicatorColor) { $indicatorColorArgs = @{ Path = $global:CursorIndicatorAccessibilityRegistryPath; Name = ([TextCursor]::IndicatorColorProperty) } $min = 1 $max = 99999999 if ($this.IndicatorColor -notin $min..$max) { throw "IndicatorColor must be between $min and $max. Value $($this.IndicatorColor) was provided." } if (-not (DoesRegistryKeyPropertyExist @indicatorColorArgs)) { New-ItemProperty @indicatorColorArgs -Value $this.IndicatorColor -PropertyType DWord } Set-ItemProperty @indicatorColorArgs -Value $this.IndicatorColor } if (0 -ne $this.Thickness) { $thicknessArgs = @{ Path = $global:ControlPanelDesktopRegistryPath; Name = ([TextCursor]::ThicknessProperty); } $min = 1 $max = 20 if ($this.Thickness -notin $min..$max) { throw "Thickness must be between $min and $max. Value $($this.Thickness) was provided." } Set-ItemProperty @thicknessArgs -Value $this.Thickness } } } } [DSCResource()] class StickyKeys { # Key required. Do not set. [DscProperty(Key)] [string] $SID [DscProperty()] [nullable[bool]] $Active [DscProperty()] [nullable[bool]] $Available [DscProperty()] [nullable[bool]] $HotkeyActive [DscProperty()] [nullable[bool]] $ConfirmOnHotkeyActivation [DscProperty()] [nullable[bool]] $HotkeySound [DscProperty()] [nullable[bool]] $VisualIndicator [DscProperty()] [nullable[bool]] $AudibleFeedback [DscProperty()] [nullable[bool]] $TriState [DscProperty()] [nullable[bool]] $TwoKeysOff static hidden [string] $SettingsProperty = 'Flags' static [System.Enum] GetCurrentFlags() { if (-not(DoesRegistryKeyPropertyExist -Path $global:StickyKeysRegistryPath -Name ([StickyKeys]::SettingsProperty))) { return [StickyKeysOptions]::None } else { $StickyKeysFlags = [System.Enum]::Parse('StickyKeysOptions', (Get-ItemPropertyValue -Path $global:StickyKeysRegistryPath -Name ([StickyKeys]::SettingsProperty))) return $StickyKeysFlags } } [StickyKeys] Get() { $currentFlags = [StickyKeys]::GetCurrentFlags() $currentState = [StickyKeys]::new() $currentState.Active = $currentFlags.HasFlag([StickyKeysOptions]::Active) $currentState.Available = $currentFlags.HasFlag([StickyKeysOptions]::Available) $currentState.HotkeyActive = $currentFlags.HasFlag([StickyKeysOptions]::HotkeyActive) $currentState.ConfirmOnHotkeyActivation = $currentFlags.HasFlag([StickyKeysOptions]::ConfirmHotkey) $currentState.HotkeySound = $currentFlags.HasFlag([StickyKeysOptions]::HotkeySound) $currentState.VisualIndicator = $currentFlags.HasFlag([StickyKeysOptions]::VisualIndicator) $currentState.AudibleFeedback = $currentFlags.HasFlag([StickyKeysOptions]::AudibleFeedback) $currentState.TriState = $currentFlags.HasFlag([StickyKeysOptions]::TriState) $currentState.TwoKeysOff = $currentFlags.HasFlag([StickyKeysOptions]::TwoKeysOff) return $currentState } [bool] Test() { $currentState = $this.Get() if (($null -ne $this.Active) -and ($this.Active -ne $currentState.Active)) { return $false } if (($null -ne $this.Available) -and ($this.Available -ne $currentState.Available)) { return $false } if (($null -ne $this.HotkeyActive) -and ($this.HotkeyActive -ne $currentState.HotkeyActive)) { return $false } if (($null -ne $this.ConfirmOnHotkeyActivation) -and ($this.ConfirmOnHotkeyActivation -ne $currentState.ConfirmOnHotkeyActivation)) { return $false } if (($null -ne $this.HotkeySound) -and ($this.HotkeySound -ne $currentState.HotkeySound)) { return $false } if (($null -ne $this.VisualIndicator) -and ($this.VisualIndicator -ne $currentState.VisualIndicator)) { return $false } if (($null -ne $this.AudibleFeedback) -and ($this.AudibleFeedback -ne $currentState.AudibleFeedback)) { return $false } if (($null -ne $this.TriState) -and ($this.TriState -ne $currentState.TriState)) { return $false } if (($null -ne $this.TwoKeysOff) -and ($this.TwoKeysOff -ne $currentState.TwoKeysOff)) { return $false } return $true } [void] Set() { # Only make changes if changes are needed if (-not $this.Test()) { # If a value isn't set in the DSC, it should remain unchanged, to do this we need the current flags $flags = [StickyKeys]::GetCurrentFlags() if ($null -ne $this.Active) { $flags = $this.Active ? $flags -bor [StickyKeysOptions]::Active : $flags -band (-bnot [StickyKeysOptions]::Active) } if ($null -ne $this.Available) { $flags = $this.Available ? $flags -bor [StickyKeysOptions]::Available : $flags -band (-bnot [StickyKeysOptions]::Available) } if ($null -ne $this.HotkeyActive) { $flags = $this.HotkeyActive ? $flags -bor [StickyKeysOptions]::HotkeyActive : $flags -band (-bnot [StickyKeysOptions]::HotkeyActive) } if ($null -ne $this.ConfirmOnHotkeyActivation) { $flags = $this.ConfirmOnHotkeyActivation ? $flags -bor [StickyKeysOptions]::ConfirmHotkey : $flags -band (-bnot [StickyKeysOptions]::ConfirmHotkey) } if ($null -ne $this.HotkeySound) { $flags = $this.HotkeySound ? $flags -bor [StickyKeysOptions]::HotkeySound : $flags -band (-bnot [StickyKeysOptions]::HotkeySound) } if ($null -ne $this.VisualIndicator) { $flags = $this.VisualIndicator ? $flags -bor [StickyKeysOptions]::VisualIndicator : $flags -band (-bnot [StickyKeysOptions]::VisualIndicator) } if ($null -ne $this.AudibleFeedback) { $flags = $this.AudibleFeedback ? $flags -bor [StickyKeysOptions]::AudibleFeedback : $flags -band (-bnot [StickyKeysOptions]::AudibleFeedback) } if ($null -ne $this.TriState) { $flags = $this.TriState ? $flags -bor [StickyKeysOptions]::TriState : $flags -band (-bnot [StickyKeysOptions]::TriState) } if ($null -ne $this.TwoKeysOff) { $flags = $this.TwoKeysOff ? $flags -bor [StickyKeysOptions]::TwoKeysOff : $flags -band (-bnot [StickyKeysOptions]::TwoKeysOff) } # Set the value in the registry Set-ItemProperty -Path $global:StickyKeysRegistryPath -Name ([StickyKeys]::SettingsProperty) -Value $flags.GetHashCode() } } } [DSCResource()] class ToggleKeys { # Key required. Do not set. [DscProperty(Key)] [string] $SID [DscProperty()] [nullable[bool]] $Active [DscProperty()] [nullable[bool]] $Available [DscProperty()] [nullable[bool]] $HotkeyActive [DscProperty()] [nullable[bool]] $ConfirmOnHotkeyActivation [DscProperty()] [nullable[bool]] $HotkeySound [DscProperty()] [nullable[bool]] $VisualIndicator static hidden [string] $SettingsProperty = 'Flags' static [System.Enum] GetCurrentFlags() { if (-not(DoesRegistryKeyPropertyExist -Path $global:ToggleKeysRegistryPath -Name ([ToggleKeys]::SettingsProperty))) { return [ToggleKeysOptions]::None } else { $ToggleKeysFlags = [System.Enum]::Parse('ToggleKeysOptions', (Get-ItemPropertyValue -Path $global:StickyKeysRegistryPath -Name ([StickyKeys]::SettingsProperty))) return $ToggleKeysFlags } } [ToggleKeys] Get() { $currentFlags = [ToggleKeys]::GetCurrentFlags() $currentState = [ToggleKeys]::new() $currentState.Active = $currentFlags.HasFlag([ToggleKeysOptions]::Active) $currentState.Available = $currentFlags.HasFlag([ToggleKeysOptions]::Available) $currentState.HotkeyActive = $currentFlags.HasFlag([ToggleKeysOptions]::HotkeyActive) $currentState.ConfirmOnHotkeyActivation = $currentFlags.HasFlag([ToggleKeysOptions]::ConfirmHotkey) $currentState.HotkeySound = $currentFlags.HasFlag([ToggleKeysOptions]::HotkeySound) $currentState.VisualIndicator = $currentFlags.HasFlag([ToggleKeysOptions]::VisualIndicator) return $currentState } [bool] Test() { $currentState = $this.Get() if (($null -ne $this.Active) -and ($this.Active -ne $currentState.Active)) { return $false } if (($null -ne $this.Available) -and ($this.Available -ne $currentState.Available)) { return $false } if (($null -ne $this.HotkeyActive) -and ($this.HotkeyActive -ne $currentState.HotkeyActive)) { return $false } if (($null -ne $this.ConfirmOnHotkeyActivation) -and ($this.ConfirmOnHotkeyActivation -ne $currentState.ConfirmOnHotkeyActivation)) { return $false } if (($null -ne $this.HotkeySound) -and ($this.HotkeySound -ne $currentState.HotkeySound)) { return $false } if (($null -ne $this.VisualIndicator) -and ($this.VisualIndicator -ne $currentState.VisualIndicator)) { return $false } return $true } [void] Set() { # Only make changes if changes are needed if (-not $this.Test()) { # If a value isn't set in the DSC, it should remain unchanged, to do this we need the current flags $flags = [ToggleKeys]::GetCurrentFlags() if ($null -ne $this.Active) { $flags = $this.Active ? $flags -bor [ToggleKeysOptions]::Active : $flags -band (-bnot [ToggleKeysOptions]::Active) } if ($null -ne $this.Available) { $flags = $this.Available ? $flags -bor [ToggleKeysOptions]::Available : $flags -band (-bnot [ToggleKeysOptions]::Available) } if ($null -ne $this.HotkeyActive) { $flags = $this.HotkeyActive ? $flags -bor [ToggleKeysOptions]::HotkeyActive : $flags -band (-bnot [ToggleKeysOptions]::HotkeyActive) } if ($null -ne $this.ConfirmOnHotkeyActivation) { $flags = $this.ConfirmOnHotkeyActivation ? $flags -bor [ToggleKeysOptions]::ConfirmHotkey : $flags -band (-bnot [ToggleKeysOptions]::ConfirmHotkey) } if ($null -ne $this.HotkeySound) { $flags = $this.HotkeySound ? $flags -bor [ToggleKeysOptions]::HotkeySound : $flags -band (-bnot [ToggleKeysOptions]::HotkeySound) } if ($null -ne $this.VisualIndicator) { $flags = $this.VisualIndicator ? $flags -bor [ToggleKeysOptions]::VisualIndicator : $flags -band (-bnot [ToggleKeysOptions]::VisualIndicator) } # Set the value in the registry Set-ItemProperty -Path $global:ToggleKeysRegistryPath -Name ([ToggleKeys]::SettingsProperty) -Value $flags.GetHashCode() } } } [DSCResource()] class FilterKeys { # Key required. Do not set. [DscProperty(Key)] [string] $SID [DscProperty()] [nullable[bool]] $Active [DscProperty()] [nullable[bool]] $Available [DscProperty()] [nullable[bool]] $HotkeyActive [DscProperty()] [nullable[bool]] $ConfirmOnHotkeyActivation [DscProperty()] [nullable[bool]] $HotkeySound [DscProperty()] [nullable[bool]] $VisualIndicator [DscProperty()] [nullable[bool]] $AudibleFeedback static hidden [string] $SettingsProperty = 'Flags' static [System.Enum] GetCurrentFlags() { if (-not(DoesRegistryKeyPropertyExist -Path $global:FilterKeysRegistryPath -Name ([FilterKeys]::SettingsProperty))) { return [FilterKeysOptions]::None } else { $FilterKeysFlags = [System.Enum]::Parse('FilterKeysOptions', (Get-ItemPropertyValue -Path $global:FilterKeysRegistryPath -Name ([FilterKeys]::SettingsProperty))) return $FilterKeysFlags } } [FilterKeys] Get() { $currentFlags = [FilterKeys]::GetCurrentFlags() $currentState = [FilterKeys]::new() $currentState.Active = $currentFlags.HasFlag([FilterKeysOptions]::Active) $currentState.Available = $currentFlags.HasFlag([FilterKeysOptions]::Available) $currentState.HotkeyActive = $currentFlags.HasFlag([FilterKeysOptions]::HotkeyActive) $currentState.ConfirmOnHotkeyActivation = $currentFlags.HasFlag([FilterKeysOptions]::ConfirmHotkey) $currentState.HotkeySound = $currentFlags.HasFlag([FilterKeysOptions]::HotkeySound) $currentState.VisualIndicator = $currentFlags.HasFlag([FilterKeysOptions]::VisualIndicator) $currentState.AudibleFeedback = $currentFlags.HasFlag([FilterKeysOptions]::AudibleFeedback) return $currentState } [bool] Test() { $currentState = $this.Get() if (($null -ne $this.Active) -and ($this.Active -ne $currentState.Active)) { return $false } if (($null -ne $this.Available) -and ($this.Available -ne $currentState.Available)) { return $false } if (($null -ne $this.HotkeyActive) -and ($this.HotkeyActive -ne $currentState.HotkeyActive)) { return $false } if (($null -ne $this.ConfirmOnHotkeyActivation) -and ($this.ConfirmOnHotkeyActivation -ne $currentState.ConfirmOnHotkeyActivation)) { return $false } if (($null -ne $this.HotkeySound) -and ($this.HotkeySound -ne $currentState.HotkeySound)) { return $false } if (($null -ne $this.VisualIndicator) -and ($this.VisualIndicator -ne $currentState.VisualIndicator)) { return $false } if (($null -ne $this.AudibleFeedback) -and ($this.AudibleFeedback -ne $currentState.AudibleFeedback)) { return $false } return $true } [void] Set() { # Only make changes if changes are needed if (-not $this.Test()) { # If a value isn't set in the DSC, it should remain unchanged, to do this we need the current flags $flags = [FilterKeys]::GetCurrentFlags() if ($null -ne $this.Active) { $flags = $this.Active ? $flags -bor [FilterKeysOptions]::Active : $flags -band (-bnot [FilterKeysOptions]::Active) } if ($null -ne $this.Available) { $flags = $this.Available ? $flags -bor [FilterKeysOptions]::Available : $flags -band (-bnot [FilterKeysOptions]::Available) } if ($null -ne $this.HotkeyActive) { $flags = $this.HotkeyActive ? $flags -bor [FilterKeysOptions]::HotkeyActive : $flags -band (-bnot [FilterKeysOptions]::HotkeyActive) } if ($null -ne $this.ConfirmOnHotkeyActivation) { $flags = $this.ConfirmOnHotkeyActivation ? $flags -bor [FilterKeysOptions]::ConfirmHotkey : $flags -band (-bnot [FilterKeysOptions]::ConfirmHotkey) } if ($null -ne $this.HotkeySound) { $flags = $this.HotkeySound ? $flags -bor [FilterKeysOptions]::HotkeySound : $flags -band (-bnot [FilterKeysOptions]::HotkeySound) } if ($null -ne $this.VisualIndicator) { $flags = $this.VisualIndicator ? $flags -bor [FilterKeysOptions]::VisualIndicator : $flags -band (-bnot [FilterKeysOptions]::VisualIndicator) } if ($null -ne $this.AudibleFeedback) { $flags = $this.AudibleFeedback ? $flags -bor [FilterKeysOptions]::AudibleFeedback : $flags -band (-bnot [FilterKeysOptions]::AudibleFeedback) } # Set the value in the registry Set-ItemProperty -Path $global:FilterKeysRegistryPath -Name ([FilterKeys]::SettingsProperty) -Value $flags.GetHashCode() } } } [DscResource()] class EyeControl { [DscProperty(Key)] [Ensure] $Ensure hidden [string] $SettingsProperty = 'Enabled' [EyeControl] Get() { $currentState = [EyeControl]::new() if (-not(DoesRegistryKeyPropertyExist -Path $global:EyeControlRegistryPath -Name $this.SettingsProperty)) { $currentState.Ensure = [Ensure]::Absent } else { $currentState.Ensure = [int]((Get-ItemPropertyValue -Path $global:EyeControlRegistryPath -Name $this.SettingsProperty) -eq 1) } return $currentState } [bool] Test() { return $this.Get().Ensure -eq $this.Ensure } [void] Set() { # Only make changes if changes are needed if ($this.Test()) { return } if (-not (DoesRegistryKeyPropertyExist -Path $global:EyeControlRegistryPath -Name $this.SettingsProperty)) { New-ItemProperty -Path $global:EyeControlRegistryPath -Name $this.SettingsProperty -PropertyType DWord } Set-ItemProperty -Path $global:EyeControlRegistryPath -Name $this.SettingsProperty -Value $([int]$this.Ensure) } } #region Functions function DoesRegistryKeyPropertyExist { param ( [Parameter(Mandatory)] [string]$Path, [Parameter(Mandatory)] [string]$Name ) # Get-ItemProperty will return $null if the registry key property does not exist. $itemProperty = Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue return $null -ne $itemProperty } #endregion Functions # SIG # Begin signature block # MIIoDwYJKoZIhvcNAQcCoIIoADCCJ/wCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBrdZoT+FMQnFFK # yP6hzsNR2nJWHjD/vW8hO7sobwiDL6CCDXYwggX0MIID3KADAgECAhMzAAAEBGx0 # Bv9XKydyAAAAAAQEMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjQwOTEyMjAxMTE0WhcNMjUwOTExMjAxMTE0WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQC0KDfaY50MDqsEGdlIzDHBd6CqIMRQWW9Af1LHDDTuFjfDsvna0nEuDSYJmNyz # NB10jpbg0lhvkT1AzfX2TLITSXwS8D+mBzGCWMM/wTpciWBV/pbjSazbzoKvRrNo # DV/u9omOM2Eawyo5JJJdNkM2d8qzkQ0bRuRd4HarmGunSouyb9NY7egWN5E5lUc3 # a2AROzAdHdYpObpCOdeAY2P5XqtJkk79aROpzw16wCjdSn8qMzCBzR7rvH2WVkvF # HLIxZQET1yhPb6lRmpgBQNnzidHV2Ocxjc8wNiIDzgbDkmlx54QPfw7RwQi8p1fy # 4byhBrTjv568x8NGv3gwb0RbAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU8huhNbETDU+ZWllL4DNMPCijEU4w # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzUwMjkyMzAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAIjmD9IpQVvfB1QehvpC # Ge7QeTQkKQ7j3bmDMjwSqFL4ri6ae9IFTdpywn5smmtSIyKYDn3/nHtaEn0X1NBj # L5oP0BjAy1sqxD+uy35B+V8wv5GrxhMDJP8l2QjLtH/UglSTIhLqyt8bUAqVfyfp # h4COMRvwwjTvChtCnUXXACuCXYHWalOoc0OU2oGN+mPJIJJxaNQc1sjBsMbGIWv3 # cmgSHkCEmrMv7yaidpePt6V+yPMik+eXw3IfZ5eNOiNgL1rZzgSJfTnvUqiaEQ0X # dG1HbkDv9fv6CTq6m4Ty3IzLiwGSXYxRIXTxT4TYs5VxHy2uFjFXWVSL0J2ARTYL # E4Oyl1wXDF1PX4bxg1yDMfKPHcE1Ijic5lx1KdK1SkaEJdto4hd++05J9Bf9TAmi # u6EK6C9Oe5vRadroJCK26uCUI4zIjL/qG7mswW+qT0CW0gnR9JHkXCWNbo8ccMk1 # sJatmRoSAifbgzaYbUz8+lv+IXy5GFuAmLnNbGjacB3IMGpa+lbFgih57/fIhamq # 5VhxgaEmn/UjWyr+cPiAFWuTVIpfsOjbEAww75wURNM1Imp9NJKye1O24EspEHmb # DmqCUcq7NqkOKIG4PVm3hDDED/WQpzJDkvu4FrIbvyTGVU01vKsg4UfcdiZ0fQ+/ # V0hf8yrtq9CkB8iIuk5bBxuPMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg # Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 # a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr # rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg # OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy # 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 # sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh # dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k # A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB # w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn # Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 # lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w # ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o # ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa # BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG # AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV # HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG # AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl # AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb # C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l # hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 # I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 # wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 # STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam # ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa # J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah # XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA # 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt # Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr # /Xmfwb1tbWrJUnMTDXpQzTGCGe8wghnrAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAAQEbHQG/1crJ3IAAAAABAQwDQYJYIZIAWUDBAIB # BQCggZAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwLwYJKoZIhvcNAQkEMSIE # IDRKi8Va9CnqSjvpVL/0guEkwVqZXwfe3hJb97gr7+UoMEIGCisGAQQBgjcCAQwx # NDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29m # dC5jb20wDQYJKoZIhvcNAQEBBQAEggEAGe+5w0HCyOB5lcfqYQbRCDQ4ZFtrJ2HU # auzGF6GYmUtkg4hrn2+ct8jCOtgF0bjVWJPr6YcQ6drksSg6TPl4R/ePxuhtKFYT # ZoDoSN9oZ8nLnYKnoRtkdWD/iuNOcbeWSbIrfT+bBCJ6tPbAq3rOlf20AeotHaoq # 5Unvh0Bnx0HAGWP7aZpL+L31Fog3W9aylbZ16Ih4WJeLz5he4uIvO9ZRKmTwQ6Yu # CbTq3UK0ZFcLaiDtQ+3fatnbqFByY+Vn+rduDUJS/1grUmluJuIrCrzWyuZdRHxp # Cjs2JxfZ4bBwDc5KqmpkFW14051qOyAoQVcOly5xM1UOu8FVPrBMmKGCF5cwgheT # BgorBgEEAYI3AwMBMYIXgzCCF38GCSqGSIb3DQEHAqCCF3AwghdsAgEDMQ8wDQYJ # YIZIAWUDBAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYB # BAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCBpgFeoU6SCfQmfDLDwz6N9SQBo3GIW # lRNJLKqi87NszgIGZ/hLylpYGBMyMDI1MDQxNTIxMjcwNy42NTJaMASAAgH0oIHR # pIHOMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYD # VQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hp # ZWxkIFRTUyBFU046MzMwMy0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBU # aW1lLVN0YW1wIFNlcnZpY2WgghHtMIIHIDCCBQigAwIBAgITMwAAAg9XmkcUQOZG # 5gABAAACDzANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg # MjAxMDAeFw0yNTAxMzAxOTQzMDRaFw0yNjA0MjIxOTQzMDRaMIHLMQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQg # QW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046MzMw # My0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZp # Y2UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCl6DTurxf66o73G0A2 # yKo1/nYvITBQsd50F52SQzo2cSrt+EDEFCDlSxZzWJD7ujQ1Z1dMbMT6YhK7JUvw # xQ+LkQXv2k/3v3xw8xJ2mhXuwbT+s1WOL0+9g9AOEAAM6WGjCzI/LZq3/tzHr56i # n/Z++o/2soGhyGhKMDwWl4J4L1Fn8ndtoM1SBibPdqmwmPXpB9QtaP+TCOC1vAaG # QOdsqXQ8AdlK6Vuk9yW9ty7S0kRP1nXkFseM33NzBu//ubaoJHb1ceYPZ4U4EOXB # Hi/2g09WRL9QWItHjPGJYjuJ0ckyrOG1ksfAZWP+Bu8PXAq4s1Ba/h/nXhXAwuxT # hpvaFb4T0bOjYO/h2LPRbdDMcMfS9Zbhq10hXP6ZFHR0RRJ+rr5A8ID9l0UgoUu/ # gNvCqHCMowz97udo7eWODA7LaVv81FHHYw3X5DSTUqJ6pwP+/0lxatxajbSGsm26 # 7zqVNsuzUoF2FzPM+YUIwiOpgQvvjYIBkB+KUwZf2vRIPWmhAEzWZAGTox/0vj4e # HgxwER9fpThcsbZGSxx0nL54Hz+L36KJyEVio+oJVvUxm75YEESaTh1RnL0Dls91 # sBw6mvKrO2O+NCbUtfx+cQXYS0JcWZef810BW9Bn/eIvow3Kcx0dVuqDfIWfW7im # eTLAK9QAEk+oZCJzUUTvhh2hYQIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFJnUMQ2O # tyAhLR/MD2qtJ9lKRP9ZMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1Gely # MF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv # cHMvY3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNy # bDBsBggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9z # b2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBD # QSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYB # BQUHAwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQBTowbo1bUE # 7fXTy+uW9m58qGEXRBGVMEQiFEfSui1fhN7jS+kSiN0SR5Kl3AuV49xOxgHo9+GI # ne5Mpg5n4NS5PW8nWIWGj/8jkE3pdJZSvAZarXD4l43iMNxDhdBZqVCkAYcdFVZn # xdy+25MRY6RfaGwkinjnYNFA6DYL/1cxw6Ya4sXyV7FgPdMmxVpffnPEDFv4mcVx # 3jvPZod7gqiDcUHbyV1gaND3PejyJ1MGfBYbAQxsynLX1FUsWLwKsNPRJjynwlzB # T/OQbxnzkjLibi4h4dOwcN+H4myDtUSnYq9Xf4YvFlZ+mJs5Ytx4U9JVCyW/WERt # IEieTvTRgvAYj/4Mh1F2Elf8cdILgzi9ezqYefxdsBD8Vix35yMC5LTnDUoyVVul # UeeDAJY8+6YBbtXIty4phIkihiIHsyWVxW2YGG6A6UWenuwY6z9oBONvMHlqtD37 # ZyLn0h1kCkkp5kcIIhMtpzEcPkfqlkbDVogMoWy80xulxt64P4+1YIzkRht3zTO+ # jLONu1pmBt+8EUh7DVct/33tuW5NOSx56jXQ1TdOdFBpgcW8HvJii8smQ1TQP42H # NIKIJY5aiMkK9M2HoxYrQy2MoHNOPySsOzr3le/4SDdX67uobGkUNerlJKzKpTR5 # ZU0SeNAu5oCyDb6gdtTiaN50lCC6m44sXjCCB3EwggVZoAMCAQICEzMAAAAVxedr # ngKbSZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp # ZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4 # MzIyNVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG # A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3 # DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qls # TnXIyjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLA # EBjoYH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrE # qv1yaa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyF # Vk3v3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1o # O5pGve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg # 3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2 # TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07B # MzlMjgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJ # NmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6 # r1AFemzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+ # auIurQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3 # FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl # 0mWnG1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUH # AgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0 # b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMA # dQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAW # gBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8v # Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRf # MjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEw # LTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL # /Klv6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu # 6WZnOlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5t # ggz1bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfg # QJY4rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8s # CXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCr # dTDFNLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZ # c9d/HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2 # tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8C # wYKiexcdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9 # JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDB # cQZqELQdVTNYs6FwZvKhggNQMIICOAIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFt # ZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjMzMDMt # MDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl # oiMKAQEwBwYFKw4DAhoDFQBetIzj2C/MkdiI03EyNsCtSOMdWqCBgzCBgKR+MHwx # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p # Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA66i4 # rDAiGA8yMDI1MDQxNTEwNTEyNFoYDzIwMjUwNDE2MTA1MTI0WjB3MD0GCisGAQQB # hFkKBAExLzAtMAoCBQDrqLisAgEAMAoCAQACAhNlAgH/MAcCAQACAhKZMAoCBQDr # qgosAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMH # oSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAFLlo+VF/LM5gBS6ICfe # IJZ3PEeMuB3Mh4PQviSE+fm4kUQ2x++9ZrvfWZvbqBL2F8YMberY3xeung9mEOI4 # 48crw8tHJ0jCU7RLdyvseTPwsewI1mvv8CFfzwjqPdtvbwQkNT/Xi3G3n0voMWBU # R68gLYh9zctpt0E4tvY6udy++s1XZ5w/69HdPVoVa9kVM7IZSaW/fhuo7ZOOP3Wa # GEQGvzmr9y/JSrX/HPvzOGpuDNsQPxFP2NdILhNpqmjX0ARdWDEGKVEVI9+yW14E # DHmPIY/vHo+g/vkZbByqRY24Ey5kx5ops4WlGX1EYQHbnYREaP5zZlP3hPmo8N/A # vCYxggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAIT # MwAAAg9XmkcUQOZG5gABAAACDzANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcN # AQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCAYL6qBZ4NB7EkAchw4 # rtgtJOQKLkvfwfbLmhuVZf1hvTCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0E # IN1Hd5UmKnm7FW7xP3niGsfHJt4xR8Xu+MxgXXc0iqn4MIGYMIGApH4wfDELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9z # b2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIPV5pHFEDmRuYAAQAAAg8wIgQg # UnAoiin1egEtN850u6EzefjKzOZN8Cwv3bqvpO4tbf8wDQYJKoZIhvcNAQELBQAE # ggIAZCfpIl8UU/x9lNpigJsPBDRgvT5wLfvC6eYti3Yxyh73//Y/w3LtYZ+TxJ9c # hY9Vl5wSX1c/ynZy5lESn5bhlsEl7SpLRj89tzpcyVV6UbBGieoHynnzeaEEHqmh # Z7sqQux2uB8n85VyydqQsH/SvFgLdKL2Zwwvt269vb4L8G65tx2oHCUTtZcDQxTR # vJMw9NHJ5B10vbKiF4ZJfx04htDDF+OaSPoQLiSyM4PfFBCfpNdqZP8XCf87fz2Y # LFezt7DWCTcVevj5mQP2Iq0EbaatZI+jbwhgWH4ldvyD51iZvN6OoANxXEiibUWo # 0Lm59+t5bSeIZKSpK86WC/AniMvQuvIM4CqyGpMEGXeOztY/N3KMuDD325OPspLt # qS8UsiTbArp8AuGMwsIxiS8fNpvxpWgW1+Gfgr60JH+wd7m6E8qTCayItODXf/10 # 1gHk6MJTI6h5stHMyBpeSXTzLtSvfUF/ngzrbAJbRGbcQ/e23i+7d9YANYl6slST # mEXOf4dQa3l5C3+0TmdtqFX8CXWxTFTdLXhf0jzyt4veqTrMq1NQfGcYs3k8s4ml # AgfRWVYssGLA0NxgnhpwKNzKURP/UD3Y68W3Xfyru79zCGk+MH/h1FhpGopN250j # LW8W+oe77HEQpr2luvjrvfVT8uucMSpzxk46YO6kfF7qq/c= # SIG # End signature block |