Skip to content

Commit c578861

Browse files
authored
nt.terminalsize (RustPython#6374)
* terminalsize * use _get_osfhandle
1 parent 79cd048 commit c578861

File tree

1 file changed

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

1 file changed

+37
-20
lines changed

crates/vm/src/stdlib/nt.rs

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -203,32 +203,49 @@ 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+
// Use _get_osfhandle for all fds
209+
let borrowed = unsafe { crt_fd::Borrowed::borrow_raw(fd) };
210+
let handle = crt_fd::as_handle(borrowed).map_err(|e| e.to_pyexception(vm))?;
211+
let h = handle.as_raw_handle() as Foundation::HANDLE;
212+
213+
let mut csbi = MaybeUninit::uninit();
214+
let ret = unsafe { Console::GetConsoleScreenBufferInfo(h, csbi.as_mut_ptr()) };
215+
if ret == 0 {
216+
// Check if error is due to lack of read access on a console handle
217+
// ERROR_ACCESS_DENIED (5) means it's a console but without read permission
218+
// In that case, try opening CONOUT$ directly with read access
219+
let err = unsafe { Foundation::GetLastError() };
220+
if err != Foundation::ERROR_ACCESS_DENIED {
221+
return Err(errno_err(vm));
216222
}
217-
if h == INVALID_HANDLE_VALUE {
223+
let conout: Vec<u16> = "CONOUT$\0".encode_utf16().collect();
224+
let console_handle = unsafe {
225+
FileSystem::CreateFileW(
226+
conout.as_ptr(),
227+
Foundation::GENERIC_READ | Foundation::GENERIC_WRITE,
228+
FileSystem::FILE_SHARE_READ | FileSystem::FILE_SHARE_WRITE,
229+
std::ptr::null(),
230+
FileSystem::OPEN_EXISTING,
231+
0,
232+
std::ptr::null_mut(),
233+
)
234+
};
235+
if console_handle == INVALID_HANDLE_VALUE {
218236
return Err(errno_err(vm));
219237
}
220-
let mut csbi = MaybeUninit::uninit();
221-
let ret = unsafe { Console::GetConsoleScreenBufferInfo(h, csbi.as_mut_ptr()) };
222-
let csbi = unsafe { csbi.assume_init() };
238+
let ret =
239+
unsafe { Console::GetConsoleScreenBufferInfo(console_handle, csbi.as_mut_ptr()) };
240+
unsafe { Foundation::CloseHandle(console_handle) };
223241
if ret == 0 {
224242
return Err(errno_err(vm));
225243
}
226-
let w = csbi.srWindow;
227-
(
228-
(w.Right - w.Left + 1) as usize,
229-
(w.Bottom - w.Top + 1) as usize,
230-
)
231-
};
244+
}
245+
let csbi = unsafe { csbi.assume_init() };
246+
let w = csbi.srWindow;
247+
let columns = (w.Right - w.Left + 1) as usize;
248+
let lines = (w.Bottom - w.Top + 1) as usize;
232249
Ok(_os::TerminalSizeData { columns, lines })
233250
}
234251

0 commit comments

Comments
 (0)