summaryrefslogtreecommitdiffstats
path: root/toolkit/components/maintenanceservice
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@wolfbeast.com>2019-03-06 12:30:20 +0100
committerwolfbeast <mcwerewolf@wolfbeast.com>2019-03-06 12:30:20 +0100
commite25ad543952b5afc13181aaebef9c5951fc27be0 (patch)
tree456a1359b3e5f810319edd423dd5cc5a1e22ada5 /toolkit/components/maintenanceservice
parent74533a843277c3687c749989ed1522354d1054d2 (diff)
parent5dba1ebe8498286762873fff0016f35f3e14d2d5 (diff)
downloadUXP-e25ad543952b5afc13181aaebef9c5951fc27be0.tar
UXP-e25ad543952b5afc13181aaebef9c5951fc27be0.tar.gz
UXP-e25ad543952b5afc13181aaebef9c5951fc27be0.tar.lz
UXP-e25ad543952b5afc13181aaebef9c5951fc27be0.tar.xz
UXP-e25ad543952b5afc13181aaebef9c5951fc27be0.zip
Merge branch 'master' into Basilisk-releasev2019.03.08
Diffstat (limited to 'toolkit/components/maintenanceservice')
-rw-r--r--toolkit/components/maintenanceservice/Makefile.in13
-rw-r--r--toolkit/components/maintenanceservice/bootstrapinstaller/maintenanceservice_installer.nsi275
-rw-r--r--toolkit/components/maintenanceservice/maintenanceservice.cpp391
-rw-r--r--toolkit/components/maintenanceservice/maintenanceservice.exe.manifest25
-rw-r--r--toolkit/components/maintenanceservice/maintenanceservice.h10
-rw-r--r--toolkit/components/maintenanceservice/maintenanceservice.rc86
-rw-r--r--toolkit/components/maintenanceservice/moz.build54
-rw-r--r--toolkit/components/maintenanceservice/resource.h20
-rw-r--r--toolkit/components/maintenanceservice/servicebase.cpp86
-rw-r--r--toolkit/components/maintenanceservice/servicebase.h22
-rw-r--r--toolkit/components/maintenanceservice/serviceinstall.cpp759
-rw-r--r--toolkit/components/maintenanceservice/serviceinstall.h21
-rw-r--r--toolkit/components/maintenanceservice/workmonitor.cpp758
-rw-r--r--toolkit/components/maintenanceservice/workmonitor.h5
14 files changed, 0 insertions, 2525 deletions
diff --git a/toolkit/components/maintenanceservice/Makefile.in b/toolkit/components/maintenanceservice/Makefile.in
deleted file mode 100644
index b07afbb0a..000000000
--- a/toolkit/components/maintenanceservice/Makefile.in
+++ /dev/null
@@ -1,13 +0,0 @@
-# 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/.
-
-ifndef MOZ_WINCONSOLE
-ifdef MOZ_DEBUG
-MOZ_WINCONSOLE = 1
-else
-MOZ_WINCONSOLE = 0
-endif
-endif
-
-include $(topsrcdir)/config/rules.mk
diff --git a/toolkit/components/maintenanceservice/bootstrapinstaller/maintenanceservice_installer.nsi b/toolkit/components/maintenanceservice/bootstrapinstaller/maintenanceservice_installer.nsi
deleted file mode 100644
index d4d21e377..000000000
--- a/toolkit/components/maintenanceservice/bootstrapinstaller/maintenanceservice_installer.nsi
+++ /dev/null
@@ -1,275 +0,0 @@
-# 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/.
-
-; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
-!verbose 3
-
-; 7-Zip provides better compression than the lzma from NSIS so we add the files
-; uncompressed and use 7-Zip to create a SFX archive of it
-SetDatablockOptimize on
-SetCompress off
-CRCCheck on
-
-RequestExecutionLevel admin
-
-; The commands inside this ifdef require NSIS 3.0a2 or greater so the ifdef can
-; be removed after we require NSIS 3.0a2 or greater.
-!ifdef NSIS_PACKEDVERSION
- Unicode true
- ManifestSupportedOS all
- ManifestDPIAware true
-!endif
-
-!addplugindir ./
-
-; Variables
-Var TempMaintServiceName
-Var BrandFullNameDA
-Var BrandFullName
-
-; Other included files may depend upon these includes!
-; The following includes are provided by NSIS.
-!include FileFunc.nsh
-!include LogicLib.nsh
-!include MUI.nsh
-!include WinMessages.nsh
-!include WinVer.nsh
-!include WordFunc.nsh
-
-!insertmacro GetOptions
-!insertmacro GetParameters
-!insertmacro GetSize
-
-; The test slaves use this fallback key to run tests.
-; And anyone that wants to run tests themselves should already have
-; this installed.
-!define FallbackKey \
- "SOFTWARE\Mozilla\MaintenanceService\3932ecacee736d366d6436db0f55bce4"
-
-!define CompanyName "Mozilla Corporation"
-!define BrandFullNameInternal ""
-
-; The following includes are custom.
-!include defines.nsi
-; We keep defines.nsi defined so that we get other things like
-; the version number, but we redefine BrandFullName
-!define MaintFullName "Mozilla Maintenance Service"
-!undef BrandFullName
-!define BrandFullName "${MaintFullName}"
-
-!include common.nsh
-!include locales.nsi
-
-VIAddVersionKey "FileDescription" "${MaintFullName} Installer"
-VIAddVersionKey "OriginalFilename" "maintenanceservice_installer.exe"
-
-Name "${MaintFullName}"
-OutFile "maintenanceservice_installer.exe"
-
-; Get installation folder from registry if available
-InstallDirRegKey HKLM "Software\Mozilla\MaintenanceService" ""
-
-SetOverwrite on
-
-!define MaintUninstallKey \
- "Software\Microsoft\Windows\CurrentVersion\Uninstall\MozillaMaintenanceService"
-
-; Always install into the 32-bit location even if we have a 64-bit build.
-; This is because we use only 1 service for all Firefox channels.
-; Allow either x86 and x64 builds to exist at this location, depending on
-; what is the latest build.
-InstallDir "$PROGRAMFILES32\${MaintFullName}\"
-ShowUnInstDetails nevershow
-
-################################################################################
-# Modern User Interface - MUI
-
-!define MUI_ICON setup.ico
-!define MUI_UNICON setup.ico
-!define MUI_WELCOMEPAGE_TITLE_3LINES
-!define MUI_UNWELCOMEFINISHPAGE_BITMAP wizWatermark.bmp
-
-;Interface Settings
-!define MUI_ABORTWARNING
-
-; Uninstaller Pages
-!insertmacro MUI_UNPAGE_CONFIRM
-!insertmacro MUI_UNPAGE_INSTFILES
-
-################################################################################
-# Language
-
-!insertmacro MOZ_MUI_LANGUAGE 'baseLocale'
-!verbose push
-!verbose 3
-!include "overrideLocale.nsh"
-!include "customLocale.nsh"
-!verbose pop
-
-; Set this after the locale files to override it if it is in the locale
-; using " " for BrandingText will hide the "Nullsoft Install System..." branding
-BrandingText " "
-
-Function .onInit
- ; Remove the current exe directory from the search order.
- ; This only effects LoadLibrary calls and not implicitly loaded DLLs.
- System::Call 'kernel32::SetDllDirectoryW(w "")'
-
- SetSilent silent
- ${Unless} ${AtLeastWin7}
- Abort
- ${EndUnless}
-FunctionEnd
-
-Function un.onInit
- ; Remove the current exe directory from the search order.
- ; This only effects LoadLibrary calls and not implicitly loaded DLLs.
- System::Call 'kernel32::SetDllDirectoryW(w "")'
-
-; The commands inside this ifndef are needed prior to NSIS 3.0a2 and can be
-; removed after we require NSIS 3.0a2 or greater.
-!ifndef NSIS_PACKEDVERSION
- ${If} ${AtLeastWinVista}
- System::Call 'user32::SetProcessDPIAware()'
- ${EndIf}
-!endif
-
- StrCpy $BrandFullNameDA "${MaintFullName}"
- StrCpy $BrandFullName "${MaintFullName}"
-FunctionEnd
-
-Section "MaintenanceService"
- AllowSkipFiles off
-
- CreateDirectory $INSTDIR
- SetOutPath $INSTDIR
-
- ; If the service already exists, then it will be stopped when upgrading it
- ; via the maintenanceservice_tmp.exe command executed below.
- ; The maintenanceservice_tmp.exe command will rename the file to
- ; maintenanceservice.exe if maintenanceservice_tmp.exe is newer.
- ; If the service does not exist yet, we install it and drop the file on
- ; disk as maintenanceservice.exe directly.
- StrCpy $TempMaintServiceName "maintenanceservice.exe"
- IfFileExists "$INSTDIR\maintenanceservice.exe" 0 skipAlreadyExists
- StrCpy $TempMaintServiceName "maintenanceservice_tmp.exe"
- skipAlreadyExists:
-
- ; We always write out a copy and then decide whether to install it or
- ; not via calling its 'install' cmdline which works by version comparison.
- CopyFiles "$EXEDIR\maintenanceservice.exe" "$INSTDIR\$TempMaintServiceName"
-
- ; The updater.ini file is only used when performing an install or upgrade,
- ; and only if that install or upgrade is successful. If an old updater.ini
- ; happened to be copied into the maintenance service installation directory
- ; but the service was not newer, the updater.ini file would be unused.
- ; It is used to fill the description of the service on success.
- CopyFiles "$EXEDIR\updater.ini" "$INSTDIR\updater.ini"
-
- ; Install the application maintenance service.
- ; If a service already exists, the command line parameter will stop the
- ; service and only install itself if it is newer than the already installed
- ; service. If successful it will remove the old maintenanceservice.exe
- ; and replace it with maintenanceservice_tmp.exe.
- ClearErrors
- ;${GetParameters} $0
- ;${GetOptions} "$0" "/Upgrade" $0
- ;${If} ${Errors}
- ExecWait '"$INSTDIR\$TempMaintServiceName" forceinstall'
- ;${Else}
- ; The upgrade cmdline is the same as install except
- ; It will fail if the service isn't already installed.
- ; ExecWait '"$INSTDIR\$TempMaintServiceName" upgrade'
- ;${EndIf}
-
- WriteUninstaller "$INSTDIR\Uninstall.exe"
- WriteRegStr HKLM "${MaintUninstallKey}" "DisplayName" "${MaintFullName}"
- WriteRegStr HKLM "${MaintUninstallKey}" "UninstallString" \
- '"$INSTDIR\uninstall.exe"'
- WriteRegStr HKLM "${MaintUninstallKey}" "DisplayIcon" \
- "$INSTDIR\Uninstall.exe,0"
- WriteRegStr HKLM "${MaintUninstallKey}" "DisplayVersion" "${AppVersion}"
- WriteRegStr HKLM "${MaintUninstallKey}" "Publisher" "Mozilla"
- WriteRegStr HKLM "${MaintUninstallKey}" "Comments" "${BrandFullName}"
- WriteRegDWORD HKLM "${MaintUninstallKey}" "NoModify" 1
- ${GetSize} "$INSTDIR" "/S=0K" $R2 $R3 $R4
- WriteRegDWORD HKLM "${MaintUninstallKey}" "EstimatedSize" $R2
-
- ; Write out that a maintenance service was attempted.
- ; We do this because on upgrades we will check this value and we only
- ; want to install once on the first upgrade to maintenance service.
- ; Also write out that we are currently installed, preferences will check
- ; this value to determine if we should show the service update pref.
- ; Since the Maintenance service can be installed either x86 or x64,
- ; always use the 64-bit registry for checking if an attempt was made.
- ${If} ${RunningX64}
- SetRegView 64
- ${EndIf}
- WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Attempted" 1
- WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Installed" 1
- DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "FFPrefetchDisabled"
-
- ; Included here for debug purposes only.
- ; These keys are used to bypass the installation dir is a valid installation
- ; check from the service so that tests can be run.
- WriteRegStr HKLM "${FallbackKey}\0" "name" "Mozilla Corporation"
- WriteRegStr HKLM "${FallbackKey}\0" "issuer" "DigiCert SHA2 Assured ID Code Signing CA"
- WriteRegStr HKLM "${FallbackKey}\1" "name" "Mozilla Fake SPC"
- WriteRegStr HKLM "${FallbackKey}\1" "issuer" "Mozilla Fake CA"
- ${If} ${RunningX64}
- SetRegView lastused
- ${EndIf}
-SectionEnd
-
-; By renaming before deleting we improve things slightly in case
-; there is a file in use error. In this case a new install can happen.
-Function un.RenameDelete
- Pop $9
- ; If the .moz-delete file already exists previously, delete it
- ; If it doesn't exist, the call is ignored.
- ; We don't need to pass /REBOOTOK here since it was already marked that way
- ; if it exists.
- Delete "$9.moz-delete"
- Rename "$9" "$9.moz-delete"
- ${If} ${Errors}
- Delete /REBOOTOK "$9"
- ${Else}
- Delete /REBOOTOK "$9.moz-delete"
- ${EndIf}
- ClearErrors
-FunctionEnd
-
-Section "Uninstall"
- ; Delete the service so that no updates will be attempted
- ExecWait '"$INSTDIR\maintenanceservice.exe" uninstall'
-
- Push "$INSTDIR\updater.ini"
- Call un.RenameDelete
- Push "$INSTDIR\maintenanceservice.exe"
- Call un.RenameDelete
- Push "$INSTDIR\maintenanceservice_tmp.exe"
- Call un.RenameDelete
- Push "$INSTDIR\maintenanceservice.old"
- Call un.RenameDelete
- Push "$INSTDIR\Uninstall.exe"
- Call un.RenameDelete
- Push "$INSTDIR\update\updater.ini"
- Call un.RenameDelete
- Push "$INSTDIR\update\updater.exe"
- Call un.RenameDelete
- RMDir /REBOOTOK "$INSTDIR\update"
- RMDir /REBOOTOK "$INSTDIR"
- DeleteRegKey HKLM "${MaintUninstallKey}"
-
- ${If} ${RunningX64}
- SetRegView 64
- ${EndIf}
- DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "Installed"
- DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "FFPrefetchDisabled"
- DeleteRegKey HKLM "${FallbackKey}\"
- ${If} ${RunningX64}
- SetRegView lastused
- ${EndIf}
-SectionEnd
-
diff --git a/toolkit/components/maintenanceservice/maintenanceservice.cpp b/toolkit/components/maintenanceservice/maintenanceservice.cpp
deleted file mode 100644
index f1275b095..000000000
--- a/toolkit/components/maintenanceservice/maintenanceservice.cpp
+++ /dev/null
@@ -1,391 +0,0 @@
-/* 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/. */
-
-#include <windows.h>
-#include <shlwapi.h>
-#include <stdio.h>
-#include <wchar.h>
-#include <shlobj.h>
-
-#include "serviceinstall.h"
-#include "maintenanceservice.h"
-#include "servicebase.h"
-#include "workmonitor.h"
-#include "uachelper.h"
-#include "updatehelper.h"
-#include "registrycertificates.h"
-
-// Link w/ subsystem window so we don't get a console when executing
-// this binary through the installer.
-#pragma comment(linker, "/SUBSYSTEM:windows")
-
-SERVICE_STATUS gSvcStatus = { 0 };
-SERVICE_STATUS_HANDLE gSvcStatusHandle = nullptr;
-HANDLE gWorkDoneEvent = nullptr;
-HANDLE gThread = nullptr;
-bool gServiceControlStopping = false;
-
-// logs are pretty small, about 20 lines, so 10 seems reasonable.
-#define LOGS_TO_KEEP 10
-
-BOOL GetLogDirectoryPath(WCHAR *path);
-
-int
-wmain(int argc, WCHAR **argv)
-{
- // If command-line parameter is "install", install the service
- // or upgrade if already installed
- // If command line parameter is "forceinstall", install the service
- // even if it is older than what is already installed.
- // If command-line parameter is "upgrade", upgrade the service
- // but do not install it if it is not already installed.
- // If command line parameter is "uninstall", uninstall the service.
- // Otherwise, the service is probably being started by the SCM.
- bool forceInstall = !lstrcmpi(argv[1], L"forceinstall");
- if (!lstrcmpi(argv[1], L"install") || forceInstall) {
- WCHAR updatePath[MAX_PATH + 1];
- if (GetLogDirectoryPath(updatePath)) {
- LogInit(updatePath, L"maintenanceservice-install.log");
- }
-
- SvcInstallAction action = InstallSvc;
- if (forceInstall) {
- action = ForceInstallSvc;
- LOG(("Installing service with force specified..."));
- } else {
- LOG(("Installing service..."));
- }
-
- bool ret = SvcInstall(action);
- if (!ret) {
- LOG_WARN(("Could not install service. (%d)", GetLastError()));
- LogFinish();
- return 1;
- }
-
- LOG(("The service was installed successfully"));
- LogFinish();
- return 0;
- }
-
- if (!lstrcmpi(argv[1], L"upgrade")) {
- WCHAR updatePath[MAX_PATH + 1];
- if (GetLogDirectoryPath(updatePath)) {
- LogInit(updatePath, L"maintenanceservice-install.log");
- }
-
- LOG(("Upgrading service if installed..."));
- if (!SvcInstall(UpgradeSvc)) {
- LOG_WARN(("Could not upgrade service. (%d)", GetLastError()));
- LogFinish();
- return 1;
- }
-
- LOG(("The service was upgraded successfully"));
- LogFinish();
- return 0;
- }
-
- if (!lstrcmpi(argv[1], L"uninstall")) {
- WCHAR updatePath[MAX_PATH + 1];
- if (GetLogDirectoryPath(updatePath)) {
- LogInit(updatePath, L"maintenanceservice-uninstall.log");
- }
- LOG(("Uninstalling service..."));
- if (!SvcUninstall()) {
- LOG_WARN(("Could not uninstall service. (%d)", GetLastError()));
- LogFinish();
- return 1;
- }
- LOG(("The service was uninstalled successfully"));
- LogFinish();
- return 0;
- }
-
- if (!lstrcmpi(argv[1], L"check-cert") && argc > 2) {
- return DoesBinaryMatchAllowedCertificates(argv[2], argv[3], FALSE) ? 0 : 1;
- }
-
- SERVICE_TABLE_ENTRYW DispatchTable[] = {
- { SVC_NAME, (LPSERVICE_MAIN_FUNCTIONW) SvcMain },
- { nullptr, nullptr }
- };
-
- // This call returns when the service has stopped.
- // The process should simply terminate when the call returns.
- if (!StartServiceCtrlDispatcherW(DispatchTable)) {
- LOG_WARN(("StartServiceCtrlDispatcher failed. (%d)", GetLastError()));
- }
-
- return 0;
-}
-
-/**
- * Obtains the base path where logs should be stored
- *
- * @param path The out buffer for the backup log path of size MAX_PATH + 1
- * @return TRUE if successful.
- */
-BOOL
-GetLogDirectoryPath(WCHAR *path)
-{
- if (!GetModuleFileNameW(nullptr, path, MAX_PATH)) {
- return FALSE;
- }
-
- if (!PathRemoveFileSpecW(path)) {
- return FALSE;
- }
-
- if (!PathAppendSafe(path, L"logs")) {
- return FALSE;
- }
- CreateDirectoryW(path, nullptr);
- return TRUE;
-}
-
-/**
- * Calculated a backup path based on the log number.
- *
- * @param path The out buffer to store the log path of size MAX_PATH + 1
- * @param basePath The base directory where the calculated path should go
- * @param logNumber The log number, 0 == updater.log
- * @return TRUE if successful.
- */
-BOOL
-GetBackupLogPath(LPWSTR path, LPCWSTR basePath, int logNumber)
-{
- WCHAR logName[64] = { L'\0' };
- wcsncpy(path, basePath, sizeof(logName) / sizeof(logName[0]) - 1);
- if (logNumber <= 0) {
- swprintf(logName, sizeof(logName) / sizeof(logName[0]),
- L"maintenanceservice.log");
- } else {
- swprintf(logName, sizeof(logName) / sizeof(logName[0]),
- L"maintenanceservice-%d.log", logNumber);
- }
- return PathAppendSafe(path, logName);
-}
-
-/**
- * Moves the old log files out of the way before a new one is written.
- * If you for example keep 3 logs, then this function will do:
- * updater2.log -> updater3.log
- * updater1.log -> updater2.log
- * updater.log -> updater1.log
- * Which clears room for a new updater.log in the basePath directory
- *
- * @param basePath The base directory path where log files are stored
- * @param numLogsToKeep The number of logs to keep
- */
-void
-BackupOldLogs(LPCWSTR basePath, int numLogsToKeep)
-{
- WCHAR oldPath[MAX_PATH + 1];
- WCHAR newPath[MAX_PATH + 1];
- for (int i = numLogsToKeep; i >= 1; i--) {
- if (!GetBackupLogPath(oldPath, basePath, i -1)) {
- continue;
- }
-
- if (!GetBackupLogPath(newPath, basePath, i)) {
- continue;
- }
-
- if (!MoveFileExW(oldPath, newPath, MOVEFILE_REPLACE_EXISTING)) {
- continue;
- }
- }
-}
-
-/**
- * Ensures the service is shutdown once all work is complete.
- * There is an issue on XP SP2 and below where the service can hang
- * in a stop pending state even though the SCM is notified of a stopped
- * state. Control *should* be returned to StartServiceCtrlDispatcher from the
- * call to SetServiceStatus on a stopped state in the wmain thread.
- * Sometimes this is not the case though. This thread will terminate the process
- * if it has been 5 seconds after all work is done and the process is still not
- * terminated. This thread is only started once a stopped state was sent to the
- * SCM. The stop pending hang can be reproduced intermittently even if you set
- * a stopped state dirctly and never set a stop pending state. It is safe to
- * forcefully terminate the process ourselves since all work is done once we
- * start this thread.
-*/
-DWORD WINAPI
-EnsureProcessTerminatedThread(LPVOID)
-{
- Sleep(5000);
- exit(0);
- return 0;
-}
-
-void
-StartTerminationThread()
-{
- // If the process does not self terminate like it should, this thread
- // will terminate the process after 5 seconds.
- HANDLE thread = CreateThread(nullptr, 0, EnsureProcessTerminatedThread,
- nullptr, 0, nullptr);
- if (thread) {
- CloseHandle(thread);
- }
-}
-
-/**
- * Main entry point when running as a service.
- */
-void WINAPI
-SvcMain(DWORD argc, LPWSTR *argv)
-{
- // Setup logging, and backup the old logs
- WCHAR updatePath[MAX_PATH + 1];
- if (GetLogDirectoryPath(updatePath)) {
- BackupOldLogs(updatePath, LOGS_TO_KEEP);
- LogInit(updatePath, L"maintenanceservice.log");
- }
-
- // Disable every privilege we don't need. Processes started using
- // CreateProcess will use the same token as this process.
- UACHelper::DisablePrivileges(nullptr);
-
- // Register the handler function for the service
- gSvcStatusHandle = RegisterServiceCtrlHandlerW(SVC_NAME, SvcCtrlHandler);
- if (!gSvcStatusHandle) {
- LOG_WARN(("RegisterServiceCtrlHandler failed. (%d)", GetLastError()));
- ExecuteServiceCommand(argc, argv);
- LogFinish();
- exit(1);
- }
-
- // These values will be re-used later in calls involving gSvcStatus
- gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- gSvcStatus.dwServiceSpecificExitCode = 0;
-
- // Report initial status to the SCM
- ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
-
- // This event will be used to tell the SvcCtrlHandler when the work is
- // done for when a stop comamnd is manually issued.
- gWorkDoneEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
- if (!gWorkDoneEvent) {
- ReportSvcStatus(SERVICE_STOPPED, 1, 0);
- StartTerminationThread();
- return;
- }
-
- // Initialization complete and we're about to start working on
- // the actual command. Report the service state as running to the SCM.
- ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
-
- // The service command was executed, stop logging and set an event
- // to indicate the work is done in case someone is waiting on a
- // service stop operation.
- ExecuteServiceCommand(argc, argv);
- LogFinish();
-
- SetEvent(gWorkDoneEvent);
-
- // If we aren't already in a stopping state then tell the SCM we're stopped
- // now. If we are already in a stopping state then the SERVICE_STOPPED state
- // will be set by the SvcCtrlHandler.
- if (!gServiceControlStopping) {
- ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
- StartTerminationThread();
- }
-}
-
-/**
- * Sets the current service status and reports it to the SCM.
- *
- * @param currentState The current state (see SERVICE_STATUS)
- * @param exitCode The system error code
- * @param waitHint Estimated time for pending operation in milliseconds
- */
-void
-ReportSvcStatus(DWORD currentState,
- DWORD exitCode,
- DWORD waitHint)
-{
- static DWORD dwCheckPoint = 1;
-
- gSvcStatus.dwCurrentState = currentState;
- gSvcStatus.dwWin32ExitCode = exitCode;
- gSvcStatus.dwWaitHint = waitHint;
-
- if (SERVICE_START_PENDING == currentState ||
- SERVICE_STOP_PENDING == currentState) {
- gSvcStatus.dwControlsAccepted = 0;
- } else {
- gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
- SERVICE_ACCEPT_SHUTDOWN;
- }
-
- if ((SERVICE_RUNNING == currentState) ||
- (SERVICE_STOPPED == currentState)) {
- gSvcStatus.dwCheckPoint = 0;
- } else {
- gSvcStatus.dwCheckPoint = dwCheckPoint++;
- }
-
- // Report the status of the service to the SCM.
- SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
-}
-
-/**
- * Since the SvcCtrlHandler should only spend at most 30 seconds before
- * returning, this function does the service stop work for the SvcCtrlHandler.
-*/
-DWORD WINAPI
-StopServiceAndWaitForCommandThread(LPVOID)
-{
- do {
- ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 1000);
- } while(WaitForSingleObject(gWorkDoneEvent, 100) == WAIT_TIMEOUT);
- CloseHandle(gWorkDoneEvent);
- gWorkDoneEvent = nullptr;
- ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
- StartTerminationThread();
- return 0;
-}
-
-/**
- * Called by SCM whenever a control code is sent to the service
- * using the ControlService function.
- */
-void WINAPI
-SvcCtrlHandler(DWORD dwCtrl)
-{
- // After a SERVICE_CONTROL_STOP there should be no more commands sent to
- // the SvcCtrlHandler.
- if (gServiceControlStopping) {
- return;
- }
-
- // Handle the requested control code.
- switch(dwCtrl) {
- case SERVICE_CONTROL_SHUTDOWN:
- case SERVICE_CONTROL_STOP: {
- gServiceControlStopping = true;
- ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 1000);
-
- // The SvcCtrlHandler thread should not spend more than 30 seconds in
- // shutdown so we spawn a new thread for stopping the service
- HANDLE thread = CreateThread(nullptr, 0,
- StopServiceAndWaitForCommandThread,
- nullptr, 0, nullptr);
- if (thread) {
- CloseHandle(thread);
- } else {
- // Couldn't start the thread so just call the stop ourselves.
- // If it happens to take longer than 30 seconds the caller will
- // get an error.
- StopServiceAndWaitForCommandThread(nullptr);
- }
- }
- break;
- default:
- break;
- }
-}
diff --git a/toolkit/components/maintenanceservice/maintenanceservice.exe.manifest b/toolkit/components/maintenanceservice/maintenanceservice.exe.manifest
deleted file mode 100644
index e6bfba8ca..000000000
--- a/toolkit/components/maintenanceservice/maintenanceservice.exe.manifest
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
-<assemblyIdentity
- version="1.0.0.0"
- processorArchitecture="*"
- name="MaintenanceService"
- type="win32"
-/>
-<description>MaintenanceService</description>
-<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
- <ms_asmv3:security>
- <ms_asmv3:requestedPrivileges>
- <ms_asmv3:requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
- </ms_asmv3:requestedPrivileges>
- </ms_asmv3:security>
-</ms_asmv3:trustInfo>
- <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
- <application>
- <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
- <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
- <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
- <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
- </application>
- </compatibility>
-</assembly>
diff --git a/toolkit/components/maintenanceservice/maintenanceservice.h b/toolkit/components/maintenanceservice/maintenanceservice.h
deleted file mode 100644
index 9e02914a0..000000000
--- a/toolkit/components/maintenanceservice/maintenanceservice.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* 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/. */
-
-void WINAPI SvcMain(DWORD dwArgc, LPWSTR *lpszArgv);
-void SvcInit(DWORD dwArgc, LPWSTR *lpszArgv);
-void WINAPI SvcCtrlHandler(DWORD dwCtrl);
-void ReportSvcStatus(DWORD dwCurrentState,
- DWORD dwWin32ExitCode,
- DWORD dwWaitHint);
diff --git a/toolkit/components/maintenanceservice/maintenanceservice.rc b/toolkit/components/maintenanceservice/maintenanceservice.rc
deleted file mode 100644
index ddd3e942b..000000000
--- a/toolkit/components/maintenanceservice/maintenanceservice.rc
+++ /dev/null
@@ -1,86 +0,0 @@
-/* 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/. */
-
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "winresrc.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// RT_MANIFEST
-//
-
-1 RT_MANIFEST "maintenanceservice.exe.manifest"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// DESIGNINFO
-//
-
-#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO
-BEGIN
-END
-#endif // APSTUDIO_INVOKED
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""winresrc.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/toolkit/components/maintenanceservice/moz.build b/toolkit/components/maintenanceservice/moz.build
deleted file mode 100644
index 2c54c8c76..000000000
--- a/toolkit/components/maintenanceservice/moz.build
+++ /dev/null
@@ -1,54 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-Program('maintenanceservice')
-
-SOURCES += [
- 'maintenanceservice.cpp',
- 'servicebase.cpp',
- 'serviceinstall.cpp',
- 'workmonitor.cpp',
-]
-
-if CONFIG['OS_ARCH'] == 'WINNT':
- USE_LIBS += [
- 'updatecommon-standalone',
- ]
-else:
- USE_LIBS += [
- 'updatecommon',
- ]
-
-# For debugging purposes only
-#DEFINES['DISABLE_UPDATER_AUTHENTICODE_CHECK'] = True
-
-DEFINES['UNICODE'] = True
-DEFINES['_UNICODE'] = True
-DEFINES['NS_NO_XPCOM'] = True
-
-# Pick up nsWindowsRestart.cpp
-LOCAL_INCLUDES += [
- '/toolkit/mozapps/update/common',
- '/toolkit/xre',
-]
-
-USE_STATIC_LIBS = True
-
-if CONFIG['_MSC_VER']:
- WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
-
-RCINCLUDE = 'maintenanceservice.rc'
-
-DISABLE_STL_WRAPPING = True
-
-OS_LIBS += [
- 'comctl32',
- 'ws2_32',
- 'shell32',
-]
-
-with Files('**'):
- BUG_COMPONENT = ('Toolkit', 'Application Update')
diff --git a/toolkit/components/maintenanceservice/resource.h b/toolkit/components/maintenanceservice/resource.h
deleted file mode 100644
index 45619457c..000000000
--- a/toolkit/components/maintenanceservice/resource.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 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/. */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by updater.rc
-//
-#define IDI_DIALOG 1003
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 102
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1003
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/toolkit/components/maintenanceservice/servicebase.cpp b/toolkit/components/maintenanceservice/servicebase.cpp
deleted file mode 100644
index a858c4537..000000000
--- a/toolkit/components/maintenanceservice/servicebase.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/* 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/. */
-
-#include "servicebase.h"
-#include "nsWindowsHelpers.h"
-
-// Shared code between applications and updater.exe
-#include "nsWindowsRestart.cpp"
-
-/**
- * Verifies if 2 files are byte for byte equivalent.
- *
- * @param file1Path The first file to verify.
- * @param file2Path The second file to verify.
- * @param sameContent Out parameter, TRUE if the files are equal
- * @return TRUE If there was no error checking the files.
- */
-BOOL
-VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent)
-{
- sameContent = FALSE;
- nsAutoHandle file1(CreateFileW(file1Path, GENERIC_READ, FILE_SHARE_READ,
- nullptr, OPEN_EXISTING, 0, nullptr));
- if (INVALID_HANDLE_VALUE == file1) {
- return FALSE;
- }
- nsAutoHandle file2(CreateFileW(file2Path, GENERIC_READ, FILE_SHARE_READ,
- nullptr, OPEN_EXISTING, 0, nullptr));
- if (INVALID_HANDLE_VALUE == file2) {
- return FALSE;
- }
-
- DWORD fileSize1 = GetFileSize(file1, nullptr);
- DWORD fileSize2 = GetFileSize(file2, nullptr);
- if (INVALID_FILE_SIZE == fileSize1 || INVALID_FILE_SIZE == fileSize2) {
- return FALSE;
- }
-
- if (fileSize1 != fileSize2) {
- // sameContent is already set to FALSE
- return TRUE;
- }
-
- char buf1[COMPARE_BLOCKSIZE];
- char buf2[COMPARE_BLOCKSIZE];
- DWORD numBlocks = fileSize1 / COMPARE_BLOCKSIZE;
- DWORD leftOver = fileSize1 % COMPARE_BLOCKSIZE;
- DWORD readAmount;
- for (DWORD i = 0; i < numBlocks; i++) {
- if (!ReadFile(file1, buf1, COMPARE_BLOCKSIZE, &readAmount, nullptr) ||
- readAmount != COMPARE_BLOCKSIZE) {
- return FALSE;
- }
-
- if (!ReadFile(file2, buf2, COMPARE_BLOCKSIZE, &readAmount, nullptr) ||
- readAmount != COMPARE_BLOCKSIZE) {
- return FALSE;
- }
-
- if (memcmp(buf1, buf2, COMPARE_BLOCKSIZE)) {
- // sameContent is already set to FALSE
- return TRUE;
- }
- }
-
- if (leftOver) {
- if (!ReadFile(file1, buf1, leftOver, &readAmount, nullptr) ||
- readAmount != leftOver) {
- return FALSE;
- }
-
- if (!ReadFile(file2, buf2, leftOver, &readAmount, nullptr) ||
- readAmount != leftOver) {
- return FALSE;
- }
-
- if (memcmp(buf1, buf2, leftOver)) {
- // sameContent is already set to FALSE
- return TRUE;
- }
- }
-
- sameContent = TRUE;
- return TRUE;
-}
diff --git a/toolkit/components/maintenanceservice/servicebase.h b/toolkit/components/maintenanceservice/servicebase.h
deleted file mode 100644
index 447981489..000000000
--- a/toolkit/components/maintenanceservice/servicebase.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* 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/. */
-
-#include <windows.h>
-#include "updatecommon.h"
-
-BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra);
-BOOL VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent);
-
-// 32KiB for comparing files at a time seems reasonable.
-// The bigger the better for speed, but this will be used
-// on the stack so I don't want it to be too big.
-#define COMPARE_BLOCKSIZE 32768
-
-// The following string resource value is used to uniquely identify the signed
-// Mozilla application as an updater. Before the maintenance service will
-// execute the updater it must have this updater identity string in its string
-// table. No other signed Mozilla product will have this string table value.
-#define UPDATER_IDENTITY_STRING \
- "moz-updater.exe-4cdccec4-5ee0-4a06-9817-4cd899a9db49"
-#define IDS_UPDATER_IDENTITY 1006
diff --git a/toolkit/components/maintenanceservice/serviceinstall.cpp b/toolkit/components/maintenanceservice/serviceinstall.cpp
deleted file mode 100644
index 3b9522d47..000000000
--- a/toolkit/components/maintenanceservice/serviceinstall.cpp
+++ /dev/null
@@ -1,759 +0,0 @@
-/* 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/. */
-
-#include <windows.h>
-#include <aclapi.h>
-#include <stdlib.h>
-#include <shlwapi.h>
-
-// Used for DNLEN and UNLEN
-#include <lm.h>
-
-#include <nsWindowsHelpers.h>
-#include "mozilla/UniquePtr.h"
-
-#include "serviceinstall.h"
-#include "servicebase.h"
-#include "updatehelper.h"
-#include "shellapi.h"
-#include "readstrings.h"
-#include "errors.h"
-
-#pragma comment(lib, "version.lib")
-
-// This uninstall key is defined originally in maintenanceservice_installer.nsi
-#define MAINT_UNINSTALL_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MozillaMaintenanceService"
-
-static BOOL
-UpdateUninstallerVersionString(LPWSTR versionString)
-{
- HKEY uninstallKey;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- MAINT_UNINSTALL_KEY, 0,
- KEY_WRITE | KEY_WOW64_32KEY,
- &uninstallKey) != ERROR_SUCCESS) {
- return FALSE;
- }
-
- LONG rv = RegSetValueExW(uninstallKey, L"DisplayVersion", 0, REG_SZ,
- reinterpret_cast<const BYTE *>(versionString),
- (wcslen(versionString) + 1) * sizeof(WCHAR));
- RegCloseKey(uninstallKey);
- return rv == ERROR_SUCCESS;
-}
-
-/**
- * A wrapper function to read strings for the maintenance service.
- *
- * @param path The path of the ini file to read from
- * @param results The maintenance service strings that were read
- * @return OK on success
-*/
-static int
-ReadMaintenanceServiceStrings(LPCWSTR path,
- MaintenanceServiceStringTable *results)
-{
- // Read in the maintenance service description string if specified.
- const unsigned int kNumStrings = 1;
- const char *kServiceKeys = "MozillaMaintenanceDescription\0";
- char serviceStrings[kNumStrings][MAX_TEXT_LEN];
- int result = ReadStrings(path, kServiceKeys,
- kNumStrings, serviceStrings);
- if (result != OK) {
- serviceStrings[0][0] = '\0';
- }
- strncpy(results->serviceDescription,
- serviceStrings[0], MAX_TEXT_LEN - 1);
- results->serviceDescription[MAX_TEXT_LEN - 1] = '\0';
- return result;
-}
-
-/**
- * Obtains the version number from the specified PE file's version information
- * Version Format: A.B.C.D (Example 10.0.0.300)
- *
- * @param path The path of the file to check the version on
- * @param A The first part of the version number
- * @param B The second part of the version number
- * @param C The third part of the version number
- * @param D The fourth part of the version number
- * @return TRUE if successful
- */
-static BOOL
-GetVersionNumberFromPath(LPWSTR path, DWORD &A, DWORD &B,
- DWORD &C, DWORD &D)
-{
- DWORD fileVersionInfoSize = GetFileVersionInfoSizeW(path, 0);
- mozilla::UniquePtr<char[]> fileVersionInfo(new char[fileVersionInfoSize]);
- if (!GetFileVersionInfoW(path, 0, fileVersionInfoSize,
- fileVersionInfo.get())) {
- LOG_WARN(("Could not obtain file info of old service. (%d)",
- GetLastError()));
- return FALSE;
- }
-
- VS_FIXEDFILEINFO *fixedFileInfo =
- reinterpret_cast<VS_FIXEDFILEINFO *>(fileVersionInfo.get());
- UINT size;
- if (!VerQueryValueW(fileVersionInfo.get(), L"\\",
- reinterpret_cast<LPVOID*>(&fixedFileInfo), &size)) {
- LOG_WARN(("Could not query file version info of old service. (%d)",
- GetLastError()));
- return FALSE;
- }
-
- A = HIWORD(fixedFileInfo->dwFileVersionMS);
- B = LOWORD(fixedFileInfo->dwFileVersionMS);
- C = HIWORD(fixedFileInfo->dwFileVersionLS);
- D = LOWORD(fixedFileInfo->dwFileVersionLS);
- return TRUE;
-}
-
-/**
- * Updates the service description with what is stored in updater.ini
- * at the same path as the currently executing module binary.
- *
- * @param serviceHandle A handle to an opened service with
- * SERVICE_CHANGE_CONFIG access right
- * @param TRUE on succcess.
-*/
-BOOL
-UpdateServiceDescription(SC_HANDLE serviceHandle)
-{
- WCHAR updaterINIPath[MAX_PATH + 1];
- if (!GetModuleFileNameW(nullptr, updaterINIPath,
- sizeof(updaterINIPath) /
- sizeof(updaterINIPath[0]))) {
- LOG_WARN(("Could not obtain module filename when attempting to "
- "modify service description. (%d)", GetLastError()));
- return FALSE;
- }
-
- if (!PathRemoveFileSpecW(updaterINIPath)) {
- LOG_WARN(("Could not remove file spec when attempting to "
- "modify service description. (%d)", GetLastError()));
- return FALSE;
- }
-
- if (!PathAppendSafe(updaterINIPath, L"updater.ini")) {
- LOG_WARN(("Could not append updater.ini filename when attempting to "
- "modify service description. (%d)", GetLastError()));
- return FALSE;
- }
-
- if (GetFileAttributesW(updaterINIPath) == INVALID_FILE_ATTRIBUTES) {
- LOG_WARN(("updater.ini file does not exist, will not modify "
- "service description. (%d)", GetLastError()));
- return FALSE;
- }
-
- MaintenanceServiceStringTable serviceStrings;
- int rv = ReadMaintenanceServiceStrings(updaterINIPath, &serviceStrings);
- if (rv != OK || !strlen(serviceStrings.serviceDescription)) {
- LOG_WARN(("updater.ini file does not contain a maintenance "
- "service description."));
- return FALSE;
- }
-
- WCHAR serviceDescription[MAX_TEXT_LEN];
- if (!MultiByteToWideChar(CP_UTF8, 0,
- serviceStrings.serviceDescription, -1,
- serviceDescription,
- sizeof(serviceDescription) /
- sizeof(serviceDescription[0]))) {
- LOG_WARN(("Could not convert description to wide string format. (%d)",
- GetLastError()));
- return FALSE;
- }
-
- SERVICE_DESCRIPTIONW descriptionConfig;
- descriptionConfig.lpDescription = serviceDescription;
- if (!ChangeServiceConfig2W(serviceHandle,
- SERVICE_CONFIG_DESCRIPTION,
- &descriptionConfig)) {
- LOG_WARN(("Could not change service config. (%d)", GetLastError()));
- return FALSE;
- }
-
- LOG(("The service description was updated successfully."));
- return TRUE;
-}
-
-/**
- * Determines if the MozillaMaintenance service path needs to be updated
- * and fixes it if it is wrong.
- *
- * @param service A handle to the service to fix.
- * @param currentServicePath The current (possibly wrong) path that is used.
- * @param servicePathWasWrong Out parameter set to TRUE if a fix was needed.
- * @return TRUE if the service path is now correct.
-*/
-BOOL
-FixServicePath(SC_HANDLE service,
- LPCWSTR currentServicePath,
- BOOL &servicePathWasWrong)
-{
- // When we originally upgraded the MozillaMaintenance service we
- // would uninstall the service on each upgrade. This had an
- // intermittent error which could cause the service to use the file
- // maintenanceservice_tmp.exe as the install path. Only a small number
- // of Nightly users would be affected by this, but we check for this
- // state here and fix the user if they are affected.
- //
- // We also fix the path in the case of the path not being quoted.
- size_t currentServicePathLen = wcslen(currentServicePath);
- bool doesServiceHaveCorrectPath =
- currentServicePathLen > 2 &&
- !wcsstr(currentServicePath, L"maintenanceservice_tmp.exe") &&
- currentServicePath[0] == L'\"' &&
- currentServicePath[currentServicePathLen - 1] == L'\"';
-
- if (doesServiceHaveCorrectPath) {
- LOG(("The MozillaMaintenance service path is correct."));
- servicePathWasWrong = FALSE;
- return TRUE;
- }
- // This is a recoverable situation so not logging as a warning
- LOG(("The MozillaMaintenance path is NOT correct. It was: %ls",
- currentServicePath));
-
- servicePathWasWrong = TRUE;
- WCHAR fixedPath[MAX_PATH + 1] = { L'\0' };
- wcsncpy(fixedPath, currentServicePath, MAX_PATH);
- PathUnquoteSpacesW(fixedPath);
- if (!PathRemoveFileSpecW(fixedPath)) {
- LOG_WARN(("Couldn't remove file spec. (%d)", GetLastError()));
- return FALSE;
- }
- if (!PathAppendSafe(fixedPath, L"maintenanceservice.exe")) {
- LOG_WARN(("Couldn't append file spec. (%d)", GetLastError()));
- return FALSE;
- }
- PathQuoteSpacesW(fixedPath);
-
-
- if (!ChangeServiceConfigW(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
- SERVICE_NO_CHANGE, fixedPath, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr)) {
- LOG_WARN(("Could not fix service path. (%d)", GetLastError()));
- return FALSE;
- }
-
- LOG(("Fixed service path to: %ls.", fixedPath));
- return TRUE;
-}
-
-/**
- * Installs or upgrades the SVC_NAME service.
- * If an existing service is already installed, we replace it with the
- * currently running process.
- *
- * @param action The action to perform.
- * @return TRUE if the service was installed/upgraded
- */
-BOOL
-SvcInstall(SvcInstallAction action)
-{
- // Get a handle to the local computer SCM database with full access rights.
- nsAutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr,
- SC_MANAGER_ALL_ACCESS));
- if (!schSCManager) {
- LOG_WARN(("Could not open service manager. (%d)", GetLastError()));
- return FALSE;
- }
-
- WCHAR newServiceBinaryPath[MAX_PATH + 1];
- if (!GetModuleFileNameW(nullptr, newServiceBinaryPath,
- sizeof(newServiceBinaryPath) /
- sizeof(newServiceBinaryPath[0]))) {
- LOG_WARN(("Could not obtain module filename when attempting to "
- "install service. (%d)",
- GetLastError()));
- return FALSE;
- }
-
- // Check if we already have the service installed.
- nsAutoServiceHandle schService(OpenServiceW(schSCManager,
- SVC_NAME,
- SERVICE_ALL_ACCESS));
- DWORD lastError = GetLastError();
- if (!schService && ERROR_SERVICE_DOES_NOT_EXIST != lastError) {
- // The service exists but we couldn't open it
- LOG_WARN(("Could not open service. (%d)", GetLastError()));
- return FALSE;
- }
-
- if (schService) {
- // The service exists but it may not have the correct permissions.
- // This could happen if the permissions were not set correctly originally
- // or have been changed after the installation. This will reset the
- // permissions back to allow limited user accounts.
- if (!SetUserAccessServiceDACL(schService)) {
- LOG_WARN(("Could not reset security ACE on service handle. It might not be "
- "possible to start the service. This error should never "
- "happen. (%d)", GetLastError()));
- }
-
- // The service exists and we opened it
- DWORD bytesNeeded;
- if (!QueryServiceConfigW(schService, nullptr, 0, &bytesNeeded) &&
- GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- LOG_WARN(("Could not determine buffer size for query service config. (%d)",
- GetLastError()));
- return FALSE;
- }
-
- // Get the service config information, in particular we want the binary
- // path of the service.
- mozilla::UniquePtr<char[]> serviceConfigBuffer(new char[bytesNeeded]);
- if (!QueryServiceConfigW(schService,
- reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()),
- bytesNeeded, &bytesNeeded)) {
- LOG_WARN(("Could open service but could not query service config. (%d)",
- GetLastError()));
- return FALSE;
- }
- QUERY_SERVICE_CONFIGW &serviceConfig =
- *reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get());
-
- // Check if we need to fix the service path
- BOOL servicePathWasWrong;
- static BOOL alreadyCheckedFixServicePath = FALSE;
- if (!alreadyCheckedFixServicePath) {
- if (!FixServicePath(schService, serviceConfig.lpBinaryPathName,
- servicePathWasWrong)) {
- LOG_WARN(("Could not fix service path. This should never happen. (%d)",
- GetLastError()));
- // True is returned because the service is pointing to
- // maintenanceservice_tmp.exe so it actually was upgraded to the
- // newest installed service.
- return TRUE;
- } else if (servicePathWasWrong) {
- // Now that the path is fixed we should re-attempt the install.
- // This current process' image path is maintenanceservice_tmp.exe.
- // The service used to point to maintenanceservice_tmp.exe.
- // The service was just fixed to point to maintenanceservice.exe.
- // Re-attempting an install from scratch will work as normal.
- alreadyCheckedFixServicePath = TRUE;
- LOG(("Restarting install action: %d", action));
- return SvcInstall(action);
- }
- }
-
- // Ensure the service path is not quoted. We own this memory and know it to
- // be large enough for the quoted path, so it is large enough for the
- // unquoted path. This function cannot fail.
- PathUnquoteSpacesW(serviceConfig.lpBinaryPathName);
-
- // Obtain the existing maintenanceservice file's version number and
- // the new file's version number. Versions are in the format of
- // A.B.C.D.
- DWORD existingA, existingB, existingC, existingD;
- DWORD newA, newB, newC, newD;
- BOOL obtainedExistingVersionInfo =
- GetVersionNumberFromPath(serviceConfig.lpBinaryPathName,
- existingA, existingB,
- existingC, existingD);
- if (!GetVersionNumberFromPath(newServiceBinaryPath, newA,
- newB, newC, newD)) {
- LOG_WARN(("Could not obtain version number from new path"));
- return FALSE;
- }
-
- // Check if we need to replace the old binary with the new one
- // If we couldn't get the old version info then we assume we should
- // replace it.
- if (ForceInstallSvc == action ||
- !obtainedExistingVersionInfo ||
- (existingA < newA) ||
- (existingA == newA && existingB < newB) ||
- (existingA == newA && existingB == newB &&
- existingC < newC) ||
- (existingA == newA && existingB == newB &&
- existingC == newC && existingD < newD)) {
-
- // We have a newer updater, so update the description from the INI file.
- UpdateServiceDescription(schService);
-
- schService.reset();
- if (!StopService()) {
- return FALSE;
- }
-
- if (!wcscmp(newServiceBinaryPath, serviceConfig.lpBinaryPathName)) {
- LOG(("File is already in the correct location, no action needed for "
- "upgrade. The path is: \"%ls\"", newServiceBinaryPath));
- return TRUE;
- }
-
- BOOL result = TRUE;
-
- // Attempt to copy the new binary over top the existing binary.
- // If there is an error we try to move it out of the way and then
- // copy it in. First try the safest / easiest way to overwrite the file.
- if (!CopyFileW(newServiceBinaryPath,
- serviceConfig.lpBinaryPathName, FALSE)) {
- LOG_WARN(("Could not overwrite old service binary file. "
- "This should never happen, but if it does the next "
- "upgrade will fix it, the service is not a critical "
- "component that needs to be installed for upgrades "
- "to work. (%d)", GetLastError()));
-
- // We rename the last 3 filename chars in an unsafe way. Manually
- // verify there are more than 3 chars for safe failure in MoveFileExW.
- const size_t len = wcslen(serviceConfig.lpBinaryPathName);
- if (len > 3) {
- // Calculate the temp file path that we're moving the file to. This
- // is the same as the proper service path but with a .old extension.
- LPWSTR oldServiceBinaryTempPath =
- new WCHAR[len + 1];
- memset(oldServiceBinaryTempPath, 0, (len + 1) * sizeof (WCHAR));
- wcsncpy(oldServiceBinaryTempPath, serviceConfig.lpBinaryPathName, len);
- // Rename the last 3 chars to 'old'
- wcsncpy(oldServiceBinaryTempPath + len - 3, L"old", 3);
-
- // Move the current (old) service file to the temp path.
- if (MoveFileExW(serviceConfig.lpBinaryPathName,
- oldServiceBinaryTempPath,
- MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
- // The old binary is moved out of the way, copy in the new one.
- if (!CopyFileW(newServiceBinaryPath,
- serviceConfig.lpBinaryPathName, FALSE)) {
- // It is best to leave the old service binary in this condition.
- LOG_WARN(("The new service binary could not be copied in."
- " The service will not be upgraded."));
- result = FALSE;
- } else {
- LOG(("The new service binary was copied in by first moving the"
- " old one out of the way."));
- }
-
- // Attempt to get rid of the old service temp path.
- if (DeleteFileW(oldServiceBinaryTempPath)) {
- LOG(("The old temp service path was deleted: %ls.",
- oldServiceBinaryTempPath));
- } else {
- // The old temp path could not be removed. It will be removed
- // the next time the user can't copy the binary in or on uninstall.
- LOG_WARN(("The old temp service path was not deleted."));
- }
- } else {
- // It is best to leave the old service binary in this condition.
- LOG_WARN(("Could not move old service file out of the way from:"
- " \"%ls\" to \"%ls\". Service will not be upgraded. (%d)",
- serviceConfig.lpBinaryPathName,
- oldServiceBinaryTempPath, GetLastError()));
- result = FALSE;
- }
- delete[] oldServiceBinaryTempPath;
- } else {
- // It is best to leave the old service binary in this condition.
- LOG_WARN(("Service binary path was less than 3, service will"
- " not be updated. This should never happen."));
- result = FALSE;
- }
- } else {
- WCHAR versionStr[128] = { L'\0' };
- swprintf(versionStr, 128, L"%d.%d.%d.%d", newA, newB, newC, newD);
- if (!UpdateUninstallerVersionString(versionStr)) {
- LOG(("The uninstaller version string could not be updated."));
- }
- LOG(("The new service binary was copied in."));
- }
-
- // We made a copy of ourselves to the existing location.
- // The tmp file (the process of which we are executing right now) will be
- // left over. Attempt to delete the file on the next reboot.
- if (MoveFileExW(newServiceBinaryPath, nullptr,
- MOVEFILE_DELAY_UNTIL_REBOOT)) {
- LOG(("Deleting the old file path on the next reboot: %ls.",
- newServiceBinaryPath));
- } else {
- LOG_WARN(("Call to delete the old file path failed: %ls.",
- newServiceBinaryPath));
- }
-
- return result;
- }
-
- // We don't need to copy ourselves to the existing location.
- // The tmp file (the process of which we are executing right now) will be
- // left over. Attempt to delete the file on the next reboot.
- MoveFileExW(newServiceBinaryPath, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
-
- // nothing to do, we already have a newer service installed
- return TRUE;
- }
-
- // If the service does not exist and we are upgrading, don't install it.
- if (UpgradeSvc == action) {
- // The service does not exist and we are upgrading, so don't install it
- return TRUE;
- }
-
- // Quote the path only if it contains spaces.
- PathQuoteSpacesW(newServiceBinaryPath);
- // The service does not already exist so create the service as on demand
- schService.own(CreateServiceW(schSCManager, SVC_NAME, SVC_DISPLAY_NAME,
- SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
- SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
- newServiceBinaryPath, nullptr, nullptr,
- nullptr, nullptr, nullptr));
- if (!schService) {
- LOG_WARN(("Could not create Windows service. "
- "This error should never happen since a service install "
- "should only be called when elevated. (%d)", GetLastError()));
- return FALSE;
- }
-
- if (!SetUserAccessServiceDACL(schService)) {
- LOG_WARN(("Could not set security ACE on service handle, the service will not "
- "be able to be started from unelevated processes. "
- "This error should never happen. (%d)",
- GetLastError()));
- }
-
- UpdateServiceDescription(schService);
-
- return TRUE;
-}
-
-/**
- * Stops the Maintenance service.
- *
- * @return TRUE if successful.
- */
-BOOL
-StopService()
-{
- // Get a handle to the local computer SCM database with full access rights.
- nsAutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr,
- SC_MANAGER_ALL_ACCESS));
- if (!schSCManager) {
- LOG_WARN(("Could not open service manager. (%d)", GetLastError()));
- return FALSE;
- }
-
- // Open the service
- nsAutoServiceHandle schService(OpenServiceW(schSCManager, SVC_NAME,
- SERVICE_ALL_ACCESS));
- if (!schService) {
- LOG_WARN(("Could not open service. (%d)", GetLastError()));
- return FALSE;
- }
-
- LOG(("Sending stop request..."));
- SERVICE_STATUS status;
- SetLastError(ERROR_SUCCESS);
- if (!ControlService(schService, SERVICE_CONTROL_STOP, &status) &&
- GetLastError() != ERROR_SERVICE_NOT_ACTIVE) {
- LOG_WARN(("Error sending stop request. (%d)", GetLastError()));
- }
-
- schSCManager.reset();
- schService.reset();
-
- LOG(("Waiting for service stop..."));
- DWORD lastState = WaitForServiceStop(SVC_NAME, 30);
-
- // The service can be in a stopped state but the exe still in use
- // so make sure the process is really gone before proceeding
- WaitForProcessExit(L"maintenanceservice.exe", 30);
- LOG(("Done waiting for service stop, last service state: %d", lastState));
-
- return lastState == SERVICE_STOPPED;
-}
-
-/**
- * Uninstalls the Maintenance service.
- *
- * @return TRUE if successful.
- */
-BOOL
-SvcUninstall()
-{
- // Get a handle to the local computer SCM database with full access rights.
- nsAutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr,
- SC_MANAGER_ALL_ACCESS));
- if (!schSCManager) {
- LOG_WARN(("Could not open service manager. (%d)", GetLastError()));
- return FALSE;
- }
-
- // Open the service
- nsAutoServiceHandle schService(OpenServiceW(schSCManager, SVC_NAME,
- SERVICE_ALL_ACCESS));
- if (!schService) {
- LOG_WARN(("Could not open service. (%d)", GetLastError()));
- return FALSE;
- }
-
- //Stop the service so it deletes faster and so the uninstaller
- // can actually delete its EXE.
- DWORD totalWaitTime = 0;
- SERVICE_STATUS status;
- static const int maxWaitTime = 1000 * 60; // Never wait more than a minute
- if (ControlService(schService, SERVICE_CONTROL_STOP, &status)) {
- do {
- Sleep(status.dwWaitHint);
- totalWaitTime += (status.dwWaitHint + 10);
- if (status.dwCurrentState == SERVICE_STOPPED) {
- break;
- } else if (totalWaitTime > maxWaitTime) {
- break;
- }
- } while (QueryServiceStatus(schService, &status));
- }
-
- // Delete the service or mark it for deletion
- BOOL deleted = DeleteService(schService);
- if (!deleted) {
- deleted = (GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE);
- }
-
- return deleted;
-}
-
-/**
- * Sets the access control list for user access for the specified service.
- *
- * @param hService The service to set the access control list on
- * @return TRUE if successful
- */
-BOOL
-SetUserAccessServiceDACL(SC_HANDLE hService)
-{
- PACL pNewAcl = nullptr;
- PSECURITY_DESCRIPTOR psd = nullptr;
- DWORD lastError = SetUserAccessServiceDACL(hService, pNewAcl, psd);
- if (pNewAcl) {
- LocalFree((HLOCAL)pNewAcl);
- }
- if (psd) {
- LocalFree((LPVOID)psd);
- }
- return ERROR_SUCCESS == lastError;
-}
-
-/**
- * Sets the access control list for user access for the specified service.
- *
- * @param hService The service to set the access control list on
- * @param pNewAcl The out param ACL which should be freed by caller
- * @param psd out param security descriptor, should be freed by caller
- * @return ERROR_SUCCESS if successful
- */
-DWORD
-SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl,
- PSECURITY_DESCRIPTOR psd)
-{
- // Get the current security descriptor needed size
- DWORD needed = 0;
- if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION,
- &psd, 0, &needed)) {
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- LOG_WARN(("Could not query service object security size. (%d)",
- GetLastError()));
- return GetLastError();
- }
-
- DWORD size = needed;
- psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, size);
- if (!psd) {
- LOG_WARN(("Could not allocate security descriptor. (%d)",
- GetLastError()));
- return ERROR_INSUFFICIENT_BUFFER;
- }
-
- // Get the actual security descriptor now
- if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION,
- psd, size, &needed)) {
- LOG_WARN(("Could not allocate security descriptor. (%d)",
- GetLastError()));
- return GetLastError();
- }
- }
-
- // Get the current DACL from the security descriptor.
- PACL pacl = nullptr;
- BOOL bDaclPresent = FALSE;
- BOOL bDaclDefaulted = FALSE;
- if ( !GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
- &bDaclDefaulted)) {
- LOG_WARN(("Could not obtain DACL. (%d)", GetLastError()));
- return GetLastError();
- }
-
- PSID sid;
- DWORD SIDSize = SECURITY_MAX_SID_SIZE;
- sid = LocalAlloc(LMEM_FIXED, SIDSize);
- if (!sid) {
- LOG_WARN(("Could not allocate SID memory. (%d)", GetLastError()));
- return GetLastError();
- }
-
- if (!CreateWellKnownSid(WinBuiltinUsersSid, nullptr, sid, &SIDSize)) {
- DWORD lastError = GetLastError();
- LOG_WARN(("Could not create well known SID. (%d)", lastError));
- LocalFree(sid);
- return lastError;
- }
-
- // Lookup the account name, the function fails if you don't pass in
- // a buffer for the domain name but it's not used since we're using
- // the built in account Sid.
- SID_NAME_USE accountType;
- WCHAR accountName[UNLEN + 1] = { L'\0' };
- WCHAR domainName[DNLEN + 1] = { L'\0' };
- DWORD accountNameSize = UNLEN + 1;
- DWORD domainNameSize = DNLEN + 1;
- if (!LookupAccountSidW(nullptr, sid, accountName,
- &accountNameSize,
- domainName, &domainNameSize, &accountType)) {
- LOG_WARN(("Could not lookup account Sid, will try Users. (%d)",
- GetLastError()));
- wcsncpy(accountName, L"Users", UNLEN);
- }
-
- // We already have the group name so we can get rid of the SID
- FreeSid(sid);
- sid = nullptr;
-
- // Build the ACE, BuildExplicitAccessWithName cannot fail so it is not logged.
- EXPLICIT_ACCESS ea;
- BuildExplicitAccessWithNameW(&ea, accountName,
- SERVICE_START | SERVICE_STOP | GENERIC_READ,
- SET_ACCESS, NO_INHERITANCE);
- DWORD lastError = SetEntriesInAclW(1, (PEXPLICIT_ACCESS)&ea, pacl, &pNewAcl);
- if (ERROR_SUCCESS != lastError) {
- LOG_WARN(("Could not set entries in ACL. (%d)", lastError));
- return lastError;
- }
-
- // Initialize a new security descriptor.
- SECURITY_DESCRIPTOR sd;
- if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
- LOG_WARN(("Could not initialize security descriptor. (%d)",
- GetLastError()));
- return GetLastError();
- }
-
- // Set the new DACL in the security descriptor.
- if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE)) {
- LOG_WARN(("Could not set security descriptor DACL. (%d)",
- GetLastError()));
- return GetLastError();
- }
-
- // Set the new security descriptor for the service object.
- if (!SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, &sd)) {
- LOG_WARN(("Could not set object security. (%d)",
- GetLastError()));
- return GetLastError();
- }
-
- // Woohoo, raise the roof
- LOG(("User access was set successfully on the service."));
- return ERROR_SUCCESS;
-}
diff --git a/toolkit/components/maintenanceservice/serviceinstall.h b/toolkit/components/maintenanceservice/serviceinstall.h
deleted file mode 100644
index d8532a968..000000000
--- a/toolkit/components/maintenanceservice/serviceinstall.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* 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/. */
-
-#include "readstrings.h"
-
-#define SVC_DISPLAY_NAME L"Mozilla Maintenance Service"
-
-enum SvcInstallAction { UpgradeSvc, InstallSvc, ForceInstallSvc };
-BOOL SvcInstall(SvcInstallAction action);
-BOOL SvcUninstall();
-BOOL StopService();
-BOOL SetUserAccessServiceDACL(SC_HANDLE hService);
-DWORD SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl,
- PSECURITY_DESCRIPTOR psd);
-
-struct MaintenanceServiceStringTable
-{
- char serviceDescription[MAX_TEXT_LEN];
-};
-
diff --git a/toolkit/components/maintenanceservice/workmonitor.cpp b/toolkit/components/maintenanceservice/workmonitor.cpp
deleted file mode 100644
index d06db3ca2..000000000
--- a/toolkit/components/maintenanceservice/workmonitor.cpp
+++ /dev/null
@@ -1,758 +0,0 @@
-/* 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/. */
-
-#include <shlobj.h>
-#include <shlwapi.h>
-#include <wtsapi32.h>
-#include <userenv.h>
-#include <shellapi.h>
-
-#pragma comment(lib, "wtsapi32.lib")
-#pragma comment(lib, "userenv.lib")
-#pragma comment(lib, "shlwapi.lib")
-#pragma comment(lib, "ole32.lib")
-#pragma comment(lib, "rpcrt4.lib")
-
-#include "nsWindowsHelpers.h"
-
-#include "workmonitor.h"
-#include "serviceinstall.h"
-#include "servicebase.h"
-#include "registrycertificates.h"
-#include "uachelper.h"
-#include "updatehelper.h"
-#include "pathhash.h"
-#include "errors.h"
-
-// Wait 15 minutes for an update operation to run at most.
-// Updates usually take less than a minute so this seems like a
-// significantly large and safe amount of time to wait.
-static const int TIME_TO_WAIT_ON_UPDATER = 15 * 60 * 1000;
-wchar_t* MakeCommandLine(int argc, wchar_t** argv);
-BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
-BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
- LPCWSTR newFileName);
-BOOL DoesFallbackKeyExist();
-
-/*
- * Read the update.status file and sets isApplying to true if
- * the status is set to applying.
- *
- * @param updateDirPath The directory where update.status is stored
- * @param isApplying Out parameter for specifying if the status
- * is set to applying or not.
- * @return TRUE if the information was filled.
-*/
-static BOOL
-IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying)
-{
- isApplying = FALSE;
- WCHAR updateStatusFilePath[MAX_PATH + 1] = {L'\0'};
- wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH);
- if (!PathAppendSafe(updateStatusFilePath, L"update.status")) {
- LOG_WARN(("Could not append path for update.status file"));
- return FALSE;
- }
-
- nsAutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ,
- FILE_SHARE_READ |
- FILE_SHARE_WRITE |
- FILE_SHARE_DELETE,
- nullptr, OPEN_EXISTING, 0, nullptr));
-
- if (INVALID_HANDLE_VALUE == statusFile) {
- LOG_WARN(("Could not open update.status file"));
- return FALSE;
- }
-
- char buf[32] = { 0 };
- DWORD read;
- if (!ReadFile(statusFile, buf, sizeof(buf), &read, nullptr)) {
- LOG_WARN(("Could not read from update.status file"));
- return FALSE;
- }
-
- const char kApplying[] = "applying";
- isApplying = strncmp(buf, kApplying,
- sizeof(kApplying) - 1) == 0;
- return TRUE;
-}
-
-/**
- * Determines whether we're staging an update.
- *
- * @param argc The argc value normally sent to updater.exe
- * @param argv The argv value normally sent to updater.exe
- * @return boolean True if we're staging an update
- */
-static bool
-IsUpdateBeingStaged(int argc, LPWSTR *argv)
-{
- // PID will be set to -1 if we're supposed to stage an update.
- return argc == 4 && !wcscmp(argv[3], L"-1") ||
- argc == 5 && !wcscmp(argv[4], L"-1");
-}
-
-/**
- * Determines whether the param only contains digits.
- *
- * @param str The string to check
- * @param boolean True if the param only contains digits
- */
-static bool
-IsDigits(WCHAR *str)
-{
- while (*str) {
- if (!iswdigit(*str++)) {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-/**
- * Determines whether the command line contains just the directory to apply the
- * update to (old command line) or if it contains the installation directory and
- * the directory to apply the update to.
- *
- * @param argc The argc value normally sent to updater.exe
- * @param argv The argv value normally sent to updater.exe
- * @param boolean True if the command line contains just the directory to apply
- * the update to
- */
-static bool
-IsOldCommandline(int argc, LPWSTR *argv)
-{
- return argc == 4 && !wcscmp(argv[3], L"-1") ||
- argc >= 4 && (wcsstr(argv[3], L"/replace") || IsDigits(argv[3]));
-}
-
-/**
- * Gets the installation directory from the arguments passed to updater.exe.
- *
- * @param argcTmp The argc value normally sent to updater.exe
- * @param argvTmp The argv value normally sent to updater.exe
- * @param aResultDir Buffer to hold the installation directory.
- */
-static BOOL
-GetInstallationDir(int argcTmp, LPWSTR *argvTmp, WCHAR aResultDir[MAX_PATH + 1])
-{
- int index = 3;
- if (IsOldCommandline(argcTmp, argvTmp)) {
- index = 2;
- }
-
- if (argcTmp < index) {
- return FALSE;
- }
-
- wcsncpy(aResultDir, argvTmp[2], MAX_PATH);
- WCHAR* backSlash = wcsrchr(aResultDir, L'\\');
- // Make sure that the path does not include trailing backslashes
- if (backSlash && (backSlash[1] == L'\0')) {
- *backSlash = L'\0';
- }
-
- // The new command line's argv[2] is always the installation directory.
- if (index == 2) {
- bool backgroundUpdate = IsUpdateBeingStaged(argcTmp, argvTmp);
- bool replaceRequest = (argcTmp >= 4 && wcsstr(argvTmp[3], L"/replace"));
- if (backgroundUpdate || replaceRequest) {
- return PathRemoveFileSpecW(aResultDir);
- }
- }
- return TRUE;
-}
-
-/**
- * Runs an update process as the service using the SYSTEM account.
- *
- * @param argc The number of arguments in argv
- * @param argv The arguments normally passed to updater.exe
- * argv[0] must be the path to updater.exe
- * @param processStarted Set to TRUE if the process was started.
- * @return TRUE if the update process was run had a return code of 0.
- */
-BOOL
-StartUpdateProcess(int argc,
- LPWSTR *argv,
- LPCWSTR installDir,
- BOOL &processStarted)
-{
- LOG(("Starting update process as the service in session 0."));
- STARTUPINFO si = {0};
- si.cb = sizeof(STARTUPINFO);
- si.lpDesktop = L"winsta0\\Default";
- PROCESS_INFORMATION pi = {0};
-
- // The updater command line is of the form:
- // updater.exe update-dir apply [wait-pid [callback-dir callback-path args]]
- LPWSTR cmdLine = MakeCommandLine(argc, argv);
-
- int index = 3;
- if (IsOldCommandline(argc, argv)) {
- index = 2;
- }
-
- // If we're about to start the update process from session 0,
- // then we should not show a GUI. This only really needs to be done
- // on Vista and higher, but it's better to keep everything consistent
- // across all OS if it's of no harm.
- if (argc >= index) {
- // Setting the desktop to blank will ensure no GUI is displayed
- si.lpDesktop = L"";
- si.dwFlags |= STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE;
- }
-
- // Add an env var for MOZ_USING_SERVICE so the updater.exe can
- // do anything special that it needs to do for service updates.
- // Search in updater.cpp for more info on MOZ_USING_SERVICE.
- putenv(const_cast<char*>("MOZ_USING_SERVICE=1"));
- LOG(("Starting service with cmdline: %ls", cmdLine));
- processStarted = CreateProcessW(argv[0], cmdLine,
- nullptr, nullptr, FALSE,
- CREATE_DEFAULT_ERROR_MODE,
- nullptr,
- nullptr, &si, &pi);
-
- BOOL updateWasSuccessful = FALSE;
- if (processStarted) {
- BOOL processTerminated = FALSE;
- BOOL noProcessExitCode = FALSE;
- // Wait for the updater process to finish
- LOG(("Process was started... waiting on result."));
- DWORD waitRes = WaitForSingleObject(pi.hProcess, TIME_TO_WAIT_ON_UPDATER);
- if (WAIT_TIMEOUT == waitRes) {
- // We waited a long period of time for updater.exe and it never finished
- // so kill it.
- TerminateProcess(pi.hProcess, 1);
- processTerminated = TRUE;
- } else {
- // Check the return code of updater.exe to make sure we get 0
- DWORD returnCode;
- if (GetExitCodeProcess(pi.hProcess, &returnCode)) {
- LOG(("Process finished with return code %d.", returnCode));
- // updater returns 0 if successful.
- updateWasSuccessful = (returnCode == 0);
- } else {
- LOG_WARN(("Process finished but could not obtain return code."));
- noProcessExitCode = TRUE;
- }
- }
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
-
- // Check just in case updater.exe didn't change the status from
- // applying. If this is the case we report an error.
- BOOL isApplying = FALSE;
- if (IsStatusApplying(argv[1], isApplying) && isApplying) {
- if (updateWasSuccessful) {
- LOG(("update.status is still applying even though update was "
- "successful."));
- if (!WriteStatusFailure(argv[1],
- SERVICE_STILL_APPLYING_ON_SUCCESS)) {
- LOG_WARN(("Could not write update.status still applying on "
- "success error."));
- }
- // Since we still had applying we know updater.exe didn't do its
- // job correctly.
- updateWasSuccessful = FALSE;
- } else {
- LOG_WARN(("update.status is still applying and update was not successful."));
- int failcode = SERVICE_STILL_APPLYING_ON_FAILURE;
- if (noProcessExitCode) {
- failcode = SERVICE_STILL_APPLYING_NO_EXIT_CODE;
- } else if (processTerminated) {
- failcode = SERVICE_STILL_APPLYING_TERMINATED;
- }
- if (!WriteStatusFailure(argv[1], failcode)) {
- LOG_WARN(("Could not write update.status still applying on "
- "failure error."));
- }
- }
- }
- } else {
- DWORD lastError = GetLastError();
- LOG_WARN(("Could not create process as current user, "
- "updaterPath: %ls; cmdLine: %ls. (%d)",
- argv[0], cmdLine, lastError));
- }
-
- // Empty value on putenv is how you remove an env variable in Windows
- putenv(const_cast<char*>("MOZ_USING_SERVICE="));
-
- free(cmdLine);
- return updateWasSuccessful;
-}
-
-/**
- * Validates a file as an official updater.
- *
- * @param updater Path to the updater to validate
- * @param installDir Path to the application installation
- * being updated
- * @param updateDir Update applyTo direcotry,
- * where logs will be written
- *
- * @return true if updater is the path to a valid updater
- */
-static bool
-UpdaterIsValid(LPWSTR updater, LPWSTR installDir, LPWSTR updateDir)
-{
- // Make sure the path to the updater to use for the update is local.
- // We do this check to make sure that file locking is available for
- // race condition security checks.
- BOOL isLocal = FALSE;
- if (!IsLocalFile(updater, isLocal) || !isLocal) {
- LOG_WARN(("Filesystem in path %ls is not supported (%d)",
- updater, GetLastError()));
- if (!WriteStatusFailure(updateDir, SERVICE_UPDATER_NOT_FIXED_DRIVE)) {
- LOG_WARN(("Could not write update.status service update failure. (%d)",
- GetLastError()));
- }
- return false;
- }
-
- nsAutoHandle noWriteLock(CreateFileW(updater, GENERIC_READ, FILE_SHARE_READ,
- nullptr, OPEN_EXISTING, 0, nullptr));
- if (INVALID_HANDLE_VALUE == noWriteLock) {
- LOG_WARN(("Could not set no write sharing access on file. (%d)",
- GetLastError()));
- if (!WriteStatusFailure(updateDir, SERVICE_COULD_NOT_LOCK_UPDATER)) {
- LOG_WARN(("Could not write update.status service update failure. (%d)",
- GetLastError()));
- }
- return false;
- }
-
- // Verify that the updater.exe that we are executing is the same
- // as the one in the installation directory which we are updating.
- // The installation dir that we are installing to is installDir.
- WCHAR installDirUpdater[MAX_PATH + 1] = { L'\0' };
- wcsncpy(installDirUpdater, installDir, MAX_PATH);
- if (!PathAppendSafe(installDirUpdater, L"updater.exe")) {
- LOG_WARN(("Install directory updater could not be determined."));
- return false;
- }
-
- BOOL updaterIsCorrect;
- if (!VerifySameFiles(updater, installDirUpdater, updaterIsCorrect)) {
- LOG_WARN(("Error checking if the updaters are the same.\n"
- "Path 1: %ls\nPath 2: %ls", updater, installDirUpdater));
- return false;
- }
-
- if (!updaterIsCorrect) {
- LOG_WARN(("The updaters do not match, updater will not run.\n"
- "Path 1: %ls\nPath 2: %ls", updater, installDirUpdater));
- if (!WriteStatusFailure(updateDir, SERVICE_UPDATER_COMPARE_ERROR)) {
- LOG_WARN(("Could not write update.status updater compare failure."));
- }
- return false;
- }
-
- LOG(("updater.exe was compared successfully to the installation directory"
- " updater.exe."));
-
- // Check to make sure the updater.exe module has the unique updater identity.
- // This is a security measure to make sure that the signed executable that
- // we will run is actually an updater.
- bool result = true;
- HMODULE updaterModule = LoadLibraryEx(updater, nullptr,
- LOAD_LIBRARY_AS_DATAFILE);
- if (!updaterModule) {
- LOG_WARN(("updater.exe module could not be loaded. (%d)", GetLastError()));
- result = false;
- } else {
- char updaterIdentity[64];
- if (!LoadStringA(updaterModule, IDS_UPDATER_IDENTITY,
- updaterIdentity, sizeof(updaterIdentity))) {
- LOG_WARN(("The updater.exe application does not contain the Mozilla"
- " updater identity."));
- result = false;
- }
-
- if (strcmp(updaterIdentity, UPDATER_IDENTITY_STRING)) {
- LOG_WARN(("The updater.exe identity string is not valid."));
- result = false;
- }
- FreeLibrary(updaterModule);
- }
-
- if (result) {
- LOG(("The updater.exe application contains the Mozilla"
- " updater identity."));
- } else {
- if (!WriteStatusFailure(updateDir, SERVICE_UPDATER_IDENTITY_ERROR)) {
- LOG_WARN(("Could not write update.status no updater identity."));
- }
- return false;
- }
-
-#ifndef DISABLE_UPDATER_AUTHENTICODE_CHECK
- return DoesBinaryMatchAllowedCertificates(installDir, updater);
-#else
- return true;
-#endif
-}
-
-/**
- * Processes a software update command
- *
- * @param argc The number of arguments in argv
- * @param argv The arguments normally passed to updater.exe
- * argv[0] must be the path to updater.exe
- * @return TRUE if the update was successful.
- */
-BOOL
-ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
-{
- BOOL result = TRUE;
- if (argc < 3) {
- LOG_WARN(("Not enough command line parameters specified. "
- "Updating update.status."));
-
- // We can only update update.status if argv[1] exists. argv[1] is
- // the directory where the update.status file exists.
- if (argc < 2 ||
- !WriteStatusFailure(argv[1], SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS)) {
- LOG_WARN(("Could not write update.status service update failure. (%d)",
- GetLastError()));
- }
- return FALSE;
- }
-
- WCHAR installDir[MAX_PATH + 1] = {L'\0'};
- if (!GetInstallationDir(argc, argv, installDir)) {
- LOG_WARN(("Could not get the installation directory"));
- if (!WriteStatusFailure(argv[1], SERVICE_INSTALLDIR_ERROR)) {
- LOG_WARN(("Could not write update.status for GetInstallationDir failure."));
- }
- return FALSE;
- }
-
- if (UpdaterIsValid(argv[0], installDir, argv[1])) {
- BOOL updateProcessWasStarted = FALSE;
- if (StartUpdateProcess(argc, argv, installDir,
- updateProcessWasStarted)) {
- LOG(("updater.exe was launched and run successfully!"));
- LogFlush();
-
- // Don't attempt to update the service when the update is being staged.
- if (!IsUpdateBeingStaged(argc, argv)) {
- // We might not execute code after StartServiceUpdate because
- // the service installer will stop the service if it is running.
- StartServiceUpdate(installDir);
- }
- } else {
- result = FALSE;
- LOG_WARN(("Error running update process. Updating update.status (%d)",
- GetLastError()));
- LogFlush();
-
- // If the update process was started, then updater.exe is responsible for
- // setting the failure code. If it could not be started then we do the
- // work. We set an error instead of directly setting status pending
- // so that the app.update.service.errors pref can be updated when
- // the callback app restarts.
- if (!updateProcessWasStarted) {
- if (!WriteStatusFailure(argv[1],
- SERVICE_UPDATER_COULD_NOT_BE_STARTED)) {
- LOG_WARN(("Could not write update.status service update failure. (%d)",
- GetLastError()));
- }
- }
- }
- } else {
- result = FALSE;
- LOG_WARN(("Could not start process due to certificate check error on "
- "updater.exe. Updating update.status. (%d)", GetLastError()));
-
- // When there is a certificate check error on the updater.exe application,
- // we want to write out the error.
- if (!WriteStatusFailure(argv[1],
- SERVICE_UPDATER_SIGN_ERROR)) {
- LOG_WARN(("Could not write pending state to update.status. (%d)",
- GetLastError()));
- }
- }
-
- return result;
-}
-
-/**
- * Obtains the updater path alongside a subdir of the service binary.
- * The purpose of this function is to return a path that is likely high
- * integrity and therefore more safe to execute code from.
- *
- * @param serviceUpdaterPath Out parameter for the path where the updater
- * should be copied to.
- * @return TRUE if a file path was obtained.
- */
-BOOL
-GetSecureUpdaterPath(WCHAR serviceUpdaterPath[MAX_PATH + 1])
-{
- if (!GetModuleFileNameW(nullptr, serviceUpdaterPath, MAX_PATH)) {
- LOG_WARN(("Could not obtain module filename when attempting to "
- "use a secure updater path. (%d)", GetLastError()));
- return FALSE;
- }
-
- if (!PathRemoveFileSpecW(serviceUpdaterPath)) {
- LOG_WARN(("Couldn't remove file spec when attempting to use a secure "
- "updater path. (%d)", GetLastError()));
- return FALSE;
- }
-
- if (!PathAppendSafe(serviceUpdaterPath, L"update")) {
- LOG_WARN(("Couldn't append file spec when attempting to use a secure "
- "updater path. (%d)", GetLastError()));
- return FALSE;
- }
-
- CreateDirectoryW(serviceUpdaterPath, nullptr);
-
- if (!PathAppendSafe(serviceUpdaterPath, L"updater.exe")) {
- LOG_WARN(("Couldn't append file spec when attempting to use a secure "
- "updater path. (%d)", GetLastError()));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Deletes the passed in updater path and the associated updater.ini file.
- *
- * @param serviceUpdaterPath The path to delete.
- * @return TRUE if a file was deleted.
- */
-BOOL
-DeleteSecureUpdater(WCHAR serviceUpdaterPath[MAX_PATH + 1])
-{
- BOOL result = FALSE;
- if (serviceUpdaterPath[0]) {
- result = DeleteFileW(serviceUpdaterPath);
- if (!result && GetLastError() != ERROR_PATH_NOT_FOUND &&
- GetLastError() != ERROR_FILE_NOT_FOUND) {
- LOG_WARN(("Could not delete service updater path: '%ls'.",
- serviceUpdaterPath));
- }
-
- WCHAR updaterINIPath[MAX_PATH + 1] = { L'\0' };
- if (PathGetSiblingFilePath(updaterINIPath, serviceUpdaterPath,
- L"updater.ini")) {
- result = DeleteFileW(updaterINIPath);
- if (!result && GetLastError() != ERROR_PATH_NOT_FOUND &&
- GetLastError() != ERROR_FILE_NOT_FOUND) {
- LOG_WARN(("Could not delete service updater INI path: '%ls'.",
- updaterINIPath));
- }
- }
- }
- return result;
-}
-
-/**
- * Executes a service command.
- *
- * @param argc The number of arguments in argv
- * @param argv The service command line arguments, argv[0] and argv[1]
- * and automatically included by Windows. argv[2] is the
- * service command.
- *
- * @return FALSE if there was an error executing the service command.
- */
-BOOL
-ExecuteServiceCommand(int argc, LPWSTR *argv)
-{
- if (argc < 3) {
- LOG_WARN(("Not enough command line arguments to execute a service command"));
- return FALSE;
- }
-
- // The tests work by making sure the log has changed, so we put a
- // unique ID in the log.
- RPC_WSTR guidString = RPC_WSTR(L"");
- GUID guid;
- HRESULT hr = CoCreateGuid(&guid);
- if (SUCCEEDED(hr)) {
- UuidToString(&guid, &guidString);
- }
- LOG(("Executing service command %ls, ID: %ls",
- argv[2], reinterpret_cast<LPCWSTR>(guidString)));
- RpcStringFree(&guidString);
-
- BOOL result = FALSE;
- if (!lstrcmpi(argv[2], L"software-update")) {
- // This check is also performed in updater.cpp and is performed here
- // as well since the maintenance service can be called directly.
- if (argc < 4 || !IsValidFullPath(argv[4])) {
- // Since the status file is written to the patch directory and the patch
- // directory is invalid don't write the status file.
- LOG_WARN(("The patch directory path is not valid for this application."));
- return FALSE;
- }
-
- // This check is also performed in updater.cpp and is performed here
- // as well since the maintenance service can be called directly.
- if (argc < 5 || !IsValidFullPath(argv[5])) {
- LOG_WARN(("The install directory path is not valid for this application."));
- if (!WriteStatusFailure(argv[4], SERVICE_INVALID_INSTALL_DIR_PATH_ERROR)) {
- LOG_WARN(("Could not write update.status for previous failure."));
- }
- return FALSE;
- }
-
- if (!IsOldCommandline(argc - 3, argv + 3)) {
- // This check is also performed in updater.cpp and is performed here
- // as well since the maintenance service can be called directly.
- if (argc < 6 || !IsValidFullPath(argv[6])) {
- LOG_WARN(("The working directory path is not valid for this application."));
- if (!WriteStatusFailure(argv[4], SERVICE_INVALID_WORKING_DIR_PATH_ERROR)) {
- LOG_WARN(("Could not write update.status for previous failure."));
- }
- return FALSE;
- }
-
- // These checks are also performed in updater.cpp and is performed here
- // as well since the maintenance service can be called directly.
- if (_wcsnicmp(argv[6], argv[5], MAX_PATH) != 0) {
- if (wcscmp(argv[7], L"-1") != 0 && !wcsstr(argv[7], L"/replace")) {
- LOG_WARN(("Installation directory and working directory must be the "
- "same for non-staged updates. Exiting."));
- if (!WriteStatusFailure(argv[4], SERVICE_INVALID_APPLYTO_DIR_ERROR)) {
- LOG_WARN(("Could not write update.status for previous failure."));
- }
- return FALSE;
- }
-
- NS_tchar workingDirParent[MAX_PATH];
- NS_tsnprintf(workingDirParent,
- sizeof(workingDirParent) / sizeof(workingDirParent[0]),
- NS_T("%s"), argv[6]);
- if (!PathRemoveFileSpecW(workingDirParent)) {
- LOG_WARN(("Couldn't remove file spec when attempting to verify the "
- "working directory path. (%d)", GetLastError()));
- if (!WriteStatusFailure(argv[4], REMOVE_FILE_SPEC_ERROR)) {
- LOG_WARN(("Could not write update.status for previous failure."));
- }
- return FALSE;
- }
-
- if (_wcsnicmp(workingDirParent, argv[5], MAX_PATH) != 0) {
- LOG_WARN(("The apply-to directory must be the same as or "
- "a child of the installation directory! Exiting."));
- if (!WriteStatusFailure(argv[4], SERVICE_INVALID_APPLYTO_DIR_STAGED_ERROR)) {
- LOG_WARN(("Could not write update.status for previous failure."));
- }
- return FALSE;
- }
- }
-
- }
-
- // Use the passed in command line arguments for the update, except for the
- // path to updater.exe. We always look for updater.exe in the installation
- // directory, then we copy updater.exe to a the directory of the
- // MozillaMaintenance service so that a low integrity process cannot
- // replace the updater.exe at any point and use that for the update.
- // It also makes DLL injection attacks harder.
- WCHAR installDir[MAX_PATH + 1] = { L'\0' };
- if (!GetInstallationDir(argc - 3, argv + 3, installDir)) {
- LOG_WARN(("Could not get the installation directory"));
- if (!WriteStatusFailure(argv[4], SERVICE_INSTALLDIR_ERROR)) {
- LOG_WARN(("Could not write update.status for previous failure."));
- }
- return FALSE;
- }
-
- if (!DoesFallbackKeyExist()) {
- WCHAR maintenanceServiceKey[MAX_PATH + 1];
- if (CalculateRegistryPathFromFilePath(installDir, maintenanceServiceKey)) {
- LOG(("Checking for Maintenance Service registry. key: '%ls'",
- maintenanceServiceKey));
- HKEY baseKey = nullptr;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- maintenanceServiceKey, 0,
- KEY_READ | KEY_WOW64_64KEY,
- &baseKey) != ERROR_SUCCESS) {
- LOG_WARN(("The maintenance service registry key does not exist."));
- if (!WriteStatusFailure(argv[4], SERVICE_INSTALL_DIR_REG_ERROR)) {
- LOG_WARN(("Could not write update.status for previous failure."));
- }
- return FALSE;
- }
- RegCloseKey(baseKey);
- } else {
- if (!WriteStatusFailure(argv[4], SERVICE_CALC_REG_PATH_ERROR)) {
- LOG_WARN(("Could not write update.status for previous failure."));
- }
- return FALSE;
- }
- }
-
- WCHAR installDirUpdater[MAX_PATH + 1] = { L'\0' };
- wcsncpy(installDirUpdater, installDir, MAX_PATH);
- if (!PathAppendSafe(installDirUpdater, L"updater.exe")) {
- LOG_WARN(("Install directory updater could not be determined."));
- result = FALSE;
- }
-
- result = UpdaterIsValid(installDirUpdater, installDir, argv[4]);
-
- WCHAR secureUpdaterPath[MAX_PATH + 1] = { L'\0' };
- if (result) {
- result = GetSecureUpdaterPath(secureUpdaterPath); // Does its own logging
- }
- if (result) {
- LOG(("Passed in path: '%ls'; Using this path for updating: '%ls'.",
- installDirUpdater, secureUpdaterPath));
- DeleteSecureUpdater(secureUpdaterPath);
- result = CopyFileW(installDirUpdater, secureUpdaterPath, FALSE);
- }
-
- if (!result) {
- LOG_WARN(("Could not copy path to secure location. (%d)",
- GetLastError()));
- if (!WriteStatusFailure(argv[4], SERVICE_COULD_NOT_COPY_UPDATER)) {
- LOG_WARN(("Could not write update.status could not copy updater error"));
- }
- } else {
-
- // We obtained the path and copied it successfully, update the path to
- // use for the service update.
- argv[3] = secureUpdaterPath;
-
- WCHAR installDirUpdaterINIPath[MAX_PATH + 1] = { L'\0' };
- WCHAR secureUpdaterINIPath[MAX_PATH + 1] = { L'\0' };
- if (PathGetSiblingFilePath(secureUpdaterINIPath, secureUpdaterPath,
- L"updater.ini") &&
- PathGetSiblingFilePath(installDirUpdaterINIPath, installDirUpdater,
- L"updater.ini")) {
- // This is non fatal if it fails there is no real harm
- if (!CopyFileW(installDirUpdaterINIPath, secureUpdaterINIPath, FALSE)) {
- LOG_WARN(("Could not copy updater.ini from: '%ls' to '%ls'. (%d)",
- installDirUpdaterINIPath, secureUpdaterINIPath, GetLastError()));
- }
- }
-
- result = ProcessSoftwareUpdateCommand(argc - 3, argv + 3);
- DeleteSecureUpdater(secureUpdaterPath);
- }
-
- // We might not reach here if the service install succeeded
- // because the service self updates itself and the service
- // installer will stop the service.
- LOG(("Service command %ls complete.", argv[2]));
- } else {
- LOG_WARN(("Service command not recognized: %ls.", argv[2]));
- // result is already set to FALSE
- }
-
- LOG(("service command %ls complete with result: %ls.",
- argv[1], (result ? L"Success" : L"Failure")));
- return TRUE;
-}
diff --git a/toolkit/components/maintenanceservice/workmonitor.h b/toolkit/components/maintenanceservice/workmonitor.h
deleted file mode 100644
index ac4cd679b..000000000
--- a/toolkit/components/maintenanceservice/workmonitor.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* 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/. */
-
-BOOL ExecuteServiceCommand(int argc, LPWSTR *argv);