Skip to content

Commit

Permalink
Improve Windows code
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Apr 6, 2024
1 parent 38bceab commit 51af902
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 185 deletions.
2 changes: 1 addition & 1 deletion src/common.rs
Expand Up @@ -1627,7 +1627,7 @@ impl UpdateKind {
///
/// When all refresh are ruled out, a [`Process`] will still retrieve the following information:
/// * Process ID ([`Pid`])
/// * Parent process ID
/// * Parent process ID (on Windows it never changes though)
/// * Process name
/// * Start time
///
Expand Down
36 changes: 6 additions & 30 deletions src/windows/disk.rs
@@ -1,5 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use crate::sys::utils::HandleWrapper;
use crate::{Disk, DiskKind};

use std::ffi::{c_void, OsStr, OsString};
Expand All @@ -8,11 +9,10 @@ use std::os::windows::ffi::OsStringExt;
use std::path::Path;

use windows::core::{Error, HRESULT, PCWSTR};
use windows::Win32::Foundation::{CloseHandle, HANDLE, MAX_PATH};
use windows::Win32::Foundation::MAX_PATH;
use windows::Win32::Storage::FileSystem::{
CreateFileW, FindFirstVolumeW, FindNextVolumeW, FindVolumeClose, GetDiskFreeSpaceExW,
GetDriveTypeW, GetVolumeInformationW, GetVolumePathNamesForVolumeNameW, FILE_ACCESS_RIGHTS,
FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING,
FindFirstVolumeW, FindNextVolumeW, FindVolumeClose, GetDiskFreeSpaceExW, GetDriveTypeW,
GetVolumeInformationW, GetVolumePathNamesForVolumeNameW,
};
use windows::Win32::System::Ioctl::{
PropertyStandardQuery, StorageDeviceSeekPenaltyProperty, DEVICE_SEEK_PENALTY_DESCRIPTOR,
Expand Down Expand Up @@ -205,31 +205,6 @@ impl DisksInner {
}
}

struct HandleWrapper(HANDLE);

impl HandleWrapper {
unsafe fn new(drive_name: &[u16], open_rights: FILE_ACCESS_RIGHTS) -> Option<Self> {
let lpfilename = PCWSTR::from_raw(drive_name.as_ptr());
let handle = CreateFileW(
lpfilename,
open_rights.0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
None,
OPEN_EXISTING,
Default::default(),
HANDLE::default(),
)
.ok()?;
Some(Self(handle))
}
}

impl Drop for HandleWrapper {
fn drop(&mut self) {
let _err = unsafe { CloseHandle(self.0) };
}
}

unsafe fn get_drive_size(mount_point: &[u16]) -> Option<(u64, u64)> {
let mut total_size = 0;
let mut available_space = 0;
Expand Down Expand Up @@ -292,7 +267,8 @@ pub(crate) unsafe fn get_list() -> Vec<Disk> {
.copied()
.chain([0])
.collect::<Vec<_>>();
let Some(handle) = HandleWrapper::new(&device_path[..], Default::default()) else {
let Some(handle) = HandleWrapper::new_from_file(&device_path[..], Default::default())
else {
return Vec::new();
};
let Some((total_space, available_space)) = get_drive_size(&mount_paths[0][..]) else {
Expand Down
204 changes: 66 additions & 138 deletions src/windows/process.rs
@@ -1,6 +1,7 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use crate::sys::system::is_proc_running;
use crate::sys::utils::HandleWrapper;
use crate::windows::Sid;
use crate::{DiskUsage, Gid, Pid, ProcessRefreshKind, ProcessStatus, Signal, Uid};

Expand All @@ -9,7 +10,6 @@ use std::fmt;
#[cfg(feature = "debug")]
use std::io;
use std::mem::{size_of, zeroed, MaybeUninit};
use std::ops::Deref;
use std::os::windows::ffi::OsStringExt;
use std::os::windows::process::CommandExt;
use std::path::{Path, PathBuf};
Expand All @@ -30,9 +30,8 @@ use windows::Wdk::System::Threading::{
ProcessWow64Information, PROCESSINFOCLASS,
};
use windows::Win32::Foundation::{
CloseHandle, LocalFree, ERROR_INSUFFICIENT_BUFFER, FILETIME, HANDLE, HINSTANCE, HLOCAL,
MAX_PATH, STATUS_BUFFER_OVERFLOW, STATUS_BUFFER_TOO_SMALL, STATUS_INFO_LENGTH_MISMATCH,
UNICODE_STRING,
LocalFree, ERROR_INSUFFICIENT_BUFFER, FILETIME, HANDLE, HINSTANCE, HLOCAL, MAX_PATH,
STATUS_BUFFER_OVERFLOW, STATUS_BUFFER_TOO_SMALL, STATUS_INFO_LENGTH_MISMATCH, UNICODE_STRING,
};
use windows::Win32::Security::{GetTokenInformation, TokenUser, TOKEN_QUERY, TOKEN_USER};
use windows::Win32::System::Diagnostics::Debug::ReadProcessMemory;
Expand Down Expand Up @@ -167,32 +166,6 @@ unsafe fn get_process_user_id(process: &mut ProcessInner, refresh_kind: ProcessR
}
}

struct HandleWrapper(HANDLE);

impl HandleWrapper {
fn new(handle: HANDLE) -> Option<Self> {
if handle.is_invalid() {
None
} else {
Some(Self(handle))
}
}
}

impl Deref for HandleWrapper {
type Target = HANDLE;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl Drop for HandleWrapper {
fn drop(&mut self) {
let _err = unsafe { CloseHandle(self.0) };
}
}

#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl Send for HandleWrapper {}
unsafe impl Sync for HandleWrapper {}
Expand Down Expand Up @@ -354,48 +327,20 @@ unsafe fn get_exe(process_handler: &HandleWrapper) -> Option<PathBuf> {
}

impl ProcessInner {
pub(crate) fn new_from_pid(
pid: Pid,
now: u64,
refresh_kind: ProcessRefreshKind,
) -> Option<Self> {
pub(crate) fn new_from_pid(pid: Pid, now: u64) -> Option<Self> {
unsafe {
let process_handler = get_process_handler(pid)?;
let mut info: MaybeUninit<PROCESS_BASIC_INFORMATION> = MaybeUninit::uninit();
if NtQueryInformationProcess(
process_handler.0,
ProcessBasicInformation,
info.as_mut_ptr().cast(),
size_of::<PROCESS_BASIC_INFORMATION>() as _,
null_mut(),
)
.is_err()
{
return None;
}
let info = info.assume_init();

let name = get_process_name(pid).unwrap_or_default();
let exe = if refresh_kind.exe().needs_update(|| true) {
get_exe(&process_handler)
} else {
None
};
let (start_time, run_time) = get_start_and_run_time(*process_handler, now);
let parent = if info.InheritedFromUniqueProcessId != 0 {
Some(Pid(info.InheritedFromUniqueProcessId as _))
} else {
None
};
let mut p = Self {
Some(Self {
handle: Some(Arc::new(process_handler)),
name,
pid,
parent,
parent: None,
user_id: None,
cmd: Vec::new(),
environ: Vec::new(),
exe,
exe: None,
cwd: None,
root: None,
status: ProcessStatus::Run,
Expand All @@ -410,10 +355,7 @@ impl ProcessInner {
old_written_bytes: 0,
read_bytes: 0,
written_bytes: 0,
};
get_process_user_id(&mut p, refresh_kind);
get_process_params(&mut p, refresh_kind);
Some(p)
})
}
}

Expand All @@ -424,75 +366,36 @@ impl ProcessInner {
virtual_memory: u64,
name: OsString,
now: u64,
refresh_kind: ProcessRefreshKind,
) -> Self {
if let Some(handle) = get_process_handler(pid) {
unsafe {
let exe = if refresh_kind.exe().needs_update(|| true) {
get_exe(&handle)
} else {
None
};
let (start_time, run_time) = get_start_and_run_time(*handle, now);
let mut p = Self {
handle: Some(Arc::new(handle)),
name,
pid,
user_id: None,
parent,
cmd: Vec::new(),
environ: Vec::new(),
exe,
cwd: None,
root: None,
status: ProcessStatus::Run,
memory,
virtual_memory,
cpu_usage: 0.,
cpu_calc_values: CPUsageCalculationValues::new(),
start_time,
run_time,
updated: true,
old_read_bytes: 0,
old_written_bytes: 0,
read_bytes: 0,
written_bytes: 0,
};

get_process_user_id(&mut p, refresh_kind);
get_process_params(&mut p, refresh_kind);
p
}
let (handle, start_time, run_time) = if let Some(handle) = get_process_handler(pid) {
let (start_time, run_time) = get_start_and_run_time(*handle, now);
(Some(Arc::new(handle)), start_time, run_time)
} else {
let exe = if refresh_kind.exe().needs_update(|| true) {
get_executable_path(pid)
} else {
None
};
Self {
handle: None,
name,
pid,
user_id: None,
parent,
cmd: Vec::new(),
environ: Vec::new(),
exe,
cwd: None,
root: None,
status: ProcessStatus::Run,
memory,
virtual_memory,
cpu_usage: 0.,
cpu_calc_values: CPUsageCalculationValues::new(),
start_time: 0,
run_time: 0,
updated: true,
old_read_bytes: 0,
old_written_bytes: 0,
read_bytes: 0,
written_bytes: 0,
}
(None, 0, 0)
};
Self {
handle,
name,
pid,
user_id: None,
parent,
cmd: Vec::new(),
environ: Vec::new(),
exe: None,
cwd: None,
root: None,
status: ProcessStatus::Run,
memory,
virtual_memory,
cpu_usage: 0.,
cpu_calc_values: CPUsageCalculationValues::new(),
start_time,
run_time,
updated: true,
old_read_bytes: 0,
old_written_bytes: 0,
read_bytes: 0,
written_bytes: 0,
}
}

Expand All @@ -501,6 +404,7 @@ impl ProcessInner {
refresh_kind: crate::ProcessRefreshKind,
nb_cpus: u64,
now: u64,
refresh_parent: bool,
) {
if refresh_kind.cpu() {
compute_cpu_usage(self, nb_cpus);
Expand All @@ -513,7 +417,7 @@ impl ProcessInner {
}
unsafe {
get_process_user_id(self, refresh_kind);
get_process_params(self, refresh_kind);
get_process_params(self, refresh_kind, refresh_parent);
}
if refresh_kind.exe().needs_update(|| self.exe.is_none()) {
unsafe {
Expand Down Expand Up @@ -858,16 +762,25 @@ macro_rules! impl_RtlUserProcessParameters {
impl_RtlUserProcessParameters!(RTL_USER_PROCESS_PARAMETERS32);
impl_RtlUserProcessParameters!(RTL_USER_PROCESS_PARAMETERS);

unsafe fn get_process_params(process: &mut ProcessInner, refresh_kind: ProcessRefreshKind) {
if !(refresh_kind.cmd().needs_update(|| process.cmd.is_empty())
fn has_anything_to_update(process: &ProcessInner, refresh_kind: ProcessRefreshKind) -> bool {
refresh_kind.cmd().needs_update(|| process.cmd.is_empty())
|| refresh_kind
.environ()
.needs_update(|| process.environ.is_empty())
|| refresh_kind.cwd().needs_update(|| process.cwd.is_none())
|| refresh_kind.root().needs_update(|| process.root.is_none()))
{
|| refresh_kind.root().needs_update(|| process.root.is_none())
}

unsafe fn get_process_params(
process: &mut ProcessInner,
refresh_kind: ProcessRefreshKind,
refresh_parent: bool,
) {
let has_anything_to_update = has_anything_to_update(process, refresh_kind);
if !refresh_parent && !has_anything_to_update {
return;
}

let handle = match process.handle.as_ref().map(|handle| handle.0) {
Some(h) => h,
None => return,
Expand Down Expand Up @@ -907,6 +820,17 @@ unsafe fn get_process_params(process: &mut ProcessInner, refresh_kind: ProcessRe
}
let pinfo = pbasicinfo.assume_init();

let parent = if pinfo.InheritedFromUniqueProcessId as usize != 0 {
Some(Pid(pinfo.InheritedFromUniqueProcessId as _))
} else {
None
};
process.parent = parent;

if !has_anything_to_update {
return;
}

let mut peb = MaybeUninit::<PEB>::uninit();
if ReadProcessMemory(
handle,
Expand Down Expand Up @@ -950,6 +874,10 @@ unsafe fn get_process_params(process: &mut ProcessInner, refresh_kind: ProcessRe
}
// target is a 32 bit process in wow64 mode

if !has_anything_to_update {
return;
}

let mut peb32 = MaybeUninit::<PEB32>::uninit();
if ReadProcessMemory(
handle,
Expand Down

0 comments on commit 51af902

Please sign in to comment.