From e08d4a11f21ed43a9869cafa832d8752ab4b9a98 Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Fri, 12 May 2017 18:48:34 -0500 Subject: [PATCH 1/3] 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. --- src/rustup-utils/src/raw.rs | 67 ++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/src/rustup-utils/src/raw.rs b/src/rustup-utils/src/raw.rs index 20b12c350b..1257753b43 100644 --- a/src/rustup-utils/src/raw.rs +++ b/src/rustup-utils/src/raw.rs @@ -7,10 +7,9 @@ use std::fs; use std::io::Write; use std::io; use std::path::Path; +use std::ptr; use std::process::{Command, Stdio, ExitStatus}; use std::str; -use std::thread; -use std::time::Duration; use rand::random; @@ -194,19 +193,6 @@ fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> { pub ReparseTarget: WCHAR, } - fn to_u16s>(s: S) -> io::Result> { - fn inner(s: &OsStr) -> io::Result> { - let mut maybe_result: Vec = 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. @@ -214,7 +200,7 @@ fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> { 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(), @@ -382,15 +368,29 @@ pub fn open_browser(path: &Path) -> io::Result { } #[cfg(windows)] fn inner(path: &Path) -> io::Result { - Command::new("cmd") - .arg("/C") - .arg("start") - .arg(path) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .spawn() - .map(|_| true) + use winapi; + 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) } @@ -402,8 +402,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; @@ -444,4 +444,17 @@ pub mod windows { } result } + + pub fn to_u16s>(s: S) -> io::Result> { + fn inner(s: &OsStr) -> io::Result> { + let mut maybe_result: Vec = 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()) + } } From c975d35968abef876f383d9d33a22228f1cc43f9 Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Fri, 12 May 2017 19:01:04 -0500 Subject: [PATCH 2/3] Shuffle usings to silence warnings --- src/rustup-utils/src/raw.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/rustup-utils/src/raw.rs b/src/rustup-utils/src/raw.rs index 1257753b43..bbce7feafc 100644 --- a/src/rustup-utils/src/raw.rs +++ b/src/rustup-utils/src/raw.rs @@ -7,8 +7,7 @@ use std::fs; use std::io::Write; use std::io; use std::path::Path; -use std::ptr; -use std::process::{Command, Stdio, ExitStatus}; +use std::process::{Command, ExitStatus}; use std::str; use rand::random; @@ -353,6 +352,8 @@ pub fn find_cmd<'a>(cmds: &[&'a str]) -> Option<&'a str> { pub fn open_browser(path: &Path) -> io::Result { #[cfg(not(windows))] fn inner(path: &Path) -> io::Result { + use std::process::Stdio; + let commands = ["xdg-open", "open", "firefox", "chromium", "sensible-browser"]; if let Some(cmd) = find_cmd(&commands) { Command::new(cmd) @@ -369,6 +370,8 @@ pub fn open_browser(path: &Path) -> io::Result { #[cfg(windows)] fn inner(path: &Path) -> io::Result { use winapi; + use std::ptr; + extern "system" { pub fn ShellExecuteW(hwnd: winapi::HWND, lpOperation: winapi::LPCWSTR, @@ -379,7 +382,7 @@ pub fn open_browser(path: &Path) -> io::Result { -> winapi::HINSTANCE; } const SW_SHOW: winapi::c_int = 5; - + let path = windows::to_u16s(path)?; let operation = windows::to_u16s("open")?; let result = unsafe { From 9733eaf86e2d7d60f2d06152e981693dc82ceb5c Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Fri, 12 May 2017 19:04:59 -0500 Subject: [PATCH 3/3] Add FIXME for winapi use --- src/rustup-utils/src/raw.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rustup-utils/src/raw.rs b/src/rustup-utils/src/raw.rs index bbce7feafc..5e78fc6b84 100644 --- a/src/rustup-utils/src/raw.rs +++ b/src/rustup-utils/src/raw.rs @@ -372,6 +372,7 @@ pub fn open_browser(path: &Path) -> io::Result { 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,