windows_erg/process/
list.rs1use windows::Win32::Foundation::{CloseHandle, ERROR_NO_MORE_FILES};
4use windows::Win32::System::Diagnostics::ToolHelp::{
5 CreateToolhelp32Snapshot, PROCESSENTRY32W, Process32FirstW, Process32NextW, TH32CS_SNAPPROCESS,
6};
7
8use super::processes::Process;
9use super::types::{ProcessId, ProcessInfo};
10use crate::error::{Error, ProcessError, ProcessOpenError, Result};
11
12impl Process {
13 pub fn list() -> Result<Vec<ProcessInfo>> {
15 let mut buffer = Vec::with_capacity(128);
16 Self::list_with_buffer(&mut buffer)?;
17 Ok(buffer)
18 }
19
20 pub fn list_with_buffer(out_processes: &mut Vec<ProcessInfo>) -> Result<usize> {
24 Self::list_with_filter_impl(out_processes, |_| true)
25 }
26
27 pub fn list_with_filter<F>(out_processes: &mut Vec<ProcessInfo>, filter: F) -> Result<usize>
35 where
36 F: Fn(&ProcessInfo) -> bool,
37 {
38 Self::list_with_filter_impl(out_processes, filter)
39 }
40
41 fn list_with_filter_impl<F>(out_processes: &mut Vec<ProcessInfo>, filter: F) -> Result<usize>
43 where
44 F: Fn(&ProcessInfo) -> bool,
45 {
46 out_processes.clear();
48
49 let snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) }.map_err(|e| {
50 Error::Process(ProcessError::OpenFailed(ProcessOpenError::with_code(
51 0,
52 "Failed to create process snapshot",
53 e.code().0,
54 )))
55 })?;
56
57 let mut entry = PROCESSENTRY32W {
58 dwSize: std::mem::size_of::<PROCESSENTRY32W>() as u32,
59 ..Default::default()
60 };
61
62 if unsafe { Process32FirstW(snapshot, &mut entry) }.is_ok() {
63 loop {
64 let name_end = entry
66 .szExeFile
67 .iter()
68 .position(|&c| c == 0)
69 .unwrap_or(entry.szExeFile.len());
70 let name = String::from_utf16_lossy(&entry.szExeFile[..name_end]);
71
72 let parent_pid = if entry.th32ParentProcessID == 0 {
73 None
74 } else {
75 Some(ProcessId::new(entry.th32ParentProcessID))
76 };
77
78 let process_info = ProcessInfo {
79 pid: ProcessId::new(entry.th32ProcessID),
80 parent_pid,
81 name,
82 thread_count: entry.cntThreads,
83 };
84
85 if filter(&process_info) {
87 out_processes.push(process_info);
88 }
89
90 match unsafe { Process32NextW(snapshot, &mut entry) } {
92 Ok(_) => continue,
93 Err(e) if e.code() == ERROR_NO_MORE_FILES.into() => break,
94 Err(_) => break,
95 }
96 }
97 }
98
99 unsafe {
100 let _ = CloseHandle(snapshot);
101 }
102 Ok(out_processes.len())
103 }
104
105 pub fn parent_id(&self) -> Result<Option<ProcessId>> {
107 let processes = Self::list()?;
109
110 for proc in processes {
111 if proc.pid == self.id() {
112 return Ok(proc.parent_pid);
113 }
114 }
115
116 Ok(None)
117 }
118
119 pub fn children(&self) -> Result<Vec<ProcessId>> {
121 let mut buffer = Vec::with_capacity(128);
122 self.children_with_buffer(&mut buffer)?;
123 Ok(buffer.into_iter().map(|p| p.pid).collect())
125 }
126
127 pub fn children_with_buffer(&self, buffer: &mut Vec<ProcessInfo>) -> Result<usize> {
129 let self_id = self.id();
130 Self::list_with_filter(buffer, |p| p.parent_pid == Some(self_id))
131 }
132}