PortValhalla/scripts/Windows/Scripts/Users.ps1
2024-10-06 21:25:34 +02:00

280 lines
9.7 KiB
PowerShell

using namespace System.Management.Automation.Host;
using namespace System.Security.Principal;
$null = New-Module {
. "$PSScriptRoot/Deployment.ps1";
. "$PSScriptRoot/Registry.ps1";
. "$PSScriptRoot/System.ps1";
. "$PSScriptRoot/../Types/OneShotTask.ps1";
. "$PSScriptRoot/../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../Common/Scripts/Operations.ps1";
$loggedInUserOption = "LoggedInUser";
<#
.SYNOPSIS
Installs all pending users to the system.
#>
function Install-ValhallaUsers {
$users = @(Get-Users);
$i = Get-CurrentUser;
for (; $i -lt $users.Count; $i++) {
Set-CurrentUser $i;
$name = $users[$i];
$msAccount = Get-UserConfig -UserName $name "microsoftAccount";
if (Test-Admin) {
Disable-BootMessage;
}
while ((Get-UserStage) -ne ([UserStage]::Completed)) {
switch (Get-UserStage) {
($null) {
Set-UserStage ([UserStage]::Create);
break;
}
([UserStage]::Create) {
if ($env:UserName -ne $name) {
$userInfo = @{
name = $name;
msAccount = $msAccount;
};
New-ValhallaUser @userInfo;
if ($msAccount) {
logoff;
}
else {
Restart-Intermediate;
}
exit;
}
else {
if ($msAccount) {
if (-not (Test-Admin)) {
Invoke-OneShot DisableUAC;
Restart-Intermediate -NoRegister;
exit;
}
Clear-SetupRegistration;
Disable-OneShotListener;
}
Set-UserStage ([UserStage]::Configure);
}
}
([UserStage]::Configure) {
$displayName = Get-UserConfig -UserName $name "displayName";
$userInfo = @{
name = $name;
};
if ($displayName) {
$userInfo.fullName = $displayName;
}
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
Set-LocalUser @userInfo;
Deploy-SoftwareAction -Action ConfigureUser;
Remove-LocalGroupMember -Member "$name" @adminGroup -ErrorAction SilentlyContinue;
foreach ($group in Get-UserConfig -UserName "$name" "groups") {
Add-LocalGroupMember -Member "$name" -Name "$group";
}
if (-not $msAccount) {
net user $name /logonpasswordchg:yes;
}
Set-UserStage ([UserStage]::Cleanup);
}
([UserStage]::Cleanup) {
$user = Get-SetupUser;
Disable-LocalUser $name;
Enable-LocalUser $user;
Set-AutologinUser $user;
Unregister-WslDistribution;
Set-UserStage ([UserStage]::Completed);
Restart-Intermediate;
exit;
}
}
}
Set-UserStage $null;
}
foreach ($user in $users) {
Enable-LocalUser $user;
}
}
<#
.SYNOPSIS
Creates a new user for the PortValhalla setup.
.PARAMETER Name
The name of the user to create.
.PARAMETER MSAccount
A value indicating whether the user should be created as a Microsoft Account.
#>
function New-ValhallaUser {
param(
[string] $Name,
[switch] $MSAccount
)
function Add-MicrosoftAccount {
param(
[string] $Name
)
$newUser = & {
while ($true) {
$currentUsers = Get-LocalUser | ForEach-Object { $_.Name };
Write-Host (
@(
"So… Windows is too dumb to create users which are bound to a Microsoft Account.",
"Thus, you have to do it by yourself.",
"So sorry…") -join "`n");
Write-Host "Create a user for ``$Name`` manually… (because Windows is too stupid)";
$null = Read-Host "Hit enter once you're done";
$newUsers = @(Get-LocalUser | Where-Object { -not ($currentUsers -contains $_.Name) });
if ($newUsers.Count) {
if ($newUsers.Count -eq 1) {
$newUser = $newUsers[0];
Write-Host "Found new user ``$newUser``";
if (
$Host.UI.PromptForChoice(
"Confirm",
"Is ``$newUser`` your user?",
[ChoiceDescription[]]@(
[ChoiceDescription]::new("&No", "``$newUser`` is not your user"),
[ChoiceDescription]::new("&Yes", "``$newUser`` is your user")),
0) -eq 1) {
return $newUser;
}
}
else {
$result = $Host.UI.PromptForChoice(
"Select your User",
"Which one is your user?",
[ChoiceDescription[]](
& {
[ChoiceDescription]::new("&None", "None of these users is yours");
for ($i = 0; $i -lt $newUsers.Count; $i++) {
$name = "$($newUsers[$i])";
[ChoiceDescription]::new("&$($i + 1) - ``$name``", "Your user is ``$name``");
}
}), 0);
if ($result -gt 0) {
return $newUsers[$result - 1];
}
}
}
else {
Write-Host "";
Write-Host "Unable to determine the new user";
Write-Host "Retrying…";
}
}
};
Set-MSAccountName ([string]$newUser);
}
if ($MSAccount) {
if (Test-Admin) {
Write-Host "Preparing environment for creating MS Account";
Register-Setup -DefaultUser;
Enable-OneShotListener;
Enable-UAC;
# Reset Windows activation status
# Otherwise the login won't work - Windows is fricking frustrating.
slmgr /upk;
slmgr /cpky;
slmgr /rearm;
Restart-Intermediate -CurrentUser;
exit;
}
}
Write-Host "Creating personal user ``$Name``";
if ($MSAccount) {
Add-MicrosoftAccount $Name;
Set-SetupOption $loggedInUserOption $env:UserName;
Invoke-OneShot ([OneShotTask]::InitializeMSAccount);
}
else {
New-LocalUser -NoPassword $Name;
Set-LocalUser $Name -PasswordNeverExpires $true;
Set-LocalUser $Name -PasswordNeverExpires $false;
Initialize-UserCreation;
}
}
<#
.SYNOPSIS
Prepares the first login for initializing the current user under configuration.
#>
function Initialize-UserCreation {
$name = (@(Get-Users))[(Get-CurrentUser)];
$msAccount = Get-UserConfig -UserName $name "microsoftAccount";
Write-Host "Initializing user ``$name``";
$userArguments = @{
name = $name;
};
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
if ($msAccount) {
$accountName = Get-MSAccountName;
Write-Host "Renaming ``$accountName`` to ``$name``";
Rename-LocalUser $accountName $name;
}
Set-LocalUser @userArguments;
if ($msAccount) {
Disable-LocalUser (Get-SetupOption $loggedInUserOption);
}
else {
Disable-LocalUser $env:UserName;
}
Add-LocalGroupMember `
@adminGroup `
$name `
-ErrorAction SilentlyContinue;
if ($msAccount) {
Disable-Autologin;
Set-BootMessage -Caption "Please Log In" -Message "Please log in using your new Microsoft Account ``$name``.";
}
else {
Set-AutologinUser "$name";
}
}
};