From 86f229961fdbbe91e0afe6850a9adfaf32b0cd50 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Mon, 18 Sep 2023 16:27:32 -0400 Subject: [PATCH] syscall: add SysProcAttr.PseudoConsole on Windows This allows the user to pass a ConPty handle to run a process on a ConPty session. See: https://learn.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session Fixes: https://learn.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session --- src/syscall/exec_windows.go | 20 ++++++++++++++++---- src/syscall/types_windows.go | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go index 06e684c7116b4f..883c53b94a593d 100644 --- a/src/syscall/exec_windows.go +++ b/src/syscall/exec_windows.go @@ -251,6 +251,7 @@ type SysProcAttr struct { NoInheritHandles bool // if set, no handles are inherited by the new process, not even the standard handles, contained in ProcAttr.Files, nor the ones contained in AdditionalInheritedHandles AdditionalInheritedHandles []Handle // a list of additional handles, already marked as inheritable, that will be inherited by the new process ParentProcess Handle // if non-zero, the new process regards the process given by this handle as its parent process, and AdditionalInheritedHandles, if set, should exist in this parent process + PseudoConsole Handle // if non-zero, the new process will be attached to the console represented by this handle, any AdditionalInheritedHandles will be ignored, this implies NoInheritHandles } var zeroProcAttr ProcAttr @@ -371,9 +372,13 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle return 0, 0, err } } - si.StdInput = fd[0] - si.StdOutput = fd[1] - si.StdErr = fd[2] + + // If a PseudoConsole is specified, then there is nothing we need to do with the handles since the process will inherit the other end of the PseudoConsole. + if sys.PseudoConsole == 0 { + si.StdInput = fd[0] + si.StdOutput = fd[1] + si.StdErr = fd[2] + } fd = append(fd, sys.AdditionalInheritedHandles...) @@ -396,7 +401,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle } fd = fd[:j] - willInheritHandles := len(fd) > 0 && !sys.NoInheritHandles + willInheritHandles := len(fd) > 0 && !sys.NoInheritHandles && sys.PseudoConsole == 0 // Do not accidentally inherit more than these handles. if willInheritHandles { @@ -406,6 +411,13 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle } } + if sys.PseudoConsole != 0 { + err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, unsafe.Pointer(sys.PseudoConsole), unsafe.Sizeof(sys.PseudoConsole), nil, nil) + if err != nil { + return 0, 0, err + } + } + envBlock, err := createEnvBlock(attr.Env) if err != nil { return 0, 0, err diff --git a/src/syscall/types_windows.go b/src/syscall/types_windows.go index b338ec47001f85..b2d3f5eaf1742f 100644 --- a/src/syscall/types_windows.go +++ b/src/syscall/types_windows.go @@ -497,6 +497,7 @@ type _PROC_THREAD_ATTRIBUTE_LIST struct { const ( _PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000 _PROC_THREAD_ATTRIBUTE_HANDLE_LIST = 0x00020002 + _PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = 0x00020016 ) type _STARTUPINFOEXW struct {