Implemented Windows registry read/write

This commit is contained in:
Hyper 2025-01-28 03:22:06 +00:00
parent 7b9b4245de
commit ef8d099309
12 changed files with 232 additions and 1 deletions

View file

@ -178,7 +178,8 @@ set(UNLEASHED_RECOMP_INSTALL_CXX_SOURCES
set(UNLEASHED_RECOMP_USER_CXX_SOURCES set(UNLEASHED_RECOMP_USER_CXX_SOURCES
"user/achievement_data.cpp" "user/achievement_data.cpp"
"user/achievement_manager.cpp" "user/achievement_manager.cpp"
"user/config.cpp" "user/config.cpp"
"user/registry.cpp"
) )
set(UNLEASHED_RECOMP_MOD_CXX_SOURCES set(UNLEASHED_RECOMP_MOD_CXX_SOURCES

View file

@ -8,6 +8,7 @@
#include <ui/game_window.h> #include <ui/game_window.h>
#include <user/config.h> #include <user/config.h>
#include <user/paths.h> #include <user/paths.h>
#include <user/registry.h>
void App::Restart(std::vector<std::string> restartArgs) void App::Restart(std::vector<std::string> restartArgs)
{ {
@ -18,6 +19,7 @@ void App::Restart(std::vector<std::string> restartArgs)
void App::Exit() void App::Exit()
{ {
Config::Save(); Config::Save();
Registry::Save();
#ifdef _WIN32 #ifdef _WIN32
timeEndPeriod(1); timeEndPeriod(1);

View file

@ -7,6 +7,8 @@
typedef returnType _##procName(__VA_ARGS__); \ typedef returnType _##procName(__VA_ARGS__); \
_##procName* procName = (_##procName*)PROC_ADDRESS(libraryName, #procName); _##procName* procName = (_##procName*)PROC_ADDRESS(libraryName, #procName);
#define STR(x) #x
template<typename T> template<typename T>
inline T RoundUp(const T& in_rValue, uint32_t in_round) inline T RoundUp(const T& in_rValue, uint32_t in_round)
{ {

View file

@ -12,9 +12,11 @@
#include <hid/hid.h> #include <hid/hid.h>
#include <user/config.h> #include <user/config.h>
#include <user/paths.h> #include <user/paths.h>
#include <user/registry.h>
#include <kernel/xdbf.h> #include <kernel/xdbf.h>
#include <install/installer.h> #include <install/installer.h>
#include <os/logger.h> #include <os/logger.h>
#include <os/process.h>
#include <ui/installer_wizard.h> #include <ui/installer_wizard.h>
#include <mod/mod_loader.h> #include <mod/mod_loader.h>
@ -165,6 +167,13 @@ int main(int argc, char *argv[])
} }
Config::Load(); Config::Load();
Registry::Load();
if (!Registry::RootDirectoryPath.empty())
{
if (!os::process::SetWorkingDirectory(std::filesystem::path(Registry::RootDirectoryPath)))
LOGFN_ERROR("Failed to set working directory: \"{}\"", Registry::RootDirectoryPath);
}
HostStartup(); HostStartup();

View file

@ -29,6 +29,12 @@ std::filesystem::path os::process::GetWorkingDirectory()
} }
} }
// TODO
bool os::process::SetWorkingDirectory(const std::filesystem::path& path)
{
return false;
}
bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work) bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work)
{ {
pid_t pid = fork(); pid_t pid = fork();

View file

@ -0,0 +1,15 @@
#include <os/registry.h>
// TODO: read from file?
template<typename T>
bool os::registry::ReadValue(const std::filesystem::path& path, const std::string& name, T& data)
{
return false;
}
// TODO: write to file?
template<typename T>
bool os::registry::WriteValue(const std::filesystem::path& path, const std::string& name, const T& data)
{
return false;
}

View file

@ -4,5 +4,6 @@ namespace os::process
{ {
std::filesystem::path GetExecutablePath(); std::filesystem::path GetExecutablePath();
std::filesystem::path GetWorkingDirectory(); std::filesystem::path GetWorkingDirectory();
bool SetWorkingDirectory(const std::filesystem::path& path);
bool StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work = {}); bool StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work = {});
} }

View file

@ -0,0 +1,16 @@
#pragma once
namespace os::registry
{
template<typename T>
bool ReadValue(const std::filesystem::path& path, const std::string& name, T& data);
template<typename T>
bool WriteValue(const std::filesystem::path& path, const std::string& name, const T& data);
}
#if _WIN32
#include <os/win32/registry_win32.inl>
#elif defined(__linux__)
#include <os/linux/registry_linux.inl>
#endif

View file

@ -20,6 +20,11 @@ std::filesystem::path os::process::GetWorkingDirectory()
return std::filesystem::path(workPath); return std::filesystem::path(workPath);
} }
bool os::process::SetWorkingDirectory(const std::filesystem::path& path)
{
return SetCurrentDirectoryW(path.c_str());
}
bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work) bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work)
{ {
if (path.empty()) if (path.empty())

View file

@ -0,0 +1,142 @@
#include <os/registry.h>
#include <unordered_map>
static const std::unordered_map<std::string, HKEY> g_rootKeys =
{
{ "HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT },
{ "HKEY_CURRENT_USER", HKEY_CURRENT_USER },
{ "HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE },
{ "HKEY_USERS", HKEY_USERS },
{ "HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG }
};
static HKEY ParseRootKey(const std::string& name)
{
auto it = g_rootKeys.find(name);
if (it == g_rootKeys.end())
return nullptr;
return it->second;
}
template<typename T>
bool os::registry::ReadValue(const std::filesystem::path& path, const std::string& name, T& data)
{
auto pathStr = path.string();
auto pathSeparator = pathStr.find('\\');
if (pathSeparator == std::string::npos)
return false;
auto rootKey = pathStr.substr(0, pathSeparator);
auto subKey = pathStr.substr(pathSeparator + 1);
HKEY hRootKey = ParseRootKey(rootKey);
if (!hRootKey)
return false;
HKEY hKey;
if (RegOpenKeyExA(hRootKey, subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
return false;
BYTE buffer[512];
DWORD bufferSize = sizeof(buffer);
DWORD dataType = 0;
auto result = RegQueryValueExA(hKey, name.c_str(), NULL, &dataType, buffer, &bufferSize);
RegCloseKey(hKey);
if (result != ERROR_SUCCESS)
return false;
if constexpr (std::is_same_v<T, std::string>)
{
if (dataType != REG_SZ)
return false;
data = std::string((char*)buffer, bufferSize - 1);
}
else if constexpr (std::is_same_v<T, uint32_t>)
{
if (dataType != REG_DWORD)
return false;
data = *(uint32_t*)buffer;
}
else if constexpr (std::is_same_v<T, uint64_t>)
{
if (dataType != REG_QWORD)
return false;
data = *(uint32_t*)buffer;
}
else
{
static_assert(false, "Unsupported data type.");
}
return true;
}
template<typename T>
bool os::registry::WriteValue(const std::filesystem::path& path, const std::string& name, const T& data)
{
auto pathStr = path.string();
auto pathSeparator = pathStr.find('\\');
if (pathSeparator == std::string::npos)
return false;
auto rootKey = pathStr.substr(0, pathSeparator);
auto subKey = pathStr.substr(pathSeparator + 1);
HKEY hRootKey = ParseRootKey(rootKey);
if (!hRootKey)
return false;
HKEY hKey;
if (RegCreateKeyExA(hRootKey, subKey.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
return false;
BYTE* pData = nullptr;
DWORD dataSize = 0;
DWORD dataType = 0;
if constexpr (std::is_same_v<T, std::string>)
{
pData = (BYTE*)data.c_str();
dataSize = data.size() + 1;
dataType = REG_SZ;
}
else if constexpr (std::is_same_v<T, uint32_t>)
{
pData = &data;
dataSize = sizeof(T);
dataType = REG_DWORD;
}
else if constexpr (std::is_same_v<T, uint64_t>)
{
pData = &data;
dataSize = sizeof(T);
dataType = REG_QWORD;
}
else
{
static_assert(false, "Unsupported data type.");
}
auto result = RegSetValueExA(hKey, name.c_str(), 0, dataType, (const BYTE*)pData, dataSize);
RegCloseKey(hKey);
if (result != ERROR_SUCCESS)
return false;
return true;
}

View file

@ -0,0 +1,21 @@
#include "registry.h"
#include <os/process.h>
#include <os/registry.h>
#include <user/config.h>
void Registry::Load()
{
std::filesystem::path path = "HKEY_CURRENT_USER\\Software\\UnleashedRecomp";
os::registry::ReadValue(path, STR(ExecutableFilePath), ExecutableFilePath);
os::registry::ReadValue(path, STR(RootDirectoryPath), RootDirectoryPath);
}
void Registry::Save()
{
std::filesystem::path path = "HKEY_CURRENT_USER\\Software\\UnleashedRecomp";
ExecutableFilePath = os::process::GetExecutablePath().string();
os::registry::WriteValue(path, STR(ExecutableFilePath), ExecutableFilePath);
}

View file

@ -0,0 +1,11 @@
#pragma once
class Registry
{
public:
inline static std::string ExecutableFilePath;
inline static std::string RootDirectoryPath;
static void Load();
static void Save();
};