extern crate winreg;
extern crate winapi;
use self::winapi::windef::HWND;
use self::winapi::winnt::LPCWSTR;
use self::winreg::RegKey;
use self::winreg::enums::HKEY_CURRENT_USER;
use app::App;
use errors::*;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::path::Path;
use std::ptr;
fn to_wide_chars(s: &str) -> Vec<u16> {
OsStr::new(s)
.encode_wide()
.chain(Some(0).into_iter())
.collect::<Vec<_>>()
}
#[link(name = "shell32")]
extern "system" {
pub fn ShellExecuteW(
hwnd: HWND,
lpOperation: LPCWSTR,
lpFile: LPCWSTR,
lpParameters: LPCWSTR,
lpDirectory: LPCWSTR,
nShowCmd: i32,
) -> i32;
}
pub fn install(app: &App, schemes: &[String]) -> Result<()> {
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
for protocol in schemes {
let base_path = Path::new("Software").join("Classes").join(protocol);
let key = hkcu.create_subkey(&base_path).chain_err(
|| "could not create subkey",
)?;
key.set_value("", &app.name).chain_err(
|| "could not set app name key",
)?;
key.set_value("URL Protocol", &"").chain_err(
|| "could set url protocol",
)?;
let command_key = hkcu.create_subkey(&base_path.join("shell").join("open").join("command"))
.chain_err(|| "could not execute open")?;
command_key
.set_value("", &format!("{} \"%1\"", app.exec))
.chain_err(|| "could not create subkey")?
}
Ok(())
}
#[allow(unsafe_code)]
pub fn open(uri: String) -> Result<()> {
let err = unsafe {
ShellExecuteW(
ptr::null_mut(),
to_wide_chars("open").as_ptr(),
to_wide_chars(&(uri.replace("\n", "%0A"))).as_ptr(),
ptr::null(),
ptr::null(),
winapi::SW_SHOWNORMAL,
)
};
if err < 32 {
Err(
format!("Executing open failed with error_code {}.", err).into(),
)
} else {
Ok(())
}
}