- Add comprehensive error types for registry operations - Implement ProgIdKind enum with Display and FromStr traits - Create ApplicationVisitor and ClassesVisitor structs - Add ExtKey methods for linking, unlinking and querying ProgId - Implement ProgIdKey creation and deletion in registry - Add safe delete function to prevent accidental registry cleanup - Introduce Display and FromStr implementations for ExtKey and ProgIdKey - Organize registry access through scoped and viewed key opening - Enable setting default "Open With" verbs for file extensions - Support both user and system level registry modifications
145 lines
3.8 KiB
Rust
145 lines
3.8 KiB
Rust
//! This module expand `winreg` crate to make it more suit for this crate.
|
|
|
|
use std::ffi::OsStr;
|
|
use std::ops::Deref;
|
|
use std::ops::DerefMut;
|
|
use windows_sys::Win32::Foundation::ERROR_FILE_NOT_FOUND;
|
|
use windows_sys::Win32::System::Registry::REG_SAM_FLAGS;
|
|
use winreg::RegKey;
|
|
use winreg::types::FromRegValue;
|
|
|
|
// region: Extra Operations
|
|
|
|
/// Get the subkey with given name.
|
|
///
|
|
/// If error occurs when fetching given subkey, it return `Err(...)`,
|
|
/// otherwise, it will return `Ok(Some(...))` if aubkey is existing,
|
|
/// or `Ok(None)` if there is no suchsub key.
|
|
///
|
|
/// Comparing with the function provided by winreg,
|
|
/// it differ "no such subkey" error and other access error.
|
|
pub fn try_open_subkey_with_flags<P: AsRef<OsStr>>(
|
|
regkey: &RegKey,
|
|
path: P,
|
|
perms: REG_SAM_FLAGS,
|
|
) -> std::io::Result<Option<RegKey>> {
|
|
match regkey.open_subkey_with_flags(path, perms) {
|
|
Ok(v) => Ok(Some(v)),
|
|
Err(e) => match e.raw_os_error() {
|
|
Some(errno) => match errno as u32 {
|
|
ERROR_FILE_NOT_FOUND => Ok(None),
|
|
_ => Err(e)
|
|
}
|
|
_ => Err(e),
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Get the value by given key.
|
|
///
|
|
/// If error occurs when fetching given key, it return `Err(...)`,
|
|
/// otherwise, it will return `Ok(Some(...))` if key is existing,
|
|
/// or `Ok(None)` if there is no such key.
|
|
///
|
|
/// Comparing with the function provided by winreg,
|
|
/// it differ "no such key" error and other access error.
|
|
pub fn try_get_value<T: FromRegValue, N: AsRef<OsStr>>(
|
|
regkey: &RegKey,
|
|
name: N,
|
|
) -> std::io::Result<Option<T>> {
|
|
match regkey.get_value::<T, N>(name) {
|
|
Ok(v) => Ok(Some(v)),
|
|
Err(e) => match e.raw_os_error() {
|
|
Some(errno) => match errno as u32 {
|
|
ERROR_FILE_NOT_FOUND => Ok(None),
|
|
_ => Err(e)
|
|
}
|
|
_ => Err(e),
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Passing empty string to `delete_subkey_all` may cause
|
|
/// that the whole parent tree are deleted, not the subkey.
|
|
/// So we create this "safe" function to prevent this horrible scenarios.
|
|
pub fn safe_delete_subkey_all<P: AsRef<OsStr>>(regkey: &RegKey, path: P) -> std::io::Result<()> {
|
|
if path.as_ref().is_empty() {
|
|
Err(std::io::Error::other("dangerous Registry delete_subkey_all"))
|
|
} else {
|
|
regkey.delete_subkey_all(path)
|
|
}
|
|
}
|
|
|
|
// endregion
|
|
|
|
// region: Expand String
|
|
|
|
/// The struct basically is the alias of String, but make a slight difference with it,
|
|
/// to make they are different when use it with String as generic argument.
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub struct ExpandString(String);
|
|
|
|
impl ExpandString {
|
|
/// Construct new ExpandString.
|
|
pub fn new(s: String) -> Self {
|
|
Self(s)
|
|
}
|
|
|
|
/// Create from &str
|
|
pub fn from_str(s: &str) -> Self {
|
|
Self(s.to_string())
|
|
}
|
|
|
|
/// Get reference to internal String.
|
|
pub fn as_str(&self) -> &str {
|
|
&self.0
|
|
}
|
|
|
|
/// Get mutable reference to internal String.
|
|
pub fn as_mut_str(&mut self) -> &mut String {
|
|
&mut self.0
|
|
}
|
|
|
|
/// Comsule self, return internal String.
|
|
pub fn into_inner(self) -> String {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
// Implement Deref trait to make it can be used like &str
|
|
impl Deref for ExpandString {
|
|
type Target = str;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
// Implement DerefMut trait
|
|
impl DerefMut for ExpandString {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.0
|
|
}
|
|
}
|
|
|
|
// Implement From/Into trait for explicit convertion
|
|
impl From<String> for ExpandString {
|
|
fn from(s: String) -> Self {
|
|
Self::new(s)
|
|
}
|
|
}
|
|
|
|
impl From<ExpandString> for String {
|
|
fn from(expand: ExpandString) -> Self {
|
|
expand.into_inner()
|
|
}
|
|
}
|
|
|
|
impl From<&str> for ExpandString {
|
|
fn from(s: &str) -> Self {
|
|
Self::from_str(s)
|
|
}
|
|
}
|
|
|
|
// endregion
|