fix: fix expand string error
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -480,6 +480,12 @@ version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "strfmt"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29fdc163db75f7b5ffa3daf0c5a7136fb0d4b2f35523cd1769da05e034159feb"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
@@ -683,6 +689,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"regex",
|
||||
"strfmt",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"widestring",
|
||||
|
||||
@@ -22,3 +22,6 @@ widestring = "1.2.1"
|
||||
indexmap = "2.11.4"
|
||||
regex = "1.11.3"
|
||||
uuid = { version = "1.18.1", features = ["v4"] }
|
||||
|
||||
[dev-dependencies]
|
||||
strfmt = "0.2.5"
|
||||
|
||||
@@ -622,11 +622,15 @@ impl Program {
|
||||
// Before setting it, we must make sure this extension is existing
|
||||
ext_key.ensure(scope)?;
|
||||
ext_key.set_default(scope, Some(progid_key.inner()))?;
|
||||
}
|
||||
None => return Err(ProgramError::BadIndex),
|
||||
};
|
||||
|
||||
// Everything is okey.
|
||||
// Notify changes and return
|
||||
win32::utilities::notify_assoc_changed();
|
||||
Ok(())
|
||||
}
|
||||
None => Err(ProgramError::BadIndex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unlink_ext(&mut self, scope: Scope, index: usize) -> Result<(), ProgramError> {
|
||||
match self.ext_keys.get_mut(index) {
|
||||
@@ -640,11 +644,15 @@ impl Program {
|
||||
// Before setting it, we must make sure this extension is existing
|
||||
ext_key.ensure(scope)?;
|
||||
ext_key.set_default(scope, None)?;
|
||||
}
|
||||
None => return Err(ProgramError::BadIndex),
|
||||
}
|
||||
|
||||
// Everything is okey.
|
||||
// Notify changes and return
|
||||
win32::utilities::notify_assoc_changed();
|
||||
Ok(())
|
||||
}
|
||||
None => Err(ProgramError::BadIndex),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query_ext(
|
||||
&self,
|
||||
|
||||
@@ -20,6 +20,8 @@ pub enum Error {
|
||||
#[error("{0}")]
|
||||
UnexpectedBlankKey(#[from] regext::BlankPathError),
|
||||
|
||||
#[error("{0}")]
|
||||
ExpandEnvVar(#[from] concept::ExpandEnvVarError),
|
||||
#[error("{0}")]
|
||||
LoadIconRc(#[from] concept::LoadIconRcError),
|
||||
#[error("{0}")]
|
||||
@@ -159,7 +161,19 @@ impl IconResVariant {
|
||||
pub fn extract(&self, kind: concept::IconSizeKind) -> Result<concept::IconRc> {
|
||||
let rc = match self {
|
||||
IconResVariant::Plain(v) => concept::IconRc::with_ico_file(v.as_str(), kind)?,
|
||||
IconResVariant::RefStr(v) => concept::IconRc::new(v.get_path(), v.get_index(), kind)?,
|
||||
IconResVariant::RefStr(v) => {
|
||||
// Try expand path part if possible
|
||||
let path_part = match concept::ExpandString::new(v.get_path()) {
|
||||
Ok(expand_string) => expand_string.expand()?,
|
||||
Err(_) => v.get_path().to_string(),
|
||||
};
|
||||
eprintln!("{path_part}");
|
||||
// Get index part.
|
||||
let index_part = v.get_index();
|
||||
eprintln!("{index_part}");
|
||||
// Resolve icon resource
|
||||
concept::IconRc::new(&path_part, index_part, kind)?
|
||||
},
|
||||
};
|
||||
Ok(rc)
|
||||
}
|
||||
@@ -214,7 +228,17 @@ impl StrResVariant {
|
||||
StrResVariant::Plain(v) => v.clone(),
|
||||
// For string reference string, we try to resolve it.
|
||||
StrResVariant::RefStr(v) => {
|
||||
let rc = concept::StrRc::new(v.get_path(), v.get_index())?;
|
||||
// Try expand path part if possible
|
||||
let path_part = match concept::ExpandString::new(v.get_path()) {
|
||||
Ok(expand_string) => expand_string.expand()?,
|
||||
Err(_) => v.get_path().to_string(),
|
||||
};
|
||||
eprintln!("{path_part}");
|
||||
// Get index part
|
||||
let index_part = v.get_index();
|
||||
eprintln!("{index_part}");
|
||||
// Resolve string resource
|
||||
let rc = concept::StrRc::new(&path_part, index_part)?;
|
||||
rc.into_string()
|
||||
}
|
||||
};
|
||||
|
||||
@@ -724,16 +724,16 @@ impl ExpandString {
|
||||
|
||||
/// Expand the variables located in this string
|
||||
/// and produce the final usable string.
|
||||
pub fn expand_string(&self) -> Result<String, ExpandEnvVarError> {
|
||||
pub fn expand(&self) -> Result<String, ExpandEnvVarError> {
|
||||
use windows_sys::Win32::System::Environment::ExpandEnvironmentStringsW;
|
||||
|
||||
// Fetch the size of expand result
|
||||
let source = WideCString::from_str(self.inner.as_str())?;
|
||||
// The return size is including null terminal.
|
||||
let size = unsafe { ExpandEnvironmentStringsW(source.as_ptr(), std::ptr::null_mut(), 0) };
|
||||
if size == 0 {
|
||||
return Err(ExpandEnvVarError::ExpandFunction);
|
||||
}
|
||||
let size_no_nul = size.checked_sub(1).ok_or(ExpandEnvVarError::Underflow)?;
|
||||
|
||||
// Allocate buffer for it.
|
||||
let len: usize = size.try_into()?;
|
||||
@@ -741,7 +741,7 @@ impl ExpandString {
|
||||
let mut buffer = vec![0; len];
|
||||
// Receive result
|
||||
let size =
|
||||
unsafe { ExpandEnvironmentStringsW(source.as_ptr(), buffer.as_mut_ptr(), size_no_nul) };
|
||||
unsafe { ExpandEnvironmentStringsW(source.as_ptr(), buffer.as_mut_ptr(), size) };
|
||||
if size == 0 {
|
||||
return Err(ExpandEnvVarError::ExpandFunction);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::str::FromStr;
|
||||
use std::{collections::HashMap, str::FromStr};
|
||||
use wfassoc::win32::concept::*;
|
||||
|
||||
// region: File Extension
|
||||
@@ -218,16 +218,36 @@ fn test_str_rc() {
|
||||
|
||||
#[test]
|
||||
fn test_expand_string() {
|
||||
fn tester(s: &str) {
|
||||
let rv = ExpandString::new(s);
|
||||
assert!(rv.is_ok());
|
||||
let rv = rv.unwrap();
|
||||
fn tester(fmt: &str, var_name: &str) {
|
||||
// We first insert variable name into format string to get the final string
|
||||
let mut vars = HashMap::new();
|
||||
vars.insert("0".to_string(), var_name.to_string());
|
||||
let final_string = strfmt::strfmt(fmt, &vars).unwrap();
|
||||
|
||||
let rv = rv.expand_string();
|
||||
assert!(rv.is_ok());
|
||||
// The we try expanding final string first
|
||||
let expand_final_string = ExpandString::new(&final_string);
|
||||
assert!(expand_final_string.is_ok());
|
||||
let expand_final_string = expand_final_string.unwrap();
|
||||
let expanded_final_string = expand_final_string.expand();
|
||||
assert!(expanded_final_string.is_ok());
|
||||
let expanded_final_string= expanded_final_string.unwrap();
|
||||
|
||||
// Then we expand variable name individually
|
||||
let expand_var_name = ExpandString::new(var_name);
|
||||
assert!(expand_var_name.is_ok());
|
||||
let expand_var_name = expand_var_name.unwrap();
|
||||
let expanded_var_name = expand_var_name.expand();
|
||||
assert!(expanded_var_name.is_ok());
|
||||
let expanded_var_name = expanded_var_name.unwrap();
|
||||
|
||||
// Finally, we directly insert expanded variable name into format string
|
||||
// to get the string which can be compared with final string.
|
||||
vars.insert("0".to_string(), expanded_var_name.clone());
|
||||
let built_final_string = strfmt::strfmt(fmt, &vars).unwrap();
|
||||
assert_eq!(expanded_final_string.to_string(), built_final_string);
|
||||
}
|
||||
|
||||
tester(r#"%SystemRoot%\System32\shell32.dll"#);
|
||||
tester(r#"{0}\System32\shell32.dll"#, "%SystemRoot%");
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
Reference in New Issue
Block a user