privacy_mode_win_magnifier: fix UAC prompt window

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2022-06-01 23:57:58 +08:00
parent 62cb9eb51e
commit fc1af7b0d9
2 changed files with 130 additions and 3 deletions

View File

@ -19,6 +19,8 @@
// https://slhck.info/video/2017/03/01/rate-control.html
use super::*;
#[cfg(windows)]
use crate::ui::win_privacy::win_event_hook;
use hbb_common::tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
Mutex as TokioMutex,
@ -301,6 +303,24 @@ pub fn test_create_capturer(privacy_mode_id: i32, timeout_millis: u64) -> bool {
false
}
#[cfg(windows)]
fn check_uac_switch(privacy_mode_id: i32, captuerer_privacy_mode_id: i32) -> ResultType<()> {
if captuerer_privacy_mode_id != 0 {
if privacy_mode_id != captuerer_privacy_mode_id {
if !win_event_hook::is_process_consent_running()? {
bail!("consent.exe is running");
}
}
//if win_event_hook::is_desktop_switched() {
if win_event_hook::is_process_consent_running()? {
// win_event_hook::reset_desktop_switch();
bail!("consent.exe is running");
}
//}
}
Ok(())
}
fn run(sp: GenericService) -> ResultType<()> {
#[cfg(windows)]
ensure_close_virtual_device()?;
@ -322,11 +342,24 @@ fn run(sp: GenericService) -> ResultType<()> {
);
let privacy_mode_id = *PRIVACY_MODE_CONN_ID.lock().unwrap();
#[cfg(not(windows))]
let captuerer_privacy_mode_id = privacy_mode_id;
#[cfg(windows)]
let mut captuerer_privacy_mode_id = privacy_mode_id;
#[cfg(windows)]
if win_event_hook::is_process_consent_running()? {
captuerer_privacy_mode_id = 0;
}
log::debug!(
"Try create capturer with privacy mode id {}",
privacy_mode_id,
"Try create capturer with captuerer privacy mode id {}",
captuerer_privacy_mode_id,
);
let mut c = create_capturer(privacy_mode_id, display)?;
if privacy_mode_id != captuerer_privacy_mode_id {
log::info!("In privacy mode, but show UAC prompt window for now");
} else {
log::info!("In privacy mode, the peer side cannot watch the screen");
}
let mut c = create_capturer(captuerer_privacy_mode_id, display)?;
let q = get_image_quality();
let (bitrate, rc_min_quantizer, rc_max_quantizer, speed) = get_quality(width, height, q);
@ -373,6 +406,9 @@ fn run(sp: GenericService) -> ResultType<()> {
#[cfg(windows)]
log::info!("gdi: {}", c.is_gdi());
while sp.ok() {
#[cfg(windows)]
check_uac_switch(privacy_mode_id, captuerer_privacy_mode_id)?;
if *SWITCH.lock().unwrap() {
bail!("SWITCH");
}
@ -480,6 +516,8 @@ fn run(sp: GenericService) -> ResultType<()> {
let wait_begin = Instant::now();
while wait_begin.elapsed().as_millis() < timeout_millis as _ {
check_privacy_mode_changed(&sp, privacy_mode_id)?;
#[cfg(windows)]
check_uac_switch(privacy_mode_id, captuerer_privacy_mode_id)?;
frame_controller.try_wait_next(&mut fetched_conn_ids, 300);
// break if all connections have received current frame
if fetched_conn_ids.len() >= frame_controller.send_conn_ids.len() {

View File

@ -552,6 +552,95 @@ pub(super) mod privacy_hook {
}
}
pub mod win_event_hook {
use hbb_common::{bail, lazy_static, ResultType};
use std::sync::Mutex;
use winapi::{
shared::{
minwindef::DWORD,
ntdef::{LONG, NULL},
windef::{HWINEVENTHOOK, HWND},
winerror::RPC_E_CHANGED_MODE,
},
um::{
combaseapi::{CoInitializeEx, CoUninitialize},
objbase::COINIT_MULTITHREADED,
winuser::{
SetWinEventHook, UnhookWinEvent, EVENT_SYSTEM_DESKTOPSWITCH, WINEVENT_OUTOFCONTEXT,
WINEVENT_SKIPOWNPROCESS,
},
},
};
lazy_static::lazy_static! {
static ref DESKTOP_SWITCH: Mutex<bool> = Mutex::new(false);
}
pub fn is_desktop_switched() -> bool {
*DESKTOP_SWITCH.lock().unwrap()
}
pub fn reset_desktop_switch() {
*DESKTOP_SWITCH.lock().unwrap() = false;
}
pub struct WinEventHook {
hook: HWINEVENTHOOK,
}
impl WinEventHook {
fn create() -> ResultType<Self> {
unsafe {
if RPC_E_CHANGED_MODE == CoInitializeEx(NULL, COINIT_MULTITHREADED) {
bail!("Failed CoInitializeEx with RPC_E_CHANGED_MODE");
}
let hook = SetWinEventHook(
EVENT_SYSTEM_DESKTOPSWITCH,
EVENT_SYSTEM_DESKTOPSWITCH,
NULL as _,
Some(hook_win_event),
0,
0,
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS,
);
Ok(Self { hook })
}
}
}
impl Drop for WinEventHook {
fn drop(&mut self) {
unsafe {
UnhookWinEvent(self.hook);
CoUninitialize();
}
}
}
#[no_mangle]
pub extern "system" fn hook_win_event(
_hook: HWINEVENTHOOK,
event: DWORD,
_hwnd: HWND,
_id_object: LONG,
_id_child: LONG,
_dw_event_thread: DWORD,
_dwms_event_time: DWORD,
) {
if event == EVENT_SYSTEM_DESKTOPSWITCH {
*DESKTOP_SWITCH.lock().unwrap() = true;
}
}
pub fn is_process_consent_running() -> ResultType<bool> {
let output = std::process::Command::new("cmd")
.args(&["/C", "tasklist | findstr consent.exe"])
.output()?;
Ok(output.status.success() && !output.stdout.is_empty())
}
}
mod test {
#[test]
fn privacy_hook() {