aboutsummaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
authorJJ Liebig <jonathan.liebig@gmail.com>2026-09-17 17:45:07 +0200
committerGitHub <noreply@github.com>2026-09-17 17:45:07 +0200
commit101ccc20d3c6483a38ed9e0a1239b2ab908b1704 (patch)
tree96b88b9631d14c05e3ef3e7f77627c6596640b8e /src/platform
parent5c61d8ec2eeb296bd5e31bdd4e8f14ebadd5b7e1 (diff)
fix(windows): prefer pwsh for the default pane shell (#4297)
* fix(windows): prefer pwsh for the default pane shell Windows panes launched Windows PowerShell 5.1 (powershell.exe) whenever [terminal] default_shell was unset, ignoring PowerShell 7 even when pwsh.exe resolved on PATH. Resolve the unset default against PATH and prefer pwsh.exe, falling back to the inbox powershell.exe. An explicit default_shell still wins. * fix(windows): validate pwsh before using it as the default shell portable-pty resolves the configured shell with Path::exists and passes that path to CreateProcessW, which does not fall through to later PATH entries. Selecting an invalid pwsh.exe would therefore break new panes instead of falling back. Only prefer a pwsh.exe that starts with the PE MZ magic, and return its path so the validated binary is the one launched. * fix(windows): validate the full PE header before preferring pwsh Checking only the DOS MZ signature still accepted truncated images, DLLs, and foreign-architecture binaries. Because portable-pty passes the resolved path straight to CreateProcessW without trying later PATH entries, validate the PE signature, the COFF header (machine, executable-image bit, not a DLL, section count), and the optional header before preferring pwsh.exe. * fix(windows): accept native ARM64 pwsh and validate the section table Herdr ships an x64 Windows build that also runs on Windows ARM64 under x64 emulation, so cfg!(target_arch) cannot tell whether a native ARM64 pwsh.exe is launchable. Accept every executable machine type Windows supports instead of rejecting ARM64 on the x86_64 build. Also bound-check the section table (40 bytes per declared section) after the optional header so a truncated table falls back instead of being selected. * fix(windows): detect the native host machine for pwsh compatibility Machine compatibility was derived from cfg!(target_arch), which reports the emulated x64 process on Windows ARM64, and then briefly accepted ARM64 on every host. Read the native machine with IsWow64Process2 in the platform layer instead: ARM64 Windows accepts ARM64/x64/x86 images, x64 accepts x64/x86, and x86 accepts only x86.
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/windows.rs33
1 files changed, 28 insertions, 5 deletions
diff --git a/src/platform/windows.rs b/src/platform/windows.rs
index 9e39a715..cdf4acfc 100644
--- a/src/platform/windows.rs
+++ b/src/platform/windows.rs
@@ -350,11 +350,11 @@ use windows_sys::{
},
Ole::{CF_DIB, CF_DIBV5, CF_UNICODETEXT},
Threading::{
- GetCurrentProcess, GetExitCodeProcess, GetProcessTimes, OpenProcess, OpenThread,
- QueryFullProcessImageNameW, ResumeThread, TerminateProcess, CREATE_NO_WINDOW,
- CREATE_SUSPENDED, DETACHED_PROCESS, PROCESS_BASIC_INFORMATION,
- PROCESS_QUERY_INFORMATION, PROCESS_QUERY_LIMITED_INFORMATION, PROCESS_VM_READ,
- THREAD_SUSPEND_RESUME,
+ GetCurrentProcess, GetExitCodeProcess, GetProcessTimes, IsWow64Process2,
+ OpenProcess, OpenThread, QueryFullProcessImageNameW, ResumeThread,
+ TerminateProcess, CREATE_NO_WINDOW, CREATE_SUSPENDED, DETACHED_PROCESS,
+ PROCESS_BASIC_INFORMATION, PROCESS_QUERY_INFORMATION,
+ PROCESS_QUERY_LIMITED_INFORMATION, PROCESS_VM_READ, THREAD_SUSPEND_RESUME,
},
},
UI::{
@@ -386,6 +386,29 @@ const FOREGROUND_SELECTION_CACHE_CAPACITY: usize = 1_024;
const FOREGROUND_SELECTION_CACHE_RETENTION: Duration = Duration::from_secs(60);
const PANE_RUNTIME_MARKER_ENV_VAR: &str = "HERDR_PANE_RUNTIME_ID";
+/// Native processor architecture of the Windows host as an
+/// `IMAGE_FILE_MACHINE_*` value. `IsWow64Process2` reports the native machine
+/// even when an x64 Herdr runs under emulation on Windows ARM64, which the
+/// build target alone cannot reveal.
+pub(crate) fn native_machine_type() -> u16 {
+ let mut process_machine = 0u16;
+ let mut native_machine = 0u16;
+ // SAFETY: `GetCurrentProcess` returns a pseudo-handle and both out-pointers
+ // are valid for the duration of the call.
+ let ok = unsafe {
+ IsWow64Process2(
+ GetCurrentProcess(),
+ &mut process_machine,
+ &mut native_machine,
+ )
+ };
+ if ok != 0 && native_machine != 0 {
+ native_machine
+ } else {
+ process_machine
+ }
+}
+
pub(crate) fn terminal_title_for_presentation(title: &str) -> &str {
title.strip_prefix("Administrator: ").unwrap_or(title)
}