Index: common/scheduled_task_utils.cc |
diff --git a/common/scheduled_task_utils.cc b/common/scheduled_task_utils.cc |
deleted file mode 100644 |
index f922f13f08eac9357a3e74e2915a31ed4a94f85a..0000000000000000000000000000000000000000 |
--- a/common/scheduled_task_utils.cc |
+++ /dev/null |
@@ -1,1076 +0,0 @@ |
-// Copyright 2007-2010 Google Inc. |
-// |
-// Licensed under the Apache License, Version 2.0 (the "License"); |
-// you may not use this file except in compliance with the License. |
-// You may obtain a copy of the License at |
-// |
-// http://www.apache.org/licenses/LICENSE-2.0 |
-// |
-// Unless required by applicable law or agreed to in writing, software |
-// distributed under the License is distributed on an "AS IS" BASIS, |
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-// See the License for the specific language governing permissions and |
-// limitations under the License. |
- |
-#include "omaha/common/scheduled_task_utils.h" |
-#include "omaha/common/scheduled_task_utils_internal.h" |
-#include <corerror.h> |
-#include <lmcons.h> |
-#include <lmsname.h> |
-#include <mstask.h> |
-#include <atlsecurity.h> |
-#include "omaha/base/debug.h" |
-#include "omaha/base/error.h" |
-#include "omaha/base/logging.h" |
-#include "omaha/base/scoped_ptr_cotask.h" |
-#include "omaha/base/service_utils.h" |
-#include "omaha/base/string.h" |
-#include "omaha/base/system_info.h" |
-#include "omaha/base/time.h" |
-#include "omaha/base/timer.h" |
-#include "omaha/base/user_info.h" |
-#include "omaha/base/utils.h" |
-#include "omaha/client/resource.h" |
-#include "omaha/common/command_line_builder.h" |
-#include "omaha/common/config_manager.h" |
-#include "omaha/common/const_cmd_line.h" |
-#include "omaha/common/const_goopdate.h" |
-#include "omaha/common/goopdate_utils.h" |
- |
-namespace omaha { |
- |
-namespace scheduled_task_utils { |
- |
-namespace internal { |
- |
-CString GetCurrentTaskNameCore(bool is_machine) { |
- UTIL_LOG(L3, (_T("[GetCurrentTaskNameCore][%d]"), is_machine)); |
- |
- CString default_name(GetDefaultGoopdateTaskName(is_machine, |
- COMMANDLINE_MODE_CORE)); |
- return goopdate_utils::GetCurrentVersionedName(is_machine, |
- kRegValueTaskNameC, |
- default_name); |
-} |
- |
-HRESULT CreateAndSetVersionedTaskNameCoreInRegistry( |
- bool is_machine) { |
- UTIL_LOG(L3, (_T("[CreateAndSetVersionedTaskNameCoreInRegistry][%d]"), |
- is_machine)); |
- |
- CString default_name(GetDefaultGoopdateTaskName(is_machine, |
- COMMANDLINE_MODE_CORE)); |
- return goopdate_utils::CreateAndSetVersionedNameInRegistry( |
- is_machine, |
- default_name, |
- kRegValueTaskNameC); |
-} |
- |
-CString GetCurrentTaskNameUA(bool is_machine) { |
- UTIL_LOG(L3, (_T("[GetCurrentTaskNameUA][%d]"), is_machine)); |
- |
- CString default_name(GetDefaultGoopdateTaskName(is_machine, |
- COMMANDLINE_MODE_UA)); |
- return goopdate_utils::GetCurrentVersionedName(is_machine, |
- kRegValueTaskNameUA, |
- default_name); |
-} |
- |
-HRESULT CreateAndSetVersionedTaskNameUAInRegistry(bool machine) { |
- UTIL_LOG(L3, (_T("[CreateAndSetVersionedTaskNameUAInRegistry][%d]"), |
- machine)); |
- |
- CString default_name(GetDefaultGoopdateTaskName(machine, |
- COMMANDLINE_MODE_UA)); |
- return goopdate_utils::CreateAndSetVersionedNameInRegistry( |
- machine, |
- default_name, |
- kRegValueTaskNameUA); |
-} |
- |
-bool IsInstalledScheduledTask(const TCHAR* task_name) { |
- ASSERT1(task_name && *task_name); |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return false; |
- } |
- |
- CComPtr<ITask> task; |
- hr = scheduler->Activate(task_name, |
- __uuidof(ITask), |
- reinterpret_cast<IUnknown**>(&task)); |
- |
- UTIL_LOG(L3, (_T("[IsInstalledScheduledTask returned][0x%x]"), hr)); |
- return COR_E_FILENOTFOUND == hr ? false : true; |
-} |
- |
-DWORD GetScheduledTaskPriority(const TCHAR* task_name) { |
- ASSERT1(task_name && *task_name); |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return 0; |
- } |
- |
- CComPtr<ITask> task; |
- hr = scheduler->Activate(task_name, |
- __uuidof(ITask), |
- reinterpret_cast<IUnknown**>(&task)); |
- |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[GetScheduledTaskPriority][Activate failed][0x%x]"), hr)); |
- return 0; |
- } |
- |
- DWORD priority = 0; |
- hr = task->GetPriority(&priority); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.GetMostRecentRunTime failed][0x%x]"), hr)); |
- return 0; |
- } |
- |
- ASSERT1(priority); |
- return priority; |
-} |
- |
-bool HasScheduledTaskEverRun(const TCHAR* task_name) { |
- ASSERT1(task_name && *task_name); |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return false; |
- } |
- |
- CComPtr<ITask> task; |
- hr = scheduler->Activate(task_name, |
- __uuidof(ITask), |
- reinterpret_cast<IUnknown**>(&task)); |
- |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[HasScheduledTaskEverRun][Activate failed][0x%x]"), hr)); |
- return false; |
- } |
- |
- SYSTEMTIME recent_run_time = {0}; |
- hr = task->GetMostRecentRunTime(&recent_run_time); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.GetMostRecentRunTime failed][0x%x]"), hr)); |
- return false; |
- } |
- |
- // hr == SCHED_S_TASK_HAS_NOT_RUN if the task has never run. |
- return hr == S_OK; |
-} |
- |
-HRESULT GetScheduledTaskStatus(const TCHAR* task_name) { |
- ASSERT1(task_name && *task_name); |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<ITask> task; |
- hr = scheduler->Activate(task_name, |
- __uuidof(ITask), |
- reinterpret_cast<IUnknown**>(&task)); |
- |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[GetScheduledTaskStatus: Activate failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- HRESULT task_status(S_OK); |
- hr = task->GetStatus(&task_status); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.GetStatus failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- return task_status; |
-} |
- |
-HRESULT GetScheduledTaskExitCode(const TCHAR* task_name) { |
- ASSERT1(task_name && *task_name); |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<ITask> task; |
- hr = scheduler->Activate(task_name, |
- __uuidof(ITask), |
- reinterpret_cast<IUnknown**>(&task)); |
- |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.Activate failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- DWORD exit_code(0); |
- hr = task->GetExitCode(&exit_code); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.GetExitCode failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- return hr == SCHED_S_TASK_HAS_NOT_RUN ? hr : exit_code; |
-} |
- |
-HRESULT StartScheduledTask(const TCHAR* task_name) { |
- ASSERT1(task_name && *task_name); |
- |
- if (v2::IsTaskScheduler2APIAvailable()) { |
- return v2::StartScheduledTask(task_name); |
- } |
- |
- if (GetScheduledTaskStatus(task_name) == SCHED_S_TASK_RUNNING) { |
- return S_OK; |
- } |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<ITask> task; |
- hr = scheduler->Activate(task_name, |
- __uuidof(ITask), |
- reinterpret_cast<IUnknown**>(&task)); |
- |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.Activate failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- hr = task->Run(); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.Run failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- return hr; |
-} |
- |
-HRESULT StopScheduledTask(const TCHAR* task_name) { |
- ASSERT1(task_name && *task_name); |
- |
- if (v2::IsTaskScheduler2APIAvailable()) { |
- return v2::StopScheduledTask(task_name); |
- } |
- |
- if (GetScheduledTaskStatus(task_name) != SCHED_S_TASK_RUNNING) { |
- return S_OK; |
- } |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<ITask> task; |
- hr = scheduler->Activate(task_name, |
- __uuidof(ITask), |
- reinterpret_cast<IUnknown**>(&task)); |
- |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.Activate failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- hr = task->Terminate(); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.Run failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- return hr; |
-} |
- |
-HRESULT CreateLogonTrigger(ITask* task) { |
- ASSERT1(task); |
- |
- CComPtr<ITaskTrigger> trigger; |
- WORD index = 0; |
- |
- // Create a trigger to run on every user logon. |
- HRESULT hr = task->CreateTrigger(&index, &trigger); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.CreateTrigger failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- TASK_TRIGGER trigger_config = {0}; |
- trigger_config.cbTriggerSize = sizeof(trigger_config); |
- // These are required parameters. A past start date is good. |
- trigger_config.wBeginDay = 1; |
- trigger_config.wBeginMonth = 1; |
- trigger_config.wBeginYear = 1999; |
- |
- // Run on every user logon. |
- trigger_config.TriggerType = TASK_EVENT_TRIGGER_AT_LOGON; |
- |
- hr = trigger->SetTrigger(&trigger_config); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskTrigger.SetTrigger failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- return S_OK; |
-} |
- |
-HRESULT CreatePeriodicTrigger(ITask* task, bool create_hourly_trigger) { |
- ASSERT1(task); |
- |
- CComPtr<ITaskTrigger> trigger; |
- WORD index = 0; |
- |
- // Create a trigger to run every day. |
- HRESULT hr = task->CreateTrigger(&index, &trigger); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.CreateTrigger failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- // Start time set to 5 minutes from the current time. |
- time64 start_time = GetCurrent100NSTime() + (5 * kMinsTo100ns); |
- SYSTEMTIME sys_time = Time64ToSystemTime(start_time); |
- SYSTEMTIME locale_time = {0}; |
- hr = SystemTimeToTzSpecificLocalTime(NULL, &sys_time, &locale_time); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[SystemTimeToTzSpecificLocalTime failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- TASK_TRIGGER trigger_config = {0}; |
- trigger_config.cbTriggerSize = sizeof(trigger_config); |
- trigger_config.wBeginYear = locale_time.wYear; |
- trigger_config.wBeginMonth = locale_time.wMonth; |
- trigger_config.wBeginDay = locale_time.wDay; |
- trigger_config.wStartHour = locale_time.wHour; |
- trigger_config.wStartMinute = locale_time.wMinute; |
- |
- trigger_config.TriggerType = TASK_TIME_TRIGGER_DAILY; |
- trigger_config.Type.Daily.DaysInterval = 1; // every 1 day |
- |
- if (create_hourly_trigger) { |
- // The task will be run daily at 24 hour intervals. And the task will be |
- // repeated every au_timer_interval_minutes within a single 24 hour |
- // interval. |
- const DWORD kTaskTrigger24HoursDuration = 24 * 60; |
- int au_timer_interval_minutes = |
- ConfigManager::Instance()->GetAutoUpdateTimerIntervalMs() / (60 * 1000); |
- ASSERT1(au_timer_interval_minutes > 0 && |
- au_timer_interval_minutes < kTaskTrigger24HoursDuration); |
- |
- trigger_config.MinutesDuration = kTaskTrigger24HoursDuration; |
- trigger_config.MinutesInterval = au_timer_interval_minutes; |
- } |
- |
- hr = trigger->SetTrigger(&trigger_config); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskTrigger.SetTrigger failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- return S_OK; |
-} |
- |
-HRESULT CreateScheduledTask(ITask* task, |
- const TCHAR* task_path, |
- const TCHAR* task_parameters, |
- const TCHAR* task_comment, |
- bool is_machine, |
- bool create_logon_trigger, |
- bool create_daily_trigger, |
- bool create_hourly_trigger) { |
- ASSERT1(task); |
- ASSERT1(task_path && *task_path); |
- ASSERT1(task_parameters); |
- ASSERT1(task_comment && *task_comment); |
- ASSERT1(create_logon_trigger || create_daily_trigger); |
- ASSERT1(!create_logon_trigger || (create_logon_trigger && is_machine)); |
- ASSERT1(!create_hourly_trigger || |
- (create_hourly_trigger && create_daily_trigger)); |
- |
- UTIL_LOG(L3, (_T("[CreateScheduledTask][%s][%s][%d]"), |
- task_path, task_parameters, is_machine)); |
- |
- HRESULT hr = task->SetApplicationName(task_path); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.SetApplicationName failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- hr = task->SetParameters(task_parameters); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.SetParameters failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- hr = task->SetComment(task_comment); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.SetComment failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- if (is_machine) { |
- // Run using SYSTEM credentials, by passing in an empty username string. |
- hr = task->SetAccountInformation(_T(""), NULL); |
- } else { |
- // Run as current user. |
- // For the user task, we set TASK_FLAG_RUN_ONLY_IF_LOGGED_ON, so that we do |
- // not need the user password for task creation. |
- hr = task->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.SetFlags failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CString user_name; |
- DWORD buffer_size = UNLEN + 1; |
- if (!::GetUserName(CStrBuf(user_name, buffer_size), &buffer_size)) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LE, (_T("[::GetUserName failed][0x%x]"), hr)); |
- return hr; |
- } |
- hr = task->SetAccountInformation(user_name, NULL); |
- } |
- |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.SetAccountInformation failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- // The default is to run for a finite number of days. We want to run |
- // indefinitely. |
- // Due to a bug introduced in Vista, and propogated to Windows 7, setting the |
- // MaxRunTime to INFINITE results in the task only running for 72 hours. For |
- // these operating systems, setting the RunTime to "INFINITE - 1" gets the |
- // desired behavior of allowing an "infinite" run of the task. |
- DWORD max_time = INFINITE - (SystemInfo::IsRunningOnVistaOrLater() ? 1 : 0); |
- hr = task->SetMaxRunTime(max_time); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITask.SetMaxRunTime failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<ITaskTrigger> trigger; |
- WORD index = 0; |
- |
- if (create_logon_trigger && is_machine) { |
- // Create a trigger to run on every user logon. Non-admin users are not able |
- // to create logon triggers, so we create only for machine. |
- hr = CreateLogonTrigger(task); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- } |
- |
- if (create_daily_trigger) { |
- hr = CreatePeriodicTrigger(task, create_hourly_trigger); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- } |
- |
- // Save task. |
- CComQIPtr<IPersistFile> persist(task); |
- if (!persist) { |
- hr = E_NOINTERFACE; |
- UTIL_LOG(LE, (_T("[ITask.QueryInterface IPersistFile failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- hr = persist->Save(NULL, TRUE); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[IPersistFile.Save failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- if (is_machine) { |
- return S_OK; |
- } |
- |
- // Adjust privileges to explicitly allow the current user to be able to |
- // manipulate this task. User applications, and consequently, Omaha, can be |
- // installed in an elevated mode. This can happen, for instance, if the user |
- // installs on XP, then upgrades to Vista. Or chooses "Run as Administrator" |
- // when running the meta-installer on Vista. Subsequently, Omaha running at |
- // medium integrity needs to be able to manipulate the installed task. |
- scoped_ptr_cotask<OLECHAR> job_file; |
- hr = persist->GetCurFile(address(job_file)); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[IPersistFile.GetCurFile failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- persist.Release(); |
- |
- CAccessToken token; |
- CSid current_sid; |
- if (!token.GetEffectiveToken(TOKEN_QUERY) || !token.GetUser(¤t_sid)) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LE, (_T("[Failed to get current user sid][0x%x]"), hr)); |
- return hr; |
- } |
- |
- hr = AddAllowedAce(job_file.get(), |
- SE_FILE_OBJECT, |
- current_sid, |
- FILE_ALL_ACCESS, |
- 0); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[Could not adjust DACL][%s][0x%x]"), job_file.get(), hr)); |
- return hr; |
- } |
- |
- return S_OK; |
-} |
- |
-HRESULT UpgradeScheduledTask(const TCHAR* task_name, |
- const TCHAR* task_path, |
- const TCHAR* task_parameters, |
- const TCHAR* task_comment, |
- bool is_machine, |
- bool create_logon_trigger, |
- bool create_daily_trigger, |
- bool create_hourly_trigger) { |
- ASSERT1(task_name && *task_name); |
- ASSERT1(IsInstalledScheduledTask(task_name)); |
- |
- UTIL_LOG(L3, (_T("[UpgradeScheduledTask][%s][%s][%s][%d]"), |
- task_name, task_path, task_parameters, is_machine)); |
- |
- // TODO(Omaha): Perhaps pass the ITaskScheduler around where possible. |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<ITask> task; |
- hr = scheduler->Activate(task_name, |
- __uuidof(ITask), |
- reinterpret_cast<IUnknown**>(&task)); |
- |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[UpgradeScheduledTask][Activate failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- // Delete existing triggers. CreateScheduledTask() will recreate them anew. |
- WORD trigger_count(0); |
- hr = task->GetTriggerCount(&trigger_count); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.GetTriggerCount failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- for (int i = 0; i < trigger_count; ++i) { |
- hr = task->DeleteTrigger(0); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.DeleteTrigger failed][0x%x]"), hr)); |
- return hr; |
- } |
- } |
- |
- return CreateScheduledTask(task, |
- task_path, |
- task_parameters, |
- task_comment, |
- is_machine, |
- create_logon_trigger, |
- create_daily_trigger, |
- create_hourly_trigger); |
-} |
- |
-// TODO(Omaha): Change the apis to avoid specifying hourly and daily triggers. |
-HRESULT InstallScheduledTask(const TCHAR* task_name, |
- const TCHAR* task_path, |
- const TCHAR* task_parameters, |
- const TCHAR* task_comment, |
- bool is_machine, |
- bool create_logon_trigger, |
- bool create_daily_trigger, |
- bool create_hourly_trigger) { |
- if (IsInstalledScheduledTask(task_name)) { |
- return UpgradeScheduledTask(task_name, |
- task_path, |
- task_parameters, |
- task_comment, |
- is_machine, |
- create_logon_trigger, |
- create_daily_trigger, |
- create_hourly_trigger); |
- } |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<ITask> task; |
- hr = scheduler->NewWorkItem(task_name, |
- CLSID_CTask, |
- __uuidof(ITask), |
- reinterpret_cast<IUnknown**>(&task)); |
- |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.NewWorkItem failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- return CreateScheduledTask(task, |
- task_path, |
- task_parameters, |
- task_comment, |
- is_machine, |
- create_logon_trigger, |
- create_daily_trigger, |
- create_hourly_trigger); |
-} |
- |
-HRESULT UninstallScheduledTask(const TCHAR* task_name) { |
- ASSERT1(task_name && *task_name); |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- // Stop the task before deleting it. Ignore return value. |
- VERIFY1(SUCCEEDED(StopScheduledTask(task_name))); |
- |
- // delete the task. |
- hr = scheduler->Delete(task_name); |
- if (FAILED(hr) && COR_E_FILENOTFOUND != hr) { |
- UTIL_LOG(LE, (_T("[GetScheduledTaskStatus][Delete failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- return S_OK; |
-} |
- |
-HRESULT UninstallScheduledTasks(const TCHAR* task_prefix) { |
- ASSERT1(task_prefix && *task_prefix); |
- |
- CComPtr<ITaskScheduler> scheduler; |
- HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<IEnumWorkItems> enum_items; |
- hr = scheduler->Enum(&enum_items); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskScheduler.Enum failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- TCHAR** task_names = NULL; |
- DWORD task_count = 0; |
- while (enum_items->Next(1, &task_names, &task_count) == S_OK) { |
- ASSERT1(task_count == 1); |
- scoped_co_task_ptr task_names_guard(task_names); |
- scoped_co_task_ptr task_name_guard(task_names[0]); |
- |
- if (String_StartsWith(task_names[0], task_prefix, true)) { |
- UninstallScheduledTask(task_names[0]); |
- } |
- } |
- |
- return S_OK; |
-} |
- |
-// Returns the task name Omaha used to install in Omaha 1.2.x. |
-CString GetOmaha1LegacyTaskName(bool is_machine) { |
- const TCHAR* const kLegacyOmaha1TaskNameMachine = _T("GoogleUpdateTask"); |
- const TCHAR* const kLegacyOmaha1TaskNameUser = _T("GoogleUpdateTaskUser"); |
- return is_machine ? kLegacyOmaha1TaskNameMachine : kLegacyOmaha1TaskNameUser; |
-} |
- |
-// Returns the task name Omaha used to install in Omaha 2 before the |
-// "GoogleUpdate.exe does not run all the time" refactoring. |
-CString GetOmaha2LegacyTaskName(bool is_machine) { |
- const TCHAR* kLegacyOmaha2TaskNameUserPrefix = _T("GoogleUpdateTaskUser"); |
- const TCHAR* kLegacyOmaha2TaskNameMachine = _T("GoogleUpdateTaskMachine"); |
- if (is_machine) { |
- return kLegacyOmaha2TaskNameMachine; |
- } |
- |
- CString task_name_user = kLegacyOmaha2TaskNameUserPrefix; |
- CString user_sid; |
- VERIFY1(SUCCEEDED(user_info::GetProcessUser(NULL, NULL, &user_sid))); |
- task_name_user += user_sid; |
- return task_name_user; |
-} |
- |
-HRESULT WaitForTaskStatus(const TCHAR* task_name, HRESULT status, int time_ms) { |
- int kSleepBetweenRetriesMs = 100; |
- Timer timer(true); |
- while (timer.GetMilliseconds() < time_ms) { |
- if (GetScheduledTaskStatus(task_name) == status) { |
- return status; |
- } |
- ::Sleep(kSleepBetweenRetriesMs); |
- } |
- return GetScheduledTaskStatus(task_name); |
-} |
- |
-namespace v2 { |
- |
-bool IsTaskScheduler2APIAvailable() { |
- CComPtr<ITaskService> task_service; |
- return SUCCEEDED(task_service.CoCreateInstance(CLSID_TaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER)); |
-} |
- |
-HRESULT GetRegisteredTask(const TCHAR* task_name, IRegisteredTask** task) { |
- ASSERT1(IsTaskScheduler2APIAvailable()); |
- ASSERT1(task_name && *task_name); |
- ASSERT1(task); |
- |
- CComPtr<ITaskService> task_service; |
- HRESULT hr = task_service.CoCreateInstance(CLSID_TaskScheduler, |
- NULL, |
- CLSCTX_INPROC_SERVER); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskService.CoCreateInstance failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- hr = task_service->Connect(CComVariant(), CComVariant(), |
- CComVariant(), CComVariant()); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[ITaskService::Connect failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<ITaskFolder> task_folder; |
- hr = task_service->GetFolder(CComBSTR(_T("\\")) , &task_folder); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[Cannot get Root Folder pointer][0x%x]"), hr)); |
- return hr; |
- } |
- |
- CComPtr<IRegisteredTask> registered_task; |
- hr = task_folder->GetTask(CComBSTR(task_name), ®istered_task); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[Cannot get the registered task][0x%x]"), hr)); |
- return hr; |
- } |
- |
- *task = registered_task.Detach(); |
- return S_OK; |
-} |
- |
-bool IsScheduledTaskRunning(const TCHAR* task_name) { |
- ASSERT1(IsTaskScheduler2APIAvailable()); |
- ASSERT1(task_name && *task_name); |
- |
- CComPtr<IRegisteredTask> registered_task; |
- HRESULT hr = GetRegisteredTask(task_name, ®istered_task); |
- if (FAILED(hr)) { |
- return false; |
- } |
- |
- CComPtr<IRunningTaskCollection> running_task_collection; |
- hr = registered_task->GetInstances(0, &running_task_collection); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[IRegisteredTask.GetInstances failed][0x%x]"), hr)); |
- return false; |
- } |
- |
- long count = 0; |
- hr = running_task_collection->get_Count(&count); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[IRunningTaskCollection.get_Count failed][0x%x]"), hr)); |
- return false; |
- } |
- |
- return count > 0; |
-} |
- |
-HRESULT StartScheduledTask(const TCHAR* task_name) { |
- ASSERT1(IsTaskScheduler2APIAvailable()); |
- ASSERT1(task_name && *task_name); |
- |
- if (IsScheduledTaskRunning(task_name)) { |
- return S_OK; |
- } |
- |
- CComPtr<IRegisteredTask> registered_task; |
- HRESULT hr = GetRegisteredTask(task_name, ®istered_task); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- hr = registered_task->Run(CComVariant(), NULL); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[IRegisteredTask.Run failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- return hr; |
-} |
- |
-HRESULT StopScheduledTask(const TCHAR* task_name) { |
- ASSERT1(IsTaskScheduler2APIAvailable()); |
- ASSERT1(task_name && *task_name); |
- |
- if (!IsScheduledTaskRunning(task_name)) { |
- return S_OK; |
- } |
- |
- CComPtr<IRegisteredTask> registered_task; |
- HRESULT hr = GetRegisteredTask(task_name, ®istered_task); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- CComPtr<IRunningTaskCollection> running_task_collection; |
- hr = registered_task->GetInstances(0, &running_task_collection); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[IRegisteredTask.GetInstances failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- long count = 0; |
- hr = running_task_collection->get_Count(&count); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[IRunningTaskCollection.get_Count failed][0x%x]"), hr)); |
- return hr; |
- } |
- |
- if (count <= 0) { |
- return S_OK; |
- } |
- |
- for (long i = 0; i < count; ++i) { |
- CComPtr<IRunningTask> running_task; |
- hr = running_task_collection->get_Item(CComVariant(i+1), &running_task); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[IRunningTaskCollection.get_Item][%d][0x%x]"), i, hr)); |
- return hr; |
- } |
- |
- hr = running_task->Stop(); |
- if (FAILED(hr)) { |
- UTIL_LOG(LE, (_T("[IRunningTask.Stop failed][%d][0x%x]"), i, hr)); |
- return hr; |
- } |
- } |
- |
- return S_OK; |
-} |
- |
-} // namespace v2 |
- |
-} // namespace internal |
- |
-CString GetDefaultGoopdateTaskName(bool is_machine, CommandLineMode mode) { |
- ASSERT1(mode == COMMANDLINE_MODE_CORE || mode == COMMANDLINE_MODE_UA); |
- |
- CString task_name; |
- if (is_machine) { |
- task_name = kScheduledTaskNameMachinePrefix; |
- } else { |
- task_name = kScheduledTaskNameUserPrefix; |
- CString user_sid; |
- VERIFY1(SUCCEEDED(user_info::GetProcessUser(NULL, NULL, &user_sid))); |
- task_name += user_sid; |
- } |
- |
- task_name += (mode == COMMANDLINE_MODE_CORE) ? kScheduledTaskNameCoreSuffix : |
- kScheduledTaskNameUASuffix; |
- return task_name; |
-} |
- |
-HRESULT InstallGoopdateTaskForMode(const TCHAR* task_path, |
- bool is_machine, |
- CommandLineMode mode) { |
- ASSERT1(mode == COMMANDLINE_MODE_CORE || mode == COMMANDLINE_MODE_UA); |
- |
- CommandLineBuilder builder(mode); |
- if (mode == COMMANDLINE_MODE_UA) { |
- builder.set_install_source(kCmdLineInstallSource_Scheduler); |
- } |
- const CString task_parameters = builder.GetCommandLineArgs(); |
- |
- CString company_name; |
- VERIFY1(company_name.LoadString(IDS_FRIENDLY_COMPANY_NAME)); |
- CString task_description; |
- task_description.FormatMessage(IDS_SCHEDULED_TASK_DESCRIPTION, company_name); |
- |
- CString task_name(mode == COMMANDLINE_MODE_CORE ? |
- internal::GetCurrentTaskNameCore(is_machine) : |
- internal::GetCurrentTaskNameUA(is_machine)); |
- if (internal::IsInstalledScheduledTask(task_name)) { |
- HRESULT hr = internal::InstallScheduledTask(task_name, |
- task_path, |
- task_parameters, |
- task_description, |
- is_machine, |
- mode == COMMANDLINE_MODE_CORE && |
- is_machine, |
- true, |
- mode == COMMANDLINE_MODE_UA); |
- |
- if (SUCCEEDED(hr)) { |
- return hr; |
- } |
- |
- // Try to uninstall the task that we failed to upgrade. Then create a new |
- // task name, and fall through to install that. |
- internal::UninstallScheduledTask(task_name); |
- if (mode == COMMANDLINE_MODE_CORE) { |
- VERIFY1(SUCCEEDED( |
- internal::CreateAndSetVersionedTaskNameCoreInRegistry(is_machine))); |
- task_name = internal::GetCurrentTaskNameCore(is_machine); |
- } else { |
- VERIFY1(SUCCEEDED( |
- internal::CreateAndSetVersionedTaskNameUAInRegistry(is_machine))); |
- task_name = internal::GetCurrentTaskNameUA(is_machine); |
- } |
- ASSERT1(!internal::IsInstalledScheduledTask(task_name)); |
- } |
- |
- return internal::InstallScheduledTask(task_name, |
- task_path, |
- task_parameters, |
- task_description, |
- is_machine, |
- mode == COMMANDLINE_MODE_CORE && |
- is_machine, |
- true, |
- mode == COMMANDLINE_MODE_UA); |
-} |
- |
-HRESULT InstallGoopdateTasks(const TCHAR* task_path, bool is_machine) { |
- HRESULT hr = InstallGoopdateTaskForMode(task_path, |
- is_machine, |
- COMMANDLINE_MODE_CORE); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- return InstallGoopdateTaskForMode(task_path, is_machine, COMMANDLINE_MODE_UA); |
-} |
- |
-HRESULT UninstallGoopdateTasks(bool is_machine) { |
- VERIFY1(SUCCEEDED(internal::UninstallScheduledTask( |
- internal::GetCurrentTaskNameCore(is_machine)))); |
- VERIFY1(SUCCEEDED(internal::UninstallScheduledTask( |
- internal::GetCurrentTaskNameUA(is_machine)))); |
- |
- // Try to uninstall any tasks that we failed to update during a previous |
- // overinstall. It is possible that we fail to uninstall these again here. |
- VERIFY1(SUCCEEDED(internal::UninstallScheduledTasks( |
- scheduled_task_utils::GetDefaultGoopdateTaskName(is_machine, |
- COMMANDLINE_MODE_CORE)))); |
- VERIFY1(SUCCEEDED(internal::UninstallScheduledTasks( |
- scheduled_task_utils::GetDefaultGoopdateTaskName(is_machine, |
- COMMANDLINE_MODE_UA)))); |
- return S_OK; |
-} |
- |
-HRESULT UninstallLegacyGoopdateTasks(bool is_machine) { |
- const CString& legacy_omaha1_task = |
- internal::GetOmaha1LegacyTaskName(is_machine); |
- VERIFY1(SUCCEEDED(internal::UninstallScheduledTask(legacy_omaha1_task))); |
- |
- const CString& legacy_omaha2_task = |
- internal::GetOmaha2LegacyTaskName(is_machine); |
- VERIFY1(SUCCEEDED(internal::UninstallScheduledTask(legacy_omaha2_task))); |
- |
- return S_OK; |
-} |
- |
-HRESULT StartGoopdateTaskCore(bool is_machine) { |
- return internal::StartScheduledTask( |
- internal::GetCurrentTaskNameCore(is_machine)); |
-} |
- |
-bool IsInstalledGoopdateTaskUA(bool is_machine) { |
- return internal::IsInstalledScheduledTask( |
- internal::GetCurrentTaskNameUA(is_machine)); |
-} |
- |
-bool IsDisabledGoopdateTaskUA(bool is_machine) { |
- const CString& task_name(internal::GetCurrentTaskNameUA(is_machine)); |
- return internal::GetScheduledTaskStatus(task_name) == SCHED_S_TASK_DISABLED; |
-} |
- |
-HRESULT GetExitCodeGoopdateTaskUA(bool is_machine) { |
- const CString& task_name(internal::GetCurrentTaskNameUA(is_machine)); |
- return internal::GetScheduledTaskExitCode(task_name); |
-} |
- |
-bool IsUATaskHealthy(bool is_machine) { |
- if (!ServiceUtils::IsServiceRunning(SERVICE_SCHEDULE)) { |
- UTIL_LOG(LW, (_T("[Task Scheduler Service is not running]"))); |
- return false; |
- } |
- |
- if (!IsInstalledGoopdateTaskUA(is_machine)) { |
- UTIL_LOG(LW, (_T("[UA Task not installed]"))); |
- return false; |
- } |
- |
- if (IsDisabledGoopdateTaskUA(is_machine)) { |
- UTIL_LOG(LW, (_T("[UA Task disabled]"))); |
- return false; |
- } |
- |
- return true; |
-} |
- |
-} // namespace scheduled_task_utils |
- |
-} // namespace omaha |