//---------------------------------------------------------------------------- // Example: List all processes owning a specific file // // Depends on "winapi" crate (tested version 0.3.9) with features // "impl-default", "restartmanager" and "winerror" enabled. //---------------------------------------------------------------------------- use std::ffi::{OsStr, OsString}; use std::io::{Error, Result}; use std::iter::once; use std::os::windows::prelude::*; use std::ptr::null_mut; //---------------------------------------------------------------------------- // Helper functions fn string_from_wide(wide: &[u16]) -> String { let os_str = OsString::from_wide(wide); let result = os_str.to_string_lossy(); if let Some(i) = result.find('\0') { result[0..i].to_string() } else { result.to_string() } } fn wide_from_string(val: &str) -> Vec { let os_str = OsStr::new(val); os_str.encode_wide().chain(once(0)).collect() } struct ProcessInfo { pid: u32, app_name: String, } fn file_owner_process_info(file_name: &str) -> Result> { use winapi::shared::winerror::ERROR_SUCCESS; use winapi::um::restartmanager::*; let mut result = Vec::new(); let mut handle = 0; let mut session_key = vec![0; CCH_RM_SESSION_KEY]; let mut errno = unsafe { RmStartSession(&mut handle, 0, session_key.as_mut_ptr()) }; if errno != ERROR_SUCCESS { return Err(Error::from_raw_os_error(errno as i32)); } let file_name = wide_from_string(file_name); let mut file_names = vec![file_name.as_ptr()]; errno = unsafe{ RmRegisterResources(handle, 1, file_names.as_mut_ptr(), 0, null_mut(), 0, null_mut()) }; if errno == ERROR_SUCCESS { let mut proc_info = vec![RM_PROCESS_INFO::default(); 100]; let mut proc_info_needed = 0; let mut proc_info_count = proc_info.len() as u32; let mut reboot_reasons = 0; errno = unsafe { RmGetList(handle, &mut proc_info_needed, &mut proc_info_count, proc_info.as_mut_ptr(), &mut reboot_reasons) }; if errno == ERROR_SUCCESS { for i in 0..proc_info_count { let info = &proc_info[i as usize]; let pid = info.Process.dwProcessId; let app_name = string_from_wide(&info.strAppName); result.push(ProcessInfo { pid, app_name }); } } } unsafe { RmEndSession(handle) }; if errno != ERROR_SUCCESS { return Err(Error::from_raw_os_error(errno as i32)); } Ok(result) } //---------------------------------------------------------------------------- fn main() -> Result<()> { let args : Vec<_> = std::env::args().collect(); let file_name = args.get(1).map(|v| v.as_str()) .unwrap_or("C:\\Windows\\system32\\cmd.exe"); println!("Owners of {}:", file_name); for info in file_owner_process_info(file_name)? { println!("pid: {},\tname: {}", info.pid, info.app_name); } Ok(()) } //----------------------------------------------------------------------------