feat: Improved installation (#545)

This commit is contained in:
Kroese 2024-05-27 12:40:19 +02:00 committed by GitHub
parent a96941c63e
commit fd83861e7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 1437 additions and 271 deletions

View File

@ -1,5 +1,5 @@
FROM scratch FROM scratch
COPY --from=qemux/qemu-docker:5.07 / / COPY --from=qemux/qemu-docker:5.08 / /
ARG VERSION_ARG="0.0" ARG VERSION_ARG="0.0"
ARG DEBCONF_NOWARNINGS="yes" ARG DEBCONF_NOWARNINGS="yes"
@ -14,6 +14,7 @@ RUN set -eu && \
7zip \ 7zip \
wsdd \ wsdd \
samba \ samba \
xz-utils \
wimtools \ wimtools \
dos2unix \ dos2unix \
cabextract \ cabextract \
@ -27,7 +28,7 @@ COPY --chmod=755 ./src /run/
COPY --chmod=755 ./assets /run/assets COPY --chmod=755 ./assets /run/assets
ADD --chmod=755 https://raw.githubusercontent.com/christgau/wsdd/v0.8/src/wsdd.py /usr/sbin/wsdd ADD --chmod=755 https://raw.githubusercontent.com/christgau/wsdd/v0.8/src/wsdd.py /usr/sbin/wsdd
ADD --chmod=664 https://github.com/qemus/virtiso/releases/download/v0.1.248/virtio-win-0.1.248.iso /run/drivers.iso ADD --chmod=664 https://github.com/qemus/virtiso/releases/download/v0.1.248/virtio-win-0.1.248.tar.xz /drivers.txz
EXPOSE 8006 3389 EXPOSE 8006 3389
VOLUME /storage VOLUME /storage

453
assets/win11x64-iot.xml Normal file
View File

@ -0,0 +1,453 @@
<?xml version="1.0" encoding="UTF-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<settings pass="windowsPE">
<component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<SetupUILanguage>
<UILanguage>en-US</UILanguage>
</SetupUILanguage>
<InputLocale>0409:00000409</InputLocale>
<SystemLocale>en-US</SystemLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-US</UserLocale>
</component>
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DiskConfiguration>
<Disk wcm:action="add">
<DiskID>0</DiskID>
<WillWipeDisk>true</WillWipeDisk>
<CreatePartitions>
<!-- System partition (ESP) -->
<CreatePartition wcm:action="add">
<Order>1</Order>
<Type>EFI</Type>
<Size>128</Size>
</CreatePartition>
<!-- Microsoft reserved partition (MSR) -->
<CreatePartition wcm:action="add">
<Order>2</Order>
<Type>MSR</Type>
<Size>128</Size>
</CreatePartition>
<!-- Windows partition -->
<CreatePartition wcm:action="add">
<Order>3</Order>
<Type>Primary</Type>
<Extend>true</Extend>
</CreatePartition>
</CreatePartitions>
<ModifyPartitions>
<!-- System partition (ESP) -->
<ModifyPartition wcm:action="add">
<Order>1</Order>
<PartitionID>1</PartitionID>
<Label>System</Label>
<Format>FAT32</Format>
</ModifyPartition>
<!-- MSR partition does not need to be modified -->
<ModifyPartition wcm:action="add">
<Order>2</Order>
<PartitionID>2</PartitionID>
</ModifyPartition>
<!-- Windows partition -->
<ModifyPartition wcm:action="add">
<Order>3</Order>
<PartitionID>3</PartitionID>
<Label>Windows</Label>
<Letter>C</Letter>
<Format>NTFS</Format>
</ModifyPartition>
</ModifyPartitions>
</Disk>
</DiskConfiguration>
<ImageInstall>
<OSImage>
<InstallFrom>
<MetaData wcm:action="add">
<Key>/image/index</Key>
<Value>2</Value>
</MetaData>
</InstallFrom>
<InstallTo>
<DiskID>0</DiskID>
<PartitionID>3</PartitionID>
</InstallTo>
<InstallToAvailablePartition>false</InstallToAvailablePartition>
</OSImage>
</ImageInstall>
<DynamicUpdate>
<Enable>true</Enable>
<WillShowUI>Never</WillShowUI>
</DynamicUpdate>
<UpgradeData>
<Upgrade>false</Upgrade>
<WillShowUI>Never</WillShowUI>
</UpgradeData>
<UserData>
<AcceptEula>true</AcceptEula>
<FullName>Docker</FullName>
<Organization>Windows for Docker</Organization>
</UserData>
<EnableFirewall>false</EnableFirewall>
<Diagnostics>
<OptIn>false</OptIn>
</Diagnostics>
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassTPMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassSecureBootCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>3</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassRAMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>4</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\MoSetup" /v AllowUpgradesWithUnsupportedTPMOrCPU /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
<settings pass="offlineServicing">
<component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<EnableLUA>false</EnableLUA>
</component>
</settings>
<settings pass="generalize">
<component name="Microsoft-Windows-PnPSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<PersistAllDeviceInstalls>true</PersistAllDeviceInstalls>
</component>
<component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<SkipRearm>1</SkipRearm>
</component>
</settings>
<settings pass="specialize">
<component name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<SkipAutoActivation>true</SkipAutoActivation>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<ComputerName>*</ComputerName>
<OEMInformation>
<Manufacturer>Dockur</Manufacturer>
<Model>Windows for Docker</Model>
<SupportHours>24/7</SupportHours>
<SupportPhone />
<SupportProvider>Dockur</SupportProvider>
<SupportURL>https://github.com/dockur/windows/issues</SupportURL>
</OEMInformation>
<OEMName>Windows for Docker</OEMName>
</component>
<component name="Microsoft-Windows-ErrorReportingCore" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DisableWER>1</DisableWER>
</component>
<component name="Microsoft-Windows-IE-InternetExplorer" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DisableAccelerators>true</DisableAccelerators>
<DisableFirstRunWizard>true</DisableFirstRunWizard>
<Home_Page>https://google.com</Home_Page>
<Help_Page>about:blank</Help_Page>
</component>
<component name="Microsoft-Windows-IE-InternetExplorer" processorArchitecture="wow64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DisableAccelerators>true</DisableAccelerators>
<DisableFirstRunWizard>true</DisableFirstRunWizard>
<Home_Page>https://google.com</Home_Page>
<Help_Page>about:blank</Help_Page>
</component>
<component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<CEIPEnabled>0</CEIPEnabled>
</component>
<component name="Microsoft-Windows-SystemRestore-Main" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DisableSR>1</DisableSR>
</component>
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<InputLocale>0409:00000409</InputLocale>
<SystemLocale>en-US</SystemLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-US</UserLocale>
</component>
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" /v BypassNRO /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>reg.exe load "HKU\mount" "C:\Users\Default\NTUSER.DAT"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>3</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "ContentDeliveryAllowed" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>4</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "FeatureManagementEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>5</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "OEMPreInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>6</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>7</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEverEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>8</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SilentInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>9</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SoftLandingEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>10</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContentEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>11</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-310093Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>12</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338387Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>13</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338388Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>14</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338389Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>15</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338393Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>16</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-353698Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>17</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SystemPaneSuggestionsEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>18</Order>
<Path>reg.exe add "HKU\mount\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableCloudOptimizedContent" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>19</Order>
<Path>reg.exe add "HKU\mount\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableWindowsConsumerFeatures" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>20</Order>
<Path>reg.exe add "HKU\mount\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableConsumerAccountStateContent" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>21</Order>
<Path>reg.exe unload "HKU\mount"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>22</Order>
<Path>reg.exe add "HKLM\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableCloudOptimizedContent" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>23</Order>
<Path>reg.exe add "HKLM\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableWindowsConsumerFeatures" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>24</Order>
<Path>reg.exe add "HKLM\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableConsumerAccountStateContent" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>25</Order>
<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>
</RunSynchronousCommand>
</RunSynchronous>
</component>
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<fDenyTSConnections>false</fDenyTSConnections>
</component>
<component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<UserAuthentication>0</UserAuthentication>
</component>
<component name="Networking-MPSSVC-Svc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<FirewallGroups>
<FirewallGroup wcm:action="add" wcm:keyValue="RemoteDesktop">
<Active>true</Active>
<Profile>all</Profile>
<Group>@FirewallAPI.dll,-28752</Group>
</FirewallGroup>
</FirewallGroups>
</component>
</settings>
<settings pass="auditSystem" />
<settings pass="auditUser" />
<settings pass="oobeSystem">
<component name="Microsoft-Windows-SecureStartup-FilterDriver" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<PreventDeviceEncryption>true</PreventDeviceEncryption>
</component>
<component name="Microsoft-Windows-EnhancedStorage-Adm" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<TCGSecurityActivationDisabled>1</TCGSecurityActivationDisabled>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<UserAccounts>
<LocalAccounts>
<LocalAccount wcm:action="add">
<Name>Docker</Name>
<Group>Administrators</Group>
<Password>
<Value />
<PlainText>true</PlainText>
</Password>
</LocalAccount>
</LocalAccounts>
<AdministratorPassword>
<Value>password</Value>
<PlainText>true</PlainText>
</AdministratorPassword>
</UserAccounts>
<AutoLogon>
<Username>Docker</Username>
<Enabled>true</Enabled>
<LogonCount>65432</LogonCount>
<Password>
<Value />
<PlainText>true</PlainText>
</Password>
</AutoLogon>
<Display>
<ColorDepth>32</ColorDepth>
<HorizontalResolution>1920</HorizontalResolution>
<VerticalResolution>1080</VerticalResolution>
</Display>
<OOBE>
<HideEULAPage>true</HideEULAPage>
<HideLocalAccountScreen>true</HideLocalAccountScreen>
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<NetworkLocation>Home</NetworkLocation>
<ProtectYourPC>3</ProtectYourPC>
<SkipUserOOBE>true</SkipUserOOBE>
<SkipMachineOOBE>true</SkipMachineOOBE>
</OOBE>
<RegisteredOrganization>Dockur</RegisteredOrganization>
<RegisteredOwner>Windows for Docker</RegisteredOwner>
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "AllowInsecureGuestAuth" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Allow guest access to network shares</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>2</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f</CommandLine>
<Description>Allow RDP login with blank password</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>3</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Enable option for passwordless sign-in</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>4</Order>
<CommandLine>cmd /C wmic useraccount where name="Docker" set PasswordExpires=false</CommandLine>
<Description>Password Never Expires</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>5</Order>
<CommandLine>cmd /C POWERCFG -H OFF</CommandLine>
<Description>Disable Hibernation</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>6</Order>
<CommandLine>cmd /C POWERCFG -X -monitor-timeout-ac 0</CommandLine>
<Description>Disable monitor blanking</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>7</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Edge" /v "HideFirstRunExperience" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Disable first-run experience in Edge</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>8</Order>
<CommandLine>reg.exe add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "HideFileExt" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Show file extensions in Explorer</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>9</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Power" /v "HibernateFileSizePercent" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Zero Hibernation File</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>10</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Power" /v "HibernateEnabled" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Disable Hibernation</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>11</Order>
<CommandLine>cmd /C POWERCFG -X -standby-timeout-ac 0</CommandLine>
<Description>Disable Sleep</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>12</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v "fAllowUnlistedRemotePrograms" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Enable RemoteAPP to launch unlisted programs</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>13</Order>
<CommandLine>reg.exe add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "ShowTaskViewButton" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Remove Task View from the Taskbar</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>14</Order>
<CommandLine>reg.exe add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "TaskbarDa" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Remove Widgets from the Taskbar</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>15</Order>
<CommandLine>reg.exe add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "TaskbarMn" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Remove Chat from the Taskbar</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>16</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v "NoAutoUpdate" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Turn off Windows Update auto download</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>17</Order>
<CommandLine>netsh advfirewall firewall set rule group="@FirewallAPI.dll,-32752" new enable=Yes</CommandLine>
<Description>Enable Network Discovery</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>18</Order>
<CommandLine>netsh advfirewall firewall set rule group="@FirewallAPI.dll,-28502" new enable=Yes</CommandLine>
<Description>Enable File Sharing</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>19</Order>
<CommandLine>reg.exe add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v SV1 /d 0 /t REG_DWORD /f</CommandLine>
<Description>Disable unsupported hardware notifications</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>20</Order>
<CommandLine>reg.exe add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v SV2 /d 0 /t REG_DWORD /f</CommandLine>
<Description>Disable unsupported hardware notifications</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>21</Order>
<CommandLine>cmd /C if exist "C:\OEM\install.bat" start "Install" "cmd /C C:\OEM\install.bat"</CommandLine>
<Description>Execute custom script from the OEM folder if exists</Description>
</SynchronousCommand>
</FirstLogonCommands>
</component>
</settings>
</unattend>

453
assets/win11x64-ltsc.xml Normal file
View File

@ -0,0 +1,453 @@
<?xml version="1.0" encoding="UTF-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<settings pass="windowsPE">
<component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<SetupUILanguage>
<UILanguage>en-US</UILanguage>
</SetupUILanguage>
<InputLocale>0409:00000409</InputLocale>
<SystemLocale>en-US</SystemLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-US</UserLocale>
</component>
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DiskConfiguration>
<Disk wcm:action="add">
<DiskID>0</DiskID>
<WillWipeDisk>true</WillWipeDisk>
<CreatePartitions>
<!-- System partition (ESP) -->
<CreatePartition wcm:action="add">
<Order>1</Order>
<Type>EFI</Type>
<Size>128</Size>
</CreatePartition>
<!-- Microsoft reserved partition (MSR) -->
<CreatePartition wcm:action="add">
<Order>2</Order>
<Type>MSR</Type>
<Size>128</Size>
</CreatePartition>
<!-- Windows partition -->
<CreatePartition wcm:action="add">
<Order>3</Order>
<Type>Primary</Type>
<Extend>true</Extend>
</CreatePartition>
</CreatePartitions>
<ModifyPartitions>
<!-- System partition (ESP) -->
<ModifyPartition wcm:action="add">
<Order>1</Order>
<PartitionID>1</PartitionID>
<Label>System</Label>
<Format>FAT32</Format>
</ModifyPartition>
<!-- MSR partition does not need to be modified -->
<ModifyPartition wcm:action="add">
<Order>2</Order>
<PartitionID>2</PartitionID>
</ModifyPartition>
<!-- Windows partition -->
<ModifyPartition wcm:action="add">
<Order>3</Order>
<PartitionID>3</PartitionID>
<Label>Windows</Label>
<Letter>C</Letter>
<Format>NTFS</Format>
</ModifyPartition>
</ModifyPartitions>
</Disk>
</DiskConfiguration>
<ImageInstall>
<OSImage>
<InstallFrom>
<MetaData wcm:action="add">
<Key>/image/index</Key>
<Value>1</Value>
</MetaData>
</InstallFrom>
<InstallTo>
<DiskID>0</DiskID>
<PartitionID>3</PartitionID>
</InstallTo>
<InstallToAvailablePartition>false</InstallToAvailablePartition>
</OSImage>
</ImageInstall>
<DynamicUpdate>
<Enable>true</Enable>
<WillShowUI>Never</WillShowUI>
</DynamicUpdate>
<UpgradeData>
<Upgrade>false</Upgrade>
<WillShowUI>Never</WillShowUI>
</UpgradeData>
<UserData>
<AcceptEula>true</AcceptEula>
<FullName>Docker</FullName>
<Organization>Windows for Docker</Organization>
</UserData>
<EnableFirewall>false</EnableFirewall>
<Diagnostics>
<OptIn>false</OptIn>
</Diagnostics>
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassTPMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassSecureBootCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>3</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassRAMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>4</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\MoSetup" /v AllowUpgradesWithUnsupportedTPMOrCPU /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
<settings pass="offlineServicing">
<component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<EnableLUA>false</EnableLUA>
</component>
</settings>
<settings pass="generalize">
<component name="Microsoft-Windows-PnPSysprep" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<PersistAllDeviceInstalls>true</PersistAllDeviceInstalls>
</component>
<component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<SkipRearm>1</SkipRearm>
</component>
</settings>
<settings pass="specialize">
<component name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<SkipAutoActivation>true</SkipAutoActivation>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<ComputerName>*</ComputerName>
<OEMInformation>
<Manufacturer>Dockur</Manufacturer>
<Model>Windows for Docker</Model>
<SupportHours>24/7</SupportHours>
<SupportPhone />
<SupportProvider>Dockur</SupportProvider>
<SupportURL>https://github.com/dockur/windows/issues</SupportURL>
</OEMInformation>
<OEMName>Windows for Docker</OEMName>
</component>
<component name="Microsoft-Windows-ErrorReportingCore" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DisableWER>1</DisableWER>
</component>
<component name="Microsoft-Windows-IE-InternetExplorer" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DisableAccelerators>true</DisableAccelerators>
<DisableFirstRunWizard>true</DisableFirstRunWizard>
<Home_Page>https://google.com</Home_Page>
<Help_Page>about:blank</Help_Page>
</component>
<component name="Microsoft-Windows-IE-InternetExplorer" processorArchitecture="wow64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DisableAccelerators>true</DisableAccelerators>
<DisableFirstRunWizard>true</DisableFirstRunWizard>
<Home_Page>https://google.com</Home_Page>
<Help_Page>about:blank</Help_Page>
</component>
<component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<CEIPEnabled>0</CEIPEnabled>
</component>
<component name="Microsoft-Windows-SystemRestore-Main" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<DisableSR>1</DisableSR>
</component>
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<InputLocale>0409:00000409</InputLocale>
<SystemLocale>en-US</SystemLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-US</UserLocale>
</component>
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" /v BypassNRO /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>reg.exe load "HKU\mount" "C:\Users\Default\NTUSER.DAT"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>3</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "ContentDeliveryAllowed" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>4</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "FeatureManagementEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>5</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "OEMPreInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>6</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>7</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEverEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>8</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SilentInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>9</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SoftLandingEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>10</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContentEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>11</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-310093Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>12</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338387Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>13</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338388Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>14</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338389Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>15</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338393Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>16</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-353698Enabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>17</Order>
<Path>reg.exe add "HKU\mount\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SystemPaneSuggestionsEnabled" /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>18</Order>
<Path>reg.exe add "HKU\mount\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableCloudOptimizedContent" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>19</Order>
<Path>reg.exe add "HKU\mount\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableWindowsConsumerFeatures" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>20</Order>
<Path>reg.exe add "HKU\mount\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableConsumerAccountStateContent" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>21</Order>
<Path>reg.exe unload "HKU\mount"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>22</Order>
<Path>reg.exe add "HKLM\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableCloudOptimizedContent" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>23</Order>
<Path>reg.exe add "HKLM\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableWindowsConsumerFeatures" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>24</Order>
<Path>reg.exe add "HKLM\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableConsumerAccountStateContent" /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>25</Order>
<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>
</RunSynchronousCommand>
</RunSynchronous>
</component>
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<fDenyTSConnections>false</fDenyTSConnections>
</component>
<component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<UserAuthentication>0</UserAuthentication>
</component>
<component name="Networking-MPSSVC-Svc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<FirewallGroups>
<FirewallGroup wcm:action="add" wcm:keyValue="RemoteDesktop">
<Active>true</Active>
<Profile>all</Profile>
<Group>@FirewallAPI.dll,-28752</Group>
</FirewallGroup>
</FirewallGroups>
</component>
</settings>
<settings pass="auditSystem" />
<settings pass="auditUser" />
<settings pass="oobeSystem">
<component name="Microsoft-Windows-SecureStartup-FilterDriver" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<PreventDeviceEncryption>true</PreventDeviceEncryption>
</component>
<component name="Microsoft-Windows-EnhancedStorage-Adm" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<TCGSecurityActivationDisabled>1</TCGSecurityActivationDisabled>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<UserAccounts>
<LocalAccounts>
<LocalAccount wcm:action="add">
<Name>Docker</Name>
<Group>Administrators</Group>
<Password>
<Value />
<PlainText>true</PlainText>
</Password>
</LocalAccount>
</LocalAccounts>
<AdministratorPassword>
<Value>password</Value>
<PlainText>true</PlainText>
</AdministratorPassword>
</UserAccounts>
<AutoLogon>
<Username>Docker</Username>
<Enabled>true</Enabled>
<LogonCount>65432</LogonCount>
<Password>
<Value />
<PlainText>true</PlainText>
</Password>
</AutoLogon>
<Display>
<ColorDepth>32</ColorDepth>
<HorizontalResolution>1920</HorizontalResolution>
<VerticalResolution>1080</VerticalResolution>
</Display>
<OOBE>
<HideEULAPage>true</HideEULAPage>
<HideLocalAccountScreen>true</HideLocalAccountScreen>
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<NetworkLocation>Home</NetworkLocation>
<ProtectYourPC>3</ProtectYourPC>
<SkipUserOOBE>true</SkipUserOOBE>
<SkipMachineOOBE>true</SkipMachineOOBE>
</OOBE>
<RegisteredOrganization>Dockur</RegisteredOrganization>
<RegisteredOwner>Windows for Docker</RegisteredOwner>
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters" /v "AllowInsecureGuestAuth" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Allow guest access to network shares</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>2</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse /t REG_DWORD /d 0 /f</CommandLine>
<Description>Allow RDP login with blank password</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>3</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device" /v "DevicePasswordLessBuildVersion" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Enable option for passwordless sign-in</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>4</Order>
<CommandLine>cmd /C wmic useraccount where name="Docker" set PasswordExpires=false</CommandLine>
<Description>Password Never Expires</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>5</Order>
<CommandLine>cmd /C POWERCFG -H OFF</CommandLine>
<Description>Disable Hibernation</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>6</Order>
<CommandLine>cmd /C POWERCFG -X -monitor-timeout-ac 0</CommandLine>
<Description>Disable monitor blanking</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>7</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Edge" /v "HideFirstRunExperience" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Disable first-run experience in Edge</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>8</Order>
<CommandLine>reg.exe add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "HideFileExt" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Show file extensions in Explorer</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>9</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Power" /v "HibernateFileSizePercent" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Zero Hibernation File</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>10</Order>
<CommandLine>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Power" /v "HibernateEnabled" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Disable Hibernation</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>11</Order>
<CommandLine>cmd /C POWERCFG -X -standby-timeout-ac 0</CommandLine>
<Description>Disable Sleep</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>12</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v "fAllowUnlistedRemotePrograms" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Enable RemoteAPP to launch unlisted programs</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>13</Order>
<CommandLine>reg.exe add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "ShowTaskViewButton" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Remove Task View from the Taskbar</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>14</Order>
<CommandLine>reg.exe add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "TaskbarDa" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Remove Widgets from the Taskbar</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>15</Order>
<CommandLine>reg.exe add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "TaskbarMn" /t REG_DWORD /d 0 /f</CommandLine>
<Description>Remove Chat from the Taskbar</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>16</Order>
<CommandLine>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v "NoAutoUpdate" /t REG_DWORD /d 1 /f</CommandLine>
<Description>Turn off Windows Update auto download</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>17</Order>
<CommandLine>netsh advfirewall firewall set rule group="@FirewallAPI.dll,-32752" new enable=Yes</CommandLine>
<Description>Enable Network Discovery</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>18</Order>
<CommandLine>netsh advfirewall firewall set rule group="@FirewallAPI.dll,-28502" new enable=Yes</CommandLine>
<Description>Enable File Sharing</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>19</Order>
<CommandLine>reg.exe add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v SV1 /d 0 /t REG_DWORD /f</CommandLine>
<Description>Disable unsupported hardware notifications</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>20</Order>
<CommandLine>reg.exe add "HKCU\Control Panel\UnsupportedHardwareNotificationCache" /v SV2 /d 0 /t REG_DWORD /f</CommandLine>
<Description>Disable unsupported hardware notifications</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>21</Order>
<CommandLine>cmd /C if exist "C:\OEM\install.bat" start "Install" "cmd /C C:\OEM\install.bat"</CommandLine>
<Description>Execute custom script from the OEM folder if exists</Description>
</SynchronousCommand>
</FirstLogonCommands>
</component>
</settings>
</unattend>

View File

@ -87,12 +87,12 @@ kubectl apply -f kubernetes.yml
|---|---|---| |---|---|---|
| `win11` | Windows 11 Pro | 6.4 GB | | `win11` | Windows 11 Pro | 6.4 GB |
| `win11e` | Windows 11 Enterprise | 5.8 GB | | `win11e` | Windows 11 Enterprise | 5.8 GB |
| `win10` | Windows 10 Pro | 5.8 GB | | `win10` | Windows 10 Pro | 5.7 GB |
| `ltsc10` | Windows 10 LTSC | 4.6 GB | | `ltsc10` | Windows 10 LTSC | 4.6 GB |
| `win10e` | Windows 10 Enterprise | 5.2 GB | | `win10e` | Windows 10 Enterprise | 5.2 GB |
|||| ||||
| `win8` | Windows 8.1 Pro | 4.2 GB | | `win8` | Windows 8.1 Pro | 4.0 GB |
| `win8e` | Windows 8.1 Enterprise | 3.8 GB | | `win8e` | Windows 8.1 Enterprise | 3.7 GB |
| `win7` | Windows 7 Enterprise | 3.0 GB | | `win7` | Windows 7 Enterprise | 3.0 GB |
| `vista` | Windows Vista Enterprise | 3.0 GB | | `vista` | Windows Vista Enterprise | 3.0 GB |
| `winxp` | Windows XP Professional | 0.6 GB | | `winxp` | Windows XP Professional | 0.6 GB |
@ -179,22 +179,9 @@ kubectl apply -f kubernetes.yml
Replace the example path `/home/user/example.iso` with the filename of your desired ISO file, the value of `VERSION` will be ignored in this case. Replace the example path `/home/user/example.iso` with the filename of your desired ISO file, the value of `VERSION` will be ignored in this case.
* ### How do I customize the installation?
If you want to modify the settings used during the automatic installation, you can do this by editing the answer file corresponding to your Windows edition, for example [win11x64.xml](https://raw.githubusercontent.com/dockur/windows/master/assets/win11x64.xml) in the case of Windows 11 Pro.
Apply your modifications to it, and add this line to your compose file:
```yaml
volumes:
- /home/user/example.xml:/custom.xml
```
Replace the example path `/home/user/example.xml` with the filename of the modified XML file.
* ### How do I run a script after installation? * ### How do I run a script after installation?
To run your own script after installation, you can create a file called `install.bat` and place it in a folder together with other files it needs (programs to install for example). Then bind it in your compose file like this: To run your own script after installation, you can create a file called `install.bat` and place it in a folder together with any additional files it needs (software to be installed for example). Then bind that folder in your compose file like this:
```yaml ```yaml
volumes: volumes:
@ -205,7 +192,7 @@ kubectl apply -f kubernetes.yml
* ### How do I perform a manual installation? * ### How do I perform a manual installation?
It's best to use the automatic installation, as it prevents common issues that occur when running Windows inside a virtualized environment and optimizes various settings to give you maximum performance. It's best 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, add the following environment variable to your compose file: However, if you insist on performing the installation manually, add the following environment variable to your compose file:
@ -214,32 +201,6 @@ kubectl apply -f kubernetes.yml
MANUAL: "Y" MANUAL: "Y"
``` ```
Then follow these steps:
- Start the container and connect to [port 8006](http://localhost:8006) of the container in your web browser. After the download is finished, you will see the Windows installation screen.
- Start the installation by clicking `Install now`. On the next screen, press 'OK' when prompted to `Load driver`.
- Select the `VirtIO SCSI` driver from the list that matches your Windows version. So for Windows 11, select `D:\amd64\w11\vioscsi.inf` and click 'Next'.
- Accept the license agreement and select your preferred Windows edition, like Home or Pro.
- Choose `Custom: Install Windows only (advanced)`, and click `Load driver` on the next screen.
- Select 'Browse' and navigate to the `D:\NetKVM\w11\amd64` folder, and click 'OK'.
- Select the `VirtIO Ethernet Adapter` from the list and click 'Next'.
- Select `Drive 0` and click 'Next'.
- Wait until Windows finishes copying files and completes the installation.
- Once you see the desktop, open File Explorer and navigate to the CD-ROM drive (`E:\`).
- Double-click on `virtio-win-gt-x64.msi` and proceed to install the VirtIO drivers.
Enjoy your brand new machine, and don't forget to star this repo!
* ### How do I verify if my system supports KVM? * ### How do I verify if my system supports KVM?
To verify if your system supports KVM, run the following commands: To verify if your system supports KVM, run the following commands:
@ -251,11 +212,11 @@ kubectl apply -f kubernetes.yml
If you receive an error from `kvm-ok` indicating that KVM acceleration can't be used, check the virtualization settings in the BIOS. If you receive an error from `kvm-ok` indicating that KVM acceleration can't be used, check the virtualization settings in the BIOS.
* ### How do I increase the amount of CPU or RAM? * ### How do I change the amount of CPU or RAM?
By default, 2 CPU cores and 4 GB of RAM are allocated to the container, as those are the minimum requirements of Windows 11. By default, the container will be allowed to use a maximum of 2 CPU cores and 4 GB of RAM.
If there arises a need to increase this, add the following environment variables: If you want to adjust this, you can specify the desired amount using the following environment variables:
```yaml ```yaml
environment: environment:
@ -265,12 +226,14 @@ kubectl apply -f kubernetes.yml
* ### How do I configure the username and password? * ### How do I configure the username and password?
By default, a user called `Docker` is created during installation with an empty password. You can change these credentials in your compose file: By default, a user called `Docker` is created during the installation, with an empty password.
If you want to use different credentials, you can change them in your compose file:
```yaml ```yaml
environment: environment:
USERNAME: "john" USERNAME: "bill"
PASSWORD: "secret" PASSWORD: "gates"
``` ```
* ### How do I connect using RDP? * ### How do I connect using RDP?
@ -279,7 +242,7 @@ kubectl apply -f kubernetes.yml
So for a better experience you can connect using any Microsoft Remote Desktop client to the IP of the container, using the username `Docker` and by leaving the password empty. So for a better experience you can connect using any Microsoft Remote Desktop client to the IP of the container, using the username `Docker` and by leaving the password empty.
There is a good RDP client for [Android](https://play.google.com/store/apps/details?id=com.microsoft.rdc.androidx) available from the Play Store and one for [iOS](https://apps.apple.com/nl/app/microsoft-remote-desktop/id714464092?l=en-GB) in the Apple Store. For Linux you can use [FreeRDP](https://www.freerdp.com/) and on Windows just type `mstsc` in the search box. 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?

View File

@ -105,6 +105,10 @@ parseVersion() {
VERSION="win10x64-enterprise-iot-eval" VERSION="win10x64-enterprise-iot-eval"
[ -z "$DETECTED" ] && DETECTED="win10x64-iot" [ -z "$DETECTED" ] && DETECTED="win10x64-iot"
;; ;;
"ltsc11" | "11ltsc" | "win11-ltsc" | "win11x64-ltsc" | "win11x64-enterprise-ltsc-eval" )
VERSION="win11x64-enterprise-ltsc-eval"
[ -z "$DETECTED" ] && DETECTED="win11x64-iot"
;;
"ltsc10" | "10ltsc" | "win10-ltsc" | "win10x64-ltsc" | "win10x64-enterprise-ltsc-eval" ) "ltsc10" | "10ltsc" | "win10-ltsc" | "win10x64-ltsc" | "win10x64-enterprise-ltsc-eval" )
VERSION="win10x64-enterprise-ltsc-eval" VERSION="win10x64-enterprise-ltsc-eval"
[ -z "$DETECTED" ] && DETECTED="win10x64-ltsc" [ -z "$DETECTED" ] && DETECTED="win10x64-ltsc"
@ -358,6 +362,10 @@ printVersion() {
"win10"* ) desc="Windows 10" ;; "win10"* ) desc="Windows 10" ;;
"win11"* ) desc="Windows 11" ;; "win11"* ) desc="Windows 11" ;;
"winxp"* ) desc="Windows XP" ;; "winxp"* ) desc="Windows XP" ;;
"win9x"* ) desc="Windows ME" ;;
"win98"* ) desc="Windows 98" ;;
"win95"* ) desc="Windows 95" ;;
"win2k"* ) desc="Windows 2000" ;;
"winvista"* ) desc="Windows Vista" ;; "winvista"* ) desc="Windows Vista" ;;
"win2025"* ) desc="Windows Server 2025" ;; "win2025"* ) desc="Windows Server 2025" ;;
"win2022"* ) desc="Windows Server 2022" ;; "win2022"* ) desc="Windows Server 2022" ;;
@ -556,19 +564,10 @@ getVersion() {
*" enterprise"* ) id="$id-enterprise" ;; *" enterprise"* ) id="$id-enterprise" ;;
esac esac
;; ;;
"win10"* ) "win10"* | "win11"* )
case "${name,,}" in
*" iot"* ) id="$id-iot" ;;
*" ltsc"* ) id="$id-ltsc" ;;
*" home"* ) id="$id-home" ;;
*" education"* ) id="$id-education" ;;
*" enterprise evaluation"* ) id="$id-enterprise-eval" ;;
*" enterprise"* ) id="$id-enterprise" ;;
esac
;;
"win11"* )
case "${name,,}" in case "${name,,}" in
*" iot"* ) id="$id-iot" ;; *" iot"* ) id="$id-iot" ;;
*" ltsc"* ) id="$id-ltsc" ;;
*" home"* ) id="$id-home" ;; *" home"* ) id="$id-home" ;;
*" education"* ) id="$id-education" ;; *" education"* ) id="$id-education" ;;
*" enterprise evaluation"* ) id="$id-enterprise-eval" ;; *" enterprise evaluation"* ) id="$id-enterprise-eval" ;;
@ -629,6 +628,14 @@ getMido() {
size=6209064960 size=6209064960
sum="c8dbc96b61d04c8b01faf6ce0794fdf33965c7b350eaa3eb1e6697019902945c" sum="c8dbc96b61d04c8b01faf6ce0794fdf33965c7b350eaa3eb1e6697019902945c"
;; ;;
"win11x64-enterprise-ltsc-eval" )
size=4428627968
sum="8abf91c9cd408368dc73aab3425d5e3c02dae74900742072eb5c750fc637c195"
;;
"win11x64-enterprise-iot-eval" )
size=4428627968
sum="8abf91c9cd408368dc73aab3425d5e3c02dae74900742072eb5c750fc637c195"
;;
"win10x64" ) "win10x64" )
size=6140975104 size=6140975104
sum="a6f470ca6d331eb353b815c043e327a347f594f37ff525f17764738fe812852e" sum="a6f470ca6d331eb353b815c043e327a347f594f37ff525f17764738fe812852e"
@ -1034,6 +1041,18 @@ getLink4() {
"zh" | "zh-"* ) url="zh-cn_windows_11_business_editions_version_23h2_updated_april_2024_x64_dvd_3db5a62b.iso" ;; "zh" | "zh-"* ) url="zh-cn_windows_11_business_editions_version_23h2_updated_april_2024_x64_dvd_3db5a62b.iso" ;;
esac esac
;; ;;
"win11x64-iot" | "win11x64-enterprise-iot-eval" )
[[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0
size=4821989376
sum="e8f1431c4e6289b3997c20eadbb2576670300bb6e1cf8948b5d7af179010a962"
url="26100.1.240331-1435.ge_release_CLIENTENTERPRISE_OEM_x64FRE_en-us.iso"
;;
"win11x64-ltsc" | "win11x64-enterprise-ltsc-eval" )
[[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0
size=4821989376
sum="e8f1431c4e6289b3997c20eadbb2576670300bb6e1cf8948b5d7af179010a962"
url="26100.1.240331-1435.ge_release_CLIENTENTERPRISE_OEM_x64FRE_en-us.iso"
;;
"win10x64" ) "win10x64" )
case "${culture,,}" in case "${culture,,}" in
"ar" | "ar-"* ) url="ar-sa_windows_10_consumer_editions_version_22h2_updated_april_2024_x64_dvd_9a92dc89.iso" ;; "ar" | "ar-"* ) url="ar-sa_windows_10_consumer_editions_version_22h2_updated_april_2024_x64_dvd_9a92dc89.iso" ;;
@ -1169,12 +1188,6 @@ getLink4() {
"zh" | "zh-"* ) url="zh-cn_windows_10_enterprise_ltsc_2021_x64_dvd_033b7312.iso" ;; "zh" | "zh-"* ) url="zh-cn_windows_10_enterprise_ltsc_2021_x64_dvd_033b7312.iso" ;;
esac esac
;; ;;
"win11x64-iot" | "win11x64-enterprise-iot-eval" )
[[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0
size=6248140800
sum="5d9b86ad467bc89f488d1651a6c5ad3656a7ea923f9f914510657a24c501bb86"
url="en-us_windows_11_iot_enterprise_version_23h2_x64_dvd_fb37549c.iso"
;;
"win10x64-iot" | "win10x64-enterprise-iot-eval" ) "win10x64-iot" | "win10x64-enterprise-iot-eval" )
[[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0 [[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-us" ]] && return 0
size=4851668992 size=4851668992
@ -1918,6 +1931,32 @@ prepareLegacy() {
return 1 return 1
} }
prepare9x() {
local iso="$1"
local dir="$2"
local file="$dir/boot.img"
ETFS=$(basename "$file")
[ -f "$file" ] && [ -s "$file" ] && return 0
rm -f "$file"
local src="[BOOT]/Boot-1.44M.img"
[ ! -f "$dir/$src" ] && error "Boot floppy not found!" && return 1
cp "$dir/$src" "$file" && return 0
return 1
}
prepare2k() {
local dir="$2"
ETFS="[BOOT]/Boot-NoEmul.img"
return 0
}
prepareXP() { prepareXP() {
local dir="$2" local dir="$2"
@ -1932,10 +1971,13 @@ prepareXP() {
target="$dir/AMD64" target="$dir/AMD64"
fi fi
rm -rf "$drivers" local msg="Adding drivers to image..."
info "$msg" && html "$msg"
if ! 7z x /run/drivers.iso -o"$drivers" > /dev/null; then mkdir -p "$drivers"
error "Failed to extract driver ISO file!" && return 1
if ! tar -xf /drivers.txz -C "$drivers" --warning=no-timestamp; then
error "Failed to extract driver!" && return 1
fi fi
cp "$drivers/viostor/xp/$arch/viostor.sys" "$target" cp "$drivers/viostor/xp/$arch/viostor.sys" "$target"
@ -1978,14 +2020,16 @@ prepareXP() {
sed -i '/^\[SCSI\]/s/$/\niaStor=\"Intel\(R\) SATA RAID\/AHCI Controller\"/' "$target/TXTSETUP.SIF" sed -i '/^\[SCSI\]/s/$/\niaStor=\"Intel\(R\) SATA RAID\/AHCI Controller\"/' "$target/TXTSETUP.SIF"
sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_8086\&DEV_2922\&CC_0106=\"iaStor\"/' "$target/TXTSETUP.SIF" sed -i '/^\[HardwareIdsDatabase\]/s/$/\nPCI\\VEN_8086\&DEV_2922\&CC_0106=\"iaStor\"/' "$target/TXTSETUP.SIF"
local key pid setup rm -rf "$drivers"
local key pid file setup
setup=$(find "$target" -maxdepth 1 -type f -iname setupp.ini | head -n 1) setup=$(find "$target" -maxdepth 1 -type f -iname setupp.ini | head -n 1)
pid=$(<"$setup") pid=$(<"$setup")
pid="${pid:(-4)}" pid="${pid:(-4)}"
pid="${pid:0:3}" pid="${pid:0:3}"
if [[ "$pid" == "270" ]]; then if [[ "$pid" == "270" ]]; then
info "Warning: this XP version requires a volume license, it will reject the generic key during installation." warn "this version of Windows XP requires a volume license key (VLK), it will ask for one during installation."
fi fi
if [[ "${arch,,}" == "x86" ]]; then if [[ "${arch,,}" == "x86" ]]; then
@ -1998,10 +2042,28 @@ prepareXP() {
key="B2RBK-7KPT9-4JP6X-QQFWM-PJD6G" key="B2RBK-7KPT9-4JP6X-QQFWM-PJD6G"
fi fi
local oem=""
local folder="/oem"
[ ! -d "$folder" ] && folder="/OEM"
[ ! -d "$folder" ] && folder="$STORAGE/oem"
[ ! -d "$folder" ] && folder="$STORAGE/OEM"
if [ -d "$folder" ]; then
file=$(find "$folder" -maxdepth 1 -type f -iname install.bat | head -n 1)
if [ -f "$file" ]; then
unix2dos -q "$file"
oem="\"Script\"=\"cmd /C start \\\"Install\\\" \\\"cmd /C C:\\\\OEM\\\\install.bat\\\"\""
fi
fi
local username="Docker" local username="Docker"
local password="*" local password="*"
[ -n "$USERNAME" ] && username="$USERNAME"
[ -n "$PASSWORD" ] && password="$PASSWORD" [ -n "$PASSWORD" ] && password="$PASSWORD"
[ -n "$USERNAME" ] && username=$(echo "$USERNAME" | sed 's/[^[:alnum:]@!._-]//g')
find "$target" -maxdepth 1 -type f -iname winnt.sif -exec rm {} \; find "$target" -maxdepth 1 -type f -iname winnt.sif -exec rm {} \;
@ -2055,9 +2117,6 @@ prepareXP() {
echo " Home_Page = http://www.google.com" echo " Home_Page = http://www.google.com"
echo " Search_Page = http://www.google.com" echo " Search_Page = http://www.google.com"
echo "" echo ""
echo "[RegionalSettings]"
echo " Language=00000409"
echo ""
echo "[TerminalServices]" echo "[TerminalServices]"
echo " AllowConnections=1" echo " AllowConnections=1"
echo "" echo ""
@ -2098,10 +2157,10 @@ prepareXP() {
echo "\"DefaultSettings.XResolution\"=dword:00000780" echo "\"DefaultSettings.XResolution\"=dword:00000780"
echo "\"DefaultSettings.YResolution\"=dword:00000438" echo "\"DefaultSettings.YResolution\"=dword:00000438"
echo "" echo ""
echo "[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnceEx]" 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\\\"\""
echo "\"ScreenSaverOff\"=\"reg add \\\"HKCU\\\\Control Panel\\\\Desktop\\\" /f /v \\\"ScreenSaveActive\\\" /t REG_SZ /d \\\"0\\\"\"" echo "\"ScreenSaverOff\"=\"reg add \\\"HKCU\\\\Control Panel\\\\Desktop\\\" /f /v \\\"ScreenSaveActive\\\" /t REG_SZ /d \\\"0\\\"\""
echo "" echo "$oem"
} | unix2dos > "$dir/\$OEM\$/install.reg" } | unix2dos > "$dir/\$OEM\$/install.reg"
{ echo "Set WshShell = WScript.CreateObject(\"WScript.Shell\")" { echo "Set WshShell = WScript.CreateObject(\"WScript.Shell\")"
@ -2118,7 +2177,18 @@ prepareXP() {
echo "" echo ""
} | unix2dos > "$dir/\$OEM\$/cmdlines.txt" } | unix2dos > "$dir/\$OEM\$/cmdlines.txt"
rm -rf "$drivers" [ ! -d "$folder" ] && return 0
msg="Adding OEM folder to image..."
info "$msg" && html "$msg"
local dest="$dir/\$OEM\$/\$1/"
mkdir -p "$dest"
if ! cp -r "$folder" "$dest"; then
error "Failed to copy OEM folder!" && return 1
fi
return 0 return 0
} }

View File

@ -35,4 +35,4 @@ cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" &
wait $! || : wait $! || :
sleep 1 & wait $! sleep 1 & wait $!
finish 0 [ ! -f "$QEMU_END" ] && finish 0

View File

@ -119,6 +119,7 @@ finishInstall() {
fi fi
rm -f "$STORAGE/windows.old" rm -f "$STORAGE/windows.old"
rm -f "$STORAGE/windows.type"
rm -f "$STORAGE/windows.base" rm -f "$STORAGE/windows.base"
rm -f "$STORAGE/windows.boot" rm -f "$STORAGE/windows.boot"
rm -f "$STORAGE/windows.mode" rm -f "$STORAGE/windows.mode"
@ -149,21 +150,30 @@ finishInstall() {
# 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" echo "$BOOT_MODE" > "$STORAGE/windows.mode"
fi fi
fi fi
fi fi
if [ -n "${DISK_TYPE:-}" ] && [[ "${DISK_TYPE:-}" != "scsi" ]]; then
echo "$DISK_TYPE" > "$STORAGE/windows.type"
fi
rm -rf "$TMP" rm -rf "$TMP"
return 0 return 0
} }
abortInstall() { abortInstall() {
local iso="$1" local dir="$1"
local iso="$2"
[[ "${iso,,}" == *".esd" ]] && exit 60 [[ "${iso,,}" == *".esd" ]] && exit 60
if [ ! -d "$dir/EFI" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy"
fi
if [ -n "$CUSTOM" ]; then if [ -n "$CUSTOM" ]; then
BOOT="$iso" BOOT="$iso"
REMOVE="N" REMOVE="N"
@ -468,6 +478,7 @@ detectLanguage() {
setXML() { setXML() {
local file="/custom.xml" local file="/custom.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$STORAGE/custom.xml" [ ! -f "$file" ] || [ ! -s "$file" ] && file="$STORAGE/custom.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="/run/assets/custom.xml" [ ! -f "$file" ] || [ ! -s "$file" ] && file="/run/assets/custom.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$1" [ ! -f "$file" ] || [ ! -s "$file" ] && file="$1"
@ -478,11 +489,81 @@ setXML() {
return 0 return 0
} }
detectLegacy() {
local dir="$1"
local find find2 desc
find=$(find "$dir" -maxdepth 1 -type d -iname win95 | head -n 1)
if [ -n "$find" ]; then
DETECTED="win95"
desc=$(printEdition "$DETECTED" "Windows 95")
info "Detected: $desc" && return 0
fi
find=$(find "$dir" -maxdepth 1 -type d -iname win98 | head -n 1)
if [ -n "$find" ]; then
DETECTED="win98"
desc=$(printEdition "$DETECTED" "Windows 98")
info "Detected: $desc" && return 0
fi
find=$(find "$dir" -maxdepth 1 -type d -iname win9x | head -n 1)
if [ -n "$find" ]; then
DETECTED="win9x"
desc=$(printEdition "$DETECTED" "Windows ME")
info "Detected: $desc" && return 0
fi
find=$(find "$dir" -maxdepth 1 -type d -iname win51 | head -n 1)
find2=$(find "$dir" -maxdepth 1 -type f -iname setupxp.htm | head -n 1)
if [ -n "$find" ] || [ -n "$find2" ] || [ -f "$dir/WIN51AP" ] || [ -f "$dir/WIN51IC" ]; then
[ -d "$dir/AMD64" ] && DETECTED="winxpx64" || DETECTED="winxpx86"
desc=$(printEdition "$DETECTED" "Windows XP")
info "Detected: $desc" && return 0
fi
if [ -f "$dir/CDROM_NT.5" ]; then
DETECTED="win2kx86"
desc=$(printEdition "$DETECTED" "Windows 2000")
info "Detected: $desc" && return 0
fi
if [ -f "$dir/WIN51AA" ] || [ -f "$dir/WIN51AD" ] || [ -f "$dir/WIN51AS" ] || [ -f "$dir/WIN51MA" ] || [ -f "$dir/WIN51MD" ]; then
desc="Windows Server 2003"
info "Detected: $desc" && error "$desc is not supported yet!" && exit 54
fi
if [ -f "$dir/WIN51IA" ] || [ -f "$dir/WIN51IB" ] || [ -f "$dir/WIN51ID" ] || [ -f "$dir/WIN51IL" ] || [ -f "$dir/WIN51IS" ]; then
desc="Windows Server 2003"
info "Detected: $desc" && error "$desc is not supported yet!" && exit 54
fi
return 1
}
skipVersion() {
local version="$1"
case "${version,,}" in
"win2k"* | "winxp"* | "win9"* )
return 0
;;
esac
return 1
}
detectImage() { detectImage() {
local dir="$1" local dir="$1"
local version="$2" local version="$2"
local desc msg language local desc msg find language
XML="" XML=""
@ -492,7 +573,7 @@ detectImage() {
if [ -n "$DETECTED" ]; then if [ -n "$DETECTED" ]; then
[[ "${DETECTED,,}" == "winxp"* ]] && return 0 skipVersion "${DETECTED,,}" && return 0
if ! setXML "" && [[ "$MANUAL" != [Yy1]* ]]; then if ! setXML "" && [[ "$MANUAL" != [Yy1]* ]]; then
MANUAL="Y" MANUAL="Y"
@ -504,31 +585,23 @@ detectImage() {
fi fi
info "Detecting version from ISO image..." info "Detecting version from ISO image..."
detectLegacy "$dir" && return 0
if [ -f "$dir/WIN51" ] || [ -f "$dir/SETUPXP.HTM" ]; then local src wim info
[ -d "$dir/AMD64" ] && DETECTED="winxpx64" || DETECTED="winxpx86"
desc=$(printEdition "$DETECTED" "Windows XP")
info "Detected: $desc"
return 0
fi
local src loc info
src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1) src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1)
if [ ! -d "$src" ]; then if [ ! -d "$src" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy"
warn "failed to locate 'sources' folder in ISO image, $FB" && return 1 warn "failed to locate 'sources' folder in ISO image, $FB" && return 1
fi fi
loc=$(find "$src" -maxdepth 1 -type f -iname install.wim | head -n 1) wim=$(find "$src" -maxdepth 1 -type f -iname install.wim | head -n 1)
[ ! -f "$loc" ] && loc=$(find "$src" -maxdepth 1 -type f -iname install.esd | head -n 1) [ ! -f "$wim" ] && wim=$(find "$src" -maxdepth 1 -type f -iname install.esd | head -n 1)
if [ ! -f "$loc" ]; then if [ ! -f "$wim" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy"
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 "$loc" | tr -d '\000') info=$(wimlib-imagex info -xml "$wim" | tr -d '\000')
! checkPlatform "$info" && exit 67 ! checkPlatform "$info" && exit 67
DETECTED=$(detectVersion "$info") DETECTED=$(detectVersion "$info")
@ -575,19 +648,33 @@ prepareImage() {
local missing local missing
case "${DETECTED,,}" in case "${DETECTED,,}" in
"win9"* | "win2k"* )
MACHINE="pc-i440fx-2.4" ;;
"winxp"* | "winvistax86"* | "win7x86"* ) "winxp"* | "winvistax86"* | "win7x86"* )
MACHINE="pc-q35-2.10" MACHINE="pc-q35-2.10" ;;
;; esac
case "${DETECTED,,}" in
"win9"* | "winxp"* | "win2k"* )
HV="N"
BOOT_MODE="windows_legacy" ;;
"winvista"* | "win7"* | "win2008"* )
BOOT_MODE="windows_legacy" ;;
esac esac
case "${DETECTED,,}" in case "${DETECTED,,}" in
"winxp"* ) "winxp"* )
BOOT_MODE="windows_legacy" DISK_TYPE="blk"
prepareXP "$iso" "$dir" && return 0 prepareXP "$iso" "$dir" && return 0
error "Failed to prepare Windows XP ISO!" && return 1 error "Failed to prepare Windows XP ISO!" && return 1 ;;
;; "win9"* )
"winvista"* | "win7"* | "win2008"* ) DISK_TYPE="auto"
BOOT_MODE="windows_legacy" ;; prepare9x "$iso" "$dir" && return 0
error "Failed to prepare Windows 9x ISO!" && return 1 ;;
"win2k"* )
DISK_TYPE="auto"
prepare2k "$iso" "$dir" && return 0
error "Failed to prepare Windows 2000 ISO!" && return 1 ;;
esac esac
if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then
@ -596,10 +683,9 @@ prepareImage() {
missing=$(basename "$dir/$EFISYS") missing=$(basename "$dir/$EFISYS")
[ ! -f "$dir/$ETFS" ] && missing=$(basename "$dir/$ETFS") [ ! -f "$dir/$ETFS" ] && missing=$(basename "$dir/$ETFS")
warn "failed to locate file '${missing,,}' in ISO image!"
[[ "${PLATFORM,,}" == "arm64" ]] && return 1 error "failed to locate file '${missing,,}' in ISO image!"
BOOT_MODE="windows_legacy" return 1
fi fi
prepareLegacy "$iso" "$dir" && return 0 prepareLegacy "$iso" "$dir" && return 0
@ -659,6 +745,118 @@ updateXML() {
return 0 return 0
} }
addDriver() {
local id="$1"
local path="$2"
local target="$3"
local driver="$4"
local folder=""
case "${id,,}" in
"win7x86"* ) folder="w7/x86" ;;
"win7x64"* ) folder="w7/amd64" ;;
"win81x64"* ) folder="w10/amd64" ;;
"win10x64"* ) folder="w10/amd64" ;;
"win11x64"* ) folder="w11/amd64" ;;
"win2022"* ) folder="2k22/amd64" ;;
"win2019"* ) folder="2k19/amd64" ;;
"win2016"* ) folder="2k16/amd64" ;;
"win2012"* ) folder="2k16/amd64" ;;
"win2008"* ) folder="2k8R2/amd64" ;;
"win10arm64"* ) folder="w10/ARM64" ;;
"win11arm64"* ) folder="w11/ARM64" ;;
"winvistax86"* ) folder="2k8/x86" ;;
"winvistax64"* ) folder="2k8/amd64" ;;
esac
if [ -z "$folder" ]; then
warn "no \"$driver\" driver found for \"$DETECTED\" !" && return 0
fi
[ ! -d "$path/$driver/$folder" ] && return 0
if [[ "${id,,}" == "winvista"* ]]; then
[[ "${driver,,}" == "viorng" ]] && return 0
fi
local dest="$path/$target/$driver"
mv "$path/$driver/$folder" "$dest"
return 0
}
addDrivers() {
local file="$1"
local index="$2"
local version="$3"
local msg="Adding drivers to image..."
info "$msg" && html "$msg"
local drivers="$TMP/drivers"
mkdir -p "$drivers"
if ! tar -xf /drivers.txz -C "$drivers" --warning=no-timestamp; then
error "Failed to extract driver!" && return 1
fi
local target="\$WinPEDriver\$"
local dest="$drivers/$target"
mkdir -p "$dest"
wimlib-imagex update "$file" "$index" --command "delete --force --recursive /$target" >/dev/null || true
addDriver "$version" "$drivers" "$target" "qxl"
addDriver "$version" "$drivers" "$target" "viofs"
addDriver "$version" "$drivers" "$target" "sriov"
addDriver "$version" "$drivers" "$target" "smbus"
addDriver "$version" "$drivers" "$target" "qxldod"
addDriver "$version" "$drivers" "$target" "viorng"
addDriver "$version" "$drivers" "$target" "viostor"
addDriver "$version" "$drivers" "$target" "NetKVM"
addDriver "$version" "$drivers" "$target" "Balloon"
addDriver "$version" "$drivers" "$target" "vioscsi"
addDriver "$version" "$drivers" "$target" "pvpanic"
addDriver "$version" "$drivers" "$target" "vioinput"
addDriver "$version" "$drivers" "$target" "viogpudo"
addDriver "$version" "$drivers" "$target" "vioserial"
addDriver "$version" "$drivers" "$target" "qemupciserial"
if ! wimlib-imagex update "$file" "$index" --command "add $dest /$target" >/dev/null; then
return 1
fi
rm -rf "$drivers"
return 0
}
addFolder() {
local src="$1"
local folder="/oem"
[ ! -d "$folder" ] && folder="/OEM"
[ ! -d "$folder" ] && folder="$STORAGE/oem"
[ ! -d "$folder" ] && folder="$STORAGE/OEM"
[ ! -d "$folder" ] && return 0
local msg="Adding OEM folder to image..."
info "$msg" && html "$msg"
local dest="$src/\$OEM\$/\$1/"
mkdir -p "$dest"
! cp -r "$folder" "$dest" && return 1
local file
file=$(find "$dest" -maxdepth 1 -type f -iname install.bat | head -n 1)
[ -f "$file" ] && unix2dos -q "$file"
return 0
}
updateImage() { updateImage() {
local dir="$1" local dir="$1"
@ -667,9 +865,9 @@ updateImage() {
local file="autounattend.xml" local file="autounattend.xml"
local org="${file//.xml/.org}" local org="${file//.xml/.org}"
local dat="${file//.xml/.dat}" local dat="${file//.xml/.dat}"
local desc path src loc xml index result local desc path src wim xml index result
[[ "${DETECTED,,}" == "winxp"* ]] && return 0 skipVersion "${DETECTED,,}" && return 0
if [ ! -s "$asset" ] || [ ! -f "$asset" ]; then if [ ! -s "$asset" ] || [ ! -f "$asset" ]; then
asset="" asset=""
@ -682,29 +880,35 @@ updateImage() {
src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1) src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1)
if [ ! -d "$src" ]; then if [ ! -d "$src" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy" error "failed to locate 'sources' folder in ISO image, $FB" && return 1
warn "failed to locate 'sources' folder in ISO image, $FB" && return 1
fi fi
loc=$(find "$src" -maxdepth 1 -type f -iname boot.wim | head -n 1) wim=$(find "$src" -maxdepth 1 -type f -iname boot.wim | head -n 1)
[ ! -f "$loc" ] && loc=$(find "$src" -maxdepth 1 -type f -iname boot.esd | head -n 1) [ ! -f "$wim" ] && wim=$(find "$src" -maxdepth 1 -type f -iname boot.esd | head -n 1)
if [ ! -f "$loc" ]; then if [ ! -f "$wim" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy" error "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" && return 1
warn "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" && return 1
fi fi
index="1" index="1"
result=$(wimlib-imagex info -xml "$loc" | tr -d '\000') result=$(wimlib-imagex info -xml "$wim" | tr -d '\000')
if [[ "${result^^}" == *"<IMAGE INDEX=\"2\">"* ]]; then if [[ "${result^^}" == *"<IMAGE INDEX=\"2\">"* ]]; then
index="2" index="2"
fi fi
if wimlib-imagex extract "$loc" "$index" "/$file" "--dest-dir=$TMP" >/dev/null 2>&1; then if ! addDrivers "$wim" "$index" "$DETECTED"; then
if ! wimlib-imagex extract "$loc" "$index" "/$dat" "--dest-dir=$TMP" >/dev/null 2>&1; then error "Failed to add drivers to image!" && return 1
if ! wimlib-imagex extract "$loc" "$index" "/$org" "--dest-dir=$TMP" >/dev/null 2>&1; then fi
if ! wimlib-imagex update "$loc" "$index" --command "rename /$file /$org" > /dev/null; then
if ! addFolder "$src"; then
error "Failed to add OEM folder to image!" && return 1
fi
if wimlib-imagex extract "$wim" "$index" "/$file" "--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" "$index" "/$org" "--dest-dir=$TMP" >/dev/null 2>&1; then
if ! wimlib-imagex update "$wim" "$index" --command "rename /$file /$org" > /dev/null; then
warn "failed to backup original answer file ($file)." warn "failed to backup original answer file ($file)."
fi fi
fi fi
@ -723,11 +927,11 @@ updateImage() {
cp "$asset" "$answer" cp "$asset" "$answer"
updateXML "$answer" "$language" updateXML "$answer" "$language"
if ! wimlib-imagex update "$loc" "$index" --command "add $answer /$file" > /dev/null; then if ! wimlib-imagex update "$wim" "$index" --command "add $answer /$file" > /dev/null; then
MANUAL="Y" MANUAL="Y"
warn "failed to add answer file ($xml) to ISO image, $FB" warn "failed to add answer file ($xml) to ISO image, $FB"
else else
wimlib-imagex update "$loc" "$index" --command "add $answer /$dat" > /dev/null || true wimlib-imagex update "$wim" "$index" --command "add $answer /$dat" > /dev/null || true
fi fi
rm -f "$answer" rm -f "$answer"
@ -736,10 +940,10 @@ updateImage() {
if [[ "$MANUAL" == [Yy1]* ]]; then if [[ "$MANUAL" == [Yy1]* ]]; then
wimlib-imagex update "$loc" "$index" --command "delete --force /$file" > /dev/null || true wimlib-imagex update "$wim" "$index" --command "delete --force /$file" > /dev/null || true
if wimlib-imagex extract "$loc" "$index" "/$org" "--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 update "$loc" "$index" --command "add $TMP/$org /$file" > /dev/null; then if ! wimlib-imagex update "$wim" "$index" --command "add $TMP/$org /$file" > /dev/null; then
warn "failed to restore original answer file ($org)." warn "failed to restore original answer file ($org)."
fi fi
fi fi
@ -763,7 +967,7 @@ updateImage() {
return 0 return 0
} }
removeDownload() { removeImage() {
local iso="$1" local iso="$1"
@ -774,43 +978,10 @@ removeDownload() {
return 0 return 0
} }
copyOEM() {
local dir="$1"
local folder="/oem"
local src dest file
[ ! -d "$folder" ] && folder="/OEM"
[ ! -d "$folder" ] && folder="$STORAGE/oem"
[ ! -d "$folder" ] && folder="$STORAGE/OEM"
[ ! -d "$folder" ] && return 0
local msg="Copying OEM folder to image..."
info "$msg" && html "$msg"
src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1)
if [ ! -d "$src" ]; then
error "failed to locate 'sources' folder in ISO image!" && return 1
fi
dest="$src/\$OEM\$/\$1/"
mkdir -p "$dest"
if ! cp -r "$folder" "$dest"; then
error "Failed to copy OEM folder!" && return 1
fi
file=$(find "$dest" -maxdepth 1 -type f -iname install.bat | head -n 1)
[ -f "$file" ] && unix2dos -q "$file"
return 0
}
buildImage() { buildImage() {
local dir="$1" local dir="$1"
local failed="N" 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 size_gb space space_gb desc
@ -841,31 +1012,25 @@ buildImage() {
if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then
if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -V "${LABEL::30}" \ ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -V "${LABEL::30}" \
-udf -boot-info-table -eltorito-alt-boot -eltorito-boot "$EFISYS" -no-emul-boot -allow-limited-size -quiet "$dir" 2> "$log"; then -udf -boot-info-table -eltorito-alt-boot -eltorito-boot "$EFISYS" -no-emul-boot -allow-limited-size -quiet "$dir" 2> "$log" && failed="y"
failed="Y"
fi
else else
if [[ "${DETECTED,,}" != "winxp"* ]]; then case "${DETECTED,,}" in
"win2k"* | "winxp"* )
! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -boot-load-seg 1984 -boot-load-size 4 -c "$cat" -iso-level 2 -J -l -D -N -joliet-long \
-relaxed-filenames -V "${LABEL::30}" -quiet "$dir" 2> "$log" && failed="y" ;;
"win9"* )
! genisoimage -o "$out" -b "$ETFS" -J -r -V "${LABEL::30}" -quiet "$dir" 2> "$log" && failed="y" ;;
* )
! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 2 -J -l -D -N -joliet-long -relaxed-filenames -V "${LABEL::30}" \
-udf -allow-limited-size -quiet "$dir" 2> "$log" && failed="y" ;;
esac
if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 2 -J -l -D -N -joliet-long -relaxed-filenames -V "${LABEL::30}" \
-udf -allow-limited-size -quiet "$dir" 2> "$log"; then
failed="Y"
fi
else
if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -boot-load-seg 1984 -boot-load-size 4 -c "$cat" -iso-level 2 -J -l -D -N -joliet-long \
-relaxed-filenames -V "${LABEL::30}" -quiet "$dir" 2> "$log"; then
failed="Y"
fi
fi
fi fi
if [[ "$failed" != "N" ]]; 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
@ -886,6 +1051,10 @@ bootWindows() {
[[ "${PLATFORM,,}" == "arm64" ]] && VGA="virtio-gpu" [[ "${PLATFORM,,}" == "arm64" ]] && VGA="virtio-gpu"
if [ -s "$STORAGE/windows.type" ] && [ -f "$STORAGE/windows.type" ]; then
DISK_TYPE=$(<"$STORAGE/windows.type")
fi
if [ -s "$STORAGE/windows.mode" ] && [ -f "$STORAGE/windows.mode" ]; then if [ -s "$STORAGE/windows.mode" ] && [ -f "$STORAGE/windows.mode" ]; then
BOOT_MODE=$(<"$STORAGE/windows.mode") BOOT_MODE=$(<"$STORAGE/windows.mode")
if [ -s "$STORAGE/windows.old" ] && [ -f "$STORAGE/windows.old" ]; then if [ -s "$STORAGE/windows.old" ] && [ -f "$STORAGE/windows.old" ]; then
@ -955,28 +1124,24 @@ if ! extractImage "$ISO" "$DIR" "$VERSION"; then
fi fi
if ! detectImage "$DIR" "$VERSION"; then if ! detectImage "$DIR" "$VERSION"; then
abortInstall "$ISO" && return 0 abortInstall "$DIR" "$ISO" && return 0
exit 60 exit 60
fi fi
if ! prepareImage "$ISO" "$DIR"; then if ! prepareImage "$ISO" "$DIR"; then
abortInstall "$ISO" && return 0 abortInstall "$DIR" "$ISO" && return 0
exit 60 exit 66
fi fi
if ! updateImage "$DIR" "$XML" "$LANGUAGE"; then if ! updateImage "$DIR" "$XML" "$LANGUAGE"; then
abortInstall "$ISO" && return 0 abortInstall "$DIR" "$ISO" && return 0
exit 60
fi
if ! removeDownload "$ISO"; then
exit 64
fi
if ! copyOEM "$DIR"; then
exit 63 exit 63
fi fi
if ! removeImage "$ISO"; then
exit 64
fi
if ! buildImage "$DIR"; then if ! buildImage "$DIR"; then
exit 65 exit 65
fi fi

View File

@ -6,12 +6,18 @@ handle_curl_error() {
local error_code="$1" local error_code="$1"
case "$error_code" in case "$error_code" in
1) error "Unsupported protocol!" ;;
2) error "Failed to initialize curl!" ;;
3) error "The URL format is malformed!" ;;
5) error "Failed to resolve address of proxy host!" ;;
6) error "Failed to resolve Microsoft servers! Is there an Internet connection?" ;; 6) error "Failed to resolve Microsoft servers! Is there an Internet connection?" ;;
7) error "Failed to contact Microsoft servers! Is there an Internet connection or is the server down?" ;; 7) error "Failed to contact Microsoft servers! Is there an Internet connection or is the server down?" ;;
8) error "Microsoft servers returned a malformed HTTP response!" ;; 8) error "Microsoft servers returned a malformed HTTP response!" ;;
16) error "A problem was detected in the HTTP2 framing layer!" ;;
22) error "Microsoft servers returned a failing HTTP status code!" ;; 22) error "Microsoft 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 "Ran out of memory during download!" ;; 26) error "Failed to read Windows media from disk!" ;;
27) error "Ran out of memory during download!" ;;
28) error "Connection timed out to Microsoft server!" ;; 28) error "Connection timed out to Microsoft server!" ;;
35) error "SSL connection error from Microsoft server!" ;; 35) error "SSL connection error from Microsoft server!" ;;
36) error "Failed to continue earlier download!" ;; 36) error "Failed to continue earlier download!" ;;
@ -32,22 +38,34 @@ handle_curl_error() {
# https://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html # https://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html
INT) error "Curl was interrupted!" ;; INT) error "Curl was interrupted!" ;;
# There could be other signals but these are most common # There could be other signals but these are most common
SEGV | ABRT ) error "Curl crashed! Failed exploitation attempt? Please report any core dumps to curl developers." ;; SEGV | ABRT ) error "Curl crashed! Please report any core dumps to curl developers." ;;
*) error "Curl terminated due to a fatal signal!" ;; *) error "Curl terminated due to fatal signal $error_code !" ;;
esac esac
esac esac
return 1 return 1
} }
get_agent() {
local user_agent
# Determine approximate latest Firefox release
browser_version="$((124 + ($(date +%s) - 1710892800) / 2419200))"
echo "Mozilla/5.0 (X11; Linux x86_64; rv:${browser_version}.0) Gecko/20100101 Firefox/${browser_version}.0"
return 0
}
download_windows() { download_windows() {
local id="$1" local id="$1"
local lang="$2" local lang="$2"
local desc="$3"
local sku_id="" local sku_id=""
local language="" local language=""
local session_id="" local session_id=""
local browser_version="" local user_agent=""
local windows_version="" local windows_version=""
local iso_download_link="" local iso_download_link=""
local product_edition_id="" local product_edition_id=""
@ -56,12 +74,13 @@ download_windows() {
local language_skuid_table_html="" local language_skuid_table_html=""
case "${id,,}" in case "${id,,}" in
"win11${PLATFORM,,}" ) windows_version="11" ;; "win11x64" ) windows_version="11" ;;
"win10${PLATFORM,,}" ) windows_version="10" ;; "win10x64" ) windows_version="10" ;;
"win81${PLATFORM,,}" ) windows_version="8" ;; "win81x64" ) windows_version="8" ;;
* ) 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)
language=$(getLanguage "$lang" "name") language=$(getLanguage "$lang" "name")
local url="https://www.microsoft.com/en-us/software-download/windows$windows_version" local url="https://www.microsoft.com/en-us/software-download/windows$windows_version"
@ -69,12 +88,8 @@ download_windows() {
8 | 10) url="${url}ISO";; 8 | 10) url="${url}ISO";;
esac esac
# Determine approximate latest Firefox release
browser_version="$((124 + ($(date +%s) - 1710892800) / 2419200))"
local user_agent="Mozilla/5.0 (X11; Linux x86_64; rv:${browser_version}.0) Gecko/20100101 Firefox/${browser_version}.0"
# uuidgen: For MacOS (installed by default) and other systems (e.g. with no /proc) that don't have a kernel interface for generating random UUIDs # uuidgen: For MacOS (installed by default) and other systems (e.g. with no /proc) that don't have a kernel interface for generating random UUIDs
session_id="$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random)" session_id=$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random)
# 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
@ -82,7 +97,7 @@ download_windows() {
# 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}" [[ "$DEBUG" == [Yy1]* ]] && echo " - Parsing download page: ${url}"
iso_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")" || { iso_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") || {
handle_curl_error $? handle_curl_error $?
return $? return $?
} }
@ -90,7 +105,7 @@ download_windows() {
[[ "$DEBUG" == [Yy1]* ]] && echo -n "Getting Product edition ID: " [[ "$DEBUG" == [Yy1]* ]] && echo -n "Getting Product edition ID: "
# tr: Filter for only numerics to prevent HTTP parameter injection # tr: Filter for only numerics to prevent HTTP parameter injection
# head -c was recently added to POSIX: https://austingroupbugs.net/view.php?id=407 # head -c was recently added to POSIX: https://austingroupbugs.net/view.php?id=407
product_edition_id="$(echo "$iso_download_page_html" | grep -Eo '<option value="[0-9]+">Windows' | cut -d '"' -f 2 | head -n 1 | tr -cd '0-9' | head -c 16)" product_edition_id=$(echo "$iso_download_page_html" | 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" [[ "$DEBUG" == [Yy1]* ]] && echo "$product_edition_id"
[[ "$DEBUG" == [Yy1]* ]] && echo "Permit Session ID: $session_id" [[ "$DEBUG" == [Yy1]* ]] && echo "Permit Session ID: $session_id"
@ -110,17 +125,17 @@ download_windows() {
# SKU ID: This specifies the language of the ISO. We always use "English (United States)", however, the SKU for this changes with each Windows release # SKU ID: This specifies the language of the ISO. We always use "English (United States)", however, the SKU for this changes with each Windows release
# We must make this request so our next one will be allowed # We must make this request so our next one will be allowed
# --data "" is required otherwise no "Content-Length" header will be sent causing HTTP response "411 Length Required" # --data "" is required otherwise no "Content-Length" header will be sent causing HTTP response "411 Length Required"
language_skuid_table_html="$(curl --silent --max-time 30 --request POST --user-agent "$user_agent" --data "" --header "Accept:" --max-filesize 10K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=a8f8f489-4c7f-463a-9ca6-5cff94d8d041&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=getskuinformationbyproductedition&sessionId=$session_id&productEditionId=$product_edition_id&sdVersion=2")" || { language_skuid_table_html=$(curl --silent --max-time 30 --request POST --user-agent "$user_agent" --data "" --header "Accept:" --max-filesize 10K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=a8f8f489-4c7f-463a-9ca6-5cff94d8d041&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=getskuinformationbyproductedition&sessionId=$session_id&productEditionId=$product_edition_id&sdVersion=2") || {
handle_curl_error $? handle_curl_error $?
return $? return $?
} }
# tr: Filter for only alphanumerics or "-" to prevent HTTP parameter injection # tr: Filter for only alphanumerics or "-" to prevent HTTP parameter injection
sku_id="$(echo "$language_skuid_table_html" | grep -m 1 ">${language}<" | sed 's/&quot;//g' | cut -d ',' -f 1 | cut -d ':' -f 2 | tr -cd '[:alnum:]-' | head -c 16)" sku_id=$(echo "$language_skuid_table_html" | grep -m 1 ">${language}<" | sed 's/&quot;//g' | cut -d ',' -f 1 | cut -d ':' -f 2 | tr -cd '[:alnum:]-' | head -c 16)
if [ -z "$sku_id" ]; then if [ -z "$sku_id" ]; then
language=$(getLanguage "$lang" "desc") language=$(getLanguage "$lang" "desc")
error "No download for the $language language available!" error "No download in the $language language available for $desc!"
return 1 return 1
fi fi
@ -130,7 +145,7 @@ download_windows() {
# 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)
# --referer: Required by Microsoft servers to allow request # --referer: Required by Microsoft servers to allow request
iso_download_link_html="$(curl --silent --max-time 30 --request POST --user-agent "$user_agent" --data "" --referer "$url" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=6e2a1789-ef16-4f27-a296-74ef7ef5d96b&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=GetProductDownloadLinksBySku&sessionId=$session_id&skuId=$sku_id&language=English&sdVersion=2")" iso_download_link_html=$(curl --silent --max-time 30 --request POST --user-agent "$user_agent" --data "" --referer "$url" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=6e2a1789-ef16-4f27-a296-74ef7ef5d96b&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=GetProductDownloadLinksBySku&sessionId=$session_id&skuId=$sku_id&language=English&sdVersion=2")
if ! [ "$iso_download_link_html" ]; then if ! [ "$iso_download_link_html" ]; 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
@ -146,7 +161,7 @@ download_windows() {
# Filter for 64-bit ISO download URL # Filter for 64-bit ISO download URL
# sed: HTML decode "&" character # sed: HTML decode "&" character
# tr: Filter for only alphanumerics or punctuation # tr: Filter for only alphanumerics or punctuation
iso_download_link="$(echo "$iso_download_link_html" | grep -o "https://software.download.prss.microsoft.com.*IsoX64" | cut -d '"' -f 1 | sed 's/&amp;/\&/g' | tr -cd '[:alnum:][:punct:]')" iso_download_link=$(echo "$iso_download_link_html" | grep -o "https://software.download.prss.microsoft.com.*IsoX64" | cut -d '"' -f 1 | sed 's/&amp;/\&/g' | tr -cd '[:alnum:][:punct:]')
if ! [ "$iso_download_link" ]; then if ! [ "$iso_download_link" ]; then
# 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
@ -162,37 +177,47 @@ download_windows_eval() {
local id="$1" local id="$1"
local lang="$2" local lang="$2"
local desc="$3"
local filter=""
local culture="" local culture=""
local language="" local language=""
local windows_version="" local user_agent=""
local enterprise_type="" local enterprise_type=""
local windows_version=""
case "${id,,}" in case "${id,,}" in
"win11${PLATFORM,,}-enterprise-eval" ) "win11${PLATFORM,,}-enterprise-eval" )
windows_version="windows-11-enterprise" enterprise_type="enterprise"
enterprise_type="enterprise" ;; windows_version="windows-11-enterprise" ;;
"win11${PLATFORM,,}-enterprise-iot-eval" )
enterprise_type="iot"
windows_version="windows-11-iot-enterprise-ltsc" ;;
"win11${PLATFORM,,}-enterprise-ltsc-eval" )
enterprise_type="iot"
windows_version="windows-11-iot-enterprise-ltsc" ;;
"win10${PLATFORM,,}-enterprise-eval" ) "win10${PLATFORM,,}-enterprise-eval" )
windows_version="windows-10-enterprise" enterprise_type="enterprise"
enterprise_type="enterprise" ;; windows_version="windows-10-enterprise" ;;
"win10${PLATFORM,,}-enterprise-ltsc-eval" ) "win10${PLATFORM,,}-enterprise-ltsc-eval" )
windows_version="windows-10-enterprise" enterprise_type="ltsc"
enterprise_type="ltsc" ;; windows_version="windows-10-enterprise" ;;
"win2022-eval" ) "win2022-eval" )
windows_version="windows-server-2022" enterprise_type="server"
enterprise_type="server" ;; windows_version="windows-server-2022" ;;
"win2019-eval" ) "win2019-eval" )
windows_version="windows-server-2019" enterprise_type="server"
enterprise_type="server" ;; windows_version="windows-server-2019" ;;
"win2016-eval" ) "win2016-eval" )
windows_version="windows-server-2016" enterprise_type="server"
enterprise_type="server" ;; windows_version="windows-server-2016" ;;
"win2012r2-eval" ) "win2012r2-eval" )
windows_version="windows-server-2012-r2" enterprise_type="server"
enterprise_type="server" ;; windows_version="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)
culture=$(getLanguage "$lang" "culture") culture=$(getLanguage "$lang" "culture")
local country="${culture#*-}" local country="${culture#*-}"
@ -200,7 +225,7 @@ download_windows_eval() {
local url="https://www.microsoft.com/en-us/evalcenter/download-$windows_version" local url="https://www.microsoft.com/en-us/evalcenter/download-$windows_version"
[[ "$DEBUG" == [Yy1]* ]] && echo "Parsing download page: ${url}" [[ "$DEBUG" == [Yy1]* ]] && echo "Parsing download page: ${url}"
iso_download_page_html="$(curl --silent --max-time 30 --location --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$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") || {
handle_curl_error $? handle_curl_error $?
return $? return $?
} }
@ -212,32 +237,52 @@ download_windows_eval() {
fi fi
[[ "$DEBUG" == [Yy1]* ]] && echo "Getting download link.." [[ "$DEBUG" == [Yy1]* ]] && echo "Getting download link.."
iso_download_links="$(echo "$iso_download_page_html" | grep -o "https://go.microsoft.com/fwlink/p/?LinkID=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country^^}")" || {
if [[ "$enterprise_type" == "iot" ]]; then
filter="https://go.microsoft.com/fwlink/?linkid=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country^^}"
else
filter="https://go.microsoft.com/fwlink/p/?LinkID=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${culture,,}&country=${country^^}"
fi
iso_download_links=$(echo "$iso_download_page_html" | 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!"
else else
language=$(getLanguage "$lang" "desc") language=$(getLanguage "$lang" "desc")
error "No download for the $language language available!" error "No download in the $language language available for $desc!"
fi fi
return 1 return 1
} }
# Limit untrusted size for input validation
iso_download_links="$(echo "$iso_download_links" | head -c 1024)"
case "$enterprise_type" in case "$enterprise_type" in
# Select x64 download link "enterprise" )
"enterprise") iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1) ;; iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1)
# Select x64 LTSC download link ;;
"ltsc") iso_download_link=$(echo "$iso_download_links" | head -n 4 | tail -n 1) ;; "iot" )
*) iso_download_link="$iso_download_links" ;; if [[ "${PLATFORM,,}" == "x64" ]]; then
iso_download_link=$(echo "$iso_download_links" | head -n 1)
fi
if [[ "${PLATFORM,,}" == "arm64" ]]; then
iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1)
fi
;;
"ltsc" )
iso_download_link=$(echo "$iso_download_links" | head -n 4 | tail -n 1)
;;
"server" )
iso_download_link=$(echo "$iso_download_links" | head -n 1)
;;
* )
error "Invalid type specified, value \"$enterprise_type\" is not recognized!" && return 1 ;;
esac esac
[[ "$DEBUG" == [Yy1]* ]] && echo "Found download link: $iso_download_link"
# Follow redirect so proceeding log message is useful # Follow redirect so proceeding log message is useful
# This is a request we make this Fido doesn't # This is a request we make this Fido doesn't
# We don't need to set "--max-filesize" here because this is a HEAD request and the output is to /dev/null anyway # We don't need to set "--max-filesize" here because this is a HEAD request and the output is to /dev/null anyway
iso_download_link="$(curl --silent --max-time 30 --location --output /dev/null --silent --write-out "%{url_effective}" --head --fail --proto =https --tlsv1.2 --http1.1 -- "$iso_download_link")" || { 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") || {
# This should only happen if the Microsoft servers are down # This should only happen if the Microsoft servers are down
handle_curl_error $? handle_curl_error $?
return $? return $?
@ -252,37 +297,46 @@ getWindows() {
local version="$1" local version="$1"
local lang="$2" local lang="$2"
local desc="$3" local desc="$3"
local language
local language edition
language=$(getLanguage "$lang" "desc")
edition=$(printEdition "$version" "$desc")
local msg="Requesting $desc from Microsoft server..." local msg="Requesting $desc from Microsoft server..."
info "$msg" && html "$msg" info "$msg" && html "$msg"
case "${version,,}" in
"win2008r2" | "win81${PLATFORM,,}-enterprise-eval" | "win11${PLATFORM,,}-enterprise-iot-eval" )
if [[ "${lang,,}" != "en" ]] && [[ "${lang,,}" != "en-"* ]]; then
error "No download in the $language language available for $edition!"
MIDO_URL="" && return 1
fi ;;
esac
case "${version,,}" in
"win11${PLATFORM,,}-enterprise-iot-eval" ) ;;
* )
if [[ "${PLATFORM,,}" != "x64" ]]; then
error "No download for the ${PLATFORM^^} platform available for $edition!"
MIDO_URL="" && return 1
fi ;;
esac
case "${version,,}" in case "${version,,}" in
"win81${PLATFORM,,}" | "win10${PLATFORM,,}" | "win11${PLATFORM,,}" ) "win81${PLATFORM,,}" | "win10${PLATFORM,,}" | "win11${PLATFORM,,}" )
download_windows "$version" "$lang" && return 0 download_windows "$version" "$lang" "$edition" && return 0
;; ;;
"win11${PLATFORM,,}-enterprise-eval" ) "win11${PLATFORM,,}-enterprise"* | "win10${PLATFORM,,}-enterprise"* )
download_windows_eval "$version" "$lang" && return 0 download_windows_eval "$version" "$lang" "$edition" && return 0
;;
"win10${PLATFORM,,}-enterprise-eval" | "win10${PLATFORM,,}-enterprise-ltsc-eval" )
download_windows_eval "$version" "$lang" && return 0
;; ;;
"win2022-eval" | "win2019-eval" | "win2016-eval" | "win2012r2-eval" ) "win2022-eval" | "win2019-eval" | "win2016-eval" | "win2012r2-eval" )
download_windows_eval "$version" "$lang" && return 0 download_windows_eval "$version" "$lang" "$edition" && return 0
;; ;;
"win81${PLATFORM,,}-enterprise-eval" ) "win81${PLATFORM,,}-enterprise-eval" )
if [[ "${lang,,}" == "en" ]] || [[ "${lang,,}" == "en-"* ]]; then MIDO_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" && return 0
MIDO_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" && return 0
fi
language=$(getLanguage "$lang" "desc")
error "No download for the $language language available!"
;; ;;
"win2008r2" ) "win2008r2" )
if [[ "${lang,,}" == "en" ]] || [[ "${lang,,}" == "en-"* ]]; then MIDO_URL="https://download.microsoft.com/download/4/1/D/41DEA7E0-B30D-4012-A1E3-F24DC03BA1BB/7601.17514.101119-1850_x64fre_server_eval_en-us-GRMSXEVAL_EN_DVD.iso" && return 0
MIDO_URL="https://download.microsoft.com/download/4/1/D/41DEA7E0-B30D-4012-A1E3-F24DC03BA1BB/7601.17514.101119-1850_x64fre_server_eval_en-us-GRMSXEVAL_EN_DVD.iso" && return 0
fi
language=$(getLanguage "$lang" "desc")
error "No download for the $language language available!"
;; ;;
* ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;; * ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;;
esac esac
@ -385,8 +439,9 @@ getESD() {
size=$(stat -c%s "$dir/$eFile") size=$(stat -c%s "$dir/$eFile")
if ((size<20)); then if ((size<20)); then
desc=$(printEdition "$version" "$desc")
language=$(getLanguage "$lang" "desc") language=$(getLanguage "$lang" "desc")
error "the $language language is not supported by this download method!" && return 1 error "No download in the $language language available for $desc!" && return 1
fi fi
local tag="FilePath" local tag="FilePath"

View File

@ -29,7 +29,12 @@ 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
if ! grep -Fq "BOOTMGR is missing" "$QEMU_PTY"; then 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
if [ -z "$fail" ]; then
info "Windows started succesfully, visit http://localhost:8006/ to view the screen..." info "Windows started succesfully, visit http://localhost:8006/ to view the screen..."
return 0 return 0
fi fi
@ -37,6 +42,11 @@ boot() {
fi fi
error "Timeout while waiting for QEMU to boot the machine!" error "Timeout while waiting for QEMU to boot the machine!"
local pid
pid=$(<"$QEMU_PID")
{ kill -15 "$pid" || true; } 2>/dev/null
return 0 return 0
} }
@ -49,18 +59,14 @@ ready() {
local last local last
local bios="Booting from Hard" local bios="Booting from Hard"
last=$(grep "^Booting.*" "$QEMU_PTY" | tail -1) last=$(grep "^Booting.*" "$QEMU_PTY" | tail -1)
if [[ "${last,,}" == "${bios,,}"* ]]; then [[ "${last,,}" != "${bios,,}"* ]] && return 1
if ! grep -Fq "BOOTMGR is missing" "$QEMU_PTY"; then grep -Fq "No bootable device." "$QEMU_PTY" && return 1
return 0 grep -Fq "BOOTMGR is missing" "$QEMU_PTY" && return 1
fi return 0
fi
return 1
fi fi
local line="\"Windows Boot Manager\"" local line="\"Windows Boot Manager\""
if grep -Fq "$line" "$QEMU_PTY"; then grep -Fq "$line" "$QEMU_PTY" && return 0
return 0
fi
return 1 return 1
} }