using namespace Microsoft.Win32; using namespace System.Security.AccessControl; using namespace System.Security.Principal; enum SetupStage { Initialize Configure Install CreateUser ConfigureUser } $null = New-Module { [string] $configRoot = "HKLM:\Software\PortValhalla"; [string] $stageOption = "Stage"; [string] $finishedOption = "Finished"; [RegistryKey] $key = $null; <# .SYNOPSIS Converts the specified path to linux and escapes it for the use in a script. .PARAMETER Path The path to convert. #> function ConvertTo-LinuxPath { param( [string] $Path ) $job = Start-Job { $env:Value = Resolve-Path $Using:Path; $env:WSLENV = "Value/p"; $result = wsl -- bash -c 'echo "$Value"'; wsl -e printf "%q" "$result"; }; Receive-Job -Wait $job; } <# .SYNOPSIS Gets the registry key containing options related to the setup. #> function Get-SetupConfigKey { if (-not (Test-Path $configRoot)) { $key = New-Item $configRoot; $acl = Get-Acl $configRoot; $acl.AddAccessRule( [RegistryAccessRule]::new( [SecurityIdentifier]::new([WellKnownSidType]::BuiltinUsersSid, $null), [RegistryRights]::FullControl, [InheritanceFlags]::ObjectInherit -bor [InheritanceFlags]::ContainerInherit, [PropagationFlags]::None, [AccessControlType]::Allow)); Set-Acl $configRoot $acl; } else { $key = Get-Item $configRoot; } return $key; } <# .SYNOPSIS Runs a script based on the `config.fish` script. .PARAMETER Script The script to run. #> function Invoke-ConfigScript { param( [string] $Script ) $scriptPath = "$PSScriptRoot/../../Common/Scripts/config.fish"; if (-not $IsWindows) { $escapedPath = (fish -c 'string escape $argv' "$scriptPath"); fish -c ". $escapedPath; $Script"; } else { function fish { wsl --shell-type login -- nix --extra-experimental-features "nix-command flakes" run nixpkgs`#fish -- $args } fish -c ". $(ConvertTo-LinuxPath $scriptPath); $Script" | ConvertFrom-Json; } } <# .SYNOPSIS Gets a configuration option. .PARAMETER Name The name of the option to get. #> function Get-Config { param( [string] $Name, [Parameter(ValueFromRemainingArguments)] [string[]] $ArgumentList ) Invoke-ConfigScript "getConfig $Name --json $ArgumentList"; } <# .SYNOPSIS Gets a user configuration. .PARAMETER UserName The name of the user to get the configuration for. .PARAMETER Name The name of the configuration to get. #> function Get-UserConfig { param( [string] $UserName = $env:UserName, [Parameter(Mandatory, Position = 0)] [string] $Name ) if ((Get-Users) -contains $UserName) { Get-Config "valhalla.windows.users.$UserName.$Name"; } else { return $null; } } <# .SYNOPSIS Gets the attributes of a configuration object. .PARAMETER Name The name of the configuration to get the attributes of. #> function Get-Attributes { param( [string] $Name ) Invoke-ConfigScript "getAttributes $Name"; } <# .SYNOPSIS Gets the names of the users to create. #> function Get-Users { [OutputType([string[]])] param() Get-Attributes "valhalla.windows.users"; } <# .SYNOPSIS Gets the name of the setup user. #> function Get-SetupUser { [OutputType([string])] param() Get-Config "valhalla.windows.setupUser"; } <# .SYNOPSIS Gets the value of an option related to the setup. .PARAMETER Name The name of the option value to get. #> function Get-SetupOption { param( [string] $Name ) $key = Get-SetupConfigKey; if ($key.GetValueNames().Contains($Name)) { return $key.GetValue($Name); } else { return $null; } } <# .SYNOPSIS Sets the value of an option related to the setup. .PARAMETER Name The name of the option to set. .PARAMETER Value The value to set the option to. #> function Set-SetupOption { param( [string] $Name, $Value ) $key = Get-SetupConfigKey; $null = Set-ItemProperty ($key.PSPath) -Name $Name -Value $Value; } <# .SYNOPSIS Gets the name of the current setup stage. #> function Get-Stage { $stage = Get-SetupOption $stageOption; if ($null -ne $stage) { $stage = [SetupStage]$stage; } return $stage; } <# .SYNOPSIS Sets the current stage. .PARAMETER Name The name to set the current stage to. #> function Set-Stage { param( $Name ) if (-not (($null -eq $Name) -or ($Name -is [string]))) { $Name = ([SetupStage]$Name).ToString(); } $null = Set-SetupOption $stageOption $Name; } <# .SYNOPSIS Gets a value indicating whether the setup has finished. #> function Get-IsFinished { return [bool] (Get-SetupOption $finishedOption); } <# .SYNOPSIS Sets a value indicating whether the setup has finished. #> function Set-IsFinished { param( $Value ) Set-SetupOption $finishedOption $true; } <# .SYNOPSIS Checks whether the specified software collection is enabled. .PARAMETER Name The name of the collection to check. #> function Test-Collection { param( [string] $Name ) Get-Config "valhalla.software.$Name"; } <# .SYNOPSIS Checks whether the current user is the setup user. #> function Test-SetupUser { $env:UserName -eq (Get-Config "valhalla.windows.setupUser"); } <# .SYNOPSIS Checks whether the active session is executed with admin rights. #> function Test-Admin { net session 2> $null | Out-Null; return $?; } }