diff options
Diffstat (limited to 'src/sys/windows/afd.rs')
-rw-r--r-- | src/sys/windows/afd.rs | 108 |
1 files changed, 63 insertions, 45 deletions
diff --git a/src/sys/windows/afd.rs b/src/sys/windows/afd.rs index 6241a45..0308e2f 100644 --- a/src/sys/windows/afd.rs +++ b/src/sys/windows/afd.rs @@ -1,17 +1,32 @@ -use ntapi::ntioapi::{IO_STATUS_BLOCK_u, IO_STATUS_BLOCK}; -use ntapi::ntioapi::{NtCancelIoFileEx, NtDeviceIoControlFile}; -use ntapi::ntrtl::RtlNtStatusToDosError; +use std::ffi::c_void; use std::fmt; use std::fs::File; use std::io; use std::mem::size_of; use std::os::windows::io::AsRawHandle; -use std::ptr::null_mut; -use winapi::shared::ntdef::{HANDLE, LARGE_INTEGER, NTSTATUS, PVOID, ULONG}; -use winapi::shared::ntstatus::{STATUS_NOT_FOUND, STATUS_PENDING, STATUS_SUCCESS}; -const IOCTL_AFD_POLL: ULONG = 0x00012024; +use windows_sys::Win32::Foundation::{ + RtlNtStatusToDosError, HANDLE, NTSTATUS, STATUS_NOT_FOUND, STATUS_PENDING, STATUS_SUCCESS, +}; +use windows_sys::Win32::System::WindowsProgramming::{ + NtDeviceIoControlFile, IO_STATUS_BLOCK, IO_STATUS_BLOCK_0, +}; +const IOCTL_AFD_POLL: u32 = 0x00012024; + +#[link(name = "ntdll")] +extern "system" { + /// See <https://processhacker.sourceforge.io/doc/ntioapi_8h.html#a0d4d550cad4d62d75b76961e25f6550c> + /// + /// This is an undocumented API and as such not part of <https://github.com/microsoft/win32metadata> + /// from which `windows-sys` is generated, and also unlikely to be added, so + /// we manually declare it here + fn NtCancelIoFileEx( + FileHandle: HANDLE, + IoRequestToCancel: *mut IO_STATUS_BLOCK, + IoStatusBlock: *mut IO_STATUS_BLOCK, + ) -> NTSTATUS; +} /// Winsock2 AFD driver instance. /// /// All operations are unsafe due to IO_STATUS_BLOCK parameter are being used by Afd driver during STATUS_PENDING before I/O Completion Port returns its result. @@ -24,7 +39,7 @@ pub struct Afd { #[derive(Debug)] pub struct AfdPollHandleInfo { pub handle: HANDLE, - pub events: ULONG, + pub events: u32, pub status: NTSTATUS, } @@ -32,10 +47,10 @@ unsafe impl Send for AfdPollHandleInfo {} #[repr(C)] pub struct AfdPollInfo { - pub timeout: LARGE_INTEGER, + pub timeout: i64, // Can have only value 1. - pub number_of_handles: ULONG, - pub exclusive: ULONG, + pub number_of_handles: u32, + pub exclusive: u32, pub handles: [AfdPollHandleInfo; 1], } @@ -58,13 +73,13 @@ impl Afd { &self, info: &mut AfdPollInfo, iosb: *mut IO_STATUS_BLOCK, - overlapped: PVOID, + overlapped: *mut c_void, ) -> io::Result<bool> { - let info_ptr: PVOID = info as *mut _ as PVOID; - (*iosb).u.Status = STATUS_PENDING; + let info_ptr = info as *mut _ as *mut c_void; + (*iosb).Anonymous.Status = STATUS_PENDING; let status = NtDeviceIoControlFile( - self.fd.as_raw_handle(), - null_mut(), + self.fd.as_raw_handle() as HANDLE, + 0, None, overlapped, iosb, @@ -93,15 +108,15 @@ impl Afd { /// Use it only with request is still being polled so that you have valid `IO_STATUS_BLOCK` to use. /// User should NOT deallocate there overlapped value after the `cancel` to prevent double free. pub unsafe fn cancel(&self, iosb: *mut IO_STATUS_BLOCK) -> io::Result<()> { - if (*iosb).u.Status != STATUS_PENDING { + if (*iosb).Anonymous.Status != STATUS_PENDING { return Ok(()); } let mut cancel_iosb = IO_STATUS_BLOCK { - u: IO_STATUS_BLOCK_u { Status: 0 }, + Anonymous: IO_STATUS_BLOCK_0 { Status: 0 }, Information: 0, }; - let status = NtCancelIoFileEx(self.fd.as_raw_handle(), iosb, &mut cancel_iosb); + let status = NtCancelIoFileEx(self.fd.as_raw_handle() as HANDLE, iosb, &mut cancel_iosb); if status == STATUS_SUCCESS || status == STATUS_NOT_FOUND { return Ok(()); } @@ -114,18 +129,21 @@ impl Afd { cfg_io_source! { use std::mem::zeroed; use std::os::windows::io::{FromRawHandle, RawHandle}; + use std::ptr::null_mut; use std::sync::atomic::{AtomicUsize, Ordering}; - use miow::iocp::CompletionPort; - use ntapi::ntioapi::{NtCreateFile, FILE_OPEN}; - use winapi::shared::ntdef::{OBJECT_ATTRIBUTES, UNICODE_STRING, USHORT, WCHAR}; - use winapi::um::handleapi::INVALID_HANDLE_VALUE; - use winapi::um::winbase::{SetFileCompletionNotificationModes, FILE_SKIP_SET_EVENT_ON_HANDLE}; - use winapi::um::winnt::{SYNCHRONIZE, FILE_SHARE_READ, FILE_SHARE_WRITE}; + use super::iocp::CompletionPort; + use windows_sys::Win32::{ + Foundation::{UNICODE_STRING, INVALID_HANDLE_VALUE}, + System::WindowsProgramming::{ + OBJECT_ATTRIBUTES, FILE_SKIP_SET_EVENT_ON_HANDLE, + }, + Storage::FileSystem::{FILE_OPEN, NtCreateFile, SetFileCompletionNotificationModes, SYNCHRONIZE, FILE_SHARE_READ, FILE_SHARE_WRITE}, + }; const AFD_HELPER_ATTRIBUTES: OBJECT_ATTRIBUTES = OBJECT_ATTRIBUTES { - Length: size_of::<OBJECT_ATTRIBUTES>() as ULONG, - RootDirectory: null_mut(), + Length: size_of::<OBJECT_ATTRIBUTES>() as u32, + RootDirectory: 0, ObjectName: &AFD_OBJ_NAME as *const _ as *mut _, Attributes: 0, SecurityDescriptor: null_mut(), @@ -133,12 +151,12 @@ cfg_io_source! { }; const AFD_OBJ_NAME: UNICODE_STRING = UNICODE_STRING { - Length: (AFD_HELPER_NAME.len() * size_of::<WCHAR>()) as USHORT, - MaximumLength: (AFD_HELPER_NAME.len() * size_of::<WCHAR>()) as USHORT, + Length: (AFD_HELPER_NAME.len() * size_of::<u16>()) as u16, + MaximumLength: (AFD_HELPER_NAME.len() * size_of::<u16>()) as u16, Buffer: AFD_HELPER_NAME.as_ptr() as *mut _, }; - const AFD_HELPER_NAME: &[WCHAR] = &[ + const AFD_HELPER_NAME: &[u16] = &[ '\\' as _, 'D' as _, 'e' as _, @@ -166,10 +184,10 @@ cfg_io_source! { impl Afd { /// Create new Afd instance. - pub fn new(cp: &CompletionPort) -> io::Result<Afd> { + pub(crate) fn new(cp: &CompletionPort) -> io::Result<Afd> { let mut afd_helper_handle: HANDLE = INVALID_HANDLE_VALUE; let mut iosb = IO_STATUS_BLOCK { - u: IO_STATUS_BLOCK_u { Status: 0 }, + Anonymous: IO_STATUS_BLOCK_0 { Status: 0 }, Information: 0, }; @@ -180,12 +198,12 @@ cfg_io_source! { &AFD_HELPER_ATTRIBUTES as *const _ as *mut _, &mut iosb, null_mut(), - 0 as ULONG, + 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, - 0 as ULONG, + 0, null_mut(), - 0 as ULONG, + 0, ); if status != STATUS_SUCCESS { let raw_err = io::Error::from_raw_os_error( @@ -204,7 +222,7 @@ cfg_io_source! { cp.add_handle(token, &afd.fd)?; match SetFileCompletionNotificationModes( afd_helper_handle, - FILE_SKIP_SET_EVENT_ON_HANDLE, + FILE_SKIP_SET_EVENT_ON_HANDLE as u8 // This is just 2, so fits in u8 ) { 0 => Err(io::Error::last_os_error()), _ => Ok(afd), @@ -214,18 +232,18 @@ cfg_io_source! { } } -pub const POLL_RECEIVE: u32 = 0b000_000_001; -pub const POLL_RECEIVE_EXPEDITED: u32 = 0b000_000_010; -pub const POLL_SEND: u32 = 0b000_000_100; -pub const POLL_DISCONNECT: u32 = 0b000_001_000; -pub const POLL_ABORT: u32 = 0b000_010_000; -pub const POLL_LOCAL_CLOSE: u32 = 0b000_100_000; +pub const POLL_RECEIVE: u32 = 0b0_0000_0001; +pub const POLL_RECEIVE_EXPEDITED: u32 = 0b0_0000_0010; +pub const POLL_SEND: u32 = 0b0_0000_0100; +pub const POLL_DISCONNECT: u32 = 0b0_0000_1000; +pub const POLL_ABORT: u32 = 0b0_0001_0000; +pub const POLL_LOCAL_CLOSE: u32 = 0b0_0010_0000; // Not used as it indicated in each event where a connection is connected, not // just the first time a connection is established. // Also see https://github.com/piscisaureus/wepoll/commit/8b7b340610f88af3d83f40fb728e7b850b090ece. -pub const POLL_CONNECT: u32 = 0b001_000_000; -pub const POLL_ACCEPT: u32 = 0b010_000_000; -pub const POLL_CONNECT_FAIL: u32 = 0b100_000_000; +pub const POLL_CONNECT: u32 = 0b0_0100_0000; +pub const POLL_ACCEPT: u32 = 0b0_1000_0000; +pub const POLL_CONNECT_FAIL: u32 = 0b1_0000_0000; pub const KNOWN_EVENTS: u32 = POLL_RECEIVE | POLL_RECEIVE_EXPEDITED |