From 6f92c8ef22a64eba57f02ac69b3608a8f0adab1b Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 25 Apr 2021 23:58:57 +0200 Subject: [PATCH] Added config parser --- DDrawCompat/Common/Path.cpp | 6 ++ DDrawCompat/Common/Path.h | 1 + DDrawCompat/Config/Parser.cpp | 101 ++++++++++++++++++++++++ DDrawCompat/Config/Parser.h | 18 +++++ DDrawCompat/DDrawCompat.vcxproj | 2 + DDrawCompat/DDrawCompat.vcxproj.filters | 9 +++ DDrawCompat/Dll/Dll.cpp | 12 +++ DDrawCompat/Dll/Dll.h | 3 + DDrawCompat/Dll/DllMain.cpp | 16 ++-- 9 files changed, 158 insertions(+), 10 deletions(-) create mode 100644 DDrawCompat/Config/Parser.cpp create mode 100644 DDrawCompat/Config/Parser.h diff --git a/DDrawCompat/Common/Path.cpp b/DDrawCompat/Common/Path.cpp index e24c284..3ed81bd 100644 --- a/DDrawCompat/Common/Path.cpp +++ b/DDrawCompat/Common/Path.cpp @@ -1,7 +1,13 @@ #include +#include namespace Compat { + std::filesystem::path getEnvPath(const char* envVar) + { + return Dll::getEnvVar(envVar); + } + std::filesystem::path getModulePath(HMODULE module) { wchar_t path[MAX_PATH]; diff --git a/DDrawCompat/Common/Path.h b/DDrawCompat/Common/Path.h index fcad69b..f0da1a4 100644 --- a/DDrawCompat/Common/Path.h +++ b/DDrawCompat/Common/Path.h @@ -6,6 +6,7 @@ namespace Compat { + std::filesystem::path getEnvPath(const char* envVar); std::filesystem::path getModulePath(HMODULE module); std::filesystem::path getSystemPath(); bool isEqual(const std::filesystem::path& p1, const std::filesystem::path& p2); diff --git a/DDrawCompat/Config/Parser.cpp b/DDrawCompat/Config/Parser.cpp new file mode 100644 index 0000000..b1136c6 --- /dev/null +++ b/DDrawCompat/Config/Parser.cpp @@ -0,0 +1,101 @@ +#include + +#include +#include +#include + +namespace +{ + void setConfig(const std::string& name, const std::string& value); + std::string trim(const std::string& str); + + void loadConfigFile(const std::string& type, const std::filesystem::path& path) + { + Compat::Log() << "Loading " << type << " config file: " << path.u8string(); + std::ifstream f(path); + if (!f.is_open()) + { + Compat::Log() << " File not found, skipping"; + return; + } + + unsigned lineNumber = 0; + std::string line; + while (std::getline(f, line)) + { + try { + ++lineNumber; + auto pos = line.find_first_of(";#"); + if (pos != std::string::npos) + { + line.resize(pos); + } + + if (line.find_first_not_of(" \t") == std::string::npos) + { + continue; + } + + pos = line.find('='); + if (pos == std::string::npos) + { + throw Config::ParsingError("missing '=' separator"); + } + + setConfig(trim(line.substr(0, pos)), trim(line.substr(pos + 1))); + } + catch (const Config::ParsingError& error) + { + Compat::Log() << " Line #" << lineNumber << ": " << error.what(); + } + } + } + + void setConfig(const std::string& name, const std::string& /*value*/) + { + if (name.empty()) + { + throw Config::ParsingError("missing setting name before '='"); + } + + throw Config::ParsingError("unknown setting: '" + name + "'"); + } + + std::string trim(const std::string& str) + { + auto result(str); + auto pos = str.find_last_not_of(" \t"); + if (pos != std::string::npos) + { + result.resize(pos + 1); + } + + pos = result.find_first_not_of(" \t"); + if (pos != std::string::npos) + { + result = result.substr(pos); + } + return result; + } +} + +namespace Config +{ + namespace Parser + { + void loadAllConfigFiles(const std::filesystem::path& processPath) + { + loadConfigFile("global", Compat::getEnvPath("PROGRAMDATA") / "DDrawCompat" / "DDrawCompat.ini"); + loadConfigFile("user", Compat::getEnvPath("LOCALAPPDATA") / "DDrawCompat" / "DDrawCompat.ini"); + loadConfigFile("directory", Compat::replaceFilename(processPath, "DDrawCompat.ini")); + + auto processConfigPath(processPath); + if (Compat::isEqual(processConfigPath.extension(), ".exe")) + { + processConfigPath.replace_extension(); + } + processConfigPath.replace_filename(L"DDrawCompat-" + processConfigPath.filename().native() + L".ini"); + loadConfigFile("process", processConfigPath); + } + } +} diff --git a/DDrawCompat/Config/Parser.h b/DDrawCompat/Config/Parser.h new file mode 100644 index 0000000..862cdd0 --- /dev/null +++ b/DDrawCompat/Config/Parser.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +namespace Config +{ + class ParsingError : public std::runtime_error + { + public: + ParsingError(const std::string& error) : runtime_error(error) {} + }; + + namespace Parser + { + void loadAllConfigFiles(const std::filesystem::path& processPath); + } +} diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 4dad45a..1461004 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -178,6 +178,7 @@ + @@ -271,6 +272,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 7c570d1..a047521 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -79,6 +79,9 @@ {c4d03748-2333-40af-90c7-ae875b07434f} + + {9d313de7-b8ca-49d0-84d2-217f2818d9d3} + @@ -390,6 +393,9 @@ Header Files\Common + + Header Files\Config + @@ -611,6 +617,9 @@ Source Files\Common + + Source Files\Config + diff --git a/DDrawCompat/Dll/Dll.cpp b/DDrawCompat/Dll/Dll.cpp index 81976a5..866ddaf 100644 --- a/DDrawCompat/Dll/Dll.cpp +++ b/DDrawCompat/Dll/Dll.cpp @@ -20,6 +20,18 @@ namespace Dll return thread; } + std::string getEnvVar(const char* var) + { + const DWORD size = GetEnvironmentVariable(var, nullptr, 0); + std::string value(size, 0); + if (!value.empty()) + { + GetEnvironmentVariable(var, &value.front(), size); + value.pop_back(); + } + return value; + } + void pinModule(HMODULE module) { HMODULE dummy = nullptr; diff --git a/DDrawCompat/Dll/Dll.h b/DDrawCompat/Dll/Dll.h index b2fa3b1..ba5ada6 100644 --- a/DDrawCompat/Dll/Dll.h +++ b/DDrawCompat/Dll/Dll.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #define VISIT_PUBLIC_DDRAW_PROCS(visit) \ @@ -68,6 +70,7 @@ namespace Dll }; HANDLE createThread(unsigned(__stdcall* threadProc)(void*), unsigned int* threadId, int priority, unsigned initFlags = 0); + std::string getEnvVar(const char* var); void pinModule(HMODULE module); void pinModule(LPCSTR moduleName); void pinModule(LPCWSTR moduleName); diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp index 5be65a7..ab61904 100644 --- a/DDrawCompat/Dll/DllMain.cpp +++ b/DDrawCompat/Dll/DllMain.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -111,14 +112,7 @@ namespace void printEnvironmentVariable(const char* var) { - const DWORD size = GetEnvironmentVariable(var, nullptr, 0); - std::string value(size, 0); - if (!value.empty()) - { - GetEnvironmentVariable(var, &value.front(), size); - value.pop_back(); - } - Compat::Log() << "Environment variable " << var << " = \"" << value << '"'; + Compat::Log() << "Environment variable " << var << " = \"" << Dll::getEnvVar(var) << '"'; } void setDpiAwareness() @@ -175,11 +169,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) auto processPath(Compat::getModulePath(nullptr)); Compat::Log::initLogging(processPath); - Compat::Log() << "Process path: " << processPath.u8string(); - printEnvironmentVariable("__COMPAT_LAYER"); + auto currentDllPath(Compat::getModulePath(hinstDLL)); Compat::Log() << "Loading DDrawCompat " << (lpvReserved ? "statically" : "dynamically") << " from " << currentDllPath.u8string(); + printEnvironmentVariable("__COMPAT_LAYER"); + + Config::Parser::loadAllConfigFiles(processPath); auto systemPath(Compat::getSystemPath()); if (Compat::isEqual(currentDllPath.parent_path(), systemPath))