Skip to content

Commit 8d1f2e5

Browse files
committed
terminalsize
1 parent a43868f commit 8d1f2e5

File tree

1 file changed

+44
-20
lines changed
  • crates/vm/src/stdlib

1 file changed

+44
-20
lines changed

crates/vm/src/stdlib/nt.rs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -203,32 +203,56 @@ pub(crate) mod module {
203203
fd: OptionalArg<i32>,
204204
vm: &VirtualMachine,
205205
) -> PyResult<_os::TerminalSizeData> {
206-
let (columns, lines) = {
207-
let stdhandle = match fd {
208-
OptionalArg::Present(0) => Console::STD_INPUT_HANDLE,
209-
OptionalArg::Present(1) | OptionalArg::Missing => Console::STD_OUTPUT_HANDLE,
210-
OptionalArg::Present(2) => Console::STD_ERROR_HANDLE,
211-
_ => return Err(vm.new_value_error("bad file descriptor")),
212-
};
213-
let h = unsafe { Console::GetStdHandle(stdhandle) };
214-
if h.is_null() {
215-
return Err(vm.new_os_error("handle cannot be retrieved".to_owned()));
206+
let fd = fd.unwrap_or(1); // default to stdout
207+
208+
// For standard streams, use GetStdHandle which returns proper console handles
209+
// For other fds, use _get_osfhandle to convert
210+
let h = match fd {
211+
0 => unsafe { Console::GetStdHandle(Console::STD_INPUT_HANDLE) },
212+
1 => unsafe { Console::GetStdHandle(Console::STD_OUTPUT_HANDLE) },
213+
2 => unsafe { Console::GetStdHandle(Console::STD_ERROR_HANDLE) },
214+
_ => {
215+
let borrowed = unsafe { crt_fd::Borrowed::borrow_raw(fd) };
216+
let handle = crt_fd::as_handle(borrowed).map_err(|e| e.to_pyexception(vm))?;
217+
handle.as_raw_handle() as _
216218
}
217-
if h == INVALID_HANDLE_VALUE {
219+
};
220+
221+
if h.is_null() || h == INVALID_HANDLE_VALUE {
222+
return Err(errno_err(vm));
223+
}
224+
225+
let mut csbi = MaybeUninit::uninit();
226+
let ret = unsafe { Console::GetConsoleScreenBufferInfo(h, csbi.as_mut_ptr()) };
227+
if ret == 0 {
228+
// If the handle doesn't have read access (e.g., conout$ opened with 'w'),
229+
// try opening CONOUT$ directly with read access like CPython does
230+
let conout: Vec<u16> = "CONOUT$\0".encode_utf16().collect();
231+
let console_handle = unsafe {
232+
FileSystem::CreateFileW(
233+
conout.as_ptr(),
234+
Foundation::GENERIC_READ | Foundation::GENERIC_WRITE,
235+
FileSystem::FILE_SHARE_READ | FileSystem::FILE_SHARE_WRITE,
236+
std::ptr::null(),
237+
FileSystem::OPEN_EXISTING,
238+
0,
239+
std::ptr::null_mut(),
240+
)
241+
};
242+
if console_handle == INVALID_HANDLE_VALUE {
218243
return Err(errno_err(vm));
219244
}
220-
let mut csbi = MaybeUninit::uninit();
221-
let ret = unsafe { Console::GetConsoleScreenBufferInfo(h, csbi.as_mut_ptr()) };
222-
let csbi = unsafe { csbi.assume_init() };
245+
let ret =
246+
unsafe { Console::GetConsoleScreenBufferInfo(console_handle, csbi.as_mut_ptr()) };
247+
unsafe { Foundation::CloseHandle(console_handle) };
223248
if ret == 0 {
224249
return Err(errno_err(vm));
225250
}
226-
let w = csbi.srWindow;
227-
(
228-
(w.Right - w.Left + 1) as usize,
229-
(w.Bottom - w.Top + 1) as usize,
230-
)
231-
};
251+
}
252+
let csbi = unsafe { csbi.assume_init() };
253+
let w = csbi.srWindow;
254+
let columns = (w.Right - w.Left + 1) as usize;
255+
let lines = (w.Bottom - w.Top + 1) as usize;
232256
Ok(_os::TerminalSizeData { columns, lines })
233257
}
234258

0 commit comments

Comments
 (0)