/
windows.rs
128 lines (112 loc) · 3.11 KB
/
windows.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::{
ffi::{OsStr, OsString},
io, iter,
os::windows::ffi::OsStrExt,
process::Command,
ptr,
};
use std::os::windows::process::CommandExt;
const CREATE_NO_WINDOW: u32 = 0x08000000;
pub fn commands<T: AsRef<OsStr>>(path: T) -> Vec<Command> {
let mut cmd = Command::new("cmd");
cmd.arg("/c")
.arg("start")
.raw_arg("\"\"")
.raw_arg(wrap_in_quotes(path))
.creation_flags(CREATE_NO_WINDOW);
vec![cmd]
}
pub fn with_command<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> Command {
let mut cmd = Command::new("cmd");
cmd.arg("/c")
.arg("start")
.raw_arg("\"\"")
.raw_arg(wrap_in_quotes(app.into()))
.raw_arg(wrap_in_quotes(path))
.creation_flags(CREATE_NO_WINDOW);
cmd
}
fn wrap_in_quotes<T: AsRef<OsStr>>(path: T) -> OsString {
let mut result = OsString::from("\"");
result.push(path);
result.push("\"");
result
}
pub fn that_detached<T: AsRef<OsStr>>(path: T) -> std::io::Result<()> {
let path = wide(path);
unsafe {
ShellExecuteW(
0,
ffi::OPEN,
path.as_ptr(),
ptr::null(),
ptr::null(),
ffi::SW_SHOW,
)
}
}
pub fn with_detached<T: AsRef<OsStr>>(path: T, app: impl Into<String>) -> std::io::Result<()> {
let app = wide(app.into());
let path = wide(path);
unsafe {
ShellExecuteW(
0,
ffi::OPEN,
app.as_ptr(),
path.as_ptr(),
ptr::null(),
ffi::SW_SHOW,
)
}
}
/// Encodes as wide and adds a null character.
fn wide<T: AsRef<OsStr>>(input: T) -> Vec<u16> {
input.as_ref().encode_wide().chain(iter::once(0)).collect()
}
/// Performs an operation on a specified file.
///
/// <https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew>
#[allow(non_snake_case)]
pub unsafe fn ShellExecuteW(
hwnd: isize,
lpoperation: *const u16,
lpfile: *const u16,
lpparameters: *const u16,
lpdirectory: *const u16,
nshowcmd: i32,
) -> std::io::Result<()> {
let hr = ffi::ShellExecuteW(
hwnd,
lpoperation,
lpfile,
lpparameters,
lpdirectory,
nshowcmd,
);
// ShellExecuteW returns > 32 on success
// https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew#return-value
if hr > 32 {
Ok(())
} else {
Err(io::Error::last_os_error())
}
}
mod ffi {
/// Activates the window and displays it in its current size and position.
///
/// <https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow>
pub const SW_SHOW: i32 = 5;
/// Null-terminated UTF-16 encoding of `open`.
pub const OPEN: *const u16 = [111, 112, 101, 110, 0].as_ptr();
#[link(name = "Shell32")]
extern "C" {
pub fn ShellExecuteW(
hwnd: isize,
lpoperation: *const u16,
lpfile: *const u16,
lpparameters: *const u16,
lpdirectory: *const u16,
nshowcmd: i32,
) -> i32;
}
}