summaryrefslogtreecommitdiff
path: root/onlineupdate/source/service/serviceinstall.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'onlineupdate/source/service/serviceinstall.cxx')
-rw-r--r--onlineupdate/source/service/serviceinstall.cxx206
1 files changed, 123 insertions, 83 deletions
diff --git a/onlineupdate/source/service/serviceinstall.cxx b/onlineupdate/source/service/serviceinstall.cxx
index 6e8a598ee995..cf7fef354186 100644
--- a/onlineupdate/source/service/serviceinstall.cxx
+++ b/onlineupdate/source/service/serviceinstall.cxx
@@ -10,18 +10,58 @@
// Used for DNLEN and UNLEN
#include <lm.h>
-#include <nsWindowsHelpers.h>
-#include "mozilla/UniquePtr.h"
-
#include "serviceinstall.hxx"
#include "servicebase.hxx"
-#include "updatehelper.hxx"
-#include "shellapi.hxx"
-#include "readstrings.hxx"
-#include "errors.hxx"
+#include "updatehelper.h"
+#include "shellapi.h"
+#include "readstrings.h"
+#include "errors.h"
+
+#include <memory>
#pragma comment(lib, "version.lib")
+namespace {
+
+struct AutoServiceHandle
+{
+ AutoServiceHandle(SC_HANDLE handle):
+ mHandle(handle)
+ {
+ }
+
+ ~AutoServiceHandle()
+ {
+ releaseHandle(mHandle);
+ }
+
+ void releaseHandle(SC_HANDLE handle)
+ {
+ if (handle != nullptr)
+ CloseServiceHandle(handle);
+ }
+
+ SC_HANDLE get() const
+ {
+ return mHandle;
+ }
+
+ operator bool() const
+ {
+ return mHandle != nullptr;
+ }
+
+ void reset(SC_HANDLE handle = nullptr)
+ {
+ releaseHandle(mHandle);
+ mHandle = handle;
+ }
+
+ SC_HANDLE mHandle;
+};
+
+}
+
/**
* A wrapper function to read strings for the maintenance service.
*
@@ -30,19 +70,19 @@
* @return OK on success
*/
static int
-ReadMaintenanceServiceStrings(LPCWSTR path,
+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,
+ int result = ReadStrings(path, kServiceKeys,
kNumStrings, serviceStrings);
if (result != OK) {
serviceStrings[0][0] = '\0';
}
- strncpy(results->serviceDescription,
+ strncpy(results->serviceDescription,
serviceStrings[0], MAX_TEXT_LEN - 1);
results->serviceDescription[MAX_TEXT_LEN - 1] = '\0';
return result;
@@ -51,7 +91,7 @@ ReadMaintenanceServiceStrings(LPCWSTR path,
/**
* 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
@@ -60,27 +100,27 @@ ReadMaintenanceServiceStrings(LPCWSTR path,
* @return TRUE if successful
*/
static BOOL
-GetVersionNumberFromPath(LPWSTR path, DWORD &A, DWORD &B,
- DWORD &C, DWORD &D)
+GetVersionNumberFromPath(LPWSTR path, DWORD &A, DWORD &B,
+ DWORD &C, DWORD &D)
{
DWORD fileVersionInfoSize = GetFileVersionInfoSizeW(path, 0);
- mozilla::UniquePtr<char[]> fileVersionInfo(new char[fileVersionInfoSize]);
+ std::unique_ptr<char[]> fileVersionInfo(new char[fileVersionInfoSize]);
if (!GetFileVersionInfoW(path, 0, fileVersionInfoSize,
fileVersionInfo.get())) {
- LOG_WARN(("Could not obtain file info of old service. (%d)",
+ LOG_WARN(("Could not obtain file info of old service. (%d)",
GetLastError()));
return FALSE;
}
- VS_FIXEDFILEINFO *fixedFileInfo =
+ VS_FIXEDFILEINFO *fixedFileInfo =
reinterpret_cast<VS_FIXEDFILEINFO *>(fileVersionInfo.get());
UINT size;
- if (!VerQueryValueW(fileVersionInfo.get(), L"\\",
+ if (!VerQueryValueW(fileVersionInfo.get(), L"\\",
reinterpret_cast<LPVOID*>(&fixedFileInfo), &size)) {
- LOG_WARN(("Could not query file version info of old service. (%d)",
+ LOG_WARN(("Could not query file version info of old service. (%d)",
GetLastError()));
return FALSE;
- }
+ }
A = HIWORD(fixedFileInfo->dwFileVersionMS);
B = LOWORD(fixedFileInfo->dwFileVersionMS);
@@ -93,7 +133,7 @@ GetVersionNumberFromPath(LPWSTR path, DWORD &A, DWORD &B,
* 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
+ * @param serviceHandle A handle to an opened service with
* SERVICE_CHANGE_CONFIG access right
* @param TRUE on succcess.
*/
@@ -101,7 +141,7 @@ BOOL
UpdateServiceDescription(SC_HANDLE serviceHandle)
{
WCHAR updaterINIPath[MAX_PATH + 1];
- if (!GetModuleFileNameW(nullptr, updaterINIPath,
+ if (!GetModuleFileNameW(nullptr, updaterINIPath,
sizeof(updaterINIPath) /
sizeof(updaterINIPath[0]))) {
LOG_WARN(("Could not obtain module filename when attempting to "
@@ -126,7 +166,7 @@ UpdateServiceDescription(SC_HANDLE serviceHandle)
"service description. (%d)", GetLastError()));
return FALSE;
}
-
+
MaintenanceServiceStringTable serviceStrings;
int rv = ReadMaintenanceServiceStrings(updaterINIPath, &serviceStrings);
if (rv != OK || !strlen(serviceStrings.serviceDescription)) {
@@ -136,10 +176,10 @@ UpdateServiceDescription(SC_HANDLE serviceHandle)
}
WCHAR serviceDescription[MAX_TEXT_LEN];
- if (!MultiByteToWideChar(CP_UTF8, 0,
+ if (!MultiByteToWideChar(CP_UTF8, 0,
serviceStrings.serviceDescription, -1,
serviceDescription,
- sizeof(serviceDescription) /
+ sizeof(serviceDescription) /
sizeof(serviceDescription[0]))) {
LOG_WARN(("Could not convert description to wide string format. (%d)",
GetLastError()));
@@ -148,8 +188,8 @@ UpdateServiceDescription(SC_HANDLE serviceHandle)
SERVICE_DESCRIPTIONW descriptionConfig;
descriptionConfig.lpDescription = serviceDescription;
- if (!ChangeServiceConfig2W(serviceHandle,
- SERVICE_CONFIG_DESCRIPTION,
+ if (!ChangeServiceConfig2W(serviceHandle,
+ SERVICE_CONFIG_DESCRIPTION,
&descriptionConfig)) {
LOG_WARN(("Could not change service config. (%d)", GetLastError()));
return FALSE;
@@ -235,7 +275,7 @@ BOOL
SvcInstall(SvcInstallAction action)
{
// Get a handle to the local computer SCM database with full access rights.
- nsAutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr,
+ AutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr,
SC_MANAGER_ALL_ACCESS));
if (!schSCManager) {
LOG_WARN(("Could not open service manager. (%d)", GetLastError()));
@@ -243,8 +283,8 @@ SvcInstall(SvcInstallAction action)
}
WCHAR newServiceBinaryPath[MAX_PATH + 1];
- if (!GetModuleFileNameW(nullptr, newServiceBinaryPath,
- sizeof(newServiceBinaryPath) /
+ if (!GetModuleFileNameW(nullptr, newServiceBinaryPath,
+ sizeof(newServiceBinaryPath) /
sizeof(newServiceBinaryPath[0]))) {
LOG_WARN(("Could not obtain module filename when attempting to "
"install service. (%d)",
@@ -253,8 +293,8 @@ SvcInstall(SvcInstallAction action)
}
// Check if we already have the service installed.
- nsAutoServiceHandle schService(OpenServiceW(schSCManager,
- SVC_NAME,
+ AutoServiceHandle schService(OpenServiceW(schSCManager.get(),
+ SVC_NAME,
SERVICE_ALL_ACCESS));
DWORD lastError = GetLastError();
if (!schService && ERROR_SERVICE_DOES_NOT_EXIST != lastError) {
@@ -262,13 +302,13 @@ SvcInstall(SvcInstallAction action)
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
+ // or have been changed after the installation. This will reset the
// permissions back to allow limited user accounts.
- if (!SetUserAccessServiceDACL(schService)) {
+ if (!SetUserAccessServiceDACL(schService.get())) {
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()));
@@ -276,31 +316,31 @@ SvcInstall(SvcInstallAction action)
// The service exists and we opened it
DWORD bytesNeeded;
- if (!QueryServiceConfigW(schService, nullptr, 0, &bytesNeeded) &&
+ if (!QueryServiceConfigW(schService.get(), 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
+ // 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()),
+ std::unique_ptr<char[]> serviceConfigBuffer(new char[bytesNeeded]);
+ if (!QueryServiceConfigW(schService.get(),
+ 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 =
+ 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,
+ if (!FixServicePath(schService.get(), serviceConfig.lpBinaryPathName,
servicePathWasWrong)) {
LOG_WARN(("Could not fix service path. This should never happen. (%d)",
GetLastError()));
@@ -329,31 +369,31 @@ SvcInstall(SvcInstallAction action)
// 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,
+ DWORD newA, newB, newC, newD;
+ BOOL obtainedExistingVersionInfo =
+ GetVersionNumberFromPath(serviceConfig.lpBinaryPathName,
+ existingA, existingB,
existingC, existingD);
- if (!GetVersionNumberFromPath(newServiceBinaryPath, newA,
+ 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
+ // If we couldn't get the old version info then we assume we should
// replace it.
if (ForceInstallSvc == action ||
- !obtainedExistingVersionInfo ||
+ !obtainedExistingVersionInfo ||
(existingA < newA) ||
(existingA == newA && existingB < newB) ||
- (existingA == newA && existingB == newB &&
+ (existingA == newA && existingB == newB &&
existingC < newC) ||
- (existingA == newA && existingB == newB &&
+ (existingA == newA && existingB == newB &&
existingC == newC && existingD < newD)) {
// We have a newer updater, so update the description from the INI file.
- UpdateServiceDescription(schService);
+ UpdateServiceDescription(schService.get());
schService.reset();
if (!StopService()) {
@@ -371,7 +411,7 @@ SvcInstall(SvcInstallAction action)
// 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,
+ 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 "
@@ -383,9 +423,9 @@ SvcInstall(SvcInstallAction action)
// 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
+ // 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 =
+ LPWSTR oldServiceBinaryTempPath =
new WCHAR[len + 1];
memset(oldServiceBinaryTempPath, 0, (len + 1) * sizeof (WCHAR));
wcsncpy(oldServiceBinaryTempPath, serviceConfig.lpBinaryPathName, len);
@@ -393,11 +433,11 @@ SvcInstall(SvcInstallAction action)
wcsncpy(oldServiceBinaryTempPath + len - 3, L"old", 3);
// Move the current (old) service file to the temp path.
- if (MoveFileExW(serviceConfig.lpBinaryPathName,
- oldServiceBinaryTempPath,
+ 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,
+ 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."
@@ -447,7 +487,7 @@ SvcInstall(SvcInstallAction action)
LOG_WARN(("Call to delete the old file path failed: %ls.",
newServiceBinaryPath));
}
-
+
return result;
}
@@ -455,11 +495,11 @@ SvcInstall(SvcInstallAction action)
// 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;
+ 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
@@ -469,7 +509,7 @@ SvcInstall(SvcInstallAction action)
// 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,
+ schService.reset(CreateServiceW(schSCManager.get(), SVC_NAME, SVC_DISPLAY_NAME,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
newServiceBinaryPath, nullptr, nullptr,
@@ -479,16 +519,16 @@ SvcInstall(SvcInstallAction action)
"This error should never happen since a service install "
"should only be called when elevated. (%d)", GetLastError()));
return FALSE;
- }
+ }
- if (!SetUserAccessServiceDACL(schService)) {
+ if (!SetUserAccessServiceDACL(schService.get())) {
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);
+ UpdateServiceDescription(schService.get());
return TRUE;
}
@@ -502,7 +542,7 @@ BOOL
StopService()
{
// Get a handle to the local computer SCM database with full access rights.
- nsAutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr,
+ AutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr,
SC_MANAGER_ALL_ACCESS));
if (!schSCManager) {
LOG_WARN(("Could not open service manager. (%d)", GetLastError()));
@@ -510,17 +550,17 @@ StopService()
}
// Open the service
- nsAutoServiceHandle schService(OpenServiceW(schSCManager, SVC_NAME,
+ AutoServiceHandle schService(OpenServiceW(schSCManager.get(), 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) &&
+ if (!ControlService(schService.get(), SERVICE_CONTROL_STOP, &status) &&
GetLastError() != ERROR_SERVICE_NOT_ACTIVE) {
LOG_WARN(("Error sending stop request. (%d)", GetLastError()));
}
@@ -548,7 +588,7 @@ BOOL
SvcUninstall()
{
// Get a handle to the local computer SCM database with full access rights.
- nsAutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr,
+ AutoServiceHandle schSCManager(OpenSCManager(nullptr, nullptr,
SC_MANAGER_ALL_ACCESS));
if (!schSCManager) {
LOG_WARN(("Could not open service manager. (%d)", GetLastError()));
@@ -556,19 +596,19 @@ SvcUninstall()
}
// Open the service
- nsAutoServiceHandle schService(OpenServiceW(schSCManager, SVC_NAME,
+ AutoServiceHandle schService(OpenServiceW(schSCManager.get(), 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)) {
+ if (ControlService(schService.get(), SERVICE_CONTROL_STOP, &status)) {
do {
Sleep(status.dwWaitHint);
totalWaitTime += (status.dwWaitHint + 10);
@@ -577,11 +617,11 @@ SvcUninstall()
} else if (totalWaitTime > maxWaitTime) {
break;
}
- } while (QueryServiceStatus(schService, &status));
+ } while (QueryServiceStatus(schService.get(), &status));
}
// Delete the service or mark it for deletion
- BOOL deleted = DeleteService(schService);
+ BOOL deleted = DeleteService(schService.get());
if (!deleted) {
deleted = (GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE);
}
@@ -619,12 +659,12 @@ SetUserAccessServiceDACL(SC_HANDLE hService)
* @return ERROR_SUCCESS if successful
*/
DWORD
-SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl,
+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,
+ if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION,
&psd, 0, &needed)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
LOG_WARN(("Could not query service object security size. (%d)",
@@ -641,7 +681,7 @@ SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl,
}
// Get the actual security descriptor now
- if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION,
+ if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION,
psd, size, &needed)) {
LOG_WARN(("Could not allocate security descriptor. (%d)",
GetLastError()));
@@ -653,7 +693,7 @@ SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl,
PACL pacl = nullptr;
BOOL bDaclPresent = FALSE;
BOOL bDaclDefaulted = FALSE;
- if ( !GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
+ if ( !GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
&bDaclDefaulted)) {
LOG_WARN(("Could not obtain DACL. (%d)", GetLastError()));
return GetLastError();
@@ -682,8 +722,8 @@ SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl,
WCHAR domainName[DNLEN + 1] = { L'\0' };
DWORD accountNameSize = UNLEN + 1;
DWORD domainNameSize = DNLEN + 1;
- if (!LookupAccountSidW(nullptr, sid, accountName,
- &accountNameSize,
+ if (!LookupAccountSidW(nullptr, sid, accountName,
+ &accountNameSize,
domainName, &domainNameSize, &accountType)) {
LOG_WARN(("Could not lookup account Sid, will try Users. (%d)",
GetLastError()));
@@ -696,8 +736,8 @@ SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl,
// Build the ACE, BuildExplicitAccessWithName cannot fail so it is not logged.
EXPLICIT_ACCESS ea;
- BuildExplicitAccessWithNameW(&ea, accountName,
- SERVICE_START | SERVICE_STOP | GENERIC_READ,
+ 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) {