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 _
};
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 _
};
Share
Improve this question
edited Nov 20, 2024 at 8:34
Tom Stock
asked Nov 19, 2024 at 17:07
Tom StockTom Stock
1,2982 gold badges15 silver badges29 bronze badges
5
|
2 Answers
Reset to default 1You 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()
.
The answer from Anton Tykhyy works splendidly; though in the meantime I have found another way to solve this problem, by casting to a c_void
type as shown below:
let cid: CLIENT_ID = CLIENT_ID {
UniqueProcess: HANDLE(pid as *mut core::ffi::c_void),
UniqueThread: HANDLE(0 as *mut core::ffi::c_void)
};
HANDLE
instead. – IInspectable Commented Nov 19, 2024 at 17:19HANDLE
? Currently I'm retrieving the PID by creating a snapshot withCreateToolhelp32Snapshot
and iterating over the snapshot handle withProcess32Next
function, filtering on the process name. This does not seem to have any way of getting theHANDLE
of the process. The goal is not to use theOpenProcess
winapi function, and instead use theNtOpenProcess
syscall. – Tom Stock Commented Nov 20, 2024 at 8:30OpenProcess()
? – Anton Tykhyy Commented Nov 20, 2024 at 9:11