Skip to main content

compio_driver\sys\op\general/
iocp.rs

1use windows_sys::Win32::{
2    Storage::FileSystem::{ReadFile, WriteFile},
3    System::{
4        IO::{DeviceIoControl, OVERLAPPED},
5        Pipes::ConnectNamedPipe,
6    },
7};
8
9use crate::{OpCode, sys::op::*};
10
11unsafe impl<T: IoBufMut, S: AsFd> OpCode for ReadAt<T, S> {
12    type Control = ();
13
14    unsafe fn operate(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
15        if let Some(overlapped) = unsafe { optr.as_mut() } {
16            overlapped.Anonymous.Anonymous.Offset = (self.offset & 0xFFFFFFFF) as _;
17            overlapped.Anonymous.Anonymous.OffsetHigh = (self.offset >> 32) as _;
18        }
19        let slice = self.buffer.sys_slice_mut();
20        let fd = self.fd.as_fd().as_raw_fd();
21        let mut transferred = 0;
22        let res = unsafe {
23            ReadFile(
24                fd,
25                slice.ptr() as _,
26                slice.len() as _,
27                &mut transferred,
28                optr,
29            )
30        };
31        win32_result(res, transferred)
32    }
33
34    fn cancel(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> io::Result<()> {
35        cancel(self.fd.as_fd().as_raw_fd(), optr)
36    }
37}
38
39unsafe impl<T: IoBuf, S: AsFd> OpCode for WriteAt<T, S> {
40    type Control = ();
41
42    unsafe fn operate(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
43        if let Some(overlapped) = unsafe { optr.as_mut() } {
44            overlapped.Anonymous.Anonymous.Offset = (self.offset & 0xFFFFFFFF) as _;
45            overlapped.Anonymous.Anonymous.OffsetHigh = (self.offset >> 32) as _;
46        }
47        let slice = self.buffer.as_init();
48        let mut transferred = 0;
49        let res = unsafe {
50            WriteFile(
51                self.fd.as_fd().as_raw_fd(),
52                slice.as_ptr() as _,
53                slice.len().try_into().unwrap_or(u32::MAX),
54                &mut transferred,
55                optr,
56            )
57        };
58        win32_result(res, transferred)
59    }
60
61    fn cancel(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> io::Result<()> {
62        cancel(self.fd.as_fd().as_raw_fd(), optr)
63    }
64}
65
66unsafe impl<T: IoBufMut, S: AsFd> OpCode for Read<T, S> {
67    type Control = ();
68
69    unsafe fn operate(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
70        let fd = self.fd.as_fd().as_raw_fd();
71        let mut transferred = 0;
72        let slice = self.buffer.sys_slice_mut();
73        let res = unsafe {
74            ReadFile(
75                fd,
76                slice.ptr() as _,
77                slice.len() as _,
78                &mut transferred,
79                optr,
80            )
81        };
82        win32_result(res, transferred)
83    }
84
85    fn cancel(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> io::Result<()> {
86        cancel(self.fd.as_fd().as_raw_fd(), optr)
87    }
88}
89
90unsafe impl<T: IoBuf, S: AsFd> OpCode for Write<T, S> {
91    type Control = ();
92
93    unsafe fn operate(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
94        let slice = self.buffer.as_init();
95        let mut transferred = 0;
96        let res = unsafe {
97            WriteFile(
98                self.fd.as_fd().as_raw_fd(),
99                slice.as_ptr() as _,
100                slice.len().try_into().unwrap_or(u32::MAX),
101                &mut transferred,
102                optr,
103            )
104        };
105        win32_result(res, transferred)
106    }
107
108    fn cancel(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> io::Result<()> {
109        cancel(self.fd.as_fd().as_raw_fd(), optr)
110    }
111}
112
113/// Connect to a named pipe.
114pub struct ConnectNamedPipe<S> {
115    pub(crate) fd: S,
116}
117
118impl<S> ConnectNamedPipe<S> {
119    /// Create [`ConnectNamedPipe`](struct@ConnectNamedPipe).
120    pub fn new(fd: S) -> Self {
121        Self { fd }
122    }
123}
124
125unsafe impl<S: AsFd> OpCode for ConnectNamedPipe<S> {
126    type Control = ();
127
128    unsafe fn operate(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
129        let res = unsafe { ConnectNamedPipe(self.fd.as_fd().as_raw_fd() as _, optr) };
130        win32_result(res, 0)
131    }
132
133    fn cancel(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> io::Result<()> {
134        cancel(self.fd.as_fd().as_raw_fd(), optr)
135    }
136}
137
138/// Send a control code to a device.
139#[doc(hidden)]
140pub struct DeviceIoControl<S, I: IoBuf, O: IoBufMut> {
141    pub(crate) fd: S,
142    pub(crate) ioctl_code: u32,
143    pub(crate) input_buffer: Option<I>,
144    pub(crate) output_buffer: Option<O>,
145}
146
147impl<S, I: IoBuf, O: IoBufMut> DeviceIoControl<S, I, O> {
148    /// Create [`DeviceIoControl`].
149    pub fn new(fd: S, ioctl_code: u32, input_buffer: Option<I>, output_buffer: Option<O>) -> Self {
150        Self {
151            fd,
152            ioctl_code,
153            input_buffer,
154            output_buffer,
155        }
156    }
157}
158
159impl<S, I: IoBuf, O: IoBufMut> IntoInner for DeviceIoControl<S, I, O> {
160    type Inner = (Option<I>, Option<O>);
161
162    fn into_inner(self) -> Self::Inner {
163        (self.input_buffer, self.output_buffer)
164    }
165}
166
167unsafe impl<S: AsFd, I: IoBuf, O: IoBufMut> OpCode for DeviceIoControl<S, I, O> {
168    type Control = ();
169
170    unsafe fn operate(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
171        let fd = self.fd.as_fd().as_raw_fd();
172
173        let input = self
174            .input_buffer
175            .as_ref()
176            .map_or(SysSlice::null(), |x| x.sys_slice());
177        let output = self
178            .output_buffer
179            .as_mut()
180            .map_or(SysSlice::null(), |x| x.sys_slice_mut());
181
182        let mut transferred = 0;
183        let res = unsafe {
184            DeviceIoControl(
185                fd,
186                self.ioctl_code,
187                input.ptr() as _,
188                input.len() as _,
189                output.ptr() as _,
190                output.len() as _,
191                &mut transferred,
192                optr,
193            )
194        };
195        win32_result(res, transferred)
196    }
197
198    fn cancel(&mut self, _: &mut (), optr: *mut OVERLAPPED) -> io::Result<()> {
199        cancel(self.fd.as_fd().as_raw_fd(), optr)
200    }
201}