119 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
#![windows_subsystem = "windows"]
 | 
						|
 | 
						|
use std::{
 | 
						|
    path::PathBuf,
 | 
						|
    process::{Command, Stdio},
 | 
						|
};
 | 
						|
 | 
						|
use bin_reader::BinaryReader;
 | 
						|
 | 
						|
pub mod bin_reader;
 | 
						|
 | 
						|
const APP_PREFIX: &str = "rustdesk";
 | 
						|
const APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME";
 | 
						|
 | 
						|
fn setup(reader: BinaryReader, dir: Option<PathBuf>, clear: bool) -> Option<PathBuf> {
 | 
						|
    let dir = if let Some(dir) = dir {
 | 
						|
        dir
 | 
						|
    } else {
 | 
						|
        // home dir
 | 
						|
        if let Some(dir) = dirs::data_local_dir() {
 | 
						|
            dir.join(APP_PREFIX)
 | 
						|
        } else {
 | 
						|
            eprintln!("not found data local dir");
 | 
						|
            return None;
 | 
						|
        }
 | 
						|
    };
 | 
						|
    if clear {
 | 
						|
        std::fs::remove_dir_all(&dir).ok();
 | 
						|
    }
 | 
						|
    for file in reader.files.iter() {
 | 
						|
        file.write_to_file(&dir);
 | 
						|
    }
 | 
						|
    #[cfg(windows)]
 | 
						|
    windows::copy_runtime_broker(&dir);
 | 
						|
    #[cfg(linux)]
 | 
						|
    reader.configure_permission(&dir);
 | 
						|
    Some(dir.join(&reader.exe))
 | 
						|
}
 | 
						|
 | 
						|
fn execute(path: PathBuf, args: Vec<String>) {
 | 
						|
    println!("executing {}", path.display());
 | 
						|
    // setup env
 | 
						|
    let exe = std::env::current_exe().unwrap_or_default();
 | 
						|
    let exe_name = exe.file_name().unwrap_or_default();
 | 
						|
    // run executable
 | 
						|
    let mut cmd = Command::new(path);
 | 
						|
    cmd.args(args);
 | 
						|
    #[cfg(windows)]
 | 
						|
    {
 | 
						|
        use std::os::windows::process::CommandExt;
 | 
						|
        cmd.creation_flags(winapi::um::winbase::CREATE_NO_WINDOW);
 | 
						|
    }
 | 
						|
    cmd.env(APPNAME_RUNTIME_ENV_KEY, exe_name)
 | 
						|
        .stdin(Stdio::inherit())
 | 
						|
        .stdout(Stdio::inherit())
 | 
						|
        .stderr(Stdio::inherit())
 | 
						|
        .output()
 | 
						|
        .ok();
 | 
						|
}
 | 
						|
 | 
						|
fn main() {
 | 
						|
    let mut args = Vec::new();
 | 
						|
    let mut arg_exe = Default::default();
 | 
						|
    let mut i = 0;
 | 
						|
    for arg in std::env::args() {
 | 
						|
        if i == 0 {
 | 
						|
            arg_exe = arg.clone();
 | 
						|
        } else {
 | 
						|
            args.push(arg);
 | 
						|
        }
 | 
						|
        i += 1;
 | 
						|
    }
 | 
						|
    let click_setup = args.is_empty() && arg_exe.to_lowercase().ends_with("install.exe");
 | 
						|
    let quick_support = args.is_empty() && arg_exe.to_lowercase().ends_with("qs.exe");
 | 
						|
 | 
						|
    let reader = BinaryReader::default();
 | 
						|
    if let Some(exe) = setup(
 | 
						|
        reader,
 | 
						|
        None,
 | 
						|
        click_setup || args.contains(&"--silent-install".to_owned()),
 | 
						|
    ) {
 | 
						|
        if click_setup {
 | 
						|
            args = vec!["--install".to_owned()];
 | 
						|
        } else if quick_support {
 | 
						|
            args = vec!["--quick_support".to_owned()];
 | 
						|
        }
 | 
						|
        execute(exe, args);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#[cfg(windows)]
 | 
						|
mod windows {
 | 
						|
    use std::{fs, os::windows::process::CommandExt, path::PathBuf, process::Command};
 | 
						|
 | 
						|
    // Used for privacy mode(magnifier impl).
 | 
						|
    pub const RUNTIME_BROKER_EXE: &'static str = "C:\\Windows\\System32\\RuntimeBroker.exe";
 | 
						|
    pub const WIN_MAG_INJECTED_PROCESS_EXE: &'static str = "RuntimeBroker_rustdesk.exe";
 | 
						|
 | 
						|
    pub(super) fn copy_runtime_broker(dir: &PathBuf) {
 | 
						|
        let src = RUNTIME_BROKER_EXE;
 | 
						|
        let tgt = WIN_MAG_INJECTED_PROCESS_EXE;
 | 
						|
        let target_file = dir.join(tgt);
 | 
						|
        if target_file.exists() {
 | 
						|
            if let (Ok(src_file), Ok(tgt_file)) = (fs::read(src), fs::read(&target_file)) {
 | 
						|
                let src_md5 = format!("{:x}", md5::compute(&src_file));
 | 
						|
                let tgt_md5 = format!("{:x}", md5::compute(&tgt_file));
 | 
						|
                if src_md5 == tgt_md5 {
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        let _allow_err = Command::new("taskkill")
 | 
						|
            .args(&["/F", "/IM", "RuntimeBroker_rustdesk.exe"])
 | 
						|
            .creation_flags(winapi::um::winbase::CREATE_NO_WINDOW)
 | 
						|
            .output();
 | 
						|
        let _allow_err = std::fs::copy(src, &format!("{}\\{}", dir.to_string_lossy(), tgt));
 | 
						|
    }
 | 
						|
}
 |