mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-26 06:31:03 +03:00
fix: allow logon screen password, on lock screen (#11566)
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
@@ -623,6 +623,31 @@ pub fn is_prelogin() -> bool {
|
||||
n < 4 && n > 1
|
||||
}
|
||||
|
||||
// Check "Lock".
|
||||
// "Switch user" can't be checked, because `get_values_of_seat0(&[0])` does not return the session.
|
||||
// The logged in session is "online" not "active".
|
||||
// And the "Switch user" screen is usually Wayland login session, which we do not support.
|
||||
pub fn is_locked() -> bool {
|
||||
if is_prelogin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let values = get_values_of_seat0(&[0]);
|
||||
// Though the values can't be empty, we still add check here for safety.
|
||||
// Because we cannot guarantee whether the internal implementation will change in the future.
|
||||
// https://github.com/rustdesk/hbb_common/blob/ebb4d4a48cf7ed6ca62e93f8ed124065c6408536/src/platform/linux.rs#L119
|
||||
if values.is_empty() {
|
||||
log::debug!("Failed to check is locked, values vector is empty.");
|
||||
return false;
|
||||
}
|
||||
let session = &values[0];
|
||||
if session.is_empty() {
|
||||
log::debug!("Failed to check is locked, session is empty.");
|
||||
return false;
|
||||
}
|
||||
is_session_locked(session)
|
||||
}
|
||||
|
||||
pub fn is_root() -> bool {
|
||||
crate::username() == "root"
|
||||
}
|
||||
|
||||
@@ -491,6 +491,38 @@ pub fn is_prelogin() -> bool {
|
||||
get_active_userid() == "0"
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/11505255/osx-check-if-the-screen-is-locked
|
||||
// No "CGSSessionScreenIsLocked" can be found when macOS is not locked.
|
||||
//
|
||||
// `ioreg -n Root -d1` returns `"CGSSessionScreenIsLocked"=Yes`
|
||||
// `ioreg -n Root -d1 -a` returns
|
||||
// ```
|
||||
// ...
|
||||
// <key>CGSSessionScreenIsLocked</key>
|
||||
// <true/>
|
||||
// ...
|
||||
// ```
|
||||
pub fn is_locked() -> bool {
|
||||
match std::process::Command::new("ioreg")
|
||||
.arg("-n")
|
||||
.arg("Root")
|
||||
.arg("-d1")
|
||||
.output()
|
||||
{
|
||||
Ok(output) => {
|
||||
let output_str = String::from_utf8_lossy(&output.stdout);
|
||||
// Although `"CGSSessionScreenIsLocked"=Yes` was printed on my macOS,
|
||||
// I also check `"CGSSessionScreenIsLocked"=true` for better compability.
|
||||
output_str.contains("\"CGSSessionScreenIsLocked\"=Yes")
|
||||
|| output_str.contains("\"CGSSessionScreenIsLocked\"=true")
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to query ioreg for the lock state: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_root() -> bool {
|
||||
crate::username() == "root"
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ use std::{
|
||||
fs,
|
||||
io::{self, prelude::*},
|
||||
mem,
|
||||
os::{raw::c_ulong, windows::process::CommandExt},
|
||||
os::{
|
||||
raw::c_ulong,
|
||||
windows::{ffi::OsStringExt, process::CommandExt},
|
||||
},
|
||||
path::*,
|
||||
ptr::null_mut,
|
||||
sync::{atomic::Ordering, Arc, Mutex},
|
||||
@@ -60,6 +63,13 @@ use winapi::{
|
||||
winuser::*,
|
||||
},
|
||||
};
|
||||
use windows::Win32::{
|
||||
Foundation::{CloseHandle as WinCloseHandle, HANDLE as WinHANDLE},
|
||||
System::Diagnostics::ToolHelp::{
|
||||
CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W,
|
||||
TH32CS_SNAPPROCESS,
|
||||
},
|
||||
};
|
||||
use windows_service::{
|
||||
define_windows_service,
|
||||
service::{
|
||||
@@ -956,6 +966,19 @@ pub fn is_prelogin() -> bool {
|
||||
username.is_empty() || username == "SYSTEM"
|
||||
}
|
||||
|
||||
// `is_logon_ui()` is regardless of multiple sessions now.
|
||||
// It only check if "LogonUI.exe" exists.
|
||||
//
|
||||
// If there're mulitple sessions (logged in users),
|
||||
// some are in the login screen, while the others are not.
|
||||
// Then this function may not work fine if the session we want to handle(connect) is not in the login screen.
|
||||
// But it's a rare case and cannot be simply handled, so it will not be dealt with for the time being.
|
||||
#[inline]
|
||||
pub fn is_logon_ui() -> ResultType<bool> {
|
||||
let pids = get_pids("LogonUI.exe")?;
|
||||
Ok(!pids.is_empty())
|
||||
}
|
||||
|
||||
pub fn is_root() -> bool {
|
||||
// https://stackoverflow.com/questions/4023586/correct-way-to-find-out-if-a-service-is-running-as-the-system-user
|
||||
unsafe { is_local_system() == TRUE }
|
||||
@@ -2916,3 +2939,38 @@ pub fn send_raw_data_to_printer(printer_name: Option<String>, data: Vec<u8>) ->
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_pids<S: AsRef<str>>(name: S) -> ResultType<Vec<u32>> {
|
||||
let name = name.as_ref().to_lowercase();
|
||||
let mut pids = Vec::new();
|
||||
|
||||
unsafe {
|
||||
let snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)?;
|
||||
if snapshot == WinHANDLE::default() {
|
||||
return Ok(pids);
|
||||
}
|
||||
|
||||
let mut entry: PROCESSENTRY32W = std::mem::zeroed();
|
||||
entry.dwSize = std::mem::size_of::<PROCESSENTRY32W>() as u32;
|
||||
|
||||
if Process32FirstW(snapshot, &mut entry).is_ok() {
|
||||
loop {
|
||||
let proc_name = OsString::from_wide(&entry.szExeFile)
|
||||
.to_string_lossy()
|
||||
.to_lowercase();
|
||||
|
||||
if proc_name.contains(&name) {
|
||||
pids.push(entry.th32ProcessID);
|
||||
}
|
||||
|
||||
if !Process32NextW(snapshot, &mut entry).is_ok() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = WinCloseHandle(snapshot);
|
||||
}
|
||||
|
||||
Ok(pids)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user