diff --git a/vm/Cargo.toml b/vm/Cargo.toml index ec1190d16..ed226016e 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -130,8 +130,10 @@ features = [ "Win32_System_Console", "Win32_System_LibraryLoader", "Win32_System_Pipes", + "Win32_System_SystemServices", "Win32_System_Threading", "Win32_UI_Shell", + "Win32_UI_WindowsAndMessaging", ] [target.'cfg(windows)'.dependencies.winapi] diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 71ca05369..aae29a9a2 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -79,6 +79,8 @@ pub mod utils; pub mod version; pub mod vm; pub mod warn; +#[cfg(windows)] +pub mod windows; pub use self::compiler::parser::source_code; pub use self::convert::{TryFromBorrowedObject, TryFromObject}; diff --git a/vm/src/stdlib/winapi.rs b/vm/src/stdlib/winapi.rs index 34ec94153..ed88fabce 100644 --- a/vm/src/stdlib/winapi.rs +++ b/vm/src/stdlib/winapi.rs @@ -6,13 +6,13 @@ mod _winapi { use crate::{ builtins::PyStrRef, common::windows::ToWideString, - convert::{ToPyException, ToPyObject, ToPyResult}, + convert::{ToPyException, ToPyResult}, function::{ArgMapping, ArgSequence, OptionalArg}, stdlib::os::errno_err, + windows::WindowsSysResult, PyObjectRef, PyResult, TryFromObject, VirtualMachine, }; use std::ptr::{null, null_mut}; - use winapi::um::winbase; use windows::{ core::PCWSTR, Win32::Foundation::{HANDLE, HINSTANCE, MAX_PATH}, @@ -20,109 +20,43 @@ mod _winapi { use windows_sys::Win32::Foundation::{BOOL, HANDLE as RAW_HANDLE}; #[pyattr] - use winapi::{ - shared::winerror::{ - ERROR_ALREADY_EXISTS, ERROR_BROKEN_PIPE, ERROR_IO_PENDING, ERROR_MORE_DATA, - ERROR_NETNAME_DELETED, ERROR_NO_DATA, ERROR_NO_SYSTEM_RESOURCES, - ERROR_OPERATION_ABORTED, ERROR_PIPE_BUSY, ERROR_PIPE_CONNECTED, ERROR_SEM_TIMEOUT, - WAIT_TIMEOUT, + use windows_sys::Win32::{ + Foundation::{ + DUPLICATE_CLOSE_SOURCE, DUPLICATE_SAME_ACCESS, ERROR_ALREADY_EXISTS, ERROR_BROKEN_PIPE, + ERROR_IO_PENDING, ERROR_MORE_DATA, ERROR_NETNAME_DELETED, ERROR_NO_DATA, + ERROR_NO_SYSTEM_RESOURCES, ERROR_OPERATION_ABORTED, ERROR_PIPE_BUSY, + ERROR_PIPE_CONNECTED, ERROR_SEM_TIMEOUT, GENERIC_READ, GENERIC_WRITE, STILL_ACTIVE, + WAIT_ABANDONED, WAIT_ABANDONED_0, WAIT_OBJECT_0, WAIT_TIMEOUT, }, - um::{ - fileapi::OPEN_EXISTING, - memoryapi::{ - FILE_MAP_ALL_ACCESS, FILE_MAP_COPY, FILE_MAP_EXECUTE, FILE_MAP_READ, FILE_MAP_WRITE, + Storage::FileSystem::{ + FILE_FLAG_FIRST_PIPE_INSTANCE, FILE_FLAG_OVERLAPPED, FILE_GENERIC_READ, + FILE_GENERIC_WRITE, FILE_TYPE_CHAR, FILE_TYPE_DISK, FILE_TYPE_PIPE, FILE_TYPE_REMOTE, + FILE_TYPE_UNKNOWN, OPEN_EXISTING, PIPE_ACCESS_DUPLEX, PIPE_ACCESS_INBOUND, SYNCHRONIZE, + }, + System::{ + Console::{STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE}, + Memory::{ + FILE_MAP_ALL_ACCESS, MEM_COMMIT, MEM_FREE, MEM_IMAGE, MEM_MAPPED, MEM_PRIVATE, + MEM_RESERVE, PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, + PAGE_EXECUTE_WRITECOPY, PAGE_GUARD, PAGE_NOACCESS, PAGE_NOCACHE, PAGE_READONLY, + PAGE_READWRITE, PAGE_WRITECOMBINE, PAGE_WRITECOPY, SEC_COMMIT, SEC_IMAGE, + SEC_LARGE_PAGES, SEC_NOCACHE, SEC_RESERVE, SEC_WRITECOMBINE, }, - minwinbase::STILL_ACTIVE, - winbase::{ + Pipes::{ + PIPE_READMODE_MESSAGE, PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_WAIT, + }, + SystemServices::LOCALE_NAME_MAX_LENGTH, + Threading::{ ABOVE_NORMAL_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS, CREATE_BREAKAWAY_FROM_JOB, CREATE_DEFAULT_ERROR_MODE, CREATE_NEW_CONSOLE, - CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW, DETACHED_PROCESS, - FILE_FLAG_FIRST_PIPE_INSTANCE, FILE_FLAG_OVERLAPPED, FILE_TYPE_CHAR, - FILE_TYPE_DISK, FILE_TYPE_PIPE, FILE_TYPE_REMOTE, FILE_TYPE_UNKNOWN, - HIGH_PRIORITY_CLASS, IDLE_PRIORITY_CLASS, INFINITE, NORMAL_PRIORITY_CLASS, - PIPE_ACCESS_DUPLEX, PIPE_ACCESS_INBOUND, PIPE_READMODE_MESSAGE, PIPE_TYPE_MESSAGE, - PIPE_UNLIMITED_INSTANCES, PIPE_WAIT, REALTIME_PRIORITY_CLASS, STARTF_USESHOWWINDOW, - STARTF_USESTDHANDLES, STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, - WAIT_ABANDONED, WAIT_ABANDONED_0, WAIT_OBJECT_0, + CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW, DETACHED_PROCESS, HIGH_PRIORITY_CLASS, + IDLE_PRIORITY_CLASS, INFINITE, NORMAL_PRIORITY_CLASS, PROCESS_DUP_HANDLE, + REALTIME_PRIORITY_CLASS, STARTF_USESHOWWINDOW, STARTF_USESTDHANDLES, }, - winnt::{ - DUPLICATE_CLOSE_SOURCE, DUPLICATE_SAME_ACCESS, FILE_GENERIC_READ, - FILE_GENERIC_WRITE, GENERIC_READ, GENERIC_WRITE, LOCALE_NAME_MAX_LENGTH, - MEM_COMMIT, MEM_FREE, MEM_IMAGE, MEM_MAPPED, MEM_PRIVATE, MEM_RESERVE, - PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY, - PAGE_GUARD, PAGE_NOACCESS, PAGE_NOCACHE, PAGE_READONLY, PAGE_READWRITE, - PAGE_WRITECOMBINE, PAGE_WRITECOPY, PROCESS_DUP_HANDLE, SEC_COMMIT, SEC_IMAGE, - SEC_LARGE_PAGES, SEC_NOCACHE, SEC_RESERVE, SEC_WRITECOMBINE, SYNCHRONIZE, - }, - winuser::SW_HIDE, }, + UI::WindowsAndMessaging::SW_HIDE, }; - fn GetLastError() -> u32 { - unsafe { winapi::um::errhandlingapi::GetLastError() } - } - - trait WindowsSysResultValue { - type Ok: ToPyObject; - fn is_err(&self) -> bool; - fn into_ok(self) -> Self::Ok; - } - - impl WindowsSysResultValue for RAW_HANDLE { - type Ok = HANDLE; - fn is_err(&self) -> bool { - *self == windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE - } - fn into_ok(self) -> Self::Ok { - HANDLE(self) - } - } - - impl WindowsSysResultValue for BOOL { - type Ok = (); - fn is_err(&self) -> bool { - *self == 0 - } - fn into_ok(self) -> Self::Ok {} - } - - struct WindowsSysResult(T); - - impl WindowsSysResult { - fn is_err(&self) -> bool { - self.0.is_err() - } - fn into_pyresult(self, vm: &VirtualMachine) -> PyResult { - if self.is_err() { - Err(errno_err(vm)) - } else { - Ok(self.0.into_ok()) - } - } - } - - impl ToPyResult for WindowsSysResult { - fn to_pyresult(self, vm: &VirtualMachine) -> PyResult { - let ok = self.into_pyresult(vm)?; - Ok(ok.to_pyobject(vm)) - } - } - - type HandleInt = usize; // TODO: change to isize when fully ported to windows-rs - - impl TryFromObject for HANDLE { - fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - let handle = HandleInt::try_from_object(vm, obj)?; - Ok(HANDLE(handle as isize)) - } - } - - impl ToPyObject for HANDLE { - fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { - (self.0 as HandleInt).to_pyobject(vm) - } - } - #[pyfunction] fn CloseHandle(handle: HANDLE) -> WindowsSysResult { WindowsSysResult(unsafe { windows_sys::Win32::Foundation::CloseHandle(handle.0) }) @@ -193,7 +127,7 @@ mod _winapi { vm: &VirtualMachine, ) -> PyResult { let file_type = unsafe { windows_sys::Win32::Storage::FileSystem::GetFileType(h.0) }; - if file_type == 0 && GetLastError() != 0 { + if file_type == 0 && unsafe { windows_sys::Win32::Foundation::GetLastError() } != 0 { Err(errno_err(vm)) } else { Ok(file_type) @@ -227,7 +161,8 @@ mod _winapi { args: CreateProcessArgs, vm: &VirtualMachine, ) -> PyResult<(HANDLE, HANDLE, u32, u32)> { - let mut si = winbase::STARTUPINFOEXW::default(); + let mut si: windows_sys::Win32::System::Threading::STARTUPINFOEXW = + unsafe { std::mem::zeroed() }; si.StartupInfo.cb = std::mem::size_of_val(&si) as _; macro_rules! si_attr { @@ -292,11 +227,11 @@ mod _winapi { std::ptr::null(), args.inherit_handles, args.creation_flags - | winbase::EXTENDED_STARTUPINFO_PRESENT - | winbase::CREATE_UNICODE_ENVIRONMENT, + | windows_sys::Win32::System::Threading::EXTENDED_STARTUPINFO_PRESENT + | windows_sys::Win32::System::Threading::CREATE_UNICODE_ENVIRONMENT, env as _, current_dir, - &mut si as *mut winbase::STARTUPINFOEXW as _, + &mut si as *mut _ as *mut _, procinfo.as_mut_ptr(), )) .into_pyresult(vm)?; @@ -390,7 +325,8 @@ mod _winapi { (result, size.assume_init()) }; if !result.is_err() - || GetLastError() != winapi::shared::winerror::ERROR_INSUFFICIENT_BUFFER + || unsafe { windows_sys::Win32::Foundation::GetLastError() } + != windows_sys::Win32::Foundation::ERROR_INSUFFICIENT_BUFFER { return Err(errno_err(vm)); } diff --git a/vm/src/windows.rs b/vm/src/windows.rs new file mode 100644 index 000000000..9216f839f --- /dev/null +++ b/vm/src/windows.rs @@ -0,0 +1,68 @@ +use crate::{ + convert::{ToPyObject, ToPyResult}, + stdlib::os::errno_err, + PyObjectRef, PyResult, TryFromObject, VirtualMachine, +}; +use windows::Win32::Foundation::HANDLE; +use windows_sys::Win32::Foundation::{BOOL, HANDLE as RAW_HANDLE}; + +pub(crate) trait WindowsSysResultValue { + type Ok: ToPyObject; + fn is_err(&self) -> bool; + fn into_ok(self) -> Self::Ok; +} + +impl WindowsSysResultValue for RAW_HANDLE { + type Ok = HANDLE; + fn is_err(&self) -> bool { + *self == windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE + } + fn into_ok(self) -> Self::Ok { + HANDLE(self) + } +} + +impl WindowsSysResultValue for BOOL { + type Ok = (); + fn is_err(&self) -> bool { + *self == 0 + } + fn into_ok(self) -> Self::Ok {} +} + +pub(crate) struct WindowsSysResult(pub T); + +impl WindowsSysResult { + pub fn is_err(&self) -> bool { + self.0.is_err() + } + pub fn into_pyresult(self, vm: &VirtualMachine) -> PyResult { + if self.is_err() { + Err(errno_err(vm)) + } else { + Ok(self.0.into_ok()) + } + } +} + +impl ToPyResult for WindowsSysResult { + fn to_pyresult(self, vm: &VirtualMachine) -> PyResult { + let ok = self.into_pyresult(vm)?; + Ok(ok.to_pyobject(vm)) + } +} + +type HandleInt = usize; // TODO: change to isize when fully ported to windows-rs + +impl TryFromObject for HANDLE { + fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { + let handle = HandleInt::try_from_object(vm, obj)?; + Ok(HANDLE(handle as isize)) + } +} + +impl ToPyObject for HANDLE { + fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { + (self.0 as HandleInt).to_pyobject(vm) + } +}