diff options
Diffstat (limited to 'ProcessUtils.cpp')
-rw-r--r-- | ProcessUtils.cpp | 155 |
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); +} |