Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions config/dns.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,59 @@
"Primary6": "2a10:50c0::bad1:ff",
"Secondary6": "2a10:50c0::bad2:ff",
"DohTemplate": "https://family.adguard-dns.com/dns-query"
},
"Mullvad":{
"Primary": "194.242.2.2",
"Secondary": "194.242.2.3",
"Primary6": "2a07:e340::2",
"Secondary6": "2a07:e340::3",
"DohOnly": true,
"DohTemplate": "https://dns.mullvad.net/dns-query",
"SecondaryDohTemplate": "https://adblock.dns.mullvad.net/dns-query"
},
"Mullvad_Ads_Trackers":{
"Primary": "194.242.2.3",
"Secondary": "194.242.2.2",
"Primary6": "2a07:e340::3",
"Secondary6": "2a07:e340::2",
"DohOnly": true,
"DohTemplate": "https://adblock.dns.mullvad.net/dns-query",
"SecondaryDohTemplate": "https://dns.mullvad.net/dns-query"
},
"Mullvad_Ads_Trackers_Malware":{
"Primary": "194.242.2.4",
"Secondary": "194.242.2.3",
"Primary6": "2a07:e340::4",
"Secondary6": "2a07:e340::3",
"DohOnly": true,
"DohTemplate": "https://base.dns.mullvad.net/dns-query",
"SecondaryDohTemplate": "https://adblock.dns.mullvad.net/dns-query"
},
"Mullvad_Ads_Trackers_Malware_Social":{
"Primary": "194.242.2.5",
"Secondary": "194.242.2.4",
"Primary6": "2a07:e340::5",
"Secondary6": "2a07:e340::4",
"DohOnly": true,
"DohTemplate": "https://extended.dns.mullvad.net/dns-query",
"SecondaryDohTemplate": "https://base.dns.mullvad.net/dns-query"
},
"Mullvad_Ads_Trackers_Malware_Adult_Gambling":{
"Primary": "194.242.2.6",
"Secondary": "194.242.2.5",
"Primary6": "2a07:e340::6",
"Secondary6": "2a07:e340::5",
"DohOnly": true,
"DohTemplate": "https://family.dns.mullvad.net/dns-query",
"SecondaryDohTemplate": "https://extended.dns.mullvad.net/dns-query"
},
"Mullvad_Ads_Trackers_Malware_Adult_Gambling_Social":{
"Primary": "194.242.2.9",
"Secondary": "194.242.2.6",
"Primary6": "2a07:e340::9",
"Secondary6": "2a07:e340::6",
"DohOnly": true,
"DohTemplate": "https://all.dns.mullvad.net/dns-query",
"SecondaryDohTemplate": "https://family.dns.mullvad.net/dns-query"
}
}
32 changes: 22 additions & 10 deletions config/tweaks.json
Original file line number Diff line number Diff line change
Expand Up @@ -1459,28 +1459,40 @@
],
"link": "https://winutil.christitus.com/code-reference/tweaks/customize-preferences/scrollbars"
},
"WPFToggleMultiplaneOverlay": {
"WPFMultiplaneOverlay": {
"Content": "Multiplane Overlay",
"Description": "Multiplane Overlay compose multiple image layers, which can sometimes cause issues with graphics cards.",
"Description": "Multiplane Overlay composes multiple image layers, which can sometimes cause issues with graphics cards. Changes to this preference are applied immediately.",
"category": "Customize Preferences",
"panel": "2",
"Type": "Toggle",
"Type": "Combobox",
"ComboItems": "Enabled|Disabled (Compatibility)|Fully Disabled",
"ComboDescriptions": {
"Enabled": "Uses Windows' default overlay behavior.",
"Disabled (Compatibility)": "Disables MPO using OverlayTestMode=5, the less aggressive compatibility method.",
"Fully Disabled": "Disables MPO using OverlayTestMode=5 and DisableOverlays=1, the more aggressive method."
},
"registry": [
{
"Path": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\Dwm",
"Name": "OverlayTestMode",
"Value": "0",
"Type": "DWord",
"OriginalValue": "5",
"DefaultState": "true"
"DefaultValue": "0",
"Values": {
"Enabled": "<RemoveEntry>",
"Disabled (Compatibility)": "5",
"Fully Disabled": "5"
}
},
{
"Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers",
"Name": "DisableOverlays",
"Value": "0",
"Type": "DWord",
"OriginalValue": "1",
"DefaultState": "true"
"DefaultValue": "0",
"Values": {
"Enabled": "<RemoveEntry>",
"Disabled (Compatibility)": "<RemoveEntry>",
"Fully Disabled": "1"
}
}
],
"link": "https://winutil.christitus.com/code-reference/tweaks/customize-preferences/multiplaneoverlay"
Expand Down Expand Up @@ -1852,7 +1864,7 @@
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"Type": "Combobox",
"ComboItems": "Default DHCP Google Cloudflare Cloudflare_Malware Cloudflare_Malware_Adult Open_DNS Quad9 AdGuard_Ads_Trackers AdGuard_Ads_Trackers_Malware_Adult",
"ComboItems": "Default DHCP Google Cloudflare Cloudflare_Malware Cloudflare_Malware_Adult Open_DNS Quad9 AdGuard_Ads_Trackers AdGuard_Ads_Trackers_Malware_Adult Mullvad Mullvad_Ads_Trackers Mullvad_Ads_Trackers_Malware Mullvad_Ads_Trackers_Malware_Social Mullvad_Ads_Trackers_Malware_Adult_Gambling Mullvad_Ads_Trackers_Malware_Adult_Gambling_Social",
"link": "https://winutil.christitus.com/code-reference/tweaks/z--advanced-tweaks---caution/changedns"
},
"WPFAddUltPerf": {
Expand Down
2 changes: 2 additions & 0 deletions docs/src/content/docs/code-reference/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,8 @@ Update UI
- `Description`: What it does
- `category`: Essential/Advanced/Customize
- `registry`: Registry changes to make
- `registry[].Values`: Per-state values for a registry-backed combobox
- `registry[].DefaultValue`: Effective value when the registry entry is absent
- `service`: Services to change
- `OriginalValue/State`: For undo functionality

Expand Down
8 changes: 8 additions & 0 deletions docs/src/content/docs/guides/tweaks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ Use the DNS section to switch both IPv4 and IPv6 DNS providers without editing a
* [**Quad9**](https://quad9.net/): Focuses on security by blocking known malicious domains.
* [**AdGuard_Ads_Trackers**](https://adguard-dns.io/en/welcome.html): AdGuard DNS blocks ads, trackers, and other unwanted DNS requests. Visit the website and sign in for a dashboard, statistics, and additional server-side customization.
* [**AdGuard_Ads_Trackers_Malware_Adult**](https://adguard-dns.io/en/welcome.html): AdGuard DNS blocks ads, trackers, malware, and adult content, and enables Safe Search and Safe Mode where possible.
* [**Mullvad**](https://mullvad.net/en/help/dns-over-https-and-dns-over-tls): Mullvad DNS without content blocking.
* [**Mullvad_Ads_Trackers**](https://mullvad.net/en/help/dns-over-https-and-dns-over-tls): Blocks ads and trackers.
* [**Mullvad_Ads_Trackers_Malware**](https://mullvad.net/en/help/dns-over-https-and-dns-over-tls): Blocks ads, trackers, and malware.
* [**Mullvad_Ads_Trackers_Malware_Social**](https://mullvad.net/en/help/dns-over-https-and-dns-over-tls): Blocks ads, trackers, malware, and social media.
* [**Mullvad_Ads_Trackers_Malware_Adult_Gambling**](https://mullvad.net/en/help/dns-over-https-and-dns-over-tls): Blocks ads, trackers, malware, adult content, and gambling.
* [**Mullvad_Ads_Trackers_Malware_Adult_Gambling_Social**](https://mullvad.net/en/help/dns-over-https-and-dns-over-tls): Applies all available Mullvad filters.

Mullvad profiles require DNS over HTTPS support in Windows. If the selected primary resolver is unavailable, WinUtil uses the closest Mullvad secondary resolver to preserve connectivity; that fallback may use a different filtering level and can be less restrictive.

### Customize Preferences

Expand Down
52 changes: 32 additions & 20 deletions functions/private/Find-TweaksByNameOrDescription.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,25 @@ function Find-TweaksByNameOrDescription {
}

if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $null
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] } | Select-Object -First 1
$container = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] -or $_ -is [Windows.Controls.StackPanel] -or $_ -is [Windows.Controls.ScrollViewer] -or $_.GetType().Name -eq "ItemsControl" } | Select-Object -First 1

if ($null -ne $itemsControl) {
if ($null -ne $container) {
$targetPanel = if ($container.PSObject.Properties['Content'] -and $null -ne $container.Content) { $container.Content } else { $container }
$items = $null
if ($targetPanel -is [Windows.Controls.ItemsControl] -or $targetPanel.GetType().Name -eq "ItemsControl") {
$items = $targetPanel.Items
}
else {
$items = $targetPanel.Children
}
# Show all items in the category
foreach ($item in $itemsControl.Items) {
foreach ($item in $items) {
if ($null -ne $item) {
# Check if it's a category label (first Label in the ItemsControl)
if ($item -is [Windows.Controls.Label]) {
# Check if it's a category label (first Label in the container)
if ($item -is [Windows.Controls.Label] -or $item.GetType().Name -eq "Label") {
$item.Visibility = [Windows.Visibility]::Visible
}
elseif ($item -is [Windows.Controls.DockPanel] -or $item -is [Windows.Controls.StackPanel]) {
elseif ($item -is [Windows.Controls.DockPanel] -or $item -is [Windows.Controls.StackPanel] -or $item.GetType().Name -eq "DockPanel" -or $item.GetType().Name -eq "StackPanel") {
# Show all checkbox containers
$item.Visibility = [Windows.Visibility]::Visible
}
Expand Down Expand Up @@ -143,16 +150,21 @@ function Find-TweaksByNameOrDescription {
}

if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $null
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] } | Select-Object -First 1
$container = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] -or $_ -is [Windows.Controls.StackPanel] -or $_ -is [Windows.Controls.ScrollViewer] -or $_.GetType().Name -eq "ItemsControl" } | Select-Object -First 1

if ($null -ne $itemsControl) {
if ($null -ne $container) {
$categoryLabel = $null

# Process all items (checkboxes, labels, panels) in the ItemsControl
for ($i = 0; $i -lt $itemsControl.Items.Count; $i++) {
$item = $itemsControl.Items[$i]

$targetPanel = if ($container.PSObject.Properties['Content'] -and $null -ne $container.Content) { $container.Content } else { $container }
$items = $null
if ($targetPanel -is [Windows.Controls.ItemsControl] -or $targetPanel.GetType().Name -eq "ItemsControl") {
$items = $targetPanel.Items
}
else {
$items = $targetPanel.Children
}
# Process all items (checkboxes, labels, panels) in the container
foreach ($item in $items) {
if ($null -eq $item) {
continue
}
Expand All @@ -161,7 +173,7 @@ function Find-TweaksByNameOrDescription {
# Check if this is a category label (usually first Label)
# ------------------------------------------------------------

if ($item -is [Windows.Controls.Label]) {
if ($item -is [Windows.Controls.Label] -or $item.GetType().Name -eq "Label") {
$categoryLabel = $item
# Initially hide category label; show it only if matches found
$item.Visibility = [Windows.Visibility]::Collapsed
Expand All @@ -171,13 +183,13 @@ function Find-TweaksByNameOrDescription {
# Check if this is a DockPanel containing a tweak checkbox
# ------------------------------------------------------------

elseif ($item -is [Windows.Controls.DockPanel]) {
elseif ($item -is [Windows.Controls.DockPanel] -or $item.GetType().Name -eq "DockPanel") {
$checkbox = $null
$label = $null

# Safely extract checkbox and label
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
$label = $item.Children | Where-Object { $_ -is [Windows.Controls.Label] } | Select-Object -First 1
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] -or $_.GetType().Name -eq "CheckBox" } | Select-Object -First 1
$label = $item.Children | Where-Object { $_ -is [Windows.Controls.Label] -or $_.GetType().Name -eq "Label" } | Select-Object -First 1

# Check if tweak matches search criteria
$itemMatches = $false
Expand Down Expand Up @@ -221,9 +233,9 @@ function Find-TweaksByNameOrDescription {
# Check if this is a StackPanel containing a tweak checkbox
# ------------------------------------------------------------

elseif ($item -is [Windows.Controls.StackPanel]) {
elseif ($item -is [Windows.Controls.StackPanel] -or $item.GetType().Name -eq "StackPanel") {
$checkbox = $null
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] -or $_.GetType().Name -eq "CheckBox" } | Select-Object -First 1

$itemMatches = $false

Expand Down
36 changes: 36 additions & 0 deletions functions/private/Get-WinUtilRegistryComboState.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
function Get-WinUtilRegistryComboState {
<#
.SYNOPSIS
Finds the configured combo-box state matching the current registry values.

.PARAMETER Registry
Registry settings containing a value mapping for each supported state.

.OUTPUTS
The name of the matching state.
#>
param(
[Parameter(Mandatory)]
$Registry
)

foreach ($state in $Registry[0].Values.PSObject.Properties) {
$stateMatches = $true
foreach ($setting in @($Registry)) {
$currentValue = Get-WinUtilRegistryComboValue -Setting $setting
$actualValue = if ($currentValue.Exists -and $null -ne $currentValue.Value) { $currentValue.Value } else { $setting.DefaultValue }
$configuredValue = $setting.Values.PSObject.Properties[$state.Name].Value
# Removal represents the effective Windows default when matching the current state.
$expectedValue = if ($configuredValue -eq "<RemoveEntry>") { $setting.DefaultValue } else { $configuredValue }
if ([string]$actualValue -ne [string]$expectedValue) {
$stateMatches = $false
break
}
}
if ($stateMatches) {
return $state.Name
}
}

throw "Registry values do not match a supported state."
}
24 changes: 24 additions & 0 deletions functions/private/Get-WinUtilRegistryComboValue.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
function Get-WinUtilRegistryComboValue {
<#
.SYNOPSIS
Reads one registry value for a registry-backed combo-box state.

.PARAMETER Setting
The registry setting from the combo-box configuration.
#>
param(
[Parameter(Mandatory)]
$Setting
)

try {
$item = Get-ItemProperty -Path $Setting.Path -Name $Setting.Name -ErrorAction Stop
$property = $item.PSObject.Properties[$Setting.Name]
return [pscustomobject]@{ Exists = $null -ne $property; Value = $property.Value }
} catch [System.Management.Automation.PSArgumentException] {
# The registry provider uses PSArgumentException when a named value is absent.
return [pscustomobject]@{ Exists = $false; Value = $null }
} catch [System.Management.Automation.ItemNotFoundException] {
return [pscustomobject]@{ Exists = $false; Value = $null }
}
}
2 changes: 1 addition & 1 deletion functions/private/Invoke-WinUtilCurrentSystem.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Function Invoke-WinUtilCurrentSystem {
$serviceKeys = $entry.service
$entryType = $entry.Type

if ($registryKeys -or $serviceKeys) {
if (($registryKeys -or $serviceKeys) -and $entryType -ne "Combobox") {
$Values = @()

if ($entryType -eq "Toggle") {
Expand Down
2 changes: 1 addition & 1 deletion functions/private/Invoke-WinUtilTweaks.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function Invoke-WinUtilTweaks {
}
}
if ($sync.configs.tweaks.$CheckBox.registry) {
$sync.configs.tweaks.$CheckBox.registry | ForEach-Object {
$sync.configs.tweaks.$CheckBox.registry | Where-Object { -not $psitem.Values } | ForEach-Object {
Set-WinUtilRegistry -Name $psitem.Name -Path $psitem.Path -Type $psitem.Type -Value $psitem.$($values.registry)
}
}
Expand Down
Loading
Loading