(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.
This commit is contained in:
sukibaby
2025-01-03 12:59:48 -08:00
committed by teejusb
parent 30a03e0ab9
commit 641fac232a
2 changed files with 74 additions and 35 deletions
+73 -34
View File
@@ -5,61 +5,100 @@
#include <windows.h>
#include <shellapi.h>
#include <string>
#include <codecvt>
#include <locale>
#include <vector>
/* 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<intptr_t>(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<wchar_t> data(iDataSize / sizeof(wchar_t));
iRet = RegQueryValueExW(hKey, L"emulation", nullptr, nullptr, reinterpret_cast<LPBYTE>(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<intptr_t>(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;
}
/*
+1 -1
View File
@@ -2,7 +2,7 @@
#define GOTO_URL_H
/** @brief Open URLs in a browser. */
bool GotoURL( RString sUrl );
bool GotoURL( const RString& sUrl );
#endif