diff options
| author | Fuwn <[email protected]> | 2022-01-03 03:20:12 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2022-01-03 03:20:12 -0800 |
| commit | 85db2b507f3f69b32811c54a89d9ac7bbbc46121 (patch) | |
| tree | 2efd66da452f8a6a2cc6c91584c925f237506ddf /crates/winioctl | |
| download | driver-85db2b507f3f69b32811c54a89d9ac7bbbc46121.tar.xz driver-85db2b507f3f69b32811c54a89d9ac7bbbc46121.zip | |
feat(driver): commit primer
Diffstat (limited to 'crates/winioctl')
| -rw-r--r-- | crates/winioctl/Cargo.toml | 13 | ||||
| -rw-r--r-- | crates/winioctl/LICENSE | 21 | ||||
| -rw-r--r-- | crates/winioctl/src/error.rs | 7 | ||||
| -rw-r--r-- | crates/winioctl/src/ioctl.rs | 423 | ||||
| -rw-r--r-- | crates/winioctl/src/lib.rs | 9 |
5 files changed, 473 insertions, 0 deletions
diff --git a/crates/winioctl/Cargo.toml b/crates/winioctl/Cargo.toml new file mode 100644 index 0000000..656c14c --- /dev/null +++ b/crates/winioctl/Cargo.toml @@ -0,0 +1,13 @@ +[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"] } diff --git a/crates/winioctl/LICENSE b/crates/winioctl/LICENSE new file mode 100644 index 0000000..68bb87c --- /dev/null +++ b/crates/winioctl/LICENSE @@ -0,0 +1,21 @@ +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. diff --git a/crates/winioctl/src/error.rs b/crates/winioctl/src/error.rs new file mode 100644 index 0000000..968b166 --- /dev/null +++ b/crates/winioctl/src/error.rs @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum Error { + #[error(transparent)] + IoError(#[from] std::io::Error), +} diff --git a/crates/winioctl/src/ioctl.rs b/crates/winioctl/src/ioctl.rs new file mode 100644 index 0000000..d2e6b91 --- /dev/null +++ b/crates/winioctl/src/ioctl.rs @@ -0,0 +1,423 @@ +use bitflags::bitflags; +use winapi::um::{ + winioctl::{ + FILE_ANY_ACCESS, + METHOD_BUFFERED, + METHOD_IN_DIRECT, + METHOD_NEITHER, + METHOD_OUT_DIRECT, + }, + 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 ACCESS_BITS: usize = 2; + const ACCESS_MASK: u32 = (1 << Self::ACCESS_BITS) - 1; + const ACCESS_SHIFT: usize = Self::NUM_SHIFT + Self::NUM_BITS; + const METHOD_BITS: usize = 2; + const METHOD_MASK: u32 = (1 << Self::METHOD_BITS) - 1; + const METHOD_SHIFT: usize = 0; + const NUM_BITS: usize = 12; + const NUM_MASK: u32 = (1 << Self::NUM_BITS) - 1; + const NUM_SHIFT: usize = Self::METHOD_SHIFT + Self::METHOD_BITS; + const TYPE_BITS: usize = 16; + const TYPE_MASK: u32 = (1 << Self::TYPE_BITS) - 1; + const TYPE_SHIFT: usize = Self::ACCESS_SHIFT + Self::ACCESS_BITS; +} + +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())?, + } + } + } +} diff --git a/crates/winioctl/src/lib.rs b/crates/winioctl/src/lib.rs new file mode 100644 index 0000000..8cd45b4 --- /dev/null +++ b/crates/winioctl/src/lib.rs @@ -0,0 +1,9 @@ +mod error; +mod ioctl; + +pub use winapi::um::ioapiset::DeviceIoControl; + +pub use crate::{ + error::Error, + ioctl::{ControlCode, DeviceType, RequiredAccess, TransferMethod}, +}; |