feat: add arbitrarily_delete_subkey_all for regext
This commit is contained in:
@@ -62,7 +62,7 @@ impl AppPathsKey {
|
|||||||
Ok(key.is_some())
|
Ok(key.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure this application key is presented in App Paths.
|
/// Ensure this application key is presented in App Paths key.
|
||||||
///
|
///
|
||||||
/// Return true if we newly create this key,
|
/// Return true if we newly create this key,
|
||||||
/// otherwise false indicating there already is an existing key.
|
/// otherwise false indicating there already is an existing key.
|
||||||
@@ -79,15 +79,16 @@ impl AppPathsKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete this application key from App Paths.
|
/// Delete this application key from App Paths key.
|
||||||
///
|
///
|
||||||
/// If there is no such key in App Paths,
|
/// Return true if we successfully delete this key,
|
||||||
/// this function does nothing.
|
/// otherwise false indicating there is no such key (already deleted).
|
||||||
pub fn delete(&mut self, scope: Scope) -> Result<()> {
|
pub fn delete(&mut self, scope: Scope) -> Result<bool> {
|
||||||
let key = self.open_scope_for_write(scope)?;
|
let key = self.open_scope_for_write(scope)?;
|
||||||
key.parent_key
|
Ok(regext::arbitrarily_delete_subkey_all(
|
||||||
.delete_subkey_all(regext::blank_path_guard(self.key_name.inner())?)?;
|
&key.parent_key,
|
||||||
Ok(())
|
regext::blank_path_guard(self.key_name.inner())?,
|
||||||
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_scope_for_getter(&self, scope: Scope) -> Result<RegKey> {
|
fn open_scope_for_getter(&self, scope: Scope) -> Result<RegKey> {
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ impl ApplicationsKey {
|
|||||||
Ok(key.is_some())
|
Ok(key.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ensure this application key is presented in Applications key.
|
||||||
|
///
|
||||||
|
/// Return true if we newly create this key,
|
||||||
|
/// otherwise false indicating there already is an existing key.
|
||||||
pub fn ensure(&mut self, scope: Scope) -> Result<bool> {
|
pub fn ensure(&mut self, scope: Scope) -> Result<bool> {
|
||||||
let key = self.open_scope_for_write(scope)?;
|
let key = self.open_scope_for_write(scope)?;
|
||||||
if let None = key.this_key {
|
if let None = key.this_key {
|
||||||
@@ -81,11 +85,16 @@ impl ApplicationsKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(&mut self, scope: Scope) -> Result<()> {
|
/// Delete this application key from Applications key.
|
||||||
|
///
|
||||||
|
/// Return true if we successfully delete this key,
|
||||||
|
/// otherwise false indicating there is no such key (already deleted).
|
||||||
|
pub fn delete(&mut self, scope: Scope) -> Result<bool> {
|
||||||
let key = self.open_scope_for_write(scope)?;
|
let key = self.open_scope_for_write(scope)?;
|
||||||
key.parent_key
|
Ok(regext::arbitrarily_delete_subkey_all(
|
||||||
.delete_subkey_all(regext::blank_path_guard(self.key_name.inner())?)?;
|
&key.parent_key,
|
||||||
Ok(())
|
regext::blank_path_guard(self.key_name.inner())?,
|
||||||
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// YYC MARK:
|
// YYC MARK:
|
||||||
@@ -176,7 +185,7 @@ impl ApplicationsKey {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Delete shell and its all subkey.
|
// Delete shell and its all subkey.
|
||||||
key.delete_subkey_all(Self::NAMEOF_SHELL_VERB_PART1)?;
|
regext::arbitrarily_delete_subkey_all(&key, Self::NAMEOF_SHELL_VERB_PART1)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +226,7 @@ impl ApplicationsKey {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Delete shell and its all subkey.
|
// Delete shell and its all subkey.
|
||||||
key.delete_subkey_all(Self::NAMEOF_DEFAULT_ICON_PART1)?;
|
regext::arbitrarily_delete_subkey_all(&key, Self::NAMEOF_DEFAULT_ICON_PART1)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +307,7 @@ impl ApplicationsKey {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Delete this subkey.
|
// Delete this subkey.
|
||||||
key.delete_subkey_all(Self::NAMEOF_SUPPORTED_TYPES)?;
|
regext::arbitrarily_delete_subkey_all(&key, Self::NAMEOF_SUPPORTED_TYPES)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ impl ExtKey {
|
|||||||
Ok(key.is_some())
|
Ok(key.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ensure this file extension key is presented in Classes key.
|
||||||
|
///
|
||||||
|
/// Return true if we newly create this key,
|
||||||
|
/// otherwise false indicating there already is an existing key.
|
||||||
pub fn ensure(&mut self, scope: Scope) -> Result<bool> {
|
pub fn ensure(&mut self, scope: Scope) -> Result<bool> {
|
||||||
let key = self.open_scope_for_write(scope)?;
|
let key = self.open_scope_for_write(scope)?;
|
||||||
if let None = key.this_key {
|
if let None = key.this_key {
|
||||||
@@ -79,16 +83,21 @@ impl ExtKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(&mut self, scope: Scope) -> Result<()> {
|
/// Delete this file extension key from Classes key.
|
||||||
|
///
|
||||||
|
/// Return true if we successfully delete this key,
|
||||||
|
/// otherwise false indicating there is no such key (already deleted).
|
||||||
|
pub fn delete(&mut self, scope: Scope) -> Result<bool> {
|
||||||
let key = self.open_scope_for_write(scope)?;
|
let key = self.open_scope_for_write(scope)?;
|
||||||
key.parent_key
|
Ok(regext::arbitrarily_delete_subkey_all(
|
||||||
.delete_subkey_all(regext::blank_path_guard(self.ext.dotted_inner())?)?;
|
&key.parent_key,
|
||||||
Ok(())
|
regext::blank_path_guard(self.ext.dotted_inner())?,
|
||||||
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// YYC MARK:
|
// YYC MARK:
|
||||||
// Reference: https://learn.microsoft.com/en-us/windows/win32/shell/fa-file-types#setting-optional-subkeys-and-file-type-extension-attributes
|
// Reference: https://learn.microsoft.com/en-us/windows/win32/shell/fa-file-types#setting-optional-subkeys-and-file-type-extension-attributes
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// We do not support "Content Type" and "PerceivedType"
|
// We do not support "Content Type" and "PerceivedType"
|
||||||
// because current interface are enough to use,
|
// because current interface are enough to use,
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ impl ProgIdKey {
|
|||||||
Ok(key.is_some())
|
Ok(key.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ensure this ProgId key is presented in Classes key.
|
||||||
|
///
|
||||||
|
/// Return true if we newly create this key,
|
||||||
|
/// otherwise false indicating there already is an existing key.
|
||||||
pub fn ensure(&mut self, scope: Scope) -> Result<bool> {
|
pub fn ensure(&mut self, scope: Scope) -> Result<bool> {
|
||||||
let key = self.open_scope_for_write(scope)?;
|
let key = self.open_scope_for_write(scope)?;
|
||||||
if let None = key.this_key {
|
if let None = key.this_key {
|
||||||
@@ -79,18 +83,23 @@ impl ProgIdKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(&mut self, scope: Scope) -> Result<()> {
|
/// Delete this ProgId key from Classes key.
|
||||||
|
///
|
||||||
|
/// Return true if we successfully delete this key,
|
||||||
|
/// otherwise false indicating there is no such key (already deleted).
|
||||||
|
pub fn delete(&mut self, scope: Scope) -> Result<bool> {
|
||||||
let key = self.open_scope_for_write(scope)?;
|
let key = self.open_scope_for_write(scope)?;
|
||||||
key.parent_key
|
Ok(regext::arbitrarily_delete_subkey_all(
|
||||||
.delete_subkey_all(regext::blank_path_guard(self.progid.to_string())?)?;
|
&key.parent_key,
|
||||||
Ok(())
|
regext::blank_path_guard(self.progid.to_string())?,
|
||||||
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// YYC MARK:
|
// YYC MARK:
|
||||||
// Reference: https://learn.microsoft.com/en-us/windows/win32/shell/fa-progids#programmatic-identifier-elements-used-by-file-associations
|
// Reference: https://learn.microsoft.com/en-us/windows/win32/shell/fa-progids#programmatic-identifier-elements-used-by-file-associations
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// Currently we only support (Default), FriendlyTypeName and DefaultIcon
|
// Currently we only support (Default), FriendlyTypeName and DefaultIcon
|
||||||
// to just cover the basic usage.
|
// to just cover the basic usage.
|
||||||
// We may expand these in future.
|
// We may expand these in future.
|
||||||
|
|
||||||
@@ -209,7 +218,7 @@ impl ProgIdKey {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Delete shell and its all subkey.
|
// Delete shell and its all subkey.
|
||||||
key.delete_subkey_all(Self::NAMEOF_SHELL_VERB_PART1)?;
|
regext::arbitrarily_delete_subkey_all(&key, Self::NAMEOF_SHELL_VERB_PART1)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +293,7 @@ impl ProgIdKey {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Delete shell and its all subkey.
|
// Delete shell and its all subkey.
|
||||||
key.delete_subkey_all(Self::NAMEOF_DEFAULT_ICON_PART1)?;
|
regext::arbitrarily_delete_subkey_all(&key, Self::NAMEOF_DEFAULT_ICON_PART1)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,12 +61,36 @@ pub fn try_get_value<T: FromRegValue, N: AsRef<OsStr>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Delete all tree of given path of given key anyway.
|
||||||
|
///
|
||||||
|
/// This function was invented to fix the shortcoming of [RegKey::delete_subkey_all].
|
||||||
|
/// This function always delete given path of given key no matter it is existing.
|
||||||
|
/// Oppositely, [RegKey::delete_subkey_all] will return error if there is no such path.
|
||||||
|
///
|
||||||
|
/// Return true if we successfully delete this key,
|
||||||
|
/// otherwise false indicating there is no such key (already deleted).
|
||||||
|
pub fn arbitrarily_delete_subkey_all<P: AsRef<OsStr>>(
|
||||||
|
regkey: &RegKey,
|
||||||
|
path: P,
|
||||||
|
) -> std::io::Result<bool> {
|
||||||
|
match regkey.delete_subkey_all(path) {
|
||||||
|
Ok(()) => Ok(true),
|
||||||
|
Err(e) => match e.raw_os_error() {
|
||||||
|
Some(errno) => match errno as u32 {
|
||||||
|
ERROR_FILE_NOT_FOUND => Ok(false),
|
||||||
|
_ => Err(e),
|
||||||
|
},
|
||||||
|
_ => Err(e),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the name of only subkey in given key.
|
/// Get the name of only subkey in given key.
|
||||||
///
|
///
|
||||||
/// If there is only one subkey in given key, the return value is its name.
|
/// If there is only one subkey in given key, the return value is its name.
|
||||||
/// If there is no any subkey, or has multiple subkeys, return None instead.
|
/// If there is no any subkey, or has multiple subkeys, return None instead.
|
||||||
/// If error occurs when fetching data, return Err(_).
|
/// If error occurs when fetching data, return Err(_).
|
||||||
///
|
///
|
||||||
/// This is usually used for ShellVerb fetching.
|
/// This is usually used for ShellVerb fetching.
|
||||||
pub fn get_sole_subkey_name(regkey: &RegKey) -> std::io::Result<Option<String>> {
|
pub fn get_sole_subkey_name(regkey: &RegKey) -> std::io::Result<Option<String>> {
|
||||||
let mut subkey_enumerator = regkey.enum_keys();
|
let mut subkey_enumerator = regkey.enum_keys();
|
||||||
@@ -85,7 +109,7 @@ pub fn get_sole_subkey_name(regkey: &RegKey) -> std::io::Result<Option<String>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the name list of all "string" subkeys in given key.
|
/// Get the name list of all "string" subkeys in given key.
|
||||||
///
|
///
|
||||||
/// This is usually used for "OpenWithProgIds" subkey.
|
/// This is usually used for "OpenWithProgIds" subkey.
|
||||||
pub fn get_all_string_subkey_names(regkey: &RegKey) -> std::io::Result<Vec<String>> {
|
pub fn get_all_string_subkey_names(regkey: &RegKey) -> std::io::Result<Vec<String>> {
|
||||||
regkey
|
regkey
|
||||||
@@ -105,11 +129,14 @@ pub fn get_all_string_subkey_names(regkey: &RegKey) -> std::io::Result<Vec<Strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Delete all contents, including values and subkeys of given key.
|
/// 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].
|
/// 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.
|
/// 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.
|
/// 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<()> {
|
pub fn clean_all_contents(regkey: &RegKey) -> std::io::Result<()> {
|
||||||
|
// There is no possibility that this key do not existing,
|
||||||
|
// because what we are cleaning is self content.
|
||||||
|
// So directly use delete_subkey_all is okey.
|
||||||
regkey.delete_subkey_all("")
|
regkey.delete_subkey_all("")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +162,7 @@ impl BlankPathError {
|
|||||||
/// Because it will cause unexpected behavior that returning key self, rather than subkey.
|
/// Because it will cause unexpected behavior that returning key self, rather than subkey.
|
||||||
/// This is VERY dangerous especially for those registry delete functions.
|
/// This is VERY dangerous especially for those registry delete functions.
|
||||||
/// So I create this function to prevent any harmful blank path was passed into registry function.
|
/// So I create this function to prevent any harmful blank path was passed into registry function.
|
||||||
///
|
///
|
||||||
/// This function MUST be used for the value, whose content can not be confirmed at compile time,
|
/// This function MUST be used for the value, whose content can not be confirmed at compile time,
|
||||||
/// and it will be passed to get/set value, or create/delete key functions.
|
/// and it will be passed to get/set value, or create/delete key functions.
|
||||||
pub fn blank_path_guard<P: AsRef<OsStr>>(path: P) -> std::result::Result<P, BlankPathError> {
|
pub fn blank_path_guard<P: AsRef<OsStr>>(path: P) -> std::result::Result<P, BlankPathError> {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ fn test_app_paths_key() {
|
|||||||
|
|
||||||
// delete and ensure
|
// delete and ensure
|
||||||
let rv = key.delete(scope);
|
let rv = key.delete(scope);
|
||||||
|
eprintln!("{rv:?}");
|
||||||
assert!(rv.is_ok());
|
assert!(rv.is_ok());
|
||||||
let rv = key.is_exist(scope);
|
let rv = key.is_exist(scope);
|
||||||
assert!(rv.is_ok());
|
assert!(rv.is_ok());
|
||||||
|
|||||||
Reference in New Issue
Block a user