mirror of
https://github.com/NexusOne23/noid-privacy.git
synced 2026-02-07 04:01:52 +01:00
332 lines
9.5 KiB
PowerShell
332 lines
9.5 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Safe registry operation utilities for NoID Privacy
|
|
|
|
.DESCRIPTION
|
|
Provides safe, validated registry manipulation functions with
|
|
automatic backup and error handling.
|
|
|
|
.NOTES
|
|
Author: NexusOne23
|
|
Version: 2.2.1
|
|
Requires: PowerShell 5.1+
|
|
#>
|
|
|
|
function Test-RegistryValueType {
|
|
<#
|
|
.SYNOPSIS
|
|
Validate registry value type matches expected type
|
|
|
|
.DESCRIPTION
|
|
Performs strict type checking to ensure registry value
|
|
matches the declared registry type before setting.
|
|
|
|
.PARAMETER Value
|
|
Value to validate
|
|
|
|
.PARAMETER Type
|
|
Expected registry type
|
|
|
|
.OUTPUTS
|
|
Boolean indicating if type matches
|
|
|
|
.EXAMPLE
|
|
Test-RegistryValueType -Value 1 -Type "DWord"
|
|
#>
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[AllowNull()]
|
|
$Value,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateSet("String", "ExpandString", "Binary", "DWord", "MultiString", "QWord")]
|
|
[string]$Type
|
|
)
|
|
|
|
# Null values are not allowed for registry
|
|
if ($null -eq $Value) {
|
|
Write-Log -Level ERROR -Message "Registry value cannot be null" -Module "Registry"
|
|
return $false
|
|
}
|
|
|
|
switch ($Type) {
|
|
"String" {
|
|
if ($Value -isnot [string]) {
|
|
Write-Log -Level ERROR -Message "Value must be [string] for type String, got [$($Value.GetType().Name)]" -Module "Registry"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
"ExpandString" {
|
|
if ($Value -isnot [string]) {
|
|
Write-Log -Level ERROR -Message "Value must be [string] for type ExpandString, got [$($Value.GetType().Name)]" -Module "Registry"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
"DWord" {
|
|
# DWord must be integer and fit in 32-bit (0 to 4294967295)
|
|
if ($Value -isnot [int] -and $Value -isnot [uint32] -and $Value -isnot [long]) {
|
|
Write-Log -Level ERROR -Message "Value must be numeric for type DWord, got [$($Value.GetType().Name)]" -Module "Registry"
|
|
return $false
|
|
}
|
|
|
|
$numValue = [long]$Value
|
|
if ($numValue -lt 0 -or $numValue -gt 4294967295) {
|
|
Write-Log -Level ERROR -Message "DWord value must be between 0 and 4294967295, got $numValue" -Module "Registry"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
"QWord" {
|
|
# QWord must be integer and fit in 64-bit
|
|
if ($Value -isnot [int] -and $Value -isnot [long] -and $Value -isnot [uint64]) {
|
|
Write-Log -Level ERROR -Message "Value must be numeric for type QWord, got [$($Value.GetType().Name)]" -Module "Registry"
|
|
return $false
|
|
}
|
|
|
|
# Check if value is in valid range for QWord (0 to 18446744073709551615)
|
|
if ([long]$Value -lt 0) {
|
|
Write-Log -Level ERROR -Message "QWord value cannot be negative, got $Value" -Module "Registry"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
"Binary" {
|
|
# Binary must be byte array
|
|
if ($Value -isnot [byte[]]) {
|
|
Write-Log -Level ERROR -Message "Value must be [byte[]] for type Binary, got [$($Value.GetType().Name)]" -Module "Registry"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
"MultiString" {
|
|
# MultiString must be string array
|
|
if ($Value -isnot [string[]]) {
|
|
Write-Log -Level ERROR -Message "Value must be [string[]] for type MultiString, got [$($Value.GetType().Name)]" -Module "Registry"
|
|
return $false
|
|
}
|
|
}
|
|
}
|
|
|
|
return $true
|
|
}
|
|
|
|
function Set-RegistryValue {
|
|
<#
|
|
.SYNOPSIS
|
|
Safely set a registry value with automatic backup
|
|
|
|
.PARAMETER Path
|
|
Registry path (e.g., "HKLM:\SOFTWARE\Policies\Microsoft\Windows")
|
|
|
|
.PARAMETER Name
|
|
Registry value name
|
|
|
|
.PARAMETER Value
|
|
Value to set
|
|
|
|
.PARAMETER Type
|
|
Registry value type (String, DWord, QWord, Binary, MultiString, ExpandString)
|
|
|
|
.PARAMETER BackupName
|
|
Optional backup name (if not provided, backup is skipped)
|
|
|
|
.OUTPUTS
|
|
Boolean indicating success
|
|
#>
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Path,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Name,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
$Value,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateSet("String", "ExpandString", "Binary", "DWord", "MultiString", "QWord")]
|
|
[string]$Type,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$BackupName
|
|
)
|
|
|
|
try {
|
|
# CRITICAL: Validate value type BEFORE setting
|
|
if (-not (Test-RegistryValueType -Value $Value -Type $Type)) {
|
|
$errMsg = "Type validation failed for $Path\$Name - Expected type: $Type, Value: $Value"
|
|
Write-Log -Level ERROR -Message $errMsg -Module "Registry"
|
|
throw $errMsg
|
|
}
|
|
|
|
# Create backup if requested
|
|
if ($BackupName) {
|
|
$parentPath = Split-Path -Path $Path -Parent
|
|
if (Test-Path -Path $parentPath) {
|
|
Backup-RegistryKey -KeyPath $parentPath -BackupName $BackupName | Out-Null
|
|
}
|
|
}
|
|
|
|
# Ensure the key exists
|
|
if (-not (Test-Path -Path $Path)) {
|
|
New-Item -Path $Path -Force | Out-Null
|
|
Write-Log -Level INFO -Message "Created registry key: $Path" -Module "Registry"
|
|
|
|
# Track newly created key for proper rollback
|
|
if (Get-Command Register-NewRegistryKey -ErrorAction SilentlyContinue) {
|
|
Register-NewRegistryKey -KeyPath $Path
|
|
}
|
|
}
|
|
|
|
# Set the value
|
|
Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type -Force -ErrorAction Stop | Out-Null
|
|
|
|
Write-Log -Level SUCCESS -Message "Set registry value: $Path\$Name = $Value (Type: $Type)" -Module "Registry"
|
|
return $true
|
|
}
|
|
catch {
|
|
Write-Log -Level ERROR -Message "Failed to set registry value: $Path\$Name - $_" -Module "Registry" -Exception $_
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Get-RegistryValue {
|
|
<#
|
|
.SYNOPSIS
|
|
Safely get a registry value
|
|
|
|
.PARAMETER Path
|
|
Registry path
|
|
|
|
.PARAMETER Name
|
|
Registry value name
|
|
|
|
.PARAMETER DefaultValue
|
|
Default value if registry value doesn't exist
|
|
|
|
.OUTPUTS
|
|
Registry value or default value
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Path,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Name,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
$DefaultValue = $null
|
|
)
|
|
|
|
try {
|
|
if (Test-Path -Path $Path) {
|
|
$value = Get-ItemProperty -Path $Path -Name $Name -ErrorAction Stop
|
|
return $value.$Name
|
|
}
|
|
else {
|
|
Write-Log -Level WARNING -Message "Registry path not found: $Path" -Module "Registry"
|
|
return $DefaultValue
|
|
}
|
|
}
|
|
catch {
|
|
Write-Log -Level WARNING -Message "Registry value not found: $Path\$Name" -Module "Registry"
|
|
return $DefaultValue
|
|
}
|
|
}
|
|
|
|
function Remove-RegistryValue {
|
|
<#
|
|
.SYNOPSIS
|
|
Safely remove a registry value
|
|
|
|
.PARAMETER Path
|
|
Registry path
|
|
|
|
.PARAMETER Name
|
|
Registry value name
|
|
|
|
.PARAMETER BackupName
|
|
Optional backup name
|
|
|
|
.OUTPUTS
|
|
Boolean indicating success
|
|
#>
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Path,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Name,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$BackupName
|
|
)
|
|
|
|
try {
|
|
# Create backup if requested
|
|
if ($BackupName) {
|
|
Backup-RegistryKey -KeyPath $Path -BackupName $BackupName | Out-Null
|
|
}
|
|
|
|
if (Test-Path -Path $Path) {
|
|
Remove-ItemProperty -Path $Path -Name $Name -Force -ErrorAction Stop
|
|
Write-Log -Level SUCCESS -Message "Removed registry value: $Path\$Name" -Module "Registry"
|
|
return $true
|
|
}
|
|
else {
|
|
Write-Log -Level WARNING -Message "Registry path not found: $Path" -Module "Registry"
|
|
return $false
|
|
}
|
|
}
|
|
catch {
|
|
Write-Log -Level ERROR -Message "Failed to remove registry value: $Path\$Name" -Module "Registry" -Exception $_
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Test-RegistryValue {
|
|
<#
|
|
.SYNOPSIS
|
|
Check if a registry value exists
|
|
|
|
.PARAMETER Path
|
|
Registry path
|
|
|
|
.PARAMETER Name
|
|
Registry value name
|
|
|
|
.OUTPUTS
|
|
Boolean indicating existence
|
|
#>
|
|
[CmdletBinding()]
|
|
[OutputType([bool])]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Path,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Name
|
|
)
|
|
|
|
try {
|
|
if (Test-Path -Path $Path) {
|
|
$null = Get-ItemProperty -Path $Path -Name $Name -ErrorAction Stop
|
|
return $true
|
|
}
|
|
return $false
|
|
}
|
|
catch {
|
|
return $false
|
|
}
|
|
}
|
|
|
|
# Note: Export-ModuleMember not used - this script is dot-sourced, not imported as module
|