Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove wrapper functions from c.rs #128092

Merged
merged 1 commit into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 12 additions & 96 deletions library/std/src/sys/pal/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use crate::ffi::CStr;
use crate::mem;
use crate::os::raw::{c_uint, c_ulong, c_ushort, c_void};
use crate::os::windows::io::{AsRawHandle, BorrowedHandle};
use crate::ptr;

pub(super) mod windows_targets;
Expand Down Expand Up @@ -114,89 +113,6 @@ if #[cfg(not(target_vendor = "uwp"))] {
}
}

pub unsafe extern "system" fn WriteFileEx(
hFile: BorrowedHandle<'_>,
lpBuffer: *mut ::core::ffi::c_void,
nNumberOfBytesToWrite: u32,
lpOverlapped: *mut OVERLAPPED,
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
) -> BOOL {
windows_sys::WriteFileEx(
hFile.as_raw_handle(),
lpBuffer.cast::<u8>(),
nNumberOfBytesToWrite,
lpOverlapped,
lpCompletionRoutine,
)
}

pub unsafe extern "system" fn ReadFileEx(
hFile: BorrowedHandle<'_>,
lpBuffer: *mut ::core::ffi::c_void,
nNumberOfBytesToRead: u32,
lpOverlapped: *mut OVERLAPPED,
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
) -> BOOL {
windows_sys::ReadFileEx(
hFile.as_raw_handle(),
lpBuffer.cast::<u8>(),
nNumberOfBytesToRead,
lpOverlapped,
lpCompletionRoutine,
)
}

cfg_if::cfg_if! {
if #[cfg(not(target_vendor = "uwp"))] {
pub unsafe fn NtReadFile(
filehandle: BorrowedHandle<'_>,
event: HANDLE,
apcroutine: PIO_APC_ROUTINE,
apccontext: *mut c_void,
iostatusblock: &mut IO_STATUS_BLOCK,
buffer: *mut crate::mem::MaybeUninit<u8>,
length: u32,
byteoffset: Option<&i64>,
key: Option<&u32>,
) -> NTSTATUS {
windows_sys::NtReadFile(
filehandle.as_raw_handle(),
event,
apcroutine,
apccontext,
iostatusblock,
buffer.cast::<c_void>(),
length,
byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()),
key.map(|k| k as *const u32).unwrap_or(ptr::null()),
)
}
pub unsafe fn NtWriteFile(
filehandle: BorrowedHandle<'_>,
event: HANDLE,
apcroutine: PIO_APC_ROUTINE,
apccontext: *mut c_void,
iostatusblock: &mut IO_STATUS_BLOCK,
buffer: *const u8,
length: u32,
byteoffset: Option<&i64>,
key: Option<&u32>,
) -> NTSTATUS {
windows_sys::NtWriteFile(
filehandle.as_raw_handle(),
event,
apcroutine,
apccontext,
iostatusblock,
buffer.cast::<c_void>(),
length,
byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()),
key.map(|k| k as *const u32).unwrap_or(ptr::null()),
)
}
}
}

// Use raw-dylib to import ProcessPrng as we can't rely on there being an import library.
cfg_if::cfg_if! {
if #[cfg(not(target_vendor = "win7"))] {
Expand Down Expand Up @@ -331,29 +247,29 @@ compat_fn_with_fallback! {
}
#[cfg(target_vendor = "uwp")]
pub fn NtReadFile(
filehandle: BorrowedHandle<'_>,
filehandle: HANDLE,
event: HANDLE,
apcroutine: PIO_APC_ROUTINE,
apccontext: *mut c_void,
iostatusblock: &mut IO_STATUS_BLOCK,
buffer: *mut crate::mem::MaybeUninit<u8>,
apccontext: *const core::ffi::c_void,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add core::ffi to the module imports here?

iostatusblock: *mut IO_STATUS_BLOCK,
buffer: *mut core::ffi::c_void,
length: u32,
byteoffset: Option<&i64>,
key: Option<&u32>
Comment on lines -341 to -342
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these lifetimes would have been very useful if the thing we returned also had a lifetime... unfortunately...

byteoffset: *const i64,
key: *const u32
) -> NTSTATUS {
STATUS_NOT_IMPLEMENTED
}
#[cfg(target_vendor = "uwp")]
pub fn NtWriteFile(
filehandle: BorrowedHandle<'_>,
filehandle: HANDLE,
event: HANDLE,
apcroutine: PIO_APC_ROUTINE,
apccontext: *mut c_void,
iostatusblock: &mut IO_STATUS_BLOCK,
buffer: *const u8,
apccontext: *const core::ffi::c_void,
iostatusblock: *mut IO_STATUS_BLOCK,
buffer: *const core::ffi::c_void,
length: u32,
byteoffset: Option<&i64>,
key: Option<&u32>
byteoffset: *const i64,
key: *const u32
) -> NTSTATUS {
STATUS_NOT_IMPLEMENTED
}
Expand Down
16 changes: 8 additions & 8 deletions library/std/src/sys/pal/windows/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,15 +243,15 @@ impl Handle {
// the provided `len`.
let status = unsafe {
c::NtReadFile(
self.as_handle(),
self.as_raw_handle(),
ptr::null_mut(),
None,
ptr::null_mut(),
&mut io_status,
buf,
buf.cast::<core::ffi::c_void>(),
len,
offset.map(|n| n as _).as_ref(),
None,
offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
ptr::null(),
)
};

Expand Down Expand Up @@ -293,15 +293,15 @@ impl Handle {
let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
let status = unsafe {
c::NtWriteFile(
self.as_handle(),
self.as_raw_handle(),
ptr::null_mut(),
None,
ptr::null_mut(),
&mut io_status,
buf.as_ptr(),
buf.as_ptr().cast::<core::ffi::c_void>(),
len,
offset.map(|n| n as _).as_ref(),
None,
offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
ptr::null(),
)
};
let status = if status == c::STATUS_PENDING {
Expand Down
45 changes: 23 additions & 22 deletions library/std/src/sys/pal/windows/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,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
Expand All @@ -244,7 +235,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 {
Expand All @@ -260,7 +254,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 {
Expand Down Expand Up @@ -295,7 +292,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)
})
}
}

Expand Down Expand Up @@ -323,12 +322,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.
Expand Down Expand Up @@ -366,20 +362,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.
Expand All @@ -390,7 +391,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;
}
Expand Down
Loading