Repository: StephanvanSchaik/windows-kernel-rs
Branch: main
Commit: dda32b0596d4
Files: 80
Total size: 136.1 KB
Directory structure:
gitextract_enzorjhr/
├── .gitignore
├── 02-hello-world/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 03-generating-bindings/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 04-safe-framework/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 05-creating-devices/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 06-reading-and-writing/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 07-io-controls/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── LICENSE
├── README.md
├── user/
│ ├── 05-creating-devices/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── 06-reading-and-writing/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ └── 07-io-controls/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── windows-kernel-build/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── windows-kernel-rs/
│ ├── Cargo.toml
│ ├── rust-toolchain
│ └── src/
│ ├── affinity.rs
│ ├── allocator.rs
│ ├── device.rs
│ ├── driver.rs
│ ├── error.rs
│ ├── intrin.rs
│ ├── io.rs
│ ├── ioctl.rs
│ ├── lib.rs
│ ├── mdl.rs
│ ├── memory.rs
│ ├── process.rs
│ ├── request.rs
│ ├── section.rs
│ ├── string.rs
│ ├── symbolic_link.rs
│ ├── sync/
│ │ ├── fast_mutex.rs
│ │ ├── mod.rs
│ │ └── push_lock.rs
│ ├── user_ptr.rs
│ └── version.rs
├── windows-kernel-sys/
│ ├── Cargo.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ ├── base.rs
│ ├── intrin.rs
│ ├── lib.rs
│ ├── netio.rs
│ ├── ntoskrnl.rs
│ ├── wrapper.c
│ ├── wrapper.h
│ ├── wrapper_intrin.c
│ └── wrapper_netio.h
└── winioctl/
├── Cargo.toml
└── src/
├── error.rs
├── ioctl.rs
└── lib.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
**/target/
*.lock
*.dll
*.pdb
*.lib
*.exe
*.cer
================================================
FILE: 02-hello-world/Cargo.toml
================================================
[package]
name = "02-hello-world"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
[build-dependencies]
windows-kernel-build = { path = "../windows-kernel-build" }
[dependencies.winapi]
git = "https://github.com/Trantect/winapi-rs.git"
branch = "feature/km"
features = [
"wdm",
"ntstatus",
]
================================================
FILE: 02-hello-world/Makefile.toml
================================================
[env]
VC_BUILD_DIR="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat"
[env.development]
TARGET_PATH = "target/debug"
[env.production]
TARGET_PATH = "target/release"
BUILD_RELEASE = "--release"
[tasks.clean-cert]
script = '''
# Remove the self-signed certificate.
if exist DriverCertificate.cer ( rm DriverCertificate.cer )
'''
[tasks.build-driver]
script = '''
cargo b %BUILD_FLAGS%
'''
[tasks.rename]
ignore_errors = true
script = '''
cd %TARGET_PATH%
rename driver.dll driver.sys
'''
[tasks.sign]
dependencies = ["build-driver", "rename"]
script = '''
call "%VC_BUILD_DIR%"
if not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )
signtool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys
'''
================================================
FILE: 02-hello-world/build.rs
================================================
fn main() {
windows_kernel_build::build().unwrap();
}
================================================
FILE: 02-hello-world/rust-toolchain
================================================
nightly
================================================
FILE: 02-hello-world/src/lib.rs
================================================
#![no_std]
use core::panic::PanicInfo;
use winapi::km::wdm::{DbgPrint, DRIVER_OBJECT};
use winapi::shared::ntdef::{NTSTATUS, UNICODE_STRING};
use winapi::shared::ntstatus::STATUS_SUCCESS;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
#[no_mangle]
pub extern "system" fn driver_entry(driver: &mut DRIVER_OBJECT, _: &UNICODE_STRING) -> NTSTATUS {
unsafe {
DbgPrint("Hello, world!\0".as_ptr());
}
driver.DriverUnload = Some(driver_exit);
STATUS_SUCCESS
}
pub extern "system" fn driver_exit(_driver: &mut DRIVER_OBJECT) {
unsafe {
DbgPrint("Bye bye!\0".as_ptr());
}
}
================================================
FILE: 03-generating-bindings/Cargo.toml
================================================
[package]
name = "03-generating-bindings"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
[build-dependencies]
windows-kernel-build = { path = "../windows-kernel-build" }
[dependencies]
windows-kernel-sys = { path = "../windows-kernel-sys" }
================================================
FILE: 03-generating-bindings/Makefile.toml
================================================
[env]
VC_BUILD_DIR="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat"
[env.development]
TARGET_PATH = "target/debug"
[env.production]
TARGET_PATH = "target/release"
BUILD_RELEASE = "--release"
[tasks.clean-cert]
script = '''
# Remove the self-signed certificate.
if exist DriverCertificate.cer ( rm DriverCertificate.cer )
'''
[tasks.build-driver]
script = '''
cargo b %BUILD_FLAGS%
'''
[tasks.rename]
ignore_errors = true
script = '''
cd %TARGET_PATH%
rename driver.dll driver.sys
'''
[tasks.sign]
dependencies = ["build-driver", "rename"]
script = '''
call "%VC_BUILD_DIR%"
if not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )
signtool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys
'''
================================================
FILE: 03-generating-bindings/build.rs
================================================
fn main() {
windows_kernel_build::build().unwrap();
}
================================================
FILE: 03-generating-bindings/rust-toolchain
================================================
nightly
================================================
FILE: 03-generating-bindings/src/lib.rs
================================================
#![no_std]
use core::panic::PanicInfo;
use windows_kernel_sys::base::{DRIVER_OBJECT, NTSTATUS, STATUS_SUCCESS, UNICODE_STRING};
use windows_kernel_sys::ntoskrnl::DbgPrint;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
#[no_mangle]
pub extern "system" fn driver_entry(driver: &mut DRIVER_OBJECT, _: &UNICODE_STRING) -> NTSTATUS {
unsafe {
DbgPrint("Hello, world!\0".as_ptr() as _);
}
driver.DriverUnload = Some(driver_exit);
STATUS_SUCCESS
}
pub unsafe extern "C" fn driver_exit(_driver: *mut DRIVER_OBJECT) {
DbgPrint("Bye bye!\0".as_ptr() as _);
}
================================================
FILE: 04-safe-framework/Cargo.toml
================================================
[package]
name = "04-safe-framework"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
[build-dependencies]
windows-kernel-build = { path = "../windows-kernel-build" }
[dependencies]
windows-kernel-rs = { path = "../windows-kernel-rs" }
windows-kernel-sys = { path = "../windows-kernel-sys" }
================================================
FILE: 04-safe-framework/Makefile.toml
================================================
[env]
VC_BUILD_DIR="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat"
[env.development]
TARGET_PATH = "target/debug"
[env.production]
TARGET_PATH = "target/release"
BUILD_RELEASE = "--release"
[tasks.clean-cert]
script = '''
# Remove the self-signed certificate.
if exist DriverCertificate.cer ( rm DriverCertificate.cer )
'''
[tasks.build-driver]
script = '''
cargo b %BUILD_FLAGS%
'''
[tasks.rename]
ignore_errors = true
script = '''
cd %TARGET_PATH%
rename driver.dll driver.sys
'''
[tasks.sign]
dependencies = ["build-driver", "rename"]
script = '''
call "%VC_BUILD_DIR%"
if not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )
signtool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys
'''
================================================
FILE: 04-safe-framework/build.rs
================================================
fn main() {
windows_kernel_build::build().unwrap();
}
================================================
FILE: 04-safe-framework/rust-toolchain
================================================
nightly
================================================
FILE: 04-safe-framework/src/lib.rs
================================================
#![no_std]
use windows_kernel_rs::{Driver, Error, kernel_module, KernelModule, println};
struct Module;
impl KernelModule for Module {
fn init(_: Driver, _: &str) -> Result<Self, Error> {
println!("Hello, world!");
Ok(Module)
}
fn cleanup(&mut self, _: Driver) {
println!("Bye bye!");
}
}
kernel_module!(Module);
================================================
FILE: 05-creating-devices/Cargo.toml
================================================
[package]
name = "05-creating-devices"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
[build-dependencies]
windows-kernel-build = { path = "../windows-kernel-build" }
[dependencies]
widestring = { version = "0.4", default-features = false, features = ["alloc"]}
windows-kernel-rs = { path = "../windows-kernel-rs" }
windows-kernel-sys = { path = "../windows-kernel-sys" }
================================================
FILE: 05-creating-devices/Makefile.toml
================================================
[env]
VC_BUILD_DIR="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat"
[env.development]
TARGET_PATH = "target/debug"
[env.production]
TARGET_PATH = "target/release"
BUILD_RELEASE = "--release"
[tasks.clean-cert]
script = '''
# Remove the self-signed certificate.
if exist DriverCertificate.cer ( rm DriverCertificate.cer )
'''
[tasks.build-driver]
script = '''
cargo b %BUILD_FLAGS%
'''
[tasks.rename]
ignore_errors = true
script = '''
cd %TARGET_PATH%
rename driver.dll driver.sys
'''
[tasks.sign]
dependencies = ["build-driver", "rename"]
script = '''
call "%VC_BUILD_DIR%"
if not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )
signtool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys
'''
================================================
FILE: 05-creating-devices/build.rs
================================================
fn main() {
windows_kernel_build::build().unwrap();
}
================================================
FILE: 05-creating-devices/rust-toolchain
================================================
nightly
================================================
FILE: 05-creating-devices/src/lib.rs
================================================
#![no_std]
use windows_kernel_rs::device::{
Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceType, RequestError};
use windows_kernel_rs::println;
use windows_kernel_rs::request::{IoRequest};
use windows_kernel_rs::{Access, Driver, Error, kernel_module, KernelModule, SymbolicLink};
struct MyDevice;
impl DeviceOperations for MyDevice {
fn create(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {
println!("userspace opened the device");
Ok(Completion::Complete(0, request))
}
fn close(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {
println!("userspace closed the device");
Ok(Completion::Complete(0, request))
}
fn cleanup(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {
println!("device is no longer in use by userspace");
Ok(Completion::Complete(0, request))
}
}
struct Module {
_device: Device,
_symbolic_link: SymbolicLink,
}
impl KernelModule for Module {
fn init(mut driver: Driver, _: &str) -> Result<Self, Error> {
let device = driver.create_device(
"\\Device\\Example",
DeviceType::Unknown,
DeviceFlags::SECURE_OPEN,
DeviceDoFlags::DO_BUFFERED_IO,
Access::NonExclusive,
MyDevice,
)?;
let symbolic_link = SymbolicLink::new("\\??\\Example", "\\Device\\Example")?;
Ok(Module {
_device: device,
_symbolic_link: symbolic_link,
})
}
fn cleanup(&mut self, _driver: Driver) {
}
}
kernel_module!(Module);
================================================
FILE: 06-reading-and-writing/Cargo.toml
================================================
[package]
name = "06-reading-and-writing"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
[build-dependencies]
windows-kernel-build = { path = "../windows-kernel-build" }
[dependencies]
widestring = { version = "0.4", default-features = false, features = ["alloc"]}
windows-kernel-rs = { path = "../windows-kernel-rs" }
windows-kernel-sys = { path = "../windows-kernel-sys" }
================================================
FILE: 06-reading-and-writing/Makefile.toml
================================================
[env]
VC_BUILD_DIR="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat"
[env.development]
TARGET_PATH = "target/debug"
[env.production]
TARGET_PATH = "target/release"
BUILD_RELEASE = "--release"
[tasks.clean-cert]
script = '''
# Remove the self-signed certificate.
if exist DriverCertificate.cer ( rm DriverCertificate.cer )
'''
[tasks.build-driver]
script = '''
cargo b %BUILD_FLAGS%
'''
[tasks.rename]
ignore_errors = true
script = '''
cd %TARGET_PATH%
rename driver.dll driver.sys
'''
[tasks.sign]
dependencies = ["build-driver", "rename"]
script = '''
call "%VC_BUILD_DIR%"
if not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )
signtool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys
'''
================================================
FILE: 06-reading-and-writing/build.rs
================================================
fn main() {
windows_kernel_build::build().unwrap();
}
================================================
FILE: 06-reading-and-writing/rust-toolchain
================================================
nightly
================================================
FILE: 06-reading-and-writing/src/lib.rs
================================================
#![no_std]
extern crate alloc;
use alloc::vec;
use alloc::vec::Vec;
use windows_kernel_rs::device::{
Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceType, RequestError};
use windows_kernel_rs::request::{ReadRequest, WriteRequest};
use windows_kernel_rs::{Access, Driver, Error, kernel_module, KernelModule, SymbolicLink};
struct MyDevice {
data: Vec<u8>,
}
impl DeviceOperations for MyDevice {
fn read(&mut self, _device: &Device, request: ReadRequest) -> Result<Completion, RequestError> {
let mut user_ptr = request.user_ptr();
let slice = user_ptr.as_mut_slice();
let offset = (request.offset() as usize).min(self.data.len());
let size = slice.len().min(self.data.len() - offset);
slice[0..size].copy_from_slice(&self.data[offset..offset + size]);
Ok(Completion::Complete(size as u32, request.into()))
}
fn write(&mut self, _device: &Device, request: WriteRequest) -> Result<Completion, RequestError> {
let user_ptr = request.user_ptr();
if request.offset() > 0 {
return Err(RequestError(Error::END_OF_FILE, request.into()))?;
}
let slice = user_ptr.as_slice();
let size = slice.len().min(4096);
self.data = slice[0..size].to_vec();
Ok(Completion::Complete(size as u32, request.into()))
}
}
struct Module {
_device: Device,
_symbolic_link: SymbolicLink,
}
impl KernelModule for Module {
fn init(mut driver: Driver, _: &str) -> Result<Self, Error> {
let device = driver.create_device(
"\\Device\\Example",
DeviceType::Unknown,
DeviceFlags::SECURE_OPEN,
DeviceDoFlags::DO_BUFFERED_IO,
Access::NonExclusive,
MyDevice {
data: vec![],
},
)?;
let symbolic_link = SymbolicLink::new("\\??\\Example", "\\Device\\Example")?;
Ok(Module {
_device: device,
_symbolic_link: symbolic_link,
})
}
}
kernel_module!(Module);
================================================
FILE: 07-io-controls/Cargo.toml
================================================
[package]
name = "07-io-controls"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
[build-dependencies]
windows-kernel-build = { path = "../windows-kernel-build" }
[dependencies]
widestring = { version = "0.4", default-features = false, features = ["alloc"]}
windows-kernel-rs = { path = "../windows-kernel-rs" }
windows-kernel-sys = { path = "../windows-kernel-sys" }
================================================
FILE: 07-io-controls/Makefile.toml
================================================
[env]
VC_BUILD_DIR="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat"
[env.development]
TARGET_PATH = "target/debug"
[env.production]
TARGET_PATH = "target/release"
BUILD_RELEASE = "--release"
[tasks.clean-cert]
script = '''
# Remove the self-signed certificate.
if exist DriverCertificate.cer ( rm DriverCertificate.cer )
'''
[tasks.build-driver]
script = '''
cargo b %BUILD_FLAGS%
'''
[tasks.rename]
ignore_errors = true
script = '''
cd %TARGET_PATH%
rename driver.dll driver.sys
'''
[tasks.sign]
dependencies = ["build-driver", "rename"]
script = '''
call "%VC_BUILD_DIR%"
if not exist DriverCertificate.cer ( makecert -r -pe -ss PrivateCertStore -n CN=DriverCertificate DriverCertificate.cer ) else ( echo Certificate already exists. )
signtool sign /a /v /s PrivateCertStore /n DriverCertificate /fd certHash /t http://timestamp.digicert.com %TARGET_PATH%/driver.sys
'''
================================================
FILE: 07-io-controls/build.rs
================================================
fn main() {
windows_kernel_build::build().unwrap();
}
================================================
FILE: 07-io-controls/rust-toolchain
================================================
nightly
================================================
FILE: 07-io-controls/src/lib.rs
================================================
#![no_std]
use windows_kernel_rs::device::{
Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceType, RequestError};
use windows_kernel_rs::request::IoControlRequest;
use windows_kernel_rs::{kernel_module, println};
use windows_kernel_rs::{Access, Driver, Error, KernelModule, RequiredAccess, SymbolicLink};
struct MyDevice {
value: u32,
}
const IOCTL_PRINT_VALUE: u32 = 0x800;
const IOCTL_READ_VALUE: u32 = 0x801;
const IOCTL_WRITE_VALUE: u32 = 0x802;
impl MyDevice {
fn print_value(&mut self, _request: &IoControlRequest) -> Result<u32, Error> {
println!("value: {}", self.value);
Ok(0)
}
fn read_value(&mut self, request: &IoControlRequest) -> Result<u32, Error> {
let mut user_ptr = request.user_ptr();
user_ptr.write(&self.value)?;
Ok(core::mem::size_of::<u32>() as u32)
}
fn write_value(&mut self, request: &IoControlRequest) -> Result<u32, Error> {
let user_ptr = request.user_ptr();
self.value = user_ptr.read()?;
Ok(0)
}
}
impl DeviceOperations for MyDevice {
fn ioctl(&mut self, _device: &Device, request: IoControlRequest) -> Result<Completion, RequestError> {
let result = match request.function() {
(_, IOCTL_PRINT_VALUE) =>
self.print_value(&request),
(RequiredAccess::READ_DATA, IOCTL_READ_VALUE) =>
self.read_value(&request),
(RequiredAccess::WRITE_DATA, IOCTL_WRITE_VALUE) =>
self.write_value(&request),
_ => Err(Error::INVALID_PARAMETER),
};
match result {
Ok(size) => Ok(Completion::Complete(size, request.into())),
Err(e) => Err(RequestError(e, request.into())),
}
}
}
struct Module {
_device: Device,
_symbolic_link: SymbolicLink,
}
impl KernelModule for Module {
fn init(mut driver: Driver, _: &str) -> Result<Self, Error> {
let device = driver.create_device(
"\\Device\\Example",
DeviceType::Unknown,
DeviceFlags::SECURE_OPEN,
DeviceDoFlags::DO_BUFFERED_IO,
Access::NonExclusive,
MyDevice {
value: 0,
},
)?;
let symbolic_link = SymbolicLink::new("\\??\\Example", "\\Device\\Example")?;
Ok(Module {
_device: device,
_symbolic_link: symbolic_link,
})
}
fn cleanup(&mut self, _driver: Driver) {
}
}
kernel_module!(Module);
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 S.J.R. van Schaik
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# windows-kernel-rs
**Note**: this is still work in progress!
This is a Windows kernel framework in Rust that consists of [windows-kernel-sys](windows-kernel-sys), a crate that provides low-level unsafe bindings generated using [bindgen](https://github.com/rust-lang/rust-bindgen), and [windows-kernel-rs](windows-kernel-rs), a crate that provides safe abstractions in Rust on top.
## Features
To give you an idea of whether these crates are useful to you, here is a non-exhaustive overview of the features that are currently supported and that are more or less planned:
* [x] `KernelModule` to provide safe entry and exit points to your driver.
* [x] Batteries included: panic handler, global allocator, etc.
* [x] Rust error handling using `Result`.
* [x] Device API to quickly set up with devices with a trait to provide the various callbacks.
* [x] Support for reading from and writing to devices.
* [x] Support for handling device I/O controls.
* [x] Basic safe abstraction on top of I/O Request Packets (IRPs) using Rust ownership to model their lifetimes.
* [x] Basic support for Memory Descriptor Lists (MDLs).
* [x] Version API to query the current version of Microsoft Windows.
* [x] Affinity API to run closures on a specific CPU or all CPUs in the system.
* [x] Device API
* [x] `FastMutex` (similar to [`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html)) based on the `FAST_MUTEX` API.
* [x] `PushLock` (similar to [`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html)) based on the `EX_PUSH_LOCK` API.
* [x] Abstraction for processes and process attachments to execute code in the context of a process.
* [x] Abstraction for sections.
* [x] Basic x86-64 intrinsics.
* [ ] More complete model of IRP handling.
* [ ] Support for x86 and AArch64.
## Articles
**Note**: this framework may progress faster than I can keep my articles up-to-date. They may currently be due for a bit of a rewrite to reflect some of the changes that made it into this repository since I have written the articles.
In addition, there are articles that cover implementing Windows kernel drivers in Rust from the ground up, including corresponding examples provided as part of this repository:
1. [Prerequisites](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-prerequisites)
2. [Hello World](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-hello-world) - [02-hello-world](02-hello-world)
3. [Generating Bindings](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-generating-bindings) - [03-generating-bindings](03-generating-bindings)
4. [Safe Framework](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-safe-framework) - [04-safe-framework](04-safe-framework)
5. [Creating Devices](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-creating-devices/) - [05-creating-devices](05-creating-devices) - [user/05-creating-devices](user/05-creating-devices)
6. [Reading and Writing](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-reading-and-writing/) - [06-reading-and-writing](06-reading-and-writing) - [user/06-reading-and-writing](user/06-reading-and-writing)
7. [I/O Controls](https://codentium.com/guides/windows-dev/windows-drivers-in-rust-io-controls/) - [07-io-controls](07-io-controls) - [user/07-io-controls](user/07-io-controls)
================================================
FILE: user/05-creating-devices/Cargo.toml
================================================
[package]
name = "user-05-creating-devices"
version = "0.1.0"
edition = "2018"
================================================
FILE: user/05-creating-devices/src/main.rs
================================================
use std::fs::File;
fn main() -> Result<(), std::io::Error> {
let _file = File::open("\\??\\Example")?;
Ok(())
}
================================================
FILE: user/06-reading-and-writing/Cargo.toml
================================================
[package]
name = "user-06-reading-and-writing"
version = "0.1.0"
edition = "2018"
================================================
FILE: user/06-reading-and-writing/src/main.rs
================================================
use std::fs::OpenOptions;
use std::io::{Read, Write};
fn main() -> Result<(), std::io::Error> {
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(false)
.open("\\??\\Example")?;
file.write_all("Hello, world!".as_bytes())?;
let mut data = vec![0u8; 4096];
let size = file.read(&mut data)?;
match std::str::from_utf8(&data[..size]) {
Ok(s) => println!("read {} bytes: \"{}\"", size, s),
_ => println!("read {} bytes: {:x?}", size, &data[..size]),
}
Ok(())
}
================================================
FILE: user/07-io-controls/Cargo.toml
================================================
[package]
name = "user-07-io-controls"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[target.'cfg(windows)'.dependencies]
winioctl = { path = "../../winioctl" }
================================================
FILE: user/07-io-controls/src/main.rs
================================================
use std::fs::OpenOptions;
use std::os::windows::io::AsRawHandle;
use winioctl::{DeviceType, Error};
use winioctl::{ioctl_none, ioctl_read, ioctl_write};
const IOCTL_PRINT_VALUE: u32 = 0x800;
const IOCTL_READ_VALUE: u32 = 0x801;
const IOCTL_WRITE_VALUE: u32 = 0x802;
ioctl_none!(ioctl_print_value, DeviceType::Unknown, IOCTL_PRINT_VALUE);
ioctl_read!(ioctl_read_value, DeviceType::Unknown, IOCTL_READ_VALUE, i32);
ioctl_write!(ioctl_write_value, DeviceType::Unknown, IOCTL_WRITE_VALUE, i32);
fn main() -> Result<(), Error> {
let file = OpenOptions::new()
.read(true)
.write(true)
.create(false)
.open("\\??\\Example")?;
let mut value = 0;
unsafe {
ioctl_read_value(file.as_raw_handle(), &mut value)?;
}
value += 1;
unsafe {
ioctl_write_value(file.as_raw_handle(), &value)?;
}
unsafe {
ioctl_print_value(file.as_raw_handle())?;
}
Ok(())
}
================================================
FILE: windows-kernel-build/Cargo.toml
================================================
[package]
name = "windows-kernel-build"
version = "0.1.0"
edition = "2021"
[dependencies]
thiserror = "1.0"
winreg = "0.51"
================================================
FILE: windows-kernel-build/src/lib.rs
================================================
use std::path::PathBuf;
use thiserror::Error;
use winreg::RegKey;
use winreg::enums::HKEY_LOCAL_MACHINE;
#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
IoError(#[from] std::io::Error),
#[error("cannot find the directory")]
DirectoryNotFound,
}
pub enum DirectoryType {
Include,
Library,
}
/// Retrieves the path to the Windows Kits directory. The default should be
/// `C:\Program Files (x86)\Windows Kits\10`.
pub fn get_windows_kits_dir() -> Result<PathBuf, Error> {
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
let key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots";
let dir: String = hklm.open_subkey(key)?.get_value("KitsRoot10")?;
Ok(dir.into())
}
/// Retrieves the path to the kernel mode libraries. The path may look something like:
/// `C:\Program Files (x86)\Windows Kits\10\lib\10.0.18362.0\km`.
pub fn get_km_dir(dir_type: DirectoryType) -> Result<PathBuf, Error> {
// We first append lib to the path and read the directory..
let dir = get_windows_kits_dir()?
.join(match dir_type {
DirectoryType::Include => "Include",
DirectoryType::Library => "Lib",
})
.read_dir()?;
// In the lib directory we may have one or more directories named after the version of Windows,
// we will be looking for the highest version number.
let dir = dir
.filter_map(|dir| dir.ok())
.map(|dir| dir.path())
.filter(|dir| {
dir.components()
.last()
.and_then(|c| c.as_os_str().to_str())
.map(|c| c.starts_with("10.") && dir.join("km").is_dir())
.unwrap_or(false)
})
.max()
.ok_or_else(|| Error::DirectoryNotFound)?;
// Finally append km to the path to get the path to the kernel mode libraries.
Ok(dir.join("km"))
}
pub fn build() -> Result<(), Error> {
// Get the path to the kernel libraries.
let dir = get_km_dir(DirectoryType::Library).unwrap();
// Append the architecture based on our target.
let target = std::env::var("TARGET").unwrap();
let arch = if target.contains("x86_64") {
"x64"
} else if target.contains("i686") {
"x86"
} else {
panic!("The target {} is currently not supported.", target);
};
let dir = dir.join(arch);
// Specify the link path.
println!("cargo:rustc-link-search=native={}", dir.to_str().unwrap());
// Ensure the right linker flags are passed for building a driver.
println!("cargo:rustc-link-arg=/NODEFAULTLIB");
println!("cargo:rustc-link-arg=/SUBSYSTEM:NATIVE");
println!("cargo:rustc-link-arg=/DRIVER");
println!("cargo:rustc-link-arg=/DYNAMICBASE");
println!("cargo:rustc-link-arg=/MANIFEST:NO");
println!("cargo:rustc-link-arg=/ENTRY:driver_entry");
println!("cargo:rustc-link-arg=/MERGE:.edata=.rdata");
println!("cargo:rustc-link-arg=/MERGE:.rustc=.data");
println!("cargo:rustc-link-arg=/INTEGRITYCHECK");
Ok(())
}
================================================
FILE: windows-kernel-rs/Cargo.toml
================================================
[package]
name = "windows-kernel-rs"
version = "0.1.0"
edition = "2021"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
[features]
default = ["alloc"]
alloc = []
system = []
[dependencies]
bitflags = "2.4.0"
cty = "0.2"
lazy_static = { version = "1.4", features = ["spin_no_std"] }
widestring = { version = "1", default-features = false, features = ["alloc"] }
windows-kernel-sys = { path = "../windows-kernel-sys" }
================================================
FILE: windows-kernel-rs/rust-toolchain
================================================
nightly
================================================
FILE: windows-kernel-rs/src/affinity.rs
================================================
//! This module provides functions to get information about the logical CPUs in the system, and to
//! run closures on specific or all CPUs.
use crate::error::{Error, IntoResult};
use windows_kernel_sys::base::{ALL_PROCESSOR_GROUPS, GROUP_AFFINITY, PROCESSOR_NUMBER, ULONG_PTR};
use windows_kernel_sys::ntoskrnl::{
KeIpiGenericCall, KeGetCurrentProcessorNumberEx, KeGetProcessorNumberFromIndex,
KeQueryActiveProcessorCountEx, KeRevertToUserGroupAffinityThread,
KeSetSystemGroupAffinityThread,
};
/// Uses [`KeGetCurrentProcessorNumberEx`] to get the logical number associated with the CPU that
/// is currently running our code.
pub fn get_current_cpu_num() -> u32 {
unsafe {
KeGetCurrentProcessorNumberEx(core::ptr::null_mut())
}
}
/// Uses [`KeQueryActiveProcessorCountEx`] to get the number of CPUs in the system, that is all the
/// CPUs from all the different CPU groups are counted, such that each of them has a logical
/// number.
pub fn get_cpu_count() -> u32 {
unsafe {
KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS as _)
}
}
/// This is the callback used by [`run_on_each_cpu_parallel`] to run the closure on all CPUs.
unsafe extern "C" fn broadcast_callback<F>(
context: ULONG_PTR,
) -> ULONG_PTR
where
F: FnMut(),
{
let f = &mut *(context as *mut F);
f();
0
}
/// Runs the given closure on all CPUs in the system without interrupting all CPUs to force them to
/// switch to kernel mode. Instead, this is a more graceful version that simply relies on
/// [`run_on_cpu`] to switch to all the possible CPUs by configuring the affinity, and execute the
/// closure on the selected CPU. Upon executing the closure on all CPUs, the affinity is restored.
/// Also see [`run_on_each_cpu_parallel`] which is a more aggressive version that relies on an IPI
/// to run a given closure on all CPUs in parallel.
pub fn run_on_each_cpu<F>(
f: &mut F,
) -> Result<(), Error>
where
F: FnMut() -> Result<(), Error>,
{
for cpu_num in 0..get_cpu_count() {
run_on_cpu(cpu_num, f)?;
}
Ok(())
}
/// Runs the given closure on all CPUs in the system by broadcasting an Inter-Processor Interrupt
/// (IPI) to interrupt all CPUs to force them to switch to kernel mode to run the given closure.
/// Upon execution of the closure, these CPUs resume their work. Also see [`run_on_each_cpu`] which
/// is a friendlier version that does not rely on an IPI but instead configures the affinity to run
/// a given a closure on all CPUs.
pub fn run_on_each_cpu_parallel<F>(
f: &F,
)
where
F: Fn(),
{
unsafe {
KeIpiGenericCall(Some(broadcast_callback::<F>), f as *const _ as ULONG_PTR);
}
}
/// Runs the given closure on the CPU with the given CPU number by temporarily configuring the CPU
/// affinity to only contain the given CPU number. Upon switching to the selected CPU, the CPU
/// executes the closure. Then the original affinity is restored.
pub fn run_on_cpu<F>(
cpu_num: u32,
f: &mut F,
) -> Result<(), Error>
where
F: FnMut() -> Result<(), Error>,
{
let mut processor_num = PROCESSOR_NUMBER {
Group: 0,
Number: 0,
Reserved: 0,
};
unsafe {
KeGetProcessorNumberFromIndex(cpu_num, &mut processor_num)
}.into_result()?;
let mut previous = GROUP_AFFINITY {
Mask: 0,
Group: 0,
Reserved: [0; 3],
};
let mut affinity = GROUP_AFFINITY {
Mask: 1 << processor_num.Number,
Group: processor_num.Group,
Reserved: [0; 3],
};
unsafe {
KeSetSystemGroupAffinityThread(&mut affinity, &mut previous);
}
let result = f();
unsafe {
KeRevertToUserGroupAffinityThread(&mut previous);
}
result
}
================================================
FILE: windows-kernel-rs/src/allocator.rs
================================================
//! This module provides an allocator to use with the [`alloc`] crate. You can define your own
//! global allocator with the `#[global_allocator]` attribute when not using the `alloc` feature,
//! in case you want to specify your own tag to use with [`ExAllocatePool2`] and
//! [`ExAllocatePoolWithTag`].
use core::alloc::{GlobalAlloc, Layout};
use crate::version::VersionInfo;
use lazy_static::lazy_static;
use windows_kernel_sys::base::_POOL_TYPE as POOL_TYPE;
use windows_kernel_sys::ntoskrnl::{ExAllocatePoolWithTag, ExAllocatePool2, ExFreePool};
/// See issue #52191.
#[alloc_error_handler]
fn alloc_error(_: Layout) -> ! {
loop {}
}
lazy_static! {
/// The version of Microsoft Windows that is currently running. This is used by
/// [`KernelAllocator`] to determine whether to use [`ExAllocatePool2`] or
/// [`ExAllocatePoolWithTag`].
static ref VERSION_INFO: VersionInfo = {
VersionInfo::query().unwrap()
};
}
/// Represents a kernel allocator that relies on the `ExAllocatePool` family of functions to
/// allocate and free memory for the `alloc` crate.
pub struct KernelAllocator {
/// The 32-bit tag to use for the pool, this is usually derived from a quadruplet of ASCII
/// bytes, e.g. by invoking `u32::from_ne_bytes(*b"rust")`.
tag: u32,
}
impl KernelAllocator {
/// Sets up a new kernel allocator with the 32-bit tag specified. The tag is usually derived
/// from a quadruplet of ASCII bytes, e.g. by invoking `u32::from_ne_bytes(*b"rust")`.
pub const fn new(tag: u32) -> Self {
Self {
tag,
}
}
}
unsafe impl GlobalAlloc for KernelAllocator {
/// Uses [`ExAllocatePool2`] on Microsoft Windows 10.0.19041 and later, and
/// [`ExAllocatePoolWithTag`] on older versions of Microsoft Windows to allocate memory.
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let use_ex_allocate_pool2 =
VERSION_INFO.major() > 10 ||
(VERSION_INFO.major() == 10 && VERSION_INFO.build_number() == 19041);
let ptr = if use_ex_allocate_pool2 {
ExAllocatePool2(
POOL_TYPE::NonPagedPool as _,
layout.size() as u64,
self.tag,
)
} else {
ExAllocatePoolWithTag(
POOL_TYPE::NonPagedPool,
layout.size() as u64,
self.tag,
)
};
if ptr.is_null() {
panic!("[kernel-alloc] failed to allocate pool.");
}
ptr as _
}
/// Uses [`ExFreePool`] to free allocated memory.
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
ExFreePool(ptr as _)
}
}
================================================
FILE: windows-kernel-rs/src/device.rs
================================================
use crate::error::Error;
use crate::request::{IoControlRequest, IoRequest, ReadRequest, WriteRequest};
use alloc::boxed::Box;
use bitflags::bitflags;
use windows_kernel_sys::base::STATUS_SUCCESS;
use windows_kernel_sys::base::{DEVICE_OBJECT, IRP, NTSTATUS};
use windows_kernel_sys::base::{
IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_MJ_CREATE, IRP_MJ_DEVICE_CONTROL, IRP_MJ_READ, IRP_MJ_WRITE,
};
use windows_kernel_sys::ntoskrnl::{IoDeleteDevice, IoGetCurrentIrpStackLocation};
#[derive(Copy, Clone, Debug)]
pub enum Access {
NonExclusive,
Exclusive,
}
impl Access {
pub fn is_exclusive(&self) -> bool {
match *self {
Access::Exclusive => true,
_ => false,
}
}
}
bitflags! {
pub struct DeviceFlags: u32 {
const SECURE_OPEN = windows_kernel_sys::base::FILE_DEVICE_SECURE_OPEN;
}
}
bitflags! {
pub struct DeviceDoFlags: u32 {
const DO_BUFFERED_IO = windows_kernel_sys::base::DO_BUFFERED_IO;
const DO_DIRECT_IO = windows_kernel_sys::base::DO_DIRECT_IO;
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DeviceType {
Port8042,
Acpi,
Battery,
Beep,
BusExtender,
Cdrom,
CdromFileSystem,
Changer,
Controller,
DataLink,
Dfs,
DfsFileSystem,
DfsVolume,
Disk,
DiskFileSystem,
Dvd,
FileSystem,
Fips,
FullscreenVideo,
InportPort,
Keyboard,
Ks,
Ksec,
Mailslot,
MassStorage,
MidiIn,
MidiOut,
Modem,
Mouse,
MultiUncProvider,
NamedPipe,
Network,
NetworkBrowser,
NetworkFileSystem,
NetworkRedirector,
Null,
ParallelPort,
PhysicalNetcard,
Printer,
Scanner,
Screen,
Serenum,
SerialPort,
SerialMousePort,
Smartcard,
Smb,
Sound,
Streams,
Tape,
TapeFileSystem,
Termsrv,
Transport,
Unknown,
Vdm,
Video,
VirtualDisk,
WaveIn,
WaveOut,
}
impl Into<u32> for DeviceType {
fn into(self) -> u32 {
match self {
DeviceType::Port8042 => windows_kernel_sys::base::FILE_DEVICE_8042_PORT,
DeviceType::Acpi => windows_kernel_sys::base::FILE_DEVICE_ACPI,
DeviceType::Battery => windows_kernel_sys::base::FILE_DEVICE_BATTERY,
DeviceType::Beep => windows_kernel_sys::base::FILE_DEVICE_BEEP,
DeviceType::BusExtender => windows_kernel_sys::base::FILE_DEVICE_BUS_EXTENDER,
DeviceType::Cdrom => windows_kernel_sys::base::FILE_DEVICE_CD_ROM,
DeviceType::CdromFileSystem => windows_kernel_sys::base::FILE_DEVICE_CD_ROM_FILE_SYSTEM,
DeviceType::Changer => windows_kernel_sys::base::FILE_DEVICE_CHANGER,
DeviceType::Controller => windows_kernel_sys::base::FILE_DEVICE_CONTROLLER,
DeviceType::DataLink => windows_kernel_sys::base::FILE_DEVICE_DATALINK,
DeviceType::Dfs => windows_kernel_sys::base::FILE_DEVICE_DFS,
DeviceType::DfsFileSystem => windows_kernel_sys::base::FILE_DEVICE_DFS_FILE_SYSTEM,
DeviceType::DfsVolume => windows_kernel_sys::base::FILE_DEVICE_DFS_VOLUME,
DeviceType::Disk => windows_kernel_sys::base::FILE_DEVICE_DISK,
DeviceType::DiskFileSystem => windows_kernel_sys::base::FILE_DEVICE_DISK_FILE_SYSTEM,
DeviceType::Dvd => windows_kernel_sys::base::FILE_DEVICE_DVD,
DeviceType::FileSystem => windows_kernel_sys::base::FILE_DEVICE_FILE_SYSTEM,
DeviceType::Fips => windows_kernel_sys::base::FILE_DEVICE_FIPS,
DeviceType::FullscreenVideo => windows_kernel_sys::base::FILE_DEVICE_FULLSCREEN_VIDEO,
DeviceType::InportPort => windows_kernel_sys::base::FILE_DEVICE_INPORT_PORT,
DeviceType::Keyboard => windows_kernel_sys::base::FILE_DEVICE_KEYBOARD,
DeviceType::Ks => windows_kernel_sys::base::FILE_DEVICE_KS,
DeviceType::Ksec => windows_kernel_sys::base::FILE_DEVICE_KSEC,
DeviceType::Mailslot => windows_kernel_sys::base::FILE_DEVICE_MAILSLOT,
DeviceType::MassStorage => windows_kernel_sys::base::FILE_DEVICE_MASS_STORAGE,
DeviceType::MidiIn => windows_kernel_sys::base::FILE_DEVICE_MIDI_IN,
DeviceType::MidiOut => windows_kernel_sys::base::FILE_DEVICE_MIDI_OUT,
DeviceType::Modem => windows_kernel_sys::base::FILE_DEVICE_MODEM,
DeviceType::Mouse => windows_kernel_sys::base::FILE_DEVICE_MOUSE,
DeviceType::MultiUncProvider => {
windows_kernel_sys::base::FILE_DEVICE_MULTI_UNC_PROVIDER
}
DeviceType::NamedPipe => windows_kernel_sys::base::FILE_DEVICE_NAMED_PIPE,
DeviceType::Network => windows_kernel_sys::base::FILE_DEVICE_NETWORK,
DeviceType::NetworkBrowser => windows_kernel_sys::base::FILE_DEVICE_NETWORK_BROWSER,
DeviceType::NetworkFileSystem => {
windows_kernel_sys::base::FILE_DEVICE_NETWORK_FILE_SYSTEM
}
DeviceType::NetworkRedirector => {
windows_kernel_sys::base::FILE_DEVICE_NETWORK_REDIRECTOR
}
DeviceType::Null => windows_kernel_sys::base::FILE_DEVICE_NULL,
DeviceType::ParallelPort => windows_kernel_sys::base::FILE_DEVICE_PARALLEL_PORT,
DeviceType::PhysicalNetcard => windows_kernel_sys::base::FILE_DEVICE_PHYSICAL_NETCARD,
DeviceType::Printer => windows_kernel_sys::base::FILE_DEVICE_PRINTER,
DeviceType::Scanner => windows_kernel_sys::base::FILE_DEVICE_SCANNER,
DeviceType::Screen => windows_kernel_sys::base::FILE_DEVICE_SCREEN,
DeviceType::Serenum => windows_kernel_sys::base::FILE_DEVICE_SERENUM,
DeviceType::SerialMousePort => windows_kernel_sys::base::FILE_DEVICE_SERIAL_MOUSE_PORT,
DeviceType::SerialPort => windows_kernel_sys::base::FILE_DEVICE_SERIAL_PORT,
DeviceType::Smartcard => windows_kernel_sys::base::FILE_DEVICE_SMARTCARD,
DeviceType::Smb => windows_kernel_sys::base::FILE_DEVICE_SMB,
DeviceType::Sound => windows_kernel_sys::base::FILE_DEVICE_SOUND,
DeviceType::Streams => windows_kernel_sys::base::FILE_DEVICE_STREAMS,
DeviceType::Tape => windows_kernel_sys::base::FILE_DEVICE_TAPE,
DeviceType::TapeFileSystem => windows_kernel_sys::base::FILE_DEVICE_TAPE_FILE_SYSTEM,
DeviceType::Termsrv => windows_kernel_sys::base::FILE_DEVICE_TERMSRV,
DeviceType::Transport => windows_kernel_sys::base::FILE_DEVICE_TRANSPORT,
DeviceType::Unknown => windows_kernel_sys::base::FILE_DEVICE_UNKNOWN,
DeviceType::Vdm => windows_kernel_sys::base::FILE_DEVICE_VDM,
DeviceType::Video => windows_kernel_sys::base::FILE_DEVICE_VIDEO,
DeviceType::VirtualDisk => windows_kernel_sys::base::FILE_DEVICE_VIRTUAL_DISK,
DeviceType::WaveIn => windows_kernel_sys::base::FILE_DEVICE_WAVE_IN,
DeviceType::WaveOut => windows_kernel_sys::base::FILE_DEVICE_WAVE_OUT,
}
}
}
impl From<u32> for DeviceType {
fn from(value: u32) -> Self {
match value {
windows_kernel_sys::base::FILE_DEVICE_8042_PORT => DeviceType::Port8042,
windows_kernel_sys::base::FILE_DEVICE_ACPI => DeviceType::Acpi,
windows_kernel_sys::base::FILE_DEVICE_BATTERY => DeviceType::Battery,
windows_kernel_sys::base::FILE_DEVICE_BEEP => DeviceType::Beep,
windows_kernel_sys::base::FILE_DEVICE_BUS_EXTENDER => DeviceType::BusExtender,
windows_kernel_sys::base::FILE_DEVICE_CD_ROM => DeviceType::Cdrom,
windows_kernel_sys::base::FILE_DEVICE_CD_ROM_FILE_SYSTEM => DeviceType::CdromFileSystem,
windows_kernel_sys::base::FILE_DEVICE_CHANGER => DeviceType::Changer,
windows_kernel_sys::base::FILE_DEVICE_CONTROLLER => DeviceType::Controller,
windows_kernel_sys::base::FILE_DEVICE_DATALINK => DeviceType::DataLink,
windows_kernel_sys::base::FILE_DEVICE_DFS => DeviceType::Dfs,
windows_kernel_sys::base::FILE_DEVICE_DFS_FILE_SYSTEM => DeviceType::DfsFileSystem,
windows_kernel_sys::base::FILE_DEVICE_DFS_VOLUME => DeviceType::DfsVolume,
windows_kernel_sys::base::FILE_DEVICE_DISK => DeviceType::Disk,
windows_kernel_sys::base::FILE_DEVICE_DISK_FILE_SYSTEM => DeviceType::DiskFileSystem,
windows_kernel_sys::base::FILE_DEVICE_DVD => DeviceType::Dvd,
windows_kernel_sys::base::FILE_DEVICE_FILE_SYSTEM => DeviceType::FileSystem,
windows_kernel_sys::base::FILE_DEVICE_FIPS => DeviceType::Fips,
windows_kernel_sys::base::FILE_DEVICE_FULLSCREEN_VIDEO => DeviceType::FullscreenVideo,
windows_kernel_sys::base::FILE_DEVICE_INPORT_PORT => DeviceType::InportPort,
windows_kernel_sys::base::FILE_DEVICE_KEYBOARD => DeviceType::Keyboard,
windows_kernel_sys::base::FILE_DEVICE_KS => DeviceType::Ks,
windows_kernel_sys::base::FILE_DEVICE_KSEC => DeviceType::Ksec,
windows_kernel_sys::base::FILE_DEVICE_MAILSLOT => DeviceType::Mailslot,
windows_kernel_sys::base::FILE_DEVICE_MASS_STORAGE => DeviceType::MassStorage,
windows_kernel_sys::base::FILE_DEVICE_MIDI_IN => DeviceType::MidiIn,
windows_kernel_sys::base::FILE_DEVICE_MIDI_OUT => DeviceType::MidiOut,
windows_kernel_sys::base::FILE_DEVICE_MODEM => DeviceType::Modem,
windows_kernel_sys::base::FILE_DEVICE_MOUSE => DeviceType::Mouse,
windows_kernel_sys::base::FILE_DEVICE_MULTI_UNC_PROVIDER => {
DeviceType::MultiUncProvider
}
windows_kernel_sys::base::FILE_DEVICE_NAMED_PIPE => DeviceType::NamedPipe,
windows_kernel_sys::base::FILE_DEVICE_NETWORK => DeviceType::Network,
windows_kernel_sys::base::FILE_DEVICE_NETWORK_BROWSER => DeviceType::NetworkBrowser,
windows_kernel_sys::base::FILE_DEVICE_NETWORK_FILE_SYSTEM => {
DeviceType::NetworkFileSystem
}
windows_kernel_sys::base::FILE_DEVICE_NETWORK_REDIRECTOR => {
DeviceType::NetworkRedirector
}
windows_kernel_sys::base::FILE_DEVICE_NULL => DeviceType::Null,
windows_kernel_sys::base::FILE_DEVICE_PARALLEL_PORT => DeviceType::ParallelPort,
windows_kernel_sys::base::FILE_DEVICE_PHYSICAL_NETCARD => DeviceType::PhysicalNetcard,
windows_kernel_sys::base::FILE_DEVICE_PRINTER => DeviceType::Printer,
windows_kernel_sys::base::FILE_DEVICE_SCANNER => DeviceType::Scanner,
windows_kernel_sys::base::FILE_DEVICE_SCREEN => DeviceType::Screen,
windows_kernel_sys::base::FILE_DEVICE_SERENUM => DeviceType::Serenum,
windows_kernel_sys::base::FILE_DEVICE_SERIAL_MOUSE_PORT => DeviceType::SerialMousePort,
windows_kernel_sys::base::FILE_DEVICE_SERIAL_PORT => DeviceType::SerialPort,
windows_kernel_sys::base::FILE_DEVICE_SMARTCARD => DeviceType::Smartcard,
windows_kernel_sys::base::FILE_DEVICE_SMB => DeviceType::Smb,
windows_kernel_sys::base::FILE_DEVICE_SOUND => DeviceType::Sound,
windows_kernel_sys::base::FILE_DEVICE_STREAMS => DeviceType::Streams,
windows_kernel_sys::base::FILE_DEVICE_TAPE => DeviceType::Tape,
windows_kernel_sys::base::FILE_DEVICE_TAPE_FILE_SYSTEM => DeviceType::TapeFileSystem,
windows_kernel_sys::base::FILE_DEVICE_TERMSRV => DeviceType::Termsrv,
windows_kernel_sys::base::FILE_DEVICE_TRANSPORT => DeviceType::Transport,
windows_kernel_sys::base::FILE_DEVICE_UNKNOWN => DeviceType::Unknown,
windows_kernel_sys::base::FILE_DEVICE_VDM => DeviceType::Vdm,
windows_kernel_sys::base::FILE_DEVICE_VIDEO => DeviceType::Video,
windows_kernel_sys::base::FILE_DEVICE_VIRTUAL_DISK => DeviceType::VirtualDisk,
windows_kernel_sys::base::FILE_DEVICE_WAVE_IN => DeviceType::WaveIn,
windows_kernel_sys::base::FILE_DEVICE_WAVE_OUT => DeviceType::WaveOut,
_ => DeviceType::Unknown,
}
}
}
#[repr(C)]
pub struct device_operations {
dispatch: Option<extern "C" fn(*mut DEVICE_OBJECT, *mut IRP, u8) -> NTSTATUS>,
release: Option<extern "C" fn(*mut DEVICE_OBJECT)>,
}
pub struct Device {
raw: *mut DEVICE_OBJECT,
}
unsafe impl Send for Device {}
unsafe impl Sync for Device {}
impl Device {
pub unsafe fn from_raw(raw: *mut DEVICE_OBJECT) -> Self {
Self { raw }
}
pub unsafe fn as_raw(&self) -> *const DEVICE_OBJECT {
self.raw as *const _
}
pub unsafe fn as_raw_mut(&self) -> *mut DEVICE_OBJECT {
self.raw
}
pub fn into_raw(mut self) -> *mut DEVICE_OBJECT {
core::mem::replace(&mut self.raw, core::ptr::null_mut())
}
pub(crate) fn extension(&self) -> &DeviceExtension {
unsafe { &*((*self.raw).DeviceExtension as *const DeviceExtension) }
}
pub(crate) fn extension_mut(&self) -> &mut DeviceExtension {
unsafe { &mut *((*self.raw).DeviceExtension as *mut DeviceExtension) }
}
pub(crate) fn device_type(&self) -> DeviceType {
self.extension().device_type
}
pub(crate) fn vtable(&self) -> &device_operations {
unsafe { &*(self.extension().vtable as *const _) }
}
pub fn data<T: DeviceOperations>(&self) -> &T {
unsafe { &*(self.extension().data as *const T) }
}
pub fn data_mut<T: DeviceOperations>(&self) -> &mut T {
unsafe { &mut *(self.extension().data as *mut T) }
}
}
impl Drop for Device {
fn drop(&mut self) {
if self.raw.is_null() {
return;
}
unsafe {
if let Some(release) = self.vtable().release {
release(self.raw);
}
IoDeleteDevice(self.raw);
}
}
}
pub struct RequestError(pub Error, pub IoRequest);
pub enum Completion {
Complete(u32, IoRequest),
}
pub trait DeviceOperations: Sync + Sized {
fn create(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {
Ok(Completion::Complete(0, request))
}
fn close(&mut self, _device: &Device, request: IoRequest) -> Result<Completion, RequestError> {
Ok(Completion::Complete(0, request))
}
fn cleanup(
&mut self,
_device: &Device,
request: IoRequest,
) -> Result<Completion, RequestError> {
Ok(Completion::Complete(0, request))
}
fn read(&mut self, _device: &Device, request: ReadRequest) -> Result<Completion, RequestError> {
Ok(Completion::Complete(0, request.into()))
}
fn write(
&mut self,
_device: &Device,
request: WriteRequest,
) -> Result<Completion, RequestError> {
Ok(Completion::Complete(0, request.into()))
}
fn ioctl(
&mut self,
_device: &Device,
request: IoControlRequest,
) -> Result<Completion, RequestError> {
Ok(Completion::Complete(0, request.into()))
}
}
extern "C" fn dispatch_callback<T: DeviceOperations>(
device: *mut DEVICE_OBJECT,
irp: *mut IRP,
major: u8,
) -> NTSTATUS {
let device = unsafe { Device::from_raw(device) };
let data: &mut T = device.data_mut();
let request = unsafe { IoRequest::from_raw(irp) };
let result = match major as _ {
IRP_MJ_CREATE => data.create(&device, request),
IRP_MJ_CLOSE => data.close(&device, request),
IRP_MJ_CLEANUP => data.cleanup(&device, request),
IRP_MJ_READ => {
let read_request = ReadRequest { inner: request };
data.read(&device, read_request)
}
IRP_MJ_WRITE => {
let write_request = WriteRequest { inner: request };
data.write(&device, write_request)
}
IRP_MJ_DEVICE_CONTROL => {
let control_request = IoControlRequest { inner: request };
if device.device_type() == control_request.control_code().device_type() {
data.ioctl(&device, control_request)
} else {
Err(RequestError(
Error::INVALID_PARAMETER,
control_request.into(),
))
}
}
_ => Err(RequestError(Error::INVALID_PARAMETER, request)),
};
device.into_raw();
match result {
Ok(Completion::Complete(size, request)) => {
request.complete(Ok(size));
STATUS_SUCCESS
}
Err(RequestError(e, request)) => {
let status = e.to_ntstatus();
request.complete(Err(e));
status
}
}
}
extern "C" fn release_callback<T: DeviceOperations>(device: *mut DEVICE_OBJECT) {
unsafe {
let extension = (*device).DeviceExtension as *mut DeviceExtension;
let ptr = core::mem::replace(&mut (*extension).data, core::ptr::null_mut());
let _ = Box::from_raw(ptr as *mut T);
}
}
pub(crate) struct DeviceOperationsVtable<T>(core::marker::PhantomData<T>);
impl<T: DeviceOperations> DeviceOperationsVtable<T> {
pub(crate) const VTABLE: device_operations = device_operations {
dispatch: Some(dispatch_callback::<T>),
release: Some(release_callback::<T>),
};
}
#[repr(C)]
pub struct DeviceExtension {
pub(crate) vtable: *const device_operations,
pub(crate) data: *mut cty::c_void,
pub(crate) device_type: DeviceType,
}
pub extern "C" fn dispatch_device(device: *mut DEVICE_OBJECT, irp: *mut IRP) -> NTSTATUS {
let stack_location = unsafe { &*IoGetCurrentIrpStackLocation(irp) };
let device = unsafe { Device::from_raw(device) };
let vtable = device.vtable();
match vtable.dispatch {
Some(dispatch) => dispatch(device.into_raw(), irp, stack_location.MajorFunction),
_ => {
device.into_raw();
STATUS_SUCCESS
}
}
}
================================================
FILE: windows-kernel-rs/src/driver.rs
================================================
use alloc::boxed::Box;
use crate::device::{Access, Device, DeviceExtension, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceOperationsVtable, DeviceType};
use crate::error::{Error, IntoResult};
use crate::string::create_unicode_string;
use widestring::U16CString;
use windows_kernel_sys::base::DRIVER_OBJECT;
use windows_kernel_sys::ntoskrnl::{IoCreateDevice};
pub struct Driver {
pub(crate) raw: *mut DRIVER_OBJECT,
}
impl Driver {
pub unsafe fn from_raw(raw: *mut DRIVER_OBJECT) -> Self {
Self {
raw,
}
}
pub unsafe fn as_raw(&self) -> *const DRIVER_OBJECT {
self.raw as _
}
pub unsafe fn as_raw_mut(&mut self) -> *mut DRIVER_OBJECT {
self.raw as _
}
pub fn create_device<T>(
&mut self,
name: &str,
device_type: DeviceType,
device_flags: DeviceFlags,
device_do_flags: DeviceDoFlags,
access: Access,
data: T,
) -> Result<Device, Error>
where
T: DeviceOperations
{
// Box the data.
let data = Box::new(data);
// Convert the name to UTF-16 and then create a UNICODE_STRING.
let name = U16CString::from_str(name).unwrap();
let mut name = create_unicode_string(name.as_slice());
// Create the device.
let mut device = core::ptr::null_mut();
unsafe {
IoCreateDevice(
self.raw,
core::mem::size_of::<DeviceExtension>() as u32,
&mut name,
device_type.into(),
device_flags.bits(),
access.is_exclusive() as _,
&mut device,
)
}.into_result()?;
unsafe {
(*device).Flags |= device_do_flags.bits();
}
let device = unsafe { Device::from_raw(device) };
// Store the boxed data and vtable.
let extension = device.extension_mut();
extension.device_type = device_type;
extension.vtable = &DeviceOperationsVtable::<T>::VTABLE;
extension.data = Box::into_raw(data) as *mut cty::c_void;
Ok(device)
}
}
================================================
FILE: windows-kernel-rs/src/error.rs
================================================
use windows_kernel_sys::base::NTSTATUS;
use windows_kernel_sys::base::{
STATUS_SUCCESS,
STATUS_GUARD_PAGE_VIOLATION,
STATUS_DATATYPE_MISALIGNMENT,
STATUS_BREAKPOINT,
STATUS_SINGLE_STEP,
STATUS_UNWIND_CONSOLIDATE,
STATUS_UNSUCCESSFUL,
STATUS_NOT_IMPLEMENTED,
STATUS_ACCESS_VIOLATION,
STATUS_IN_PAGE_ERROR,
STATUS_INVALID_HANDLE,
STATUS_INVALID_PARAMETER,
STATUS_END_OF_FILE,
STATUS_NO_MEMORY,
STATUS_ILLEGAL_INSTRUCTION,
STATUS_NONCONTINUABLE_EXCEPTION,
STATUS_INVALID_DISPOSITION,
STATUS_ARRAY_BOUNDS_EXCEEDED,
STATUS_FLOAT_DENORMAL_OPERAND,
STATUS_FLOAT_DIVIDE_BY_ZERO,
STATUS_FLOAT_INEXACT_RESULT,
STATUS_FLOAT_INVALID_OPERATION,
STATUS_FLOAT_OVERFLOW,
STATUS_FLOAT_STACK_CHECK,
STATUS_FLOAT_UNDERFLOW,
STATUS_INTEGER_DIVIDE_BY_ZERO,
STATUS_INTEGER_OVERFLOW,
STATUS_PRIVILEGED_INSTRUCTION,
STATUS_INSUFFICIENT_RESOURCES,
STATUS_INVALID_USER_BUFFER,
STATUS_STACK_OVERFLOW,
};
#[derive(Clone, Copy, Debug)]
pub struct Error(NTSTATUS);
impl Error {
pub const GUARD_PAGE_VIOLATION: Error = Error(STATUS_GUARD_PAGE_VIOLATION);
pub const DATATYPE_MISALIGNMENT: Error = Error(STATUS_DATATYPE_MISALIGNMENT);
pub const BREAKPOINT: Error = Error(STATUS_BREAKPOINT);
pub const SINGLE_STEP: Error = Error(STATUS_SINGLE_STEP);
pub const UNWIND_CONSOLIDATE: Error = Error(STATUS_UNWIND_CONSOLIDATE);
pub const UNSUCCESSFUL: Error = Error(STATUS_UNSUCCESSFUL);
pub const NOT_IMPLEMENTED: Error = Error(STATUS_NOT_IMPLEMENTED);
pub const ACCESS_VIOLATION: Error = Error(STATUS_ACCESS_VIOLATION);
pub const IN_PAGE_ERROR: Error = Error(STATUS_IN_PAGE_ERROR);
pub const INVALID_HANDLE: Error = Error(STATUS_INVALID_HANDLE);
pub const INVALID_PARAMETER: Error = Error(STATUS_INVALID_PARAMETER);
pub const END_OF_FILE: Error = Error(STATUS_END_OF_FILE);
pub const NO_MEMORY: Error = Error(STATUS_NO_MEMORY);
pub const ILLEGAL_INSTRUCTION: Error = Error(STATUS_ILLEGAL_INSTRUCTION);
pub const NONCONTINUABLE_EXCEPTION: Error = Error(STATUS_NONCONTINUABLE_EXCEPTION);
pub const INVALID_DISPOSITION: Error = Error(STATUS_INVALID_DISPOSITION);
pub const ARRAY_BOUNDS_EXCEEDED: Error = Error(STATUS_ARRAY_BOUNDS_EXCEEDED);
pub const FLOAT_DENORMAL_OPERAND: Error = Error(STATUS_FLOAT_DENORMAL_OPERAND);
pub const FLOAT_DIVIDE_BY_ZERO: Error = Error(STATUS_FLOAT_DIVIDE_BY_ZERO);
pub const FLOAT_INEXACT_RESULT: Error = Error(STATUS_FLOAT_INEXACT_RESULT);
pub const FLOAT_INVALID_OPERATION: Error = Error(STATUS_FLOAT_INVALID_OPERATION);
pub const FLOAT_OVERFLOW: Error = Error(STATUS_FLOAT_OVERFLOW);
pub const FLOAT_STACK_CHECK: Error = Error(STATUS_FLOAT_STACK_CHECK);
pub const FLOAT_UNDERFLOW: Error = Error(STATUS_FLOAT_UNDERFLOW);
pub const INTEGER_DIVIDE_BY_ZERO: Error = Error(STATUS_INTEGER_DIVIDE_BY_ZERO);
pub const INTEGER_OVERFLOW: Error = Error(STATUS_INTEGER_OVERFLOW);
pub const PRIVILEGED_INSTRUCTION: Error = Error(STATUS_PRIVILEGED_INSTRUCTION);
pub const INSUFFICIENT_RESOURCES: Error = Error(STATUS_INSUFFICIENT_RESOURCES);
pub const INVALID_USER_BUFFER: Error = Error(STATUS_INVALID_USER_BUFFER);
pub const STACK_OVERFLOW: Error = Error(STATUS_STACK_OVERFLOW);
pub fn from_ntstatus(status: NTSTATUS) -> Error {
Error(status)
}
pub fn to_ntstatus(&self) -> NTSTATUS {
self.0
}
}
pub trait IntoResult {
fn into_result(self) -> Result<(), Error>;
}
impl IntoResult for NTSTATUS {
fn into_result(self) -> Result<(), Error> {
match self {
STATUS_SUCCESS => Ok(()),
status => Err(Error::from_ntstatus(status)),
}
}
}
================================================
FILE: windows-kernel-rs/src/intrin.rs
================================================
use crate::error::{Error, IntoResult};
use windows_kernel_sys::intrin::{read_msr_safe, write_msr_safe};
/// Attempts to read the given model-specific register. Accessing an invalid model-specific
/// register would normally result in a CPU exception. This function uses Structured Exception
/// Handling (SEH) to safely catch CPU exceptions and to turn them into an [`Error`]. This prevents
/// a hang.
pub fn read_msr(register: u32) -> Result<u64, Error> {
let mut value = 0;
unsafe {
read_msr_safe(register, &mut value)
}.into_result()?;
Ok(value)
}
/// Attempts to write the given value to the given model-specific register. Accessing an invalid
/// model-specific register would normally result in a CPU exception. This function uses Structured
/// Handling (SEH) to safely catch CPU exceptions and to turn them into an [`Error`]. This prevents
/// a hang.
pub fn write_msr(register: u32, value: u64) -> Result<(), Error> {
unsafe {
write_msr_safe(register, value)
}.into_result()?;
Ok(())
}
================================================
FILE: windows-kernel-rs/src/io.rs
================================================
use windows_kernel_sys::base::ANSI_STRING;
use windows_kernel_sys::ntoskrnl::DbgPrint;
#[macro_export]
macro_rules! print {
($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
}
#[macro_export]
macro_rules! println {
() => ($crate::print!("\n"));
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
}
#[doc(hidden)]
pub fn _print(args: core::fmt::Arguments) {
// Format the string using the `alloc::format!` as this is guaranteed to return a `String`
// instead of a `Result` that we would have to `unwrap`. This ensures that this code stays
// panic-free.
let s = alloc::format!("{}", args);
// Print the string. We must make sure to not pass this user-supplied string as the format
// string, as `DbgPrint` may then format any format specifiers it contains. This could
// potentially be an attack vector.
let s = ANSI_STRING {
Length: s.len() as u16,
MaximumLength: s.len() as u16,
Buffer: s.as_ptr() as _,
};
unsafe { DbgPrint("%Z\0".as_ptr() as _, &s) };
}
================================================
FILE: windows-kernel-rs/src/ioctl.rs
================================================
use crate::device::DeviceType;
use bitflags::bitflags;
use windows_kernel_sys::base::{
FILE_ANY_ACCESS, FILE_READ_DATA, FILE_WRITE_DATA, METHOD_BUFFERED, METHOD_IN_DIRECT,
METHOD_NEITHER, METHOD_OUT_DIRECT,
};
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RequiredAccess: u32 {
const ANY_ACCESS = FILE_ANY_ACCESS;
const READ_DATA = FILE_READ_DATA;
const WRITE_DATA = FILE_WRITE_DATA;
const READ_WRITE_DATA = FILE_READ_DATA | FILE_WRITE_DATA;
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum TransferMethod {
Neither = METHOD_NEITHER,
InputDirect = METHOD_IN_DIRECT,
OutputDirect = METHOD_OUT_DIRECT,
Buffered = METHOD_BUFFERED,
}
impl From<u32> for TransferMethod {
fn from(value: u32) -> Self {
match value & 0x3 {
METHOD_NEITHER => Self::Neither,
METHOD_IN_DIRECT => Self::InputDirect,
METHOD_OUT_DIRECT => Self::OutputDirect,
METHOD_BUFFERED => Self::Buffered,
_ => unreachable!(),
}
}
}
impl Into<u32> for TransferMethod {
fn into(self) -> u32 {
match self {
Self::Neither => METHOD_NEITHER,
Self::InputDirect => METHOD_IN_DIRECT,
Self::OutputDirect => METHOD_OUT_DIRECT,
Self::Buffered => METHOD_BUFFERED,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ControlCode(
pub DeviceType,
pub RequiredAccess,
pub u32,
pub TransferMethod,
);
impl ControlCode {
const METHOD_BITS: usize = 2;
const NUM_BITS: usize = 12;
const ACCESS_BITS: usize = 2;
const TYPE_BITS: usize = 16;
const METHOD_SHIFT: usize = 0;
const NUM_SHIFT: usize = Self::METHOD_SHIFT + Self::METHOD_BITS;
const ACCESS_SHIFT: usize = Self::NUM_SHIFT + Self::NUM_BITS;
const TYPE_SHIFT: usize = Self::ACCESS_SHIFT + Self::ACCESS_BITS;
const METHOD_MASK: u32 = (1 << Self::METHOD_BITS) - 1;
const NUM_MASK: u32 = (1 << Self::NUM_BITS) - 1;
const ACCESS_MASK: u32 = (1 << Self::ACCESS_BITS) - 1;
const TYPE_MASK: u32 = (1 << Self::TYPE_BITS) - 1;
pub fn device_type(&self) -> DeviceType {
self.0
}
pub fn required_access(&self) -> RequiredAccess {
self.1
}
pub fn number(&self) -> u32 {
self.2
}
pub fn transfer_method(&self) -> TransferMethod {
self.3
}
}
impl From<u32> for ControlCode {
fn from(value: u32) -> Self {
let method = (value >> Self::METHOD_SHIFT) & Self::METHOD_MASK;
let num = (value >> Self::NUM_SHIFT) & Self::NUM_MASK;
let access = (value >> Self::ACCESS_SHIFT) & Self::ACCESS_MASK;
let ty = (value >> Self::TYPE_SHIFT) & Self::TYPE_MASK;
Self(
ty.into(),
RequiredAccess::from_bits(access).unwrap_or(RequiredAccess::READ_DATA),
num,
method.into(),
)
}
}
impl Into<u32> for ControlCode {
fn into(self) -> u32 {
let method = Into::<u32>::into(self.3) << Self::METHOD_SHIFT;
let num = self.2 << Self::NUM_SHIFT;
let access = self.1.bits() << Self::ACCESS_SHIFT;
let ty = Into::<u32>::into(self.0) << Self::TYPE_SHIFT;
ty | access | num | method
}
}
================================================
FILE: windows-kernel-rs/src/lib.rs
================================================
#![no_std]
#![feature(alloc_error_handler)]
extern crate alloc;
pub mod affinity;
pub mod allocator;
pub mod device;
pub mod driver;
pub mod error;
pub mod intrin;
pub mod io;
pub mod ioctl;
pub mod mdl;
pub mod memory;
pub mod process;
pub mod request;
pub mod section;
pub mod string;
pub mod symbolic_link;
pub mod sync;
pub mod user_ptr;
pub mod version;
pub use crate::affinity::{get_cpu_count, get_current_cpu_num, run_on_cpu, run_on_each_cpu};
pub use crate::device::{Access, Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, DeviceType, dispatch_device, RequestError};
pub use crate::driver::Driver;
pub use crate::error::Error;
pub use crate::ioctl::{ControlCode, RequiredAccess, TransferMethod};
pub use crate::request::{IoRequest, IoControlRequest, ReadRequest, WriteRequest};
pub use crate::symbolic_link::SymbolicLink;
pub use crate::user_ptr::UserPtr;
pub use widestring::U16CString;
pub use windows_kernel_sys::base::{DRIVER_OBJECT, IRP_MJ_MAXIMUM_FUNCTION, NTSTATUS, STATUS_SUCCESS, UNICODE_STRING};
#[cfg(feature = "alloc")]
#[global_allocator]
static ALLOCATOR: allocator::KernelAllocator = allocator::KernelAllocator::new(
u32::from_ne_bytes(*b"rust")
);
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
#[used]
#[no_mangle]
pub static _fltused: i32 = 0;
#[no_mangle]
pub extern "system" fn __CxxFrameHandler3() -> i32 {
0
}
#[macro_export]
macro_rules! kernel_module {
($module:ty) => {
static mut __MOD: Option<$module> = None;
#[no_mangle]
pub extern "system" fn driver_entry(
driver: &mut $crate::DRIVER_OBJECT,
registry_path: &$crate::UNICODE_STRING,
) -> $crate::NTSTATUS {
unsafe {
driver.DriverUnload = Some(driver_exit);
for i in 0..$crate::IRP_MJ_MAXIMUM_FUNCTION {
driver.MajorFunction[i as usize] = Some($crate::dispatch_device);
}
}
let driver = unsafe {
Driver::from_raw(driver)
};
let registry_path = unsafe {
$crate::U16CString::from_ptr_str(registry_path.Buffer)
};
let registry_path = registry_path.to_string_lossy();
match <$module as $crate::KernelModule>::init(driver, registry_path.as_str()) {
Ok(m) => {
unsafe {
__MOD = Some(m);
}
$crate::STATUS_SUCCESS
}
Err(e) => {
e.to_ntstatus()
}
}
}
pub unsafe extern "C" fn driver_exit(
driver: *mut $crate::DRIVER_OBJECT,
) {
let driver = unsafe {
Driver::from_raw(driver)
};
match __MOD.take() {
Some(mut m) => m.cleanup(driver),
_ => (),
}
}
};
}
pub trait KernelModule: Sized + Sync {
fn init(driver: Driver, registry_path: &str) -> Result<Self, Error>;
fn cleanup(&mut self, _driver: Driver) {
}
}
================================================
FILE: windows-kernel-rs/src/mdl.rs
================================================
use crate::error::Error;
use crate::memory::MemoryCaching;
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AccessMode {
KernelMode = windows_kernel_sys::base::_MODE::KernelMode,
UserMode = windows_kernel_sys::base::_MODE::UserMode,
}
pub struct MemoryDescriptorList {
raw: *mut windows_kernel_sys::base::MDL,
}
unsafe impl Send for MemoryDescriptorList {}
unsafe impl Sync for MemoryDescriptorList {}
impl MemoryDescriptorList {
pub fn new(
addr: *mut core::ffi::c_void,
size: usize,
) -> Result<Self, Error> {
use windows_kernel_sys::ntoskrnl::IoAllocateMdl;
let raw = unsafe {
IoAllocateMdl(addr, size as _, false as _, false as _, core::ptr::null_mut())
};
if raw.is_null() {
return Err(Error::INSUFFICIENT_RESOURCES);
}
Ok(Self {
raw,
})
}
pub fn build_for_non_paged_pool(
&mut self,
) {
use windows_kernel_sys::ntoskrnl::MmBuildMdlForNonPagedPool;
unsafe {
MmBuildMdlForNonPagedPool(self.raw);
}
}
pub fn map_locked_pages(
self,
access: AccessMode,
caching: MemoryCaching,
desired_addr: Option<*mut core::ffi::c_void>,
) -> Result<LockedMapping, Error> {
use windows_kernel_sys::ntoskrnl::MmMapLockedPagesSpecifyCache;
let ptr = unsafe {
MmMapLockedPagesSpecifyCache(
self.raw,
access as _,
caching as _,
desired_addr.unwrap_or(core::ptr::null_mut()),
false as _,
0,
)
};
Ok(LockedMapping {
raw: self.raw,
ptr,
})
}
}
impl Drop for MemoryDescriptorList {
fn drop(&mut self) {
use windows_kernel_sys::ntoskrnl::IoFreeMdl;
unsafe {
IoFreeMdl(self.raw);
}
}
}
pub struct LockedMapping {
raw: *mut windows_kernel_sys::base::MDL,
ptr: *mut core::ffi::c_void,
}
unsafe impl Send for LockedMapping {}
unsafe impl Sync for LockedMapping {}
impl LockedMapping {
pub fn ptr(&self) -> *mut core::ffi::c_void {
self.ptr
}
pub fn unlock(self) -> MemoryDescriptorList {
use windows_kernel_sys::ntoskrnl::MmUnmapLockedPages;
unsafe {
MmUnmapLockedPages(self.ptr, self.raw);
}
MemoryDescriptorList {
raw: self.raw,
}
}
}
impl Drop for LockedMapping {
fn drop(&mut self) {
use windows_kernel_sys::ntoskrnl::{IoFreeMdl, MmUnmapLockedPages};
unsafe {
MmUnmapLockedPages(self.ptr, self.raw);
IoFreeMdl(self.raw);
}
}
}
================================================
FILE: windows-kernel-rs/src/memory.rs
================================================
use crate::error::{Error, IntoResult};
use windows_kernel_sys::base::{MM_COPY_ADDRESS, MM_COPY_MEMORY_PHYSICAL, MM_COPY_MEMORY_VIRTUAL, PHYSICAL_ADDRESS};
use windows_kernel_sys::base::_MEMORY_CACHING_TYPE as MEMORY_CACHING_TYPE;
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MemoryCaching {
NonCached = MEMORY_CACHING_TYPE::MmNonCached,
Cached = MEMORY_CACHING_TYPE::MmCached,
WriteCombined = MEMORY_CACHING_TYPE::MmWriteCombined,
#[cfg(feature = "system")]
HardwareCoherentCached = MEMORY_CACHING_TYPE::MmHardwareCoherentCached,
#[cfg(feature = "system")]
NonCachedUnordered = MEMORY_CACHING_TYPE::MmNonCachedUnordered,
#[cfg(feature = "system")]
USWCCached = MEMORY_CACHING_TYPE::MmUSWCCached,
NotMapped = MEMORY_CACHING_TYPE::MmNotMapped,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct PhysicalAddress(u64);
impl From<u64> for PhysicalAddress {
fn from(value: u64) -> Self {
Self(value)
}
}
impl Into<u64> for PhysicalAddress {
fn into(self) -> u64 {
self.0
}
}
impl From<PHYSICAL_ADDRESS> for PhysicalAddress {
fn from(value: PHYSICAL_ADDRESS) -> Self {
Self(unsafe { value.QuadPart } as _)
}
}
impl Into<PHYSICAL_ADDRESS> for PhysicalAddress {
fn into(self) -> PHYSICAL_ADDRESS {
let mut addr: PHYSICAL_ADDRESS = unsafe { core::mem::zeroed() };
addr.QuadPart = self.0 as _;
addr
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CopyAddress {
Virtual(*mut core::ffi::c_void),
Physical(PhysicalAddress),
}
unsafe impl Send for CopyAddress {}
unsafe impl Sync for CopyAddress {}
impl Into<(u32, MM_COPY_ADDRESS)> for CopyAddress {
fn into(self) -> (u32, MM_COPY_ADDRESS) {
let mut copy_addr: MM_COPY_ADDRESS = unsafe {
core::mem::zeroed()
};
let flags = match self {
CopyAddress::Virtual(addr) => {
copy_addr.__bindgen_anon_1.VirtualAddress = addr as _;
MM_COPY_MEMORY_VIRTUAL
}
CopyAddress::Physical(addr) => {
copy_addr.__bindgen_anon_1.PhysicalAddress = addr.into();
MM_COPY_MEMORY_PHYSICAL
}
};
(flags, copy_addr)
}
}
pub struct IoMapping {
ptr: *mut core::ffi::c_void,
size: usize,
}
unsafe impl Send for IoMapping {}
unsafe impl Sync for IoMapping {}
impl IoMapping {
pub fn new(addr: PhysicalAddress, size: usize, caching: MemoryCaching) -> Result<Self, Error> {
use windows_kernel_sys::ntoskrnl::MmMapIoSpace;
let ptr = unsafe {
MmMapIoSpace(addr.into(), size as _, caching as _)
};
if ptr.is_null() {
return Err(Error::INVALID_PARAMETER);
}
Ok(Self {
ptr,
size,
})
}
pub fn ptr(&self) -> *mut core::ffi::c_void {
self.ptr
}
pub fn size(&self) -> usize {
self.size
}
}
impl Drop for IoMapping {
fn drop(&mut self) {
use windows_kernel_sys::ntoskrnl::MmUnmapIoSpace;
unsafe {
MmUnmapIoSpace(self.ptr, self.size as _);
}
}
}
#[cfg(feature = "system")]
pub fn get_virtual_for_physical(addr: PhysicalAddress) -> *mut core::ffi::c_void {
use windows_kernel_sys::ntoskrnl::MmGetVirtualForPhysical;
let virt_addr = unsafe { MmGetVirtualForPhysical(addr.into()) };
virt_addr as _
}
pub fn read_memory(
buffer: &mut [u8],
source: CopyAddress,
) -> Result<usize, Error> {
use windows_kernel_sys::ntoskrnl::MmCopyMemory;
let (flags, copy_addr) = source.into();
let mut bytes = 0;
unsafe {
MmCopyMemory(
buffer.as_mut_ptr() as _,
copy_addr,
buffer.len() as _,
flags,
&mut bytes,
)
}.into_result()?;
Ok(bytes as _)
}
#[cfg(feature = "system")]
pub fn write_memory(
target: CopyAddress,
buffer: &[u8],
) -> Result<usize, Error> {
use windows_kernel_sys::ntoskrnl::MmCopyMemory;
let mut copy_addr: MM_COPY_ADDRESS = unsafe { core::mem::zeroed() };
let mut bytes = 0;
let target = match target {
CopyAddress::Virtual(addr) => addr,
CopyAddress::Physical(addr) => get_virtual_for_physical(addr),
};
copy_addr.__bindgen_anon_1.VirtualAddress = buffer.as_ptr() as _;
unsafe {
MmCopyMemory(
target as _,
copy_addr,
buffer.len() as _,
MM_COPY_MEMORY_VIRTUAL,
&mut bytes,
)
}.into_result()?;
Ok(bytes as _)
}
================================================
FILE: windows-kernel-rs/src/process.rs
================================================
use bitflags::bitflags;
use crate::error::{Error, IntoResult};
use windows_kernel_sys::base::{CLIENT_ID, HANDLE, KAPC_STATE, OBJECT_ATTRIBUTES, PEPROCESS};
use windows_kernel_sys::ntoskrnl::{KeStackAttachProcess, KeUnstackDetachProcess};
use windows_kernel_sys::ntoskrnl::{ObDereferenceObject, ObReferenceObject};
use windows_kernel_sys::ntoskrnl::{PsGetCurrentProcess, PsLookupProcessByProcessId};
use windows_kernel_sys::ntoskrnl::{ZwClose, ZwOpenProcess};
pub type ProcessId = usize;
#[derive(Clone, Debug)]
pub struct Process {
pub process: PEPROCESS,
}
impl Process {
pub fn as_ptr(&self) -> PEPROCESS {
self.process
}
pub fn current() -> Self {
let process = unsafe {
PsGetCurrentProcess()
};
unsafe {
ObReferenceObject(process as _);
}
Self {
process,
}
}
pub fn by_id(process_id: ProcessId) -> Result<Self, Error> {
let mut process = core::ptr::null_mut();
unsafe {
PsLookupProcessByProcessId(process_id as _, &mut process)
}.into_result()?;
Ok(Self {
process,
})
}
pub fn id(&self) -> ProcessId {
let handle = unsafe {
windows_kernel_sys::ntoskrnl::PsGetProcessId(self.process)
};
handle as _
}
pub fn attach(&self) -> ProcessAttachment {
unsafe {
ProcessAttachment::attach(self.process)
}
}
}
impl Drop for Process {
fn drop(&mut self) {
unsafe {
ObDereferenceObject(self.process as _);
}
}
}
pub struct ProcessAttachment {
process: PEPROCESS,
state: KAPC_STATE,
}
impl ProcessAttachment {
pub unsafe fn attach(process: PEPROCESS) -> Self {
let mut state: KAPC_STATE = core::mem::zeroed();
ObReferenceObject(process as _);
KeStackAttachProcess(process, &mut state);
Self {
process,
state,
}
}
}
impl Drop for ProcessAttachment {
fn drop(&mut self) {
unsafe {
KeUnstackDetachProcess(&mut self.state);
ObDereferenceObject(self.process as _);
}
}
}
bitflags! {
pub struct ProcessAccess: u32 {
const ALL_ACCESS = windows_kernel_sys::base::PROCESS_ALL_ACCESS;
}
}
pub struct ZwProcess {
pub(crate) handle: HANDLE,
}
impl ZwProcess {
pub fn open(id: ProcessId, access: ProcessAccess) -> Result<Self, Error> {
let mut attrs: OBJECT_ATTRIBUTES = unsafe { core::mem::zeroed() };
attrs.Length = core::mem::size_of::<OBJECT_ATTRIBUTES>() as u32;
let mut client_id = CLIENT_ID {
UniqueProcess: id as _,
UniqueThread: core::ptr::null_mut(),
};
let mut handle = core::ptr::null_mut();
unsafe {
ZwOpenProcess(&mut handle, access.bits(), &mut attrs, &mut client_id)
}.into_result()?;
Ok(Self {
handle,
})
}
}
impl Drop for ZwProcess {
fn drop(&mut self) {
unsafe {
ZwClose(self.handle);
}
}
}
================================================
FILE: windows-kernel-rs/src/request.rs
================================================
use bitflags::bitflags;
use core::ops::Deref;
use crate::error::Error;
use crate::ioctl::{ControlCode, RequiredAccess, TransferMethod};
use crate::user_ptr::UserPtr;
use windows_kernel_sys::base::{IO_NO_INCREMENT, IO_STACK_LOCATION, IRP, STATUS_SUCCESS};
use windows_kernel_sys::base::_MM_PAGE_PRIORITY as MM_PAGE_PRIORITY;
use windows_kernel_sys::ntoskrnl::{IoCompleteRequest, IoGetCurrentIrpStackLocation};
use windows_kernel_sys::ntoskrnl::{MmGetMdlByteCount, MmGetMdlByteOffset, MmGetSystemAddressForMdlSafe};
bitflags! {
pub struct IrpFlags: u32 {
const NOCACHE = windows_kernel_sys::base::IRP_NOCACHE;
const PAGING_IO = windows_kernel_sys::base::IRP_PAGING_IO;
const MOUNT_COMPLETION = windows_kernel_sys::base::IRP_MOUNT_COMPLETION;
const SYNCHRONOUS_API = windows_kernel_sys::base::IRP_SYNCHRONOUS_API;
const ASSOCIATED_IRP = windows_kernel_sys::base::IRP_ASSOCIATED_IRP;
const BUFFERED_IO = windows_kernel_sys::base::IRP_BUFFERED_IO;
const DEALLOCATE_BUFFER = windows_kernel_sys::base::IRP_DEALLOCATE_BUFFER;
const INPUT_OPERATION = windows_kernel_sys::base::IRP_INPUT_OPERATION;
const SYNCHRONOUS_PAGING_IO = windows_kernel_sys::base::IRP_SYNCHRONOUS_PAGING_IO;
const CREATE_OPERATION = windows_kernel_sys::base::IRP_CREATE_OPERATION;
const READ_OPERATION = windows_kernel_sys::base::IRP_READ_OPERATION;
const WRITE_OPERATION = windows_kernel_sys::base::IRP_WRITE_OPERATION;
const CLOSE_OPERATION = windows_kernel_sys::base::IRP_CLOSE_OPERATION;
const DEFER_IO_COMPLETION = windows_kernel_sys::base::IRP_DEFER_IO_COMPLETION;
const OB_QUERY_NAME = windows_kernel_sys::base::IRP_OB_QUERY_NAME;
const HOLD_DEVICE_QUEUE = windows_kernel_sys::base::IRP_HOLD_DEVICE_QUEUE;
const UM_DRIVER_INITIATED_IO = windows_kernel_sys::base::IRP_UM_DRIVER_INITIATED_IO;
}
}
pub struct IoRequest {
irp: *mut IRP,
}
impl IoRequest {
pub unsafe fn from_raw(irp: *mut IRP) -> Self {
Self { irp }
}
pub fn irp(&self) -> &IRP {
unsafe { &*self.irp }
}
pub fn irp_mut(&self) -> &mut IRP {
unsafe { &mut *self.irp }
}
pub fn flags(&self) -> IrpFlags {
IrpFlags::from_bits(self.irp().Flags)
.unwrap_or(IrpFlags::empty())
}
pub fn stack_location(&self) -> &IO_STACK_LOCATION {
unsafe { &*IoGetCurrentIrpStackLocation(self.irp_mut()) }
}
pub fn major(&self) -> u8 {
self.stack_location().MajorFunction
}
pub(crate) fn complete(&self, value: Result<u32, Error>) {
let irp = self.irp_mut();
match value {
Ok(value) => {
irp.IoStatus.Information = value as _;
irp.IoStatus.__bindgen_anon_1.Status = STATUS_SUCCESS;
}
Err(error) => {
irp.IoStatus.Information = 0;
irp.IoStatus.__bindgen_anon_1.Status = error.to_ntstatus();
}
}
unsafe {
IoCompleteRequest(irp, IO_NO_INCREMENT as _);
}
}
}
pub struct ReadRequest {
pub(crate) inner: IoRequest,
}
impl Deref for ReadRequest {
type Target = IoRequest;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl ReadRequest {
pub fn user_ptr(&self) -> UserPtr {
let stack_location = self.stack_location();
let irp = self.irp();
let (ptr, size) = if !irp.MdlAddress.is_null() {
let ptr = unsafe {
MmGetSystemAddressForMdlSafe(irp.MdlAddress, MM_PAGE_PRIORITY::HighPagePriority as _)
};
let size = unsafe { MmGetMdlByteCount(irp.MdlAddress) } as usize;
(ptr, size)
} else if !unsafe { irp.AssociatedIrp.SystemBuffer }.is_null() {
let ptr = unsafe { irp.AssociatedIrp.SystemBuffer };
let size = unsafe { stack_location.Parameters.Read }.Length as usize;
(ptr, size)
} else {
(core::ptr::null_mut(), 0)
};
unsafe { UserPtr::new_buffered(ptr, 0, size) }
}
pub fn offset(&self) -> i64 {
let stack_location = self.stack_location();
let irp = self.irp();
if !irp.MdlAddress.is_null() {
(unsafe { MmGetMdlByteOffset(irp.MdlAddress) }) as i64
} else if !unsafe { irp.AssociatedIrp.SystemBuffer }.is_null() {
unsafe { stack_location.Parameters.Read.ByteOffset.QuadPart }
} else {
0
}
}
}
impl Into<IoRequest> for ReadRequest {
fn into(self) -> IoRequest {
self.inner
}
}
pub struct WriteRequest {
pub(crate) inner: IoRequest,
}
impl Deref for WriteRequest {
type Target = IoRequest;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl WriteRequest {
pub fn user_ptr(&self) -> UserPtr {
let stack_location = self.stack_location();
let irp = self.irp();
let (ptr, size) = if !irp.MdlAddress.is_null() {
let ptr = unsafe {
MmGetSystemAddressForMdlSafe(irp.MdlAddress, MM_PAGE_PRIORITY::HighPagePriority as _)
};
let size = unsafe { MmGetMdlByteCount(irp.MdlAddress) } as usize;
(ptr, size)
} else if !unsafe {irp.AssociatedIrp.SystemBuffer }.is_null() {
let ptr = unsafe { irp.AssociatedIrp.SystemBuffer };
let size = unsafe { stack_location.Parameters.Write }.Length as usize;
(ptr, size)
} else {
(core::ptr::null_mut(), 0)
};
unsafe { UserPtr::new_buffered(ptr, size, 0) }
}
pub fn offset(&self) -> i64 {
let stack_location = self.stack_location();
let irp = self.irp();
if !irp.MdlAddress.is_null() {
(unsafe { MmGetMdlByteOffset(irp.MdlAddress) }) as i64
} else if !unsafe { irp.AssociatedIrp.SystemBuffer }.is_null() {
unsafe { stack_location.Parameters.Write.ByteOffset.QuadPart }
} else {
0
}
}
}
impl Into<IoRequest> for WriteRequest {
fn into(self) -> IoRequest {
self.inner
}
}
pub struct IoControlRequest {
pub(crate) inner: IoRequest,
}
impl Deref for IoControlRequest {
type Target = IoRequest;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl IoControlRequest {
pub fn control_code(&self) -> ControlCode {
let stack_location = self.stack_location();
unsafe {
stack_location.Parameters.DeviceIoControl.IoControlCode.into()
}
}
pub fn function(&self) -> (RequiredAccess, u32) {
let code = self.control_code();
(code.required_access(), code.number())
}
pub fn user_ptr(&self) -> UserPtr {
let stack_location = self.stack_location();
let irp = self.irp();
let system_buffer = unsafe { irp.AssociatedIrp.SystemBuffer };
let mdl_address = if !irp.MdlAddress.is_null() {
unsafe { MmGetSystemAddressForMdlSafe(irp.MdlAddress, MM_PAGE_PRIORITY::HighPagePriority as _) }
} else {
core::ptr::null_mut()
};
let input_size = unsafe {
stack_location.Parameters.DeviceIoControl.InputBufferLength
} as usize;
let output_size = unsafe {
stack_location.Parameters.DeviceIoControl.OutputBufferLength
} as usize;
match self.control_code().transfer_method() {
TransferMethod::Buffered =>
unsafe { UserPtr::new_buffered(system_buffer, input_size, output_size) },
TransferMethod::InputDirect =>
unsafe { UserPtr::new_direct(mdl_address, system_buffer, output_size, input_size) },
TransferMethod::OutputDirect =>
unsafe { UserPtr::new_direct(system_buffer, mdl_address, input_size, output_size) },
TransferMethod::Neither =>
unsafe { UserPtr::new_neither() },
}
}
}
impl Into<IoRequest> for IoControlRequest {
fn into(self) -> IoRequest {
self.inner
}
}
================================================
FILE: windows-kernel-rs/src/section.rs
================================================
use bitflags::bitflags;
use crate::error::{Error, IntoResult};
use crate::process::ZwProcess;
use crate::string::create_unicode_string;
use widestring::U16CString;
use windows_kernel_sys::base::{HANDLE, LARGE_INTEGER, OBJECT_ATTRIBUTES};
use windows_kernel_sys::ntoskrnl::{ZwClose, ZwMapViewOfSection, ZwOpenSection, ZwUnmapViewOfSection};
bitflags! {
pub struct AllocationFlags: u32 {
const RESERVE = windows_kernel_sys::base::MEM_RESERVE;
const LARGE_PAGES = windows_kernel_sys::base::MEM_LARGE_PAGES;
const TOP_DOWN = windows_kernel_sys::base::MEM_TOP_DOWN;
}
}
bitflags! {
pub struct ProtectFlags: u32 {
const READ_WRITE = windows_kernel_sys::base::PAGE_READWRITE;
}
}
bitflags! {
pub struct SectionAccess: u32 {
const EXTEND_SIZE = windows_kernel_sys::base::SECTION_EXTEND_SIZE;
const MAP_EXECUTE = windows_kernel_sys::base::SECTION_MAP_EXECUTE;
const MAP_READ = windows_kernel_sys::base::SECTION_MAP_READ;
const MAP_WRITE = windows_kernel_sys::base::SECTION_MAP_WRITE;
const QUERY = windows_kernel_sys::base::SECTION_QUERY;
const ALL_ACCESS = windows_kernel_sys::base::SECTION_ALL_ACCESS;
}
}
bitflags! {
pub struct ObjectFlags: u32 {
const CASE_INSENSITIVE = windows_kernel_sys::base::OBJ_CASE_INSENSITIVE;
const KERNEL_HANDLE = windows_kernel_sys::base::OBJ_KERNEL_HANDLE;
}
}
#[repr(i32)]
pub enum SectionInherit {
ViewShare = windows_kernel_sys::base::_SECTION_INHERIT::ViewShare,
ViewUnmap = windows_kernel_sys::base::_SECTION_INHERIT::ViewUnmap,
}
pub enum BaseAddress {
Desired(*mut core::ffi::c_void),
ZeroBits(usize),
}
pub struct Section {
handle: HANDLE,
}
unsafe impl Send for Section {}
unsafe impl Sync for Section {}
impl Section {
pub fn open(path: &str, obj_flags: ObjectFlags, access: SectionAccess) -> Result<Self, Error> {
let name = U16CString::from_str(path).unwrap();
let mut name = create_unicode_string(name.as_slice());
let mut attrs = OBJECT_ATTRIBUTES {
Length: core::mem::size_of::<OBJECT_ATTRIBUTES>() as u32,
RootDirectory: core::ptr::null_mut(),
ObjectName: &mut name,
Attributes: obj_flags.bits(),
SecurityDescriptor: core::ptr::null_mut(),
SecurityQualityOfService: core::ptr::null_mut(),
};
let mut handle: HANDLE = core::ptr::null_mut();
unsafe {
ZwOpenSection(&mut handle, access.bits(), &mut attrs)
}.into_result()?;
Ok(Self {
handle
})
}
pub fn map_view(
&mut self,
process: ZwProcess,
base_address: BaseAddress,
commit_size: usize,
offset: Option<u64>,
view_size: usize,
inherit: SectionInherit,
allocation: AllocationFlags,
protection: ProtectFlags,
) -> Result<SectionView, Error> {
let (mut base_address, zero_bits) = match base_address {
BaseAddress::Desired(ptr) => (ptr, 0),
BaseAddress::ZeroBits(bits) => (core::ptr::null_mut(), bits),
};
let mut offset = offset.map(|value| {
let mut offset: LARGE_INTEGER = unsafe { core::mem::zeroed() };
offset.QuadPart = value as _;
offset
});
let mut size: u64 = view_size as _;
unsafe {
ZwMapViewOfSection(
self.handle,
process.handle,
&mut base_address,
zero_bits as _,
commit_size as _,
match offset {
Some(ref mut offset) => offset as _,
_ => core::ptr::null_mut(),
},
&mut size,
inherit as _,
allocation.bits(),
protection.bits(),
)
}.into_result()?;
Ok(SectionView {
process,
address: base_address,
})
}
}
impl Drop for Section {
fn drop(&mut self) {
unsafe {
ZwClose(self.handle);
}
}
}
pub struct SectionView {
process: ZwProcess,
address: *mut core::ffi::c_void,
}
unsafe impl Send for SectionView {}
unsafe impl Sync for SectionView {}
impl SectionView {
pub fn address(&self) -> *mut core::ffi::c_void {
self.address
}
}
impl Drop for SectionView {
fn drop(&mut self) {
unsafe {
ZwUnmapViewOfSection(
self.process.handle,
self.address,
);
}
}
}
================================================
FILE: windows-kernel-rs/src/string.rs
================================================
use windows_kernel_sys::base::UNICODE_STRING;
pub fn create_unicode_string(s: &[u16]) -> UNICODE_STRING {
let len = s.len();
let n = if len > 0 && s[len - 1] == 0 { len - 1 } else { len };
UNICODE_STRING {
Length: (n * 2) as u16,
MaximumLength: (len * 2) as u16,
Buffer: s.as_ptr() as _,
}
}
================================================
FILE: windows-kernel-rs/src/symbolic_link.rs
================================================
use crate::error::{Error, IntoResult};
use crate::string::create_unicode_string;
use widestring::U16CString;
use windows_kernel_sys::ntoskrnl::{IoCreateSymbolicLink, IoDeleteSymbolicLink};
pub struct SymbolicLink {
name: U16CString,
}
impl SymbolicLink {
pub fn new(name: &str, target: &str) -> Result<Self, Error> {
// Convert the name to UTF-16 and then create a UNICODE_STRING.
let name = U16CString::from_str(name).unwrap();
let mut name_ptr = create_unicode_string(name.as_slice());
// Convert the target to UTF-16 and then create a UNICODE_STRING.
let target = U16CString::from_str(target).unwrap();
let mut target_ptr = create_unicode_string(target.as_slice());
unsafe {
IoCreateSymbolicLink(&mut name_ptr, &mut target_ptr)
}.into_result()?;
Ok(Self {
name,
})
}
}
impl Drop for SymbolicLink {
fn drop(&mut self) {
let mut name_ptr = create_unicode_string(self.name.as_slice());
unsafe {
IoDeleteSymbolicLink(&mut name_ptr);
}
}
}
================================================
FILE: windows-kernel-rs/src/sync/fast_mutex.rs
================================================
use alloc::boxed::Box;
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use windows_kernel_sys::base::FAST_MUTEX;
use windows_kernel_sys::ntoskrnl::{
ExInitializeFastMutex, ExAcquireFastMutex, ExReleaseFastMutex, ExTryToAcquireFastMutex,
};
/// A mutual exclusion primitive useful for protecting shared data.
///
/// This mutex will block threads waiting for the lock to become available. The mutex can also be
/// statically initialized or created via a [`new`] constructor. Each mutex has a type parameter
/// which represents the data that it is protecting. The data can only be accessed through the RAII
/// guards returned from [`lock`] and [`try_lock`], which guarantees that the data is only ever
/// accessed when the mutex is locked.
///
/// [`new`]: FastMutex::new
/// [`lock`]: FastMutex::lock
/// [`try_lock`]: FastMutex::try_lock
pub struct FastMutex<T: ?Sized> {
pub(crate) lock: Box<FAST_MUTEX>,
pub(crate) data: UnsafeCell<T>,
}
unsafe impl<T> Send for FastMutex<T> {}
unsafe impl<T> Sync for FastMutex<T> {}
impl<T> FastMutex<T> {
/// Creates a new mutex in an unlocked state ready for use.
pub fn new(data: T) -> Self {
let mut lock: Box<FAST_MUTEX> = Box::new(unsafe {
core::mem::zeroed()
});
unsafe {
ExInitializeFastMutex(
&mut *lock,
)
};
Self {
lock,
data: UnsafeCell::new(data),
}
}
/// Consumes this `FastMutex`, returning the underlying data.
#[inline]
pub fn into_inner(self) -> T {
let Self { data, .. } = self;
data.into_inner()
}
/// Attempts to acquire this lock.
///
/// If the lock could not be acquired at this time, then `None` is returned. Otherwise, an RAII
/// guard is returned. The lock will be unlocked when the guard is dropped.
///
/// This function does not block.
#[inline]
pub fn try_lock(&mut self) -> Option<FastMutexGuard<T>> {
let status = unsafe {
ExTryToAcquireFastMutex(
&mut *self.lock,
)
} != 0;
match status {
true => Some(FastMutexGuard {
lock: &mut self.lock,
data: unsafe { &mut *self.data.get() },
}),
_ => None,
}
}
/// Acquires a mutex, blocking the current thread until it is able to do so.
///
/// This function will block the local thread until it is available to acquire the mutex. Upon
/// returning, the thread is the only thread with the lock held. An RAII guard is returned to
/// allow scoped unlock of the lock. When the guard goes out of scope, the mutex will be
/// unlocked.
///
/// The underlying function does not allow for recursion. If the thread already holds the lock
/// and tries to lock the mutex again, this function will return `None` instead.
#[inline]
pub fn lock(&mut self) -> Option<FastMutexGuard<T>> {
unsafe {
ExAcquireFastMutex(
&mut *self.lock,
)
};
Some(FastMutexGuard {
lock: &mut self.lock,
data: unsafe { &mut *self.data.get() },
})
}
}
impl<T: ?Sized + Default> Default for FastMutex<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T> From<T> for FastMutex<T> {
fn from(data: T) -> Self {
Self::new(data)
}
}
/// An RAII implementation of a "scoped lock" of a mutex. When this structure is dropped (falls out
/// of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be accessed through this guard via its [`Deref`] and
/// [`DerefMut`] implementations.
///
/// This structure is created by the [`lock`] and [`try_lock`] methods on [`FastMutex`].
///
/// [`lock`]: FastMutex::lock
/// [`try_lock`]: FastMutex::try_lock
pub struct FastMutexGuard<'a, T: 'a + ?Sized> {
pub(crate) lock: &'a mut FAST_MUTEX,
pub(crate) data: &'a mut T,
}
impl<'a, T: ?Sized> Drop for FastMutexGuard<'a, T> {
fn drop(&mut self) {
unsafe {
ExReleaseFastMutex(
&mut *self.lock,
)
};
}
}
impl<'a, T: ?Sized> Deref for FastMutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.data
}
}
impl<'a, T: ?Sized> DerefMut for FastMutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.data
}
}
================================================
FILE: windows-kernel-rs/src/sync/mod.rs
================================================
pub mod fast_mutex;
pub mod push_lock;
pub use self::fast_mutex::FastMutex as Mutex;
pub use self::push_lock::PushLock as RwLock;
================================================
FILE: windows-kernel-rs/src/sync/push_lock.rs
================================================
use alloc::boxed::Box;
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use windows_kernel_sys::base::EX_PUSH_LOCK;
use windows_kernel_sys::ntoskrnl::{
ExInitializePushLock,
ExAcquirePushLockShared,
ExReleasePushLockShared,
ExAcquirePushLockExclusive,
ExReleasePushLockExclusive,
KeEnterCriticalRegion,
KeLeaveCriticalRegion,
};
/// A [`PushLock`] is an efficient implementation of a reader-writer lock that can be stored both
/// in paged and non-paged memory.
///
/// This type of lock allows a number of readers or at most one writer at any point in time. The
/// write portion of this lock typically allows modifications of the underlying data (exclusive
/// access) and the read portion of this lock typically allows for read-only access (shared
/// access).
///
/// In comparison, a [`FastMutex`] does not distinguish between readers or writers that acquire the
/// lock, therefore blocking any threads waiting for the lock to become available. A [`PushLock`]
/// will allow any number of readers to acquire the lock as long as a writer is not holding the
/// lock.
///
/// The priority policy is such that a thread trying to acquire the [`PushLock`] for exclusive
/// access will be prioritized over threads trying to acquire the [`PushLock`] for shared access.
/// More specifically, if a thread cannot lock the [`PushLock`] for exclusive access immediately,
/// it will wait for the thread(s) that currently holds the lock to release the lock. If another
/// thread tries to acquire the [`PushLock`] for shared access while a thread is waiting to acquire
/// the lock for exclusive access, it will yield to the thread(s) trying to acquire the
/// [`PushLock`] for exclusive access, even in the event that the [`PushLock`] is acquired for
/// shared access.
///
/// [`FastMutex`]: crate::fast_mutex::FastMutex
pub struct PushLock<T: ?Sized> {
pub(crate) lock: Box<EX_PUSH_LOCK>,
pub(crate) data: UnsafeCell<T>,
}
unsafe impl<T> Send for PushLock<T> {}
unsafe impl<T> Sync for PushLock<T> {}
impl<T> PushLock<T> {
/// Creates new instance of [`PushLock<T>`] that is unlocked.
pub fn new(data: T) -> Self {
let mut lock: Box<EX_PUSH_LOCK> = Box::new(0);
unsafe {
ExInitializePushLock(
&mut *lock,
)
};
Self {
lock,
data: UnsafeCell::new(data),
}
}
/// Consumes this [`PushLock`], returning the underlying data.
#[inline]
pub fn into_inner(self) -> T {
let Self { data, .. } = self;
data.into_inner()
}
/// Locks this [`PushLock`] with shared read access, blocking the current thread until it can
/// be acquired.
///
/// The calling thread will be blocked until there are no more writers which hold the lock.
/// There may be other readers currently inside the lock when this method returns.
///
/// This function will yield to threads waiting to acquire the [`PushLock`] for exclusive
/// access, even in the event that the [`PushLock`] is currently held by one or more threads
/// for shared access.
///
/// While the underlying function does allow for recursion, this atomically increments a shared
/// reader counter. Since dropping the RAII guard releases the lock by atomically decrementing
/// this shared counter, it will eventually reach zero once all RAII guards have been dropped.
#[inline]
pub fn read(&mut self) -> Option<PushLockReadGuard<T>> {
unsafe {
KeEnterCriticalRegion()
};
unsafe {
ExAcquirePushLockShared(
&mut *self.lock,
)
};
Some(PushLockReadGuard {
lock: &mut self.lock,
data: unsafe { &mut *self.data.get() },
})
}
/// Locks this [`PushLock`] with exclusive write access, blocking the current thread until it can
/// be acquired.
///
/// This function will not return while other writers or other readers currently have access to
/// the lock.
///
/// Returns an RAII guard which will drop the write access of this [`PushLock`] when dropped.
///
/// This thread will take priority over any threads that are trying to acquire the lock for
/// shared access but that do not currently hold the lock for shared access.
///
/// The underlying function does not allow for recursion, which ensures correct behavior.
#[inline]
pub fn write(&mut self) -> Option<PushLockWriteGuard<T>> {
unsafe {
KeEnterCriticalRegion()
};
unsafe {
ExAcquirePushLockExclusive(
&mut *self.lock,
)
};
Some(PushLockWriteGuard {
lock: &mut self.lock,
data: unsafe { &mut *self.data.get() },
})
}
}
/// RAII structure used to release the shared read access of a lock when dropped.
///
/// This structure is created by the [`read`] and [`try_read`] methods on [`PushLock`]
///
/// [`read`]: PushLock::read
/// [`try_read`]: PushLock::try_read
pub struct PushLockReadGuard<'a, T: 'a + ?Sized> {
pub(crate) lock: &'a mut EX_PUSH_LOCK,
pub(crate) data: &'a T,
}
impl<'a, T: ?Sized> Drop for PushLockReadGuard<'a, T> {
fn drop(&mut self) {
unsafe {
ExReleasePushLockShared(
&mut *self.lock,
)
};
unsafe {
KeLeaveCriticalRegion()
};
}
}
impl<'a, T: ?Sized> Deref for PushLockReadGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.data
}
}
/// RAII structure used to release the exclusive write access of a lock when dropped.
///
/// This structure is created by the [`write`] and [`try_write`] methods on [`PushLock`]
///
/// [`write`]: PushLock::write
/// [`try_write`]: PushLock::try_write
pub struct PushLockWriteGuard<'a, T: 'a + ?Sized> {
pub(crate) lock: &'a mut EX_PUSH_LOCK,
pub(crate) data: &'a mut T,
}
impl<'a, T: ?Sized> Drop for PushLockWriteGuard<'a, T> {
fn drop(&mut self) {
unsafe {
ExReleasePushLockExclusive(
&mut *self.lock,
)
};
unsafe {
KeLeaveCriticalRegion()
};
}
}
impl<'a, T: ?Sized> Deref for PushLockWriteGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.data
}
}
impl<'a, T: ?Sized> DerefMut for PushLockWriteGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.data
}
}
================================================
FILE: windows-kernel-rs/src/user_ptr.rs
================================================
use crate::error::Error;
pub enum UserPtr {
Buffered {
ptr: *mut cty::c_void,
read_size: usize,
write_size: usize,
},
Direct {
read_ptr: *const cty::c_void,
write_ptr: *mut cty::c_void,
read_size: usize,
write_size: usize,
},
Neither,
}
impl UserPtr {
pub unsafe fn new_buffered(
ptr: *mut cty::c_void,
read_size: usize,
write_size: usize,
) -> Self {
Self::Buffered{
ptr,
read_size,
write_size,
}
}
pub unsafe fn new_direct(
read_ptr: *const cty::c_void,
write_ptr: *mut cty::c_void,
read_size: usize,
write_size: usize,
) -> Self {
Self::Direct {
read_ptr,
write_ptr,
read_size,
write_size,
}
}
pub unsafe fn new_neither() -> Self {
Self::Neither
}
pub fn read_size(&self) -> usize {
match self {
Self::Buffered { read_size, .. } => *read_size,
Self::Direct { read_size, .. } => *read_size,
Self::Neither => 0,
}
}
pub fn write_size(&self) -> usize {
match self {
Self::Buffered { write_size, .. } => *write_size,
Self::Direct { write_size, .. } => *write_size,
Self::Neither => 0,
}
}
pub fn as_slice(&self) -> &[u8] {
let (ptr, size) = match self {
Self::Buffered { ptr, read_size, .. } => (*ptr as _, *read_size),
Self::Direct { read_ptr, read_size, .. } => (*read_ptr, *read_size),
Self::Neither => (core::ptr::null(), 0),
};
if ptr.is_null() || size == 0 {
&[]
} else {
unsafe {
core::slice::from_raw_parts(ptr as *const u8, size)
}
}
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
let (ptr, size) = match self {
Self::Buffered { ptr, write_size, .. } => (*ptr, *write_size),
Self::Direct { write_ptr, write_size, .. } => (*write_ptr, *write_size),
Self::Neither => (core::ptr::null_mut(), 0),
};
if ptr.is_null() || size == 0 {
&mut []
} else {
unsafe {
core::slice::from_raw_parts_mut(ptr as *mut u8, size)
}
}
}
pub fn read<T: Copy + Default>(&self) -> Result<T, Error> {
let (ptr, size) = match self {
Self::Buffered { ptr, read_size, .. } => (*ptr as _, *read_size),
Self::Direct { read_ptr, read_size, .. } => (*read_ptr, *read_size),
Self::Neither => (core::ptr::null(), 0),
};
if ptr.is_null() || size == 0 {
return Err(Error::INVALID_PARAMETER);
}
if core::mem::size_of::<T>() > size {
return Err(Error::INVALID_USER_BUFFER);
}
let mut obj = T::default();
unsafe {
core::ptr::copy_nonoverlapping(
ptr as _,
&mut obj,
1,
);
}
Ok(obj)
}
pub fn write<T: Copy>(&mut self, obj: &T) -> Result<(), Error> {
let (ptr, size) = match self {
Self::Buffered { ptr, write_size, .. } => (*ptr, *write_size),
Self::Direct { write_ptr, write_size, .. } => (*write_ptr, *write_size),
Self::Neither => (core::ptr::null_mut(), 0),
};
if ptr.is_null() || size == 0 {
return Err(Error::INVALID_PARAMETER);
}
if core::mem::size_of::<T>() > size {
return Err(Error::INVALID_USER_BUFFER);
}
unsafe {
core::ptr::copy_nonoverlapping(
obj,
ptr as _,
1,
);
}
Ok(())
}
}
================================================
FILE: windows-kernel-rs/src/version.rs
================================================
//! This module provides utilities to query information about the version of Microsoft Windows.
use crate::error::{Error, IntoResult};
use windows_kernel_sys::base::RTL_OSVERSIONINFOW;
use windows_kernel_sys::ntoskrnl::RtlGetVersion;
/// Represents version information for Microsoft Windows.
pub struct VersionInfo {
version_info: RTL_OSVERSIONINFOW,
}
impl VersionInfo {
/// Uses [`RtlGetVersion`] to query the version info for Microsoft Windows.
pub fn query() -> Result<Self, Error> {
let mut version_info: RTL_OSVERSIONINFOW = unsafe { core::mem::zeroed() };
version_info.dwOSVersionInfoSize = core::mem::size_of::<RTL_OSVERSIONINFOW>() as u32;
unsafe {
RtlGetVersion(&mut version_info)
}.into_result()?;
Ok(Self {
version_info,
})
}
/// Retrieves the major version of Microsoft Windows.
pub fn major(&self) -> u32 {
self.version_info.dwMajorVersion
}
/// Retrieves the minor version of Microsoft Windows.
pub fn minor(&self) -> u32 {
self.version_info.dwMinorVersion
}
/// Retrieves the build number of Microsoft Windows.
pub fn build_number(&self) -> u32 {
self.version_info.dwBuildNumber
}
}
================================================
FILE: windows-kernel-sys/Cargo.toml
================================================
[package]
name = "windows-kernel-sys"
version = "0.1.0"
edition = "2021"
[features]
default = ["intrin", "ntoskrnl"]
intrin = []
ntoskrnl = []
netio = []
[dependencies]
cty = "0.2"
[build-dependencies]
bindgen = "0.68"
cc = "1.0"
windows-kernel-build = { path = "../windows-kernel-build" }
================================================
FILE: windows-kernel-sys/build.rs
================================================
use std::path::PathBuf;
use windows_kernel_build::DirectoryType;
use bindgen::callbacks::*;
#[derive(Debug)]
struct Callbacks;
impl ParseCallbacks for Callbacks {
fn int_macro(&self, name: &str, _value: i64) -> Option<IntKind> {
Some(match name {
"TRUE" | "FALSE" => IntKind::UChar,
_ => return None,
})
}
}
fn generate_base() {
println!("cargo:rerun-if-changed=src/wrapper.h");
let include_dir = windows_kernel_build::get_km_dir(DirectoryType::Include).unwrap();
let out_path = PathBuf::from(
std::env::var_os("OUT_DIR")
.expect("the environment variable OUT_DIR is undefined")
);
bindgen::Builder::default()
.header("src/wrapper.h")
.use_core()
.derive_debug(false)
.layout_tests(false)
.ctypes_prefix("cty")
.default_enum_style(bindgen::EnumVariation::ModuleConsts)
.clang_arg(format!("-I{}", include_dir.to_str().unwrap()))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.parse_callbacks(Box::new(Callbacks))
.ignore_functions()
.generate()
.unwrap()
.write_to_file(out_path.join("base.rs"))
.unwrap();
}
#[cfg(feature = "intrin")]
fn generate_intrin() {
println!("cargo:rerun-if-changed=src/wrapper_intrin.c");
let include_dir = windows_kernel_build::get_km_dir(DirectoryType::Include).unwrap();
cc::Build::new()
.flag("/kernel")
.include(include_dir)
.file("src/wrapper_intrin.c")
.compile("wrapper_intrin");
}
#[cfg(not(feature = "intrin"))]
fn generate_intrin() {
}
#[cfg(feature = "ntoskrnl")]
fn generate_ntoskrnl() {
println!("cargo:rerun-if-changed=src/wrapper.h");
println!("cargo:rerun-if-changed=src/wrapper.c");
println!("cargo:rustc-link-lib=ntoskrnl");
let include_dir = windows_kernel_build::get_km_dir(DirectoryType::Include).unwrap();
let out_path = PathBuf::from(
std::env::var_os("OUT_DIR")
.expect("the environment variable OUT_DIR is undefined")
);
bindgen::Builder::default()
.header("src/wrapper.h")
.use_core()
.derive_debug(false)
.layout_tests(false)
.ctypes_prefix("cty")
.default_enum_style(bindgen::EnumVariation::ModuleConsts)
.clang_arg(format!("-I{}", include_dir.to_str().unwrap()))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.blocklist_type(".*")
.allowlist_function(".*")
.allowlist_recursively(false)
.generate()
.unwrap()
.write_to_file(out_path.join("ntoskrnl.rs"))
.unwrap();
cc::Build::new()
.flag("/kernel")
.include(include_dir)
.file("src/wrapper.c")
.compile("wrapper_ntoskrnl");
}
#[cfg(not(feature = "ntoskrnl"))]
fn generate_ntoskrnl() {
}
#[cfg(feature = "netio")]
fn generate_netio() {
println!("cargo:rerun-if-changed=src/wrapper_netio.h");
println!("cargo:rustc-link-lib=netio");
let include_dir = windows_kernel_build::get_km_dir(DirectoryType::Include).unwrap();
let out_path = PathBuf::from(
std::env::var_os("OUT_DIR")
.expect("the environment variable OUT_DIR is undefined")
);
bindgen::Builder::default()
.header("src/wrapper.h")
.use_core()
.derive_debug(false)
.layout_tests(false)
.ctypes_prefix("cty")
.default_enum_style(bindgen::EnumVariation::ModuleConsts)
.clang_arg(format!("-I{}", include_dir.to_str().unwrap()))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.blocklist_type(".*")
.allowlist_function(".*")
.allowlist_recursively(false)
.generate()
.unwrap()
.write_to_file(out_path.join("netio.rs"))
.unwrap();
}
#[cfg(not(feature = "netio"))]
fn generate_netio() {
}
fn main() {
println!("cargo:rerun-if-changed=build.rs");
generate_base();
generate_intrin();
generate_ntoskrnl();
generate_netio();
}
================================================
FILE: windows-kernel-sys/rust-toolchain
================================================
nightly
================================================
FILE: windows-kernel-sys/src/base.rs
================================================
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
pub use cty::*;
include!(concat!(env!("OUT_DIR"), "/base.rs"));
pub const STATUS_SUCCESS: NTSTATUS = 0x00000000;
pub const STATUS_GUARD_PAGE_VIOLATION: NTSTATUS = 0x80000001 as u32 as i32;
pub const STATUS_DATATYPE_MISALIGNMENT: NTSTATUS = 0x80000002 as u32 as i32;
pub const STATUS_BREAKPOINT: NTSTATUS = 0x80000003 as u32 as i32;
pub const STATUS_SINGLE_STEP: NTSTATUS = 0x80000004 as u32 as i32;
pub const STATUS_UNWIND_CONSOLIDATE: NTSTATUS = 0x80000029 as u32 as i32;
pub const STATUS_UNSUCCESSFUL: NTSTATUS = 0xC0000001 as u32 as i32;
pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002 as u32 as i32;
pub const STATUS_ACCESS_VIOLATION: NTSTATUS = 0xC0000005 as u32 as i32;
pub const STATUS_IN_PAGE_ERROR: NTSTATUS = 0xC0000006 as u32 as i32;
pub const STATUS_INVALID_HANDLE: NTSTATUS = 0xC0000008 as u32 as i32;
pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xC000000D as u32 as i32;
pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011 as u32 as i32;
pub const STATUS_NO_MEMORY: NTSTATUS = 0xC0000017 as u32 as i32;
pub const STATUS_ILLEGAL_INSTRUCTION: NTSTATUS = 0xC000001D as u32 as i32;
pub const STATUS_NONCONTINUABLE_EXCEPTION: NTSTATUS = 0xC0000025 as u32 as i32;
pub const STATUS_INVALID_DISPOSITION: NTSTATUS = 0xC0000026 as u32 as i32;
pub const STATUS_ARRAY_BOUNDS_EXCEEDED: NTSTATUS = 0xC000008C as u32 as i32;
pub const STATUS_FLOAT_DENORMAL_OPERAND: NTSTATUS = 0xC000008D as u32 as i32;
pub const STATUS_FLOAT_DIVIDE_BY_ZERO: NTSTATUS = 0xC000008E as u32 as i32;
pub const STATUS_FLOAT_INEXACT_RESULT: NTSTATUS = 0xC000008F as u32 as i32;
pub const STATUS_FLOAT_INVALID_OPERATION: NTSTATUS = 0xC0000090 as u32 as i32;
pub const STATUS_FLOAT_OVERFLOW: NTSTATUS = 0xC0000091 as u32 as i32;
pub const STATUS_FLOAT_STACK_CHECK: NTSTATUS = 0xC0000092 as u32 as i32;
pub const STATUS_FLOAT_UNDERFLOW: NTSTATUS = 0xC0000093 as u32 as i32;
pub const STATUS_INTEGER_DIVIDE_BY_ZERO: NTSTATUS = 0xC0000094 as u32 as i32;
pub const STATUS_INTEGER_OVERFLOW: NTSTATUS = 0xC0000095 as u32 as i32;
pub const STATUS_PRIVILEGED_INSTRUCTION: NTSTATUS = 0xC0000096 as u32 as i32;
pub const STATUS_INSUFFICIENT_RESOURCES: NTSTATUS = 0xC000009A as u32 as i32;
pub const STATUS_INVALID_USER_BUFFER: NTSTATUS = 0xC00000E8 as u32 as i32;
pub const STATUS_STACK_OVERFLOW: NTSTATUS = 0xC00000FD as u32 as i32;
================================================
FILE: windows-kernel-sys/src/intrin.rs
================================================
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
use crate::base::*;
#[link(name = "wrapper_intrin")]
extern "C" {
pub fn read_cr3() -> u64;
pub fn write_cr3(value: u64);
pub fn read_msr(register: u32) -> u64;
pub fn read_msr_safe(register: u32, value: &mut u64) -> NTSTATUS;
pub fn write_msr(register: u32, value: u64);
pub fn write_msr_safe(register: u32, value: u64) -> NTSTATUS;
pub fn invlpg(value: usize);
}
================================================
FILE: windows-kernel-sys/src/lib.rs
================================================
#![no_std]
pub mod base;
#[cfg(feature = "intrin")]
pub mod intrin;
#[cfg(feature = "netio")]
pub mod netio;
#[cfg(feature = "ntoskrnl")]
pub mod ntoskrnl;
pub use cty::*;
================================================
FILE: windows-kernel-sys/src/netio.rs
================================================
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
use crate::base::*;
include!(concat!(env!("OUT_DIR"), "/netio.rs"));
================================================
FILE: windows-kernel-sys/src/ntoskrnl.rs
================================================
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
use crate::base::*;
#[link(name = "wrapper_ntoskrnl")]
extern "C" {
pub fn _ExInitializeFastMutex(mutex: PFAST_MUTEX);
pub fn _ExAcquirePushLockExclusive(push_lock: PEX_PUSH_LOCK);
pub fn _ExReleasePushLockExclusive(push_lock: PEX_PUSH_LOCK);
pub fn _ExAcquirePushLockShared(push_lock: PEX_PUSH_LOCK);
pub fn _ExReleasePushLockShared(push_lock: PEX_PUSH_LOCK);
pub fn _IoGetCurrentIrpStackLocation(irp: PIRP) -> PIO_STACK_LOCATION;
pub fn _IoGetNextIrpStackLocation(irp: PIRP) -> PIO_STACK_LOCATION;
pub fn _IoSetCompletionRoutine(
irp: PIRP,
completion_routine: PIO_COMPLETION_ROUTINE,
context: PVOID,
invoke_on_success: BOOLEAN,
invoke_on_error: BOOLEAN,
invoke_on_cancel: BOOLEAN,
);
pub fn _IoCompleteRequest(irp: PIRP, priority_boost: CCHAR);
pub fn _MmGetMdlByteCount(mdl: PMDL) -> ULONG;
pub fn _MmGetMdlByteOffset(mdl: PMDL) -> ULONG;
pub fn _MmGetSystemAddressForMdlSafe(mdl: PMDL, priority: ULONG) -> PVOID;
pub fn _ObDereferenceObject(p: *mut cty::c_void);
pub fn _ObReferenceObject(p: *mut cty::c_void);
}
pub use self::_ExInitializeFastMutex as ExInitializeFastMutex;
pub use self::_ExAcquirePushLockExclusive as ExAcquirePushLockExclusive;
pub use self::_ExReleasePushLockExclusive as ExReleasePushLockExclusive;
pub use self::_ExAcquirePushLockShared as ExAcquirePushLockShared;
pub use self::_ExReleasePushLockShared as ExReleasePushLockShared;
pub use self::_IoGetCurrentIrpStackLocation as IoGetCurrentIrpStackLocation;
pub use self::_IoGetNextIrpStackLocation as IoGetNextIrpStackLocation;
pub use self::_IoSetCompletionRoutine as IoSetCompletionRoutine;
pub use self::_IoCompleteRequest as IoCompleteRequest;
pub use self::_MmGetMdlByteCount as MmGetMdlByteCount;
pub use self::_MmGetMdlByteOffset as MmGetMdlByteOffset;
pub use self::_MmGetSystemAddressForMdlSafe as MmGetSystemAddressForMdlSafe;
pub use self::_ObDereferenceObject as ObDereferenceObject;
pub use self::_ObReferenceObject as ObReferenceObject;
pub use self::IoGetCurrentProcess as PsGetCurrentProcess;
include!(concat!(env!("OUT_DIR"), "/ntoskrnl.rs"));
================================================
FILE: windows-kernel-sys/src/wrapper.c
================================================
#include "wrapper.h"
void _ExInitializeFastMutex(
PFAST_MUTEX fast_mutex
) {
ExInitializeFastMutex(fast_mutex);
}
void _ExAcquirePushLockExclusive(
PEX_PUSH_LOCK push_lock
) {
ExAcquirePushLockExclusive(push_lock);
}
void _ExReleasePushLockExclusive(
PEX_PUSH_LOCK push_lock
) {
ExReleasePushLockExclusive(push_lock);
}
void _ExAcquirePushLockShared(
PEX_PUSH_LOCK push_lock
) {
ExAcquirePushLockShared(push_lock);
}
void _ExReleasePushLockShared(
PEX_PUSH_LOCK push_lock
) {
ExReleasePushLockShared(push_lock);
}
PIO_STACK_LOCATION _IoGetCurrentIrpStackLocation(PIRP irp) {
return IoGetCurrentIrpStackLocation(irp);
}
PIO_STACK_LOCATION _IoGetNextIrpStackLocation(PIRP irp) {
return IoGetNextIrpStackLocation(irp);
}
void _IoSetCompletionRoutine(
PIRP irp,
PIO_COMPLETION_ROUTINE completion_routine,
PVOID context,
BOOLEAN invoke_on_success,
BOOLEAN invoke_on_error,
BOOLEAN invoke_on_cancel
) {
IoSetCompletionRoutine(irp, completion_routine, context, invoke_on_success, invoke_on_error, invoke_on_cancel);
}
void _IoCompleteRequest(
PIRP irp,
CCHAR priority_boost
) {
IoCompleteRequest(irp, priority_boost);
}
ULONG _MmGetMdlByteCount(PMDL mdl) {
return MmGetMdlByteCount(mdl);
}
ULONG _MmGetMdlByteOffset(PMDL mdl) {
return MmGetMdlByteOffset(mdl);
}
PVOID _MmGetSystemAddressForMdlSafe(PMDL mdl, ULONG priority) {
return MmGetSystemAddressForMdlSafe(mdl, priority);
}
void _ObDereferenceObject(PVOID p) {
ObDereferenceObject(p);
}
void _ObReferenceObject(PVOID p) {
ObReferenceObject(p);
}
================================================
FILE: windows-kernel-sys/src/wrapper.h
================================================
#define _AMD64_
#include "ntdef.h"
#include "ntstatus.h"
typedef ULONG_PTR _EX_PUSH_LOCK;
typedef ULONG_PTR EX_PUSH_LOCK;
typedef ULONG_PTR *PEX_PUSH_LOCK;
typedef union _KGDTENTRY64
{
struct
{
unsigned short LimitLow;
unsigned short BaseLow;
union
{
struct
{
unsigned char BaseMiddle;
unsigned char Flags1;
unsigned char Flags2;
unsigned char BaseHigh;
} Bytes;
struct
{
unsigned long BaseMiddle : 8;
unsigned long Type : 5;
unsigned long Dpl : 2;
unsigned long Present : 1;
unsigned long LimitHigh : 4;
unsigned long System : 1;
unsigned long LongMode : 1;
unsigned long DefaultBig : 1;
unsigned long Granularity : 1;
unsigned long BaseHigh : 8;
} Bits;
};
unsigned long BaseUpper;
unsigned long MustBeZero;
};
unsigned __int64 Alignment;
} KGDTENTRY64, *PKGDTENTRY64;
typedef union _KIDTENTRY64
{
struct
{
unsigned short OffsetLow;
unsigned short Selector;
unsigned short IstIndex : 3;
unsigned short Reserved0 : 5;
unsigned short Type : 5;
unsigned short Dpl : 2;
unsigned short Present : 1;
unsigned short OffsetMiddle;
unsigned long OffsetHigh;
unsigned long Reserved1;
};
unsigned __int64 Alignment;
} KIDTENTRY64, *PKIDTENTRY64;
#include "ntifs.h"
================================================
FILE: windows-kernel-sys/src/wrapper_intrin.c
================================================
#define _AMD64_
#include "wdm.h"
#include "intrin.h"
unsigned __int64 read_cr3(void) {
return __readcr3();
}
void write_cr3(unsigned __int64 Value) {
__writecr3(Value);
}
unsigned __int64 read_msr(
unsigned long Register
) {
return __readmsr(Register);
}
NTSTATUS read_msr_safe(
unsigned long Register,
unsigned __int64 *Value
) {
if (!Value) {
return STATUS_INVALID_PARAMETER;
}
__try {
*Value = __readmsr(Register);
} __except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
return STATUS_SUCCESS;
}
void write_msr(
unsigned long Register,
unsigned __int64 Value
) {
__writemsr(Register, Value);
}
NTSTATUS write_msr_safe(
unsigned long Register,
unsigned __int64 Value
) {
__try {
__writemsr(Register, Value);
} __except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
return STATUS_SUCCESS;
}
void invlpg(
void *Address
) {
__invlpg(Address);
}
================================================
FILE: windows-kernel-sys/src/wrapper_netio.h
================================================
#define _AMD64_
#include "ntdef.h"
#include "wdm.h"
#include "wsk.h"
================================================
FILE: winioctl/Cargo.toml
================================================
[package]
name = "winioctl"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bitflags = "1.3"
thiserror = "1.0"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["ioapiset", "winioctl"] }
================================================
FILE: winioctl/src/error.rs
================================================
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
IoError(#[from] std::io::Error),
}
================================================
FILE: winioctl/src/ioctl.rs
================================================
use bitflags::bitflags;
use winapi::um::winioctl::{
FILE_ANY_ACCESS,
METHOD_NEITHER, METHOD_IN_DIRECT, METHOD_OUT_DIRECT, METHOD_BUFFERED
};
use winapi::um::winnt::{
FILE_READ_DATA, FILE_WRITE_DATA,
};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DeviceType {
Port8042,
Acpi,
Battery,
Beep,
BusExtender,
Cdrom,
CdromFileSystem,
Changer,
Controller,
DataLink,
Dfs,
DfsFileSystem,
DfsVolume,
Disk,
DiskFileSystem,
Dvd,
FileSystem,
Fips,
FullscreenVideo,
InportPort,
Keyboard,
Ks,
Ksec,
Mailslot,
MassStorage,
MidiIn,
MidiOut,
Modem,
Mouse,
MultiUncProvider,
NamedPipe,
Network,
NetworkBrowser,
NetworkFileSystem,
NetworkRedirector,
Null,
ParallelPort,
PhysicalNetcard,
Printer,
Scanner,
Screen,
Serenum,
SerialPort,
SerialMousePort,
Smartcard,
Smb,
Sound,
Streams,
Tape,
TapeFileSystem,
Termsrv,
Transport,
Unknown,
Vdm,
Video,
VirtualDisk,
WaveIn,
WaveOut,
}
impl Into<u32> for DeviceType {
fn into(self) -> u32 {
match self {
DeviceType::Port8042 => winapi::um::winioctl::FILE_DEVICE_8042_PORT,
DeviceType::Acpi => winapi::um::winioctl::FILE_DEVICE_ACPI,
DeviceType::Battery => winapi::um::winioctl::FILE_DEVICE_BATTERY,
DeviceType::Beep => winapi::um::winioctl::FILE_DEVICE_BEEP,
DeviceType::BusExtender => winapi::um::winioctl::FILE_DEVICE_BUS_EXTENDER,
DeviceType::Cdrom => winapi::um::winioctl::FILE_DEVICE_CD_ROM,
DeviceType::CdromFileSystem => winapi::um::winioctl::FILE_DEVICE_CD_ROM_FILE_SYSTEM,
DeviceType::Changer => winapi::um::winioctl::FILE_DEVICE_CHANGER,
DeviceType::Controller => winapi::um::winioctl::FILE_DEVICE_CONTROLLER,
DeviceType::DataLink => winapi::um::winioctl::FILE_DEVICE_DATALINK,
DeviceType::Dfs => winapi::um::winioctl::FILE_DEVICE_DFS,
DeviceType::DfsFileSystem => winapi::um::winioctl::FILE_DEVICE_DFS_FILE_SYSTEM,
DeviceType::DfsVolume => winapi::um::winioctl::FILE_DEVICE_DFS_VOLUME,
DeviceType::Disk => winapi::um::winioctl::FILE_DEVICE_DISK,
DeviceType::DiskFileSystem => winapi::um::winioctl::FILE_DEVICE_DISK_FILE_SYSTEM,
DeviceType::Dvd => winapi::um::winioctl::FILE_DEVICE_DVD,
DeviceType::FileSystem => winapi::um::winioctl::FILE_DEVICE_FILE_SYSTEM,
DeviceType::Fips => winapi::um::winioctl::FILE_DEVICE_FIPS,
DeviceType::FullscreenVideo => winapi::um::winioctl::FILE_DEVICE_FULLSCREEN_VIDEO,
DeviceType::InportPort => winapi::um::winioctl::FILE_DEVICE_INPORT_PORT,
DeviceType::Keyboard => winapi::um::winioctl::FILE_DEVICE_KEYBOARD,
DeviceType::Ks => winapi::um::winioctl::FILE_DEVICE_KS,
DeviceType::Ksec => winapi::um::winioctl::FILE_DEVICE_KSEC,
DeviceType::Mailslot => winapi::um::winioctl::FILE_DEVICE_MAILSLOT,
DeviceType::MassStorage => winapi::um::winioctl::FILE_DEVICE_MASS_STORAGE,
DeviceType::MidiIn => winapi::um::winioctl::FILE_DEVICE_MIDI_IN,
DeviceType::MidiOut => winapi::um::winioctl::FILE_DEVICE_MIDI_OUT,
DeviceType::Modem => winapi::um::winioctl::FILE_DEVICE_MODEM,
DeviceType::Mouse => winapi::um::winioctl::FILE_DEVICE_MOUSE,
DeviceType::MultiUncProvider => winapi::um::winioctl::FILE_DEVICE_MULTI_UNC_PROVIDER,
DeviceType::NamedPipe => winapi::um::winioctl::FILE_DEVICE_NAMED_PIPE,
DeviceType::Network => winapi::um::winioctl::FILE_DEVICE_NETWORK,
DeviceType::NetworkBrowser => winapi::um::winioctl::FILE_DEVICE_NETWORK_BROWSER,
DeviceType::NetworkFileSystem => winapi::um::winioctl::FILE_DEVICE_NETWORK_FILE_SYSTEM,
DeviceType::NetworkRedirector => winapi::um::winioctl::FILE_DEVICE_NETWORK_REDIRECTOR,
DeviceType::Null => winapi::um::winioctl::FILE_DEVICE_NULL,
DeviceType::ParallelPort => winapi::um::winioctl::FILE_DEVICE_PARALLEL_PORT,
DeviceType::PhysicalNetcard => winapi::um::winioctl::FILE_DEVICE_PHYSICAL_NETCARD,
DeviceType::Printer => winapi::um::winioctl::FILE_DEVICE_PRINTER,
DeviceType::Scanner => winapi::um::winioctl::FILE_DEVICE_SCANNER,
DeviceType::Screen => winapi::um::winioctl::FILE_DEVICE_SCREEN,
DeviceType::Serenum => winapi::um::winioctl::FILE_DEVICE_SERENUM,
DeviceType::SerialMousePort => winapi::um::winioctl::FILE_DEVICE_SERIAL_MOUSE_PORT,
DeviceType::SerialPort => winapi::um::winioctl::FILE_DEVICE_SERIAL_PORT,
DeviceType::Smartcard => winapi::um::winioctl::FILE_DEVICE_SMARTCARD,
DeviceType::Smb => winapi::um::winioctl::FILE_DEVICE_SMB,
DeviceType::Sound => winapi::um::winioctl::FILE_DEVICE_SOUND,
DeviceType::Streams => winapi::um::winioctl::FILE_DEVICE_STREAMS,
DeviceType::Tape => winapi::um::winioctl::FILE_DEVICE_TAPE,
DeviceType::TapeFileSystem => winapi::um::winioctl::FILE_DEVICE_TAPE_FILE_SYSTEM,
DeviceType::Termsrv => winapi::um::winioctl::FILE_DEVICE_TERMSRV,
DeviceType::Transport => winapi::um::winioctl::FILE_DEVICE_TRANSPORT,
DeviceType::Unknown => winapi::um::winioctl::FILE_DEVICE_UNKNOWN,
DeviceType::Vdm => winapi::um::winioctl::FILE_DEVICE_VDM,
DeviceType::Video => winapi::um::winioctl::FILE_DEVICE_VIDEO,
DeviceType::VirtualDisk => winapi::um::winioctl::FILE_DEVICE_VIRTUAL_DISK,
DeviceType::WaveIn => winapi::um::winioctl::FILE_DEVICE_WAVE_IN,
DeviceType::WaveOut => winapi::um::winioctl::FILE_DEVICE_WAVE_OUT,
}
}
}
impl From<u32> for DeviceType {
fn from(value: u32) -> Self {
match value {
winapi::um::winioctl::FILE_DEVICE_8042_PORT => DeviceType::Port8042,
winapi::um::winioctl::FILE_DEVICE_ACPI => DeviceType::Acpi,
winapi::um::winioctl::FILE_DEVICE_BATTERY => DeviceType::Battery,
winapi::um::winioctl::FILE_DEVICE_BEEP => DeviceType::Beep,
winapi::um::winioctl::FILE_DEVICE_BUS_EXTENDER => DeviceType::BusExtender,
winapi::um::winioctl::FILE_DEVICE_CD_ROM => DeviceType::Cdrom,
winapi::um::winioctl::FILE_DEVICE_CD_ROM_FILE_SYSTEM => DeviceType::CdromFileSystem,
winapi::um::winioctl::FILE_DEVICE_CHANGER => DeviceType::Changer,
winapi::um::winioctl::FILE_DEVICE_CONTROLLER => DeviceType::Controller,
winapi::um::winioctl::FILE_DEVICE_DATALINK => DeviceType::DataLink,
winapi::um::winioctl::FILE_DEVICE_DFS => DeviceType::Dfs,
winapi::um::winioctl::FILE_DEVICE_DFS_FILE_SYSTEM => DeviceType::DfsFileSystem,
winapi::um::winioctl::FILE_DEVICE_DFS_VOLUME => DeviceType::DfsVolume,
winapi::um::winioctl::FILE_DEVICE_DISK => DeviceType::Disk,
winapi::um::winioctl::FILE_DEVICE_DISK_FILE_SYSTEM => DeviceType::DiskFileSystem,
winapi::um::winioctl::FILE_DEVICE_DVD => DeviceType::Dvd,
winapi::um::winioctl::FILE_DEVICE_FILE_SYSTEM => DeviceType::FileSystem,
winapi::um::winioctl::FILE_DEVICE_FIPS => DeviceType::Fips,
winapi::um::winioctl::FILE_DEVICE_FULLSCREEN_VIDEO => DeviceType::FullscreenVideo,
winapi::um::winioctl::FILE_DEVICE_INPORT_PORT => DeviceType::InportPort,
winapi::um::winioctl::FILE_DEVICE_KEYBOARD => DeviceType::Keyboard,
winapi::um::winioctl::FILE_DEVICE_KS => DeviceType::Ks,
winapi::um::winioctl::FILE_DEVICE_KSEC => DeviceType::Ksec,
winapi::um::winioctl::FILE_DEVICE_MAILSLOT => DeviceType::Mailslot,
winapi::um::winioctl::FILE_DEVICE_MASS_STORAGE => DeviceType::MassStorage,
winapi::um::winioctl::FILE_DEVICE_MIDI_IN => DeviceType::MidiIn,
winapi::um::winioctl::FILE_DEVICE_MIDI_OUT => DeviceType::MidiOut,
winapi::um::winioctl::FILE_DEVICE_MODEM => DeviceType::Modem,
winapi::um::winioctl::FILE_DEVICE_MOUSE => DeviceType::Mouse,
winapi::um::winioctl::FILE_DEVICE_MULTI_UNC_PROVIDER => DeviceType::MultiUncProvider,
winapi::um::winioctl::FILE_DEVICE_NAMED_PIPE => DeviceType::NamedPipe,
winapi::um::winioctl::FILE_DEVICE_NETWORK => DeviceType::Network,
winapi::um::winioctl::FILE_DEVICE_NETWORK_BROWSER => DeviceType::NetworkBrowser,
winapi::um::winioctl::FILE_DEVICE_NETWORK_FILE_SYSTEM => DeviceType::NetworkFileSystem,
winapi::um::winioctl::FILE_DEVICE_NETWORK_REDIRECTOR => DeviceType::NetworkRedirector,
winapi::um::winioctl::FILE_DEVICE_NULL => DeviceType::Null,
winapi::um::winioctl::FILE_DEVICE_PARALLEL_PORT => DeviceType::ParallelPort,
winapi::um::winioctl::FILE_DEVICE_PHYSICAL_NETCARD => DeviceType::PhysicalNetcard,
winapi::um::winioctl::FILE_DEVICE_PRINTER => DeviceType::Printer,
winapi::um::winioctl::FILE_DEVICE_SCANNER => DeviceType::Scanner,
winapi::um::winioctl::FILE_DEVICE_SCREEN => DeviceType::Screen,
winapi::um::winioctl::FILE_DEVICE_SERENUM => DeviceType::Serenum,
winapi::um::winioctl::FILE_DEVICE_SERIAL_MOUSE_PORT => DeviceType::SerialMousePort,
winapi::um::winioctl::FILE_DEVICE_SERIAL_PORT => DeviceType::SerialPort,
winapi::um::winioctl::FILE_DEVICE_SMARTCARD => DeviceType::Smartcard,
winapi::um::winioctl::FILE_DEVICE_SMB => DeviceType::Smb,
winapi::um::winioctl::FILE_DEVICE_SOUND => DeviceType::Sound,
winapi::um::winioctl::FILE_DEVICE_STREAMS => DeviceType::Streams,
winapi::um::winioctl::FILE_DEVICE_TAPE => DeviceType::Tape,
winapi::um::winioctl::FILE_DEVICE_TAPE_FILE_SYSTEM => DeviceType::TapeFileSystem,
winapi::um::winioctl::FILE_DEVICE_TERMSRV => DeviceType::Termsrv,
winapi::um::winioctl::FILE_DEVICE_TRANSPORT => DeviceType::Transport,
winapi::um::winioctl::FILE_DEVICE_UNKNOWN => DeviceType::Unknown,
winapi::um::winioctl::FILE_DEVICE_VDM => DeviceType::Vdm,
winapi::um::winioctl::FILE_DEVICE_VIDEO => DeviceType::Video,
winapi::um::winioctl::FILE_DEVICE_VIRTUAL_DISK => DeviceType::VirtualDisk,
winapi::um::winioctl::FILE_DEVICE_WAVE_IN => DeviceType::WaveIn,
winapi::um::winioctl::FILE_DEVICE_WAVE_OUT => DeviceType::WaveOut,
_ => DeviceType::Unknown,
}
}
}
bitflags! {
pub struct RequiredAccess: u32 {
const ANY_ACCESS = FILE_ANY_ACCESS;
const READ_DATA = FILE_READ_DATA;
const WRITE_DATA = FILE_WRITE_DATA;
const READ_WRITE_DATA = FILE_READ_DATA | FILE_WRITE_DATA;
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum TransferMethod {
Neither = METHOD_NEITHER,
InputDirect = METHOD_IN_DIRECT,
OutputDirect = METHOD_OUT_DIRECT,
Buffered = METHOD_BUFFERED,
}
impl From<u32> for TransferMethod {
fn from(value: u32) -> Self {
match value & 0x3 {
METHOD_NEITHER => Self::Neither,
METHOD_IN_DIRECT => Self::InputDirect,
METHOD_OUT_DIRECT => Self::OutputDirect,
METHOD_BUFFERED => Self::Buffered,
_ => unreachable!(),
}
}
}
impl Into<u32> for TransferMethod {
fn into(self) -> u32 {
match self {
Self::Neither => METHOD_NEITHER,
Self::InputDirect => METHOD_IN_DIRECT,
Self::OutputDirect => METHOD_OUT_DIRECT,
Self::Buffered => METHOD_BUFFERED,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ControlCode(pub DeviceType, pub RequiredAccess, pub u32, pub TransferMethod);
impl ControlCode {
const METHOD_BITS: usize = 2;
const NUM_BITS: usize = 12;
const ACCESS_BITS: usize = 2;
const TYPE_BITS: usize = 16;
const METHOD_SHIFT: usize = 0;
const NUM_SHIFT: usize = Self::METHOD_SHIFT + Self::METHOD_BITS;
const ACCESS_SHIFT: usize = Self::NUM_SHIFT + Self::NUM_BITS;
const TYPE_SHIFT: usize = Self::ACCESS_SHIFT + Self::ACCESS_BITS;
const METHOD_MASK: u32 = (1 << Self::METHOD_BITS) - 1;
const NUM_MASK: u32 = (1 << Self::NUM_BITS) - 1;
const ACCESS_MASK: u32 = (1 << Self::ACCESS_BITS) - 1;
const TYPE_MASK: u32 = (1 << Self::TYPE_BITS) - 1;
}
impl From<u32> for ControlCode {
fn from(value: u32) -> Self {
let method = (value >> Self::METHOD_SHIFT) & Self::METHOD_MASK;
let num = (value >> Self::NUM_SHIFT) & Self::NUM_MASK;
let access = (value >> Self::ACCESS_SHIFT) & Self::ACCESS_MASK;
let ty = (value >> Self::TYPE_SHIFT) & Self::TYPE_MASK;
Self(
ty.into(),
RequiredAccess::from_bits(access).unwrap_or(RequiredAccess::READ_DATA),
num,
method.into()
)
}
}
impl Into<u32> for ControlCode {
fn into(self) -> u32 {
let method = Into::<u32>::into(self.3) << Self::METHOD_SHIFT;
let num = self.2 << Self::NUM_SHIFT;
let access = self.1.bits() << Self::ACCESS_SHIFT;
let ty = Into::<u32>::into(self.0) << Self::TYPE_SHIFT;
ty | access | num | method
}
}
#[macro_export]
macro_rules! ioctl_none {
($(#[$attr:meta])* $name:ident, $dev_ty:expr, $nr:expr) => {
$(#[$attr])*
pub unsafe fn $name(handle: *mut std::ffi::c_void) -> Result<u32, $crate::Error> {
let code = $crate::ControlCode(
$dev_ty,
$crate::RequiredAccess::ANY_ACCESS,
$nr,
$crate::TransferMethod::Neither,
).into();
let mut return_value = 0;
let status = $crate::DeviceIoControl(
handle as _,
code,
std::ptr::null_mut(),
0,
std::ptr::null_mut(),
0,
&mut return_value,
std::ptr::null_mut(),
) != 0;
match status {
true => Ok(return_value),
_ => Err(std::io::Error::last_os_error())?,
}
}
}
}
#[macro_export]
macro_rules! ioctl_read {
($(#[$attr:meta])* $name:ident, $dev_ty:expr, $nr:expr, $ty:ty) => {
$(#[$attr])*
pub unsafe fn $name(handle: *mut std::ffi::c_void, data: *mut $ty) -> Result<u32, $crate::Error> {
let code = $crate::ControlCode(
$dev_ty,
$crate::RequiredAccess::READ_DATA,
$nr,
$crate::TransferMethod::Buffered,
).into();
let mut return_value = 0;
let status = $crate::DeviceIoControl(
handle as _,
code,
data as _,
std::mem::size_of::<$ty>() as _,
data as _,
std::mem::size_of::<$ty>() as _,
&mut return_value,
std::ptr::null_mut(),
) != 0;
match status {
true => Ok(return_value),
_ => Err(std::io::Error::last_os_error())?,
}
}
}
}
#[macro_export]
macro_rules! ioctl_write {
($(#[$attr:meta])* $name:ident, $dev_ty:expr, $nr:expr, $ty:ty) => {
$(#[$attr])*
pub unsafe fn $name(handle: *mut std::ffi::c_void, data: *const $ty) -> Result<u32, $crate::Error> {
let code = $crate::ControlCode(
$dev_ty,
$crate::RequiredAccess::WRITE_DATA,
$nr,
$crate::TransferMethod::Buffered,
).into();
let mut return_value = 0;
let status = $crate::DeviceIoControl(
handle as _,
code,
data as _,
std::mem::size_of::<$ty>() as _,
std::ptr::null_mut(),
0,
&mut return_value,
std::ptr::null_mut(),
) != 0;
match status {
true => Ok(return_value),
_ => Err(std::io::Error::last_os_error())?,
}
}
}
}
#[macro_export]
macro_rules! ioctl_readwrite {
($(#[$attr:meta])* $name:ident, $dev_ty:expr, $nr:expr, $ty:ty) => {
$(#[$attr])*
pub unsafe fn $name(handle: *mut std::ffi::c_void, data: *mut $ty) -> Result<u32, $crate::Error> {
let code = $crate::ControlCode(
$dev_ty,
$crate::RequiredAccess::READ_WRITE_DATA,
$nr,
$crate::TransferMethod::Buffered,
).into();
let mut return_value = 0;
let status = $crate::DeviceIoControl(
handle as _,
code,
data as _,
std::mem::size_of::<$ty>() as _,
data as _,
std::mem::size_of::<$ty>() as _,
&mut return_value,
std::ptr::null_mut(),
) != 0;
match status {
true => Ok(return_value),
_ => Err(std::io::Error::last_os_error())?,
}
}
}
}
================================================
FILE: winioctl/src/lib.rs
================================================
mod error;
mod ioctl;
pub use crate::error::Error;
pub use crate::ioctl::{ControlCode, DeviceType, RequiredAccess, TransferMethod};
pub use winapi::um::ioapiset::DeviceIoControl;
gitextract_enzorjhr/
├── .gitignore
├── 02-hello-world/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 03-generating-bindings/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 04-safe-framework/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 05-creating-devices/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 06-reading-and-writing/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── 07-io-controls/
│ ├── Cargo.toml
│ ├── Makefile.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ └── lib.rs
├── LICENSE
├── README.md
├── user/
│ ├── 05-creating-devices/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── 06-reading-and-writing/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ └── 07-io-controls/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── windows-kernel-build/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── windows-kernel-rs/
│ ├── Cargo.toml
│ ├── rust-toolchain
│ └── src/
│ ├── affinity.rs
│ ├── allocator.rs
│ ├── device.rs
│ ├── driver.rs
│ ├── error.rs
│ ├── intrin.rs
│ ├── io.rs
│ ├── ioctl.rs
│ ├── lib.rs
│ ├── mdl.rs
│ ├── memory.rs
│ ├── process.rs
│ ├── request.rs
│ ├── section.rs
│ ├── string.rs
│ ├── symbolic_link.rs
│ ├── sync/
│ │ ├── fast_mutex.rs
│ │ ├── mod.rs
│ │ └── push_lock.rs
│ ├── user_ptr.rs
│ └── version.rs
├── windows-kernel-sys/
│ ├── Cargo.toml
│ ├── build.rs
│ ├── rust-toolchain
│ └── src/
│ ├── base.rs
│ ├── intrin.rs
│ ├── lib.rs
│ ├── netio.rs
│ ├── ntoskrnl.rs
│ ├── wrapper.c
│ ├── wrapper.h
│ ├── wrapper_intrin.c
│ └── wrapper_netio.h
└── winioctl/
├── Cargo.toml
└── src/
├── error.rs
├── ioctl.rs
└── lib.rs
SYMBOL INDEX (395 symbols across 45 files)
FILE: 02-hello-world/build.rs
function main (line 1) | fn main() {
FILE: 02-hello-world/src/lib.rs
function panic (line 9) | fn panic(_info: &PanicInfo) -> ! {
function driver_entry (line 14) | pub extern "system" fn driver_entry(driver: &mut DRIVER_OBJECT, _: &UNIC...
function driver_exit (line 24) | pub extern "system" fn driver_exit(_driver: &mut DRIVER_OBJECT) {
FILE: 03-generating-bindings/build.rs
function main (line 1) | fn main() {
FILE: 03-generating-bindings/src/lib.rs
function panic (line 8) | fn panic(_info: &PanicInfo) -> ! {
function driver_entry (line 13) | pub extern "system" fn driver_entry(driver: &mut DRIVER_OBJECT, _: &UNIC...
function driver_exit (line 23) | pub unsafe extern "C" fn driver_exit(_driver: *mut DRIVER_OBJECT) {
FILE: 04-safe-framework/build.rs
function main (line 1) | fn main() {
FILE: 04-safe-framework/src/lib.rs
type Module (line 5) | struct Module;
method init (line 8) | fn init(_: Driver, _: &str) -> Result<Self, Error> {
method cleanup (line 14) | fn cleanup(&mut self, _: Driver) {
FILE: 05-creating-devices/build.rs
function main (line 1) | fn main() {
FILE: 05-creating-devices/src/lib.rs
type MyDevice (line 9) | struct MyDevice;
method create (line 12) | fn create(&mut self, _device: &Device, request: IoRequest) -> Result<Com...
method close (line 18) | fn close(&mut self, _device: &Device, request: IoRequest) -> Result<Comp...
method cleanup (line 24) | fn cleanup(&mut self, _device: &Device, request: IoRequest) -> Result<Co...
type Module (line 31) | struct Module {
method init (line 37) | fn init(mut driver: Driver, _: &str) -> Result<Self, Error> {
method cleanup (line 54) | fn cleanup(&mut self, _driver: Driver) {
FILE: 06-reading-and-writing/build.rs
function main (line 1) | fn main() {
FILE: 06-reading-and-writing/src/lib.rs
type MyDevice (line 12) | struct MyDevice {
method read (line 17) | fn read(&mut self, _device: &Device, request: ReadRequest) -> Result<Com...
method write (line 29) | fn write(&mut self, _device: &Device, request: WriteRequest) -> Result<C...
type Module (line 45) | struct Module {
method init (line 51) | fn init(mut driver: Driver, _: &str) -> Result<Self, Error> {
FILE: 07-io-controls/build.rs
function main (line 1) | fn main() {
FILE: 07-io-controls/src/lib.rs
type MyDevice (line 9) | struct MyDevice {
method print_value (line 18) | fn print_value(&mut self, _request: &IoControlRequest) -> Result<u32, ...
method read_value (line 24) | fn read_value(&mut self, request: &IoControlRequest) -> Result<u32, Er...
method write_value (line 32) | fn write_value(&mut self, request: &IoControlRequest) -> Result<u32, E...
constant IOCTL_PRINT_VALUE (line 13) | const IOCTL_PRINT_VALUE: u32 = 0x800;
constant IOCTL_READ_VALUE (line 14) | const IOCTL_READ_VALUE: u32 = 0x801;
constant IOCTL_WRITE_VALUE (line 15) | const IOCTL_WRITE_VALUE: u32 = 0x802;
method ioctl (line 42) | fn ioctl(&mut self, _device: &Device, request: IoControlRequest) -> Resu...
type Module (line 60) | struct Module {
method init (line 66) | fn init(mut driver: Driver, _: &str) -> Result<Self, Error> {
method cleanup (line 85) | fn cleanup(&mut self, _driver: Driver) {
FILE: user/05-creating-devices/src/main.rs
function main (line 3) | fn main() -> Result<(), std::io::Error> {
FILE: user/06-reading-and-writing/src/main.rs
function main (line 4) | fn main() -> Result<(), std::io::Error> {
FILE: user/07-io-controls/src/main.rs
constant IOCTL_PRINT_VALUE (line 6) | const IOCTL_PRINT_VALUE: u32 = 0x800;
constant IOCTL_READ_VALUE (line 7) | const IOCTL_READ_VALUE: u32 = 0x801;
constant IOCTL_WRITE_VALUE (line 8) | const IOCTL_WRITE_VALUE: u32 = 0x802;
function main (line 14) | fn main() -> Result<(), Error> {
FILE: windows-kernel-build/src/lib.rs
type Error (line 7) | pub enum Error {
type DirectoryType (line 14) | pub enum DirectoryType {
function get_windows_kits_dir (line 21) | pub fn get_windows_kits_dir() -> Result<PathBuf, Error> {
function get_km_dir (line 31) | pub fn get_km_dir(dir_type: DirectoryType) -> Result<PathBuf, Error> {
function build (line 59) | pub fn build() -> Result<(), Error> {
FILE: windows-kernel-rs/src/affinity.rs
function get_current_cpu_num (line 14) | pub fn get_current_cpu_num() -> u32 {
function get_cpu_count (line 23) | pub fn get_cpu_count() -> u32 {
function broadcast_callback (line 30) | unsafe extern "C" fn broadcast_callback<F>(
function run_on_each_cpu (line 48) | pub fn run_on_each_cpu<F>(
function run_on_each_cpu_parallel (line 66) | pub fn run_on_each_cpu_parallel<F>(
function run_on_cpu (line 80) | pub fn run_on_cpu<F>(
FILE: windows-kernel-rs/src/allocator.rs
function alloc_error (line 14) | fn alloc_error(_: Layout) -> ! {
type KernelAllocator (line 29) | pub struct KernelAllocator {
method new (line 38) | pub const fn new(tag: u32) -> Self {
method alloc (line 48) | unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
method dealloc (line 75) | unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
FILE: windows-kernel-rs/src/device.rs
type Access (line 13) | pub enum Access {
method is_exclusive (line 19) | pub fn is_exclusive(&self) -> bool {
type DeviceType (line 41) | pub enum DeviceType {
method into (line 103) | fn into(self) -> u32 {
method from (line 174) | fn from(value: u32) -> Self {
type device_operations (line 246) | pub struct device_operations {
type Device (line 251) | pub struct Device {
method from_raw (line 259) | pub unsafe fn from_raw(raw: *mut DEVICE_OBJECT) -> Self {
method as_raw (line 263) | pub unsafe fn as_raw(&self) -> *const DEVICE_OBJECT {
method as_raw_mut (line 267) | pub unsafe fn as_raw_mut(&self) -> *mut DEVICE_OBJECT {
method into_raw (line 271) | pub fn into_raw(mut self) -> *mut DEVICE_OBJECT {
method extension (line 275) | pub(crate) fn extension(&self) -> &DeviceExtension {
method extension_mut (line 279) | pub(crate) fn extension_mut(&self) -> &mut DeviceExtension {
method device_type (line 283) | pub(crate) fn device_type(&self) -> DeviceType {
method vtable (line 287) | pub(crate) fn vtable(&self) -> &device_operations {
method data (line 291) | pub fn data<T: DeviceOperations>(&self) -> &T {
method data_mut (line 295) | pub fn data_mut<T: DeviceOperations>(&self) -> &mut T {
method drop (line 301) | fn drop(&mut self) {
type RequestError (line 316) | pub struct RequestError(pub Error, pub IoRequest);
type Completion (line 318) | pub enum Completion {
type DeviceOperations (line 322) | pub trait DeviceOperations: Sync + Sized {
method create (line 323) | fn create(&mut self, _device: &Device, request: IoRequest) -> Result<C...
method close (line 327) | fn close(&mut self, _device: &Device, request: IoRequest) -> Result<Co...
method cleanup (line 331) | fn cleanup(
method read (line 339) | fn read(&mut self, _device: &Device, request: ReadRequest) -> Result<C...
method write (line 343) | fn write(
method ioctl (line 351) | fn ioctl(
function dispatch_callback (line 360) | extern "C" fn dispatch_callback<T: DeviceOperations>(
function release_callback (line 413) | extern "C" fn release_callback<T: DeviceOperations>(device: *mut DEVICE_...
type DeviceOperationsVtable (line 422) | pub(crate) struct DeviceOperationsVtable<T>(core::marker::PhantomData<T>);
constant VTABLE (line 425) | pub(crate) const VTABLE: device_operations = device_operations {
type DeviceExtension (line 432) | pub struct DeviceExtension {
function dispatch_device (line 438) | pub extern "C" fn dispatch_device(device: *mut DEVICE_OBJECT, irp: *mut ...
FILE: windows-kernel-rs/src/driver.rs
type Driver (line 9) | pub struct Driver {
method from_raw (line 14) | pub unsafe fn from_raw(raw: *mut DRIVER_OBJECT) -> Self {
method as_raw (line 20) | pub unsafe fn as_raw(&self) -> *const DRIVER_OBJECT {
method as_raw_mut (line 24) | pub unsafe fn as_raw_mut(&mut self) -> *mut DRIVER_OBJECT {
method create_device (line 28) | pub fn create_device<T>(
FILE: windows-kernel-rs/src/error.rs
type Error (line 37) | pub struct Error(NTSTATUS);
constant GUARD_PAGE_VIOLATION (line 40) | pub const GUARD_PAGE_VIOLATION: Error = Error(STATUS_GUARD_PAGE_VI...
constant DATATYPE_MISALIGNMENT (line 41) | pub const DATATYPE_MISALIGNMENT: Error = Error(STATUS_DATATYPE_MISA...
constant BREAKPOINT (line 42) | pub const BREAKPOINT: Error = Error(STATUS_BREAKPOINT);
constant SINGLE_STEP (line 43) | pub const SINGLE_STEP: Error = Error(STATUS_SINGLE_STEP);
constant UNWIND_CONSOLIDATE (line 44) | pub const UNWIND_CONSOLIDATE: Error = Error(STATUS_UNWIND_CONSOL...
constant UNSUCCESSFUL (line 45) | pub const UNSUCCESSFUL: Error = Error(STATUS_UNSUCCESSFUL);
constant NOT_IMPLEMENTED (line 46) | pub const NOT_IMPLEMENTED: Error = Error(STATUS_NOT_IMPLEMENT...
constant ACCESS_VIOLATION (line 47) | pub const ACCESS_VIOLATION: Error = Error(STATUS_ACCESS_VIOLAT...
constant IN_PAGE_ERROR (line 48) | pub const IN_PAGE_ERROR: Error = Error(STATUS_IN_PAGE_ERROR);
constant INVALID_HANDLE (line 49) | pub const INVALID_HANDLE: Error = Error(STATUS_INVALID_HANDLE);
constant INVALID_PARAMETER (line 50) | pub const INVALID_PARAMETER: Error = Error(STATUS_INVALID_PARAM...
constant END_OF_FILE (line 51) | pub const END_OF_FILE: Error = Error(STATUS_END_OF_FILE);
constant NO_MEMORY (line 52) | pub const NO_MEMORY: Error = Error(STATUS_NO_MEMORY);
constant ILLEGAL_INSTRUCTION (line 53) | pub const ILLEGAL_INSTRUCTION: Error = Error(STATUS_ILLEGAL_INSTR...
constant NONCONTINUABLE_EXCEPTION (line 54) | pub const NONCONTINUABLE_EXCEPTION: Error = Error(STATUS_NONCONTINUABL...
constant INVALID_DISPOSITION (line 55) | pub const INVALID_DISPOSITION: Error = Error(STATUS_INVALID_DISPO...
constant ARRAY_BOUNDS_EXCEEDED (line 56) | pub const ARRAY_BOUNDS_EXCEEDED: Error = Error(STATUS_ARRAY_BOUNDS_...
constant FLOAT_DENORMAL_OPERAND (line 57) | pub const FLOAT_DENORMAL_OPERAND: Error = Error(STATUS_FLOAT_DENORMA...
constant FLOAT_DIVIDE_BY_ZERO (line 58) | pub const FLOAT_DIVIDE_BY_ZERO: Error = Error(STATUS_FLOAT_DIVIDE_...
constant FLOAT_INEXACT_RESULT (line 59) | pub const FLOAT_INEXACT_RESULT: Error = Error(STATUS_FLOAT_INEXACT...
constant FLOAT_INVALID_OPERATION (line 60) | pub const FLOAT_INVALID_OPERATION: Error = Error(STATUS_FLOAT_INVALID...
constant FLOAT_OVERFLOW (line 61) | pub const FLOAT_OVERFLOW: Error = Error(STATUS_FLOAT_OVERFLOW);
constant FLOAT_STACK_CHECK (line 62) | pub const FLOAT_STACK_CHECK: Error = Error(STATUS_FLOAT_STACK_C...
constant FLOAT_UNDERFLOW (line 63) | pub const FLOAT_UNDERFLOW: Error = Error(STATUS_FLOAT_UNDERFL...
constant INTEGER_DIVIDE_BY_ZERO (line 64) | pub const INTEGER_DIVIDE_BY_ZERO: Error = Error(STATUS_INTEGER_DIVID...
constant INTEGER_OVERFLOW (line 65) | pub const INTEGER_OVERFLOW: Error = Error(STATUS_INTEGER_OVERF...
constant PRIVILEGED_INSTRUCTION (line 66) | pub const PRIVILEGED_INSTRUCTION: Error = Error(STATUS_PRIVILEGED_IN...
constant INSUFFICIENT_RESOURCES (line 67) | pub const INSUFFICIENT_RESOURCES: Error = Error(STATUS_INSUFFICIENT_...
constant INVALID_USER_BUFFER (line 68) | pub const INVALID_USER_BUFFER: Error = Error(STATUS_INVALID_USER_...
constant STACK_OVERFLOW (line 69) | pub const STACK_OVERFLOW: Error = Error(STATUS_STACK_OVERFLOW);
method from_ntstatus (line 71) | pub fn from_ntstatus(status: NTSTATUS) -> Error {
method to_ntstatus (line 75) | pub fn to_ntstatus(&self) -> NTSTATUS {
type IntoResult (line 80) | pub trait IntoResult {
method into_result (line 81) | fn into_result(self) -> Result<(), Error>;
method into_result (line 85) | fn into_result(self) -> Result<(), Error> {
FILE: windows-kernel-rs/src/intrin.rs
function read_msr (line 8) | pub fn read_msr(register: u32) -> Result<u64, Error> {
function write_msr (line 22) | pub fn write_msr(register: u32, value: u64) -> Result<(), Error> {
FILE: windows-kernel-rs/src/io.rs
function _print (line 16) | pub fn _print(args: core::fmt::Arguments) {
FILE: windows-kernel-rs/src/ioctl.rs
type TransferMethod (line 20) | pub enum TransferMethod {
method from (line 28) | fn from(value: u32) -> Self {
method into (line 40) | fn into(self) -> u32 {
type ControlCode (line 51) | pub struct ControlCode(
constant METHOD_BITS (line 59) | const METHOD_BITS: usize = 2;
constant NUM_BITS (line 60) | const NUM_BITS: usize = 12;
constant ACCESS_BITS (line 61) | const ACCESS_BITS: usize = 2;
constant TYPE_BITS (line 62) | const TYPE_BITS: usize = 16;
constant METHOD_SHIFT (line 64) | const METHOD_SHIFT: usize = 0;
constant NUM_SHIFT (line 65) | const NUM_SHIFT: usize = Self::METHOD_SHIFT + Self::METHOD_BITS;
constant ACCESS_SHIFT (line 66) | const ACCESS_SHIFT: usize = Self::NUM_SHIFT + Self::NUM_BITS;
constant TYPE_SHIFT (line 67) | const TYPE_SHIFT: usize = Self::ACCESS_SHIFT + Self::ACCESS_BITS;
constant METHOD_MASK (line 69) | const METHOD_MASK: u32 = (1 << Self::METHOD_BITS) - 1;
constant NUM_MASK (line 70) | const NUM_MASK: u32 = (1 << Self::NUM_BITS) - 1;
constant ACCESS_MASK (line 71) | const ACCESS_MASK: u32 = (1 << Self::ACCESS_BITS) - 1;
constant TYPE_MASK (line 72) | const TYPE_MASK: u32 = (1 << Self::TYPE_BITS) - 1;
method device_type (line 74) | pub fn device_type(&self) -> DeviceType {
method required_access (line 78) | pub fn required_access(&self) -> RequiredAccess {
method number (line 82) | pub fn number(&self) -> u32 {
method transfer_method (line 86) | pub fn transfer_method(&self) -> TransferMethod {
method from (line 92) | fn from(value: u32) -> Self {
method into (line 108) | fn into(self) -> u32 {
FILE: windows-kernel-rs/src/lib.rs
function panic (line 45) | fn panic(_info: &core::panic::PanicInfo) -> ! {
function __CxxFrameHandler3 (line 54) | pub extern "system" fn __CxxFrameHandler3() -> i32 {
type KernelModule (line 114) | pub trait KernelModule: Sized + Sync {
method init (line 115) | fn init(driver: Driver, registry_path: &str) -> Result<Self, Error>;
method cleanup (line 116) | fn cleanup(&mut self, _driver: Driver) {
FILE: windows-kernel-rs/src/mdl.rs
type AccessMode (line 6) | pub enum AccessMode {
type MemoryDescriptorList (line 11) | pub struct MemoryDescriptorList {
method new (line 19) | pub fn new(
method build_for_non_paged_pool (line 38) | pub fn build_for_non_paged_pool(
method map_locked_pages (line 48) | pub fn map_locked_pages(
method drop (line 75) | fn drop(&mut self) {
type LockedMapping (line 84) | pub struct LockedMapping {
method ptr (line 93) | pub fn ptr(&self) -> *mut core::ffi::c_void {
method unlock (line 97) | pub fn unlock(self) -> MemoryDescriptorList {
method drop (line 111) | fn drop(&mut self) {
FILE: windows-kernel-rs/src/memory.rs
type MemoryCaching (line 7) | pub enum MemoryCaching {
type PhysicalAddress (line 21) | pub struct PhysicalAddress(u64);
method from (line 24) | fn from(value: u64) -> Self {
method into (line 30) | fn into(self) -> u64 {
method from (line 36) | fn from(value: PHYSICAL_ADDRESS) -> Self {
method into (line 42) | fn into(self) -> PHYSICAL_ADDRESS {
type CopyAddress (line 52) | pub enum CopyAddress {
method into (line 61) | fn into(self) -> (u32, MM_COPY_ADDRESS) {
type IoMapping (line 81) | pub struct IoMapping {
method new (line 90) | pub fn new(addr: PhysicalAddress, size: usize, caching: MemoryCaching)...
method ptr (line 107) | pub fn ptr(&self) -> *mut core::ffi::c_void {
method size (line 111) | pub fn size(&self) -> usize {
method drop (line 117) | fn drop(&mut self) {
function get_virtual_for_physical (line 127) | pub fn get_virtual_for_physical(addr: PhysicalAddress) -> *mut core::ffi...
function read_memory (line 135) | pub fn read_memory(
function write_memory (line 158) | pub fn write_memory(
FILE: windows-kernel-rs/src/process.rs
type ProcessId (line 9) | pub type ProcessId = usize;
type Process (line 12) | pub struct Process {
method as_ptr (line 17) | pub fn as_ptr(&self) -> PEPROCESS {
method current (line 21) | pub fn current() -> Self {
method by_id (line 35) | pub fn by_id(process_id: ProcessId) -> Result<Self, Error> {
method id (line 47) | pub fn id(&self) -> ProcessId {
method attach (line 55) | pub fn attach(&self) -> ProcessAttachment {
method drop (line 63) | fn drop(&mut self) {
type ProcessAttachment (line 70) | pub struct ProcessAttachment {
method attach (line 76) | pub unsafe fn attach(process: PEPROCESS) -> Self {
method drop (line 90) | fn drop(&mut self) {
type ZwProcess (line 104) | pub struct ZwProcess {
method open (line 109) | pub fn open(id: ProcessId, access: ProcessAccess) -> Result<Self, Erro...
method drop (line 131) | fn drop(&mut self) {
FILE: windows-kernel-rs/src/request.rs
type IoRequest (line 33) | pub struct IoRequest {
method from_raw (line 38) | pub unsafe fn from_raw(irp: *mut IRP) -> Self {
method irp (line 42) | pub fn irp(&self) -> &IRP {
method irp_mut (line 46) | pub fn irp_mut(&self) -> &mut IRP {
method flags (line 50) | pub fn flags(&self) -> IrpFlags {
method stack_location (line 55) | pub fn stack_location(&self) -> &IO_STACK_LOCATION {
method major (line 59) | pub fn major(&self) -> u8 {
method complete (line 63) | pub(crate) fn complete(&self, value: Result<u32, Error>) {
type ReadRequest (line 83) | pub struct ReadRequest {
method user_ptr (line 96) | pub fn user_ptr(&self) -> UserPtr {
method offset (line 120) | pub fn offset(&self) -> i64 {
method into (line 135) | fn into(self) -> IoRequest {
type Target (line 88) | type Target = IoRequest;
method deref (line 90) | fn deref(&self) -> &Self::Target {
type WriteRequest (line 140) | pub struct WriteRequest {
method user_ptr (line 153) | pub fn user_ptr(&self) -> UserPtr {
method offset (line 177) | pub fn offset(&self) -> i64 {
method into (line 192) | fn into(self) -> IoRequest {
type Target (line 145) | type Target = IoRequest;
method deref (line 147) | fn deref(&self) -> &Self::Target {
type IoControlRequest (line 197) | pub struct IoControlRequest {
method control_code (line 210) | pub fn control_code(&self) -> ControlCode {
method function (line 218) | pub fn function(&self) -> (RequiredAccess, u32) {
method user_ptr (line 224) | pub fn user_ptr(&self) -> UserPtr {
method into (line 257) | fn into(self) -> IoRequest {
type Target (line 202) | type Target = IoRequest;
method deref (line 204) | fn deref(&self) -> &Self::Target {
FILE: windows-kernel-rs/src/section.rs
type SectionInherit (line 42) | pub enum SectionInherit {
type BaseAddress (line 47) | pub enum BaseAddress {
type Section (line 52) | pub struct Section {
method open (line 60) | pub fn open(path: &str, obj_flags: ObjectFlags, access: SectionAccess)...
method map_view (line 84) | pub fn map_view(
method drop (line 134) | fn drop(&mut self) {
type SectionView (line 141) | pub struct SectionView {
method address (line 150) | pub fn address(&self) -> *mut core::ffi::c_void {
method drop (line 156) | fn drop(&mut self) {
FILE: windows-kernel-rs/src/string.rs
function create_unicode_string (line 3) | pub fn create_unicode_string(s: &[u16]) -> UNICODE_STRING {
FILE: windows-kernel-rs/src/symbolic_link.rs
type SymbolicLink (line 6) | pub struct SymbolicLink {
method new (line 11) | pub fn new(name: &str, target: &str) -> Result<Self, Error> {
method drop (line 31) | fn drop(&mut self) {
FILE: windows-kernel-rs/src/sync/fast_mutex.rs
type FastMutex (line 20) | pub struct FastMutex<T: ?Sized> {
function new (line 30) | pub fn new(data: T) -> Self {
function into_inner (line 49) | pub fn into_inner(self) -> T {
function try_lock (line 61) | pub fn try_lock(&mut self) -> Option<FastMutexGuard<T>> {
function lock (line 87) | pub fn lock(&mut self) -> Option<FastMutexGuard<T>> {
method default (line 102) | fn default() -> Self {
function from (line 108) | fn from(data: T) -> Self {
type FastMutexGuard (line 123) | pub struct FastMutexGuard<'a, T: 'a + ?Sized> {
method drop (line 129) | fn drop(&mut self) {
type Target (line 139) | type Target = T;
method deref (line 141) | fn deref(&self) -> &T {
method deref_mut (line 147) | fn deref_mut(&mut self) -> &mut T {
FILE: windows-kernel-rs/src/sync/push_lock.rs
type PushLock (line 38) | pub struct PushLock<T: ?Sized> {
function new (line 48) | pub fn new(data: T) -> Self {
function into_inner (line 65) | pub fn into_inner(self) -> T {
function read (line 84) | pub fn read(&mut self) -> Option<PushLockReadGuard<T>> {
function write (line 114) | pub fn write(&mut self) -> Option<PushLockWriteGuard<T>> {
type PushLockReadGuard (line 138) | pub struct PushLockReadGuard<'a, T: 'a + ?Sized> {
method drop (line 144) | fn drop(&mut self) {
type Target (line 158) | type Target = T;
method deref (line 160) | fn deref(&self) -> &T {
type PushLockWriteGuard (line 171) | pub struct PushLockWriteGuard<'a, T: 'a + ?Sized> {
method drop (line 177) | fn drop(&mut self) {
type Target (line 191) | type Target = T;
method deref (line 193) | fn deref(&self) -> &T {
method deref_mut (line 199) | fn deref_mut(&mut self) -> &mut T {
FILE: windows-kernel-rs/src/user_ptr.rs
type UserPtr (line 3) | pub enum UserPtr {
method new_buffered (line 19) | pub unsafe fn new_buffered(
method new_direct (line 31) | pub unsafe fn new_direct(
method new_neither (line 45) | pub unsafe fn new_neither() -> Self {
method read_size (line 49) | pub fn read_size(&self) -> usize {
method write_size (line 57) | pub fn write_size(&self) -> usize {
method as_slice (line 65) | pub fn as_slice(&self) -> &[u8] {
method as_mut_slice (line 81) | pub fn as_mut_slice(&mut self) -> &mut [u8] {
method read (line 97) | pub fn read<T: Copy + Default>(&self) -> Result<T, Error> {
method write (line 125) | pub fn write<T: Copy>(&mut self, obj: &T) -> Result<(), Error> {
FILE: windows-kernel-rs/src/version.rs
type VersionInfo (line 8) | pub struct VersionInfo {
method query (line 14) | pub fn query() -> Result<Self, Error> {
method major (line 29) | pub fn major(&self) -> u32 {
method minor (line 34) | pub fn minor(&self) -> u32 {
method build_number (line 39) | pub fn build_number(&self) -> u32 {
FILE: windows-kernel-sys/build.rs
type Callbacks (line 7) | struct Callbacks;
method int_macro (line 10) | fn int_macro(&self, name: &str, _value: i64) -> Option<IntKind> {
function generate_base (line 18) | fn generate_base() {
function generate_intrin (line 45) | fn generate_intrin() {
function generate_intrin (line 58) | fn generate_intrin() {
function generate_ntoskrnl (line 62) | fn generate_ntoskrnl() {
function generate_ntoskrnl (line 98) | fn generate_ntoskrnl() {
function generate_netio (line 102) | fn generate_netio() {
function generate_netio (line 131) | fn generate_netio() {
function main (line 134) | fn main() {
FILE: windows-kernel-sys/src/base.rs
constant STATUS_SUCCESS (line 9) | pub const STATUS_SUCCESS: NTSTATUS = 0x00000000;
constant STATUS_GUARD_PAGE_VIOLATION (line 10) | pub const STATUS_GUARD_PAGE_VIOLATION: NTSTATUS = 0x80000001 as u32 ...
constant STATUS_DATATYPE_MISALIGNMENT (line 11) | pub const STATUS_DATATYPE_MISALIGNMENT: NTSTATUS = 0x80000002 as u32 ...
constant STATUS_BREAKPOINT (line 12) | pub const STATUS_BREAKPOINT: NTSTATUS = 0x80000003 as u32 ...
constant STATUS_SINGLE_STEP (line 13) | pub const STATUS_SINGLE_STEP: NTSTATUS = 0x80000004 as u32 ...
constant STATUS_UNWIND_CONSOLIDATE (line 14) | pub const STATUS_UNWIND_CONSOLIDATE: NTSTATUS = 0x80000029 as u32 ...
constant STATUS_UNSUCCESSFUL (line 15) | pub const STATUS_UNSUCCESSFUL: NTSTATUS = 0xC0000001 as u32 ...
constant STATUS_NOT_IMPLEMENTED (line 16) | pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002 as u32 ...
constant STATUS_ACCESS_VIOLATION (line 17) | pub const STATUS_ACCESS_VIOLATION: NTSTATUS = 0xC0000005 as u32 ...
constant STATUS_IN_PAGE_ERROR (line 18) | pub const STATUS_IN_PAGE_ERROR: NTSTATUS = 0xC0000006 as u32 ...
constant STATUS_INVALID_HANDLE (line 19) | pub const STATUS_INVALID_HANDLE: NTSTATUS = 0xC0000008 as u32 ...
constant STATUS_INVALID_PARAMETER (line 20) | pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xC000000D as u32 ...
constant STATUS_END_OF_FILE (line 21) | pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011 as u32 ...
constant STATUS_NO_MEMORY (line 22) | pub const STATUS_NO_MEMORY: NTSTATUS = 0xC0000017 as u32 ...
constant STATUS_ILLEGAL_INSTRUCTION (line 23) | pub const STATUS_ILLEGAL_INSTRUCTION: NTSTATUS = 0xC000001D as u32 ...
constant STATUS_NONCONTINUABLE_EXCEPTION (line 24) | pub const STATUS_NONCONTINUABLE_EXCEPTION: NTSTATUS = 0xC0000025 as u32 ...
constant STATUS_INVALID_DISPOSITION (line 25) | pub const STATUS_INVALID_DISPOSITION: NTSTATUS = 0xC0000026 as u32 ...
constant STATUS_ARRAY_BOUNDS_EXCEEDED (line 26) | pub const STATUS_ARRAY_BOUNDS_EXCEEDED: NTSTATUS = 0xC000008C as u32 ...
constant STATUS_FLOAT_DENORMAL_OPERAND (line 27) | pub const STATUS_FLOAT_DENORMAL_OPERAND: NTSTATUS = 0xC000008D as u32 ...
constant STATUS_FLOAT_DIVIDE_BY_ZERO (line 28) | pub const STATUS_FLOAT_DIVIDE_BY_ZERO: NTSTATUS = 0xC000008E as u32 ...
constant STATUS_FLOAT_INEXACT_RESULT (line 29) | pub const STATUS_FLOAT_INEXACT_RESULT: NTSTATUS = 0xC000008F as u32 ...
constant STATUS_FLOAT_INVALID_OPERATION (line 30) | pub const STATUS_FLOAT_INVALID_OPERATION: NTSTATUS = 0xC0000090 as u32 ...
constant STATUS_FLOAT_OVERFLOW (line 31) | pub const STATUS_FLOAT_OVERFLOW: NTSTATUS = 0xC0000091 as u32 ...
constant STATUS_FLOAT_STACK_CHECK (line 32) | pub const STATUS_FLOAT_STACK_CHECK: NTSTATUS = 0xC0000092 as u32 ...
constant STATUS_FLOAT_UNDERFLOW (line 33) | pub const STATUS_FLOAT_UNDERFLOW: NTSTATUS = 0xC0000093 as u32 ...
constant STATUS_INTEGER_DIVIDE_BY_ZERO (line 34) | pub const STATUS_INTEGER_DIVIDE_BY_ZERO: NTSTATUS = 0xC0000094 as u32 ...
constant STATUS_INTEGER_OVERFLOW (line 35) | pub const STATUS_INTEGER_OVERFLOW: NTSTATUS = 0xC0000095 as u32 ...
constant STATUS_PRIVILEGED_INSTRUCTION (line 36) | pub const STATUS_PRIVILEGED_INSTRUCTION: NTSTATUS = 0xC0000096 as u32 ...
constant STATUS_INSUFFICIENT_RESOURCES (line 37) | pub const STATUS_INSUFFICIENT_RESOURCES: NTSTATUS = 0xC000009A as u32 ...
constant STATUS_INVALID_USER_BUFFER (line 38) | pub const STATUS_INVALID_USER_BUFFER: NTSTATUS = 0xC00000E8 as u32 ...
constant STATUS_STACK_OVERFLOW (line 39) | pub const STATUS_STACK_OVERFLOW: NTSTATUS = 0xC00000FD as u32 ...
FILE: windows-kernel-sys/src/intrin.rs
function read_cr3 (line 9) | pub fn read_cr3() -> u64;
function write_cr3 (line 10) | pub fn write_cr3(value: u64);
function read_msr (line 11) | pub fn read_msr(register: u32) -> u64;
function read_msr_safe (line 12) | pub fn read_msr_safe(register: u32, value: &mut u64) -> NTSTATUS;
function write_msr (line 13) | pub fn write_msr(register: u32, value: u64);
function write_msr_safe (line 14) | pub fn write_msr_safe(register: u32, value: u64) -> NTSTATUS;
function invlpg (line 15) | pub fn invlpg(value: usize);
FILE: windows-kernel-sys/src/ntoskrnl.rs
function _ExInitializeFastMutex (line 9) | pub fn _ExInitializeFastMutex(mutex: PFAST_MUTEX);
function _ExAcquirePushLockExclusive (line 10) | pub fn _ExAcquirePushLockExclusive(push_lock: PEX_PUSH_LOCK);
function _ExReleasePushLockExclusive (line 11) | pub fn _ExReleasePushLockExclusive(push_lock: PEX_PUSH_LOCK);
function _ExAcquirePushLockShared (line 12) | pub fn _ExAcquirePushLockShared(push_lock: PEX_PUSH_LOCK);
function _ExReleasePushLockShared (line 13) | pub fn _ExReleasePushLockShared(push_lock: PEX_PUSH_LOCK);
function _IoGetCurrentIrpStackLocation (line 14) | pub fn _IoGetCurrentIrpStackLocation(irp: PIRP) -> PIO_STACK_LOCATION;
function _IoGetNextIrpStackLocation (line 15) | pub fn _IoGetNextIrpStackLocation(irp: PIRP) -> PIO_STACK_LOCATION;
function _IoSetCompletionRoutine (line 16) | pub fn _IoSetCompletionRoutine(
function _IoCompleteRequest (line 24) | pub fn _IoCompleteRequest(irp: PIRP, priority_boost: CCHAR);
function _MmGetMdlByteCount (line 25) | pub fn _MmGetMdlByteCount(mdl: PMDL) -> ULONG;
function _MmGetMdlByteOffset (line 26) | pub fn _MmGetMdlByteOffset(mdl: PMDL) -> ULONG;
function _MmGetSystemAddressForMdlSafe (line 27) | pub fn _MmGetSystemAddressForMdlSafe(mdl: PMDL, priority: ULONG) -> PVOID;
function _ObDereferenceObject (line 28) | pub fn _ObDereferenceObject(p: *mut cty::c_void);
function _ObReferenceObject (line 29) | pub fn _ObReferenceObject(p: *mut cty::c_void);
FILE: windows-kernel-sys/src/wrapper.c
function _ExInitializeFastMutex (line 3) | void _ExInitializeFastMutex(
function _ExAcquirePushLockExclusive (line 9) | void _ExAcquirePushLockExclusive(
function _ExReleasePushLockExclusive (line 15) | void _ExReleasePushLockExclusive(
function _ExAcquirePushLockShared (line 21) | void _ExAcquirePushLockShared(
function _ExReleasePushLockShared (line 27) | void _ExReleasePushLockShared(
function PIO_STACK_LOCATION (line 33) | PIO_STACK_LOCATION _IoGetCurrentIrpStackLocation(PIRP irp) {
function PIO_STACK_LOCATION (line 37) | PIO_STACK_LOCATION _IoGetNextIrpStackLocation(PIRP irp) {
function _IoSetCompletionRoutine (line 41) | void _IoSetCompletionRoutine(
function _IoCompleteRequest (line 52) | void _IoCompleteRequest(
function ULONG (line 59) | ULONG _MmGetMdlByteCount(PMDL mdl) {
function ULONG (line 63) | ULONG _MmGetMdlByteOffset(PMDL mdl) {
function PVOID (line 67) | PVOID _MmGetSystemAddressForMdlSafe(PMDL mdl, ULONG priority) {
function _ObDereferenceObject (line 71) | void _ObDereferenceObject(PVOID p) {
function _ObReferenceObject (line 75) | void _ObReferenceObject(PVOID p) {
FILE: windows-kernel-sys/src/wrapper.h
type ULONG_PTR (line 6) | typedef ULONG_PTR _EX_PUSH_LOCK;
type ULONG_PTR (line 7) | typedef ULONG_PTR EX_PUSH_LOCK;
type ULONG_PTR (line 8) | typedef ULONG_PTR *PEX_PUSH_LOCK;
type KGDTENTRY64 (line 10) | typedef union _KGDTENTRY64
type KIDTENTRY64 (line 45) | typedef union _KIDTENTRY64
FILE: windows-kernel-sys/src/wrapper_intrin.c
function read_cr3 (line 6) | unsigned __int64 read_cr3(void) {
function write_cr3 (line 10) | void write_cr3(unsigned __int64 Value) {
function read_msr (line 14) | unsigned __int64 read_msr(
function NTSTATUS (line 20) | NTSTATUS read_msr_safe(
function write_msr (line 37) | void write_msr(
function NTSTATUS (line 44) | NTSTATUS write_msr_safe(
function invlpg (line 57) | void invlpg(
FILE: winioctl/src/error.rs
type Error (line 4) | pub enum Error {
FILE: winioctl/src/ioctl.rs
type DeviceType (line 11) | pub enum DeviceType {
method into (line 73) | fn into(self) -> u32 {
method from (line 138) | fn from(value: u32) -> Self {
type TransferMethod (line 214) | pub enum TransferMethod {
method from (line 222) | fn from(value: u32) -> Self {
method into (line 234) | fn into(self) -> u32 {
type ControlCode (line 245) | pub struct ControlCode(pub DeviceType, pub RequiredAccess, pub u32, pub ...
constant METHOD_BITS (line 248) | const METHOD_BITS: usize = 2;
constant NUM_BITS (line 249) | const NUM_BITS: usize = 12;
constant ACCESS_BITS (line 250) | const ACCESS_BITS: usize = 2;
constant TYPE_BITS (line 251) | const TYPE_BITS: usize = 16;
constant METHOD_SHIFT (line 253) | const METHOD_SHIFT: usize = 0;
constant NUM_SHIFT (line 254) | const NUM_SHIFT: usize = Self::METHOD_SHIFT + Self::METHOD_BITS;
constant ACCESS_SHIFT (line 255) | const ACCESS_SHIFT: usize = Self::NUM_SHIFT + Self::NUM_BITS;
constant TYPE_SHIFT (line 256) | const TYPE_SHIFT: usize = Self::ACCESS_SHIFT + Self::ACCESS_BITS;
constant METHOD_MASK (line 258) | const METHOD_MASK: u32 = (1 << Self::METHOD_BITS) - 1;
constant NUM_MASK (line 259) | const NUM_MASK: u32 = (1 << Self::NUM_BITS) - 1;
constant ACCESS_MASK (line 260) | const ACCESS_MASK: u32 = (1 << Self::ACCESS_BITS) - 1;
constant TYPE_MASK (line 261) | const TYPE_MASK: u32 = (1 << Self::TYPE_BITS) - 1;
method from (line 265) | fn from(value: u32) -> Self {
method into (line 281) | fn into(self) -> u32 {
Condensed preview — 80 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (149K chars).
[
{
"path": ".gitignore",
"chars": 48,
"preview": "**/target/\n*.lock\n*.dll\n*.pdb\n*.lib\n*.exe\n*.cer\n"
},
{
"path": "02-hello-world/Cargo.toml",
"chars": 482,
"preview": "[package]\nname = \"02-hello-world\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://d"
},
{
"path": "02-hello-world/Makefile.toml",
"chars": 938,
"preview": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.b"
},
{
"path": "02-hello-world/build.rs",
"chars": 58,
"preview": "fn main() {\n windows_kernel_build::build().unwrap();\n}\n"
},
{
"path": "02-hello-world/rust-toolchain",
"chars": 8,
"preview": "nightly\n"
},
{
"path": "02-hello-world/src/lib.rs",
"chars": 630,
"preview": "#![no_std]\n\nuse core::panic::PanicInfo;\nuse winapi::km::wdm::{DbgPrint, DRIVER_OBJECT};\nuse winapi::shared::ntdef::{NTST"
},
{
"path": "03-generating-bindings/Cargo.toml",
"chars": 425,
"preview": "[package]\nname = \"03-generating-bindings\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at h"
},
{
"path": "03-generating-bindings/Makefile.toml",
"chars": 938,
"preview": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.b"
},
{
"path": "03-generating-bindings/build.rs",
"chars": 58,
"preview": "fn main() {\n windows_kernel_build::build().unwrap();\n}\n"
},
{
"path": "03-generating-bindings/rust-toolchain",
"chars": 8,
"preview": "nightly\n"
},
{
"path": "03-generating-bindings/src/lib.rs",
"chars": 603,
"preview": "#![no_std]\n\nuse core::panic::PanicInfo;\nuse windows_kernel_sys::base::{DRIVER_OBJECT, NTSTATUS, STATUS_SUCCESS, UNICODE_"
},
{
"path": "04-safe-framework/Cargo.toml",
"chars": 474,
"preview": "[package]\nname = \"04-safe-framework\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https:"
},
{
"path": "04-safe-framework/Makefile.toml",
"chars": 938,
"preview": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.b"
},
{
"path": "04-safe-framework/build.rs",
"chars": 58,
"preview": "fn main() {\n windows_kernel_build::build().unwrap();\n}\n"
},
{
"path": "04-safe-framework/rust-toolchain",
"chars": 8,
"preview": "nightly\n"
},
{
"path": "04-safe-framework/src/lib.rs",
"chars": 359,
"preview": "#![no_std]\n\nuse windows_kernel_rs::{Driver, Error, kernel_module, KernelModule, println};\n\nstruct Module;\n\nimpl KernelMo"
},
{
"path": "05-creating-devices/Cargo.toml",
"chars": 556,
"preview": "[package]\nname = \"05-creating-devices\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at http"
},
{
"path": "05-creating-devices/Makefile.toml",
"chars": 938,
"preview": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.b"
},
{
"path": "05-creating-devices/build.rs",
"chars": 58,
"preview": "fn main() {\n windows_kernel_build::build().unwrap();\n}\n"
},
{
"path": "05-creating-devices/rust-toolchain",
"chars": 8,
"preview": "nightly\n"
},
{
"path": "05-creating-devices/src/lib.rs",
"chars": 1693,
"preview": "#![no_std]\n\nuse windows_kernel_rs::device::{\n Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, Devic"
},
{
"path": "06-reading-and-writing/Cargo.toml",
"chars": 559,
"preview": "[package]\nname = \"06-reading-and-writing\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at h"
},
{
"path": "06-reading-and-writing/Makefile.toml",
"chars": 938,
"preview": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.b"
},
{
"path": "06-reading-and-writing/build.rs",
"chars": 58,
"preview": "fn main() {\n windows_kernel_build::build().unwrap();\n}\n"
},
{
"path": "06-reading-and-writing/rust-toolchain",
"chars": 8,
"preview": "nightly\n"
},
{
"path": "06-reading-and-writing/src/lib.rs",
"chars": 2069,
"preview": "#![no_std]\n\nextern crate alloc;\n\nuse alloc::vec;\nuse alloc::vec::Vec;\nuse windows_kernel_rs::device::{\n Completion, D"
},
{
"path": "07-io-controls/Cargo.toml",
"chars": 551,
"preview": "[package]\nname = \"07-io-controls\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://d"
},
{
"path": "07-io-controls/Makefile.toml",
"chars": 938,
"preview": "[env]\nVC_BUILD_DIR=\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2019\\\\BuildTools\\\\VC\\\\Auxiliary\\\\Build\\\\vcvars64.b"
},
{
"path": "07-io-controls/build.rs",
"chars": 58,
"preview": "fn main() {\n windows_kernel_build::build().unwrap();\n}\n"
},
{
"path": "07-io-controls/rust-toolchain",
"chars": 8,
"preview": "nightly\n"
},
{
"path": "07-io-controls/src/lib.rs",
"chars": 2526,
"preview": "#![no_std]\n\nuse windows_kernel_rs::device::{\n Completion, Device, DeviceDoFlags, DeviceFlags, DeviceOperations, Devic"
},
{
"path": "LICENSE",
"chars": 1074,
"preview": "MIT License\n\nCopyright (c) 2021 S.J.R. van Schaik\n\nPermission is hereby granted, free of charge, to any person obtaining"
},
{
"path": "README.md",
"chars": 3354,
"preview": "# windows-kernel-rs\n\n**Note**: this is still work in progress!\n\nThis is a Windows kernel framework in Rust that consists"
},
{
"path": "user/05-creating-devices/Cargo.toml",
"chars": 79,
"preview": "[package]\nname = \"user-05-creating-devices\"\nversion = \"0.1.0\"\nedition = \"2018\"\n"
},
{
"path": "user/05-creating-devices/src/main.rs",
"chars": 122,
"preview": "use std::fs::File;\n\nfn main() -> Result<(), std::io::Error> {\n let _file = File::open(\"\\\\??\\\\Example\")?;\n\n Ok(())\n"
},
{
"path": "user/06-reading-and-writing/Cargo.toml",
"chars": 82,
"preview": "[package]\nname = \"user-06-reading-and-writing\"\nversion = \"0.1.0\"\nedition = \"2018\"\n"
},
{
"path": "user/06-reading-and-writing/src/main.rs",
"chars": 558,
"preview": "use std::fs::OpenOptions;\nuse std::io::{Read, Write};\n\nfn main() -> Result<(), std::io::Error> {\n let mut file = Open"
},
{
"path": "user/07-io-controls/Cargo.toml",
"chars": 249,
"preview": "[package]\nname = \"user-07-io-controls\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at http"
},
{
"path": "user/07-io-controls/src/main.rs",
"chars": 942,
"preview": "use std::fs::OpenOptions;\nuse std::os::windows::io::AsRawHandle;\nuse winioctl::{DeviceType, Error};\nuse winioctl::{ioctl"
},
{
"path": "windows-kernel-build/Cargo.toml",
"chars": 125,
"preview": "[package]\nname = \"windows-kernel-build\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\nthiserror = \"1.0\"\nwinreg = \"0"
},
{
"path": "windows-kernel-build/src/lib.rs",
"chars": 3034,
"preview": "use std::path::PathBuf;\nuse thiserror::Error;\nuse winreg::RegKey;\nuse winreg::enums::HKEY_LOCAL_MACHINE;\n\n#[derive(Debug"
},
{
"path": "windows-kernel-rs/Cargo.toml",
"chars": 437,
"preview": "[package]\nname = \"windows-kernel-rs\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[profile.dev]\npanic = \"abort\"\n\n[profile.release"
},
{
"path": "windows-kernel-rs/rust-toolchain",
"chars": 8,
"preview": "nightly\n"
},
{
"path": "windows-kernel-rs/src/affinity.rs",
"chars": 3760,
"preview": "//! This module provides functions to get information about the logical CPUs in the system, and to\n//! run closures on s"
},
{
"path": "windows-kernel-rs/src/allocator.rs",
"chars": 2699,
"preview": "//! This module provides an allocator to use with the [`alloc`] crate. You can define your own\n//! global allocator with"
},
{
"path": "windows-kernel-rs/src/device.rs",
"chars": 18080,
"preview": "use crate::error::Error;\nuse crate::request::{IoControlRequest, IoRequest, ReadRequest, WriteRequest};\nuse alloc::boxed:"
},
{
"path": "windows-kernel-rs/src/driver.rs",
"chars": 2145,
"preview": "use alloc::boxed::Box;\nuse crate::device::{Access, Device, DeviceExtension, DeviceDoFlags, DeviceFlags, DeviceOperations"
},
{
"path": "windows-kernel-rs/src/error.rs",
"chars": 3948,
"preview": "use windows_kernel_sys::base::NTSTATUS;\nuse windows_kernel_sys::base::{\n STATUS_SUCCESS,\n STATUS_GUARD_PAGE_VIOLAT"
},
{
"path": "windows-kernel-rs/src/intrin.rs",
"chars": 1045,
"preview": "use crate::error::{Error, IntoResult};\nuse windows_kernel_sys::intrin::{read_msr_safe, write_msr_safe};\n\n/// Attempts to"
},
{
"path": "windows-kernel-rs/src/io.rs",
"chars": 1068,
"preview": "use windows_kernel_sys::base::ANSI_STRING;\nuse windows_kernel_sys::ntoskrnl::DbgPrint;\n\n#[macro_export]\nmacro_rules! pri"
},
{
"path": "windows-kernel-rs/src/ioctl.rs",
"chars": 3301,
"preview": "use crate::device::DeviceType;\nuse bitflags::bitflags;\nuse windows_kernel_sys::base::{\n FILE_ANY_ACCESS, FILE_READ_DA"
},
{
"path": "windows-kernel-rs/src/lib.rs",
"chars": 3160,
"preview": "#![no_std]\n\n#![feature(alloc_error_handler)]\n\nextern crate alloc;\n\npub mod affinity;\npub mod allocator;\npub mod device;\n"
},
{
"path": "windows-kernel-rs/src/mdl.rs",
"chars": 2759,
"preview": "use crate::error::Error;\nuse crate::memory::MemoryCaching;\n\n#[repr(i32)]\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npu"
},
{
"path": "windows-kernel-rs/src/memory.rs",
"chars": 4711,
"preview": "use crate::error::{Error, IntoResult};\nuse windows_kernel_sys::base::{MM_COPY_ADDRESS, MM_COPY_MEMORY_PHYSICAL, MM_COPY_"
},
{
"path": "windows-kernel-rs/src/process.rs",
"chars": 3129,
"preview": "use bitflags::bitflags;\nuse crate::error::{Error, IntoResult};\nuse windows_kernel_sys::base::{CLIENT_ID, HANDLE, KAPC_ST"
},
{
"path": "windows-kernel-rs/src/request.rs",
"chars": 8154,
"preview": "use bitflags::bitflags;\nuse core::ops::Deref;\nuse crate::error::Error;\nuse crate::ioctl::{ControlCode, RequiredAccess, T"
},
{
"path": "windows-kernel-rs/src/section.rs",
"chars": 4637,
"preview": "use bitflags::bitflags;\nuse crate::error::{Error, IntoResult};\nuse crate::process::ZwProcess;\nuse crate::string::create_"
},
{
"path": "windows-kernel-rs/src/string.rs",
"chars": 335,
"preview": "use windows_kernel_sys::base::UNICODE_STRING;\n\npub fn create_unicode_string(s: &[u16]) -> UNICODE_STRING {\n let len ="
},
{
"path": "windows-kernel-rs/src/symbolic_link.rs",
"chars": 1105,
"preview": "use crate::error::{Error, IntoResult};\nuse crate::string::create_unicode_string;\nuse widestring::U16CString;\nuse windows"
},
{
"path": "windows-kernel-rs/src/sync/fast_mutex.rs",
"chars": 4490,
"preview": "use alloc::boxed::Box;\nuse core::cell::UnsafeCell;\nuse core::ops::{Deref, DerefMut};\nuse windows_kernel_sys::base::FAST_"
},
{
"path": "windows-kernel-rs/src/sync/mod.rs",
"chars": 131,
"preview": "pub mod fast_mutex;\npub mod push_lock;\n\npub use self::fast_mutex::FastMutex as Mutex;\npub use self::push_lock::PushLock "
},
{
"path": "windows-kernel-rs/src/sync/push_lock.rs",
"chars": 6571,
"preview": "use alloc::boxed::Box;\nuse core::cell::UnsafeCell;\nuse core::ops::{Deref, DerefMut};\nuse windows_kernel_sys::base::EX_PU"
},
{
"path": "windows-kernel-rs/src/user_ptr.rs",
"chars": 3892,
"preview": "use crate::error::Error;\n\npub enum UserPtr {\n Buffered {\n ptr: *mut cty::c_void,\n read_size: usize,\n "
},
{
"path": "windows-kernel-rs/src/version.rs",
"chars": 1256,
"preview": "//! This module provides utilities to query information about the version of Microsoft Windows.\n\nuse crate::error::{Erro"
},
{
"path": "windows-kernel-sys/Cargo.toml",
"chars": 293,
"preview": "[package]\nname = \"windows-kernel-sys\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[features]\ndefault = [\"intrin\", \"ntoskrnl\"]\nin"
},
{
"path": "windows-kernel-sys/build.rs",
"chars": 4047,
"preview": "use std::path::PathBuf;\nuse windows_kernel_build::DirectoryType;\n\nuse bindgen::callbacks::*;\n\n#[derive(Debug)]\nstruct Ca"
},
{
"path": "windows-kernel-sys/rust-toolchain",
"chars": 8,
"preview": "nightly\n"
},
{
"path": "windows-kernel-sys/src/base.rs",
"chars": 2625,
"preview": "#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n\npub use cty::*;\n\ninclude!(c"
},
{
"path": "windows-kernel-sys/src/intrin.rs",
"chars": 487,
"preview": "#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n\nuse crate::base::*;\n\n#[link"
},
{
"path": "windows-kernel-sys/src/lib.rs",
"chars": 175,
"preview": "#![no_std]\n\npub mod base;\n\n#[cfg(feature = \"intrin\")]\npub mod intrin;\n#[cfg(feature = \"netio\")]\npub mod netio;\n#[cfg(fea"
},
{
"path": "windows-kernel-sys/src/netio.rs",
"chars": 163,
"preview": "#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n\nuse crate::base::*;\n\ninclud"
},
{
"path": "windows-kernel-sys/src/ntoskrnl.rs",
"chars": 2247,
"preview": "#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n\nuse crate::base::*;\n\n#[link"
},
{
"path": "windows-kernel-sys/src/wrapper.c",
"chars": 1537,
"preview": "#include \"wrapper.h\"\n\nvoid _ExInitializeFastMutex(\n\tPFAST_MUTEX fast_mutex\n) {\n\tExInitializeFastMutex(fast_mutex);\n}\n\nvo"
},
{
"path": "windows-kernel-sys/src/wrapper.h",
"chars": 1277,
"preview": "#define _AMD64_\n\n#include \"ntdef.h\"\n#include \"ntstatus.h\"\n\ntypedef ULONG_PTR _EX_PUSH_LOCK;\ntypedef ULONG_PTR EX_PUSH_LO"
},
{
"path": "windows-kernel-sys/src/wrapper_intrin.c",
"chars": 913,
"preview": "#define _AMD64_\n\n#include \"wdm.h\"\n#include \"intrin.h\"\n\nunsigned __int64 read_cr3(void) {\n\treturn __readcr3();\n}\n\nvoid wr"
},
{
"path": "windows-kernel-sys/src/wrapper_netio.h",
"chars": 70,
"preview": "#define _AMD64_\n\n#include \"ntdef.h\"\n#include \"wdm.h\"\n#include \"wsk.h\"\n"
},
{
"path": "winioctl/Cargo.toml",
"chars": 316,
"preview": "[package]\nname = \"winioctl\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rus"
},
{
"path": "winioctl/src/error.rs",
"chars": 129,
"preview": "use thiserror::Error;\n\n#[derive(Debug, Error)]\npub enum Error {\n #[error(transparent)]\n IoError(#[from] std::io::E"
},
{
"path": "winioctl/src/ioctl.rs",
"chars": 17490,
"preview": "use bitflags::bitflags;\nuse winapi::um::winioctl::{\n FILE_ANY_ACCESS,\n METHOD_NEITHER, METHOD_IN_DIRECT, METHOD_OU"
},
{
"path": "winioctl/src/lib.rs",
"chars": 181,
"preview": "mod error;\nmod ioctl;\n\npub use crate::error::Error;\npub use crate::ioctl::{ControlCode, DeviceType, RequiredAccess, Tran"
}
]
About this extraction
This page contains the full source code of the StephanvanSchaik/windows-kernel-rs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 80 files (136.1 KB), approximately 37.0k tokens, and a symbol index with 395 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.