diff --git a/Cargo.toml b/Cargo.toml index 54b96f33..fb412211 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ log = "0.4" rayon = "1.2" sysinfo = "0.9.4" tokio = "0.2.0-alpha.4" +winapi = "0.3.8" [dependencies.tui-temp-fork] #git = "https://github.com/ClementTsang/tui-rs" diff --git a/TODO.md b/TODO.md index 0c617cae..87eccf38 100644 --- a/TODO.md +++ b/TODO.md @@ -24,6 +24,8 @@ Note this will probably migrate to GitHub's native Issues; this was mostly for p * Travis +* Refactoring! Please. + * Scaling in and out (zoom), may need to show zoom levels * More keybinds diff --git a/src/app/process_killer.rs b/src/app/process_killer.rs index 2e74de16..3e5feb76 100644 --- a/src/app/process_killer.rs +++ b/src/app/process_killer.rs @@ -1,5 +1,35 @@ /// This file is meant to house (OS specific) implementations on how to kill processes. use std::process::Command; +use std::ptr::null_mut; +use winapi::{ + shared::{minwindef::DWORD, ntdef::HANDLE}, + um::{ + processthreadsapi::{OpenProcess, TerminateProcess}, + winnt::{PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE}, + }, +}; + +// Copied from SO: https://stackoverflow.com/a/55231715 +struct Process(HANDLE); +impl Process { + fn open(pid : DWORD) -> Result { + let pc = unsafe { OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE, 0, pid) }; + if pc == null_mut() { + return Err("!OpenProcess".to_string()); + } + Ok(Process(pc)) + } + + fn kill(self) -> Result<(), String> { + unsafe { TerminateProcess(self.0, 1) }; + Ok(()) + } +} +impl Drop for Process { + fn drop(&mut self) { + unsafe { winapi::um::handleapi::CloseHandle(self.0) }; + } +} /// Kills a process, given a PID. pub fn kill_process_given_pid(pid : u64) -> crate::utils::error::Result<()> { @@ -8,9 +38,8 @@ pub fn kill_process_given_pid(pid : u64) -> crate::utils::error::Result<()> { Command::new("kill").arg(pid.to_string()).output()?; } else if cfg!(target_os = "windows") { - // Windows - // See how sysinfo does it... https://docs.rs/sysinfo/0.9.5/sysinfo/trait.ProcessExt.html - debug!("Sorry, Windows support is not implemented yet!"); + let process = Process::open(pid as DWORD)?; + process.kill()?; } else if cfg!(target_os = "macos") { // TODO: macOS diff --git a/src/utils/error.rs b/src/utils/error.rs index eecda2d5..ed829c3e 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -27,6 +27,11 @@ pub enum RustopError { /// The data provided is the error found. #[fail(display = "ERROR: Invalid error due to Crossterm: {}", message)] CrosstermError { message : String }, + /// An error to represent generic errors + /// + /// The data provided is the error found. + #[fail(display = "ERROR: Invalid generic error: {}", message)] + GenericError { message : String }, } impl From for RustopError { @@ -52,3 +57,9 @@ impl From for RustopError { RustopError::InvalidArg { message : err.to_string() } } } + +impl From for RustopError { + fn from(err : std::string::String) -> Self { + RustopError::GenericError { message : err.to_string() } + } +}