I'm trying to make the NtOpenProcess
syscall in rust using the windows-rs
crate. I've got the following code but cannot figure out how to convert a u32
pid to a HANDLE
type, which is needed for the struct.
use windows::Wdk::Foundation::{
OBJECT_ATTRIBUTES,
};
use windows::Win32::Foundation::{
HANDLE,
};
use windows::Win32::System::WindowsProgramming::{
CLIENT_ID,
};
use windows::Win32::System::Threading::{
PROCESS_ALL_ACCESS,
};
fn some_func() {
// ...
let pid: u32 = 1402; // Obtained somewhere else (not relevant to the question how)
let mut handle: HANDLE = HANDLE::default();
let oa = OBJECT_ATTRIBUTES::default();
let cid: CLIENT_ID = CLIENT_ID {
UniqueProcess: pid,
UniqueThread: 0
};
unsafe {
// This part is out of scope for the question; assume this macro will work
syscall!(
"NtOpenProcess",
&mut handle,
PROCESS_ALL_ACCESS,
&oa,
&cid
);
}
// ...
}
When compiling I get the following errors:
error[E0308]: mismatched types
--> src/main.rs:67:28
|
67 | UniqueProcess: pid,
| ^^^ expected `HANDLE`, found `u32`
error[E0308]: mismatched types
--> src/main.rs:68:27
|
68 | UniqueThread: 0
| ^ expected `HANDLE`, found integer
So the question is; how to I convert this to valid code?
Edit: Using the ntapi
crate it does seem to be possible to obtain a valid CLIENT_ID
using a u32
PID. However, I would really like to use a single package for all windows interaction (the windows-rs
one, as this one is maintained by Microsoft).
use ntapi::ntapi_base::CLIENT_ID;
let cid: CLIENT_ID = CLIENT_ID {
UniqueProcess: pid as _,
UniqueThread: 0 as _
};
You are getting type mismatches because windows::Win32::System::WindowsProgramming::CLIENT_ID
is auto-generated from winternl.h, an oddball include file in Windows SDK that should not be used to work with ntdll-level APIs like NtOpenProcess()
that are not part of Windows API. If you use NtOpenProcess()
, you need to use corresponding struct definitions. If you don't want to pull in the whole ntapi
crate, just define your own struct CLIENT_ID
. Since you're invoking NtOpenProcess()
with a "soft" syscall macro anyway, it should not make any difference in terms of compatibility, portability etc.
PS: a bit of wording clarification: a PID and a HANDLE
are completely different things and cannot be 'converted' to each other. HANDLE
is a userspace handle to the kernel process object and a PID is a property of said object. You get the PID by handle with GetProcessId()
, and you get a handle by creating a new process or opening an existing process, whether with OpenProcess()
or NtOpenProcess()
.