From 3e22c2b3dec9aeb5313967b4a92fec92cd8ae7c2 Mon Sep 17 00:00:00 2001 From: Liam <33645555+lj3954@users.noreply.github.com> Date: Thu, 28 Dec 2023 18:23:08 -0600 Subject: [PATCH] Add support for windows languages & windows server * Add windows languages, many bugfixes Entering a release, edition, or OS with only part of a valid one will now throw an error, rather than attempting to download i.e. $quickget windows 1 > "ERROR! Windows 1 is not a supported release", rather than attempting to download a nonexistent ISO * Replace "languages" with "editions" to improve consistency * Remove unnecessary code, hardcode windows editions to not waste time * Add windows server, LTSC * Windows server requires IDE drive * Update Windows Guests section in README.md * Improve support for windows server Add back the language array, change stylization of languages in list --- README.md | 14 +++- quickemu | 20 ++++-- quickget | 208 ++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 207 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 1efdcfa..24935b7 100644 --- a/README.md +++ b/README.md @@ -511,7 +511,7 @@ sudo rm /Library/Preferences/SystemConfiguration/NetworkInterfaces.plist Now reboot, and the App Store should work. -## Windows 8, 10 & 11 Guests +## Windows Guests `quickget` can download [Windows10](https://www.microsoft.com/software-download/windows10) and @@ -523,6 +523,9 @@ Windows](https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/). Windows 8.1 is also supported but doesn't feature any automated installation or driver optimisation. +`quickget` can also download [Windows 10 LTSC](https://www.microsoft.com/en-us/evalcenter/download-windows-10-enterprise) and Windows Server [2012-r2](https://www.microsoft.com/en-us/evalcenter/download-windows-server-2012-r2), [2016](https://www.microsoft.com/en-us/evalcenter/download-windows-server-2016), [2019](https://www.microsoft.com/en-us/evalcenter/download-windows-server-2019), and [2022](https://www.microsoft.com/en-us/evalcenter/download-windows-server-2022). No automated installation is supported for these releases. + + ``` bash quickget windows 11 quickemu --vm windows-11.conf @@ -535,6 +538,15 @@ quickemu --vm windows-11.conf - Username: `Quickemu` - Password: `quickemu` +### Regional versions + +By default `quickget` will download the *"English International"* release (*"English (United States)"* for server releases), +but you can optionally specify one of the supported languages: For example: + +``` bash +quickget windows 11 "Chinese (Traditional)" +``` + The default Windows 11 configuration looks like this: ``` bash diff --git a/quickemu b/quickemu index 3842da4..fb129b5 100755 --- a/quickemu +++ b/quickemu @@ -337,7 +337,7 @@ function vm_boot() { fi echo ", ${RAM_VM} RAM" - if [ "${guest_os}" == "macos" ] || [ "${guest_os}" == "windows" ]; then + if [ "${guest_os}" == "macos" ] || [ "${guest_os}" == "windows" ] || [ "${guest_os}" == "windows-server" ]; then if [ "${RAM_VM//G/}" -lt 4 ]; then echo "ERROR! You have insufficient RAM to run ${guest_os} in a VM" exit 1 @@ -348,7 +348,7 @@ function vm_boot() { boot=${boot,,} guest_os=${guest_os,,} - if [ "${guest_os}" == "macos" ] || [ "${guest_os}" == "windows" ]; then + if [ "${guest_os}" == "macos" ] || [ "${guest_os}" == "windows" ] || [ "${guest_os}" == "windows-server" ]; then # Display MSRs alert if the guest is macOS or windows ignore_msrs_alert fi @@ -585,7 +585,7 @@ function vm_boot() { disk_size="96G" fi ;; - windows) + windows|windows-server) if [ "${QEMU_VER_SHORT}" -gt 60 ]; then CPU="-cpu host,kvm=on,+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_passthrough" else @@ -738,7 +738,7 @@ function vm_boot() { # qxl-vga supports seamless mouse and sane resolutions if only one scanout # is used. Which is whay '-vga none' is added to the QEMU command line. DISPLAY_DEVICE="qxl-vga" - elif [ "${guest_os}" == "windows" ]; then + elif [ "${guest_os}" == "windows" ] || [ "${guest_os}" == "windows-server" ]; then case ${OUTPUT} in # virtio-gpu "works" with gtk but is limited to 1024x1024 and exhibits other issues. # https://kevinlocke.name/bits/2021/12/10/windows-11-guest-virtio-libvirt/#video @@ -907,7 +907,7 @@ function vm_boot() { esac fi - if [ "${guest_os}" != "windows" ] && [ -n "${PUBLIC}" ]; then + if [ "${guest_os}" != "windows" ] || [ "${guest_os}" == "windows-server" ] && [ -n "${PUBLIC}" ]; then echo -n " - 9P: On guest: " if [ "${guest_os}" == "linux" ]; then echo "sudo mount -t 9p -o trans=virtio,version=9p2000.L,msize=104857600 ${PUBLIC_TAG} ~/$(basename "${PUBLIC}")" @@ -1153,6 +1153,10 @@ function vm_boot() { # shellcheck disable=SC2054,SC2206 args+=(-drive if=ide,index=0,media=disk,file="${disk_img}") + elif [ "${guest_os}" == "windows-server" ]; then + args+=(-device ide-hd,drive=SystemDisk + -drive id=SystemDisk,if=none,format=qcow2,file="${disk_img}" ${STATUS_QUO}) + else # shellcheck disable=SC2054,SC2206 args+=(-device virtio-blk-pci,drive=SystemDisk @@ -1161,7 +1165,7 @@ function vm_boot() { # https://wiki.qemu.org/Documentation/9psetup # https://askubuntu.com/questions/772784/9p-libvirt-qemu-share-modes - if [ "${guest_os}" != "windows" ] && [ -n "${PUBLIC}" ]; then + if [ "${guest_os}" != "windows" ] || [ "${guest_os}" == "windows-server" ] && [ -n "${PUBLIC}" ]; then # shellcheck disable=SC2054 args+=(-fsdev local,id=fsdev0,path="${PUBLIC}",security_model=mapped-xattr -device virtio-9p-pci,fsdev=fsdev0,mount_tag="${PUBLIC_TAG}") @@ -1917,6 +1921,10 @@ if [ ${VM_UP} -eq 0 ]; then sleep 3.5 monitor_send_cmd "sendkey ret" fi + if [ -n "${iso}" ] && [ "${guest_os}" == "windows-server" ]; then + sleep 7 + monitor_send_cmd "sendkey ret" + fi start_viewer else parse_ports_from_file diff --git a/quickget b/quickget index ed9d570..7f0a3aa 100755 --- a/quickget +++ b/quickget @@ -108,6 +108,7 @@ function pretty_name() { vanillaos) PRETTY_NAME="Vanilla OS";; void) PRETTY_NAME="Void Linux";; vxlinux) PRETTY_NAME="VX Linux";; + windows-server) PRETTY_NAME="Windows Server";; xerolinux) PRETTY_NAME="XeroLinux";; zorin) PRETTY_NAME="Zorin OS";; *) PRETTY_NAME="${SIMPLE_NAME^}";; @@ -128,7 +129,7 @@ function validate_release() { esac RELEASES=$(${RELEASE_GENERATOR}) - if [[ "${RELEASES}" != *"${RELEASE}"* ]]; then + if [[ ! " ${RELEASES[*]} " =~ " ${RELEASE} " ]]; then echo -e "ERROR! ${DISPLAY_NAME} ${RELEASE} is not a supported release.\n" echo -n "${RELEASES}" exit 1 @@ -189,7 +190,8 @@ function list_csv() { for OPTION in $(editions_"${OS}"); do echo "${DISPLAY_NAME},${OS},${RELEASE},${OPTION},${DOWNLOADER},${PNG},${SVG}" done - elif [ "${OS}" == "windows" ]; then + elif [[ "${OS}" == "windows"* ]]; then + "languages_${OS}" for OPTION in "${LANGS[@]}"; do echo "${DISPLAY_NAME},${OS},${RELEASE},${OPTION},${DOWNLOADER},${PNG},${SVG}" done @@ -279,6 +281,7 @@ function os_support() { void \ vxlinux \ windows \ + windows-server \ xerolinux \ xubuntu \ zorin @@ -365,6 +368,7 @@ function os_homepages(){ void) HOMEPAGE="https://voidlinux.org/";; vxlinux) HOMEPAGE="https://vxlinux.org/";; windows) HOMEPAGE="https://www.microsoft.com/en-us/windows/";; + windows-server) HOMEPAGE="https://www.microsoft.com/en-us/windows-server/";; xerolinux) HOMEPAGE="https://xerolinux.xyz/";; xubuntu) HOMEPAGE="https://xubuntu.org/";; zorin) HOMEPAGE="https://zorin.com/os/";; @@ -876,7 +880,32 @@ function releases_vxlinux() { } function releases_windows() { - echo 8 10 11 + echo 8 10 10-ltsc 11 +} + +function languages_windows() { + if [ "${RELEASE}" == 8 ]; then + LANGS=("Arabic" "Brazilian Portuguese" "Bulgarian" "Chinese (Simplified)" "Chinese (Traditional)" "Chinese (Traditional Hong Kong)" \ + "Croatian" "Czech" "Danish" "Dutch" "English (United States)" "English International" "Estonian" "Finnish" "French" "German" "Greek" \ + "Hebrew" "Hungarian" "Italian" "Japanese" "Latvian" "Lithuanian" "Norwegian" "Polish" "Portuguese" "Romanian" "Russian" "Serbian Latin" \ + "Slovak" "Slovenian" "Spanish" "Swedish" "Thai" "Turkish" "Ukrainian") + elif [ "${RELEASE}" == "10-ltsc" ]; then + LANGS=("English (United States)" "English (Great Britain)" "Chinese (Simplified)" "Chinese (Traditional)" \ + "French" "German" "Italian" "Japanese" "Korean" "Portuguese (Brazil)" "Spanish") + else + LANGS=("Arabic" "Brazilian Portuguese" "Bulgarian" "Chinese (Simplified)" "Chinese (Traditional)" "Croatian" "Czech" "Danish" "Dutch" \ + "English (United States)" "English International" "Estonian" "Finnish" "French" "French Canadian" "German" "Greek" "Hebrew" "Hungarian" \ + "Italian" "Japanese" "Korean" "Latvian" "Lithuanian" "Norwegian" "Polish" "Portuguese" "Romanian" "Russian" "Serbian Latin" "Slovak" \ + "Slovenian" "Spanish" "Spanish (Mexico)" "Swedish" "Thai" "Turkish" "Ukrainian") + fi +} + +function releases_windows-server() { + echo 2012-r2 2016 2019 2022 +} + +function languages_windows-server() { + LANGS=("English (United States)" "Chinese (Simplified)" "French" "German" "Italian" "Japanese" "Russian" "Spanish") } function releases_xerolinux() { @@ -952,7 +981,7 @@ function web_get() { exit 1 fi - if [[ ${OS} != windows && ${OS} != macos ]]; then + if [[ ${OS} != windows && ${OS} != macos && ${OS} != windows-server ]]; then echo Downloading $(pretty_name "${OS}") ${RELEASE} ${EDITION:+ $EDITION} from ${URL} fi @@ -1069,16 +1098,15 @@ function make_vm_config() { windows) GUEST="windows" IMAGE_TYPE="iso";; + windows-server) + GUEST="windows-server" + IMAGE_TYPE="iso";; *) GUEST="linux" IMAGE_TYPE="iso";; esac - if [ -n "${EDITION}" ]; then - CONF_FILE="${OS}-${RELEASE}-${EDITION}.conf" - else - CONF_FILE="${OS}-${RELEASE}.conf" - fi + CONF_FILE="${VM_PATH}.conf" if [ ! -e "${CONF_FILE}" ]; then echo "Making ${CONF_FILE}" @@ -1164,7 +1192,7 @@ EOF echo "disk_size=\"32G\"" >> "${CONF_FILE}" fi # Enable TPM for Windows 11 - if [ "${OS}" == "windows" ] && [ "${RELEASE}" -ge 11 ]; then + if [ "${OS}" == "windows" ] && [ "${RELEASE}" == 11 ] || [ "${OS}" == "windows-server" ] && [ "${RELEASE}" == "2022" ]; then echo "tpm=\"on\"" >> "${CONF_FILE}" echo "secureboot=\"off\"" >> "${CONF_FILE}" fi @@ -2609,6 +2637,89 @@ handle_curl_error() { return 1 } +function download_windows-server() { + # Download enterprise evaluation windows versions + local windows_version="$1" + local enterprise_type="$2" + + local url="https://www.microsoft.com/en-us/evalcenter/download-$windows_version" + + local iso_download_page_html="$(curl --silent --location --fail --proto =https --tlsv1.2 --http1.1 -- "$url")" || { + handle_curl_error $? + return $? + } + + local CULTURE="" + local COUNTRY="" + local PRETTY_RELEASE="" + + case "$RELEASE" in + "10-ltsc") PRETTY_RELEASE="10 LTSC";; + "2012-r2") PRETTY_RELEASE="2012 R2";; + *) PRETTY_RELEASE="$RELEASE";; + esac + + + case "$LANG" in + "English (Great Britain)") + CULTURE="en-gb" + COUNTRY="GB";; + "Chinese (Simplified)") + CULTURE="zh-cn" + COUNTRY="CN";; + "Chinese (Traditional)") + CULTURE="zh-tw" + COUNTRY="TW";; + "French") + CULTURE="fr-fr" + COUNTRY="FR";; + "German") + CULTURE="de-de" + COUNTRY="DE";; + "Italian") + CULTURE="it-it" + COUNTRY="IT";; + "Japanese") + CULTURE="ja-jp" + COUNTRY="JP";; + "Korean") + CULTURE="ko-kr" + COUNTRY="KR";; + "Portuguese (Brazil)") + CULTURE="pt-br" + COUNTRY="BR";; + "Spanish") + CULTURE="es-es" + COUNTRY="ES";; + "Russian") + CULTURE="ru-ru" + COUNTRY="RU";; + *) + CULTURE="en-us" + COUNTRY="US";; + esac + + iso_download_links="$(echo "$iso_download_page_html" | grep -o "https://go.microsoft.com/fwlink/p/?LinkID=[0-9]\+&clcid=0x[0-9a-z]\+&culture=$CULTURE&country=$COUNTRY" | head -c 1024)" + + case "$enterprise_type" in + # Select x64 LTSC download link + "ltsc") iso_download_link=$(echo "$iso_download_links" | head -n 4 | tail -n 1) ;; + *) iso_download_link="$iso_download_links" ;; + esac + + iso_download_link="$(curl --silent --location --output /dev/null --silent --write-out "%{url_effective}" --head --fail --proto =https --tlsv1.2 --http1.1 -- "$iso_download_link")" + + if [ "${COUNTRY}" != "US" ]; then + echo Downloading $(pretty_name "${OS}") ${PRETTY_RELEASE} in "${LANG}" from "$iso_download_link" + else + echo Downloading $(pretty_name "${OS}") ${PRETTY_RELEASE} from "$iso_download_link" + fi + + FILE_NAME="${iso_download_link##*/}" + web_get "$iso_download_link" "${VM_PATH}" "${FILE_NAME}" + OS="windows-server" +} + function download_windows() { # Download newer consumer Windows versions from behind gated Microsoft API # This function aims to precisely emulate what Fido does down to the URL requests and HTTP headers (exceptions: updated user agent and referer adapts to Windows version instead of always being "windows11") but written in POSIX sh (with coreutils) and curl instead of PowerShell (also simplified to greatly reduce attack surface) @@ -2622,7 +2733,7 @@ function download_windows() { # # If this function in Mido fails to work for you then please test with the Fido script before creating an issue because we basically just copy what Fido does exactly: # https://github.com/pbatard/Fido - + # Either 8, 10, or 11 local windows_version="$1" @@ -2650,7 +2761,7 @@ function download_windows() { # tr: Filter for only numerics to prevent HTTP parameter injection # head -c was recently added to POSIX: https://austingroupbugs.net/view.php?id=407 local product_edition_id="$(echo "$iso_download_page_html" | grep -Eo '