From abcd0f4810cbcdee4d80dba01a6474ad711efa61 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 17 Nov 2025 23:18:12 +0800 Subject: [PATCH 1/2] fix(windows): pass canonicalized path to `ILCreateFromPathW` --- src/windows.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/windows.rs b/src/windows.rs index da608a3..f9f864b 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -38,17 +38,11 @@ fn wrap_in_quotes>(path: T) -> OsString { #[cfg(feature = "shellexecute-on-windows")] pub fn that_detached>(path: T) -> std::io::Result<()> { - use std::path::Path; - let path = path.as_ref(); let is_dir = std::fs::metadata(path).map(|f| f.is_dir()).unwrap_or(false); if is_dir { - let path = dunce::simplified(Path::new(path)); - let path = wide(path); - unsafe { ffi::CoInitialize(std::ptr::null()) }; - let folder = unsafe { ffi::ILCreateFromPathW(path.as_ptr()) }; - if unsafe { SHOpenFolderAndSelectItems(folder, Some(&[folder]), 0) }.is_ok() { + if shell_open_folder(path).is_ok() { return Ok(()); } }; @@ -73,6 +67,20 @@ pub fn that_detached>(path: T) -> std::io::Result<()> { unsafe { ShellExecuteExW(&mut info) } } +#[cfg(feature = "shellexecute-on-windows")] +fn shell_open_folder(path: &OsStr) -> Result<(), std::io::Error> { + let path = dunce::canonicalize(path)?; + let path = wide(path); + unsafe { ffi::CoInitialize(std::ptr::null()) }; + let folder = unsafe { ffi::ILCreateFromPathW(path.as_ptr()) }; + if folder.is_null() { + return Err(std::io::Error::last_os_error()); + } + let result = unsafe { SHOpenFolderAndSelectItems(folder, Some(&[folder]), 0) }; + unsafe { ffi::ILFree(folder) }; + result +} + #[cfg(feature = "shellexecute-on-windows")] pub fn with_detached>(path: T, app: impl Into) -> std::io::Result<()> { let app = wide(app.into()); @@ -156,10 +164,10 @@ mod ffi { /// pub const SW_SHOWNORMAL: i32 = 1; - /// Null-terminated UTF-16 encoding of `explore`. + /// Null-terminated UTF-16 encoding of `explore`. pub const EXPLORE: *const u16 = [101, 120, 112, 108, 111, 114, 101, 0].as_ptr(); - /// Null-terminated UTF-16 encoding of `folder`. + /// Null-terminated UTF-16 encoding of `folder`. pub const FOLDER: *const u16 = [102, 111, 108, 100, 101, 114, 0].as_ptr(); // Taken from https://docs.rs/windows-sys/latest/windows_sys/ @@ -214,6 +222,7 @@ mod ffi { apidl: *const *const ITEMIDLIST, dwflags: u32, ) -> i32; + pub fn ILFree(pidl: *const ITEMIDLIST) -> i32; } #[link(name = "ole32")] From c84cadebb81e7d214845bb1030e3e44fbf49fd91 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 17 Nov 2025 20:52:30 +0100 Subject: [PATCH 2/2] Fix CI by using a more recent Windows image --- .github/workflows/cross-platform-testing.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cross-platform-testing.yml b/.github/workflows/cross-platform-testing.yml index c28d1ca..2ed9dbb 100644 --- a/.github/workflows/cross-platform-testing.yml +++ b/.github/workflows/cross-platform-testing.yml @@ -35,11 +35,11 @@ jobs: rust: nightly target: x86_64-apple-darwin - build: win-msvc - os: windows-2019 + os: windows-2022 rust: stable target: x86_64-pc-windows-msvc - build: win-gnu - os: windows-2019 + os: windows-2022 rust: stable target: x86_64-pc-windows-gnu - build: win32-gnu