Microsoft Windows user-mode API access with clean Rust types.
Some Windows APIs execute in several layers:
- The stable user-mode component
- The unstable native component
- The system call to the kernel
For example, to terminate a process, one typically calls the stable user-mode function
kernel32.TerminateProcess, which itself calls the unstable native function
ntdll.NtTerminateProcess, which then performs a system call to ntoskrnl.NtTerminateProcess.
This crate allows to call every single variant in this chain, but also provides a default
option. What the default option uses can be defined with the winapi attribute:
| Attribute | Usage |
|---|---|
| Unspecified | Stable user-mode |
native |
Unstable native |
syscall |
Direct system call |
The attribute can be specified as an argument to rustc via --cfg winapi="syscall", or used
by cargo build by specifying the following in the .cargo/config file at the crate-root:
[target.YOUR_TARGET]
rustflags = ['--cfg', 'winapi="syscall"']System calls are done by triggering a transition from user- to kernel-mode - the executing
thread will end up at a specific function in the Windows kernel. To know which function the user
wanted to call, a 0 (ntoskrnl.exe) or 0x1000 (win32k.sys) based index must be specified
in the eax register.
The crate loads these indices from the crate::SYSCALL_IDS variable, which must be set by the
crate user prior to any winapi2 usage. Either set them explicitly, or call a function like
winapi2::SyscallIds::initialize_statically to outsource the task to the library itself:
fn main() {
// Either outsourced:
winapi2::SyscallIds::initialize_statically();
// Or explicit:
#[cfg(target_arch = "x86")]
unsafe {
winapi2::SYSCALL_IDS = Some(winapi2::SyscallIds {
terminate_process: 0x0001,
// .. set all the system specific system call ids.
});
}
#[cfg(target_arch = "x86_64")]
unsafe {
winapi2::SYSCALL_IDS = Some(winapi2::SyscallIds {
terminate_process: 0x0001,
// .. set all the system specific system call ids.
});
}
// Now the `syscall` mode and specific `*_syscall` functions can be used.
winapi2::Process::current().terminate_syscall(0);
}Warning: This is architecture specific! It supports 32 bit applications on a 32 bit Windows system, and 64 bit applications on a 64 bit Windows system. Executing a system call in a 32 bit application on a 64 bit Windows system ("WOW64") will not work and potentially crash the application if no exception handlers are set up!
This project assumes target_pointer_width >= 32.
This crate optionally provides implementations for the symbols: __chkstk, __fltused,
__alldiv, __allrem, __aulldiv and __aullrem (and others of the same kind), if the
feature builtins is used:
[dependencies]
winapi2 = { ..., features = ["builtins"] }