Compare commits

..

26 Commits
v4.24 ... v4.31

Author SHA1 Message Date
Kroese
d008b18d1d feat: Don't display domain (#1190) 2025-04-06 08:36:54 +02:00
Kroese
fa40d30e5d feat: Add Windows 2000 support (#1188) 2025-04-06 00:42:46 +02:00
Kroese
de4bda71e2 build: Update qemu-docker to v7.08 (#1185) 2025-04-04 01:29:45 +02:00
Kroese
aa16eeba6c docs: Disk pass-through (#1183) 2025-04-03 10:28:44 +02:00
Kroese
70a92d3503 docs: Product key (#1182) 2025-04-03 02:06:22 +02:00
Kroese
6c3ef15ffd docs: Manual installation (#1181) 2025-04-03 02:03:46 +02:00
Kroese
71c9586fb4 fix: Ignore missing custom .iso after install (#1180) 2025-04-03 01:45:49 +02:00
Kroese
81e9fff270 build: Update to qemu-docker v7.07 (#1176) 2025-03-28 20:33:37 +01:00
Kroese
90df2d88e3 docs: Github Codespaces (#1173) 2025-03-27 01:51:12 +01:00
Kroese
ffcb483452 fix: Update download links (#1172) 2025-03-26 19:55:08 +01:00
Kroese
c081ec2693 feat: Additional download mirrors (#1170) 2025-03-26 14:45:37 +01:00
Kroese
96fbb26d6f fix: Warn on invalid path (#1168) 2025-03-26 08:33:24 +01:00
Kroese
db45817a7c docs: Github Codespaces (#1165) 2025-03-25 14:51:59 +01:00
Kroese
a9e3ffa413 fix: Remove non-printable characters (#1160) 2025-03-24 14:10:30 +01:00
renovate[bot]
77a8e4d26e build: Update qemu-docker to v7.04 (#1157) 2025-03-21 22:13:13 +01:00
Lars The
9fd266a09d fix: Disable Hyper-V role (#1155) 2025-03-21 20:57:15 +01:00
Kroese
d570eca629 docs: KVM information (#1152) 2025-03-20 23:21:55 +01:00
Kroese
7b31f538ba docs: Compatibility chart (#1151) 2025-03-20 23:07:24 +01:00
Kroese
6bf854fc12 fix: Detect image platform (#1149) 2025-03-20 20:15:06 +01:00
Kroese
6f604dca8e fix: Check image platform (#1148) 2025-03-20 20:11:13 +01:00
Kroese
663a6b5da0 docs: Add Podman (#1147) 2025-03-20 20:03:51 +01:00
Kroese
839900f495 fix: Detect image platform (#1146) 2025-03-20 17:42:43 +01:00
Kroese
e2be4f6d0c feat: Platform variable (#1143) 2025-03-20 11:09:40 +01:00
Kroese
5d734616aa fix: Disable output buffering (#1141) 2025-03-20 01:19:05 +01:00
Kroese
972240061e fix: Rename bootmessage (#1140) 2025-03-20 00:41:09 +01:00
sequencerr
0c8943f541 fix: Prevent terminal control sequences (#1139) 2025-03-19 23:42:24 +01:00
7 changed files with 362 additions and 188 deletions

View File

@@ -1,7 +1,7 @@
ARG VERSION_ARG="latest" ARG VERSION_ARG="latest"
FROM scratch AS build-amd64 FROM scratch AS build-amd64
COPY --from=qemux/qemu:7.02 / / COPY --from=qemux/qemu:7.09 / /
ARG DEBCONF_NOWARNINGS="yes" ARG DEBCONF_NOWARNINGS="yes"
ARG DEBIAN_FRONTEND="noninteractive" ARG DEBIAN_FRONTEND="noninteractive"
@@ -16,7 +16,8 @@ RUN set -eu && \
dos2unix \ dos2unix \
cabextract \ cabextract \
libxml2-utils \ libxml2-utils \
libarchive-tools && \ libarchive-tools \
netcat-openbsd && \
apt-get clean && \ apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

View File

@@ -159,6 +159,11 @@
<Path>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\FirstNetwork" /v Category /t REG_DWORD /d 1 /f</Path> <Path>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\FirstNetwork" /v Category /t REG_DWORD /d 1 /f</Path>
<Description>Set Network Location to Home</Description> <Description>Set Network Location to Home</Description>
</RunSynchronousCommand> </RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>dism.exe /online /Disable-Feature /FeatureName:Microsoft-Hyper-V /NoRestart</Path>
<Description>Disable Hyper-V role</Description>
</RunSynchronousCommand>
</RunSynchronous> </RunSynchronous>
</component> </component>
<component name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> <component name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">

View File

@@ -64,18 +64,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
##### Via Github Codespaces: ##### Via Github Codespaces:
[`Click here to launch this container in the cloud!`](https://github.com/codespaces/new?skip_quickstart=true&machine=basicLinux32gb&repo=743140652&ref=master&devcontainer_path=.devcontainer.json) [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/dockur/windows)
## Compatibility ⚙️
| **Product** | **Platform** | |
|---|---|---|
| Docker Engine | Linux| ✅ |
| Docker Desktop | Linux | ❌ |
| Docker Desktop | macOS | ❌ |
| Docker Desktop | Windows 11 | ✅ |
| Docker Desktop | Windows 10 | ❌ |
| Github Codespaces | Cloud | ✅ |
## FAQ 💬 ## FAQ 💬
@@ -102,28 +91,29 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
Select from the values below: Select from the values below:
| **Value** | **Version** | **Size** | | **Value** | **Version** | **Size** |
|---|---|---| |---|---|---|
| `11` | Windows 11 Pro | 5.4 GB | | `11` | Windows 11 Pro | 5.4 GB |
| `11l` | Windows 11 LTSC | 4.7 GB | | `11l` | Windows 11 LTSC | 4.7 GB |
| `11e` | Windows 11 Enterprise | 4.0 GB | | `11e` | Windows 11 Enterprise | 4.0 GB |
|||| ||||
| `10` | Windows 10 Pro | 5.7 GB | | `10` | Windows 10 Pro | 5.7 GB |
| `10l` | Windows 10 LTSC | 4.6 GB | | `10l` | Windows 10 LTSC | 4.6 GB |
| `10e` | Windows 10 Enterprise | 5.2 GB | | `10e` | Windows 10 Enterprise | 5.2 GB |
|||| ||||
| `8e` | Windows 8.1 Enterprise | 3.7 GB | | `8e` | Windows 8.1 Enterprise | 3.7 GB |
| `7e` | Windows 7 Enterprise | 3.0 GB | | `7e` | Windows 7 Enterprise | 3.0 GB |
| `ve` | Windows Vista Enterprise | 3.0 GB | | `ve` | Windows Vista Enterprise | 3.0 GB |
| `xp` | Windows XP Professional | 0.6 GB | | `xp` | Windows XP Professional | 0.6 GB |
| `2k` | Windows 2000 Professional | 0.4 GB |
|||| ||||
| `2025` | Windows Server 2025 | 5.6 GB | | `2025` | Windows Server 2025 | 5.6 GB |
| `2022` | Windows Server 2022 | 4.7 GB | | `2022` | Windows Server 2022 | 4.7 GB |
| `2019` | Windows Server 2019 | 5.3 GB | | `2019` | Windows Server 2019 | 5.3 GB |
| `2016` | Windows Server 2016 | 6.5 GB | | `2016` | Windows Server 2016 | 6.5 GB |
| `2012` | Windows Server 2012 | 4.3 GB | | `2012` | Windows Server 2012 | 4.3 GB |
| `2008` | Windows Server 2008 | 3.0 GB | | `2008` | Windows Server 2008 | 3.0 GB |
| `2003` | Windows Server 2003 | 0.6 GB | | `2003` | Windows Server 2003 | 0.6 GB |
> [!TIP] > [!TIP]
> To install ARM64 versions of Windows use [dockur/windows-arm](https://github.com/dockur/windows-arm/). > To install ARM64 versions of Windows use [dockur/windows-arm](https://github.com/dockur/windows-arm/).
@@ -181,7 +171,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
### How do I configure the username and password? ### How do I configure the username and password?
By default, a user called `Docker` (with an empty password) is created during installation. By default, a user called `Docker` is created during installation and its password is `admin`.
If you want to use different credentials, you can configure them in your compose file (only before installation): If you want to use different credentials, you can configure them in your compose file (only before installation):
@@ -214,15 +204,6 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
KEYBOARD: "en-US" KEYBOARD: "en-US"
``` ```
### How do I set the product key?
By default, an evaluation version of Windows will be installed, but if you have a product key you can add a `KEY` variable like this (before installation):
```yaml
environment:
KEY: "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"
```
### How do I select the edition? ### How do I select the edition?
Windows Server offers a minimalistic Core edition without a GUI. To select those non-standard editions, you can add a `EDITION` variable like this (before installation): Windows Server offers a minimalistic Core edition without a GUI. To select those non-standard editions, you can add a `EDITION` variable like this (before installation):
@@ -267,7 +248,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
It's recommended to stick to the automatic installation, as it adjusts various settings to prevent common issues when running Windows inside a virtual environment. It's recommended to stick to the automatic installation, as it adjusts various settings to prevent common issues when running Windows inside a virtual environment.
However, if you insist on performing the installation manually on your own risk, add the following environment variable to your compose file: However, if you insist on performing the installation manually at your own risk, add the following environment variable to your compose file:
```yaml ```yaml
environment: environment:
@@ -278,7 +259,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
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. 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. 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 password `admin`.
There is a 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. There is a 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.
@@ -349,12 +330,12 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
### How do I pass-through a disk? ### 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: It is possible to pass-through disk devices or partitions directly by adding them to your compose file in this way:
```yaml ```yaml
devices: devices:
- /dev/sdb:/disk1 - /dev/sdb:/disk1
- /dev/sdc:/disk2 - /dev/sdc1:/disk2
``` ```
Use `/disk1` if you want it to become your main drive (which will be formatted during installation), and use `/disk2` and higher to add them as secondary drives (which will stay untouched). Use `/disk1` if you want it to become your main drive (which will be formatted during installation), and use `/disk2` and higher to add them as secondary drives (which will stay untouched).
@@ -374,9 +355,16 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
### How do I verify if my system supports KVM? ### How do I verify if my system supports KVM?
Only Linux and Windows 11 support KVM virtualization, macOS and Windows 10 do not unfortunately. First check if your software is compatible using this chart:
You can run the following commands in Linux to check your system: | **Product** | **Linux** | **Win11** | **Win10** | **macOS** |
|---|---|---|---|---|
| Docker CLI | ✅ | ✅ | ❌ | ❌ |
| Docker Desktop | ❌ | ✅ | ❌ | ❌ |
| Podman CLI | ✅ | ✅ | ❌ | ❌ |
| Podman Desktop | ✅ | ✅ | ❌ | ❌ |
After that you can run the following commands in Linux to check your system:
```bash ```bash
sudo apt install cpu-checker sudo apt install cpu-checker
@@ -391,11 +379,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
- you are not using a cloud provider, as most of them do not allow nested virtualization for their VPS's. - you are not using a cloud provider, as most of them do not allow nested virtualization for their VPS's.
If you do not receive any error from `kvm-ok` but the container still complains about KVM, please check whether: If you did not receive any error from `kvm-ok` but the container still complains about a missing KVM device, it could help to add `privileged: true` to your compose file (or `sudo` to your `docker` command) to rule out any permission issue.
- you are not using "Docker Desktop for Linux" as it does not support KVM, instead make use of Docker Engine directly.
- it could help to add `privileged: true` to your compose file (or `sudo` to your `docker run` command), to rule out any permission issue.
### How do I run macOS in a container? ### How do I run macOS in a container?

View File

@@ -17,7 +17,6 @@ set -Eeuo pipefail
: "${PASSWORD:=""}" : "${PASSWORD:=""}"
MIRRORS=3 MIRRORS=3
PLATFORM="x64"
parseVersion() { parseVersion() {
@@ -90,6 +89,9 @@ parseVersion() {
"xp64" | "xpx64" | "5x64" | "winxp64" | "winxpx64" | "windowsxp64" | "windowsxpx64" ) "xp64" | "xpx64" | "5x64" | "winxp64" | "winxpx64" | "windowsxp64" | "windowsxpx64" )
VERSION="winxpx64" VERSION="winxpx64"
;; ;;
"2k" | "2000" | "win2k" | "win2000" | "windows2k" | "windows2000" )
VERSION="win2kx86"
;;
"25" | "2025" | "win25" | "win2025" | "windows2025" | "windows 2025" ) "25" | "2025" | "win25" | "win2025" | "windows2025" | "windows 2025" )
VERSION="win2025-eval" VERSION="win2025-eval"
;; ;;
@@ -102,7 +104,7 @@ parseVersion() {
"16" | "2016" | "win16" | "win2016" | "windows2016" | "windows 2016" ) "16" | "2016" | "win16" | "win2016" | "windows2016" | "windows 2016" )
VERSION="win2016-eval" VERSION="win2016-eval"
;; ;;
"hv" | "hyperv" | "hyper v" | "hyper-v" | "19hv" | "2019hv" | "win2019hv") "hv" | "hyperv" | "hyper v" | "hyper-v" | "19hv" | "2019hv" | "win2019hv" )
VERSION="win2019-hv" VERSION="win2019-hv"
;; ;;
"2012" | "2012r2" | "win2012" | "win2012r2" | "windows2012" | "windows 2012" ) "2012" | "2012r2" | "win2012" | "win2012r2" | "windows2012" | "windows 2012" )
@@ -742,11 +744,6 @@ getMido() {
sum="2dedd44c45646c74efc5a028f65336027e14a56f76686a4631cf94ffe37c72f2" sum="2dedd44c45646c74efc5a028f65336027e14a56f76686a4631cf94ffe37c72f2"
url="https://download.microsoft.com/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X64FREE_EN-US_DV9.ISO" url="https://download.microsoft.com/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X64FREE_EN-US_DV9.ISO"
;; ;;
"win7x64" | "win7x64-enterprise-eval" )
size=3121248256
sum="2c16c73388a5c02a0ec4cd8b9e5c14ba28b7b45d13d0c9c7d44459feecc0385f"
url="http://care.dlservice.microsoft.com/dl/download/evalx/win7/x64/EN/7600.16385.090713-1255_x64fre_enterprise_en-us_EVAL_Eval_Enterprise-GRMCENXEVAL_EN_DVD.iso"
;;
"win2025-eval" ) "win2025-eval" )
size=6014152704 size=6014152704
sum="d0ef4502e350e3c6c53c15b1b3020d38a5ded011bf04998e950720ac8579b23d" sum="d0ef4502e350e3c6c53c15b1b3020d38a5ded011bf04998e950720ac8579b23d"
@@ -888,7 +885,7 @@ getLink1() {
sum="0b738b55a5ea388ad016535a5c8234daf2e5715a0638488ddd8a228a836055a1" sum="0b738b55a5ea388ad016535a5c8234daf2e5715a0638488ddd8a228a836055a1"
url="7/en_windows_7_with_sp1_x64.iso" url="7/en_windows_7_with_sp1_x64.iso"
;; ;;
"win7x86" | "win7x86-enterprise" ) "win7x86" | "win7x86-enterprise" | "win7x86-enterprise-eval" )
size=2434502656 size=2434502656
sum="8bdd46ff8cb8b8de9c4aba02706629c8983c45e87da110e64e13be17c8434dad" sum="8bdd46ff8cb8b8de9c4aba02706629c8983c45e87da110e64e13be17c8434dad"
url="7/en_windows_7_enterprise_with_sp1_x86_dvd_u_677710.iso" url="7/en_windows_7_enterprise_with_sp1_x86_dvd_u_677710.iso"
@@ -918,6 +915,11 @@ getLink1() {
sum="8fac68e1e56c64ad9a2aa0ad464560282e67fa4f4dd51d09a66f4e548eb0f2d6" sum="8fac68e1e56c64ad9a2aa0ad464560282e67fa4f4dd51d09a66f4e548eb0f2d6"
url="xp/professional/en_win_xp_pro_x64_vl.iso" url="xp/professional/en_win_xp_pro_x64_vl.iso"
;; ;;
"win2kx86" )
size=331701982
sum="a93251b31f92316411bb48458a695d9051b13cdeba714c46f105012fdda45bf3"
url="2000/5.00.2195.6717_x86fre_client-professional_retail_en-us.7z"
;;
esac esac
case "${ret,,}" in case "${ret,,}" in
@@ -972,7 +974,7 @@ getLink2() {
sum="36f4fa2416d0982697ab106e3a72d2e120dbcdb6cc54fd3906d06120d0653808" sum="36f4fa2416d0982697ab106e3a72d2e120dbcdb6cc54fd3906d06120d0653808"
url="Windows%207/en_windows_7_ultimate_with_sp1_x64_dvd_u_677332.iso" url="Windows%207/en_windows_7_ultimate_with_sp1_x64_dvd_u_677332.iso"
;; ;;
"win7x86" | "win7x86-enterprise" ) "win7x86" | "win7x86-enterprise" | "win7x86-enterprise-eval" )
size=2434502656 size=2434502656
sum="8bdd46ff8cb8b8de9c4aba02706629c8983c45e87da110e64e13be17c8434dad" sum="8bdd46ff8cb8b8de9c4aba02706629c8983c45e87da110e64e13be17c8434dad"
url="Windows%207/en_windows_7_enterprise_with_sp1_x86_dvd_u_677710.iso" url="Windows%207/en_windows_7_enterprise_with_sp1_x86_dvd_u_677710.iso"
@@ -1056,11 +1058,40 @@ getLink3() {
sum="a11116c0645d892d6a5a7c585ecc1fa13aa66f8c7cc6b03bf1f27bd16860cc35" sum="a11116c0645d892d6a5a7c585ecc1fa13aa66f8c7cc6b03bf1f27bd16860cc35"
url="tiny-10-23-h2/tiny10%20x64%2023h2.iso" url="tiny-10-23-h2/tiny10%20x64%2023h2.iso"
;; ;;
"win7x64" | "win7x64-enterprise" | "win7x64-enterprise-eval" )
size=3182604288
sum="ee69f3e9b86ff973f632db8e01700c5724ef78420b175d25bae6ead90f6805a7"
url="en_windows_7_enterprise_with_sp1_x64_dvd_u_677651_202006/en_windows_7_enterprise_with_sp1_x64_dvd_u_677651.iso"
;;
"win7x64-ultimate" )
size=3320903680
sum="36f4fa2416d0982697ab106e3a72d2e120dbcdb6cc54fd3906d06120d0653808"
url="win7-ult-sp1-english/Win7_Ult_SP1_English_x64.iso"
;;
"win7x86" | "win7x86-enterprise" | "win7x86-enterprise-eval" )
size=2434502656
sum="8bdd46ff8cb8b8de9c4aba02706629c8983c45e87da110e64e13be17c8434dad"
url="en_windows_7_enterprise_with_sp1_x86_dvd_u_677710_202006/en_windows_7_enterprise_with_sp1_x86_dvd_u_677710.iso"
;;
"win7x86-ultimate" )
size=2564476928
sum="e2c009a66d63a742941f5087acae1aa438dcbe87010bddd53884b1af6b22c940"
url="win7-ult-sp1-english/Win7_Ult_SP1_English_x32.iso"
;;
"winxpx86" ) "winxpx86" )
size=617756672 size=617756672
sum="62b6c91563bad6cd12a352aa018627c314cfc5162d8e9f8af0756a642e602a46" sum="62b6c91563bad6cd12a352aa018627c314cfc5162d8e9f8af0756a642e602a46"
url="XPPRO_SP3_ENU/en_windows_xp_professional_with_service_pack_3_x86_cd_x14-80428.iso" url="XPPRO_SP3_ENU/en_windows_xp_professional_with_service_pack_3_x86_cd_x14-80428.iso"
;; ;;
"winxpx64" )
size=614166528
sum="8fac68e1e56c64ad9a2aa0ad464560282e67fa4f4dd51d09a66f4e548eb0f2d6"
url="windows-xp-all-sp-msdn-iso-files-en-de-ru-tr-x86-x64/en_win_xp_sp1_pro_x64_vl.iso"
;;
"win2kx86" )
size=386859008
sum="e3816f6e80b66ff686ead03eeafffe9daf020a5e4717b8bd4736b7c51733ba22"
url="MicrosoftWindows2000BuildCollection/5.00.2195.6717_x86fre_client-professional_retail_en-us-ZRMPFPP_EN.iso"
esac esac
case "${ret,,}" in case "${ret,,}" in
@@ -1197,89 +1228,104 @@ prepareInstall() {
local driver="$4" local driver="$4"
local drivers="/tmp/drivers" local drivers="/tmp/drivers"
rm -rf "$drivers"
mkdir -p "$drivers"
ETFS="[BOOT]/Boot-NoEmul.img" ETFS="[BOOT]/Boot-NoEmul.img"
if [ ! -f "$dir/$ETFS" ] || [ ! -s "$dir/$ETFS" ]; then if [ ! -f "$dir/$ETFS" ] || [ ! -s "$dir/$ETFS" ]; then
error "Failed to locate file \"$ETFS\" in $desc ISO image!" && return 1 error "Failed to locate file \"$ETFS\" in $desc ISO image!" && return 1
fi fi
local msg="Adding drivers to image..."
info "$msg" && html "$msg"
if ! bsdtar -xf /drivers.txz -C "$drivers"; then
error "Failed to extract drivers!" && return 1
fi
local arch target local arch target
[ -d "$dir/AMD64" ] && arch="amd64" || arch="x86" [ -d "$dir/AMD64" ] && arch="amd64" || arch="x86"
[[ "${arch,,}" == "x86" ]] && target="$dir/I386" || target="$dir/AMD64" [[ "${arch,,}" == "x86" ]] && target="$dir/I386" || target="$dir/AMD64"
if [ ! -f "$drivers/viostor/$driver/$arch/viostor.sys" ]; then if [ ! -d "$target" ]; then
error "Failed to locate required storage drivers!" && return 1 error "Failed to locate directory \"$target\" in $desc ISO image!" && return 1
fi fi
cp -L "$drivers/viostor/$driver/$arch/viostor.sys" "$target" || return 1 if [[ "${driver,,}" == "xp" ]] || [[ "${driver,,}" == "2k3" ]]; then
mkdir -p "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1 local msg="Adding drivers to image..."
cp -L "$drivers/viostor/$driver/$arch/viostor.cat" "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1 info "$msg" && html "$msg"
cp -L "$drivers/viostor/$driver/$arch/viostor.inf" "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1
cp -L "$drivers/viostor/$driver/$arch/viostor.sys" "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1 rm -rf "$drivers"
mkdir -p "$drivers"
if ! bsdtar -xf /drivers.txz -C "$drivers"; then
error "Failed to extract drivers!" && return 1
fi
if [ ! -f "$drivers/viostor/$driver/$arch/viostor.sys" ]; then
error "Failed to locate required storage drivers!" && return 1
fi
cp -L "$drivers/viostor/$driver/$arch/viostor.sys" "$target" || return 1
mkdir -p "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1
cp -L "$drivers/viostor/$driver/$arch/viostor.cat" "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1
cp -L "$drivers/viostor/$driver/$arch/viostor.inf" "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1
cp -L "$drivers/viostor/$driver/$arch/viostor.sys" "$dir/\$OEM\$/\$1/Drivers/viostor" || return 1
if [ ! -f "$drivers/NetKVM/$driver/$arch/netkvm.sys" ]; then
error "Failed to locate required network drivers!" && return 1
fi
mkdir -p "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.cat" "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.inf" "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.sys" "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
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"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00000000=\"viostor\"/' "$target/TXTSETUP.SIF"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00020000=\"viostor\"/' "$target/TXTSETUP.SIF"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00021AF4=\"viostor\"/' "$target/TXTSETUP.SIF"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00000000=\"viostor\"/' "$target/TXTSETUP.SIF"
if [ ! -d "$drivers/sata/xp/$arch" ]; then
error "Failed to locate required SATA drivers!" && return 1
fi
mkdir -p "$dir/\$OEM\$/\$1/Drivers/sata" || return 1
cp -Lr "$drivers/sata/xp/$arch/." "$dir/\$OEM\$/\$1/Drivers/sata" || return 1
cp -Lr "$drivers/sata/xp/$arch/." "$target" || return 1
sed -i '/^\[SCSI.Load\]/s/$/\niaStor=iaStor.sys,4/' "$target/TXTSETUP.SIF"
sed -i '/^\[FileFlags\]/s/$/\niaStor.sys = 16/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaStor.cat = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaStor.inf = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaStor.sys = 1,,,,,,4_,4,1,,,1,4/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaStor.sys = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaahci.cat = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaAHCI.inf = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
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"
rm -rf "$drivers"
if [ ! -f "$drivers/NetKVM/$driver/$arch/netkvm.sys" ]; then
error "Failed to locate required network drivers!" && return 1
fi fi
mkdir -p "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.cat" "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.inf" "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
cp -L "$drivers/NetKVM/$driver/$arch/netkvm.sys" "$dir/\$OEM\$/\$1/Drivers/NetKVM" || return 1
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"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00000000=\"viostor\"/' "$target/TXTSETUP.SIF"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00020000=\"viostor\"/' "$target/TXTSETUP.SIF"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00021AF4=\"viostor\"/' "$target/TXTSETUP.SIF"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_1AF4\&DEV_1001\&SUBSYS_00000000=\"viostor\"/' "$target/TXTSETUP.SIF"
if [ ! -d "$drivers/sata/xp/$arch" ]; then
error "Failed to locate required SATA drivers!" && return 1
fi
mkdir -p "$dir/\$OEM\$/\$1/Drivers/sata" || return 1
cp -Lr "$drivers/sata/xp/$arch/." "$dir/\$OEM\$/\$1/Drivers/sata" || return 1
cp -Lr "$drivers/sata/xp/$arch/." "$target" || return 1
sed -i '/^\[SCSI.Load\]/s/$/\niaStor=iaStor.sys,4/' "$target/TXTSETUP.SIF"
sed -i '/^\[FileFlags\]/s/$/\niaStor.sys = 16/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaStor.cat = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaStor.inf = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaStor.sys = 1,,,,,,4_,4,1,,,1,4/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaStor.sys = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaahci.cat = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
sed -i '/^\[SourceDisksFiles.'"$arch"'\]/s/$/\niaAHCI.inf = 1,,,,,,,1,0,0/' "$target/TXTSETUP.SIF"
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"
rm -rf "$drivers"
local pid file setup local pid file setup
setup=$(find "$target" -maxdepth 1 -type f -iname setupp.ini | head -n 1) 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 if [ -n "$setup" ]; then
warn "this version of $desc requires a volume license key (VLK), it will ask for one during installation."
pid=$(<"$setup")
pid="${pid:(-4)}"
pid="${pid:0:3}"
if [[ "$pid" == "270" ]]; then
warn "this version of $desc requires a volume license key (VLK), it will ask for one during installation."
fi
fi fi
mkdir -p "$dir/\$OEM\$"
if ! addFolder "$dir"; then if ! addFolder "$dir"; then
error "Failed to add OEM folder to image!" && return 1 error "Failed to add OEM folder to image!" && return 1
fi fi
@@ -1294,33 +1340,48 @@ prepareInstall() {
XHEX=$(printf '%x\n' "$WIDTH") XHEX=$(printf '%x\n' "$WIDTH")
YHEX=$(printf '%x\n' "$HEIGHT") YHEX=$(printf '%x\n' "$HEIGHT")
local username="Docker" local username=""
local password="*" local password=""
[ -n "$PASSWORD" ] && password="$PASSWORD"
[ -n "$USERNAME" ] && username=$(echo "$USERNAME" | sed 's/[^[:alnum:]@!._-]//g') [ -n "$USERNAME" ] && username=$(echo "$USERNAME" | sed 's/[^[:alnum:]@!._-]//g')
[ -z "$username" ] && username="Docker"
[ -n "$PASSWORD" ] && password=$(echo "$PASSWORD" | sed 's/"//g')
[ -z "$password" ] && password="admin"
local ip="20.20.20.1" local ip="20.20.20.1"
[ -n "${VM_NET_IP:-}" ] && ip="${VM_NET_IP%.*}.1" [ -n "${VM_NET_IP:-}" ] && ip="${VM_NET_IP%.*}.1"
# These are not pirated keys, they come from the official MS documentation. # These are not pirated keys, they come from the official MS documentation.
if [[ "${driver,,}" == "xp" ]]; then case "${driver,,}" in
if [[ "${arch,,}" == "x86" ]]; then "xp" )
# Windows XP Professional x86 generic key (no activation, trial-only)
[ -z "$KEY" ] && KEY="DR8GV-C8V6J-BYXHG-7PYJR-DB66Y" if [[ "${arch,,}" == "x86" ]]; then
else # Windows XP Professional x86 generic key (no activation, trial-only)
# Windows XP Professional x64 generic key (no activation, trial-only) [ -z "$KEY" ] && KEY="DR8GV-C8V6J-BYXHG-7PYJR-DB66Y"
[ -z "$KEY" ] && KEY="B2RBK-7KPT9-4JP6X-QQFWM-PJD6G" else
fi # Windows XP Professional x64 generic key (no activation, trial-only)
else [ -z "$KEY" ] && KEY="B2RBK-7KPT9-4JP6X-QQFWM-PJD6G"
if [[ "${arch,,}" == "x86" ]]; then fi ;;
# Windows Server 2003 Standard x86 generic key (no activation, trial-only)
[ -z "$KEY" ] && KEY="QKDCQ-TP2JM-G4MDG-VR6F2-P9C48" "2k3" )
else
# Windows Server 2003 Standard x64 generic key (no activation, trial-only) if [[ "${arch,,}" == "x86" ]]; then
[ -z "$KEY" ] && KEY="P4WJG-WK3W7-3HM8W-RWHCK-8JTRY" # Windows Server 2003 Standard x86 generic key (no activation, trial-only)
fi [ -z "$KEY" ] && KEY="QKDCQ-TP2JM-G4MDG-VR6F2-P9C48"
fi else
# Windows Server 2003 Standard x64 generic key (no activation, trial-only)
[ -z "$KEY" ] && KEY="P4WJG-WK3W7-3HM8W-RWHCK-8JTRY"
fi ;;
"2k" )
# Windows 2000 Professional x86 generic key
KEY="G74HG-XXQTJ-RTX64-QKP3F-HKHXP" ;;
* ) error "Unknown version: \"$driver\"" && return 1 ;;
esac
find "$target" -maxdepth 1 -type f -iname winnt.sif -exec rm {} \; find "$target" -maxdepth 1 -type f -iname winnt.sif -exec rm {} \;
@@ -1359,7 +1420,7 @@ prepareInstall() {
echo " FullName=\"$username\"" echo " FullName=\"$username\""
echo " ComputerName=\"*\"" echo " ComputerName=\"*\""
echo " OrgName=\"Windows for Docker\"" echo " OrgName=\"Windows for Docker\""
echo " ProductKey=$KEY" echo " ProductID=$KEY"
echo "" echo ""
echo "[Identification]" echo "[Identification]"
echo " JoinWorkgroup = WORKGROUP" echo " JoinWorkgroup = WORKGROUP"
@@ -1418,12 +1479,14 @@ prepareInstall() {
echo "[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced]" echo "[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced]"
echo "\"HideFileExt\"=dword:00000000" echo "\"HideFileExt\"=dword:00000000"
echo "" echo ""
echo "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer]"
echo "\"NoWelcomeScreen\"=\"1\""
echo ""
echo "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]" echo "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]"
echo "\"DefaultUserName\"=\"$username\""
echo "\"DefaultDomainName\"=\"Dockur\""
echo "\"AltDefaultUserName\"=\"$username\""
echo "\"AltDefaultDomainName\"=\"Dockur\""
echo "\"AutoAdminLogon\"=\"1\"" echo "\"AutoAdminLogon\"=\"1\""
echo "\"DefaultUserName\"=\"$username\""
echo "\"DefaultPassword\"=\"$password\""
echo "\"DefaultDomainName\"=\"Dockur\""
echo "" echo ""
echo "[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Video\{23A77BF7-ED96-40EC-AF06-9B1F4867732A}\0000]" echo "[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Video\{23A77BF7-ED96-40EC-AF06-9B1F4867732A}\0000]"
echo "\"DefaultSettings.BitsPerPel\"=dword:00000020" echo "\"DefaultSettings.BitsPerPel\"=dword:00000020"
@@ -1494,11 +1557,13 @@ prepareInstall() {
echo "" echo ""
echo "Call Domain.MoveHere(LocalAdminADsPath, \"$username\")" echo "Call Domain.MoveHere(LocalAdminADsPath, \"$username\")"
echo "" echo ""
echo "Set oFSO = CreateObject(\"Scripting.FileSystemObject\")" echo "With (CreateObject(\"Scripting.FileSystemObject\"))"
echo "Set oHosts = oFSO.GetFile(\"C:\Windows\System32\drivers\etc\hosts\")" echo " SysRoot = WshShell.ExpandEnvironmentStrings(\"%SystemRoot%\")"
echo "Set fileAPPEND = oFSO.OpenTextFile(\"C:\Windows\System32\drivers\etc\hosts\", 8, true)" echo " Set oFile = .OpenTextFile(SysRoot & \"\system32\drivers\etc\hosts\", 8, true)"
echo "fileAPPEND.Write(\"$ip host.lan\")" echo " oFile.Write(\"$ip host.lan\")"
echo "fileAPPEND.Close()" echo " oFile.Close()"
echo " Set oFile = Nothing"
echo "End With"
echo "" echo ""
} | unix2dos > "$dir/\$OEM\$/admin.vbs" } | unix2dos > "$dir/\$OEM\$/admin.vbs"
@@ -1595,7 +1660,9 @@ setMachine() {
"win9"* ) "win9"* )
ETFS="[BOOT]/Boot-1.44M.img" ;; ETFS="[BOOT]/Boot-1.44M.img" ;;
"win2k"* ) "win2k"* )
ETFS="[BOOT]/Boot-NoEmul.img" ;; if ! prepareInstall "$iso" "$dir" "$desc" "2k"; then
error "Failed to prepare $desc ISO!" && return 1
fi ;;
"winxp"* ) "winxp"* )
if ! prepareInstall "$iso" "$dir" "$desc" "xp"; then if ! prepareInstall "$iso" "$dir" "$desc" "xp"; then
error "Failed to prepare $desc ISO!" && return 1 error "Failed to prepare $desc ISO!" && return 1
@@ -1607,10 +1674,20 @@ setMachine() {
esac esac
case "${id,,}" in case "${id,,}" in
"win9"* | "win2k"* ) "win9"* )
USB="no"
VGA="cirrus"
DISK_TYPE="auto" DISK_TYPE="auto"
ADAPTER="rtl8139"
MACHINE="pc-i440fx-2.4" MACHINE="pc-i440fx-2.4"
BOOT_MODE="windows_legacy" ;; BOOT_MODE="windows_legacy" ;;
"win2k"* )
VGA="cirrus"
MACHINE="pc"
USB="pci-ohci"
DISK_TYPE="auto"
ADAPTER="rtl8139"
BOOT_MODE="windows_legacy" ;;
"winxp"* | "win2003"* ) "winxp"* | "win2003"* )
DISK_TYPE="blk" DISK_TYPE="blk"
BOOT_MODE="windows_legacy" ;; BOOT_MODE="windows_legacy" ;;

View File

@@ -2,6 +2,7 @@
set -Eeuo pipefail set -Eeuo pipefail
: "${APP:="Windows"}" : "${APP:="Windows"}"
: "${PLATFORM:="x64"}"
: "${BOOT_MODE:="windows"}" : "${BOOT_MODE:="windows"}"
: "${SUPPORT:="https://github.com/dockur/windows"}" : "${SUPPORT:="https://github.com/dockur/windows"}"
@@ -32,8 +33,10 @@ info "Booting ${APP}${BOOT_DESC} using QEMU v$version..."
terminal terminal
( sleep 30; boot ) & ( sleep 30; boot ) &
tail -fn +0 "$QEMU_LOG" 2>/dev/null & tail -fn +0 "$QEMU_LOG" 2>/dev/null &
cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" & cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" | \
wait $! || : sed -u -e 's/\x1B\[[=0-9;]*[a-z]//gi' \
-e 's/failed to load Boot/skipped Boot/g' \
-e 's/0): Not Found/0)/g' & wait $! || :
sleep 1 & wait $! sleep 1 & wait $!
[ ! -f "$QEMU_END" ] && finish 0 [ ! -f "$QEMU_END" ] && finish 0

View File

@@ -10,21 +10,31 @@ EFISYS="efi/microsoft/boot/efisys_noprompt.bin"
skipInstall() { skipInstall() {
local iso="$1" local iso="$1"
local method=""
local magic byte local magic byte
local boot="$STORAGE/windows.boot" local boot="$STORAGE/windows.boot"
local previous="$STORAGE/windows.base" local previous="$STORAGE/windows.base"
if [ -f "$previous" ]; then if [ -f "$previous" ]; then
previous=$(<"$previous") previous=$(<"$previous")
previous="${previous//[![:print:]]/}"
if [ -n "$previous" ]; then if [ -n "$previous" ]; then
previous="$STORAGE/$previous" if [[ "${STORAGE,,}/${previous,,}" != "${iso,,}" ]]; then
if [[ "${previous,,}" != "${iso,,}" ]]; then
if [ -f "$boot" ] && hasDisk; then if [ -f "$boot" ] && hasDisk; then
info "Detected that the version was changed, but ignoring this because Windows is already installed." if [[ "${iso,,}" == "${STORAGE,,}/windows."* ]]; then
info "Please start with an empty /storage folder, if you want to install a different version of Windows." method="your custom .iso file"
else
if [[ "${previous,,}" != "windows."* ]]; then
method="the VERSION variable"
fi
fi
if [ -n "$method" ]; then
info "Detected that $method was changed, but ignoring this because Windows is already installed."
info "Please start with an empty /storage folder, if you want to install a different version of Windows."
fi
return 0 return 0
fi fi
[ -f "$previous" ] && rm -f "$previous" rm -f "$STORAGE/$previous"
return 1 return 1
fi fi
fi fi
@@ -118,6 +128,8 @@ finishInstall() {
rm -f "$STORAGE/windows.old" rm -f "$STORAGE/windows.old"
rm -f "$STORAGE/windows.vga" rm -f "$STORAGE/windows.vga"
rm -f "$STORAGE/windows.net"
rm -f "$STORAGE/windows.usb"
rm -f "$STORAGE/windows.args" rm -f "$STORAGE/windows.args"
rm -f "$STORAGE/windows.base" rm -f "$STORAGE/windows.base"
rm -f "$STORAGE/windows.boot" rm -f "$STORAGE/windows.boot"
@@ -160,10 +172,22 @@ finishInstall() {
echo "$ARGS" > "$STORAGE/windows.args" echo "$ARGS" > "$STORAGE/windows.args"
fi fi
if [ -n "${VGA:-}" ] && [[ "${VGA:-}" != "virtio"* ]]; then
echo "$VGA" > "$STORAGE/windows.vga"
fi
if [ -n "${USB:-}" ] && [[ "${USB:-}" != "qemu-xhci"* ]]; then
echo "$USB" > "$STORAGE/windows.usb"
fi
if [ -n "${DISK_TYPE:-}" ] && [[ "${DISK_TYPE:-}" != "scsi" ]]; then if [ -n "${DISK_TYPE:-}" ] && [[ "${DISK_TYPE:-}" != "scsi" ]]; then
echo "$DISK_TYPE" > "$STORAGE/windows.type" echo "$DISK_TYPE" > "$STORAGE/windows.type"
fi fi
if [ -n "${ADAPTER:-}" ] && [[ "${ADAPTER:-}" != "virtio-net-pci" ]]; then
echo "$ADAPTER" > "$STORAGE/windows.net"
fi
rm -rf "$TMP" rm -rf "$TMP"
return 0 return 0
} }
@@ -175,6 +199,7 @@ abortInstall() {
local efi local efi
[[ "${iso,,}" == *".esd" ]] && exit 60 [[ "${iso,,}" == *".esd" ]] && exit 60
[[ "${UNPACK:-}" == [Yy1]* ]] && exit 60
efi=$(find "$dir" -maxdepth 1 -type d -iname efi | head -n 1) efi=$(find "$dir" -maxdepth 1 -type d -iname efi | head -n 1)
@@ -199,13 +224,19 @@ abortInstall() {
detectCustom() { detectCustom() {
local file base local dir file base
local fname="custom.iso" local fname="custom.iso"
local boot="$STORAGE/windows.boot"
CUSTOM="" CUSTOM=""
if [ -d "/$fname" ]; then dir=$(find / -maxdepth 1 -type d -iname "$fname" | head -n 1)
error "The file /$fname has an invalid path!" && return 1 [ ! -d "$dir" ] && dir=$(find "$STORAGE" -maxdepth 1 -type d -iname "$fname" | head -n 1)
if [ -d "$dir" ]; then
if ! hasDisk || [ ! -f "$boot" ]; then
error "The bind $dir maps to a file that does not exist!" && return 1
fi
fi fi
file=$(find / -maxdepth 1 -type f -iname "$fname" | head -n 1) file=$(find / -maxdepth 1 -type f -iname "$fname" | head -n 1)
@@ -320,7 +351,7 @@ extractImage() {
local dir="$2" local dir="$2"
local version="$3" local version="$3"
local desc="local ISO" local desc="local ISO"
local size size_gb space space_gb local file size size_gb space space_gb
if [ -z "$CUSTOM" ]; then if [ -z "$CUSTOM" ]; then
desc="downloaded ISO" desc="downloaded ISO"
@@ -359,7 +390,26 @@ extractImage() {
error "Failed to extract ISO file: $iso" && return 1 error "Failed to extract ISO file: $iso" && return 1
fi fi
LABEL=$(isoinfo -d -i "$iso" | sed -n 's/Volume id: //p') if [[ "${UNPACK:-}" != [Yy1]* ]]; then
LABEL=$(isoinfo -d -i "$iso" | sed -n 's/Volume id: //p')
else
file=$(find "$dir" -maxdepth 1 -type f -iname "*.iso" | head -n 1)
if [ -z "$file" ]; then
error "Failed to find any .iso file in archive!" && return 1
fi
if ! 7z x "$file" -o"$dir" > /dev/null; then
error "Failed to extract archive!" && return 1
fi
LABEL=$(isoinfo -d -i "$file" | sed -n 's/Volume id: //p')
rm -f "$file"
fi
return 0 return 0
} }
@@ -494,7 +544,7 @@ setXML() {
local file="/custom.xml" local file="/custom.xml"
if [ -d "$file" ]; then if [ -d "$file" ]; then
warn "The file $file has an invalid path!" error "The bind $file maps to a file that does not exist!" && exit 67
fi fi
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$STORAGE/custom.xml" [ ! -f "$file" ] || [ ! -s "$file" ] && file="$STORAGE/custom.xml"
@@ -581,6 +631,10 @@ detectImage() {
info "Detected: $desc" info "Detected: $desc"
setXML "" && return 0 setXML "" && return 0
if [[ "$DETECTED" == "win81x86"* ]] || [[ "$DETECTED" == "win10x86"* ]]; then
error "The 32-bit version of $desc is not supported!" && return 1
fi
msg="the answer file for $desc was not found ($DETECTED.xml)" msg="the answer file for $desc was not found ($DETECTED.xml)"
local fallback="/run/assets/${DETECTED%%-*}.xml" local fallback="/run/assets/${DETECTED%%-*}.xml"
@@ -669,16 +723,17 @@ updateXML() {
sed -i "s/<Username>Docker<\/Username>/<Username>$user<\/Username>/g" "$asset" sed -i "s/<Username>Docker<\/Username>/<Username>$user<\/Username>/g" "$asset"
fi fi
if [ -n "$PASSWORD" ]; then [ -n "$PASSWORD" ] && pass="$PASSWORD" || pass="admin"
pass=$(printf '%s' "${PASSWORD}Password" | iconv -f utf-8 -t utf-16le | base64 -w 0)
admin=$(printf '%s' "${PASSWORD}AdministratorPassword" | iconv -f utf-8 -t utf-16le | base64 -w 0) pw=$(printf '%s' "${pass}Password" | iconv -f utf-8 -t utf-16le | base64 -w 0)
sed -i "s/<Value>password<\/Value>/<Value>$admin<\/Value>/g" "$asset" admin=$(printf '%s' "${pass}AdministratorPassword" | iconv -f utf-8 -t utf-16le | base64 -w 0)
sed -i "s/<PlainText>true<\/PlainText>/<PlainText>false<\/PlainText>/g" "$asset"
sed -z "s/<Password>...........<Value \/>/<Password>\n <Value>$pass<\/Value>/g" -i "$asset" sed -i "s/<Value>password<\/Value>/<Value>$admin<\/Value>/g" "$asset"
sed -z "s/<Password>...............<Value \/>/<Password>\n <Value>$pass<\/Value>/g" -i "$asset" sed -i "s/<PlainText>true<\/PlainText>/<PlainText>false<\/PlainText>/g" "$asset"
sed -z "s/<AdministratorPassword>...........<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset" sed -z "s/<Password>...........<Value \/>/<Password>\n <Value>$pw<\/Value>/g" -i "$asset"
sed -z "s/<AdministratorPassword>...............<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset" sed -z "s/<Password>...............<Value \/>/<Password>\n <Value>$pw<\/Value>/g" -i "$asset"
fi sed -z "s/<AdministratorPassword>...........<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset"
sed -z "s/<AdministratorPassword>...............<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset"
if [ -n "$EDITION" ]; then if [ -n "$EDITION" ]; then
[[ "${EDITION^^}" == "CORE" ]] && EDITION="STANDARDCORE" [[ "${EDITION^^}" == "CORE" ]] && EDITION="STANDARDCORE"
@@ -726,7 +781,11 @@ addDriver() {
if [ -z "$folder" ]; then if [ -z "$folder" ]; then
desc=$(printVersion "$id" "$id") desc=$(printVersion "$id" "$id")
warn "no \"$driver\" driver available for \"$desc\" !" && return 0 if [[ "${id,,}" != *"x86"* ]]; then
warn "no \"$driver\" driver available for \"$desc\" !" && return 0
else
warn "no \"$driver\" driver available for the 32-bit version of \"$desc\" !" && return 0
fi
fi fi
[ ! -d "$path/$driver/$folder" ] && return 0 [ ! -d "$path/$driver/$folder" ] && return 0
@@ -1006,19 +1065,48 @@ bootWindows() {
if [ -f "$STORAGE/windows.args" ]; then if [ -f "$STORAGE/windows.args" ]; then
ARGS=$(<"$STORAGE/windows.args") ARGS=$(<"$STORAGE/windows.args")
ARGS="${ARGS//[![:print:]]/}"
ARGUMENTS="$ARGS ${ARGUMENTS:-}" ARGUMENTS="$ARGS ${ARGUMENTS:-}"
fi fi
if [ -s "$STORAGE/windows.vga" ] && [ -f "$STORAGE/windows.vga" ]; then
if [ -z "${VGA:-}" ]; then
VGA=$(<"$STORAGE/windows.vga")
VGA="${VGA//[![:print:]]/}"
fi
fi
if [ -s "$STORAGE/windows.usb" ] && [ -f "$STORAGE/windows.usb" ]; then
if [ -z "${USB:-}" ]; then
USB=$(<"$STORAGE/windows.usb")
USB="${USB//[![:print:]]/}"
fi
fi
if [ -s "$STORAGE/windows.net" ] && [ -f "$STORAGE/windows.net" ]; then
if [ -z "${ADAPTER:-}" ]; then
ADAPTER=$(<"$STORAGE/windows.net")
ADAPTER="${ADAPTER//[![:print:]]/}"
fi
fi
if [ -s "$STORAGE/windows.type" ] && [ -f "$STORAGE/windows.type" ]; then if [ -s "$STORAGE/windows.type" ] && [ -f "$STORAGE/windows.type" ]; then
[ -z "${DISK_TYPE:-}" ] && DISK_TYPE=$(<"$STORAGE/windows.type") if [ -z "${DISK_TYPE:-}" ]; then
DISK_TYPE=$(<"$STORAGE/windows.type")
DISK_TYPE="${DISK_TYPE//[![:print:]]/}"
fi
fi fi
if [ -s "$STORAGE/windows.mode" ] && [ -f "$STORAGE/windows.mode" ]; then if [ -s "$STORAGE/windows.mode" ] && [ -f "$STORAGE/windows.mode" ]; then
BOOT_MODE=$(<"$STORAGE/windows.mode") BOOT_MODE=$(<"$STORAGE/windows.mode")
BOOT_MODE="${BOOT_MODE//[![:print:]]/}"
fi fi
if [ -s "$STORAGE/windows.old" ] && [ -f "$STORAGE/windows.old" ]; then if [ -s "$STORAGE/windows.old" ] && [ -f "$STORAGE/windows.old" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && MACHINE=$(<"$STORAGE/windows.old") if [[ "${PLATFORM,,}" == "x64" ]]; then
MACHINE=$(<"$STORAGE/windows.old")
MACHINE="${MACHINE//[![:print:]]/}"
fi
fi fi
return 0 return 0

View File

@@ -93,6 +93,7 @@ download_windows() {
# uuidgen: For MacOS (installed by default) and other systems (e.g. with no /proc) that don't have a kernel interface for generating random UUIDs # uuidgen: For MacOS (installed by default) and other systems (e.g. with no /proc) that don't have a kernel interface for generating random UUIDs
session_id=$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random) session_id=$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random)
session_id="${session_id//[![:print:]]/}"
# Get product edition ID for latest release of given Windows version # Get product edition ID for latest release of given Windows version
# Product edition ID: This specifies both the Windows release (e.g. 22H2) and edition ("multi-edition" is default, either Home/Pro/Edu/etc., we select "Pro" in the answer files) in one number # Product edition ID: This specifies both the Windows release (e.g. 22H2) and edition ("multi-edition" is default, either Home/Pro/Edu/etc., we select "Pro" in the answer files) in one number
@@ -313,7 +314,7 @@ getWindows() {
info "$msg" && html "$msg" info "$msg" && html "$msg"
case "${version,,}" in case "${version,,}" in
"win2008r2" | "win7${PLATFORM,,}"* | "win81${PLATFORM,,}"* | "win11${PLATFORM,,}-enterprise-iot"* | "win11${PLATFORM,,}-enterprise-ltsc"* ) "win2008r2" | "win81${PLATFORM,,}"* | "win11${PLATFORM,,}-enterprise-iot"* | "win11${PLATFORM,,}-enterprise-ltsc"* )
if [[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-"* ]]; then if [[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-"* ]]; then
error "No download in the $language language available for $edition!" error "No download in the $language language available for $edition!"
MIDO_URL="" && return 1 MIDO_URL="" && return 1
@@ -341,7 +342,7 @@ getWindows() {
"win2025-eval" | "win2022-eval" | "win2019-eval" | "win2019-hv" | "win2016-eval" | "win2012r2-eval" ) "win2025-eval" | "win2022-eval" | "win2019-eval" | "win2019-hv" | "win2016-eval" | "win2012r2-eval" )
download_windows_eval "$version" "$lang" "$edition" && return 0 download_windows_eval "$version" "$lang" "$edition" && return 0
;; ;;
"win7${PLATFORM,,}"* | "win81${PLATFORM,,}-enterprise"* | "win2008r2" ) "win81${PLATFORM,,}-enterprise"* | "win2008r2" )
;; ;;
* ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;; * ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;;
esac esac
@@ -471,6 +472,18 @@ getESD() {
return 0 return 0
} }
isCompressed() {
local file="$1"
case "${file,,}" in
*".7z" | *".zip" | *".rar" | *".lzma" | *".bz" | *".bz2" )
return 0 ;;
esac
return 1
}
verifyFile() { verifyFile() {
local iso="$1" local iso="$1"
@@ -516,6 +529,7 @@ downloadFile() {
local size="$4" local size="$4"
local lang="$5" local lang="$5"
local desc="$6" local desc="$6"
local msg="Downloading $desc"
local rc total total_gb progress domain dots space folder local rc total total_gb progress domain dots space folder
rm -f "$iso" rm -f "$iso"
@@ -534,8 +548,8 @@ downloadFile() {
progress="--progress=dot:giga" progress="--progress=dot:giga"
fi fi
local msg="Downloading $desc"
html "$msg..." html "$msg..."
/run/progress.sh "$iso" "$size" "$msg ([P])..." &
domain=$(echo "$url" | awk -F/ '{print $3}') domain=$(echo "$url" | awk -F/ '{print $3}')
dots=$(echo "$domain" | tr -cd '.' | wc -c) dots=$(echo "$domain" | tr -cd '.' | wc -c)
@@ -546,7 +560,6 @@ downloadFile() {
fi fi
info "$msg..." info "$msg..."
/run/progress.sh "$iso" "$size" "$msg ([P])..." &
{ wget "$url" -O "$iso" -q --timeout=30 --no-http-keep-alive --show-progress "$progress"; rc=$?; } || : { wget "$url" -O "$iso" -q --timeout=30 --no-http-keep-alive --show-progress "$progress"; rc=$?; } || :
@@ -559,6 +572,7 @@ downloadFile() {
error "Invalid download link: $url (is only $total_gb ?). Please report this at $SUPPORT/issues." && return 1 error "Invalid download link: $url (is only $total_gb ?). Please report this at $SUPPORT/issues." && return 1
fi fi
verifyFile "$iso" "$size" "$total" "$sum" || return 1 verifyFile "$iso" "$size" "$total" "$sum" || return 1
isCompressed "$url" && UNPACK="Y"
html "Download finished successfully..." && return 0 html "Download finished successfully..." && return 0
fi fi
@@ -583,12 +597,14 @@ downloadImage() {
local msg="Will retry after $delay seconds..." local msg="Will retry after $delay seconds..."
if [[ "${version,,}" == "http"* ]]; then if [[ "${version,,}" == "http"* ]]; then
base=$(basename "$iso") base=$(basename "$iso")
desc=$(fromFile "$base") desc=$(fromFile "$base")
downloadFile "$iso" "$version" "" "" "" "$desc" && return 0 downloadFile "$iso" "$version" "" "" "" "$desc" && return 0
info "$msg" && html "$msg" && sleep "$delay" info "$msg" && html "$msg" && sleep "$delay"
downloadFile "$iso" "$version" "" "" "" "$desc" && return 0 downloadFile "$iso" "$version" "" "" "" "$desc" && return 0
rm -f "$iso" rm -f "$iso"
return 1 return 1
fi fi