37
37
//! }
38
38
//! # }
39
39
//! ```
40
+ #[ cfg( windows) ]
41
+ extern crate winapi;
42
+
43
+ #[ cfg( not( target_os = "windows" ) ) ]
44
+ use std:: process:: Command ;
45
+
40
46
use std:: ffi:: OsStr ;
41
47
use std:: io;
42
- use std:: process:: { Command , ExitStatus } ;
48
+ use std:: process:: ExitStatus ;
43
49
44
50
#[ cfg( not( any( target_os = "windows" , target_os = "macos" ) ) ) ]
45
51
pub fn that < T : AsRef < OsStr > + Sized > ( path : T ) -> io:: Result < ExitStatus > {
@@ -59,22 +65,53 @@ pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
59
65
60
66
#[ cfg( target_os = "windows" ) ]
61
67
pub fn that < T : AsRef < OsStr > + Sized > ( path : T ) -> io:: Result < ExitStatus > {
62
- Command :: new ( "cmd" )
63
- . arg ( "/C" )
64
- . arg ( "start" )
65
- . arg ( "" )
66
- . arg ( {
67
- let path_ref = path. as_ref ( ) ;
68
- match path_ref. to_str ( ) {
69
- Some ( s) => s. replace ( "&" , "^&" ) ,
70
- None => path_ref,
71
- }
72
- } )
73
- . spawn ( ) ?
74
- . wait ( )
68
+ use winapi:: ctypes:: c_int;
69
+ use winapi:: um:: shellapi:: ShellExecuteW ;
70
+ use std:: os:: windows:: ffi:: OsStrExt ;
71
+ use std:: os:: windows:: process:: ExitStatusExt ;
72
+ use std:: ptr;
73
+
74
+ const SW_SHOW : c_int = 5 ;
75
+
76
+ let path = windows:: convert_path ( path. as_ref ( ) ) ?;
77
+ let operation: Vec < u16 > = OsStr :: new ( "open\0 " ) . encode_wide ( ) . collect ( ) ;
78
+ let result = unsafe {
79
+ ShellExecuteW (
80
+ ptr:: null_mut ( ) ,
81
+ operation. as_ptr ( ) ,
82
+ path. as_ptr ( ) ,
83
+ ptr:: null ( ) ,
84
+ ptr:: null ( ) ,
85
+ SW_SHOW ,
86
+ )
87
+ } ;
88
+ if result as c_int > 32 {
89
+ Ok ( ExitStatus :: from_raw ( 0 ) )
90
+ } else {
91
+ Err ( io:: Error :: last_os_error ( ) )
92
+ }
75
93
}
76
94
77
95
#[ cfg( target_os = "macos" ) ]
78
96
pub fn that < T : AsRef < OsStr > + Sized > ( path : T ) -> io:: Result < ExitStatus > {
79
97
Command :: new ( "open" ) . arg ( path. as_ref ( ) ) . spawn ( ) ?. wait ( )
80
98
}
99
+
100
+ #[ cfg( windows) ]
101
+ mod windows {
102
+ use std:: io;
103
+ use std:: ffi:: OsStr ;
104
+ use std:: os:: windows:: ffi:: OsStrExt ;
105
+
106
+ pub fn convert_path ( path : & OsStr ) -> io:: Result < Vec < u16 > > {
107
+ let mut maybe_result: Vec < _ > = path. encode_wide ( ) . collect ( ) ;
108
+ if maybe_result. iter ( ) . any ( |& u| u == 0 ) {
109
+ return Err ( io:: Error :: new (
110
+ io:: ErrorKind :: InvalidInput ,
111
+ "path contains NUL byte(s)" ,
112
+ ) ) ;
113
+ }
114
+ maybe_result. push ( 0 ) ;
115
+ Ok ( maybe_result)
116
+ }
117
+ }
0 commit comments