Files
rustdesk/libs/portable/src/main.rs
RustDesk 21a7cef98a keep-awake-during-incoming-sessions (#14082)
* keep-awake-during-incoming-sessions

* Update flutter/lib/desktop/pages/desktop_setting_page.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update flutter/lib/common.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update flutter/lib/mobile/pages/settings_page.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update common.dart

* wakelock

Signed-off-by: 21pages <sunboeasy@gmail.com>

* fix build

Signed-off-by: 21pages <sunboeasy@gmail.com>

* Update server_model.dart

---------

Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: 21pages <sunboeasy@gmail.com>
2026-01-21 16:25:57 +08:00

249 lines
7.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#![windows_subsystem = "windows"]
use std::{
path::{Path, PathBuf},
process::{Command, Stdio},
};
use bin_reader::BinaryReader;
pub mod bin_reader;
#[cfg(windows)]
mod ui;
#[cfg(windows)]
const APP_METADATA: &[u8] = include_bytes!("../app_metadata.toml");
#[cfg(not(windows))]
const APP_METADATA: &[u8] = &[];
const APP_METADATA_CONFIG: &str = "meta.toml";
const META_LINE_PREFIX_TIMESTAMP: &str = "timestamp = ";
const APP_PREFIX: &str = "rustdesk";
const APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME";
#[cfg(windows)]
const SET_FOREGROUND_WINDOW_ENV_KEY: &str = "SET_FOREGROUND_WINDOW";
fn is_timestamp_matches(dir: &Path, ts: &mut u64) -> bool {
let Ok(app_metadata) = std::str::from_utf8(APP_METADATA) else {
return true;
};
for line in app_metadata.lines() {
if line.starts_with(META_LINE_PREFIX_TIMESTAMP) {
if let Ok(stored_ts) = line.replace(META_LINE_PREFIX_TIMESTAMP, "").parse::<u64>() {
*ts = stored_ts;
break;
}
}
}
if *ts == 0 {
return true;
}
if let Ok(content) = std::fs::read_to_string(dir.join(APP_METADATA_CONFIG)) {
for line in content.lines() {
if line.starts_with(META_LINE_PREFIX_TIMESTAMP) {
if let Ok(stored_ts) = line.replace(META_LINE_PREFIX_TIMESTAMP, "").parse::<u64>() {
return *ts == stored_ts;
}
}
}
}
false
}
fn write_meta(dir: &Path, ts: u64) {
let meta_file = dir.join(APP_METADATA_CONFIG);
if ts != 0 {
let content = format!("{}{}", META_LINE_PREFIX_TIMESTAMP, ts);
// Ignore is ok here
let _ = std::fs::write(meta_file, content);
}
}
fn setup(
reader: BinaryReader,
dir: Option<PathBuf>,
clear: bool,
_args: &Vec<String>,
_ui: &mut 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;
}
};
let mut ts = 0;
if clear || !is_timestamp_matches(&dir, &mut ts) {
#[cfg(windows)]
if _args.is_empty() {
*_ui = true;
ui::setup();
}
std::fs::remove_dir_all(&dir).ok();
}
for file in reader.files.iter() {
file.write_to_file(&dir);
}
write_meta(&dir, ts);
#[cfg(windows)]
win::copy_runtime_broker(&dir);
#[cfg(linux)]
reader.configure_permission(&dir);
Some(dir.join(&reader.exe))
}
fn use_null_stdio() -> bool {
#[cfg(windows)]
{
// When running in CMD on Windows 7, using Stdio::inherit() with spawn returns an "invalid handle" error.
// Since using Stdio::null() didnt cause any issues, and determining whether the program is launched from CMD or by double-clicking would require calling more APIs during startup, we also use Stdio::null() when launched by double-clicking on Windows 7.
let is_windows_7 = is_windows_7();
println!("is windows7: {}", is_windows_7);
return is_windows_7;
}
#[cfg(not(windows))]
false
}
#[cfg(windows)]
fn is_windows_7() -> bool {
use windows::Wdk::System::SystemServices::RtlGetVersion;
use windows::Win32::System::SystemInformation::OSVERSIONINFOW;
unsafe {
let mut version_info = OSVERSIONINFOW::default();
version_info.dwOSVersionInfoSize = std::mem::size_of::<OSVERSIONINFOW>() as u32;
if RtlGetVersion(&mut version_info).is_ok() {
// Windows 7 is version 6.1
println!(
"Windows version: {}.{}",
version_info.dwMajorVersion, version_info.dwMinorVersion
);
return version_info.dwMajorVersion == 6 && version_info.dwMinorVersion == 1;
}
}
false
}
fn execute(path: PathBuf, args: Vec<String>, _ui: bool) {
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);
if _ui {
cmd.env(SET_FOREGROUND_WINDOW_ENV_KEY, "1");
}
}
cmd.env(APPNAME_RUNTIME_ENV_KEY, exe_name);
if use_null_stdio() {
cmd.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null());
} else {
cmd.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit());
}
let _child = cmd.spawn();
#[cfg(windows)]
if _ui {
match _child {
Ok(child) => unsafe {
winapi::um::winuser::AllowSetForegroundWindow(child.id() as u32);
},
Err(e) => {
eprintln!("{:?}", e);
}
}
}
}
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");
#[cfg(windows)]
let quick_support = args.is_empty() && win::is_quick_support_exe(&arg_exe);
#[cfg(not(windows))]
let quick_support = false;
let mut ui = false;
let reader = BinaryReader::default();
if let Some(exe) = setup(
reader,
None,
click_setup || args.contains(&"--silent-install".to_owned()),
&args,
&mut ui,
) {
if click_setup {
args = vec!["--install".to_owned()];
} else if quick_support {
args = vec!["--quick_support".to_owned()];
}
execute(exe, args, ui);
}
}
#[cfg(windows)]
mod win {
use std::{fs, os::windows::process::CommandExt, path::Path, process::Command};
// Used for privacy mode(magnifier impl).
pub const RUNTIME_BROKER_EXE: &'static str = "C:\\Windows\\System32\\RuntimeBroker.exe";
pub const WIN_TOPMOST_INJECTED_PROCESS_EXE: &'static str = "RuntimeBroker_rustdesk.exe";
pub(super) fn copy_runtime_broker(dir: &Path) {
let src = RUNTIME_BROKER_EXE;
let tgt = WIN_TOPMOST_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));
}
/// Check if the executable is a Quick Support version.
/// Note: This function must be kept in sync with `src/core_main.rs`.
#[inline]
pub(super) fn is_quick_support_exe(exe: &str) -> bool {
let exe = exe.to_lowercase();
exe.contains("-qs-") || exe.contains("-qs.exe") || exe.contains("_qs.exe")
}
}