Files
neovim/src/nvim/os/pty_conpty_win.c
Justin M. Keyes 057d27a9d6 refactor: rename "process" => "proc" #30387
Problem:
- "process" is often used as a verb (`multiqueue_process_events`), which
  is ambiguous for cases where it's used as a topic.
- The documented naming convention for processes is "proc".
  - `:help dev-name-common`
- Shorter is better, when it doesn't harm readability or
  discoverability.

Solution:
Rename "process" => "proc" in all C symbols and module names.
2024-09-15 12:20:58 -07:00

190 lines
5.9 KiB
C

#include <uv.h>
#include "nvim/log.h"
#include "nvim/os/os.h"
#include "nvim/os/pty_conpty_win.h"
#include "nvim/vim_defs.h"
#ifndef EXTENDED_STARTUPINFO_PRESENT
# define EXTENDED_STARTUPINFO_PRESENT 0x00080000
#endif
#ifndef PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
# define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x00020016
#endif
HRESULT(WINAPI *pCreatePseudoConsole)(COORD, HANDLE, HANDLE, DWORD, HPCON *);
HRESULT(WINAPI *pResizePseudoConsole)(HPCON, COORD);
void(WINAPI *pClosePseudoConsole)(HPCON);
bool os_has_conpty_working(void)
{
static TriState has_conpty = kNone;
if (has_conpty == kNone) {
has_conpty = os_dyn_conpty_init();
}
return has_conpty == kTrue;
}
TriState os_dyn_conpty_init(void)
{
uv_lib_t kernel;
if (uv_dlopen("kernel32.dll", &kernel)) {
uv_dlclose(&kernel);
return kFalse;
}
static struct {
char *name;
FARPROC *ptr;
} conpty_entry[] = {
{ "CreatePseudoConsole", (FARPROC *)&pCreatePseudoConsole },
{ "ResizePseudoConsole", (FARPROC *)&pResizePseudoConsole },
{ "ClosePseudoConsole", (FARPROC *)&pClosePseudoConsole },
{ NULL, NULL }
};
for (int i = 0;
conpty_entry[i].name != NULL && conpty_entry[i].ptr != NULL; i++) {
if (uv_dlsym(&kernel, conpty_entry[i].name, (void **)conpty_entry[i].ptr)) {
uv_dlclose(&kernel);
return kFalse;
}
}
return kTrue;
}
conpty_t *os_conpty_init(char **in_name, char **out_name, uint16_t width, uint16_t height)
{
static int count = 0;
conpty_t *conpty_object = xcalloc(1, sizeof(*conpty_object));
const char *emsg = NULL;
HANDLE in_read = INVALID_HANDLE_VALUE;
HANDLE out_write = INVALID_HANDLE_VALUE;
char buf[MAXPATHL];
SECURITY_ATTRIBUTES sa = { 0 };
const DWORD mode = PIPE_ACCESS_INBOUND
| PIPE_ACCESS_OUTBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE;
sa.nLength = sizeof(sa);
snprintf(buf, sizeof(buf), "\\\\.\\pipe\\nvim-term-in-%lld-%d",
os_get_pid(), count);
*in_name = xstrdup(buf);
if ((in_read = CreateNamedPipeA(*in_name,
mode,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
0,
0,
30000,
&sa)) == INVALID_HANDLE_VALUE) {
emsg = "create input pipe failed";
goto failed;
}
snprintf(buf, sizeof(buf), "\\\\.\\pipe\\nvim-term-out-%lld-%d",
os_get_pid(), count);
*out_name = xstrdup(buf);
if ((out_write = CreateNamedPipeA(*out_name,
mode,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
0,
0,
30000,
&sa)) == INVALID_HANDLE_VALUE) {
emsg = "create output pipe failed";
goto failed;
}
assert(width <= SHRT_MAX);
assert(height <= SHRT_MAX);
COORD size = { (int16_t)width, (int16_t)height };
HRESULT hr;
hr = pCreatePseudoConsole(size, in_read, out_write, 0, &conpty_object->pty);
if (FAILED(hr)) {
emsg = "create pseudo console failed";
goto failed;
}
conpty_object->si_ex.StartupInfo.cb = sizeof(conpty_object->si_ex);
size_t bytes_required;
InitializeProcThreadAttributeList(NULL, 1, 0, &bytes_required);
conpty_object->si_ex.lpAttributeList =
(PPROC_THREAD_ATTRIBUTE_LIST)xmalloc(bytes_required);
if (!InitializeProcThreadAttributeList(conpty_object->si_ex.lpAttributeList,
1,
0,
&bytes_required)) {
emsg = "InitializeProcThreadAttributeList failed";
goto failed;
}
if (!UpdateProcThreadAttribute(conpty_object->si_ex.lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
conpty_object->pty,
sizeof(conpty_object->pty),
NULL,
NULL)) {
emsg = "UpdateProcThreadAttribute failed";
goto failed;
}
count++;
goto finished;
failed:
ELOG("os_conpty_init:%s : error code: %d",
emsg, os_translate_sys_error((int)GetLastError()));
os_conpty_free(conpty_object);
conpty_object = NULL;
finished:
if (in_read != INVALID_HANDLE_VALUE) {
CloseHandle(in_read);
}
if (out_write != INVALID_HANDLE_VALUE) {
CloseHandle(out_write);
}
return conpty_object;
}
bool os_conpty_spawn(conpty_t *conpty_object, HANDLE *proc_handle, wchar_t *name,
wchar_t *cmd_line, wchar_t *cwd, wchar_t *env)
{
PROCESS_INFORMATION pi = { 0 };
if (!CreateProcessW(name,
cmd_line,
NULL,
NULL,
false,
EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT,
env,
cwd,
&conpty_object->si_ex.StartupInfo,
&pi)) {
return false;
}
*proc_handle = pi.hProcess;
return true;
}
void os_conpty_set_size(conpty_t *conpty_object, uint16_t width, uint16_t height)
{
assert(width <= SHRT_MAX);
assert(height <= SHRT_MAX);
COORD size = { (int16_t)width, (int16_t)height };
if (pResizePseudoConsole(conpty_object->pty, size) != S_OK) {
ELOG("ResizePseudoConsoel failed: error code: %d",
os_translate_sys_error((int)GetLastError()));
}
}
void os_conpty_free(conpty_t *conpty_object)
{
if (conpty_object != NULL) {
if (conpty_object->si_ex.lpAttributeList != NULL) {
DeleteProcThreadAttributeList(conpty_object->si_ex.lpAttributeList);
xfree(conpty_object->si_ex.lpAttributeList);
}
if (conpty_object->pty != NULL) {
pClosePseudoConsole(conpty_object->pty);
}
}
xfree(conpty_object);
}