refactor(winreg): reorganize Windows registry utilities into extra module
Move winreg_extra functionality into new extra/winreg module and restructure project layout Add Windows icon handling utilities in extra/windows module Update dependencies and clean up unused wincmd module
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -739,6 +739,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"widestring",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
@ -764,6 +765,12 @@ dependencies = [
|
|||||||
"wfassoc",
|
"wfassoc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "widestring"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|||||||
@ -12,9 +12,11 @@ windows-sys = { version = "0.60.2", features = [
|
|||||||
"Win32_Security",
|
"Win32_Security",
|
||||||
"Win32_System_SystemServices",
|
"Win32_System_SystemServices",
|
||||||
"Win32_UI_Shell",
|
"Win32_UI_Shell",
|
||||||
|
"Win32_UI_WindowsAndMessaging",
|
||||||
"Win32_System_Registry",
|
"Win32_System_Registry",
|
||||||
] }
|
] }
|
||||||
winreg = { version = "0.55.0", features = ["transactions"] }
|
winreg = { version = "0.55.0", features = ["transactions"] }
|
||||||
|
widestring = "1.2.1"
|
||||||
indexmap = "2.11.4"
|
indexmap = "2.11.4"
|
||||||
regex = "1.11.3"
|
regex = "1.11.3"
|
||||||
uuid = "1.18.1"
|
uuid = "1.18.1"
|
||||||
|
|||||||
7
wfassoc/src/extra.rs
Normal file
7
wfassoc/src/extra.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//! The extension for some existing crates.
|
||||||
|
//! Some imported crates are not enough for my project,
|
||||||
|
//! so I need create something to enrich them.
|
||||||
|
|
||||||
|
pub mod winreg;
|
||||||
|
pub mod windows;
|
||||||
|
|
||||||
96
wfassoc/src/extra/windows.rs
Normal file
96
wfassoc/src/extra/windows.rs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
//! This module expand Windows-related stuff by `windows-sys` crate.
|
||||||
|
//! These features are not implemented in any crates (as I known scope)
|
||||||
|
//! and should be manually implemented for our file association use.
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use thiserror::Error as TeError;
|
||||||
|
use widestring::WideCString;
|
||||||
|
use windows_sys::Win32::UI::Shell::ExtractIconExW;
|
||||||
|
use windows_sys::Win32::UI::WindowsAndMessaging::{DestroyIcon, HICON};
|
||||||
|
|
||||||
|
// region: Icon
|
||||||
|
|
||||||
|
/// Error occurs when loading icon.
|
||||||
|
#[derive(Debug, TeError)]
|
||||||
|
#[error("error occurs when loading icon")]
|
||||||
|
pub enum LoadIconError {
|
||||||
|
EmbeddedNul(#[from] widestring::error::ContainsNul<widestring::WideChar>),
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The size kind of loaded icon
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum IconSizeKind {
|
||||||
|
/// Small Icon
|
||||||
|
Small,
|
||||||
|
/// Large Icon
|
||||||
|
Large,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The struct representing a loaded icon resource.
|
||||||
|
pub struct Icon {
|
||||||
|
icon: HICON,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Icon {
|
||||||
|
pub fn new(file: &Path, index: i32, kind: IconSizeKind) -> Result<Self, LoadIconError> {
|
||||||
|
let mut icon = HICON::default();
|
||||||
|
let icon_ptr = &mut icon as *mut HICON;
|
||||||
|
let file = WideCString::from_os_str(file.as_os_str())?;
|
||||||
|
|
||||||
|
let rv = unsafe {
|
||||||
|
match kind {
|
||||||
|
IconSizeKind::Small => {
|
||||||
|
ExtractIconExW(file.as_ptr(), index, Default::default(), icon_ptr, 1)
|
||||||
|
}
|
||||||
|
IconSizeKind::Large => {
|
||||||
|
ExtractIconExW(file.as_ptr(), index, icon_ptr, Default::default(), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if rv != 1 || icon.is_null() {
|
||||||
|
Err(LoadIconError::Other)
|
||||||
|
} else {
|
||||||
|
Ok(Self { icon })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_raw(hicon: HICON) -> Self {
|
||||||
|
Self { icon: hicon }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_raw(self) -> HICON {
|
||||||
|
self.icon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Icon {
|
||||||
|
pub fn get_icon(&self) -> HICON {
|
||||||
|
self.icon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Icon {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if !self.icon.is_null() {
|
||||||
|
unsafe {
|
||||||
|
DestroyIcon(self.icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region: Cmd Path
|
||||||
|
|
||||||
|
pub struct CmdPath {}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region: Cmd Arguments
|
||||||
|
|
||||||
|
pub struct CmdArgs {}
|
||||||
|
|
||||||
|
// endregion
|
||||||
@ -4,10 +4,9 @@
|
|||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
compile_error!("Crate wfassoc is only supported on Windows.");
|
compile_error!("Crate wfassoc is only supported on Windows.");
|
||||||
|
|
||||||
pub mod assoc;
|
pub mod extra;
|
||||||
pub mod utilities;
|
pub mod utilities;
|
||||||
pub mod wincmd;
|
pub mod assoc;
|
||||||
pub mod winreg_extra;
|
|
||||||
|
|
||||||
use assoc::{Ext, ProgId};
|
use assoc::{Ext, ProgId};
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
@ -411,10 +410,10 @@ impl Program {
|
|||||||
// Open key for this extension.
|
// Open key for this extension.
|
||||||
// If there is no such key, return directly.
|
// If there is no such key, return directly.
|
||||||
if let Some(subkey) =
|
if let Some(subkey) =
|
||||||
winreg_extra::try_open_subkey_with_flags(&classes, ext.to_string(), KEY_WRITE)?
|
extra::winreg::try_open_subkey_with_flags(&classes, ext.to_string(), KEY_WRITE)?
|
||||||
{
|
{
|
||||||
// Only delete the default key if it is equal to our ProgId
|
// Only delete the default key if it is equal to our ProgId
|
||||||
if let Some(value) = winreg_extra::try_get_value::<String, _>(&subkey, "")? {
|
if let Some(value) = extra::winreg::try_get_value::<String, _>(&subkey, "")? {
|
||||||
if value == prog_id.to_string() {
|
if value == prog_id.to_string() {
|
||||||
// Delete the default key.
|
// Delete the default key.
|
||||||
subkey.delete_value("")?;
|
subkey.delete_value("")?;
|
||||||
@ -449,10 +448,10 @@ impl Program {
|
|||||||
|
|
||||||
// Open key for this extension if possible
|
// Open key for this extension if possible
|
||||||
let rv =
|
let rv =
|
||||||
match winreg_extra::try_open_subkey_with_flags(&classes, ext.to_string(), KEY_READ)? {
|
match extra::winreg::try_open_subkey_with_flags(&classes, ext.to_string(), KEY_READ)? {
|
||||||
Some(subkey) => {
|
Some(subkey) => {
|
||||||
// Try get associated ProgId if possible
|
// Try get associated ProgId if possible
|
||||||
match winreg_extra::try_get_value::<String, _>(&subkey, "")? {
|
match extra::winreg::try_get_value::<String, _>(&subkey, "")? {
|
||||||
Some(value) => Some(ProgId::from(value.as_str())),
|
Some(value) => Some(ProgId::from(value.as_str())),
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
//! This module involve Windows command line stuff, like argument splittor and path,
|
|
||||||
//! because they are different with POSIX standard.
|
|
||||||
|
|
||||||
// region: Cmd Path
|
|
||||||
|
|
||||||
pub struct CmdPath {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region: Cmd Arguments
|
|
||||||
|
|
||||||
pub struct CmdArgs {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
@ -117,6 +117,7 @@ fn run_unregister(cli: &Cli, target: &Target) -> Result<()> {
|
|||||||
fn run_query(cli: &Cli) -> Result<()> {
|
fn run_query(cli: &Cli) -> Result<()> {
|
||||||
let composition = Composition::new(cli)?;
|
let composition = Composition::new(cli)?;
|
||||||
|
|
||||||
|
// Show file association
|
||||||
let mut table = Table::new();
|
let mut table = Table::new();
|
||||||
table.set_header(["Extension", "Hybrid", "User", "System"]);
|
table.set_header(["Extension", "Hybrid", "User", "System"]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user