Skip to content

Commit 6ce408c

Browse files
committed
Windows: Fallback for overlapped I/O
Try waiting on the file handle once. If that fails then give up.
1 parent bc16cd3 commit 6ce408c

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

std/src/sys/windows/c.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,9 @@ union IO_STATUS_BLOCK_union {
326326
}
327327
impl Default for IO_STATUS_BLOCK_union {
328328
fn default() -> Self {
329-
Self { Pointer: ptr::null_mut() }
329+
let mut this = Self { Pointer: ptr::null_mut() };
330+
this.Status = STATUS_PENDING;
331+
this
330332
}
331333
}
332334
#[repr(C)]
@@ -335,6 +337,16 @@ pub struct IO_STATUS_BLOCK {
335337
u: IO_STATUS_BLOCK_union,
336338
pub Information: usize,
337339
}
340+
impl IO_STATUS_BLOCK {
341+
pub fn status(&self) -> NTSTATUS {
342+
// SAFETY: If `self.u.Status` was set then this is obviously safe.
343+
// If `self.u.Pointer` was set then this is the equivalent to converting
344+
// the pointer to an integer, which is also safe.
345+
// Currently the only safe way to construct `IO_STATUS_BLOCK` outside of
346+
// this module is to call the `default` method, which sets the `Status`.
347+
unsafe { self.u.Status }
348+
}
349+
}
338350

339351
pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn(
340352
dwErrorCode: DWORD,

std/src/sys/windows/handle.rs

+13
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,13 @@ impl Handle {
248248
offset.map(|n| n as _).as_ref(),
249249
None,
250250
);
251+
252+
let status = if status == c::STATUS_PENDING {
253+
c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE);
254+
io_status.status()
255+
} else {
256+
status
257+
};
251258
match status {
252259
// If the operation has not completed then abort the process.
253260
// Doing otherwise means that the buffer and stack may be written to
@@ -291,6 +298,12 @@ impl Handle {
291298
None,
292299
)
293300
};
301+
let status = if status == c::STATUS_PENDING {
302+
unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
303+
io_status.status()
304+
} else {
305+
status
306+
};
294307
match status {
295308
// If the operation has not completed then abort the process.
296309
// Doing otherwise means that the buffer may be read and the stack

0 commit comments

Comments
 (0)