use windows::{ Win32::{ Foundation::{CloseHandle, HANDLE}, Security::{GetTokenInformation, TOKEN_ELEVATION, TOKEN_QUERY, TokenElevation}, System::Threading::{GetCurrentProcess, OpenProcessToken}, UI::{ Input::KeyboardAndMouse::{GetAsyncKeyState, VIRTUAL_KEY}, Shell::ShellExecuteW, WindowsAndMessaging::{ CURSOR_SHOWING, CURSORINFO, GetCursorInfo, GetForegroundWindow, GetWindowTextW, SW_NORMAL, }, }, }, core::{HSTRING, PCWSTR}, }; pub enum ElevationExitMethod<'a> { Gentle(&'a mut bool), Forced, } pub fn is_cursor_visible() -> bool { let mut ci = CURSORINFO { cbSize: u32::try_from(std::mem::size_of::()).unwrap(), ..Default::default() }; unsafe { GetCursorInfo(&mut ci).unwrap(); } ci.flags == CURSOR_SHOWING } pub fn is_window_focused(target_title: &str) -> bool { let mut buffer = [0; 512]; unsafe { let hwnd = GetForegroundWindow(); let length = GetWindowTextW(hwnd, &mut buffer); let current_title = String::from_utf16_lossy(&buffer[..length as usize]); current_title == target_title } } pub fn is_any_key_pressed(keys: &[VIRTUAL_KEY]) -> bool { keys.iter() .any(|&key| unsafe { (GetAsyncKeyState(i32::from(key.0)) & i16::MIN) != 0 }) } pub fn elevate(closing: ElevationExitMethod) { let exe = std::env::current_exe().unwrap(); unsafe { ShellExecuteW( None, &HSTRING::from("runas"), &HSTRING::from(exe.as_path()), PCWSTR::null(), PCWSTR::null(), SW_NORMAL, ); } match closing { ElevationExitMethod::Gentle(closing) => *closing = true, ElevationExitMethod::Forced => std::process::exit(0), } } pub fn is_elevated() -> bool { let mut token: HANDLE = HANDLE::default(); unsafe { if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &mut token).is_err() { return false; } let mut elevation = TOKEN_ELEVATION::default(); let mut size = u32::try_from(std::mem::size_of::()).unwrap(); let result = GetTokenInformation( token, TokenElevation, Some((&raw mut elevation).cast()), size, &mut size, ); CloseHandle(token).unwrap(); result.is_ok() && elevation.TokenIsElevated != 0 } }