2015-10-22 23:16:47 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "Command.h"
|
|
|
|
#include "Event.h"
|
|
|
|
#include "RemoteHandle.h"
|
|
|
|
#include "ShmemParcel.h"
|
|
|
|
#include "Spawn.h"
|
|
|
|
#include "UnicodeConversions.h"
|
|
|
|
|
|
|
|
class RemoteWorker {
|
|
|
|
friend class RemoteHandle;
|
2015-10-26 04:28:34 +00:00
|
|
|
static DWORD dwDefaultCreationFlags;
|
|
|
|
|
|
|
|
public:
|
|
|
|
static void setDefaultCreationFlags(DWORD flags) {
|
|
|
|
dwDefaultCreationFlags = flags;
|
|
|
|
}
|
|
|
|
static DWORD defaultCreationFlags() {
|
|
|
|
return dwDefaultCreationFlags;
|
|
|
|
}
|
2015-10-22 23:16:47 +00:00
|
|
|
|
|
|
|
public:
|
2015-10-23 20:29:46 +00:00
|
|
|
struct {} static constexpr DoNotSpawn = {};
|
|
|
|
explicit RemoteWorker(decltype(DoNotSpawn));
|
2015-10-26 04:28:34 +00:00
|
|
|
explicit RemoteWorker() : RemoteWorker({false, dwDefaultCreationFlags}) {}
|
|
|
|
explicit RemoteWorker(SpawnParams params);
|
2015-10-23 03:23:48 +00:00
|
|
|
RemoteWorker child(SpawnParams params={});
|
2015-10-23 04:57:30 +00:00
|
|
|
RemoteWorker tryChild(SpawnParams params={}, DWORD *errCode=nullptr);
|
2015-10-23 03:23:48 +00:00
|
|
|
~RemoteWorker() { cleanup(); }
|
|
|
|
bool valid() { return m_valid; }
|
|
|
|
void exit();
|
2015-10-22 23:16:47 +00:00
|
|
|
private:
|
2015-10-23 03:23:48 +00:00
|
|
|
void cleanup() { if (m_valid) { exit(); } }
|
2015-10-22 23:16:47 +00:00
|
|
|
public:
|
|
|
|
|
|
|
|
// basic worker info
|
|
|
|
HANDLE processHandle() { return m_process; }
|
|
|
|
DWORD pid() { return GetProcessId(m_process); }
|
|
|
|
|
|
|
|
// allow moving
|
|
|
|
RemoteWorker(RemoteWorker &&other) :
|
2015-10-23 03:23:48 +00:00
|
|
|
m_valid(std::move(other.m_valid)),
|
2015-10-22 23:16:47 +00:00
|
|
|
m_name(std::move(other.m_name)),
|
|
|
|
m_parcel(std::move(other.m_parcel)),
|
|
|
|
m_startEvent(std::move(other.m_startEvent)),
|
|
|
|
m_finishEvent(std::move(other.m_finishEvent)),
|
|
|
|
m_process(std::move(other.m_process))
|
|
|
|
{
|
|
|
|
other.m_valid = false;
|
2015-10-23 03:23:48 +00:00
|
|
|
other.m_process = nullptr;
|
2015-10-22 23:16:47 +00:00
|
|
|
}
|
|
|
|
RemoteWorker &operator=(RemoteWorker &&other) {
|
|
|
|
cleanup();
|
2015-10-23 03:23:48 +00:00
|
|
|
m_valid = std::move(other.m_valid);
|
2015-10-22 23:16:47 +00:00
|
|
|
m_name = std::move(other.m_name);
|
|
|
|
m_parcel = std::move(other.m_parcel);
|
|
|
|
m_startEvent = std::move(other.m_startEvent);
|
|
|
|
m_finishEvent = std::move(other.m_finishEvent);
|
|
|
|
m_process = std::move(other.m_process);
|
|
|
|
other.m_valid = false;
|
2015-10-23 03:23:48 +00:00
|
|
|
other.m_process = nullptr;
|
2015-10-22 23:16:47 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Commands
|
|
|
|
RemoteHandle getStdin() { rpc(Command::GetStdin); return RemoteHandle(cmd().handle, *this); }
|
|
|
|
RemoteHandle getStdout() { rpc(Command::GetStdout); return RemoteHandle(cmd().handle, *this); }
|
|
|
|
RemoteHandle getStderr() { rpc(Command::GetStderr); return RemoteHandle(cmd().handle, *this); }
|
|
|
|
bool detach() { rpc(Command::FreeConsole); return cmd().success; }
|
|
|
|
bool attach(RemoteWorker &worker) { cmd().dword = GetProcessId(worker.m_process); rpc(Command::AttachConsole); return cmd().success; }
|
|
|
|
bool alloc() { rpc(Command::AllocConsole); return cmd().success; }
|
|
|
|
void dumpStandardHandles() { rpc(Command::DumpStandardHandles); }
|
|
|
|
int system(const std::string &arg) { cmd().u.systemText = arg; rpc(Command::System); return cmd().dword; }
|
|
|
|
HWND consoleWindow() { rpc(Command::GetConsoleWindow); return cmd().hwnd; }
|
|
|
|
|
|
|
|
CONSOLE_SELECTION_INFO selectionInfo();
|
|
|
|
void dumpConsoleHandles(BOOL writeToEach=FALSE);
|
|
|
|
std::vector<RemoteHandle> scanForConsoleHandles();
|
|
|
|
void setTitle(const std::string &str) { auto b = setTitleInternal(widenString(str)); ASSERT(b && "setTitle failed"); }
|
|
|
|
bool setTitleInternal(const std::wstring &str);
|
|
|
|
std::string title();
|
|
|
|
DWORD titleInternal(std::array<wchar_t, 1024> &buf, DWORD bufSize);
|
|
|
|
std::vector<DWORD> consoleProcessList();
|
|
|
|
|
|
|
|
RemoteHandle openConin(BOOL bInheritHandle=FALSE) {
|
|
|
|
cmd().bInheritHandle = bInheritHandle;
|
|
|
|
rpc(Command::OpenConin);
|
|
|
|
return RemoteHandle(cmd().handle, *this);
|
|
|
|
}
|
|
|
|
|
|
|
|
RemoteHandle openConout(BOOL bInheritHandle=FALSE) {
|
|
|
|
cmd().bInheritHandle = bInheritHandle;
|
|
|
|
rpc(Command::OpenConout);
|
|
|
|
return RemoteHandle(cmd().handle, *this);
|
|
|
|
}
|
|
|
|
|
|
|
|
RemoteHandle newBuffer(BOOL bInheritHandle=FALSE, wchar_t firstChar=L'\0') {
|
|
|
|
cmd().bInheritHandle = bInheritHandle;
|
|
|
|
rpc(Command::NewBuffer);
|
|
|
|
auto h = RemoteHandle(cmd().handle, *this);
|
|
|
|
if (firstChar != L'\0') {
|
|
|
|
h.setFirstChar(firstChar);
|
|
|
|
}
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Command &cmd() { return m_parcel.value(); }
|
|
|
|
void rpc(Command::Kind kind);
|
|
|
|
void rpcAsync(Command::Kind kind);
|
|
|
|
void rpcImpl(Command::Kind kind);
|
|
|
|
|
|
|
|
private:
|
2015-10-23 03:23:48 +00:00
|
|
|
bool m_valid = false;
|
2015-10-22 23:16:47 +00:00
|
|
|
std::string m_name;
|
|
|
|
ShmemParcelTyped<Command> m_parcel;
|
|
|
|
Event m_startEvent;
|
|
|
|
Event m_finishEvent;
|
|
|
|
HANDLE m_process = NULL;
|
|
|
|
};
|