oslib/os/windows/unattend.nix
2024-06-24 12:54:49 -06:00

247 lines
8.5 KiB
Nix

{ pkgs }: rec {
xml = import ./xml.nix;
# generate = import ./generate.nix;
settingsPass = name: contents: xml.elem "settings" [ (xml.attr "pass" name) ] contents;
component = name: subelems: xml.elem "component" [
(xml.attr "name" name)
(xml.attr "processorArchitecture" "amd64")
(xml.attr "publicKeyToken" "31bf3856ad364e35")
(xml.attr "language" "neutral")
(xml.attr "versionScope" "nonSxS")
(xml.attr "xmlns:wcm" "http://schemas.microsoft.com/WMIConfig/2002/State")
(xml.attr "xmlns:xsi" "http://www.w3.org/2001/XMLSchema-instance")
] subelems;
listElem = n: v: xml.elem n [ (xml.attr "wcm:action" "add") ] v;
list = name: subname: items: xml.elem name [] (map (item: listElem subname item) items);
elem = name: contents: xml.elem name [] contents;
typeCheck = tname: test: x:
if test x then x else builtins.abort ("expected " + tname + ", found " + builtins.typeOf x);
typeConvert = tname: test: conv: x: conv (typeCheck tname test x);
typeString = typeConvert "string" builtins.isString (x: x);
typeInt = typeConvert "int" builtins.isInt builtins.toString;
typeBool = typeConvert "bool" builtins.isBool (t: if t then "true" else "false");
typeBoolAlwaysNever = typeConvert "bool" builtins.isBool (t: if t then "Always" else "Never");
mkElem = name: type: option: elem name (type option);
optional = config: name: elem: xml.opt (builtins.hasAttr name config) elem;
process = config: xml.elem "unattend" [ (xml.attr "xmlns" "urn:schemas-microsoft-com:unattend") ] [
(settingsPass "specialize" [
(component "Microsoft-Windows-Shell-Setup" [
(optional config "oemInfo" (mkElem "OEMInformation" [
(mkElem "Manufacturer" typeString config.oemInfo.manufacturer)
(mkElem "Model" typeString config.oemInfo.model)
]))
(mkElem "ComputerName" typeString config.name)
(optional config "productKey" (mkElem "ProductKey" typeString config.productKey))
(mkElem "TimeZone" typeString config.locale.timeZone)
])
(component "Microsoft-Windows-Security-SPP-UX" [
(elem "SkipAutoActivation" "true")
])
(component "Microsoft-Windows-Deployment" [
(list "RunSynchronous" "RunSynchronousCommand" [
[
(elem "Description" "Notify Host")
(elem "Order" "1")
(elem "Path" "cmd.exe /C echo specialize>COM1")
]
])
])
])
(settingsPass "windowsPE" [
(component "Microsoft-Windows-Setup" [
(elem "DiskConfiguration" [
(mkElem "WillShowUI" typeBoolAlwaysNever config.diskConfig.showUI)
(xml.elem "Disk" [ (xml.attr "wcm:action" "add") ] [
(list "CreatePartitions" "CreatePartition" [
[
(elem "Order" "1")
(elem "Size" "100")
(elem "Type" "Primary")
]
[
(elem "Order" "2")
(elem "Extend" "true")
(elem "Type" "Primary")
]
])
(list "ModifyPartitions" "ModifyPartition" [
[
(elem "Format" "NTFS")
(elem "Label" "System Reserved")
(elem "Order" "1")
(elem "Active" "true")
(elem "PartitionID" "1")
(elem "TypeID" "0x27")
]
[
(elem "Format" "NTFS")
(elem "Label" "Local Disk")
(elem "Order" "2")
(elem "Active" "true")
(elem "PartitionID" "1")
(elem "Letter" "C")
]
])
(elem "DiskID" "0")
(elem "WillWipeDisk" "true")
])
])
(elem "DynamicUpdate" [
(mkElem "WillShowUI" typeBoolAlwaysNever config.dynamicUpdate.showUI)
])
(elem "ImageInstall" [
(elem "OSImage" [
(elem "InstallTo" [
(elem "DiskID" "0")
(elem "PartitionID" "2")
])
(elem "InstallToAvailablePartition" "false")
(elem "WillShowUI" "Never")
])
])
(elem "UserData" [
(elem "ProductKey" [
(optional config "productKey" (mkElem "Key" typeString config.productKey))
])
(mkElem "AcceptEula" typeBool config.userData.acceptEula)
(mkElem "FullName" typeString config.userData.fullName)
(mkElem "Organization" typeString config.userData.organization)
])
])
(component "Microsoft-Windows-International-Core-WinPE" [
(elem "SetupUILanguage" [
(mkElem "UILanguage" typeString config.locale.language)
(mkElem "WillShowUI" typeBoolAlwaysNever config.locale.showUI)
])
(mkElem "InputLocale" typeString config.locale.input)
(mkElem "SystemLocale" typeString config.locale.language)
(mkElem "UILanguage" typeString config.locale.language)
(mkElem "UserLocale" typeString config.locale.language)
])
])
(settingsPass "generalize" [
(component "Microsoft-Windows-Security-SPP" [
(elem "SkipRearm" "1")
])
])
(settingsPass "oobeSystem" [
(component "Microsoft-Windows-International-Core" [
(mkElem "InputLocale" typeString config.locale.input)
(mkElem "UILanguage" typeString config.locale.language)
(mkElem "UserLocale" typeString config.locale.language)
])
(component "Microsoft-Windows-Shell-Setup" [
(mkElem "RegisteredOwner" typeString config.userData.fullName)
(mkElem "RegisteredOrganization" typeString config.userData.organization)
(elem "DisableAutoDaylightTimeSet" "false")
(elem "OOBE" [
(elem "HideEULAPage" "true")
(elem "HideWirelessSetupInOOBE" "true")
(elem "NetworkLocation" "Home")
(elem "ProtectYourPC" "3")
(elem "SkipMachineOOBE" "true")
(elem "SkipUserOOBE" "true")
])
(list "FirstLogonCommands" "SynchronousCommand" (map (item: [
(mkElem "Description" typeString item.description)
(mkElem "CommandLine" typeString item.command)
(mkElem "Order" typeInt item.order)
]) config.firstLogonCommands))
# TODO make autologin reference the users list
(if builtins.hasAttr "autoLogon" config then
(elem "AutoLogon" [
(elem "Enabled" "true")
(mkElem "Username" typeString config.autoLogon.username)
(elem "Password" [
(mkElem "Value" typeString config.autoLogon.password)
(elem "PlainText" "true")
])
])
else
(elem "AutoLogon" [ (elem "Enabled" "false") ])
)
(xml.elem "UserAccounts" [] [
(list "LocalAccounts" "LocalAccount" (map (user: [
(elem "DisplayName" user.displayName)
(elem "Name" user.name)
(elem "Group" user.group)
(if user.password.enable then
(elem "Password" [
(elem "Value" user.password.value)
(elem "PlainText" user.password.plainText)
])
else
(elem "Password" [
(elem "Value" "")
(elem "PlainText" "true")
])
)
]) config.users))
])
])
])
];
default = let
user = {
name = "idiot";
displayName = "Idiot";
group = "Administrators";
password.enable = false;
};
in {
name = user.displayName + "-PC";
locale = {
language = "en-US";
timeZone = "Mountain Standard Time";
input = "1033:00000409";
showUI = false;
};
users = [ user ];
skipAutoActivation = true;
diskConfig = {
showUI = false;
};
dynamicUpdate.showUI = false;
userData = {
acceptEula = true;
fullName = user.displayName;
organization = "Dumbass Inc.";
};
firstLogonCommands = [
{
order = 1;
description = "Disable Auto Updates";
command = "reg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\" /v AUOptions /t REG_DWORD /d 1 /f";
}
{
order = 2;
description = "Notify Host";
command = "cmd.exe /C echo ready>COM1";
}
];
autoLogon = {
username = "idiot";
password = "";
};
};
genConfig = config: builtins.concatStringsSep "" [
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
(xml.toText (process config))
];
}