From 54ef8b7a561bf66ffecdf310e9b547b1f9be2e45 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sun, 7 Dec 2025 22:59:27 +0900 Subject: [PATCH 1/5] winapi.ExitProcess --- crates/vm/src/stdlib/winapi.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/vm/src/stdlib/winapi.rs b/crates/vm/src/stdlib/winapi.rs index 10a14acbc9..5cb3e2b24a 100644 --- a/crates/vm/src/stdlib/winapi.rs +++ b/crates/vm/src/stdlib/winapi.rs @@ -294,6 +294,11 @@ mod _winapi { } } + #[pyfunction] + fn ExitProcess(exit_code: u32) { + unsafe { windows_sys::Win32::System::Threading::ExitProcess(exit_code) } + } + #[pyfunction] fn NeedCurrentDirectoryForExePath(exe_name: PyStrRef) -> bool { let exe_name = exe_name.as_str().to_wide_with_nul(); From 98c68c450450bd0faeb40a0b5aa025eb490649c1 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sun, 7 Dec 2025 23:04:26 +0900 Subject: [PATCH 2/5] Fix winapi Handle --- crates/vm/src/stdlib/winapi.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/crates/vm/src/stdlib/winapi.rs b/crates/vm/src/stdlib/winapi.rs index 5cb3e2b24a..58bfdf61d4 100644 --- a/crates/vm/src/stdlib/winapi.rs +++ b/crates/vm/src/stdlib/winapi.rs @@ -19,7 +19,7 @@ mod _winapi { Win32::Foundation::{HANDLE, HINSTANCE, MAX_PATH}, core::PCWSTR, }; - use windows_sys::Win32::Foundation::{BOOL, HANDLE as RAW_HANDLE}; + use windows_sys::Win32::Foundation::{BOOL, INVALID_HANDLE_VALUE}; #[pyattr] use windows_sys::Win32::{ @@ -87,8 +87,18 @@ mod _winapi { #[pyfunction] fn GetStdHandle( std_handle: windows_sys::Win32::System::Console::STD_HANDLE, - ) -> WindowsSysResult { - WindowsSysResult(unsafe { windows_sys::Win32::System::Console::GetStdHandle(std_handle) }) + vm: &VirtualMachine, + ) -> PyResult> { + let handle = unsafe { windows_sys::Win32::System::Console::GetStdHandle(std_handle) }; + if handle == INVALID_HANDLE_VALUE { + return Err(errno_err(vm)); + } + Ok(if handle.is_null() { + // NULL handle - return None + None + } else { + Some(HANDLE(handle as isize)) + }) } #[pyfunction] @@ -114,7 +124,8 @@ mod _winapi { #[pyfunction] fn DuplicateHandle( - (src_process, src): (HANDLE, HANDLE), + src_process: HANDLE, + src: HANDLE, target_process: HANDLE, access: u32, inherit: BOOL, From e76fbaa894f8d117af96388b2dab9cd068fb6a1b Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sun, 7 Dec 2025 23:01:18 +0900 Subject: [PATCH 3/5] msvcrt.GetErrorMode --- crates/vm/src/stdlib/msvcrt.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/vm/src/stdlib/msvcrt.rs b/crates/vm/src/stdlib/msvcrt.rs index 3eff6849e4..aee36adcf2 100644 --- a/crates/vm/src/stdlib/msvcrt.rs +++ b/crates/vm/src/stdlib/msvcrt.rs @@ -109,6 +109,12 @@ mod msvcrt { .map_err(|e| e.into_pyexception(vm)) } + #[allow(non_snake_case)] + #[pyfunction] + fn GetErrorMode() -> u32 { + unsafe { suppress_iph!(Debug::GetErrorMode()) } + } + #[allow(non_snake_case)] #[pyfunction] fn SetErrorMode(mode: Debug::THREAD_ERROR_MODE, _: &VirtualMachine) -> u32 { From e3f74fa1da1fd60fbde5769bac97cc1edc2e2999 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sun, 7 Dec 2025 23:03:42 +0900 Subject: [PATCH 4/5] windows stats --- crates/vm/src/stdlib/stat.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/vm/src/stdlib/stat.rs b/crates/vm/src/stdlib/stat.rs index f7b3abb432..90f045fcaf 100644 --- a/crates/vm/src/stdlib/stat.rs +++ b/crates/vm/src/stdlib/stat.rs @@ -237,6 +237,17 @@ mod stat { FILE_ATTRIBUTE_TEMPORARY, FILE_ATTRIBUTE_VIRTUAL, }; + // Windows reparse point tags + #[cfg(windows)] + #[pyattr] + pub const IO_REPARSE_TAG_SYMLINK: u32 = 0xA000000C; + #[cfg(windows)] + #[pyattr] + pub const IO_REPARSE_TAG_MOUNT_POINT: u32 = 0xA0000003; + #[cfg(windows)] + #[pyattr] + pub const IO_REPARSE_TAG_APPEXECLINK: u32 = 0x8000001B; + // Unix file flags (if on Unix) #[pyattr] From a97c075d2c4573dcc83a40c6245574dcd252441a Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Sun, 7 Dec 2025 23:48:19 +0900 Subject: [PATCH 5/5] unmark tests --- Lib/test/test_faulthandler.py | 1 - Lib/test/test_shutil.py | 2 -- Lib/test/test_subprocess.py | 1 - 3 files changed, 4 deletions(-) diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 1225db997e..6316f937e2 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -374,7 +374,6 @@ def test_enable_single_thread(self): 'Segmentation fault', all_threads=False) - @unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; AttributeError: module 'msvcrt' has no attribute 'GetErrorMode'") @skip_segfault_on_android def test_disable(self): code = """ diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 1fe2aef39d..91bc986aab 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -739,7 +739,6 @@ def test_copytree_dirs_exist_ok(self): with self.assertRaises(FileExistsError): shutil.copytree(src_dir, dst_dir, dirs_exist_ok=False) - @unittest.expectedFailureIfWindows("TODO: RUSTPYTHON") @os_helper.skip_unless_symlink def test_copytree_symlinks(self): tmp_dir = self.mkdtemp() @@ -1007,7 +1006,6 @@ def test_copytree_dangling_symlinks(self): shutil.copytree(src_dir, dst_dir, symlinks=True) self.assertIn('test.txt', os.listdir(dst_dir)) - @unittest.expectedFailureIfWindows("TODO: RUSTPYTHON") @os_helper.skip_unless_symlink def test_copytree_symlink_dir(self): src_dir = self.mkdtemp() diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 5a75971be6..e2aabf3dcf 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1337,7 +1337,6 @@ def _test_bufsize_equal_one(self, line, expected, universal_newlines): self.assertEqual(p.returncode, 0) self.assertEqual(read_line, expected) - @unittest.expectedFailureIfWindows("TODO: RUSTPYTHON") def test_bufsize_equal_one_text_mode(self): # line is flushed in text mode with bufsize=1. # we should get the full line in return