Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new bluetooth module #147

Open
wants to merge 21 commits into
base: main
Choose a base branch
from

Conversation

Gijsreyn
Copy link
Contributor

@Gijsreyn Gijsreyn commented Jan 19, 2025


This PR addresses starts to address issue #94. The following DSC resources are introduced:

  • USB
  • PenWindowsInk
  • Mouse
  • AutoPlay
  • PrinterAndScanner
  • MobileDevice
Microsoft Reviewers: Open in CodeFlow

@Gijsreyn
Copy link
Contributor Author

Hi @denelon. I started working on this module with quite some hiccups. Despite the hiccups, working with the low-level APIs was an interesting learning curve, and I guess the engineers in your team will like it as well. I aimed to address the logoff/login for users when applying a DSC resource. There might only be 1 or 2 at the moment because it didn't have a clear function to call (it's in a TODO).

Unfortunately, I couldn't finish the Touchpad class. I already constructed the function with the C/C++ code, but somehow, I cannot get it to work. Hopefully, someone on the team can help me with it.

This comment has been minimized.

Copy link
Collaborator

@stephengillie stephengillie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Gijsreyn,

Apologies for experimenting with your module instead of one of my own. In reviewing your very well-formatted code, I kept seeing the code patterns stand out and wanted to express them in a more compact way. Please let me know what you think.

# TODO: There is no refresh win32_api, so users have to logout and login to see the changes.
}
}
#endregion Functions
Copy link
Collaborator

@stephengillie stephengillie Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#endregion Functions
#endregion Functions
#Region CommonFunctions
function Set-RegistryKey {
param(
$NewValue,
$RegistryPath,
$RegistryKey,
$KeyType = "DWORD"
)
if ($null -ne $NewValue) {
if (-not (DoesRegistryKeyPropertyExist -Path $RegistryPath -Name $RegistryKey)) {
New-ItemProperty -Path $RegistryPath -Name $RegistryKey -Value $NewValue -PropertyType $KeyType | Out-Null
}
Set-ItemProperty -Path $RegistryPath -Name $RegistryKey -Value $NewValue
}
}
function Get-RegistryKey {
param(
$RegistryPath,
$RegistryKey,
$KeyParameter,
$ReturnValue = 1
)
if (-not (DoesRegistryKeyPropertyExist -Path $RegistryPath -Name $RegistryKey)) {
return $true
} else {
$KeyValue = (Get-ItemProperty -Path $RegistryPath -Name $RegistryKey).$KeyName
return ($KeyValue -eq $ReturnValue)
}
}
#endregion CommonFunctions

Comment on lines +504 to +527
[void] Set() {
if (-not ($this.Test())) {
if ($null -ne $this.ConnectionNotifications) {
if (-not (DoesRegistryKeyPropertyExist -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty))) {
New-ItemProperty -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty) -Value ([int]$this.ConnectionNotifications) -PropertyType DWord | Out-Null
}
Set-ItemProperty -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty) -Value ([int]$this.ConnectionNotifications)
}

if ($null -ne $this.SlowChargingNotification) {
if (-not (DoesRegistryKeyPropertyExist -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty))) {
New-ItemProperty -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty) -Value ([int]$this.SlowChargingNotification) -PropertyType DWord | Out-Null
}
Set-ItemProperty -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty) -Value ([int]$this.SlowChargingNotification)
}

if ($null -ne $this.BatterySaver) {
if (-not (DoesRegistryKeyPropertyExist -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty))) {
New-ItemProperty -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty) -Value ([int]$this.BatterySaver) -PropertyType DWord | Out-Null
}
Set-ItemProperty -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty) -Value ([int]$this.BatterySaver)
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[void] Set() {
if (-not ($this.Test())) {
if ($null -ne $this.ConnectionNotifications) {
if (-not (DoesRegistryKeyPropertyExist -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty))) {
New-ItemProperty -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty) -Value ([int]$this.ConnectionNotifications) -PropertyType DWord | Out-Null
}
Set-ItemProperty -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty) -Value ([int]$this.ConnectionNotifications)
}
if ($null -ne $this.SlowChargingNotification) {
if (-not (DoesRegistryKeyPropertyExist -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty))) {
New-ItemProperty -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty) -Value ([int]$this.SlowChargingNotification) -PropertyType DWord | Out-Null
}
Set-ItemProperty -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty) -Value ([int]$this.SlowChargingNotification)
}
if ($null -ne $this.BatterySaver) {
if (-not (DoesRegistryKeyPropertyExist -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty))) {
New-ItemProperty -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty) -Value ([int]$this.BatterySaver) -PropertyType DWord | Out-Null
}
Set-ItemProperty -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty) -Value ([int]$this.BatterySaver)
}
}
}
[void] Set() {
if (-not ($this.Test())) {
Set-RegistryKey -NewValue [int]$this.ConnectionNotifications -RegistryPath $global:USBShellPath -RegistryKey ([USB]::ConnectionNotificationsProperty)
Set-RegistryKey -NewValue [int]$this.SlowChargingNotification -RegistryPath $global:USBShellPath -RegistryKey ([USB]::SlowChargingNotificationProperty)
Set-RegistryKey -NewValue [int]$this.BatterySaver -RegistryPath $global:USBMachinePath -RegistryKey ([USB]::BatterySaverProperty)
}
}```

Comment on lines +529 to +557
#region USB helper functions
static [bool] GetConnectionNotificationStatus() {
if (-not(DoesRegistryKeyPropertyExist -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty))) {
return $true
} else {
$ConnectionNotificationsValue = (Get-ItemProperty -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty)).NotifyOnUsbErrors
return ($ConnectionNotificationsValue -eq 1)
}
}

static [bool] GetSlowChargingNotificationStatus() {
if (-not(DoesRegistryKeyPropertyExist -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty))) {
return $true
} else {
$SlowChargingNotificationValue = (Get-ItemProperty -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty)).NotifyOnWeakCharger
return ($SlowChargingNotificationValue -eq 1)
}
}

static [bool] GetBatterySaverStatus() {
if (-not(DoesRegistryKeyPropertyExist -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty))) {
return $false # It is not enabled by default if the registry key does not exist.
} else {
$BatterySaverValue = (Get-ItemProperty -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty)).AttemptRecoveryFromUsbPowerDrain
return ($BatterySaverValue -eq 1)
}
}
#endregion USB helper functions
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#region USB helper functions
static [bool] GetConnectionNotificationStatus() {
if (-not(DoesRegistryKeyPropertyExist -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty))) {
return $true
} else {
$ConnectionNotificationsValue = (Get-ItemProperty -Path $global:USBShellPath -Name ([USB]::ConnectionNotificationsProperty)).NotifyOnUsbErrors
return ($ConnectionNotificationsValue -eq 1)
}
}
static [bool] GetSlowChargingNotificationStatus() {
if (-not(DoesRegistryKeyPropertyExist -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty))) {
return $true
} else {
$SlowChargingNotificationValue = (Get-ItemProperty -Path $global:USBShellPath -Name ([USB]::SlowChargingNotificationProperty)).NotifyOnWeakCharger
return ($SlowChargingNotificationValue -eq 1)
}
}
static [bool] GetBatterySaverStatus() {
if (-not(DoesRegistryKeyPropertyExist -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty))) {
return $false # It is not enabled by default if the registry key does not exist.
} else {
$BatterySaverValue = (Get-ItemProperty -Path $global:USBMachinePath -Name ([USB]::BatterySaverProperty)).AttemptRecoveryFromUsbPowerDrain
return ($BatterySaverValue -eq 1)
}
}
#endregion USB helper functions
}
}

Comment on lines +479 to +481
$currentState.ConnectionNotifications = [USB]::GetConnectionNotificationStatus()
$currentState.SlowChargingNotification = [USB]::GetSlowChargingNotificationStatus()
$currentState.BatterySaver = [USB]::GetBatterySaverStatus()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$currentState.ConnectionNotifications = [USB]::GetConnectionNotificationStatus()
$currentState.SlowChargingNotification = [USB]::GetSlowChargingNotificationStatus()
$currentState.BatterySaver = [USB]::GetBatterySaverStatus()
$currentState.ConnectionNotifications = Get-RegistryKey -RegistryPath $global:USBShellPath -RegistryKey ([USB]::ConnectionNotificationsProperty) -KeyParameter "NotifyOnUsbErrors"
$currentState.SlowChargingNotification = Get-RegistryKey -RegistryPath $global:USBShellPath -RegistryKey ([USB]::SlowChargingNotificationProperty) -KeyParameter "NotifyOnWeakCharger"
$currentState.BatterySaver = Get-RegistryKey -RegistryPath $global:USBMachinePath -RegistryKey ([USB]::BatterySaverProperty) -KeyParameter "AttemptRecoveryFromUsbPowerDrain"

Comment on lines +242 to +248
# TODO: Does not work, error code 87. See: https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
# TODO: Might also require checking if touchpad is present on machine, and if result can be captured as C++ acts different
$result = [Touchpad32Functions]::SystemParametersInfo(0x00AE, 0, [ref]$touchpad, 0) # SPI_GETTOUCHPADPARAMETERS
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
if ($err -ne 0) {
throw [System.ComponentModel.Win32Exception]::new($err)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...error code 87.

From the website:

ERROR_INVALID_PARAMETER: The parameter is incorrect.

On my laptop, which has a touchpad, I get code 203: The system could not find the environment option that was entered. I'm having difficulty finding documentation of the Touchpad32Functions assembly, which complicates troubleshooting.

I did locate another set of Touchpad settings, under HKCU:\Software\Microsoft\Windows\CurrentVersion\PrecisionTouchPad:

First, the enabled/disabled switch is in a subfolder:

PS C:\ManVal> Get-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\PrecisionTouchPad\Status\

Enabled      : 1

And the rest of the settings are in the main folder:

PS C:\ManVal> Get-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\PrecisionTouchPad

AAPThreshold            : 2
CursorSpeed             : 10
ScrollDirection         : 0
EnableEdgy              : 4294967295
LeaveOnWithMouse        : 0
PanEnabled              : 4294967295
RightClickZoneEnabled   : 0
TapAndDrag              : 0
TapsEnabled             : 4294967295
TwoFingerTapEnabled     : 0
ZoomEnabled             : 4294967295
HonorMouseAccelSetting  : 0
FeedbackIntensity       : 50
FeedbackEnabled         : 4294967295
ThreeFingerSlideEnabled : 0
ThreeFingerTapEnabled   : 0
FourFingerSlideEnabled  : 0
FourFingerTapEnabled    : 0
PSPath                  : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\PrecisionTouchPad

@Gijsreyn
Copy link
Contributor Author

Gijsreyn commented Feb 8, 2025

Hi @Gijsreyn,

Apologies for experimenting with your module instead of one of my own. In reviewing your very well-formatted code, I kept seeing the code patterns stand out and wanted to express them in a more compact way. Please let me know what you think.

Hey @stephengillie, thanks for hopping in. Yes, that's what I noticed as well, and I didn't really like it. There's so much overlap in each module, and Demitrius mentioned one sentence back about having the modules move toward the DSC community. That sentence remained with me.

Having said that, I had some time spent investigating the class-based development within the DSC community. It was a bit tough to get started, but I finally managed to get a mock setup, and I feel it's a way better approach with modularity included. I demoed this during the last community call as a sneak peek, and I intend to move most of the content that I have PRed here to that module.

image

Basically, the 010.SettingsBase.ps1 contains a class that can be inherited across (nearly) all settings unless they don't contain 0 or 1 values as DWORDS (still thinking about it to expand). Others can be more self-contained.

The repository is still private, but if you and @denelon want access to it, just give me a heads-up. I'm just letting you know that I'll not spend much time around this repository, and I guess most PRs can be abandoned.

Lastly, on the touchpad settings. Thanks for the deep dive and yes, I think I noticed these settings also. The thing is, you can change them in the registry, but the user would still have to log out and log back in. That's why I wanted to use the API to get the values and set it using that. Anyway, if you've someone internal who might be able to help out, that would be pretty cool :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants