about summary refs log tree commit diff
path: root/library/std/src/sys/pal/windows/pipe.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/pal/windows/pipe.rs')
-rw-r--r--library/std/src/sys/pal/windows/pipe.rs45
1 files changed, 23 insertions, 22 deletions
diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs
index d5e2356116f..01433d68b69 100644
--- a/library/std/src/sys/pal/windows/pipe.rs
+++ b/library/std/src/sys/pal/windows/pipe.rs
@@ -238,15 +238,6 @@ fn random_number() -> usize {
     }
 }
 
-// Abstracts over `ReadFileEx` and `WriteFileEx`
-type AlertableIoFn = unsafe extern "system" fn(
-    BorrowedHandle<'_>,
-    *mut core::ffi::c_void,
-    u32,
-    *mut c::OVERLAPPED,
-    c::LPOVERLAPPED_COMPLETION_ROUTINE,
-) -> c::BOOL;
-
 impl AnonPipe {
     pub fn handle(&self) -> &Handle {
         &self.inner
@@ -262,7 +253,10 @@ impl AnonPipe {
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let result = unsafe {
             let len = crate::cmp::min(buf.len(), u32::MAX as usize) as u32;
-            self.alertable_io_internal(c::ReadFileEx, buf.as_mut_ptr() as _, len)
+            let ptr = buf.as_mut_ptr();
+            self.alertable_io_internal(|overlapped, callback| {
+                c::ReadFileEx(self.inner.as_raw_handle(), ptr, len, overlapped, callback)
+            })
         };
 
         match result {
@@ -278,7 +272,10 @@ impl AnonPipe {
     pub fn read_buf(&self, mut buf: BorrowedCursor<'_>) -> io::Result<()> {
         let result = unsafe {
             let len = crate::cmp::min(buf.capacity(), u32::MAX as usize) as u32;
-            self.alertable_io_internal(c::ReadFileEx, buf.as_mut().as_mut_ptr() as _, len)
+            let ptr = buf.as_mut().as_mut_ptr().cast::<u8>();
+            self.alertable_io_internal(|overlapped, callback| {
+                c::ReadFileEx(self.inner.as_raw_handle(), ptr, len, overlapped, callback)
+            })
         };
 
         match result {
@@ -313,7 +310,9 @@ impl AnonPipe {
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         unsafe {
             let len = crate::cmp::min(buf.len(), u32::MAX as usize) as u32;
-            self.alertable_io_internal(c::WriteFileEx, buf.as_ptr() as _, len)
+            self.alertable_io_internal(|overlapped, callback| {
+                c::WriteFileEx(self.inner.as_raw_handle(), buf.as_ptr(), len, overlapped, callback)
+            })
         }
     }
 
@@ -341,12 +340,9 @@ impl AnonPipe {
     /// [`ReadFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfileex
     /// [`WriteFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefileex
     /// [Asynchronous Procedure Call]: https://docs.microsoft.com/en-us/windows/win32/sync/asynchronous-procedure-calls
-    #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn alertable_io_internal(
         &self,
-        io: AlertableIoFn,
-        buf: *mut core::ffi::c_void,
-        len: u32,
+        io: impl FnOnce(&mut c::OVERLAPPED, c::LPOVERLAPPED_COMPLETION_ROUTINE) -> c::BOOL,
     ) -> io::Result<usize> {
         // Use "alertable I/O" to synchronize the pipe I/O.
         // This has four steps.
@@ -384,20 +380,25 @@ impl AnonPipe {
             lpOverlapped: *mut c::OVERLAPPED,
         ) {
             // Set `async_result` using a pointer smuggled through `hEvent`.
-            let result =
-                AsyncResult { error: dwErrorCode, transferred: dwNumberOfBytesTransferred };
-            *(*lpOverlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result);
+            // SAFETY:
+            // At this point, the OVERLAPPED struct will have been written to by the OS,
+            // except for our `hEvent` field which we set to a valid AsyncResult pointer (see below)
+            unsafe {
+                let result =
+                    AsyncResult { error: dwErrorCode, transferred: dwNumberOfBytesTransferred };
+                *(*lpOverlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result);
+            }
         }
 
         // STEP 1: Start the I/O operation.
-        let mut overlapped: c::OVERLAPPED = crate::mem::zeroed();
+        let mut overlapped: c::OVERLAPPED = unsafe { crate::mem::zeroed() };
         // `hEvent` is unused by `ReadFileEx` and `WriteFileEx`.
         // Therefore the documentation suggests using it to smuggle a pointer to the callback.
         overlapped.hEvent = core::ptr::addr_of_mut!(async_result) as *mut _;
 
         // Asynchronous read of the pipe.
         // If successful, `callback` will be called once it completes.
-        let result = io(self.inner.as_handle(), buf, len, &mut overlapped, Some(callback));
+        let result = io(&mut overlapped, Some(callback));
         if result == c::FALSE {
             // We can return here because the call failed.
             // After this we must not return until the I/O completes.
@@ -408,7 +409,7 @@ impl AnonPipe {
         let result = loop {
             // STEP 2: Enter an alertable state.
             // The second parameter of `SleepEx` is used to make this sleep alertable.
-            c::SleepEx(c::INFINITE, c::TRUE);
+            unsafe { c::SleepEx(c::INFINITE, c::TRUE) };
             if let Some(result) = async_result {
                 break result;
             }