aboutsummaryrefslogtreecommitdiff
path: root/alacritty_terminal
diff options
context:
space:
mode:
authorPavel Roskin <1317472+proski@users.noreply.github.com>2023-06-19 11:29:17 -0700
committerGitHub <noreply@github.com>2023-06-19 18:29:17 +0000
commitb9c886872d1202fc9302f68a0bedbb17daa35335 (patch)
treef1d3840f21f506dc19718272dfd3d06952d94abd /alacritty_terminal
parentee938243586ae5482cf26ff238ddc99e66e1d1c4 (diff)
downloadalacritty-b9c886872d1202fc9302f68a0bedbb17daa35335.tar.gz
alacritty-b9c886872d1202fc9302f68a0bedbb17daa35335.zip
Add support for loading conpty.dll
Co-Authored-By: @fredizzimo Co-Authored-By: @grueslayer
Diffstat (limited to 'alacritty_terminal')
-rw-r--r--alacritty_terminal/Cargo.toml1
-rw-r--r--alacritty_terminal/src/tty/windows/conpty.rs76
2 files changed, 72 insertions, 5 deletions
diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml
index 9844939f..4ad17f45 100644
--- a/alacritty_terminal/Cargo.toml
+++ b/alacritty_terminal/Cargo.toml
@@ -45,6 +45,7 @@ windows-sys = { version = "0.48", features = [
"Win32_System_Console",
"Win32_Foundation",
"Win32_Security",
+ "Win32_System_LibraryLoader",
"Win32_System_Threading",
"Win32_System_WindowsProgramming",
]}
diff --git a/alacritty_terminal/src/tty/windows/conpty.rs b/alacritty_terminal/src/tty/windows/conpty.rs
index 3f6349de..c9ed631e 100644
--- a/alacritty_terminal/src/tty/windows/conpty.rs
+++ b/alacritty_terminal/src/tty/windows/conpty.rs
@@ -1,14 +1,18 @@
+use log::info;
use std::io::Error;
use std::os::windows::io::IntoRawHandle;
use std::{mem, ptr};
use mio_anonymous_pipes::{EventedAnonRead, EventedAnonWrite};
-use windows_sys::core::PWSTR;
+use windows_sys::core::{HRESULT, PWSTR};
use windows_sys::Win32::Foundation::{HANDLE, S_OK};
use windows_sys::Win32::System::Console::{
ClosePseudoConsole, CreatePseudoConsole, ResizePseudoConsole, COORD, HPCON,
};
+use windows_sys::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryW};
+use windows_sys::{s, w};
+
use windows_sys::Win32::System::Threading::{
CreateProcessW, InitializeProcThreadAttributeList, UpdateProcThreadAttribute,
EXTENDED_STARTUPINFO_PRESENT, PROCESS_INFORMATION, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
@@ -20,9 +24,70 @@ use crate::event::{OnResize, WindowSize};
use crate::tty::windows::child::ChildExitWatcher;
use crate::tty::windows::{cmdline, win32_string, Pty};
+/// Load the pseudoconsole API from conpty.dll if possible, otherwise use the
+/// standard Windows API.
+///
+/// The conpty.dll from the Windows Terminal project
+/// supports loading OpenConsole.exe, which offers many improvements and
+/// bugfixes compared to the standard conpty that ships with Windows.
+///
+/// The conpty.dll and OpenConsole.exe files will be searched in PATH and in
+/// the directory where Alacritty's executable is located.
+type CreatePseudoConsoleFn =
+ unsafe extern "system" fn(COORD, HANDLE, HANDLE, u32, *mut HPCON) -> HRESULT;
+type ResizePseudoConsoleFn = unsafe extern "system" fn(HPCON, COORD) -> HRESULT;
+type ClosePseudoConsoleFn = unsafe extern "system" fn(HPCON);
+
+struct ConptyApi {
+ create: CreatePseudoConsoleFn,
+ resize: ResizePseudoConsoleFn,
+ close: ClosePseudoConsoleFn,
+}
+
+impl ConptyApi {
+ fn new() -> Self {
+ match Self::load_conpty() {
+ Some(conpty) => {
+ info!("Using conpty.dll for pseudoconsole");
+ conpty
+ },
+ None => {
+ // Cannot load conpty.dll - use the standard Windows API.
+ info!("Using Windows API for pseudoconsole");
+ Self {
+ create: CreatePseudoConsole,
+ resize: ResizePseudoConsole,
+ close: ClosePseudoConsole,
+ }
+ },
+ }
+ }
+
+ /// Try loading ConptyApi from conpty.dll library.
+ fn load_conpty() -> Option<Self> {
+ type LoadedFn = unsafe extern "system" fn() -> isize;
+ unsafe {
+ let hmodule = LoadLibraryW(w!("conpty.dll"));
+ if hmodule == 0 {
+ return None;
+ }
+ let create_fn = GetProcAddress(hmodule, s!("CreatePseudoConsole"))?;
+ let resize_fn = GetProcAddress(hmodule, s!("ResizePseudoConsole"))?;
+ let close_fn = GetProcAddress(hmodule, s!("ClosePseudoConsole"))?;
+
+ Some(Self {
+ create: mem::transmute::<LoadedFn, CreatePseudoConsoleFn>(create_fn),
+ resize: mem::transmute::<LoadedFn, ResizePseudoConsoleFn>(resize_fn),
+ close: mem::transmute::<LoadedFn, ClosePseudoConsoleFn>(close_fn),
+ })
+ }
+ }
+}
+
/// RAII Pseudoconsole.
pub struct Conpty {
pub handle: HPCON,
+ api: ConptyApi,
}
impl Drop for Conpty {
@@ -31,7 +96,7 @@ impl Drop for Conpty {
// conout pipe has already been dropped by this point.
//
// See PR #3084 and https://docs.microsoft.com/en-us/windows/console/closepseudoconsole.
- unsafe { ClosePseudoConsole(self.handle) }
+ unsafe { (self.api.close)(self.handle) }
}
}
@@ -39,6 +104,7 @@ impl Drop for Conpty {
unsafe impl Send for Conpty {}
pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
+ let api = ConptyApi::new();
let mut pty_handle: HPCON = 0;
// Passing 0 as the size parameter allows the "system default" buffer
@@ -50,7 +116,7 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
// Create the Pseudo Console, using the pipes.
let result = unsafe {
- CreatePseudoConsole(
+ (api.create)(
window_size.into(),
conin_pty_handle.into_raw_handle() as HANDLE,
conout_pty_handle.into_raw_handle() as HANDLE,
@@ -158,7 +224,7 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
let conout = EventedAnonRead::new(conout);
let child_watcher = ChildExitWatcher::new(proc_info.hProcess).unwrap();
- let conpty = Conpty { handle: pty_handle as HPCON };
+ let conpty = Conpty { handle: pty_handle as HPCON, api };
Some(Pty::new(conpty, conout, conin, child_watcher))
}
@@ -170,7 +236,7 @@ fn panic_shell_spawn() {
impl OnResize for Conpty {
fn on_resize(&mut self, window_size: WindowSize) {
- let result = unsafe { ResizePseudoConsole(self.handle, window_size.into()) };
+ let result = unsafe { (self.api.resize)(self.handle, window_size.into()) };
assert_eq!(result, S_OK);
}
}