|
|
|
|
@@ -30,6 +30,8 @@ pub enum Error {
|
|
|
|
|
ParseVerb(#[from] concept::ParseVerbError),
|
|
|
|
|
#[error("{0}")]
|
|
|
|
|
ParseCmdLine(#[from] concept::ParseCmdLineError),
|
|
|
|
|
#[error("{0}")]
|
|
|
|
|
ParseExt(#[from] concept::ParseExtError),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// endregion
|
|
|
|
|
@@ -303,6 +305,9 @@ impl From<View> for OpenKeyTerritory {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const PERM_R: u32 = KEY_READ;
|
|
|
|
|
const PERM_RW: u32 = KEY_READ | KEY_WRITE;
|
|
|
|
|
|
|
|
|
|
/// The purpose of opening this key.
|
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
|
enum OpenKeyPurpose {
|
|
|
|
|
@@ -312,6 +317,15 @@ enum OpenKeyPurpose {
|
|
|
|
|
ReadWrite,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl OpenKeyPurpose {
|
|
|
|
|
fn to_permission(&self) -> u32 {
|
|
|
|
|
match self {
|
|
|
|
|
OpenKeyPurpose::Read => PERM_R,
|
|
|
|
|
OpenKeyPurpose::ReadWrite => PERM_RW,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Check whether we have enough privilege when operating in given territory and purpose.
|
|
|
|
|
/// If we have, simply return, otherwise return error.
|
|
|
|
|
fn check_privilege(territory: OpenKeyTerritory, purpose: OpenKeyPurpose) -> Result<(), Error> {
|
|
|
|
|
@@ -382,10 +396,7 @@ impl AppPathsKey {
|
|
|
|
|
// check privilege
|
|
|
|
|
check_privilege(territory, purpose)?;
|
|
|
|
|
// Fetch the permission
|
|
|
|
|
let perms = match purpose {
|
|
|
|
|
OpenKeyPurpose::Read => KEY_READ,
|
|
|
|
|
OpenKeyPurpose::ReadWrite => KEY_READ | KEY_WRITE,
|
|
|
|
|
};
|
|
|
|
|
let perms = purpose.to_permission();
|
|
|
|
|
|
|
|
|
|
// get the root key
|
|
|
|
|
let hk = match territory {
|
|
|
|
|
@@ -395,7 +406,8 @@ impl AppPathsKey {
|
|
|
|
|
OpenKeyTerritory::Hybrid => panic!("unexpected hybrid key territory"),
|
|
|
|
|
};
|
|
|
|
|
// navigate to App Paths
|
|
|
|
|
let app_paths = hk.open_subkey_with_flags(Self::APP_PATHS, perms)?;
|
|
|
|
|
let app_paths =
|
|
|
|
|
hk.open_subkey_with_flags(regext::blank_path_guard(Self::APP_PATHS)?, perms)?;
|
|
|
|
|
// open file name key if possible
|
|
|
|
|
let this_app = regext::try_open_subkey_with_flags(
|
|
|
|
|
&app_paths,
|
|
|
|
|
@@ -429,7 +441,7 @@ impl AppPathsKey {
|
|
|
|
|
if let None = key.this_key {
|
|
|
|
|
let _ = key.parent_key.create_subkey_with_flags(
|
|
|
|
|
regext::blank_path_guard(self.key_name.inner())?,
|
|
|
|
|
KEY_READ | KEY_WRITE,
|
|
|
|
|
PERM_RW,
|
|
|
|
|
)?;
|
|
|
|
|
Ok(true)
|
|
|
|
|
} else {
|
|
|
|
|
@@ -535,10 +547,7 @@ impl ApplicationsKey {
|
|
|
|
|
// check privilege
|
|
|
|
|
check_privilege(territory, purpose)?;
|
|
|
|
|
// Fetch the permission
|
|
|
|
|
let perms = match purpose {
|
|
|
|
|
OpenKeyPurpose::Read => KEY_READ,
|
|
|
|
|
OpenKeyPurpose::ReadWrite => KEY_READ | KEY_WRITE,
|
|
|
|
|
};
|
|
|
|
|
let perms = purpose.to_permission();
|
|
|
|
|
|
|
|
|
|
// get the root key
|
|
|
|
|
let hk = match territory {
|
|
|
|
|
@@ -547,12 +556,14 @@ impl ApplicationsKey {
|
|
|
|
|
OpenKeyTerritory::Hybrid => RegKey::predef(HKEY_CLASSES_ROOT),
|
|
|
|
|
};
|
|
|
|
|
let applications = match territory {
|
|
|
|
|
OpenKeyTerritory::User | OpenKeyTerritory::System => {
|
|
|
|
|
hk.open_subkey_with_flags(Self::FULL_APPLICATIONS, perms)?
|
|
|
|
|
}
|
|
|
|
|
OpenKeyTerritory::Hybrid => {
|
|
|
|
|
hk.open_subkey_with_flags(Self::PARTIAL_APPLICATIONS, perms)?
|
|
|
|
|
}
|
|
|
|
|
OpenKeyTerritory::User | OpenKeyTerritory::System => hk.open_subkey_with_flags(
|
|
|
|
|
regext::blank_path_guard(Self::FULL_APPLICATIONS)?,
|
|
|
|
|
perms,
|
|
|
|
|
)?,
|
|
|
|
|
OpenKeyTerritory::Hybrid => hk.open_subkey_with_flags(
|
|
|
|
|
regext::blank_path_guard(Self::PARTIAL_APPLICATIONS)?,
|
|
|
|
|
perms,
|
|
|
|
|
)?,
|
|
|
|
|
};
|
|
|
|
|
// open app key if possible
|
|
|
|
|
let this_app = regext::try_open_subkey_with_flags(
|
|
|
|
|
@@ -582,7 +593,7 @@ impl ApplicationsKey {
|
|
|
|
|
if let None = key.this_key {
|
|
|
|
|
let _ = key.parent_key.create_subkey_with_flags(
|
|
|
|
|
regext::blank_path_guard(self.key_name.inner())?,
|
|
|
|
|
KEY_READ | KEY_WRITE,
|
|
|
|
|
PERM_RW,
|
|
|
|
|
)?;
|
|
|
|
|
Ok(true)
|
|
|
|
|
} else {
|
|
|
|
|
@@ -622,8 +633,8 @@ impl ApplicationsKey {
|
|
|
|
|
// Get shell subkey
|
|
|
|
|
let shell_key = match regext::try_open_subkey_with_flags(
|
|
|
|
|
&key,
|
|
|
|
|
Self::NAMEOF_SHELL_VERB_PART1,
|
|
|
|
|
KEY_READ,
|
|
|
|
|
regext::blank_path_guard(Self::NAMEOF_SHELL_VERB_PART1)?,
|
|
|
|
|
PERM_R,
|
|
|
|
|
)? {
|
|
|
|
|
Some(key) => key,
|
|
|
|
|
None => return Ok(None),
|
|
|
|
|
@@ -633,16 +644,19 @@ impl ApplicationsKey {
|
|
|
|
|
Some(key) => key,
|
|
|
|
|
None => return Ok(None),
|
|
|
|
|
};
|
|
|
|
|
let verb_key =
|
|
|
|
|
match regext::try_open_subkey_with_flags(&shell_key, &verb_key_name, KEY_READ)? {
|
|
|
|
|
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,
|
|
|
|
|
Self::NAMEOF_SHELL_VERB_PART3,
|
|
|
|
|
KEY_READ,
|
|
|
|
|
regext::blank_path_guard(Self::NAMEOF_SHELL_VERB_PART3)?,
|
|
|
|
|
PERM_R,
|
|
|
|
|
)? {
|
|
|
|
|
Some(key) => key,
|
|
|
|
|
None => return Ok(None),
|
|
|
|
|
@@ -670,16 +684,16 @@ impl ApplicationsKey {
|
|
|
|
|
Some(sv) => {
|
|
|
|
|
// Create shell subkey
|
|
|
|
|
let (shell_key, _) = key.create_subkey_with_flags(
|
|
|
|
|
Self::NAMEOF_SHELL_VERB_PART1,
|
|
|
|
|
KEY_READ | KEY_WRITE,
|
|
|
|
|
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(), KEY_READ | KEY_WRITE)?;
|
|
|
|
|
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(
|
|
|
|
|
Self::NAMEOF_SHELL_VERB_PART3,
|
|
|
|
|
KEY_READ | KEY_WRITE,
|
|
|
|
|
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())?;
|
|
|
|
|
@@ -701,8 +715,8 @@ impl ApplicationsKey {
|
|
|
|
|
// Get default icon subkey
|
|
|
|
|
let default_icon_key = match regext::try_open_subkey_with_flags(
|
|
|
|
|
&key,
|
|
|
|
|
Self::NAMEOF_DEFAULT_ICON_PART1,
|
|
|
|
|
KEY_READ,
|
|
|
|
|
regext::blank_path_guard(Self::NAMEOF_DEFAULT_ICON_PART1)?,
|
|
|
|
|
PERM_R,
|
|
|
|
|
)? {
|
|
|
|
|
Some(key) => key,
|
|
|
|
|
None => return Ok(None),
|
|
|
|
|
@@ -725,8 +739,8 @@ impl ApplicationsKey {
|
|
|
|
|
Some(icon) => {
|
|
|
|
|
// Create default icon subkey
|
|
|
|
|
let (default_icon_key, _) = key.create_subkey_with_flags(
|
|
|
|
|
Self::NAMEOF_DEFAULT_ICON_PART1,
|
|
|
|
|
KEY_READ | KEY_WRITE,
|
|
|
|
|
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())?;
|
|
|
|
|
@@ -774,7 +788,25 @@ impl ApplicationsKey {
|
|
|
|
|
const NAMEOF_SUPPORTED_TYPES: &str = "SupportedTypes";
|
|
|
|
|
|
|
|
|
|
pub fn get_supported_types(&self, view: View) -> Result<Option<Vec<concept::Ext>>, Error> {
|
|
|
|
|
todo!()
|
|
|
|
|
let key = self.open_view_for_getter(view)?;
|
|
|
|
|
// Get supported types subkey
|
|
|
|
|
let supported_types_key = match regext::try_open_subkey_with_flags(
|
|
|
|
|
&key,
|
|
|
|
|
regext::blank_path_guard(Self::NAMEOF_SUPPORTED_TYPES)?,
|
|
|
|
|
PERM_R,
|
|
|
|
|
)? {
|
|
|
|
|
Some(key) => key,
|
|
|
|
|
None => return Ok(None),
|
|
|
|
|
};
|
|
|
|
|
// Fetch all sub-values
|
|
|
|
|
let key_names = regext::get_all_string_subkey_names(&supported_types_key)?;
|
|
|
|
|
// Map the result
|
|
|
|
|
let exts = key_names
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|name| name.parse::<concept::Ext>())
|
|
|
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
|
// Return value
|
|
|
|
|
Ok(Some(exts))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_supported_types(
|
|
|
|
|
@@ -782,7 +814,29 @@ impl ApplicationsKey {
|
|
|
|
|
scope: Scope,
|
|
|
|
|
tys: Option<&[&concept::Ext]>,
|
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
|
todo!()
|
|
|
|
|
let key = self.open_scope_for_setter(scope)?;
|
|
|
|
|
|
|
|
|
|
match tys {
|
|
|
|
|
Some(tys) => {
|
|
|
|
|
// Create supported types key
|
|
|
|
|
let (supported_types_key, _) = key.create_subkey_with_flags(
|
|
|
|
|
regext::blank_path_guard(Self::NAMEOF_SUPPORTED_TYPES)?,
|
|
|
|
|
PERM_RW,
|
|
|
|
|
)?;
|
|
|
|
|
// Clean all contents of this key
|
|
|
|
|
regext::clean_all_contents(&supported_types_key)?;
|
|
|
|
|
// Add file types one by one
|
|
|
|
|
for ty in tys {
|
|
|
|
|
supported_types_key.set_value(ty.dotted_inner(), &"")?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
// Delete this subkey.
|
|
|
|
|
key.delete_subkey_all(regext::blank_path_guard(Self::NAMEOF_SUPPORTED_TYPES)?)?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NAMEOF_NO_OPEN_WITH: &str = "NoOpenWith";
|
|
|
|
|
@@ -837,10 +891,7 @@ impl ExtKey {
|
|
|
|
|
// check privilege
|
|
|
|
|
check_privilege(territory, purpose)?;
|
|
|
|
|
// Fetch the permission
|
|
|
|
|
let perms = match purpose {
|
|
|
|
|
OpenKeyPurpose::Read => KEY_READ,
|
|
|
|
|
OpenKeyPurpose::ReadWrite => KEY_READ | KEY_WRITE,
|
|
|
|
|
};
|
|
|
|
|
let perms = purpose.to_permission();
|
|
|
|
|
|
|
|
|
|
// navigate to extension container
|
|
|
|
|
let hk = match territory {
|
|
|
|
|
@@ -850,9 +901,11 @@ impl ExtKey {
|
|
|
|
|
};
|
|
|
|
|
let classes = match territory {
|
|
|
|
|
OpenKeyTerritory::User | OpenKeyTerritory::System => {
|
|
|
|
|
hk.open_subkey_with_flags(Self::FULL_CLASSES, perms)?
|
|
|
|
|
hk.open_subkey_with_flags(regext::blank_path_guard(Self::FULL_CLASSES)?, perms)?
|
|
|
|
|
}
|
|
|
|
|
OpenKeyTerritory::Hybrid => {
|
|
|
|
|
hk.open_subkey_with_flags(regext::blank_path_guard(Self::PARTIAL_CLASSES)?, perms)?
|
|
|
|
|
}
|
|
|
|
|
OpenKeyTerritory::Hybrid => hk.open_subkey_with_flags(Self::PARTIAL_CLASSES, perms)?,
|
|
|
|
|
};
|
|
|
|
|
// open extension key if possible
|
|
|
|
|
let this_ext = regext::try_open_subkey_with_flags(
|
|
|
|
|
@@ -882,7 +935,7 @@ impl ExtKey {
|
|
|
|
|
if let None = key.this_key {
|
|
|
|
|
let _ = key.parent_key.create_subkey_with_flags(
|
|
|
|
|
regext::blank_path_guard(self.ext.dotted_inner())?,
|
|
|
|
|
KEY_READ | KEY_WRITE,
|
|
|
|
|
PERM_RW,
|
|
|
|
|
)?;
|
|
|
|
|
Ok(true)
|
|
|
|
|
} else {
|
|
|
|
|
@@ -919,11 +972,28 @@ impl ExtKey {
|
|
|
|
|
const NAMEOF_DEFAULT: &str = "";
|
|
|
|
|
|
|
|
|
|
pub fn get_default(&self, view: View) -> Result<Option<LosseProgId>, Error> {
|
|
|
|
|
todo!()
|
|
|
|
|
let key = self.open_view_for_getter(view)?;
|
|
|
|
|
// Get value of it
|
|
|
|
|
let value = regext::try_get_value::<String, _>(&key, Self::NAMEOF_DEFAULT)?;
|
|
|
|
|
// Transform it as result
|
|
|
|
|
Ok(value.map(|v| LosseProgId::from(v.as_str())))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_default(&mut self, scope: Scope, pid: Option<&LosseProgId>) -> Result<(), Error> {
|
|
|
|
|
todo!()
|
|
|
|
|
let key = self.open_scope_for_setter(scope)?;
|
|
|
|
|
|
|
|
|
|
match pid {
|
|
|
|
|
Some(pid) => {
|
|
|
|
|
// Set value for this key
|
|
|
|
|
key.set_value(Self::NAMEOF_DEFAULT, &pid.to_string())?;
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
// Delete this key
|
|
|
|
|
key.delete_value(Self::NAMEOF_DEFAULT)?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NAMEOF_OPEN_WITH_PROGIDS: &str = "OpenWithProgIds";
|
|
|
|
|
@@ -984,10 +1054,7 @@ impl ProgIdKey {
|
|
|
|
|
// check privilege
|
|
|
|
|
check_privilege(territory, purpose)?;
|
|
|
|
|
// Fetch the permission
|
|
|
|
|
let perms = match purpose {
|
|
|
|
|
OpenKeyPurpose::Read => KEY_READ,
|
|
|
|
|
OpenKeyPurpose::ReadWrite => KEY_READ | KEY_WRITE,
|
|
|
|
|
};
|
|
|
|
|
let perms = purpose.to_permission();
|
|
|
|
|
|
|
|
|
|
// navigate to ProgId container
|
|
|
|
|
let hk = match territory {
|
|
|
|
|
@@ -997,9 +1064,11 @@ impl ProgIdKey {
|
|
|
|
|
};
|
|
|
|
|
let classes = match territory {
|
|
|
|
|
OpenKeyTerritory::User | OpenKeyTerritory::System => {
|
|
|
|
|
hk.open_subkey_with_flags(Self::FULL_CLASSES, perms)?
|
|
|
|
|
hk.open_subkey_with_flags(regext::blank_path_guard(Self::FULL_CLASSES)?, perms)?
|
|
|
|
|
}
|
|
|
|
|
OpenKeyTerritory::Hybrid => {
|
|
|
|
|
hk.open_subkey_with_flags(regext::blank_path_guard(Self::PARTIAL_CLASSES)?, perms)?
|
|
|
|
|
}
|
|
|
|
|
OpenKeyTerritory::Hybrid => hk.open_subkey_with_flags(Self::PARTIAL_CLASSES, perms)?,
|
|
|
|
|
};
|
|
|
|
|
// open ProgId key if possible
|
|
|
|
|
let this_progid = regext::try_open_subkey_with_flags(
|
|
|
|
|
@@ -1029,7 +1098,7 @@ impl ProgIdKey {
|
|
|
|
|
if let None = key.this_key {
|
|
|
|
|
let _ = key.parent_key.create_subkey_with_flags(
|
|
|
|
|
regext::blank_path_guard(self.progid.to_string())?,
|
|
|
|
|
KEY_READ | KEY_WRITE,
|
|
|
|
|
PERM_RW,
|
|
|
|
|
)?;
|
|
|
|
|
Ok(true)
|
|
|
|
|
} else {
|
|
|
|
|
|