Kaydet (Commit) 7eca4fa0 authored tarafından Markus Mohrhard's avatar Markus Mohrhard

get the update service working

Change-Id: I25921090083f20c4bb416f9cfdd5ec6400a27a21
üst 19066caf
......@@ -93,6 +93,9 @@ $(eval $(call gb_Helper_register_executables_for_install,SDK,sdk, \
$(eval $(call gb_Helper_register_executables_for_install,OOO,brand, \
$(if $(ENABLE_ONLINE_UPDATE_MAR),\
mar \
$(if $(filter WNT,$(OS)), \
update_service \
) \
updater )\
$(call gb_Helper_optional,BREAKPAD,minidump_upload) \
$(call gb_Helper_optional,FUZZERS,wmffuzzer) \
......
......@@ -9,16 +9,44 @@
$(eval $(call gb_Executable_Executable,update_service))
$(eval $(call gb_Executable_set_targettype_gui,update_service,YES))
$(eval $(call gb_Executable_set_include,update_service,\
-I$(SRCDIR)/onlineupdate/source/libmar/src/ \
-I$(SRCDIR)/onlineupdate/source/libmar/verify/ \
-I$(SRCDIR)/onlineupdate/source/libmar/sign/ \
-I$(SRCDIR)/onlineupdate/source/update/common/ \
$$(INCLUDE) \
))
$(eval $(call gb_Executable_use_static_libraries,update_service,\
updatehelper \
winhelper \
))
$(eval $(call gb_Executable_add_libs,update_service,\
ws2_32.lib \
Crypt32.lib \
shell32.lib \
wintrust.lib \
version.lib \
wtsapi32.lib \
userenv.lib \
shlwapi.lib \
ole32.lib \
rpcrt4.lib \
comctl32.lib \
shlwapi.lib \
kernel32.lib \
advapi32.lib \
))
$(eval $(call gb_Executable_add_defs,update_service,\
-DUNICODE \
))
$(eval $(call gb_Executable_add_ldflags,update_service,\
/ENTRY:wmainCRTStartup \
))
$(eval $(call gb_Executable_add_cxxobjects,update_service,\
......
......@@ -18,6 +18,7 @@ $(eval $(call gb_Module_add_targets,onlineupdate,\
StaticLibrary_winhelper )\
Executable_mar \
Executable_updater \
Executable_update_service \
))
endif
......
......@@ -21,15 +21,15 @@ static const int ENCODING = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
*
* @param filePath The PE file path to check
* @param infoToMatch The acceptable information to match
* @return ERROR_SUCCESS if successful, ERROR_NOT_FOUND if the info
* @return ERROR_SUCCESS if successful, ERROR_NOT_FOUND if the info
* does not match, or the last error otherwise.
*/
DWORD
CheckCertificateForPEFile(LPCWSTR filePath,
CheckCertificateForPEFile(LPCWSTR filePath,
CertificateCheckInfo &infoToMatch)
{
HCERTSTORE certStore = nullptr;
HCRYPTMSG cryptMsg = nullptr;
HCRYPTMSG cryptMsg = nullptr;
PCCERT_CONTEXT certContext = nullptr;
PCMSG_SIGNER_INFO signerInfo = nullptr;
DWORD lastError = ERROR_SUCCESS;
......@@ -37,9 +37,9 @@ CheckCertificateForPEFile(LPCWSTR filePath,
// Get the HCERTSTORE and HCRYPTMSG from the signed file.
DWORD encoding, contentType, formatType;
BOOL result = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
filePath,
filePath,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_CONTENT_FLAG_ALL,
CERT_QUERY_CONTENT_FLAG_ALL,
0, &encoding, &contentType,
&formatType, &certStore, &cryptMsg, nullptr);
if (!result) {
......@@ -50,7 +50,7 @@ CheckCertificateForPEFile(LPCWSTR filePath,
// Pass in nullptr to get the needed signer information size.
DWORD signerInfoSize;
result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0,
result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0,
nullptr, &signerInfoSize);
if (!result) {
lastError = GetLastError();
......@@ -68,7 +68,7 @@ CheckCertificateForPEFile(LPCWSTR filePath,
// Get the signer information (PCMSG_SIGNER_INFO).
// In particular we want the issuer and serial number.
result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0,
result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0,
(PVOID)signerInfo, &signerInfoSize);
if (!result) {
lastError = GetLastError();
......@@ -77,10 +77,10 @@ CheckCertificateForPEFile(LPCWSTR filePath,
}
// Search for the signer certificate in the certificate store.
CERT_INFO certInfo;
CERT_INFO certInfo;
certInfo.Issuer = signerInfo->Issuer;
certInfo.SerialNumber = signerInfo->SerialNumber;
certContext = CertFindCertificateInStore(certStore, ENCODING, 0,
certContext = CertFindCertificateInStore(certStore, ENCODING, 0,
CERT_FIND_SUBJECT_CERT,
(PVOID)&certInfo, nullptr);
if (!certContext) {
......@@ -102,10 +102,10 @@ cleanup:
if (certContext) {
CertFreeCertificateContext(certContext);
}
if (certStore) {
if (certStore) {
CertCloseStore(certStore, 0);
}
if (cryptMsg) {
if (cryptMsg) {
CryptMsgClose(cryptMsg);
}
return lastError;
......@@ -118,8 +118,8 @@ cleanup:
* @param infoToMatch The acceptable information to match
* @return FALSE if the info does not match or if any error occurs in the check
*/
BOOL
DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
BOOL
DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
CertificateCheckInfo &infoToMatch)
{
DWORD dwData;
......@@ -127,7 +127,7 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
if (infoToMatch.issuer) {
// Pass in nullptr to get the needed size of the issuer buffer.
dwData = CertGetNameString(certContext,
dwData = CertGetNameString(certContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG, nullptr,
nullptr, 0);
......@@ -190,7 +190,7 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
}
// If the issuer does not match, return a failure.
if (!infoToMatch.name ||
if (!infoToMatch.name ||
wcscmp(szName, infoToMatch.name)) {
LocalFree(szName);
return FALSE;
......@@ -210,10 +210,10 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
* @param inputString The string to duplicate
* @return The duplicated string which should be freed by the caller.
*/
LPWSTR
LPWSTR
AllocateAndCopyWideString(LPCWSTR inputString)
{
LPWSTR outputString =
LPWSTR outputString =
(LPWSTR)LocalAlloc(LPTR, (wcslen(inputString) + 1) * sizeof(WCHAR));
if (outputString) {
lstrcpyW(outputString, inputString);
......@@ -243,7 +243,7 @@ VerifyCertificateTrustForFile(LPCWSTR filePath)
trustData.pPolicyCallbackData = nullptr;
trustData.pSIPClientData = nullptr;
trustData.dwUIChoice = WTD_UI_NONE;
trustData.fdwRevocationChecks = WTD_REVOKE_NONE;
trustData.fdwRevocationChecks = WTD_REVOKE_NONE;
trustData.dwUnionChoice = WTD_CHOICE_FILE;
trustData.dwStateAction = 0;
trustData.hWVTStateData = nullptr;
......
......@@ -12,15 +12,15 @@
#include "maintenanceservice.hxx"
#include "servicebase.hxx"
#include "workmonitor.hxx"
#include "uachelper.hxx"
#include "updatehelper.hxx"
#include "uachelper.h"
#include "updatehelper.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;
SERVICE_STATUS gSvcStatus = { 0 };
SERVICE_STATUS_HANDLE gSvcStatusHandle = nullptr;
HANDLE gWorkDoneEvent = nullptr;
HANDLE gThread = nullptr;
bool gServiceControlStopping = false;
......@@ -30,9 +30,14 @@ bool gServiceControlStopping = false;
BOOL GetLogDirectoryPath(WCHAR *path);
int
int
wmain(int argc, WCHAR **argv)
{
if (argc < 2)
{
LOG_WARN(("missing mandatory command line argument"));
return 1;
}
// If command-line parameter is "install", install the service
// or upgrade if already installed
// If command line parameter is "forceinstall", install the service
......@@ -66,7 +71,7 @@ wmain(int argc, WCHAR **argv)
LOG(("The service was installed successfully"));
LogFinish();
return 0;
}
}
if (!lstrcmpi(argv[1], L"upgrade")) {
WCHAR updatePath[MAX_PATH + 1];
......@@ -102,12 +107,12 @@ wmain(int argc, WCHAR **argv)
return 0;
}
SERVICE_TABLE_ENTRYW DispatchTable[] = {
{ SVC_NAME, (LPSERVICE_MAIN_FUNCTIONW) SvcMain },
{ nullptr, nullptr }
};
SERVICE_TABLE_ENTRYW DispatchTable[] = {
{ SVC_NAME, (LPSERVICE_MAIN_FUNCTIONW) SvcMain },
{ nullptr, nullptr }
};
// This call returns when the service has stopped.
// 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()));
......@@ -125,7 +130,7 @@ wmain(int argc, WCHAR **argv)
BOOL
GetLogDirectoryPath(WCHAR *path)
{
HRESULT hr = SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA, nullptr,
HRESULT hr = SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA, nullptr,
SHGFP_TYPE_CURRENT, path);
if (FAILED(hr)) {
return FALSE;
......@@ -175,7 +180,7 @@ GetBackupLogPath(LPWSTR path, LPCWSTR basePath, int logNumber)
* 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
*/
......@@ -203,14 +208,14 @@ BackupOldLogs(LPCWSTR basePath, int numLogsToKeep)
* 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.
* 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
* 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
......@@ -218,13 +223,12 @@ EnsureProcessTerminatedThread(LPVOID)
{
Sleep(5000);
exit(0);
return 0;
}
void
StartTerminationThread()
{
// If the process does not self terminate like it should, this thread
// 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);
......@@ -254,10 +258,10 @@ SvcMain(DWORD argc, LPWSTR *argv)
gSvcStatusHandle = RegisterServiceCtrlHandlerW(SVC_NAME, SvcCtrlHandler);
if (!gSvcStatusHandle) {
LOG_WARN(("RegisterServiceCtrlHandler failed. (%d)", GetLastError()));
ExecuteServiceCommand(argc, argv);
ExecuteServiceCommand(argc, argv);
LogFinish();
exit(1);
}
}
// These values will be re-used later in calls involving gSvcStatus
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
......@@ -282,7 +286,7 @@ SvcMain(DWORD argc, LPWSTR *argv)
// 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);
ExecuteServiceCommand(argc, argv);
LogFinish();
SetEvent(gWorkDoneEvent);
......@@ -298,14 +302,14 @@ SvcMain(DWORD argc, LPWSTR *argv)
/**
* 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,
ReportSvcStatus(DWORD currentState,
DWORD exitCode,
DWORD waitHint)
{
static DWORD dwCheckPoint = 1;
......@@ -314,11 +318,11 @@ ReportSvcStatus(DWORD currentState,
gSvcStatus.dwWin32ExitCode = exitCode;
gSvcStatus.dwWaitHint = waitHint;
if (SERVICE_START_PENDING == currentState ||
if (SERVICE_START_PENDING == currentState ||
SERVICE_STOP_PENDING == currentState) {
gSvcStatus.dwControlsAccepted = 0;
} else {
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_SHUTDOWN;
}
......@@ -334,8 +338,8 @@ ReportSvcStatus(DWORD currentState,
}
/**
* Since the SvcCtrlHandler should only spend at most 30 seconds before
* returning, this function does the service stop work for the SvcCtrlHandler.
* 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)
......@@ -363,15 +367,15 @@ SvcCtrlHandler(DWORD dwCtrl)
return;
}
// Handle the requested control code.
// 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
// 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);
......
......@@ -6,13 +6,46 @@
#include <stdlib.h>
#include <windows.h>
#include <memory>
#include "registrycertificates.hxx"
#include "pathhash.hxx"
#include "nsWindowsHelpers.hxx"
#include "pathhash.h"
#include "servicebase.hxx"
#include "updatehelper.hxx"
#include "updatehelper.h"
#define MAX_KEY_LENGTH 255
namespace {
struct AutoRegKey
{
AutoRegKey(HKEY key):
mKey(key)
{
}
~AutoRegKey()
{
releaseKey(mKey);
}
void releaseKey(HKEY key)
{
if (key != nullptr)
{
RegCloseKey(key);
}
}
HKEY mKey;
HKEY get()
{
return mKey;
}
};
}
/**
* Verifies if the file path matches any certificate stored in the registry.
*
......@@ -21,9 +54,9 @@
*/
BOOL
DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
{
{
WCHAR maintenanceServiceKey[MAX_PATH + 1];
if (!CalculateRegistryPathFromFilePath(basePathForUpdate,
if (!CalculateRegistryPathFromFilePath(basePathForUpdate,
maintenanceServiceKey)) {
return FALSE;
}
......@@ -35,15 +68,15 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
// force the non redirected registry under Wow6432Node.
// This flag is ignored on 32bit systems.
HKEY baseKeyRaw;
LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
maintenanceServiceKey, 0,
LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
maintenanceServiceKey, 0,
KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not open key. (%d)", retCode));
// Our tests run with a different apply directory for each test.
// We use this registry key on our test slaves to store the
// We use this registry key on our test slaves to store the
// allowed name/issuers.
retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
TEST_ONLY_FALLBACK_KEY_PATH, 0,
KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw);
if (retCode != ERROR_SUCCESS) {
......@@ -51,11 +84,11 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
return FALSE;
}
}
nsAutoRegKey baseKey(baseKeyRaw);
AutoRegKey baseKey(baseKeyRaw);
// Get the number of subkeys.
DWORD subkeyCount = 0;
retCode = RegQueryInfoKeyW(baseKey, nullptr, nullptr, nullptr, &subkeyCount,
retCode = RegQueryInfoKeyW(baseKey.get(), nullptr, nullptr, nullptr, &subkeyCount,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr);
if (retCode != ERROR_SUCCESS) {
......@@ -64,12 +97,12 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
}
// Enumerate the subkeys, each subkey represents an allowed certificate.
for (DWORD i = 0; i < subkeyCount; i++) {
for (DWORD i = 0; i < subkeyCount; i++) {
WCHAR subkeyBuffer[MAX_KEY_LENGTH];
DWORD subkeyBufferCount = MAX_KEY_LENGTH;
retCode = RegEnumKeyExW(baseKey, i, subkeyBuffer,
&subkeyBufferCount, nullptr,
nullptr, nullptr, nullptr);
DWORD subkeyBufferCount = MAX_KEY_LENGTH;
retCode = RegEnumKeyExW(baseKey.get(), i, subkeyBuffer,
&subkeyBufferCount, nullptr,
nullptr, nullptr, nullptr);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not enum certs. (%d)", retCode));
return FALSE;
......@@ -77,12 +110,12 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
// Open the subkey for the current certificate
HKEY subKeyRaw;
retCode = RegOpenKeyExW(baseKey,
subkeyBuffer,
0,
KEY_READ | KEY_WOW64_64KEY,
retCode = RegOpenKeyExW(baseKey.get(),
subkeyBuffer,
0,
KEY_READ | KEY_WOW64_64KEY,
&subKeyRaw);
nsAutoRegKey subKey(subKeyRaw);
AutoRegKey subKey(subKeyRaw);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not open subkey. (%d)", retCode));
continue; // Try the next subkey
......@@ -94,7 +127,7 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
WCHAR issuer[MAX_CHAR_COUNT] = { L'\0' };
// Get the name from the registry
retCode = RegQueryValueExW(subKey, L"name", 0, nullptr,
retCode = RegQueryValueExW(subKey.get(), L"name", 0, nullptr,
(LPBYTE)name, &valueBufSize);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not obtain name from registry. (%d)", retCode));
......@@ -103,7 +136,7 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
// Get the issuer from the registry
valueBufSize = MAX_CHAR_COUNT * sizeof(WCHAR);
retCode = RegQueryValueExW(subKey, L"issuer", 0, nullptr,
retCode = RegQueryValueExW(subKey.get(), L"issuer", 0, nullptr,
(LPBYTE)issuer, &valueBufSize);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not obtain issuer from registry. (%d)", retCode));
......@@ -111,8 +144,8 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
}
CertificateCheckInfo allowedCertificate = {
name,
issuer,
name,
issuer,
};
retCode = CheckCertificateForPEFile(filePath, allowedCertificate);
......@@ -128,9 +161,9 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
}
// Raise the roof, we found a match!
return TRUE;
return TRUE;
}
// No certificates match, :'(
return FALSE;
}
......@@ -3,10 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "servicebase.hxx"
#include "nsWindowsHelpers.hxx"
#include "windowsHelper.hxx"
// Shared code between applications and updater.exe
#include "nsWindowsRestart.cpp"
/**
* Verifies if 2 files are byte for byte equivalent.
......@@ -20,19 +19,19 @@ BOOL
VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent)
{
sameContent = FALSE;
nsAutoHandle file1(CreateFileW(file1Path, GENERIC_READ, FILE_SHARE_READ,
AutoHandle file1(CreateFileW(file1Path, GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, 0, nullptr));
if (INVALID_HANDLE_VALUE == file1) {
if (file1 == INVALID_HANDLE_VALUE) {
return FALSE;
}
nsAutoHandle file2(CreateFileW(file2Path, GENERIC_READ, FILE_SHARE_READ,
AutoHandle file2(CreateFileW(file2Path, GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, 0, nullptr));
if (INVALID_HANDLE_VALUE == file2) {
if (file2 == INVALID_HANDLE_VALUE) {
return FALSE;
}
DWORD fileSize1 = GetFileSize(file1, nullptr);
DWORD fileSize2 = GetFileSize(file2, nullptr);
DWORD fileSize1 = GetFileSize(file1.get(), nullptr);
DWORD fileSize2 = GetFileSize(file2.get(), nullptr);
if (INVALID_FILE_SIZE == fileSize1 || INVALID_FILE_SIZE == fileSize2) {
return FALSE;
}
......@@ -48,12 +47,12 @@ VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent)
DWORD leftOver = fileSize1 % COMPARE_BLOCKSIZE;
DWORD readAmount;
for (DWORD i = 0; i < numBlocks; i++) {
if (!ReadFile(file1, buf1, COMPARE_BLOCKSIZE, &readAmount, nullptr) ||
if (!ReadFile(file1.get(), buf1, COMPARE_BLOCKSIZE, &readAmount, nullptr) ||
readAmount != COMPARE_BLOCKSIZE) {
return FALSE;
}
if (!ReadFile(file2, buf2, COMPARE_BLOCKSIZE, &readAmount, nullptr) ||
if (!ReadFile(file2.get(), buf2, COMPARE_BLOCKSIZE, &readAmount, nullptr) ||
readAmount != COMPARE_BLOCKSIZE) {
return FALSE;
}
......@@ -65,12 +64,12 @@ VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent)
}
if (leftOver) {
if (!ReadFile(file1, buf1, leftOver, &readAmount, nullptr) ||
if (!ReadFile(file1.get(), buf1, leftOver, &readAmount, nullptr) ||
readAmount != leftOver) {
return FALSE;
}
if (!ReadFile(file2, buf2, leftOver, &readAmount, nullptr) ||
if (!ReadFile(file2.get(), buf2, leftOver, &readAmount, nullptr) ||
readAmount != leftOver) {
return FALSE;
}
......
......@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <windows.h>
#include "updatelogging.hxx"
#include "updatelogging.h"
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra);
BOOL VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent);
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* 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 INCLUDED_ONLINEUPDATE_SERVICE_WINDOWSHELPER_HXX
#define INCLUDED_ONLINEUPDATE_SERVICE_WINDOWSHELPER_HXX
struct AutoHandle
{
AutoHandle(HANDLE handle):
mHandle(handle)
{
}
~AutoHandle()
{
release(mHandle);
}
void release(HANDLE handle)
{
if (handle && handle != INVALID_HANDLE_VALUE)
{
CloseHandle(handle);
}
}
HANDLE get() const
{
return mHandle;
}
bool operator==(const AutoHandle& rhs)
{
return mHandle == rhs.mHandle;
}
HANDLE mHandle;
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
......@@ -7,6 +7,7 @@
#include <wtsapi32.h>
#include <userenv.h>
#include <shellapi.h>
#include <cstddef>
#pragma comment(lib, "wtsapi32.lib")
#pragma comment(lib, "userenv.lib")
......@@ -14,23 +15,22 @@
#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 "workmonitor.hxx"
#include "serviceinstall.hxx"
#include "servicebase.hxx"
#include "registrycertificates.hxx"
#include "uachelper.h"
#include "updatehelper.h"
#include "errors.h"
#include "windowsHelper.hxx"
// 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;
char16_t* MakeCommandLine(int argc, char16_t **argv);
wchar_t* MakeCommandLine(int argc, wchar_t **argv);
BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
LPCWSTR newFileName);
/*
......@@ -53,20 +53,20 @@ IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying)
return FALSE;
}
nsAutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ,
AutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ,
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, 0, nullptr));
if (INVALID_HANDLE_VALUE == statusFile) {
if (statusFile == INVALID_HANDLE_VALUE) {
LOG_WARN(("Could not open update.status file"));
return FALSE;
}
char buf[32] = { 0 };
DWORD read;
if (!ReadFile(statusFile, buf, sizeof(buf), &read, nullptr)) {
if (!ReadFile(statusFile.get(), buf, sizeof(buf), &read, nullptr)) {
LOG_WARN(("Could not read from update.status file"));
return FALSE;
}
......@@ -378,9 +378,9 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
return FALSE;
}
nsAutoHandle noWriteLock(CreateFileW(argv[0], GENERIC_READ, FILE_SHARE_READ,
AutoHandle noWriteLock(CreateFileW(argv[0], GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, 0, nullptr));
if (INVALID_HANDLE_VALUE == noWriteLock) {
if (noWriteLock == INVALID_HANDLE_VALUE) {
LOG_WARN(("Could not set no write sharing access on file. (%d)",
GetLastError()));
if (!WriteStatusFailure(argv[1],
......@@ -401,7 +401,7 @@ ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
result = FALSE;
}
BOOL updaterIsCorrect;
BOOL updaterIsCorrect = FALSE;
if (result && !VerifySameFiles(argv[0], installDirUpdater,
updaterIsCorrect)) {
LOG_WARN(("Error checking if the updaters are the same.\n"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment