Windows: Fallback for overlapped I/O

Try waiting on the file handle once. If that fails then give up.
This commit is contained in:
Chris Denton 2022-07-06 16:38:35 +01:00
parent ae60dbdcac
commit 3ae47e76a8
No known key found for this signature in database
GPG Key ID: 713472F2F45627DE
2 changed files with 26 additions and 1 deletions

View File

@ -326,7 +326,9 @@ union IO_STATUS_BLOCK_union {
} }
impl Default for IO_STATUS_BLOCK_union { impl Default for IO_STATUS_BLOCK_union {
fn default() -> Self { fn default() -> Self {
Self { Pointer: ptr::null_mut() } let mut this = Self { Pointer: ptr::null_mut() };
this.Status = STATUS_PENDING;
this
} }
} }
#[repr(C)] #[repr(C)]
@ -335,6 +337,16 @@ pub struct IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_union, u: IO_STATUS_BLOCK_union,
pub Information: usize, pub Information: usize,
} }
impl IO_STATUS_BLOCK {
pub fn status(&self) -> NTSTATUS {
// SAFETY: If `self.u.Status` was set then this is obviously safe.
// If `self.u.Pointer` was set then this is the equivalent to converting
// the pointer to an integer, which is also safe.
// Currently the only safe way to construct `IO_STATUS_BLOCK` outside of
// this module is to call the `default` method, which sets the `Status`.
unsafe { self.u.Status }
}
}
pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn( pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn(
dwErrorCode: DWORD, dwErrorCode: DWORD,

View File

@ -248,6 +248,13 @@ unsafe fn synchronous_read(
offset.map(|n| n as _).as_ref(), offset.map(|n| n as _).as_ref(),
None, None,
); );
let status = if status == c::STATUS_PENDING {
c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE);
io_status.status()
} else {
status
};
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 and stack may be written to // Doing otherwise means that the buffer and stack may be written to
@ -291,6 +298,12 @@ fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize
None, None,
) )
}; };
let status = if status == c::STATUS_PENDING {
unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
io_status.status()
} else {
status
};
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