From 44c6b9989bbd4c147df87a4ab5e276f3c5ee0bd2 Mon Sep 17 00:00:00 2001 From: Kroese Date: Thu, 25 Jan 2024 16:15:18 +0100 Subject: [PATCH] feat: Support more Windows versions (#92) --- assets/win10x64.xml | 17 ++- assets/win11x64.xml | 17 ++- assets/win2016-eval.xml | 17 ++- assets/win2019-eval.xml | 17 ++- assets/win2022-eval.xml | 17 ++- assets/win7x64-ultimate.xml | 222 ++++++++++++++++++++++++++++++++++++ assets/win81x64.xml | 17 ++- readme.md | 4 +- src/install.sh | 195 +++++++++++++++++++++++-------- src/power.sh | 22 ++-- 10 files changed, 482 insertions(+), 63 deletions(-) create mode 100644 assets/win7x64-ultimate.xml diff --git a/assets/win10x64.xml b/assets/win10x64.xml index 88a117e..74f7cd7 100644 --- a/assets/win10x64.xml +++ b/assets/win10x64.xml @@ -170,6 +170,21 @@ Windows for Docker + + 1 + + + true + true + about:blank + about:blank + + + true + true + about:blank + about:blank + 0 @@ -307,7 +322,7 @@ true true true - Home + Other 3 true true diff --git a/assets/win11x64.xml b/assets/win11x64.xml index a993f01..2363a2f 100644 --- a/assets/win11x64.xml +++ b/assets/win11x64.xml @@ -188,6 +188,21 @@ Windows for Docker + + 1 + + + true + true + about:blank + about:blank + + + true + true + about:blank + about:blank + 0 @@ -325,7 +340,7 @@ true true true - Home + Other 3 true true diff --git a/assets/win2016-eval.xml b/assets/win2016-eval.xml index bd6d3a4..7356e33 100644 --- a/assets/win2016-eval.xml +++ b/assets/win2016-eval.xml @@ -172,6 +172,21 @@ Windows for Docker + + 1 + + + true + true + about:blank + about:blank + + + true + true + about:blank + about:blank + 0 @@ -237,7 +252,7 @@ true true true - Home + Other 3 true true diff --git a/assets/win2019-eval.xml b/assets/win2019-eval.xml index 8ea29bd..4caa666 100644 --- a/assets/win2019-eval.xml +++ b/assets/win2019-eval.xml @@ -176,6 +176,21 @@ Windows for Docker + + 1 + + + true + true + about:blank + about:blank + + + true + true + about:blank + about:blank + 0 @@ -241,7 +256,7 @@ true true true - Home + Other 3 true true diff --git a/assets/win2022-eval.xml b/assets/win2022-eval.xml index 5e9e275..7bebb6a 100644 --- a/assets/win2022-eval.xml +++ b/assets/win2022-eval.xml @@ -176,6 +176,21 @@ Windows for Docker + + 1 + + + true + true + about:blank + about:blank + + + true + true + about:blank + about:blank + 0 @@ -241,7 +256,7 @@ true true true - Home + Other 3 true true diff --git a/assets/win7x64-ultimate.xml b/assets/win7x64-ultimate.xml new file mode 100644 index 0000000..933d82d --- /dev/null +++ b/assets/win7x64-ultimate.xml @@ -0,0 +1,222 @@ + + + + + + en-US + + 0409:00000409 + en-US + en-US + en-US + + + + OnError + + 0 + true + + + 1 + Primary + 100 + + + 2 + Primary + true + + + + + NTFS + + 1 + true + 1 + 0x27 + + + true + NTFS + + C + 2 + 2 + + + + + + + + + /IMAGE/INDEX + 1 + + + + 0 + 2 + + false + + + + true + Never + + + false + Never + + + true + Docker + Windows for Docker + + D4F6K-QK3RD-TMVMJ-BBMRX-3MBMV + OnError + + + false + + false + + + + + + D:\viostor\w7\amd64 + + + D:\NetKVM\w7\amd64 + + + D:\Balloon\w7\amd64 + + + D:\pvpanic\w7\amd64 + + + D:\qemupciserial\w7\amd64 + + + D:\qxldod\w7\amd64 + + + D:\vioinput\w7\amd64 + + + D:\viorng\w7\amd64 + + + D:\vioscsi\w7\amd64 + + + D:\vioserial\w7\amd64 + + + + + + + false + + + * + + + + + true + + + 1 + + + + + true + + + 1 + + + true + true + about:blank + about:blank + + + true + true + about:blank + about:blank + + + 0 + + + 0409:00000409 + en-US + en-US + en-US + + + + + + + + Docker + Administrators + + + true</PlainText> + </Password> + </LocalAccount> + </LocalAccounts> + <AdministratorPassword> + <Value>password</Value> + <PlainText>true</PlainText> + </AdministratorPassword> + </UserAccounts> + <AutoLogon> + <Username>Docker</Username> + <Enabled>true</Enabled> + <LogonCount>1</LogonCount> + <Password> + <Value /> + <PlainText>true</PlainText> + </Password> + </AutoLogon> + <OOBE> + <HideEULAPage>true</HideEULAPage> + <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> + <NetworkLocation>Other</NetworkLocation> + <ProtectYourPC>3</ProtectYourPC> + <SkipUserOOBE>true</SkipUserOOBE> + <SkipMachineOOBE>true</SkipMachineOOBE> + </OOBE> + <FirstLogonCommands> + <SynchronousCommand wcm:action="add"> + <Order>1</Order> + <CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoLogonCount /t REG_DWORD /d 0 /f</CommandLine> + <Description>Set AutoLogonCount to 0</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>2</Order> + <CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f</CommandLine> + <Description>Allow RDP login with blank password</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>3</Order> + <CommandLine>cmd /C POWERCFG -H OFF</CommandLine> + <Description>Disable Hibernation</Description> + </SynchronousCommand> + </FirstLogonCommands> + </component> + </settings> +</unattend> diff --git a/assets/win81x64.xml b/assets/win81x64.xml index 8f2f856..1f94aa7 100644 --- a/assets/win81x64.xml +++ b/assets/win81x64.xml @@ -173,6 +173,21 @@ </OEMInformation> <OEMName>Windows for Docker</OEMName> </component> + <component name="Microsoft-Windows-ErrorReportingCore" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> + <DisableWER>1</DisableWER> + </component> + <component name="Microsoft-Windows-IE-InternetExplorer" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> + <DisableAccelerators>true</DisableAccelerators> + <DisableFirstRunWizard>true</DisableFirstRunWizard> + <Home_Page>about:blank</Home_Page> + <Help_Page>about:blank</Help_Page> + </component> + <component name="Microsoft-Windows-IE-InternetExplorer" processorArchitecture="wow64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> + <DisableAccelerators>true</DisableAccelerators> + <DisableFirstRunWizard>true</DisableFirstRunWizard> + <Home_Page>about:blank</Home_Page> + <Help_Page>about:blank</Help_Page> + </component> <component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> <CEIPEnabled>0</CEIPEnabled> </component> @@ -216,7 +231,7 @@ <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> <HideOnlineAccountScreens>true</HideOnlineAccountScreens> <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> - <NetworkLocation>Home</NetworkLocation> + <NetworkLocation>Other</NetworkLocation> <ProtectYourPC>3</ProtectYourPC> <SkipUserOOBE>true</SkipUserOOBE> <SkipMachineOOBE>true</SkipMachineOOBE> diff --git a/readme.md b/readme.md index 3c479dd..85d87a7 100644 --- a/readme.md +++ b/readme.md @@ -81,7 +81,9 @@ docker run -it --rm -p 8006:8006 --device=/dev/kvm --cap-add NET_ADMIN --stop-ti - ```win22``` = Windows Server 2022 - ```win19``` = Windows Server 2019 - ```win16``` = Windows Server 2016 - + - ```tiny11``` = Tiny 11 (Slow download) + - ```win7``` = Windows 7 (Slow download) + * ### How do I increase the amount of CPU or RAM? By default, 2 CPU cores and 4 GB of RAM are allocated to the container, as those are the minimum requirements of Windows 11. diff --git a/src/install.sh b/src/install.sh index 161259c..14edce5 100644 --- a/src/install.sh +++ b/src/install.sh @@ -20,6 +20,10 @@ fi [[ "${VERSION,,}" == "win81" ]] && VERSION="win81x64" [[ "${VERSION,,}" == "win8" ]] && VERSION="win81x64" +[[ "${VERSION,,}" == "7" ]] && VERSION="win7x64-ultimate" +[[ "${VERSION,,}" == "win7" ]] && VERSION="win7x64-ultimate" +[[ "${VERSION,,}" == "win7x64" ]] && VERSION="win7x64-ultimate" + [[ "${VERSION,,}" == "22" ]] && VERSION="win2022-eval" [[ "${VERSION,,}" == "2022" ]] && VERSION="win2022-eval" [[ "${VERSION,,}" == "win22" ]] && VERSION="win2022-eval" @@ -35,6 +39,10 @@ fi [[ "${VERSION,,}" == "win16" ]] && VERSION="win2016-eval" [[ "${VERSION,,}" == "win2016" ]] && VERSION="win2016-eval" +if [[ "${VERSION,,}" == "tiny11" ]]; then + VERSION="https://archive.org/download/tiny-11-core-x-64-beta-1/tiny11%20core%20x64%20beta%201.iso" +fi + CUSTOM="custom.iso" [ ! -f "$STORAGE/$CUSTOM" ] && CUSTOM="Custom.iso" @@ -106,10 +114,28 @@ finishInstall() { rm -f "$STORAGE/windows.boot" cp /run/version "$STORAGE/windows.ver" + if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then + touch "$STORAGE/windows.old" + else + rm -f "$STORAGE/windows.old" + fi + rm -rf "$TMP" return 0 } +abortInstall() { + + local iso="$1" + + if [[ "$iso" != "$STORAGE/$BASE" ]]; then + mv -f "$iso" "$STORAGE/$BASE" + fi + + finishInstall "$STORAGE/$BASE" + return 0 +} + startInstall() { local magic @@ -207,12 +233,13 @@ downloadImage() { if [[ "$EXTERNAL" != [Yy1]* ]]; then cd "$TMP" - /run/mido.sh "$url" + if ! /run/mido.sh "$url"; then + return 1 + fi cd /run - [ ! -f "$iso" ] && error "Failed to download $url" && exit 61 + [ ! -f "$iso" ] && return 1 return 0 - fi info "Downloading $BASE as boot image..." @@ -225,10 +252,9 @@ downloadImage() { fi { wget "$url" -O "$iso" -q --no-check-certificate --show-progress "$progress"; rc=$?; } || : - (( rc != 0 )) && error "Failed to download $url, reason: $rc" && exit 60 - [ ! -f "$iso" ] && error "Failed to download $url" && exit 61 + [ ! -f "$iso" ] && return 1 return 0 } @@ -256,7 +282,11 @@ extractImage() { fi rm -rf "$dir" - 7z x "$iso" -o"$dir" > /dev/null + + if ! 7z x "$iso" -o"$dir" > /dev/null; then + error "Failed to extract ISO file!" + exit 66 + fi if [ ! -f "$dir/$ETFS" ] || [ ! -f "$dir/$EFISYS" ]; then @@ -266,11 +296,10 @@ extractImage() { warn "failed to locate file 'efisys_noprompt.bin' in ISO image, $FB" fi + BOOT_MODE="windows_legacy" return 1 fi - [ -z "$CUSTOM" ] && rm -f "$iso" - return 0 } @@ -285,22 +314,30 @@ findVersion() { [[ "${name,,}" == *"server 2022"* ]] && detected="win2022-eval" [[ "${name,,}" == *"server 2019"* ]] && detected="win2019-eval" [[ "${name,,}" == *"server 2016"* ]] && detected="win2016-eval" + [[ "${name,,}" == *"windows 7"* ]] && detected="win7x64-ultimate" echo "$detected" return 0 } -selectXML() { +detectImage() { local dir="$1" - local tag result name name2 detected + local tag result name name2 XML="" - [[ "$MANUAL" == [Yy1]* ]] && return 0 + DETECTED="" if [[ "$EXTERNAL" != [Yy1]* ]] && [ -z "$CUSTOM" ]; then - XML="$VERSION.xml" - [ -f "/run/assets/$XML" ] && return 0 + DETECTED="$VERSION" + if [[ "$MANUAL" != [Yy1]* ]]; then + if [ -f "/run/assets/$DETECTED.xml" ]; then + XML="$DETECTED.xml" + else + warn "image type is '$DETECTED', but no matching XML file exists, $FB." + fi + fi + return 0 fi info "Detecting Windows version from ISO image..." @@ -310,53 +347,71 @@ selectXML() { if [ ! -f "$loc" ]; then warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" - return 0 + BOOT_MODE="windows_legacy" + return 1 fi tag="DISPLAYNAME" result=$(wimlib-imagex info -xml "$loc" | tr -d '\000') name=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$result") - detected=$(findVersion "$name") + DETECTED=$(findVersion "$name") - if [ -z "$detected" ]; then + if [ -z "$DETECTED" ]; then tag="PRODUCTNAME" name2=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$result") [ -z "$name" ] && name="$name2" - detected=$(findVersion "$name2") + DETECTED=$(findVersion "$name2") fi - if [ -n "$detected" ]; then + if [ -n "$DETECTED" ]; then - if [ -f "/run/assets/$detected.xml" ]; then - XML="$detected.xml" - echo "Detected image of type '$detected', which supports automatic installation." + if [ -f "/run/assets/$DETECTED.xml" ]; then + [[ "$MANUAL" != [Yy1]* ]] && XML="$DETECTED.xml" + info "Detected image of type: '$DETECTED'" else - warn "detected image of type '$detected', but no matching XML file exists, $FB." + warn "detected image of type '$DETECTED', but no matching XML file exists, $FB." fi else if [ -z "$name" ]; then - warn "failed to detect Windows version from image, $FB" + warn "failed to determine Windows version from image, $FB" else - if [[ "${name,,}" == "windows 7" ]]; then - warn "detected Windows 7 image, $FB" - else - warn "failed to detect Windows version from string '$name', $FB" - fi + warn "failed to determine Windows version from string '$name', $FB" fi fi +} + +prepareImage() { + + local iso="$1" + local dir="$2" + + [[ "${DETECTED,,}" != "win7x64"* ]] && return 0 + + ETFS="boot.img" + BOOT_MODE="windows_legacy" + + local len offset + len=$(isoinfo -d -i "$iso" | grep "Nsect " | grep -o "[^ ]*$") + offset=$(isoinfo -d -i "$iso" | grep "Bootoff " | grep -o "[^ ]*$") + + if ! dd "if=$iso" "of=$dir/$ETFS" bs=2048 "count=$len" "skip=$offset" status=none; then + error "Failed to extract boot image from ISO!" + exit 67 + fi return 0 } updateImage() { - local dir="$1" - local asset="$2" + local iso="$1" + local dir="$2" + local asset="/run/assets/$3" local index result [ ! -f "$asset" ] && return 0 @@ -367,7 +422,8 @@ updateImage() { if [ ! -f "$loc" ]; then warn "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" - return 0 + BOOT_MODE="windows_legacy" + return 1 fi info "Adding XML file for automatic installation..." @@ -379,7 +435,10 @@ updateImage() { index="2" fi - wimlib-imagex update "$loc" "$index" --command "add $asset /autounattend.xml" > /dev/null + if ! wimlib-imagex update "$loc" "$index" --command "add $asset /autounattend.xml" > /dev/null; then + warn "failed to add XML to ISO image, $FB" + return 1 + fi return 0 } @@ -389,6 +448,7 @@ buildImage() { local dir="$1" local cat="BOOT.CAT" local label="${BASE%.*}" + local log="/run/shm/iso.log" local size size_gb space space_gb label="${label::30}" @@ -404,16 +464,37 @@ buildImage() { space_gb=$(( (space + 1073741823)/1073741824 )) if (( size > space )); then - error "Not enough free space in $STORAGE, have $space_gb GB available but need at least $size_gb GB." && exit 63 + error "Not enough free space in $STORAGE, have $space_gb GB available but need at least $size_gb GB." + return 1 fi - genisoimage -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -quiet -V "$label" -udf \ - -boot-info-table -eltorito-alt-boot -eltorito-boot "$EFISYS" -no-emul-boot -o "$out" -allow-limited-size "$dir" + if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then - [ -n "$CUSTOM" ] && rm -f "$STORAGE/$CUSTOM" + if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -V "$label" \ + -udf -boot-info-table -eltorito-alt-boot -eltorito-boot "$EFISYS" -no-emul-boot -allow-limited-size -quiet "$dir" 2> "$log"; then + [ -f "$log" ] && echo "$(<"$log")" + return 1 + fi + + else + + if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 2 -J -l -D -N -joliet-long -relaxed-filenames -V "$label" \ + -udf -allow-limited-size -quiet "$dir" 2> "$log"; then + [ -f "$log" ] && echo "$(<"$log")" + return 1 + fi + + fi + + local error="" + local hide="Warning: creating filesystem that does not conform to ISO-9660." + + [ -f "$log" ] && error="$(<"$log")" + [[ "$error" != "$hide" ]] && echo "$error" if [ -f "$STORAGE/$BASE" ]; then - error "File $STORAGE/$BASE does already exist ?!" && exit 64 + error "File $STORAGE/$BASE does already exist?!" + return 1 fi mv "$out" "$STORAGE/$BASE" @@ -423,30 +504,48 @@ buildImage() { ###################################### if ! startInstall; then + + if [ -f "$STORAGE/windows.old" ]; then + BOOT_MODE="windows_legacy" + fi + rm -rf "$TMP" return 0 fi if [ ! -f "$ISO" ]; then - downloadImage "$ISO" "$VERSION" + if ! downloadImage "$ISO" "$VERSION"; then + error "Failed to download $VERSION" + exit 61 + fi fi if ! extractImage "$ISO" "$DIR"; then - - if [[ "$ISO" != "$STORAGE/$BASE" ]]; then - mv -f "$ISO" "$STORAGE/$BASE" - fi - - finishInstall "$STORAGE/$BASE" + abortInstall "$ISO" return 0 - fi -selectXML "$DIR" +if ! detectImage "$DIR"; then + abortInstall "$ISO" + return 0 +fi -updateImage "$DIR" "/run/assets/$XML" +if ! prepareImage "$ISO" "$DIR"; then + abortInstall "$ISO" + return 0 +fi -buildImage "$DIR" +if ! updateImage "$ISO" "$DIR" "$XML"; then + abortInstall "$ISO" + return 0 +fi + +rm -f "$ISO" + +if ! buildImage "$DIR"; then + error "Failed to build image!" + exit 65 +fi finishInstall "$STORAGE/$BASE" diff --git a/src/power.sh b/src/power.sh index 74f5d0d..e7f9b97 100644 --- a/src/power.sh +++ b/src/power.sh @@ -116,14 +116,15 @@ _graceful_shutdown() { finish "$code" && return "$code" fi - if [ ! -f "$STORAGE/windows.boot" ] && [ -f "$QEMU_PTY" ]; then - if ! grep -Fq "Windows Boot Manager" "$QEMU_PTY"; then - info "Cannot send ACPI signal during Windows setup, aborting..." - finish "$code" && return "$code" - else - if [ -f "$STORAGE/$BASE" ]; then - rm -f "$STORAGE/$BASE" - touch "$STORAGE/windows.boot" + local remove_iso="" + + if [ ! -f "$STORAGE/windows.old" ]; then + if [ ! -f "$STORAGE/windows.boot" ] && [ -f "$QEMU_PTY" ]; then + if grep -Fq "Windows Boot Manager" "$QEMU_PTY"; then + [ -f "$STORAGE/$BASE" ] && remove_iso="y" + else + info "Cannot send ACPI signal during Windows setup, aborting..." + finish "$code" && return "$code" fi fi fi @@ -150,6 +151,11 @@ _graceful_shutdown() { if [ "$cnt" -ge "$QEMU_TIMEOUT" ]; then error "Shutdown timeout reached, aborting..." + else + if [ -n "$remove_iso" ]; then + rm -f "$STORAGE/$BASE" + touch "$STORAGE/windows.boot" + fi fi finish "$code" && return "$code"