Skip to content

Commit

Permalink
New Microsoft.Windows.Setting.Privacy
Browse files Browse the repository at this point in the history
  • Loading branch information
Gijsreyn committed Nov 14, 2024
1 parent d9e3196 commit 9cd2f95
Show file tree
Hide file tree
Showing 4 changed files with 462 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#
# Module manifest for module 'Microsoft.Windows.Setting.Privacy'
#
# Generated by: Microsoft Corporation
#
# Generated on: 11/14/2024
#

@{

# Script module or binary module file associated with this manifest.
RootModule = 'Microsoft.Windows.Setting.Privacy.psm1'

# Version number of this module.
ModuleVersion = '0.1.0'

# Supported PSEditions
# CompatiblePSEditions = @()

# ID used to uniquely identify this module
GUID = '151d9b2f-4c29-4920-b75f-a220fdb24888'

# Author of this module
Author = 'Microsoft Corporation'

# Company or vendor of this module
CompanyName = 'Microsoft Corporation'

# Copyright statement for this module
Copyright = '(c) Microsoft Corporation. All rights reserved.'

# Description of the functionality provided by this module
Description = 'DSC Resource for Windows Settings Privacy'

# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '7.2'

# Name of the PowerShell host required by this module
# PowerShellHostName = ''

# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''

# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''

# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# ClrVersion = ''

# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''

# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()

# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()

# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()

# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()

# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()

# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
# FunctionsToExport = @()

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
# CmdletsToExport = @()

# Variables to export from this module
# VariablesToExport = @()

# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
# AliasesToExport = @()

# DSC resources to export from this module
DscResourcesToExport = @('Privacy')

# List of all modules packaged with this module
# ModuleList = @()

# List of all files packaged with this module
# FileList = @()

# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{

PSData = @{

# Tags applied to this module. These help with module discovery in online galleries.
# Tags = @()

# A URL to the license for this module.
LicenseUri = 'https://github.com/microsoft/winget-dsc/blob/main/LICENSE'

# A URL to the main website for this project.
ProjectUri = 'https://github.com/microsoft/winget-dsc'

# A URL to an icon representing this module.
# IconUri = ''

# ReleaseNotes of this module
# ReleaseNotes = ''

# Prerelease string of this module
Prerelease = 'alpha'

# Flag to indicate whether the module requires explicit user acceptance for install/update/save
# RequireLicenseAcceptance = $false

# External dependent modules of this module
# ExternalModuleDependencies = @()

} # End of PSData hashtable

} # End of PrivateData hashtable

# HelpInfo URI of this module
# HelpInfoURI = ''

# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
if ([string]::IsNullOrEmpty($env:TestRegistryPath)) {
# $global:webcamConsentStorePath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\webcam'

Check warning on line 2 in resources/Microsoft.Windows.Setting.Privacy/Microsoft.Windows.Setting.Privacy.psm1

View workflow job for this annotation

GitHub Actions / Check Spelling

`webcam` is not a recognized word. (unrecognized-spelling)

Check warning on line 2 in resources/Microsoft.Windows.Setting.Privacy/Microsoft.Windows.Setting.Privacy.psm1

View workflow job for this annotation

GitHub Actions / Check Spelling

`webcam` is not a recognized word. (unrecognized-spelling)
$global:advertisingInfoPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo'
$global:userProfilePath = 'HKCU:\Control Panel\International\User Profile'
$global:advancedProfilePath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'
$global:contentDeliveryManagerPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager'
$global:accountNotificationsPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\SystemSettings\AccountNotifications'
} else {
$global:advertisingInfoPath = $env:TestRegistryPath
}

#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

if ($itemProperty) {
return $itemProperty.$Name
}
}

function GetPropertyMapping {
$inputObject = [System.Collections.Generic.List[PSCustomObject]]::new()

$inputObject.Add([PSCustomObject]@{
Name = 'EnablePersonalizedAds'
Key = 'Enabled'
Expression = 1
Path = $global:advertisingInfoPath
})

$inputObject.Add([PSCustomObject]@{
Name = 'EnableLocalContentByLanguageList'
Key = 'HttpAcceptLanguageOptOut'
Expression = 0
Path = $global:userProfilePath
})

$inputObject.Add([PSCustomObject]@{
Name = 'EnableAppLaunchTracking'
Key = 'Start_TrackProgs'
Expression = 1
Path = $global:advancedProfilePath
})

$inputObject.Add([PSCustomObject]@{
Name = 'ShowContentSuggestion'
Key = @('SubscribedContent-338393Enabled', 'SubscribedContent-353694Enabled', 'SubscribedContent-353696Enabled')
Expression = 1
Path = $global:contentDeliveryManagerPath
})

$inputObject.Add([PSCustomObject]@{
Name = 'EnableAccountNotifications'
Key = 'EnableAccountNotifications'
Expression = 1
Path = $global:accountNotificationsPath
})

return $inputObject
}

function GetPrivacyState {
[CmdletBinding()]
[OutputType([Privacy])]
param (
[Parameter()]
[AllowNull()]
[hashtable] $SettableProperties
)

$currentState = [Privacy]::New()
$mapping = GetPropertyMapping

foreach ($p in $SettableProperties.GetEnumerator()) {
$property = $mapping | Where-Object { $_.Name -eq $p.Key }
$expression = $property.Expression
$path = $property.Path

if ($null -ne $property) {
# wondering why we check for array? This is because the HttpAcceptLanguageOptOut key is buggy
$keyValue = if ($property.Key -is [array]) {
$property.Key | ForEach-Object { DoesRegistryKeyPropertyExist -Path $path -Name $_ }
} else {
DoesRegistryKeyPropertyExist -Path $path -Name $property.Key
}

if (-not ([string]::IsNullOrEmpty($keyValue))) {
[bool]$setter = ($keyValue -eq $expression)

$currentState.$($p.Key) = $setter
} else {
$currentState.$($p.Key) = $true
}
}
}

return $currentState
}

function TestPrivacyState {
[CmdletBinding()]
[OutputType([bool])]
param (
[Parameter(Mandatory = $true)]
[hashtable] $CurrentState,

[Parameter(Mandatory = $true)]
[Privacy] $TestState
)

$res = $true
$CurrentState.GetEnumerator() | ForEach-Object {
$testValue = $TestState.psobject.properties[$_.Key].Value

Check warning on line 122 in resources/Microsoft.Windows.Setting.Privacy/Microsoft.Windows.Setting.Privacy.psm1

View workflow job for this annotation

GitHub Actions / Check Spelling

`psobject` is not a recognized word. (unrecognized-spelling)
if ($null -ne $testValue) {
if ($testValue -ne $_.Value) {
$res = $false
}
}
}

return $res
}

function SetPrivacyState {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Privacy] $PrivacyState
)

$mapping = GetPropertyMapping

$props = $PrivacyState.psobject.properties | Where-Object { $null -ne $_.Value }

Check warning on line 142 in resources/Microsoft.Windows.Setting.Privacy/Microsoft.Windows.Setting.Privacy.psm1

View workflow job for this annotation

GitHub Actions / Check Spelling

`psobject` is not a recognized word. (unrecognized-spelling)

foreach ($p in $props) {
$map = $mapping | Where-Object { $_.Name -eq $p.Name }
if (-not (Test-Path $map.Path)) {
New-Item -Path $map.Path -Force | Out-Null
}

foreach ($key in $map.Key) {
$value = ($p.Value -as [int])
if ($map.Key -eq 'HttpAcceptLanguageOptOut') {
$value = ($value -eq 0) ? 1 : 0
}

if (-not (DoesRegistryKeyPropertyExist -Path $map.Path -Name $key)) {
New-ItemProperty -Path $map.Path -Name $key -Value $value -PropertyType DWord
}

Set-ItemProperty -Path $map.Path -Name $key -Value $value -Force
}
}
}
#endregion Functions

#region Classes

[DSCResource()]
class Privacy {
# Key required. Do not set.
[DscProperty(Key)]
[string] $SID

[DscProperty()]
[nullable[bool]] $EnablePersonalizedAds

[DscProperty()]
[nullable[bool]] $EnableLocalContentByLanguageList

[DscProperty()]
[nullable[bool]] $EnableAppLaunchTracking

[DscProperty()]
[nullable[bool]] $ShowContentSuggestion

[DscProperty()]
[nullable[bool]] $EnableAccountNotifications

[Privacy] Get() {
$currentState = GetPrivacyState -SettableProperties $this.ToHashTable()
return $currentState
}

[bool] Test() {
$currentState = $this.Get()
$result = TestPrivacyState -CurrentState $currentState.ToHashTable() -TestState $this
return $result
}

[void] Set() {
if (-not $this.Test()) {
SetPrivacyState -PrivacyState $this
}
}

#region Privacy helper functions
static [bool] GetPersonalizedAdsStatus() {
$keyValue = TryGetRegistryValue -Key $global:advertisingInfoPath -Property 'Enabled'
return ($keyvalue -eq 1)

Check warning on line 209 in resources/Microsoft.Windows.Setting.Privacy/Microsoft.Windows.Setting.Privacy.psm1

View workflow job for this annotation

GitHub Actions / Check Spelling

`keyvalue` is not a recognized word. (unrecognized-spelling)
}

[hashtable] ToHashTable() {
$parameters = @{}
foreach ($property in $this.PSObject.Properties) {
if (-not ([string]::IsNullOrEmpty($property.Value))) {
$parameters[$property.Name] = $property.Value
}
}

return $parameters
}

#endRegion Privacy helper functions
}
#endRegion classes
Loading

0 comments on commit 9cd2f95

Please sign in to comment.