1use crate::{AutoLaunch, Result};
2use winreg::enums::RegType::REG_BINARY;
3use winreg::enums::{HKEY_CURRENT_USER, KEY_READ, KEY_SET_VALUE};
4use winreg::{RegKey, RegValue};
5
6static AL_REGKEY: &str = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
7static TASK_MANAGER_OVERRIDE_REGKEY: &str =
8 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\Run";
9static TASK_MANAGER_OVERRIDE_ENABLED_VALUE: [u8; 12] = [
10 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11];
12
13impl AutoLaunch {
15 pub fn new(app_name: &str, app_path: &str, args: &[impl AsRef<str>]) -> AutoLaunch {
24 AutoLaunch {
25 app_name: app_name.into(),
26 app_path: app_path.into(),
27 args: args.iter().map(|s| s.as_ref().to_string()).collect(),
28 }
29 }
30
31 pub fn enable(&self) -> Result<()> {
38 let hkcu = RegKey::predef(HKEY_CURRENT_USER);
39 hkcu.open_subkey_with_flags(AL_REGKEY, KEY_SET_VALUE)?
40 .set_value::<_, _>(
41 &self.app_name,
42 &format!("{} {}", &self.app_path, &self.args.join(" ")),
43 )?;
44
45 if let Ok(reg) = hkcu.open_subkey_with_flags(TASK_MANAGER_OVERRIDE_REGKEY, KEY_SET_VALUE) {
47 reg.set_raw_value(
48 &self.app_name,
49 &RegValue {
50 vtype: REG_BINARY,
51 bytes: TASK_MANAGER_OVERRIDE_ENABLED_VALUE.to_vec(),
52 },
53 )?;
54 }
55
56 Ok(())
57 }
58
59 pub fn disable(&self) -> Result<()> {
66 let hkcu = RegKey::predef(HKEY_CURRENT_USER);
67 hkcu.open_subkey_with_flags(AL_REGKEY, KEY_SET_VALUE)?
68 .delete_value(&self.app_name)?;
69 Ok(())
70 }
71
72 pub fn is_enabled(&self) -> Result<bool> {
74 let hkcu = RegKey::predef(HKEY_CURRENT_USER);
75
76 let al_enabled = hkcu
77 .open_subkey_with_flags(AL_REGKEY, KEY_READ)?
78 .get_value::<String, _>(&self.app_name)
79 .is_ok();
80 let task_manager_enabled = self.task_manager_enabled(hkcu);
81
82 Ok(al_enabled && task_manager_enabled.unwrap_or(true))
83 }
84
85 fn task_manager_enabled(&self, hkcu: RegKey) -> Option<bool> {
86 let task_manager_override_raw_value = hkcu
87 .open_subkey_with_flags(TASK_MANAGER_OVERRIDE_REGKEY, KEY_READ)
88 .ok()?
89 .get_raw_value(&self.app_name)
90 .ok()?;
91 Some(last_eight_bytes_all_zeros(
92 &task_manager_override_raw_value.bytes,
93 )?)
94 }
95}
96
97fn last_eight_bytes_all_zeros(bytes: &[u8]) -> Option<bool> {
98 if bytes.len() < 8 {
99 return None;
100 }
101 Some(bytes.iter().rev().take(8).all(|v| *v == 0u8))
102}