summaryrefslogtreecommitdiffhomepage
path: root/talpid-windows
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2023-10-17 13:14:12 +0200
committerDavid Lönnhager <david.l@mullvad.net>2023-10-20 18:17:24 +0200
commit8a5ad4bb07dec0e34985fc5eaa9c40352bc05655 (patch)
treeb95ea58bc205e0f717e9e4d75bef39d773786f2a /talpid-windows
parent5cee95d43bb0cc3654e5558ba02919dbf32d52aa (diff)
downloadmullvadvpn-8a5ad4bb07dec0e34985fc5eaa9c40352bc05655.tar.xz
mullvadvpn-8a5ad4bb07dec0e34985fc5eaa9c40352bc05655.zip
Add process module to talpid-windows
Diffstat (limited to 'talpid-windows')
-rw-r--r--talpid-windows/src/lib.rs3
-rw-r--r--talpid-windows/src/process.rs157
-rw-r--r--talpid-windows/src/sync.rs24
3 files changed, 162 insertions, 22 deletions
diff --git a/talpid-windows/src/lib.rs b/talpid-windows/src/lib.rs
index 865c3e8a81..755f6b2e30 100644
--- a/talpid-windows/src/lib.rs
+++ b/talpid-windows/src/lib.rs
@@ -12,3 +12,6 @@ pub mod net;
/// Synchronization
pub mod sync;
+
+/// Processes
+pub mod process;
diff --git a/talpid-windows/src/process.rs b/talpid-windows/src/process.rs
new file mode 100644
index 0000000000..ecddbe09f2
--- /dev/null
+++ b/talpid-windows/src/process.rs
@@ -0,0 +1,157 @@
+use std::{
+ ffi::{c_char, CStr},
+ io, mem,
+};
+use windows_sys::Win32::{
+ Foundation::{CloseHandle, ERROR_NO_MORE_FILES, HANDLE, INVALID_HANDLE_VALUE},
+ System::Diagnostics::ToolHelp::{
+ CreateToolhelp32Snapshot, Module32First, Module32Next, Process32FirstW, Process32NextW,
+ MODULEENTRY32, PROCESSENTRY32W,
+ },
+};
+
+/// A snapshot of process modules, threads, and heaps
+pub struct ProcessSnapshot {
+ handle: HANDLE,
+}
+
+impl ProcessSnapshot {
+ /// Create a new process snapshot using `CreateToolhelp32Snapshot`
+ pub fn new(flags: u32, process_id: u32) -> io::Result<ProcessSnapshot> {
+ let snap = unsafe { CreateToolhelp32Snapshot(flags, process_id) };
+
+ if snap == INVALID_HANDLE_VALUE {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(ProcessSnapshot { handle: snap })
+ }
+ }
+
+ /// Return the raw handle
+ pub fn as_raw(&self) -> HANDLE {
+ self.handle
+ }
+
+ /// Return an iterator over the modules in the snapshot
+ pub fn modules(&self) -> ProcessSnapshotModules<'_> {
+ let mut entry: MODULEENTRY32 = unsafe { mem::zeroed() };
+ entry.dwSize = mem::size_of::<MODULEENTRY32>() as u32;
+
+ ProcessSnapshotModules {
+ snapshot: self,
+ iter_started: false,
+ temp_entry: entry,
+ }
+ }
+
+ /// Return an iterator over the processes in the snapshot
+ pub fn processes(&self) -> ProcessSnapshotEntries<'_> {
+ let mut entry: PROCESSENTRY32W = unsafe { mem::zeroed() };
+ entry.dwSize = mem::size_of::<PROCESSENTRY32W>() as u32;
+
+ ProcessSnapshotEntries {
+ snapshot: self,
+ iter_started: false,
+ temp_entry: entry,
+ }
+ }
+}
+
+impl Drop for ProcessSnapshot {
+ fn drop(&mut self) {
+ unsafe {
+ CloseHandle(self.handle);
+ }
+ }
+}
+
+/// Description of a snapshot module entry. See `MODULEENTRY32`
+pub struct ModuleEntry {
+ /// Module name
+ pub name: String,
+ /// Module base address (in the owning process)
+ pub base_address: *const u8,
+ /// Size of the module (in bytes)
+ pub size: usize,
+}
+
+/// Module iterator for [ProcessSnapshot]
+pub struct ProcessSnapshotModules<'a> {
+ snapshot: &'a ProcessSnapshot,
+ iter_started: bool,
+ temp_entry: MODULEENTRY32,
+}
+
+impl Iterator for ProcessSnapshotModules<'_> {
+ type Item = io::Result<ModuleEntry>;
+
+ fn next(&mut self) -> Option<io::Result<ModuleEntry>> {
+ if self.iter_started {
+ if unsafe { Module32Next(self.snapshot.as_raw(), &mut self.temp_entry) } == 0 {
+ let last_error = io::Error::last_os_error();
+
+ return if last_error.raw_os_error().unwrap() as u32 == ERROR_NO_MORE_FILES {
+ None
+ } else {
+ Some(Err(last_error))
+ };
+ }
+ } else {
+ if unsafe { Module32First(self.snapshot.as_raw(), &mut self.temp_entry) } == 0 {
+ return Some(Err(io::Error::last_os_error()));
+ }
+ self.iter_started = true;
+ }
+
+ let cstr_ref = &self.temp_entry.szModule[0];
+ let cstr = unsafe { CStr::from_ptr(cstr_ref as *const u8 as *const c_char) };
+ Some(Ok(ModuleEntry {
+ name: cstr.to_string_lossy().into_owned(),
+ base_address: self.temp_entry.modBaseAddr,
+ size: self.temp_entry.modBaseSize as usize,
+ }))
+ }
+}
+
+/// Description of a snapshot process entry. See `PROCESSENTRY32W`
+pub struct ProcessEntry {
+ /// Process identifier
+ pub pid: u32,
+ /// Process identifier of the parent process
+ pub parent_pid: u32,
+}
+
+/// Process iterator for [ProcessSnapshot]
+pub struct ProcessSnapshotEntries<'a> {
+ snapshot: &'a ProcessSnapshot,
+ iter_started: bool,
+ temp_entry: PROCESSENTRY32W,
+}
+
+impl Iterator for ProcessSnapshotEntries<'_> {
+ type Item = io::Result<ProcessEntry>;
+
+ fn next(&mut self) -> Option<io::Result<ProcessEntry>> {
+ if self.iter_started {
+ if unsafe { Process32NextW(self.snapshot.as_raw(), &mut self.temp_entry) } == 0 {
+ let last_error = io::Error::last_os_error();
+
+ return if last_error.raw_os_error().unwrap() as u32 == ERROR_NO_MORE_FILES {
+ None
+ } else {
+ Some(Err(last_error))
+ };
+ }
+ } else {
+ if unsafe { Process32FirstW(self.snapshot.as_raw(), &mut self.temp_entry) } == 0 {
+ return Some(Err(io::Error::last_os_error()));
+ }
+ self.iter_started = true;
+ }
+
+ Some(Ok(ProcessEntry {
+ pid: self.temp_entry.th32ProcessID,
+ parent_pid: self.temp_entry.th32ParentProcessID,
+ }))
+ }
+}
diff --git a/talpid-windows/src/sync.rs b/talpid-windows/src/sync.rs
index 7b4ed59be3..202c96524d 100644
--- a/talpid-windows/src/sync.rs
+++ b/talpid-windows/src/sync.rs
@@ -1,7 +1,7 @@
use std::{io, ptr};
use windows_sys::Win32::{
- Foundation::{CloseHandle, DuplicateHandle, BOOL, DUPLICATE_SAME_ACCESS, HANDLE},
- System::Threading::{CreateEventW, GetCurrentProcess, SetEvent},
+ Foundation::{CloseHandle, BOOL, HANDLE},
+ System::Threading::{CreateEventW, SetEvent},
};
/// Windows event object
@@ -39,26 +39,6 @@ impl Event {
pub fn as_raw(&self) -> HANDLE {
self.0
}
-
- /// Duplicate the event object with `DuplicateHandle()`
- pub fn duplicate(&self) -> io::Result<Event> {
- let mut new_event = 0;
- let status = unsafe {
- DuplicateHandle(
- GetCurrentProcess(),
- self.0,
- GetCurrentProcess(),
- &mut new_event,
- 0,
- 0,
- DUPLICATE_SAME_ACCESS,
- )
- };
- if status == 0 {
- return Err(io::Error::last_os_error());
- }
- Ok(Event(new_event))
- }
}
impl Drop for Event {