Skip to main content

framework_system/
is_elevated.rs

1//! 判断当前进程是否已提权。
2
3use anyhow::Result;
4
5/// 判断当前进程是否以管理员(Windows)或 root(Linux、macOS)身份运行。
6///
7/// - Windows:查询当前进程令牌的 `TokenElevation`,为真表示已提权。
8/// - Linux、macOS:判断有效用户 ID 是否为 `0`。
9/// - 其他平台:始终返回假。
10#[cfg(unix)]
11pub fn is_elevated() -> Result<bool> {
12    Ok(unsafe { libc::geteuid() } == 0)
13}
14
15/// 判断当前进程是否以管理员身份运行。
16#[cfg(windows)]
17pub fn is_elevated() -> Result<bool> {
18    use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
19    use windows_sys::Win32::Security::{
20        GetTokenInformation, TOKEN_ELEVATION, TOKEN_QUERY, TokenElevation,
21    };
22    use windows_sys::Win32::System::Threading::{GetCurrentProcess, OpenProcessToken};
23
24    unsafe {
25        let mut token: HANDLE = std::ptr::null_mut();
26        if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &mut token) == 0 {
27            return Err(std::io::Error::last_os_error().into());
28        }
29
30        let mut elevation = TOKEN_ELEVATION { TokenIsElevated: 0 };
31        let mut return_length = 0u32;
32        let result = GetTokenInformation(
33            token,
34            TokenElevation,
35            &mut elevation as *mut _ as *mut _,
36            size_of::<TOKEN_ELEVATION>() as u32,
37            &mut return_length,
38        );
39        let last_error = if result == 0 {
40            Some(std::io::Error::last_os_error())
41        } else {
42            None
43        };
44        // 令牌必须显式关闭,先取出错误再关闭,避免提前返回时泄漏句柄。
45        CloseHandle(token);
46
47        if let Some(error) = last_error {
48            return Err(error.into());
49        }
50
51        Ok(elevation.TokenIsElevated != 0)
52    }
53}
54
55/// 判断当前进程是否已提权;当前平台无法判断,始终返回假。
56#[cfg(not(any(unix, windows)))]
57pub fn is_elevated() -> Result<bool> {
58    Ok(false)
59}