[*] Recrinkle win32 process send term and stdin CONIN/OUT win32 logic
This commit is contained in:
parent
c6d649e3de
commit
9e26996463
@ -108,61 +108,76 @@ namespace Aurora::Console::ConsoleStd
|
||||
DWORD dwMode;
|
||||
bool ok;
|
||||
// Obtain a win32 file HANDLE of STDIN
|
||||
auto fileHandle = CreateFileA("CONIN$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
auto fileHandle =
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
GetStdHandle(STD_INPUT_HANDLE);
|
||||
#else
|
||||
CreateFileW(L"CONIN$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
SysAssert(fileHandle != INVALID_HANDLE_VALUE, "Couldn't open CONIN");
|
||||
gInputStream = fileHandle;
|
||||
|
||||
// Obtain a win32 file HANDLE of STDOUT
|
||||
fileHandle = CreateFileA("CONOUT$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
fileHandle =
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
#else
|
||||
CreateFileW(L"CONOUT$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
SysAssert(fileHandle != INVALID_HANDLE_VALUE, "Couldn't open CONOUT");
|
||||
gOutputStream = fileHandle;
|
||||
|
||||
// Get current console flags
|
||||
if (GetConsoleMode(gOutputStream, &dwMode))
|
||||
{
|
||||
if (gRuntimeConfig.console.enableStdPassthrough ^ gRuntimeConfig.console.enableStdOut)
|
||||
{
|
||||
// Enable escape processing; enable colored output
|
||||
dwMode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
ok = SetConsoleMode(gOutputStream, dwMode);
|
||||
SysAssert(ok, "Couldn't set console mode");
|
||||
bool isNotPipe = GetFileType(fileHandle) != FILE_TYPE_PIPE;
|
||||
|
||||
if (isNotPipe)
|
||||
{
|
||||
// Get current console flags
|
||||
if (GetConsoleMode(gOutputStream, &dwMode))
|
||||
{
|
||||
if (gRuntimeConfig.console.enableStdPassthrough ^ gRuntimeConfig.console.enableStdOut)
|
||||
{
|
||||
// Enable escape processing; enable colored output
|
||||
dwMode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
ok = SetConsoleMode(gOutputStream, dwMode);
|
||||
SysAssert(ok, "Couldn't set console mode");
|
||||
|
||||
// Set the output stream to use UTF-8
|
||||
ok = SetConsoleOutputCP(CP_UTF8);
|
||||
SysAssert(ok, "Couldn't maintain UTF-8 stdout stream");
|
||||
}
|
||||
}
|
||||
|
||||
// Set binary mode if redirecting stdin to user
|
||||
if (gRuntimeConfig.console.enableStdPassthrough && gRuntimeConfig.console.enableStdOut)
|
||||
{
|
||||
SetConsoleMode(gOutputStream, 0);
|
||||
}
|
||||
|
||||
if (gRuntimeConfig.console.enableStdPassthrough ^ gRuntimeConfig.console.enableStdIn)
|
||||
{
|
||||
ok = SetConsoleCP(CP_UTF8);
|
||||
#if 0
|
||||
SysAssert(ok, "Couldn't maintain UTF-8 stdin stream");
|
||||
#endif
|
||||
|
||||
// Set the output stream to use UTF-8
|
||||
ok = SetConsoleOutputCP(CP_UTF8);
|
||||
SysAssert(ok, "Couldn't maintain UTF-8 stdout stream");
|
||||
}
|
||||
}
|
||||
|
||||
// Set binary mode if redirecting stdin to user
|
||||
if (gRuntimeConfig.console.enableStdPassthrough && gRuntimeConfig.console.enableStdOut)
|
||||
{
|
||||
SetConsoleMode(gOutputStream, 0);
|
||||
}
|
||||
|
||||
if (gRuntimeConfig.console.enableStdPassthrough ^ gRuntimeConfig.console.enableStdIn)
|
||||
{
|
||||
ok = SetConsoleCP(CP_UTF8);
|
||||
#if 0
|
||||
SysAssert(ok, "Couldn't maintain UTF-8 stdin stream");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (gRuntimeConfig.console.enableStdPassthrough && gRuntimeConfig.console.enableStdIn)
|
||||
if (gRuntimeConfig.console.enableStdPassthrough && gRuntimeConfig.console.enableStdIn && isNotPipe)
|
||||
{
|
||||
if (!GetConsoleMode(gInputStream, &dwMode))
|
||||
{
|
||||
@ -201,13 +216,11 @@ namespace Aurora::Console::ConsoleStd
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gRuntimeConfig.console.forceConsoleWindow)
|
||||
if (gRuntimeConfig.console.forceConsoleWindow)
|
||||
{
|
||||
return;
|
||||
auto ok = AllocConsole();
|
||||
SysAssert(ok, "Request of a Win32 console yielded nada, forceConsole wasn't respected");
|
||||
}
|
||||
|
||||
auto ok = AllocConsole();
|
||||
SysAssert(ok, "Request of a Win32 console yielded nada, forceConsole wasn't respected");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -194,7 +194,7 @@ namespace Aurora::IO::FS
|
||||
if (str[1] == kPathSplitter)
|
||||
{
|
||||
auto c = str[0];
|
||||
if ((c == '.') || (c == '~') || (c == '!') || (c == '?'))
|
||||
if ((c == '.') || (c == '~') || (c == '!') || (c == '?' || (c == '^')))
|
||||
{
|
||||
requiresMountUpdate = true;
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#include "ArgvQuote.hpp"
|
||||
|
||||
#include <Source/IO/FS/FS.hpp>
|
||||
|
||||
namespace Aurora::Processes
|
||||
{
|
||||
ProcessImpl::ProcessImpl(const StartupParmaters ¶ms) : startup_(params)
|
||||
@ -293,7 +295,7 @@ namespace Aurora::Processes
|
||||
startupInfo.hStdOutput = pipeStdOutWrite_;
|
||||
startupInfo.dwFlags |= (inheritHandles ? STARTF_USESTDHANDLES : 0);
|
||||
|
||||
auto result = CreateProcessW(Locale::ConvertFromUTF8(this->startup_.process).c_str(),
|
||||
auto result = CreateProcessW(Locale::ConvertFromUTF8(AuIOFS::NormalizePathRet(this->startup_.process)).c_str(),
|
||||
Locale::ConvertFromUTF8(this->windowsCli_).data(),
|
||||
NULL, NULL, inheritHandles,
|
||||
this->startup_.noShowConsole ? CREATE_NO_WINDOW : NULL, // yea we can keep CREATE_NO_WINDOW on for non-console apps. its legal -> https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
|
||||
@ -301,6 +303,7 @@ namespace Aurora::Processes
|
||||
|
||||
if (!result)
|
||||
{
|
||||
DWORD wr = GetLastError();
|
||||
SysPushErrorGen("CreateProcess failed");
|
||||
return false;
|
||||
}
|
||||
@ -308,9 +311,9 @@ namespace Aurora::Processes
|
||||
this->process_ = processInfo.hProcess;
|
||||
this->hthread_ = processInfo.hThread;
|
||||
|
||||
AuWin32CloseHandle(this->pipeStdOutRead_);
|
||||
AuWin32CloseHandle(this->pipeStdErrRead_);
|
||||
AuWin32CloseHandle(this->pipeStdInWrite_);
|
||||
AuWin32CloseHandle(this->pipeStdOutWrite_);
|
||||
AuWin32CloseHandle(this->pipeStdErrWrite_);
|
||||
AuWin32CloseHandle(this->pipeStdInRead_);
|
||||
|
||||
if (this->type_ == ESpawnType::eSpawnChildProcessWorker)
|
||||
{
|
||||
|
@ -60,11 +60,24 @@ namespace Aurora::Processes
|
||||
|
||||
return exitCode != STILL_ACTIVE;
|
||||
}
|
||||
|
||||
struct Hack
|
||||
{
|
||||
HANDLE base;
|
||||
AuUInt32 count;
|
||||
};
|
||||
|
||||
static BOOL TermWinHandleWin32Thread(HWND handle, LPARAM a)
|
||||
{
|
||||
SendMessageA(handle, WM_CLOSE, 0, 0);
|
||||
(*reinterpret_cast<AuUInt32 *>(a))++;
|
||||
DWORD windowpid;
|
||||
auto context = reinterpret_cast<Hack *>(a);
|
||||
auto pid = GetProcessId(context->base);
|
||||
GetWindowThreadProcessId(handle, &windowpid);
|
||||
if (pid && pid == windowpid)
|
||||
{
|
||||
SendMessageA(handle, WM_CLOSE, 0, 0);
|
||||
context->count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -72,15 +85,25 @@ namespace Aurora::Processes
|
||||
{
|
||||
THREADENTRY32 te{};
|
||||
HANDLE h{};
|
||||
Hack hello;
|
||||
|
||||
hello.count = 0;
|
||||
hello.base = handle;
|
||||
|
||||
te.dwSize = sizeof(te);
|
||||
te.th32OwnerProcessID = GetProcessId(handle);
|
||||
|
||||
if (!te.th32OwnerProcessID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetProcessId(handle));
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
te.dwSize = sizeof(te);
|
||||
AuUInt32 count{};
|
||||
|
||||
if (Thread32First(h, &te))
|
||||
{
|
||||
do
|
||||
@ -88,7 +111,7 @@ namespace Aurora::Processes
|
||||
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
|
||||
sizeof(te.th32OwnerProcessID))
|
||||
{
|
||||
EnumThreadWindows(te.th32ThreadID, TermWinHandleWin32Thread, reinterpret_cast<LPARAM>(&count));
|
||||
EnumThreadWindows(te.th32ThreadID, TermWinHandleWin32Thread, reinterpret_cast<LPARAM>(&hello));
|
||||
}
|
||||
te.dwSize = sizeof(te);
|
||||
} while (Thread32Next(h, &te));
|
||||
@ -96,7 +119,7 @@ namespace Aurora::Processes
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
if (!count)
|
||||
if (!hello.count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -106,11 +129,19 @@ namespace Aurora::Processes
|
||||
|
||||
static bool SendControlCEquiv(HANDLE handle)
|
||||
{
|
||||
auto cwnd = GetConsoleWindow();
|
||||
|
||||
if (!(AttachConsole(GetProcessId(handle))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cwnd == GetConsoleWindow())
|
||||
{
|
||||
FreeConsole();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SetConsoleCtrlHandler({}, true))
|
||||
{
|
||||
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user