@@ -6,20 +6,19 @@ use crate::platform::windows::tcp_table::TcpTable;
66use crate :: platform:: windows:: tcp6_table:: Tcp6Table ;
77use std:: collections:: HashMap ;
88use std:: collections:: hash_map:: Entry ;
9+ use std:: ffi:: CStr ;
910use std:: mem:: size_of;
1011use std:: mem:: zeroed;
1112use std:: net:: { IpAddr , SocketAddr } ;
1213use std:: os:: windows:: ffi:: OsStringExt ;
1314use std:: path:: Path ;
14- use windows :: Win32 :: Foundation :: CloseHandle ;
15- use windows :: Win32 :: System :: Diagnostics :: ToolHelp :: {
15+ use windows_sys :: Win32 :: Foundation :: { CloseHandle , FALSE , HANDLE , INVALID_HANDLE_VALUE } ;
16+ use windows_sys :: Win32 :: System :: Diagnostics :: ToolHelp :: {
1617 CreateToolhelp32Snapshot , PROCESSENTRY32 , Process32First , Process32Next , TH32CS_SNAPPROCESS ,
1718} ;
18- use windows :: Win32 :: System :: Threading :: {
19- OpenProcess , PROCESS_NAME_FORMAT , PROCESS_QUERY_LIMITED_INFORMATION , QueryFullProcessImageNameW ,
19+ use windows_sys :: Win32 :: System :: Threading :: {
20+ OpenProcess , PROCESS_NAME_WIN32 , PROCESS_QUERY_LIMITED_INFORMATION , QueryFullProcessImageNameW ,
2021} ;
21- use windows:: core:: PCSTR ;
22- use windows:: core:: PWSTR ;
2322
2423use super :: udp_table:: UdpTable ;
2524use super :: udp6_table:: Udp6Table ;
@@ -149,27 +148,46 @@ impl PidNamePathCache {
149148 }
150149}
151150
151+ fn is_invalid ( handle : HANDLE ) -> bool {
152+ handle. is_null ( ) || handle == INVALID_HANDLE_VALUE
153+ }
154+
155+ /// Takes a snapshot of the running processes.
156+ fn process_snapshot ( ) -> Option < HANDLE > {
157+ let handle = unsafe { CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS , 0 ) } ;
158+ ( !is_invalid ( handle) ) . then_some ( handle)
159+ }
160+
161+ /// Reads the `szExeFile` field of a process entry.
162+ ///
163+ /// Returns `None` if the field isn't NUL-terminated or isn't valid UTF-8.
164+ fn exe_file ( process : & PROCESSENTRY32 ) -> Option < String > {
165+ let raw = & process. szExeFile ;
166+ // SAFETY: `c_char` and `u8` share their layout, and the length is taken from the
167+ // array itself, so the read stays within `szExeFile` even if the OS didn't
168+ // NUL-terminate it.
169+ let bytes = unsafe { std:: slice:: from_raw_parts ( raw. as_ptr ( ) . cast :: < u8 > ( ) , raw. len ( ) ) } ;
170+ let name = CStr :: from_bytes_until_nul ( bytes) . ok ( ) ?;
171+ name. to_str ( ) . ok ( ) . map ( str:: to_owned)
172+ }
173+
152174fn pname ( pid : u32 ) -> Option < String > {
153- let h = unsafe { CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS , 0 ) . ok ( ) ? } ;
175+ let dw_size = u32:: try_from ( size_of :: < PROCESSENTRY32 > ( ) ) . ok ( ) ?;
176+ let h = process_snapshot ( ) ?;
154177
155178 let mut process = unsafe { zeroed :: < PROCESSENTRY32 > ( ) } ;
156- process. dwSize = u32 :: try_from ( size_of :: < PROCESSENTRY32 > ( ) ) . ok ( ) ? ;
179+ process. dwSize = dw_size ;
157180
158181 let mut result = None ;
159182
160- if unsafe { Process32First ( h, & raw mut process) } . is_ok ( ) {
183+ if unsafe { Process32First ( h, & raw mut process) } != FALSE {
161184 loop {
162185 if process. th32ProcessID == pid {
163- let name = unsafe {
164- PCSTR ( process. szExeFile . as_ptr ( ) . cast :: < u8 > ( ) )
165- . to_string ( )
166- . ok ( ) ?
167- } ;
168- result = Some ( name) ;
186+ result = exe_file ( & process) ;
169187 break ;
170188 }
171189
172- if unsafe { Process32Next ( h, & raw mut process) } . is_err ( ) {
190+ if unsafe { Process32Next ( h, & raw mut process) } == FALSE {
173191 break ;
174192 }
175193 }
@@ -184,10 +202,8 @@ fn pname(pid: u32) -> Option<String> {
184202
185203fn ppath ( pid : u32 ) -> String {
186204 unsafe {
187- let Ok ( handle) = OpenProcess ( PROCESS_QUERY_LIMITED_INFORMATION , false , pid) else {
188- return String :: new ( ) ;
189- } ;
190- if handle. is_invalid ( ) {
205+ let handle = OpenProcess ( PROCESS_QUERY_LIMITED_INFORMATION , FALSE , pid) ;
206+ if is_invalid ( handle) {
191207 return String :: new ( ) ;
192208 }
193209
@@ -196,13 +212,13 @@ fn ppath(pid: u32) -> String {
196212
197213 let result = QueryFullProcessImageNameW (
198214 handle,
199- PROCESS_NAME_FORMAT ( 0 ) ,
200- PWSTR ( buffer. as_mut_ptr ( ) ) ,
215+ PROCESS_NAME_WIN32 ,
216+ buffer. as_mut_ptr ( ) ,
201217 & raw mut size,
202218 ) ;
203219 let _ = CloseHandle ( handle) ;
204220
205- if result. is_err ( ) {
221+ if result == FALSE {
206222 return String :: new ( ) ;
207223 }
208224
@@ -214,25 +230,24 @@ fn ppath(pid: u32) -> String {
214230fn pname_collect ( ) -> HashMap < u32 , String > {
215231 let mut ret_val = HashMap :: default ( ) ;
216232
217- let Ok ( h ) = ( unsafe { CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS , 0 ) } ) else {
233+ let Ok ( dw_size ) = u32 :: try_from ( size_of :: < PROCESSENTRY32 > ( ) ) else {
218234 return ret_val;
219235 } ;
220-
221- let mut process = unsafe { zeroed :: < PROCESSENTRY32 > ( ) } ;
222- let Ok ( dw_size) = u32:: try_from ( size_of :: < PROCESSENTRY32 > ( ) ) else {
236+ let Some ( h) = process_snapshot ( ) else {
223237 return ret_val;
224238 } ;
239+
240+ let mut process = unsafe { zeroed :: < PROCESSENTRY32 > ( ) } ;
225241 process. dwSize = dw_size;
226242
227- if unsafe { Process32First ( h, & raw mut process) } . is_ok ( ) {
243+ if unsafe { Process32First ( h, & raw mut process) } != FALSE {
228244 loop {
229- if let Ok ( name) = unsafe { PCSTR ( process. szExeFile . as_ptr ( ) . cast :: < u8 > ( ) ) . to_string ( ) }
230- {
245+ if let Some ( name) = exe_file ( & process) {
231246 let id = process. th32ProcessID ;
232247 ret_val. insert ( id, name) ;
233248 }
234249
235- if unsafe { Process32Next ( h, & raw mut process) } . is_err ( ) {
250+ if unsafe { Process32Next ( h, & raw mut process) } == FALSE {
236251 break ;
237252 }
238253 }
0 commit comments