Skip to content
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
116 changes: 76 additions & 40 deletions crates/stdlib/src/overlapped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod _overlapped {
convert::{ToPyException, ToPyObject},
function::OptionalArg,
protocol::PyBuffer,
types::Constructor,
types::{Constructor, Destructor},
};
use windows_sys::Win32::{
Foundation::{self, GetLastError, HANDLE},
Expand Down Expand Up @@ -235,14 +235,8 @@ mod _overlapped {
}

fn from_windows_err(err: u32, vm: &VirtualMachine) -> PyBaseExceptionRef {
use Foundation::{ERROR_CONNECTION_ABORTED, ERROR_CONNECTION_REFUSED};
debug_assert_ne!(err, 0, "call errno_err instead");
let exc = match err {
ERROR_CONNECTION_REFUSED => vm.ctx.exceptions.connection_refused_error,
ERROR_CONNECTION_ABORTED => vm.ctx.exceptions.connection_aborted_error,
err => return std::io::Error::from_raw_os_error(err as i32).to_pyexception(vm),
};
vm.new_exception_empty(exc.to_owned())
std::io::Error::from_raw_os_error(err as i32).to_pyexception(vm)
}

fn HasOverlappedIoCompleted(overlapped: &OVERLAPPED) -> bool {
Expand Down Expand Up @@ -383,7 +377,7 @@ mod _overlapped {
}
}

#[pyclass(with(Constructor))]
#[pyclass(with(Constructor, Destructor))]
impl Overlapped {
#[pygetset]
fn address(&self, _vm: &VirtualMachine) -> usize {
Expand Down Expand Up @@ -438,7 +432,6 @@ mod _overlapped {
use windows_sys::Win32::Foundation::{
ERROR_BROKEN_PIPE, ERROR_IO_PENDING, ERROR_MORE_DATA, ERROR_SUCCESS,
};
use windows_sys::Win32::System::IO::GetOverlappedResult;

let mut inner = zelf.inner.lock();
let wait = wait.unwrap_or(false);
Expand All @@ -454,7 +447,7 @@ mod _overlapped {
// Get the result
let mut transferred: u32 = 0;
let ret = unsafe {
GetOverlappedResult(
windows_sys::Win32::System::IO::GetOverlappedResult(
inner.handle,
&inner.overlapped,
&mut transferred,
Expand Down Expand Up @@ -1190,35 +1183,6 @@ mod _overlapped {
}
}

// ConnectPipe - this is a static method that returns a handle
#[pymethod]
fn ConnectPipe(address: String, vm: &VirtualMachine) -> PyResult<isize> {
use windows_sys::Win32::Storage::FileSystem::{
CreateFileW, FILE_FLAG_OVERLAPPED, FILE_GENERIC_READ, FILE_GENERIC_WRITE,
OPEN_EXISTING,
};

let address_wide: Vec<u16> = address.encode_utf16().chain(std::iter::once(0)).collect();

let handle = unsafe {
CreateFileW(
address_wide.as_ptr(),
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
0,
std::ptr::null(),
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
std::ptr::null_mut(),
)
};

if handle == windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE {
return Err(vm.new_last_os_error());
}

Ok(handle as isize)
}

// WSASendTo
#[pymethod]
fn WSASendTo(
Expand Down Expand Up @@ -1508,6 +1472,78 @@ mod _overlapped {
}
}

impl Destructor for Overlapped {
fn del(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
use windows_sys::Win32::System::IO::{CancelIoEx, GetOverlappedResult};

let mut inner = zelf.inner.lock();
let olderr = unsafe { GetLastError() };

// Cancel pending I/O and wait for completion
if !HasOverlappedIoCompleted(&inner.overlapped)
&& !matches!(
inner.data,
OverlappedData::None | OverlappedData::NotStarted
)
{
let cancelled = unsafe { CancelIoEx(inner.handle, &inner.overlapped) } != 0;

if cancelled {
// Wait for the cancellation to complete
let mut transferred: u32 = 0;
unsafe {
GetOverlappedResult(
inner.handle,
&inner.overlapped,
&mut transferred,
1, // bWait = TRUE
)
};
}
}

// Close the event handle
if !inner.overlapped.hEvent.is_null() {
unsafe {
Foundation::CloseHandle(inner.overlapped.hEvent);
}
inner.overlapped.hEvent = std::ptr::null_mut();
}

// Restore last error
unsafe { Foundation::SetLastError(olderr) };

Ok(())
}
}

#[pyfunction]
fn ConnectPipe(address: String, vm: &VirtualMachine) -> PyResult<isize> {
use windows_sys::Win32::Storage::FileSystem::{
CreateFileW, FILE_FLAG_OVERLAPPED, FILE_GENERIC_READ, FILE_GENERIC_WRITE, OPEN_EXISTING,
};

let address_wide: Vec<u16> = address.encode_utf16().chain(std::iter::once(0)).collect();

let handle = unsafe {
CreateFileW(
address_wide.as_ptr(),
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
0,
std::ptr::null(),
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
std::ptr::null_mut(),
)
};

if handle == windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE {
return Err(vm.new_last_os_error());
}

Ok(handle as isize)
}

#[pyfunction]
fn CreateIoCompletionPort(
handle: isize,
Expand Down
1 change: 1 addition & 0 deletions crates/vm/src/stdlib/winapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ mod _winapi {
SEC_LARGE_PAGES, SEC_NOCACHE, SEC_RESERVE, SEC_WRITECOMBINE,
},
Pipes::{
NMPWAIT_NOWAIT, NMPWAIT_USE_DEFAULT_WAIT, NMPWAIT_WAIT_FOREVER,
PIPE_READMODE_MESSAGE, PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_WAIT,
},
SystemServices::LOCALE_NAME_MAX_LENGTH,
Expand Down
Loading