dll_syringe/process/
owned.rs1use std::{
2 hash::{Hash, Hasher},
3 io,
4 os::windows::{
5 prelude::{
6 AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle,
7 RawHandle,
8 },
9 raw::HANDLE,
10 },
11 path::Path,
12 process::Child,
13 time::Duration,
14};
15
16use winapi::{shared::minwindef::FALSE, um::processthreadsapi::OpenProcess};
17
18use crate::process::{BorrowedProcess, OwnedProcessModule, Process, PROCESS_INJECTION_ACCESS};
19
20#[repr(transparent)]
31#[derive(Debug)]
32pub struct OwnedProcess(OwnedHandle);
33
34unsafe impl Send for OwnedProcess {}
35unsafe impl Sync for OwnedProcess {}
36
37impl AsRawHandle for OwnedProcess {
38 fn as_raw_handle(&self) -> HANDLE {
39 self.0.as_raw_handle()
40 }
41}
42
43impl AsHandle for OwnedProcess {
44 fn as_handle(&self) -> BorrowedHandle<'_> {
45 self.0.as_handle()
46 }
47}
48
49impl IntoRawHandle for OwnedProcess {
50 fn into_raw_handle(self) -> RawHandle {
51 self.0.into_raw_handle()
52 }
53}
54
55impl FromRawHandle for OwnedProcess {
56 unsafe fn from_raw_handle(handle: HANDLE) -> Self {
57 Self(unsafe { OwnedHandle::from_raw_handle(handle) })
58 }
59}
60
61impl From<Child> for OwnedProcess {
62 fn from(child: Child) -> Self {
63 Self::from_child(child)
64 }
65}
66
67impl TryFrom<BorrowedProcess<'_>> for OwnedProcess {
68 type Error = io::Error;
69
70 fn try_from(process: BorrowedProcess<'_>) -> Result<Self, Self::Error> {
71 process.try_to_owned()
72 }
73}
74
75impl PartialEq for OwnedProcess {
76 fn eq(&self, other: &Self) -> bool {
77 self.borrowed() == other.borrowed()
78 }
79}
80
81impl Eq for OwnedProcess {}
82
83impl Hash for OwnedProcess {
84 fn hash<H: Hasher>(&self, state: &mut H) {
85 self.borrowed().hash(state);
86 }
87}
88
89impl Process for OwnedProcess {
90 type Handle = OwnedHandle;
91
92 fn borrowed(&self) -> BorrowedProcess<'_> {
93 unsafe { BorrowedProcess::from_handle_unchecked(self.as_handle()) }
94 }
95
96 fn try_clone(&self) -> Result<Self, io::Error> {
97 self.borrowed().try_to_owned()
98 }
99
100 fn into_handle(self) -> Self::Handle {
101 self.0
102 }
103
104 unsafe fn from_handle_unchecked(handle: Self::Handle) -> Self {
105 Self(handle)
106 }
107
108 fn current_handle() -> Self::Handle {
109 unsafe { OwnedHandle::from_raw_handle(Self::raw_current_handle()) }
110 }
111
112 fn find_module_by_name(
113 &self,
114 module_name: impl AsRef<Path>,
115 ) -> Result<Option<OwnedProcessModule>, io::Error> {
116 if let Some(module) = self.borrowed().find_module_by_name(module_name)? {
117 Ok(Some(module.try_to_owned()?))
118 } else {
119 Ok(None)
120 }
121 }
122
123 fn find_module_by_path(
124 &self,
125 module_path: impl AsRef<Path>,
126 ) -> Result<Option<OwnedProcessModule>, io::Error> {
127 if let Some(module) = self.borrowed().find_module_by_path(module_path)? {
128 Ok(Some(module.try_to_owned()?))
129 } else {
130 Ok(None)
131 }
132 }
133
134 fn wait_for_module_by_name(
135 &self,
136 module_name: impl AsRef<Path>,
137 timeout: Duration,
138 ) -> Result<Option<OwnedProcessModule>, io::Error> {
139 if let Some(module) = self
140 .borrowed()
141 .wait_for_module_by_name(module_name, timeout)?
142 {
143 Ok(Some(module.try_to_owned()?))
144 } else {
145 Ok(None)
146 }
147 }
148
149 fn wait_for_module_by_path(
150 &self,
151 module_path: impl AsRef<Path>,
152 timeout: Duration,
153 ) -> Result<Option<OwnedProcessModule>, io::Error> {
154 if let Some(module) = self
155 .borrowed()
156 .wait_for_module_by_path(module_path, timeout)?
157 {
158 Ok(Some(module.try_to_owned()?))
159 } else {
160 Ok(None)
161 }
162 }
163}
164
165impl OwnedProcess {
166 pub fn from_pid(pid: u32) -> Result<OwnedProcess, io::Error> {
168 let handle = unsafe {
169 OpenProcess(
170 PROCESS_INJECTION_ACCESS,
172 FALSE,
173 pid,
174 )
175 };
176
177 if handle.is_null() {
178 return Err(io::Error::last_os_error());
179 }
180
181 Ok(unsafe { OwnedProcess::from_raw_handle(handle.cast()) })
182 }
183
184 #[must_use]
186 pub fn all() -> Vec<OwnedProcess> {
187 let mut system = sysinfo::System::new();
190 system.refresh_processes_specifics(
191 sysinfo::ProcessesToUpdate::All,
192 true,
193 sysinfo::ProcessRefreshKind::nothing(),
194 );
195 system
196 .processes()
197 .values()
198 .map(|process| process.pid())
199 .filter_map(|pid| OwnedProcess::from_pid(pid.as_u32()).ok())
200 .collect()
201 }
202
203 #[must_use]
205 pub fn find_all_by_name(name: impl AsRef<str>) -> Vec<OwnedProcess> {
206 let mut system = sysinfo::System::new();
209 system.refresh_processes_specifics(
210 sysinfo::ProcessesToUpdate::All,
211 true,
212 sysinfo::ProcessRefreshKind::nothing(),
213 );
214 system
215 .processes()
216 .values()
217 .filter(move |process| process.name().to_string_lossy().contains(name.as_ref()))
218 .map(|process| process.pid())
219 .filter_map(|pid| OwnedProcess::from_pid(pid.as_u32()).ok())
220 .collect()
221 }
222
223 #[must_use]
225 pub fn find_first_by_name(name: impl AsRef<str>) -> Option<OwnedProcess> {
226 let mut system = sysinfo::System::new();
229 system.refresh_processes_specifics(
230 sysinfo::ProcessesToUpdate::All,
231 true,
232 sysinfo::ProcessRefreshKind::nothing(),
233 );
234 system
235 .processes()
236 .values()
237 .filter(move |process| process.name().to_string_lossy().contains(name.as_ref()))
238 .map(|process| process.pid())
239 .find_map(|pid| OwnedProcess::from_pid(pid.as_u32()).ok())
240 }
241
242 #[must_use]
244 pub fn from_child(child: Child) -> OwnedProcess {
245 unsafe { OwnedProcess::from_raw_handle(child.into_raw_handle()) }
246 }
247
248 #[must_use]
254 pub unsafe fn borrowed_static(&self) -> BorrowedProcess<'static> {
255 unsafe {
256 BorrowedProcess::from_handle_unchecked(BorrowedHandle::borrow_raw(self.as_raw_handle()))
257 }
258 }
259
260 pub fn try_clone(&self) -> Result<Self, io::Error> {
262 self.borrowed().try_to_owned()
263 }
264
265 #[allow(clippy::must_use_candidate)]
267 pub fn leak(self) -> BorrowedProcess<'static> {
268 unsafe { self.borrowed_static() }
269 }
270
271 #[must_use]
273 pub const fn kill_on_drop(self) -> ProcessKillGuard {
274 ProcessKillGuard(self)
275 }
276}
277
278#[derive(Debug, shrinkwraprs::Shrinkwrap)]
279#[shrinkwrap(mutable)]
280pub struct ProcessKillGuard(pub OwnedProcess);
282
283impl Drop for ProcessKillGuard {
284 fn drop(&mut self) {
285 let _ = self.0.kill();
286 }
287}