From 0616eb344780587398f2ba29de171d70ec9dcd95 Mon Sep 17 00:00:00 2001 From: Kroese Date: Sat, 4 May 2024 13:28:12 +0200 Subject: [PATCH] feat: Improved installation (#453) --- .github/workflows/check.yml | 2 +- Dockerfile | 7 +- assets/win7x64.xml | 6 +- assets/winvistax64.xml | 6 +- readme.md | 117 +++-- src/define.sh | 892 +++++++++++++++++++++++------------- src/install.sh | 529 ++++++++++++--------- src/mido.sh | 2 +- src/power.sh | 6 +- src/samba.sh | 1 + 10 files changed, 955 insertions(+), 613 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index ea76481..2c1ce5a 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -21,5 +21,5 @@ jobs: uses: hadolint/hadolint-action@v3.1.0 with: dockerfile: Dockerfile - ignore: DL3008,DL4006,SC3037 + ignore: DL3008 failure-threshold: warning diff --git a/Dockerfile b/Dockerfile index 5334813..4184a68 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM scratch -COPY --from=qemux/qemu-docker:4.27 / / +COPY --from=qemux/qemu-docker:5.00 / / ARG DEBCONF_NOWARNINGS "yes" ARG DEBIAN_FRONTEND "noninteractive" @@ -12,14 +12,11 @@ RUN apt-get update && \ 7zip \ wsdd \ samba \ + wimtools \ dos2unix \ cabextract \ genisoimage \ libxml2-utils && \ - echo "deb http://deb.debian.org/debian/ sid main" >> /etc/apt/sources.list.d/sid.list && \ - echo -e "Package: *\nPin: release n=trixie\nPin-Priority: 900\nPackage: *\nPin: release n=sid\nPin-Priority: 400" | tee /etc/apt/preferences.d/preferences > /dev/null && \ - apt-get update && \ - apt-get -t sid --no-install-recommends -y install wimtools && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* diff --git a/assets/win7x64.xml b/assets/win7x64.xml index e0ae7e0..29c0ab7 100644 --- a/assets/win7x64.xml +++ b/assets/win7x64.xml @@ -52,8 +52,8 @@ - 1 - /IMAGE/INDEX + Windows 7 PROFESSIONAL + /IMAGE/NAME @@ -76,7 +76,7 @@ Docker Windows for Docker - H7X92-3VPBB-Q799D-Y6JJ3-86WC6 + HYF8J-CVRMY-CM74G-RPHKF-PW487 OnError diff --git a/assets/winvistax64.xml b/assets/winvistax64.xml index b613f6f..252e6ae 100644 --- a/assets/winvistax64.xml +++ b/assets/winvistax64.xml @@ -51,7 +51,7 @@ - Windows Vista Ultimate + Windows Vista BUSINESS /IMAGE/NAME @@ -68,7 +68,7 @@ Docker Windows for Docker - VMCB9-FDRV6-6CDQM-RV23K-RP8F7 + 4D2XH-PRBMM-8Q22B-K8BM3-MRW4W @@ -100,7 +100,7 @@ * - VMCB9-FDRV6-6CDQM-RV23K-RP8F7 + 4D2XH-PRBMM-8Q22B-K8BM3-MRW4W Pacific Standard Time Dockur diff --git a/readme.md b/readme.md index b0510f2..c894f80 100644 --- a/readme.md +++ b/readme.md @@ -88,7 +88,7 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ | `win81` | Windows 8.1 Pro | 4.2 GB | | `win81e` | Windows 8.1 Enterprise | 3.8 GB | | `win7` | Windows 7 Enterprise | 3.0 GB | - | `vista` | Windows Vista Ultimate | 3.6 GB | + | `vista` | Windows Vista Enterprise | 3.0 GB | | `winxp` | Windows XP Professional | 0.6 GB | |||| | `2022` | Windows Server 2022 | 4.7 GB | @@ -103,37 +103,6 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ To install ARM64 versions of Windows use [dockur/windows-arm](https://github.com/dockur/windows-arm/). -* ### How do I connect using RDP? - - The web-viewer is mainly meant to be used during installation, as its picture quality is low, and it has no audio or clipboard for example. - - So for a better experience you can connect using any Microsoft Remote Desktop client to the IP of the container, using the username `docker` and by leaving the password empty. - - There is a good RDP client for [Android](https://play.google.com/store/apps/details?id=com.microsoft.rdc.androidx) available from the Play Store and one for [iOS](https://apps.apple.com/nl/app/microsoft-remote-desktop/id714464092?l=en-GB) in the Apple Store. For Linux you can use [FreeRDP](https://www.freerdp.com/) and on Windows just type `mstsc` in the search box. - -* ### 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. - - To increase this, add the following environment variables: - - ```yaml - environment: - RAM_SIZE: "8G" - CPU_CORES: "4" - ``` - -* ### How do I change the size of the disk? - - To expand the default size of 64 GB, add the `DISK_SIZE` setting to your compose file and set it to your preferred capacity: - - ```yaml - environment: - DISK_SIZE: "256G" - ``` - - This can also be used to resize the existing disk to a larger capacity without any data loss. - * ### How do I change the storage location? To change the storage location, include the following bind mount in your compose file: @@ -145,40 +114,53 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ Replace the example path `/var/win` with the desired storage folder. +* ### How do I change the size of the disk? + + To expand the default size of 64 GB, add the `DISK_SIZE` setting to your compose file and set it to your preferred capacity: + + ```yaml + environment: + DISK_SIZE: "256G" + ``` + + This can also be used to resize the existing disk to a larger capacity without any data loss. + * ### How do I share files with the host? - Open File Explorer and click on the Network section, you will see a computer called `host.lan`, double-click it and it will show a folder called `Data`. + Open 'File Explorer' and click on the 'Network' section, you will see a computer called `host.lan`, double-click it and it will show a folder called `Data`. - Inside this folder you can access any files that are placed in `/storage/shared` (see above) on the host. + Inside this folder you can access any files that are placed in `/storage/shared` (see above) on the host. You can optionally map it to a drive letter, for easy access. * ### How do I install a custom image? - In order to download a custom ISO image, start a fresh container with the URL of the ISO specified in the `VERSION` environment variable: + In order to download any ISO image that is not part of the list above, start a fresh container with the URL of that ISO specified in the `VERSION` environment variable, for example: ```yaml environment: VERSION: "https://example.com/win.iso" ``` - Alternatively, you can also use a local file directly, and skip the download, by binding it in your compose file in this way: + Alternatively, you can also use a local file directly, and skip the download altogether, by binding it in your compose file in this way: ```yaml volumes: - /home/user/example.iso:/storage/custom.iso ``` - Replace the example path `/home/user/example.iso` with the filename of the desired ISO file. The value of `VERSION` will be ignored in this case. + Replace the example path `/home/user/example.iso` with the filename of your desired ISO file. The value of `VERSION` will be ignored in this case. * ### How do I customize the installation? - You can customize every setting used by the automatic installation. Download the XML file corresponding to your Windows version, for example [win11x64.xml](https://raw.githubusercontent.com/dockur/windows/master/assets/win11x64.xml). Then apply your modifications to it, and add this line to your compose file: + If you want to modify the settings used during the automatic installation, you can do this by editing the answer file corresponding to your Windows edition, for example [win11x64.xml](https://raw.githubusercontent.com/dockur/windows/master/assets/win11x64.xml) in the case of Windows 11 Pro. + + Apply your modifications to it, and add this line to your compose file: ```yaml volumes: - - /home/user/custom.xml:/run/assets/win11x64.xml + - /home/user/example.xml:/storage/custom.xml ``` - Replace the example path `/home/user/custom.xml` with the filename of the modified XML file. + Replace the example path `/home/user/example.xml` with the filename of the modified XML file. * ### How do I run a script after installation? @@ -189,7 +171,7 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ - /home/user/example:/storage/oem ``` - The example path `/home/user/example` will be copied to `C:\OEM` during installation and the containing `install.bat` will be executed. + The example folder `/home/user/example` will be copied to `C:\OEM` during installation and the containing `install.bat` will be executed during the last step. * ### How do I perform a manual installation? @@ -219,6 +201,37 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ - Once you see the desktop, open File Explorer and navigate to the CD-ROM drive (E:). Double-click on `virtio-win-gt-x64.msi` and proceed to install the VirtIO drivers. Enjoy your brand new machine, and don't forget to star this repo! + +* ### How do I verify if my system supports KVM? + + To verify if your system supports KVM, run the following commands: + + ```bash + sudo apt install cpu-checker + sudo kvm-ok + ``` + + If you receive an error from `kvm-ok` indicating that KVM acceleration can't be used, check the virtualization settings in the BIOS. + +* ### 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. + + If there arises a need to increase this, add the following environment variables: + + ```yaml + environment: + RAM_SIZE: "8G" + CPU_CORES: "4" + ``` + +* ### How do I connect using RDP? + + The web-viewer is mainly meant to be used during installation, as its picture quality is low, and it has no audio or clipboard for example. + + So for a better experience you can connect using any Microsoft Remote Desktop client to the IP of the container, using the username `docker` and by leaving the password empty. + + There is a good RDP client for [Android](https://play.google.com/store/apps/details?id=com.microsoft.rdc.androidx) available from the Play Store and one for [iOS](https://apps.apple.com/nl/app/microsoft-remote-desktop/id714464092?l=en-GB) in the Apple Store. For Linux you can use [FreeRDP](https://www.freerdp.com/) and on Windows just type `mstsc` in the search box. * ### How do I assign an individual IP address to the container? @@ -272,21 +285,18 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ ``` Please note that in this mode, the container and Windows will each have their own separate IPs. The container will keep the macvlan IP, and Windows will use the DHCP IP. - + * ### How do I pass-through a disk? It is possible to pass-through disk devices directly by adding them to your compose file in this way: ```yaml - environment: - DEVICE: "/dev/sda" - DEVICE2: "/dev/sdb" devices: - - /dev/sda - - /dev/sdb + - /dev/sdb:/dev/disk1 + - /dev/sdc:/dev/disk2 ``` - Use `DEVICE` if you want it to become your main drive, and use `DEVICE2` and higher to add them as secondary drives. + Use `/dev/disk1` if you want it to become your main drive, and use `/dev/disk2` and higher to add them as secondary drives. * ### How do I pass-through a USB device? @@ -298,17 +308,6 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_ devices: - /dev/bus/usb ``` - -* ### How do I verify if my system supports KVM? - - To verify if your system supports KVM, run the following commands: - - ```bash - sudo apt install cpu-checker - sudo kvm-ok - ``` - - If you receive an error from `kvm-ok` indicating that KVM acceleration can't be used, check the virtualization settings in the BIOS. * ### Is this project legal? diff --git a/src/define.sh b/src/define.sh index 518e405..cd0e104 100644 --- a/src/define.sh +++ b/src/define.sh @@ -1,11 +1,14 @@ #!/usr/bin/env bash set -Eeuo pipefail +: "${VERIFY:=""}" : "${MANUAL:=""}" : "${VERSION:=""}" : "${DETECTED:=""}" : "${PLATFORM:="x64"}" +MIRRORS=5 + parseVersion() { [ -z "$VERSION" ] && VERSION="win11" @@ -15,64 +18,74 @@ parseVersion() { fi case "${VERSION,,}" in - "11" | "win11" | "windows11" | "windows 11") + "11" | "win11" | "windows11" | "windows 11" ) VERSION="win11${PLATFORM,,}" ;; - "11e" | "win11e" | "windows11e" | "windows 11e") + "11e" | "win11e" | "windows11e" | "windows 11e" ) VERSION="win11${PLATFORM,,}-enterprise-eval" ;; - "10" | "win10" | "windows10" | "windows 10") + "10" | "win10" | "windows10" | "windows 10" ) VERSION="win10${PLATFORM,,}" ;; - "10e" | "win10e" | "windows10e" | "windows 10e") + "10e" | "win10e" | "windows10e" | "windows 10e" ) VERSION="win10${PLATFORM,,}-enterprise-eval" ;; - "8" | "81" | "8.1" | "win8" | "win81" | "windows 8" | "windows 8.1") + "8" | "81" | "8.1" | "win8" | "win81" | "windows 8" ) VERSION="win81${PLATFORM,,}" ;; - "8e" | "81e" | "8.1e" | "win8e" | "win81e" | "windows8e" | "windows 8e") + "8e" | "81e" | "8.1e" | "win8e" | "win81e" | "windows 8e" ) VERSION="win81${PLATFORM,,}-enterprise-eval" ;; - "7" | "7e" | "win7" | "win7e" | "windows7" | "windows 7") + "7" | "7e" | "win7" | "win7e" | "windows7" | "windows 7" ) VERSION="win7${PLATFORM,,}" DETECTED="win7${PLATFORM,,}-enterprise" ;; - "vista" | "winvista" | "windowsvista" | "windows vista") + "vista" | "winvista" | "windowsvista" | "windows vista" ) VERSION="winvista${PLATFORM,,}" - DETECTED="winvista${PLATFORM,,}-ultimate" + DETECTED="winvista${PLATFORM,,}-enterprise" ;; - "xp" | "winxp" | "windowsxp" | "windows xp") + "xp" | "xp32" | "winxp" | "windowsxp" | "windows xp" ) VERSION="winxpx86" ;; - "xp64" | "winxp64" | "windowsxp64") + "xp64" | "winxp64" | "windowsxp64" | "windows xp 64" ) VERSION="winxpx64" ;; - "22" | "2022" | "win22" | "win2022" | "windows2022" | "windows 2022") + "22" | "2022" | "win22" | "win2022" | "windows2022" | "windows 2022" ) VERSION="win2022-eval" ;; - "19" | "2019" | "win19" | "win2019" | "windows2019" | "windows 2019") + "19" | "2019" | "win19" | "win2019" | "windows2019" | "windows 2019" ) VERSION="win2019-eval" ;; - "16" | "2016" | "win16" | "win2016" | "windows2016" | "windows 2016") + "16" | "2016" | "win16" | "win2016" | "windows2016" | "windows 2016" ) VERSION="win2016-eval" ;; - "2012" | "2012r2" | "win2012" | "win2012r2" | "windows2012" | "windows 2012") + "2012" | "2012r2" | "win2012" | "win2012r2" | "windows2012" | "windows 2012" ) VERSION="win2012r2-eval" ;; - "2008" | "2008r2" | "win2008" | "win2008r2" | "windows2008" | "windows 2008") + "2008" | "2008r2" | "win2008" | "win2008r2" | "windows2008" | "windows 2008" ) VERSION="win2008r2" ;; - "core11" | "core 11" | "tiny11" | "tiny 11") + "core11" | "core 11" ) + VERSION="core11" DETECTED="win11${PLATFORM,,}" ;; - "tiny10" | "tiny 10") + "tiny11" | "tiny 11" ) + VERSION="tiny11" + DETECTED="win11${PLATFORM,,}" + ;; + "tiny10" | "tiny 10" ) + VERSION="tiny10" DETECTED="win10${PLATFORM,,}-ltsc" ;; - "iot10" | "10iot" | "win10-iot" | "win10${PLATFORM,,}-iot" | "win10${PLATFORM,,}-enterprise-iot-eval") + "iot11" | "11iot" | "win11-iot" | "win11${PLATFORM,,}-iot" | "win11${PLATFORM,,}-enterprise-iot-eval" ) + DETECTED="win11${PLATFORM,,}-iot" + VERSION="win11${PLATFORM,,}-enterprise-iot-eval" + ;; + "iot10" | "10iot" | "win10-iot" | "win10${PLATFORM,,}-iot" | "win10${PLATFORM,,}-enterprise-iot-eval" ) DETECTED="win10${PLATFORM,,}-iot" VERSION="win10${PLATFORM,,}-enterprise-iot-eval" ;; - "ltsc10" | "10ltsc" | "win10-ltsc" | "win10${PLATFORM,,}-ltsc" | "win10${PLATFORM,,}-enterprise-ltsc-eval") + "ltsc10" | "10ltsc" | "win10-ltsc" | "win10${PLATFORM,,}-ltsc" | "win10${PLATFORM,,}-enterprise-ltsc-eval" ) DETECTED="win10${PLATFORM,,}-ltsc" VERSION="win10${PLATFORM,,}-enterprise-ltsc-eval" ;; @@ -86,157 +99,262 @@ printVersion() { local id="$1" local desc="$2" - [[ "$id" == "win7"* ]] && desc="Windows 7" - [[ "$id" == "win8"* ]] && desc="Windows 8" - [[ "$id" == "win10"* ]] && desc="Windows 10" - [[ "$id" == "win11"* ]] && desc="Windows 11" - [[ "$id" == "winxp"* ]] && desc="Windows XP" - [[ "$id" == "winvista"* ]] && desc="Windows Vista" + case "${id,,}" in + "tiny11"* ) desc="Tiny 11" ;; + "tiny10"* ) desc="Tiny 10" ;; + "core11"* ) desc="Core 11" ;; + "win7"* ) desc="Windows 7" ;; + "win8"* ) desc="Windows 8" ;; + "win10"* ) desc="Windows 10" ;; + "win11"* ) desc="Windows 11" ;; + "winxp"* ) desc="Windows XP" ;; + "winvista"* ) desc="Windows Vista" ;; + "win2025"* ) desc="Windows Server 2025" ;; + "win2022"* ) desc="Windows Server 2022" ;; + "win2019"* ) desc="Windows Server 2019" ;; + "win2016"* ) desc="Windows Server 2016" ;; + "win2012"* ) desc="Windows Server 2012" ;; + "win2008"* ) desc="Windows Server 2008" ;; + esac - [[ "$id" == "win2025"* ]] && desc="Windows Server 2025" - [[ "$id" == "win2022"* ]] && desc="Windows Server 2022" - [[ "$id" == "win2019"* ]] && desc="Windows Server 2019" - [[ "$id" == "win2016"* ]] && desc="Windows Server 2016" - [[ "$id" == "win2012"* ]] && desc="Windows Server 2012" - [[ "$id" == "win2008"* ]] && desc="Windows Server 2008" - - [ -z "$desc" ] && desc="Windows" + if [ -z "$desc" ]; then + desc="Windows" + [[ "${PLATFORM,,}" != "x64" ]] && desc="$desc for ${PLATFORM}" + fi echo "$desc" return 0 } -getName() { +printEdition() { - local file="$1" + local id="$1" local desc="$2" + local result="" + local edition="" - [[ "${file,,}" == "win11"* ]] && desc="Windows 11" - [[ "${file,,}" == "win10"* ]] && desc="Windows 10" - [[ "${file,,}" == "win8"* ]] && desc="Windows 8" - [[ "${file,,}" == "win7"* ]] && desc="Windows 7" - [[ "${file,,}" == "winxp"* ]] && desc="Windows XP" - [[ "${file,,}" == "winvista"* ]] && desc="Windows Vista" - [[ "${file,,}" == "tiny10"* ]] && desc="Tiny 10" - [[ "${file,,}" == "tiny11"* ]] && desc="Tiny 11" - [[ "${file,,}" == "tiny11_core"* ]] && desc="Tiny 11 Core" - [[ "${file,,}" == *"windows11"* ]] && desc="Windows 11" - [[ "${file,,}" == *"windows10"* ]] && desc="Windows 10" - [[ "${file,,}" == *"windows8"* ]] && desc="Windows 8" - [[ "${file,,}" == *"windows7"* ]] && desc="Windows 7" - [[ "${file,,}" == *"windowsxp"* ]] && desc="Windows XP" - [[ "${file,,}" == *"windowsvista"* ]] && desc="Windows Vista" - [[ "${file,,}" == *"windows_11"* ]] && desc="Windows 11" - [[ "${file,,}" == *"windows_10"* ]] && desc="Windows 10" - [[ "${file,,}" == *"windows_8"* ]] && desc="Windows 8" - [[ "${file,,}" == *"windows_7"* ]] && desc="Windows 7" - [[ "${file,,}" == *"windows_xp"* ]] && desc="Windows XP" - [[ "${file,,}" == *"windows_vista"* ]] && desc="Windows Vista" - [[ "${file,,}" == *"windows 11"* ]] && desc="Windows 11" - [[ "${file,,}" == *"windows 10"* ]] && desc="Windows 10" - [[ "${file,,}" == *"windows 8"* ]] && desc="Windows 8" - [[ "${file,,}" == *"windows 7"* ]] && desc="Windows 7" - [[ "${file,,}" == *"windows xp"* ]] && desc="Windows XP" - [[ "${file,,}" == *"windows vista"* ]] && desc="Windows Vista" - [[ "${file,,}" == *"server2008"* ]] && desc="Windows Server 2008" - [[ "${file,,}" == *"server2012"* ]] && desc="Windows Server 2012" - [[ "${file,,}" == *"server2016"* ]] && desc="Windows Server 2016" - [[ "${file,,}" == *"server2019"* ]] && desc="Windows Server 2019" - [[ "${file,,}" == *"server2022"* ]] && desc="Windows Server 2022" - [[ "${file,,}" == *"server2025"* ]] && desc="Windows Server 2025" - [[ "${file,,}" == *"server_2008"* ]] && desc="Windows Server 2008" - [[ "${file,,}" == *"server_2012"* ]] && desc="Windows Server 2012" - [[ "${file,,}" == *"server_2016"* ]] && desc="Windows Server 2016" - [[ "${file,,}" == *"server_2019"* ]] && desc="Windows Server 2019" - [[ "${file,,}" == *"server_2022"* ]] && desc="Windows Server 2022" - [[ "${file,,}" == *"server_2025"* ]] && desc="Windows Server 2025" - [[ "${file,,}" == *"server 2008"* ]] && desc="Windows Server 2008" - [[ "${file,,}" == *"server 2012"* ]] && desc="Windows Server 2012" - [[ "${file,,}" == *"server 2016"* ]] && desc="Windows Server 2016" - [[ "${file,,}" == *"server 2019"* ]] && desc="Windows Server 2019" - [[ "${file,,}" == *"server 2022"* ]] && desc="Windows Server 2022" - [[ "${file,,}" == *"server 2025"* ]] && desc="Windows Server 2025" + result=$(printVersion "$id" "x") + [[ "$result" == "x" ]] && echo "$desc" && return 0 - [ -z "$desc" ] && desc="Windows" + case "${id,,}" in + "win7${PLATFORM,,}-home"* ) + edition="Home" + ;; + "win7${PLATFORM,,}-starter"* ) + edition="Starter" + ;; + "win7${PLATFORM,,}-ultimate"* ) + edition="Ultimate" + ;; + "win7${PLATFORM,,}-enterprise"* ) + edition="Enterprise" + ;; + "win7"* ) + edition="Professional" + ;; + "win8${PLATFORM,,}-enterprise"* ) + edition="Enterprise" + ;; + "win8"* ) + edition="Pro" + ;; + "win10${PLATFORM,,}-iot"* ) + edition="IoT" + ;; + "win10${PLATFORM,,}-ltsc"* ) + edition="LTSC" + ;; + "win10${PLATFORM,,}-home"* ) + edition="Home" + ;; + "win10${PLATFORM,,}-education"* ) + edition="Education" + ;; + "win10${PLATFORM,,}-enterprise"* ) + edition="Enterprise" + ;; + "win10"* ) + edition="Pro" + ;; + "win11${PLATFORM,,}-iot"* ) + edition="IoT" + ;; + "win11${PLATFORM,,}-home"* ) + edition="Home" + ;; + "win11${PLATFORM,,}-education"* ) + edition="Education" + ;; + "win11${PLATFORM,,}-enterprise"* ) + edition="Enterprise" + ;; + "win11"* ) + edition="Pro" + ;; + "winxp"* ) + edition="Professional" + ;; + "winvista${PLATFORM,,}-home"* ) + edition="Home" + ;; + "winvista${PLATFORM,,}-starter"* ) + edition="Starter" + ;; + "winvista${PLATFORM,,}-ultimate"* ) + edition="Ultimate" + ;; + "winvista${PLATFORM,,}-enterprise"* ) + edition="Enterprise" + ;; + "winvista"* ) + edition="Business" + ;; + "win2025"* | "win2022"* | "win2019"* | "win2016"* | "win2012"* | "win2008"* ) + edition="Standard" + ;; + esac + + [[ "${id,,}" == *"-eval" ]] && edition="$edition (Evaluation)" + [ -n "$edition" ] && result="$result $edition" + + echo "$result" + return 0 +} + +fromFile() { + + local id="" + local desc="$1" + local file="${1,,}" + + case "${file/ /_}" in + "win7"* | "win_7"* | *"windows7"* | *"windows_7"* ) + id="win7${PLATFORM,,}" + ;; + "win8"* | "win_8"* | *"windows8"* | *"windows_8"* ) + id="win81${PLATFORM,,}" + ;; + "win10"*| "win_10"* | *"windows10"* | *"windows_10"* ) + id="win10${PLATFORM,,}" + ;; + "win11"* | "win_11"* | *"windows11"* | *"windows_11"* ) + id="win11${PLATFORM,,}" + ;; + *"winxp"* | *"win_xp"* | *"windowsxp"* | *"windows_xp"* ) + id="winxpx86" + ;; + *"winvista"* | *"win_vista"* | *"windowsvista"* | *"windows_vista"* ) + id="winvista${PLATFORM,,}" + ;; + "tiny11core"* | "tiny11_core"* | "tiny_11_core"* ) + id="core11" + ;; + "tiny11"* | "tiny_11"* ) + id="tiny11" + ;; + "tiny10"* | "tiny_10"* ) + id="tiny10" + ;; + *"server2025"* | *"server_2025"* ) + id="win2025" + ;; + *"server2022"* | *"server_2022"* ) + id="win2022" + ;; + *"server2019"* | *"server_2019"* ) + id="win2019" + ;; + *"server2016"* | *"server_2016"* ) + id="win2016" + ;; + *"server2012"* | *"server_2012"* ) + id="win2012r2" + ;; + *"server2008"* | *"server_2008"* ) + id="win2008r2" + ;; + esac + + if [ -n "$id" ]; then + desc=$(printVersion "$id" "$desc") + fi echo "$desc" return 0 } +fromName() { + + local id="" + local name="$1" + + case "${name,,}" in + *"server 2025"* ) id="win2025" ;; + *"server 2022"* ) id="win2022" ;; + *"server 2019"* ) id="win2019" ;; + *"server 2016"* ) id="win2016" ;; + *"server 2012"* ) id="win2012r2" ;; + *"server 2008"* ) id="win2008r2" ;; + *"windows 7"* ) id="win7${PLATFORM,,}" ;; + *"windows 8"* ) id="win81${PLATFORM,,}" ;; + *"windows 10"* ) id="win10${PLATFORM,,}" ;; + *"windows 11"* ) id="win11${PLATFORM,,}" ;; + *"windows vista"* ) id="winvista${PLATFORM,,}" ;; + esac + + echo "$id" + return 0 +} + getVersion() { + local id local name="$1" - local detected="" - if [[ "${name,,}" == *"windows 7"* ]]; then - detected="win7${PLATFORM,,}" - [[ "${name,,}" == *"ultimate"* ]] && detected="win7${PLATFORM,,}-ultimate" - [[ "${name,,}" == *"enterprise"* ]] && detected="win7${PLATFORM,,}-enterprise" - fi + id=$(fromName "$name") - if [[ "${name,,}" == *"windows vista"* ]]; then - detected="winvista${PLATFORM,,}" - [[ "${name,,}" == *"ultimate"* ]] && detected="winvista${PLATFORM,,}-ultimate" - [[ "${name,,}" == *"enterprise"* ]] && detected="winvista${PLATFORM,,}-enterprise" - fi + case "${id,,}" in + "win7"* | "winvista"* ) + case "${name,,}" in + *" home"* ) id="$id-home" ;; + *" starter"* ) id="$id-starter" ;; + *" ultimate"* ) id="$id-ultimate" ;; + *" enterprise"* ) id="$id-enterprise" ;; + esac + ;; + "win8"* ) + case "${name,,}" in + *" enterprise evaluation"* ) id="$id-enterprise-eval" ;; + *" enterprise"* ) id="$id-enterprise" ;; + esac + ;; + "win10"* ) + case "${name,,}" in + *" iot"* ) id="$id-iot" ;; + *" ltsc"* ) id="$id-ltsc" ;; + *" home"* ) id="$id-home" ;; + *" education"* ) id="$id-education" ;; + *" enterprise evaluation"* ) id="$id-enterprise-eval" ;; + *" enterprise"* ) id="$id-enterprise" ;; + esac + ;; + "win11"* ) + case "${name,,}" in + *" iot"* ) id="$id-iot" ;; + *" home"* ) id="$id-home" ;; + *" education"* ) id="$id-education" ;; + *" enterprise evaluation"* ) id="$id-enterprise-eval" ;; + *" enterprise"* ) id="$id-enterprise" ;; + esac + ;; + "win2025"* | "win2022"* | "win2019"* | "win2016"* | "win2012"* | "win2008"* ) + case "${name,,}" in + *" evaluation"* ) id="$id-eval" ;; + esac + ;; + esac - if [[ "${name,,}" == *"server 2025"* ]]; then - detected="win2025" - [[ "${name,,}" == *"evaluation"* ]] && detected="win2025-eval" - fi - - if [[ "${name,,}" == *"server 2022"* ]]; then - detected="win2022" - [[ "${name,,}" == *"evaluation"* ]] && detected="win2022-eval" - fi - - if [[ "${name,,}" == *"server 2019"* ]]; then - detected="win2019" - [[ "${name,,}" == *"evaluation"* ]] && detected="win2019-eval" - fi - - if [[ "${name,,}" == *"server 2016"* ]]; then - detected="win2016" - [[ "${name,,}" == *"evaluation"* ]] && detected="win2016-eval" - fi - - if [[ "${name,,}" == *"server 2012"* ]]; then - detected="win2012r2" - [[ "${name,,}" == *"evaluation"* ]] && detected="win2012r2-eval" - fi - - if [[ "${name,,}" == *"server 2008"* ]]; then - detected="win2008r2" - [[ "${name,,}" == *"evaluation"* ]] && detected="win2008r2-eval" - fi - - if [[ "${name,,}" == *"windows 8"* ]]; then - detected="win81${PLATFORM,,}" - [[ "${name,,}" == *"enterprise"* ]] && detected="win81${PLATFORM,,}-enterprise" - [[ "${name,,}" == *"enterprise evaluation"* ]] && detected="win81${PLATFORM,,}-enterprise-eval" - fi - - if [[ "${name,,}" == *"windows 11"* ]]; then - detected="win11${PLATFORM,,}" - [[ "${name,,}" == *"enterprise"* ]] && detected="win11${PLATFORM,,}-enterprise" - [[ "${name,,}" == *"enterprise evaluation"* ]] && detected="win11${PLATFORM,,}-enterprise-eval" - fi - - if [[ "${name,,}" == *"windows 10"* ]]; then - detected="win10${PLATFORM,,}" - if [[ "${name,,}" == *" iot "* ]]; then - detected="win10${PLATFORM,,}-iot" - else - if [[ "${name,,}" == *"ltsc"* ]]; then - detected="win10${PLATFORM,,}-ltsc" - else - [[ "${name,,}" == *"enterprise"* ]] && detected="win10${PLATFORM,,}-enterprise" - [[ "${name,,}" == *"enterprise evaluation"* ]] && detected="win10${PLATFORM,,}-enterprise-eval" - fi - fi - fi - - echo "$detected" + echo "$id" return 0 } @@ -245,30 +363,20 @@ switchEdition() { local id="$1" case "${id,,}" in - "win11${PLATFORM,,}-enterprise-eval") + "win11${PLATFORM,,}-enterprise-eval" ) DETECTED="win11${PLATFORM,,}-enterprise" ;; - "win10${PLATFORM,,}-enterprise-eval") + "win10${PLATFORM,,}-enterprise-eval" ) DETECTED="win10${PLATFORM,,}-enterprise" ;; - "win81${PLATFORM,,}-enterprise-eval") + "win81${PLATFORM,,}-enterprise-eval" ) DETECTED="win81${PLATFORM,,}-enterprise" ;; - "win2022-eval") - DETECTED="win2022" - ;; - "win2019-eval") - DETECTED="win2019" - ;; - "win2016-eval") - DETECTED="win2016" - ;; - "win2012r2-eval") - DETECTED="win2012r2" - ;; - "win2008r2-eval") - DETECTED="win2008r2" - ;; + "win2022-eval" ) DETECTED="win2022" ;; + "win2019-eval" ) DETECTED="win2019" ;; + "win2016-eval" ) DETECTED="win2016" ;; + "win2012r2-eval" ) DETECTED="win2012r2" ;; + "win2008r2-eval" ) DETECTED="win2008r2" ;; esac return 0 @@ -279,12 +387,8 @@ isESD() { local id="$1" case "${id,,}" in - "win11${PLATFORM,,}") - return 0 - ;; - "win10${PLATFORM,,}") - return 0 - ;; + "win11${PLATFORM,,}" ) return 0 ;; + "win10${PLATFORM,,}" ) return 0 ;; esac return 1 @@ -295,164 +399,319 @@ isMido() { local id="$1" case "${id,,}" in - "win11${PLATFORM,,}" | "win11${PLATFORM,,}-enterprise-eval") - return 0 - ;; - "win10${PLATFORM,,}" | "win10${PLATFORM,,}-enterprise-eval" | "win10${PLATFORM,,}-enterprise-ltsc-eval") - return 0 - ;; - "win81${PLATFORM,,}" | "win81${PLATFORM,,}-enterprise-eval") - return 0 - ;; - "win2022-eval" | "win2019-eval" | "win2016-eval" | "win2012r2-eval" | "win2008r2") - return 0 - ;; + "win11${PLATFORM,,}" | "win11${PLATFORM,,}-enterprise-eval" ) + return 0 ;; + "win10${PLATFORM,,}" | "win10${PLATFORM,,}-enterprise-eval" | "win10${PLATFORM,,}-enterprise-ltsc-eval" ) + return 0 ;; + "win81${PLATFORM,,}" | "win81${PLATFORM,,}-enterprise-eval" ) + return 0 ;; + "win2022-eval" | "win2019-eval" | "win2016-eval" | "win2012r2-eval" | "win2008r2" ) + return 0 ;; esac return 1 } -getLink() { +getLink1() { # Fallbacks for users who cannot connect to the Microsoft servers local id="$1" + local ret="$2" local url="" - local host="https://dl.bobpony.com" + local sum="" + local host="https://dl.bobpony.com/windows" case "${id,,}" in - "win11${PLATFORM,,}") - url="$host/windows/11/en-us_windows_11_23h2_${PLATFORM,,}.iso" + "win11${PLATFORM,,}" ) + sum="5bb1459034f50766ee480d895d751af73a4af30814240ae32ebc5633546a5af7" + url="$host/11/en-us_windows_11_23h2_${PLATFORM,,}.iso" ;; - "win10${PLATFORM,,}") - url="$host/windows/10/en-us_windows_10_22h2_${PLATFORM,,}.iso" + "win10${PLATFORM,,}" ) + sum="6673e2ab6c6939a74eceff2c2bb4d36feb94ff8a6f71700adef0f0b998fdcaca" + url="$host/10/en-us_windows_10_22h2_${PLATFORM,,}.iso" ;; - "win10${PLATFORM,,}-iot" | "win10${PLATFORM,,}-enterprise-iot-eval") - url="$host/windows/10/en-us_windows_10_iot_enterprise_ltsc_2021_${PLATFORM,,}_dvd_257ad90f.iso" + "win10${PLATFORM,,}-iot" | "win10${PLATFORM,,}-enterprise-iot-eval" ) + sum="a0334f31ea7a3e6932b9ad7206608248f0bd40698bfb8fc65f14fc5e4976c160" + url="$host/10/en-us_windows_10_iot_enterprise_ltsc_2021_${PLATFORM,,}_dvd_257ad90f.iso" ;; - "win10${PLATFORM,,}-ltsc" | "win10${PLATFORM,,}-enterprise-ltsc-eval") - url="$host/windows/10/en-us_windows_10_enterprise_ltsc_2021_${PLATFORM,,}_dvd_d289cf96.iso" + "win10${PLATFORM,,}-ltsc" | "win10${PLATFORM,,}-enterprise-ltsc-eval" ) + sum="c90a6df8997bf49e56b9673982f3e80745058723a707aef8f22998ae6479597d" + url="$host/10/en-us_windows_10_enterprise_ltsc_2021_${PLATFORM,,}_dvd_d289cf96.iso" ;; - "win81${PLATFORM,,}") - url="$host/windows/8.x/8.1/en_windows_8.1_with_update_${PLATFORM,,}_dvd_6051480.iso" + "win81${PLATFORM,,}" ) + sum="d8333cf427eb3318ff6ab755eb1dd9d433f0e2ae43745312c1cd23e83ca1ce51" + url="$host/8.x/8.1/en_windows_8.1_with_update_${PLATFORM,,}_dvd_6051480.iso" ;; - "win2022" | "win2022-eval") - url="$host/windows/server/2022/en-us_windows_server_2022_updated_jan_2024_${PLATFORM,,}_dvd_2b7a0c9f.iso" + "win2022" | "win2022-eval" ) + sum="c3c57bb2cf723973a7dcfb1a21e97dfa035753a7f111e348ad918bb64b3114db" + url="$host/server/2022/en-us_windows_server_2022_updated_jan_2024_${PLATFORM,,}_dvd_2b7a0c9f.iso" ;; - "win2019" | "win2019-eval") - url="$host/windows/server/2019/en-us_windows_server_2019_updated_aug_2021_${PLATFORM,,}_dvd_a6431a28.iso" + "win2019" | "win2019-eval" ) + sum="0067afe7fdc4e61f677bd8c35a209082aa917df9c117527fc4b2b52a447e89bb" + url="$host/server/2019/en-us_windows_server_2019_updated_aug_2021_${PLATFORM,,}_dvd_a6431a28.iso" ;; - "win2016" | "win2016-eval") - url="$host/windows/server/2016/en_windows_server_2016_updated_feb_2018_${PLATFORM,,}_dvd_11636692.iso" + "win2016" | "win2016-eval" ) + sum="af06e5483c786c023123e325cea4775050324d9e1366f46850b515ae43f764be" + url="$host/server/2016/en_windows_server_2016_updated_feb_2018_${PLATFORM,,}_dvd_11636692.iso" ;; - "win2012r2" | "win2012r2-eval") - url="$host/windows/server/2012r2/en_windows_server_2012_r2_with_update_${PLATFORM,,}_dvd_6052708-004.iso" + "win2012r2" | "win2012r2-eval" ) + sum="f351e89eb88a96af4626ceb3450248b8573e3ed5924a4e19ea891e6003b62e4e" + url="$host/server/2012r2/en_windows_server_2012_r2_with_update_${PLATFORM,,}_dvd_6052708-004.iso" ;; - "win2008r2" | "win2008r2-eval") - url="$host/windows/server/2008r2/en_windows_server_2008_r2_with_sp1_${PLATFORM,,}_dvd_617601-018.iso" + "win2008r2" | "win2008r2-eval" ) + sum="dfd9890881b7e832a927c38310fb415b7ea62ac5a896671f2ce2a111998f0df8" + url="$host/server/2008r2/en_windows_server_2008_r2_with_sp1_${PLATFORM,,}_dvd_617601-018.iso" ;; - "win7${PLATFORM,,}" | "win7${PLATFORM,,}-enterprise") - url="$host/windows/7/en_windows_7_enterprise_with_sp1_${PLATFORM,,}_dvd_u_677651.iso" + "win7${PLATFORM,,}" | "win7${PLATFORM,,}-enterprise" ) + sum="ee69f3e9b86ff973f632db8e01700c5724ef78420b175d25bae6ead90f6805a7" + url="$host/7/en_windows_7_enterprise_with_sp1_${PLATFORM,,}_dvd_u_677651.iso" ;; - "winvista${PLATFORM,,}" | "winvista${PLATFORM,,}-ultimate") - url="$host/windows/vista/en_windows_vista_sp2_${PLATFORM,,}_dvd_342267.iso" + "win7${PLATFORM,,}-ultimate" ) + sum="0b738b55a5ea388ad016535a5c8234daf2e5715a0638488ddd8a228a836055a1" + url="$host/7/en_windows_7_with_sp1_${PLATFORM,,}.iso" ;; - "winxpx86") - url="$host/windows/xp/professional/en_windows_xp_professional_with_service_pack_3_x86_cd_x14-80428.iso" + "winvista${PLATFORM,,}-ultimate" ) + sum="edf9f947c5791469fd7d2d40a5dcce663efa754f91847aa1d28ed7f585675b78" + url="$host/vista/en_windows_vista_sp2_${PLATFORM,,}_dvd_342267.iso" ;; - "winxpx64") - url="$host/windows/xp/professional/en_win_xp_pro_${PLATFORM,,}_vl.iso" + "winxpx86" ) + sum="62b6c91563bad6cd12a352aa018627c314cfc5162d8e9f8af0756a642e602a46" + url="$host/xp/professional/en_windows_xp_professional_with_service_pack_3_x86_cd_x14-80428.iso" ;; - "core11") - url="https://file.cnxiaobai.com/Windows/%E7%B3%BB%E7%BB%9F%E5%AE%89%E8%A3%85%E5%8C%85/Tiny%2010_11/tiny11%20core%20${PLATFORM,,}%20beta%201.iso" - ;; - "tiny11") - url="https://file.cnxiaobai.com/Windows/%E7%B3%BB%E7%BB%9F%E5%AE%89%E8%A3%85%E5%8C%85/Tiny%2010_11/tiny11%202311%20${PLATFORM,,}.iso" - ;; - "tiny10") - url="https://file.cnxiaobai.com/Windows/%E7%B3%BB%E7%BB%9F%E5%AE%89%E8%A3%85%E5%8C%85/Tiny%2010_11/tiny10%2023H2%20${PLATFORM,,}.iso" + "winxpx64" ) + sum="8fac68e1e56c64ad9a2aa0ad464560282e67fa4f4dd51d09a66f4e548eb0f2d6" + url="$host/xp/professional/en_win_xp_pro_${PLATFORM,,}_vl.iso" ;; esac + [ -z "$ret" ] && echo "$url" || echo "$sum" + return 0 +} + +getLink2() { + + local id="$1" + local ret="$2" + local url="" + local sum="" + local host="https://files.dog/MSDN" + + case "${id,,}" in + "win81${PLATFORM,,}" ) + sum="d8333cf427eb3318ff6ab755eb1dd9d433f0e2ae43745312c1cd23e83ca1ce51" + url="$host/Windows%208.1%20with%20Update/en_windows_8.1_with_update_${PLATFORM,,}_dvd_6051480.iso" + ;; + "win81${PLATFORM,,}-enterprise" | "win81${PLATFORM,,}-enterprise-eval" ) + sum="c3c604c03677504e8905090a8ce5bb1dde76b6fd58e10f32e3a25bef21b2abe1" + url="$host/Windows%208.1%20with%20Update/en_windows_8.1_enterprise_with_update_${PLATFORM,,}_dvd_6054382.iso" + ;; + "win2012r2" | "win2012r2-eval" ) + sum="f351e89eb88a96af4626ceb3450248b8573e3ed5924a4e19ea891e6003b62e4e" + url="$host/Windows%20Server%202012%20R2%20with%20Update/en_windows_server_2012_r2_with_update_${PLATFORM,,}_dvd_6052708.iso" + ;; + "win2008r2" | "win2008r2-eval" ) + sum="dfd9890881b7e832a927c38310fb415b7ea62ac5a896671f2ce2a111998f0df8" + url="$host/Windows%20Server%202008%20R2/en_windows_server_2008_r2_with_sp1_${PLATFORM,,}_dvd_617601.iso" + ;; + "win7${PLATFORM,,}" | "win7${PLATFORM,,}-enterprise" ) + sum="ee69f3e9b86ff973f632db8e01700c5724ef78420b175d25bae6ead90f6805a7" + url="$host/Windows%207/en_windows_7_enterprise_with_sp1_${PLATFORM,,}_dvd_u_677651.iso" + ;; + "win7${PLATFORM,,}-ultimate" ) + sum="36f4fa2416d0982697ab106e3a72d2e120dbcdb6cc54fd3906d06120d0653808" + url="$host/Windows%207/en_windows_7_ultimate_with_sp1_${PLATFORM,,}_dvd_u_677332.iso" + ;; + "winvista${PLATFORM,,}" | "winvista${PLATFORM,,}-enterprise" ) + sum="0a0cd511b3eac95c6f081419c9c65b12317b9d6a8d9707f89d646c910e788016" + url="$host/Windows%20Vista/en_windows_vista_enterprise_sp2_${PLATFORM,,}_dvd_342332.iso" + ;; + "winvista${PLATFORM,,}-ultimate" ) + sum="edf9f947c5791469fd7d2d40a5dcce663efa754f91847aa1d28ed7f585675b78" + url="$host/Windows%20Vista/en_windows_vista_sp2_${PLATFORM,,}_dvd_342267.iso" + ;; + "winxpx86" ) + sum="62b6c91563bad6cd12a352aa018627c314cfc5162d8e9f8af0756a642e602a46" + url="$host/Windows%20XP/en_windows_xp_professional_with_service_pack_3_x86_cd_x14-80428.iso" + ;; + "winxpx64" ) + sum="8fac68e1e56c64ad9a2aa0ad464560282e67fa4f4dd51d09a66f4e548eb0f2d6" + url="$host/Windows%20XP/en_win_xp_pro_${PLATFORM,,}_vl.iso" + ;; + esac + + [ -z "$ret" ] && echo "$url" || echo "$sum" + return 0 +} + +getLink3() { + + local id="$1" + local ret="$2" + local url="" + local sum="" + local host="https://file.cnxiaobai.com/Windows" + + case "${id,,}" in + "core11" ) + sum="78f0f44444ff95b97125b43e560a72e0d6ce0a665cf9f5573bf268191e5510c1" + url="$host/%E7%B3%BB%E7%BB%9F%E5%AE%89%E8%A3%85%E5%8C%85/Tiny%2010_11/tiny11%20core%20${PLATFORM,,}%20beta%201.iso" + ;; + "tiny11" ) + sum="a028800a91addc35d8ae22dce7459b67330f7d69d2f11c70f53c0fdffa5b4280" + url="$host/%E7%B3%BB%E7%BB%9F%E5%AE%89%E8%A3%85%E5%8C%85/Tiny%2010_11/tiny11%202311%20${PLATFORM,,}.iso" + ;; + "tiny10" ) + sum="a11116c0645d892d6a5a7c585ecc1fa13aa66f8c7cc6b03bf1f27bd16860cc35" + url="$host/%E7%B3%BB%E7%BB%9F%E5%AE%89%E8%A3%85%E5%8C%85/Tiny%2010_11/tiny10%2023H2%20${PLATFORM,,}.iso" + ;; + esac + + [ -z "$ret" ] && echo "$url" || echo "$sum" + return 0 +} + +getLink4() { + + # Fallbacks for users who cannot connect to the Microsoft servers + + local id="$1" + local ret="$2" + local url="" + local sum="" + local host="https://drive.massgrave.dev" + + case "${id,,}" in + "win11${PLATFORM,,}" ) + sum="a6c21313210182e0315054789a2b658b77394d5544b69b5341075492f89f51e5" + url="$host/en-us_windows_11_consumer_editions_version_23h2_updated_april_2024_${PLATFORM,,}_dvd_d986680b.iso" + ;; + "win11${PLATFORM,,}-enterprise" | "win11${PLATFORM,,}-enterprise-eval" ) + sum="3d4d388d6ffa371956304fa7401347b4535fd10e3137978a8f7750b790a43521" + url="$host/en-us_windows_11_business_editions_version_23h2_updated_april_2024_${PLATFORM,,}_dvd_349cd577.iso" + ;; + "win11${PLATFORM,,}-iot" | "win11${PLATFORM,,}-enterprise-iot-eval" ) + sum="5d9b86ad467bc89f488d1651a6c5ad3656a7ea923f9f914510657a24c501bb86" + url="$host/en-us_windows_11_iot_enterprise_version_23h2_${PLATFORM,,}_dvd_fb37549c.iso" + ;; + "win10${PLATFORM,,}" ) + sum="b072627c9b8d9f62af280faf2a8b634376f91dc73ea1881c81943c151983aa4a" + url="$host/en-us_windows_10_consumer_editions_version_22h2_updated_april_2024_${PLATFORM,,}_dvd_9a92dc89.iso" + ;; + "win10${PLATFORM,,}-enterprise" | "win10${PLATFORM,,}-enterprise-eval" ) + sum="05fe9de04c2626bd00fbe69ad19129b2dbb75a93a2fe030ebfb2256d937ceab8" + url="$host/en-us_windows_10_business_editions_version_22h2_updated_april_2024_${PLATFORM,,}_dvd_c00090a7.iso" + ;; + "win10${PLATFORM,,}-iot" | "win10${PLATFORM,,}-enterprise-iot-eval" ) + sum="a0334f31ea7a3e6932b9ad7206608248f0bd40698bfb8fc65f14fc5e4976c160" + url="$host/en-us_windows_10_iot_enterprise_ltsc_2021_${PLATFORM,,}_dvd_257ad90f.iso" + ;; + "win10${PLATFORM,,}-ltsc" | "win10${PLATFORM,,}-enterprise-ltsc-eval" ) + sum="c90a6df8997bf49e56b9673982f3e80745058723a707aef8f22998ae6479597d" + url="$host/en-us_windows_10_enterprise_ltsc_2021_${PLATFORM,,}_dvd_d289cf96.iso" + ;; + "win81${PLATFORM,,}-enterprise" | "win81${PLATFORM,,}-enterprise-eval" ) + sum="c3c604c03677504e8905090a8ce5bb1dde76b6fd58e10f32e3a25bef21b2abe1" + url="$host/en_windows_8.1_enterprise_with_update_${PLATFORM,,}_dvd_6054382.iso" + ;; + "win2022" | "win2022-eval" ) + sum="7f41d603224e8a0bf34ba957d3abf0a02437ab75000dd758b5ce3f050963e91f" + url="$host/en-us_windows_server_2022_updated_april_2024_${PLATFORM,,}_dvd_164349f3.iso" + ;; + "win2019" | "win2019-eval" ) + sum="4c5dd63efee50117986a2e38d4b3a3fbaf3c1c15e2e7ea1d23ef9d8af148dd2d" + url="$host/en_windows_server_2019_${PLATFORM,,}_dvd_4cb967d8.iso" + ;; + "win2016" | "win2016-eval" ) + sum="4caeb24b661fcede81cd90661aec31aa69753bf49a5ac247253dd021bc1b5cbb" + url="$host/en_windows_server_2016_${PLATFORM,,}_dvd_9327751.iso" + ;; + "win2012r2" | "win2012r2-eval" ) + sum="f351e89eb88a96af4626ceb3450248b8573e3ed5924a4e19ea891e6003b62e4e" + url="$host/en_windows_server_2012_r2_with_update_${PLATFORM,,}_dvd_6052708.iso" + ;; + "win2008r2" | "win2008r2-eval" ) + sum="dfd9890881b7e832a927c38310fb415b7ea62ac5a896671f2ce2a111998f0df8" + url="$host/en_windows_server_2008_r2_with_sp1_${PLATFORM,,}_dvd_617601.iso" + ;; + "win7${PLATFORM,,}" | "win7${PLATFORM,,}-enterprise" ) + sum="ee69f3e9b86ff973f632db8e01700c5724ef78420b175d25bae6ead90f6805a7" + url="$host/en_windows_7_enterprise_with_sp1_${PLATFORM,,}_dvd_u_677651.iso" + ;; + "win7${PLATFORM,,}-ultimate" ) + sum="36f4fa2416d0982697ab106e3a72d2e120dbcdb6cc54fd3906d06120d0653808" + url="$host/en_windows_7_ultimate_with_sp1_${PLATFORM,,}_dvd_u_677332.iso" + ;; + "winvista${PLATFORM,,}" | "winvista${PLATFORM,,}-enterprise" ) + sum="0a0cd511b3eac95c6f081419c9c65b12317b9d6a8d9707f89d646c910e788016" + url="$host/en_windows_vista_enterprise_sp2_${PLATFORM,,}_dvd_342332.iso" + ;; + "winvista${PLATFORM,,}-ultimate" ) + sum="edf9f947c5791469fd7d2d40a5dcce663efa754f91847aa1d28ed7f585675b78" + url="$host/en_windows_vista_sp2_${PLATFORM,,}_dvd_342267.iso" + ;; + esac + + [ -z "$ret" ] && echo "$url" || echo "$sum" + return 0 +} + +getLink5() { + + local id="$1" + local ret="$2" + local url="" + local sum="" + local host="https://archive.org/download" + + case "${id,,}" in + "core11" ) + sum="78f0f44444ff95b97125b43e560a72e0d6ce0a665cf9f5573bf268191e5510c1" + url="$host/tiny-11-core-x-64-beta-1/tiny11%20core%20${PLATFORM,,}%20beta%201.iso" + ;; + "tiny11" ) + sum="a028800a91addc35d8ae22dce7459b67330f7d69d2f11c70f53c0fdffa5b4280" + url="$host/tiny11-2311/tiny11%202311%20${PLATFORM,,}.iso" + ;; + "tiny10" ) + sum="a11116c0645d892d6a5a7c585ecc1fa13aa66f8c7cc6b03bf1f27bd16860cc35" + url="$host/tiny-10-23-h2/tiny10%20${PLATFORM,,}%2023h2.iso" + ;; + "winxpx86" ) + sum="62b6c91563bad6cd12a352aa018627c314cfc5162d8e9f8af0756a642e602a46" + url="$host/XPPRO_SP3_ENU/en_windows_xp_professional_with_service_pack_3_x86_cd_x14-80428.iso" + ;; + esac + + [ -z "$ret" ] && echo "$url" || echo "$sum" + return 0 +} + +getLink() { + + local url="" + local id="$2" + local func="getLink$1" + + if [ "$1" -gt 0 ] && [ "$1" -le "$MIRRORS" ]; then + url=$($func "$id" "") + fi + echo "$url" return 0 } -secondLink() { +getHash() { - # Fallbacks for users who cannot connect to the Microsoft servers + local sum="" + local id="$2" + local func="getLink$1" - local id="$1" - local url="" - local host="https://drive.massgrave.dev" + if [ "$1" -gt 0 ] && [ "$1" -le "$MIRRORS" ]; then + sum=$($func "$id" "sum") + fi - case "${id,,}" in - "win11${PLATFORM,,}") - url="$host/en-us_windows_11_consumer_editions_version_23h2_updated_april_2024_${PLATFORM,,}_dvd_d986680b.iso" - ;; - "win11${PLATFORM,,}-enterprise" | "win11${PLATFORM,,}-enterprise-eval") - url="$host/en-us_windows_11_business_editions_version_23h2_updated_april_2024_${PLATFORM,,}_dvd_349cd577.iso" - ;; - "win11${PLATFORM,,}-iot" | "win11${PLATFORM,,}-enterprise-iot-eval") - url="$host/en-us_windows_11_iot_enterprise_version_23h2_${PLATFORM,,}_dvd_fb37549c.iso" - ;; - "win10${PLATFORM,,}") - url="$host/en-us_windows_10_consumer_editions_version_22h2_updated_april_2024_${PLATFORM,,}_dvd_9a92dc89.iso" - ;; - "win10${PLATFORM,,}-enterprise" | "win10${PLATFORM,,}-enterprise-eval") - url="$host/en-us_windows_10_business_editions_version_22h2_updated_april_2024_${PLATFORM,,}_dvd_c00090a7.iso" - ;; - "win10${PLATFORM,,}-iot" | "win10${PLATFORM,,}-enterprise-iot-eval") - url="$host/en-us_windows_10_iot_enterprise_ltsc_2021_${PLATFORM,,}_dvd_257ad90f.iso" - ;; - "win10${PLATFORM,,}-ltsc" | "win10${PLATFORM,,}-enterprise-ltsc-eval") - url="$host/en-us_windows_10_enterprise_ltsc_2021_${PLATFORM,,}_dvd_d289cf96.iso" - ;; - "win81${PLATFORM,,}") - url="$host/en_windows_8.1_pro_vl_with_update_${PLATFORM,,}_dvd_6050880.iso" - ;; - "win81${PLATFORM,,}-enterprise" | "win81${PLATFORM,,}-enterprise-eval") - url="$host/en_windows_8.1_enterprise_with_update_${PLATFORM,,}_dvd_6054382.iso" - ;; - "win2022" | "win2022-eval") - url="$host/en-us_windows_server_2022_updated_april_2024_${PLATFORM,,}_dvd_164349f3.iso" - ;; - "win2019" | "win2019-eval") - url="$host/en_windows_server_2019_${PLATFORM,,}_dvd_4cb967d8.iso" - ;; - "win2016" | "win2016-eval") - url="$host/en_windows_server_2016_${PLATFORM,,}_dvd_9327751.iso" - ;; - "win2012r2" | "win2012r2-eval") - url="$host/en_windows_server_2012_r2_with_update_${PLATFORM,,}_dvd_6052708.iso" - ;; - "win2008r2" | "win2008r2-eval") - url="$host/en_windows_server_2008_r2_with_sp1_${PLATFORM,,}_dvd_617601.iso" - ;; - "win7${PLATFORM,,}" | "win7${PLATFORM,,}-enterprise") - url="$host/en_windows_7_enterprise_with_sp1_${PLATFORM,,}_dvd_u_677651.iso" - ;; - "winvista${PLATFORM,,}" | "winvista${PLATFORM,,}-ultimate") - url="$host/en_windows_vista_sp2_${PLATFORM,,}_dvd_342267.iso" - ;; - "winxpx86") - url="$host/en_windows_xp_professional_with_service_pack_3_x86_cd_vl_x14-73974.iso" - ;; - "winxpx64") - url="$host/en_win_xp_pro_${PLATFORM,,}_with_sp2_vl_x13-41611.iso" - ;; - "core11") - url="https://archive.org/download/tiny-11-core-x-64-beta-1/tiny11%20core%20${PLATFORM,,}%20beta%201.iso" - ;; - "tiny11") - url="https://archive.org/download/tiny11-2311/tiny11%202311%20${PLATFORM,,}.iso" - ;; - "tiny10") - url="https://archive.org/download/tiny-10-23-h2/tiny10%20${PLATFORM,,}%2023h2.iso" - ;; - esac - - echo "$url" + echo "$sum" return 0 } @@ -464,11 +723,12 @@ validVersion() { isESD "$id" && return 0 isMido "$id" && return 0 - url=$(getLink "$id") - [ -n "$url" ] && return 0 + for ((i=1;i<=MIRRORS;i++)); do - url=$(secondLink "$id") - [ -n "$url" ] && return 0 + url=$(getLink "$i" "$id") + [ -n "$url" ] && return 0 + + done return 1 } @@ -526,6 +786,10 @@ configXP() { cp "$drivers/NetKVM/xp/$arch/netkvm.inf" "$dir/\$OEM\$/\$1/Drivers/NetKVM" cp "$drivers/NetKVM/xp/$arch/netkvm.sys" "$dir/\$OEM\$/\$1/Drivers/NetKVM" + if [ ! -f "$target/TXTSETUP.SIF" ]; then + error "The file TXTSETUP.SIF could not be found!" && return 1 + fi + sed -i '/^\[SCSI.Load\]/s/$/\nviostor=viostor.sys,4/' "$target/TXTSETUP.SIF" sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\nviostor.sys=1,,,,,,4_,4,1,,,1,4/' "$target/TXTSETUP.SIF" sed -i '/^\[SCSI\]/s/$/\nviostor=\"Red Hat VirtIO SCSI Disk Device\"/' "$target/TXTSETUP.SIF" @@ -550,17 +814,24 @@ configXP() { sed -i '/^\[SCSI\]/s/$/\niaStor=\"Intel\(R\) SATA RAID\/AHCI Controller\"/' "$target/TXTSETUP.SIF" sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_8086\&DEV_2922\&CC_0106=\"iaStor\"/' "$target/TXTSETUP.SIF" - # Windows XP Pro generic key (no activation) - local key="DR8GV-C8V6J-BYXHG-7PYJR-DB66Y" - - local pid setup + local key pid setup setup=$(find "$target" -maxdepth 1 -type f -iname setupp.ini | head -n 1) pid=$(<"$setup") pid="${pid:(-4)}" pid="${pid:0:3}" if [[ "$pid" == "270" ]]; then - info "Warning: this ISO requires a volume license, it will reject the generic key during installation." + info "Warning: this XP version requires a volume license, it will reject the generic key during installation." + fi + + if [[ "${arch,,}" == "x86" ]]; then + # Windows XP Professional x86 generic key (no activation, trial-only) + # This is not a pirated key, it comes from the official MS documentation. + key="DR8GV-C8V6J-BYXHG-7PYJR-DB66Y" + else + # Windows XP Professional x64 generic key (no activation, trial-only) + # This is not a pirated key, it comes from the official MS documentation. + key="B2RBK-7KPT9-4JP6X-QQFWM-PJD6G" fi find "$target" -maxdepth 1 -type f -iname winnt.sif -exec rm {} \; @@ -683,13 +954,12 @@ prepareXP() { local dir="$2" MACHINE="pc-q35-2.10" - BOOT_MODE="windows_legacy" ETFS="[BOOT]/Boot-NoEmul.img" [[ "$MANUAL" == [Yy1]* ]] && return 0 configXP "$dir" && return 0 - error "Failed to generate XP configuration files!" && exit 66 + return 1 } prepareLegacy() { @@ -698,19 +968,15 @@ prepareLegacy() { local dir="$2" ETFS="boot.img" - BOOT_MODE="windows_legacy" - rm -f "$dir/$ETFS" 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 + dd "if=$iso" "of=$dir/$ETFS" bs=2048 "count=$len" "skip=$offset" status=none && return 0 - return 0 + return 1 } return 0 diff --git a/src/install.sh b/src/install.sh index 70aec16..a95049c 100644 --- a/src/install.sh +++ b/src/install.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash set -Eeuo pipefail -ESD_URL="" TMP="$STORAGE/tmp" DIR="$TMP/unpack" FB="falling back to manual installation!" @@ -28,6 +27,78 @@ skipInstall() { return 1 } +startInstall() { + + html "Starting Windows..." + + [ -z "$MANUAL" ] && MANUAL="N" + + if [ -f "$STORAGE/$CUSTOM" ]; then + + BASE="$CUSTOM" + + else + + CUSTOM="" + + if [[ "${VERSION,,}" != "http"* ]]; then + + BASE="$VERSION.iso" + + else + + BASE=$(basename "${VERSION%%\?*}") + : "${BASE//+/ }"; printf -v BASE '%b' "${_//%/\\x}" + BASE=$(echo "$BASE" | sed -e 's/[^A-Za-z0-9._-]/_/g') + + fi + fi + + if [[ "${PLATFORM,,}" == "x64" ]]; then + ! migrateFiles "$BASE" "$VERSION" && error "Migration failed!" && exit 57 + fi + + if skipInstall; then + if [ ! -f "$STORAGE/$BASE" ]; then + BASE="custom.iso" + [ ! -f "$STORAGE/$BASE" ] && BASE="" + fi + [[ "${PLATFORM,,}" == "arm64" ]] && VGA="virtio-gpu" + return 1 + fi + + if [ -f "$STORAGE/$BASE" ]; then + + # Check if the ISO was already processed by our script + local magic="" + magic=$(dd if="$STORAGE/$BASE" seek=0 bs=1 count=1 status=none | tr -d '\000') + magic="$(printf '%s' "$magic" | od -A n -t x1 -v | tr -d ' \n')" + + if [[ "$magic" == "16" ]]; then + + if hasDisk || [[ "$MANUAL" == [Yy1]* ]]; then + return 1 + fi + + fi + + CUSTOM="$BASE" + + fi + + rm -rf "$TMP" + mkdir -p "$TMP" + + if [ ! -f "$STORAGE/$CUSTOM" ]; then + CUSTOM="" + ISO="$TMP/$BASE" + else + ISO="$STORAGE/$CUSTOM" + fi + + return 0 +} + finishInstall() { local iso="$1" @@ -44,12 +115,12 @@ finishInstall() { fi fi - rm -f "$STORAGE/windows.ver" rm -f "$STORAGE/windows.old" rm -f "$STORAGE/windows.boot" rm -f "$STORAGE/windows.mode" cp /run/version "$STORAGE/windows.ver" + echo "$BASE" > "$STORAGE/windows.base" if [[ "${PLATFORM,,}" == "x64" ]]; then if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then @@ -87,92 +158,32 @@ abortInstall() { return 1 } -startInstall() { - - html "Starting Windows..." - - [ -z "$MANUAL" ] && MANUAL="N" - - if [ -f "$STORAGE/$CUSTOM" ]; then - - EXTERNAL="Y" - BASE="$CUSTOM" - - else - - CUSTOM="" - - if [[ "${VERSION,,}" != "http"* ]]; then - - EXTERNAL="N" - BASE="$VERSION.iso" - - else - - EXTERNAL="Y" - BASE=$(basename "${VERSION%%\?*}") - : "${BASE//+/ }"; printf -v BASE '%b' "${_//%/\\x}" - BASE=$(echo "$BASE" | sed -e 's/[^A-Za-z0-9._-]/_/g') - - fi - fi - - if [[ "${PLATFORM,,}" == "x64" ]]; then - ! migrateFiles "$BASE" "$VERSION" && error "Migration failed!" && exit 57 - fi - - if skipInstall; then - [ ! -f "$STORAGE/$BASE" ] && BASE="" - [[ "${PLATFORM,,}" == "arm64" ]] && VGA="virtio-gpu" - return 1 - fi - - if [ -f "$STORAGE/$BASE" ]; then - - # Check if the ISO was already processed by our script - local magic="" - magic=$(dd if="$STORAGE/$BASE" seek=0 bs=1 count=1 status=none | tr -d '\000') - magic="$(printf '%s' "$magic" | od -A n -t x1 -v | tr -d ' \n')" - - if [[ "$magic" == "16" ]]; then - - if hasDisk || [[ "$MANUAL" == [Yy1]* ]]; then - return 1 - fi - - fi - - EXTERNAL="Y" - CUSTOM="$BASE" - - fi - - rm -rf "$TMP" - mkdir -p "$TMP" - - if [ ! -f "$STORAGE/$CUSTOM" ]; then - CUSTOM="" - ISO="$TMP/$BASE" - else - ISO="$STORAGE/$CUSTOM" - fi - - return 0 -} - detectCustom() { - CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname windows.iso -printf "%f\n" | head -n 1) - [ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.iso -printf "%f\n" | head -n 1) - [ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname boot.iso -printf "%f\n" | head -n 1) - [ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.img -printf "%f\n" | head -n 1) + CUSTOM="" + local file size - if [ -z "$CUSTOM" ] && [[ "${VERSION,,}" != "http"* ]]; then - FN="${VERSION/\/storage\//}" - [[ "$FN" == "."* ]] && FN="${FN:1}" - CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname "$FN" -printf "%f\n" | head -n 1) + if [[ "${VERSION,,}" != "http"* ]]; then + file="${VERSION/\/storage\//}" + [[ "$file" == "."* ]] && file="${file:1}" + [[ "$file" == *"/"* ]] && file="" + [ -n "$file" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname "$file" -printf "%f\n" | head -n 1) fi + [ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.iso -printf "%f\n" | head -n 1) + [ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.img -printf "%f\n" | head -n 1) + [ -z "$CUSTOM" ] && return 0 + + size="$(stat -c%s "$STORAGE/$CUSTOM")" + + if [ -z "$size" ] || [[ "$size" == "0" ]]; then + CUSTOM="" + return 0 + fi + + file="windows.$size.iso" + [ -s "$STORAGE/$file" ] && CUSTOM="$file" + return 0 } @@ -183,15 +194,9 @@ getESD() { local winCatalog size case "${version,,}" in - "win11${PLATFORM,,}") - winCatalog="https://go.microsoft.com/fwlink?linkid=2156292" - ;; - "win10${PLATFORM,,}") - winCatalog="https://go.microsoft.com/fwlink/?LinkId=841361" - ;; - *) - error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1 - ;; + "win11${PLATFORM,,}" ) winCatalog="https://go.microsoft.com/fwlink?linkid=2156292" ;; + "win10${PLATFORM,,}" ) winCatalog="https://go.microsoft.com/fwlink/?LinkId=841361" ;; + *) error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1 ;; esac local msg="Downloading product information from Microsoft..." @@ -235,9 +240,9 @@ getESD() { error "Failed to find Windows product in $eFile!" && return 1 fi - ESD_URL=$(xmllint --nonet --xpath '//FilePath' "$dir/$eFile" | sed -E -e 's/<[\/]?FilePath>//g') + ESD=$(xmllint --nonet --xpath '//FilePath' "$dir/$eFile" | sed -E -e 's/<[\/]?FilePath>//g') - if [ -z "$ESD_URL" ]; then + if [ -z "$ESD" ]; then error "Failed to find ESD URL in $eFile!" && return 1 fi @@ -277,12 +282,36 @@ doMido() { return 1 } +verifyFile() { + + local iso="$1" + local check="$2" + local hash="" + + [ -z "$check" ] && return 0 + + html "Verifying downloaded ISO..." + info "Calculating SHA256 checksum of the ISO file..." + + hash=$(sha256sum "$iso" | cut -f1 -d' ') + + if [[ "$hash" == "$check" ]]; then + info "Succesfully verified that the checksum was correct!" && return 0 + fi + + error "Invalid sha256 checksum: $hash , but expected value is: $check ! Please report this at $SUPPORT/issues" + + rm -f "$iso" + return 1 +} + downloadFile() { local iso="$1" local url="$2" - local desc="$3" - local rc progress domain + local sum="$3" + local desc="$4" + local rc progress domain dots rm -f "$iso" @@ -296,8 +325,12 @@ downloadFile() { local msg="Downloading $desc..." domain=$(echo "$url" | awk -F/ '{print $3}') - domain=$(expr "$domain" : '.*\.\(.*\..*\)') - [[ "${domain,,}" != *"microsoft.com" ]] && msg="Downloading $desc from $domain..." + dots=$(echo "$domain" | tr -cd '.' | wc -c) + (( dots > 1 )) && domain=$(expr "$domain" : '.*\.\(.*\..*\)') + + if [ -n "$domain" ] && [[ "${domain,,}" != *"microsoft.com" ]]; then + msg="Downloading $desc from $domain..." + fi info "$msg" && html "$msg" /run/progress.sh "$iso" "Downloading $desc ([P])..." & @@ -308,13 +341,16 @@ downloadFile() { if (( rc == 0 )) && [ -f "$iso" ]; then if [ "$(stat -c%s "$iso")" -gt 100000000 ]; then + if [[ "$VERIFY" == [Yy1]* ]] && [ -n "$sum" ]; then + ! verifyFile "$iso" "$sum" && return 1 + fi html "Download finished successfully..." && return 0 fi fi - rm -f "$iso" error "Failed to download $url , reason: $rc" + rm -f "$iso" return 1 } @@ -323,25 +359,19 @@ downloadImage() { local iso="$1" local version="$2" local tried="n" - local url desc + local url sum desc if [[ "${version,,}" == "http"* ]]; then - - desc=$(getName "$BASE" "$BASE") - downloadFile "$iso" "$version" "$desc" && return 0 + desc=$(fromFile "$BASE") + downloadFile "$iso" "$version" "" "$desc" && return 0 return 1 - fi if ! validVersion "$version"; then error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1 fi - if [[ "${PLATFORM,,}" == "x64" ]]; then - desc=$(printVersion "$version" "Windows") - else - desc=$(printVersion "$version" "Windows for ${PLATFORM}") - fi + desc=$(printVersion "$version" "") if [[ "${PLATFORM,,}" == "x64" ]]; then if isMido "$version"; then @@ -361,37 +391,26 @@ downloadImage() { if getESD "$TMP/esd" "$version"; then ISO="$TMP/$version.esd" - downloadFile "$ISO" "$ESD_URL" "$desc" && return 0 + downloadFile "$ISO" "$ESD" "" "$desc" && return 0 ISO="$TMP/$BASE" fi fi - url=$(getLink "$version") + for ((i=1;i<=MIRRORS;i++)); do - if [ -n "$url" ]; then + url=$(getLink "$i" "$version") - if [[ "$tried" != "n" ]]; then - info "Failed to download $desc from Microsoft, will try another mirror now..." + if [ -n "$url" ]; then + if [[ "$tried" != "n" ]]; then + info "Failed to download $desc, will try another mirror now..." + fi + tried="y" + sum=$(getHash "$i" "$version") + downloadFile "$iso" "$url" "$sum" "$desc" && return 0 fi - tried="y" - downloadFile "$iso" "$url" "$desc" && return 0 - - fi - - url=$(secondLink "$version") - - if [ -n "$url" ]; then - - if [[ "$tried" != "n" ]]; then - info "Failed to download $desc, will try another mirror now..." - fi - - tried="y" - downloadFile "$iso" "$url" "$desc" && return 0 - - fi + done return 1 } @@ -450,21 +469,21 @@ extractESD() { error "Adding Windows Setup failed" && return ${retVal} } + if [[ "${PLATFORM,,}" == "x64" ]]; then + LABEL="CCCOMA_X64FRE_EN-US_DV9" + else + LABEL="CPBA_A64FRE_EN-US_DV9" + fi + local msg="Extracting $desc image..." info "$msg" && html "$msg" local edition imageIndex imageEdition case "${version,,}" in - "win11${PLATFORM,,}") - edition="11 pro" - ;; - "win10${PLATFORM,,}") - edition="10 pro" - ;; - *) - error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1 - ;; + "win11${PLATFORM,,}" ) edition="11 pro" ;; + "win10${PLATFORM,,}" ) edition="10 pro" ;; + *) error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1 ;; esac for (( imageIndex=4; imageIndex<=esdImageCount; imageIndex++ )); do @@ -485,11 +504,14 @@ extractImage() { local iso="$1" local dir="$2" local version="$3" - local desc="downloaded ISO" + local desc="local ISO" local size size_gb space space_gb - if [[ "$EXTERNAL" != [Yy1]* ]] && [ -z "$CUSTOM" ]; then - desc=$(printVersion "$version" "downloaded ISO") + if [ -z "$CUSTOM" ]; then + desc="downloaded ISO" + if [[ "$version" != "http"* ]]; then + desc=$(printVersion "$version" "$desc") + fi fi if [[ "${iso,,}" == *".esd" ]]; then @@ -498,7 +520,6 @@ extractImage() { fi local msg="Extracting $desc image..." - [ -n "$CUSTOM" ] && msg="Extracting local ISO image..." info "$msg" && html "$msg" rm -rf "$dir" @@ -523,56 +544,119 @@ extractImage() { error "Failed to extract ISO file: $iso" && return 1 fi + LABEL=$(isoinfo -d -i "$iso" | sed -n 's/Volume id: //p') + + return 0 +} + +setXML() { + + [[ "$MANUAL" == [Yy1]* ]] && return 0 + + local file="$STORAGE/custom.xml" + [ -f "$file" ] && [ -s "$file" ] && XML="$file" && return 0 + + file="/run/assets/custom.xml" + [ -f "$file" ] && [ -s "$file" ] && XML="$file" && return 0 + + file="$1" + [ -z "$file" ] && file="/run/assets/$DETECTED.xml" + [ -f "$file" ] && [ -s "$file" ] && XML="$file" && return 0 + + return 1 +} + +selectVersion() { + + local tag="$1" + local xml="$2" + local id find name prefer + + name=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml") + [[ "$name" == *"Operating System"* ]] && name="" + [ -z "$name" ] && return 0 + + id=$(fromName "$name") + [ -z "$id" ] && warn "Unknown ${tag,,}: '$name'" && return 0 + + prefer="$id-enterprise" + [ -f "/run/assets/$prefer.xml" ] && find=$(printEdition "$prefer" "") || find="" + if [ -n "$find" ] && [[ "${xml,,}" == *"<${tag,,}>${find,,}"* ]]; then + echo "$prefer" && return 0 + fi + + prefer="$id-ultimate" + [ -f "/run/assets/$prefer.xml" ] && find=$(printEdition "$prefer" "") || find="" + if [ -n "$find" ] && [[ "${xml,,}" == *"<${tag,,}>${find,,}"* ]]; then + echo "$prefer" && return 0 + fi + + prefer="$id" + [ -f "/run/assets/$prefer.xml" ] && find=$(printEdition "$prefer" "") || find="" + if [ -n "$find" ] && [[ "${xml,,}" == *"<${tag,,}>${find,,}"* ]]; then + echo "$prefer" && return 0 + fi + + prefer=$(getVersion "$name") + + echo "$prefer" + return 0 +} + +detectVersion() { + + local xml="$1" + local id="" + + id=$(selectVersion "DISPLAYNAME" "$xml") + [ -n "$id" ] && [[ "${id,,}" != *"unknown"* ]] && echo "$id" && return 0 + + id=$(selectVersion "PRODUCTNAME" "$xml") + [ -n "$id" ] && [[ "${id,,}" != *"unknown"* ]] && echo "$id" && return 0 + + id=$(selectVersion "NAME" "$xml") + [ -n "$id" ] && [[ "${id,,}" != *"unknown"* ]] && echo "$id" && return 0 + return 0 } detectImage() { - XML="" - local dsc local dir="$1" + local version="$2" + local desc msg + + XML="" if [ -n "$CUSTOM" ]; then DETECTED="" else - if [ -z "$DETECTED" ] && [[ "$EXTERNAL" != [Yy1]* ]]; then - DETECTED="$VERSION" + if [ -z "$DETECTED" ] && [[ "${version,,}" != "http"* ]]; then + DETECTED="$version" fi fi if [ -n "$DETECTED" ]; then - if [ -f "/run/assets/$DETECTED.xml" ]; then - [[ "$MANUAL" != [Yy1]* ]] && XML="$DETECTED.xml" - return 0 - fi + [[ "${DETECTED,,}" == "winxp"* ]] && return 0 - if [[ "${DETECTED,,}" != "winxp"* ]]; then - - dsc=$(printVersion "$DETECTED" "$DETECTED") - - warn "got $dsc, but no matching file called $DETECTED.xml exists, $FB." - fi + setXML "" && return 0 + desc=$(printEdition "$DETECTED" "this version") + warn "the answer file for $desc was not found ($DETECTED.xml), $FB." return 0 fi - info "Detecting Windows version from ISO image..." + info "Detecting version from ISO image..." - if [[ "${PLATFORM,,}" == "x64" ]]; then - if [ -f "$dir/WIN51" ] || [ -f "$dir/SETUPXP.HTM" ]; then - if [ -d "$dir/AMD64" ]; then - DETECTED="winxpx64" - else - DETECTED="winxpx86" - fi - dsc=$(printVersion "$DETECTED" "$DETECTED") - info "Detected: $dsc" - return 0 - fi + if [ -f "$dir/WIN51" ] || [ -f "$dir/SETUPXP.HTM" ]; then + [ -d "$dir/AMD64" ] && DETECTED="winxpx64" || DETECTED="winxpx86" + desc=$(printEdition "$DETECTED" "Windows XP") + info "Detected: $desc" + return 0 fi - local src loc tag result name name2 desc + local src loc info src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1) if [ ! -d "$src" ]; then @@ -588,33 +672,26 @@ detectImage() { warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" && 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=$(getVersion "$name") + info=$(wimlib-imagex info -xml "$loc" | tr -d '\000') + DETECTED=$(detectVersion "$info") if [ -z "$DETECTED" ]; then - - tag="PRODUCTNAME" - name2=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$result") - [ -z "$name" ] && name="$name2" - DETECTED=$(getVersion "$name2") - + msg="Failed to determine Windows version from image" + setXML "" && info "${msg}!" && return 0 + warn "${msg}, $FB" && return 0 fi - if [ -z "$DETECTED" ]; then - warn "failed to determine Windows version from string '$name', $FB" && return 0 - fi + desc=$(printEdition "$DETECTED" "$DETECTED") - desc=$(printVersion "$DETECTED" "$DETECTED") + info "Detected: $desc" + setXML "" && return 0 - if [ -f "/run/assets/$DETECTED.xml" ]; then - [[ "$MANUAL" != [Yy1]* ]] && XML="$DETECTED.xml" - info "Detected: $desc" - else - warn "detected $desc, but no matching file called $DETECTED.xml exists, $FB." - fi + msg="the answer file for $desc was not found ($DETECTED.xml)" + local fallback="/run/assets/${DETECTED%%-*}.xml" + setXML "$fallback" && warn "${msg}." && return 0 + + warn "${msg}, $FB." return 0 } @@ -622,45 +699,41 @@ prepareImage() { local iso="$1" local dir="$2" + local missing + + case "${DETECTED,,}" in + "winxp"* ) + BOOT_MODE="windows_legacy" + prepareXP "$iso" "$dir" && return 0 + error "Failed to prepare Windows XP ISO!" && return 1 + ;; + "winvista"* | "win7"* | "win2008"* ) + BOOT_MODE="windows_legacy" ;; + esac if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then - if [[ "${DETECTED,,}" != "winxp"* ]] && [[ "${DETECTED,,}" != "win2008"* ]]; then - if [[ "${DETECTED,,}" != "winvista"* ]] && [[ "${DETECTED,,}" != "win7"* ]]; then - if [ -f "$dir/$ETFS" ] && [ -f "$dir/$EFISYS" ]; then - return 0 - fi + [ -f "$dir/$ETFS" ] && [ -f "$dir/$EFISYS" ] && return 0 - if [ ! -f "$dir/$ETFS" ]; then - warn "failed to locate file 'etfsboot.com' in ISO image, falling back to legacy boot!" - else - warn "failed to locate file 'efisys_noprompt.bin' in ISO image, falling back to legacy boot!" - fi + missing=$(basename "$dir/$EFISYS") + [ ! -f "$dir/$ETFS" ] && missing=$(basename "$dir/$ETFS") + warn "failed to locate file '${missing,,}' in ISO image!" - fi - fi + [[ "${PLATFORM,,}" == "arm64" ]] && return 1 + BOOT_MODE="windows_legacy" fi - [[ "${PLATFORM,,}" == "arm64" ]] && return 1 + prepareLegacy "$iso" "$dir" && return 0 - if [[ "${DETECTED,,}" == "winxp"* ]]; then - if ! prepareXP "$iso" "$dir"; then - error "Failed to prepare Windows XP ISO!" && return 1 - fi - else - if ! prepareLegacy "$iso" "$dir"; then - error "Failed to prepare Windows ISO!" && return 1 - fi - fi - - return 0 + error "Failed to extract boot image from ISO!" + return 1 } updateImage() { local iso="$1" local dir="$2" - local asset="/run/assets/$3" + local asset="$3" local path src loc xml index result [ ! -s "$asset" ] || [ ! -f "$asset" ] && return 0 @@ -694,17 +767,20 @@ updateImage() { fi 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 + warn "failed to add answer file ($xml) to ISO image, $FB" && return 1 fi return 0 } copyOEM() { + local dir="$1" - local folder="$STORAGE/oem" + local folder="/oem" local src + [ ! -d "$folder" ] && folder="/OEM" + [ ! -d "$folder" ] && folder="$STORAGE/OEM" [ ! -d "$folder" ] && folder="$STORAGE/OEM" [ ! -d "$folder" ] && folder="$STORAGE/shared/oem" [ ! -d "$folder" ] && folder="$STORAGE/shared/OEM" @@ -734,12 +810,10 @@ buildImage() { local dir="$1" local failed="N" local cat="BOOT.CAT" - local label="${BASE%.*}" local log="/run/shm/iso.log" local size size_gb space space_gb desc + local out="$TMP/${BASE%.*}.tmp" - label="${label::30}" - local out="$TMP/$label.tmp" rm -f "$out" desc=$(printVersion "$DETECTED" "ISO") @@ -756,9 +830,11 @@ buildImage() { error "Not enough free space in $STORAGE, have $space_gb GB available but need at least $size_gb GB." && return 1 fi + [ -z "$LABEL" ] && LABEL="Windows" + if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then - if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -V "$label" \ + if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -V "${LABEL::30}" \ -udf -boot-info-table -eltorito-alt-boot -eltorito-boot "$EFISYS" -no-emul-boot -allow-limited-size -quiet "$dir" 2> "$log"; then failed="Y" fi @@ -767,7 +843,7 @@ buildImage() { if [[ "${DETECTED,,}" != "winxp"* ]]; then - if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 2 -J -l -D -N -joliet-long -relaxed-filenames -V "$label" \ + if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 2 -J -l -D -N -joliet-long -relaxed-filenames -V "${LABEL::30}" \ -udf -allow-limited-size -quiet "$dir" 2> "$log"; then failed="Y" fi @@ -775,7 +851,7 @@ buildImage() { else if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -boot-load-seg 1984 -boot-load-size 4 -c "$cat" -iso-level 2 -J -l -D -N -joliet-long \ - -relaxed-filenames -V "$label" -quiet "$dir" 2> "$log"; then + -relaxed-filenames -V "${LABEL::30}" -quiet "$dir" 2> "$log"; then failed="Y" fi @@ -872,7 +948,7 @@ if ! extractImage "$ISO" "$DIR" "$VERSION"; then exit 62 fi -if ! detectImage "$DIR"; then +if ! detectImage "$DIR" "$VERSION"; then abortInstall "$ISO" && return 0 exit 60 fi @@ -888,7 +964,8 @@ if ! updateImage "$ISO" "$DIR" "$XML"; then fi if ! rm -f "$ISO" 2> /dev/null; then - BASE="windows.iso" + size="$(stat -c%s "$ISO")" + BASE="windows.$size.iso" ISO="$STORAGE/$BASE" rm -f "$ISO" fi diff --git a/src/mido.sh b/src/mido.sh index 3c3d1db..870061d 100644 --- a/src/mido.sh +++ b/src/mido.sh @@ -388,7 +388,7 @@ consumer_download() { # Filter for 64-bit ISO download URL # sed: HTML decode "&" character # tr: Filter for only alphanumerics or punctuation - iso_download_link="$(echo "$iso_download_link_html" | grep -o "https://software.download.prss.microsoft.com.*IsoX64" | cut -d '"' -f 1 | sed 's/&/\&/g' | tr -cd '[:alnum:][:punct:]' | head -c 512)" + iso_download_link="$(echo "$iso_download_link_html" | grep -o "https://software.download.prss.microsoft.com.*IsoX64" | cut -d '"' -f 1 | sed 's/&/\&/g' | tr -cd '[:alnum:][:punct:]')" if ! [ "$iso_download_link" ]; then # This should only happen if there's been some change to the download endpoint web address diff --git a/src/power.sh b/src/power.sh index 0b500fc..e198610 100644 --- a/src/power.sh +++ b/src/power.sh @@ -28,7 +28,7 @@ boot() { [ -f "$QEMU_END" ] && return 0 if [ -s "$QEMU_PTY" ]; then - if grep -iq " hard" "$QEMU_PTY"; then + if [ "$(stat -c%s "$QEMU_PTY")" -gt 7 ]; then info "Windows started succesfully, visit http://localhost:8006/ to view the screen..." return 0 fi @@ -93,7 +93,9 @@ finish() { pid="/var/run/tpm.pid" [ -s "$pid" ] && pKill "$(<"$pid")" - fKill "wsdd" + pid="/var/run/wsdd.pid" + [ -s "$pid" ] && pKill "$(<"$pid")" + fKill "smbd" closeNetwork diff --git a/src/samba.sh b/src/samba.sh index 7544fc6..9e47fd7 100644 --- a/src/samba.sh +++ b/src/samba.sh @@ -82,6 +82,7 @@ if [[ "$isXP" == [Yy1]* ]]; then else # Enable Web Service Discovery wsdd -i "$interface" -p -n "$hostname" & + echo "$!" > /var/run/wsdd.pid fi return 0