Bug 1177861 - remove remaining unused declarations and cleanup update staging. r=spohl

--HG--
rename : toolkit/components/maintenanceservice/certificatecheck.cpp => toolkit/mozapps/update/common/certificatecheck.cpp
rename : toolkit/components/maintenanceservice/certificatecheck.h => toolkit/mozapps/update/common/certificatecheck.h
rename : toolkit/components/maintenanceservice/registrycertificates.cpp => toolkit/mozapps/update/common/registrycertificates.cpp
rename : toolkit/components/maintenanceservice/registrycertificates.h => toolkit/mozapps/update/common/registrycertificates.h
This commit is contained in:
Robert Strong 2015-08-11 14:30:35 -07:00
Родитель ceabbae040
Коммит b7924a4a24
14 изменённых файлов: 201 добавлений и 269 удалений

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

@ -7,9 +7,7 @@
Program('maintenanceservice')
SOURCES += [
'certificatecheck.cpp',
'maintenanceservice.cpp',
'registrycertificates.cpp',
'servicebase.cpp',
'serviceinstall.cpp',
'workmonitor.cpp',

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

@ -206,23 +206,6 @@ StartUpdateProcess(int argc,
si.wShowWindow = SW_HIDE;
}
// We move the updater.ini file out of the way because we will handle
// executing PostUpdate through the service. We handle PostUpdate from
// the service because there are some per user things that happen that
// can't run in session 0 which we run updater.exe in.
// Once we are done running updater.exe we rename updater.ini back so
// that if there were any errors the next updater.exe will run correctly.
WCHAR updaterINI[MAX_PATH + 1];
WCHAR updaterINITemp[MAX_PATH + 1];
BOOL selfHandlePostUpdate = FALSE;
// We use the updater.ini from the same directory as the updater.exe
// because of background updates.
if (PathGetSiblingFilePath(updaterINI, argv[0], L"updater.ini") &&
PathGetSiblingFilePath(updaterINITemp, argv[0], L"updater.tmp")) {
selfHandlePostUpdate = MoveFileExW(updaterINI, updaterINITemp,
MOVEFILE_REPLACE_EXISTING);
}
// 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.
@ -297,37 +280,6 @@ StartUpdateProcess(int argc,
argv[0], cmdLine, lastError));
}
// Now that we're done with the update, restore back the updater.ini file
// We use it ourselves, and also we want it back in case we had any type
// of error so that the normal update process can use it.
if (selfHandlePostUpdate) {
MoveFileExW(updaterINITemp, updaterINI, MOVEFILE_REPLACE_EXISTING);
// Only run the PostUpdate if the update was successful
if (updateWasSuccessful && argc > index) {
LPCWSTR updateInfoDir = argv[1];
bool stagingUpdate = IsUpdateBeingStaged(argc, argv);
// Launch the PostProcess with admin access in session 0. This is
// actually launching the post update process but it takes in the
// callback app path to figure out where to apply to.
// The PostUpdate process with user only access will be done inside
// the unelevated updater.exe after the update process is complete
// from the service. We don't know here which session to start
// the user PostUpdate process from.
// Note that we don't need to do this if we're just staging the
// update in the background, as the PostUpdate step runs when
// performing the replacing in that case.
if (!stagingUpdate) {
LOG(("Launching post update process as the service in session 0."));
if (!LaunchWinPostProcess(installDir, updateInfoDir, true, nullptr)) {
LOG_WARN(("The post update process could not be launched."
" installDir: %ls, updateInfoDir: %ls",
installDir, updateInfoDir));
}
}
}
}
// Empty value on putenv is how you remove an env variable in Windows
putenv(const_cast<char*>("MOZ_USING_SERVICE="));

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

@ -9,7 +9,7 @@
#include <wintrust.h>
#include "certificatecheck.h"
#include "servicebase.h"
#include "updatelogging.h"
#pragma comment(lib, "wintrust.lib")
#pragma comment(lib, "crypt32.lib")
@ -123,7 +123,7 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
CertificateCheckInfo &infoToMatch)
{
DWORD dwData;
LPTSTR szName = nullptr;
LPWSTR szName = nullptr;
if (infoToMatch.issuer) {
// Pass in nullptr to get the needed size of the issuer buffer.
@ -138,7 +138,7 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
}
// Allocate memory for Issuer name buffer.
LPTSTR szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR));
szName = (LPWSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR));
if (!szName) {
LOG_WARN(("Unable to allocate memory for issuer name. (%d)",
GetLastError()));
@ -146,7 +146,7 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
}
// Get Issuer name.
if (!CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE,
if (!CertGetNameStringW(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG, nullptr, szName, dwData)) {
LOG_WARN(("CertGetNameString failed. (%d)", GetLastError()));
LocalFree(szName);
@ -174,7 +174,7 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
}
// Allocate memory for the name buffer.
szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR));
szName = (LPWSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR));
if (!szName) {
LOG_WARN(("Unable to allocate memory for subject name. (%d)",
GetLastError()));
@ -182,7 +182,7 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
}
// Obtain the name.
if (!(CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
if (!(CertGetNameStringW(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
nullptr, szName, dwData))) {
LOG_WARN(("CertGetNameString failed. (%d)", GetLastError()));
LocalFree(szName);
@ -204,23 +204,6 @@ DoCertificateAttributesMatch(PCCERT_CONTEXT certContext,
return TRUE;
}
/**
* Duplicates the specified string
*
* @param inputString The string to duplicate
* @return The duplicated string which should be freed by the caller.
*/
LPWSTR
AllocateAndCopyWideString(LPCWSTR inputString)
{
LPWSTR outputString =
(LPWSTR)LocalAlloc(LPTR, (wcslen(inputString) + 1) * sizeof(WCHAR));
if (outputString) {
lstrcpyW(outputString, inputString);
}
return outputString;
}
/**
* Verifies the trust of the specified file path.
*

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

@ -82,6 +82,8 @@
#define WRITE_ERROR_DIR_ACCESS_DENIED 68
#define WRITE_ERROR_DELETE_BACKUP 69
#define WRITE_ERROR_EXTRACT 70
#define REMOVE_FILE_SPEC_ERROR 71
#define INVALID_STAGED_PARENT_ERROR 72
// Error codes 80 through 99 are reserved for nsUpdateService.js

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

@ -12,7 +12,9 @@ EXPORTS += [
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXPORTS += [
'certificatecheck.h',
'pathhash.h',
'registrycertificates.h',
'uachelper.h',
'updatehelper.cpp',
'updatehelper.h',
@ -20,10 +22,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
Library('updatecommon')
DEFINES['NS_NO_XPCOM'] = True
srcdir = '.'
include('sources.mozbuild')
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

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

@ -8,8 +8,7 @@
#include "registrycertificates.h"
#include "pathhash.h"
#include "nsWindowsHelpers.h"
#include "servicebase.h"
#include "updatelogging.h"
#include "updatehelper.h"
#define MAX_KEY_LENGTH 255
@ -41,10 +40,10 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath,
// to put those certificate attributes in and hence why we always
// force the non redirected registry under Wow6432Node.
// This flag is ignored on 32bit systems.
HKEY baseKeyRaw;
HKEY baseKey;
LONG retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
maintenanceServiceKey, 0,
KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw);
KEY_READ | KEY_WOW64_64KEY, &baseKey);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not open key. (%d)", retCode));
// Our tests run with a different apply directory for each test.
@ -52,7 +51,7 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath,
// allowed name/issuers.
retCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
TEST_ONLY_FALLBACK_KEY_PATH, 0,
KEY_READ | KEY_WOW64_64KEY, &baseKeyRaw);
KEY_READ | KEY_WOW64_64KEY, &baseKey);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not open fallback key. (%d)", retCode));
return FALSE;
@ -60,10 +59,10 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath,
LOG_WARN(("Fallback key present, skipping VerifyCertificateTrustForFile "
"check and the certificate attribute registry matching "
"check."));
RegCloseKey(baseKey);
return TRUE;
}
}
nsAutoRegKey baseKey(baseKeyRaw);
// Get the number of subkeys.
DWORD subkeyCount = 0;
@ -72,6 +71,7 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath,
nullptr, nullptr);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not query info key. (%d)", retCode));
RegCloseKey(baseKey);
return FALSE;
}
@ -84,17 +84,17 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath,
nullptr, nullptr, nullptr);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not enum certs. (%d)", retCode));
RegCloseKey(baseKey);
return FALSE;
}
// Open the subkey for the current certificate
HKEY subKeyRaw;
HKEY subKey;
retCode = RegOpenKeyExW(baseKey,
subkeyBuffer,
0,
KEY_READ | KEY_WOW64_64KEY,
&subKeyRaw);
nsAutoRegKey subKey(subKeyRaw);
&subKey);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not open subkey. (%d)", retCode));
continue; // Try the next subkey
@ -110,6 +110,7 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath,
(LPBYTE)name, &valueBufSize);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not obtain name from registry. (%d)", retCode));
RegCloseKey(subKey);
continue; // Try the next subkey
}
@ -119,6 +120,7 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath,
(LPBYTE)issuer, &valueBufSize);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Could not obtain issuer from registry. (%d)", retCode));
RegCloseKey(subKey);
continue; // Try the next subkey
}
@ -130,19 +132,23 @@ DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath,
retCode = CheckCertificateForPEFile(filePath, allowedCertificate);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Error on certificate check. (%d)", retCode));
RegCloseKey(subKey);
continue; // Try the next subkey
}
retCode = VerifyCertificateTrustForFile(filePath);
if (retCode != ERROR_SUCCESS) {
LOG_WARN(("Error on certificate trust check. (%d)", retCode));
RegCloseKey(subKey);
continue; // Try the next subkey
}
RegCloseKey(baseKey);
// Raise the roof, we found a match!
return TRUE;
}
RegCloseKey(baseKey);
// No certificates match, :'(
return FALSE;
}

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

@ -6,7 +6,9 @@ sources = []
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
sources += [
'certificatecheck.cpp',
'pathhash.cpp',
'registrycertificates.cpp',
'uachelper.cpp',
'updatehelper.cpp',
]

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

@ -21,8 +21,10 @@
using mozilla::MakeUnique;
using mozilla::UniquePtr;
WCHAR* MakeCommandLine(int argc, WCHAR **argv);
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra);
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer,
LPCWSTR siblingFilePath,
LPCWSTR newFileName);
/**
* Obtains the path of a file in the same directory as the specified file.
@ -53,137 +55,6 @@ PathGetSiblingFilePath(LPWSTR destinationBuffer,
return PathAppendSafe(destinationBuffer, newFileName);
}
/**
* Launch the post update application as the specified user (helper.exe).
* It takes in the path of the callback application to calculate the path
* of helper.exe. For service updates this is called from both the system
* account and the current user account.
*
* @param installationDir The path to the callback application binary.
* @param updateInfoDir The directory where update info is stored.
* @param forceSync If true even if the ini file specifies async, the
* process will wait for termination of PostUpdate.
* @param userToken The user token to run as, if nullptr the current
* user will be used.
* @return TRUE if there was no error starting the process.
*/
BOOL
LaunchWinPostProcess(const WCHAR *installationDir,
const WCHAR *updateInfoDir,
bool forceSync,
HANDLE userToken)
{
WCHAR workingDirectory[MAX_PATH + 1] = { L'\0' };
wcsncpy(workingDirectory, installationDir, MAX_PATH);
// Launch helper.exe to perform post processing (e.g. registry and log file
// modifications) for the update.
WCHAR inifile[MAX_PATH + 1] = { L'\0' };
wcsncpy(inifile, installationDir, MAX_PATH);
if (!PathAppendSafe(inifile, L"updater.ini")) {
return FALSE;
}
WCHAR exefile[MAX_PATH + 1];
WCHAR exearg[MAX_PATH + 1];
WCHAR exeasync[10];
bool async = true;
if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeRelPath", nullptr,
exefile, MAX_PATH + 1, inifile)) {
return FALSE;
}
if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeArg", nullptr, exearg,
MAX_PATH + 1, inifile)) {
return FALSE;
}
if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeAsync", L"TRUE",
exeasync,
sizeof(exeasync)/sizeof(exeasync[0]),
inifile)) {
return FALSE;
}
WCHAR exefullpath[MAX_PATH + 1] = { L'\0' };
wcsncpy(exefullpath, installationDir, MAX_PATH);
if (!PathAppendSafe(exefullpath, exefile)) {
return false;
}
WCHAR dlogFile[MAX_PATH + 1];
if (!PathGetSiblingFilePath(dlogFile, exefullpath, L"uninstall.update")) {
return FALSE;
}
WCHAR slogFile[MAX_PATH + 1] = { L'\0' };
wcsncpy(slogFile, updateInfoDir, MAX_PATH);
if (!PathAppendSafe(slogFile, L"update.log")) {
return FALSE;
}
WCHAR dummyArg[14] = { L'\0' };
wcsncpy(dummyArg, L"argv0ignored ", sizeof(dummyArg) / sizeof(dummyArg[0]) - 1);
size_t len = wcslen(exearg) + wcslen(dummyArg);
WCHAR *cmdline = (WCHAR *) malloc((len + 1) * sizeof(WCHAR));
if (!cmdline) {
return FALSE;
}
wcsncpy(cmdline, dummyArg, len);
wcscat(cmdline, exearg);
if (forceSync ||
!_wcsnicmp(exeasync, L"false", 6) ||
!_wcsnicmp(exeasync, L"0", 2)) {
async = false;
}
// We want to launch the post update helper app to update the Windows
// registry even if there is a failure with removing the uninstall.update
// file or copying the update.log file.
CopyFileW(slogFile, dlogFile, false);
STARTUPINFOW si = {sizeof(si), 0};
si.lpDesktop = L"";
PROCESS_INFORMATION pi = {0};
bool ok;
if (userToken) {
ok = CreateProcessAsUserW(userToken,
exefullpath,
cmdline,
nullptr, // no special security attributes
nullptr, // no special thread attributes
false, // don't inherit filehandles
0, // No special process creation flags
nullptr, // inherit my environment
workingDirectory,
&si,
&pi);
} else {
ok = CreateProcessW(exefullpath,
cmdline,
nullptr, // no special security attributes
nullptr, // no special thread attributes
false, // don't inherit filehandles
0, // No special process creation flags
nullptr, // inherit my environment
workingDirectory,
&si,
&pi);
}
free(cmdline);
if (ok) {
if (!async)
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return ok;
}
/**
* Starts the upgrade process for update of the service if it is
* already installed.

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

@ -2,12 +2,7 @@
* 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 LaunchWinPostProcess(const WCHAR *installationDir,
const WCHAR *updateInfoDir,
bool forceSync,
HANDLE userToken);
BOOL StartServiceUpdate(LPCWSTR installDir);
BOOL GetUpdateDirectoryPath(LPWSTR path);
DWORD LaunchServiceSoftwareUpdateCommand(int argc, LPCWSTR *argv);
BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
DWORD WaitForServiceStop(LPCWSTR serviceName, DWORD maxWaitSeconds);

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

@ -1079,10 +1079,9 @@ function shouldUseService() {
}
/**
* Determines if the service is is installed and enabled or not.
* Determines if the service is is installed.
*
* @return true if the service should be used for updates,
* is installed and enabled.
* @return true if the service is installed.
*/
function isServiceInstalled() {
if (AppConstants.MOZ_MAINTENANCE_SERVICE && AppConstants.platform == "win") {

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

@ -34,6 +34,7 @@
# define LOG_S "%S"
#include "../common/updatehelper.h"
#include "../common/certificatecheck.h"
#else
# include <unistd.h>
@ -132,45 +133,6 @@ CheckMsg(const NS_tchar *path, const char *expected)
return isMatch;
}
#ifdef XP_WIN
/**
* Verifies the trust of the specified file path.
*
* @param filePath The file path to check.
* @return ERROR_SUCCESS if successful, or the last error code otherwise.
*/
DWORD
VerifyCertificateTrustForFile(LPCWSTR filePath)
{
// Setup the file to check.
WINTRUST_FILE_INFO fileToCheck;
ZeroMemory(&fileToCheck, sizeof(fileToCheck));
fileToCheck.cbStruct = sizeof(WINTRUST_FILE_INFO);
fileToCheck.pcwszFilePath = filePath;
// Setup what to check, we want to check it is signed and trusted.
WINTRUST_DATA trustData;
ZeroMemory(&trustData, sizeof(trustData));
trustData.cbStruct = sizeof(trustData);
trustData.pPolicyCallbackData = nullptr;
trustData.pSIPClientData = nullptr;
trustData.dwUIChoice = WTD_UI_NONE;
trustData.fdwRevocationChecks = WTD_REVOKE_NONE;
trustData.dwUnionChoice = WTD_CHOICE_FILE;
trustData.dwStateAction = 0;
trustData.hWVTStateData = nullptr;
trustData.pwszURLReference = nullptr;
// no UI
trustData.dwUIContext = 0;
trustData.pFile = &fileToCheck;
GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
// Check if the file is signed by something that is trusted.
return WinVerifyTrust(nullptr, &policyGUID, &trustData);
}
#endif
int NS_main(int argc, NS_tchar **argv)
{
if (argc == 2) {
@ -187,6 +149,16 @@ int NS_main(int argc, NS_tchar **argv)
NS_tchar runFilePath[MAXPATHLEN];
NS_tsnprintf(runFilePath, sizeof(runFilePath)/sizeof(runFilePath[0]),
NS_T("%s.running"), exePath);
#ifdef XP_WIN
if (!NS_taccess(runFilePath, F_OK)) {
// This makes it possible to check if the post update process was
// launched twice which happens when the service performs an update.
NS_tchar runFilePathBak[MAXPATHLEN];
NS_tsnprintf(runFilePathBak, sizeof(runFilePathBak)/sizeof(runFilePathBak[0]),
NS_T("%s.bak"), runFilePath);
MoveFileExW(runFilePath, runFilePathBak, MOVEFILE_REPLACE_EXISTING);
}
#endif
WriteMsg(runFilePath, "running");
if (!NS_tstrcmp(argv[1], NS_T("post-update-sync"))) {

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

@ -127,6 +127,11 @@ static bool sUseHardLinks = true;
#endif
#ifdef XP_WIN
#include "registrycertificates.h"
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra);
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer,
LPCWSTR siblingFilePath,
LPCWSTR newFileName);
#include "updatehelper.h"
// Closes the handle if valid and if the updater is elevated returns with the
@ -138,6 +143,7 @@ static bool sUseHardLinks = true;
CloseHandle(handle); \
} \
if (_waccess(path, F_OK) == 0 && NS_tremove(path) != 0) { \
LogFinish(); \
return retCode; \
} \
}
@ -1813,6 +1819,129 @@ PatchIfFile::Finish(int status)
#include "nsWindowsHelpers.h"
#include "uachelper.h"
#include "pathhash.h"
/**
* Launch the post update application (helper.exe). It takes in the path of the
* callback application to calculate the path of helper.exe. For service updates
* this is called from both the system account and the current user account.
*
* @param installationDir The path to the callback application binary.
* @param updateInfoDir The directory where update info is stored.
* @return true if there was no error starting the process.
*/
bool
LaunchWinPostProcess(const WCHAR *installationDir,
const WCHAR *updateInfoDir)
{
WCHAR workingDirectory[MAX_PATH + 1] = { L'\0' };
wcsncpy(workingDirectory, installationDir, MAX_PATH);
// Launch helper.exe to perform post processing (e.g. registry and log file
// modifications) for the update.
WCHAR inifile[MAX_PATH + 1] = { L'\0' };
wcsncpy(inifile, installationDir, MAX_PATH);
if (!PathAppendSafe(inifile, L"updater.ini")) {
return false;
}
WCHAR exefile[MAX_PATH + 1];
WCHAR exearg[MAX_PATH + 1];
WCHAR exeasync[10];
bool async = true;
if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeRelPath", nullptr,
exefile, MAX_PATH + 1, inifile)) {
return false;
}
if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeArg", nullptr, exearg,
MAX_PATH + 1, inifile)) {
return false;
}
if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeAsync", L"TRUE",
exeasync,
sizeof(exeasync)/sizeof(exeasync[0]),
inifile)) {
return false;
}
// Verify that exeFile doesn't contain relative paths
if (wcsstr(exefile, L"..") != nullptr) {
return false;
}
WCHAR exefullpath[MAX_PATH + 1] = { L'\0' };
wcsncpy(exefullpath, installationDir, MAX_PATH);
if (!PathAppendSafe(exefullpath, exefile)) {
return false;
}
#if !defined(TEST_UPDATER)
if (sUsingService &&
!DoesBinaryMatchAllowedCertificates(installationDir, exefullpath)) {
return false;
}
#endif
WCHAR dlogFile[MAX_PATH + 1];
if (!PathGetSiblingFilePath(dlogFile, exefullpath, L"uninstall.update")) {
return false;
}
WCHAR slogFile[MAX_PATH + 1] = { L'\0' };
wcsncpy(slogFile, updateInfoDir, MAX_PATH);
if (!PathAppendSafe(slogFile, L"update.log")) {
return false;
}
WCHAR dummyArg[14] = { L'\0' };
wcsncpy(dummyArg, L"argv0ignored ", sizeof(dummyArg) / sizeof(dummyArg[0]) - 1);
size_t len = wcslen(exearg) + wcslen(dummyArg);
WCHAR *cmdline = (WCHAR *) malloc((len + 1) * sizeof(WCHAR));
if (!cmdline) {
return false;
}
wcsncpy(cmdline, dummyArg, len);
wcscat(cmdline, exearg);
if (sUsingService ||
!_wcsnicmp(exeasync, L"false", 6) ||
!_wcsnicmp(exeasync, L"0", 2)) {
async = false;
}
// We want to launch the post update helper app to update the Windows
// registry even if there is a failure with removing the uninstall.update
// file or copying the update.log file.
CopyFileW(slogFile, dlogFile, false);
STARTUPINFOW si = {sizeof(si), 0};
si.lpDesktop = L"";
PROCESS_INFORMATION pi = {0};
bool ok = CreateProcessW(exefullpath,
cmdline,
nullptr, // no special security attributes
nullptr, // no special thread attributes
false, // don't inherit filehandles
0, // No special process creation flags
nullptr, // inherit my environment
workingDirectory,
&si,
&pi);
free(cmdline);
if (ok) {
if (!async) {
WaitForSingleObject(pi.hProcess, INFINITE);
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return ok;
}
#endif
static void
@ -2535,6 +2664,28 @@ int NS_main(int argc, NS_tchar **argv)
LOG(("INSTALLATION DIRECTORY " LOG_S, gInstallDirPath));
LOG(("WORKING DIRECTORY " LOG_S, gWorkingDirPath));
#if defined(XP_WIN)
if (sReplaceRequest || sStagedUpdate) {
NS_tchar stagedParent[MAX_PATH];
NS_tsnprintf(stagedParent, sizeof(stagedParent)/sizeof(stagedParent[0]),
NS_T("%s"), gWorkingDirPath);
if (!PathRemoveFileSpecW(stagedParent)) {
WriteStatusFile(REMOVE_FILE_SPEC_ERROR);
LOG(("Error calling PathRemoveFileSpecW: %d", GetLastError()));
LogFinish();
return 1;
}
if (_wcsnicmp(stagedParent, gInstallDirPath, MAX_PATH) != 0) {
WriteStatusFile(INVALID_STAGED_PARENT_ERROR);
LOG(("Stage and Replace requests require that the working directory " \
"is a sub-directory of the installation directory! Exiting"));
LogFinish();
return 1;
}
}
#endif
#ifdef MOZ_WIDGET_GONK
const char *prioEnv = getenv("MOZ_UPDATER_PRIO");
if (prioEnv) {
@ -2828,8 +2979,7 @@ int NS_main(int argc, NS_tchar **argv)
bool updateStatusSucceeded = false;
if (IsUpdateStatusSucceeded(updateStatusSucceeded) &&
updateStatusSucceeded) {
if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath, false,
nullptr)) {
if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) {
fprintf(stderr, "The post update process which runs as the user"
" for service update could not be launched.");
}
@ -3224,6 +3374,10 @@ int NS_main(int argc, NS_tchar **argv)
if (argc > callbackIndex) {
#if defined(XP_WIN)
if (gSucceeded) {
if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) {
fprintf(stderr, "The post update process was not launched");
}
// The service update will only be executed if it is already installed.
// For first time installs of the service, the install will happen from
// the PostUpdate process. We do the service update process here
@ -3232,10 +3386,6 @@ int NS_main(int argc, NS_tchar **argv)
// the service to a newer version in that case. If we are not running
// through the service, then MOZ_USING_SERVICE will not exist.
if (!sUsingService) {
if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath, false, nullptr)) {
LOG(("NS_main: The post update process could not be launched."));
}
StartServiceUpdate(gInstallDirPath);
}
}