diff --git a/wfassoc/src/lowlevel.rs b/wfassoc/src/lowlevel.rs index a03bc1e..2cffcb9 100644 --- a/wfassoc/src/lowlevel.rs +++ b/wfassoc/src/lowlevel.rs @@ -16,10 +16,14 @@ pub enum Error { NoPrivilege, #[error("given registry key is inexistant")] InexistantKey, + #[error("registry operation error: {0}")] BadRegOp(#[from] std::io::Error), #[error("{0}")] + BadSoleSubKey(#[from] regext::OnlySubKeyError), + #[error("{0}")] UnexpectedBlankKey(#[from] regext::BlankPathError), + #[error("{0}")] LoadIconRc(#[from] concept::LoadIconRcError), #[error("{0}")] diff --git a/wfassoc/src/win32/regext.rs b/wfassoc/src/win32/regext.rs index 647c7e9..02ea06a 100644 --- a/wfassoc/src/win32/regext.rs +++ b/wfassoc/src/win32/regext.rs @@ -7,6 +7,7 @@ use thiserror::Error as TeError; use windows_sys::Win32::Foundation::ERROR_FILE_NOT_FOUND; use windows_sys::Win32::System::Registry::REG_SAM_FLAGS; use winreg::RegKey; +use winreg::enums::RegType; use winreg::types::FromRegValue; // region: Extra Operations @@ -60,6 +61,57 @@ pub fn try_get_value>( } } +/// The error occurs when fetching the name of only subkey. +#[derive(Debug, TeError)] +pub enum OnlySubKeyError { + #[error("registry operation error: {0}")] + Io(#[from] std::io::Error), + + #[error("there is no any subkey in given RegKey")] + NoSubKey, + #[error("there is more than one subkey in given RegKey")] + TooManySubKey, +} + +/// Get the name of only subkey in given key. +/// +/// This is usually used for ShellVerb fetching. +pub fn get_sole_subkey_name(regkey: &RegKey) -> Result { + let mut subkey_enumerator = regkey.enum_keys(); + + // Get first one. + let rv = match subkey_enumerator.next() { + Some(key) => key?, + None => return Err(OnlySubKeyError::NoSubKey), + }; + + // Check whether there is second one. + match subkey_enumerator.next() { + Some(_) => Err(OnlySubKeyError::TooManySubKey), + None => Ok(rv), + } +} + +/// Get the name list of all "string" subkeys in given key. +/// +/// This is usually used for "OpenWithProgIds" subkey. +pub fn get_all_string_subkey_names(regkey: &RegKey) -> std::io::Result> { + regkey + .enum_values() + .filter_map(|item| match item { + Ok((key, value)) => { + // Check subkey type. + if value.vtype == RegType::REG_SZ { + Some(Ok(key)) + } else { + None + } + } + Err(err) => Some(Err(err)), + }) + .collect::, _>>() +} + // endregion // region: Blank Path Guard