diff --git a/wfassoc/src/lowlevel.rs b/wfassoc/src/lowlevel.rs index 9a92204..2385353 100644 --- a/wfassoc/src/lowlevel.rs +++ b/wfassoc/src/lowlevel.rs @@ -160,17 +160,21 @@ pub enum IconResVariant { impl IconResVariant { pub fn extract(&self, kind: concept::IconSizeKind) -> Result { let rc = match self { - IconResVariant::Plain(v) => concept::IconRc::with_ico_file(v.as_str(), kind)?, + IconResVariant::Plain(v) => { + eprintln!("plain: {v}"); + concept::IconRc::with_ico_file(v.as_str(), kind)? + }, IconResVariant::RefStr(v) => { // Try expand path part if possible - let path_part = match concept::ExpandString::new(v.get_path()) { + let path_part = strip_quote(v.get_path()); + let path_part = match concept::ExpandString::new(path_part) { Ok(expand_string) => expand_string.expand()?, - Err(_) => v.get_path().to_string(), + Err(_) => path_part.to_string(), }; - eprintln!("{path_part}"); + eprintln!("refstr: {path_part}"); // Get index part. let index_part = v.get_index(); - eprintln!("{index_part}"); + eprintln!("refstr: {index_part}"); // Resolve icon resource concept::IconRc::new(&path_part, index_part, kind)? }, @@ -229,9 +233,10 @@ impl StrResVariant { // For string reference string, we try to resolve it. StrResVariant::RefStr(v) => { // Try expand path part if possible - let path_part = match concept::ExpandString::new(v.get_path()) { + let path_part = strip_quote(v.get_path()); + let path_part = match concept::ExpandString::new(path_part) { Ok(expand_string) => expand_string.expand()?, - Err(_) => v.get_path().to_string(), + Err(_) => path_part.to_string(), }; eprintln!("{path_part}"); // Get index part @@ -413,6 +418,22 @@ fn check_privilege(territory: OpenKeyTerritory, purpose: OpenKeyPurpose) -> Resu } } +/// Remove quote pair if possible. +/// +/// In some cases, the path part of [concept::IconRefStr] or [concept::StrRefStr] is quoted by quote. +/// This can no be recognized by Win32 functions. +/// So in this case, we should remove this quote pair. +fn strip_quote<'a>(s: &'a str) -> &'a str { + let bytes = s.as_bytes(); + if bytes.len() >= 2 && bytes[0] == b'"' && bytes[bytes.len() - 1] == b'"' { + // Because quote is 1 byte in UTF8, we can safely slice it, + // without worry about panic. + &s[1..s.len() - 1] + } else { + s + } +} + // endregion // region: Registry Keys diff --git a/wfassoc/src/win32/concept.rs b/wfassoc/src/win32/concept.rs index 2f4d730..ba9ecea 100644 --- a/wfassoc/src/win32/concept.rs +++ b/wfassoc/src/win32/concept.rs @@ -373,7 +373,7 @@ impl FromStr for IconRefStr { fn from_str(s: &str) -> Result { static RE: LazyLock = LazyLock::new(|| { - Regex::new(r"^([^,@].*),-([0-9]+)$").expect("unexpected bad regex pattern string") + Regex::new(r"^([^,@][^,]*),-?([0-9]+)$").expect("unexpected bad regex pattern string") }); let caps = RE.captures(s); if let Some(caps) = caps { @@ -461,7 +461,7 @@ impl FromStr for StrRefStr { fn from_str(s: &str) -> Result { static RE: LazyLock = LazyLock::new(|| { - Regex::new(r"^@(.+),-([0-9]+)$").expect("unexpected bad regex pattern string") + Regex::new(r"^@([^,]+),-?([0-9]+)$").expect("unexpected bad regex pattern string") }); let caps = RE.captures(s); if let Some(caps) = caps { diff --git a/wfassoc/tests/concept.rs b/wfassoc/tests/concept.rs index 833782c..7088361 100644 --- a/wfassoc/tests/concept.rs +++ b/wfassoc/tests/concept.rs @@ -134,6 +134,13 @@ fn test_icon_ref_str() { r#"%SystemRoot%\System32\imageres.dll,-72"#, (r#"%SystemRoot%\System32\imageres.dll"#, 72), ); + ok_tester( + r#""D:\Software\Krita\Krita (x64)\shellex\kritafile.ico",0"#, + ( + r#""D:\Software\Krita\Krita (x64)\shellex\kritafile.ico""#, + 0, + ), + ); err_tester(r#"C:\Windows\Cursors\aero_arrow.cur"#); err_tester(r#"This is my application, OK?"#); err_tester(r#"@%SystemRoot%\System32\shell32.dll,-30596"#); @@ -161,6 +168,10 @@ fn test_str_ref_str() { r#"@%SystemRoot%\System32\shell32.dll,-30596"#, (r#"%SystemRoot%\System32\shell32.dll"#, 30596), ); + ok_tester( + r#"@%SystemRoot%\System32\shell32.dll,30596"#, + (r#"%SystemRoot%\System32\shell32.dll"#, 30596), + ); err_tester(r#"This is my application, OK?"#); err_tester(r#"%SystemRoot%\System32\imageres.dll,-72"#); } @@ -230,7 +241,7 @@ fn test_expand_string() { 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(); + let expanded_final_string = expanded_final_string.unwrap(); // Then we expand variable name individually let expand_var_name = ExpandString::new(var_name);