feat: add more guard and const in lowlevel
This commit is contained in:
@@ -105,9 +105,9 @@ bool WFProgramQueryExt(Token in_program, View in_view, size_t in_index, Token *o
|
||||
|
||||
bool WFExtStatusDestroy(Token in_ext_status);
|
||||
|
||||
bool WFExtStatuGetName(Token in_ext_status, CStyleString *out_name);
|
||||
bool WFExtStatusGetName(Token in_ext_status, CStyleString *out_name);
|
||||
|
||||
bool WFExtStatuGetIcon(Token in_ext_status, HICON *out_icon);
|
||||
bool WFExtStatusGetIcon(Token in_ext_status, HICON *out_icon);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
@@ -577,7 +577,7 @@ pub extern "C" fn WFExtStatusDestroy(in_ext_status: in_param_ty!(Token)) -> bool
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFExtStatuGetName(
|
||||
pub extern "C" fn WFExtStatusGetName(
|
||||
in_ext_status: in_param_ty!(Token),
|
||||
out_name: out_param_ty!(CStyleString),
|
||||
) -> bool {
|
||||
@@ -591,7 +591,7 @@ pub extern "C" fn WFExtStatuGetName(
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn WFExtStatuGetIcon(
|
||||
pub extern "C" fn WFExtStatusGetIcon(
|
||||
in_ext_status: in_param_ty!(Token),
|
||||
out_icon: out_param_ty!(HICON),
|
||||
) -> bool {
|
||||
|
||||
+123
-54
@@ -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 {
|
||||
|
||||
@@ -104,6 +104,15 @@ pub fn get_all_string_subkey_names(regkey: &RegKey) -> std::io::Result<Vec<Strin
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
}
|
||||
|
||||
/// Delete all contents, including values and subkeys of given key.
|
||||
///
|
||||
/// Deleting all contents of given key rely on giving a special parameter to [RegKey::delete_subkey_all].
|
||||
/// This is very dangerous and may be used by accident.
|
||||
/// So I create this to explicitly indicate this behavior and avoid any mis-type in code.
|
||||
pub fn clean_all_contents(regkey: &RegKey) -> std::io::Result<()> {
|
||||
regkey.delete_subkey_all("")
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region: Blank Path Guard
|
||||
|
||||
Reference in New Issue
Block a user