12#pragma comment(lib, "wtsapi32.lib")
13#pragma comment(lib, "userenv.lib")
14#pragma comment(lib, "shlwapi.lib")
15#pragma comment(lib, "ole32.lib")
16#pragma comment(lib, "rpcrt4.lib")
49 WCHAR updateStatusFilePath[
MAX_PATH + 1] = {L
'\0'};
50 wcsncpy(updateStatusFilePath, updateDirPath,
MAX_PATH);
53 LOG_WARN((
"Could not append path for update.status file"));
57 AutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ,
61 nullptr, OPEN_EXISTING, 0,
nullptr));
63 if (statusFile == INVALID_HANDLE_VALUE)
65 LOG_WARN((
"Could not open update.status file"));
71 if (!ReadFile(statusFile.
get(), buf,
sizeof(buf), &read,
nullptr))
73 LOG_WARN((
"Could not read from update.status file"));
77 LOG((
"updater.exe returned status: %s", buf));
79 const char kApplying[] =
"applying";
80 isApplying = strncmp(buf, kApplying,
81 sizeof(kApplying) - 1) == 0;
96 return argc == 4 && !wcscmp(argv[3], L
"-1") ||
97 argc == 5 && !wcscmp(argv[4], L
"-1");
111 if (!iswdigit(*str++))
132 return argc == 4 && !wcscmp(argv[3], L
"-1") ||
133 argc >= 4 && (wcsstr(argv[3], L
"/replace") ||
IsDigits(argv[3]));
157 wcsncpy(aResultDir, argvTmp[2],
MAX_PATH);
158 WCHAR* backSlash = wcsrchr(aResultDir, L
'\\');
160 if (backSlash && (backSlash[1] == L
'\0'))
169 bool replaceRequest = (argcTmp >= 4 && wcsstr(argvTmp[3], L
"/replace"));
170 if (backgroundUpdate || replaceRequest)
172 return PathRemoveFileSpecW(aResultDir);
191 BOOL &processStarted)
193 LOG((
"Starting update process as the service in session 0."));
194 STARTUPINFO si = {0};
195 si.cb =
sizeof(STARTUPINFO);
196 si.lpDesktop = L
"winsta0\\Default";
197 PROCESS_INFORMATION pi = {0};
217 si.dwFlags |= STARTF_USESHOWWINDOW;
218 si.wShowWindow = SW_HIDE;
235 selfHandlePostUpdate = MoveFileExW(updaterINI, updaterINITemp,
236 MOVEFILE_REPLACE_EXISTING);
242 putenv(
const_cast<char*
>(
"USING_SERVICE=1"));
243 LOG((
"Starting service with cmdline: %ls", cmdLine));
244 processStarted = CreateProcessW(argv[0], cmdLine,
245 nullptr,
nullptr,
FALSE,
246 CREATE_DEFAULT_ERROR_MODE,
250 putenv(
const_cast<char*
>(
"USING_SERVICE="));
256 LOG((
"Process was started... waiting on result."));
258 if (WAIT_TIMEOUT == waitRes)
262 TerminateProcess(pi.hProcess, 1);
268 if (GetExitCodeProcess(pi.hProcess, &returnCode))
270 LOG((
"Process finished with return code %d.", returnCode));
272 updateWasSuccessful = (returnCode == 0);
276 LOG_WARN((
"Process finished but could not obtain return code."));
279 CloseHandle(pi.hProcess);
280 CloseHandle(pi.hThread);
287 if (updateWasSuccessful)
289 LOG((
"update.status is still applying even know update "
290 " was successful."));
294 LOG_WARN((
"Could not write update.status still applying on"
299 updateWasSuccessful =
FALSE;
303 LOG_WARN((
"update.status is still applying and update was not successful."));
307 LOG_WARN((
"Could not write update.status still applying on"
315 DWORD lastError = GetLastError();
316 LOG_WARN((
"Could not create process as current user, "
317 "updaterPath: %ls; cmdLine: %ls. (%d)",
318 argv[0], cmdLine, lastError));
324 if (selfHandlePostUpdate)
326 MoveFileExW(updaterINITemp, updaterINI, MOVEFILE_REPLACE_EXISTING);
329 if (updateWasSuccessful && argc >
index)
331 LPCWSTR updateInfoDir = argv[1];
346 LOG((
"Launching post update process as the service in session 0."));
349 LOG_WARN((
"The post update process could not be launched."
350 " installDir: %ls, updateInfoDir: %ls",
351 installDir, updateInfoDir));
358 return updateWasSuccessful;
375 LOG_WARN((
"Not enough command line parameters specified. "
376 "Updating update.status."));
384 LOG_WARN((
"Could not write update.status service update failure. (%d)",
390 WCHAR installDir[
MAX_PATH + 1] = {L
'\0'};
393 LOG_WARN((
"Could not get the installation directory"));
397 LOG_WARN((
"Could not write update.status for GetInstallationDir failure."));
408 LOG_WARN((
"Filesystem in path %ls is not supported (%d)",
409 argv[0], GetLastError()));
413 LOG_WARN((
"Could not write update.status service update failure. (%d)",
419 AutoHandle noWriteLock(CreateFileW(argv[0], GENERIC_READ, FILE_SHARE_READ,
420 nullptr, OPEN_EXISTING, 0,
nullptr));
421 if (noWriteLock == INVALID_HANDLE_VALUE)
423 LOG_WARN((
"Could not set no write sharing access on file. (%d)",
428 LOG_WARN((
"Could not write update.status service update failure. (%d)",
437 WCHAR installDirUpdater[
MAX_PATH + 1] = { L
'\0' };
438 wcsncpy(installDirUpdater, installDir,
MAX_PATH);
441 LOG_WARN((
"Install directory updater could not be determined."));
449 LOG_WARN((
"Error checking if the updaters are the same.\n"
450 "Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater));
454 if (
result && !updaterIsCorrect)
456 LOG_WARN((
"The updaters do not match, updater will not run.\n"
457 "Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater));
463 LOG((
"updater.exe was compared successfully to the installation directory"
471 LOG_WARN((
"Could not write update.status updater compare failure."));
479 HMODULE updaterModule = LoadLibraryEx(argv[0],
nullptr,
480 LOAD_LIBRARY_AS_DATAFILE);
483 LOG_WARN((
"updater.exe module could not be loaded. (%d)", GetLastError()));
488 char updaterIdentity[64];
490 updaterIdentity,
sizeof(updaterIdentity)))
492 LOG_WARN((
"The updater.exe application does not contain the Mozilla"
493 " updater identity."));
499 LOG_WARN((
"The updater.exe identity string is not valid."));
502 FreeLibrary(updaterModule);
507 LOG((
"The updater.exe application contains the Mozilla"
508 " updater identity."));
515 LOG_WARN((
"Could not write update.status no updater identity."));
522#ifndef DISABLE_UPDATER_AUTHENTICODE_CHECK
528 if (!updaterSignProblem)
532 updateProcessWasStarted))
534 LOG((
"updater.exe was launched and run successfully!"));
548 LOG_WARN((
"Error running update process. Updating update.status (%d)",
557 if (!updateProcessWasStarted)
562 LOG_WARN((
"Could not write update.status service update failure. (%d)",
571 LOG_WARN((
"Could not start process due to certificate check error on "
572 "updater.exe. Updating update.status. (%d)", GetLastError()));
579 LOG_WARN((
"Could not write pending state to update.status. (%d)",
599 if (!GetModuleFileNameW(
nullptr, serviceUpdaterPath,
MAX_PATH))
601 LOG_WARN((
"Could not obtain module filename when attempting to "
602 "use a secure updater path. (%d)", GetLastError()));
606 if (!PathRemoveFileSpecW(serviceUpdaterPath))
608 LOG_WARN((
"Couldn't remove file spec when attempting to use a secure "
609 "updater path. (%d)", GetLastError()));
615 LOG_WARN((
"Couldn't append file spec when attempting to use a secure "
616 "updater path. (%d)", GetLastError()));
620 CreateDirectoryW(serviceUpdaterPath,
nullptr);
624 LOG_WARN((
"Couldn't append file spec when attempting to use a secure "
625 "updater path. (%d)", GetLastError()));
642 if (serviceUpdaterPath[0])
644 result = DeleteFileW(serviceUpdaterPath);
645 if (!
result && GetLastError() != ERROR_PATH_NOT_FOUND &&
646 GetLastError() != ERROR_FILE_NOT_FOUND)
648 LOG_WARN((
"Could not delete service updater path: '%ls'.",
649 serviceUpdaterPath));
652 WCHAR updaterINIPath[
MAX_PATH + 1] = { L
'\0' };
656 result = DeleteFileW(updaterINIPath);
657 if (!
result && GetLastError() != ERROR_PATH_NOT_FOUND &&
658 GetLastError() != ERROR_FILE_NOT_FOUND)
660 LOG_WARN((
"Could not delete service updater INI path: '%ls'.",
683 LOG_WARN((
"Not enough command line arguments to execute a service command"));
689 RPC_WSTR guidString = RPC_WSTR(L
"");
691 HRESULT
hr = CoCreateGuid(&guid);
694 UuidToString(&guid, &guidString);
696 LOG((
"Executing service command %ls, ID: %ls",
697 argv[2],
reinterpret_cast<LPCWSTR
>(guidString)));
698 RpcStringFree(&guidString);
701 if (!lstrcmpi(argv[2], L
"software-update"))
709 LPWSTR oldUpdaterPath = argv[3];
710 WCHAR secureUpdaterPath[
MAX_PATH + 1] = { L
'\0' };
714 LOG((
"Passed in path: '%ls'; Using this path for updating: '%ls'.",
715 oldUpdaterPath, secureUpdaterPath));
717 result = CopyFileW(oldUpdaterPath, secureUpdaterPath,
FALSE);
722 LOG_WARN((
"Could not copy path to secure location. (%d)",
727 LOG_WARN((
"Could not write update.status could not copy updater error"));
735 argv[3] = secureUpdaterPath;
737 WCHAR oldUpdaterINIPath[
MAX_PATH + 1] = { L
'\0' };
738 WCHAR secureUpdaterINIPath[
MAX_PATH + 1] = { L
'\0' };
745 if (!CopyFileW(oldUpdaterINIPath, secureUpdaterINIPath,
FALSE))
747 LOG_WARN((
"Could not copy updater.ini from: '%ls' to '%ls'. (%d)",
748 oldUpdaterINIPath, secureUpdaterINIPath, GetLastError()));
759 LOG((
"Service command %ls complete.", argv[2]));
763 LOG_WARN((
"Service command not recognized: %ls.", argv[2]));
767 LOG((
"service command %ls complete with result: %ls.",
768 argv[1], (
result ? L
"Success" : L
"Failure")));
#define SERVICE_UPDATER_SIGN_ERROR
#define SERVICE_COULD_NOT_LOCK_UPDATER
#define SERVICE_UPDATER_IDENTITY_ERROR
#define SERVICE_INSTALLDIR_ERROR
#define SERVICE_STILL_APPLYING_ON_FAILURE
#define SERVICE_STILL_APPLYING_ON_SUCCESS
#define SERVICE_UPDATER_COULD_NOT_BE_STARTED
#define SERVICE_UPDATER_NOT_FIXED_DRIVE
#define SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS
#define SERVICE_COULD_NOT_COPY_UPDATER
#define SERVICE_UPDATER_COMPARE_ERROR
const wchar_t *typedef BOOL
BOOL DoesBinaryMatchAllowedCertificates(LPCWSTR basePathForUpdate, LPCWSTR filePath)
Verifies if the file path matches any certificate stored in the registry.
BOOL VerifySameFiles(LPCWSTR file1Path, LPCWSTR file2Path, BOOL &sameContent)
Verifies if 2 files are byte for byte equivalent.
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra)
#define UPDATER_IDENTITY_STRING
#define IDS_UPDATER_IDENTITY
BOOL LaunchWinPostProcess(const WCHAR *installationDir, const WCHAR *updateInfoDir, bool forceSync, HANDLE userToken)
BOOL StartServiceUpdate(LPCWSTR installDir)
BOOL IsLocalFile(LPCWSTR file, BOOL &isLocal)
static bool IsDigits(WCHAR *str)
Determines whether the param only contains digits.
BOOL ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
Processes a software update command.
BOOL DeleteSecureUpdater(WCHAR serviceUpdaterPath[MAX_PATH+1])
Deletes the passed in updater path and the associated updater.ini file.
static BOOL IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying)
static bool IsOldCommandline(int argc, LPWSTR *argv)
Determines whether the command line contains just the directory to apply the update to (old command l...
static BOOL GetInstallationDir(int argcTmp, LPWSTR *argvTmp, WCHAR aResultDir[MAX_PATH+1])
Gets the installation directory from the arguments passed to updater.exe.
BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath, LPCWSTR newFileName)
static bool IsUpdateBeingStaged(int argc, LPWSTR *argv)
Determines whether we're staging an update.
static const int TIME_TO_WAIT_ON_UPDATER
BOOL StartUpdateProcess(int argc, LPWSTR *argv, LPCWSTR installDir, BOOL &processStarted)
Runs an update process as the service using the SYSTEM account.
wchar_t * MakeCommandLine(int argc, wchar_t **argv)
BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode)
BOOL ExecuteServiceCommand(int argc, LPWSTR *argv)
Executes a service command.
BOOL GetSecureUpdaterPath(WCHAR serviceUpdaterPath[MAX_PATH+1])
Obtains the updater path alongside a subdir of the service binary.