#![warn(missing_docs)]
#[cfg(windows)]
mod handles;
#[cfg(windows)]
mod ntapi;
use std::path::Path;
pub fn find_processes_locking_path<P: AsRef<Path>>(path: P) -> Vec<usize> {
#[cfg(windows)]
{
handles::find_processes_for_paths(&[path.as_ref()])
}
#[cfg(not(windows))]
{
let _ = path;
Vec::new()
}
}
pub fn is_process_elevated() -> bool {
#[cfg(windows)]
{
use std::ptr;
use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
use windows_sys::Win32::Security::{
GetTokenInformation, TokenElevation, TOKEN_ELEVATION, TOKEN_QUERY,
};
use windows_sys::Win32::System::Threading::GetCurrentProcess;
#[link(name = "advapi32")]
extern "system" {
fn OpenProcessToken(
process_handle: HANDLE,
desired_access: u32,
token_handle: *mut HANDLE,
) -> i32;
}
unsafe {
let mut token: HANDLE = ptr::null_mut();
if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &mut token) == 0 {
return false;
}
let mut elevation = TOKEN_ELEVATION {
TokenIsElevated: 0,
};
let mut size = 0u32;
let ok = GetTokenInformation(
token,
TokenElevation,
(&mut elevation as *mut TOKEN_ELEVATION).cast(),
std::mem::size_of::<TOKEN_ELEVATION>() as u32,
&mut size,
);
CloseHandle(token);
ok != 0 && elevation.TokenIsElevated != 0
}
}
#[cfg(not(windows))]
{
false
}
}
pub fn set_debug_privilege() -> bool {
#[cfg(windows)]
{
use std::ptr;
use windows_sys::Win32::Foundation::{
CloseHandle, GetLastError, HANDLE, ERROR_NOT_ALL_ASSIGNED,
};
use windows_sys::Win32::Security::{
AdjustTokenPrivileges, LookupPrivilegeValueW, LUID_AND_ATTRIBUTES,
SE_PRIVILEGE_ENABLED, TOKEN_ADJUST_PRIVILEGES, TOKEN_PRIVILEGES,
};
use windows_sys::Win32::System::Threading::GetCurrentProcess;
#[link(name = "advapi32")]
extern "system" {
fn OpenProcessToken(
process_handle: HANDLE,
desired_access: u32,
token_handle: *mut HANDLE,
) -> i32;
}
const SE_DEBUG_NAME: [u16; 17] = [
83, 101, 68, 101, 98, 117, 103, 80, 114, 105, 118, 105, 108, 101, 103, 101, 0,
];
unsafe {
let mut token: HANDLE = ptr::null_mut();
if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &mut token) == 0 {
return false;
}
let mut luid = std::mem::zeroed();
if LookupPrivilegeValueW(ptr::null(), SE_DEBUG_NAME.as_ptr(), &mut luid) == 0 {
CloseHandle(token);
return false;
}
let tp = TOKEN_PRIVILEGES {
PrivilegeCount: 1,
Privileges: [LUID_AND_ATTRIBUTES {
Luid: luid,
Attributes: SE_PRIVILEGE_ENABLED,
}],
};
let ok = AdjustTokenPrivileges(
token,
0,
&tp,
std::mem::size_of::<TOKEN_PRIVILEGES>() as u32,
ptr::null_mut(),
ptr::null_mut(),
);
let failed = ok == 0 || GetLastError() == ERROR_NOT_ALL_ASSIGNED;
CloseHandle(token);
!failed
}
}
#[cfg(not(windows))]
{
false
}
}
pub fn pid_to_process_path(pid: usize) -> Option<String> {
#[cfg(windows)]
{
use std::ptr;
use windows_sys::Win32::System::ProcessStatus::GetModuleFileNameExW;
use windows_sys::Win32::System::Threading::{
OpenProcess, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ,
};
let process =
unsafe { OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, pid as u32) };
let process = ntapi::SafeHandle::from_raw(process)?;
let mut buf = vec![0u16; 65536];
let len = unsafe {
GetModuleFileNameExW(process.raw(), ptr::null_mut(), buf.as_mut_ptr(), buf.len() as u32)
};
if len == 0 {
return None;
}
buf.truncate(len as usize);
Some(String::from_utf16_lossy(&buf))
}
#[cfg(not(windows))]
{
let _ = pid;
None
}
}
pub fn quit_processes(pids: Vec<usize>) -> bool {
#[cfg(windows)]
{
use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::System::Threading::{
OpenProcess, TerminateProcess, PROCESS_TERMINATE,
};
let mut ok = true;
for pid in pids {
unsafe {
let process = OpenProcess(PROCESS_TERMINATE, 0, pid as u32);
if process.is_null() {
ok = false;
continue;
}
TerminateProcess(process, 0);
CloseHandle(process);
}
}
ok
}
#[cfg(not(windows))]
{
let _ = pids;
true
}
}