extern crate libc;
mod kernel32;
use super::Process;
use super::Problem;
fn process(entry: &kernel32::PROCESSENTRY32) -> Process {
let mut ps = Process {
pid: entry.pid as i32,
ppid: entry.ppid as i32,
name: String::from_utf16_lossy(&entry.file).trim_right_matches(0x00 as char).to_string(),
path: None,
};
unsafe {
let handle = kernel32::OpenProcess(0x00000400, 0, entry.pid);
if (handle as i32) >= 0 {
let mut name: [u16; 260] = [0; 260];
let mut size = 260;
let result = kernel32::QueryFullProcessImageNameW(handle, 0, &mut name[0], &mut size);
kernel32::CloseHandle(handle);
if result != 0 {
let full =
String::from_utf16_lossy(&name).trim_right_matches(0x00 as char).to_string();
ps.path = Some(full);
}
}
}
return ps;
}
fn problem(code: u32) -> Problem {
let message: String;
unsafe {
let mut buff: [u16; kernel32::MAX_PATH] = [0; kernel32::MAX_PATH];
let size = kernel32::MAX_PATH as u32;
let null = 0 as *mut libc::c_void;
kernel32::FormatMessageW(kernel32::FORMAT_MESSAGE_FROM_SYSTEM,
null,
code,
0,
&mut buff[0],
size,
null);
message = String::from_utf16_lossy(&buff).trim_right_matches(0x00 as char).to_string();
}
return Problem::new(message.as_str());
}
fn snapshot() -> Result<Vec<kernel32::PROCESSENTRY32>, Problem> {
let mut processes: Vec<kernel32::PROCESSENTRY32> = Vec::new();
unsafe {
let snapshot = kernel32::CreateToolhelp32Snapshot(kernel32::TH32CS_SNAPPROCESS, 0);
if (snapshot as i32) < 0 {
return Err(problem(kernel32::GetLastError()));
}
let mut entry = Box::new(kernel32::PROCESSENTRY32::new());
let mut result = kernel32::Process32FirstW(snapshot, &mut *entry);
if result == 0 {
kernel32::CloseHandle(snapshot);
let error = kernel32::GetLastError();
if error == kernel32::ERROR_NO_MORE_FILES {
return Ok(processes);
} else {
return Err(problem(error));
}
} else {
processes.push(*(entry.clone()));
}
loop {
result = kernel32::Process32NextW(snapshot, &mut *entry);
if result == 0 {
kernel32::CloseHandle(snapshot);
let error = kernel32::GetLastError();
if error == kernel32::ERROR_NO_MORE_FILES {
return Ok(processes);
} else {
return Err(problem(error));
}
}
processes.push(*(entry.clone()));
}
}
}
pub fn find(pid: u32) -> Result<Process, Problem> {
match snapshot() {
Ok(pss) => {
for ps in pss {
if ps.pid == pid {
return Ok(process(&ps));
}
}
return Err(problem(kernel32::ERROR_NOT_FOUND));
}
Err(err) => {
return Err(err);
}
};
}