|
1 | 1 | use core::result::Result as CResult; |
2 | | -use std::{ |
3 | | - future::Future, |
4 | | - io::{ErrorKind, Write}, |
5 | | - path::Path, |
6 | | - process::{Child, ExitStatus}, |
7 | | -}; |
| 2 | +use std::future::Future; |
| 3 | +use std::io::{ErrorKind, Write}; |
| 4 | +use std::path::Path; |
| 5 | +use std::process::{Child, ExitStatus}; |
8 | 6 |
|
9 | 7 | use async_trait::async_trait; |
10 | 8 | use error_stack::{bail, IntoReport, Result, ResultExt}; |
11 | 9 | use lazy_static::lazy_static; |
12 | 10 | use regex::Regex; |
13 | 11 | use serde::Deserialize; |
14 | 12 | use tokio_util::sync::CancellationToken; |
15 | | -use winreg::{enums::HKEY_LOCAL_MACHINE, RegKey}; |
| 13 | +use winreg::enums::HKEY_LOCAL_MACHINE; |
| 14 | +use winreg::RegKey; |
16 | 15 | use wmi::{COMLibrary, WMIConnection, WMIError}; |
17 | 16 |
|
18 | | -use super::{ |
19 | | - create_dump_file, Dumper, IntoModuleReport, IntoUninstallReport, ModuleError, ModuleMetadata, |
20 | | - ModuleRunInfo, ModuleStrategy, ToUninstall, UninstallError, |
21 | | -}; |
22 | | -use crate::{ |
23 | | - cleanup_modules::get_path_to_dump, |
24 | | - services::{ |
25 | | - self, identifiers, regex_cache, terminal, |
26 | | - windows::{enumerate_driver_packages, DriverPackage}, |
27 | | - }, |
28 | | - State, |
29 | | -}; |
| 17 | +use super::*; |
| 18 | + |
| 19 | +use crate::services; |
| 20 | +use crate::services::identifiers; |
| 21 | +use crate::services::regex_cache; |
| 22 | +use crate::services::terminal; |
| 23 | +use crate::services::windows::{enumerate_driver_packages, DriverPackage}; |
| 24 | +use crate::State; |
30 | 25 |
|
31 | 26 | const MODULE_NAME: &str = "Driver Package Cleanup"; |
32 | 27 | const MODULE_CLI: &str = "driver-package-cleanup"; |
33 | 28 | const IDENTIFIER: &str = "driver_package_identifiers.json"; |
34 | 29 |
|
| 30 | +#[derive(Deserialize, Debug)] |
| 31 | +enum UninstallMethod { |
| 32 | + Normal, |
| 33 | + Deferred, |
| 34 | + RegistryOnly, |
| 35 | +} |
| 36 | + |
35 | 37 | #[derive(Default)] |
36 | 38 | pub struct DriverPackageCleanupModule { |
37 | 39 | objects_to_uninstall: Vec<DriverPackageToUninstall>, |
@@ -68,7 +70,6 @@ impl ModuleStrategy for DriverPackageCleanupModule { |
68 | 70 | type ToUninstall = DriverPackageToUninstall; |
69 | 71 |
|
70 | 72 | async fn initialize(&mut self, state: &State) -> Result<(), ModuleError> { |
71 | | - let _name = self.name().to_string(); |
72 | 73 | let resource = identifiers::get_resource(IDENTIFIER, state) |
73 | 74 | .await |
74 | 75 | .into_module_report(MODULE_NAME)?; |
@@ -119,26 +120,28 @@ impl ModuleStrategy for DriverPackageCleanupModule { |
119 | 120 | } |
120 | 121 | } |
121 | 122 |
|
122 | | -fn uninstall_registry_only( |
123 | | - object: DriverPackage, |
124 | | - to_uninstall: &DriverPackageToUninstall, |
125 | | -) -> Result<(), UninstallError> { |
126 | | - let key_path = Path::new(object.key_name()); |
127 | | - let key_parent = key_path.parent().unwrap(); |
128 | | - let key_name = key_path.file_name().unwrap(); |
129 | | - let flags = winreg::enums::KEY_WRITE; |
| 123 | +#[derive(Deserialize, Debug)] |
| 124 | +#[serde(deny_unknown_fields)] |
| 125 | +pub struct DriverPackageToUninstall { |
| 126 | + friendly_name: String, |
| 127 | + display_name: Option<String>, |
| 128 | + display_version: Option<String>, |
| 129 | + publisher: Option<String>, |
| 130 | + uninstall_method: UninstallMethod, |
| 131 | +} |
130 | 132 |
|
131 | | - let uninstall_key = RegKey::predef(HKEY_LOCAL_MACHINE) |
132 | | - .open_subkey_with_flags(key_parent, flags) |
133 | | - .into_report() |
134 | | - .attach_printable_lazy(|| key_parent.to_string_lossy().to_string()) |
135 | | - .into_uninstall_report(to_uninstall)?; |
| 133 | +impl ToUninstall<DriverPackage> for DriverPackageToUninstall { |
| 134 | + fn matches(&self, other: &DriverPackage) -> bool { |
| 135 | + regex_cache::cached_match(other.display_name(), self.display_name.as_deref()) |
| 136 | + && regex_cache::cached_match(other.display_version(), self.display_version.as_deref()) |
| 137 | + && regex_cache::cached_match(other.publisher(), self.publisher.as_deref()) |
| 138 | + } |
| 139 | +} |
136 | 140 |
|
137 | | - uninstall_key |
138 | | - .delete_subkey_all(key_name) |
139 | | - .into_report() |
140 | | - .attach_printable_lazy(|| key_path.to_string_lossy().to_string()) |
141 | | - .into_uninstall_report(to_uninstall) |
| 141 | +impl std::fmt::Display for DriverPackageToUninstall { |
| 142 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 143 | + write!(f, "{}", self.friendly_name) |
| 144 | + } |
142 | 145 | } |
143 | 146 |
|
144 | 147 | #[derive(Default)] |
@@ -179,6 +182,22 @@ impl Dumper for DriverPackageDumper { |
179 | 182 | } |
180 | 183 | } |
181 | 184 |
|
| 185 | +#[derive(Deserialize, Debug)] |
| 186 | +#[serde(rename = "Win32_Process")] |
| 187 | +#[serde(rename_all = "PascalCase")] |
| 188 | +struct ProcessInfo { |
| 189 | + process_id: u32, |
| 190 | + parent_process_id: u32, |
| 191 | + command_line: Option<String>, |
| 192 | +} |
| 193 | + |
| 194 | +impl ProcessInfo { |
| 195 | + fn query() -> CResult<Vec<Self>, WMIError> { |
| 196 | + let wmi_con = WMIConnection::new(COMLibrary::new()?)?; |
| 197 | + wmi_con.query() |
| 198 | + } |
| 199 | +} |
| 200 | + |
182 | 201 | fn is_of_interest(driver_package: &DriverPackage) -> bool { |
183 | 202 | use crate::services::interest::is_of_interest_iter as candidate_iter; |
184 | 203 | driver_package.display_name().is_some() |
@@ -287,7 +306,7 @@ async fn uninstall_deferred( |
287 | 306 |
|
288 | 307 | tokio::time::sleep(std::time::Duration::from_secs_f32(0.5)).await; |
289 | 308 |
|
290 | | - let processes = get_process_infos().unwrap(); |
| 309 | + let processes = ProcessInfo::query().unwrap(); |
291 | 310 | let process_delegate = processes |
292 | 311 | .iter() |
293 | 312 | .filter(|p| p.parent_process_id == id) |
@@ -353,49 +372,26 @@ async fn wait_for_process_async(child: Child) -> CResult<ExitStatus, std::io::Er |
353 | 372 | .unwrap() |
354 | 373 | } |
355 | 374 |
|
356 | | -#[derive(Deserialize, Debug)] |
357 | | -enum UninstallMethod { |
358 | | - Normal, |
359 | | - Deferred, |
360 | | - RegistryOnly, |
361 | | -} |
362 | | - |
363 | | -#[derive(Deserialize, Debug)] |
364 | | -#[serde(deny_unknown_fields)] |
365 | | -pub struct DriverPackageToUninstall { |
366 | | - friendly_name: String, |
367 | | - display_name: Option<String>, |
368 | | - display_version: Option<String>, |
369 | | - publisher: Option<String>, |
370 | | - uninstall_method: UninstallMethod, |
371 | | -} |
372 | | - |
373 | | -impl ToUninstall<DriverPackage> for DriverPackageToUninstall { |
374 | | - fn matches(&self, other: &DriverPackage) -> bool { |
375 | | - regex_cache::cached_match(other.display_name(), self.display_name.as_deref()) |
376 | | - && regex_cache::cached_match(other.display_version(), self.display_version.as_deref()) |
377 | | - && regex_cache::cached_match(other.publisher(), self.publisher.as_deref()) |
378 | | - } |
379 | | -} |
380 | | - |
381 | | -impl std::fmt::Display for DriverPackageToUninstall { |
382 | | - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
383 | | - write!(f, "{}", self.friendly_name) |
384 | | - } |
385 | | -} |
| 375 | +fn uninstall_registry_only( |
| 376 | + object: DriverPackage, |
| 377 | + to_uninstall: &DriverPackageToUninstall, |
| 378 | +) -> Result<(), UninstallError> { |
| 379 | + let key_path = Path::new(object.key_name()); |
| 380 | + let key_parent = key_path.parent().unwrap(); |
| 381 | + let key_name = key_path.file_name().unwrap(); |
| 382 | + let flags = winreg::enums::KEY_WRITE; |
386 | 383 |
|
387 | | -#[derive(Deserialize, Debug)] |
388 | | -#[serde(rename = "Win32_Process")] |
389 | | -#[serde(rename_all = "PascalCase")] |
390 | | -struct ProcessInfo { |
391 | | - process_id: u32, |
392 | | - parent_process_id: u32, |
393 | | - command_line: Option<String>, |
394 | | -} |
| 384 | + let uninstall_key = RegKey::predef(HKEY_LOCAL_MACHINE) |
| 385 | + .open_subkey_with_flags(key_parent, flags) |
| 386 | + .into_report() |
| 387 | + .attach_printable_lazy(|| key_parent.to_string_lossy().to_string()) |
| 388 | + .into_uninstall_report(to_uninstall)?; |
395 | 389 |
|
396 | | -fn get_process_infos() -> CResult<Vec<ProcessInfo>, WMIError> { |
397 | | - let wmi_con = WMIConnection::new(COMLibrary::new()?)?; |
398 | | - wmi_con.query() |
| 390 | + uninstall_key |
| 391 | + .delete_subkey_all(key_name) |
| 392 | + .into_report() |
| 393 | + .attach_printable_lazy(|| key_path.to_string_lossy().to_string()) |
| 394 | + .into_uninstall_report(to_uninstall) |
399 | 395 | } |
400 | 396 |
|
401 | 397 | fn to_command(command: &str) -> std::process::Command { |
|
0 commit comments