1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#[cfg(not(target_os = "windows"))]
extern crate libc;
#[cfg(target_os = "windows")]
extern crate winapi;
extern crate nserror;
extern crate xpcom;
use std::convert::TryInto;
use nserror::{nsresult, NS_ERROR_FAILURE, NS_OK};
use xpcom::{interfaces::nsIProcessToolsService, xpcom, xpcom_method, RefPtr};
// Separate this `use` to avoid build-breaking warnings.
#[cfg(target_os = "windows")]
use nserror::NS_ERROR_NOT_AVAILABLE;
#[no_mangle]
pub unsafe extern "C" fn new_process_tools_service(result: *mut *const nsIProcessToolsService) {
let service: RefPtr<ProcessToolsService> = ProcessToolsService::new();
RefPtr::new(service.coerce::<nsIProcessToolsService>()).forget(&mut *result);
}
// Implementation note:
//
// We're following the strategy employed by the `kvstore`.
// See https://searchfox.org/mozilla-central/rev/a87a1c3b543475276e6d57a7a80cb02f3e42b6ed/toolkit/components/kvstore/src/lib.rs#78
#[derive(xpcom)]
#[refcnt = "atomic"]
#[xpimplements(nsIProcessToolsService)]
pub struct InitProcessToolsService {}
impl ProcessToolsService {
pub fn new() -> RefPtr<ProcessToolsService> {
ProcessToolsService::allocate(InitProcessToolsService {})
}
// Method `kill`.
xpcom_method!(
kill => Kill(id: u64)
);
#[cfg(target_os = "windows")]
pub fn kill(&self, pid: u64) -> Result<(), nsresult> {
let handle = unsafe {
winapi::um::processthreadsapi::OpenProcess(
/* dwDesiredAccess */
winapi::um::winnt::PROCESS_TERMINATE | winapi::um::winnt::SYNCHRONIZE,
/* bInheritHandle */ 0,
/* dwProcessId */ pid.try_into().unwrap(),
)
};
if handle.is_null() {
// Could not open process.
return Err(NS_ERROR_NOT_AVAILABLE);
}
let result = unsafe {
winapi::um::processthreadsapi::TerminateProcess(
/* hProcess */ handle, /* uExitCode */ 0,
)
};
// Close handle regardless of success.
let _ = unsafe { winapi::um::handleapi::CloseHandle(handle) };
if result == 0 {
return Err(NS_ERROR_FAILURE);
}
Ok(())
}
#[cfg(not(target_os = "windows"))]
pub fn kill(&self, pid: u64) -> Result<(), nsresult> {
let pid = pid.try_into().or(Err(NS_ERROR_FAILURE))?;
let result = unsafe { libc::kill(pid, libc::SIGKILL) };
if result == 0 {
Ok(())
} else {
Err(NS_ERROR_FAILURE)
}
}
// Attribute `pid`
xpcom_method!(
get_pid => GetPid() -> u64
);
#[cfg(not(target_os = "windows"))]
pub fn get_pid(&self) -> Result<u64, nsresult> {
let pid = unsafe { libc::getpid() } as u64;
Ok(pid)
}
#[cfg(target_os = "windows")]
pub fn get_pid(&self) -> Result<u64, nsresult> {
let pid = unsafe { winapi::um::processthreadsapi::GetCurrentProcessId() } as u64;
Ok(pid)
}
}
|