summaryrefslogtreecommitdiff
path: root/crates/winioctl/src/ioctl.rs
diff options
context:
space:
mode:
authorFuwn <[email protected]>2022-01-03 03:20:12 -0800
committerFuwn <[email protected]>2022-01-03 03:20:12 -0800
commit85db2b507f3f69b32811c54a89d9ac7bbbc46121 (patch)
tree2efd66da452f8a6a2cc6c91584c925f237506ddf /crates/winioctl/src/ioctl.rs
downloaddriver-85db2b507f3f69b32811c54a89d9ac7bbbc46121.tar.xz
driver-85db2b507f3f69b32811c54a89d9ac7bbbc46121.zip
feat(driver): commit primer
Diffstat (limited to 'crates/winioctl/src/ioctl.rs')
-rw-r--r--crates/winioctl/src/ioctl.rs423
1 files changed, 423 insertions, 0 deletions
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())?,
+ }
+ }
+ }
+}