mirror of
https://github.com/dockur/windows.git
synced 2026-08-03 20:47:12 +01:00
Compare commits
150 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 85a7529b4e | |||
| 360d8c11d9 | |||
| c1b999849a | |||
| 69f35d3aa1 | |||
| fed8b00b45 | |||
| d92c2f276c | |||
| 85fedb00d6 | |||
| f0a9a729c6 | |||
| 0f331c234c | |||
| 988f47fb40 | |||
| ba6d34c362 | |||
| a8c38640c0 | |||
| 0b119d589c | |||
| 3a0b973c0b | |||
| 08f058b758 | |||
| 99c1f10263 | |||
| 7a20e4aea8 | |||
| 559033a57d | |||
| 936fde9ac0 | |||
| 28571435bb | |||
| 633cbefb86 | |||
| c488bdee93 | |||
| 0d22f9150e | |||
| 23a1028d8c | |||
| 2436d0e764 | |||
| de136699cc | |||
| ebd4b00a7f | |||
| 9aa074f877 | |||
| efe9915c24 | |||
| 67f3f23a35 | |||
| 57a766c738 | |||
| 35fe5aab9c | |||
| 1e12c90226 | |||
| 068b3cb966 | |||
| b4754f5826 | |||
| 029f59db2e | |||
| 8ad66b62a8 | |||
| 075b6bc97f | |||
| 9c4ac26372 | |||
| 6d79a7c9ab | |||
| 8006b7f992 | |||
| da032a401e | |||
| cfc44829f8 | |||
| 47dcf3732c | |||
| e377c62aaf | |||
| 0bee04a7dd | |||
| fceb286849 | |||
| d443ca377d | |||
| e6b0e530ba | |||
| aacf70657a | |||
| 7a81862263 | |||
| 0538bd5e32 | |||
| c763015734 | |||
| 700b3b0902 | |||
| fc8c850b6d | |||
| 11acdefafb | |||
| 264d03e871 | |||
| 38c65b2565 | |||
| c2e6c65248 | |||
| 4325600626 | |||
| 19d5951aac | |||
| c70c0c304b | |||
| b590190cc3 | |||
| 57f3a4a723 | |||
| 9c6c348f5d | |||
| 67eec73e33 | |||
| c768ba894d | |||
| 0c9472b62c | |||
| 8d2f27bd67 | |||
| bcae867d68 | |||
| 77c164a3fa | |||
| f088a60e2c | |||
| 6dc5ce7919 | |||
| ba478700de | |||
| 6e45deea2f | |||
| 0bc2380452 | |||
| e1732e66ec | |||
| 8f70ffa902 | |||
| 7b4404db6b | |||
| 2412a3ed18 | |||
| 8c57b119cf | |||
| 40867f6e85 | |||
| b5d8c2ad08 | |||
| 603465a687 | |||
| d8a548c3fb | |||
| 60e5925d72 | |||
| 398344163f | |||
| f2809a8929 | |||
| 7fd7ab3050 | |||
| fddbebadae | |||
| 34f312ddff | |||
| daea34a10f | |||
| c5417e8fca | |||
| 603ee5f93b | |||
| 4926ad0ea9 | |||
| a81c45de30 | |||
| 85bacbec63 | |||
| 8f1335d7f8 | |||
| 8d50472167 | |||
| 173f35d21b | |||
| e21418b228 | |||
| 1246667afa | |||
| 247e4e0b38 | |||
| c534901402 | |||
| 49e962e56a | |||
| 3e37a04d96 | |||
| 0ea63962af | |||
| 4d01a81586 | |||
| d8e51d8965 | |||
| 8d4788f7c0 | |||
| 8ec135d826 | |||
| 0400f5f45d | |||
| 588969ae5f | |||
| c7aac1edcf | |||
| ea03c67a04 | |||
| bdb0488151 | |||
| ad6f87046a | |||
| e7a3894210 | |||
| 8443559a76 | |||
| 6dbac13cd1 | |||
| fd907bb78a | |||
| 1a6a2dbad0 | |||
| 11a19f6a9d | |||
| 544501107a | |||
| 122d1ff98e | |||
| c1c44c4da7 | |||
| f661df3abc | |||
| a0bcd719be | |||
| 9236127a86 | |||
| fa606aec53 | |||
| 8790b4ec7c | |||
| e3cf3ccf3d | |||
| b244fa544f | |||
| 4cb7e1074f | |||
| ac106067bd | |||
| 0e95680704 | |||
| 5476760551 | |||
| 0caa4d76b8 | |||
| 4e0a29605b | |||
| c3ba25bfb7 | |||
| 10449a3d29 | |||
| b998cd4c7f | |||
| 6f84823117 | |||
| c997bf7765 | |||
| c6a8c0b702 | |||
| f1ea8ee227 | |||
| 0ab3198ded | |||
| 42a149d7b9 | |||
| 0b0de7de14 | |||
| 8472d700dc |
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "windows",
|
|
||||||
"service": "windows",
|
|
||||||
"forwardPorts": [8006],
|
|
||||||
"dockerComposeFile": ".github/codespaces.yml"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows 11 Enterprise",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "11e"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows 11 LTSC",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "11l"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows 10 Pro",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "10"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows 10 Enterprise",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "10e"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows 10 LTSC",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "10l"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows 8.1 Enterprise",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "8e"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows 7 Ultimate",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "7u"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows Vista Ultimate",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "vu"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows XP Professional",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "xp"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows 2000 Professional",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "2k"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows Server 2025",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "2025"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows Server 2022",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "2022"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows Server 2019",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "2019"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows Server 2016",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "2016"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows Server 2012 R2",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "2012"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows Server 2008 R2",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "2008"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows Server 2003",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "2003"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Tiny11",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "tiny11"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Tiny11 Core",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "core11"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Tiny11 Nano",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "nano11"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Tiny10",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "tiny10"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "../codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
services:
|
services:
|
||||||
windows:
|
windows:
|
||||||
image: dockurr/windows
|
|
||||||
container_name: windows
|
container_name: windows
|
||||||
|
image: ghcr.io/dockur/windows
|
||||||
environment:
|
environment:
|
||||||
VERSION: "11"
|
RAM_SIZE: "half"
|
||||||
RAM_SIZE: "max"
|
|
||||||
DISK_SIZE: "max"
|
DISK_SIZE: "max"
|
||||||
CPU_CORES: "max"
|
CPU_CORES: "max"
|
||||||
devices:
|
devices:
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Windows 11 Pro",
|
||||||
|
"service": "windows",
|
||||||
|
"containerEnv": {
|
||||||
|
"VERSION": "11"
|
||||||
|
},
|
||||||
|
"forwardPorts": [8006],
|
||||||
|
"portsAttributes": {
|
||||||
|
"8006": {
|
||||||
|
"label": "Web",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otherPortsAttributes": {
|
||||||
|
"onAutoForward": "ignore"
|
||||||
|
},
|
||||||
|
"dockerComposeFile": "codespaces.yml",
|
||||||
|
"initializeCommand": "docker system prune --all --force"
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
.dockerignore
|
.dockerignore
|
||||||
|
.devcontainer
|
||||||
.git
|
.git
|
||||||
.github
|
.github
|
||||||
.gitignore
|
.gitignore
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ updates:
|
|||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: weekly
|
interval: weekly
|
||||||
|
cooldown:
|
||||||
|
default-days: 7
|
||||||
- package-ecosystem: github-actions
|
- package-ecosystem: github-actions
|
||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: weekly
|
interval: weekly
|
||||||
|
cooldown:
|
||||||
|
default-days: 7
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 59 KiB |
@@ -22,13 +22,13 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
name: Docker metadata
|
name: Docker metadata
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v6
|
||||||
with:
|
with:
|
||||||
context: git
|
context: git
|
||||||
images: |
|
images: |
|
||||||
@@ -43,23 +43,23 @@ jobs:
|
|||||||
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
|
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v4
|
||||||
-
|
-
|
||||||
name: Login into Docker Hub
|
name: Login into Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
-
|
-
|
||||||
name: Login to GitHub Container Registry
|
name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-
|
-
|
||||||
name: Build Docker image
|
name: Build Docker image
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
|||||||
@@ -7,19 +7,30 @@ jobs:
|
|||||||
name: shellcheck
|
name: shellcheck
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
-
|
||||||
- name: Run ShellCheck
|
name: Checkout
|
||||||
|
uses: actions/checkout@v7
|
||||||
|
- parallel:
|
||||||
|
-
|
||||||
|
name: Run ShellCheck
|
||||||
uses: ludeeus/action-shellcheck@master
|
uses: ludeeus/action-shellcheck@master
|
||||||
env:
|
env:
|
||||||
SHELLCHECK_OPTS: -x --source-path=src -e SC1091 -e SC2001 -e SC2002 -e SC2034 -e SC2064 -e SC2153 -e SC2317 -e SC2028
|
SHELLCHECK_OPTS: -x --source-path=src -e SC1091 -e SC2001 -e SC2002 -e SC2034 -e SC2064 -e SC2153 -e SC2317 -e SC2028
|
||||||
- name: Validate XML
|
-
|
||||||
uses: action-pack/valid-xml@v1
|
name: Lint Dockerfile
|
||||||
with:
|
|
||||||
path: "assets"
|
|
||||||
file-endings: ".xml"
|
|
||||||
- name: Lint Dockerfile
|
|
||||||
uses: hadolint/hadolint-action@v3.3.0
|
uses: hadolint/hadolint-action@v3.3.0
|
||||||
with:
|
with:
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
ignore: DL3006,DL3008
|
ignore: DL3006,DL3008
|
||||||
failure-threshold: warning
|
failure-threshold: warning
|
||||||
|
-
|
||||||
|
name: Validate XML
|
||||||
|
uses: action-pack/valid-xml@v1
|
||||||
|
with:
|
||||||
|
path: "assets"
|
||||||
|
file-endings: ".xml"
|
||||||
|
-
|
||||||
|
name: Validate JSON and YML files
|
||||||
|
uses: GrantBirki/json-yaml-validate@v5.0.0
|
||||||
|
with:
|
||||||
|
yaml_exclude_regex: ".*\\kubernetes\\.yml$"
|
||||||
|
|||||||
+12
-10
@@ -12,13 +12,15 @@ jobs:
|
|||||||
dockerHubDescription:
|
dockerHubDescription:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
-
|
||||||
-
|
name: Checkout repo
|
||||||
name: Docker Hub Description
|
uses: actions/checkout@v7
|
||||||
uses: peter-evans/dockerhub-description@v5
|
-
|
||||||
with:
|
name: Docker Hub Description
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
uses: peter-evans/dockerhub-description@v5
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
with:
|
||||||
repository: ${{ secrets.DOCKERHUB_REPO }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
short-description: ${{ github.event.repository.description }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
readme-filepath: ./readme.md
|
repository: ${{ secrets.DOCKERHUB_REPO }}
|
||||||
|
short-description: ${{ github.event.repository.description }}
|
||||||
|
readme-filepath: ./readme.md
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
name: Links
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: links
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
links:
|
||||||
|
name: Links
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
packages: read
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
-
|
||||||
|
name: Validate Links
|
||||||
|
run: |
|
||||||
|
errors=0
|
||||||
|
count=0
|
||||||
|
host=""
|
||||||
|
declare -A seen
|
||||||
|
wget https://github.com/lwthiker/curl-impersonate/releases/download/v0.6.1/curl-impersonate-v0.6.1.x86_64-linux-gnu.tar.gz
|
||||||
|
tar -xzf curl-impersonate-v0.6.1.x86_64-linux-gnu.tar.gz
|
||||||
|
sudo cp curl-impersonate-ff /usr/local/bin/
|
||||||
|
check() {
|
||||||
|
local url="$1" http
|
||||||
|
http=$(curl-impersonate-ff -sSL -o /dev/null -w "%{http_code}" --max-time 10 -I -- "$url" 2>&1) || http="000"
|
||||||
|
[[ "$http" == 2* ]] && return 0
|
||||||
|
http=$(curl-impersonate-ff -sSL -o /dev/null -w "%{http_code}" --max-time 10 -r "0-0" -- "$url" 2>&1) || http="000"
|
||||||
|
[[ "$http" == 2* ]]
|
||||||
|
}
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*local[[:space:]]+host=\"(https://[^\"]+)\" ]]; then
|
||||||
|
host="${BASH_REMATCH[1]%/}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
[[ "$line" =~ ^[[:space:]]*url=\"(.+)\" ]] || continue
|
||||||
|
val="${BASH_REMATCH[1]#/}"
|
||||||
|
if [[ "$val" == https://* ]]; then
|
||||||
|
url="$val"
|
||||||
|
elif [[ -n "$host" ]]; then
|
||||||
|
url="$host/$val"
|
||||||
|
else
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
[[ -v seen[$url] ]] && continue
|
||||||
|
seen[$url]=1
|
||||||
|
count=$((count + 1))
|
||||||
|
if check "$url"; then
|
||||||
|
echo " OK: $url"
|
||||||
|
else
|
||||||
|
echo "FAIL: $url"
|
||||||
|
errors=$((errors + 1))
|
||||||
|
fi
|
||||||
|
done < "src/define.sh"
|
||||||
|
echo ""
|
||||||
|
printf '%d/%d links valid\n' "$(( count - errors ))" "$count"
|
||||||
|
(( errors == 0 ))
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
name: "Review"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
checks: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
review:
|
||||||
|
name: review
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v7
|
||||||
|
- parallel:
|
||||||
|
-
|
||||||
|
name: Spelling
|
||||||
|
uses: reviewdog/action-misspell@v1
|
||||||
|
with:
|
||||||
|
locale: "US"
|
||||||
|
level: warning
|
||||||
|
pattern: |
|
||||||
|
*.md
|
||||||
|
*.sh
|
||||||
|
reporter: github-pr-review
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Hadolint
|
||||||
|
uses: reviewdog/action-hadolint@v1
|
||||||
|
with:
|
||||||
|
level: warning
|
||||||
|
fail_level: error
|
||||||
|
reporter: github-pr-review
|
||||||
|
hadolint_ignore: DL3006 DL3008
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: YamlLint
|
||||||
|
uses: reviewdog/action-yamllint@v1
|
||||||
|
with:
|
||||||
|
level: warning
|
||||||
|
reporter: github-pr-review
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: ActionLint
|
||||||
|
uses: reviewdog/action-actionlint@v1
|
||||||
|
with:
|
||||||
|
level: warning
|
||||||
|
reporter: github-pr-review
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Shellformat
|
||||||
|
uses: reviewdog/action-shfmt@v1
|
||||||
|
if: false
|
||||||
|
with:
|
||||||
|
level: warning
|
||||||
|
fail_on_error: "true"
|
||||||
|
shfmt_flags: "-i 2 -ci -bn"
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Shellcheck
|
||||||
|
uses: reviewdog/action-shellcheck@v1
|
||||||
|
with:
|
||||||
|
level: warning
|
||||||
|
fail_level: error
|
||||||
|
reporter: github-pr-review
|
||||||
|
shellcheck_flags: -x -e SC1091 -e SC2001 -e SC2002 -e SC2034 -e SC2064 -e SC2153 -e SC2317 -e SC2028
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
+25
-16
@@ -3,37 +3,46 @@
|
|||||||
ARG VERSION_ARG="latest"
|
ARG VERSION_ARG="latest"
|
||||||
FROM scratch AS build-amd64
|
FROM scratch AS build-amd64
|
||||||
|
|
||||||
COPY --from=qemux/qemu:7.24 / /
|
COPY --from=qemux/qemu:7.36 / /
|
||||||
|
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
ARG VERSION_WSDD="1.26"
|
||||||
|
ARG VERSION_VIRTIO="1.9.58"
|
||||||
|
|
||||||
ARG DEBCONF_NOWARNINGS="yes"
|
ARG DEBCONF_NOWARNINGS="yes"
|
||||||
ARG DEBIAN_FRONTEND="noninteractive"
|
ARG DEBIAN_FRONTEND="noninteractive"
|
||||||
ARG DEBCONF_NONINTERACTIVE_SEEN="true"
|
ARG DEBCONF_NONINTERACTIVE_SEEN="true"
|
||||||
|
|
||||||
RUN set -eu && \
|
RUN <<EOF
|
||||||
apt-get update && \
|
set -eu
|
||||||
apt-get --no-install-recommends -y install \
|
|
||||||
samba \
|
apt-get update
|
||||||
wimtools \
|
apt-get --no-install-recommends -y install \
|
||||||
dos2unix \
|
samba \
|
||||||
cabextract \
|
wimtools \
|
||||||
libxml2-utils \
|
dos2unix \
|
||||||
libarchive-tools && \
|
cabextract \
|
||||||
wget "https://github.com/gershnik/wsdd-native/releases/download/v1.21/wsddn_1.21_${TARGETARCH}.deb" -O /tmp/wsddn.deb -q && \
|
libxml2-utils \
|
||||||
dpkg -i /tmp/wsddn.deb && \
|
libarchive-tools
|
||||||
apt-get clean && \
|
|
||||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
# Install wsdd
|
||||||
|
wget "https://github.com/gershnik/wsdd-native/releases/download/v${VERSION_WSDD}/wsddn_${VERSION_WSDD}_${TARGETARCH}.deb" -O /tmp/wsddn.deb -q --timeout=10
|
||||||
|
dpkg -i /tmp/wsddn.deb
|
||||||
|
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
EOF
|
||||||
|
|
||||||
COPY --chmod=755 ./src /run/
|
COPY --chmod=755 ./src /run/
|
||||||
COPY --chmod=755 ./assets /run/assets
|
COPY --chmod=755 ./assets /run/assets
|
||||||
|
|
||||||
ADD --chmod=664 https://github.com/qemus/virtiso-whql/releases/download/v1.9.47-0/virtio-win-1.9.47.tar.xz /var/drivers.txz
|
ADD --chmod=664 https://github.com/qemus/virtiso-whql/releases/download/v${VERSION_VIRTIO}-0/virtio-win-${VERSION_VIRTIO}.tar.xz /var/drivers.txz
|
||||||
|
|
||||||
FROM dockurr/windows-arm:${VERSION_ARG} AS build-arm64
|
FROM dockurr/windows-arm:${VERSION_ARG} AS build-arm64
|
||||||
FROM build-${TARGETARCH}
|
FROM build-${TARGETARCH}
|
||||||
|
|
||||||
ARG VERSION_ARG="0.00"
|
ARG VERSION_ARG="0.00"
|
||||||
RUN echo "$VERSION_ARG" > /run/version
|
RUN echo "$VERSION_ARG" > /etc/version
|
||||||
|
|
||||||
VOLUME /storage
|
VOLUME /storage
|
||||||
EXPOSE 3389 8006
|
EXPOSE 3389 8006
|
||||||
|
|||||||
@@ -246,6 +246,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>26</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -249,6 +249,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>26</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -255,6 +255,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>26</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -252,6 +252,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>26</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -249,6 +249,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>26</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -269,6 +269,11 @@
|
|||||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||||
<Description>Install VirtIO display driver</Description>
|
<Description>Install VirtIO display driver</Description>
|
||||||
</RunSynchronousCommand>
|
</RunSynchronousCommand>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>27</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -272,6 +272,11 @@
|
|||||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||||
<Description>Install VirtIO display driver</Description>
|
<Description>Install VirtIO display driver</Description>
|
||||||
</RunSynchronousCommand>
|
</RunSynchronousCommand>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>27</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -272,6 +272,11 @@
|
|||||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||||
<Description>Install VirtIO display driver</Description>
|
<Description>Install VirtIO display driver</Description>
|
||||||
</RunSynchronousCommand>
|
</RunSynchronousCommand>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>27</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -272,6 +272,11 @@
|
|||||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||||
<Description>Install VirtIO display driver</Description>
|
<Description>Install VirtIO display driver</Description>
|
||||||
</RunSynchronousCommand>
|
</RunSynchronousCommand>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>27</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -272,6 +272,11 @@
|
|||||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||||
<Description>Install VirtIO display driver</Description>
|
<Description>Install VirtIO display driver</Description>
|
||||||
</RunSynchronousCommand>
|
</RunSynchronousCommand>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>27</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -154,6 +154,15 @@
|
|||||||
</FirewallGroup>
|
</FirewallGroup>
|
||||||
</FirewallGroups>
|
</FirewallGroups>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
<RunSynchronous>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
|
</RunSynchronous>
|
||||||
|
</component>
|
||||||
</settings>
|
</settings>
|
||||||
<settings pass="oobeSystem">
|
<settings pass="oobeSystem">
|
||||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -157,6 +157,15 @@
|
|||||||
</FirewallGroup>
|
</FirewallGroup>
|
||||||
</FirewallGroups>
|
</FirewallGroups>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
<RunSynchronous>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
|
</RunSynchronous>
|
||||||
|
</component>
|
||||||
</settings>
|
</settings>
|
||||||
<settings pass="oobeSystem">
|
<settings pass="oobeSystem">
|
||||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -155,6 +155,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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -158,6 +158,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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -155,6 +155,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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -158,6 +158,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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -164,6 +164,11 @@
|
|||||||
<Path>dism.exe /online /Disable-Feature /FeatureName:Microsoft-Hyper-V /NoRestart</Path>
|
<Path>dism.exe /online /Disable-Feature /FeatureName:Microsoft-Hyper-V /NoRestart</Path>
|
||||||
<Description>Disable Hyper-V role</Description>
|
<Description>Disable Hyper-V role</Description>
|
||||||
</RunSynchronousCommand>
|
</RunSynchronousCommand>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>3</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -162,6 +162,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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -162,6 +162,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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -164,6 +164,11 @@
|
|||||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||||
<Description>Install VirtIO display driver</Description>
|
<Description>Install VirtIO display driver</Description>
|
||||||
</RunSynchronousCommand>
|
</RunSynchronousCommand>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>4</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -167,6 +167,11 @@
|
|||||||
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
<Path>pnputil -i -a C:\Windows\Drivers\viogpudo\viogpudo.inf</Path>
|
||||||
<Description>Install VirtIO display driver</Description>
|
<Description>Install VirtIO display driver</Description>
|
||||||
</RunSynchronousCommand>
|
</RunSynchronousCommand>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>4</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</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">
|
||||||
|
|||||||
@@ -148,6 +148,15 @@
|
|||||||
</FirewallGroup>
|
</FirewallGroup>
|
||||||
</FirewallGroups>
|
</FirewallGroups>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
<RunSynchronous>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
|
</RunSynchronous>
|
||||||
|
</component>
|
||||||
</settings>
|
</settings>
|
||||||
<settings pass="oobeSystem">
|
<settings pass="oobeSystem">
|
||||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -152,6 +152,15 @@
|
|||||||
</FirewallGroup>
|
</FirewallGroup>
|
||||||
</FirewallGroups>
|
</FirewallGroups>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
<RunSynchronous>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
|
</RunSynchronous>
|
||||||
|
</component>
|
||||||
</settings>
|
</settings>
|
||||||
<settings pass="oobeSystem">
|
<settings pass="oobeSystem">
|
||||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -152,6 +152,15 @@
|
|||||||
</FirewallGroup>
|
</FirewallGroup>
|
||||||
</FirewallGroups>
|
</FirewallGroups>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
<RunSynchronous>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
|
</RunSynchronous>
|
||||||
|
</component>
|
||||||
</settings>
|
</settings>
|
||||||
<settings pass="oobeSystem">
|
<settings pass="oobeSystem">
|
||||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -152,6 +152,15 @@
|
|||||||
</FirewallGroup>
|
</FirewallGroup>
|
||||||
</FirewallGroups>
|
</FirewallGroups>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
<RunSynchronous>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
|
</RunSynchronous>
|
||||||
|
</component>
|
||||||
</settings>
|
</settings>
|
||||||
<settings pass="oobeSystem">
|
<settings pass="oobeSystem">
|
||||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -146,6 +146,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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -149,6 +149,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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -156,6 +156,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>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
</RunSynchronous>
|
</RunSynchronous>
|
||||||
</component>
|
</component>
|
||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -90,6 +90,15 @@
|
|||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
<fDenyTSConnections>false</fDenyTSConnections>
|
<fDenyTSConnections>false</fDenyTSConnections>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
<RunSynchronous>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
|
</RunSynchronous>
|
||||||
|
</component>
|
||||||
</settings>
|
</settings>
|
||||||
<settings pass="oobeSystem">
|
<settings pass="oobeSystem">
|
||||||
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -90,6 +90,15 @@
|
|||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
<fDenyTSConnections>false</fDenyTSConnections>
|
<fDenyTSConnections>false</fDenyTSConnections>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
<RunSynchronous>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
|
</RunSynchronous>
|
||||||
|
</component>
|
||||||
</settings>
|
</settings>
|
||||||
<settings pass="oobeSystem">
|
<settings pass="oobeSystem">
|
||||||
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -90,6 +90,15 @@
|
|||||||
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
<fDenyTSConnections>false</fDenyTSConnections>
|
<fDenyTSConnections>false</fDenyTSConnections>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
<RunSynchronous>
|
||||||
|
<RunSynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Path>C:\Windows\Drivers\Balloon\blnsvr.exe -i</Path>
|
||||||
|
<Description>Install VirtIO Balloon service</Description>
|
||||||
|
</RunSynchronousCommand>
|
||||||
|
</RunSynchronous>
|
||||||
|
</component>
|
||||||
</settings>
|
</settings>
|
||||||
<settings pass="oobeSystem">
|
<settings pass="oobeSystem">
|
||||||
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
# Environment Variables
|
||||||
|
|
||||||
|
This page lists all the environment variables that can be used to configure the container.
|
||||||
|
|
||||||
|
An empty default means the variable is unset and its value is determined automatically when applicable.
|
||||||
|
|
||||||
|
## 🪟 Windows
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `VERSION` | `11` | Windows version to install, such as `10` or `11`. |
|
||||||
|
| `EDITION` | | Windows edition to install, such as `core` for Windows Server Core. |
|
||||||
|
| `LANGUAGE` | `en-US` | Windows display language, such as `English`, `en-US`, or `en`. |
|
||||||
|
| `REGION` | | Windows regional format. Uses `LANGUAGE` when unset. |
|
||||||
|
| `KEYBOARD` | | Keyboard layout. Uses `LANGUAGE` when unset. |
|
||||||
|
| `USERNAME` | `Docker` | Name of the Windows user account. |
|
||||||
|
| `PASSWORD` | `admin` | Password for the Windows account. |
|
||||||
|
| `KEY` | | Windows product key used to install and activate Windows. |
|
||||||
|
| `MANUAL` | `N` | Enables manual installation instead of unattended installation. |
|
||||||
|
| `VERIFY` | `N` | Verifies downloaded images against a predefined list of checksums. |
|
||||||
|
| `REMOVE` | `Y` | Deletes the downloaded Windows ISO after installation to save space. |
|
||||||
|
|
||||||
|
## 🧠 CPU and Memory
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `CPU_CORES` | `2` | Number of virtual CPU cores, such as `4`, `half`, or `max`. |
|
||||||
|
| `CPU_MODEL` | `host` | QEMU CPU model. |
|
||||||
|
| `CPU_FLAGS` | | Additional QEMU CPU flags. |
|
||||||
|
| `KVM` | `Y` | Enables KVM hardware acceleration. |
|
||||||
|
| `VMX` | `N` | Exposes Intel VMX virtualization extensions to the guest. |
|
||||||
|
| `HV` | `Y` | Enables Hyper-V enlightenments for Windows guests. |
|
||||||
|
| `RAM_SIZE` | `4G` | Amount of RAM assigned to Windows, such as `8G`, `half`, or `max`. |
|
||||||
|
| `RAM_CHECK` | `Y` | Checks whether enough host memory is available before starting Windows. |
|
||||||
|
|
||||||
|
## 💾 Storage
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `DISK_SIZE` | `64G` | Size of the primary disk. |
|
||||||
|
| `DISK_FMT` | `raw` | Disk image format: `raw` or `qcow2`. |
|
||||||
|
| `DISK_TYPE` | `scsi` | Disk device type, such as `sata`, `scsi`, `nvme`, or `blk`. |
|
||||||
|
| `DISK_CACHE` | `none` | Disk cache mode, such as `none` or `writeback`. |
|
||||||
|
| `DISK_IO` | `native` | Disk I/O mode, such as `native`, `threads`, or `io_uring`. |
|
||||||
|
| `DISK_DISCARD` | `unmap` | Discard/TRIM mode for the primary disk. |
|
||||||
|
| `DISK_ROTATION` | `1` | Rotation rate reported to the guest. Use `1` to identify the disk as an SSD. |
|
||||||
|
| `DISK_FLAGS` | | Additional options used when creating `qcow2` disks. |
|
||||||
|
| `ALLOCATE` | `N` | Preallocates space for the primary disk. |
|
||||||
|
| `STORAGE` | `/storage` | Storage directory used for disks, firmware variables, and downloads. |
|
||||||
|
|
||||||
|
## 🌐 Networking
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `NETWORK` | | Network mode, such as `nat`, `passt`, `slirp`, or `N` to disable networking. |
|
||||||
|
| `DHCP` | `N` | Enables macvtap networking so Windows receives an address from the external LAN through DHCP. |
|
||||||
|
| `HOST` | `Windows` | Hostname assigned to Windows. |
|
||||||
|
| `IP` | | Overrides the automatically selected guest IPv4 address. |
|
||||||
|
| `MAC` | | Guest network adapter MAC address. |
|
||||||
|
| `ADAPTER` | `virtio-net-pci` | QEMU network adapter model. |
|
||||||
|
| `DEV` | `eth0` | Container network interface used as the uplink. |
|
||||||
|
| `MTU` | | MTU assigned to the guest network interface. |
|
||||||
|
| `MASK` | `255.255.255.0` | IPv4 netmask. |
|
||||||
|
| `TAP` | `qemu` | TAP or macvtap interface name. |
|
||||||
|
| `BRIDGE` | `docker` | Bridge name used for NAT networking. |
|
||||||
|
| `HOST_PORTS` | | Ports excluded from guest forwarding. |
|
||||||
|
| `USER_PORTS` | | Additional ports to forward to Windows when using user-mode networking. |
|
||||||
|
| `DNSMASQ_OPTS` | | Additional options passed to dnsmasq. |
|
||||||
|
| `DNSMASQ_DEBUG` | `N` | Enables dnsmasq debug output. |
|
||||||
|
| `DNSMASQ_DISABLE` | `N` | Disables the internal dnsmasq resolver. |
|
||||||
|
| `PASST_OPTS` | | Additional options passed to passt. |
|
||||||
|
| `PASST_DEBUG` | `N` | Enables passt debug output. |
|
||||||
|
|
||||||
|
## 🖥️ Display
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `DISPLAY` | `web` | Display backend, such as `web`, `vnc`, `disabled`, or `none`. |
|
||||||
|
| `VGA` | `virtio` | QEMU video adapter model. |
|
||||||
|
| `WIDTH` | `1920` | Display width configured in Windows. |
|
||||||
|
| `HEIGHT` | `1080` | Display height configured in Windows. |
|
||||||
|
| `GPU` | `N` | Enables experimental Intel iGPU acceleration. |
|
||||||
|
| `RENDERNODE` | `/dev/dri/renderD128` | Render node used for GPU acceleration. |
|
||||||
|
|
||||||
|
## 🌍 Web UI
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `WEB` | `Y` | Enables the web interface. |
|
||||||
|
| `WEB_PORT` | `8006` | Port for the web interface. |
|
||||||
|
| `VNC_PORT` | `5900` | Port for the VNC server. |
|
||||||
|
| `WSS_PORT` | `5700` | WebSocket port used by noVNC. |
|
||||||
|
| `WSD_PORT` | `8004` | Internal websocketd port used for the display stream. |
|
||||||
|
| `AUDIO` | `N` | Streams guest audio to the web viewer. |
|
||||||
|
| `SOUND` | `intel-hda` | QEMU audio device used by the web viewer. |
|
||||||
|
| `AUX_PORT` | `8003` | Internal WebSocket port used for the audio stream. |
|
||||||
|
| `PROTECT` | `N` | Enables password protection for the web interface. |
|
||||||
|
|
||||||
|
## 📁 File Sharing
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `SAMBA` | `Y` | Enables the Samba shared folder. |
|
||||||
|
| `SAMBA_DEBUG` | `N` | Enables Samba debug output. |
|
||||||
|
|
||||||
|
## ⚙️ System
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `MACHINE` | `q35` | QEMU machine type. |
|
||||||
|
| `UUID` | | UUID assigned to Windows. |
|
||||||
|
| `HPET` | `off` | QEMU HPET timer setting. |
|
||||||
|
| `VMPORT` | `off` | QEMU VMware port setting. |
|
||||||
|
| `SM_BIOS` | | Additional arguments passed to QEMU’s `-smbios` option. |
|
||||||
|
| `ARGUMENTS` | | Additional raw arguments appended to the QEMU command line. |
|
||||||
|
|
||||||
|
## 🚀 Boot
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `BOOT_MODE` | `windows` | Boot configuration, such as `windows`, `windows_secure`, or `windows_legacy`. |
|
||||||
|
| `BOOT_INDEX` | `9` | Boot priority index for the installation media. |
|
||||||
|
| `BIOS` | | Custom firmware file. |
|
||||||
|
| `TPM` | `N` | Enables the TPM emulator, usually set by `BOOT_MODE`. |
|
||||||
|
| `SMM` | `N` | Enables System Management Mode, usually set by `BOOT_MODE`. |
|
||||||
|
| `LOGO` | `Y` | Enables the custom boot logo. |
|
||||||
|
| `CLEAR` | `N` | Resets the NVRAM variables on the next boot. |
|
||||||
|
| `USB` | `qemu-xhci,id=xhci` | QEMU USB controller configuration. |
|
||||||
|
|
||||||
|
## 🎈 Memory Ballooning
|
||||||
|
|
||||||
|
Also see [Dynamic memory allocation](https://github.com/qemus/qemu/blob/master/docs/ballooning.md) for usage instructions and important caveats.
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `BALLOONING` | `N` | Enables dynamic memory ballooning. |
|
||||||
|
| `BALLOONING_MIN_MEM` | `33%` | Minimum amount of memory retained by the VM. |
|
||||||
|
| `BALLOONING_RAM_THRESHOLD` | `80.0` | Host RAM usage percentage at which ballooning begins adjusting memory. |
|
||||||
|
| `BALLOONING_RAM_THRESHOLD_HARD` | `90.0` | Host RAM usage percentage at which ballooning becomes more aggressive. |
|
||||||
|
| `BALLOONING_PSI_PRESSURE` | `10.0` | PSI memory pressure level at which ballooning becomes more aggressive. |
|
||||||
|
| `BALLOONING_PSI_PRESSURE_MAX` | `50.0` | PSI memory pressure level at which ballooning reaches its strongest response. |
|
||||||
|
| `BALLOONING_HYSTERESIS` | `128M` | Minimum memory change before the balloon target is updated. |
|
||||||
|
| `BALLOONING_KP` | `0.5` | Proportional gain used by the ballooning controller. |
|
||||||
|
| `BALLOONING_KI` | `0.05` | Integral gain used by the ballooning controller. |
|
||||||
|
| `BALLOONING_INTERVAL` | `5` | Polling interval in seconds. |
|
||||||
|
| `BALLOONING_DEBUG` | `N` | Enables debug output for the ballooning monitor. |
|
||||||
|
|
||||||
|
## 🔌 Shutdown
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `SHUTDOWN` | `Y` | Enables graceful ACPI shutdown. |
|
||||||
|
| `TIMEOUT` | `115` | Maximum time, in seconds, to wait before forcing Windows to stop. |
|
||||||
|
|
||||||
|
## 🐞 Debugging
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `DEBUG` | `N` | Enables verbose debug output. |
|
||||||
|
| `TRACE` | `N` | Enables shell command tracing. |
|
||||||
|
| `DETECTED` | | Overrides the automatically detected Windows image identifier. |
|
||||||
|
| `SERIAL` | `mon:stdio` | QEMU serial device configuration. |
|
||||||
|
| `MONITOR` | `unix:$QEMU_DIR/monitor.sock,server,wait=off,nodelay` | QEMU monitor configuration. |
|
||||||
@@ -66,6 +66,7 @@ spec:
|
|||||||
claimName: windows-pvc
|
claimName: windows-pvc
|
||||||
- hostPath:
|
- hostPath:
|
||||||
path: /dev/kvm
|
path: /dev/kvm
|
||||||
|
type: CharDevice
|
||||||
name: dev-kvm
|
name: dev-kvm
|
||||||
- hostPath:
|
- hostPath:
|
||||||
path: /dev/net/tun
|
path: /dev/net/tun
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<h1 align="center">Windows<br />
|
<h1 align="center">Windows<br />
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://github.com/dockur/windows"><img src="https://github.com/dockur/windows/raw/master/.github/logo.png" title="Logo" style="max-width:100%;" width="128" /></a>
|
<a href="https://github.com/dockur/windows"><img src="https://github.com/dockur/windows/raw/master/.github/logo.png" title="Logo" style="max-width:100%;" width="96" /></a>
|
||||||
</div>
|
</div>
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
@@ -16,17 +16,22 @@ Windows inside a Docker container.
|
|||||||
|
|
||||||
## Features ✨
|
## Features ✨
|
||||||
|
|
||||||
- ISO downloader
|
- Runs Windows inside a Docker container
|
||||||
- KVM acceleration
|
- Automatic download and hands-free installation
|
||||||
- Web-based viewer
|
- Supports modern and legacy Windows releases
|
||||||
|
- Near-native performance with KVM acceleration
|
||||||
|
- Customizable CPU, memory, and storage allocation
|
||||||
|
- Dynamic memory allocation with memory ballooning
|
||||||
|
- USB passthrough and host folder sharing
|
||||||
|
- Supports NAT, user-mode, macvlan, and macvtap networking
|
||||||
|
|
||||||
## Video 📺
|
## Video 📺
|
||||||
|
|
||||||
[](https://www.youtube.com/watch?v=xhGYobuG508)
|
[](https://www.youtube.com/watch?v=xhGYobuG508)
|
||||||
|
|
||||||
## Usage 🐳
|
## Usage 🐳
|
||||||
|
|
||||||
##### Via Docker Compose:
|
##### Docker Compose:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
@@ -50,26 +55,36 @@ services:
|
|||||||
stop_grace_period: 2m
|
stop_grace_period: 2m
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Via Docker CLI:
|
##### Docker CLI:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v "${PWD:-.}/windows:/storage" --stop-timeout 120 dockurr/windows
|
docker run -it --rm --name windows -e "VERSION=11" -p 8006:8006 --device=/dev/kvm --device=/dev/net/tun --cap-add NET_ADMIN -v "${PWD:-.}/windows:/storage" --stop-timeout 120 docker.io/dockurr/windows
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Via Kubernetes:
|
##### Kubernetes:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/master/kubernetes.yml
|
kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/master/kubernetes.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Via Github Codespaces:
|
##### GitHub Codespaces:
|
||||||
|
|
||||||
[](https://codespaces.new/dockur/windows)
|
[](https://codespaces.new/dockur/windows)
|
||||||
|
|
||||||
##### Via a graphical installer:
|
##### Graphical installer:
|
||||||
|
|
||||||
[](https://winboat.app)
|
[](https://winboat.app)
|
||||||
|
|
||||||
|
## Requirements ⚙️
|
||||||
|
|
||||||
|
- Docker or Podman on a Linux host with KVM support.
|
||||||
|
- Docker Desktop or Podman (Desktop) on Windows 11 with nested virtualization enabled.
|
||||||
|
- At least 4 GB of available RAM.
|
||||||
|
- At least 64 GB of free disk space.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Docker Desktop on Linux, macOS, and Windows 10 does not currently provide KVM access to containers and is therefore not supported.
|
||||||
|
|
||||||
## FAQ 💬
|
## FAQ 💬
|
||||||
|
|
||||||
### How do I use it?
|
### How do I use it?
|
||||||
@@ -78,7 +93,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
|
|
||||||
- Start the container and connect to [port 8006](http://127.0.0.1:8006/) using your web browser.
|
- Start the container and connect to [port 8006](http://127.0.0.1:8006/) using your web browser.
|
||||||
|
|
||||||
- Sit back and relax while the magic happens, the whole installation will be performed fully automatic.
|
- Sit back and relax while the magic happens, the whole installation will be performed fully automatically.
|
||||||
|
|
||||||
- Once you see the desktop, your Windows installation is ready for use.
|
- Once you see the desktop, your Windows installation is ready for use.
|
||||||
|
|
||||||
@@ -90,14 +105,14 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
environment:
|
environment:
|
||||||
VERSION: "11"
|
VERSION: "10"
|
||||||
```
|
```
|
||||||
|
|
||||||
Select from the values below:
|
Select from the values below:
|
||||||
|
|
||||||
| **Value** | **Version** | **Size** |
|
| **Value** | **Version** | **Size** |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `11` | Windows 11 Pro | 7.2 GB |
|
| `11` | Windows 11 Pro | 7.9 GB |
|
||||||
| `11l` | Windows 11 LTSC | 4.7 GB |
|
| `11l` | Windows 11 LTSC | 4.7 GB |
|
||||||
| `11e` | Windows 11 Enterprise | 6.6 GB |
|
| `11e` | Windows 11 Enterprise | 6.6 GB |
|
||||||
||||
|
||||
|
||||||
@@ -111,7 +126,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
| `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 |
|
||||||
||||
|
||||
|
||||||
| `2025` | Windows Server 2025 | 6.7 GB |
|
| `2025` | Windows Server 2025 | 7.6 GB |
|
||||||
| `2022` | Windows Server 2022 | 6.0 GB |
|
| `2022` | Windows Server 2022 | 6.0 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 |
|
||||||
@@ -143,7 +158,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
```
|
```
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> This can also be used to resize the existing disk to a larger capacity without any data loss. However you will need to [manually extend the disk partition](https://learn.microsoft.com/en-us/windows-server/storage/disk-management/extend-a-basic-volume?tabs=disk-management) since the added disk space will appear as unallocated.
|
> This can also be used to resize an existing disk to a larger capacity without any data loss. However, you will need to [manually extend the disk partition](https://learn.microsoft.com/en-us/windows-server/storage/disk-management/extend-a-basic-volume?tabs=disk-management) afterwards, since the added disk space will appear as unallocated.
|
||||||
|
|
||||||
### How do I share files with the host?
|
### How do I share files with the host?
|
||||||
|
|
||||||
@@ -170,11 +185,30 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
CPU_CORES: "4"
|
CPU_CORES: "4"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### How do I enable audio?
|
||||||
|
|
||||||
|
Audio is disabled by default unless you are using RDP. To stream it to the browser, add the following environment variable:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
environment:
|
||||||
|
AUDIO: "Y"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then enable **Audio** under **Settings → Advanced** in the web viewer. The stream is only active while this option is enabled, so it uses no extra bandwidth otherwise.
|
||||||
|
|
||||||
|
### How do I connect using RDP?
|
||||||
|
|
||||||
|
The web viewer is mainly intended for use during installation, since it is less responsive than RDP and does not support features such as clipboard sharing.
|
||||||
|
|
||||||
|
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 an 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 configure the username and password?
|
### How do I configure the username and password?
|
||||||
|
|
||||||
By default, a user called `Docker` is created and its password is `admin`.
|
By default, a user called `Docker` is created and its password is `admin`.
|
||||||
|
|
||||||
If you want to use different credentials during installation, you can configure them in your compose file:
|
If you want to set up different credentials during installation, you can configure them in your compose file:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
environment:
|
environment:
|
||||||
@@ -197,7 +231,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
|
|
||||||
### How do I select the keyboard layout?
|
### How do I select the keyboard layout?
|
||||||
|
|
||||||
If you want to use a keyboard layout or locale that is not the default for your selected language, you can add `KEYBOARD` and `REGION` variables like this:
|
If you want to set up a keyboard layout or locale that is not the default for your selected language, you can add `KEYBOARD` and `REGION` variables like this:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
environment:
|
environment:
|
||||||
@@ -218,7 +252,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
volumes:
|
volumes:
|
||||||
- ./example.iso:/boot.iso
|
- ./example.iso:/custom.iso
|
||||||
```
|
```
|
||||||
|
|
||||||
Replace the example path `./example.iso` with the filename of your desired ISO file. The value of `VERSION` will be ignored in this case.
|
Replace the example path `./example.iso` with the filename of your desired ISO file. The value of `VERSION` will be ignored in this case.
|
||||||
@@ -234,27 +268,19 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
- ./example:/oem
|
- ./example:/oem
|
||||||
```
|
```
|
||||||
|
|
||||||
The example folder `./example` will be copied to `C:\OEM` and the containing `install.bat` will be executed during the last step of the automatic installation.
|
The example folder `./example` will be copied to `C:\OEM` and the `install.bat` file inside that folder will be executed during the last step of the automatic installation.
|
||||||
|
|
||||||
### How do I perform a manual installation?
|
### How do I perform a manual installation?
|
||||||
|
|
||||||
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 at 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:
|
||||||
MANUAL: "Y"
|
MANUAL: "Y"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 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 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.
|
|
||||||
|
|
||||||
### How do I assign an individual IP address to the container?
|
### How do I assign an individual IP address to the container?
|
||||||
|
|
||||||
By default, the container uses bridge networking, which shares the IP address with the host.
|
By default, the container uses bridge networking, which shares the IP address with the host.
|
||||||
@@ -320,9 +346,9 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
- ./example3:/storage3
|
- ./example3:/storage3
|
||||||
```
|
```
|
||||||
|
|
||||||
### How do I pass-through a disk?
|
### How do I pass through a disk?
|
||||||
|
|
||||||
It is possible to pass-through disk devices or partitions directly by adding them to your compose file in this way:
|
You can pass through disk devices or partitions directly by adding them to your compose file in this way:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
devices:
|
devices:
|
||||||
@@ -332,9 +358,9 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
|
|
||||||
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).
|
||||||
|
|
||||||
### How do I pass-through a USB device?
|
### How do I pass through a USB device?
|
||||||
|
|
||||||
To pass-through a USB device, first lookup its vendor and product id via the `lsusb` command, then add them to your compose file like this:
|
To pass through a USB device, first look up its vendor and product IDs via the `lsusb` command, then add them to your compose file like this:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
environment:
|
environment:
|
||||||
@@ -343,35 +369,49 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
- /dev/bus/usb
|
- /dev/bus/usb
|
||||||
```
|
```
|
||||||
|
|
||||||
If the device is a USB disk drive, please wait until after the installation is fully completed before connecting it. Otherwise the installation may fail, as the order of the disks can get rearranged.
|
> [!WARNING]
|
||||||
|
> Adding a USB mass storage device before Windows Setup has finished may cause it to fail. Or worse: the drive can get formatted as the system disk, and all your data will be lost! So always keep them disconnected when launching the container for the first time.
|
||||||
|
|
||||||
### How do I verify if my system supports KVM?
|
### How do I enable dynamic memory allocation?
|
||||||
|
|
||||||
First check if your software is compatible using this chart:
|
By default, the VM is allocated the full amount of RAM configured via `RAM_SIZE` for its entire lifetime.
|
||||||
|
|
||||||
| **Product** | **Linux** | **Win11** | **Win10** | **macOS** |
|
However, you can enable [memory ballooning](https://github.com/qemus/qemu/blob/master/docs/ballooning.md) if you want the container to dynamically reclaim unused guest RAM based on host memory pressure.
|
||||||
|---|---|---|---|---|
|
|
||||||
| Docker CLI | ✅ | ✅ | ❌ | ❌ |
|
|
||||||
| Docker Desktop | ❌ | ✅ | ❌ | ❌ |
|
|
||||||
| Podman CLI | ✅ | ✅ | ❌ | ❌ |
|
|
||||||
| Podman Desktop | ✅ | ✅ | ❌ | ❌ |
|
|
||||||
|
|
||||||
After that you can run the following commands in Linux to check your system:
|
### Are these all available options?
|
||||||
|
|
||||||
|
No. For a complete overview of all supported settings, see the [environment variables](docs/environment.md) page.
|
||||||
|
|
||||||
|
### How do I verify that KVM is available?
|
||||||
|
|
||||||
|
First, make sure your platform and container runtime meet the [requirements](#requirements-️) listed above.
|
||||||
|
|
||||||
|
On a Linux host, install `cpu-checker` and run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt install cpu-checker
|
sudo apt install cpu-checker
|
||||||
sudo kvm-ok
|
sudo kvm-ok
|
||||||
```
|
```
|
||||||
|
|
||||||
If you receive an error from `kvm-ok` indicating that KVM cannot be used, please check whether:
|
A working configuration should report:
|
||||||
|
|
||||||
- the virtualization extensions (`Intel VT-x` or `AMD SVM`) are enabled in your BIOS.
|
```text
|
||||||
|
KVM acceleration can be used
|
||||||
|
```
|
||||||
|
|
||||||
- you enabled "nested virtualization" if you are running the container inside a virtual machine.
|
You can also verify that the KVM device exists:
|
||||||
|
|
||||||
- you are not using a cloud provider, as most of them do not allow nested virtualization for their VPS's.
|
```bash
|
||||||
|
ls -l /dev/kvm
|
||||||
|
```
|
||||||
|
|
||||||
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.
|
If KVM is unavailable, check whether:
|
||||||
|
|
||||||
|
- Hardware virtualization (`Intel VT-x` or `AMD-V`) is enabled in your BIOS or UEFI.
|
||||||
|
- Nested virtualization is enabled when the host itself is a virtual machine.
|
||||||
|
- Your VPS or cloud provider supports nested virtualization.
|
||||||
|
|
||||||
|
If `kvm-ok` succeeds but the container still reports that KVM is unavailable, you can temporarily add `privileged: true` to your Compose file to rule out a permission or device-access issue.
|
||||||
|
|
||||||
### How do I run macOS in a container?
|
### How do I run macOS in a container?
|
||||||
|
|
||||||
@@ -383,7 +423,12 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/mas
|
|||||||
|
|
||||||
### Is this project legal?
|
### Is this project legal?
|
||||||
|
|
||||||
Yes, this project contains only open-source code and does not distribute any copyrighted material. Any product keys found in the code are just generic placeholders provided by Microsoft for trial purposes. So under all applicable laws, this project will be considered legal.
|
Yes, this project contains only open-source code and does not distribute Windows itself. Any product keys found in the code are generic installation keys published by Microsoft for trial purposes and are not valid activation licenses.
|
||||||
|
|
||||||
|
You are responsible for ensuring that you have a valid Windows license and that your use complies with Microsoft's licensing terms.
|
||||||
|
|
||||||
|
## Stars 🌟
|
||||||
|
[](https://github.com/dockur/windows/stargazers)
|
||||||
|
|
||||||
## Disclaimer ⚖️
|
## Disclaimer ⚖️
|
||||||
|
|
||||||
|
|||||||
+92
-94
@@ -16,15 +16,21 @@ set -Eeuo pipefail
|
|||||||
: "${USERNAME:=""}"
|
: "${USERNAME:=""}"
|
||||||
: "${PASSWORD:=""}"
|
: "${PASSWORD:=""}"
|
||||||
|
|
||||||
|
# Sanitize variables
|
||||||
|
KEY=$(strip "$KEY")
|
||||||
|
WIDTH=$(strip "$WIDTH")
|
||||||
|
HEIGHT=$(strip "$HEIGHT")
|
||||||
|
REGION=$(strip "$REGION")
|
||||||
|
EDITION=$(strip "$EDITION")
|
||||||
|
KEYBOARD=$(strip "$KEYBOARD")
|
||||||
|
LANGUAGE=$(strip "$LANGUAGE")
|
||||||
|
USERNAME=$(strip "$USERNAME")
|
||||||
|
|
||||||
MIRRORS=4
|
MIRRORS=4
|
||||||
|
|
||||||
parseVersion() {
|
parseVersion() {
|
||||||
|
|
||||||
if [[ "${VERSION}" == \"*\" || "${VERSION}" == \'*\' ]]; then
|
VERSION=$(strip "$VERSION")
|
||||||
VERSION="${VERSION:1:-1}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERSION=$(expr "$VERSION" : "^\ *\(.*[^ ]\)\ *$")
|
|
||||||
[ -z "$VERSION" ] && VERSION="win11"
|
[ -z "$VERSION" ] && VERSION="win11"
|
||||||
|
|
||||||
case "${VERSION,,}" in
|
case "${VERSION,,}" in
|
||||||
@@ -138,7 +144,7 @@ parseVersion() {
|
|||||||
"nano11" | "nano 11" )
|
"nano11" | "nano 11" )
|
||||||
VERSION="nano11"
|
VERSION="nano11"
|
||||||
[ -z "$DETECTED" ] && DETECTED="win11x64"
|
[ -z "$DETECTED" ] && DETECTED="win11x64"
|
||||||
;;
|
;;
|
||||||
"core11" | "core 11" )
|
"core11" | "core 11" )
|
||||||
VERSION="core11"
|
VERSION="core11"
|
||||||
[ -z "$DETECTED" ] && DETECTED="win11x64"
|
[ -z "$DETECTED" ] && DETECTED="win11x64"
|
||||||
@@ -147,7 +153,7 @@ parseVersion() {
|
|||||||
VERSION="tiny11"
|
VERSION="tiny11"
|
||||||
[ -z "$DETECTED" ] && DETECTED="win11x64"
|
[ -z "$DETECTED" ] && DETECTED="win11x64"
|
||||||
;;
|
;;
|
||||||
"tiny10" | "tiny 10" )
|
"tiny10" | "tiny 10" )
|
||||||
VERSION="tiny10"
|
VERSION="tiny10"
|
||||||
[ -z "$DETECTED" ] && DETECTED="win10x64-ltsc"
|
[ -z "$DETECTED" ] && DETECTED="win10x64-ltsc"
|
||||||
;;
|
;;
|
||||||
@@ -169,32 +175,26 @@ getLanguage() {
|
|||||||
"ar" | "ar-"* )
|
"ar" | "ar-"* )
|
||||||
short="ar"
|
short="ar"
|
||||||
lang="Arabic"
|
lang="Arabic"
|
||||||
desc="$lang"
|
|
||||||
culture="ar-SA" ;;
|
culture="ar-SA" ;;
|
||||||
"bg" | "bg-"* )
|
"bg" | "bg-"* )
|
||||||
short="bg"
|
short="bg"
|
||||||
lang="Bulgarian"
|
lang="Bulgarian"
|
||||||
desc="$lang"
|
|
||||||
culture="bg-BG" ;;
|
culture="bg-BG" ;;
|
||||||
"cs" | "cs-"* | "cz" | "cz-"* )
|
"cs" | "cs-"* | "cz" | "cz-"* )
|
||||||
short="cs"
|
short="cs"
|
||||||
lang="Czech"
|
lang="Czech"
|
||||||
desc="$lang"
|
|
||||||
culture="cs-CZ" ;;
|
culture="cs-CZ" ;;
|
||||||
"da" | "da-"* | "dk" | "dk-"* )
|
"da" | "da-"* | "dk" | "dk-"* )
|
||||||
short="da"
|
short="da"
|
||||||
lang="Danish"
|
lang="Danish"
|
||||||
desc="$lang"
|
|
||||||
culture="da-DK" ;;
|
culture="da-DK" ;;
|
||||||
"de" | "de-"* )
|
"de" | "de-"* )
|
||||||
short="de"
|
short="de"
|
||||||
lang="German"
|
lang="German"
|
||||||
desc="$lang"
|
|
||||||
culture="de-DE" ;;
|
culture="de-DE" ;;
|
||||||
"el" | "el-"* | "gr" | "gr-"* )
|
"el" | "el-"* | "gr" | "gr-"* )
|
||||||
short="el"
|
short="el"
|
||||||
lang="Greek"
|
lang="Greek"
|
||||||
desc="$lang"
|
|
||||||
culture="el-GR" ;;
|
culture="el-GR" ;;
|
||||||
"gb" | "en-gb" )
|
"gb" | "en-gb" )
|
||||||
short="en-gb"
|
short="en-gb"
|
||||||
@@ -204,7 +204,6 @@ getLanguage() {
|
|||||||
"en" | "en-"* )
|
"en" | "en-"* )
|
||||||
short="en"
|
short="en"
|
||||||
lang="English"
|
lang="English"
|
||||||
desc="English"
|
|
||||||
culture="en-US" ;;
|
culture="en-US" ;;
|
||||||
"mx" | "es-mx" )
|
"mx" | "es-mx" )
|
||||||
short="mx"
|
short="mx"
|
||||||
@@ -214,17 +213,14 @@ getLanguage() {
|
|||||||
"es" | "es-"* )
|
"es" | "es-"* )
|
||||||
short="es"
|
short="es"
|
||||||
lang="Spanish"
|
lang="Spanish"
|
||||||
desc="$lang"
|
|
||||||
culture="es-ES" ;;
|
culture="es-ES" ;;
|
||||||
"et" | "et-"* )
|
"et" | "et-"* )
|
||||||
short="et"
|
short="et"
|
||||||
lang="Estonian"
|
lang="Estonian"
|
||||||
desc="$lang"
|
|
||||||
culture="et-EE" ;;
|
culture="et-EE" ;;
|
||||||
"fi" | "fi-"* )
|
"fi" | "fi-"* )
|
||||||
short="fi"
|
short="fi"
|
||||||
lang="Finnish"
|
lang="Finnish"
|
||||||
desc="$lang"
|
|
||||||
culture="fi-FI" ;;
|
culture="fi-FI" ;;
|
||||||
"ca" | "fr-ca" )
|
"ca" | "fr-ca" )
|
||||||
short="ca"
|
short="ca"
|
||||||
@@ -234,62 +230,50 @@ getLanguage() {
|
|||||||
"fr" | "fr-"* )
|
"fr" | "fr-"* )
|
||||||
short="fr"
|
short="fr"
|
||||||
lang="French"
|
lang="French"
|
||||||
desc="$lang"
|
|
||||||
culture="fr-FR" ;;
|
culture="fr-FR" ;;
|
||||||
"he" | "he-"* | "il" | "il-"* )
|
"he" | "he-"* | "il" | "il-"* )
|
||||||
short="he"
|
short="he"
|
||||||
lang="Hebrew"
|
lang="Hebrew"
|
||||||
desc="$lang"
|
|
||||||
culture="he-IL" ;;
|
culture="he-IL" ;;
|
||||||
"hr" | "hr-"* | "cr" | "cr-"* )
|
"hr" | "hr-"* | "cr" | "cr-"* )
|
||||||
short="hr"
|
short="hr"
|
||||||
lang="Croatian"
|
lang="Croatian"
|
||||||
desc="$lang"
|
|
||||||
culture="hr-HR" ;;
|
culture="hr-HR" ;;
|
||||||
"hu" | "hu-"* )
|
"hu" | "hu-"* )
|
||||||
short="hu"
|
short="hu"
|
||||||
lang="Hungarian"
|
lang="Hungarian"
|
||||||
desc="$lang"
|
|
||||||
culture="hu-HU" ;;
|
culture="hu-HU" ;;
|
||||||
"it" | "it-"* )
|
"it" | "it-"* )
|
||||||
short="it"
|
short="it"
|
||||||
lang="Italian"
|
lang="Italian"
|
||||||
desc="$lang"
|
|
||||||
culture="it-IT" ;;
|
culture="it-IT" ;;
|
||||||
"ja" | "ja-"* | "jp" | "jp-"* )
|
"ja" | "ja-"* | "jp" | "jp-"* )
|
||||||
short="ja"
|
short="ja"
|
||||||
lang="Japanese"
|
lang="Japanese"
|
||||||
desc="$lang"
|
|
||||||
culture="ja-JP" ;;
|
culture="ja-JP" ;;
|
||||||
"ko" | "ko-"* | "kr" | "kr-"* )
|
"ko" | "ko-"* | "kr" | "kr-"* )
|
||||||
short="ko"
|
short="ko"
|
||||||
lang="Korean"
|
lang="Korean"
|
||||||
desc="$lang"
|
|
||||||
culture="ko-KR" ;;
|
culture="ko-KR" ;;
|
||||||
"lt" | "lt-"* )
|
"lt" | "lt-"* )
|
||||||
short="lt"
|
short="lt"
|
||||||
lang="Lithuanian"
|
lang="Lithuanian"
|
||||||
desc="$lang"
|
|
||||||
culture="lt-LT" ;;
|
culture="lt-LT" ;;
|
||||||
"lv" | "lv-"* )
|
"lv" | "lv-"* )
|
||||||
short="lv"
|
short="lv"
|
||||||
lang="Latvian"
|
lang="Latvian"
|
||||||
desc="$lang"
|
|
||||||
culture="lv-LV" ;;
|
culture="lv-LV" ;;
|
||||||
"nb" | "nb-"* |"nn" | "nn-"* | "no" | "no-"* )
|
"nb" | "nb-"* | "nn" | "nn-"* | "no" | "no-"* )
|
||||||
short="no"
|
short="no"
|
||||||
lang="Norwegian"
|
lang="Norwegian"
|
||||||
desc="$lang"
|
|
||||||
culture="nb-NO" ;;
|
culture="nb-NO" ;;
|
||||||
"nl" | "nl-"* )
|
"nl" | "nl-"* )
|
||||||
short="nl"
|
short="nl"
|
||||||
lang="Dutch"
|
lang="Dutch"
|
||||||
desc="$lang"
|
|
||||||
culture="nl-NL" ;;
|
culture="nl-NL" ;;
|
||||||
"pl" | "pl-"* )
|
"pl" | "pl-"* )
|
||||||
short="pl"
|
short="pl"
|
||||||
lang="Polish"
|
lang="Polish"
|
||||||
desc="$lang"
|
|
||||||
culture="pl-PL" ;;
|
culture="pl-PL" ;;
|
||||||
"br" | "pt-br" )
|
"br" | "pt-br" )
|
||||||
short="pt"
|
short="pt"
|
||||||
@@ -299,27 +283,22 @@ getLanguage() {
|
|||||||
"pt" | "pt-"* )
|
"pt" | "pt-"* )
|
||||||
short="pp"
|
short="pp"
|
||||||
lang="Portuguese"
|
lang="Portuguese"
|
||||||
desc="$lang"
|
|
||||||
culture="pt-BR" ;;
|
culture="pt-BR" ;;
|
||||||
"ro" | "ro-"* )
|
"ro" | "ro-"* )
|
||||||
short="ro"
|
short="ro"
|
||||||
lang="Romanian"
|
lang="Romanian"
|
||||||
desc="$lang"
|
|
||||||
culture="ro-RO" ;;
|
culture="ro-RO" ;;
|
||||||
"ru" | "ru-"* )
|
"ru" | "ru-"* )
|
||||||
short="ru"
|
short="ru"
|
||||||
lang="Russian"
|
lang="Russian"
|
||||||
desc="$lang"
|
|
||||||
culture="ru-RU" ;;
|
culture="ru-RU" ;;
|
||||||
"sk" | "sk-"* )
|
"sk" | "sk-"* )
|
||||||
short="sk"
|
short="sk"
|
||||||
lang="Slovak"
|
lang="Slovak"
|
||||||
desc="$lang"
|
|
||||||
culture="sk-SK" ;;
|
culture="sk-SK" ;;
|
||||||
"sl" | "sl-"* | "si" | "si-"* )
|
"sl" | "sl-"* | "si" | "si-"* )
|
||||||
short="sl"
|
short="sl"
|
||||||
lang="Slovenian"
|
lang="Slovenian"
|
||||||
desc="$lang"
|
|
||||||
culture="sl-SI" ;;
|
culture="sl-SI" ;;
|
||||||
"sr" | "sr-"* )
|
"sr" | "sr-"* )
|
||||||
short="sr"
|
short="sr"
|
||||||
@@ -329,22 +308,18 @@ getLanguage() {
|
|||||||
"sv" | "sv-"* | "se" | "se-"* )
|
"sv" | "sv-"* | "se" | "se-"* )
|
||||||
short="sv"
|
short="sv"
|
||||||
lang="Swedish"
|
lang="Swedish"
|
||||||
desc="$lang"
|
|
||||||
culture="sv-SE" ;;
|
culture="sv-SE" ;;
|
||||||
"th" | "th-"* )
|
"th" | "th-"* )
|
||||||
short="th"
|
short="th"
|
||||||
lang="Thai"
|
lang="Thai"
|
||||||
desc="$lang"
|
|
||||||
culture="th-TH" ;;
|
culture="th-TH" ;;
|
||||||
"tr" | "tr-"* )
|
"tr" | "tr-"* )
|
||||||
short="tr"
|
short="tr"
|
||||||
lang="Turkish"
|
lang="Turkish"
|
||||||
desc="$lang"
|
|
||||||
culture="tr-TR" ;;
|
culture="tr-TR" ;;
|
||||||
"ua" | "ua-"* | "uk" | "uk-"* )
|
"ua" | "ua-"* | "uk" | "uk-"* )
|
||||||
short="uk"
|
short="uk"
|
||||||
lang="Ukrainian"
|
lang="Ukrainian"
|
||||||
desc="$lang"
|
|
||||||
culture="uk-UA" ;;
|
culture="uk-UA" ;;
|
||||||
"hk" | "zh-hk" | "cn-hk" )
|
"hk" | "zh-hk" | "cn-hk" )
|
||||||
short="hk"
|
short="hk"
|
||||||
@@ -363,6 +338,8 @@ getLanguage() {
|
|||||||
culture="zh-CN" ;;
|
culture="zh-CN" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
[ -z "$desc" ] && desc="$lang"
|
||||||
|
|
||||||
case "${ret,,}" in
|
case "${ret,,}" in
|
||||||
"desc" ) echo "$desc" ;;
|
"desc" ) echo "$desc" ;;
|
||||||
"name" ) echo "$lang" ;;
|
"name" ) echo "$lang" ;;
|
||||||
@@ -376,9 +353,9 @@ getLanguage() {
|
|||||||
|
|
||||||
parseLanguage() {
|
parseLanguage() {
|
||||||
|
|
||||||
REGION="${REGION//_/-/}"
|
REGION="${REGION//_/-}"
|
||||||
KEYBOARD="${KEYBOARD//_/-/}"
|
KEYBOARD="${KEYBOARD//_/-}"
|
||||||
LANGUAGE="${LANGUAGE//_/-/}"
|
LANGUAGE="${LANGUAGE//_/-}"
|
||||||
|
|
||||||
[ -z "$LANGUAGE" ] && LANGUAGE="en"
|
[ -z "$LANGUAGE" ] && LANGUAGE="en"
|
||||||
|
|
||||||
@@ -722,8 +699,8 @@ getMido() {
|
|||||||
|
|
||||||
case "${id,,}" in
|
case "${id,,}" in
|
||||||
"win11x64" )
|
"win11x64" )
|
||||||
size=7736125440
|
size=8471603200
|
||||||
sum="d141f6030fed50f75e2b03e1eb2e53646c4b21e5386047cb860af5223f102a32"
|
sum="768984706b909479417b2368438909440f2967ff05c6a9195ed2667254e465e3"
|
||||||
url="https://software-static.download.prss.microsoft.com/dbazure/888969d5-f34g-4e03-ac9d-1f9786c66749/26200.6584.250915-1905.25h2_ge_release_svc_refresh_CLIENT_CONSUMER_x64FRE_en-us.iso"
|
url="https://software-static.download.prss.microsoft.com/dbazure/888969d5-f34g-4e03-ac9d-1f9786c66749/26200.6584.250915-1905.25h2_ge_release_svc_refresh_CLIENT_CONSUMER_x64FRE_en-us.iso"
|
||||||
;;
|
;;
|
||||||
"win11x64-enterprise-eval" )
|
"win11x64-enterprise-eval" )
|
||||||
@@ -734,11 +711,7 @@ getMido() {
|
|||||||
"win11x64-enterprise-iot-eval" | "win11x64-enterprise-ltsc-eval" )
|
"win11x64-enterprise-iot-eval" | "win11x64-enterprise-ltsc-eval" )
|
||||||
size=5060020224
|
size=5060020224
|
||||||
sum="2cee70bd183df42b92a2e0da08cc2bb7a2a9ce3a3841955a012c0f77aeb3cb29"
|
sum="2cee70bd183df42b92a2e0da08cc2bb7a2a9ce3a3841955a012c0f77aeb3cb29"
|
||||||
url="https://software-static.download.prss.microsoft.com/dbazure/888969d5-f34g-4e03-ac9d-1f9786c66749/26100.1.240331-1435.ge_release_CLIENT_IOT_LTSC_EVAL_x64FRE_en-us.iso"
|
url="https://software-static.download.prss.microsoft.com/dbazure/998969d5-f34g-4e03-ac9d-1f9786c66749/26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_IOT_LTSC_EVAL_x64FRE_en-us.iso"
|
||||||
;;
|
|
||||||
"win10x64" )
|
|
||||||
size=6140975104
|
|
||||||
sum="a6f470ca6d331eb353b815c043e327a347f594f37ff525f17764738fe812852e"
|
|
||||||
;;
|
;;
|
||||||
"win10x64-enterprise-eval" )
|
"win10x64-enterprise-eval" )
|
||||||
size=5550497792
|
size=5550497792
|
||||||
@@ -756,9 +729,9 @@ getMido() {
|
|||||||
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"
|
||||||
;;
|
;;
|
||||||
"win2025-eval" )
|
"win2025-eval" )
|
||||||
size=6014152704
|
size=8152356864
|
||||||
sum="d0ef4502e350e3c6c53c15b1b3020d38a5ded011bf04998e950720ac8579b23d"
|
sum="7b052573ba7894c9924e3e87ba732ccd354d18cb75a883efa9b900ea125bfd51"
|
||||||
url="https://software-static.download.prss.microsoft.com/dbazure/888969d5-f34g-4e03-ac9d-1f9786c66749/26100.1742.240906-0331.ge_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso"
|
url="https://software-static.download.prss.microsoft.com/dbazure/998969d5-f34g-4e03-ac9d-1f9786c66749/26100.32230.260111-0550.lt_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso"
|
||||||
;;
|
;;
|
||||||
"win2022-eval" )
|
"win2022-eval" )
|
||||||
size=5044094976
|
size=5044094976
|
||||||
@@ -817,9 +790,9 @@ getLink1() {
|
|||||||
|
|
||||||
case "${id,,}" in
|
case "${id,,}" in
|
||||||
"win11x64" | "win11x64-enterprise" | "win11x64-enterprise-eval" )
|
"win11x64" | "win11x64-enterprise" | "win11x64-enterprise-eval" )
|
||||||
size=5332989952
|
size=6927149056
|
||||||
sum="aa1ad990f930d907b7a34ea897abbb0dfbe47552ca8acc146f92e40381839e05"
|
sum="f5ffe9313eebc6299fba9e6eeb2971007264e6c6be013073a89b5ae9bd85bfb3"
|
||||||
url="11/en-us_windows_11_24h2_x64.iso"
|
url="11/en-us_windows_11_25h2_x64.iso"
|
||||||
;;
|
;;
|
||||||
"win11x64-iot" | "win11x64-enterprise-iot" | "win11x64-enterprise-iot-eval" )
|
"win11x64-iot" | "win11x64-enterprise-iot" | "win11x64-enterprise-iot-eval" )
|
||||||
size=5144817664
|
size=5144817664
|
||||||
@@ -832,8 +805,8 @@ getLink1() {
|
|||||||
url="11/X23-81951_26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_ENTERPRISES_OEM_x64FRE_en-us.iso"
|
url="11/X23-81951_26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_ENTERPRISES_OEM_x64FRE_en-us.iso"
|
||||||
;;
|
;;
|
||||||
"win10x64" | "win10x64-enterprise" | "win10x64-enterprise-eval" )
|
"win10x64" | "win10x64-enterprise" | "win10x64-enterprise-eval" )
|
||||||
size=5535252480
|
size=5723299840
|
||||||
sum="557871965263d0fd0a1ea50b5d0d0d7cb04a279148ca905c1c675c9bc0d5486c"
|
sum="316f718f21fc9b386d81dadd62dc60268a1cfd65b184ac6a052875a454c3431b"
|
||||||
url="10/en-us_windows_10_22h2_x64.iso"
|
url="10/en-us_windows_10_22h2_x64.iso"
|
||||||
;;
|
;;
|
||||||
"win10x64-iot" | "win10x64-enterprise-iot" | "win10x64-enterprise-iot-eval" )
|
"win10x64-iot" | "win10x64-enterprise-iot" | "win10x64-enterprise-iot-eval" )
|
||||||
@@ -857,14 +830,14 @@ getLink1() {
|
|||||||
url="8.x/8.1/en_windows_8.1_enterprise_with_update_x64_dvd_6054382.iso"
|
url="8.x/8.1/en_windows_8.1_enterprise_with_update_x64_dvd_6054382.iso"
|
||||||
;;
|
;;
|
||||||
"win2025" | "win2025-eval" )
|
"win2025" | "win2025-eval" )
|
||||||
size=6786627584
|
size=7571058688
|
||||||
sum="bf3ef0849c7cb5e818e1035b7466d206af5aa227ace1a3f4b0de2bf00d2e2144"
|
sum="d273d0a85565ffbc06a3d46313f619103e2830a3373306ddbb9a08b8824f509d"
|
||||||
url="server/2025/en-us_windows_server_2025_updated_april_2025_x64_dvd_ea86301d.iso"
|
url="server/2025/en-us_windows_server_2025_updated_oct_2025_x64_dvd_6c0c5aa8.iso"
|
||||||
;;
|
;;
|
||||||
"win2022" | "win2022-eval" )
|
"win2022" | "win2022-eval" )
|
||||||
size=6005706752
|
size=6023239680
|
||||||
sum="cea2cb2c09de9910c236e64eae3a801c55e9c77ec25e8d81585e3a4581d24bfb"
|
sum="5d6d91efa972cbdd6701d78db1dcf6a34c7024ca931c1718e7cb3d0c6dd54e88"
|
||||||
url="server/2022/en-us_windows_server_2022_updated_april_2025_x64_dvd_3f755ec1.iso"
|
url="server/2022/en-us_windows_server_2022_updated_oct_2025_x64_dvd_26e9af36.iso"
|
||||||
;;
|
;;
|
||||||
"win2019" | "win2019-eval" )
|
"win2019" | "win2019-eval" )
|
||||||
size=5575774208
|
size=5575774208
|
||||||
@@ -1078,6 +1051,7 @@ getLink3() {
|
|||||||
size=387424256
|
size=387424256
|
||||||
sum="08b11c3897eb38d1e6566a17cec5cdf2b3c620444e160e3db200a7e223aabbd8"
|
sum="08b11c3897eb38d1e6566a17cec5cdf2b3c620444e160e3db200a7e223aabbd8"
|
||||||
url="Windows_2000_SP4.iso"
|
url="Windows_2000_SP4.iso"
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case "${ret,,}" in
|
case "${ret,,}" in
|
||||||
@@ -1108,14 +1082,14 @@ getLink4() {
|
|||||||
url="nano11_25h2/nano11%2025h2.iso"
|
url="nano11_25h2/nano11%2025h2.iso"
|
||||||
;;
|
;;
|
||||||
"core11" )
|
"core11" )
|
||||||
size=2159738880
|
size=3176654848
|
||||||
sum="78f0f44444ff95b97125b43e560a72e0d6ce0a665cf9f5573bf268191e5510c1"
|
sum="29c055fcfb7b089abd9e007e7abe4bb82c70a03aac9d65e56a38b87ab32d04d2"
|
||||||
url="tiny-11-core-x-64-beta-1/tiny11%20core%20x64%20beta%201.iso"
|
url="tiny11_25H2/tiny11core_25H2_Oct25.iso"
|
||||||
;;
|
;;
|
||||||
"tiny11" )
|
"tiny11" )
|
||||||
size=3788177408
|
size=5514559488
|
||||||
sum="a028800a91addc35d8ae22dce7459b67330f7d69d2f11c70f53c0fdffa5b4280"
|
sum="92484f2b7f707e42383294402a9eabbadeaa5ede80ac633390ae7f3537e36275"
|
||||||
url="tiny11-2311/tiny11%202311%20x64.iso"
|
url="tiny11_25H2/tiny11_25H2_Oct25.iso"
|
||||||
;;
|
;;
|
||||||
"tiny10" )
|
"tiny10" )
|
||||||
size=3839819776
|
size=3839819776
|
||||||
@@ -1123,9 +1097,9 @@ getLink4() {
|
|||||||
url="tiny-10-23-h2/tiny10%20x64%2023h2.iso"
|
url="tiny-10-23-h2/tiny10%20x64%2023h2.iso"
|
||||||
;;
|
;;
|
||||||
"win11x64" )
|
"win11x64" )
|
||||||
size=5819484160
|
size=7736125440
|
||||||
sum="b56b911bf18a2ceaeb3904d87e7c770bdf92d3099599d61ac2497b91bf190b11"
|
sum="d141f6030fed50f75e2b03e1eb2e53646c4b21e5386047cb860af5223f102a32"
|
||||||
url="windows-11-24h2-x64/Windows%2011%2024H2%20x64.iso"
|
url="W11x64_26200.6584/26200.6584.250915-1905.25h2_ge_release_svc_refresh_CLIENT_CONSUMER_x64FRE_en-us.iso"
|
||||||
;;
|
;;
|
||||||
"win11x64-enterprise" | "win11x64-enterprise-eval" )
|
"win11x64-enterprise" | "win11x64-enterprise-eval" )
|
||||||
size=6209064960
|
size=6209064960
|
||||||
@@ -1167,10 +1141,15 @@ getLink4() {
|
|||||||
sum="c3c604c03677504e8905090a8ce5bb1dde76b6fd58e10f32e3a25bef21b2abe1"
|
sum="c3c604c03677504e8905090a8ce5bb1dde76b6fd58e10f32e3a25bef21b2abe1"
|
||||||
url="en_windows_8.1_enterprise_with_update_x64_dvd/en_windows_8.1_enterprise_with_update_x64_dvd_6054382.iso"
|
url="en_windows_8.1_enterprise_with_update_x64_dvd/en_windows_8.1_enterprise_with_update_x64_dvd_6054382.iso"
|
||||||
;;
|
;;
|
||||||
|
"win2025" | "win2025-eval" )
|
||||||
|
size=6014152704
|
||||||
|
sum="d0ef4502e350e3c6c53c15b1b3020d38a5ded011bf04998e950720ac8579b23d"
|
||||||
|
url="26100.1742.240906-0331.ge-release-svc-refresh-server-eval-x-64-fre-en-us/26100.1742.240906-0331.ge_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso"
|
||||||
|
;;
|
||||||
"win2022" | "win2022-eval" )
|
"win2022" | "win2022-eval" )
|
||||||
size=5365624832
|
size=5550684160
|
||||||
sum="c3c57bb2cf723973a7dcfb1a21e97dfa035753a7f111e348ad918bb64b3114db"
|
sum="5a077ee2a95976ef9f3623eb4040e25cdf7f8f01dee3b8165a32a7626f39f025"
|
||||||
url="win-server-2022/2227-January_2024/en-us_windows_server_2022_updated_jan_2024_x64_dvd_2b7a0c9f.iso"
|
url="en-us_windows_server_2022_x64_dvd_620d7eac_202405/en-us_windows_server_2022_x64_dvd_620d7eac.iso"
|
||||||
;;
|
;;
|
||||||
"win2019" | "win2019-eval" )
|
"win2019" | "win2019-eval" )
|
||||||
size=5575774208
|
size=5575774208
|
||||||
@@ -1215,7 +1194,7 @@ getLink4() {
|
|||||||
"winvistax64" | "winvistax64-ultimate" )
|
"winvistax64" | "winvistax64-ultimate" )
|
||||||
size=3861460992
|
size=3861460992
|
||||||
sum="edf9f947c5791469fd7d2d40a5dcce663efa754f91847aa1d28ed7f585675b78"
|
sum="edf9f947c5791469fd7d2d40a5dcce663efa754f91847aa1d28ed7f585675b78"
|
||||||
url="en_windows_vista_sp2_x64_dvd_342267_202010/en_windows_vista_sp2_x64_dvd_342267.iso"
|
url="ms_windows_vista_sp2/en_windows_vista_sp2_x64_dvd_342267.iso"
|
||||||
;;
|
;;
|
||||||
"winvistax64-enterprise" )
|
"winvistax64-enterprise" )
|
||||||
size=3205953536
|
size=3205953536
|
||||||
@@ -1251,6 +1230,7 @@ getLink4() {
|
|||||||
size=386859008
|
size=386859008
|
||||||
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"
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case "${ret,,}" in
|
case "${ret,,}" in
|
||||||
@@ -1311,7 +1291,7 @@ isMido() {
|
|||||||
local lang="$2"
|
local lang="$2"
|
||||||
local sum
|
local sum
|
||||||
|
|
||||||
[[ "${MIDO:-}" == [Nn]* ]] && return 1
|
disabled "${MIDO:-}" && return 1
|
||||||
|
|
||||||
sum=$(getMido "$id" "en" "sum")
|
sum=$(getMido "$id" "en" "sum")
|
||||||
[ -n "$sum" ] && return 0
|
[ -n "$sum" ] && return 0
|
||||||
@@ -1324,7 +1304,7 @@ isESD() {
|
|||||||
local id="$1"
|
local id="$1"
|
||||||
local lang="$2"
|
local lang="$2"
|
||||||
|
|
||||||
[[ "${ESD:-}" == [Nn]* ]] && return 1
|
disabled "${ESD:-}" && return 1
|
||||||
|
|
||||||
case "${id,,}" in
|
case "${id,,}" in
|
||||||
"win11${PLATFORM,,}" | "win10${PLATFORM,,}" )
|
"win11${PLATFORM,,}" | "win10${PLATFORM,,}" )
|
||||||
@@ -1379,7 +1359,13 @@ addFolder() {
|
|||||||
|
|
||||||
local file
|
local file
|
||||||
file=$(find "$dest" -maxdepth 1 -type f -iname install.bat -print -quit)
|
file=$(find "$dest" -maxdepth 1 -type f -iname install.bat -print -quit)
|
||||||
[ -f "$file" ] && unix2dos -q "$file"
|
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
if ! unix2dos -q "$file"; then
|
||||||
|
error "Failed to convert $file to DOS format!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -1572,8 +1558,8 @@ prepareInstall() {
|
|||||||
[ -z "$WIDTH" ] && WIDTH="1280"
|
[ -z "$WIDTH" ] && WIDTH="1280"
|
||||||
[ -z "$HEIGHT" ] && HEIGHT="720"
|
[ -z "$HEIGHT" ] && HEIGHT="720"
|
||||||
|
|
||||||
XHEX=$(printf '%x\n' "$WIDTH")
|
XHEX=$(printf '%08x\n' "$WIDTH")
|
||||||
YHEX=$(printf '%x\n' "$HEIGHT")
|
YHEX=$(printf '%08x\n' "$HEIGHT")
|
||||||
|
|
||||||
local username=""
|
local username=""
|
||||||
local password=""
|
local password=""
|
||||||
@@ -1605,7 +1591,7 @@ prepareInstall() {
|
|||||||
echo " OemPnPDriversPath=\"Drivers\viostor;Drivers\NetKVM;Drivers\sata\""
|
echo " OemPnPDriversPath=\"Drivers\viostor;Drivers\NetKVM;Drivers\sata\""
|
||||||
echo " NoWaitAfterTextMode=1"
|
echo " NoWaitAfterTextMode=1"
|
||||||
echo " NoWaitAfterGUIMode=1"
|
echo " NoWaitAfterGUIMode=1"
|
||||||
echo " FileSystem-ConvertNTFS"
|
echo " FileSystem=ConvertNTFS"
|
||||||
echo " ExtendOemPartition=0"
|
echo " ExtendOemPartition=0"
|
||||||
echo " Hibernation=\"No\""
|
echo " Hibernation=\"No\""
|
||||||
echo ""
|
echo ""
|
||||||
@@ -1692,13 +1678,13 @@ prepareInstall() {
|
|||||||
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"
|
||||||
echo "\"DefaultSettings.XResolution\"=dword:00000$XHEX"
|
echo "\"DefaultSettings.XResolution\"=dword:$XHEX"
|
||||||
echo "\"DefaultSettings.YResolution\"=dword:00000$YHEX"
|
echo "\"DefaultSettings.YResolution\"=dword:$YHEX"
|
||||||
echo ""
|
echo ""
|
||||||
echo "[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Control\VIDEO\{23A77BF7-ED96-40EC-AF06-9B1F4867732A}\0000]"
|
echo "[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Control\VIDEO\{23A77BF7-ED96-40EC-AF06-9B1F4867732A}\0000]"
|
||||||
echo "\"DefaultSettings.BitsPerPel\"=dword:00000020"
|
echo "\"DefaultSettings.BitsPerPel\"=dword:00000020"
|
||||||
echo "\"DefaultSettings.XResolution\"=dword:00000$XHEX"
|
echo "\"DefaultSettings.XResolution\"=dword:$XHEX"
|
||||||
echo "\"DefaultSettings.YResolution\"=dword:00000$YHEX"
|
echo "\"DefaultSettings.YResolution\"=dword:$YHEX"
|
||||||
echo ""
|
echo ""
|
||||||
echo "[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce]"
|
echo "[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce]"
|
||||||
echo "\"ScreenSaver\"=\"reg add \\\"HKCU\\\\Control Panel\\\\Desktop\\\" /f /v \\\"SCRNSAVE.EXE\\\" /t REG_SZ /d \\\"off\\\"\""
|
echo "\"ScreenSaver\"=\"reg add \\\"HKCU\\\\Control Panel\\\\Desktop\\\" /f /v \\\"SCRNSAVE.EXE\\\" /t REG_SZ /d \\\"off\\\"\""
|
||||||
@@ -1766,7 +1752,7 @@ prepareInstall() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo "Call Domain.MoveHere(LocalAdminADsPath, \"$username\")"
|
echo "Call Domain.MoveHere(LocalAdminADsPath, \"$username\")"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Set oLink = WshShell.CreateShortcut(WshShell.ExpandEnvironmentStrings(\"%userprofile%\\Desktop\\Shared.lnk\"))"
|
echo "Set oLink = WshShell.CreateShortcut(WshShell.SpecialFolders(\"Desktop\") & \"\\Shared.lnk\")"
|
||||||
echo "With oLink"
|
echo "With oLink"
|
||||||
echo " .TargetPath = \"\\\\host.lan\\Data\""
|
echo " .TargetPath = \"\\\\host.lan\\Data\""
|
||||||
echo " .Save"
|
echo " .Save"
|
||||||
@@ -1796,8 +1782,21 @@ prepareLegacy() {
|
|||||||
rm -f "$dir/$ETFS"
|
rm -f "$dir/$ETFS"
|
||||||
|
|
||||||
local len offset
|
local len offset
|
||||||
len=$(isoinfo -d -i "$iso" | grep "Nsect " | grep -o "[^ ]*$")
|
|
||||||
offset=$(isoinfo -d -i "$iso" | grep "Bootoff " | grep -o "[^ ]*$")
|
if ! len=$(isoinfo -d -i "$iso" | grep "Nsect " | grep -o "[^ ]*$"); then
|
||||||
|
error "Failed to determine boot image size from $desc ISO!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! offset=$(isoinfo -d -i "$iso" | grep "Bootoff " | grep -o "[^ ]*$"); then
|
||||||
|
error "Failed to determine boot image offset from $desc ISO!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! "$len" =~ ^[0-9]+$ ]] || [[ ! "$offset" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "Invalid boot image location found in $desc ISO!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
if ! dd "if=$iso" "of=$dir/$ETFS" bs=2048 "count=$len" "skip=$offset" status=none; then
|
if ! dd "if=$iso" "of=$dir/$ETFS" bs=2048 "count=$len" "skip=$offset" status=none; then
|
||||||
error "Failed to extract boot image from $desc ISO!" && return 1
|
error "Failed to extract boot image from $desc ISO!" && return 1
|
||||||
@@ -1857,7 +1856,6 @@ detectLegacy() {
|
|||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IB -print -quit)
|
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IB -print -quit)
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51ID -print -quit)
|
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51ID -print -quit)
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IL -print -quit)
|
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IL -print -quit)
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IS -print -quit)
|
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AA -print -quit)
|
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AA -print -quit)
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AD -print -quit)
|
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AD -print -quit)
|
||||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AS -print -quit)
|
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AS -print -quit)
|
||||||
@@ -1915,16 +1913,16 @@ setMachine() {
|
|||||||
USB="no"
|
USB="no"
|
||||||
VGA="cirrus"
|
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"
|
||||||
|
[ -z "${ADAPTER:-}" ] && ADAPTER="pcnet" ;;
|
||||||
"win2k"* )
|
"win2k"* )
|
||||||
VGA="cirrus"
|
VGA="cirrus"
|
||||||
MACHINE="pc"
|
MACHINE="pc"
|
||||||
USB="pci-ohci"
|
USB="pci-ohci"
|
||||||
DISK_TYPE="auto"
|
DISK_TYPE="auto"
|
||||||
ADAPTER="rtl8139"
|
BOOT_MODE="windows_legacy"
|
||||||
BOOT_MODE="windows_legacy" ;;
|
[ -z "${ADAPTER:-}" ] && ADAPTER="rtl8139" ;;
|
||||||
"winxp"* | "win2003"* )
|
"winxp"* | "win2003"* )
|
||||||
DISK_TYPE="blk"
|
DISK_TYPE="blk"
|
||||||
BOOT_MODE="windows_legacy" ;;
|
BOOT_MODE="windows_legacy" ;;
|
||||||
|
|||||||
+31
-11
@@ -17,28 +17,48 @@ cd /run
|
|||||||
. install.sh # Run installation
|
. install.sh # Run installation
|
||||||
. disk.sh # Initialize disks
|
. disk.sh # Initialize disks
|
||||||
. display.sh # Initialize graphics
|
. display.sh # Initialize graphics
|
||||||
|
. audio.sh # Initialize audio
|
||||||
. network.sh # Initialize network
|
. network.sh # Initialize network
|
||||||
. samba.sh # Configure samba
|
. samba.sh # Configure samba
|
||||||
. boot.sh # Configure boot
|
. boot.sh # Configure boot
|
||||||
. proc.sh # Initialize processor
|
. proc.sh # Initialize processor
|
||||||
. power.sh # Configure shutdown
|
. power.sh # Configure shutdown
|
||||||
|
. memory.sh # Check available memory
|
||||||
|
. balloon.sh # Initialize ballooning
|
||||||
. config.sh # Configure arguments
|
. config.sh # Configure arguments
|
||||||
|
. finish.sh # Finish initialization
|
||||||
|
|
||||||
trap - ERR
|
trap - ERR
|
||||||
|
|
||||||
version=$(qemu-system-x86_64 --version | head -n 1 | cut -d '(' -f 1 | awk '{ print $NF }')
|
cmd=(qemu-system-x86_64)
|
||||||
info "Booting ${APP}${BOOT_DESC} using QEMU v$version..."
|
version=$("${cmd[@]}" --version | awk 'NR==1 { print $4 }')
|
||||||
|
info "Booting ${APP}${BOOT_DESC} using QEMU v$version..." && echo
|
||||||
|
|
||||||
{ qemu-system-x86_64 ${ARGS:+ $ARGS} >"$QEMU_OUT" 2>"$QEMU_LOG"; rc=$?; } || :
|
pipe="$QEMU_DIR/qemu.pipe"
|
||||||
(( rc != 0 )) && error "$(<"$QEMU_LOG")" && exit 15
|
rm -f "$pipe" && mkfifo "$pipe"
|
||||||
|
|
||||||
terminal
|
tee "$QEMU_PTY" <"$pipe" |
|
||||||
|
sed -u \
|
||||||
|
-e 's/\x1B\[[=0-9;]*[a-z]//gi' \
|
||||||
|
-e 's/\x1B\x63//g' \
|
||||||
|
-e 's/\x1B\[[=?]7l//g' \
|
||||||
|
-e '/^$/d' \
|
||||||
|
-e 's/\x44\x53\x73//g' \
|
||||||
|
-e 's/failed to load Boot/skipped Boot/g' \
|
||||||
|
-e 's/0): Not Found/0)/g' &
|
||||||
|
|
||||||
|
if ! enabled "$SHUTDOWN"; then
|
||||||
|
exec "${cmd[@]}" ${ARGS:+ $ARGS} >"$pipe"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"${cmd[@]}" ${ARGS:+ $ARGS} >"$pipe" &
|
||||||
|
|
||||||
|
pid=$!
|
||||||
( sleep 30; boot ) &
|
( sleep 30; boot ) &
|
||||||
tail -fn +0 "$QEMU_LOG" --pid=$$ 2>/dev/null &
|
|
||||||
cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" | \
|
rc=0
|
||||||
sed -u -e 's/\x1B\[[=0-9;]*[a-z]//gi' \
|
wait "$pid" || rc=$?
|
||||||
-e 's/failed to load Boot/skipped Boot/g' \
|
[ -f "$QEMU_END" ] && exit "$rc"
|
||||||
-e 's/0): Not Found/0)/g' & wait $! || :
|
|
||||||
|
|
||||||
sleep 1 & wait $!
|
sleep 1 & wait $!
|
||||||
[ ! -f "$QEMU_END" ] && finish 0
|
finish "$rc"
|
||||||
|
|||||||
+351
-243
@@ -11,30 +11,30 @@ backup () {
|
|||||||
local iso="$1"
|
local iso="$1"
|
||||||
local name="unknown"
|
local name="unknown"
|
||||||
local root="$STORAGE/backups"
|
local root="$STORAGE/backups"
|
||||||
local previous="$STORAGE/windows.base"
|
local previous
|
||||||
|
|
||||||
if [ -f "$previous" ]; then
|
previous=$(readState "base") || return 1
|
||||||
|
[ -n "$previous" ] && name="${previous%.*}"
|
||||||
previous=$(<"$previous")
|
|
||||||
previous="${previous//[![:print:]]/}"
|
|
||||||
|
|
||||||
[ -n "$previous" ] && name="${previous%.*}"
|
|
||||||
|
|
||||||
|
if ! makeDir "$root"; then
|
||||||
|
error "Failed to create directory \"$root\" !"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$root"
|
|
||||||
local folder="$name"
|
local folder="$name"
|
||||||
local dir="$root/$folder"
|
local dir="$root/$folder"
|
||||||
|
|
||||||
while [ -d "$dir" ]
|
while [ -d "$dir" ]
|
||||||
do
|
do
|
||||||
count=$((count+1))
|
(( count++ ))
|
||||||
folder="${name}.${count}"
|
folder="${name}.${count}"
|
||||||
dir="$root/$folder"
|
dir="$root/$folder"
|
||||||
done
|
done
|
||||||
|
|
||||||
rm -rf "$dir"
|
if ! makeDir "$dir"; then
|
||||||
mkdir -p "$dir"
|
error "Failed to create directory \"$dir\" !"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
[ -f "$iso" ] && mv -f "$iso" "$dir/"
|
[ -f "$iso" ] && mv -f "$iso" "$dir/"
|
||||||
find "$STORAGE" -maxdepth 1 -type f -iname 'data.*' -not -iname '*.iso' -exec mv -n {} "$dir/" \;
|
find "$STORAGE" -maxdepth 1 -type f -iname 'data.*' -not -iname '*.iso' -exec mv -n {} "$dir/" \;
|
||||||
@@ -53,47 +53,42 @@ skipInstall() {
|
|||||||
local method=""
|
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
|
||||||
|
|
||||||
if [ -f "$previous" ]; then
|
previous=$(readState "base") || return 1
|
||||||
|
|
||||||
previous=$(<"$previous")
|
if [ -n "$previous" ]; then
|
||||||
previous="${previous//[![:print:]]/}"
|
if [[ "${STORAGE,,}/${previous,,}" != "${iso,,}" ]]; then
|
||||||
|
|
||||||
if [ -n "$previous" ]; then
|
if ! hasDisk; then
|
||||||
if [[ "${STORAGE,,}/${previous,,}" != "${iso,,}" ]]; then
|
|
||||||
|
|
||||||
if ! hasDisk; then
|
|
||||||
|
|
||||||
rm -f "$STORAGE/$previous"
|
|
||||||
return 1
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${iso,,}" == "${STORAGE,,}/windows."* ]]; then
|
|
||||||
method="your custom .iso file was changed"
|
|
||||||
else
|
|
||||||
if [[ "${previous,,}" != "windows."* ]]; then
|
|
||||||
method="the VERSION variable was changed"
|
|
||||||
else
|
|
||||||
method="your custom .iso file was removed"
|
|
||||||
|
|
||||||
if [ -f "$boot" ]; then
|
|
||||||
info "Detected that $method, will be ignored."
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
info "Detected that $method, a backup of your previous installation will be saved..."
|
|
||||||
! backup "$STORAGE/$previous" && error "Backup failed!"
|
|
||||||
|
|
||||||
|
rm -f "$STORAGE/$previous"
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
|
if [[ "${iso,,}" == "${STORAGE,,}/windows."* ]]; then
|
||||||
|
method="your custom .iso file was changed"
|
||||||
|
else
|
||||||
|
if [[ "${previous,,}" != "windows."* ]]; then
|
||||||
|
method="the VERSION variable was changed"
|
||||||
|
else
|
||||||
|
method="your custom .iso file was removed"
|
||||||
|
|
||||||
|
if [ -f "$boot" ]; then
|
||||||
|
info "Detected that $method, will be ignored."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Detected that $method, a backup of your previous installation will be saved..."
|
||||||
|
! backup "$STORAGE/$previous" && error "Backup failed!"
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -f "$boot" ] && hasDisk && return 0
|
[ -f "$boot" ] && hasDisk && return 0
|
||||||
@@ -102,9 +97,9 @@ skipInstall() {
|
|||||||
[ ! -s "$iso" ] && return 1
|
[ ! -s "$iso" ] && return 1
|
||||||
|
|
||||||
# Check if the ISO was already processed by our script
|
# Check if the ISO was already processed by our script
|
||||||
magic=$(dd if="$iso" seek=0 bs=1 count=1 status=none | tr -d '\000')
|
magic=$(dd if="$iso" bs=1 count=1 status=none | tr -d '\000')
|
||||||
magic="$(printf '%s' "$magic" | od -A n -t x1 -v | tr -d ' \n')"
|
magic="$(printf '%s' "$magic" | od -A n -t x1 -v | tr -d ' \n')"
|
||||||
byte="16" && [[ "$MANUAL" == [Yy1]* ]] && byte="17"
|
byte="16" && enabled "$MANUAL" && byte="17"
|
||||||
|
|
||||||
if [[ "$magic" != "$byte" ]]; then
|
if [[ "$magic" != "$byte" ]]; then
|
||||||
|
|
||||||
@@ -127,7 +122,6 @@ startInstall() {
|
|||||||
if [[ "${VERSION,,}" == "http"* ]]; then
|
if [[ "${VERSION,,}" == "http"* ]]; then
|
||||||
|
|
||||||
file=$(basename "${VERSION%%\?*}")
|
file=$(basename "${VERSION%%\?*}")
|
||||||
file="${file//+/ }"
|
|
||||||
printf -v file '%b' "${file//%/\\x}"
|
printf -v file '%b' "${file//%/\\x}"
|
||||||
file="${file//[!A-Za-z0-9._-]/_}"
|
file="${file//[!A-Za-z0-9._-]/_}"
|
||||||
|
|
||||||
@@ -156,7 +150,9 @@ startInstall() {
|
|||||||
! backup "" && error "Backup failed!"
|
! backup "" && error "Backup failed!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$TMP"
|
if ! makeDir "$TMP"; then
|
||||||
|
error "Failed to create directory \"$TMP\" !" && exit 50
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "$CUSTOM" ]; then
|
if [ -z "$CUSTOM" ]; then
|
||||||
|
|
||||||
@@ -178,6 +174,24 @@ startInstall() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkFreeSpace() {
|
||||||
|
|
||||||
|
local dir="$1"
|
||||||
|
local size="$2"
|
||||||
|
local size_gb space space_gb
|
||||||
|
|
||||||
|
size_gb=$(formatBytes "$size")
|
||||||
|
space=$(df --output=avail -B 1 "$dir" | tail -n 1)
|
||||||
|
space_gb=$(formatBytes "$space")
|
||||||
|
|
||||||
|
if (( size > space )); then
|
||||||
|
error "Not enough free space in $STORAGE, have $space_gb available but need at least $size_gb."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
finishInstall() {
|
finishInstall() {
|
||||||
|
|
||||||
local iso="$1"
|
local iso="$1"
|
||||||
@@ -188,64 +202,77 @@ finishInstall() {
|
|||||||
error "Failed to find ISO file: $iso" && return 1
|
error "Failed to find ISO file: $iso" && return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$iso" == "$STORAGE/"* ]]; then
|
||||||
|
if ! setOwner "$iso"; then
|
||||||
|
error "Failed to set the owner for \"$iso\" !"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$aborted" != [Yy1]* ]]; then
|
if [[ "$aborted" != [Yy1]* ]]; then
|
||||||
# Mark ISO as prepared via magic byte
|
# Mark ISO as prepared via magic byte
|
||||||
byte="16" && [[ "$MANUAL" == [Yy1]* ]] && byte="17"
|
byte="16" && enabled "$MANUAL" && byte="17"
|
||||||
if ! printf '%b' "\x$byte" | dd of="$iso" bs=1 seek=0 count=1 conv=notrunc status=none; then
|
if ! printf '%b' "\x$byte" | dd of="$iso" bs=1 seek=0 count=1 conv=notrunc status=none; then
|
||||||
warn "failed to set magic byte in ISO file: $iso"
|
warn "failed to set magic byte in ISO file: $iso"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp -f /run/version "$STORAGE/windows.ver"
|
local file="$STORAGE/windows.ver"
|
||||||
|
cp -f /etc/version "$file" || return 1
|
||||||
|
|
||||||
|
if ! setOwner "$file"; then
|
||||||
|
error "Failed to set the owner for \"$file\" !"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$iso" == "$STORAGE/"* ]]; then
|
if [[ "$iso" == "$STORAGE/"* ]]; then
|
||||||
if [[ "$aborted" != [Yy1]* ]] || [ -z "$CUSTOM" ]; then
|
if [[ "$aborted" != [Yy1]* ]] || [ -z "$CUSTOM" ]; then
|
||||||
base=$(basename "$iso")
|
base=$(basename "$iso")
|
||||||
echo "$base" > "$STORAGE/windows.base"
|
writeState "base" "$base" || return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${PLATFORM,,}" == "x64" ]]; then
|
if [[ "${PLATFORM,,}" == "x64" ]]; then
|
||||||
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
|
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
|
||||||
echo "$BOOT_MODE" > "$STORAGE/windows.mode"
|
writeState "mode" "$BOOT_MODE" || return 1
|
||||||
if [[ "${MACHINE,,}" != "q35" ]]; then
|
if [[ "${MACHINE,,}" != "q35" ]]; then
|
||||||
echo "$MACHINE" > "$STORAGE/windows.old"
|
writeState "old" "$MACHINE" || return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# Enable secure boot + TPM on manual installs as Win11 requires
|
# Enable secure boot + TPM on manual installs as Win11 requires
|
||||||
if [[ "$MANUAL" == [Yy1]* || "$aborted" == [Yy1]* ]]; then
|
if enabled "$MANUAL" || [[ "$aborted" == [Yy1]* ]]; then
|
||||||
if [[ "${DETECTED,,}" == "win11"* ]]; then
|
if [[ "${DETECTED,,}" == "win11"* ]]; then
|
||||||
BOOT_MODE="windows_secure"
|
BOOT_MODE="windows_secure"
|
||||||
echo "$BOOT_MODE" > "$STORAGE/windows.mode"
|
writeState "mode" "$BOOT_MODE" || return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# Enable secure boot on multi-socket systems to workaround freeze
|
# Enable secure boot on multi-socket systems to workaround freeze
|
||||||
if [ -n "$SOCKETS" ] && [[ "$SOCKETS" != "1" ]]; then
|
if [ -n "$SOCKETS" ] && [[ "$SOCKETS" != "1" ]]; then
|
||||||
BOOT_MODE="windows_secure"
|
BOOT_MODE="windows_secure"
|
||||||
echo "$BOOT_MODE" > "$STORAGE/windows.mode"
|
writeState "mode" "$BOOT_MODE" || return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${ARGS:-}" ]; then
|
if [ -n "${ARGS:-}" ]; then
|
||||||
ARGUMENTS="$ARGS ${ARGUMENTS:-}"
|
ARGUMENTS="$ARGS ${ARGUMENTS:-}"
|
||||||
echo "$ARGS" > "$STORAGE/windows.args"
|
writeState "args" "$ARGS" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${VGA:-}" ] && [[ "${VGA:-}" != "virtio"* ]]; then
|
if [ -n "${VGA:-}" ] && [[ "${VGA:-}" != "virtio"* ]]; then
|
||||||
echo "$VGA" > "$STORAGE/windows.vga"
|
writeState "vga" "$VGA" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${USB:-}" ] && [[ "${USB:-}" != "qemu-xhci"* ]]; then
|
if [ -n "${USB:-}" ] && [[ "${USB:-}" != "qemu-xhci"* ]]; then
|
||||||
echo "$USB" > "$STORAGE/windows.usb"
|
writeState "usb" "$USB" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${DISK_TYPE:-}" ] && [[ "${DISK_TYPE:-}" != "scsi" ]]; then
|
if [ -n "${DISK_TYPE:-}" ] && [[ "${DISK_TYPE:-}" != "scsi" ]]; then
|
||||||
echo "$DISK_TYPE" > "$STORAGE/windows.type"
|
writeState "type" "$DISK_TYPE" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${ADAPTER:-}" ] && [[ "${ADAPTER:-}" != "virtio-net-pci" ]]; then
|
if [ -n "${ADAPTER:-}" ] && [[ "${ADAPTER:-}" != "virtio-net-pci" ]]; then
|
||||||
echo "$ADAPTER" > "$STORAGE/windows.net"
|
writeState "net" "$ADAPTER" || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$TMP"
|
rm -rf "$TMP"
|
||||||
@@ -259,7 +286,7 @@ abortInstall() {
|
|||||||
local efi
|
local efi
|
||||||
|
|
||||||
[[ "${iso,,}" == *".esd" ]] && exit 60
|
[[ "${iso,,}" == *".esd" ]] && exit 60
|
||||||
[[ "${UNPACK:-}" == [Yy1]* ]] && exit 60
|
enabled "${UNPACK:-}" && exit 60
|
||||||
|
|
||||||
efi=$(find "$dir" -maxdepth 1 -type d -iname efi -print -quit)
|
efi=$(find "$dir" -maxdepth 1 -type d -iname efi -print -quit)
|
||||||
|
|
||||||
@@ -333,91 +360,180 @@ detectCustom() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEsdField() {
|
||||||
|
|
||||||
|
local list="$1"
|
||||||
|
local index="$2"
|
||||||
|
|
||||||
|
sed -n "${index}p" <<< "$list" | tr -cd '0-9'
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
extractESD() {
|
extractESD() {
|
||||||
|
|
||||||
local iso="$1"
|
local iso="$1"
|
||||||
local dir="$2"
|
local dir="$2"
|
||||||
local version="$3"
|
local version="$3"
|
||||||
local desc="$4"
|
local desc="$4"
|
||||||
local size size_gb space space_gb desc
|
|
||||||
|
|
||||||
local msg="Extracting $desc bootdisk..."
|
local msg ret index
|
||||||
info "$msg" && html "$msg"
|
local minSize freeSpace bootPad installPad
|
||||||
|
local info count totals links
|
||||||
|
local bootTotal bootLinks bootSize
|
||||||
|
local wimTotal wimLinks wimSize
|
||||||
|
local installSize
|
||||||
|
local bootWim installWim
|
||||||
|
local edition imgEdition
|
||||||
|
|
||||||
if [ "$(stat -c%s "$iso")" -lt 100000000 ]; then
|
minSize=100000000
|
||||||
error "Invalid ESD file: Size is smaller than 100 MB" && return 1
|
freeSpace=9606127360
|
||||||
|
bootPad=60000000
|
||||||
|
installPad=3000000
|
||||||
|
|
||||||
|
msg="Extracting $desc bootdisk"
|
||||||
|
info "$msg..." && html "$msg..."
|
||||||
|
|
||||||
|
if [ "$(stat -c%s "$iso")" -lt "$minSize" ]; then
|
||||||
|
error "Invalid ESD file: Size is smaller than 100 MB"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$dir"
|
rm -rf "$dir"
|
||||||
mkdir -p "$dir"
|
|
||||||
|
|
||||||
size=16106127360
|
if ! makeDir "$dir"; then
|
||||||
size_gb=$(formatBytes "$size")
|
error "Failed to create directory \"$dir\" !"
|
||||||
space=$(df --output=avail -B 1 "$dir" | tail -n 1)
|
return 1
|
||||||
space_gb=$(formatBytes "$space")
|
|
||||||
|
|
||||||
if (( size > space )); then
|
|
||||||
error "Not enough free space in $STORAGE, have $space_gb available but need at least $size_gb." && return 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local esdImageCount
|
checkFreeSpace "$dir" "$freeSpace" || return 1
|
||||||
esdImageCount=$(wimlib-imagex info "$iso" | awk '/Image Count:/ {print $3}')
|
|
||||||
|
|
||||||
if [ -z "$esdImageCount" ]; then
|
info=$(wimlib-imagex info "$iso") || {
|
||||||
error "Cannot read the image count in ESD file!" && return 1
|
error "Cannot read ESD file information!"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
count=$(awk '/Image Count:/ {print $3}' <<< "$info")
|
||||||
|
|
||||||
|
if [[ ! "$count" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "Cannot read the image count in ESD file!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
wimlib-imagex apply "$iso" 1 "$dir" --quiet 2>/dev/null || {
|
if (( count < 3 )); then
|
||||||
retVal=$?
|
error "Invalid ESD file: expected at least 3 images, found $count."
|
||||||
error "Extracting $desc bootdisk failed" && return $retVal
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
totals=$(grep "Total Bytes:" <<< "$info" || true)
|
||||||
|
links=$(grep "Hard Link Bytes:" <<< "$info" || true)
|
||||||
|
|
||||||
|
bootTotal=$(getEsdField "$totals" 1)
|
||||||
|
bootLinks=$(getEsdField "$links" 1)
|
||||||
|
|
||||||
|
if [[ ! "$bootTotal" =~ ^[0-9]+$ ]] || [[ ! "$bootLinks" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "Cannot read bootdisk size from ESD file!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
bootSize=$(( bootTotal - bootLinks ))
|
||||||
|
|
||||||
|
wimTotal=$(getEsdField "$totals" 3)
|
||||||
|
wimLinks=$(getEsdField "$links" 3)
|
||||||
|
|
||||||
|
if [[ ! "$wimTotal" =~ ^[0-9]+$ ]] || [[ ! "$wimLinks" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "Cannot read boot.wim size from ESD file!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
wimSize=$(( wimTotal - wimLinks + bootPad ))
|
||||||
|
|
||||||
|
/run/progress.sh "$dir" "$bootSize" "$msg ([P])..." &
|
||||||
|
|
||||||
|
index="1"
|
||||||
|
wimlib-imagex apply "$iso" "$index" "$dir" --quiet 2>/dev/null || {
|
||||||
|
ret=$?
|
||||||
|
fKill "progress.sh"
|
||||||
|
error "Extracting $desc bootdisk failed ($ret)"
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
local bootWimFile="$dir/sources/boot.wim"
|
fKill "progress.sh"
|
||||||
local installWimFile="$dir/sources/install.wim"
|
|
||||||
|
|
||||||
local msg="Extracting $desc environment..."
|
bootWim="$dir/sources/boot.wim"
|
||||||
info "$msg" && html "$msg"
|
installWim="$dir/sources/install.wim"
|
||||||
|
|
||||||
wimlib-imagex export "$iso" 2 "$bootWimFile" --compress=none --quiet || {
|
msg="Extracting $desc environment"
|
||||||
retVal=$?
|
info "$msg..." && html "$msg..."
|
||||||
error "Adding WinPE failed" && return ${retVal}
|
|
||||||
|
index="2"
|
||||||
|
/run/progress.sh "$bootWim" "$wimSize" "$msg ([P])..." &
|
||||||
|
|
||||||
|
wimlib-imagex export "$iso" "$index" "$bootWim" --compress=none --quiet || {
|
||||||
|
ret=$?
|
||||||
|
fKill "progress.sh"
|
||||||
|
error "Adding WinPE failed ($ret)"
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
local msg="Extracting $desc setup..."
|
fKill "progress.sh"
|
||||||
info "$msg" && html "$msg"
|
|
||||||
|
|
||||||
wimlib-imagex export "$iso" 3 "$bootWimFile" --compress=none --boot --quiet || {
|
msg="Extracting $desc setup"
|
||||||
retVal=$?
|
info "$msg..."
|
||||||
error "Adding Windows Setup failed" && return ${retVal}
|
|
||||||
|
index="3"
|
||||||
|
/run/progress.sh "$bootWim" "$wimSize" "$msg ([P])..." &
|
||||||
|
|
||||||
|
wimlib-imagex export "$iso" "$index" "$bootWim" --compress=none --boot --quiet || {
|
||||||
|
ret=$?
|
||||||
|
fKill "progress.sh"
|
||||||
|
error "Adding Windows Setup failed ($ret)"
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fKill "progress.sh"
|
||||||
|
|
||||||
if [[ "${PLATFORM,,}" == "x64" ]]; then
|
if [[ "${PLATFORM,,}" == "x64" ]]; then
|
||||||
LABEL="CCCOMA_X64FRE_EN-US_DV9"
|
LABEL="CCCOMA_X64FRE_EN-US_DV9"
|
||||||
else
|
else
|
||||||
LABEL="CPBA_A64FRE_EN-US_DV9"
|
LABEL="CPBA_A64FRE_EN-US_DV9"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local msg="Extracting $desc image..."
|
msg="Extracting $desc image"
|
||||||
info "$msg" && html "$msg"
|
info "$msg..." && html "$msg..."
|
||||||
|
|
||||||
local edition imageIndex imageEdition
|
|
||||||
edition=$(getCatalog "$version" "name")
|
edition=$(getCatalog "$version" "name")
|
||||||
|
|
||||||
if [ -z "$edition" ]; then
|
if [ -z "$edition" ]; then
|
||||||
error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
|
error "Invalid VERSION specified, value \"$version\" is not recognized!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for (( imageIndex=4; imageIndex<=esdImageCount; imageIndex++ )); do
|
for (( index=4; index<=count; index++ )); do
|
||||||
imageEdition=$(wimlib-imagex info "$iso" ${imageIndex} | grep '^Description:' | sed 's/Description:[ \t]*//')
|
|
||||||
[[ "${imageEdition,,}" != "${edition,,}" ]] && continue
|
imgEdition=$(wimlib-imagex info "$iso" "$index" | grep '^Description:' | sed 's/Description:[ \t]*//')
|
||||||
wimlib-imagex export "$iso" ${imageIndex} "$installWimFile" --compress=LZMS --chunk-size 128K --quiet || {
|
[[ "${imgEdition,,}" != "${edition,,}" ]] && continue
|
||||||
retVal=$?
|
|
||||||
error "Addition of $imageIndex to the $desc image failed" && return $retVal
|
installSize=$(stat -c%s "$iso")
|
||||||
|
installSize=$(( installSize + installPad ))
|
||||||
|
|
||||||
|
/run/progress.sh "$installWim" "$installSize" "$msg ([P])..." &
|
||||||
|
|
||||||
|
wimlib-imagex export "$iso" "$index" "$installWim" --compress=LZMS --chunk-size 128K --quiet || {
|
||||||
|
ret=$?
|
||||||
|
fKill "progress.sh"
|
||||||
|
error "Addition of $index to the $desc image failed ($ret)"
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fKill "progress.sh"
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
error "Failed to find product '$edition' in install.wim!" && return 1
|
fKill "progress.sh"
|
||||||
|
error "Failed to find product '$edition' in install.wim!"
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
extractImage() {
|
extractImage() {
|
||||||
@@ -426,7 +542,7 @@ extractImage() {
|
|||||||
local dir="$2"
|
local dir="$2"
|
||||||
local version="$3"
|
local version="$3"
|
||||||
local desc="local ISO"
|
local desc="local ISO"
|
||||||
local file size size_gb space space_gb
|
local file size
|
||||||
|
|
||||||
if [ -z "$CUSTOM" ]; then
|
if [ -z "$CUSTOM" ]; then
|
||||||
desc="downloaded ISO"
|
desc="downloaded ISO"
|
||||||
@@ -440,34 +556,36 @@ extractImage() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local msg="Extracting $desc image..."
|
local msg="Extracting $desc image"
|
||||||
info "$msg" && html "$msg"
|
info "$msg..." && html "$msg..."
|
||||||
|
|
||||||
rm -rf "$dir"
|
rm -rf "$dir"
|
||||||
mkdir -p "$dir"
|
|
||||||
|
if ! makeDir "$dir"; then
|
||||||
|
error "Failed to create directory \"$dir\" !" && return 1
|
||||||
|
fi
|
||||||
|
|
||||||
size=$(stat -c%s "$iso")
|
size=$(stat -c%s "$iso")
|
||||||
size_gb=$(formatBytes "$size")
|
|
||||||
space=$(df --output=avail -B 1 "$dir" | tail -n 1)
|
|
||||||
space_gb=$(formatBytes "$space")
|
|
||||||
|
|
||||||
if ((size<100000000)); then
|
if (( size < 100000000 )); then
|
||||||
error "Invalid ISO file: Size is smaller than 100 MB" && return 1
|
error "Invalid ISO file: Size is smaller than 100 MB" && return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (( size > space )); then
|
checkFreeSpace "$dir" "$size" || return 1
|
||||||
error "Not enough free space in $STORAGE, have $space_gb available but need at least $size_gb." && return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -rf "$dir"
|
rm -rf "$dir"
|
||||||
|
/run/progress.sh "$dir" "$size" "$msg ([P])..." &
|
||||||
|
|
||||||
if ! 7z x "$iso" -o"$dir" > /dev/null; then
|
if ! 7z x "$iso" -o"$dir" > /dev/null; then
|
||||||
|
fKill "progress.sh"
|
||||||
error "Failed to extract ISO file: $iso" && return 1
|
error "Failed to extract ISO file: $iso" && return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${UNPACK:-}" != [Yy1]* ]]; then
|
fKill "progress.sh"
|
||||||
|
|
||||||
LABEL=$(isoinfo -d -i "$iso" | sed -n 's/Volume id: //p')
|
if ! enabled "${UNPACK:-}"; then
|
||||||
|
|
||||||
|
LABEL=$(isoinfo -d -i "$iso" | sed -n 's/Volume id: //p') || LABEL=""
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@@ -481,8 +599,8 @@ extractImage() {
|
|||||||
error "Failed to extract archive!" && return 1
|
error "Failed to extract archive!" && return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
LABEL=$(isoinfo -d -i "$file" | sed -n 's/Volume id: //p')
|
LABEL=$(isoinfo -d -i "$file" | sed -n 's/Volume id: //p') || LABEL=""
|
||||||
rm -f "$file"
|
rm -f "$file" || warn "Failed to remove temporary ISO file: $file"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -501,7 +619,7 @@ getPlatform() {
|
|||||||
case "${arch,,}" in
|
case "${arch,,}" in
|
||||||
"0" ) platform="x86" ;;
|
"0" ) platform="x86" ;;
|
||||||
"9" ) platform="x64" ;;
|
"9" ) platform="x64" ;;
|
||||||
"12" )platform="arm64" ;;
|
"12" ) platform="arm64" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo "$platform"
|
echo "$platform"
|
||||||
@@ -636,7 +754,7 @@ detectImage() {
|
|||||||
|
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
local version="$2"
|
local version="$2"
|
||||||
local desc msg find language
|
local desc msg language
|
||||||
|
|
||||||
XML=""
|
XML=""
|
||||||
|
|
||||||
@@ -648,7 +766,7 @@ detectImage() {
|
|||||||
|
|
||||||
skipVersion "${DETECTED,,}" && return 0
|
skipVersion "${DETECTED,,}" && return 0
|
||||||
|
|
||||||
if ! setXML "" && [[ "$MANUAL" != [Yy1]* ]]; then
|
if ! setXML "" && ! enabled "$MANUAL"; then
|
||||||
MANUAL="Y"
|
MANUAL="Y"
|
||||||
desc=$(printEdition "$DETECTED" "this version")
|
desc=$(printEdition "$DETECTED" "this version")
|
||||||
warn "the answer file for $desc was not found ($DETECTED.xml), $FB."
|
warn "the answer file for $desc was not found ($DETECTED.xml), $FB."
|
||||||
@@ -678,14 +796,18 @@ detectImage() {
|
|||||||
warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" && return 1
|
warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" && return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info=$(wimlib-imagex info -xml "$wim" | iconv -f UTF-16LE -t UTF-8)
|
if ! info=$(wimlib-imagex info -xml "$wim" | iconv -f UTF-16LE -t UTF-8); then
|
||||||
|
warn "failed to read Windows image information, $FB"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
checkPlatform "$info" || exit 67
|
checkPlatform "$info" || exit 67
|
||||||
|
|
||||||
DETECTED=$(detectVersion "$info")
|
DETECTED=$(detectVersion "$info")
|
||||||
|
|
||||||
if [ -z "$DETECTED" ]; then
|
if [ -z "$DETECTED" ]; then
|
||||||
msg="Failed to determine Windows version from image"
|
msg="Failed to determine Windows version from image"
|
||||||
if setXML "" || [[ "$MANUAL" == [Yy1]* ]]; then
|
if setXML "" || enabled "$MANUAL"; then
|
||||||
info "${msg}!"
|
info "${msg}!"
|
||||||
else
|
else
|
||||||
MANUAL="Y"
|
MANUAL="Y"
|
||||||
@@ -712,8 +834,8 @@ detectImage() {
|
|||||||
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"
|
||||||
|
|
||||||
if setXML "$fallback" || [[ "$MANUAL" == [Yy1]* ]]; then
|
if setXML "$fallback" || enabled "$MANUAL"; then
|
||||||
[[ "$MANUAL" != [Yy1]* ]] && warn "${msg}."
|
! enabled "$MANUAL" && warn "${msg}."
|
||||||
else
|
else
|
||||||
MANUAL="Y"
|
MANUAL="Y"
|
||||||
warn "${msg}, $FB."
|
warn "${msg}, $FB."
|
||||||
@@ -754,7 +876,7 @@ updateXML() {
|
|||||||
|
|
||||||
local asset="$1"
|
local asset="$1"
|
||||||
local language="$2"
|
local language="$2"
|
||||||
local culture region user admin pass keyboard
|
local culture region user admin pass pw keyboard
|
||||||
|
|
||||||
[ -z "$HEIGHT" ] && HEIGHT="720"
|
[ -z "$HEIGHT" ] && HEIGHT="720"
|
||||||
[ -z "$WIDTH" ] && WIDTH="1280"
|
[ -z "$WIDTH" ] && WIDTH="1280"
|
||||||
@@ -800,12 +922,12 @@ updateXML() {
|
|||||||
pw=$(printf '%s' "${pass}Password" | 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)
|
||||||
admin=$(printf '%s' "${pass}AdministratorPassword" | iconv -f utf-8 -t utf-16le | base64 -w 0)
|
admin=$(printf '%s' "${pass}AdministratorPassword" | iconv -f utf-8 -t utf-16le | base64 -w 0)
|
||||||
|
|
||||||
sed -i "s/<Value>password<\/Value>/<Value>$admin<\/Value>/g" "$asset"
|
sed -i "s|<Value>password<\/Value>|<Value>$admin<\/Value>|g" "$asset"
|
||||||
sed -i "s/<PlainText>true<\/PlainText>/<PlainText>false<\/PlainText>/g" "$asset"
|
sed -i "s|<PlainText>true<\/PlainText>|<PlainText>false<\/PlainText>|g" "$asset"
|
||||||
sed -z "s/<Password>...........<Value \/>/<Password>\n <Value>$pw<\/Value>/g" -i "$asset"
|
sed -i -z "s|<Password>...........<Value \/>|<Password>\n <Value>$pw<\/Value>|g" "$asset"
|
||||||
sed -z "s/<Password>...............<Value \/>/<Password>\n <Value>$pw<\/Value>/g" -i "$asset"
|
sed -i -z "s|<Password>...............<Value \/>|<Password>\n <Value>$pw<\/Value>|g" "$asset"
|
||||||
sed -z "s/<AdministratorPassword>...........<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset"
|
sed -i -z "s|<AdministratorPassword>...........<Value \/>|<AdministratorPassword>\n <Value>$admin<\/Value>|g" "$asset"
|
||||||
sed -z "s/<AdministratorPassword>...............<Value \/>/<AdministratorPassword>\n <Value>$admin<\/Value>/g" -i "$asset"
|
sed -i -z "s|<AdministratorPassword>...............<Value \/>|<AdministratorPassword>\n <Value>$admin<\/Value>|g" "$asset"
|
||||||
|
|
||||||
if [ -n "$EDITION" ]; then
|
if [ -n "$EDITION" ]; then
|
||||||
[[ "${EDITION^^}" == "CORE" ]] && EDITION="STANDARDCORE"
|
[[ "${EDITION^^}" == "CORE" ]] && EDITION="STANDARDCORE"
|
||||||
@@ -905,29 +1027,20 @@ addDrivers() {
|
|||||||
|
|
||||||
wimlib-imagex update "$file" "$index" --command "delete --force --recursive /$target" >/dev/null || true
|
wimlib-imagex update "$file" "$index" --command "delete --force --recursive /$target" >/dev/null || true
|
||||||
|
|
||||||
addDriver "$version" "$drivers" "$target" "qxl" || return 1
|
local driver
|
||||||
addDriver "$version" "$drivers" "$target" "viofs" || return 1
|
local driver_list=( qxl viofs sriov smbus qxldod viorng viostor viomem NetKVM Balloon vioscsi pvpanic vioinput viogpudo vioserial qemupciserial )
|
||||||
addDriver "$version" "$drivers" "$target" "sriov" || return 1
|
|
||||||
addDriver "$version" "$drivers" "$target" "smbus" || return 1
|
for driver in "${driver_list[@]}"; do
|
||||||
addDriver "$version" "$drivers" "$target" "qxldod" || return 1
|
addDriver "$version" "$drivers" "$target" "$driver" || return 1
|
||||||
addDriver "$version" "$drivers" "$target" "viorng" || return 1
|
done
|
||||||
addDriver "$version" "$drivers" "$target" "viostor" || return 1
|
|
||||||
addDriver "$version" "$drivers" "$target" "viomem" || return 1
|
local dst="$src/\$OEM\$/\$\$/Drivers"
|
||||||
addDriver "$version" "$drivers" "$target" "NetKVM" || return 1
|
mkdir -p "$dst" || return 1
|
||||||
addDriver "$version" "$drivers" "$target" "Balloon" || return 1
|
cp -Lr "$dest/." "$dst" || return 1
|
||||||
addDriver "$version" "$drivers" "$target" "vioscsi" || return 1
|
|
||||||
addDriver "$version" "$drivers" "$target" "pvpanic" || return 1
|
|
||||||
addDriver "$version" "$drivers" "$target" "vioinput" || return 1
|
|
||||||
addDriver "$version" "$drivers" "$target" "viogpudo" || return 1
|
|
||||||
addDriver "$version" "$drivers" "$target" "vioserial" || return 1
|
|
||||||
addDriver "$version" "$drivers" "$target" "qemupciserial" || return 1
|
|
||||||
|
|
||||||
case "${version,,}" in
|
case "${version,,}" in
|
||||||
"win11x64"* | "win2025"* )
|
"win11x64"* | "win2025"* )
|
||||||
# Workaround Virtio GPU driver bug
|
# Workaround Virtio GPU driver bug
|
||||||
local dst="$src/\$OEM\$/\$\$/Drivers"
|
|
||||||
mkdir -p "$dst" || return 1
|
|
||||||
cp -Lr "$dest/." "$dst" || return 1
|
|
||||||
rm -rf "$dest/viogpudo"
|
rm -rf "$dest/viogpudo"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -946,16 +1059,16 @@ updateImage() {
|
|||||||
local asset="$2"
|
local asset="$2"
|
||||||
local language="$3"
|
local language="$3"
|
||||||
local tmp="/tmp/install"
|
local tmp="/tmp/install"
|
||||||
local file="autounattend.xml"
|
local xml="autounattend.xml"
|
||||||
local org="${file//.xml/.org}"
|
local bak="${xml//.xml/.org}"
|
||||||
local dat="${file//.xml/.dat}"
|
local dat="${xml//.xml/.dat}"
|
||||||
local desc path src wim xml index result
|
local desc path src wim name info idx
|
||||||
|
|
||||||
skipVersion "${DETECTED,,}" && return 0
|
skipVersion "${DETECTED,,}" && return 0
|
||||||
|
|
||||||
if [ ! -s "$asset" ] || [ ! -f "$asset" ]; then
|
if [ ! -s "$asset" ] || [ ! -f "$asset" ]; then
|
||||||
asset=""
|
asset=""
|
||||||
if [[ "$MANUAL" != [Yy1]* ]]; then
|
if ! enabled "$MANUAL"; then
|
||||||
MANUAL="Y"
|
MANUAL="Y"
|
||||||
warn "no answer file provided, $FB."
|
warn "no answer file provided, $FB."
|
||||||
fi
|
fi
|
||||||
@@ -967,23 +1080,30 @@ updateImage() {
|
|||||||
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit)
|
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit)
|
||||||
|
|
||||||
if [ ! -d "$src" ]; then
|
if [ ! -d "$src" ]; then
|
||||||
error "failed to locate 'sources' folder in ISO image, $FB" && return 1
|
error "failed to locate 'sources' folder in ISO image, $FB"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
wim=$(find "$src" -maxdepth 1 -type f \( -iname boot.wim -or -iname boot.esd \) -print -quit)
|
wim=$(find "$src" -maxdepth 1 -type f \( -iname boot.wim -or -iname boot.esd \) -print -quit)
|
||||||
|
|
||||||
if [ ! -f "$wim" ]; then
|
if [ ! -f "$wim" ]; then
|
||||||
error "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" && return 1
|
error "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
index="1"
|
idx="1"
|
||||||
result=$(wimlib-imagex info -xml "$wim" | iconv -f UTF-16LE -t UTF-8)
|
|
||||||
|
|
||||||
if [[ "${result^^}" == *"<IMAGE INDEX=\"2\">"* ]]; then
|
if ! info=$(wimlib-imagex info -xml "$wim" | iconv -f UTF-16LE -t UTF-8); then
|
||||||
index="2"
|
warn "failed to read boot image information, $FB"
|
||||||
|
MANUAL="Y"
|
||||||
|
info=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! addDrivers "$src" "$tmp" "$wim" "$index" "$DETECTED"; then
|
if [[ "${info^^}" == *"<IMAGE INDEX=\"2\">"* ]]; then
|
||||||
|
idx="2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! addDrivers "$src" "$tmp" "$wim" "$idx" "$DETECTED"; then
|
||||||
error "Failed to add drivers to image!"
|
error "Failed to add drivers to image!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -991,55 +1111,69 @@ updateImage() {
|
|||||||
error "Failed to add OEM folder to image!"
|
error "Failed to add OEM folder to image!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if wimlib-imagex extract "$wim" "$index" "/$file" "--dest-dir=$tmp" >/dev/null 2>&1; then
|
if wimlib-imagex extract "$wim" "$idx" "/$xml" "--dest-dir=$tmp" >/dev/null 2>&1; then
|
||||||
if ! wimlib-imagex extract "$wim" "$index" "/$dat" "--dest-dir=$tmp" >/dev/null 2>&1; then
|
if ! wimlib-imagex extract "$wim" "$idx" "/$dat" "--dest-dir=$tmp" >/dev/null 2>&1; then
|
||||||
if ! wimlib-imagex extract "$wim" "$index" "/$org" "--dest-dir=$tmp" >/dev/null 2>&1; then
|
if ! wimlib-imagex extract "$wim" "$idx" "/$bak" "--dest-dir=$tmp" >/dev/null 2>&1; then
|
||||||
if ! wimlib-imagex update "$wim" "$index" --command "rename /$file /$org" > /dev/null; then
|
if ! wimlib-imagex update "$wim" "$idx" --command "rename /$xml /$bak" > /dev/null; then
|
||||||
warn "failed to backup original answer file ($file)."
|
warn "failed to backup original answer file ($xml)."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$MANUAL" != [Yy1]* ]]; then
|
if ! enabled "$MANUAL"; then
|
||||||
|
|
||||||
xml=$(basename "$asset")
|
name=$(basename "$asset")
|
||||||
info "Adding $xml for automatic installation..."
|
local answer="$tmp/$name"
|
||||||
|
|
||||||
local answer="$tmp/$xml"
|
info "Adding $name for automatic installation..."
|
||||||
cp "$asset" "$answer"
|
|
||||||
updateXML "$answer" "$language"
|
|
||||||
|
|
||||||
if ! wimlib-imagex update "$wim" "$index" --command "add $answer /$file" > /dev/null; then
|
if ! cp "$asset" "$answer"; then
|
||||||
|
error "Failed to copy answer file to $answer."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! updateXML "$answer" "$language"; then
|
||||||
|
error "Failed to update answer file: $answer"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! wimlib-imagex update "$wim" "$idx" --command "add $answer /$xml" > /dev/null; then
|
||||||
MANUAL="Y"
|
MANUAL="Y"
|
||||||
warn "failed to add answer file ($xml) to ISO image, $FB"
|
warn "failed to add answer file ($name) to ISO image, $FB"
|
||||||
else
|
else
|
||||||
wimlib-imagex update "$wim" "$index" --command "add $answer /$dat" > /dev/null || true
|
wimlib-imagex update "$wim" "$idx" --command "add $answer /$dat" > /dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$MANUAL" == [Yy1]* ]]; then
|
if enabled "$MANUAL"; then
|
||||||
|
|
||||||
wimlib-imagex update "$wim" "$index" --command "delete --force /$file" > /dev/null || true
|
wimlib-imagex update "$wim" "$idx" --command "delete --force /$xml" > /dev/null || true
|
||||||
|
|
||||||
if wimlib-imagex extract "$wim" "$index" "/$org" "--dest-dir=$tmp" >/dev/null 2>&1; then
|
if wimlib-imagex extract "$wim" "$idx" "/$bak" "--dest-dir=$tmp" >/dev/null 2>&1; then
|
||||||
if ! wimlib-imagex update "$wim" "$index" --command "add $tmp/$org /$file" > /dev/null; then
|
if ! wimlib-imagex update "$wim" "$idx" --command "add $tmp/$bak /$xml" > /dev/null; then
|
||||||
warn "failed to restore original answer file ($org)."
|
warn "failed to restore original answer file ($bak)."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local find="$file"
|
name="$xml"
|
||||||
[[ "$MANUAL" == [Yy1]* ]] && find="$org"
|
enabled "$MANUAL" && name="$bak"
|
||||||
path=$(find "$dir" -maxdepth 1 -type f -iname "$find" -print -quit)
|
path=$(find "$dir" -maxdepth 1 -type f -iname "$name" -print -quit)
|
||||||
|
|
||||||
if [ -f "$path" ]; then
|
if [ -f "$path" ]; then
|
||||||
if [[ "$MANUAL" != [Yy1]* ]]; then
|
if ! enabled "$MANUAL"; then
|
||||||
mv -f "$path" "${path%.*}.org"
|
if ! mv -f "$path" "${path%.*}.org"; then
|
||||||
|
error "Failed to rename answer file: $path"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
mv -f "$path" "${path%.*}.xml"
|
if ! mv -f "$path" "${path%.*}.xml"; then
|
||||||
|
error "Failed to rename answer file: $path"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1065,7 +1199,7 @@ buildImage() {
|
|||||||
local failed=""
|
local failed=""
|
||||||
local cat="BOOT.CAT"
|
local cat="BOOT.CAT"
|
||||||
local log="/run/shm/iso.log"
|
local log="/run/shm/iso.log"
|
||||||
local base size size_gb space space_gb desc
|
local base size desc
|
||||||
|
|
||||||
if [ -f "$BOOT" ]; then
|
if [ -f "$BOOT" ]; then
|
||||||
error "File $BOOT does already exist?!" && return 1
|
error "File $BOOT does already exist?!" && return 1
|
||||||
@@ -1077,8 +1211,8 @@ buildImage() {
|
|||||||
|
|
||||||
desc=$(printVersion "$DETECTED" "ISO")
|
desc=$(printVersion "$DETECTED" "ISO")
|
||||||
|
|
||||||
local msg="Building $desc image..."
|
local msg="Building $desc image"
|
||||||
info "$msg" && html "$msg"
|
info "$msg..." && html "$msg..."
|
||||||
|
|
||||||
[ -z "$LABEL" ] && LABEL="Windows"
|
[ -z "$LABEL" ] && LABEL="Windows"
|
||||||
|
|
||||||
@@ -1086,14 +1220,10 @@ buildImage() {
|
|||||||
error "Failed to locate file \"$ETFS\" in ISO image!" && return 1
|
error "Failed to locate file \"$ETFS\" in ISO image!" && return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
size=$(du -h -b --max-depth=0 "$dir" | cut -f1)
|
size=$(du -b --max-depth=0 "$dir" | cut -f1)
|
||||||
size_gb=$(formatBytes "$size")
|
checkFreeSpace "$TMP" "$size" || return 1
|
||||||
space=$(df --output=avail -B 1 "$TMP" | tail -n 1)
|
|
||||||
space_gb=$(formatBytes "$space")
|
|
||||||
|
|
||||||
if (( size > space )); then
|
/run/progress.sh "$out" "$size" "$msg ([P])..." &
|
||||||
error "Not enough free space in $STORAGE, have $space_gb available but need at least $size_gb." && return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then
|
if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then
|
||||||
|
|
||||||
@@ -1115,67 +1245,45 @@ buildImage() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
fKill "progress.sh"
|
||||||
|
|
||||||
if [ -n "$failed" ]; then
|
if [ -n "$failed" ]; then
|
||||||
[ -s "$log" ] && echo "$(<"$log")"
|
[ -s "$log" ] && echo "$(<"$log")"
|
||||||
error "Failed to build image!" && return 1
|
error "Failed to build image!" && return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local error=""
|
local err=""
|
||||||
local hide="Warning: creating filesystem that does not conform to ISO-9660."
|
local hide="Warning: creating filesystem that does not conform to ISO-9660."
|
||||||
|
|
||||||
[ -s "$log" ] && error="$(<"$log")"
|
[ -s "$log" ] && err="$(<"$log")"
|
||||||
[[ "$error" != "$hide" ]] && echo "$error"
|
[[ "$err" != "$hide" ]] && echo "$err"
|
||||||
|
|
||||||
mv -f "$out" "$BOOT" || return 1
|
mv -f "$out" "$BOOT" || return 1
|
||||||
|
|
||||||
|
if ! setOwner "$BOOT"; then
|
||||||
|
error "Failed to set the owner for \"$BOOT\" !"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
bootWindows() {
|
bootWindows() {
|
||||||
|
|
||||||
if [ -f "$STORAGE/windows.args" ]; then
|
ARGS=$(readState "$STORAGE/windows.args") || return 1
|
||||||
ARGS=$(<"$STORAGE/windows.args")
|
|
||||||
ARGS="${ARGS//[![:print:]]/}"
|
if [ -n "$ARGS" ]; then
|
||||||
ARGUMENTS="$ARGS ${ARGUMENTS:-}"
|
ARGUMENTS="$ARGS ${ARGUMENTS:-}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -s "$STORAGE/windows.vga" ] && [ -f "$STORAGE/windows.vga" ]; then
|
restoreState "VGA" "$STORAGE/windows.vga" || return 1
|
||||||
if [ -z "${VGA:-}" ]; then
|
restoreState "USB" "$STORAGE/windows.usb" || return 1
|
||||||
VGA=$(<"$STORAGE/windows.vga")
|
restoreState "ADAPTER" "$STORAGE/windows.net" || return 1
|
||||||
VGA="${VGA//[![:print:]]/}"
|
restoreState "DISK_TYPE" "$STORAGE/windows.type" || return 1
|
||||||
fi
|
restoreState "BOOT_MODE" "$STORAGE/windows.mode" "Y" || return 1
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -s "$STORAGE/windows.usb" ] && [ -f "$STORAGE/windows.usb" ]; then
|
if [[ "${PLATFORM,,}" == "x64" ]]; then
|
||||||
if [ -z "${USB:-}" ]; then
|
restoreState "MACHINE" "$STORAGE/windows.old" "Y" || return 1
|
||||||
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 [ -z "${DISK_TYPE:-}" ]; then
|
|
||||||
DISK_TYPE=$(<"$STORAGE/windows.type")
|
|
||||||
DISK_TYPE="${DISK_TYPE//[![:print:]]/}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -s "$STORAGE/windows.mode" ] && [ -f "$STORAGE/windows.mode" ]; then
|
|
||||||
BOOT_MODE=$(<"$STORAGE/windows.mode")
|
|
||||||
BOOT_MODE="${BOOT_MODE//[![:print:]]/}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -s "$STORAGE/windows.old" ] && [ -f "$STORAGE/windows.old" ]; then
|
|
||||||
if [[ "${PLATFORM,,}" == "x64" ]]; then
|
|
||||||
MACHINE=$(<"$STORAGE/windows.old")
|
|
||||||
MACHINE="${MACHINE//[![:print:]]/}"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
+337
-234
@@ -1,55 +1,53 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
handle_curl_error() {
|
handleCurlError() {
|
||||||
|
|
||||||
local error_code="$1"
|
local code="$1"
|
||||||
local server_name="$2"
|
local server="$2"
|
||||||
|
|
||||||
case "$error_code" in
|
case "$code" in
|
||||||
1) error "Unsupported protocol!" ;;
|
1) error "Unsupported protocol!" ;;
|
||||||
2) error "Failed to initialize curl!" ;;
|
2) error "Failed to initialize curl!" ;;
|
||||||
3) error "The URL format is malformed!" ;;
|
3) error "The URL format is malformed!" ;;
|
||||||
5) error "Failed to resolve address of proxy host!" ;;
|
5) error "Failed to resolve address of proxy host!" ;;
|
||||||
6) error "Failed to resolve $server_name servers! Is there an Internet connection?" ;;
|
6) error "Failed to resolve $server servers! Is there an Internet connection?" ;;
|
||||||
7) error "Failed to contact $server_name servers! Is there an Internet connection or is the server down?" ;;
|
7) error "Failed to contact $server servers! Is there an Internet connection or is the server down?" ;;
|
||||||
8) error "$server_name servers returned a malformed HTTP response!" ;;
|
8) error "$server servers returned a malformed HTTP response!" ;;
|
||||||
16) error "A problem was detected in the HTTP2 framing layer!" ;;
|
16) error "A problem was detected in the HTTP2 framing layer!" ;;
|
||||||
22) error "$server_name servers returned a failing HTTP status code!" ;;
|
22) error "$server servers returned a failing HTTP status code!" ;;
|
||||||
23) error "Failed at writing Windows media to disk! Out of disk space or permission error?" ;;
|
23) error "Failed at writing Windows media to disk! Out of disk space or permission error?" ;;
|
||||||
26) error "Failed to read Windows media from disk!" ;;
|
26) error "Failed to read Windows media from disk!" ;;
|
||||||
27) error "Ran out of memory during download!" ;;
|
27) error "Ran out of memory during download!" ;;
|
||||||
28) error "Connection timed out to $server_name server!" ;;
|
28) error "Connection timed out to $server server!" ;;
|
||||||
35) error "SSL connection error from $server_name server!" ;;
|
35) error "SSL connection error from $server server!" ;;
|
||||||
36) error "Failed to continue earlier download!" ;;
|
36) error "Failed to continue earlier download!" ;;
|
||||||
52) error "Received no data from the $server_name server!" ;;
|
52) error "Received no data from the $server server!" ;;
|
||||||
63) error "$server_name servers returned an unexpectedly large response!" ;;
|
63) error "$server servers returned an unexpectedly large response!" ;;
|
||||||
# POSIX defines exit statuses 1-125 as usable by us
|
126) error "Curl command cannot be executed!" ;;
|
||||||
# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_02
|
127) error "Curl command not found!" ;;
|
||||||
$((error_code <= 125)))
|
|
||||||
# Must be some other server or network error (possibly with this specific request/file)
|
|
||||||
# This is when accounting for all possible errors in the curl manual assuming a correctly formed curl command and an HTTP(S) request, using only the curl features we're using, and a sane build
|
|
||||||
error "Miscellaneous server or network error, reason: $error_code"
|
|
||||||
;;
|
|
||||||
126 | 127 ) error "Curl command not found!" ;;
|
|
||||||
# Exit statuses are undefined by POSIX beyond this point
|
|
||||||
*)
|
*)
|
||||||
case "$(kill -l "$error_code")" in
|
if (( code <= 125 )); then
|
||||||
# Signals defined to exist by POSIX:
|
# Must be some other server or network error (possibly with this specific request/file)
|
||||||
# https://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html
|
# This is when accounting for all possible errors in the curl manual assuming a correctly formed
|
||||||
INT) error "Curl was interrupted!" ;;
|
# curl command and an HTTP(S) request, using only the curl features we're using, and a sane build.
|
||||||
# There could be other signals but these are most common
|
error "Miscellaneous server or network error, reason: $code"
|
||||||
SEGV | ABRT ) error "Curl crashed! Please report any core dumps to curl developers." ;;
|
else
|
||||||
*) error "Curl terminated due to fatal signal $error_code !" ;;
|
case "$(kill -l "$code" 2>/dev/null || true)" in
|
||||||
esac
|
INT) error "Curl was interrupted!" ;;
|
||||||
|
SEGV | ABRT) error "Curl crashed! Please report any core dumps to curl developers." ;;
|
||||||
|
*) error "Curl terminated due to fatal signal $code !" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
get_agent() {
|
getAgent() {
|
||||||
|
|
||||||
local user_agent
|
local browser_version
|
||||||
|
|
||||||
# Determine approximate latest Firefox release
|
# Determine approximate latest Firefox release
|
||||||
browser_version="$((124 + ($(date +%s) - 1710892800) / 2419200))"
|
browser_version="$((124 + ($(date +%s) - 1710892800) / 2419200))"
|
||||||
@@ -58,202 +56,249 @@ get_agent() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
download_windows() {
|
downloadWindows() {
|
||||||
|
|
||||||
local id="$1"
|
local id="$1"
|
||||||
local lang="$2"
|
local lang="$2"
|
||||||
local desc="$3"
|
local desc="$3"
|
||||||
local sku_id=""
|
|
||||||
local sku_url=""
|
local rc=0
|
||||||
local iso_url=""
|
local ovToken="" ovTicks="" ovTime=""
|
||||||
local iso_json=""
|
local skuId="" skuUrl="" skuJson=""
|
||||||
local language=""
|
local linkUrl="" linkJson="" link=""
|
||||||
local session_id=""
|
local language="" orgId=""
|
||||||
local user_agent=""
|
local instance="" vlsUrl="" ovUrl="" ovData=""
|
||||||
local download_type=""
|
local session="" agent="" type=""
|
||||||
local windows_version=""
|
local winVer="" page="" productId=""
|
||||||
local iso_download_link=""
|
|
||||||
local download_page_html=""
|
|
||||||
local product_edition_id=""
|
|
||||||
local language_skuid_json=""
|
|
||||||
local profile="606624d44113"
|
local profile="606624d44113"
|
||||||
|
|
||||||
user_agent=$(get_agent)
|
agent=$(getAgent)
|
||||||
language=$(getLanguage "$lang" "name")
|
language=$(getLanguage "$lang" "name")
|
||||||
|
|
||||||
case "${id,,}" in
|
case "${id,,}" in
|
||||||
"win11x64" ) windows_version="11" && download_type="1" ;;
|
"win11x64" ) winVer="11" && type="1" ;;
|
||||||
"win10x64" ) windows_version="10" && download_type="1" ;;
|
"win11arm64" ) winVer="11arm64" && type="2" ;;
|
||||||
"win11arm64" ) windows_version="11arm64" && download_type="2" ;;
|
|
||||||
* ) error "Invalid VERSION specified, value \"$id\" is not recognized!" && return 1 ;;
|
* ) error "Invalid VERSION specified, value \"$id\" is not recognized!" && return 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
local url="https://www.microsoft.com/en-us/software-download/windows$windows_version"
|
local url="https://www.microsoft.com/en-us/software-download/windows$winVer"
|
||||||
[[ "${id,,}" == "win10"* ]] && url+="ISO"
|
|
||||||
|
|
||||||
# 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)
|
if ! session=$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random); then
|
||||||
session_id="${session_id//[![:print:]]/}"
|
error "Failed to generate session ID!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
session="${session//[![:print:]]/}"
|
||||||
|
|
||||||
|
if [ -z "$session" ]; then
|
||||||
|
error "Failed to generate session ID!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
# 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
|
||||||
# This is the *only* request we make that Fido doesn't. Fido manually maintains a list of all the Windows release/edition product edition IDs in its script (see: $WindowsVersions array). This is helpful for downloading older releases (e.g. Windows 10 1909, 21H1, etc.) but we always want to get the newest release which is why we get this value dynamically
|
# This is the *only* request we make that Fido doesn't. Fido manually maintains a list of all the Windows release/edition product edition IDs in its script (see: $WindowsVersions array). This is helpful for downloading older releases (e.g. Windows 10 1909, 21H1, etc.) but we always want to get the newest release which is why we get this value dynamically
|
||||||
# Also, keeping a "$WindowsVersions" array like Fido does would be way too much of a maintenance burden
|
# Also, keeping a "$WindowsVersions" array like Fido does would be way too much of a maintenance burden
|
||||||
# Remove "Accept" header that curl sends by default
|
# Remove "Accept" header that curl sends by default
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Parsing download page: ${url}"
|
enabled "$DEBUG" && echo "Parsing download page: ${url}"
|
||||||
download_page_html=$(curl --silent --max-time 30 --user-agent "$user_agent" --header "Accept:" --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url") || {
|
page=$(curl --silent --max-time 30 --user-agent "$agent" --header "Accept:" --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url") || {
|
||||||
handle_curl_error "$?" "Microsoft"
|
handleCurlError "$?" "Microsoft"
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo -n "Getting Product edition ID: "
|
enabled "$DEBUG" && echo -n "Getting Product edition ID: "
|
||||||
product_edition_id=$(echo "$download_page_html" | grep -Eo '<option value="[0-9]+">Windows' | cut -d '"' -f 2 | head -n 1 | tr -cd '0-9' | head -c 16)
|
productId=$(echo "$page" | grep -Eo '<option value="[0-9]+">Windows' | cut -d '"' -f 2 | head -n 1 | tr -cd '0-9' | head -c 16)
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "$product_edition_id"
|
enabled "$DEBUG" && echo "$productId"
|
||||||
|
|
||||||
if [ -z "$product_edition_id" ]; then
|
if [ -z "$productId" ]; then
|
||||||
error "Product edition ID not found!"
|
error "Product edition ID not found!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Permit Session ID: $session_id"
|
# Microsoft download "protection" requires the sessionId to be whitelisted through vlscppe.microsoft.com/tags
|
||||||
|
|
||||||
|
orgId="y6jn8c31"
|
||||||
|
vlsUrl="https://vlscppe.microsoft.com/tags?org_id=$orgId&session_id=$session"
|
||||||
|
|
||||||
|
enabled "$DEBUG" && echo "Getting Session ID: $session"
|
||||||
|
|
||||||
# Permit Session ID
|
# Permit Session ID
|
||||||
curl --silent --max-time 30 --output /dev/null --user-agent "$user_agent" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "https://vlscppe.microsoft.com/tags?org_id=y6jn8c31&session_id=$session_id" || {
|
curl --silent --max-time 30 --output /dev/null --user-agent "$agent" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "$vlsUrl" || {
|
||||||
# This should only happen if there's been some change to how this API works
|
# This should only happen if there's been some change to how this API works
|
||||||
handle_curl_error "$?" "Microsoft"
|
handleCurlError "$?" "Microsoft"
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo -n "Getting language SKU ID: "
|
# Microsoft download "protection" also requires an ov-df.microsoft.com request/reply
|
||||||
sku_url="https://www.microsoft.com/software-download-connector/api/getskuinformationbyproductedition?profile=$profile&ProductEditionId=$product_edition_id&SKU=undefined&friendlyFileName=undefined&Locale=en-US&sessionID=$session_id"
|
# 1) Request mdt.js to get w and rticks. InstanceId is (currently) constant.
|
||||||
language_skuid_json=$(curl --silent --max-time 30 --request GET --user-agent "$user_agent" --referer "$url" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "$sku_url") || {
|
|
||||||
handle_curl_error "$?" "Microsoft"
|
instance="560dc9f3-1aa5-4a2f-b63c-9e18f8d0e175"
|
||||||
|
ovUrl="https://ov-df.microsoft.com/mdt.js?instanceId=$instance&PageId=si&session_id=$session"
|
||||||
|
|
||||||
|
enabled "$DEBUG" && echo -n "Getting OV data: "
|
||||||
|
|
||||||
|
ovData=$(curl --silent --max-time 30 --user-agent "$agent" --header "Accept:" --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$ovUrl") || {
|
||||||
|
handleCurlError "$?" "Microsoft"
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
{ sku_id=$(echo "$language_skuid_json" | jq --arg LANG "$language" -r '.Skus[] | select(.Language==$LANG).Id') 2>/dev/null; rc=$?; } || :
|
if [[ $ovData =~ [\?\&]w=([A-Fa-f0-9]+) ]]; then
|
||||||
|
ovToken="${BASH_REMATCH[1]}"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "$sku_id" ] || [[ "${sku_id,,}" == "null" ]] || (( rc != 0 )); then
|
if [[ $ovData =~ rticks=\"\+?([0-9]+) ]]; then
|
||||||
|
ovTicks="${BASH_REMATCH[1]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $ovToken || -z $ovTicks ]]; then
|
||||||
|
error "Could not extract ov-df data from Microsoft server!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
enabled "$DEBUG" && echo "$ovToken"
|
||||||
|
|
||||||
|
sleep 0.2
|
||||||
|
|
||||||
|
# 2) Send a reply with session ID, current epoch and previously retrieved w and rticks
|
||||||
|
|
||||||
|
ovTime=$(date +%s%3N)
|
||||||
|
ovUrl="https://ov-df.microsoft.com/?session_id=$session&CustomerId=$instance&PageId=si&w=$ovToken&mdt=$ovTime&rticks=$ovTicks"
|
||||||
|
|
||||||
|
enabled "$DEBUG" && echo "Sending OV reply: $instance"
|
||||||
|
|
||||||
|
curl --silent --max-time 30 --output /dev/null --user-agent "$agent" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "$ovUrl" || {
|
||||||
|
# This should only happen if there's been some change to how this API works
|
||||||
|
handleCurlError "$?" "Microsoft"
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled "$DEBUG" && echo -n "Getting language SKU ID: "
|
||||||
|
|
||||||
|
skuUrl="https://www.microsoft.com/software-download-connector/api/getskuinformationbyproductedition?profile=$profile&ProductEditionId=$productId&SKU=undefined&friendlyFileName=undefined&Locale=en-US&sessionID=$session"
|
||||||
|
skuJson=$(curl --silent --max-time 30 --request GET --user-agent "$agent" --referer "$url" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "$skuUrl") || {
|
||||||
|
handleCurlError "$?" "Microsoft"
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
{ skuId=$(echo "$skuJson" | jq --arg LANG "$language" -r '.Skus[] | select(.Language==$LANG).Id') 2>/dev/null; rc=$?; } || :
|
||||||
|
|
||||||
|
if [ -z "$skuId" ] || [[ "${skuId,,}" == "null" ]] || (( rc != 0 )); then
|
||||||
language=$(getLanguage "$lang" "desc")
|
language=$(getLanguage "$lang" "desc")
|
||||||
error "No download in the $language language available for $desc!"
|
error "No download in the $language language available for $desc!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "$sku_id"
|
enabled "$DEBUG" && echo "$skuId"
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Getting ISO download link..."
|
enabled "$DEBUG" && echo "Getting ISO download link..."
|
||||||
|
|
||||||
# Get ISO download link
|
# Get ISO download link
|
||||||
# If any request is going to be blocked by Microsoft it's always this last one (the previous requests always seem to succeed)
|
# If any request is going to be blocked by Microsoft it's always this last one (the previous requests always seem to succeed)
|
||||||
|
|
||||||
iso_url="https://www.microsoft.com/software-download-connector/api/GetProductDownloadLinksBySku?profile=$profile&ProductEditionId=undefined&SKU=$sku_id&friendlyFileName=undefined&Locale=en-US&sessionID=$session_id"
|
linkUrl="https://www.microsoft.com/software-download-connector/api/GetProductDownloadLinksBySku?profile=$profile&ProductEditionId=undefined&SKU=$skuId&friendlyFileName=undefined&Locale=en-US&sessionID=$session"
|
||||||
iso_json=$(curl --silent --max-time 30 --request GET --user-agent "$user_agent" --referer "$url" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "$iso_url")
|
linkJson=$(curl --silent --max-time 30 --request GET --user-agent "$agent" --referer "$url" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "$linkUrl") || {
|
||||||
|
handleCurlError "$?" "Microsoft"
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
if ! [ "$iso_json" ]; then
|
if ! [ "$linkJson" ]; then
|
||||||
# This should only happen if there's been some change to how this API works
|
# This should only happen if there's been some change to how this API works
|
||||||
error "Microsoft servers gave us an empty response to our request for an automated download."
|
error "Microsoft servers gave us an empty response to our request for an automated download."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if echo "$iso_json" | grep -q "Sentinel marked this request as rejected."; then
|
if echo "$linkJson" | grep -q "Sentinel marked this request as rejected."; then
|
||||||
error "Microsoft blocked the automated download request based on your IP address."
|
error "Microsoft blocked the automated download request based on your IP address."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if echo "$iso_json" | grep -q "We are unable to complete your request at this time."; then
|
if echo "$linkJson" | grep -q "We are unable to complete your request at this time."; then
|
||||||
error "Microsoft blocked the automated download request based on your IP address."
|
error "Microsoft blocked the automated download request."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
{ iso_download_link=$(echo "$iso_json" | jq --argjson TYPE "$download_type" -r '.ProductDownloadOptions[] | select(.DownloadType==$TYPE).Uri') 2>/dev/null; rc=$?; } || :
|
{ link=$(echo "$linkJson" | jq --argjson TYPE "$type" -r '.ProductDownloadOptions[] | select(.DownloadType==$TYPE).Uri') 2>/dev/null; rc=$?; } || :
|
||||||
|
|
||||||
if [ -z "$iso_download_link" ] || [[ "${iso_download_link,,}" == "null" ]] || (( rc != 0 )); then
|
if [ -z "$link" ] || [[ "${link,,}" == "null" ]] || (( rc != 0 )); then
|
||||||
error "Microsoft servers gave us no download link to our request for an automated download!"
|
error "Microsoft server gave us no download link to our request for an automated download!"
|
||||||
info "Response: $iso_json"
|
info "Response: $linkJson"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MIDO_URL="$iso_download_link"
|
MIDO_URL="$link"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
download_windows_eval() {
|
downloadWindowsEval() {
|
||||||
|
|
||||||
local id="$1"
|
local id="$1"
|
||||||
local lang="$2"
|
local lang="$2"
|
||||||
local desc="$3"
|
local desc="$3"
|
||||||
local filter=""
|
local filter="" culture="" compare="" language=""
|
||||||
local culture=""
|
local agent="" type="" winVer=""
|
||||||
local compare=""
|
|
||||||
local language=""
|
|
||||||
local user_agent=""
|
|
||||||
local enterprise_type=""
|
|
||||||
local windows_version=""
|
|
||||||
|
|
||||||
case "${id,,}" in
|
case "${id,,}" in
|
||||||
"win11${PLATFORM,,}-enterprise-eval" )
|
"win11${PLATFORM,,}-enterprise-eval" )
|
||||||
enterprise_type="enterprise"
|
type="enterprise"
|
||||||
windows_version="windows-11-enterprise" ;;
|
winVer="windows-11-enterprise" ;;
|
||||||
"win11${PLATFORM,,}-enterprise-iot-eval" )
|
"win11${PLATFORM,,}-enterprise-iot-eval" )
|
||||||
enterprise_type="iot"
|
type="iot"
|
||||||
windows_version="windows-11-iot-enterprise-ltsc-eval" ;;
|
winVer="windows-11-iot-enterprise-ltsc-eval" ;;
|
||||||
"win11${PLATFORM,,}-enterprise-ltsc-eval" )
|
"win11${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||||
enterprise_type="iot"
|
type="iot"
|
||||||
windows_version="windows-11-iot-enterprise-ltsc-eval" ;;
|
winVer="windows-11-iot-enterprise-ltsc-eval" ;;
|
||||||
"win10${PLATFORM,,}-enterprise-eval" )
|
|
||||||
enterprise_type="enterprise"
|
|
||||||
windows_version="windows-10-enterprise" ;;
|
|
||||||
"win10${PLATFORM,,}-enterprise-ltsc-eval" )
|
|
||||||
enterprise_type="ltsc"
|
|
||||||
windows_version="windows-10-enterprise" ;;
|
|
||||||
"win2025-eval" )
|
"win2025-eval" )
|
||||||
enterprise_type="server"
|
type="server"
|
||||||
windows_version="windows-server-2025" ;;
|
winVer="windows-server-2025" ;;
|
||||||
"win2022-eval" )
|
"win2022-eval" )
|
||||||
enterprise_type="server"
|
type="server"
|
||||||
windows_version="windows-server-2022" ;;
|
winVer="windows-server-2022" ;;
|
||||||
"win2019-hv" )
|
"win2019-hv" )
|
||||||
enterprise_type="server"
|
type="server"
|
||||||
windows_version="hyper-v-server-2019" ;;
|
winVer="hyper-v-server-2019" ;;
|
||||||
"win2019-eval" )
|
"win2019-eval" )
|
||||||
enterprise_type="server"
|
type="server"
|
||||||
windows_version="windows-server-2019" ;;
|
winVer="windows-server-2019" ;;
|
||||||
"win2016-eval" )
|
"win2016-eval" )
|
||||||
enterprise_type="server"
|
type="server"
|
||||||
windows_version="windows-server-2016" ;;
|
winVer="windows-server-2016" ;;
|
||||||
"win2012r2-eval" )
|
"win2012r2-eval" )
|
||||||
enterprise_type="server"
|
type="server"
|
||||||
windows_version="windows-server-2012-r2" ;;
|
winVer="windows-server-2012-r2" ;;
|
||||||
* )
|
* )
|
||||||
error "Invalid VERSION specified, value \"$id\" is not recognized!" && return 1 ;;
|
error "Invalid VERSION specified, value \"$id\" is not recognized!" && return 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
user_agent=$(get_agent)
|
agent=$(getAgent)
|
||||||
culture=$(getLanguage "$lang" "culture")
|
culture=$(getLanguage "$lang" "culture")
|
||||||
|
|
||||||
local country="${culture#*-}"
|
local country="${culture#*-}"
|
||||||
local iso_download_page_html=""
|
local link=""
|
||||||
local url="https://www.microsoft.com/en-us/evalcenter/download-$windows_version"
|
local links=""
|
||||||
|
local page=""
|
||||||
|
local url="https://www.microsoft.com/en-us/evalcenter/download-$winVer"
|
||||||
|
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Parsing download page: ${url}"
|
enabled "$DEBUG" && echo "Parsing download page: ${url}"
|
||||||
iso_download_page_html=$(curl --silent --max-time 30 --user-agent "$user_agent" --location --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url") || {
|
page=$(curl --silent --max-time 30 --user-agent "$agent" --location --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url") || {
|
||||||
handle_curl_error "$?" "Microsoft"
|
handleCurlError "$?" "Microsoft"
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
if ! [ "$iso_download_page_html" ]; then
|
if ! [ "$page" ]; then
|
||||||
# This should only happen if there's been some change to where this download page is located
|
# This should only happen if there's been some change to where this download page is located
|
||||||
error "Windows server download page gave us an empty response"
|
error "Windows server download page gave us an empty response"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Getting download link.."
|
enabled "$DEBUG" && echo "Getting download link.."
|
||||||
|
|
||||||
filter="https://go.microsoft.com/fwlink/?linkid=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country,,}"
|
filter="https://go.microsoft.com/fwlink/?linkid=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country,,}"
|
||||||
|
|
||||||
if ! echo "$iso_download_page_html" | grep -io "$filter" > /dev/null; then
|
if ! echo "$page" | grep -io "$filter" > /dev/null; then
|
||||||
filter="https://go.microsoft.com/fwlink/p/?linkid=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country,,}"
|
filter="https://go.microsoft.com/fwlink/p/?linkid=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country,,}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
iso_download_links=$(echo "$iso_download_page_html" | grep -io "$filter") || {
|
links=$(echo "$page" | grep -io "$filter") || {
|
||||||
# This should only happen if there's been some change to the download endpoint web address
|
# This should only happen if there's been some change to the download endpoint web address
|
||||||
if [[ "${lang,,}" == "en" || "${lang,,}" == "en-"* ]]; then
|
if [[ "${lang,,}" == "en" || "${lang,,}" == "en-"* ]]; then
|
||||||
error "Windows server download page gave us no download link!"
|
error "Windows server download page gave us no download link!"
|
||||||
@@ -264,74 +309,74 @@ download_windows_eval() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$enterprise_type" in
|
case "$type" in
|
||||||
"iot" | "ltsc" )
|
"iot" | "ltsc" )
|
||||||
case "${PLATFORM,,}" in
|
case "${PLATFORM,,}" in
|
||||||
"x64" )
|
"x64" )
|
||||||
if [[ "$windows_version" != "windows-10"* ]]; then
|
if [[ "$winVer" != "windows-10"* ]]; then
|
||||||
iso_download_link=$(echo "$iso_download_links" | head -n 1)
|
link=$(echo "$links" | head -n 1)
|
||||||
else
|
else
|
||||||
iso_download_link=$(echo "$iso_download_links" | head -n 4 | tail -n 1)
|
link=$(echo "$links" | head -n 4 | tail -n 1)
|
||||||
fi ;;
|
fi ;;
|
||||||
"arm64" )
|
"arm64" )
|
||||||
iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1) ;;
|
link=$(echo "$links" | head -n 2 | tail -n 1) ;;
|
||||||
esac ;;
|
esac ;;
|
||||||
"enterprise" )
|
"enterprise" )
|
||||||
case "${PLATFORM,,}" in
|
case "${PLATFORM,,}" in
|
||||||
"x64" )
|
"x64" )
|
||||||
if [[ "$windows_version" != "windows-10"* ]]; then
|
if [[ "$winVer" != "windows-10"* ]]; then
|
||||||
iso_download_link=$(echo "$iso_download_links" | head -n 1)
|
link=$(echo "$links" | head -n 1)
|
||||||
else
|
else
|
||||||
iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1)
|
link=$(echo "$links" | head -n 2 | tail -n 1)
|
||||||
fi ;;
|
fi ;;
|
||||||
"arm64" )
|
"arm64" )
|
||||||
iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1) ;;
|
link=$(echo "$links" | head -n 2 | tail -n 1) ;;
|
||||||
esac ;;
|
esac ;;
|
||||||
"server" )
|
"server" )
|
||||||
case "${PLATFORM,,}" in
|
case "${PLATFORM,,}" in
|
||||||
"x64" )
|
"x64" )
|
||||||
iso_download_link=$(echo "$iso_download_links" | head -n 1) ;;
|
link=$(echo "$links" | head -n 1) ;;
|
||||||
esac ;;
|
esac ;;
|
||||||
* )
|
* )
|
||||||
error "Invalid type specified, value \"$enterprise_type\" is not recognized!" && return 1 ;;
|
error "Invalid type specified, value \"$type\" is not recognized!" && return 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
[ -z "$iso_download_link" ] && error "Could not parse download link from page!" && return 1
|
[ -z "$link" ] && error "Could not parse download link from page!" && return 1
|
||||||
|
|
||||||
# Follow redirect so proceeding log message is useful
|
# Follow redirect so proceeding log message is useful
|
||||||
# This is a request we make that Fido doesn't
|
# This is a request we make that Fido doesn't
|
||||||
|
|
||||||
iso_download_link=$(curl --silent --max-time 30 --user-agent "$user_agent" --location --output /dev/null --silent --write-out "%{url_effective}" --head --fail --proto =https --tlsv1.2 --http1.1 -- "$iso_download_link") || {
|
link=$(curl --silent --max-time 30 --user-agent "$agent" --location --output /dev/null --silent --write-out "%{url_effective}" --head --fail --proto =https --tlsv1.2 --http1.1 -- "$link") || {
|
||||||
# This should only happen if the Microsoft servers are down
|
# This should only happen if the Microsoft servers are down
|
||||||
handle_curl_error "$?" "Microsoft"
|
handleCurlError "$?" "Microsoft"
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
case "${PLATFORM,,}" in
|
case "${PLATFORM,,}" in
|
||||||
"x64" )
|
"x64" )
|
||||||
if [[ "${iso_download_link,,}" != *"x64"* ]]; then
|
if [[ "${link,,}" != *"x64"* ]]; then
|
||||||
echo "Found download link: $iso_download_link"
|
echo "Found download link: $link"
|
||||||
error "Download link is for the wrong platform? Please report this at $SUPPORT/issues"
|
error "Download link is for the wrong platform? Please report this at $SUPPORT/issues"
|
||||||
return 1
|
return 1
|
||||||
fi ;;
|
fi ;;
|
||||||
"arm64" )
|
"arm64" )
|
||||||
if [[ "${iso_download_link,,}" != *"a64"* && "${iso_download_link,,}" != *"arm64"* ]]; then
|
if [[ "${link,,}" != *"a64"* && "${link,,}" != *"arm64"* ]]; then
|
||||||
if [[ "$DEBUG" == [Yy1]* ]]; then
|
if enabled "$DEBUG"; then
|
||||||
echo "Found download link: $iso_download_link"
|
echo "Found download link: $link"
|
||||||
echo "Link for ARM platform currently not available!"
|
echo "Link for ARM platform currently not available!"
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
fi ;;
|
fi ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [[ "$DEBUG" == [Yy1]* && "$VERIFY" == [Yy1]* && "${lang,,}" == "en"* ]]; then
|
if enabled "$DEBUG" && enabled "$VERIFY" && [[ "${lang,,}" == "en"* ]]; then
|
||||||
compare=$(getMido "$id" "$lang" "")
|
compare=$(getMido "$id" "$lang" "")
|
||||||
if [[ "${iso_download_link,,}" != "${compare,,}" ]]; then
|
if [[ "${link,,}" != "${compare,,}" ]]; then
|
||||||
echo "Retrieved link does not match the fixed link: $compare"
|
echo "Retrieved link does not match the fixed link: $compare"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MIDO_URL="$iso_download_link"
|
MIDO_URL="$link"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +394,8 @@ getWindows() {
|
|||||||
info "$msg" && html "$msg"
|
info "$msg" && html "$msg"
|
||||||
|
|
||||||
case "${version,,}" in
|
case "${version,,}" in
|
||||||
"win2008r2" | "win81${PLATFORM,,}"* | "win11${PLATFORM,,}-enterprise-iot"* | "win11${PLATFORM,,}-enterprise-ltsc"* )
|
"win2008r2" | "win81${PLATFORM,,}"* | "win10${PLATFORM,,}-enterprise"* | \
|
||||||
|
"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
|
||||||
@@ -367,16 +413,16 @@ getWindows() {
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
case "${version,,}" in
|
case "${version,,}" in
|
||||||
"win10${PLATFORM,,}" | "win11${PLATFORM,,}" )
|
"win11${PLATFORM,,}" )
|
||||||
download_windows "$version" "$lang" "$edition" && return 0
|
downloadWindows "$version" "$lang" "$edition" && return 0
|
||||||
;;
|
;;
|
||||||
"win11${PLATFORM,,}-enterprise"* | "win10${PLATFORM,,}-enterprise"* )
|
"win11${PLATFORM,,}-enterprise"* )
|
||||||
download_windows_eval "$version" "$lang" "$edition" && return 0
|
downloadWindowsEval "$version" "$lang" "$edition" && return 0
|
||||||
;;
|
;;
|
||||||
"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
|
downloadWindowsEval "$version" "$lang" "$edition" && return 0
|
||||||
;;
|
;;
|
||||||
"win81${PLATFORM,,}-enterprise"* | "win2008r2" )
|
"win2008r2" | "win81${PLATFORM,,}"* | "win10${PLATFORM,,}-enterprise"* )
|
||||||
;;
|
;;
|
||||||
* ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;;
|
* ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;;
|
||||||
esac
|
esac
|
||||||
@@ -461,18 +507,29 @@ getCatalog() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getXmlTag() {
|
||||||
|
|
||||||
|
local tag="$1"
|
||||||
|
local file="$2"
|
||||||
|
|
||||||
|
xmllint --nonet --xpath "//$tag" "$file" 2>/dev/null | sed -E -e "s/<[\/]?$tag>//g" || true
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
getESD() {
|
getESD() {
|
||||||
|
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
local version="$2"
|
local version="$2"
|
||||||
local lang="$3"
|
local lang="$3"
|
||||||
local desc="$4"
|
local desc="$4"
|
||||||
local file
|
local rc=0
|
||||||
local result
|
local file result culture
|
||||||
local culture
|
local language edition catalog
|
||||||
local language
|
local xmlFile="products.xml"
|
||||||
local edition
|
local esdFile="esd_edition.xml"
|
||||||
local catalog
|
local filterFile="products_filter.xml"
|
||||||
|
local query
|
||||||
|
|
||||||
file=$(getCatalog "$version" "file")
|
file=$(getCatalog "$version" "file")
|
||||||
catalog=$(getCatalog "$version" "url")
|
catalog=$(getCatalog "$version" "url")
|
||||||
@@ -480,18 +537,19 @@ getESD() {
|
|||||||
edition=$(getCatalog "$version" "edition")
|
edition=$(getCatalog "$version" "edition")
|
||||||
|
|
||||||
if [ -z "$file" ] || [ -z "$catalog" ]; then
|
if [ -z "$file" ] || [ -z "$catalog" ]; then
|
||||||
error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
|
error "Invalid VERSION specified, value \"$version\" is not recognized!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local msg="Downloading catalog..."
|
local msg="Downloading catalog from the Microsoft servers..."
|
||||||
info "$msg" && html "$msg"
|
info "$msg" && html "$msg"
|
||||||
|
|
||||||
rm -rf "$dir"
|
rm -rf "$dir"
|
||||||
mkdir -p "$dir"
|
|
||||||
|
|
||||||
local xFile="products.xml"
|
if ! makeDir "$dir"; then
|
||||||
local eFile="esd_edition.xml"
|
error "Failed to create directory \"$dir\" !"
|
||||||
local fFile="products_filter.xml"
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
{ wget "$catalog" -O "$dir/$file" -q --timeout=30 --no-http-keep-alive; rc=$?; } || :
|
{ wget "$catalog" -O "$dir/$file" -q --timeout=30 --no-http-keep-alive; rc=$?; } || :
|
||||||
|
|
||||||
@@ -503,75 +561,79 @@ getESD() {
|
|||||||
|
|
||||||
if [[ "$file" == *".xml" ]]; then
|
if [[ "$file" == *".xml" ]]; then
|
||||||
|
|
||||||
mv -f "$dir/$file" "$dir/$xFile"
|
if ! mv -f "$dir/$file" "$dir/$xmlFile"; then
|
||||||
|
error "Failed to rename $file to $xmlFile."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
cd "$dir"
|
if ! (
|
||||||
|
cd "$dir" || exit 1
|
||||||
if ! cabextract "$file" > /dev/null; then
|
cabextract "$file" > /dev/null
|
||||||
cd /run
|
); then
|
||||||
error "Failed to extract $file!" && return 1
|
error "Failed to extract $file!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd /run
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -s "$dir/$xFile" ]; then
|
if [ ! -s "$dir/$xmlFile" ]; then
|
||||||
error "Failed to find $xFile in $file!" && return 1
|
error "Failed to find $xmlFile in $file!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local edQuery='//File[Architecture="'${PLATFORM,,}'"]'"${edition}"''
|
query='//File[Architecture="'${PLATFORM,,}'"]'"${edition}"''
|
||||||
result=$(xmllint --nonet --xpath "${edQuery}" "$dir/$xFile" 2>/dev/null)
|
result=$(xmllint --nonet --xpath "${query}" "$dir/$xmlFile" 2>/dev/null || true)
|
||||||
|
|
||||||
if [ -z "$result" ]; then
|
if [ -z "$result" ]; then
|
||||||
|
|
||||||
edQuery='//File[Architecture="'${PLATFORM^^}'"]'"${edition}"''
|
query='//File[Architecture="'${PLATFORM^^}'"]'"${edition}"''
|
||||||
|
result=$(xmllint --nonet --xpath "${query}" "$dir/$xmlFile" 2>/dev/null || true)
|
||||||
result=$(xmllint --nonet --xpath "${edQuery}" "$dir/$xFile" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$result" ]; then
|
if [ -z "$result" ]; then
|
||||||
desc=$(printEdition "$version" "$desc")
|
desc=$(printEdition "$version" "$desc")
|
||||||
language=$(getLanguage "$lang" "desc")
|
language=$(getLanguage "$lang" "desc")
|
||||||
error "No download link available for $desc!" && return 1
|
error "No download link available for $desc!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e '<Catalog>' > "$dir/$fFile"
|
echo -e '<Catalog>' > "$dir/$filterFile"
|
||||||
echo "$result" >> "$dir/$fFile"
|
echo "$result" >> "$dir/$filterFile"
|
||||||
echo -e '</Catalog>'>> "$dir/$fFile"
|
echo -e '</Catalog>'>> "$dir/$filterFile"
|
||||||
|
|
||||||
result=$(xmllint --nonet --xpath "//File[LanguageCode=\"${culture,,}\"]" "$dir/$fFile" 2>/dev/null)
|
result=$(xmllint --nonet --xpath "//File[LanguageCode=\"${culture,,}\"]" "$dir/$filterFile" 2>/dev/null || true)
|
||||||
|
|
||||||
if [ -z "$result" ]; then
|
if [ -z "$result" ]; then
|
||||||
desc=$(printEdition "$version" "$desc")
|
desc=$(printEdition "$version" "$desc")
|
||||||
language=$(getLanguage "$lang" "desc")
|
language=$(getLanguage "$lang" "desc")
|
||||||
error "No download in the $language language available for $desc!" && return 1
|
error "No download in the $language language available for $desc!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "$result" > "$dir/$eFile"
|
echo "$result" > "$dir/$esdFile"
|
||||||
|
|
||||||
local tag="FilePath"
|
ESD=$(getXmlTag "FilePath" "$dir/$esdFile")
|
||||||
ESD=$(xmllint --nonet --xpath "//$tag" "$dir/$eFile" | sed -E -e "s/<[\/]?$tag>//g" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$ESD" ]; then
|
if [ -z "$ESD" ]; then
|
||||||
error "Failed to find ESD URL in $eFile!" && return 1
|
error "Failed to find ESD URL in $esdFile!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tag="Sha1"
|
ESD_SUM=$(getXmlTag "Sha1" "$dir/$esdFile")
|
||||||
ESD_SUM=$(xmllint --nonet --xpath "//$tag" "$dir/$eFile" | sed -E -e "s/<[\/]?$tag>//g" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$ESD_SUM" ]; then
|
if [ -z "$ESD_SUM" ]; then
|
||||||
error "Failed to find ESD checksum in $eFile!" && return 1
|
error "Failed to find ESD checksum in $esdFile!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tag="Size"
|
ESD_SIZE=$(getXmlTag "Size" "$dir/$esdFile")
|
||||||
ESD_SIZE=$(xmllint --nonet --xpath "//$tag" "$dir/$eFile" | sed -E -e "s/<[\/]?$tag>//g" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$ESD_SIZE" ]; then
|
if [ -z "$ESD_SIZE" ]; then
|
||||||
error "Failed to find ESD filesize in $eFile!" && return 1
|
error "Failed to find ESD filesize in $esdFile!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$dir"
|
rm -rf "$dir"
|
||||||
@@ -598,7 +660,7 @@ verifyFile() {
|
|||||||
local check="$4"
|
local check="$4"
|
||||||
|
|
||||||
if [ -n "$size" ] && [[ "$total" != "$size" && "$size" != "0" ]]; then
|
if [ -n "$size" ] && [[ "$total" != "$size" && "$size" != "0" ]]; then
|
||||||
if [[ "$VERIFY" == [Yy1]* || "$DEBUG" == [Yy1]* ]]; then
|
if enabled "$VERIFY" || enabled "$DEBUG"; then
|
||||||
warn "The downloaded file has a different size ( $total bytes) than expected ( $size bytes). Please report this at $SUPPORT/issues"
|
warn "The downloaded file has a different size ( $total bytes) than expected ( $size bytes). Please report this at $SUPPORT/issues"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -607,16 +669,22 @@ verifyFile() {
|
|||||||
local algo="SHA256"
|
local algo="SHA256"
|
||||||
|
|
||||||
[ -z "$check" ] && return 0
|
[ -z "$check" ] && return 0
|
||||||
[[ "$VERIFY" != [Yy1]* ]] && return 0
|
! enabled "$VERIFY" && return 0
|
||||||
[[ "${#check}" == "40" ]] && algo="SHA1"
|
[[ "${#check}" == "40" ]] && algo="SHA1"
|
||||||
|
|
||||||
local msg="Verifying downloaded ISO..."
|
local msg="Verifying downloaded ISO..."
|
||||||
info "$msg" && html "$msg"
|
info "$msg" && html "$msg"
|
||||||
|
|
||||||
if [[ "${algo,,}" != "sha256" ]]; then
|
if [[ "${algo,,}" != "sha256" ]]; then
|
||||||
hash=$(sha1sum "$iso" | cut -f1 -d' ')
|
if ! hash=$(sha1sum "$iso" | cut -f1 -d' '); then
|
||||||
|
error "Failed to calculate SHA1 checksum for $iso!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
hash=$(sha256sum "$iso" | cut -f1 -d' ')
|
if ! hash=$(sha256sum "$iso" | cut -f1 -d' '); then
|
||||||
|
error "Failed to calculate SHA256 checksum for $iso!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$hash" == "$check" ]]; then
|
if [[ "$hash" == "$check" ]]; then
|
||||||
@@ -638,11 +706,17 @@ downloadFile() {
|
|||||||
local msg="Downloading $desc"
|
local msg="Downloading $desc"
|
||||||
local rc total total_gb progress domain dots agent space folder
|
local rc total total_gb progress domain dots agent space folder
|
||||||
|
|
||||||
agent=$(get_agent)
|
agent=$(getAgent)
|
||||||
|
|
||||||
if [ -n "$size" ] && [[ "$size" != "0" ]]; then
|
if [ -n "$size" ] && [[ "$size" != "0" ]]; then
|
||||||
|
|
||||||
folder=$(dirname -- "$iso")
|
folder=$(dirname -- "$iso")
|
||||||
space=$(df --output=avail -B 1 "$folder" | tail -n 1)
|
|
||||||
|
if ! space=$(df --output=avail -B 1 "$folder" | tail -n 1); then
|
||||||
|
error "Failed to check free space in $folder!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
total_gb=$(formatBytes "$space")
|
total_gb=$(formatBytes "$space")
|
||||||
(( size > space )) && error "Not enough free space to download file, only $total_gb left!" && return 1
|
(( size > space )) && error "Not enough free space to download file, only $total_gb left!" && return 1
|
||||||
fi
|
fi
|
||||||
@@ -666,21 +740,32 @@ downloadFile() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
info "$msg..."
|
info "$msg..."
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Downloading: $url"
|
enabled "$DEBUG" && echo "Downloading: $url"
|
||||||
|
|
||||||
{ wget "$url" -O "$iso" --continue -q --timeout=30 --no-http-keep-alive --user-agent "$agent" --show-progress "$progress"; rc=$?; } || :
|
{ wget "$url" -O "$iso" --continue -q --timeout=30 --no-http-keep-alive --user-agent "$agent" --show-progress "$progress"; rc=$?; } || :
|
||||||
|
|
||||||
fKill "progress.sh"
|
fKill "progress.sh"
|
||||||
|
|
||||||
if (( rc == 0 )) && [ -f "$iso" ]; then
|
if (( rc == 0 )) && [ -f "$iso" ]; then
|
||||||
total=$(stat -c%s "$iso")
|
|
||||||
total_gb=$(formatBytes "$total")
|
if ! total=$(stat -c%s "$iso"); then
|
||||||
if [ "$total" -lt 100000000 ]; then
|
error "Failed to determine downloaded file size: $iso"
|
||||||
error "Invalid download link: $url (is only $total_gb ?). Please report this at $SUPPORT/issues" && return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
total_gb=$(formatBytes "$total")
|
||||||
|
|
||||||
|
if [ "$total" -lt 100000000 ]; then
|
||||||
|
error "Invalid download link: $url (is only $total_gb ?). Please report this at $SUPPORT/issues"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
verifyFile "$iso" "$size" "$total" "$sum" || return 1
|
verifyFile "$iso" "$size" "$total" "$sum" || return 1
|
||||||
|
|
||||||
isCompressed "$url" && UNPACK="Y"
|
isCompressed "$url" && UNPACK="Y"
|
||||||
html "Download finished successfully..." && return 0
|
|
||||||
|
html "Download finished successfully..."
|
||||||
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg="Failed to download $url"
|
msg="Failed to download $url"
|
||||||
@@ -708,6 +793,25 @@ delay() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tryDownload() {
|
||||||
|
|
||||||
|
local iso="$1"
|
||||||
|
local url="$2"
|
||||||
|
local sum="$3"
|
||||||
|
local size="$4"
|
||||||
|
local lang="$5"
|
||||||
|
local desc="$6"
|
||||||
|
local seconds="$7"
|
||||||
|
|
||||||
|
rm -f "$iso"
|
||||||
|
downloadFile "$iso" "$url" "$sum" "$size" "$lang" "$desc" && return 0
|
||||||
|
delay "$seconds"
|
||||||
|
downloadFile "$iso" "$url" "$sum" "$size" "$lang" "$desc" && return 0
|
||||||
|
rm -f "$iso"
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
downloadImage() {
|
downloadImage() {
|
||||||
|
|
||||||
local iso="$1"
|
local iso="$1"
|
||||||
@@ -716,24 +820,20 @@ downloadImage() {
|
|||||||
local tried="n"
|
local tried="n"
|
||||||
local success="n"
|
local success="n"
|
||||||
local seconds="5"
|
local seconds="5"
|
||||||
local url sum size base desc language
|
local url sum size base desc language i
|
||||||
|
|
||||||
if [[ "${version,,}" == "http"* ]]; then
|
if [[ "${version,,}" == "http"* ]]; then
|
||||||
|
|
||||||
base=$(basename "$iso")
|
base=$(basename "$iso")
|
||||||
desc=$(fromFile "$base")
|
desc=$(fromFile "$base")
|
||||||
|
|
||||||
rm -f "$iso"
|
tryDownload "$iso" "$version" "" "" "" "$desc" "$seconds" && return 0
|
||||||
downloadFile "$iso" "$version" "" "" "" "$desc" && return 0
|
|
||||||
delay "$seconds"
|
|
||||||
downloadFile "$iso" "$version" "" "" "" "$desc" && return 0
|
|
||||||
rm -f "$iso"
|
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! validVersion "$version" "en"; then
|
if ! validVersion "$version" "en"; then
|
||||||
error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
|
error "Invalid VERSION specified, value \"$version\" is not recognized!"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
desc=$(printVersion "$version" "")
|
desc=$(printVersion "$version" "")
|
||||||
@@ -742,7 +842,8 @@ downloadImage() {
|
|||||||
language=$(getLanguage "$lang" "desc")
|
language=$(getLanguage "$lang" "desc")
|
||||||
if ! validVersion "$version" "$lang"; then
|
if ! validVersion "$version" "$lang"; then
|
||||||
desc=$(printEdition "$version" "$desc")
|
desc=$(printEdition "$version" "$desc")
|
||||||
error "The $language language version of $desc is not available, please switch to English." && return 1
|
error "The $language language version of $desc is not available, please switch to English."
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
desc+=" in $language"
|
desc+=" in $language"
|
||||||
fi
|
fi
|
||||||
@@ -760,14 +861,21 @@ downloadImage() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$success" == "y" ]]; then
|
if [[ "$success" == "y" ]]; then
|
||||||
size=$(getMido "$version" "$lang" "size" )
|
|
||||||
sum=$(getMido "$version" "$lang" "sum")
|
|
||||||
|
|
||||||
rm -f "$iso"
|
url=$(getMido "$version" "$lang" "")
|
||||||
downloadFile "$iso" "$MIDO_URL" "$sum" "$size" "$lang" "$desc" && return 0
|
|
||||||
delay "$seconds"
|
sum=""
|
||||||
downloadFile "$iso" "$MIDO_URL" "$sum" "$size" "$lang" "$desc" && return 0
|
size=""
|
||||||
rm -f "$iso"
|
|
||||||
|
if [[ "${MIDO_URL%%\?*}" == "${url%%\?*}" ]]; then
|
||||||
|
size=$(getMido "$version" "$lang" "size")
|
||||||
|
sum=$(getMido "$version" "$lang" "sum")
|
||||||
|
else
|
||||||
|
enabled "$DEBUG" && echo "Skipping verification because the retrieved URL differs from the static URL."
|
||||||
|
fi
|
||||||
|
|
||||||
|
tryDownload "$iso" "$MIDO_URL" "$sum" "$size" "$lang" "$desc" "$seconds" && return 0
|
||||||
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -792,11 +900,10 @@ downloadImage() {
|
|||||||
if [[ "$success" == "y" ]]; then
|
if [[ "$success" == "y" ]]; then
|
||||||
ISO="${ISO%.*}.esd"
|
ISO="${ISO%.*}.esd"
|
||||||
|
|
||||||
rm -f "$ISO"
|
if tryDownload "$ISO" "$ESD" "$ESD_SUM" "$ESD_SIZE" "$lang" "$desc" "$seconds"; then
|
||||||
downloadFile "$ISO" "$ESD" "$ESD_SUM" "$ESD_SIZE" "$lang" "$desc" && return 0
|
return 0
|
||||||
delay "$seconds"
|
fi
|
||||||
downloadFile "$ISO" "$ESD" "$ESD_SUM" "$ESD_SIZE" "$lang" "$desc" && return 0
|
|
||||||
rm -f "$ISO"
|
|
||||||
ISO="$iso"
|
ISO="$iso"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -816,11 +923,7 @@ downloadImage() {
|
|||||||
size=$(getSize "$i" "$version" "$lang")
|
size=$(getSize "$i" "$version" "$lang")
|
||||||
sum=$(getHash "$i" "$version" "$lang")
|
sum=$(getHash "$i" "$version" "$lang")
|
||||||
|
|
||||||
rm -f "$iso"
|
tryDownload "$iso" "$url" "$sum" "$size" "$lang" "$desc" "$seconds" && return 0
|
||||||
downloadFile "$iso" "$url" "$sum" "$size" "$lang" "$desc" && return 0
|
|
||||||
delay "$seconds"
|
|
||||||
downloadFile "$iso" "$url" "$sum" "$size" "$lang" "$desc" && return 0
|
|
||||||
rm -f "$iso"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|||||||
+239
-139
@@ -1,26 +1,80 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
: "${QEMU_TIMEOUT:="110"}" # QEMU Termination timeout
|
: "${SHUTDOWN:="Y"}" # Graceful ACPI shutdown
|
||||||
|
: "${TIMEOUT:="115"}" # QEMU termination timeout
|
||||||
|
|
||||||
# Configure QEMU for graceful shutdown
|
# Configure QEMU for graceful shutdown
|
||||||
|
|
||||||
QEMU_TERM=""
|
|
||||||
QEMU_DIR="/run/shm"
|
|
||||||
QEMU_PID="$QEMU_DIR/qemu.pid"
|
|
||||||
QEMU_PTY="$QEMU_DIR/qemu.pty"
|
QEMU_PTY="$QEMU_DIR/qemu.pty"
|
||||||
QEMU_LOG="$QEMU_DIR/qemu.log"
|
|
||||||
QEMU_OUT="$QEMU_DIR/qemu.out"
|
|
||||||
QEMU_END="$QEMU_DIR/qemu.end"
|
QEMU_END="$QEMU_DIR/qemu.end"
|
||||||
|
|
||||||
rm -f "$QEMU_DIR/qemu.*"
|
|
||||||
touch "$QEMU_LOG"
|
|
||||||
|
|
||||||
_trap() {
|
_trap() {
|
||||||
func="$1" ; shift
|
|
||||||
for sig ; do
|
local func="$1"; shift
|
||||||
|
local sig
|
||||||
|
TRAP_PID=$BASHPID
|
||||||
|
|
||||||
|
for sig; do
|
||||||
trap "$func $sig" "$sig"
|
trap "$func $sig" "$sig"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
signalCode() {
|
||||||
|
|
||||||
|
local sig="$1"
|
||||||
|
|
||||||
|
case "$sig" in
|
||||||
|
SIGHUP) echo 129 ;;
|
||||||
|
SIGINT) echo 130 ;;
|
||||||
|
SIGQUIT) echo 131 ;;
|
||||||
|
SIGABRT) echo 134 ;;
|
||||||
|
SIGTERM) echo 143 ;;
|
||||||
|
*) echo 0 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
displayReason() {
|
||||||
|
|
||||||
|
local reason="$1"
|
||||||
|
|
||||||
|
case "$reason" in
|
||||||
|
129 ) echo "SIGHUP" ;;
|
||||||
|
130 ) echo "SIGINT" ;;
|
||||||
|
131 ) echo "SIGQUIT" ;;
|
||||||
|
134 ) echo "SIGABRT" ;;
|
||||||
|
143 ) echo "SIGTERM" ;;
|
||||||
|
* ) echo "$reason" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
readQemuPid() {
|
||||||
|
|
||||||
|
local -n _pid="$1"
|
||||||
|
|
||||||
|
if [ ! -s "$QEMU_PID" ] || ! read -r _pid <"$QEMU_PID"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
bootFailed() {
|
||||||
|
|
||||||
|
local fail=""
|
||||||
|
|
||||||
|
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
|
||||||
|
grep -Fq "No bootable device." "$QEMU_PTY" && fail="y"
|
||||||
|
grep -Fq "BOOTMGR is missing" "$QEMU_PTY" && fail="y"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$fail" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
boot() {
|
boot() {
|
||||||
@@ -29,23 +83,28 @@ boot() {
|
|||||||
|
|
||||||
if [ -s "$QEMU_PTY" ]; then
|
if [ -s "$QEMU_PTY" ]; then
|
||||||
if [ "$(stat -c%s "$QEMU_PTY")" -gt 7 ]; then
|
if [ "$(stat -c%s "$QEMU_PTY")" -gt 7 ]; then
|
||||||
local fail=""
|
if ! bootFailed; then
|
||||||
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
|
info "$(app) started successfully, visit http://127.0.0.1:8006/ to view the screen..."
|
||||||
grep -Fq "No bootable device." "$QEMU_PTY" && fail="y"
|
|
||||||
grep -Fq "BOOTMGR is missing" "$QEMU_PTY" && fail="y"
|
|
||||||
fi
|
|
||||||
if [ -z "$fail" ]; then
|
|
||||||
info "Windows started successfully, visit http://127.0.0.1:8006/ to view the screen..."
|
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
error "Timeout while waiting for QEMU to boot the machine!"
|
error "Timeout while waiting for QEMU to boot the machine, aborting..."
|
||||||
|
sKill "$QEMU_PID"
|
||||||
|
|
||||||
local pid
|
return 0
|
||||||
pid=$(<"$QEMU_PID")
|
}
|
||||||
{ kill -15 "$pid" || true; } 2>/dev/null
|
|
||||||
|
legacyBootReady() {
|
||||||
|
|
||||||
|
local last
|
||||||
|
local bios="Booting from Hard"
|
||||||
|
|
||||||
|
last=$(grep "^Booting.*" "$QEMU_PTY" | tail -1)
|
||||||
|
[[ "${last,,}" != "${bios,,}"* ]] && return 1
|
||||||
|
grep -Fq "No bootable device." "$QEMU_PTY" && return 1
|
||||||
|
grep -Fq "BOOTMGR is missing" "$QEMU_PTY" && return 1
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -56,13 +115,8 @@ ready() {
|
|||||||
[ ! -s "$QEMU_PTY" ] && return 1
|
[ ! -s "$QEMU_PTY" ] && return 1
|
||||||
|
|
||||||
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
|
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
|
||||||
local last
|
legacyBootReady && return 0
|
||||||
local bios="Booting from Hard"
|
return 1
|
||||||
last=$(grep "^Booting.*" "$QEMU_PTY" | tail -1)
|
|
||||||
[[ "${last,,}" != "${bios,,}"* ]] && return 1
|
|
||||||
grep -Fq "No bootable device." "$QEMU_PTY" && return 1
|
|
||||||
grep -Fq "BOOTMGR is missing" "$QEMU_PTY" && return 1
|
|
||||||
return 0
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local line="\"Windows Boot Manager\""
|
local line="\"Windows Boot Manager\""
|
||||||
@@ -71,161 +125,207 @@ ready() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
finish() {
|
forceKillQemu() {
|
||||||
|
|
||||||
local pid
|
local reason="$1"
|
||||||
local reason=$1
|
local pid=""
|
||||||
|
local display
|
||||||
|
|
||||||
touch "$QEMU_END"
|
! readQemuPid pid && return 0
|
||||||
|
! isAlive "$pid" && return 0
|
||||||
|
|
||||||
|
display=$(displayReason "$reason")
|
||||||
|
error "Forcefully terminating $(app), reason: $display..."
|
||||||
|
{ disown "$pid" || :; kill -9 -- "$pid" || :; } 2>/dev/null
|
||||||
|
|
||||||
if [ -s "$QEMU_PID" ]; then
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
pid=$(<"$QEMU_PID")
|
markWindowsBooted() {
|
||||||
error "Forcefully terminating Windows, reason: $reason..."
|
|
||||||
{ kill -15 "$pid" || true; } 2>/dev/null
|
|
||||||
|
|
||||||
while isAlive "$pid"; do
|
local file="$STORAGE/windows.boot"
|
||||||
sleep 1
|
|
||||||
# Workaround for zombie pid
|
if [ -f "$file" ] || [ ! -f "$BOOT" ]; then
|
||||||
[ ! -s "$QEMU_PID" ] && break
|
return 0
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "$STORAGE/windows.boot" ] && [ -f "$BOOT" ]; then
|
# Remove CD-ROM ISO after install
|
||||||
# Remove CD-ROM ISO after install
|
! ready && return 0
|
||||||
if ready; then
|
|
||||||
touch "$STORAGE/windows.boot"
|
touch "$file"
|
||||||
if [[ "$REMOVE" != [Nn]* ]]; then
|
! setOwner "$file" && error "Failed to set the owner for \"$file\" !"
|
||||||
rm -f "$BOOT" 2>/dev/null || true
|
|
||||||
fi
|
if ! disabled "$REMOVE"; then
|
||||||
fi
|
rm -f "$BOOT" 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pid="/var/run/tpm.pid"
|
return 0
|
||||||
[ -s "$pid" ] && pKill "$(<"$pid")"
|
}
|
||||||
rm -f "$pid"
|
|
||||||
|
|
||||||
pid="/var/run/wsdd.pid"
|
cleanupHelpers() {
|
||||||
[ -s "$pid" ] && pKill "$(<"$pid")"
|
|
||||||
rm -f "$pid"
|
|
||||||
|
|
||||||
pid="/var/run/samba/nmbd.pid"
|
local pids=( "${SMB_PID:-}" "${NMB_PID:-}" "${DDN_PID:-}" \
|
||||||
[ -s "$pid" ] && pKill "$(<"$pid")"
|
"${TPM_PID:-}" "${WSD_PID:-}" "${WEB_PID:-}" \
|
||||||
rm -f "$pid"
|
"${AUX_PID:-}" "${AUDIO_PID:-}" "${PASST_PID:-}" \
|
||||||
|
"${DNSMASQ_PID:-}" "${BALLOONING_PID:-}" )
|
||||||
|
|
||||||
pid="/var/run/samba/smbd.pid"
|
mKill "${pids[@]}"
|
||||||
[ -s "$pid" ] && pKill "$(<"$pid")"
|
|
||||||
rm -f "$pid"
|
|
||||||
|
|
||||||
closeNetwork
|
closeNetwork
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
sleep 0.5
|
finish() {
|
||||||
echo "❯ Shutdown completed!"
|
|
||||||
|
local reason=$1
|
||||||
|
touch "$QEMU_END"
|
||||||
|
|
||||||
|
forceKillQemu "$reason"
|
||||||
|
|
||||||
|
if [ ! -f "$STORAGE/windows.boot" ]; then
|
||||||
|
markWindowsBooted
|
||||||
|
fi
|
||||||
|
|
||||||
|
cleanupHelpers
|
||||||
|
|
||||||
|
if ! waitPidFile "$QEMU_PID" 10; then
|
||||||
|
warn "Timed out while waiting for $(app) to exit!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
(( reason != 1 )) && echo && echo "❯ Shutdown completed!"
|
||||||
|
|
||||||
exit "$reason"
|
exit "$reason"
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal() {
|
normalizeTimeout() {
|
||||||
|
|
||||||
local dev=""
|
local term_grace=3 # seconds before loop ends to send SIGTERM
|
||||||
|
local cleanup_grace=3 # seconds reserved after the loop for cleanup
|
||||||
|
local min
|
||||||
|
|
||||||
if [ -s "$QEMU_OUT" ]; then
|
TIMEOUT=$(strip "$TIMEOUT")
|
||||||
|
if [[ ! "$TIMEOUT" =~ ^[0-9]+$ ]]; then
|
||||||
local msg
|
TIMEOUT=115
|
||||||
msg=$(<"$QEMU_OUT")
|
|
||||||
|
|
||||||
if [ -n "$msg" ]; then
|
|
||||||
|
|
||||||
if [[ "${msg,,}" != "char"* || "$msg" != *"serial0)" ]]; then
|
|
||||||
echo "$msg"
|
|
||||||
fi
|
|
||||||
|
|
||||||
dev="${msg#*/dev/p}"
|
|
||||||
dev="/dev/p${dev%% *}"
|
|
||||||
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -c "$dev" ]; then
|
if (( TIMEOUT >= 30 )); then
|
||||||
dev=$(echo 'info chardev' | nc -q 1 -w 1 localhost "$MON_PORT" | tr -d '\000')
|
term_grace=5
|
||||||
dev="${dev#*serial0}"
|
cleanup_grace=5
|
||||||
dev="${dev#*pty:}"
|
elif (( TIMEOUT >= 15 )); then
|
||||||
dev="${dev%%$'\n'*}"
|
term_grace=4
|
||||||
dev="${dev%%$'\r'*}"
|
cleanup_grace=4
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -c "$dev" ]; then
|
min=$((term_grace + cleanup_grace + 1))
|
||||||
error "Device '$dev' not found!"
|
(( TIMEOUT < min )) && (( TIMEOUT = min ))
|
||||||
finish 34 && return 34
|
|
||||||
fi
|
wait_until=$((TIMEOUT - cleanup_grace))
|
||||||
|
sigterm_at=$((wait_until - term_grace))
|
||||||
|
|
||||||
QEMU_TERM="$dev"
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
_graceful_shutdown() {
|
sendAcpiShutdown() {
|
||||||
|
|
||||||
local code=$?
|
[ ! -S "$QEMU_DIR/monitor.sock" ] && return 0
|
||||||
|
|
||||||
set +e
|
|
||||||
|
|
||||||
if [ -f "$QEMU_END" ]; then
|
|
||||||
info "Received $1 while already shutting down..."
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
touch "$QEMU_END"
|
|
||||||
info "Received $1, sending ACPI shutdown signal..."
|
|
||||||
|
|
||||||
if [ ! -s "$QEMU_PID" ]; then
|
|
||||||
error "QEMU PID file does not exist?"
|
|
||||||
finish "$code" && return "$code"
|
|
||||||
fi
|
|
||||||
|
|
||||||
local pid=""
|
|
||||||
pid=$(<"$QEMU_PID")
|
|
||||||
|
|
||||||
if ! isAlive "$pid"; then
|
|
||||||
error "QEMU process does not exist?"
|
|
||||||
finish "$code" && return "$code"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! ready; then
|
|
||||||
info "Cannot send ACPI signal during Windows setup, aborting..."
|
|
||||||
finish "$code" && return "$code"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Send ACPI shutdown signal
|
# Send ACPI shutdown signal
|
||||||
echo 'system_powerdown' | nc -q 1 -w 1 localhost "$MON_PORT" > /dev/null
|
nc -q 1 -w 1 -U "$QEMU_DIR/monitor.sock" &> /dev/null <<<'system_powerdown' || :
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
abortDuringSetup() {
|
||||||
|
|
||||||
|
local code="$1"
|
||||||
|
info "Cannot send ACPI signal during $(app) setup, aborting..."
|
||||||
|
|
||||||
|
sKill "$QEMU_PID"
|
||||||
|
|
||||||
|
if ! waitPidFile "$QEMU_PID" 5; then
|
||||||
|
warn "Timed out while waiting for $(app) to exit!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
finish "$code"
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForShutdown() {
|
||||||
|
|
||||||
local cnt=0
|
local cnt=0
|
||||||
while [ "$cnt" -lt "$QEMU_TIMEOUT" ]; do
|
local pid="$1"
|
||||||
|
local name="$APP"
|
||||||
|
local slp
|
||||||
|
|
||||||
sleep 1
|
while (( cnt <= wait_until )); do
|
||||||
cnt=$((cnt+1))
|
|
||||||
|
|
||||||
|
sleep 1 &
|
||||||
|
slp=$!
|
||||||
|
|
||||||
|
# Stop waiting if the process has exited
|
||||||
! isAlive "$pid" && break
|
! isAlive "$pid" && break
|
||||||
# Workaround for zombie pid
|
|
||||||
|
# Workaround for stale/zombie QEMU pid file
|
||||||
[ ! -s "$QEMU_PID" ] && break
|
[ ! -s "$QEMU_PID" ] && break
|
||||||
|
|
||||||
info "Waiting for Windows to shutdown... ($cnt/$QEMU_TIMEOUT)"
|
if (( cnt == sigterm_at )); then
|
||||||
|
info "${name^} is still running, sending SIGTERM... ($cnt/$wait_until)"
|
||||||
|
kill -15 -- "$pid" 2>/dev/null || :
|
||||||
|
elif (( cnt > 0 )); then
|
||||||
|
info "Waiting for $name to shut down... ($cnt/$wait_until)"
|
||||||
|
fi
|
||||||
|
|
||||||
# Send ACPI shutdown signal
|
sendAcpiShutdown
|
||||||
echo 'system_powerdown' | nc -q 1 -w 1 localhost "$MON_PORT" > /dev/null
|
|
||||||
|
wait "$slp"
|
||||||
|
(( cnt++ ))
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$cnt" -ge "$QEMU_TIMEOUT" ]; then
|
return 0
|
||||||
error "Shutdown timeout reached, aborting..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
finish "$code" && return "$code"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SERIAL="pty"
|
graceful_shutdown() {
|
||||||
MONITOR="telnet:localhost:$MON_PORT,server,nowait,nodelay"
|
|
||||||
MONITOR+=" -daemonize -D $QEMU_LOG -pidfile $QEMU_PID"
|
|
||||||
|
|
||||||
_trap _graceful_shutdown SIGTERM SIGHUP SIGINT SIGABRT SIGQUIT
|
local sig="$1"
|
||||||
|
local pid=""
|
||||||
|
local code=0
|
||||||
|
|
||||||
|
[[ $BASHPID != "$TRAP_PID" ]] && return
|
||||||
|
|
||||||
|
code=$(signalCode "$sig")
|
||||||
|
|
||||||
|
if [ -f "$QEMU_END" ]; then
|
||||||
|
echo && info "Received $1 signal while already shutting down..."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
touch "$QEMU_END"
|
||||||
|
echo && info "Received $1 signal, sending ACPI shutdown signal..."
|
||||||
|
|
||||||
|
if ! readQemuPid pid; then
|
||||||
|
warn "QEMU PID file ($QEMU_PID) does not exist?"
|
||||||
|
finish "$code"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! isAlive "$pid"; then
|
||||||
|
warn "QEMU process with PID $pid does not exist?"
|
||||||
|
finish "$code"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! ready; then
|
||||||
|
abortDuringSetup "$code"
|
||||||
|
fi
|
||||||
|
|
||||||
|
normalizeTimeout
|
||||||
|
waitForShutdown "$pid"
|
||||||
|
|
||||||
|
finish "$code"
|
||||||
|
}
|
||||||
|
|
||||||
|
! enabled "$SHUTDOWN" && return 0
|
||||||
|
[ -n "${QEMU_TIMEOUT:-}" ] && TIMEOUT="$QEMU_TIMEOUT"
|
||||||
|
|
||||||
|
_trap graceful_shutdown SIGTERM SIGHUP SIGABRT SIGQUIT
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
+226
-150
@@ -2,43 +2,75 @@
|
|||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
: "${SAMBA:="Y"}" # Enable Samba
|
: "${SAMBA:="Y"}" # Enable Samba
|
||||||
: "${SAMBA_LEVEL:="1"}" # Logging level
|
|
||||||
: "${SAMBA_DEBUG:="N"}" # Disable debug
|
: "${SAMBA_DEBUG:="N"}" # Disable debug
|
||||||
|
|
||||||
tmp="/tmp/smb"
|
tmp="/tmp/smb"
|
||||||
rm -rf "$tmp"
|
rm -rf "$tmp"
|
||||||
|
|
||||||
rm -f /var/run/wsdd.pid
|
DDN_PID="/var/run/wsdd.pid"
|
||||||
rm -f /var/run/samba/nmbd.pid
|
NMB_PID="/var/run/samba/nmbd.pid"
|
||||||
rm -f /var/run/samba/smbd.pid
|
SMB_PID="/var/run/samba/smbd.pid"
|
||||||
|
|
||||||
[[ "$SAMBA" == [Nn]* ]] && return 0
|
rm -f "$SMB_PID" "$NMB_PID" "$DDN_PID"
|
||||||
[[ "$NETWORK" == [Nn]* ]] && return 0
|
|
||||||
|
|
||||||
if [[ "$DHCP" == [Yy1]* ]]; then
|
disabled "$SAMBA" && return 0
|
||||||
socket="$IP"
|
disabled "$NETWORK" && return 0
|
||||||
hostname="$IP"
|
|
||||||
interfaces="$VM_NET_DEV"
|
configureNetwork() {
|
||||||
else
|
|
||||||
hostname="host.lan"
|
if enabled "$DHCP"; then
|
||||||
case "${NETWORK,,}" in
|
socket="$UPLINK"
|
||||||
"passt" | "slirp" )
|
hostname="$UPLINK"
|
||||||
|
interfaces="$DEV"
|
||||||
|
else
|
||||||
|
hostname="host.lan"
|
||||||
|
|
||||||
|
if isUserMode; then
|
||||||
interfaces="lo"
|
interfaces="lo"
|
||||||
socket="127.0.0.1" ;;
|
socket="127.0.0.1"
|
||||||
*)
|
else
|
||||||
socket="$VM_NET_IP"
|
socket="$IP"
|
||||||
interfaces="$VM_NET_BRIDGE" ;;
|
interfaces="$BRIDGE"
|
||||||
esac
|
fi
|
||||||
if [ -n "${SAMBA_INTERFACE:-}" ]; then
|
|
||||||
interfaces+=",$SAMBA_INTERFACE"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
html "Initializing shared folder..."
|
if [ -n "${SAMBA_INTERFACE:-}" ]; then
|
||||||
SAMBA_CONFIG="/etc/samba/smb.conf"
|
interfaces+=",$SAMBA_INTERFACE"
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Starting Samba daemon..."
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
writeReadme() {
|
||||||
|
|
||||||
|
local dir="$1"
|
||||||
|
local ref="$2"
|
||||||
|
|
||||||
|
{ echo "--------------------------------------------------------"
|
||||||
|
echo " $APP for $ENGINE v$(</etc/version)..."
|
||||||
|
echo " For support visit $SUPPORT"
|
||||||
|
echo "--------------------------------------------------------"
|
||||||
|
echo ""
|
||||||
|
echo "Using this folder you can exchange files with the host machine."
|
||||||
|
echo ""
|
||||||
|
echo "To select a folder on the host for this purpose, include the following bind mount in your compose file:"
|
||||||
|
echo ""
|
||||||
|
echo " volumes:"
|
||||||
|
echo " - \"./example:${ref}\""
|
||||||
|
echo ""
|
||||||
|
echo "Or in your run command:"
|
||||||
|
echo ""
|
||||||
|
echo " -v \"\${PWD:-.}/example:${ref}\""
|
||||||
|
echo ""
|
||||||
|
echo "Replace the example path ./example with your desired shared folder, which then will become visible here."
|
||||||
|
echo ""
|
||||||
|
} | unix2dos > "$dir/readme.txt"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
addShare() {
|
addShare() {
|
||||||
|
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
local ref="$2"
|
local ref="$2"
|
||||||
local name="$3"
|
local name="$3"
|
||||||
@@ -46,177 +78,221 @@ addShare() {
|
|||||||
local cfg="$5"
|
local cfg="$5"
|
||||||
local owner=""
|
local owner=""
|
||||||
|
|
||||||
mkdir -p "$dir" || return 1
|
if [ ! -d "$dir" ]; then
|
||||||
|
if ! mkdir -p "$dir"; then
|
||||||
|
error "Failed to create shared folder ($dir)." && return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if ! ls -A "$dir" >/dev/null 2>&1; then
|
if ! ls -A "$dir" >/dev/null 2>&1; then
|
||||||
error "Failed to access directory $dir" && return 1
|
msg="No permission to access shared folder ($dir)."
|
||||||
|
msg+=" If SELinux is active, you need to add the \":Z\" flag to the bind mount."
|
||||||
|
error "$msg" && return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -w "$dir" ]; then
|
||||||
|
msg="shared folder ($dir) is not writeable!"
|
||||||
|
warn "$msg"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$(ls -A "$dir")" ]; then
|
if [ -z "$(ls -A "$dir")" ]; then
|
||||||
|
|
||||||
if ! chmod 2777 "$dir"; then
|
if ! chmod 2777 "$dir"; then
|
||||||
error "Failed to set permissions for directory $dir" && return 1
|
error "Failed to set permissions for directory $dir" && return 1
|
||||||
fi
|
fi
|
||||||
owner=$(stat -c %u "$dir")
|
|
||||||
|
if ! owner=$(stat -c %u "$dir"); then
|
||||||
|
error "Failed to determine ownership for directory $dir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$owner" == "0" ]]; then
|
if [[ "$owner" == "0" ]]; then
|
||||||
if ! chown "1000:1000" "$dir"; then
|
if ! chown "1000:1000" "$dir"; then
|
||||||
error "Failed to set ownership for directory $dir" && return 1
|
error "Failed to set ownership for directory $dir" && return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$dir" == "$tmp" ]]; then
|
if [[ "$dir" == "$tmp" ]]; then
|
||||||
|
writeReadme "$dir" "$ref" || return 1
|
||||||
{ echo "--------------------------------------------------------"
|
|
||||||
echo " $APP for $ENGINE v$(</run/version)..."
|
|
||||||
echo " For support visit $SUPPORT"
|
|
||||||
echo "--------------------------------------------------------"
|
|
||||||
echo ""
|
|
||||||
echo "Using this folder you can exchange files with the host machine."
|
|
||||||
echo ""
|
|
||||||
echo "To select a folder on the host for this purpose, include the following bind mount in your compose file:"
|
|
||||||
echo ""
|
|
||||||
echo " volumes:"
|
|
||||||
echo " - \"./example:${ref}\""
|
|
||||||
echo ""
|
|
||||||
echo "Or in your run command:"
|
|
||||||
echo ""
|
|
||||||
echo " -v \"\${PWD:-.}/example:${ref}\""
|
|
||||||
echo ""
|
|
||||||
echo "Replace the example path ./example with your desired shared folder, which then will become visible here."
|
|
||||||
echo ""
|
|
||||||
} | unix2dos > "$dir/readme.txt"
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
{ echo ""
|
if ! {
|
||||||
echo "[$name]"
|
echo ""
|
||||||
echo " path = $dir"
|
echo "[$name]"
|
||||||
echo " comment = $comment"
|
echo " path = $dir"
|
||||||
echo " writable = yes"
|
echo " comment = $comment"
|
||||||
echo " guest ok = yes"
|
echo " writable = yes"
|
||||||
echo " guest only = yes"
|
echo " guest ok = yes"
|
||||||
} >> "$cfg"
|
echo " guest only = yes"
|
||||||
|
} >> "$cfg"; then
|
||||||
|
error "Failed to update Samba config \"$cfg\" !"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
{ echo "[global]"
|
writeConfig() {
|
||||||
echo " server string = Dockur"
|
|
||||||
echo " netbios name = $hostname"
|
|
||||||
echo " workgroup = WORKGROUP"
|
|
||||||
echo " interfaces = $interfaces"
|
|
||||||
echo " bind interfaces only = yes"
|
|
||||||
echo " socket address = $socket"
|
|
||||||
echo " security = user"
|
|
||||||
echo " guest account = nobody"
|
|
||||||
echo " map to guest = Bad User"
|
|
||||||
echo " server min protocol = NT1"
|
|
||||||
echo " follow symlinks = yes"
|
|
||||||
echo " wide links = yes"
|
|
||||||
echo " unix extensions = no"
|
|
||||||
echo " inherit owner = yes"
|
|
||||||
echo " create mask = 0666"
|
|
||||||
echo " directory mask = 02777"
|
|
||||||
echo " force user = root"
|
|
||||||
echo " force group = root"
|
|
||||||
echo " force create mode = 0666"
|
|
||||||
echo " force directory mode = 02777"
|
|
||||||
echo ""
|
|
||||||
echo " # Disable printing services"
|
|
||||||
echo " load printers = no"
|
|
||||||
echo " printing = bsd"
|
|
||||||
echo " printcap name = /dev/null"
|
|
||||||
echo " disable spoolss = yes"
|
|
||||||
} > "$SAMBA_CONFIG"
|
|
||||||
|
|
||||||
# Add shared folders
|
{ echo "[global]"
|
||||||
share="/shared"
|
echo " server string = Dockur"
|
||||||
[ ! -d "$share" ] && [ -d "$STORAGE/shared" ] && share="$STORAGE/shared"
|
echo " netbios name = $hostname"
|
||||||
[ ! -d "$share" ] && [ -d "/data" ] && share="/data"
|
echo " workgroup = WORKGROUP"
|
||||||
[ ! -d "$share" ] && [ -d "$STORAGE/data" ] && share="$STORAGE/data"
|
echo " interfaces = $interfaces"
|
||||||
[ ! -d "$share" ] && share="$tmp"
|
echo " bind interfaces only = yes"
|
||||||
|
echo " socket address = $socket"
|
||||||
|
echo " security = user"
|
||||||
|
echo " guest account = nobody"
|
||||||
|
echo " map to guest = Bad User"
|
||||||
|
echo " server min protocol = NT1"
|
||||||
|
echo " follow symlinks = yes"
|
||||||
|
echo " wide links = yes"
|
||||||
|
echo " unix extensions = no"
|
||||||
|
echo " inherit owner = yes"
|
||||||
|
echo " create mask = 0666"
|
||||||
|
echo " directory mask = 02777"
|
||||||
|
echo " force user = root"
|
||||||
|
echo " force group = root"
|
||||||
|
echo " force create mode = 0666"
|
||||||
|
echo " force directory mode = 02777"
|
||||||
|
echo ""
|
||||||
|
echo " # Disable printing services"
|
||||||
|
echo " load printers = no"
|
||||||
|
echo " printing = bsd"
|
||||||
|
echo " printcap name = /dev/null"
|
||||||
|
echo " disable spoolss = yes"
|
||||||
|
} > "$SAMBA_CONFIG"
|
||||||
|
|
||||||
m1="Failed to add shared folder"
|
return 0
|
||||||
m2="Please check its permissions."
|
}
|
||||||
|
|
||||||
if ! addShare "$share" "/shared" "Data" "Shared" "$SAMBA_CONFIG"; then
|
selectPrimaryShare() {
|
||||||
error "$m1 '$share'. $m2" && return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "/shared2" ]; then
|
share="/shared"
|
||||||
addShare "/shared2" "/shared2" "Data2" "Shared" "$SAMBA_CONFIG" || error "$m1 '/shared2'. $m2"
|
[ ! -d "$share" ] && [ -d "$STORAGE/shared" ] && share="$STORAGE/shared"
|
||||||
else
|
[ ! -d "$share" ] && [ -d "/data" ] && share="/data"
|
||||||
if [ -d "/data2" ]; then
|
[ ! -d "$share" ] && [ -d "$STORAGE/data" ] && share="$STORAGE/data"
|
||||||
addShare "/data2" "/shared2" "Data2" "Shared" "$SAMBA_CONFIG" || error "$m1 '/data2'. $m2."
|
[ ! -d "$share" ] && share="$tmp"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
addOptionalShare() {
|
||||||
|
|
||||||
|
local index="$1"
|
||||||
|
local ref="/shared$index"
|
||||||
|
local name="Data$index"
|
||||||
|
|
||||||
|
if [ -d "$ref" ]; then
|
||||||
|
addShare "$ref" "$ref" "$name" "Shared" "$SAMBA_CONFIG" || :
|
||||||
|
elif [ -d "/data$index" ]; then
|
||||||
|
addShare "/data$index" "$ref" "$name" "Shared" "$SAMBA_CONFIG" || :
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "/shared3" ]; then
|
return 0
|
||||||
addShare "/shared3" "/shared3" "Data3" "Shared" "$SAMBA_CONFIG" || error "$m1 '/shared3'. $m2"
|
}
|
||||||
else
|
|
||||||
if [ -d "/data3" ]; then
|
prepareSambaDirs() {
|
||||||
addShare "/data3" "/shared3" "Data3" "Shared" "$SAMBA_CONFIG" || error "$m1 '/data3'. $m2"
|
|
||||||
|
# Create directories if missing
|
||||||
|
mkdir -p \
|
||||||
|
/var/lib/samba/sysvol \
|
||||||
|
/var/lib/samba/private \
|
||||||
|
/var/lib/samba/bind-dns || return 1
|
||||||
|
|
||||||
|
# Try to repair Samba permissions
|
||||||
|
[ -d /run/samba/msg.lock ] && chmod -R 0755 /run/samba/msg.lock 2>/dev/null || :
|
||||||
|
[ -d /var/log/samba/cores ] && chmod -R 0700 /var/log/samba/cores 2>/dev/null || :
|
||||||
|
[ -d /var/cache/samba/msg.lock ] && chmod -R 0755 /var/cache/samba/msg.lock 2>/dev/null || :
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
debugLog() {
|
||||||
|
|
||||||
|
local file="$1"
|
||||||
|
|
||||||
|
if enabled "$SAMBA_DEBUG"; then
|
||||||
|
tail -fn +0 "$file" --pid=$$ &
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# Create directories if missing
|
return 0
|
||||||
mkdir -p /var/lib/samba/sysvol
|
}
|
||||||
mkdir -p /var/lib/samba/private
|
|
||||||
mkdir -p /var/lib/samba/bind-dns
|
|
||||||
|
|
||||||
# Try to repair Samba permissions
|
startDaemon() {
|
||||||
[ -d /run/samba/msg.lock ] && chmod -R 0755 /run/samba/msg.lock 2>/dev/null || :
|
|
||||||
[ -d /var/log/samba/cores ] && chmod -R 0700 /var/log/samba/cores 2>/dev/null || :
|
|
||||||
[ -d /var/cache/samba/msg.lock ] && chmod -R 0755 /var/cache/samba/msg.lock 2>/dev/null || :
|
|
||||||
|
|
||||||
rm -f /var/log/samba/log.smbd
|
local name="$1"
|
||||||
|
local log="$2"
|
||||||
|
shift 2
|
||||||
|
|
||||||
if ! smbd -l /var/log/samba; then
|
rm -f "$log"
|
||||||
SAMBA_DEBUG="Y"
|
|
||||||
error "Failed to start Samba daemon!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$SAMBA_DEBUG" == [Yy1]* ]]; then
|
if ! "$@"; then
|
||||||
tail -fn +0 /var/log/samba/log.smbd --pid=$$ &
|
SAMBA_DEBUG="Y"
|
||||||
fi
|
error "Failed to start $name daemon!"
|
||||||
|
fi
|
||||||
|
|
||||||
case "${NETWORK,,}" in
|
debugLog "$log"
|
||||||
"passt" | "slirp" )
|
return 0
|
||||||
return 0 ;;
|
}
|
||||||
esac
|
|
||||||
|
|
||||||
if [[ "${BOOT_MODE:-}" == "windows_legacy" ]]; then
|
startSamba() {
|
||||||
|
|
||||||
|
startDaemon "Samba" "/var/log/samba/log.smbd" \
|
||||||
|
smbd -l /var/log/samba
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
startNetbios() {
|
||||||
|
|
||||||
# Enable NetBIOS on Windows 7 and lower
|
# Enable NetBIOS on Windows 7 and lower
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Starting NetBIOS daemon..."
|
enabled "$DEBUG" && echo "Starting NetBIOS daemon..."
|
||||||
|
|
||||||
rm -f /var/log/samba/log.nmbd
|
startDaemon "NetBIOS" "/var/log/samba/log.nmbd" \
|
||||||
|
nmbd -l /var/log/samba
|
||||||
|
|
||||||
if ! nmbd -l /var/log/samba; then
|
return 0
|
||||||
SAMBA_DEBUG="Y"
|
}
|
||||||
error "Failed to start NetBIOS daemon!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$SAMBA_DEBUG" == [Yy1]* ]]; then
|
startWsddn() {
|
||||||
tail -fn +0 /var/log/samba/log.nmbd --pid=$$ &
|
|
||||||
fi
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
# Enable Web Service Discovery on Vista and up
|
# Enable Web Service Discovery on Vista and up
|
||||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Starting wsddn daemon..."
|
enabled "$DEBUG" && echo "Starting wsddn daemon..."
|
||||||
|
|
||||||
rm -f /var/log/wsddn.log
|
startDaemon "wsddn" "/var/log/wsddn.log" \
|
||||||
|
wsddn -i "${interfaces%%,*}" -H "$hostname" \
|
||||||
|
--unixd --log-file=/var/log/wsddn.log --pid-file="$DDN_PID"
|
||||||
|
|
||||||
if ! wsddn -i "${interfaces%%,*}" -H "$hostname" --unixd --log-file=/var/log/wsddn.log --pid-file=/var/run/wsdd.pid; then
|
return 0
|
||||||
SAMBA_DEBUG="Y"
|
}
|
||||||
error "Failed to start wsddn daemon!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$SAMBA_DEBUG" == [Yy1]* ]]; then
|
configureNetwork
|
||||||
tail -fn +0 /var/log/wsddn.log --pid=$$ &
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
html "Initializing shared folder..."
|
||||||
|
SAMBA_CONFIG="/etc/samba/smb.conf"
|
||||||
|
enabled "$DEBUG" && echo "Starting Samba daemon..."
|
||||||
|
|
||||||
|
writeConfig || return 1
|
||||||
|
|
||||||
|
# Add shared folders
|
||||||
|
selectPrimaryShare
|
||||||
|
! addShare "$share" "/shared" "Data" "Shared" "$SAMBA_CONFIG" && return 0
|
||||||
|
|
||||||
|
addOptionalShare "2"
|
||||||
|
addOptionalShare "3"
|
||||||
|
|
||||||
|
prepareSambaDirs || return 1
|
||||||
|
startSamba
|
||||||
|
|
||||||
|
isUserMode && return 0
|
||||||
|
|
||||||
|
if [[ "${BOOT_MODE:-}" == "windows_legacy" ]]; then
|
||||||
|
startNetbios
|
||||||
|
else
|
||||||
|
startWsddn
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
Reference in New Issue
Block a user