From e1c2b8de6efe9104576ed7b048dea92e68086c89 Mon Sep 17 00:00:00 2001 From: 21pages Date: Mon, 26 Sep 2022 16:23:09 +0800 Subject: [PATCH 1/5] windows portable: request elevation && run as system Signed-off-by: 21pages --- Cargo.lock | 19 +++++++++++++++ Cargo.toml | 2 ++ src/client.rs | 6 ++++- src/core_main.rs | 6 +++++ src/platform/windows.rs | 53 ++++++++++++++++++++++++++++++++++++++--- 5 files changed, 82 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60852eba1..48f47a86f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2537,6 +2537,14 @@ dependencies = [ "tiff", ] +[[package]] +name = "impersonate_system" +version = "0.1.0" +source = "git+https://github.com/21pages/impersonate-system#af4a82050580217a434c2024e181a98de24823ec" +dependencies = [ + "cc", +] + [[package]] name = "include_dir" version = "0.7.2" @@ -2593,6 +2601,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +[[package]] +name = "is_elevated" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5299060ff5db63e788015dcb9525ad9b84f4fd9717ed2cbdeba5018cbf42f9b5" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "itertools" version = "0.9.0" @@ -4329,7 +4346,9 @@ dependencies = [ "flutter_rust_bridge_codegen", "hbb_common", "hound", + "impersonate_system", "include_dir", + "is_elevated", "jni", "lazy_static", "libc", diff --git a/Cargo.toml b/Cargo.toml index 062e32abb..f8b93c2cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,6 +91,8 @@ winapi = { version = "0.3", features = ["winuser"] } winreg = "0.10" windows-service = "0.4" virtual_display = { path = "libs/virtual_display" } +is_elevated = "0.1.2" +impersonate_system = { git = "https://github.com/21pages/impersonate-system" } [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2" diff --git a/src/client.rs b/src/client.rs index c70956b63..214af6cf7 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1354,7 +1354,11 @@ impl LoginConfigHandler { username: self.id.clone(), password: password.into(), my_id, - my_name: crate::username(), + my_name: if cfg!(windows) { + crate::platform::get_active_username() + } else { + crate::username() + }, option: self.get_option_message(true).into(), session_id: self.session_id, version: crate::VERSION.to_string(), diff --git a/src/core_main.rs b/src/core_main.rs index f514cd790..7c86bdd19 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -57,6 +57,12 @@ pub fn core_main() -> Option> { .ok(); } } + #[cfg(windows)] + #[cfg(not(debug_assertions))] + if !crate::platform::is_installed() && args.is_empty() { + let arg = if is_setup { "--noinstall" } else { "" }; + crate::platform::run_check_elevation(arg); + } if args.is_empty() { std::thread::spawn(move || crate::start_server(false)); } else { diff --git a/src/platform/windows.rs b/src/platform/windows.rs index fa9fb5b10..be549f7e1 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1420,16 +1420,63 @@ pub fn get_user_token(session_id: u32, as_user: bool) -> HANDLE { } } -pub fn check_super_user_permission() -> ResultType { +pub fn run_uac(exe: &str, arg: &str) -> ResultType { unsafe { + let cstring; let ret = ShellExecuteA( NULL as _, CString::new("runas")?.as_ptr() as _, - CString::new("cmd")?.as_ptr() as _, - CString::new("/c /q")?.as_ptr() as _, + CString::new(exe)?.as_ptr() as _, + if arg.is_empty() { + NULL as _ + } else { + cstring = CString::new(arg)?; + cstring.as_ptr() as _ + }, NULL as _, SW_SHOWNORMAL, ); return Ok(ret as i32 > 32); } } + +pub fn check_super_user_permission() -> ResultType { + run_uac("cmd", "/c /q") +} + +pub fn elevate(arg: &str) -> ResultType { + run_uac( + std::env::current_exe()? + .to_string_lossy() + .to_string() + .as_str(), + arg, + ) +} + +pub fn run_as_system(arg: &str) -> ResultType<()> { + let exe = std::env::current_exe()?.to_string_lossy().to_string(); + if impersonate_system::run_as_system(&exe, arg).is_err() { + bail!(format!("Failed to run {} as system", exe)); + } + Ok(()) +} + +pub fn run_check_elevation(arg: &str) { + if !is_elevated::is_elevated() { + if let Ok(true) = elevate(arg) { + std::process::exit(0); + } else { + // do nothing but prompt + } + } else { + if !is_root() { + if run_as_system(arg).is_ok() { + std::process::exit(0); + } else { + // to-do: should not happen + log::error!("Failed to run as system"); + } + } + } +} From 728985e3bf10ab0049fde048e26f501ac5630283 Mon Sep 17 00:00:00 2001 From: 21pages Date: Tue, 27 Sep 2022 13:30:49 +0800 Subject: [PATCH 2/5] elevation prompt && uac warning Signed-off-by: 21pages --- .../lib/desktop/pages/desktop_home_page.dart | 9 +++++++ libs/hbb_common/protos/message.proto | 1 + src/client/io_loop.rs | 6 +++++ src/flutter_ffi.rs | 8 ++++++ src/lang/cn.rs | 3 +++ src/lang/cs.rs | 3 +++ src/lang/da.rs | 3 +++ src/lang/de.rs | 3 +++ src/lang/en.rs | 2 ++ src/lang/eo.rs | 3 +++ src/lang/es.rs | 3 +++ src/lang/fr.rs | 3 +++ src/lang/hu.rs | 3 +++ src/lang/id.rs | 3 +++ src/lang/it.rs | 3 +++ src/lang/ja.rs | 3 +++ src/lang/ko.rs | 3 +++ src/lang/kz.rs | 3 +++ src/lang/pl.rs | 3 +++ src/lang/pt_PT.rs | 3 +++ src/lang/ptbr.rs | 3 +++ src/lang/ru.rs | 3 +++ src/lang/sk.rs | 3 +++ src/lang/template.rs | 3 +++ src/lang/tr.rs | 3 +++ src/lang/tw.rs | 3 +++ src/lang/vn.rs | 3 +++ src/server/connection.rs | 15 +++++++++++ src/server/video_service.rs | 19 +++++++++++++ src/ui.rs | 27 ++++++++----------- src/ui/index.tis | 6 +++++ src/ui_interface.rs | 13 +++++++++ 32 files changed, 156 insertions(+), 16 deletions(-) diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index f25e3263a..fcc8c4991 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -407,6 +407,15 @@ class _DesktopHomePageState extends State @override void initState() { super.initState(); + Timer(const Duration(seconds: 1), () async { + final installed = bind.mainIsInstalled(); + final root = await bind.mainIsRoot(); + final release = await bind.mainIsRelease(); + if (Platform.isWindows && release && !installed && !root) { + msgBox('custom-elevation-nocancel', 'Prompt', 'elevation_prompt', + gFFI.dialogManager); + } + }); Timer(const Duration(seconds: 5), () async { updateUrl = await bind.mainGetSoftwareUpdateUrl(); if (updateUrl.isNotEmpty) setState(() {}); diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 8fb67e5c1..1ed538759 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -556,6 +556,7 @@ message Misc { bool video_received = 12; BackNotification back_notification = 13; bool restart_remote_device = 14; + bool uac = 15; } } diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index cf6168834..619c67b79 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -979,6 +979,12 @@ impl Remote { return false; } } + Some(misc::Union::Uac(uac)) => { + if uac { + self.handler + .msgbox("custom-uac-nocancel", "Warning", "uac_warning"); + } + } _ => {} }, Some(message::Union::TestDelay(t)) => { diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 1adee6988..d4c198eea 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -800,6 +800,14 @@ pub fn main_has_hwcodec() -> SyncReturn { SyncReturn(has_hwcodec()) } +pub fn main_is_root() -> bool { + is_root() +} + +pub fn main_is_release() -> bool { + is_release() +} + pub fn session_send_mouse(id: String, msg: String) { if let Ok(m) = serde_json::from_str::>(&msg) { let alt = m.get("alt").is_some(); diff --git a/src/lang/cn.rs b/src/lang/cn.rs index c974bf7fe..ab92b047b 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", "允许局域网发现"), ("Deny LAN Discovery", "拒绝局域网发现"), ("Write a message", "输入聊天消息"), + ("Prompt", "提示"), + ("elevation_prompt", "以当前用户权限运行软件,可能导致远端在访问本机时,没有足够的权限来操作部分窗口。"), + ("uac_warning", "暂时无法访问远端设备,因为远端设备正在请求用户账户权限,请等待对方关闭UAC窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index def7206a7..8c89e5552 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 8151ea4e0..18f5af14e 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 57596f709..0f8fe34b3 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 14232c4e2..e4c862203 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -30,5 +30,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("android_open_battery_optimizations_tip", "If you want to disable this feature, please go to the next RustDesk application settings page, find and enter [Battery], Uncheck [Unrestricted]"), ("remote_restarting_tip", "Remote device is restarting, please close this message box and reconnect with permanent password after a while"), ("Are you sure to close the connection?", "Are you sure you want to close the connection?"), + ("elevation_prompt", "Running software without privilege elevation may cause problems when remote users operate certain windows."), + ("uac_warning", "Temporarily denied access due to elevation request, please wait for the remote user to accept the UAC dialog. To avoid this problem, it is recommended to install the software on the remote device or run it with administrator privileges."), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index cc21e7509..226255eb3 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 1e57c6913..5a31d730b 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 479c701bf..cf9109378 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 1847c8cc5..17467077a 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index ebb83c862..57e5669ae 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 2db9f3026..1c59a319d 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 0021f0db9..a20b5436a 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 89bc69fa2..1c11c54e3 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 6eea0d8be..6c576b497 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -359,5 +359,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 1f101a069..983fe5b48 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index ab49d9f93..13f645d95 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 640a35d10..66636bc20 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index f1d9c6f31..205874a5b 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index a7b527302..a0ec2682a 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index e879b2a21..20112dd81 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 50ce2ec2a..1df6473d7 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index c02c95df1..271bfc829 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", "允許局域網發現"), ("Deny LAN Discovery", "拒絕局域網發現"), ("Write a message", "輸入聊天消息"), + ("Prompt", "提示"), + ("elevation_prompt", "以當前用戶權限運行軟件,可能導致遠端在訪問本機時,沒有足夠的權限來操作部分窗口。"), + ("uac_warning", "暂时无法访问远端设备,因为远端设备正在请求用户账户权限,请等待对方关闭UAC窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index dce16bb7b..9f6841d10 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -360,5 +360,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enable LAN Discovery", ""), ("Deny LAN Discovery", ""), ("Write a message", ""), + ("Prompt", ""), + ("elevation_prompt", ""), + ("uac_warning", ""), ].iter().cloned().collect(); } diff --git a/src/server/connection.rs b/src/server/connection.rs index 15d313fbe..056c906fa 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -229,6 +229,8 @@ impl Connection { #[cfg(not(any(target_os = "android", target_os = "ios")))] std::thread::spawn(move || Self::handle_input(rx_input, tx_cloned)); + let mut second_timer = time::interval(Duration::from_secs(1)); + let mut uac = false; loop { tokio::select! { @@ -400,6 +402,19 @@ impl Connection { break; } }, + _ = second_timer.tick() => { + let is_uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone(); + if uac != is_uac { + if !crate::platform::is_installed() && !crate::platform::is_root() { + uac = is_uac; + let mut misc = Misc::new(); + misc.set_uac(uac); + let mut msg = Message::new(); + msg.set_misc(misc); + conn.inner.send(msg.into()); + } + } + } _ = test_delay_timer.tick() => { if last_recv_time.elapsed() >= SEC30 { conn.on_close("Timeout", true).await; diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 272bcf8d5..25806f0aa 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -33,6 +33,7 @@ use std::{ collections::HashSet, io::ErrorKind::WouldBlock, ops::{Deref, DerefMut}, + sync::Once, time::{self, Duration, Instant}, }; #[cfg(windows)] @@ -51,6 +52,7 @@ lazy_static::lazy_static! { static ref PRIVACY_MODE_CONN_ID: Mutex = Mutex::new(0); static ref IS_CAPTURER_MAGNIFIER_SUPPORTED: bool = is_capturer_mag_supported(); pub static ref VIDEO_QOS: Arc> = Default::default(); + pub static ref IS_UAC_RUNNING: Arc> = Default::default(); } fn is_capturer_mag_supported() -> bool { @@ -451,6 +453,8 @@ fn run(sp: GenericService) -> ResultType<()> { }; #[cfg(any(target_os = "android", target_os = "ios"))] let recorder: Arc>> = Default::default(); + #[cfg(windows)] + start_uac_check(); while sp.ok() { #[cfg(windows)] @@ -832,3 +836,18 @@ pub(super) fn get_current_display_2(mut all: Vec) -> ResultType<(usize, fn get_current_display() -> ResultType<(usize, usize, Display)> { get_current_display_2(try_get_displays()?) } + +#[cfg(windows)] +fn start_uac_check() { + static START: Once = Once::new(); + START.call_once(|| { + if !crate::platform::is_installed() && !crate::platform::is_root() { + std::thread::spawn(|| loop { + std::thread::sleep(std::time::Duration::from_secs(1)); + if let Ok(uac) = crate::ui::win_privacy::is_process_consent_running() { + *IS_UAC_RUNNING.lock().unwrap() = uac; + } + }); + } + }); +} diff --git a/src/ui.rs b/src/ui.rs index 095559811..63dc4704a 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -20,22 +20,7 @@ use hbb_common::{ use crate::common::get_app_name; use crate::ipc; -use crate::ui_interface::{ - check_mouse_time, closing, create_shortcut, current_is_wayland, default_video_save_directory, - fix_login_wayland, forget_password, get_api_server, get_async_job_status, get_connect_status, - get_error, get_fav, get_icon, get_lan_peers, get_langs, get_license, get_local_option, - get_mouse_time, get_new_version, get_option, get_options, get_peer, get_peer_option, - get_recent_sessions, get_remote_id, get_size, get_socks, get_software_ext, - get_software_store_path, get_software_update_url, get_uuid, get_version, goto_install, - has_hwcodec, has_rendezvous_service, install_me, install_path, is_can_screen_recording, - is_installed, is_installed_daemon, is_installed_lower_version, is_login_wayland, - is_ok_change_id, is_process_trusted, is_rdp_service_open, is_share_rdp, is_xfce, - modify_default_login, new_remote, open_url, peer_has_password, permanent_password, - post_request, recent_sessions_updated, remove_peer, run_without_install, set_local_option, - set_option, set_options, set_peer_option, set_permanent_password, set_remote_id, set_share_rdp, - set_socks, show_run_without_install, store_fav, t, temporary_password, test_if_valid_server, - update_me, update_temporary_password, using_public_server, -}; +use crate::ui_interface::*; mod cm; #[cfg(feature = "inline")] @@ -349,6 +334,14 @@ impl UI { is_installed() } + fn is_root(&self) -> bool { + is_root() + } + + fn is_release(&self) -> bool { + is_release() + } + fn is_rdp_service_open(&self) -> bool { is_rdp_service_open() } @@ -615,6 +608,8 @@ impl sciter::EventHandler for UI { fn get_icon(); fn install_me(String, String); fn is_installed(); + fn is_root(); + fn is_release(); fn set_socks(String, String, String); fn get_socks(); fn is_rdp_service_open(); diff --git a/src/ui/index.tis b/src/ui/index.tis index b889ff010..a2d895733 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -1242,3 +1242,9 @@ function refreshCurrentUser() { function getHttpHeaders() { return "Authorization: Bearer " + handler.get_local_option("access_token"); } + +$(body).timer(1000, function check_elevation(){ + if (is_win && handler.is_release() && !handler.is_installed() && !handler.is_root()) { + msgbox("custom-elevation-nocancel", "Prompt", "elevation_prompt"); + } +}); \ No newline at end of file diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 31c203fb4..3e357faa7 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -755,6 +755,19 @@ pub fn has_hwcodec() -> bool { return true; } +#[inline] +pub fn is_release() -> bool { + #[cfg(not(debug_assertions))] + return true; + #[cfg(debug_assertions)] + return false; +} + +#[inline] +pub fn is_root() -> bool { + crate::platform::is_root() +} + #[inline] pub fn check_super_user_permission() -> bool { #[cfg(any(windows, target_os = "linux"))] From ae8d97eb724c52e75b2c0dd5a9af76eafd42f427 Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 28 Sep 2022 10:55:19 +0800 Subject: [PATCH 3/5] deal with flutter SYSTEM user Signed-off-by: 21pages --- flutter/lib/models/native_model.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index 666116d78..54895f947 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -106,7 +106,12 @@ class PlatformFFI { debugPrint('initializing FFI $_appType'); try { _translate = dylib.lookupFunction('translate'); - _dir = (await getApplicationDocumentsDirectory()).path; + try { + // SYSTEM user failed + _dir = (await getApplicationDocumentsDirectory()).path; + } catch (e) { + debugPrint('Failed to get documents directory: $e'); + } _ffiBind = RustdeskImpl(dylib); _startListenEvent(_ffiBind); // global event try { From 02aedd234c27152ce5964ab2b215fd322f9a2ed7 Mon Sep 17 00:00:00 2001 From: 21pages Date: Wed, 28 Sep 2022 20:48:14 +0800 Subject: [PATCH 4/5] prompt foreground window elevation Signed-off-by: 21pages --- Cargo.lock | 10 ---- Cargo.toml | 1 - libs/hbb_common/protos/message.proto | 1 + src/client/io_loop.rs | 9 ++++ src/lang/cn.rs | 1 + src/lang/cs.rs | 1 + src/lang/da.rs | 1 + src/lang/de.rs | 1 + src/lang/en.rs | 3 +- src/lang/eo.rs | 1 + src/lang/es.rs | 1 + src/lang/fr.rs | 1 + src/lang/hu.rs | 1 + src/lang/id.rs | 1 + src/lang/it.rs | 1 + src/lang/ja.rs | 1 + src/lang/ko.rs | 1 + src/lang/kz.rs | 1 + src/lang/pl.rs | 1 + src/lang/pt_PT.rs | 1 + src/lang/ptbr.rs | 1 + src/lang/ru.rs | 1 + src/lang/sk.rs | 1 + src/lang/template.rs | 1 + src/lang/tr.rs | 1 + src/lang/tw.rs | 1 + src/lang/vn.rs | 1 + src/platform/windows.rs | 72 ++++++++++++++++++++++++++-- src/server/connection.rs | 30 +++++++----- src/server/video_service.rs | 13 +++-- 30 files changed, 131 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48f47a86f..55949fe8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2601,15 +2601,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" -[[package]] -name = "is_elevated" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5299060ff5db63e788015dcb9525ad9b84f4fd9717ed2cbdeba5018cbf42f9b5" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "itertools" version = "0.9.0" @@ -4348,7 +4339,6 @@ dependencies = [ "hound", "impersonate_system", "include_dir", - "is_elevated", "jni", "lazy_static", "libc", diff --git a/Cargo.toml b/Cargo.toml index f8b93c2cd..919f39d1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,7 +91,6 @@ winapi = { version = "0.3", features = ["winuser"] } winreg = "0.10" windows-service = "0.4" virtual_display = { path = "libs/virtual_display" } -is_elevated = "0.1.2" impersonate_system = { git = "https://github.com/21pages/impersonate-system" } [target.'cfg(target_os = "macos")'.dependencies] diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index 1ed538759..1f3d24157 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -557,6 +557,7 @@ message Misc { BackNotification back_notification = 13; bool restart_remote_device = 14; bool uac = 15; + bool foreground_window_elevated = 16; } } diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 619c67b79..7e3bbb3dc 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -985,6 +985,15 @@ impl Remote { .msgbox("custom-uac-nocancel", "Warning", "uac_warning"); } } + Some(misc::Union::ForegroundWindowElevated(elevated)) => { + if elevated { + self.handler.msgbox( + "custom-elevated-foreground-nocancel", + "Warning", + "elevated_foreground_window_warning", + ); + } + } _ => {} }, Some(message::Union::TestDelay(t)) => { diff --git a/src/lang/cn.rs b/src/lang/cn.rs index ab92b047b..3dc5dc434 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", "提示"), ("elevation_prompt", "以当前用户权限运行软件,可能导致远端在访问本机时,没有足够的权限来操作部分窗口。"), ("uac_warning", "暂时无法访问远端设备,因为远端设备正在请求用户账户权限,请等待对方关闭UAC窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"), + ("elevated_foreground_window_warning", "暂时无法使用鼠标键盘,因为远端桌面的当前窗口需要更高的权限才能操作, 可以请求对方最小化当前窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 8c89e5552..81df20cc9 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 18f5af14e..18e4e4949 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 0f8fe34b3..df7c5f238 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index e4c862203..279f26cd1 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -32,5 +32,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Are you sure to close the connection?", "Are you sure you want to close the connection?"), ("elevation_prompt", "Running software without privilege elevation may cause problems when remote users operate certain windows."), ("uac_warning", "Temporarily denied access due to elevation request, please wait for the remote user to accept the UAC dialog. To avoid this problem, it is recommended to install the software on the remote device or run it with administrator privileges."), - ].iter().cloned().collect(); + ("elevated_foreground_window_warning", "Temporarily unable to use the mouse and keyboard, because the current window of the remote desktop requires higher privilege to operate, you can request the remote user to minimize the current window. To avoid this problem, it is recommended to install the software on the remote device or run it with administrator privileges."), + ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 226255eb3..578f9cef4 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 5a31d730b..42470b120 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index cf9109378..ce054a021 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 17467077a..caf74eaaa 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 57e5669ae..e993f2042 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 1c59a319d..2f5115171 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index a20b5436a..c5ebb9b15 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 1c11c54e3..069210625 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 6c576b497..45f2ecdc5 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -362,5 +362,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 983fe5b48..bcef81afc 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 13f645d95..3e1c505e6 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 66636bc20..7d8ce5ac7 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 205874a5b..30bc52d95 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index a0ec2682a..5c3b7ef6e 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 20112dd81..2a2d6eb8a 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 1df6473d7..8daa4bb88 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 271bfc829..5f9a6632c 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", "提示"), ("elevation_prompt", "以當前用戶權限運行軟件,可能導致遠端在訪問本機時,沒有足夠的權限來操作部分窗口。"), ("uac_warning", "暂时无法访问远端设备,因为远端设备正在请求用户账户权限,请等待对方关闭UAC窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"), + ("elevated_foreground_window_warning", "暫時無法使用鼠標鍵盤,因為遠端桌面的當前窗口需要更高的權限才能操作, 可以請求對方最小化當前窗口。為避免這個問題,建議在遠端設備上安裝或者以管理員權限運行本軟件。"), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 9f6841d10..541436331 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -363,5 +363,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Prompt", ""), ("elevation_prompt", ""), ("uac_warning", ""), + ("elevated_foreground_window_warning", ""), ].iter().cloned().collect(); } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index be549f7e1..b5a595b5a 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -14,11 +14,21 @@ use std::{ time::{Duration, Instant}, }; use winapi::{ + ctypes::c_void, shared::{minwindef::*, ntdef::NULL, windef::*}, um::{ - errhandlingapi::GetLastError, handleapi::CloseHandle, minwinbase::STILL_ACTIVE, - processthreadsapi::GetExitCodeProcess, shellapi::ShellExecuteA, winbase::*, wingdi::*, - winnt::HANDLE, winuser::*, + errhandlingapi::GetLastError, + handleapi::CloseHandle, + minwinbase::STILL_ACTIVE, + processthreadsapi::{GetCurrentProcess, GetExitCodeProcess, OpenProcess, OpenProcessToken}, + securitybaseapi::GetTokenInformation, + shellapi::ShellExecuteA, + winbase::*, + wingdi::*, + winnt::{ + TokenElevation, HANDLE, PROCESS_QUERY_LIMITED_INFORMATION, TOKEN_ELEVATION, TOKEN_QUERY, + }, + winuser::*, }, }; use windows_service::{ @@ -1463,7 +1473,7 @@ pub fn run_as_system(arg: &str) -> ResultType<()> { } pub fn run_check_elevation(arg: &str) { - if !is_elevated::is_elevated() { + if let Ok(false) = is_elevated(None) { if let Ok(true) = elevate(arg) { std::process::exit(0); } else { @@ -1480,3 +1490,57 @@ pub fn run_check_elevation(arg: &str) { } } } + +// https://github.com/mgostIH/process_list/blob/master/src/windows/mod.rs +#[repr(transparent)] +pub(self) struct RAIIHandle(pub HANDLE); + +impl Drop for RAIIHandle { + fn drop(&mut self) { + // This never gives problem except when running under a debugger. + unsafe { CloseHandle(self.0) }; + } +} + +pub fn is_elevated(process_id: Option) -> ResultType { + unsafe { + let handle: HANDLE = match process_id { + Some(process_id) => OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id), + None => GetCurrentProcess(), + }; + if handle == NULL { + bail!("Failed to open process, errno {}", GetLastError()) + } + let _handle = RAIIHandle(handle); + let mut token: HANDLE = mem::zeroed(); + if OpenProcessToken(handle, TOKEN_QUERY, &mut token) == FALSE { + bail!("Failed to open process token, errno {}", GetLastError()) + } + let _token = RAIIHandle(token); + let mut token_elevation: TOKEN_ELEVATION = mem::zeroed(); + let mut size: DWORD = 0; + if GetTokenInformation( + token, + TokenElevation, + (&mut token_elevation) as *mut _ as *mut c_void, + mem::size_of::() as _, + &mut size, + ) == FALSE + { + bail!("Failed to get token information, errno {}", GetLastError()) + } + + Ok(token_elevation.TokenIsElevated != 0) + } +} + +pub fn is_foreground_window_elevated() -> ResultType { + unsafe { + let mut process_id: DWORD = 0; + GetWindowThreadProcessId(GetForegroundWindow(), &mut process_id); + if process_id == 0 { + bail!("Failed to get processId, errno {}", GetLastError()) + } + is_elevated(Some(process_id)) + } +} diff --git a/src/server/connection.rs b/src/server/connection.rs index 056c906fa..8ad408885 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -230,7 +230,8 @@ impl Connection { #[cfg(not(any(target_os = "android", target_os = "ios")))] std::thread::spawn(move || Self::handle_input(rx_input, tx_cloned)); let mut second_timer = time::interval(Duration::from_secs(1)); - let mut uac = false; + let mut last_uac = false; + let mut last_foreground_window_elevated = false; loop { tokio::select! { @@ -403,16 +404,23 @@ impl Connection { } }, _ = second_timer.tick() => { - let is_uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone(); - if uac != is_uac { - if !crate::platform::is_installed() && !crate::platform::is_root() { - uac = is_uac; - let mut misc = Misc::new(); - misc.set_uac(uac); - let mut msg = Message::new(); - msg.set_misc(misc); - conn.inner.send(msg.into()); - } + let uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone(); + if last_uac != uac { + last_uac = uac; + let mut misc = Misc::new(); + misc.set_uac(uac); + let mut msg = Message::new(); + msg.set_misc(misc); + conn.inner.send(msg.into()); + } + let foreground_window_elevated = crate::video_service::IS_FOREGROUND_WINDOW_ELEVATED.lock().unwrap().clone(); + if last_foreground_window_elevated != foreground_window_elevated { + last_foreground_window_elevated = foreground_window_elevated; + let mut misc = Misc::new(); + misc.set_foreground_window_elevated(foreground_window_elevated); + let mut msg = Message::new(); + msg.set_misc(misc); + conn.inner.send(msg.into()); } } _ = test_delay_timer.tick() => { diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 25806f0aa..ad6f5f620 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -53,6 +53,7 @@ lazy_static::lazy_static! { static ref IS_CAPTURER_MAGNIFIER_SUPPORTED: bool = is_capturer_mag_supported(); pub static ref VIDEO_QOS: Arc> = Default::default(); pub static ref IS_UAC_RUNNING: Arc> = Default::default(); + pub static ref IS_FOREGROUND_WINDOW_ELEVATED: Arc> = Default::default(); } fn is_capturer_mag_supported() -> bool { @@ -454,7 +455,7 @@ fn run(sp: GenericService) -> ResultType<()> { #[cfg(any(target_os = "android", target_os = "ios"))] let recorder: Arc>> = Default::default(); #[cfg(windows)] - start_uac_check(); + start_uac_elevation_check(); while sp.ok() { #[cfg(windows)] @@ -838,15 +839,21 @@ fn get_current_display() -> ResultType<(usize, usize, Display)> { } #[cfg(windows)] -fn start_uac_check() { +fn start_uac_elevation_check() { static START: Once = Once::new(); START.call_once(|| { - if !crate::platform::is_installed() && !crate::platform::is_root() { + if !crate::platform::is_installed() + && !crate::platform::is_root() + && !crate::platform::is_elevated(None).map_or(false, |b| b) + { std::thread::spawn(|| loop { std::thread::sleep(std::time::Duration::from_secs(1)); if let Ok(uac) = crate::ui::win_privacy::is_process_consent_running() { *IS_UAC_RUNNING.lock().unwrap() = uac; } + if let Ok(elevated) = crate::platform::is_foreground_window_elevated() { + *IS_FOREGROUND_WINDOW_ELEVATED.lock().unwrap() = elevated; + } }); } }); From 9d8032e5e79fd285521f4f8040dad22e2a0e5ca8 Mon Sep 17 00:00:00 2001 From: 21pages Date: Thu, 29 Sep 2022 09:00:04 +0800 Subject: [PATCH 5/5] add arg to avoid possible recursive run Signed-off-by: 21pages --- src/core_main.rs | 13 +++++++++--- src/platform/windows.rs | 46 +++++++++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/core_main.rs b/src/core_main.rs index 7c86bdd19..d159e115e 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -8,12 +8,20 @@ pub fn core_main() -> Option> { let mut args = Vec::new(); let mut i = 0; let mut is_setup = false; + let mut _is_elevate = false; + let mut _is_run_as_system = false; for arg in std::env::args() { // to-do: how to pass to flutter? if i == 0 && crate::common::is_setup(&arg) { is_setup = true; } else if i > 0 { - args.push(arg); + if arg == "--elevate" { + _is_elevate = true; + } else if arg == "--run-as-system" { + _is_run_as_system = true; + } else { + args.push(arg); + } } i += 1; } @@ -60,8 +68,7 @@ pub fn core_main() -> Option> { #[cfg(windows)] #[cfg(not(debug_assertions))] if !crate::platform::is_installed() && args.is_empty() { - let arg = if is_setup { "--noinstall" } else { "" }; - crate::platform::run_check_elevation(arg); + crate::platform::elevate_or_run_as_system(is_setup, _is_elevate, _is_run_as_system); } if args.is_empty() { std::thread::spawn(move || crate::start_server(false)); diff --git a/src/platform/windows.rs b/src/platform/windows.rs index b5a595b5a..10b0dcee6 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1472,22 +1472,50 @@ pub fn run_as_system(arg: &str) -> ResultType<()> { Ok(()) } -pub fn run_check_elevation(arg: &str) { - if let Ok(false) = is_elevated(None) { - if let Ok(true) = elevate(arg) { - std::process::exit(0); - } else { - // do nothing but prompt - } +pub fn elevate_or_run_as_system(is_setup: bool, is_elevate: bool, is_run_as_system: bool) { + // avoid possible run recursively due to failed run, which hasn't happened yet. + let arg_elevate = if is_setup { + "--noinstall --elevate" } else { + "--elevate" + }; + let arg_run_as_system = if is_setup { + "--noinstall --run-as-system" + } else { + "--run-as-system" + }; + let rerun_as_system = || { if !is_root() { - if run_as_system(arg).is_ok() { + if run_as_system(arg_run_as_system).is_ok() { std::process::exit(0); } else { - // to-do: should not happen log::error!("Failed to run as system"); } } + }; + + if is_elevate { + if !is_elevated(None).map_or(true, |b| b) { + log::error!("Failed to elevate"); + return; + } + rerun_as_system(); + } else if is_run_as_system { + if !is_root() { + log::error!("Failed to be system"); + } + } else { + if let Ok(true) = is_elevated(None) { + // right click + rerun_as_system(); + } else { + // left click || run without install + if let Ok(true) = elevate(arg_elevate) { + std::process::exit(0); + } else { + // do nothing but prompt + } + } } }