mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-02-26 07:18:53 -06:00
Implemented Windows registry read/write (#225)
* Implemented Windows registry read/write * Simplify registry API and handle path writes * Linux SetWorkingDirectory * Implement reading path and unicode string from windows registry * Use string_view value names for registry * Use RegGetValueW * Paths adjustments * / * Update working directory update failure message * Updated linux SetWorkingDirectory * Update flatpak define * Remove RootDirectoryPath and save registry at startup * dont save registry on exit * Slight formatting update --------- Co-authored-by: Sajid <sajidur78@gmail.com>
This commit is contained in:
@@ -29,6 +29,11 @@ std::filesystem::path os::process::GetWorkingDirectory()
|
||||
}
|
||||
}
|
||||
|
||||
bool os::process::SetWorkingDirectory(const std::filesystem::path& path)
|
||||
{
|
||||
return chdir(path.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
|
||||
21
UnleashedRecomp/os/linux/registry_linux.inl
Normal file
21
UnleashedRecomp/os/linux/registry_linux.inl
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <os/registry.h>
|
||||
|
||||
// TODO: Implement
|
||||
inline bool os::registry::Init()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: read from file?
|
||||
template<typename T>
|
||||
bool os::registry::ReadValue(const std::string_view& name, T& data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: write to file?
|
||||
template<typename T>
|
||||
bool os::registry::WriteValue(const std::string_view& 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 = {});
|
||||
}
|
||||
|
||||
18
UnleashedRecomp/os/registry.h
Normal file
18
UnleashedRecomp/os/registry.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
namespace os::registry
|
||||
{
|
||||
bool Init();
|
||||
|
||||
template<typename T>
|
||||
bool ReadValue(const std::string_view& name, T& data);
|
||||
|
||||
template<typename T>
|
||||
bool WriteValue(const std::string_view& 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())
|
||||
|
||||
153
UnleashedRecomp/os/win32/registry_win32.inl
Normal file
153
UnleashedRecomp/os/win32/registry_win32.inl
Normal file
@@ -0,0 +1,153 @@
|
||||
#include <os/registry.h>
|
||||
#include <unordered_map>
|
||||
|
||||
inline const wchar_t* g_registryRoot = L"Software\\UnleashedRecomp";
|
||||
|
||||
inline bool os::registry::Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool os::registry::ReadValue(const std::string_view& name, T& data)
|
||||
{
|
||||
HKEY hKey;
|
||||
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, g_registryRoot, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
||||
return false;
|
||||
|
||||
wchar_t wideName[128];
|
||||
int wideNameSize = MultiByteToWideChar(CP_UTF8, 0, name.data(), name.size(), wideName, sizeof(wideName));
|
||||
if (wideNameSize == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wideName[wideNameSize] = 0;
|
||||
DWORD bufferSize = 0;
|
||||
DWORD dataType = 0;
|
||||
|
||||
auto result = RegGetValueW(hKey, nullptr, wideName, RRF_RT_ANY, &dataType, nullptr, &bufferSize);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = ERROR_INVALID_FUNCTION;
|
||||
if constexpr (std::is_same_v<T, std::string>)
|
||||
{
|
||||
if (dataType == REG_SZ)
|
||||
{
|
||||
std::vector<uint8_t> buffer{};
|
||||
buffer.reserve(bufferSize);
|
||||
result = RegGetValueW(hKey, nullptr, wideName, RRF_RT_REG_SZ, nullptr, buffer.data(), &bufferSize);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
int valueSize = WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)buffer.data(), (bufferSize / sizeof(wchar_t)) - 1, nullptr, 0, nullptr, nullptr);
|
||||
data.resize(valueSize);
|
||||
WideCharToMultiByte(CP_UTF8, 0, (wchar_t*)buffer.data(), (bufferSize / sizeof(wchar_t)) - 1, data.data(), valueSize, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::filesystem::path>)
|
||||
{
|
||||
if (dataType == REG_SZ)
|
||||
{
|
||||
std::vector<uint8_t> buffer{};
|
||||
buffer.reserve(bufferSize);
|
||||
result = RegGetValueW(hKey, nullptr, wideName, RRF_RT_REG_SZ, nullptr, buffer.data(), &bufferSize);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
data = reinterpret_cast<wchar_t*>(buffer.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, uint32_t>)
|
||||
{
|
||||
result = RegGetValueW(hKey, nullptr, wideName, RRF_RT_DWORD, nullptr, (BYTE*)&data, &bufferSize);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, uint64_t>)
|
||||
{
|
||||
result = RegGetValueW(hKey, nullptr, wideName, RRF_RT_QWORD, nullptr, (BYTE*)&data, &bufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(false, "Unsupported data type.");
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return result == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool os::registry::WriteValue(const std::string_view& name, const T& data)
|
||||
{
|
||||
HKEY hKey;
|
||||
|
||||
if (RegCreateKeyExW(HKEY_CURRENT_USER, g_registryRoot, 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
|
||||
return false;
|
||||
|
||||
BYTE* pData = nullptr;
|
||||
DWORD dataSize = 0;
|
||||
DWORD dataType = 0;
|
||||
bool wideString = false;
|
||||
|
||||
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 if constexpr (std::is_same_v<T, std::filesystem::path>)
|
||||
{
|
||||
pData = (BYTE*)data.c_str();
|
||||
dataSize = (wcslen((const wchar_t*)pData) + 1) * sizeof(wchar_t);
|
||||
dataType = REG_SZ;
|
||||
wideString = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(false, "Unsupported data type.");
|
||||
}
|
||||
|
||||
LSTATUS result = ERROR_INVALID_FUNCTION;
|
||||
if (wideString)
|
||||
{
|
||||
wchar_t wideName[128];
|
||||
int wideNameSize = MultiByteToWideChar(CP_UTF8, 0, name.data(), name.size(), wideName, sizeof(wideName));
|
||||
if (wideNameSize == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wideName[wideNameSize] = 0;
|
||||
result = RegSetValueExW(hKey, wideName, 0, dataType, pData, dataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = RegSetValueExA(hKey, name.data(), 0, dataType, pData, dataSize);
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user