Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
core
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
LibreOffice
core
Commits
7eca4fa0
Kaydet (Commit)
7eca4fa0
authored
Ara 27, 2016
tarafından
Markus Mohrhard
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
get the update service working
Change-Id: I25921090083f20c4bb416f9cfdd5ec6400a27a21
üst
19066caf
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
344 additions
and
188 deletions
+344
-188
Repository.mk
Repository.mk
+3
-0
Executable_update_service.mk
onlineupdate/Executable_update_service.mk
+28
-0
Module_onlineupdate.mk
onlineupdate/Module_onlineupdate.mk
+1
-0
certificatecheck.cxx
onlineupdate/source/service/certificatecheck.cxx
+18
-18
maintenanceservice.cxx
onlineupdate/source/service/maintenanceservice.cxx
+37
-33
registrycertificates.cxx
onlineupdate/source/service/registrycertificates.cxx
+60
-27
servicebase.cxx
onlineupdate/source/service/servicebase.cxx
+11
-12
servicebase.hxx
onlineupdate/source/service/servicebase.hxx
+1
-1
serviceinstall.cxx
onlineupdate/source/service/serviceinstall.cxx
+123
-83
windowsHelper.hxx
onlineupdate/source/service/windowsHelper.hxx
+48
-0
workmonitor.cxx
onlineupdate/source/service/workmonitor.cxx
+14
-14
No files found.
Repository.mk
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -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) \
...
...
onlineupdate/Executable_update_service.mk
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -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,\
...
...
onlineupdate/Module_onlineupdate.mk
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -18,6 +18,7 @@ $(eval $(call gb_Module_add_targets,onlineupdate,\
StaticLibrary_winhelper )\
Executable_mar \
Executable_updater \
Executable_update_service \
))
endif
...
...
onlineupdate/source/service/certificatecheck.cxx
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -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
;
...
...
onlineupdate/source/service/maintenanceservice.cxx
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -12,15 +12,15 @@
#include "maintenanceservice.hxx"
#include "servicebase.hxx"
#include "workmonitor.hxx"
#include "uachelper.h
xx
"
#include "updatehelper.h
xx
"
#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
);
...
...
onlineupdate/source/service/registrycertificates.cxx
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -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.h
xx
"
#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
;
}
}
ns
AutoRegKey
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
);
ns
AutoRegKey
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
;
}
onlineupdate/source/service/servicebase.cxx
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -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
;
}
...
...
onlineupdate/source/service/servicebase.hxx
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <windows.h>
#include "updatelogging.h
xx
"
#include "updatelogging.h"
BOOL
PathAppendSafe
(
LPWSTR
base
,
LPCWSTR
extra
);
BOOL
VerifySameFiles
(
LPCWSTR
file1Path
,
LPCWSTR
file2Path
,
BOOL
&
sameContent
);
...
...
onlineupdate/source/service/serviceinstall.cxx
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -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
::
UniqueP
tr
<
char
[]
>
fileVersionInfo
(
new
char
[
fileVersionInfoSize
]);
std
::
unique_p
tr
<
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
::
UniqueP
tr
<
char
[]
>
serviceConfigBuffer
(
new
char
[
bytesNeeded
]);
if
(
!
QueryServiceConfigW
(
schService
,
reinterpret_cast
<
QUERY_SERVICE_CONFIGW
*>
(
serviceConfigBuffer
.
get
()),
std
::
unique_p
tr
<
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
)
{
...
...
onlineupdate/source/service/windowsHelper.hxx
0 → 100644
Dosyayı görüntüle @
7eca4fa0
/* -*- 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: */
onlineupdate/source/service/workmonitor.cxx
Dosyayı görüntüle @
7eca4fa0
...
...
@@ -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
;
}
ns
AutoHandle
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
;
}
ns
AutoHandle
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
"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment