Merge pull request #4030 from bylaws/eccfg

Windows: Load per-application configs
This commit is contained in:
Ryan Houdek 2024-09-03 16:11:42 -07:00 committed by GitHub
commit 49b40b71a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 100 additions and 78 deletions

View File

@ -337,8 +337,57 @@ fextl::string RecoverGuestProgramFilename(fextl::string Program, bool ExecFDInte
return Program;
}
ApplicationNames LoadConfig(fextl::unique_ptr<FEX::ArgLoader::ArgLoader> ArgsLoader, bool LoadProgramConfig, char** const envp,
bool ExecFDInterp, int ProgramFDFromEnv, const PortableInformation& PortableInfo) {
ApplicationNames GetApplicationNames(fextl::vector<fextl::string> Args, bool ExecFDInterp, int ProgramFDFromEnv) {
if (Args.empty()) {
// Early exit if we weren't passed an argument
return {};
}
fextl::string Program {};
fextl::string ProgramName {};
Args[0] = RecoverGuestProgramFilename(std::move(Args[0]), ExecFDInterp, ProgramFDFromEnv);
Program = Args[0];
bool Wine = false;
for (size_t CurrentProgramNameIndex = 0; CurrentProgramNameIndex < Args.size(); ++CurrentProgramNameIndex) {
auto CurrentProgramName = FHU::Filesystem::GetFilename(Args[CurrentProgramNameIndex]);
if (CurrentProgramName == "wine-preloader" || CurrentProgramName == "wine64-preloader") {
// Wine preloader is required to be in the format of `wine-preloader <wine executable>`
// The preloader doesn't execve the executable, instead maps it directly itself
// Skip the next argument since we know it is wine (potentially with custom wine executable name)
++CurrentProgramNameIndex;
Wine = true;
} else if (CurrentProgramName == "wine" || CurrentProgramName == "wine64") {
// Next argument, this isn't the program we want
//
// If we are running wine or wine64 then we should check the next argument for the application name instead.
// wine will change the active program name with `setprogname` or `prctl(PR_SET_NAME`.
// Since FEX needs this data far earlier than libraries we need a different check.
Wine = true;
} else {
if (Wine == true) {
// If this was path separated with '\' then we need to check that.
auto WinSeparator = CurrentProgramName.find_last_of('\\');
if (WinSeparator != CurrentProgramName.npos) {
// Used windows separators
CurrentProgramName = CurrentProgramName.substr(WinSeparator + 1);
}
}
ProgramName = CurrentProgramName;
// Past any wine program names
break;
}
}
return ApplicationNames {std::move(Program), std::move(ProgramName)};
}
void LoadConfig(fextl::unique_ptr<FEX::ArgLoader::ArgLoader> ArgsLoader, fextl::string ProgramName, char** const envp,
const PortableInformation& PortableInfo) {
const bool IsPortable = PortableInfo.IsPortable;
FEX::Config::InitializeConfigs(PortableInfo);
FEXCore::Config::Initialize();
@ -347,53 +396,7 @@ ApplicationNames LoadConfig(fextl::unique_ptr<FEX::ArgLoader::ArgLoader> ArgsLoa
}
FEXCore::Config::AddLayer(CreateMainLayer());
auto Args = ArgsLoader->Get();
fextl::string Program {};
fextl::string ProgramName {};
if (LoadProgramConfig) {
if (Args.empty()) {
// Early exit if we weren't passed an argument
return {};
}
Args[0] = RecoverGuestProgramFilename(std::move(Args[0]), ExecFDInterp, ProgramFDFromEnv);
Program = Args[0];
bool Wine = false;
for (size_t CurrentProgramNameIndex = 0; CurrentProgramNameIndex < Args.size(); ++CurrentProgramNameIndex) {
auto CurrentProgramName = FHU::Filesystem::GetFilename(Args[CurrentProgramNameIndex]);
if (CurrentProgramName == "wine-preloader" || CurrentProgramName == "wine64-preloader") {
// Wine preloader is required to be in the format of `wine-preloader <wine executable>`
// The preloader doesn't execve the executable, instead maps it directly itself
// Skip the next argument since we know it is wine (potentially with custom wine executable name)
++CurrentProgramNameIndex;
Wine = true;
} else if (CurrentProgramName == "wine" || CurrentProgramName == "wine64") {
// Next argument, this isn't the program we want
//
// If we are running wine or wine64 then we should check the next argument for the application name instead.
// wine will change the active program name with `setprogname` or `prctl(PR_SET_NAME`.
// Since FEX needs this data far earlier than libraries we need a different check.
Wine = true;
} else {
if (Wine == true) {
// If this was path separated with '\' then we need to check that.
auto WinSeparator = CurrentProgramName.find_last_of('\\');
if (WinSeparator != CurrentProgramName.npos) {
// Used windows separators
CurrentProgramName = CurrentProgramName.substr(WinSeparator + 1);
}
}
ProgramName = CurrentProgramName;
// Past any wine program names
break;
}
}
if (!ProgramName.empty()) {
if (!IsPortable) {
FEXCore::Config::AddLayer(CreateAppLayer(ProgramName, FEXCore::Config::LayerType::LAYER_GLOBAL_APP));
}
@ -411,7 +414,7 @@ ApplicationNames LoadConfig(fextl::unique_ptr<FEX::ArgLoader::ArgLoader> ArgsLoa
}
}
if (ArgsLoader->GetLoadType() == FEX::ArgLoader::ArgLoader::LoadType::WITH_FEXLOADER_PARSER) {
if (ArgsLoader && ArgsLoader->GetLoadType() == FEX::ArgLoader::ArgLoader::LoadType::WITH_FEXLOADER_PARSER) {
FEXCore::Config::AddLayer(std::move(ArgsLoader));
}
@ -422,13 +425,6 @@ ApplicationNames LoadConfig(fextl::unique_ptr<FEX::ArgLoader::ArgLoader> ArgsLoa
FEXCore::Config::AddLayer(CreateEnvironmentLayer(envp));
FEXCore::Config::Load();
if (LoadProgramConfig) {
return ApplicationNames {std::move(Program), std::move(ProgramName)};
} else {
return {};
}
}
#ifndef _WIN32

View File

@ -35,18 +35,22 @@ struct PortableInformation {
};
/**
* @brief Loads the FEX and application configurations for the application that is getting ready to run.
*
* @param ArgLoader Argument loader for argument based config options
* @param LoadProgramConfig Do we want to load application specific configurations?
* @param envp The `envp` passed to main(...)
* @param ExecFDInterp If FEX was executed with binfmt_misc FD argument
* @param ProgramFDFromEnv The execveat FD argument passed through FEX
*
* @return The application name and path structure
*/
ApplicationNames LoadConfig(fextl::unique_ptr<FEX::ArgLoader::ArgLoader> ArgLoader, bool LoadProgramConfig, char** const envp,
bool ExecFDInterp, int ProgramFDFromEnv, const PortableInformation& PortableInfo);
ApplicationNames GetApplicationNames(fextl::vector<fextl::string> Args, bool ExecFDInterp, int ProgramFDFromEnv);
/**
* @brief Loads the FEX and application configurations for the application that is getting ready to run.
*
* @param ArgLoader Optional argument loader for argument based config options
* @param ProgramName Optional program name, if non-empty application specific configurations will be loaded
* @param envp Optional `envp` passed to main(...)
*/
void LoadConfig(fextl::unique_ptr<FEX::ArgLoader::ArgLoader> ArgLoader = {}, fextl::string ProgramName = {}, char** const envp = nullptr,
const PortableInformation& PortableInfo = {});
const char* GetHomeDirectory();

View File

@ -324,13 +324,14 @@ int main(int argc, char** argv, char** const envp) {
argc, argv);
auto Args = ArgsLoader->Get();
auto ParsedArgs = ArgsLoader->GetParsedArgs();
auto Program = FEX::Config::LoadConfig(std::move(ArgsLoader), true, envp, ExecutedWithFD, FEXFD, PortableInfo);
auto Program = FEX::Config::GetApplicationNames(Args, ExecutedWithFD, FEXFD);
if (Program.ProgramPath.empty() && FEXFD == -1) {
// Early exit if we weren't passed an argument
return 0;
}
FEX::Config::LoadConfig(std::move(ArgsLoader), Program.ProgramName, envp, PortableInfo);
// Reload the meta layer
FEXCore::Config::ReloadMetaLayer();
FEXCore::Config::Set(FEXCore::Config::CONFIG_IS_INTERPRETER, IsInterpreter ? "1" : "0");

View File

@ -1091,7 +1091,7 @@ bool ExtractEroFS(const fextl::string& Path, const fextl::string& RootFS, const
int main(int argc, char** argv, char** const envp) {
auto ArgsLoader = fextl::make_unique<FEX::ArgLoader::ArgLoader>(FEX::ArgLoader::ArgLoader::LoadType::WITHOUT_FEXLOADER_PARSER, argc, argv);
FEX::Config::LoadConfig(std::move(ArgsLoader), false, envp, false, false, FEX::Config::PortableInformation {});
FEX::Config::LoadConfig(std::move(ArgsLoader), {}, envp);
// Reload the meta layer
FEXCore::Config::ReloadMetaLayer();

View File

@ -117,7 +117,7 @@ int main(int argc, char** argv, char** const envp) {
}
auto ArgsLoader = fextl::make_unique<FEX::ArgLoader::ArgLoader>(FEX::ArgLoader::ArgLoader::LoadType::WITHOUT_FEXLOADER_PARSER, argc, argv);
FEX::Config::LoadConfig(std::move(ArgsLoader), false, envp, false, false, FEX::Config::PortableInformation {});
FEX::Config::LoadConfig(std::move(ArgsLoader), {}, envp);
// Reload the meta layer
FEXCore::Config::ReloadMetaLayer();

View File

@ -24,12 +24,14 @@ $end_info$
#include <FEXCore/Utils/MathUtils.h>
#include <FEXCore/Utils/TypeDefines.h>
#include "Common/ArgumentLoader.h"
#include "Common/Config.h"
#include "Common/Exception.h"
#include "Common/InvalidationTracker.h"
#include "Common/TSOHandlerConfig.h"
#include "Common/CPUFeatures.h"
#include "Common/Logging.h"
#include "Common/Module.h"
#include "Common/CRT/CRT.h"
#include "DummyHandlers.h"
#include "BTInterface.h"
@ -456,11 +458,7 @@ extern "C" void SyncThreadContext(CONTEXT* Context) {
NTSTATUS ProcessInit() {
FEX::Windows::InitCRTProcess();
FEX::Config::InitializeConfigs(FEX::Config::PortableInformation {});
FEXCore::Config::Initialize();
FEXCore::Config::AddLayer(FEX::Config::CreateGlobalMainLayer());
FEXCore::Config::AddLayer(FEX::Config::CreateMainLayer());
FEXCore::Config::Load();
FEX::Config::LoadConfig(nullptr, FEX::Windows::GetExecutableFilePath());
FEXCore::Config::ReloadMetaLayer();
FEX::Windows::Logging::Init();

View File

@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
#pragma once
#include <array>
#include <FEXCore/fextl/string.h>
#include <winternl.h>
namespace FEX::Windows {
fextl::string GetExecutableFilePath() {
std::array<WCHAR, PATH_MAX> Buf;
UNICODE_STRING PathW {.Length = 0, .MaximumLength = Buf.size() * sizeof(WCHAR), .Buffer = Buf.data()};
if (LdrGetDllFullName(nullptr, &PathW)) {
return {};
}
STRING PathA;
RtlUnicodeStringToAnsiString(&PathA, &PathW, TRUE);
fextl::string Path(PathA.Buffer);
RtlFreeAnsiString(&PathA);
return Path.substr(Path.find_last_of('\\') + 1);
}
} // namespace FEX::Windows

View File

@ -25,12 +25,14 @@ $end_info$
#include <FEXCore/Utils/ArchHelpers/Arm64.h>
#include <FEXCore/Utils/TypeDefines.h>
#include "Common/ArgumentLoader.h"
#include "Common/Config.h"
#include "Common/Exception.h"
#include "Common/TSOHandlerConfig.h"
#include "Common/InvalidationTracker.h"
#include "Common/CPUFeatures.h"
#include "Common/Logging.h"
#include "Common/Module.h"
#include "Common/CRT/CRT.h"
#include "DummyHandlers.h"
#include "BTInterface.h"
@ -424,11 +426,7 @@ public:
void BTCpuProcessInit() {
FEX::Windows::InitCRTProcess();
FEX::Config::InitializeConfigs(FEX::Config::PortableInformation {});
FEXCore::Config::Initialize();
FEXCore::Config::AddLayer(FEX::Config::CreateGlobalMainLayer());
FEXCore::Config::AddLayer(FEX::Config::CreateMainLayer());
FEXCore::Config::Load();
FEX::Config::LoadConfig(nullptr, FEX::Windows::GetExecutableFilePath());
FEXCore::Config::ReloadMetaLayer();
FEX::Windows::Logging::Init();

View File

@ -433,6 +433,7 @@ typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...);
NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE);
NTSTATUS WINAPI LdrGetDllFullName(HMODULE, UNICODE_STRING*);
NTSTATUS WINAPI LdrGetDllHandle(LPCWSTR, ULONG, const UNICODE_STRING*, HMODULE*);
NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, const ANSI_STRING*, ULONG, void**);
NTSTATUS WINAPI NtAllocateVirtualMemoryEx(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG);