From f2af419b957f5557c80508cafdbc28df9ac500dc Mon Sep 17 00:00:00 2001 From: James Date: Sun, 30 Dec 2018 09:04:55 +1100 Subject: [PATCH] Fix crashes while detecting other processes --- Cargo.lock | 77 +--------------------- Cargo.toml | 4 +- src/main.rs | 2 +- src/native/mod.rs | 106 ++++++++++++++++++++++++++++++ src/tasks/ensure_only_instance.rs | 17 +++-- 5 files changed, 118 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5ba3bc9..4659ba7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,15 +155,6 @@ dependencies = [ "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-deque" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-deque" version = "0.6.1" @@ -173,20 +164,6 @@ dependencies = [ "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-epoch" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-epoch" version = "0.5.2" @@ -200,14 +177,6 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-utils" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-utils" version = "0.5.0" @@ -227,11 +196,6 @@ name = "dtoa" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "either" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "encoding_rs" version = "0.8.6" @@ -511,12 +475,12 @@ dependencies = [ "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "sysinfo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "web-view 0.2.1 (git+https://github.com/Boscop/web-view.git?rev=555f422d09cbb94e82a728d47e9e07ca91963f6e)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "winres 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "xz-decom 0.2.0 (git+https://github.com/j-selby/xz-decom.git?rev=9ebf3d00d9ff909c39eec1d2cf7e6e068ce214e5)", "zip 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -902,27 +866,6 @@ name = "rand_core" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rayon" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "redox_syscall" version = "0.1.40" @@ -1166,17 +1109,6 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sysinfo" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "take" version = "0.1.0" @@ -1717,15 +1649,11 @@ dependencies = [ "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-deque 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3486aefc4c0487b9cb52372c97df0a48b8c249514af1ee99703bf70d2f2ceda1" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9" -"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" "checksum dirs 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f679c09c1cf5428702cc10f6846c56e4e23420d3a88bcc9335b17c630a7b710b" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" -"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum encoding_rs 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2a91912d6f37c6a8fef8a2316a862542d036f13c923ad518b5aca7bcaac7544c" "checksum fern 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "57915fe00a83af935983eb2d00b0ecc62419c4741b28c207ecbf98fd4a1b94c8" "checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f" @@ -1798,8 +1726,6 @@ dependencies = [ "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" -"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" -"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" @@ -1831,7 +1757,6 @@ dependencies = [ "checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9056ebe7f2d6a38bc63171816fd1d3430da5a43896de21676dc5c0a4b8274a11" -"checksum sysinfo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c747a1fbe091faa7bf76c19f40099f9f12495384c811485d81cf3d60c0eae62" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f41ca4a5689f06998f0247fcb60da6c760f1950cc9df2a10d71575ad0b062a" "checksum tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "55c1195ef8513f3273d55ff59fe5da6940287a0d7a98331254397f464833675b" diff --git a/Cargo.toml b/Cargo.toml index e56d219..66737f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,8 +38,6 @@ chrono = "0.4.5" clap = "2.32.0" -sysinfo = "*" - [build-dependencies] walkdir = "2" serde = "1.0.27" @@ -50,6 +48,8 @@ toml = "0.4" # NFD is needed on Windows, as web-view doesn't work correctly here nfd = "0.0.4" +winapi = { version = "0.3", features = ["psapi", "winbase", "winioctl", "winnt"] } + [target.'cfg(windows)'.build-dependencies] winres = "0.1" cc = "1.0" diff --git a/src/main.rs b/src/main.rs index e18a9af..199e86e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,7 @@ extern crate chrono; extern crate clap; -extern crate sysinfo; +extern crate winapi; mod archives; mod assets; diff --git a/src/native/mod.rs b/src/native/mod.rs index 2c2569c..2ffb1ba 100644 --- a/src/native/mod.rs +++ b/src/native/mod.rs @@ -1,11 +1,20 @@ //! Natives/platform specific interactions. +/// Basic definition of some running process. +#[derive(Debug)] +pub struct Process { + pub pid : usize, + pub name : String +} + #[cfg(windows)] mod natives { #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] + const PROCESS_LEN: usize = 10192; + use std::ffi::CString; use logging::LoggingErrors; @@ -13,6 +22,16 @@ mod natives { use std::env; use std::process::Command; + use winapi::shared::minwindef::{DWORD, FALSE, MAX_PATH}; + use winapi::um::winnt::{ + HANDLE, PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE, PROCESS_VM_READ, + }; + use winapi::um::processthreadsapi::{OpenProcess}; + use winapi::um::psapi::{ + K32EnumProcesses, + EnumProcessModulesEx, GetModuleFileNameExW, LIST_MODULES_ALL, + }; + extern "C" { pub fn saveShortcut( shortcutPath: *const ::std::os::raw::c_char, @@ -99,6 +118,87 @@ mod natives { .spawn() .log_expect("Unable to start child process"); } + + #[allow(unsafe_code)] + fn get_process_handler(pid: u32) -> Option { + if pid == 0 { + return None; + } + let options = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE; + let process_handler = unsafe { OpenProcess(options, FALSE, pid as DWORD) }; + if process_handler.is_null() { + let options = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ; + let process_handler = unsafe { OpenProcess(options, FALSE, pid as DWORD) }; + if process_handler.is_null() { + None + } else { + Some(process_handler) + } + } else { + Some(process_handler) + } + } + + /// Returns a list of running processes + #[allow(unsafe_code)] + pub fn get_process_names() -> Vec { + // Port from https://github.com/GuillaumeGomez/sysinfo/blob/master/src/windows/system.rs + // I think that 10192 as length will be enough to get all processes at once... + let mut process_ids = [0 as DWORD; PROCESS_LEN]; + let mut cb_needed = 0; + + let size = ::std::mem::size_of::() * process_ids.len(); + unsafe { + if K32EnumProcesses(process_ids.as_mut_ptr(), + size as DWORD, + &mut cb_needed) == 0 { + return vec![]; + } + } + + let nb_processes = cb_needed / ::std::mem::size_of::() as DWORD; + + let mut processes = Vec::new(); + + for i in 0 .. nb_processes { + let pid = process_ids[i as usize]; + + unsafe { + if let Some(process_handler) = get_process_handler(pid) { + let mut h_mod = ::std::ptr::null_mut(); + let mut process_name = [0u16; MAX_PATH + 1]; + let mut cb_needed = 0; + + if EnumProcessModulesEx(process_handler, + &mut h_mod, + ::std::mem::size_of::() as DWORD, + &mut cb_needed, + LIST_MODULES_ALL) != 0 { + GetModuleFileNameExW(process_handler, + h_mod, + process_name.as_mut_ptr(), + MAX_PATH as DWORD + 1); + + let mut pos = 0; + for x in process_name.iter() { + if *x == 0 { + break + } + pos += 1; + } + let name = String::from_utf16_lossy(&process_name[..pos]); + + processes.push(super::Process { + pid: pid as _, + name, + }); + } + } + } + } + + processes + } } #[cfg(not(windows))] @@ -139,6 +239,12 @@ mod natives { eprintln!("Failed to delete installer log: {:?}", e); }; } + + /// Returns a list of running processes + pub fn get_process_names() -> Vec { + // TODO: no-op + vec![] + } } pub use self::natives::*; diff --git a/src/tasks/ensure_only_instance.rs b/src/tasks/ensure_only_instance.rs index 47a97ad..6d404f8 100644 --- a/src/tasks/ensure_only_instance.rs +++ b/src/tasks/ensure_only_instance.rs @@ -7,10 +7,10 @@ use tasks::TaskDependency; use tasks::TaskMessage; use tasks::TaskParamType; -use sysinfo; -use sysinfo::get_current_pid; -use sysinfo::ProcessExt; -use sysinfo::SystemExt; +use native::Process; +use native::get_process_names; + +use std::process; pub struct EnsureOnlyInstanceTask {} @@ -23,14 +23,13 @@ impl Task for EnsureOnlyInstanceTask { ) -> Result { assert_eq!(input.len(), 0); - let system = sysinfo::System::new(); - let current_pid = get_current_pid(); - for (pid, process) in system.get_process_list() { - if pid == ¤t_pid { + let current_pid = process::id() as usize; + for Process { pid, name } in get_process_names() { + if pid == current_pid { continue; } - let exe = process.exe(); + let exe = name; if exe.ends_with("maintenancetool.exe") || exe.ends_with("maintenancetool") { return Err(format!("Maintenance tool is already running!"));