forked from mirrors/gecko-dev
		
	 72a7b95555
			
		
	
	
		72a7b95555
		
	
	
	
	
		
			
			Backed out changeset 44c66f2233cf (bug 1844908) Backed out changeset a8010ff534bf (bug 1844908) Backed out changeset 225dc3aeb220 (bug 1844908) Backed out changeset a1414db64e33 (bug 1844908) Backed out changeset 7f1e0a527839 (bug 1844908) Backed out changeset 6dc7646d1ffa (bug 1844908) Backed out changeset 8d715131510f (bug 1844908) Backed out changeset 4b6fe8a4e7db (bug 1844908) Backed out changeset 2b419fabf1e8 (bug 1844908) Backed out changeset af84e701d616 (bug 1844908) Backed out changeset 2fa203969ec5 (bug 1844908) Backed out changeset 2b3d2df94db3 (bug 1844908) Backed out changeset 7eca452f5fd7 (bug 1844908) Backed out changeset 3d961cf25afe (bug 1844908) Backed out changeset 3c59143f8dd7 (bug 1844908) Backed out changeset ab50c6c5425a (bug 1844908) Backed out changeset b2c5636df673 (bug 1844908) Backed out changeset e9a0f1c6760c (bug 1844908) Backed out changeset 945ccbedde0b (bug 1844908)
		
			
				
	
	
		
			212 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| /**
 | |
|  * This file exists so that LaunchModernSettingsDialogDefaultApps can be called
 | |
|  * without linking to libxul.
 | |
|  */
 | |
| #include "WindowsDefaultBrowser.h"
 | |
| 
 | |
| #include "city.h"
 | |
| #include "mozilla/ArrayUtils.h"
 | |
| #include "mozilla/UniquePtr.h"
 | |
| #include "mozilla/WindowsVersion.h"
 | |
| #include "mozilla/WinHeaderOnlyUtils.h"
 | |
| 
 | |
| // Needed for access to IApplicationActivationManager
 | |
| // This must be before any other includes that might include shlobj.h
 | |
| #ifdef _WIN32_WINNT
 | |
| #  undef _WIN32_WINNT
 | |
| #endif
 | |
| #define _WIN32_WINNT 0x0600
 | |
| #define INITGUID
 | |
| #undef NTDDI_VERSION
 | |
| #define NTDDI_VERSION NTDDI_WIN8
 | |
| #include <shlobj.h>
 | |
| 
 | |
| #include <lm.h>
 | |
| #include <shellapi.h>
 | |
| #include <shlwapi.h>
 | |
| #include <wchar.h>
 | |
| #include <windows.h>
 | |
| 
 | |
| #define APP_REG_NAME_BASE L"Firefox-"
 | |
| 
 | |
| static bool IsWindowsLogonConnected() {
 | |
|   WCHAR userName[UNLEN + 1];
 | |
|   DWORD size = mozilla::ArrayLength(userName);
 | |
|   if (!GetUserNameW(userName, &size)) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   LPUSER_INFO_24 info;
 | |
|   if (NetUserGetInfo(nullptr, userName, 24, (LPBYTE*)&info) != NERR_Success) {
 | |
|     return false;
 | |
|   }
 | |
|   bool connected = info->usri24_internet_identity;
 | |
|   NetApiBufferFree(info);
 | |
| 
 | |
|   return connected;
 | |
| }
 | |
| 
 | |
| static bool SettingsAppBelievesConnected() {
 | |
|   const wchar_t* keyPath = L"SOFTWARE\\Microsoft\\Windows\\Shell\\Associations";
 | |
|   const wchar_t* valueName = L"IsConnectedAtLogon";
 | |
| 
 | |
|   uint32_t value = 0;
 | |
|   DWORD size = sizeof(uint32_t);
 | |
|   LSTATUS ls = RegGetValueW(HKEY_CURRENT_USER, keyPath, valueName, RRF_RT_ANY,
 | |
|                             nullptr, &value, &size);
 | |
|   if (ls != ERROR_SUCCESS) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   return !!value;
 | |
| }
 | |
| 
 | |
| bool GetAppRegName(mozilla::UniquePtr<wchar_t[]>& aAppRegName) {
 | |
|   mozilla::UniquePtr<wchar_t[]> appDirStr;
 | |
|   bool success = GetInstallDirectory(appDirStr);
 | |
|   if (!success) {
 | |
|     return success;
 | |
|   }
 | |
| 
 | |
|   uint64_t hash = CityHash64(reinterpret_cast<char*>(appDirStr.get()),
 | |
|                              wcslen(appDirStr.get()) * sizeof(wchar_t));
 | |
| 
 | |
|   const wchar_t* format = L"%s%I64X";
 | |
|   int bufferSize = _scwprintf(format, APP_REG_NAME_BASE, hash);
 | |
|   ++bufferSize;  // Extra byte for terminating null
 | |
|   aAppRegName = mozilla::MakeUnique<wchar_t[]>(bufferSize);
 | |
| 
 | |
|   _snwprintf_s(aAppRegName.get(), bufferSize, _TRUNCATE, format,
 | |
|                APP_REG_NAME_BASE, hash);
 | |
| 
 | |
|   return success;
 | |
| }
 | |
| 
 | |
| bool LaunchControlPanelDefaultPrograms() {
 | |
|   // Build the path control.exe path safely
 | |
|   WCHAR controlEXEPath[MAX_PATH + 1] = {'\0'};
 | |
|   if (!GetSystemDirectoryW(controlEXEPath, MAX_PATH)) {
 | |
|     return false;
 | |
|   }
 | |
|   LPCWSTR controlEXE = L"control.exe";
 | |
|   if (wcslen(controlEXEPath) + wcslen(controlEXE) >= MAX_PATH) {
 | |
|     return false;
 | |
|   }
 | |
|   if (!PathAppendW(controlEXEPath, controlEXE)) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   const wchar_t* paramFormat =
 | |
|       L"control.exe /name Microsoft.DefaultPrograms "
 | |
|       L"/page pageDefaultProgram\\pageAdvancedSettings?pszAppName=%s";
 | |
|   mozilla::UniquePtr<wchar_t[]> appRegName;
 | |
|   GetAppRegName(appRegName);
 | |
|   int bufferSize = _scwprintf(paramFormat, appRegName.get());
 | |
|   ++bufferSize;  // Extra byte for terminating null
 | |
|   mozilla::UniquePtr<wchar_t[]> params =
 | |
|       mozilla::MakeUnique<wchar_t[]>(bufferSize);
 | |
|   _snwprintf_s(params.get(), bufferSize, _TRUNCATE, paramFormat,
 | |
|                appRegName.get());
 | |
| 
 | |
|   STARTUPINFOW si = {sizeof(si), 0};
 | |
|   si.dwFlags = STARTF_USESHOWWINDOW;
 | |
|   si.wShowWindow = SW_SHOWDEFAULT;
 | |
|   PROCESS_INFORMATION pi = {0};
 | |
|   if (!CreateProcessW(controlEXEPath, params.get(), nullptr, nullptr, FALSE, 0,
 | |
|                       nullptr, nullptr, &si, &pi)) {
 | |
|     return false;
 | |
|   }
 | |
|   CloseHandle(pi.hProcess);
 | |
|   CloseHandle(pi.hThread);
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| static bool IsAppRegistered(HKEY rootKey, const wchar_t* appRegName) {
 | |
|   const wchar_t* keyPath = L"Software\\RegisteredApplications";
 | |
| 
 | |
|   DWORD size = sizeof(uint32_t);
 | |
|   LSTATUS ls = RegGetValueW(rootKey, keyPath, appRegName, RRF_RT_ANY, nullptr,
 | |
|                             nullptr, &size);
 | |
|   return ls == ERROR_SUCCESS;
 | |
| }
 | |
| 
 | |
| static bool LaunchMsSettingsProtocol() {
 | |
|   mozilla::UniquePtr<wchar_t[]> params = nullptr;
 | |
|   if (mozilla::HasPackageIdentity()) {
 | |
|     mozilla::UniquePtr<wchar_t[]> packageFamilyName =
 | |
|         mozilla::GetPackageFamilyName();
 | |
|     if (packageFamilyName) {
 | |
|       const wchar_t* paramFormat =
 | |
|           L"ms-settings:defaultapps?registeredAUMID=%s!App";
 | |
|       int bufferSize = _scwprintf(paramFormat, packageFamilyName.get());
 | |
|       ++bufferSize;  // Extra byte for terminating null
 | |
|       params = mozilla::MakeUnique<wchar_t[]>(bufferSize);
 | |
|       _snwprintf_s(params.get(), bufferSize, _TRUNCATE, paramFormat,
 | |
|                    packageFamilyName.get());
 | |
|     }
 | |
|   }
 | |
|   if (!params) {
 | |
|     mozilla::UniquePtr<wchar_t[]> appRegName;
 | |
|     GetAppRegName(appRegName);
 | |
|     const wchar_t* paramFormat =
 | |
|         IsAppRegistered(HKEY_CURRENT_USER, appRegName.get()) ||
 | |
|                 !IsAppRegistered(HKEY_LOCAL_MACHINE, appRegName.get())
 | |
|             ? L"ms-settings:defaultapps?registeredAppUser=%s"
 | |
|             : L"ms-settings:defaultapps?registeredAppMachine=%s";
 | |
|     int bufferSize = _scwprintf(paramFormat, appRegName.get());
 | |
|     ++bufferSize;  // Extra byte for terminating null
 | |
|     params = mozilla::MakeUnique<wchar_t[]>(bufferSize);
 | |
|     _snwprintf_s(params.get(), bufferSize, _TRUNCATE, paramFormat,
 | |
|                  appRegName.get());
 | |
|   }
 | |
| 
 | |
|   SHELLEXECUTEINFOW seinfo = {sizeof(seinfo)};
 | |
|   seinfo.lpFile = params.get();
 | |
|   seinfo.nShow = SW_SHOWNORMAL;
 | |
|   return ShellExecuteExW(&seinfo);
 | |
| }
 | |
| 
 | |
| bool LaunchModernSettingsDialogDefaultApps() {
 | |
|   if (mozilla::IsWin11OrLater()) {
 | |
|     return LaunchMsSettingsProtocol();
 | |
|   }
 | |
| 
 | |
|   if (!mozilla::IsWindowsBuildOrLater(14965) && !IsWindowsLogonConnected() &&
 | |
|       SettingsAppBelievesConnected()) {
 | |
|     // Use the classic Control Panel to work around a bug of older
 | |
|     // builds of Windows 10.
 | |
|     return LaunchControlPanelDefaultPrograms();
 | |
|   }
 | |
| 
 | |
|   IApplicationActivationManager* pActivator;
 | |
|   HRESULT hr = CoCreateInstance(
 | |
|       CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC,
 | |
|       IID_IApplicationActivationManager, (void**)&pActivator);
 | |
| 
 | |
|   if (SUCCEEDED(hr)) {
 | |
|     DWORD pid;
 | |
|     hr = pActivator->ActivateApplication(
 | |
|         L"windows.immersivecontrolpanel_cw5n1h2txyewy"
 | |
|         L"!microsoft.windows.immersivecontrolpanel",
 | |
|         L"page=SettingsPageAppsDefaults", AO_NONE, &pid);
 | |
|     if (SUCCEEDED(hr)) {
 | |
|       // Do not check error because we could at least open
 | |
|       // the "Default apps" setting.
 | |
|       pActivator->ActivateApplication(
 | |
|           L"windows.immersivecontrolpanel_cw5n1h2txyewy"
 | |
|           L"!microsoft.windows.immersivecontrolpanel",
 | |
|           L"page=SettingsPageAppsDefaults"
 | |
|           L"&target=SystemSettings_DefaultApps_Browser",
 | |
|           AO_NONE, &pid);
 | |
|     }
 | |
|     pActivator->Release();
 | |
|     return SUCCEEDED(hr);
 | |
|   }
 | |
|   return true;
 | |
| }
 |