Skip to content

Commit b8b620d

Browse files
committed
Auto merge of #1117 - mattico:use-shellexecute, r=Diggsey
Use ShellExecute rather than start.exe to open docs on windows Closes #499 The implementation is not too complicated, so it's a bit better than spawning a cmd.exe just to open docs. It also should fix opening docs for the few people still using a year-old insider preview build.
2 parents 07582cd + 9733eaf commit b8b620d

File tree

1 file changed

+45
-28
lines changed

1 file changed

+45
-28
lines changed

src/rustup-utils/src/raw.rs

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ use std::fs;
77
use std::io::Write;
88
use std::io;
99
use std::path::Path;
10-
use std::process::{Command, Stdio, ExitStatus};
10+
use std::process::{Command, ExitStatus};
1111
use std::str;
12-
use std::thread;
13-
use std::time::Duration;
1412

1513
use rand::random;
1614

@@ -194,27 +192,14 @@ fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> {
194192
pub ReparseTarget: WCHAR,
195193
}
196194

197-
fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
198-
fn inner(s: &OsStr) -> io::Result<Vec<u16>> {
199-
let mut maybe_result: Vec<u16> = s.encode_wide().collect();
200-
if maybe_result.iter().any(|&u| u == 0) {
201-
return Err(io::Error::new(io::ErrorKind::InvalidInput,
202-
"strings passed to WinAPI cannot contain NULs"));
203-
}
204-
maybe_result.push(0);
205-
Ok(maybe_result)
206-
}
207-
inner(s.as_ref())
208-
}
209-
210195
// We're using low-level APIs to create the junction, and these are more picky about paths.
211196
// For example, forward slashes cannot be used as a path separator, so we should try to
212197
// canonicalize the path first.
213198
let target = try!(fs::canonicalize(target));
214199

215200
try!(fs::create_dir(junction));
216201

217-
let path = try!(to_u16s(junction));
202+
let path = try!(windows::to_u16s(junction));
218203

219204
unsafe {
220205
let h = CreateFileW(path.as_ptr(),
@@ -367,6 +352,8 @@ pub fn find_cmd<'a>(cmds: &[&'a str]) -> Option<&'a str> {
367352
pub fn open_browser(path: &Path) -> io::Result<bool> {
368353
#[cfg(not(windows))]
369354
fn inner(path: &Path) -> io::Result<bool> {
355+
use std::process::Stdio;
356+
370357
let commands = ["xdg-open", "open", "firefox", "chromium", "sensible-browser"];
371358
if let Some(cmd) = find_cmd(&commands) {
372359
Command::new(cmd)
@@ -382,15 +369,32 @@ pub fn open_browser(path: &Path) -> io::Result<bool> {
382369
}
383370
#[cfg(windows)]
384371
fn inner(path: &Path) -> io::Result<bool> {
385-
Command::new("cmd")
386-
.arg("/C")
387-
.arg("start")
388-
.arg(path)
389-
.stdin(Stdio::null())
390-
.stdout(Stdio::null())
391-
.stderr(Stdio::null())
392-
.spawn()
393-
.map(|_| true)
372+
use winapi;
373+
use std::ptr;
374+
375+
// FIXME: When winapi has this function, use their version
376+
extern "system" {
377+
pub fn ShellExecuteW(hwnd: winapi::HWND,
378+
lpOperation: winapi::LPCWSTR,
379+
lpFile: winapi::LPCWSTR,
380+
lpParameters: winapi::LPCWSTR,
381+
lpDirectory: winapi::LPCWSTR,
382+
nShowCmd: winapi::c_int)
383+
-> winapi::HINSTANCE;
384+
}
385+
const SW_SHOW: winapi::c_int = 5;
386+
387+
let path = windows::to_u16s(path)?;
388+
let operation = windows::to_u16s("open")?;
389+
let result = unsafe {
390+
ShellExecuteW(ptr::null_mut(),
391+
operation.as_ptr(),
392+
path.as_ptr(),
393+
ptr::null(),
394+
ptr::null(),
395+
SW_SHOW)
396+
};
397+
Ok(result as usize > 32)
394398
}
395399
inner(path)
396400
}
@@ -402,8 +406,8 @@ pub mod windows {
402406
use std::path::PathBuf;
403407
use std::ptr;
404408
use std::slice;
405-
use std::ffi::OsString;
406-
use std::os::windows::ffi::OsStringExt;
409+
use std::ffi::{OsString, OsStr};
410+
use std::os::windows::ffi::{OsStringExt, OsStrExt};
407411
use shell32;
408412
use ole32;
409413

@@ -444,4 +448,17 @@ pub mod windows {
444448
}
445449
result
446450
}
451+
452+
pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
453+
fn inner(s: &OsStr) -> io::Result<Vec<u16>> {
454+
let mut maybe_result: Vec<u16> = s.encode_wide().collect();
455+
if maybe_result.iter().any(|&u| u == 0) {
456+
return Err(io::Error::new(io::ErrorKind::InvalidInput,
457+
"strings passed to WinAPI cannot contain NULs"));
458+
}
459+
maybe_result.push(0);
460+
Ok(maybe_result)
461+
}
462+
inner(s.as_ref())
463+
}
447464
}

0 commit comments

Comments
 (0)