diff --git a/Cargo.lock b/Cargo.lock index f839258a61..af3f7c0dde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1433,7 +1433,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core", ] [[package]] @@ -3265,7 +3265,6 @@ dependencies = [ "wasm-bindgen", "which", "widestring", - "windows", "windows-sys 0.61.2", ] @@ -4347,25 +4346,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core 0.52.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-core" version = "0.62.2" diff --git a/crates/vm/Cargo.toml b/crates/vm/Cargo.toml index 0e3f90a461..502ace0126 100644 --- a/crates/vm/Cargo.toml +++ b/crates/vm/Cargo.toml @@ -112,16 +112,6 @@ num_cpus = "1.17.0" [target.'cfg(windows)'.dependencies] junction = { workspace = true } -[target.'cfg(windows)'.dependencies.windows] -version = "0.52.0" -features = [ - "Win32_Foundation", - "Win32_System_LibraryLoader", - "Win32_System_Threading", - "Win32_System_Time", - "Win32_UI_Shell", -] - [target.'cfg(windows)'.dependencies.windows-sys] workspace = true features = [ @@ -143,6 +133,7 @@ features = [ "Win32_System_SystemInformation", "Win32_System_SystemServices", "Win32_System_Threading", + "Win32_System_Time", "Win32_System_WindowsProgramming", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging", diff --git a/crates/vm/src/stdlib/nt.rs b/crates/vm/src/stdlib/nt.rs index 2304a15e4f..1f36683c91 100644 --- a/crates/vm/src/stdlib/nt.rs +++ b/crates/vm/src/stdlib/nt.rs @@ -556,23 +556,26 @@ pub(crate) mod module { String::from_utf16(wstr).map_err(|e| vm.new_unicode_decode_error(e.to_string())) } - let wbuf = windows::core::PCWSTR::from_raw(backslashed.as_ptr()); - let (root, path) = match unsafe { windows::Win32::UI::Shell::PathCchSkipRoot(wbuf) } { - Ok(end) => { - assert!(!end.is_null()); - let len: usize = unsafe { end.as_ptr().offset_from(wbuf.as_ptr()) } - .try_into() - .expect("len must be non-negative"); - assert!( - len < backslashed.len(), // backslashed is null-terminated - "path: {:?} {} < {}", - std::path::PathBuf::from(std::ffi::OsString::from_wide(&backslashed)), - len, - backslashed.len() - ); - (from_utf16(&orig[..len], vm)?, from_utf16(&orig[len..], vm)?) - } - Err(_) => ("".to_owned(), from_utf16(&orig, vm)?), + let mut end: *const u16 = std::ptr::null(); + let hr = unsafe { + windows_sys::Win32::UI::Shell::PathCchSkipRoot(backslashed.as_ptr(), &mut end) + }; + let (root, path) = if hr == 0 { + // S_OK + assert!(!end.is_null()); + let len: usize = unsafe { end.offset_from(backslashed.as_ptr()) } + .try_into() + .expect("len must be non-negative"); + assert!( + len < backslashed.len(), // backslashed is null-terminated + "path: {:?} {} < {}", + std::path::PathBuf::from(std::ffi::OsString::from_wide(&backslashed)), + len, + backslashed.len() + ); + (from_utf16(&orig[..len], vm)?, from_utf16(&orig[len..], vm)?) + } else { + ("".to_owned(), from_utf16(&orig, vm)?) }; Ok((root, path)) } diff --git a/crates/vm/src/stdlib/time.rs b/crates/vm/src/stdlib/time.rs index ef4fbbea7f..212697b7a9 100644 --- a/crates/vm/src/stdlib/time.rs +++ b/crates/vm/src/stdlib/time.rs @@ -46,7 +46,7 @@ mod decl { use std::time::Duration; #[cfg(target_env = "msvc")] #[cfg(not(target_arch = "wasm32"))] - use windows::Win32::System::Time; + use windows_sys::Win32::System::Time::{GetTimeZoneInformation, TIME_ZONE_INFORMATION}; #[allow(dead_code)] pub(super) const SEC_TO_MS: i64 = 1000; @@ -186,10 +186,9 @@ mod decl { #[cfg(target_env = "msvc")] #[cfg(not(target_arch = "wasm32"))] - fn get_tz_info() -> Time::TIME_ZONE_INFORMATION { - let mut info = Time::TIME_ZONE_INFORMATION::default(); - let info_ptr = &mut info as *mut Time::TIME_ZONE_INFORMATION; - let _ = unsafe { Time::GetTimeZoneInformation(info_ptr) }; + fn get_tz_info() -> TIME_ZONE_INFORMATION { + let mut info: TIME_ZONE_INFORMATION = unsafe { std::mem::zeroed() }; + unsafe { GetTimeZoneInformation(&mut info) }; info } diff --git a/crates/vm/src/stdlib/winapi.rs b/crates/vm/src/stdlib/winapi.rs index fea24d226d..6b6e452b38 100644 --- a/crates/vm/src/stdlib/winapi.rs +++ b/crates/vm/src/stdlib/winapi.rs @@ -12,14 +12,10 @@ mod _winapi { convert::{ToPyException, ToPyResult}, function::{ArgMapping, ArgSequence, OptionalArg}, stdlib::os::errno_err, - windows::WindowsSysResult, + windows::{WinHandle, WindowsSysResult}, }; use std::ptr::{null, null_mut}; - use windows::{ - Win32::Foundation::{HANDLE, HINSTANCE, MAX_PATH}, - core::PCWSTR, - }; - use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE; + use windows_sys::Win32::Foundation::{INVALID_HANDLE_VALUE, MAX_PATH}; #[pyattr] use windows_sys::Win32::{ @@ -78,15 +74,15 @@ mod _winapi { const NULL: isize = 0; #[pyfunction] - fn CloseHandle(handle: HANDLE) -> WindowsSysResult { - WindowsSysResult(unsafe { windows_sys::Win32::Foundation::CloseHandle(handle.0 as _) }) + fn CloseHandle(handle: WinHandle) -> WindowsSysResult { + WindowsSysResult(unsafe { windows_sys::Win32::Foundation::CloseHandle(handle.0) }) } #[pyfunction] fn GetStdHandle( std_handle: windows_sys::Win32::System::Console::STD_HANDLE, vm: &VirtualMachine, - ) -> PyResult> { + ) -> PyResult> { let handle = unsafe { windows_sys::Win32::System::Console::GetStdHandle(std_handle) }; if handle == INVALID_HANDLE_VALUE { return Err(errno_err(vm)); @@ -95,7 +91,7 @@ mod _winapi { // NULL handle - return None None } else { - Some(HANDLE(handle as isize)) + Some(WinHandle(handle)) }) } @@ -104,39 +100,41 @@ mod _winapi { _pipe_attrs: PyObjectRef, size: u32, vm: &VirtualMachine, - ) -> PyResult<(HANDLE, HANDLE)> { + ) -> PyResult<(WinHandle, WinHandle)> { + use windows_sys::Win32::Foundation::HANDLE; let (read, write) = unsafe { - let mut read = std::mem::MaybeUninit::::uninit(); - let mut write = std::mem::MaybeUninit::::uninit(); + let mut read = std::mem::MaybeUninit::::uninit(); + let mut write = std::mem::MaybeUninit::::uninit(); WindowsSysResult(windows_sys::Win32::System::Pipes::CreatePipe( - read.as_mut_ptr() as _, - write.as_mut_ptr() as _, + read.as_mut_ptr(), + write.as_mut_ptr(), std::ptr::null(), size, )) .to_pyresult(vm)?; (read.assume_init(), write.assume_init()) }; - Ok((HANDLE(read), HANDLE(write))) + Ok((WinHandle(read), WinHandle(write))) } #[pyfunction] fn DuplicateHandle( - src_process: HANDLE, - src: HANDLE, - target_process: HANDLE, + src_process: WinHandle, + src: WinHandle, + target_process: WinHandle, access: u32, inherit: i32, options: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { + ) -> PyResult { + use windows_sys::Win32::Foundation::HANDLE; let target = unsafe { - let mut target = std::mem::MaybeUninit::::uninit(); + let mut target = std::mem::MaybeUninit::::uninit(); WindowsSysResult(windows_sys::Win32::Foundation::DuplicateHandle( - src_process.0 as _, - src.0 as _, - target_process.0 as _, - target.as_mut_ptr() as _, + src_process.0, + src.0, + target_process.0, + target.as_mut_ptr(), access, inherit, options.unwrap_or(0), @@ -144,7 +142,7 @@ mod _winapi { .to_pyresult(vm)?; target.assume_init() }; - Ok(HANDLE(target)) + Ok(WinHandle(target)) } #[pyfunction] @@ -153,16 +151,16 @@ mod _winapi { } #[pyfunction] - fn GetCurrentProcess() -> HANDLE { - unsafe { windows::Win32::System::Threading::GetCurrentProcess() } + fn GetCurrentProcess() -> WinHandle { + WinHandle(unsafe { windows_sys::Win32::System::Threading::GetCurrentProcess() }) } #[pyfunction] fn GetFileType( - h: HANDLE, + h: WinHandle, vm: &VirtualMachine, ) -> PyResult { - let file_type = unsafe { windows_sys::Win32::Storage::FileSystem::GetFileType(h.0 as _) }; + let file_type = unsafe { windows_sys::Win32::Storage::FileSystem::GetFileType(h.0) }; if file_type == 0 && unsafe { windows_sys::Win32::Foundation::GetLastError() } != 0 { Err(errno_err(vm)) } else { @@ -206,7 +204,7 @@ mod _winapi { fn CreateProcess( args: CreateProcessArgs, vm: &VirtualMachine, - ) -> PyResult<(HANDLE, HANDLE, u32, u32)> { + ) -> PyResult<(WinHandle, WinHandle, u32, u32)> { let mut si: windows_sys::Win32::System::Threading::STARTUPINFOEXW = unsafe { std::mem::zeroed() }; si.StartupInfo.cb = std::mem::size_of_val(&si) as _; @@ -285,22 +283,31 @@ mod _winapi { }; Ok(( - HANDLE(procinfo.hProcess as _), - HANDLE(procinfo.hThread as _), + WinHandle(procinfo.hProcess), + WinHandle(procinfo.hThread), procinfo.dwProcessId, procinfo.dwThreadId, )) } #[pyfunction] - fn OpenProcess(desired_access: u32, inherit_handle: bool, process_id: u32) -> isize { - unsafe { + fn OpenProcess( + desired_access: u32, + inherit_handle: bool, + process_id: u32, + vm: &VirtualMachine, + ) -> PyResult { + let handle = unsafe { windows_sys::Win32::System::Threading::OpenProcess( desired_access, i32::from(inherit_handle), process_id, - ) as _ + ) + }; + if handle.is_null() { + return Err(errno_err(vm)); } + Ok(WinHandle(handle)) } #[pyfunction] @@ -434,7 +441,7 @@ mod _winapi { 0, (2 & 0xffff) | 0x20000, // PROC_THREAD_ATTRIBUTE_HANDLE_LIST handlelist.as_mut_ptr() as _, - (handlelist.len() * std::mem::size_of::()) as _, + (handlelist.len() * std::mem::size_of::()) as _, std::ptr::null_mut(), std::ptr::null(), ) @@ -447,9 +454,8 @@ mod _winapi { } #[pyfunction] - fn WaitForSingleObject(h: HANDLE, ms: u32, vm: &VirtualMachine) -> PyResult { - let ret = - unsafe { windows_sys::Win32::System::Threading::WaitForSingleObject(h.0 as _, ms) }; + fn WaitForSingleObject(h: WinHandle, ms: u32, vm: &VirtualMachine) -> PyResult { + let ret = unsafe { windows_sys::Win32::System::Threading::WaitForSingleObject(h.0, ms) }; if ret == windows_sys::Win32::Foundation::WAIT_FAILED { Err(errno_err(vm)) } else { @@ -458,11 +464,11 @@ mod _winapi { } #[pyfunction] - fn GetExitCodeProcess(h: HANDLE, vm: &VirtualMachine) -> PyResult { + fn GetExitCodeProcess(h: WinHandle, vm: &VirtualMachine) -> PyResult { unsafe { let mut ec = std::mem::MaybeUninit::uninit(); WindowsSysResult(windows_sys::Win32::System::Threading::GetExitCodeProcess( - h.0 as _, + h.0, ec.as_mut_ptr(), )) .to_pyresult(vm)?; @@ -471,9 +477,9 @@ mod _winapi { } #[pyfunction] - fn TerminateProcess(h: HANDLE, exit_code: u32) -> WindowsSysResult { + fn TerminateProcess(h: WinHandle, exit_code: u32) -> WindowsSysResult { WindowsSysResult(unsafe { - windows_sys::Win32::System::Threading::TerminateProcess(h.0 as _, exit_code) + windows_sys::Win32::System::Threading::TerminateProcess(h.0, exit_code) }) } @@ -481,23 +487,25 @@ mod _winapi { #[allow(dead_code)] fn LoadLibrary(path: PyStrRef, vm: &VirtualMachine) -> PyResult { let path = path.as_str().to_wide_with_nul(); - let handle = unsafe { - windows::Win32::System::LibraryLoader::LoadLibraryW(PCWSTR::from_raw(path.as_ptr())) - .unwrap() - }; - if handle.is_invalid() { + let handle = + unsafe { windows_sys::Win32::System::LibraryLoader::LoadLibraryW(path.as_ptr()) }; + if handle.is_null() { return Err(vm.new_runtime_error("LoadLibrary failed")); } - Ok(handle.0) + Ok(handle as isize) } #[pyfunction] fn GetModuleFileName(handle: isize, vm: &VirtualMachine) -> PyResult { let mut path: Vec = vec![0; MAX_PATH as usize]; - let handle = HINSTANCE(handle); - let length = - unsafe { windows::Win32::System::LibraryLoader::GetModuleFileNameW(handle, &mut path) }; + let length = unsafe { + windows_sys::Win32::System::LibraryLoader::GetModuleFileNameW( + handle as windows_sys::Win32::Foundation::HMODULE, + path.as_mut_ptr(), + path.len() as u32, + ) + }; if length == 0 { return Err(vm.new_runtime_error("GetModuleFileName failed")); } @@ -507,17 +515,23 @@ mod _winapi { } #[pyfunction] - fn OpenMutexW(desired_access: u32, inherit_handle: bool, name: u16) -> PyResult { + fn OpenMutexW( + desired_access: u32, + inherit_handle: bool, + name: PyStrRef, + vm: &VirtualMachine, + ) -> PyResult { + let name_wide = name.as_str().to_wide_with_nul(); let handle = unsafe { windows_sys::Win32::System::Threading::OpenMutexW( desired_access, i32::from(inherit_handle), - windows_sys::core::PCWSTR::from(name as _), + name_wide.as_ptr(), ) }; - // if handle.is_invalid() { - // return Err(errno_err(vm)); - // } + if handle == INVALID_HANDLE_VALUE { + return Err(errno_err(vm)); + } Ok(handle as _) } diff --git a/crates/vm/src/windows.rs b/crates/vm/src/windows.rs index 6825ee5841..df766bec35 100644 --- a/crates/vm/src/windows.rs +++ b/crates/vm/src/windows.rs @@ -8,8 +8,11 @@ use crate::{ stdlib::os::errno_err, }; use std::ffi::OsStr; -use windows::Win32::Foundation::HANDLE; -use windows_sys::Win32::Foundation::{HANDLE as RAW_HANDLE, INVALID_HANDLE_VALUE}; +use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE}; + +/// Windows HANDLE wrapper for Python interop +#[derive(Clone, Copy)] +pub struct WinHandle(pub HANDLE); pub(crate) trait WindowsSysResultValue { type Ok: ToPyObject; @@ -17,13 +20,13 @@ pub(crate) trait WindowsSysResultValue { fn into_ok(self) -> Self::Ok; } -impl WindowsSysResultValue for RAW_HANDLE { - type Ok = HANDLE; +impl WindowsSysResultValue for HANDLE { + type Ok = WinHandle; fn is_err(&self) -> bool { *self == INVALID_HANDLE_VALUE } fn into_ok(self) -> Self::Ok { - HANDLE(self as _) + WinHandle(self) } } @@ -60,14 +63,14 @@ impl ToPyResult for WindowsSysResult { type HandleInt = usize; // TODO: change to isize when fully ported to windows-rs -impl TryFromObject for HANDLE { +impl TryFromObject for WinHandle { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { let handle = HandleInt::try_from_object(vm, obj)?; - Ok(HANDLE(handle as isize)) + Ok(WinHandle(handle as HANDLE)) } } -impl ToPyObject for HANDLE { +impl ToPyObject for WinHandle { fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { (self.0 as HandleInt).to_pyobject(vm) }