find_firefox.cpp (3773B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 #include "find_firefox.h" 5 6 #include <iostream> 7 #include <optional> 8 #include <string> 9 #include <windows.h> 10 11 // The firefox_node logic here mirrors the definition of BrandFullNameInternal 12 // in browser/branding/${channel}/branding.nsi 13 // Opened Bug 1979135 to address refactoring this. 14 #if defined(MOZ_BRANDING_IS_OFFICIAL) 15 static const wchar_t* firefox_node = L"SOFTWARE\\Mozilla\\Mozilla Firefox"; 16 #elif defined(MOZ_BRANDING_IS_NIGHTLY) 17 static const wchar_t* firefox_node = L"SOFTWARE\\Mozilla\\Nightly"; 18 #elif defined(MOZ_BRANDING_IS_BETA) 19 static const wchar_t* firefox_node = L"SOFTWARE\\Mozilla\\Mozilla Firefox"; 20 #elif defined(MOZ_BRANDING_IS_DEVEDITION) 21 static const wchar_t* firefox_node = 22 L"SOFTWARE\\Mozilla\\Firefox Developer Edition"; 23 #elif defined(MOZ_BRANDING_IS_UNOFFICIAL) 24 static const wchar_t* firefox_node = 25 L"SOFTWARE\\Mozilla\\Mozilla Developer Preview"; 26 #else 27 // Unexpected case. Fail the build here so we can figure out the missing case. 28 static_assert(false); 29 #endif 30 31 /** 32 * The base registry key that Firefox uses to store its settings is different 33 * depending on the branding for the build. This function exposes the correct 34 * registry key to use for the current build's branding. 35 */ 36 const wchar_t* getFirefoxRegistryBranding() { return firefox_node; } 37 38 /** 39 * Look up Firefox path in a particular HKEY 40 */ 41 static std::optional<std::wstring> lookupFirefoxPathInHKEY(HKEY hkey) { 42 std::wstring current_version = L"CurrentVersion"; 43 wchar_t buffer[MAX_PATH]; 44 // RegGetValueW will store the size of the value (including terminal \0) in 45 // bytes into this variable. 46 DWORD value_size = sizeof(buffer); 47 48 // First we need to get the current version of Firefox 49 LSTATUS status = 50 RegGetValueW(hkey, getFirefoxRegistryBranding(), current_version.c_str(), 51 RRF_RT_REG_SZ, nullptr, buffer, &value_size); 52 if (status != ERROR_SUCCESS || value_size < 2) { 53 std::wcout << L"Failed to get firefox current version at node " 54 << getFirefoxRegistryBranding() << L"status: " << status 55 << std::endl; 56 return std::nullopt; 57 } 58 DWORD value_len = value_size / sizeof(wchar_t) - 1; 59 // Then we need to see where that version is installed 60 std::wstring current_version_string = std::wstring(buffer, value_len); 61 std::wstring current_version_node = 62 std::wstring(getFirefoxRegistryBranding()) + L"\\" + 63 current_version_string + L"\\Main"; 64 std::wstring path_to_exe = L"PathToExe"; 65 value_size = sizeof(buffer); 66 status = RegGetValueW(hkey, current_version_node.c_str(), path_to_exe.c_str(), 67 RRF_RT_REG_SZ, nullptr, buffer, &value_size); 68 if (status != ERROR_SUCCESS || value_size < 2) { 69 std::wcout 70 << L"Failed to get firefox path for current version, at location " 71 << current_version_node << L" status was " << status << std::endl; 72 return std::nullopt; 73 } 74 value_len = value_size / sizeof(wchar_t) - 1; 75 // We should have the path in buffer. Note that value_len contains the size of 76 // the path in bytes, so we need to divide by 2 to get the length in 77 // characters. 78 std::wstring firefox_path = std::wstring(buffer, value_len); 79 return firefox_path; 80 } 81 82 /** 83 * Look up Firefox path in registry keys 84 * @return the path as a std::wstring if found 85 */ 86 std::optional<std::wstring> lookupFirefoxPath() { 87 auto sharedInstallPath = lookupFirefoxPathInHKEY(HKEY_CURRENT_USER); 88 if (sharedInstallPath.has_value()) { 89 return sharedInstallPath; 90 } else { 91 return lookupFirefoxPathInHKEY(HKEY_LOCAL_MACHINE); 92 } 93 }