Skip to content

Commit 6680edb

Browse files
committed
terminalsize
1 parent cc534d2 commit 6680edb

File tree

1 file changed

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

1 file changed

+49
-20
lines changed

crates/vm/src/stdlib/nt.rs

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -203,32 +203,61 @@ 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+
// Check if error is due to lack of read access on a console handle
229+
// ERROR_ACCESS_DENIED (5) means it's a console but without read permission
230+
// In that case, try opening CONOUT$ directly with read access
231+
let err = unsafe { Foundation::GetLastError() };
232+
if err != Foundation::ERROR_ACCESS_DENIED {
218233
return Err(errno_err(vm));
219234
}
220-
let mut csbi = MaybeUninit::uninit();
221-
let ret = unsafe { Console::GetConsoleScreenBufferInfo(h, csbi.as_mut_ptr()) };
222-
let csbi = unsafe { csbi.assume_init() };
235+
let conout: Vec<u16> = "CONOUT$\0".encode_utf16().collect();
236+
let console_handle = unsafe {
237+
FileSystem::CreateFileW(
238+
conout.as_ptr(),
239+
Foundation::GENERIC_READ | Foundation::GENERIC_WRITE,
240+
FileSystem::FILE_SHARE_READ | FileSystem::FILE_SHARE_WRITE,
241+
std::ptr::null(),
242+
FileSystem::OPEN_EXISTING,
243+
0,
244+
std::ptr::null_mut(),
245+
)
246+
};
247+
if console_handle == INVALID_HANDLE_VALUE {
248+
return Err(errno_err(vm));
249+
}
250+
let ret =
251+
unsafe { Console::GetConsoleScreenBufferInfo(console_handle, csbi.as_mut_ptr()) };
252+
unsafe { Foundation::CloseHandle(console_handle) };
223253
if ret == 0 {
224254
return Err(errno_err(vm));
225255
}
226-
let w = csbi.srWindow;
227-
(
228-
(w.Right - w.Left + 1) as usize,
229-
(w.Bottom - w.Top + 1) as usize,
230-
)
231-
};
256+
}
257+
let csbi = unsafe { csbi.assume_init() };
258+
let w = csbi.srWindow;
259+
let columns = (w.Right - w.Left + 1) as usize;
260+
let lines = (w.Bottom - w.Top + 1) as usize;
232261
Ok(_os::TerminalSizeData { columns, lines })
233262
}
234263

0 commit comments

Comments
 (0)