[+] AuProcesses::StartupParameters::environmentVariables

[+] AuProcesses::StartupParameters::bInheritEnvironmentVariables
[+] AuProcesses::StartupParameters::handleOutStream
[+] AuProcesses::StartupParameters::handleErrorStream
[+] AuProcesses::StartupParameters::handleInputStream
[+] AuProcesses::StartupParameters::optAffinity
This commit is contained in:
Reece Wilson 2023-08-20 22:26:30 +01:00
parent 58302586a9
commit 3fe2d15a2f
7 changed files with 160 additions and 17 deletions

View File

@ -13,6 +13,7 @@ namespace Aurora::Processes
eNull,
eCurrentProcess,
eAsyncPipe,
eNewConsoleWindow
eNewConsoleWindow,
eIOHandle
));
}

View File

@ -45,7 +45,7 @@ namespace Aurora::Processes
/**
* @brief Creates the process, for the first and only time, given the input
* StartupParmaters provided to the relevant Spawn function
* StartupParameters provided to the relevant Spawn function
* @return
*/
virtual bool Start() = 0;

View File

@ -11,7 +11,7 @@
#include "EStandardHandle.hpp"
#include "EStreamForward.hpp"
#include "IProcess.hpp"
#include "StartupParmaters.hpp"
#include "StartupParameters.hpp"
#include "Spawn.hpp"
#include "Open.hpp"

View File

@ -9,5 +9,5 @@
namespace Aurora::Processes
{
AUKN_SHARED_API(Spawn, IProcess, const StartupParmaters &startup);
AUKN_SHARED_API(Spawn, IProcess, StartupParameters &&startup);
}

View File

@ -1,7 +1,7 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: StartupParmaters.hpp
File: StartupParameters.hpp
Date: 2022-1-29
Author: Reece
***/
@ -9,10 +9,11 @@
namespace Aurora::Processes
{
struct StartupParmaters
struct StartupParameters
{
AU_COPY_MOVE_DEF(StartupParmaters);
AU_DEF(StartupParameters);
AU_MOVE(StartupParameters);
/**
* @brief Relative or absolute path to the executable binary
*/
@ -54,5 +55,17 @@ namespace Aurora::Processes
bool bInDebugMode {};
AuOptional<AuString> workingDirectory;
AuList<AuPair<AuString, AuString>> environmentVariables;
bool bInheritEnvironmentVariables { true };
IO::IOHandle handleOutStream;
IO::IOHandle handleErrorStream;
IO::IOHandle handleInputStream;
AuOptionalEx<HWInfo::CpuBitId> optAffinity;
};
}

View File

@ -40,7 +40,7 @@ namespace Aurora::Processes
return AuLoop::ELoopSource::eProcessDead;
}
ProcessImpl::ProcessImpl(const StartupParmaters &params) : startup_(params)
ProcessImpl::ProcessImpl(StartupParameters &&params) : startup_(AuMove(params))
{
AuIOFS::NormalizePath(this->startup_.process, this->startup_.process);
if (this->startup_.workingDirectory)
@ -269,6 +269,28 @@ namespace Aurora::Processes
return false;
}
}
else if (this->startup_.fwdOut == EStreamForward::eIOHandle)
{
auto optHandle = this->startup_.handleOutStream->GetOSHandleSafe();
if (!optHandle)
{
return {};
}
HANDLE hTargetProcess = ::GetCurrentProcess();
HANDLE hHandle { (HANDLE) optHandle.value() };
if (!::DuplicateHandle(hTargetProcess,
hHandle,
hTargetProcess,
&this->pipeStdOutWrite_,
GENERIC_READ | GENERIC_WRITE,
TRUE,
0))
{
return false;
}
}
else if (this->startup_.fwdOut == EStreamForward::eCurrentProcess)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
@ -299,6 +321,28 @@ namespace Aurora::Processes
return false;
}
}
else if (this->startup_.fwdErr == EStreamForward::eIOHandle)
{
auto optHandle = this->startup_.handleErrorStream->GetOSHandleSafe();
if (!optHandle)
{
return {};
}
HANDLE hTargetProcess = ::GetCurrentProcess();
HANDLE hHandle { (HANDLE) optHandle.value() };
if (!::DuplicateHandle(hTargetProcess,
hHandle,
hTargetProcess,
&this->pipeStdErrWrite_,
GENERIC_READ | GENERIC_WRITE,
TRUE,
0))
{
return false;
}
}
else if (this->startup_.fwdErr == EStreamForward::eCurrentProcess)
{
HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
@ -329,6 +373,28 @@ namespace Aurora::Processes
return false;
}
}
else if (this->startup_.fwdIn == EStreamForward::eIOHandle)
{
auto optHandle = this->startup_.handleInputStream->GetOSHandleSafe();
if (!optHandle)
{
return {};
}
HANDLE hTargetProcess = ::GetCurrentProcess();
HANDLE hHandle { (HANDLE) optHandle.value() };
if (!::DuplicateHandle(hTargetProcess,
hHandle,
hTargetProcess,
&this->pipeStdInRead_,
GENERIC_READ,
TRUE,
0))
{
return false;
}
}
else if (this->startup_.fwdIn == EStreamForward::eCurrentProcess)
{
HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
@ -474,7 +540,8 @@ namespace Aurora::Processes
}
}
if (this->startup_.bInDebugMode)
if (this->startup_.bInDebugMode ||
this->startup_.optAffinity)
{
uCreateFlags |= CREATE_SUSPENDED;
}
@ -485,11 +552,46 @@ namespace Aurora::Processes
uCreateFlags |= CREATE_NO_WINDOW;
}
AuList<AuPair<AuString, AuString>> envVars;
if (this->startup_.bInheritEnvironmentVariables)
{
if (this->startup_.environmentVariables.size())
{
envVars = AuProcess::EnvironmentGetAll();
for (const auto pair : this->startup_.environmentVariables)
{
envVars.push_back(pair);
}
}
}
else
{
envVars = this->startup_.environmentVariables;
}
std::wstring envVarBlock;
if (envVars.size() || !this->startup_.bInheritEnvironmentVariables)
{
for (const auto &[key, value] : envVars)
{
envVarBlock += AuLocale::ConvertFromUTF8(key);
envVarBlock += L'=';
envVarBlock += AuLocale::ConvertFromUTF8(value);
envVarBlock += L'\x00';
}
envVarBlock += L'\x00';
uCreateFlags |= CREATE_UNICODE_ENVIRONMENT;
}
auto result = CreateProcessW(Locale::ConvertFromUTF8(this->startup_.process).c_str(),
Locale::ConvertFromUTF8(this->windowsCli_).data(),
NULL, NULL, true,
uCreateFlags,
NULL, wcwd.size() ? wcwd.data() : nullptr, &startupInfo, &processInfo);
envVarBlock.size() ? envVarBlock.data() : nullptr,
wcwd.size() ? wcwd.data() : nullptr, &startupInfo, &processInfo);
if (!result)
{
@ -503,6 +605,33 @@ namespace Aurora::Processes
RelOtherHandles();
if (this->startup_.optAffinity)
{
{
// This is good enough for now
// Minimum supported client: Windows XP [desktop apps | UWP apps]
auto primary = this->startup_.optAffinity.Value();
auto secondary = this->startup_.optAffinity.Value();
secondary.lower = 0;
if ((!bool(secondary)) &&
(bool(primary)))
{
::SetProcessAffinityMask(this->process_, primary.lower);
::SetThreadAffinityMask(this->hthread_, primary.lower);
}
else
{
auto cpuSets = primary.ToCpuSets();
// TODO:
}
}
if (!this->startup_.bInDebugMode)
{
::ResumeThread(this->hthread_);
}
}
if (this->type_ == ESpawnType::eSpawnChildProcessWorker)
{
#if defined(AURORA_PLATFORM_WIN32)
@ -569,11 +698,11 @@ namespace Aurora::Processes
}
}
AUKN_SYM IProcess *SpawnNew(const StartupParmaters &params)
AUKN_SYM IProcess *SpawnNew(StartupParameters &&params)
{
try
{
auto hi = _new ProcessImpl(params);
auto hi = _new ProcessImpl(AuMove(params));
if (!hi)
{
return {};

View File

@ -13,7 +13,7 @@ namespace Aurora::Processes
{
struct ProcessImpl : IProcess
{
ProcessImpl(const StartupParmaters &params);
ProcessImpl(StartupParameters &&params);
~ProcessImpl();
bool TermWinEnumProcesses();
@ -43,6 +43,8 @@ namespace Aurora::Processes
void RelOtherHandles();
private:
HANDLE process_ {INVALID_HANDLE_VALUE};
HANDLE hthread_ {INVALID_HANDLE_VALUE};
HANDLE pipeStdOutRead_ {INVALID_HANDLE_VALUE};
HANDLE pipeStdOutWrite_ {INVALID_HANDLE_VALUE};
@ -65,7 +67,7 @@ namespace Aurora::Processes
AuSPtr<IO::IIOHandle> fsErrorHandle_;
AuSPtr<IO::FS::NtAsyncFileStream> fsErrorStream_;
StartupParmaters startup_;
StartupParameters startup_;
ESpawnType type_;
AuList<const char *> cargs_;
@ -73,8 +75,6 @@ namespace Aurora::Processes
AuThreads::ThreadUnique_t thread_;
HANDLE poke_ {INVALID_HANDLE_VALUE};
HANDLE process_ {INVALID_HANDLE_VALUE};
HANDLE hthread_ {INVALID_HANDLE_VALUE};
AuSInt exitCode_;
};
}