|
28 | 28 |
|
29 | 29 | #include "llviewerprecompiledheaders.h" |
30 | 30 | #include "llvelopack.h" |
| 31 | +#include "llstring.h" |
31 | 32 |
|
32 | 33 | #include "Velopack.h" |
33 | 34 |
|
|
37 | 38 | #include <shobjidl.h> |
38 | 39 | #include <shlwapi.h> |
39 | 40 | #include <objbase.h> |
| 41 | +#include <filesystem> |
40 | 42 |
|
41 | 43 | #pragma comment(lib, "shlwapi.lib") |
42 | 44 | #pragma comment(lib, "ole32.lib") |
@@ -175,6 +177,81 @@ static void register_protocol_handler(const std::wstring& protocol, |
175 | 177 | } |
176 | 178 | } |
177 | 179 |
|
| 180 | +bool get_nsis_uninstaller_path(wchar_t* path_buffer, DWORD bufSize) |
| 181 | +{ |
| 182 | + // Test for presense of NSIS viewer registration, then |
| 183 | + // attempt to read uninstall info |
| 184 | + std::wstring app_name_oneword = get_app_name_oneword(); |
| 185 | + std::wstring uninstall_key_path = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + app_name_oneword; |
| 186 | + HKEY hkey; |
| 187 | + LONG result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, uninstall_key_path.c_str(), 0, KEY_READ, &hkey); |
| 188 | + if (result != ERROR_SUCCESS) |
| 189 | + { |
| 190 | + return false; |
| 191 | + } |
| 192 | + |
| 193 | + // Read DisplayVersion |
| 194 | + wchar_t version_buf[64] = { 0 }; |
| 195 | + DWORD version_buf_size = sizeof(version_buf); |
| 196 | + DWORD type = 0; |
| 197 | + LONG ver_rv = RegGetValueW(hkey, nullptr, L"DisplayVersion", RRF_RT_REG_SZ, &type, version_buf, &version_buf_size); |
| 198 | + // Compare versions if both are available |
| 199 | + if (ver_rv == ERROR_SUCCESS) |
| 200 | + { |
| 201 | + // Get current version as UTF-8 string, convert to wstring |
| 202 | + std::string current_version_str = velopack_get_current_version(); |
| 203 | + std::wstring current_version_w; |
| 204 | + if (!current_version_str.empty()) |
| 205 | + { |
| 206 | + int wlen = MultiByteToWideChar(CP_UTF8, 0, current_version_str.c_str(), -1, nullptr, 0); |
| 207 | + if (wlen > 0) |
| 208 | + { |
| 209 | + current_version_w.resize(wlen - 1); |
| 210 | + MultiByteToWideChar(CP_UTF8, 0, current_version_str.c_str(), -1, ¤t_version_w[0], wlen); |
| 211 | + } |
| 212 | + } |
| 213 | + // If NSIS version is newer, skip removal |
| 214 | + // todo: for testing purposes this ignores missing version, |
| 215 | + // should skip if current version is uknown |
| 216 | + if (!current_version_w.empty() && wcscmp(version_buf, current_version_w.c_str()) > 0) |
| 217 | + { |
| 218 | + RegCloseKey(hkey); |
| 219 | + return false; |
| 220 | + } |
| 221 | + } |
| 222 | + |
| 223 | + LONG rv = RegGetValueW(hkey, nullptr, L"UninstallString", RRF_RT_REG_SZ, &type, path_buffer, &bufSize); |
| 224 | + RegCloseKey(hkey); |
| 225 | + if (rv != ERROR_SUCCESS) |
| 226 | + { |
| 227 | + return false; |
| 228 | + } |
| 229 | + size_t len = wcslen(path_buffer); |
| 230 | + if (len > 0) |
| 231 | + { |
| 232 | + if (path_buffer[0] == L'\"') |
| 233 | + { |
| 234 | + // Shift all characters left by one, including the null terminator |
| 235 | + memmove(path_buffer, path_buffer + 1, (len) * sizeof(wchar_t)); |
| 236 | + } |
| 237 | + |
| 238 | + wchar_t* pos = wcsstr(path_buffer, L"uninst.exe"); |
| 239 | + if (pos) |
| 240 | + { |
| 241 | + pos[wcslen(L"uninst.exe")] = L'\0'; |
| 242 | + } |
| 243 | + } |
| 244 | + std::error_code ec; |
| 245 | + std::filesystem::path path(path_buffer); |
| 246 | + if (!std::filesystem::exists(path, ec)) |
| 247 | + { |
| 248 | + // If ec, assume that it's there? |
| 249 | + return false; |
| 250 | + } |
| 251 | + |
| 252 | + return true; |
| 253 | +} |
| 254 | + |
178 | 255 | static void unregister_protocol_handler(const std::wstring& protocol) |
179 | 256 | { |
180 | 257 | std::wstring key_path = L"SOFTWARE\\Classes\\" + protocol; |
@@ -206,6 +283,18 @@ static void register_uninstall_info(const std::wstring& install_dir, |
206 | 283 | RegSetValueExW(hkey, L"DisplayIcon", 0, REG_SZ, |
207 | 284 | (BYTE*)exe_path.c_str(), (DWORD)((exe_path.size() + 1) * sizeof(wchar_t))); |
208 | 285 |
|
| 286 | + std::wstring link_url = L"https://support.secondlife.com/contact-support/"; |
| 287 | + RegSetValueExW(hkey, L"HelpLink", 0, REG_SZ, |
| 288 | + (BYTE*)link_url.c_str(), (DWORD)((link_url.size() + 1) * sizeof(wchar_t))); |
| 289 | + |
| 290 | + link_url = L"https://secondlife.com/whatis/"; |
| 291 | + RegSetValueExW(hkey, L"URLInfoAbout", 0, REG_SZ, |
| 292 | + (BYTE*)link_url.c_str(), (DWORD)((link_url.size() + 1) * sizeof(wchar_t))); |
| 293 | + |
| 294 | + link_url = L"http://secondlife.com/support/downloads/"; |
| 295 | + RegSetValueExW(hkey, L"URLUpdateInfo", 0, REG_SZ, |
| 296 | + (BYTE*)link_url.c_str(), (DWORD)((link_url.size() + 1) * sizeof(wchar_t))); |
| 297 | + |
209 | 298 | DWORD no_modify = 1; |
210 | 299 | RegSetValueExW(hkey, L"NoModify", 0, REG_DWORD, (BYTE*)&no_modify, sizeof(DWORD)); |
211 | 300 | RegSetValueExW(hkey, L"NoRepair", 0, REG_DWORD, (BYTE*)&no_modify, sizeof(DWORD)); |
@@ -251,6 +340,8 @@ static void remove_shortcuts(const std::wstring& app_name) |
251 | 340 |
|
252 | 341 | static void on_after_install(void* user_data, const char* app_version) |
253 | 342 | { |
| 343 | + LLVelopack::sAfterInstall = true; |
| 344 | + |
254 | 345 | std::wstring install_dir = get_install_dir(); |
255 | 346 | std::wstring app_name = get_app_name(); |
256 | 347 | std::wstring exe_path = install_dir + L"\\" + VIEWER_EXE_NAME; |
|
0 commit comments