Skip to content

Commit 0638147

Browse files
committed
terminalsize
1 parent 0cc40db commit 0638147

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
@@ -207,32 +207,56 @@ pub(crate) mod module {
207207
fd: OptionalArg<i32>,
208208
vm: &VirtualMachine,
209209
) -> PyResult<_os::TerminalSizeData> {
210-
let (columns, lines) = {
211-
let stdhandle = match fd {
212-
OptionalArg::Present(0) => Console::STD_INPUT_HANDLE,
213-
OptionalArg::Present(1) | OptionalArg::Missing => Console::STD_OUTPUT_HANDLE,
214-
OptionalArg::Present(2) => Console::STD_ERROR_HANDLE,
215-
_ => return Err(vm.new_value_error("bad file descriptor")),
216-
};
217-
let h = unsafe { Console::GetStdHandle(stdhandle) };
218-
if h.is_null() {
219-
return Err(vm.new_os_error("handle cannot be retrieved".to_owned()));
210+
let fd = fd.unwrap_or(1); // default to stdout
211+
212+
// For standard streams, use GetStdHandle which returns proper console handles
213+
// For other fds, use _get_osfhandle to convert
214+
let h = match fd {
215+
0 => unsafe { Console::GetStdHandle(Console::STD_INPUT_HANDLE) },
216+
1 => unsafe { Console::GetStdHandle(Console::STD_OUTPUT_HANDLE) },
217+
2 => unsafe { Console::GetStdHandle(Console::STD_ERROR_HANDLE) },
218+
_ => {
219+
let borrowed = unsafe { crt_fd::Borrowed::borrow_raw(fd) };
220+
let handle = crt_fd::as_handle(borrowed).map_err(|e| e.to_pyexception(vm))?;
221+
handle.as_raw_handle() as _
220222
}
221-
if h == INVALID_HANDLE_VALUE {
223+
};
224+
225+
if h.is_null() || h == INVALID_HANDLE_VALUE {
226+
return Err(errno_err(vm));
227+
}
228+
229+
let mut csbi = MaybeUninit::uninit();
230+
let ret = unsafe { Console::GetConsoleScreenBufferInfo(h, csbi.as_mut_ptr()) };
231+
if ret == 0 {
232+
// If the handle doesn't have read access (e.g., conout$ opened with 'w'),
233+
// try opening CONOUT$ directly with read access like CPython does
234+
let conout: Vec<u16> = "CONOUT$\0".encode_utf16().collect();
235+
let console_handle = unsafe {
236+
FileSystem::CreateFileW(
237+
conout.as_ptr(),
238+
Foundation::GENERIC_READ | Foundation::GENERIC_WRITE,
239+
FileSystem::FILE_SHARE_READ | FileSystem::FILE_SHARE_WRITE,
240+
std::ptr::null(),
241+
FileSystem::OPEN_EXISTING,
242+
0,
243+
std::ptr::null_mut(),
244+
)
245+
};
246+
if console_handle == INVALID_HANDLE_VALUE {
222247
return Err(errno_err(vm));
223248
}
224-
let mut csbi = MaybeUninit::uninit();
225-
let ret = unsafe { Console::GetConsoleScreenBufferInfo(h, csbi.as_mut_ptr()) };
226-
let csbi = unsafe { csbi.assume_init() };
249+
let ret =
250+
unsafe { Console::GetConsoleScreenBufferInfo(console_handle, csbi.as_mut_ptr()) };
251+
unsafe { Foundation::CloseHandle(console_handle) };
227252
if ret == 0 {
228253
return Err(errno_err(vm));
229254
}
230-
let w = csbi.srWindow;
231-
(
232-
(w.Right - w.Left + 1) as usize,
233-
(w.Bottom - w.Top + 1) as usize,
234-
)
235-
};
255+
}
256+
let csbi = unsafe { csbi.assume_init() };
257+
let w = csbi.srWindow;
258+
let columns = (w.Right - w.Left + 1) as usize;
259+
let lines = (w.Bottom - w.Top + 1) as usize;
236260
Ok(_os::TerminalSizeData { columns, lines })
237261
}
238262

0 commit comments

Comments
 (0)