Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ShellExecute rather than start.exe to open docs on windows #1117

Merged
merged 3 commits into from
May 18, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 45 additions & 28 deletions src/rustup-utils/src/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ use std::fs;
use std::io::Write;
use std::io;
use std::path::Path;
use std::process::{Command, Stdio, ExitStatus};
use std::process::{Command, ExitStatus};
use std::str;
use std::thread;
use std::time::Duration;

use rand::random;

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

fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
fn inner(s: &OsStr) -> io::Result<Vec<u16>> {
let mut maybe_result: Vec<u16> = s.encode_wide().collect();
if maybe_result.iter().any(|&u| u == 0) {
return Err(io::Error::new(io::ErrorKind::InvalidInput,
"strings passed to WinAPI cannot contain NULs"));
}
maybe_result.push(0);
Ok(maybe_result)
}
inner(s.as_ref())
}

// We're using low-level APIs to create the junction, and these are more picky about paths.
// For example, forward slashes cannot be used as a path separator, so we should try to
// canonicalize the path first.
let target = try!(fs::canonicalize(target));

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

let path = try!(to_u16s(junction));
let path = try!(windows::to_u16s(junction));

unsafe {
let h = CreateFileW(path.as_ptr(),
Expand Down Expand Up @@ -367,6 +352,8 @@ pub fn find_cmd<'a>(cmds: &[&'a str]) -> Option<&'a str> {
pub fn open_browser(path: &Path) -> io::Result<bool> {
#[cfg(not(windows))]
fn inner(path: &Path) -> io::Result<bool> {
use std::process::Stdio;

let commands = ["xdg-open", "open", "firefox", "chromium", "sensible-browser"];
if let Some(cmd) = find_cmd(&commands) {
Command::new(cmd)
Expand All @@ -382,15 +369,32 @@ pub fn open_browser(path: &Path) -> io::Result<bool> {
}
#[cfg(windows)]
fn inner(path: &Path) -> io::Result<bool> {
Command::new("cmd")
.arg("/C")
.arg("start")
.arg(path)
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.map(|_| true)
use winapi;
use std::ptr;

// FIXME: When winapi has this function, use their version
extern "system" {
pub fn ShellExecuteW(hwnd: winapi::HWND,
lpOperation: winapi::LPCWSTR,
lpFile: winapi::LPCWSTR,
lpParameters: winapi::LPCWSTR,
lpDirectory: winapi::LPCWSTR,
nShowCmd: winapi::c_int)
-> winapi::HINSTANCE;
}
const SW_SHOW: winapi::c_int = 5;

let path = windows::to_u16s(path)?;
let operation = windows::to_u16s("open")?;
let result = unsafe {
ShellExecuteW(ptr::null_mut(),
operation.as_ptr(),
path.as_ptr(),
ptr::null(),
ptr::null(),
SW_SHOW)
};
Ok(result as usize > 32)
}
inner(path)
}
Expand All @@ -402,8 +406,8 @@ pub mod windows {
use std::path::PathBuf;
use std::ptr;
use std::slice;
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
use std::ffi::{OsString, OsStr};
use std::os::windows::ffi::{OsStringExt, OsStrExt};
use shell32;
use ole32;

Expand Down Expand Up @@ -444,4 +448,17 @@ pub mod windows {
}
result
}

pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
fn inner(s: &OsStr) -> io::Result<Vec<u16>> {
let mut maybe_result: Vec<u16> = s.encode_wide().collect();
if maybe_result.iter().any(|&u| u == 0) {
return Err(io::Error::new(io::ErrorKind::InvalidInput,
"strings passed to WinAPI cannot contain NULs"));
}
maybe_result.push(0);
Ok(maybe_result)
}
inner(s.as_ref())
}
}