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 # MIIoUgYJKoZIhvcNAQcCoIIoQzCCKD8CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBrdZoT+FMQnFFK # yP6hzsNR2nJWHjD/vW8hO7sobwiDL6CCDYUwggYDMIID66ADAgECAhMzAAAEA73V # lV0POxitAAAAAAQDMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjQwOTEyMjAxMTEzWhcNMjUwOTExMjAxMTEzWjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQCfdGddwIOnbRYUyg03O3iz19XXZPmuhEmW/5uyEN+8mgxl+HJGeLGBR8YButGV # LVK38RxcVcPYyFGQXcKcxgih4w4y4zJi3GvawLYHlsNExQwz+v0jgY/aejBS2EJY # oUhLVE+UzRihV8ooxoftsmKLb2xb7BoFS6UAo3Zz4afnOdqI7FGoi7g4vx/0MIdi # kwTn5N56TdIv3mwfkZCFmrsKpN0zR8HD8WYsvH3xKkG7u/xdqmhPPqMmnI2jOFw/ # /n2aL8W7i1Pasja8PnRXH/QaVH0M1nanL+LI9TsMb/enWfXOW65Gne5cqMN9Uofv # ENtdwwEmJ3bZrcI9u4LZAkujAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU6m4qAkpz4641iK2irF8eWsSBcBkw # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwMjkyNjAfBgNVHSMEGDAW # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB # AFFo/6E4LX51IqFuoKvUsi80QytGI5ASQ9zsPpBa0z78hutiJd6w154JkcIx/f7r # EBK4NhD4DIFNfRiVdI7EacEs7OAS6QHF7Nt+eFRNOTtgHb9PExRy4EI/jnMwzQJV # NokTxu2WgHr/fBsWs6G9AcIgvHjWNN3qRSrhsgEdqHc0bRDUf8UILAdEZOMBvKLC # rmf+kJPEvPldgK7hFO/L9kmcVe67BnKejDKO73Sa56AJOhM7CkeATrJFxO9GLXos # oKvrwBvynxAg18W+pagTAkJefzneuWSmniTurPCUE2JnvW7DalvONDOtG01sIVAB # +ahO2wcUPa2Zm9AiDVBWTMz9XUoKMcvngi2oqbsDLhbK+pYrRUgRpNt0y1sxZsXO # raGRF8lM2cWvtEkV5UL+TQM1ppv5unDHkW8JS+QnfPbB8dZVRyRmMQ4aY/tx5x5+ # sX6semJ//FbiclSMxSI+zINu1jYerdUwuCi+P6p7SmQmClhDM+6Q+btE2FtpsU0W # +r6RdYFf/P+nK6j2otl9Nvr3tWLu+WXmz8MGM+18ynJ+lYbSmFWcAj7SYziAfT0s # IwlQRFkyC71tsIZUhBHtxPliGUu362lIO0Lpe0DOrg8lspnEWOkHnCT5JEnWCbzu # iVt8RX1IV07uIveNZuOBWLVCzWJjEGa+HhaEtavjy6i7MIIHejCCBWKgAwIBAgIK # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGiMwghofAgEBMIGVMH4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAQDvdWVXQ87GK0AAAAA # BAMwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIDRK # i8Va9CnqSjvpVL/0guEkwVqZXwfe3hJb97gr7+UoMEIGCisGAQQBgjcCAQwxNDAy # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEAFybm5KEF7m+qAl0UusT9iksVv2DmiZw7Coy8 # swSP8hB9zXXJrVjYUi9lc2xBE+ovWOp1paYw0f74xVieIIAi/ut5B7Oe/bxeYNJW # a6gNRcP+Y33+vVtELeuxWYr/qeqiGqye8LL+jqI0SW9XNUVhDSzxr0N7DAZ5/H/5 # h9YsQQAZx6ftXv97BEgCyZKNQsx05nTfIIQvdeglUCwB1laPgd+gnNqCvqV78IOD # 92bLfNZh519gTpGtBxLCG1T0P0+iY1+EUa/3xMolzoe1GkbLmGG2Wzc8+Fp4TxUt # b+NMbdCHLUpHum0CK9RYSsdE1u8edWqoSklMzqCIGY3G5dgNAKGCF60wghepBgor # BgEEAYI3AwMBMYIXmTCCF5UGCSqGSIb3DQEHAqCCF4YwgheCAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFFMIIBQQIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCB565RmRY8hGmQNpmlvlQ/xc+nyyFfpF1qZ # 1u+G5GYR7gIGZuszQSxGGBMyMDI0MTExMjE3MjMwMi40OTRaMASAAgH0oIHZpIHW # MIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsT # Hm5TaGllbGQgVFNTIEVTTjoyRDFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9z # b2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEfswggcoMIIFEKADAgECAhMzAAAB/XP5 # aFrNDGHtAAEAAAH9MA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w # IFBDQSAyMDEwMB4XDTI0MDcyNTE4MzExNloXDTI1MTAyMjE4MzExNlowgdMxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jv # c29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOjJEMUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt # ZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA # oWWs+D+Ou4JjYnRHRedu0MTFYzNJEVPnILzc02R3qbnujvhZgkhp+p/lymYLzkQy # G2zpxYceTjIF7HiQWbt6FW3ARkBrthJUz05ZnKpcF31lpUEb8gUXiD2xIpo8YM+S # D0S+hTP1TCA/we38yZ3BEtmZtcVnaLRp/Avsqg+5KI0Kw6TDJpKwTLl0VW0/23sK # ikeWDSnHQeTprO0zIm/btagSYm3V/8zXlfxy7s/EVFdSglHGsUq8EZupUO8XbHzz # 7tURyiD3kOxNnw5ox1eZX/c/XmW4H6b4yNmZF0wTZuw37yA1PJKOySSrXrWEh+H6 # ++Wb6+1ltMCPoMJHUtPP3Cn0CNcNvrPyJtDacqjnITrLzrsHdOLqjsH229Zkvndk # 0IqxBDZgMoY+Ef7ffFRP2pPkrF1F9IcBkYz8hL+QjX+u4y4Uqq4UtT7VRnsqvR/x # /+QLE0pcSEh/XE1w1fcp6Jmq8RnHEXikycMLN/a/KYxpSP3FfFbLZuf+qIryFL0g # EDytapGn1ONjVkiKpVP2uqVIYj4ViCjy5pLUceMeqiKgYqhpmUHCE2WssLLhdQBH # dpl28+k+ZY6m4dPFnEoGcJHuMcIZnw4cOwixojROr+Nq71cJj7Q4L0XwPvuTHQt0 # oH7RKMQgmsy7CVD7v55dOhdHXdYsyO69dAdK+nWlyYcCAwEAAaOCAUkwggFFMB0G # A1UdDgQWBBTpDMXA4ZW8+yL2+3vA6RmU7oEKpDAfBgNVHSMEGDAWgBSfpxVdAF5i # XYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jv # c29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENB # JTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRp # bWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1Ud # JQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsF # AAOCAgEAY9hYX+T5AmCrYGaH96TdR5T52/PNOG7ySYeopv4flnDWQLhBlravAg+p # jlNv5XSXZrKGv8e4s5dJ5WdhfC9ywFQq4TmXnUevPXtlubZk+02BXK6/23hM0TSK # s2KlhYiqzbRe8QbMfKXEDtvMoHSZT7r+wI2IgjYQwka+3P9VXgERwu46/czz8IR/ # Zq+vO5523Jld6ssVuzs9uwIrJhfcYBj50mXWRBcMhzajLjWDgcih0DuykPcBpoTL # lOL8LpXooqnr+QLYE4BpUep3JySMYfPz2hfOL3g02WEfsOxp8ANbcdiqM31dm3vS # heEkmjHA2zuM+Tgn4j5n+Any7IODYQkIrNVhLdML09eu1dIPhp24lFtnWTYNaFTO # fMqFa3Ab8KDKicmp0AthRNZVg0BPAL58+B0UcoBGKzS9jscwOTu1JmNlisOKkVUV # kSJ5Fo/ctfDSPdCTVaIXXF7l40k1cM/X2O0JdAS97T78lYjtw/PybuzX5shxBh/R # qTPvCyAhIxBVKfN/hfs4CIoFaqWJ0r/8SB1CGsyyIcPfEgMo8ceq1w5Zo0JfnyFi # 6Guo+z3LPFl/exQaRubErsAUTfyBY5/5liyvjAgyDYnEB8vHO7c7Fg2tGd5hGgYs # +AOoWx24+XcyxpUkAajDhky9Dl+8JZTjts6BcT9sYTmOodk/SgIwggdxMIIFWaAD # AgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD # VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe # MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv # ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5MzAxODIy # MjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw # MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5 # vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64 # NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhu # je3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl # 3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHINSi947SHJMPg # yY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJiss254o2I # 5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2 # ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY7afomXw/ # TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtcodgLiMxhy # 16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y # 1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6H # XtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMB # AAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQW # BBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30B # ATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYB # BAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMB # Af8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBL # oEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv # TWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggr # BgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNS # b29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ1Vffwq # reEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27 # DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AFvonoaeC6Ce5732pv # vinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9Ak # vUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWK # NsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2 # kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+ # c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep # 8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+k77L+Dvk # txW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1Zyvg # DbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/ # 2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDVjCCAj4CAQEwggEBoYHZpIHW # MIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsT # Hm5TaGllbGQgVFNTIEVTTjoyRDFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9z # b2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAoj0WtVVQUNSK # oqtrjinRAsBUdoOggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz # aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv # cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx # MDANBgkqhkiG9w0BAQsFAAIFAOrdh98wIhgPMjAyNDExMTIwNzUzMDNaGA8yMDI0 # MTExMzA3NTMwM1owdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA6t2H3wIBADAHAgEA # AgIiSDAHAgEAAgISYjAKAgUA6t7ZXwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgor # BgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUA # A4IBAQAIkXts31e/A7X4VkNA7bus2rUsNpmtuo1QAnazkk9TZCgrzp/ZEU8RctPU # PX5tFfjojKvDi1pfdF92zwcwKOWZnFUvubIDiuGs+9WY/v7/SBUphzD7jCTUatGn # cWXrwJhrZrqK7atUKwAtb/nHgCvEeG155XYheCVTi+CWHlWC/CO5/QKoefSEf96U # RZ1M4L4ZCr37LzariIJHCghRXmVLfQ4YTUqTmP9L6Mfy57D/2e5tcFHEAlkOpUQX # A/ECcgbv8IesZWaiNCGkg7IuucchEEcxu79vEO34dfmi/engCLS0Yc+99RY4+M9S # vuNkwUC3l2SHbbrsWVXwR+5c+GL1MYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTACEzMAAAH9c/loWs0MYe0AAQAAAf0wDQYJYIZIAWUD # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B # CQQxIgQgRFllWqFdpzYc9mGTnynmS/fMeqMILvUA77VXAmXZpQcwgfoGCyqGSIb3 # DQEJEAIvMYHqMIHnMIHkMIG9BCCAKEgNyUowvIfx/eDfYSupHkeF1p6GFwjKBs8l # RB4NRzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB # /XP5aFrNDGHtAAEAAAH9MCIEIN63ory/oSqdzAAkC84gWzleUStbJYjnVI5ruVjd # Uee7MA0GCSqGSIb3DQEBCwUABIICAGwutZXhQXFV9U9N6W6Eewy8VNlG3gs6bSva # vKg9N87J4WmJq0tiE3sxQKpfIDWBS0FJ2RrZO+2psG9LTBmDBVhwhvnuz8AL9NbM # +KPwWHSCcIhIwWu1hyf8X4X9E8Lp5taUzmJlOTkM5eUxCPQWsE3IPb0YvT9peTfJ # u9zJbnQ7iJYOrlzHhZV+RjXAvc4B9S07K34Llouu4gQ+bNB5TXKkUVIkomyqvNIn # aoFc5ivxUK0fhm/zm5MEJLsuNjK6YiNsxjIg5od/KkpwR9itg4mxJdLRCxSBXVgS # ijCldqLSpSUANneJTPPzdBRwOpAndFgXr7BOs+DaeUsDuDLkkH2AQnCQjf5OHcEQ # 9+Go7GGkLtzlLuR+TZvwciwcP6OalcfzoxQZCKILt4yoIH3oj6t4oHNFNFXpWPMq # qZudC7o+PIVsFIDa+UpMyVwkq4WRwczyPe1qIQxo1EEaP+5rwrrwKyNDjbMR6fPh # EG+PWCCBG4ai9I/EWRZNwthu1lEYlDJW66CqkSLkhQun6Loesgj3Rq3iJiT3OC4i # 5IK3VQ8Fx8waxZD1IP+YPLP8KscdKW9jdbWgZbNovYuQUHRAkHQT1B5hioXxksc9 # CAITs4NgU9Nfo/wQsmTScnBl3PD0Jtz8MnpFWQHMdjXf7hbX6a5jURoXwYEVkRmd # csbP06hL # SIG # End signature block |