431 lines
10 KiB
PowerShell
431 lines
10 KiB
PowerShell
using namespace Microsoft.Win32;
|
|
using namespace System.Security.AccessControl;
|
|
using namespace System.Security.Principal;
|
|
|
|
enum SetupStage {
|
|
Idle
|
|
Initialize
|
|
OneShot
|
|
Configure
|
|
Install
|
|
CreateUser
|
|
}
|
|
|
|
enum UserStage {
|
|
Create
|
|
Configure
|
|
Completed
|
|
}
|
|
|
|
$null = New-Module {
|
|
[string] $configRoot = "HKLM:\Software\PortValhalla";
|
|
[string] $stageOption = "Stage";
|
|
[string] $userOption = "SetupUser";
|
|
[string] $userStageOption = "UserStage";
|
|
[string] $accountOption = "MSAccount";
|
|
[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
|
|
)
|
|
|
|
& {
|
|
$ErrorActionPreference = 'Continue';
|
|
$completed = $false;
|
|
|
|
while (-not $completed) {
|
|
$job = Start-Job {
|
|
$env:Value = Resolve-Path $Using:Path;
|
|
$env:WSLENV = "Value/p";
|
|
$result = wsl -- bash -c 'echo "$Value"';
|
|
wsl -e printf "%q" "$result";
|
|
};
|
|
|
|
$result = Receive-Job -Wait $job;
|
|
|
|
|
|
if ((Split-Path -Leaf $Path) -ne (Split-Path -Leaf $result)) {
|
|
Write-Error "The result of the path conversion of ``$Path`` was unexpected: ``$result``";
|
|
continue;
|
|
}
|
|
|
|
if ($job.State -ne ([System.Management.Automation.JobState]::Completed)) {
|
|
Write-Error "An error occurred while converting ``$Path`` to a Linux path.`nOutput: ``$result``";
|
|
continue;
|
|
}
|
|
|
|
$completed = $true;
|
|
}
|
|
|
|
$result;
|
|
};
|
|
}
|
|
|
|
<#
|
|
.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 ($env:CONFIG_MODULE) {
|
|
$output = & {
|
|
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
|
|
}
|
|
|
|
$output = fish -c ". $(ConvertTo-LinuxPath $scriptPath); $Script";
|
|
|
|
if (-not $?) {
|
|
Write-Error "The configuration could not be retrieved!";
|
|
} else {
|
|
$output;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-not ($output -and ($output | Test-Json))) {
|
|
Write-Error "The value ``$output`` is not valid JSON.";
|
|
} else {
|
|
$output | ConvertFrom-Json;
|
|
}
|
|
} else {
|
|
$null;
|
|
}
|
|
}
|
|
|
|
<#
|
|
.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 the current user to set up.
|
|
#>
|
|
function Get-CurrentUser {
|
|
return (Get-SetupOption $userOption) ?? 0;
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Sets the index of the current user to set up.
|
|
|
|
.PARAMETER Value
|
|
The index of the user to set up.
|
|
#>
|
|
function Set-CurrentUser {
|
|
param(
|
|
[int] $Value
|
|
)
|
|
|
|
Set-SetupOption $userOption $value;
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Gets the name of the current stage of the user setup.
|
|
#>
|
|
function Get-UserStage {
|
|
$stage = Get-SetupOption $userStageOption;
|
|
|
|
if ($null -ne $stage) {
|
|
$stage = [UserStage]$stage;
|
|
}
|
|
|
|
return $stage;
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Sets the current stage of the user setup.
|
|
|
|
.PARAMETER Name
|
|
The name of the stage to set.
|
|
#>
|
|
function Set-UserStage {
|
|
param(
|
|
$Name
|
|
)
|
|
|
|
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
|
|
$Name = ([UserStage]$Name).ToString();
|
|
}
|
|
|
|
$null = Set-SetupOption $userStageOption $Name;
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Gets the name of the microsoft account to create.
|
|
#>
|
|
function Get-MSAccountName {
|
|
return Get-SetupOption $accountOption;
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Sets the name of the microsoft account to create.
|
|
|
|
.PARAMETER Name
|
|
The name of the microsoft account to create.
|
|
#>
|
|
function Set-MSAccountName {
|
|
param(
|
|
[string] $Name
|
|
)
|
|
|
|
Set-SetupOption $accountOption $Name;
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Gets a value indicating whether the setup has finished.
|
|
#>
|
|
function Get-IsFinished {
|
|
return [bool] (((Get-Stage) -eq ([SetupStage]::Idle)) -or (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 running system is a QEMU virtual machine.
|
|
#>
|
|
function Test-Qemu {
|
|
((Get-WmiObject win32_computersystem).Manufacturer) -eq "QEMU";
|
|
}
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Checks whether the current user is the setup user.
|
|
#>
|
|
function Test-SetupUser {
|
|
($IsWindows ? $env:UserName : $env:USER) -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 $?;
|
|
}
|
|
}
|