Bug 1588549 - --disable-maintenance-service should exclude all maintenance service-related code r=bytesized,mhowell

Exclude Windows Maintenance Service-related C++ code and avoid linking
with unnecessary libraries when building with --disable-maintenance-service.

Differential Revision: https://phabricator.services.mozilla.com/D76349
This commit is contained in:
Mark Smith 2020-05-27 21:22:15 +00:00
Родитель a2f2d585ea
Коммит 7b93c9ae97
6 изменённых файлов: 84 добавлений и 57 удалений

Просмотреть файл

@ -14,15 +14,19 @@ EXPORTS += [
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXPORTS += [
'certificatecheck.h',
'pathhash.h',
'registrycertificates.h',
'uachelper.h',
'updatehelper.cpp',
'updatehelper.h',
'updateutils_win.h',
]
if CONFIG['MOZ_MAINTENANCE_SERVICE']:
EXPORTS += [
'certificatecheck.h',
'registrycertificates.h',
]
Library('updatecommon')
DEFINES['NS_NO_XPCOM'] = True
@ -37,21 +41,26 @@ DisableStlWrapping()
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
SOURCES += [
'certificatecheck.cpp',
'pathhash.cpp',
'registrycertificates.cpp',
'uachelper.cpp',
'updatehelper.cpp',
'updateutils_win.cpp',
]
OS_LIBS += [
'advapi32',
'crypt32',
'ole32',
'rpcrt4',
'shell32',
'wintrust',
]
if CONFIG['MOZ_MAINTENANCE_SERVICE']:
SOURCES += [
'certificatecheck.cpp',
'registrycertificates.cpp',
]
OS_LIBS += [
'crypt32',
'wintrust',
]
SOURCES += [
'/other-licenses/nsis/Contrib/CityHash/cityhash/city.cpp',

Просмотреть файл

@ -6,23 +6,26 @@
// Needed for CreateToolhelp32Snapshot
#include <tlhelp32.h>
#ifndef ONLY_SERVICE_LAUNCHING
# include <stdio.h>
# include <direct.h>
# include "mozilla/UniquePtr.h"
# include "pathhash.h"
# include "shlobj.h"
# include "registrycertificates.h"
# include "uachelper.h"
# include "updatehelper.h"
# include "updateutils_win.h"
#include <stdio.h>
#include <direct.h>
#include "shlobj.h"
// Needed for PathAppendW
# include <shlwapi.h>
#include <shlwapi.h>
#include "updatehelper.h"
#include "updateutils_win.h"
#ifdef MOZ_MAINTENANCE_SERVICE
# include "mozilla/UniquePtr.h"
# include "pathhash.h"
# include "registrycertificates.h"
# include "uachelper.h"
using mozilla::MakeUnique;
using mozilla::UniquePtr;
#endif
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
LPCWSTR newFileName);
@ -31,7 +34,7 @@ BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
* Obtains the path of a file in the same directory as the specified file.
*
* @param destinationBuffer A buffer of size MAX_PATH + 1 to store the result.
* @param siblingFIlePath The path of another file in the same directory
* @param siblingFilePath The path of another file in the same directory
* @param newFileName The filename of another file in the same directory
* @return TRUE if successful
*/
@ -251,6 +254,7 @@ void RemoveSecureOutputFiles(LPCWSTR patchDirPath) {
}
}
#ifdef MOZ_MAINTENANCE_SERVICE
/**
* Starts the upgrade process for update of the service if it is
* already installed.
@ -353,8 +357,6 @@ BOOL StartServiceUpdate(LPCWSTR installDir) {
return svcUpdateProcessStarted;
}
#endif
/**
* Executes a maintenance service command
*
@ -409,8 +411,6 @@ StartServiceCommand(int argc, LPCWSTR* argv) {
return lastError;
}
#ifndef ONLY_SERVICE_LAUNCHING
/**
* Launch a service initiated action for a software update with the
* specified arguments.
@ -480,8 +480,6 @@ BOOL WriteStatusFailure(LPCWSTR patchDirPath, int errorCode) {
return TRUE;
}
#endif
/**
* Waits for a service to enter a stopped state.
* This function does not stop the service, it just blocks until the service
@ -610,8 +608,7 @@ WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds) {
CloseServiceHandle(serviceManager);
return lastServiceState;
}
#ifndef ONLY_SERVICE_LAUNCHING
#endif
/**
* Determines if there is at least one process running for the specified
@ -649,7 +646,7 @@ IsProcessRunning(LPCWSTR filename) {
}
/**
* Waits for the specified applicaiton to exit.
* Waits for the specified application to exit.
*
* @param filename The application to wait for.
* @param maxSeconds The maximum amount of seconds to wait for all
@ -676,6 +673,7 @@ WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds) {
return applicationRunningError;
}
#ifdef MOZ_MAINTENANCE_SERVICE
/**
* Determines if the fallback key exists or not
*
@ -693,8 +691,6 @@ BOOL DoesFallbackKeyExist() {
return TRUE;
}
#endif
/**
* Determines if the file system for the specified file handle is local
* @param file path to check the filesystem type for, must be at most MAX_PATH
@ -764,3 +760,4 @@ BOOL IsUnpromptedElevation(BOOL& isUnpromptedElevation) {
return success;
}
#endif

Просмотреть файл

@ -2,16 +2,19 @@
* 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/. */
#ifdef MOZ_MAINTENANCE_SERVICE
BOOL StartServiceUpdate(LPCWSTR installDir);
DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR* argv);
BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds);
DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds);
DWORD IsProcessRunning(LPCWSTR filename);
BOOL DoesFallbackKeyExist();
BOOL IsLocalFile(LPCWSTR file, BOOL& isLocal);
DWORD StartServiceCommand(int argc, LPCWSTR* argv);
BOOL IsUnpromptedElevation(BOOL& isUnpromptedElevation);
#endif
DWORD WaitForProcessExit(LPCWSTR filename, DWORD maxSeconds);
DWORD IsProcessRunning(LPCWSTR filename);
BOOL GetSecureOutputDirectoryPath(LPWSTR outBuf);
BOOL GetSecureOutputFilePath(LPCWSTR patchDirPath, LPCWSTR fileExt,
LPWSTR outBuf);
@ -20,9 +23,10 @@ void RemoveSecureOutputFiles(LPCWSTR patchDirPath);
#define PATCH_DIR_PATH L"\\updates\\0"
#define SVC_NAME L"MozillaMaintenance"
#ifdef MOZ_MAINTENANCE_SERVICE
# define SVC_NAME L"MozillaMaintenance"
#define BASE_SERVICE_REG_KEY L"SOFTWARE\\Mozilla\\MaintenanceService"
# define BASE_SERVICE_REG_KEY L"SOFTWARE\\Mozilla\\MaintenanceService"
// The test only fallback key, as its name implies, is only present on machines
// that will use automated tests. Since automated tests always run from a
@ -30,5 +34,6 @@ void RemoveSecureOutputFiles(LPCWSTR patchDirPath);
// "This is a valid installation directory" check. This key also stores
// the allowed name and issuer for cert checks so that the cert check
// code can still be run unchanged.
#define TEST_ONLY_FALLBACK_KEY_PATH \
BASE_SERVICE_REG_KEY L"\\3932ecacee736d366d6436db0f55bce4"
# define TEST_ONLY_FALLBACK_KEY_PATH \
BASE_SERVICE_REG_KEY L"\\3932ecacee736d366d6436db0f55bce4"
#endif

Просмотреть файл

@ -287,7 +287,7 @@ int NS_main(int argc, NS_tchar** argv) {
}
if (!NS_tstrcmp(argv[1], NS_T("wait-for-service-stop"))) {
#ifdef XP_WIN
#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE)
const int maxWaitSeconds = NS_ttoi(argv[3]);
LPCWSTR serviceName = argv[2];
DWORD serviceState = WaitForServiceStop(serviceName, maxWaitSeconds);
@ -320,18 +320,8 @@ int NS_main(int argc, NS_tchar** argv) {
#endif
}
if (!NS_tstrcmp(argv[1], NS_T("is-process-running"))) {
#ifdef XP_WIN
LPCWSTR application = argv[2];
return (ERROR_NOT_FOUND == IsProcessRunning(application)) ? 0 : 1;
#else
// Not implemented on non-Windows platforms
return 1;
#endif
}
if (!NS_tstrcmp(argv[1], NS_T("launch-service"))) {
#ifdef XP_WIN
#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE)
DWORD ret =
LaunchServiceSoftwareUpdateCommand(argc - 2, (LPCWSTR*)argv + 2);
if (ret != ERROR_SUCCESS) {

Просмотреть файл

@ -1948,7 +1948,9 @@ void PatchIfFile::Finish(int status) {
# include "nsWindowsRestart.cpp"
# include "nsWindowsHelpers.h"
# include "uachelper.h"
# include "pathhash.h"
# ifdef MOZ_MAINTENANCE_SERVICE
# include "pathhash.h"
# endif
/**
* Launch the post update application (helper.exe). It takes in the path of the
@ -2239,7 +2241,7 @@ static bool IsUpdateStatusPendingService() {
}
#endif
#ifdef XP_WIN
#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE)
/*
* Reads the secure update status file and sets isSucceeded to true if the
* status is set to succeeded.
@ -2448,7 +2450,7 @@ static int ProcessReplaceRequest() {
return 0;
}
#ifdef XP_WIN
#if defined(XP_WIN) && defined(MOZ_MAINTENANCE_SERVICE)
static void WaitForServiceFinishThread(void* param) {
// We wait at most 10 minutes, we already waited 5 seconds previously
// before deciding to show this UI.
@ -2652,6 +2654,7 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv,
fprintf(stderr, "The post update process was not launched");
}
# ifdef MOZ_MAINTENANCE_SERVICE
// The service update will only be executed if it is already installed.
// For first time installs of the service, the install will happen from
// the PostUpdate process. We do the service update process here
@ -2662,6 +2665,7 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv,
if (!sUsingService) {
StartServiceUpdate(gInstallDirPath);
}
# endif
}
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0);
#elif XP_MACOSX
@ -3175,6 +3179,7 @@ int NS_main(int argc, NS_tchar** argv) {
return 1;
}
# ifdef MOZ_MAINTENANCE_SERVICE
// Make sure the path to the updater to use for the update is on local.
// We do this check to make sure that file locking is available for
// race condition security checks.
@ -3208,9 +3213,9 @@ int NS_main(int argc, NS_tchar** argv) {
&baseKey) == ERROR_SUCCESS) {
RegCloseKey(baseKey);
} else {
# ifdef TEST_UPDATER
# ifdef TEST_UPDATER
useService = testOnlyFallbackKeyExists;
# endif
# endif
if (!useService) {
lastFallbackError = FALLBACKKEY_NOKEY_ERROR;
}
@ -3289,6 +3294,7 @@ int NS_main(int argc, NS_tchar** argv) {
lastFallbackError = FALLBACKKEY_LAUNCH_ERROR;
}
}
# endif
// If the service can't be used when staging an update, make sure that
// the UAC prompt is not shown! In this case, just set the status to
@ -3305,6 +3311,7 @@ int NS_main(int argc, NS_tchar** argv) {
return 0;
}
# ifdef MOZ_MAINTENANCE_SERVICE
// If we started the service command, and it finished, check the secure
// update status file to make sure that it succeeded, and if it did we
// need to launch the PostUpdate process in the unelevated updater which
@ -3322,6 +3329,7 @@ int NS_main(int argc, NS_tchar** argv) {
}
}
}
# endif
// If we didn't want to use the service at all, or if an update was
// already happening, or launching the service command failed, then

Просмотреть файл

@ -784,8 +784,12 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
bool aUseServiceOnFailure,
const nsAutoString& aInstallPath)
: Runnable(aName),
mUseServiceOnFailure(aUseServiceOnFailure),
mState(State::Initializing) {
mState(State::Initializing)
# ifdef MOZ_MAINTENANCE_SERVICE
,
mUseServiceOnFailure(aUseServiceOnFailure)
# endif
{
size_t installPathSize = aInstallPath.Length() + 1;
mInstallPath = mozilla::MakeUnique<wchar_t[]>(installPathSize);
if (mInstallPath) {
@ -798,6 +802,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
}
NS_IMETHOD Run() override {
# ifdef MOZ_MAINTENANCE_SERVICE
// These constants control how often and how many times we poll the
// maintenance service to see if it has stopped. If there is no delay in
// the event queue, this works out to 8 minutes of polling.
@ -808,6 +813,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
// out to 5 seconds of polling.
const unsigned int kMaxStartAttempts = 50;
const unsigned int kStartAttemptIntervalMS = 100;
# endif
if (mState == State::Initializing) {
if (!mInstallPath) {
@ -823,13 +829,20 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
if (SUCCEEDED(permResult)) {
LOG(("Successfully fixed permissions from within Firefox\n"));
return NS_OK;
} else if (!mUseServiceOnFailure) {
}
# ifdef MOZ_MAINTENANCE_SERVICE
else if (!mUseServiceOnFailure) {
LOG(
("Error: Unable to fix permissions within Firefox and "
"maintenance service is disabled\n"));
return ReportUpdateError();
}
# else
LOG(("Error: Unable to fix permissions\n"));
return ReportUpdateError();
# endif
# ifdef MOZ_MAINTENANCE_SERVICE
SC_HANDLE serviceManager =
OpenSCManager(nullptr, nullptr,
SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
@ -867,7 +880,9 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
mState = State::WaitingToStart;
mCurrentTry = 1;
# endif
}
# ifdef MOZ_MAINTENANCE_SERVICE
if (mState == State::WaitingToStart ||
mState == State::WaitingForFinish) {
SERVICE_STATUS_PROCESS ssp;
@ -933,6 +948,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
}
return RetryInMS(kStartAttemptIntervalMS);
}
# endif
// We should not have fallen through all three state checks above
LOG(
("Error: Reached logically unreachable code when correcting update "
@ -941,10 +957,11 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
}
private:
bool mUseServiceOnFailure;
unsigned int mCurrentTry;
State mState;
mozilla::UniquePtr<wchar_t[]> mInstallPath;
# ifdef MOZ_MAINTENANCE_SERVICE
bool mUseServiceOnFailure;
unsigned int mCurrentTry;
nsAutoServiceHandle mServiceManager;
nsAutoServiceHandle mService;
DWORD mStartServiceArgCount;
@ -955,6 +972,7 @@ nsUpdateProcessor::FixUpdateDirectoryPerms(bool aUseServiceOnFailure) {
nsCOMPtr<nsIRunnable> runnable(this);
return NS_DelayedDispatchToCurrentThread(runnable.forget(), aDelayMS);
}
# endif
nsresult ReportUpdateError() {
return NS_DispatchToMainThread(NS_NewRunnableFunction(
"nsUpdateProcessor::FixUpdateDirectoryPerms::"