[+] AuProcesses::StartupParameters::environmentVariables
[+] AuProcesses::StartupParameters::bInheritEnvironmentVariables [+] AuProcesses::StartupParameters::handleOutStream [+] AuProcesses::StartupParameters::handleErrorStream [+] AuProcesses::StartupParameters::handleInputStream [+] AuProcesses::StartupParameters::optAffinity
This commit is contained in:
parent
58302586a9
commit
3fe2d15a2f
@ -13,6 +13,7 @@ namespace Aurora::Processes
|
||||
eNull,
|
||||
eCurrentProcess,
|
||||
eAsyncPipe,
|
||||
eNewConsoleWindow
|
||||
eNewConsoleWindow,
|
||||
eIOHandle
|
||||
));
|
||||
}
|
@ -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;
|
||||
|
@ -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"
|
@ -9,5 +9,5 @@
|
||||
|
||||
namespace Aurora::Processes
|
||||
{
|
||||
AUKN_SHARED_API(Spawn, IProcess, const StartupParmaters &startup);
|
||||
AUKN_SHARED_API(Spawn, IProcess, StartupParameters &&startup);
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
@ -40,7 +40,7 @@ namespace Aurora::Processes
|
||||
return AuLoop::ELoopSource::eProcessDead;
|
||||
}
|
||||
|
||||
ProcessImpl::ProcessImpl(const StartupParmaters ¶ms) : startup_(params)
|
||||
ProcessImpl::ProcessImpl(StartupParameters &¶ms) : 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 ¶ms)
|
||||
AUKN_SYM IProcess *SpawnNew(StartupParameters &¶ms)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto hi = _new ProcessImpl(params);
|
||||
auto hi = _new ProcessImpl(AuMove(params));
|
||||
if (!hi)
|
||||
{
|
||||
return {};
|
||||
|
@ -13,7 +13,7 @@ namespace Aurora::Processes
|
||||
{
|
||||
struct ProcessImpl : IProcess
|
||||
{
|
||||
ProcessImpl(const StartupParmaters ¶ms);
|
||||
ProcessImpl(StartupParameters &¶ms);
|
||||
~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_;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user