我正在尝试使用
NtOpenProcess
板条箱在 Rust 中进行 windows-rs
系统调用。我有以下代码,但无法弄清楚如何将 u32
pid 转换为 HANDLE
类型,这是结构所需的。
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
);
}
// ...
}
编译时出现以下错误:
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
所以问题是;如何将其转换为有效的代码?
编辑: 使用
ntapi
板条箱似乎确实可以使用 CLIENT_ID
PID 获得有效的 u32
。但是,我真的很想对所有 Windows 交互使用单个包(windows-rs
包,因为这个包是由 Microsoft 维护的)。
use ntapi::ntapi_base::CLIENT_ID;
let cid: CLIENT_ID = CLIENT_ID {
UniqueProcess: pid as _,
UniqueThread: 0 as _
};
您会遇到类型不匹配的情况,因为
windows::Win32::System::WindowsProgramming::CLIENT_ID
是从 Winternl.h 自动生成的,winternl.h 是 Windows SDK 中的一个奇怪的包含文件,不应该用于与 ntdll 级 API(例如 NtOpenProcess()
)一起使用,这些 API 不属于 Windows API。如果使用NtOpenProcess()
,则需要使用相应的结构体定义。如果您不想引入整个 ntapi
箱子,只需定义您自己的 struct CLIENT_ID
即可。由于无论如何您都使用“软”系统调用宏调用 NtOpenProcess()
,因此它在兼容性、可移植性等方面不应该产生任何差异。
PS:一些措辞澄清:PID 和
HANDLE
是完全不同的东西,不能相互“转换”。 HANDLE
是内核进程对象的用户空间句柄,PID 是该对象的属性。您可以使用 GetProcessId()
通过句柄获取 PID,并且可以通过创建新进程或打开现有进程来获取句柄,无论是使用 OpenProcess()
还是NtOpenProcess()
。