use std::ffi::c_void;
use windows_sys::Win32::Storage::FileSystem::{
BuildIoRingCancelRequest, BuildIoRingFlushFile, BuildIoRingReadFile,
BuildIoRingRegisterBuffers, BuildIoRingRegisterFileHandles, BuildIoRingWriteFile,
FILE_FLUSH_MODE, IORING_BUFFER_INFO, IORING_BUFFER_REF, IORING_CQE, IORING_HANDLE_REF,
PopIoRingCompletion, SetIoRingCompletionEvent, SubmitIoRing,
};
use windows_sys::core::HRESULT;
use crate::accounting::RingId;
#[cfg(all(feature = "kernel-seam", feature = "fault-injection"))]
mod call_faults;
#[cfg(feature = "kernel-seam")]
mod registered;
#[cfg(feature = "kernel-seam")]
mod resolver;
#[cfg(feature = "kernel-seam")]
mod responses;
#[cfg(all(feature = "kernel-seam", feature = "fault-injection"))]
pub use call_faults::{
Call, CallFaultControl, CallFaults, SubmitFaultControl, call_faults, submit_faults,
};
#[cfg(feature = "kernel-seam")]
pub(crate) use registered::ring_dropped;
#[cfg(feature = "kernel-seam")]
pub use registered::{Registration, register};
#[cfg(feature = "kernel-seam")]
pub use resolver::{
Resolver, ResolverConfig, ResolverStats, ResolverWatch, SEED_VAR as RESOLVER_SEED_VAR,
};
#[cfg(feature = "kernel-seam")]
pub use responses::Responses;
macro_rules! through_seam {
($ring_id:expr; $method:ident ( $($arg:expr),* $(,)? ) else $real:expr) => {{
#[cfg(feature = "kernel-seam")]
{
if let Some(answer) =
$crate::sys::registered::with($ring_id, |r| unsafe { r.$method($($arg),*) })
{
return answer;
}
}
#[cfg(not(feature = "kernel-seam"))]
let _ = $ring_id;
unsafe { $real }
}};
}
#[inline(always)]
pub(crate) unsafe fn submit(
ring_id: RingId,
ring: *mut c_void,
wait_operations: u32,
milliseconds: u32,
submitted: *mut u32,
) -> HRESULT {
through_seam!(
ring_id; submit(ring, wait_operations, milliseconds, submitted)
else SubmitIoRing(ring, wait_operations, milliseconds, submitted)
)
}
#[inline(always)]
pub(crate) unsafe fn pop(ring_id: RingId, ring: *mut c_void, cqe: *mut IORING_CQE) -> HRESULT {
through_seam!(ring_id; pop(ring, cqe) else PopIoRingCompletion(ring, cqe))
}
#[inline(always)]
#[allow(clippy::too_many_arguments)]
pub(crate) unsafe fn build_read(
ring_id: RingId,
ring: *mut c_void,
file: IORING_HANDLE_REF,
buffer: IORING_BUFFER_REF,
bytes: u32,
offset: u64,
user_data: usize,
flags: i32,
) -> HRESULT {
through_seam!(
ring_id; build_read(ring, file, buffer, bytes, offset, user_data, flags)
else BuildIoRingReadFile(ring, file, buffer, bytes, offset, user_data, flags)
)
}
#[inline(always)]
#[allow(clippy::too_many_arguments)]
pub(crate) unsafe fn build_write(
ring_id: RingId,
ring: *mut c_void,
file: IORING_HANDLE_REF,
buffer: IORING_BUFFER_REF,
bytes: u32,
offset: u64,
caching: i32,
user_data: usize,
flags: i32,
) -> HRESULT {
through_seam!(
ring_id; build_write(ring, file, buffer, bytes, offset, caching, user_data, flags)
else BuildIoRingWriteFile(ring, file, buffer, bytes, offset, caching, user_data, flags)
)
}
#[inline(always)]
pub(crate) unsafe fn build_flush(
ring_id: RingId,
ring: *mut c_void,
file: IORING_HANDLE_REF,
mode: FILE_FLUSH_MODE,
user_data: usize,
flags: i32,
) -> HRESULT {
through_seam!(
ring_id; build_flush(ring, file, mode, user_data, flags)
else BuildIoRingFlushFile(ring, file, mode, user_data, flags)
)
}
#[inline(always)]
pub(crate) unsafe fn build_cancel(
ring_id: RingId,
ring: *mut c_void,
file: IORING_HANDLE_REF,
cancel_user_data: usize,
user_data: usize,
) -> HRESULT {
through_seam!(
ring_id; build_cancel(ring, file, cancel_user_data, user_data)
else BuildIoRingCancelRequest(ring, file, cancel_user_data, user_data)
)
}
#[inline(always)]
pub(crate) unsafe fn build_register_files(
ring_id: RingId,
ring: *mut c_void,
count: u32,
handles: *const *mut c_void,
user_data: usize,
) -> HRESULT {
through_seam!(
ring_id; build_register_files(ring, count, handles, user_data)
else BuildIoRingRegisterFileHandles(ring, count, handles, user_data)
)
}
#[inline(always)]
pub(crate) unsafe fn build_register_buffers(
ring_id: RingId,
ring: *mut c_void,
count: u32,
buffers: *const IORING_BUFFER_INFO,
user_data: usize,
) -> HRESULT {
through_seam!(
ring_id; build_register_buffers(ring, count, buffers, user_data)
else BuildIoRingRegisterBuffers(ring, count, buffers, user_data)
)
}
#[inline(always)]
pub(crate) unsafe fn set_completion_event(
ring_id: RingId,
ring: *mut c_void,
event: *mut c_void,
) -> HRESULT {
through_seam!(
ring_id; set_completion_event(ring, event) else SetIoRingCompletionEvent(ring, event)
)
}
#[cfg(feature = "kernel-seam")]
pub(crate) mod real {
pub(crate) use windows_sys::Win32::Storage::FileSystem::{
BuildIoRingCancelRequest, BuildIoRingFlushFile, BuildIoRingReadFile,
BuildIoRingRegisterBuffers, BuildIoRingRegisterFileHandles, BuildIoRingWriteFile,
PopIoRingCompletion, SetIoRingCompletionEvent, SubmitIoRing,
};
}