From 641fac232abbbb6ce4a7b1718fa36f61c050218b Mon Sep 17 00:00:00 2001 From: sukibaby <163092272+sukibaby@users.noreply.github.com> Date: Fri, 3 Jan 2025 12:59:48 -0800 Subject: [PATCH] (Win32 refresh) GotoURL Mitigate some security concerns, update API calls (RegOpenKeyExW & ShellExecuteEx), support unicode natively, const correctness, etc. - not doing anything new, just updating what's here to be more modern. --- src/archutils/Win32/GotoURL.cpp | 107 ++++++++++++++++++++++---------- src/archutils/Win32/GotoURL.h | 2 +- 2 files changed, 74 insertions(+), 35 deletions(-) diff --git a/src/archutils/Win32/GotoURL.cpp b/src/archutils/Win32/GotoURL.cpp index 6fe07bdb8c..b5e4955a28 100644 --- a/src/archutils/Win32/GotoURL.cpp +++ b/src/archutils/Win32/GotoURL.cpp @@ -5,61 +5,100 @@ #include #include +#include +#include +#include +#include -/* This is called from the crash handler; don't use RegistryAccess, since it's - * not crash-conditions safe. */ -static LONG GetRegKey( HKEY key, RString subkey, LPTSTR retdata ) +static std::wstring ConvertToWString(const std::string& str) { - HKEY hKey; - LONG iRet = RegOpenKeyEx( key, subkey, 0, KEY_QUERY_VALUE, &hKey ); - - if( iRet != ERROR_SUCCESS ) - return iRet; - - long iDataSize = MAX_PATH; - char data[MAX_PATH]; - RegQueryValue( hKey, "emulation", data, &iDataSize ); - strcpy( retdata, data ); - RegCloseKey( hKey ); - - return ERROR_SUCCESS; + int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0); + std::wstring wstrTo(size_needed, 0); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstrTo[0], size_needed); + return wstrTo; } -bool GotoURL( RString sUrl ) +static LONG GetRegKey(HKEY key, const std::wstring& subkey, std::wstring& retdata) { - // First try ShellExecute() - intptr_t iRet = reinterpret_cast(ShellExecute( nullptr, "open", sUrl, nullptr, nullptr, SW_SHOWDEFAULT )); + HKEY hKey; + LONG iRet = RegOpenKeyExW(key, subkey.c_str(), 0, KEY_QUERY_VALUE, &hKey); - // If it failed, get the .htm regkey and lookup the program - if( iRet > 32 ) + if (iRet != ERROR_SUCCESS) + { + return iRet; + } + + DWORD iDataSize = 0; + iRet = RegQueryValueExW(hKey, L"emulation", nullptr, nullptr, nullptr, &iDataSize); + if (iRet != ERROR_SUCCESS) + { + RegCloseKey(hKey); + return iRet; + } + + std::vector data(iDataSize / sizeof(wchar_t)); + iRet = RegQueryValueExW(hKey, L"emulation", nullptr, nullptr, reinterpret_cast(data.data()), &iDataSize); + if (iRet == ERROR_SUCCESS) + { + retdata.assign(data.begin(), data.end() - 1); + } + + RegCloseKey(hKey); + return iRet; +} + +bool GotoURL(const RString& sUrl) +{ + // Convert RString to std::wstring + std::wstring iUrl = ConvertToWString(sUrl); + + // First try ShellExecuteEx + SHELLEXECUTEINFOW sei = { sizeof(sei) }; + sei.lpVerb = L"open"; + sei.lpFile = iUrl.c_str(); + sei.nShow = SW_SHOWDEFAULT; + sei.fMask = SEE_MASK_FLAG_NO_UI; + + if (ShellExecuteExW(&sei) && reinterpret_cast(sei.hInstApp) > 32) return true; - char key[2*MAX_PATH]; - if( GetRegKey(HKEY_CLASSES_ROOT, ".htm", key) != ERROR_SUCCESS ) + // If it failed, get the .htm regkey and lookup the program + std::wstring key; + if (GetRegKey(HKEY_CLASSES_ROOT, L".htm", key) != ERROR_SUCCESS) return false; - strcpy( key, "\\shell\\open\\command" ); + key += L"\\shell\\open\\command"; if( GetRegKey(HKEY_CLASSES_ROOT, key, key) != ERROR_SUCCESS ) return false; - char *szPos = strstr( key, "\"%1\"" ); - if( szPos == nullptr ) + size_t pos = key.find(L"\"%1\""); + if (pos == std::wstring::npos) { // No quotes found. Check for %1 without quotes - szPos = strstr( key, "%1" ); - if( szPos == nullptr ) - szPos = key+lstrlen(key)-1; // No parameter. + pos = key.find(L"%1"); + if (pos == std::wstring::npos) + pos = key.length() - 1; // No parameter. else - *szPos = '\0'; // Remove the parameter + key.erase(pos); // Remove the parameter } else - *szPos = '\0'; // Remove the parameter + { + key.erase(pos); // Remove the parameter + } - strcat( szPos, " " ); - strcat( szPos, sUrl ); + key += L" " + iUrl; - return WinExec( key, SW_SHOWDEFAULT ) > 32; + STARTUPINFOW si = { sizeof(si) }; + PROCESS_INFORMATION pi; + if (CreateProcessW(nullptr, &key[0], nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi)) + { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return true; + } + + return false; } /* diff --git a/src/archutils/Win32/GotoURL.h b/src/archutils/Win32/GotoURL.h index 7721eaecfd..f2b18967fb 100644 --- a/src/archutils/Win32/GotoURL.h +++ b/src/archutils/Win32/GotoURL.h @@ -2,7 +2,7 @@ #define GOTO_URL_H /** @brief Open URLs in a browser. */ -bool GotoURL( RString sUrl ); +bool GotoURL( const RString& sUrl ); #endif