mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 21:01:37 +00:00
Implemented Windows registry read/write
This commit is contained in:
parent
7b9b4245de
commit
ef8d099309
12 changed files with 232 additions and 1 deletions
|
|
@ -178,7 +178,8 @@ set(UNLEASHED_RECOMP_INSTALL_CXX_SOURCES
|
|||
set(UNLEASHED_RECOMP_USER_CXX_SOURCES
|
||||
"user/achievement_data.cpp"
|
||||
"user/achievement_manager.cpp"
|
||||
"user/config.cpp"
|
||||
"user/config.cpp"
|
||||
"user/registry.cpp"
|
||||
)
|
||||
|
||||
set(UNLEASHED_RECOMP_MOD_CXX_SOURCES
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <ui/game_window.h>
|
||||
#include <user/config.h>
|
||||
#include <user/paths.h>
|
||||
#include <user/registry.h>
|
||||
|
||||
void App::Restart(std::vector<std::string> restartArgs)
|
||||
{
|
||||
|
|
@ -18,6 +19,7 @@ void App::Restart(std::vector<std::string> restartArgs)
|
|||
void App::Exit()
|
||||
{
|
||||
Config::Save();
|
||||
Registry::Save();
|
||||
|
||||
#ifdef _WIN32
|
||||
timeEndPeriod(1);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
typedef returnType _##procName(__VA_ARGS__); \
|
||||
_##procName* procName = (_##procName*)PROC_ADDRESS(libraryName, #procName);
|
||||
|
||||
#define STR(x) #x
|
||||
|
||||
template<typename T>
|
||||
inline T RoundUp(const T& in_rValue, uint32_t in_round)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@
|
|||
#include <hid/hid.h>
|
||||
#include <user/config.h>
|
||||
#include <user/paths.h>
|
||||
#include <user/registry.h>
|
||||
#include <kernel/xdbf.h>
|
||||
#include <install/installer.h>
|
||||
#include <os/logger.h>
|
||||
#include <os/process.h>
|
||||
#include <ui/installer_wizard.h>
|
||||
#include <mod/mod_loader.h>
|
||||
|
||||
|
|
@ -165,6 +167,13 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
|
|
|
|||
15
UnleashedRecomp/os/linux/registry_linux.inl
Normal file
15
UnleashedRecomp/os/linux/registry_linux.inl
Normal 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;
|
||||
}
|
||||
|
|
@ -4,5 +4,6 @@ namespace os::process
|
|||
{
|
||||
std::filesystem::path GetExecutablePath();
|
||||
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 = {});
|
||||
}
|
||||
|
|
|
|||
16
UnleashedRecomp/os/registry.h
Normal file
16
UnleashedRecomp/os/registry.h
Normal 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
|
||||
|
|
@ -20,6 +20,11 @@ std::filesystem::path os::process::GetWorkingDirectory()
|
|||
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)
|
||||
{
|
||||
if (path.empty())
|
||||
|
|
|
|||
142
UnleashedRecomp/os/win32/registry_win32.inl
Normal file
142
UnleashedRecomp/os/win32/registry_win32.inl
Normal 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;
|
||||
}
|
||||
21
UnleashedRecomp/user/registry.cpp
Normal file
21
UnleashedRecomp/user/registry.cpp
Normal 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);
|
||||
}
|
||||
11
UnleashedRecomp/user/registry.h
Normal file
11
UnleashedRecomp/user/registry.h
Normal 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();
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue