diff --git a/wfassoc/src/highlevel.rs b/wfassoc/src/highlevel.rs index f32cd65..c1d16d4 100644 --- a/wfassoc/src/highlevel.rs +++ b/wfassoc/src/highlevel.rs @@ -516,7 +516,7 @@ impl Program { // Write ProgId values let name = Some(&program_key.name.inner); progid_key.set_default(scope, name)?; - progid_key.set_shell_verb(scope, &program_key.behavior.inner)?; + progid_key.set_shell_verb(scope, Some(&program_key.behavior.inner))?; progid_key.set_friendly_type_name(scope, name)?; progid_key.set_default_icon(scope, Some(&program_key.icon.inner))?; diff --git a/wfassoc/src/lowlevel/progid_key.rs b/wfassoc/src/lowlevel/progid_key.rs index d8de4f7..5f954a4 100644 --- a/wfassoc/src/lowlevel/progid_key.rs +++ b/wfassoc/src/lowlevel/progid_key.rs @@ -1,9 +1,10 @@ -use super::{Error, Result, Scope, View, LosseProgId, OpenedKey, OpenKeyTerritory, OpenKeyPurpose, StrResVariant, IconResVariant, ShellVerb, check_privilege, PERM_R, PERM_RW}; -use crate::win32::{concept, regext}; -use winreg::RegKey; -use winreg::enums::{ - HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE +use super::{ + Error, IconResVariant, LosseProgId, OpenKeyPurpose, OpenKeyTerritory, OpenedKey, PERM_R, + PERM_RW, Result, Scope, ShellVerb, StrResVariant, View, check_privilege, }; +use crate::win32::regext; +use winreg::RegKey; +use winreg::enums::{HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE}; // region: ProgId Key @@ -26,11 +27,7 @@ impl ProgIdKey { const FULL_CLASSES: &str = "Software\\Classes"; const PARTIAL_CLASSES: &str = ""; - fn open_key( - &self, - territory: OpenKeyTerritory, - purpose: OpenKeyPurpose, - ) -> Result { + fn open_key(&self, territory: OpenKeyTerritory, purpose: OpenKeyPurpose) -> Result { // check privilege check_privilege(territory, purpose)?; // Fetch the permission @@ -114,31 +111,125 @@ impl ProgIdKey { const NAMEOF_DEFAULT: &str = ""; pub fn get_default(&self, view: View) -> Result> { - todo!() + let key = self.open_view_for_getter(view)?; + // Get value of it + let value = regext::try_get_value::(&key, Self::NAMEOF_DEFAULT)?; + // Transform it as result + Ok(value.map(|v| StrResVariant::from(v.as_str()))) } /// /// /// The legacy way to set friendly name for this ProgId. pub fn set_default(&mut self, scope: Scope, name: Option<&StrResVariant>) -> Result<()> { - todo!() + let key = self.open_scope_for_setter(scope)?; + + match name { + Some(name) => { + // Set value for this key + key.set_value(Self::NAMEOF_DEFAULT, &name.to_string())?; + } + None => { + // Delete this key + key.delete_value(Self::NAMEOF_DEFAULT)?; + } + } + + Ok(()) } const NAMEOF_SHELL_VERB_PART1: &str = "shell"; const NAMEOF_SHELL_VERB_PART3: &str = "command"; + const NAMEOF_SHELL_VERB_PART4: &str = ""; - pub fn get_shell_verb(&self, view: View) -> Result { - todo!() + pub fn get_shell_verb(&self, view: View) -> Result> { + let key = self.open_view_for_getter(view)?; + + // Get shell subkey + let shell_key = match regext::try_open_subkey_with_flags( + &key, + regext::blank_path_guard(Self::NAMEOF_SHELL_VERB_PART1)?, + PERM_R, + )? { + Some(key) => key, + None => return Ok(None), + }; + // Get verb subkey name, then get subkey itself. + let verb_key_name = match regext::get_sole_subkey_name(&shell_key)? { + Some(key) => key, + None => return Ok(None), + }; + let verb_key = match regext::try_open_subkey_with_flags( + &shell_key, + regext::blank_path_guard(&verb_key_name)?, + PERM_R, + )? { + Some(key) => key, + None => return Ok(None), + }; + // Get command subkey. + let command_key = match regext::try_open_subkey_with_flags( + &verb_key, + regext::blank_path_guard(Self::NAMEOF_SHELL_VERB_PART3)?, + PERM_R, + )? { + Some(key) => key, + None => return Ok(None), + }; + // Get the default value of command subkey + let command_default_value = match regext::try_get_value::( + &command_key, + Self::NAMEOF_SHELL_VERB_PART4, + )? { + Some(value) => value, + None => return Ok(None), + }; + + // Okey, return value. + Ok(Some(ShellVerb::new( + verb_key_name.parse()?, + command_default_value.parse()?, + ))) } - pub fn set_shell_verb(&mut self, scope: Scope, sv: &ShellVerb) -> Result<()> { - todo!() + pub fn set_shell_verb(&mut self, scope: Scope, sv: Option<&ShellVerb>) -> Result<()> { + let key = self.open_scope_for_setter(scope)?; + + match sv { + Some(sv) => { + // Create shell subkey + let (shell_key, _) = key.create_subkey_with_flags( + regext::blank_path_guard(Self::NAMEOF_SHELL_VERB_PART1)?, + PERM_RW, + )?; + // Create verb key + let (verb_key, _) = + shell_key.create_subkey_with_flags(sv.get_verb().inner(), PERM_RW)?; + // Create command key + let (command_key, _) = verb_key.create_subkey_with_flags( + regext::blank_path_guard(Self::NAMEOF_SHELL_VERB_PART3)?, + PERM_RW, + )?; + // Set command key default value + command_key.set_value(Self::NAMEOF_SHELL_VERB_PART4, &sv.get_command().full())?; + } + None => { + // Delete shell and its all subkey. + key.delete_subkey_all(regext::blank_path_guard(Self::NAMEOF_SHELL_VERB_PART1)?)?; + } + } + + Ok(()) } const NAMEOF_FRIENDLY_TYPE_NAME: &str = "FriendlyTypeName"; pub fn get_friendly_type_name(&self, view: View) -> Result> { - todo!() + let key = self.open_view_for_getter(view)?; + // Get value of it + let value = regext::try_get_value::(&key, Self::NAMEOF_FRIENDLY_TYPE_NAME)?; + // Transform it as result + Ok(value.map(|v| StrResVariant::from(v.as_str()))) } /// @@ -149,22 +240,63 @@ impl ProgIdKey { scope: Scope, name: Option<&StrResVariant>, ) -> Result<()> { - todo!() + let key = self.open_scope_for_setter(scope)?; + + match name { + Some(name) => { + // Set value for this key + key.set_value(Self::NAMEOF_FRIENDLY_TYPE_NAME, &name.to_string())?; + } + None => { + // Delete this key + key.delete_value(Self::NAMEOF_FRIENDLY_TYPE_NAME)?; + } + } + + Ok(()) } const NAMEOF_DEFAULT_ICON_PART1: &str = "DefaultIcon"; const NAMEOF_DEFAULT_ICON_PART2: &str = ""; pub fn get_default_icon(&self, view: View) -> Result> { - todo!() + let key = self.open_view_for_getter(view)?; + // Get default icon subkey + let default_icon_key = match regext::try_open_subkey_with_flags( + &key, + regext::blank_path_guard(Self::NAMEOF_DEFAULT_ICON_PART1)?, + PERM_R, + )? { + Some(key) => key, + None => return Ok(None), + }; + // Get the default value of default icon subkey + let default_icon_default_value = + regext::try_get_value::(&default_icon_key, Self::NAMEOF_DEFAULT_ICON_PART2)?; + // Transform it as result + Ok(default_icon_default_value.map(|v| IconResVariant::from(v.as_str()))) } - pub fn set_default_icon( - &mut self, - scope: Scope, - icon: Option<&IconResVariant>, - ) -> Result<()> { - todo!() + pub fn set_default_icon(&mut self, scope: Scope, icon: Option<&IconResVariant>) -> Result<()> { + let key = self.open_scope_for_setter(scope)?; + + match icon { + Some(icon) => { + // Create default icon subkey + let (default_icon_key, _) = key.create_subkey_with_flags( + regext::blank_path_guard(Self::NAMEOF_DEFAULT_ICON_PART1)?, + PERM_RW, + )?; + // Set default value of default icon subkey. + default_icon_key.set_value(Self::NAMEOF_DEFAULT_ICON_PART2, &icon.to_string())?; + } + None => { + // Delete shell and its all subkey. + key.delete_subkey_all(regext::blank_path_guard(Self::NAMEOF_DEFAULT_ICON_PART1)?)?; + } + } + + Ok(()) } }