aboutsummaryrefslogtreecommitdiff
path: root/ProcessUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ProcessUtils.cpp')
-rw-r--r--ProcessUtils.cpp155
1 files changed, 155 insertions, 0 deletions
diff --git a/ProcessUtils.cpp b/ProcessUtils.cpp
new file mode 100644
index 0000000..8b8aa45
--- /dev/null
+++ b/ProcessUtils.cpp
@@ -0,0 +1,155 @@
+#include "ProcessUtils.h"
+#include <Windows.h>
+#include <tchar.h>
+#include <vector>
+
+// TODO
+// Support .lnk files
+
+namespace {
+ void Clear(SubProcessData* spd)
+ {
+ spd->hOutput = NULL;
+ spd->hInput = NULL;
+ spd->pi.hThread = NULL;
+ spd->pi.hProcess = NULL;
+ spd->hPC = NULL;
+ }
+
+ SubProcessData CreateSubProcess(LPCTSTR cmd, COORD size, HANDLE hInput, HANDLE hOutput, bool bUseConPty)
+ {
+ SubProcessData spd = {};
+
+ DWORD dwCreationFlags = EXTENDED_STARTUPINFO_PRESENT;
+ STARTUPINFOEX si = {};
+ std::vector<BYTE> attrList;
+ si.StartupInfo.cb = sizeof(si);
+
+ if (bUseConPty)
+ {
+ spd.hr = CreatePseudoConsole(
+ size,
+ hInput,
+ hOutput,
+ 0,
+ &spd.hPC);
+ if (spd.hr != S_OK)
+ {
+ CleanupSubProcess(&spd);
+ Clear(&spd);
+ return spd;
+ }
+
+ SIZE_T size = 0;
+ if (InitializeProcThreadAttributeList(NULL, 1, 0, &size))
+ {
+ spd.hr = HRESULT_FROM_WIN32(GetLastError());
+ CleanupSubProcess(&spd);
+ Clear(&spd);
+ return spd;
+ }
+
+ attrList.resize(size);
+ si.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(attrList.data());
+ if (!InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size))
+ {
+ spd.hr = HRESULT_FROM_WIN32(GetLastError());
+ CleanupSubProcess(&spd);
+ Clear(&spd);
+ return spd;
+ }
+ if (!UpdateProcThreadAttribute(
+ si.lpAttributeList,
+ 0,
+ PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
+ spd.hPC, sizeof(HPCON),
+ NULL,
+ NULL))
+ {
+ spd.hr = HRESULT_FROM_WIN32(GetLastError());
+ CleanupSubProcess(&spd);
+ Clear(&spd);
+ return spd;
+ }
+ }
+ else
+ {
+ si.StartupInfo.dwXSize = size.X;
+ si.StartupInfo.dwYSize = size.Y;
+ si.StartupInfo.dwFlags = STARTF_USESIZE | STARTF_USESTDHANDLES;
+ si.StartupInfo.hStdInput = hInput;
+ si.StartupInfo.hStdOutput = hOutput;
+ si.StartupInfo.hStdError = si.StartupInfo.hStdOutput;
+ dwCreationFlags |= CREATE_NO_WINDOW;
+ }
+
+ TCHAR localcmd[MAX_PATH];
+ wcscpy_s(localcmd, cmd);
+ if (!CreateProcess(nullptr, localcmd, nullptr, nullptr, FALSE, dwCreationFlags, nullptr, nullptr, &si.StartupInfo, &spd.pi))
+ {
+ spd.hr = HRESULT_FROM_WIN32(GetLastError());
+ CleanupSubProcess(&spd);
+ Clear(&spd);
+ return spd;
+ }
+
+ spd.hr = S_OK;
+ return spd;
+ }
+}
+
+SubProcessData CreateSubProcess(LPCTSTR cmd, COORD size, bool bUseConPty)
+{
+ SubProcessData spd = {};
+
+ HANDLE hReadPipeInput = NULL;
+ HANDLE hWritePipeInput = NULL;
+ if (spd.hr == S_OK && !CreatePipe(&hReadPipeInput, &hWritePipeInput, nullptr, 0))
+ spd.hr = HRESULT_FROM_WIN32(GetLastError());
+
+ HANDLE hWritePipeOutput = NULL;
+ HANDLE hReadPipeOutput = NULL;
+ if (spd.hr == S_OK && !CreatePipe(&hReadPipeOutput, &hWritePipeOutput, nullptr, 0))
+ spd.hr = HRESULT_FROM_WIN32(GetLastError());
+
+ if (spd.hr == S_OK)
+ spd = CreateSubProcess(cmd, size, hReadPipeInput, hWritePipeOutput, true);
+
+ if (spd.hr == S_OK)
+ {
+ spd.hInput = hWritePipeInput;
+ spd.hOutput = hReadPipeOutput;
+ }
+ else
+ {
+ CloseHandle(hWritePipeInput);
+ CloseHandle(hReadPipeOutput);
+ }
+
+ CloseHandle(hReadPipeInput);
+ CloseHandle(hWritePipeOutput);
+
+ return spd;
+}
+
+void CleanupSubProcess(const SubProcessData* spd)
+{
+ CloseHandle(spd->hOutput);
+ CloseHandle(spd->hInput);
+
+ TerminateProcess(spd->pi.hProcess, 0xFF);
+
+ CloseHandle(spd->pi.hThread);
+ CloseHandle(spd->pi.hProcess);
+ ClosePseudoConsole(spd->hPC);
+}
+
+UINT GetIcon(const SubProcessData* spd, HICON *phIconLarge, HICON *phIconSmall)
+{
+ TCHAR exe[MAX_PATH];
+ DWORD exelen = ARRAYSIZE(exe);
+ QueryFullProcessImageName(spd->pi.hProcess, 0, exe, &exelen);
+
+ WORD iIcon = 0;
+ return ExtractIconEx(exe, 0, phIconLarge, phIconSmall, 1);
+}