LibreOffice Module onlineupdate (master) 1
workmonitor.cxx
Go to the documentation of this file.
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include <shlobj.h>
6#include <shlwapi.h>
7#include <wtsapi32.h>
8#include <userenv.h>
9#include <shellapi.h>
10#include <cstddef>
11
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")
17
18#include "workmonitor.hxx"
19#include "serviceinstall.hxx"
20#include "servicebase.hxx"
22#include "uachelper.h"
23#include "updatehelper.h"
24#include "errors.h"
25#include "windowsHelper.hxx"
26
27// Wait 15 minutes for an update operation to run at most.
28// Updates usually take less than a minute so this seems like a
29// significantly large and safe amount of time to wait.
30static const int TIME_TO_WAIT_ON_UPDATER = 15 * 60 * 1000;
31wchar_t* MakeCommandLine(int argc, wchar_t **argv);
32BOOL WriteStatusFailure(LPCWSTR updateDirPath, int errorCode);
33BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
34 LPCWSTR newFileName);
35
36/*
37 * Read the update.status file and sets isApplying to true if
38 * the status is set to applying.
39 *
40 * @param updateDirPath The directory where update.status is stored
41 * @param isApplying Out parameter for specifying if the status
42 * is set to applying or not.
43 * @return TRUE if the information was filled.
44*/
45static BOOL
46IsStatusApplying(LPCWSTR updateDirPath, BOOL &isApplying)
47{
48 isApplying = FALSE;
49 WCHAR updateStatusFilePath[MAX_PATH + 1] = {L'\0'};
50 wcsncpy(updateStatusFilePath, updateDirPath, MAX_PATH);
51 if (!PathAppendSafe(updateStatusFilePath, L"update.status"))
52 {
53 LOG_WARN(("Could not append path for update.status file"));
54 return FALSE;
55 }
56
57 AutoHandle statusFile(CreateFileW(updateStatusFilePath, GENERIC_READ,
58 FILE_SHARE_READ |
59 FILE_SHARE_WRITE |
60 FILE_SHARE_DELETE,
61 nullptr, OPEN_EXISTING, 0, nullptr));
62
63 if (statusFile == INVALID_HANDLE_VALUE)
64 {
65 LOG_WARN(("Could not open update.status file"));
66 return FALSE;
67 }
68
69 char buf[32] = { 0 };
70 DWORD read;
71 if (!ReadFile(statusFile.get(), buf, sizeof(buf), &read, nullptr))
72 {
73 LOG_WARN(("Could not read from update.status file"));
74 return FALSE;
75 }
76
77 LOG(("updater.exe returned status: %s", buf));
78
79 const char kApplying[] = "applying";
80 isApplying = strncmp(buf, kApplying,
81 sizeof(kApplying) - 1) == 0;
82 return TRUE;
83}
84
92static bool
93IsUpdateBeingStaged(int argc, LPWSTR *argv)
94{
95 // PID will be set to -1 if we're supposed to stage an update.
96 return argc == 4 && !wcscmp(argv[3], L"-1") ||
97 argc == 5 && !wcscmp(argv[4], L"-1");
98}
99
106static bool
107IsDigits(WCHAR *str)
108{
109 while (*str)
110 {
111 if (!iswdigit(*str++))
112 {
113 return FALSE;
114 }
115 }
116 return TRUE;
117}
118
129static bool
130IsOldCommandline(int argc, LPWSTR *argv)
131{
132 return argc == 4 && !wcscmp(argv[3], L"-1") ||
133 argc >= 4 && (wcsstr(argv[3], L"/replace") || IsDigits(argv[3]));
134}
135
143static BOOL
144GetInstallationDir(int argcTmp, LPWSTR *argvTmp, WCHAR aResultDir[MAX_PATH + 1])
145{
146 int index = 3;
147 if (IsOldCommandline(argcTmp, argvTmp))
148 {
149 index = 2;
150 }
151
152 if (argcTmp < index)
153 {
154 return FALSE;
155 }
156
157 wcsncpy(aResultDir, argvTmp[2], MAX_PATH);
158 WCHAR* backSlash = wcsrchr(aResultDir, L'\\');
159 // Make sure that the path does not include trailing backslashes
160 if (backSlash && (backSlash[1] == L'\0'))
161 {
162 *backSlash = L'\0';
163 }
164
165 // The new command line's argv[2] is always the installation directory.
166 if (index == 2)
167 {
168 bool backgroundUpdate = IsUpdateBeingStaged(argcTmp, argvTmp);
169 bool replaceRequest = (argcTmp >= 4 && wcsstr(argvTmp[3], L"/replace"));
170 if (backgroundUpdate || replaceRequest)
171 {
172 return PathRemoveFileSpecW(aResultDir);
173 }
174 }
175 return TRUE;
176}
177
187BOOL
189 LPWSTR *argv,
190 LPCWSTR installDir,
191 BOOL &processStarted)
192{
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};
198
199 // The updater command line is of the form:
200 // updater.exe update-dir apply [wait-pid [callback-dir callback-path args]]
201 LPWSTR cmdLine = MakeCommandLine(argc, argv);
202
203 int index = 3;
204 if (IsOldCommandline(argc, argv))
205 {
206 index = 2;
207 }
208
209 // If we're about to start the update process from session 0,
210 // then we should not show a GUI. This only really needs to be done
211 // on Vista and higher, but it's better to keep everything consistent
212 // across all OS if it's of no harm.
213 if (argc >= index)
214 {
215 // Setting the desktop to blank will ensure no GUI is displayed
216 si.lpDesktop = L"";
217 si.dwFlags |= STARTF_USESHOWWINDOW;
218 si.wShowWindow = SW_HIDE;
219 }
220
221 // We move the updater.ini file out of the way because we will handle
222 // executing PostUpdate through the service. We handle PostUpdate from
223 // the service because there are some per user things that happen that
224 // can't run in session 0 which we run updater.exe in.
225 // Once we are done running updater.exe we rename updater.ini back so
226 // that if there were any errors the next updater.exe will run correctly.
227 WCHAR updaterINI[MAX_PATH + 1];
228 WCHAR updaterINITemp[MAX_PATH + 1];
229 BOOL selfHandlePostUpdate = FALSE;
230 // We use the updater.ini from the same directory as the updater.exe
231 // because of background updates.
232 if (PathGetSiblingFilePath(updaterINI, argv[0], L"updater.ini") &&
233 PathGetSiblingFilePath(updaterINITemp, argv[0], L"updater.tmp"))
234 {
235 selfHandlePostUpdate = MoveFileExW(updaterINI, updaterINITemp,
236 MOVEFILE_REPLACE_EXISTING);
237 }
238
239 // Add an env var for USING_SERVICE so the updater.exe can
240 // do anything special that it needs to do for service updates.
241 // Search in updater.cpp for more info on USING_SERVICE.
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,
247 nullptr,
248 nullptr, &si, &pi);
249 // Empty value on putenv is how you remove an env variable in Windows
250 putenv(const_cast<char*>("USING_SERVICE="));
251
252 BOOL updateWasSuccessful = FALSE;
253 if (processStarted)
254 {
255 // Wait for the updater process to finish
256 LOG(("Process was started... waiting on result."));
257 DWORD waitRes = WaitForSingleObject(pi.hProcess, TIME_TO_WAIT_ON_UPDATER);
258 if (WAIT_TIMEOUT == waitRes)
259 {
260 // We waited a long period of time for updater.exe and it never finished
261 // so kill it.
262 TerminateProcess(pi.hProcess, 1);
263 }
264 else
265 {
266 // Check the return code of updater.exe to make sure we get 0
267 DWORD returnCode;
268 if (GetExitCodeProcess(pi.hProcess, &returnCode))
269 {
270 LOG(("Process finished with return code %d.", returnCode));
271 // updater returns 0 if successful.
272 updateWasSuccessful = (returnCode == 0);
273 }
274 else
275 {
276 LOG_WARN(("Process finished but could not obtain return code."));
277 }
278 }
279 CloseHandle(pi.hProcess);
280 CloseHandle(pi.hThread);
281
282 // Check just in case updater.exe didn't change the status from
283 // applying. If this is the case we report an error.
284 BOOL isApplying = FALSE;
285 if (IsStatusApplying(argv[1], isApplying) && isApplying)
286 {
287 if (updateWasSuccessful)
288 {
289 LOG(("update.status is still applying even know update "
290 " was successful."));
291 if (!WriteStatusFailure(argv[1],
293 {
294 LOG_WARN(("Could not write update.status still applying on"
295 " success error."));
296 }
297 // Since we still had applying we know updater.exe didn't do its
298 // job correctly.
299 updateWasSuccessful = FALSE;
300 }
301 else
302 {
303 LOG_WARN(("update.status is still applying and update was not successful."));
304 if (!WriteStatusFailure(argv[1],
306 {
307 LOG_WARN(("Could not write update.status still applying on"
308 " success error."));
309 }
310 }
311 }
312 }
313 else
314 {
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));
319 }
320
321 // Now that we're done with the update, restore back the updater.ini file
322 // We use it ourselves, and also we want it back in case we had any type
323 // of error so that the normal update process can use it.
324 if (selfHandlePostUpdate)
325 {
326 MoveFileExW(updaterINITemp, updaterINI, MOVEFILE_REPLACE_EXISTING);
327
328 // Only run the PostUpdate if the update was successful
329 if (updateWasSuccessful && argc > index)
330 {
331 LPCWSTR updateInfoDir = argv[1];
332 bool stagingUpdate = IsUpdateBeingStaged(argc, argv);
333
334 // Launch the PostProcess with admin access in session 0. This is
335 // actually launching the post update process but it takes in the
336 // callback app path to figure out where to apply to.
337 // The PostUpdate process with user only access will be done inside
338 // the unelevated updater.exe after the update process is complete
339 // from the service. We don't know here which session to start
340 // the user PostUpdate process from.
341 // Note that we don't need to do this if we're just staging the
342 // update in the background, as the PostUpdate step runs when
343 // performing the replacing in that case.
344 if (!stagingUpdate)
345 {
346 LOG(("Launching post update process as the service in session 0."));
347 if (!LaunchWinPostProcess(installDir, updateInfoDir, true, nullptr))
348 {
349 LOG_WARN(("The post update process could not be launched."
350 " installDir: %ls, updateInfoDir: %ls",
351 installDir, updateInfoDir));
352 }
353 }
354 }
355 }
356
357 free(cmdLine);
358 return updateWasSuccessful;
359}
360
369BOOL
370ProcessSoftwareUpdateCommand(DWORD argc, LPWSTR *argv)
371{
372 BOOL result = TRUE;
373 if (argc < 3)
374 {
375 LOG_WARN(("Not enough command line parameters specified. "
376 "Updating update.status."));
377
378 // We can only update update.status if argv[1] exists. argv[1] is
379 // the directory where the update.status file exists.
380 if (argc < 2 ||
381 !WriteStatusFailure(argv[1],
383 {
384 LOG_WARN(("Could not write update.status service update failure. (%d)",
385 GetLastError()));
386 }
387 return FALSE;
388 }
389
390 WCHAR installDir[MAX_PATH + 1] = {L'\0'};
391 if (!GetInstallationDir(argc, argv, installDir))
392 {
393 LOG_WARN(("Could not get the installation directory"));
394 if (!WriteStatusFailure(argv[1],
396 {
397 LOG_WARN(("Could not write update.status for GetInstallationDir failure."));
398 }
399 return FALSE;
400 }
401
402 // Make sure the path to the updater to use for the update is local.
403 // We do this check to make sure that file locking is available for
404 // race condition security checks.
405 BOOL isLocal = FALSE;
406 if (!IsLocalFile(argv[0], isLocal) || !isLocal)
407 {
408 LOG_WARN(("Filesystem in path %ls is not supported (%d)",
409 argv[0], GetLastError()));
410 if (!WriteStatusFailure(argv[1],
412 {
413 LOG_WARN(("Could not write update.status service update failure. (%d)",
414 GetLastError()));
415 }
416 return FALSE;
417 }
418
419 AutoHandle noWriteLock(CreateFileW(argv[0], GENERIC_READ, FILE_SHARE_READ,
420 nullptr, OPEN_EXISTING, 0, nullptr));
421 if (noWriteLock == INVALID_HANDLE_VALUE)
422 {
423 LOG_WARN(("Could not set no write sharing access on file. (%d)",
424 GetLastError()));
425 if (!WriteStatusFailure(argv[1],
427 {
428 LOG_WARN(("Could not write update.status service update failure. (%d)",
429 GetLastError()));
430 }
431 return FALSE;
432 }
433
434 // Verify that the updater.exe that we are executing is the same
435 // as the one in the installation directory which we are updating.
436 // The installation dir that we are installing to is installDir.
437 WCHAR installDirUpdater[MAX_PATH + 1] = { L'\0' };
438 wcsncpy(installDirUpdater, installDir, MAX_PATH);
439 if (!PathAppendSafe(installDirUpdater, L"updater.exe"))
440 {
441 LOG_WARN(("Install directory updater could not be determined."));
442 result = FALSE;
443 }
444
445 BOOL updaterIsCorrect = FALSE;
446 if (result && !VerifySameFiles(argv[0], installDirUpdater,
447 updaterIsCorrect))
448 {
449 LOG_WARN(("Error checking if the updaters are the same.\n"
450 "Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater));
451 result = FALSE;
452 }
453
454 if (result && !updaterIsCorrect)
455 {
456 LOG_WARN(("The updaters do not match, updater will not run.\n"
457 "Path 1: %ls\nPath 2: %ls", argv[0], installDirUpdater));
458 result = FALSE;
459 }
460
461 if (result)
462 {
463 LOG(("updater.exe was compared successfully to the installation directory"
464 " updater.exe."));
465 }
466 else
467 {
468 if (!WriteStatusFailure(argv[1],
470 {
471 LOG_WARN(("Could not write update.status updater compare failure."));
472 }
473 return FALSE;
474 }
475
476 // Check to make sure the updater.exe module has the unique updater identity.
477 // This is a security measure to make sure that the signed executable that
478 // we will run is actually an updater.
479 HMODULE updaterModule = LoadLibraryEx(argv[0], nullptr,
480 LOAD_LIBRARY_AS_DATAFILE);
481 if (!updaterModule)
482 {
483 LOG_WARN(("updater.exe module could not be loaded. (%d)", GetLastError()));
484 result = FALSE;
485 }
486 else
487 {
488 char updaterIdentity[64];
489 if (!LoadStringA(updaterModule, IDS_UPDATER_IDENTITY,
490 updaterIdentity, sizeof(updaterIdentity)))
491 {
492 LOG_WARN(("The updater.exe application does not contain the Mozilla"
493 " updater identity."));
494 result = FALSE;
495 }
496
497 if (strcmp(updaterIdentity, UPDATER_IDENTITY_STRING))
498 {
499 LOG_WARN(("The updater.exe identity string is not valid."));
500 result = FALSE;
501 }
502 FreeLibrary(updaterModule);
503 }
504
505 if (result)
506 {
507 LOG(("The updater.exe application contains the Mozilla"
508 " updater identity."));
509 }
510 else
511 {
512 if (!WriteStatusFailure(argv[1],
514 {
515 LOG_WARN(("Could not write update.status no updater identity."));
516 }
517 return TRUE;
518 }
519
520 // Check for updater.exe sign problems
521 BOOL updaterSignProblem = FALSE;
522#ifndef DISABLE_UPDATER_AUTHENTICODE_CHECK
523 updaterSignProblem = !DoesBinaryMatchAllowedCertificates(installDir,
524 argv[0]);
525#endif
526
527 // Only proceed with the update if we have no signing problems
528 if (!updaterSignProblem)
529 {
530 BOOL updateProcessWasStarted = FALSE;
531 if (StartUpdateProcess(argc, argv, installDir,
532 updateProcessWasStarted))
533 {
534 LOG(("updater.exe was launched and run successfully!"));
535 LogFlush();
536
537 // Don't attempt to update the service when the update is being staged.
538 if (!IsUpdateBeingStaged(argc, argv))
539 {
540 // We might not execute code after StartServiceUpdate because
541 // the service installer will stop the service if it is running.
542 StartServiceUpdate(installDir);
543 }
544 }
545 else
546 {
547 result = FALSE;
548 LOG_WARN(("Error running update process. Updating update.status (%d)",
549 GetLastError()));
550 LogFlush();
551
552 // If the update process was started, then updater.exe is responsible for
553 // setting the failure code. If it could not be started then we do the
554 // work. We set an error instead of directly setting status pending
555 // so that the app.update.service.errors pref can be updated when
556 // the callback app restarts.
557 if (!updateProcessWasStarted)
558 {
559 if (!WriteStatusFailure(argv[1],
561 {
562 LOG_WARN(("Could not write update.status service update failure. (%d)",
563 GetLastError()));
564 }
565 }
566 }
567 }
568 else
569 {
570 result = FALSE;
571 LOG_WARN(("Could not start process due to certificate check error on "
572 "updater.exe. Updating update.status. (%d)", GetLastError()));
573
574 // When there is a certificate check error on the updater.exe application,
575 // we want to write out the error.
576 if (!WriteStatusFailure(argv[1],
578 {
579 LOG_WARN(("Could not write pending state to update.status. (%d)",
580 GetLastError()));
581 }
582 }
583
584 return result;
585}
586
596BOOL
597GetSecureUpdaterPath(WCHAR serviceUpdaterPath[MAX_PATH + 1])
598{
599 if (!GetModuleFileNameW(nullptr, serviceUpdaterPath, MAX_PATH))
600 {
601 LOG_WARN(("Could not obtain module filename when attempting to "
602 "use a secure updater path. (%d)", GetLastError()));
603 return FALSE;
604 }
605
606 if (!PathRemoveFileSpecW(serviceUpdaterPath))
607 {
608 LOG_WARN(("Couldn't remove file spec when attempting to use a secure "
609 "updater path. (%d)", GetLastError()));
610 return FALSE;
611 }
612
613 if (!PathAppendSafe(serviceUpdaterPath, L"update"))
614 {
615 LOG_WARN(("Couldn't append file spec when attempting to use a secure "
616 "updater path. (%d)", GetLastError()));
617 return FALSE;
618 }
619
620 CreateDirectoryW(serviceUpdaterPath, nullptr);
621
622 if (!PathAppendSafe(serviceUpdaterPath, L"updater.exe"))
623 {
624 LOG_WARN(("Couldn't append file spec when attempting to use a secure "
625 "updater path. (%d)", GetLastError()));
626 return FALSE;
627 }
628
629 return TRUE;
630}
631
638BOOL
639DeleteSecureUpdater(WCHAR serviceUpdaterPath[MAX_PATH + 1])
640{
641 BOOL result = FALSE;
642 if (serviceUpdaterPath[0])
643 {
644 result = DeleteFileW(serviceUpdaterPath);
645 if (!result && GetLastError() != ERROR_PATH_NOT_FOUND &&
646 GetLastError() != ERROR_FILE_NOT_FOUND)
647 {
648 LOG_WARN(("Could not delete service updater path: '%ls'.",
649 serviceUpdaterPath));
650 }
651
652 WCHAR updaterINIPath[MAX_PATH + 1] = { L'\0' };
653 if (PathGetSiblingFilePath(updaterINIPath, serviceUpdaterPath,
654 L"updater.ini"))
655 {
656 result = DeleteFileW(updaterINIPath);
657 if (!result && GetLastError() != ERROR_PATH_NOT_FOUND &&
658 GetLastError() != ERROR_FILE_NOT_FOUND)
659 {
660 LOG_WARN(("Could not delete service updater INI path: '%ls'.",
661 updaterINIPath));
662 }
663 }
664 }
665 return result;
666}
667
678BOOL
679ExecuteServiceCommand(int argc, LPWSTR *argv)
680{
681 if (argc < 3)
682 {
683 LOG_WARN(("Not enough command line arguments to execute a service command"));
684 return FALSE;
685 }
686
687 // The tests work by making sure the log has changed, so we put a
688 // unique ID in the log.
689 RPC_WSTR guidString = RPC_WSTR(L"");
690 GUID guid;
691 HRESULT hr = CoCreateGuid(&guid);
692 if (SUCCEEDED(hr))
693 {
694 UuidToString(&guid, &guidString);
695 }
696 LOG(("Executing service command %ls, ID: %ls",
697 argv[2], reinterpret_cast<LPCWSTR>(guidString)));
698 RpcStringFree(&guidString);
699
700 BOOL result = FALSE;
701 if (!lstrcmpi(argv[2], L"software-update"))
702 {
703
704 // Use the passed in command line arguments for the update, except for the
705 // path to updater.exe. We copy updater.exe to the directory of the
706 // MozillaMaintenance service so that a low integrity process cannot
707 // replace the updater.exe at any point and use that for the update.
708 // It also makes DLL injection attacks harder.
709 LPWSTR oldUpdaterPath = argv[3];
710 WCHAR secureUpdaterPath[MAX_PATH + 1] = { L'\0' };
711 result = GetSecureUpdaterPath(secureUpdaterPath); // Does its own logging
712 if (result)
713 {
714 LOG(("Passed in path: '%ls'; Using this path for updating: '%ls'.",
715 oldUpdaterPath, secureUpdaterPath));
716 DeleteSecureUpdater(secureUpdaterPath);
717 result = CopyFileW(oldUpdaterPath, secureUpdaterPath, FALSE);
718 }
719
720 if (!result)
721 {
722 LOG_WARN(("Could not copy path to secure location. (%d)",
723 GetLastError()));
724 if (argc > 4 && !WriteStatusFailure(argv[4],
726 {
727 LOG_WARN(("Could not write update.status could not copy updater error"));
728 }
729 }
730 else
731 {
732
733 // We obtained the path and copied it successfully, update the path to
734 // use for the service update.
735 argv[3] = secureUpdaterPath;
736
737 WCHAR oldUpdaterINIPath[MAX_PATH + 1] = { L'\0' };
738 WCHAR secureUpdaterINIPath[MAX_PATH + 1] = { L'\0' };
739 if (PathGetSiblingFilePath(secureUpdaterINIPath, secureUpdaterPath,
740 L"updater.ini") &&
741 PathGetSiblingFilePath(oldUpdaterINIPath, oldUpdaterPath,
742 L"updater.ini"))
743 {
744 // This is non fatal if it fails there is no real harm
745 if (!CopyFileW(oldUpdaterINIPath, secureUpdaterINIPath, FALSE))
746 {
747 LOG_WARN(("Could not copy updater.ini from: '%ls' to '%ls'. (%d)",
748 oldUpdaterINIPath, secureUpdaterINIPath, GetLastError()));
749 }
750 }
751
752 result = ProcessSoftwareUpdateCommand(argc - 3, argv + 3);
753 DeleteSecureUpdater(secureUpdaterPath);
754 }
755
756 // We might not reach here if the service install succeeded
757 // because the service self updates itself and the service
758 // installer will stop the service.
759 LOG(("Service command %ls complete.", argv[2]));
760 }
761 else
762 {
763 LOG_WARN(("Service command not recognized: %ls.", argv[2]));
764 // result is already set to FALSE
765 }
766
767 LOG(("service command %ls complete with result: %ls.",
768 argv[1], (result ? L"Success" : L"Failure")));
769 return TRUE;
770}
#define SERVICE_UPDATER_SIGN_ERROR
Definition: errors.h:48
#define SERVICE_COULD_NOT_LOCK_UPDATER
Definition: errors.h:54
#define SERVICE_UPDATER_IDENTITY_ERROR
Definition: errors.h:50
#define SERVICE_INSTALLDIR_ERROR
Definition: errors.h:55
#define SERVICE_STILL_APPLYING_ON_FAILURE
Definition: errors.h:52
#define SERVICE_STILL_APPLYING_ON_SUCCESS
Definition: errors.h:51
#define SERVICE_UPDATER_COULD_NOT_BE_STARTED
Definition: errors.h:46
#define SERVICE_UPDATER_NOT_FIXED_DRIVE
Definition: errors.h:53
#define SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS
Definition: errors.h:47
#define SERVICE_COULD_NOT_COPY_UPDATER
Definition: errors.h:71
#define SERVICE_UPDATER_COMPARE_ERROR
Definition: errors.h:49
#define TRUE
#define FALSE
#define MAX_PATH
index
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.
Definition: servicebase.cxx:19
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra)
#define UPDATER_IDENTITY_STRING
Definition: servicebase.hxx:20
#define IDS_UPDATER_IDENTITY
Definition: servicebase.hxx:21
return hr
HANDLE get() const
Any result
BOOL LaunchWinPostProcess(const WCHAR *installationDir, const WCHAR *updateInfoDir, bool forceSync, HANDLE userToken)
BOOL StartServiceUpdate(LPCWSTR installDir)
BOOL IsLocalFile(LPCWSTR file, BOOL &isLocal)
#define LogFlush()
Definition: updatelogging.h:45
#define LOG_WARN(args)
Definition: updatelogging.h:38
#define LOG(args)
Definition: updatelogging.h:39
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)
Definition: workmonitor.cxx:46
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.
Definition: workmonitor.cxx:93
static const int TIME_TO_WAIT_ON_UPDATER
Definition: workmonitor.cxx:30
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.