Make synchronous_write safe to call

This commit is contained in:
Chris Denton 2022-04-04 06:08:16 +01:00
parent 084b71a54f
commit 88c05edc9d
No known key found for this signature in database
GPG Key ID: 713472F2F45627DE
2 changed files with 18 additions and 23 deletions

View File

@ -986,13 +986,6 @@ extern "system" {
lpOverlapped: LPOVERLAPPED, lpOverlapped: LPOVERLAPPED,
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
) -> BOOL; ) -> BOOL;
pub fn WriteFile(
hFile: BorrowedHandle<'_>,
lpBuffer: LPVOID,
nNumberOfBytesToWrite: DWORD,
lpNumberOfBytesWritten: LPDWORD,
lpOverlapped: LPOVERLAPPED,
) -> BOOL;
pub fn WriteFileEx( pub fn WriteFileEx(
hFile: BorrowedHandle<'_>, hFile: BorrowedHandle<'_>,
lpBuffer: LPVOID, lpBuffer: LPVOID,

View File

@ -192,7 +192,7 @@ impl Handle {
} }
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
unsafe { self.synchronous_write(&buf, None) } self.synchronous_write(&buf, None)
} }
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
@ -205,7 +205,7 @@ impl Handle {
} }
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
unsafe { self.synchronous_write(&buf, Some(offset)) } self.synchronous_write(&buf, Some(offset))
} }
pub fn try_clone(&self) -> io::Result<Self> { pub fn try_clone(&self) -> io::Result<Self> {
@ -276,12 +276,13 @@ impl Handle {
/// See #81357. /// See #81357.
/// ///
/// If `offset` is `None` then the current file position is used. /// If `offset` is `None` then the current file position is used.
unsafe fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> { fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> {
let mut io_status = c::IO_STATUS_BLOCK::default(); let mut io_status = c::IO_STATUS_BLOCK::default();
// The length is clamped at u32::MAX. // The length is clamped at u32::MAX.
let len = cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD; let len = cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD;
let status = c::NtWriteFile( let status = unsafe {
c::NtWriteFile(
self.as_handle(), self.as_handle(),
ptr::null_mut(), ptr::null_mut(),
None, None,
@ -291,7 +292,8 @@ impl Handle {
len, len,
offset.map(|n| n as _).as_ref(), offset.map(|n| n as _).as_ref(),
None, None,
); )
};
match status { match status {
// If the operation has not completed then abort the process. // If the operation has not completed then abort the process.
// Doing otherwise means that the buffer may be read and the stack // Doing otherwise means that the buffer may be read and the stack
@ -305,7 +307,7 @@ impl Handle {
status if c::nt_success(status) => Ok(io_status.Information), status if c::nt_success(status) => Ok(io_status.Information),
status => { status => {
let error = c::RtlNtStatusToDosError(status); let error = unsafe { c::RtlNtStatusToDosError(status) };
Err(io::Error::from_raw_os_error(error as _)) Err(io::Error::from_raw_os_error(error as _))
} }
} }