diff --git a/src/Application/GamePathResolver.cpp b/src/Application/GamePathResolver.cpp index e8f260e515f6..17a02ae375dc 100644 --- a/src/Application/GamePathResolver.cpp +++ b/src/Application/GamePathResolver.cpp @@ -5,19 +5,19 @@ #include "Library/Logger/Logger.h" #include "Library/Platform/Interface/Platform.h" -static std::string _resolvePath(Platform *platform, const char *envVarOverride, const std::vector ®istryKeys); +static std::string _resolvePath(Platform *platform, const char *envVarOverride, const std::vector ®istryKeys); std::string resolveMm6Path(Platform *platform) { return _resolvePath( platform, mm6PathOverrideKey, { - L"HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/Games/1207661253/PATH", - L"HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/GOGMM6/PATH", - L"HKEY_LOCAL_MACHINE/SOFTWARE/New World Computing/Might and Magic\x00AE VI/1.0/AppPath", - L"HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/Games/1207661253/PATH", - L"HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/GOGMM6/PATH", - L"HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/New World Computing/Might and Magic\x00AE VI/1.0/AppPath", + "HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/Games/1207661253/PATH", + "HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/GOGMM6/PATH", + "HKEY_LOCAL_MACHINE/SOFTWARE/New World Computing/Might and Magic\x00AE VI/1.0/AppPath", + "HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/Games/1207661253/PATH", + "HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/GOGMM6/PATH", + "HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/New World Computing/Might and Magic\x00AE VI/1.0/AppPath", } ); } @@ -28,12 +28,12 @@ std::string resolveMm7Path(Platform *platform) { platform, mm7PathOverrideKey, { - L"HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/Games/1207658916/Path", - L"HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/GOGMM7/PATH", - L"HKEY_LOCAL_MACHINE/SOFTWARE/New World Computing/Might and Magic VII/1.0/AppPath", - L"HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/Games/1207658916/Path", - L"HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/GOGMM7/PATH", - L"HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/New World Computing/Might and Magic VII/1.0/AppPath", + "HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/Games/1207658916/Path", + "HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/GOGMM7/PATH", + "HKEY_LOCAL_MACHINE/SOFTWARE/New World Computing/Might and Magic VII/1.0/AppPath", + "HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/Games/1207658916/Path", + "HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/GOGMM7/PATH", + "HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/New World Computing/Might and Magic VII/1.0/AppPath", } ); } @@ -44,10 +44,10 @@ std::string resolveMm8Path(Platform *platform) { platform, mm8PathOverrideKey, { - L"HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/GOGMM8/PATH", - L"HKEY_LOCAL_MACHINE/SOFTWARE/New World Computing/Might and Magic Day of the Destroyer/1.0/AppPath", - L"HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/GOGMM8/PATH", - L"HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/New World Computing/Might and Magic Day of the Destroyer/1.0/AppPath", + "HKEY_LOCAL_MACHINE/SOFTWARE/GOG.com/GOGMM8/PATH", + "HKEY_LOCAL_MACHINE/SOFTWARE/New World Computing/Might and Magic Day of the Destroyer/1.0/AppPath", + "HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/GOG.com/GOGMM8/PATH", + "HKEY_LOCAL_MACHINE/SOFTWARE/WOW6432Node/New World Computing/Might and Magic Day of the Destroyer/1.0/AppPath", } ); } @@ -56,7 +56,7 @@ std::string resolveMm8Path(Platform *platform) { static std::string _resolvePath( Platform *platform, const char *envVarOverride, - const std::vector ®istryKeys + const std::vector ®istryKeys ) { #ifdef __ANDROID__ // TODO: find a better way to deal with paths and remove this android specific block. diff --git a/src/Library/Platform/Interface/Platform.h b/src/Library/Platform/Interface/Platform.h index 259ae2f98dc1..f83b05585983 100644 --- a/src/Library/Platform/Interface/Platform.h +++ b/src/Library/Platform/Interface/Platform.h @@ -143,7 +143,7 @@ class Platform { * @param path Registry path to query. * @return Value at the given path, or an empty string in case of an error. */ - virtual std::string winQueryRegistry(const std::wstring &path) const = 0; + virtual std::string winQueryRegistry(const std::string &path) const = 0; /** * Get various application filesystem paths. diff --git a/src/Library/Platform/Null/NullPlatform.cpp b/src/Library/Platform/Null/NullPlatform.cpp index dbda90d17086..b2d442c4238e 100644 --- a/src/Library/Platform/Null/NullPlatform.cpp +++ b/src/Library/Platform/Null/NullPlatform.cpp @@ -44,7 +44,7 @@ int64_t NullPlatform::tickCount() const { return 0; // Time's not flowing in null platform. } -std::string NullPlatform::winQueryRegistry(const std::wstring &path) const { +std::string NullPlatform::winQueryRegistry(const std::string &path) const { return {}; } diff --git a/src/Library/Platform/Null/NullPlatform.h b/src/Library/Platform/Null/NullPlatform.h index 0aabe7f5fb25..70223d62a080 100644 --- a/src/Library/Platform/Null/NullPlatform.h +++ b/src/Library/Platform/Null/NullPlatform.h @@ -23,7 +23,7 @@ class NullPlatform : public Platform { virtual std::vector displayGeometries() const override; virtual void showMessageBox(const std::string &title, const std::string &message) const override; virtual int64_t tickCount() const override; - virtual std::string winQueryRegistry(const std::wstring &path) const override; + virtual std::string winQueryRegistry(const std::string &path) const override; virtual std::string storagePath(const PlatformStorage type) const override; private: diff --git a/src/Library/Platform/Proxy/ProxyPlatform.cpp b/src/Library/Platform/Proxy/ProxyPlatform.cpp index f3dea7213c36..19edec665d8c 100644 --- a/src/Library/Platform/Proxy/ProxyPlatform.cpp +++ b/src/Library/Platform/Proxy/ProxyPlatform.cpp @@ -37,7 +37,7 @@ int64_t ProxyPlatform::tickCount() const { return nonNullBase()->tickCount(); } -std::string ProxyPlatform::winQueryRegistry(const std::wstring &path) const { +std::string ProxyPlatform::winQueryRegistry(const std::string &path) const { return nonNullBase()->winQueryRegistry(path); } diff --git a/src/Library/Platform/Proxy/ProxyPlatform.h b/src/Library/Platform/Proxy/ProxyPlatform.h index ffd02d57f731..bdd13757fc92 100644 --- a/src/Library/Platform/Proxy/ProxyPlatform.h +++ b/src/Library/Platform/Proxy/ProxyPlatform.h @@ -22,6 +22,6 @@ class ProxyPlatform : public ProxyBase { virtual std::vector displayGeometries() const override; virtual void showMessageBox(const std::string &title, const std::string &message) const override; virtual int64_t tickCount() const override; - virtual std::string winQueryRegistry(const std::wstring &path) const override; + virtual std::string winQueryRegistry(const std::string &path) const override; virtual std::string storagePath(const PlatformStorage type) const override; }; diff --git a/src/Library/Platform/Sdl/SdlPlatform.cpp b/src/Library/Platform/Sdl/SdlPlatform.cpp index 9b9cc48f0e9e..cfa434a9a1b6 100644 --- a/src/Library/Platform/Sdl/SdlPlatform.cpp +++ b/src/Library/Platform/Sdl/SdlPlatform.cpp @@ -137,7 +137,7 @@ int64_t SdlPlatform::tickCount() const { return SDL_GetTicks64(); } -std::string SdlPlatform::winQueryRegistry(const std::wstring &) const { +std::string SdlPlatform::winQueryRegistry(const std::string &) const { return {}; } diff --git a/src/Library/Platform/Sdl/SdlPlatform.h b/src/Library/Platform/Sdl/SdlPlatform.h index e291d6bcfa02..57f4a043664a 100644 --- a/src/Library/Platform/Sdl/SdlPlatform.h +++ b/src/Library/Platform/Sdl/SdlPlatform.h @@ -29,7 +29,7 @@ class SdlPlatform: public Platform { virtual int64_t tickCount() const override; - virtual std::string winQueryRegistry(const std::wstring &path) const override; + virtual std::string winQueryRegistry(const std::string &path) const override; virtual std::string storagePath(const PlatformStorage type) const override; diff --git a/src/Library/Platform/Win/WinPlatform.cpp b/src/Library/Platform/Win/WinPlatform.cpp index d2f5331ea08e..dd2d730f8bf8 100644 --- a/src/Library/Platform/Win/WinPlatform.cpp +++ b/src/Library/Platform/Win/WinPlatform.cpp @@ -9,7 +9,32 @@ #include "Utility/String.h" -static bool OS_GetAppStringRecursive(HKEY parent_key, const wchar_t *path, char *out_string, int out_string_size, int flags) { +static std::string toUtf8(std::wstring_view wstr) { + std::string result; + + int len = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr.size(), nullptr, 0, nullptr, nullptr); + if (len == 0) + return result; + + result.resize(len); + WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr.size(), result.data(), len, nullptr, nullptr); + return result; +} + +static std::wstring toUtf16(std::string_view str) { + std::wstring result; + + int len = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), nullptr, 0); + if (len == 0) + return result; + + result.resize(len); + MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), result.data(), len); + return result; +} + +// TODO(captainurist): revisit this code once I'm on a win machine. +static std::wstring OS_GetAppStringRecursive(HKEY parent_key, const wchar_t *path, int flags) { wchar_t current_key[256]; wchar_t path_tail[4096]; @@ -32,7 +57,7 @@ static bool OS_GetAppStringRecursive(HKEY parent_key, const wchar_t *path, char else if (!wcsicmp(current_key, L"HKEY_USERS")) parent_key = HKEY_USERS; else - return false; + return {}; delimiter = wcsstr(path_tail, L"/"); if (delimiter) { @@ -41,62 +66,43 @@ static bool OS_GetAppStringRecursive(HKEY parent_key, const wchar_t *path, char wcscpy(path_tail, delimiter + 1); } else { - return false; + return {}; } } if (!wcscmp(current_key, L"WOW6432Node")) { - return OS_GetAppStringRecursive(parent_key, path_tail, out_string, out_string_size, KEY_WOW64_32KEY); + return OS_GetAppStringRecursive(parent_key, path_tail, KEY_WOW64_32KEY); } - bool result = false; HKEY key; if (!RegOpenKeyExW(parent_key, current_key, 0, KEY_READ | flags, &key)) { - result = OS_GetAppStringRecursive(key, path_tail, out_string, out_string_size, 0); + std::wstring result = OS_GetAppStringRecursive(key, path_tail, 0); RegCloseKey(key); + return result; } - return result; + return {}; } else { - auto regValue = std::make_unique(out_string_size + 1); - for (int i = 0; i < out_string_size; ++i) { - regValue.get()[i] = L'x'; - out_string[i] = 'x'; - } - DWORD regNumBytesRead = sizeof(wchar_t) * (out_string_size + 1); + std::array buffer = {{}}; + DWORD regNumBytesRead = sizeof(buffer); LSTATUS status = RegGetValueW( parent_key, nullptr, path, RRF_RT_REG_SZ | RRF_RT_REG_EXPAND_SZ, nullptr, - regValue.get(), + buffer.data(), ®NumBytesRead ); - if (status == ERROR_SUCCESS) { - if (regNumBytesRead > 0) { - int numBytesConverted = WideCharToMultiByte(CP_ACP, 0, regValue.get(), -1, out_string, out_string_size, nullptr, nullptr); - if (0 == numBytesConverted) { - status = ERROR_PATH_NOT_FOUND; - } - } else { - status = ERROR_PATH_NOT_FOUND; - } - } - - if (status != ERROR_SUCCESS) { - strcpy(out_string, ""); - } + if (status == ERROR_SUCCESS) + return buffer.data(); - return status == ERROR_SUCCESS; + return {}; } } -std::string WinPlatform::winQueryRegistry(const std::wstring &path) const { - char buffer[8192]; - if (OS_GetAppStringRecursive(nullptr, path.c_str(), buffer, sizeof(buffer), 0)) - return std::string(buffer); - return {}; +std::string WinPlatform::winQueryRegistry(const std::string &path) const { + return toUtf8(OS_GetAppStringRecursive(NULL, toUtf16(path).c_str(), 0)); } std::unique_ptr Platform::createStandardPlatform(Logger *logger) { diff --git a/src/Library/Platform/Win/WinPlatform.h b/src/Library/Platform/Win/WinPlatform.h index 35063642eb08..965b0fdb4f71 100644 --- a/src/Library/Platform/Win/WinPlatform.h +++ b/src/Library/Platform/Win/WinPlatform.h @@ -8,5 +8,5 @@ class WinPlatform : public SdlPlatform { public: using SdlPlatform::SdlPlatform; - virtual std::string winQueryRegistry(const std::wstring &path) const override; + virtual std::string winQueryRegistry(const std::string &path) const override; };