diff --git a/boot_diags/src/app.rs b/boot_diags/src/app.rs index 11e3358..191ca66 100644 --- a/boot_diags/src/app.rs +++ b/boot_diags/src/app.rs @@ -31,7 +31,6 @@ use core::{ system::{ boot::{self, SafeMode, configure_disk}, cpu::get_cpu_name, - disk::PartitionTableType, drivers, }, tasks::{Task, TaskResult, TaskType, Tasks}, @@ -40,7 +39,6 @@ use core::{ use std::{ env, iter::zip, - path::PathBuf, sync::{Arc, Mutex}, }; @@ -54,9 +52,12 @@ use ratatui::{ use tokio::sync::mpsc; use tracing::{debug, info}; -use crate::diags::{ - DiagGroup, Type as DiagType, get_diag_type, parse_bcd, parse_bitlocker, parse_chkdsk, - parse_dism, parse_registry_hives, parse_system_files, +use crate::{ + diags::{ + DiagGroup, Type as DiagType, get_diag_type, parse_bcd, parse_bitlocker, parse_chkdsk, + parse_dism, parse_registry_hives, parse_system_files, + }, + scan, }; pub struct App { @@ -204,7 +205,13 @@ impl App { popup::Type::Info, String::from("Gathering info..."), ))?; - self.queue_boot_scan_tasks()?; + scan::queue_boot_scan_tasks( + self.action_tx.clone(), + &self.clone, + self.diag_groups.clone(), + self.system32.clone(), + &mut self.tasks, + )?; } Mode::InjectDrivers | Mode::InstallDrivers => self.clone.scan_drivers(), Mode::Process => { @@ -546,159 +553,6 @@ impl App { Ok(()) } - fn queue_boot_scan_tasks(&mut self) -> Result<()> { - if let Ok(mut diag_groups) = self.diag_groups.lock() { - diag_groups.clear(); - } - let disk_list = self.clone.disk_list.lock().unwrap(); - if let Some(disk_index) = self.clone.disk_index_dest { - if let Some(disk) = disk_list.get(disk_index) { - let table_type = disk.part_type.clone(); - let letter_boot = disk.get_part_letter(self.clone.part_index_boot.unwrap()); - let letter_os = disk.get_part_letter(self.clone.part_index_os.unwrap()); - - // Safety check - if letter_os.is_empty() { - if letter_boot.is_empty() { - self.action_tx.send(Action::Error(String::from( - "ERROR\n\n\nFailed to get drive letters for the boot and OS volumes", - )))?; - } else { - self.action_tx.send(Action::Error(String::from( - "ERROR\n\n\nFailed to get drive letter for the OS volume", - )))?; - } - return Ok(()); - } - - // BCD - if !letter_boot.is_empty() { - self.tasks.add_group( - DiagType::BootConfigData.to_string().as_str(), - vec![TaskType::CommandWait( - PathBuf::from(format!("{}\\bcdedit.exe", &self.system32)), - vec![ - String::from("/store"), - format!( - "{letter_boot}:{}\\Boot\\BCD", - if table_type == PartitionTableType::Guid { - "\\EFI\\Microsoft" - } else { - "" - } - ), - String::from("/enum"), - ], - )], - ); - } - - // Bitlocker - self.tasks.add_group( - DiagType::Bitlocker.to_string().as_str(), - vec![ - TaskType::CommandWait( - PathBuf::from(format!("{}\\manage-bde.exe", &self.system32)), - vec![String::from("-status"), format!("{letter_os}:")], - ), - TaskType::CommandWait( - PathBuf::from(format!("{}\\manage-bde.exe", &self.system32)), - vec![ - String::from("-protectors"), - String::from("-get"), - format!("{letter_os}:"), - ], - ), - ], - ); - - // Filesystem Health - self.tasks.add_group( - DiagType::CheckDisk.to_string().as_str(), - vec![TaskType::CommandWait( - PathBuf::from(format!("{}\\chkdsk.exe", &self.system32)), - vec![format!("{letter_os}:")], - )], - ); - - // DISM Health - self.tasks.add_group( - DiagType::ComponentStore.to_string().as_str(), - vec![TaskType::CommandWait( - PathBuf::from(format!("{}\\dism.exe", &self.system32)), - vec![ - format!("/Image:{letter_os}:"), - String::from("/Cleanup-Image"), - String::from("/ScanHealth"), - ], - )], - ); - - // Critical Files/Folders - let paths: Vec = [ - // Files/Folders - "Users", - "Program Files", - "Program Files (x86)", - "ProgramData", - "Windows\\System32\\config", - ] - .iter() - .map(|s| PathBuf::from(format!("{letter_os}:\\{s}"))) - .collect(); - self.tasks.add_group( - DiagType::SystemFiles.to_string().as_str(), - vec![TaskType::TestPaths(paths)], - ); - - // Registry - self.tasks.add_group( - DiagType::Registry.to_string().as_str(), - vec![ - TaskType::CommandWait( - PathBuf::from(format!("{}\\reg.exe", &self.system32)), - vec![ - String::from("load"), - String::from("HKLM\\TmpSoftware"), - format!("{letter_os}:\\Windows\\System32\\config\\SOFTWARE"), - ], - ), - TaskType::CommandWait( - PathBuf::from(format!("{}\\reg.exe", &self.system32)), - vec![ - String::from("load"), - String::from("HKLM\\TmpSystem"), - format!("{letter_os}:\\Windows\\System32\\config\\SYSTEM"), - ], - ), - TaskType::CommandWait( - PathBuf::from(format!("{}\\reg.exe", &self.system32)), - vec![ - String::from("load"), - String::from("HKU\\TmpDefault"), - format!("{letter_os}:\\Windows\\System32\\config\\DEFAULT"), - ], - ), - TaskType::CommandWait( - PathBuf::from(format!("{}\\reg.exe", &self.system32)), - vec![String::from("unload"), String::from("HKLM\\TmpSoftware")], - ), - TaskType::CommandWait( - PathBuf::from(format!("{}\\reg.exe", &self.system32)), - vec![String::from("unload"), String::from("HKLM\\TmpSystem")], - ), - TaskType::CommandWait( - PathBuf::from(format!("{}\\reg.exe", &self.system32)), - vec![String::from("unload"), String::from("HKU\\TmpDefault")], - ), - ], - ); - self.tasks.add(TaskType::Sleep); // NOTE: DELETEME - } - } - Ok(()) - } - fn render(&mut self, tui: &mut Tui) -> Result<()> { tui.draw(|frame| { if let [header, _body, footer, left, right, popup, progress, results] = diff --git a/boot_diags/src/main.rs b/boot_diags/src/main.rs index ac77131..b71a458 100644 --- a/boot_diags/src/main.rs +++ b/boot_diags/src/main.rs @@ -21,6 +21,7 @@ use crate::app::App; mod app; mod components; mod diags; +mod scan; #[tokio::main] async fn main() -> Result<()> { diff --git a/boot_diags/src/scan.rs b/boot_diags/src/scan.rs new file mode 100644 index 0000000..56112f9 --- /dev/null +++ b/boot_diags/src/scan.rs @@ -0,0 +1,169 @@ +use color_eyre::Result; +use core::state::CloneSettings; +use core::system::disk::PartitionTableType; +use core::tasks::Tasks; +use core::{action::Action, tasks::TaskType}; +use std::path::PathBuf; +use std::sync::{Arc, Mutex}; +use tokio::sync::mpsc; + +use crate::diags::{DiagGroup, Type as DiagType}; + +pub fn queue_boot_scan_tasks( + action_tx: mpsc::UnboundedSender, + clone: &CloneSettings, + diag_groups: Arc>>, + system32: String, + tasks: &mut Tasks, +) -> Result<()> { + if let Ok(mut diag_groups) = diag_groups.lock() { + diag_groups.clear(); + } + let disk_list = clone.disk_list.lock().unwrap(); + if let Some(disk_index) = clone.disk_index_dest { + if let Some(disk) = disk_list.get(disk_index) { + let table_type = disk.part_type.clone(); + let letter_boot = disk.get_part_letter(clone.part_index_boot.unwrap()); + let letter_os = disk.get_part_letter(clone.part_index_os.unwrap()); + + // Safety check + if letter_os.is_empty() { + if letter_boot.is_empty() { + action_tx.send(Action::Error(String::from( + "ERROR\n\n\nFailed to get drive letters for the boot and OS volumes", + )))?; + } else { + action_tx.send(Action::Error(String::from( + "ERROR\n\n\nFailed to get drive letter for the OS volume", + )))?; + } + return Ok(()); + } + + // BCD + if !letter_boot.is_empty() { + tasks.add_group( + DiagType::BootConfigData.to_string().as_str(), + vec![TaskType::CommandWait( + PathBuf::from(format!("{}\\bcdedit.exe", &system32)), + vec![ + String::from("/store"), + format!( + "{letter_boot}:{}\\Boot\\BCD", + if table_type == PartitionTableType::Guid { + "\\EFI\\Microsoft" + } else { + "" + } + ), + String::from("/enum"), + ], + )], + ); + } + + // Bitlocker + tasks.add_group( + DiagType::Bitlocker.to_string().as_str(), + vec![ + TaskType::CommandWait( + PathBuf::from(format!("{}\\manage-bde.exe", &system32)), + vec![String::from("-status"), format!("{letter_os}:")], + ), + TaskType::CommandWait( + PathBuf::from(format!("{}\\manage-bde.exe", &system32)), + vec![ + String::from("-protectors"), + String::from("-get"), + format!("{letter_os}:"), + ], + ), + ], + ); + + // Filesystem Health + tasks.add_group( + DiagType::CheckDisk.to_string().as_str(), + vec![TaskType::CommandWait( + PathBuf::from(format!("{}\\chkdsk.exe", &system32)), + vec![format!("{letter_os}:")], + )], + ); + + // DISM Health + tasks.add_group( + DiagType::ComponentStore.to_string().as_str(), + vec![TaskType::CommandWait( + PathBuf::from(format!("{}\\dism.exe", &system32)), + vec![ + format!("/Image:{letter_os}:"), + String::from("/Cleanup-Image"), + String::from("/ScanHealth"), + ], + )], + ); + + // Critical Files/Folders + let paths: Vec = [ + // Files/Folders + "Users", + "Program Files", + "Program Files (x86)", + "ProgramData", + "Windows\\System32\\config", + ] + .iter() + .map(|s| PathBuf::from(format!("{letter_os}:\\{s}"))) + .collect(); + tasks.add_group( + DiagType::SystemFiles.to_string().as_str(), + vec![TaskType::TestPaths(paths)], + ); + + // Registry + tasks.add_group( + DiagType::Registry.to_string().as_str(), + vec![ + TaskType::CommandWait( + PathBuf::from(format!("{}\\reg.exe", &system32)), + vec![ + String::from("load"), + String::from("HKLM\\TmpSoftware"), + format!("{letter_os}:\\Windows\\System32\\config\\SOFTWARE"), + ], + ), + TaskType::CommandWait( + PathBuf::from(format!("{}\\reg.exe", &system32)), + vec![ + String::from("load"), + String::from("HKLM\\TmpSystem"), + format!("{letter_os}:\\Windows\\System32\\config\\SYSTEM"), + ], + ), + TaskType::CommandWait( + PathBuf::from(format!("{}\\reg.exe", &system32)), + vec![ + String::from("load"), + String::from("HKU\\TmpDefault"), + format!("{letter_os}:\\Windows\\System32\\config\\DEFAULT"), + ], + ), + TaskType::CommandWait( + PathBuf::from(format!("{}\\reg.exe", &system32)), + vec![String::from("unload"), String::from("HKLM\\TmpSoftware")], + ), + TaskType::CommandWait( + PathBuf::from(format!("{}\\reg.exe", &system32)), + vec![String::from("unload"), String::from("HKLM\\TmpSystem")], + ), + TaskType::CommandWait( + PathBuf::from(format!("{}\\reg.exe", &system32)), + vec![String::from("unload"), String::from("HKU\\TmpDefault")], + ), + ], + ); + tasks.add(TaskType::Sleep); // NOTE: DELETEME + } + } + Ok(()) +}