@@ -43,17 +43,18 @@ pub fn that_detached<T: AsRef<OsStr>>(path: T) -> std::io::Result<()> {
43
43
44
44
let path = wide ( path) ;
45
45
46
- let ( verb, class) = if is_dir {
47
- ( ffi:: EXPLORE , ffi:: FOLDER )
48
- } else {
49
- ( std:: ptr:: null ( ) , std:: ptr:: null ( ) )
46
+ if is_dir {
47
+ unsafe { ffi:: CoInitialize ( std:: ptr:: null ( ) ) } ;
48
+ let folder = unsafe { ffi:: ILCreateFromPathW ( path. as_ptr ( ) ) } ;
49
+ unsafe { SHOpenFolderAndSelectItems ( folder, Some ( & [ folder] ) , 0 ) ? } ;
50
+ return Ok ( ( ) ) ;
50
51
} ;
51
52
52
53
let mut info = ffi:: SHELLEXECUTEINFOW {
53
54
cbSize : std:: mem:: size_of :: < ffi:: SHELLEXECUTEINFOW > ( ) as _ ,
54
55
nShow : ffi:: SW_SHOWNORMAL ,
55
- lpVerb : verb ,
56
- lpClass : class ,
56
+ lpVerb : std :: ptr :: null ( ) ,
57
+ lpClass : std :: ptr :: null ( ) ,
57
58
lpFile : path. as_ptr ( ) ,
58
59
..unsafe { std:: mem:: zeroed ( ) }
59
60
} ;
@@ -104,6 +105,36 @@ pub unsafe fn ShellExecuteExW(info: *mut ffi::SHELLEXECUTEINFOW) -> std::io::Res
104
105
}
105
106
}
106
107
108
+ // Taken from https://microsoft.github.io/windows-docs-rs/doc/windows/
109
+ /// Opens a Windows Explorer window with specified items in a particular folder selected.
110
+ ///
111
+ /// <https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shopenfolderandselectitems>
112
+ #[ allow( non_snake_case) ]
113
+ #[ cfg( feature = "shellexecute-on-windows" ) ]
114
+ pub unsafe fn SHOpenFolderAndSelectItems (
115
+ pidlfolder : * const ffi:: ITEMIDLIST ,
116
+ apidl : Option < & [ * const ffi:: ITEMIDLIST ] > ,
117
+ dwflags : u32 ,
118
+ ) -> std:: io:: Result < ( ) > {
119
+ use std:: convert:: TryInto ;
120
+
121
+ match ffi:: SHOpenFolderAndSelectItems (
122
+ pidlfolder,
123
+ apidl
124
+ . as_deref ( )
125
+ . map_or ( 0 , |slice| slice. len ( ) . try_into ( ) . unwrap ( ) ) ,
126
+ core:: mem:: transmute (
127
+ apidl
128
+ . as_deref ( )
129
+ . map_or ( core:: ptr:: null ( ) , |slice| slice. as_ptr ( ) ) ,
130
+ ) ,
131
+ dwflags,
132
+ ) {
133
+ 0 => Ok ( ( ) ) ,
134
+ error_code => Err ( std:: io:: Error :: from_raw_os_error ( error_code) ) ,
135
+ }
136
+ }
137
+
107
138
#[ cfg( feature = "shellexecute-on-windows" ) ]
108
139
#[ allow( non_snake_case) ]
109
140
mod ffi {
@@ -114,12 +145,6 @@ mod ffi {
114
145
/// <https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow>
115
146
pub const SW_SHOWNORMAL : i32 = 1 ;
116
147
117
- /// Null-terminated UTF-16 encoding of `explore`.
118
- pub const EXPLORE : * const u16 = [ 101 , 120 , 112 , 108 , 111 , 114 , 101 , 0 ] . as_ptr ( ) ;
119
-
120
- /// Null-terminated UTF-16 encoding of `folder`.
121
- pub const FOLDER : * const u16 = [ 102 , 111 , 108 , 100 , 101 , 114 , 0 ] . as_ptr ( ) ;
122
-
123
148
// Taken from https://docs.rs/windows-sys/latest/windows_sys/
124
149
#[ cfg_attr( not( target_arch = "x86" ) , repr( C ) ) ]
125
150
#[ cfg_attr( target_arch = "x86" , repr( C , packed( 1 ) ) ) ]
@@ -149,8 +174,33 @@ mod ffi {
149
174
pub hMonitor : isize ,
150
175
}
151
176
177
+ // Taken from https://microsoft.github.io/windows-docs-rs/doc/windows/
178
+ #[ repr( C , packed( 1 ) ) ]
179
+ pub struct SHITEMID {
180
+ pub cb : u16 ,
181
+ pub abID : [ u8 ; 1 ] ,
182
+ }
183
+
184
+ // Taken from https://microsoft.github.io/windows-docs-rs/doc/windows/
185
+ #[ repr( C , packed( 1 ) ) ]
186
+ pub struct ITEMIDLIST {
187
+ pub mkid : SHITEMID ,
188
+ }
189
+
152
190
#[ link( name = "shell32" ) ]
153
191
extern "system" {
154
192
pub fn ShellExecuteExW ( info : * mut SHELLEXECUTEINFOW ) -> isize ;
193
+ pub fn ILCreateFromPathW ( pszpath : * const u16 ) -> * mut ITEMIDLIST ;
194
+ pub fn SHOpenFolderAndSelectItems (
195
+ pidlfolder : * const ITEMIDLIST ,
196
+ cidl : u32 ,
197
+ apidl : * const * const ITEMIDLIST ,
198
+ dwflags : u32 ,
199
+ ) -> i32 ;
200
+ }
201
+
202
+ #[ link( name = "ole32" ) ]
203
+ extern "system" {
204
+ pub fn CoInitialize ( pvreserved : * const core:: ffi:: c_void ) -> i32 ;
155
205
}
156
206
}
0 commit comments