feat: Implement Windows 98 support (#2143)

This commit is contained in:
Kroese
2026-08-15 16:02:41 +02:00
committed by GitHub
parent 8713fa50e1
commit a0822d00a7
5 changed files with 1930 additions and 90 deletions
+127 -1
View File
@@ -231,7 +231,7 @@ jobs:
set -Eeuo pipefail set -Eeuo pipefail
case "$CALLBACK" in case "$CALLBACK" in
powershell | legacy) powershell | legacy | basic)
;; ;;
*) *)
echo "Unsupported guest script type: $CALLBACK" echo "Unsupported guest script type: $CALLBACK"
@@ -249,6 +249,7 @@ jobs:
printf '%s\n' "$token" > "$RUNNER_TEMP/data/validation.token" printf '%s\n' "$token" > "$RUNNER_TEMP/data/validation.token"
printf '%s\n' "$token" > "$RUNNER_TEMP/oem/validation.token" printf '%s\n' "$token" > "$RUNNER_TEMP/oem/validation.token"
if [[ "$CALLBACK" != "basic" ]]; then
cat > "$RUNNER_TEMP/oem/sync-log.bat" <<'BATCH' cat > "$RUNNER_TEMP/oem/sync-log.bat" <<'BATCH'
@echo off @echo off
setlocal setlocal
@@ -327,6 +328,7 @@ jobs:
shell.Run "cmd.exe /C echo VALIDATION_CALLBACK_FAILED^>COM1", 0, True shell.Run "cmd.exe /C echo VALIDATION_CALLBACK_FAILED^>COM1", 0, True
VBSCRIPT VBSCRIPT
fi
case "$CALLBACK" in case "$CALLBACK" in
powershell) powershell)
@@ -764,6 +766,34 @@ jobs:
exit /B %result% exit /B %result%
EOF EOF
;; ;;
basic)
cat > "$RUNNER_TEMP/oem/install.bat" <<'BATCH'
@echo off
:retry
if not exist \\host.lan\Data\validation.token goto wait
echo TOKEN> C:\OEM\validation.result
type C:\OEM\validation.token >> C:\OEM\validation.result
echo SHARE>> C:\OEM\validation.result
type \\host.lan\Data\validation.token >> C:\OEM\validation.result
echo VERSION>> C:\OEM\validation.result
ver >> C:\OEM\validation.result
if exist \\host.lan\Data\validation.result del \\host.lan\Data\validation.result >nul
copy C:\OEM\validation.result \\host.lan\Data\validation.result >nul
if errorlevel 1 goto wait
goto end
:wait
ping 127.0.0.1 -n 6 >nul
goto retry
:end
BATCH
;;
esac esac
echo "token=$token" >> "$GITHUB_OUTPUT" echo "token=$token" >> "$GITHUB_OUTPUT"
@@ -890,6 +920,7 @@ jobs:
- name: Install and validate Windows - name: Install and validate Windows
shell: bash shell: bash
env: env:
CALLBACK: ${{ inputs.callback }}
KILL_ON_FAILURE: ${{ inputs.kill_on_failure }} KILL_ON_FAILURE: ${{ inputs.kill_on_failure }}
INSTALL_TIMEOUT: ${{ inputs.install_timeout }} INSTALL_TIMEOUT: ${{ inputs.install_timeout }}
REBOOT_TIMEOUT: ${{ inputs.reboot_timeout }} REBOOT_TIMEOUT: ${{ inputs.reboot_timeout }}
@@ -1130,6 +1161,101 @@ jobs:
exit 1 exit 1
fi fi
basic_result="$RUNNER_TEMP/data/validation.result"
if [[ "$CALLBACK" == "basic" && -s "$basic_result" ]]; then
basic_response="$(tr -d '\r' < "$basic_result")"
oem_file="$(
awk '$0 == "TOKEN" { getline; print; exit }' <<< "$basic_response"
)"
share="$(
awk '$0 == "SHARE" { getline; print; exit }' <<< "$basic_response"
)"
version="$(
awk '
$0 == "VERSION" { found = 1; next }
found && NF { print; exit }
' <<< "$basic_response"
)"
if [[ -z "$oem_file" || -z "$share" || -z "$version" ]] ||
! grep -Eq '[0-9]+\.[0-9]+\.[0-9]+' <<< "$version"; then
sleep 1
continue
fi
stop_logs
trap - EXIT
echo
echo "------------------------------------------------------------"
echo "Received response:"
printf '%s\n' "$basic_response"
if [[ "$oem_file" != "$EXPECTED_TOKEN" ]]; then
echo "Failed to read C:\\OEM\\validation.token."
echo "Expected contents:"
echo " $EXPECTED_TOKEN"
echo "Received:"
echo " ${oem_file:-empty}"
exit 1
fi
if [[ "$share" != "$EXPECTED_TOKEN" ]]; then
echo "Failed to read \\\\host.lan\\Data\\validation.token."
echo "Expected contents:"
echo " $EXPECTED_TOKEN"
echo "Received:"
echo " ${share:-empty}"
exit 1
fi
normalized_caption="${version//\(R\)/}"
normalized_expected_caption="${EXPECTED_CAPTION//\(R\)/}"
if [[ "$normalized_caption" != *"$normalized_expected_caption"* ]]; then
echo "Expected caption containing:"
echo " $EXPECTED_CAPTION"
echo "Received:"
echo " $version"
exit 1
fi
version_number="$(
grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' <<< "$version" |
head -n 1 || true
)"
if [[ ! "$version_number" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Unexpected Windows version: $version"
exit 1
fi
build="${version_number##*.}"
if [[ ! "$build" =~ ^[0-9]+$ ]]; then
echo "Invalid Windows build number: $build"
exit 1
fi
if (( build < MINIMUM_BUILD )); then
echo "Expected build $MINIMUM_BUILD or newer."
echo "Received build: $build"
exit 1
fi
echo
echo "$DISPLAY_NAME installed successfully."
echo "Version: $version_number"
echo "Build: $build"
echo "OEM files: copied successfully"
echo "Shared folder: readable and writable"
exit 0
fi
response="$( response="$(
grep -F 'VALIDATION_RESULT=' <<< "$container_log" | grep -F 'VALIDATION_RESULT=' <<< "$container_log" |
tail -n 1 | tail -n 1 |
+33
View File
@@ -206,6 +206,39 @@ jobs:
minimum_build: ${{ matrix.minimum_build }} minimum_build: ${{ matrix.minimum_build }}
platform: ${{ matrix.platform }} platform: ${{ matrix.platform }}
win9x:
strategy:
fail-fast: false
matrix:
include:
- name: Windows 95
version: "95"
expected_caption: Windows 95
minimum_build: 950
platform: x86
- name: Windows 98
version: "98"
expected_caption: Windows 98
minimum_build: 2222
platform: x86
- name: Windows ME
version: "me"
expected_caption: Windows Millennium
minimum_build: 3000
platform: x86
name: ${{ matrix.name }}
uses: ./.github/workflows/settings.yml
with:
name: ${{ matrix.name }}
version: ${{ matrix.version }}
callback: basic
expected_caption: ${{ matrix.expected_caption }}
minimum_build: ${{ matrix.minimum_build }}
platform: ${{ matrix.platform }}
tiny: tiny:
strategy: strategy:
fail-fast: false fail-fast: false
+3
View File
@@ -125,6 +125,9 @@ For a complete graphical desktop experience, see [WinBoat](https://winboat.app),
| `vu` | Windows Vista Ultimate | 3.0 GB | | `vu` | Windows Vista Ultimate | 3.0 GB |
| `xp` | Windows XP Professional | 0.6 GB | | `xp` | Windows XP Professional | 0.6 GB |
| `2k` | Windows 2000 Professional | 0.4 GB | | `2k` | Windows 2000 Professional | 0.4 GB |
| `me` | Windows ME | 0.5 GB |
| `98` | Windows 98 | 0.7 GB |
| `95` | Windows 95 | 0.6 GB |
|||| ||||
| `2025` | Windows Server 2025 | 7.6 GB | | `2025` | Windows Server 2025 | 7.6 GB |
| `2022` | Windows Server 2022 | 6.0 GB | | `2022` | Windows Server 2022 | 6.0 GB |
+89 -16
View File
@@ -95,6 +95,12 @@ parseVersion() {
VERSION="winxpx64" ;; VERSION="winxpx64" ;;
"2k" | "2000" | "win2k" | "win2000" | "windows2k" | "windows2000" ) "2k" | "2000" | "win2k" | "win2000" | "windows2k" | "windows2000" )
VERSION="win2kx86" ;; VERSION="win2kx86" ;;
"me" | "winme" | "win9x" | "windowsme" | "windows me" )
VERSION="win9x" ;;
"98" | "98se" | "win98" | "win98se" | "windows98" | "windows98se" | "windows 98" | "windows 98 se" )
VERSION="win98" ;;
"95" | "95c" | "win95" | "win95c" | "windows95" | "windows 95" )
VERSION="win95" ;;
"25" | "2025" | "win25" | "win2025" | "windows2025" | "windows 2025" ) "25" | "2025" | "win25" | "win2025" | "windows2025" | "windows 2025" )
VERSION="win2025-eval" ;; VERSION="win2025-eval" ;;
"22" | "2022" | "win22" | "win2022" | "windows2022" | "windows 2022" ) "22" | "2022" | "win22" | "win2022" | "windows2022" | "windows 2022" )
@@ -570,6 +576,14 @@ fromFile() {
id="win11${arch}" ;; id="win11${arch}" ;;
*"winxp"* | *"win_xp"* | *"windowsxp"* | *"windows_xp"* ) *"winxp"* | *"win_xp"* | *"windowsxp"* | *"windows_xp"* )
id="winxpx86" ;; id="winxpx86" ;;
*"winme"* | *"win_me"* | *"win9x"* | *"windowsme"* | *"windows_me"* )
id="win9x" ;;
*"win98"* | *"win_98"* | *"windows98"* | *"windows_98"* )
id="win98" ;;
*"win95"* | *"win_95"* | *"windows95"* | *"windows_95"* )
id="win95" ;;
*"winnt4"* | *"win_nt4"* | *"windowsnt4"* | *"windows_nt4"* | *"windows_nt_4"* )
id="winnt4" ;;
*"winvista"* | *"win_vista"* | *"windowsvista"* | *"windows_vista"* ) *"winvista"* | *"win_vista"* | *"windowsvista"* | *"windows_vista"* )
id="winvista${arch}" ;; id="winvista${arch}" ;;
"tiny11core"* | "tiny11_core"* | "tiny_11_core"* ) "tiny11core"* | "tiny11_core"* | "tiny_11_core"* )
@@ -1038,7 +1052,7 @@ isLegacy() {
local id="$1" local id="$1"
case "${id,,}" in case "${id,,}" in
"win9"* | "winnt4"* | "win2k"* | "winxp"* | "win2003"* | \ "win9"* | "winnt4" | "win2k"* | "winxp"* | "win2003"* | \
"winvista"* | "win7"* | "win2008"* | "reactos" ) "winvista"* | "win7"* | "win2008"* | "reactos" )
return 0 ;; return 0 ;;
esac esac
@@ -1051,13 +1065,56 @@ supportsUnattended() {
local id="$1" local id="$1"
case "${id,,}" in case "${id,,}" in
"win9"* | "winnt4"* | "reactos" ) "winnt4" | "reactos" )
return 1 ;; return 1 ;;
esac esac
return 0 return 0
} }
supportsXML() {
local id="$1"
supportsSIF "$id" && return 1
supportsUnattended "$id" || return 1
case "${id,,}" in
"win9"* )
return 1 ;;
esac
return 0
}
supportsSIF() {
local id="$1"
case "${id,,}" in
"win2k"* | "winxp"* | "win2003"* )
return 0 ;;
esac
return 1
}
supportsACPI() {
local id="$1"
case "${id,,}" in
"reactos" )
# If the ISO is a Live-CD it will ignore ACPI signals.
hasSystemImage && return 1 ;;
esac
return 0
}
supportsBootKey() { supportsBootKey() {
local id="$1" local id="$1"
@@ -1072,20 +1129,6 @@ supportsBootKey() {
return 0 return 0
} }
supportsXML() {
local id="$1"
supportsUnattended "$id" || return 1
case "${id,,}" in
"win2k"* | "winxp"* | "win2003"* )
return 1 ;;
esac
return 0
}
getDriverFolder() { getDriverFolder() {
local id="$1" local id="$1"
@@ -1337,6 +1380,21 @@ getLink1() {
sum="a93251b31f92316411bb48458a695d9051b13cdeba714c46f105012fdda45bf3" sum="a93251b31f92316411bb48458a695d9051b13cdeba714c46f105012fdda45bf3"
url="2000/5.00.2195.6717_x86fre_client-professional_retail_en-us.7z" url="2000/5.00.2195.6717_x86fre_client-professional_retail_en-us.7z"
;; ;;
"win9x" )
size=448957271
sum="36e75592cf89e072e165da60100f91ca59b7667be90494f1aa4a78091011cfea"
url="9x/me/Windows%20Me_en.zip"
;;
"win98" )
size=558263127
sum="980bfc9abc93c3104d1a00690c5db702efda7a377de7e06cda61889a972e2e08"
url="9x/98/se/Microsoft%20Windows%2098%20Second%20Edition%20%284.10.2222%29.rar"
;;
"win95" )
size=422127699
sum="5456632a73a3c70f8e5ee566374876266a81f61968e623ef5500028dec8e2979"
url="9x/95/Microsoft%20Windows%2095C%20%284.03.1216.osr2.5%29.zip"
;;
esac esac
case "${ret,,}" in case "${ret,,}" in
@@ -1616,6 +1674,21 @@ getLink4() {
sum="e3816f6e80b66ff686ead03eeafffe9daf020a5e4717b8bd4736b7c51733ba22" sum="e3816f6e80b66ff686ead03eeafffe9daf020a5e4717b8bd4736b7c51733ba22"
url="MicrosoftWindows2000BuildCollection/5.00.2195.6717_x86fre_client-professional_retail_en-us-ZRMPFPP_EN.iso" url="MicrosoftWindows2000BuildCollection/5.00.2195.6717_x86fre_client-professional_retail_en-us-ZRMPFPP_EN.iso"
;; ;;
"win9x" )
size=523665408
sum="bff3e9e69e625d2fdffd01b326988c45be8b9285465a4dabbae96ac550de611e"
url="windows-me_202209/Windows%20ME.ISO"
;;
"win98" )
size=655591424
sum="2adfb46df8a9c7bbd2f67bff07461cc2f9d9ec8e01f0e112cb044c9e3e62f607"
url="windows-98-se-isofile/Windows%2098%20Second%20Edition.iso"
;;
"win95" )
size=618229760
sum="493212b2a3cd391269e55a8fde5ee0a35e29ddece4b5910ec49df69ab62f5e26"
url="win-95-osr-25_202103/Win95_OSR25.iso"
;;
"core11" ) "core11" )
size=3304132608 size=3304132608
sum="c0e0252b24144b8defb6c7ded2bc09f9297daf1fb8369b16c5b85382331eb47f" sum="c0e0252b24144b8defb6c7ded2bc09f9297daf1fb8369b16c5b85382331eb47f"
+1658 -53
View File
File diff suppressed because it is too large Load Diff