From 7c98bfd3639e96122522084018ac740ea69f281f Mon Sep 17 00:00:00 2001 From: fufesou Date: Sun, 19 Nov 2023 19:23:10 +0800 Subject: [PATCH] check if WDA_EXCLUDEFROMCAPTURE is supported Signed-off-by: fufesou --- src/lang/cn.rs | 2 +- src/lang/en.rs | 2 +- src/platform/windows.cc | 42 +++++++++++- src/platform/windows.rs | 26 ++++++++ src/privacy_mode.rs | 68 ++++++++++++-------- src/privacy_mode/win_exclude_from_capture.rs | 6 ++ 6 files changed, 114 insertions(+), 32 deletions(-) diff --git a/src/lang/cn.rs b/src/lang/cn.rs index ee4d2a06a..60c257606 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -570,7 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("id_input_tip", ""), ("privacy_mode_impl_mag_tip", "模式 1 (不推荐)"), ("privacy_mode_impl_virtual_display_tip", "模式 2 (推荐)"), - ("privacy_mode_impl_exclude_from_capture_tip", "模式 3"), + ("privacy_mode_impl_exclude_from_capture_tip", "模式 1"), ("Enter privacy mode", "进入隐私模式"), ("Exit privacy mode", "退出隐私模式"), ].iter().cloned().collect(); diff --git a/src/lang/en.rs b/src/lang/en.rs index 9a6eebe33..5c2d039b5 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -205,6 +205,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("id_input_tip", "You can input an ID, a direct IP, or a domain with a port (:).\nIf you want to access a device on another server, please append the server address (@?key=), for example,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nIf you want to access a device on a public server, please input \"@public\", the key is not needed for public server"), ("privacy_mode_impl_mag_tip", "Mode 1 (deprecated)"), ("privacy_mode_impl_virtual_display_tip", "Mode 2 (recommended)"), - ("privacy_mode_impl_exclude_from_capture_tip", "Mode 3"), + ("privacy_mode_impl_exclude_from_capture_tip", "Mode 1"), ].iter().cloned().collect(); } diff --git a/src/platform/windows.cc b/src/platform/windows.cc index 4ffa6eeeb..b76fca2fd 100644 --- a/src/platform/windows.cc +++ b/src/platform/windows.cc @@ -628,8 +628,46 @@ extern "C" return bSystem; } - void alloc_console_and_redirect() { + void alloc_console_and_redirect() + { AllocConsole(); freopen("CONOUT$", "w", stdout); } -} // end of extern "C" \ No newline at end of file +} // end of extern "C" + +extern "C" +{ + // https://github.com/nodejs/node-convergence-archive/blob/e11fe0c2777561827cdb7207d46b0917ef3c42a7/deps/uv/src/win/util.c#L780 + BOOL IsWindowsVersionOrGreater(DWORD os_major, + DWORD os_minor, + DWORD build_number, + WORD service_pack_major, + WORD service_pack_minor) + { + OSVERSIONINFOEX osvi; + DWORDLONG condition_mask = 0; + int op = VER_GREATER_EQUAL; + + /* Initialize the OSVERSIONINFOEX structure. */ + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi.dwMajorVersion = os_major; + osvi.dwMinorVersion = os_minor; + osvi.dwBuildNumber = build_number; + osvi.wServicePackMajor = service_pack_major; + osvi.wServicePackMinor = service_pack_minor; + + /* Initialize the condition mask. */ + VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op); + VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op); + VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op); + VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op); + + /* Perform the test. */ + return VerifyVersionInfo( + &osvi, + VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, + condition_mask); + } +} diff --git a/src/platform/windows.rs b/src/platform/windows.rs index c0c7e4fc3..4e88ea99c 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -460,6 +460,13 @@ extern "C" { fn is_win_down() -> BOOL; fn is_local_system() -> BOOL; fn alloc_console_and_redirect(); + fn IsWindowsVersionOrGreater( + os_major: DWORD, + os_minor: DWORD, + build_number: DWORD, + service_pack_major: WORD, + service_pack_minor: WORD, + ) -> BOOL; } extern "system" { @@ -1283,6 +1290,25 @@ pub fn block_input(v: bool) -> (bool, String) { } } +#[inline] +pub fn is_windows_version_or_greater( + os_major: u32, + os_minor: u32, + build_number: u32, + service_pack_major: u32, + service_pack_minor: u32, +) -> bool { + unsafe { + IsWindowsVersionOrGreater( + os_major as _, + os_minor as _, + build_number as _, + service_pack_major as _, + service_pack_minor as _, + ) == TRUE + } +} + pub fn add_recent_document(path: &str) { extern "C" { fn AddRecentDocument(path: *const u16); diff --git a/src/privacy_mode.rs b/src/privacy_mode.rs index 811a96e3c..c3ff04de7 100644 --- a/src/privacy_mode.rs +++ b/src/privacy_mode.rs @@ -90,23 +90,26 @@ lazy_static::lazy_static! { pub static ref DEFAULT_PRIVACY_MODE_IMPL: String = { #[cfg(windows)] { - PRIVACY_MODE_IMPL_WIN_EXCLUDE_FROM_CAPTURE.to_owned() - // if display_service::is_privacy_mode_mag_supported() { - // PRIVACY_MODE_IMPL_WIN_MAG - // } else { - // #[cfg(feature = "virtual_display_driver")] - // { - // if is_installed() { - // PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY - // } else { - // "" - // } - // } - // #[cfg(not(feature = "virtual_display_driver"))] - // { - // "" - // } - // }.to_owned() + if win_exclude_from_capture::is_supported() { + PRIVACY_MODE_IMPL_WIN_EXCLUDE_FROM_CAPTURE + } else { + if display_service::is_privacy_mode_mag_supported() { + PRIVACY_MODE_IMPL_WIN_MAG + } else { + #[cfg(feature = "virtual_display_driver")] + { + if is_installed() { + PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY + } else { + "" + } + } + #[cfg(not(feature = "virtual_display_driver"))] + { + "" + } + } + }.to_owned() } #[cfg(not(windows))] { @@ -140,13 +143,15 @@ lazy_static::lazy_static! { let mut map: HashMap<&'static str, PrivacyModeCreator> = HashMap::new(); #[cfg(windows)] { - map.insert(win_mag::PRIVACY_MODE_IMPL, || { - Box::new(win_mag::PrivacyModeImpl::default()) - }); - - map.insert(win_exclude_from_capture::PRIVACY_MODE_IMPL, || { + if win_exclude_from_capture::is_supported() { + map.insert(win_exclude_from_capture::PRIVACY_MODE_IMPL, || { Box::new(win_exclude_from_capture::PrivacyModeImpl::default()) }); + } else { + map.insert(win_mag::PRIVACY_MODE_IMPL, || { + Box::new(win_mag::PrivacyModeImpl::default()) + }); + } #[cfg(feature = "virtual_display_driver")] map.insert(win_virtual_display::PRIVACY_MODE_IMPL, || { @@ -280,13 +285,18 @@ pub fn get_supported_privacy_mode_impl() -> Vec<(&'static str, &'static str)> { #[cfg(target_os = "windows")] { let mut vec_impls = Vec::new(); - if display_service::is_privacy_mode_mag_supported() { - vec_impls.push((PRIVACY_MODE_IMPL_WIN_MAG, "privacy_mode_impl_mag_tip")); + + if win_exclude_from_capture::is_supported() { + vec_impls.push(( + PRIVACY_MODE_IMPL_WIN_EXCLUDE_FROM_CAPTURE, + "privacy_mode_impl_exclude_from_capture_tip", + )); + } else { + if display_service::is_privacy_mode_mag_supported() { + vec_impls.push((PRIVACY_MODE_IMPL_WIN_MAG, "privacy_mode_impl_mag_tip")); + } } - vec_impls.push(( - PRIVACY_MODE_IMPL_WIN_EXCLUDE_FROM_CAPTURE, - "privacy_mode_impl_exclude_from_capture_tip", - )); + #[cfg(feature = "virtual_display_driver")] if is_installed() { vec_impls.push(( @@ -294,6 +304,7 @@ pub fn get_supported_privacy_mode_impl() -> Vec<(&'static str, &'static str)> { "privacy_mode_impl_virtual_display_tip", )); } + vec_impls } #[cfg(not(target_os = "windows"))] @@ -324,6 +335,7 @@ pub fn check_privacy_mode_err( display_idx: usize, timeout_millis: u64, ) -> String { + // win magnifier implementation requires a test of creating a capturer. if is_current_privacy_mode_impl(PRIVACY_MODE_IMPL_WIN_MAG) { crate::video_service::test_create_capturer(privacy_mode_id, display_idx, timeout_millis) } else { diff --git a/src/privacy_mode/win_exclude_from_capture.rs b/src/privacy_mode/win_exclude_from_capture.rs index 2ef752c5b..0bb81f693 100644 --- a/src/privacy_mode/win_exclude_from_capture.rs +++ b/src/privacy_mode/win_exclude_from_capture.rs @@ -1,3 +1,9 @@ pub use super::win_topmost_window::PrivacyModeImpl; pub(super) const PRIVACY_MODE_IMPL: &str = "privacy_mode_impl_exclude_from_capture"; + +pub(super) fn is_supported() -> bool { + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowdisplayaffinity + // https://en.wikipedia.org/wiki/Windows_10_version_history + crate::platform::windows::is_windows_version_or_greater(10, 0, 19041, 0, 0) +}