Skip to content

Commit

Permalink
fix(windows): mistach os error type
Browse files Browse the repository at this point in the history
chore: up

chore: up

chore: up

chore: up

chore: up
  • Loading branch information
greenhat616 committed Nov 24, 2024
1 parent f2277ad commit 729d542
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 72 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ thiserror = "2"
dirs = "5.0.1"

[target.'cfg(windows)'.dependencies]
windows-registry = { version = "0.3.0", features = ["std"] }
windows-registry = "0.3.0"
windows-result = "0.2.0"
15 changes: 9 additions & 6 deletions src/linux.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use crate::AutoLaunch;
use crate::Result;
use std::fs;
use std::io::Write;
use std::path::PathBuf;
use crate::{AutoLaunch, Result};
use std::{fs, io::Write, path::PathBuf};

/// Linux implement
impl AutoLaunch {
Expand Down Expand Up @@ -47,7 +44,13 @@ impl AutoLaunch {

let dir = get_dir();
if !dir.exists() {
fs::create_dir(&dir)?;
fs::create_dir_all(&dir).or_else(|e| {
if e.kind() == std::io::ErrorKind::AlreadyExists {
Ok(())
} else {
Err(e)
}
})?;
}
let mut file = fs::OpenOptions::new()
.write(true)
Expand Down
107 changes: 58 additions & 49 deletions src/windows.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{AutoLaunch, Result};
use windows_registry::{Key, CURRENT_USER, LOCAL_MACHINE};
use windows_result::HRESULT;

const ADMIN_AL_REGKEY: &str = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run";
const AL_REGKEY: &str = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
Expand All @@ -10,6 +11,8 @@ const TASK_MANAGER_OVERRIDE_REGKEY: &str =
const TASK_MANAGER_OVERRIDE_ENABLED_VALUE: [u8; 12] = [
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
const E_ACCESSDENIED: HRESULT = HRESULT::from_win32(0x80070005_u32);
const E_FILENOTFOUND: HRESULT = HRESULT::from_win32(0x80070002_u32);

/// Windows implement
impl AutoLaunch {
Expand All @@ -36,21 +39,25 @@ impl AutoLaunch {
/// - failed to open the registry key
/// - failed to set value
pub fn enable(&self) -> Result<()> {
self.enable_as_admin().or_else(|e| match e.kind() {
std::io::ErrorKind::PermissionDenied => {
self.enable_as_current_user().map_err(Into::into)
}
_ => Err(e.into()),
})
self.enable_as_admin()
.or_else(|e| {
if e.code() == E_ACCESSDENIED {
self.enable_as_current_user()
} else {
Err(e)
}
})
.map_err(std::io::Error::from)?;
Ok(())
}

fn enable_as_admin(&self) -> std::io::Result<()> {
LOCAL_MACHINE.open(ADMIN_AL_REGKEY)?.set_string(
fn enable_as_admin(&self) -> windows_registry::Result<()> {
LOCAL_MACHINE.create(ADMIN_AL_REGKEY)?.set_string(
&self.app_name,
&format!("{} {}", &self.app_path, &self.args.join(" ")),
)?;
// this key maybe not found
if let Ok(key) = LOCAL_MACHINE.open(ADMIN_TASK_MANAGER_OVERRIDE_REGKEY) {
if let Ok(key) = LOCAL_MACHINE.create(ADMIN_TASK_MANAGER_OVERRIDE_REGKEY) {
key.set_bytes(
&self.app_name,
windows_registry::Type::Bytes,
Expand All @@ -60,21 +67,13 @@ impl AutoLaunch {
Ok(())
}

fn enable_as_current_user(&self) -> std::io::Result<()> {
CURRENT_USER
.open(AL_REGKEY)
.map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("failed to open {AL_REGKEY}: {}", e),
)
})?
.set_string(
&self.app_name,
&format!("{} {}", &self.app_path, &self.args.join(" ")),
)?;
fn enable_as_current_user(&self) -> windows_registry::Result<()> {
CURRENT_USER.create(AL_REGKEY)?.set_string(
&self.app_name,
&format!("{} {}", &self.app_path, &self.args.join(" ")),
)?;
// this key maybe not found
if let Ok(key) = CURRENT_USER.open(TASK_MANAGER_OVERRIDE_REGKEY) {
if let Ok(key) = CURRENT_USER.create(TASK_MANAGER_OVERRIDE_REGKEY) {
key.set_bytes(
&self.app_name,
windows_registry::Type::Bytes,
Expand All @@ -91,63 +90,73 @@ impl AutoLaunch {
/// - failed to open the registry key
/// - failed to delete value
pub fn disable(&self) -> Result<()> {
self.disable_as_admin().or_else(|e| match e.kind() {
std::io::ErrorKind::PermissionDenied => {
self.disable_as_current_user().map_err(Into::into)
}
_ => Err(e.into()),
})
self.disable_as_admin()
.or_else(|e| {
if e.code() == E_ACCESSDENIED {
self.disable_as_current_user()
} else {
Err(e)
}
})
.map_err(std::io::Error::from)?;
Ok(())
}

fn disable_as_admin(&self) -> std::io::Result<()> {
fn disable_as_admin(&self) -> windows_registry::Result<()> {
LOCAL_MACHINE
.open(ADMIN_AL_REGKEY)?
.create(ADMIN_AL_REGKEY)?
.remove_value(&self.app_name)?;
Ok(())
}

fn disable_as_current_user(&self) -> std::io::Result<()> {
CURRENT_USER.open(AL_REGKEY)?.remove_value(&self.app_name)?;
fn disable_as_current_user(&self) -> windows_registry::Result<()> {
CURRENT_USER
.create(AL_REGKEY)?
.remove_value(&self.app_name)?;
Ok(())
}

/// Check whether the AutoLaunch setting is enabled
pub fn is_enabled(&self) -> Result<bool> {
match self.is_enabled_as_admin() {
Ok(false) => self.is_enabled_as_current_user().map_err(Into::into),
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
self.is_enabled_as_current_user().map_err(Into::into)
}
let res = match self.is_enabled_as_admin() {
Ok(false) => self.is_enabled_as_current_user(),
Err(e) if e.code() == E_ACCESSDENIED => self.is_enabled_as_current_user(),
Ok(enabled) => Ok(enabled),
Err(e) => Err(e.into()),
Err(e) => Err(e),
}
.map_err(std::io::Error::from)?;
Ok(res)
}

fn is_enabled_as_admin(&self) -> std::io::Result<bool> {
fn is_enabled_as_admin(&self) -> windows_registry::Result<bool> {
let adm_enabled = LOCAL_MACHINE
.open(ADMIN_AL_REGKEY)?
.get_string(&self.app_name)
.map(|_| true)
.map_err(std::io::Error::from)
.or_else(|e| match e.kind() {
std::io::ErrorKind::NotFound => Ok(false),
_ => Err(e),
.or_else(|e| {
if e.code() == E_FILENOTFOUND {
Ok(false)
} else {
Err(e)
}
})?;
let task_manager_enabled = self
.task_manager_enabled(LOCAL_MACHINE, ADMIN_TASK_MANAGER_OVERRIDE_REGKEY)
.unwrap_or(true);
Ok(adm_enabled && task_manager_enabled)
}

fn is_enabled_as_current_user(&self) -> std::io::Result<bool> {
fn is_enabled_as_current_user(&self) -> windows_registry::Result<bool> {
let al_enabled = CURRENT_USER
.open(AL_REGKEY)?
.get_string(&self.app_name)
.map(|_| true)
.map_err(std::io::Error::from)
.or_else(|e| match e.kind() {
std::io::ErrorKind::NotFound => Ok(false),
_ => Err(e),
.or_else(|e| {
if e.code() == E_FILENOTFOUND {
Ok(false)
} else {
Err(e)
}
})?;
let task_manager_enabled = self
.task_manager_enabled(CURRENT_USER, TASK_MANAGER_OVERRIDE_REGKEY)
Expand Down
31 changes: 15 additions & 16 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ mod unit_test {
assert!(AutoLaunch::is_support());
}

// There will be conflicts with other test cases on macos
#[cfg(not(target_os = "macos"))]
#[test]
fn test_builder() {
Expand Down Expand Up @@ -141,29 +140,29 @@ mod windows_unit_test {

assert_eq!(auto.get_app_name(), app_name);

assert!(auto.enable().is_ok());
auto.enable().unwrap();
assert!(auto.is_enabled().unwrap());
assert!(auto.disable().is_ok());
auto.disable().unwrap();
assert!(!auto.is_enabled().unwrap());

if get_task_manager_override_subkey().is_some() {
// windows can enable after disabled by task manager
assert!(auto.enable().is_ok());
auto.enable().unwrap();
assert!(auto.is_enabled().unwrap());
set_task_manager_override_value(app_name, TASK_MANAGER_OVERRIDE_TEST_DATA[0].1);
set_admin_task_manager_override_value(app_name, TASK_MANAGER_OVERRIDE_TEST_DATA[0].1)
.unwrap_or(());

assert!(!auto.is_enabled().unwrap());

assert!(auto.enable().is_ok());
auto.enable().unwrap();
assert!(auto.is_enabled().unwrap());

// test windows task manager overrides
delete_task_manager_override_value(app_name).ok(); // Ensure previous test runs are cleaned up

assert_eq!(auto.get_app_name(), app_name);
assert!(auto.enable().is_ok());
auto.enable().unwrap();
assert!(auto.is_enabled().unwrap());

for (expected_enabled, value) in TASK_MANAGER_OVERRIDE_TEST_DATA {
Expand All @@ -177,7 +176,7 @@ mod windows_unit_test {
);
}

assert!(auto.disable().is_ok());
auto.disable().unwrap();
assert!(!auto.is_enabled().unwrap());
}
}
Expand Down Expand Up @@ -227,9 +226,9 @@ mod macos_unit_test {
// use applescript
let auto1 = AutoLaunch::new(app_name, app_path, false, args);
assert_eq!(auto1.get_app_name(), app_name);
assert!(auto1.enable().is_ok());
auto1.enable().unwrap();
assert!(auto1.is_enabled().unwrap());
assert!(auto1.disable().is_ok());
auto1.disable().unwrap();
assert!(!auto1.is_enabled().unwrap());

let auto2 = AutoLaunch::new(app_name_not, app_path_not, false, args);
Expand All @@ -240,16 +239,16 @@ mod macos_unit_test {
// use launch agent
let auto1 = AutoLaunch::new(app_name, app_path, true, args);
assert_eq!(auto1.get_app_name(), app_name);
assert!(auto1.enable().is_ok());
auto1.enable().unwrap();
assert!(auto1.is_enabled().unwrap());
assert!(auto1.disable().is_ok());
auto1.disable().unwrap();
assert!(!auto1.is_enabled().unwrap());

let auto2 = AutoLaunch::new(app_name, app_path_not, true, args);
assert_eq!(auto2.get_app_name(), app_name); // will not change the name
assert!(auto2.enable().is_err());
assert!(!auto2.is_enabled().unwrap());
assert!(auto2.disable().is_ok());
auto2.disable().unwrap();
assert!(!auto2.is_enabled().unwrap());

// test builder
Expand All @@ -261,9 +260,9 @@ mod macos_unit_test {
.unwrap();

assert_eq!(auto.get_app_name(), app_name);
assert!(auto.enable().is_ok());
auto.enable().unwrap();
assert!(auto.is_enabled().unwrap());
assert!(auto.disable().is_ok());
auto.disable().unwrap();
assert!(!auto.is_enabled().unwrap());

// use launch agent
Expand All @@ -276,9 +275,9 @@ mod macos_unit_test {
.unwrap();

assert_eq!(auto.get_app_name(), app_name);
assert!(auto.enable().is_ok());
auto.enable().unwrap();
assert!(auto.is_enabled().unwrap());
assert!(auto.disable().is_ok());
auto.disable().unwrap();
assert!(!auto.is_enabled().unwrap());
}
}
Expand Down

0 comments on commit 729d542

Please sign in to comment.