From 9d02a2187f7a53baf22179abd6fe31ef71bdcef7 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sun, 17 May 2026 12:37:14 +0800 Subject: [PATCH] feat: add some boring function in lowlevel --- wfassoc/src/lowlevel.rs | 136 +++++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 16 deletions(-) diff --git a/wfassoc/src/lowlevel.rs b/wfassoc/src/lowlevel.rs index 2cffcb9..633284b 100644 --- a/wfassoc/src/lowlevel.rs +++ b/wfassoc/src/lowlevel.rs @@ -615,7 +615,8 @@ impl ApplicationsKey { todo!() } - const NAMEOF_DEFAULT_ICON: &str = "DefaultIcon"; + const NAMEOF_DEFAULT_ICON_PART1: &str = "DefaultIcon"; + const NAMEOF_DEFAULT_ICON_PART2: &str = ""; pub fn get_default_icon(&self, view: View) -> Result, Error> { todo!() @@ -654,18 +655,27 @@ impl ApplicationsKey { scope: Scope, tys: Option<&[&concept::Ext]>, ) -> Result<(), Error> { - // TODO: If given slice is empty, do not create this key. todo!() } const NAMEOF_NO_OPEN_WITH: &str = "NoOpenWith"; pub fn get_no_open_with(&self, view: View) -> Result { - todo!() + let key = self.open_view_for_getter(view)?; + match regext::try_get_value::(&key, Self::NAMEOF_NO_OPEN_WITH)? { + Some(_) => Ok(true), + None => Ok(false), + } } pub fn set_no_open_with(&mut self, scope: Scope, flag: bool) -> Result<(), Error> { - todo!() + let key = self.open_scope_for_setter(scope)?; + if flag { + key.set_value(Self::NAMEOF_NO_OPEN_WITH, &"")?; + } else { + key.delete_value(Self::NAMEOF_NO_OPEN_WITH)?; + } + Ok(()) } } @@ -727,16 +737,37 @@ impl ExtKey { Ok(OpenedKey::new(classes, this_ext)) } + fn open_view_for_read(&self, view: View) -> Result { + self.open_key(view.into(), OpenKeyPurpose::Read) + } + + fn open_scope_for_write(&self, scope: Scope) -> Result { + self.open_key(scope.into(), OpenKeyPurpose::ReadWrite) + } + pub fn is_exist(&self, view: View) -> Result { - todo!() + let key = self.open_view_for_read(view)?.this_key; + Ok(key.is_some()) } pub fn ensure(&mut self, scope: Scope) -> Result { - todo!() + let key = self.open_scope_for_write(scope)?; + 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, + )?; + Ok(true) + } else { + Ok(false) + } } pub fn delete(&mut self, scope: Scope) -> Result<(), Error> { - todo!() + let key = self.open_scope_for_write(scope)?; + key.parent_key + .delete_subkey_all(regext::blank_path_guard(self.ext.dotted_inner())?)?; + Ok(()) } // YYC MARK: @@ -744,6 +775,18 @@ impl ExtKey { // because current interface are enough to use, // and these types has not been made as concept struct in Rust. + fn open_view_for_getter(&self, view: View) -> Result { + self.open_view_for_read(view)? + .this_key + .ok_or(Error::InexistantKey) + } + + fn open_scope_for_setter(&self, scope: Scope) -> Result { + self.open_scope_for_write(scope)? + .this_key + .ok_or(Error::InexistantKey) + } + const NAMEOF_DEFAULT: &str = ""; pub fn get_default(&self, view: View) -> Result, Error> { @@ -809,33 +852,93 @@ impl ProgIdKey { territory: OpenKeyTerritory, purpose: OpenKeyPurpose, ) -> Result { - todo!() + // check privilege + check_privilege(territory, purpose)?; + // Fetch the permission + let perms = match purpose { + OpenKeyPurpose::Read => KEY_READ, + OpenKeyPurpose::ReadWrite => KEY_READ | KEY_WRITE, + }; + + // navigate to ProgId container + let hk = match territory { + OpenKeyTerritory::User => RegKey::predef(HKEY_CURRENT_USER), + OpenKeyTerritory::System => RegKey::predef(HKEY_LOCAL_MACHINE), + OpenKeyTerritory::Hybrid => RegKey::predef(HKEY_CLASSES_ROOT), + }; + let classes = match territory { + OpenKeyTerritory::User | OpenKeyTerritory::System => { + hk.open_subkey_with_flags(Self::FULL_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( + &classes, + regext::blank_path_guard(self.progid.to_string())?, + perms, + )?; + // okey + Ok(OpenedKey::new(classes, this_progid)) + } + + fn open_view_for_read(&self, view: View) -> Result { + self.open_key(view.into(), OpenKeyPurpose::Read) + } + + fn open_scope_for_write(&self, scope: Scope) -> Result { + self.open_key(scope.into(), OpenKeyPurpose::ReadWrite) } pub fn is_exist(&self, view: View) -> Result { - todo!() + let key = self.open_view_for_read(view)?.this_key; + Ok(key.is_some()) } pub fn ensure(&mut self, scope: Scope) -> Result { - todo!() + let key = self.open_scope_for_write(scope)?; + 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, + )?; + Ok(true) + } else { + Ok(false) + } } pub fn delete(&mut self, scope: Scope) -> Result<(), Error> { - todo!() + let key = self.open_scope_for_write(scope)?; + key.parent_key + .delete_subkey_all(regext::blank_path_guard(self.progid.to_string())?)?; + Ok(()) } // YYC MARK: // Currently we only support (Default), FriendlyTypeName and DefaultIcon // to just cover the basic usage. + fn open_view_for_getter(&self, view: View) -> Result { + self.open_view_for_read(view)? + .this_key + .ok_or(Error::InexistantKey) + } + + fn open_scope_for_setter(&self, scope: Scope) -> Result { + self.open_scope_for_write(scope)? + .this_key + .ok_or(Error::InexistantKey) + } + const NAMEOF_DEFAULT: &str = ""; pub fn get_default(&self, view: View) -> Result, Error> { todo!() } - /// - /// + /// + /// /// The legacy way to set friendly name for this ProgId. pub fn set_default(&mut self, scope: Scope, name: Option<&StrResVariant>) -> Result<(), Error> { todo!() @@ -858,8 +961,8 @@ impl ProgIdKey { todo!() } - /// - /// + /// + /// /// Set this entry to a friendly name for the ProgID. pub fn set_friendly_type_name( &mut self, @@ -869,7 +972,8 @@ impl ProgIdKey { todo!() } - const NAMEOF_DEFAULT_ICON: &str = "DefaultIcon"; + const NAMEOF_DEFAULT_ICON_PART1: &str = "DefaultIcon"; + const NAMEOF_DEFAULT_ICON_PART2: &str = ""; pub fn get_default_icon(&self, view: View) -> Result, Error> { todo!()