Add manager ability to send the cmd line and working directory instead.

This commit is contained in:
Michael Niksa 2019-07-23 15:29:41 -07:00
parent 9dfbdec349
commit c41151aba7
15 changed files with 244 additions and 45 deletions

View file

@ -911,12 +911,20 @@ namespace winrt::TerminalApp::implementation
// currently displayed, it will be shown. // currently displayed, it will be shown.
// Arguments: // Arguments:
// - settings: the TerminalSettings object to use to create the TerminalControl with. // - settings: the TerminalSettings object to use to create the TerminalControl with.
void App::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings) void App::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings, std::optional<uint64_t> serverHandle)
{ {
// Initialize the new tab // Initialize the new tab
TerminalConnection::ITerminalConnection connection = nullptr;
// Create a Conhost connection based on the values in our settings object. // Create a Conhost connection based on the values in our settings object.
TerminalConnection::ITerminalConnection connection = TerminalConnection::ConhostConnection(settings.Commandline(), settings.StartingDirectory(), 30, 80, winrt::guid()); if (!serverHandle)
{
connection = TerminalConnection::ConhostConnection(settings.Commandline(), settings.StartingDirectory(), 30, 80, winrt::guid());
}
else
{
connection = TerminalConnection::ConhostConnection(serverHandle.value(), 30, 80, winrt::guid());
}
TermControl term{ settings, connection }; TermControl term{ settings, connection };
@ -1158,10 +1166,30 @@ namespace winrt::TerminalApp::implementation
return { L"Windows Terminal" }; return { L"Windows Terminal" };
} }
void App::IncomingConnection() void App::IncomingConnection(uint64_t serverHandle)
{ {
_root.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [this]() { _root.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [this, serverHandle]() {
_OpenNewTab(std::nullopt); // Getting Guid for default profile
const auto globalSettings = _settings->GlobalSettings();
auto profileGuid = globalSettings.GetDefaultProfile();
TerminalSettings settings = _settings->MakeSettings(profileGuid);
_CreateNewTabFromSettings(profileGuid, settings, serverHandle);
});
}
void App::IncomingConnection(hstring cmdline, hstring workingDir)
{
_root.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [this, cmdline, workingDir]() {
// Getting Guid for default profile
const auto globalSettings = _settings->GlobalSettings();
auto profileGuid = globalSettings.GetDefaultProfile();
TerminalSettings settings = _settings->MakeSettings(profileGuid);
settings.Commandline(cmdline);
settings.StartingDirectory(workingDir);
_CreateNewTabFromSettings(profileGuid, settings);
}); });
} }

View file

@ -40,7 +40,8 @@ namespace winrt::TerminalApp::implementation
hstring GetTitle(); hstring GetTitle();
void IncomingConnection(); void IncomingConnection(uint64_t serverHandle);
void IncomingConnection(hstring cmdline, hstring workingDir);
// -------------------------------- WinRT Events --------------------------------- // -------------------------------- WinRT Events ---------------------------------
DECLARE_EVENT(TitleChanged, _titleChangeHandlers, winrt::Microsoft::Terminal::TerminalControl::TitleChangedEventArgs); DECLARE_EVENT(TitleChanged, _titleChangeHandlers, winrt::Microsoft::Terminal::TerminalControl::TitleChangedEventArgs);
@ -102,7 +103,7 @@ namespace winrt::TerminalApp::implementation
void _RegisterTerminalEvents(Microsoft::Terminal::TerminalControl::TermControl term, std::shared_ptr<Tab> hostingTab); void _RegisterTerminalEvents(Microsoft::Terminal::TerminalControl::TermControl term, std::shared_ptr<Tab> hostingTab);
void _CreateNewTabFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings); void _CreateNewTabFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings, std::optional<uint64_t> serverHandle = std::nullopt);
void _OpenNewTab(std::optional<int> profileIndex); void _OpenNewTab(std::optional<int> profileIndex);
void _DuplicateTabViewItem(); void _DuplicateTabViewItem();

View file

@ -31,6 +31,7 @@ namespace TerminalApp
String GetTitle(); String GetTitle();
void IncomingConnection(); void IncomingConnection(UInt64 serverHandle);
void IncomingConnection(String cmdline, String workingDir);
} }
} }

View file

@ -37,6 +37,23 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
} }
} }
ConhostConnection::ConhostConnection(const uint64_t server,
const uint32_t initialRows,
const uint32_t initialCols,
const guid& initialGuid) :
_initialRows{ initialRows },
_initialCols{ initialCols },
_commandline{},
_startingDirectory{},
_guid{ initialGuid },
_hServer{ reinterpret_cast<HANDLE>(server) }
{
if (_guid == guid{})
{
_guid = Utils::CreateGuid();
}
}
winrt::guid ConhostConnection::Guid() const noexcept winrt::guid ConhostConnection::Guid() const noexcept
{ {
return _guid; return _guid;
@ -71,6 +88,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
startingDirectory = _startingDirectory; startingDirectory = _startingDirectory;
} }
std::optional<HANDLE> server;
if (_hServer)
{
server = _hServer.get();
}
EnvironmentVariableMapW extraEnvVars; EnvironmentVariableMapW extraEnvVars;
{ {
// Convert connection Guid to string and ignore the enclosing '{}'. // Convert connection Guid to string and ignore the enclosing '{}'.
@ -88,6 +111,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
startingDirectory, startingDirectory,
static_cast<short>(_initialCols), static_cast<short>(_initialCols),
static_cast<short>(_initialRows), static_cast<short>(_initialRows),
server,
&_inPipe, &_inPipe,
&_outPipe, &_outPipe,
&_signalPipe, &_signalPipe,

View file

@ -10,6 +10,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
struct ConhostConnection : ConhostConnectionT<ConhostConnection> struct ConhostConnection : ConhostConnectionT<ConhostConnection>
{ {
ConhostConnection(const hstring& cmdline, const hstring& startingDirectory, const uint32_t rows, const uint32_t cols, const guid& guid); ConhostConnection(const hstring& cmdline, const hstring& startingDirectory, const uint32_t rows, const uint32_t cols, const guid& guid);
ConhostConnection(const uint64_t server, const uint32_t rows, const uint32_t cols, const guid& guid);
winrt::event_token TerminalOutput(TerminalConnection::TerminalOutputEventArgs const& handler); winrt::event_token TerminalOutput(TerminalConnection::TerminalOutputEventArgs const& handler);
void TerminalOutput(winrt::event_token const& token) noexcept; void TerminalOutput(winrt::event_token const& token) noexcept;
@ -41,6 +42,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
wil::unique_handle _hOutputThread; wil::unique_handle _hOutputThread;
wil::unique_process_information _piConhost; wil::unique_process_information _piConhost;
wil::unique_handle _hJob; wil::unique_handle _hJob;
wil::unique_handle _hServer;
static DWORD WINAPI StaticOutputThreadProc(LPVOID lpParameter); static DWORD WINAPI StaticOutputThreadProc(LPVOID lpParameter);
DWORD _OutputThread(); DWORD _OutputThread();

View file

@ -9,6 +9,7 @@ namespace Microsoft.Terminal.TerminalConnection
runtimeclass ConhostConnection : ITerminalConnection runtimeclass ConhostConnection : ITerminalConnection
{ {
ConhostConnection(String cmdline, String startingDirectory, UInt32 rows, UInt32 columns, Guid guid); ConhostConnection(String cmdline, String startingDirectory, UInt32 rows, UInt32 columns, Guid guid);
ConhostConnection(UInt64 server, UInt32 rows, UInt32 columns, Guid guid);
Guid Guid { get; }; Guid Guid { get; };
}; };

View file

@ -72,9 +72,14 @@ void AppHost::Initialize()
_window->OnAppInitialized(_app); _window->OnAppInitialized(_app);
} }
void AppHost::IncomingConnection() void AppHost::IncomingConnectionByHandle(HANDLE handle)
{ {
_app.IncomingConnection(); _app.IncomingConnection(reinterpret_cast<uint64_t>(handle));
}
void AppHost::IncomingConnectionByLaunch(std::wstring_view cmdline, std::wstring_view workingDir)
{
_app.IncomingConnection(winrt::hstring(cmdline), winrt::hstring(workingDir));
} }
// Method Description: // Method Description:

View file

@ -14,7 +14,8 @@ public:
AppHost() noexcept; AppHost() noexcept;
virtual ~AppHost(); virtual ~AppHost();
void IncomingConnection(); void IncomingConnectionByHandle(HANDLE handle);
void IncomingConnectionByLaunch(std::wstring_view cmdline, std::wstring_view workingDir);
void AppTitleChanged(winrt::hstring newTitle); void AppTitleChanged(winrt::hstring newTitle);
void LastTabClosed(); void LastTabClosed();
void Initialize(); void Initialize();

View file

@ -108,15 +108,15 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
// provides an implementation of Windows.UI.Xaml.Application. // provides an implementation of Windows.UI.Xaml.Application.
AppHost host; AppHost host;
auto lambda = std::function<void()>([&] {
host.IncomingConnection();
});
// Create a manager object for IPC. // Create a manager object for IPC.
Manager manager; Manager manager;
Manager::s_RegisterOnConnection(lambda); // Create and register on connection callbacks from the manager into the application host.
std::function<void(HANDLE)> onHandleConnection = std::bind(&AppHost::IncomingConnectionByHandle, &host, std::placeholders::_1);
std::function<void(std::wstring_view, std::wstring_view)> onLaunchConnection = std::bind(&AppHost::IncomingConnectionByLaunch, &host, std::placeholders::_1, std::placeholders::_2);
Manager::s_RegisterOnConnection(onHandleConnection);
Manager::s_RegisterOnConnection(onLaunchConnection);
// !!! LOAD BEARING !!! // !!! LOAD BEARING !!!
// This is _magic_. Do the initial loading of our settings *BEFORE* we // This is _magic_. Do the initial loading of our settings *BEFORE* we

View file

@ -104,7 +104,8 @@ ConsoleArguments::ConsoleArguments(const std::wstring& commandline,
_recievedEarlySizeChange{ false }, _recievedEarlySizeChange{ false },
_originalWidth{ -1 }, _originalWidth{ -1 },
_originalHeight{ -1 }, _originalHeight{ -1 },
_forceManager{ false } _forceManager{ false },
_workingDirectory{ wil::GetCurrentDirectoryW().get() }
{ {
_clientCommandline = L""; _clientCommandline = L"";
_vtMode = L""; _vtMode = L"";

View file

@ -111,6 +111,8 @@ private:
std::wstring _clientCommandline; std::wstring _clientCommandline;
std::wstring _workingDirectory;
HANDLE _vtInHandle; HANDLE _vtInHandle;
HANDLE _vtOutHandle; HANDLE _vtOutHandle;

View file

@ -201,6 +201,7 @@ bool SignalResizeWindow(const HANDLE hSignal,
// - startingDirectory: The directory to start the process in // - startingDirectory: The directory to start the process in
// - w: The initial width of the pty, in characters // - w: The initial width of the pty, in characters
// - h: The initial height of the pty, in characters // - h: The initial height of the pty, in characters
// - hServer: An optional handle to a server connection handle already established for this PTY.
// - hInput: A handle to the pipe for writing input to the pty. // - hInput: A handle to the pipe for writing input to the pty.
// - hOutput: A handle to the pipe for reading the output of the pty. // - hOutput: A handle to the pipe for reading the output of the pty.
// - hSignal: A handle to the pipe for writing signal messages to the pty. // - hSignal: A handle to the pipe for writing signal messages to the pty.
@ -216,6 +217,7 @@ bool SignalResizeWindow(const HANDLE hSignal,
std::optional<std::wstring> startingDirectory, std::optional<std::wstring> startingDirectory,
const unsigned short w, const unsigned short w,
const unsigned short h, const unsigned short h,
std::optional<HANDLE> const hServer,
HANDLE* const hInput, HANDLE* const hInput,
HANDLE* const hOutput, HANDLE* const hOutput,
HANDLE* const hSignal, HANDLE* const hSignal,
@ -254,6 +256,11 @@ bool SignalResizeWindow(const HANDLE hSignal,
SetHandleInformation(outPipeConhostSide, HANDLE_FLAG_INHERIT, 1); SetHandleInformation(outPipeConhostSide, HANDLE_FLAG_INHERIT, 1);
SetHandleInformation(signalPipeConhostSide, HANDLE_FLAG_INHERIT, 1); SetHandleInformation(signalPipeConhostSide, HANDLE_FLAG_INHERIT, 1);
if (hServer.has_value())
{
SetHandleInformation(hServer.value(), HANDLE_FLAG_INHERIT, 1);
}
std::wstring conhostCmdline = L"conhost.exe"; std::wstring conhostCmdline = L"conhost.exe";
conhostCmdline += L" --headless"; conhostCmdline += L" --headless";
std::wstringstream ss; std::wstringstream ss;
@ -264,9 +271,19 @@ bool SignalResizeWindow(const HANDLE hSignal,
} }
ss << L" --signal 0x" << std::hex << HandleToUlong(signalPipeConhostSide); ss << L" --signal 0x" << std::hex << HandleToUlong(signalPipeConhostSide);
if (hServer.has_value())
{
ss << L" --server 0x" << std::hex << HandleToUlong(hServer.value());
}
conhostCmdline += ss.str(); conhostCmdline += ss.str();
conhostCmdline += L" -- ";
conhostCmdline += cmdline; if (!hServer.has_value())
{
conhostCmdline += L" -- ";
conhostCmdline += cmdline;
}
STARTUPINFO si = { 0 }; STARTUPINFO si = { 0 };
si.cb = sizeof(STARTUPINFOW); si.cb = sizeof(STARTUPINFOW);

View file

@ -16,13 +16,14 @@
{ {
if (args.ShouldSendToManager()) if (args.ShouldSendToManager())
{ {
Manager::s_TrySendToManager(args.GetServerHandle()); if (Manager::s_TrySendToManager(args.GetServerHandle()))
return S_OK; {
} SleepEx(INFINITE, FALSE);
else return S_OK;
{ }
return ConsoleCreateIoThreadLegacy(args);
} }
return ConsoleCreateIoThreadLegacy(args);
} }
// this function has unreachable code due to its unusual lifetime. We // this function has unreachable code due to its unusual lifetime. We
@ -32,6 +33,15 @@
[[nodiscard]] HRESULT Entrypoints::StartConsoleForCmdLine(ConsoleArguments& args) [[nodiscard]] HRESULT Entrypoints::StartConsoleForCmdLine(ConsoleArguments& args)
{ {
if (args.ShouldSendToManager())
{
if (Manager::s_TrySendToManager(args.GetClientCommandline(), L"C:\\windows\\system32"))
{
SleepEx(INFINITE, FALSE);
return S_OK;
}
}
// Create a scope because we're going to exit thread if everything goes well. // Create a scope because we're going to exit thread if everything goes well.
// This scope will ensure all C++ objects and smart pointers get a chance to destruct before ExitThread is called. // This scope will ensure all C++ objects and smart pointers get a chance to destruct before ExitThread is called.
{ {

View file

@ -39,6 +39,7 @@ Manager::Manager() :
else else
{ {
ManagerMessageQuery query; ManagerMessageQuery query;
query.size = sizeof(query);
query.type = ManagerMessageTypes::GetManagerPid; query.type = ManagerMessageTypes::GetManagerPid;
const auto reply = _ask(query); const auto reply = _ask(query);
@ -50,7 +51,7 @@ Manager::Manager() :
WaitForSingleObject(managerProcess.get(), INFINITE); WaitForSingleObject(managerProcess.get(), INFINITE);
_becomeServer(); _becomeServer();
}); });
} }
} }
@ -70,6 +71,7 @@ bool Manager::s_TrySendToManager(const HANDLE server)
{ {
// Get PID from remote process. // Get PID from remote process.
ManagerMessageQuery query; ManagerMessageQuery query;
query.size = sizeof(query);
query.type = ManagerMessageTypes::GetManagerPid; query.type = ManagerMessageTypes::GetManagerPid;
auto reply = _ask(query); auto reply = _ask(query);
@ -88,12 +90,51 @@ bool Manager::s_TrySendToManager(const HANDLE server)
DUPLICATE_SAME_ACCESS)); DUPLICATE_SAME_ACCESS));
// Tell remote process about new handle ID // Tell remote process about new handle ID
query.size = sizeof(query);
query.type = ManagerMessageTypes::SendConnection; query.type = ManagerMessageTypes::SendConnection;
query.query.sendConn.handle = targetHandle; query.query.sendConn.handle = targetHandle;
reply = _ask(query); reply = _ask(query);
return true; return reply.reply.sendConn.ok;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
return false;
}
}
bool Manager::s_TrySendToManager(const std::wstring_view cmdline,
const std::wstring_view workingDir)
{
try
{
// Figure out how much data we actually need to send with the variable length strings
size_t size = sizeof(ManagerMessageQuery) + 1;
size += 2*(cmdline.size() + 1);
size += 2*(workingDir.size() + 1);
// Make a big buffer to hold it all contiguously
const auto buffer = std::make_unique<byte[]>(size);
// Make pointers to fill up each piece of data
const auto query = reinterpret_cast<ManagerMessageQuery*>(buffer.get());
const auto cmdPayload = reinterpret_cast<PWCHAR>(buffer.get() + sizeof(ManagerMessageQuery) + 1);
const auto workingPayload = reinterpret_cast<PWCHAR>(buffer.get() + sizeof(ManagerMessageQuery) + 1 + (cmdline.size() + 1) * 2);
// Tell the remote process the command line and working directory
query->size = gsl::narrow<DWORD>(size);
query->type = ManagerMessageTypes::SendCmdAndWorking;
query->query.sendCmdAndWorking.cmd = gsl::narrow<DWORD>(cmdline.size());
query->query.sendCmdAndWorking.working = gsl::narrow<DWORD>(workingDir.size());
THROW_IF_FAILED(StringCchCopyW(cmdPayload, cmdline.size() + 1, cmdline.data()));
THROW_IF_FAILED(StringCchCopyW(workingPayload, workingDir.size() + 1, workingDir.data()));
const auto reply = _ask(*query);
return reply.reply.sendConn.ok;
} }
catch (...) catch (...)
{ {
@ -163,7 +204,7 @@ void Manager::_serverLoop()
const auto loosePipeHandle = pipe.release(); const auto loosePipeHandle = pipe.release();
auto future = std::async(std::launch::async, [this, loosePipeHandle] { auto future = std::async(std::launch::async, [this, loosePipeHandle] {
_perClientLoop(wil::unique_handle(loosePipeHandle)); _perClientLoop(wil::unique_handle(loosePipeHandle));
}); });
_perClientWork.push_back(std::move(future)); _perClientWork.push_back(std::move(future));
} }
else if (ret == WAIT_FAILED) else if (ret == WAIT_FAILED)
@ -184,11 +225,30 @@ void Manager::_perClientLoop(wil::unique_handle pipe)
{ {
ManagerMessageQuery query; ManagerMessageQuery query;
DWORD bytesRead = 0; DWORD bytesRead = 0;
THROW_IF_WIN32_BOOL_FALSE(ReadFile(pipe.get(), SetLastError(S_OK);
&query, const auto result = ReadFile(pipe.get(),
sizeof(query), &query,
&bytesRead, sizeof(query),
nullptr)); &bytesRead,
nullptr);
// False is OK if it's ERROR_MORE_DATA.
const auto gle = GetLastError();
THROW_LAST_ERROR_IF(!result && gle != ERROR_MORE_DATA);
std::unique_ptr<byte[]> buffer;
if (gle == ERROR_MORE_DATA)
{
const auto remainingBytes = query.size - gsl::narrow<DWORD>(sizeof(query));
buffer = std::make_unique<byte[]>(remainingBytes);
bytesRead = 0;
THROW_IF_WIN32_BOOL_FALSE(ReadFile(pipe.get(),
buffer.get(),
remainingBytes,
&bytesRead,
nullptr));
}
ManagerMessageReply reply; ManagerMessageReply reply;
switch (query.type) switch (query.type)
@ -199,6 +259,9 @@ void Manager::_perClientLoop(wil::unique_handle pipe)
case ManagerMessageTypes::SendConnection: case ManagerMessageTypes::SendConnection:
reply = _sendConnection(query); reply = _sendConnection(query);
break; break;
case ManagerMessageTypes::SendCmdAndWorking:
reply = _sendCmdAndWorking(query, buffer);
break;
default: default:
THROW_HR(E_NOTIMPL); THROW_HR(E_NOTIMPL);
} }
@ -212,14 +275,14 @@ void Manager::_perClientLoop(wil::unique_handle pipe)
} }
} }
Manager::ManagerMessageReply Manager::_ask(Manager::ManagerMessageQuery query) Manager::ManagerMessageReply Manager::_ask(Manager::ManagerMessageQuery& query)
{ {
ManagerMessageReply reply; ManagerMessageReply reply;
DWORD bytesRead = 0; DWORD bytesRead = 0;
THROW_IF_WIN32_BOOL_FALSE(CallNamedPipeW(PIPE_NAME.data(), THROW_IF_WIN32_BOOL_FALSE(CallNamedPipeW(PIPE_NAME.data(),
&query, &query,
sizeof(query), query.size,
&reply, &reply,
sizeof(reply), sizeof(reply),
&bytesRead, &bytesRead,
@ -238,17 +301,21 @@ Manager::ManagerMessageReply Manager::_getPid(ManagerMessageQuery /*query*/)
return reply; return reply;
} }
static std::vector<std::function<void()>> s_onConnection; static std::vector<std::function<void(HANDLE)>> s_onHandleConnection;
void Manager::s_RegisterOnConnection(std::function<void(HANDLE)> func)
{
s_onHandleConnection.push_back(func);
}
Manager::ManagerMessageReply Manager::_sendConnection(ManagerMessageQuery query) Manager::ManagerMessageReply Manager::_sendConnection(ManagerMessageQuery query)
{ {
const auto server = query.query.sendConn.handle; const auto serverHandle = query.query.sendConn.handle;
server;
// create new conhost connection... // create new conhost connection...
for (const auto& func : s_onConnection) for (const auto& func : s_onHandleConnection)
{ {
func(); func(serverHandle);
} }
ManagerMessageReply reply; ManagerMessageReply reply;
@ -259,8 +326,32 @@ Manager::ManagerMessageReply Manager::_sendConnection(ManagerMessageQuery query)
return reply; return reply;
} }
void Manager::s_RegisterOnConnection(std::function<void()> func) static std::vector<std::function<void(std::wstring_view, std::wstring_view)>> s_onLaunchConnection;
void Manager::s_RegisterOnConnection(std::function<void(std::wstring_view, std::wstring_view)> func)
{ {
s_onConnection.push_back(func); s_onLaunchConnection.push_back(func);
}
Manager::ManagerMessageReply Manager::_sendCmdAndWorking(ManagerMessageQuery query, std::unique_ptr<BYTE[]>& buffer)
{
const auto cmd = query.query.sendCmdAndWorking.cmd;
const auto work = query.query.sendCmdAndWorking.working;
std::wstring_view cmdline(reinterpret_cast<wchar_t*>(buffer.get() + 1), cmd);
std::wstring_view workingDir(reinterpret_cast<wchar_t*>(buffer.get() + 1 + (cmd + 1) * 2), work);
// create new conhost connection...
for (const auto& func : s_onLaunchConnection)
{
func(cmdline, workingDir);
}
ManagerMessageReply reply;
reply.type = ManagerMessageTypes::SendCmdAndWorking;
reply.reply.sendCmdAndWorking.ok = true;
return reply;
} }

View file

@ -9,8 +9,11 @@ public:
void NotifyExit(); void NotifyExit();
static void s_RegisterOnConnection(std::function<void()> func); static void s_RegisterOnConnection(std::function<void(HANDLE)> func);
static void s_RegisterOnConnection(std::function<void(std::wstring_view, std::wstring_view)> func);
static bool s_TrySendToManager(const HANDLE server); static bool s_TrySendToManager(const HANDLE server);
static bool s_TrySendToManager(const std::wstring_view cmdline,
const std::wstring_view workingDir);
Manager(const Manager&) = delete; Manager(const Manager&) = delete;
Manager(Manager&&) = delete; Manager(Manager&&) = delete;
@ -28,11 +31,13 @@ private:
enum class ManagerMessageTypes enum class ManagerMessageTypes
{ {
GetManagerPid, GetManagerPid,
SendConnection SendConnection,
SendCmdAndWorking
}; };
struct ManagerMessageQuery struct ManagerMessageQuery
{ {
DWORD size;
ManagerMessageTypes type; ManagerMessageTypes type;
union union
{ {
@ -40,6 +45,11 @@ private:
{ {
HANDLE handle; HANDLE handle;
} sendConn; } sendConn;
struct SendCmdAndWorking
{
DWORD cmd;
DWORD working;
} sendCmdAndWorking;
} query; } query;
}; };
@ -56,12 +66,17 @@ private:
{ {
bool ok; bool ok;
} sendConn; } sendConn;
struct SendCmdAndWorking
{
bool ok;
} sendCmdAndWorking;
} reply; } reply;
}; };
static ManagerMessageReply _ask(ManagerMessageQuery query); static ManagerMessageReply _ask(ManagerMessageQuery& query);
static ManagerMessageReply _getPid(ManagerMessageQuery query); static ManagerMessageReply _getPid(ManagerMessageQuery query);
static ManagerMessageReply _sendConnection(ManagerMessageQuery query); static ManagerMessageReply _sendConnection(ManagerMessageQuery query);
static ManagerMessageReply _sendCmdAndWorking(ManagerMessageQuery query, std::unique_ptr<byte[]>& buffer);
void _becomeServer(); void _becomeServer();
void _serverLoop(); void _serverLoop();