Compare commits
4 commits
8a65313039
...
3b975af2ba
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b975af2ba | |||
| b8fe43fd8f | |||
| 8495d62a06 | |||
| 4a306b56d9 |
5 changed files with 145 additions and 10 deletions
83
config/unattend.xml
Executable file
83
config/unattend.xml
Executable file
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||
<settings pass="disabled">
|
||||
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" language="neutral" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
|
||||
<UserData>
|
||||
<ProductKey>
|
||||
<Key />
|
||||
</ProductKey>
|
||||
</UserData>
|
||||
<RunSynchronous>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassTPMCheck /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassSecureBootCheck /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassRAMCheck /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="specialize">
|
||||
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" language="neutral" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
|
||||
<RunSynchronous>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<Path>reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE /v BypassNRO /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" language="neutral" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
|
||||
<OOBE>
|
||||
<ProtectYourPC>3</ProtectYourPC>
|
||||
</OOBE>
|
||||
<UserAccounts>
|
||||
<LocalAccounts>
|
||||
<LocalAccount wcm:action="add">
|
||||
<Name>NEWUSERNAME</Name>
|
||||
<DisplayName>NEWUSERNAME</DisplayName>
|
||||
<Group>Administrators;Power Users</Group>
|
||||
<Password>
|
||||
<Value>UABhAHMAcwB3AG8AcgBkAA==</Value>
|
||||
<PlainText>false</PlainText>
|
||||
</Password>
|
||||
</LocalAccount>
|
||||
</LocalAccounts>
|
||||
</UserAccounts>
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<CommandLine>net user "NEWUSERNAME" /expires:never</CommandLine>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<CommandLine>net user "NEWUSERNAME" /passwordchg:yes</CommandLine>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<CommandLine>net user "NEWUSERNAME" /passwordreq:no</CommandLine>
|
||||
</SynchronousCommand>
|
||||
</FirstLogonCommands>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" language="neutral" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
|
||||
<InputLocale>00000409</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UILanguageFallback></UILanguageFallback>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-SecureStartup-FilterDriver" processorArchitecture="amd64" language="neutral" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
|
||||
<PreventDeviceEncryption>true</PreventDeviceEncryption>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-EnhancedStorage-Adm" processorArchitecture="amd64" language="neutral" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" publicKeyToken="31bf3856ad364e35" versionScope="nonSxS">
|
||||
<TCGSecurityActivationDisabled>1</TCGSecurityActivationDisabled>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
||||
|
|
@ -38,6 +38,8 @@ use core::{
|
|||
};
|
||||
use std::{
|
||||
env,
|
||||
fs::{File, create_dir_all},
|
||||
io::Write,
|
||||
iter::zip,
|
||||
path::PathBuf,
|
||||
sync::{Arc, Mutex},
|
||||
|
|
@ -51,11 +53,12 @@ use ratatui::{
|
|||
style::Color,
|
||||
};
|
||||
use tokio::sync::mpsc;
|
||||
use tracing::{debug, info};
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
use crate::{
|
||||
components::{set_username::InputUsername, wim_scan::WimScan},
|
||||
state::{ScanType, State},
|
||||
wim::gen_unattend_xml,
|
||||
};
|
||||
|
||||
pub struct App {
|
||||
|
|
@ -195,7 +198,7 @@ impl App {
|
|||
// Get image info
|
||||
let wim_sources = self.state.wim_sources.lock().unwrap();
|
||||
let wim_file = wim_sources.get_file(self.state.wim_file_index.unwrap());
|
||||
let wim_index = format!("{}", self.state.wim_image_index.unwrap());
|
||||
let wim_index = self.state.wim_image_index.unwrap() + 1; // wimapply uses 1-based index
|
||||
|
||||
// Add actions
|
||||
let disk_list = self.state.disk_list.lock().unwrap();
|
||||
|
|
@ -206,7 +209,12 @@ impl App {
|
|||
let dest_path = format!("{}:\\", disk.get_part_letter(num_parts - 1));
|
||||
self.tasks.add(TaskType::CommandWait(
|
||||
wimlib_imagex,
|
||||
vec![String::from("apply"), wim_file.path, wim_index, dest_path],
|
||||
vec![
|
||||
String::from("apply"),
|
||||
wim_file.path,
|
||||
format!("{wim_index}"),
|
||||
dest_path,
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -215,6 +223,8 @@ impl App {
|
|||
popup::Type::Info,
|
||||
String::from("Updating boot configuration"),
|
||||
))?;
|
||||
let wim_sources = self.state.wim_sources.lock().unwrap();
|
||||
let wim_file = wim_sources.get_file(self.state.wim_file_index.unwrap());
|
||||
|
||||
// Get System32 path
|
||||
let system32 = get_system32_path(&self.action_tx);
|
||||
|
|
@ -244,10 +254,15 @@ impl App {
|
|||
}
|
||||
|
||||
// Create boot files
|
||||
let safe_mode = if wim_file.is_backup {
|
||||
boot::SafeMode::Enable
|
||||
} else {
|
||||
boot::SafeMode::Disable
|
||||
};
|
||||
for task in boot::configure_disk(
|
||||
&letter_boot,
|
||||
&letter_os,
|
||||
boot::SafeMode::Enable,
|
||||
safe_mode,
|
||||
&system32,
|
||||
&table_type,
|
||||
) {
|
||||
|
|
@ -265,6 +280,29 @@ impl App {
|
|||
)))?;
|
||||
}
|
||||
}
|
||||
|
||||
// Add unattend.xml (if applicable)
|
||||
if let Some(username) = &self.state.username
|
||||
&& !wim_file.is_backup
|
||||
{
|
||||
let unattend_xml_str = gen_unattend_xml(username);
|
||||
let panther_path = format!("{letter_os}:\\Windows\\Panther");
|
||||
if create_dir_all(PathBuf::from(&panther_path)).is_ok() {
|
||||
if let Ok(mut unattend_xml) =
|
||||
File::create(format!("{panther_path}\\unattend.xml"))
|
||||
{
|
||||
if unattend_xml.write_all(unattend_xml_str.as_bytes()).is_ok() {
|
||||
info!("Created unattend.xml with username set to: {username}");
|
||||
} else {
|
||||
error!("Failed to write to unattend.xml");
|
||||
}
|
||||
} else {
|
||||
error!("Failed to create unattend.xml");
|
||||
}
|
||||
} else {
|
||||
error!("Failed to create Panther dir");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Mode::ScanDisks => {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ pub fn connect_network_share(
|
|||
lpRemoteName: remote_name.as_c_str().as_ptr() as *mut u8,
|
||||
};
|
||||
|
||||
let username = to_cstr(username);
|
||||
let username = format!("{server}\\{username}");
|
||||
let username = to_cstr(&username);
|
||||
let password = to_cstr(password);
|
||||
|
||||
// mount
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ pub fn scan_network_share(config: Config, wim_sources_arc: Arc<Mutex<WimSources>
|
|||
if let Ok(item) = item
|
||||
&& item.file_name().to_string_lossy().ends_with(".wim")
|
||||
&& let Some(path_str) = item.path().to_str()
|
||||
&& let Ok(new_source) = parse_wim_file(path_str, true)
|
||||
&& let Ok(new_source) = parse_wim_file(path_str, false)
|
||||
// Assuming all network sources are installers
|
||||
{
|
||||
wim_files.push(new_source);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ use xml::reader::{EventReader, XmlEvent};
|
|||
|
||||
use core::system::disk::bytes_to_string;
|
||||
|
||||
const UNATTEND_XML: &str = include_str!("../../config/unattend.xml");
|
||||
|
||||
static WIMINFO_EXE: LazyLock<String> = LazyLock::new(|| {
|
||||
let program_files =
|
||||
PathBuf::from(env::var("PROGRAMFILES").expect("Failed to resolve %PROGRAMFILES%"));
|
||||
|
|
@ -176,13 +178,20 @@ impl WimSources {
|
|||
}
|
||||
|
||||
pub fn get_file(&self, index: usize) -> WimFile {
|
||||
let rel_index: usize;
|
||||
let num_local = self.local.len();
|
||||
let index = if index < num_local {
|
||||
index
|
||||
let mut use_local = true;
|
||||
if index < num_local {
|
||||
rel_index = index;
|
||||
} else {
|
||||
index - num_local
|
||||
rel_index = index - num_local;
|
||||
use_local = false;
|
||||
};
|
||||
self.local.get(index).unwrap().clone()
|
||||
if use_local {
|
||||
self.local.get(rel_index).unwrap().clone()
|
||||
} else {
|
||||
self.network.get(rel_index).unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_file_list(&self) -> Vec<WimFile> {
|
||||
|
|
@ -222,6 +231,10 @@ impl WimSources {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn gen_unattend_xml(username: &str) -> String {
|
||||
UNATTEND_XML.replace("NEWUSERNAME", username)
|
||||
}
|
||||
|
||||
fn get_wim_xml(wim_file: &str) -> std::io::Result<File> {
|
||||
let tmp_file = NamedTempFile::new()?;
|
||||
let _ = Command::new(&*WIMINFO_EXE)
|
||||
|
|
|
|||
Loading…
Reference in a new issue