| OLD | NEW |
| (Empty) |
| 1 // Copyright 2007-2010 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 | |
| 15 #include "omaha/common/scheduled_task_utils.h" | |
| 16 #include "omaha/common/scheduled_task_utils_internal.h" | |
| 17 #include <corerror.h> | |
| 18 #include <lmcons.h> | |
| 19 #include <lmsname.h> | |
| 20 #include <mstask.h> | |
| 21 #include <atlsecurity.h> | |
| 22 #include "omaha/base/debug.h" | |
| 23 #include "omaha/base/error.h" | |
| 24 #include "omaha/base/logging.h" | |
| 25 #include "omaha/base/scoped_ptr_cotask.h" | |
| 26 #include "omaha/base/service_utils.h" | |
| 27 #include "omaha/base/string.h" | |
| 28 #include "omaha/base/system_info.h" | |
| 29 #include "omaha/base/time.h" | |
| 30 #include "omaha/base/timer.h" | |
| 31 #include "omaha/base/user_info.h" | |
| 32 #include "omaha/base/utils.h" | |
| 33 #include "omaha/client/resource.h" | |
| 34 #include "omaha/common/command_line_builder.h" | |
| 35 #include "omaha/common/config_manager.h" | |
| 36 #include "omaha/common/const_cmd_line.h" | |
| 37 #include "omaha/common/const_goopdate.h" | |
| 38 #include "omaha/common/goopdate_utils.h" | |
| 39 | |
| 40 namespace omaha { | |
| 41 | |
| 42 namespace scheduled_task_utils { | |
| 43 | |
| 44 namespace internal { | |
| 45 | |
| 46 CString GetCurrentTaskNameCore(bool is_machine) { | |
| 47 UTIL_LOG(L3, (_T("[GetCurrentTaskNameCore][%d]"), is_machine)); | |
| 48 | |
| 49 CString default_name(GetDefaultGoopdateTaskName(is_machine, | |
| 50 COMMANDLINE_MODE_CORE)); | |
| 51 return goopdate_utils::GetCurrentVersionedName(is_machine, | |
| 52 kRegValueTaskNameC, | |
| 53 default_name); | |
| 54 } | |
| 55 | |
| 56 HRESULT CreateAndSetVersionedTaskNameCoreInRegistry( | |
| 57 bool is_machine) { | |
| 58 UTIL_LOG(L3, (_T("[CreateAndSetVersionedTaskNameCoreInRegistry][%d]"), | |
| 59 is_machine)); | |
| 60 | |
| 61 CString default_name(GetDefaultGoopdateTaskName(is_machine, | |
| 62 COMMANDLINE_MODE_CORE)); | |
| 63 return goopdate_utils::CreateAndSetVersionedNameInRegistry( | |
| 64 is_machine, | |
| 65 default_name, | |
| 66 kRegValueTaskNameC); | |
| 67 } | |
| 68 | |
| 69 CString GetCurrentTaskNameUA(bool is_machine) { | |
| 70 UTIL_LOG(L3, (_T("[GetCurrentTaskNameUA][%d]"), is_machine)); | |
| 71 | |
| 72 CString default_name(GetDefaultGoopdateTaskName(is_machine, | |
| 73 COMMANDLINE_MODE_UA)); | |
| 74 return goopdate_utils::GetCurrentVersionedName(is_machine, | |
| 75 kRegValueTaskNameUA, | |
| 76 default_name); | |
| 77 } | |
| 78 | |
| 79 HRESULT CreateAndSetVersionedTaskNameUAInRegistry(bool machine) { | |
| 80 UTIL_LOG(L3, (_T("[CreateAndSetVersionedTaskNameUAInRegistry][%d]"), | |
| 81 machine)); | |
| 82 | |
| 83 CString default_name(GetDefaultGoopdateTaskName(machine, | |
| 84 COMMANDLINE_MODE_UA)); | |
| 85 return goopdate_utils::CreateAndSetVersionedNameInRegistry( | |
| 86 machine, | |
| 87 default_name, | |
| 88 kRegValueTaskNameUA); | |
| 89 } | |
| 90 | |
| 91 bool IsInstalledScheduledTask(const TCHAR* task_name) { | |
| 92 ASSERT1(task_name && *task_name); | |
| 93 | |
| 94 CComPtr<ITaskScheduler> scheduler; | |
| 95 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 96 NULL, | |
| 97 CLSCTX_INPROC_SERVER); | |
| 98 if (FAILED(hr)) { | |
| 99 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 100 return false; | |
| 101 } | |
| 102 | |
| 103 CComPtr<ITask> task; | |
| 104 hr = scheduler->Activate(task_name, | |
| 105 __uuidof(ITask), | |
| 106 reinterpret_cast<IUnknown**>(&task)); | |
| 107 | |
| 108 UTIL_LOG(L3, (_T("[IsInstalledScheduledTask returned][0x%x]"), hr)); | |
| 109 return COR_E_FILENOTFOUND == hr ? false : true; | |
| 110 } | |
| 111 | |
| 112 DWORD GetScheduledTaskPriority(const TCHAR* task_name) { | |
| 113 ASSERT1(task_name && *task_name); | |
| 114 | |
| 115 CComPtr<ITaskScheduler> scheduler; | |
| 116 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 117 NULL, | |
| 118 CLSCTX_INPROC_SERVER); | |
| 119 if (FAILED(hr)) { | |
| 120 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 121 return 0; | |
| 122 } | |
| 123 | |
| 124 CComPtr<ITask> task; | |
| 125 hr = scheduler->Activate(task_name, | |
| 126 __uuidof(ITask), | |
| 127 reinterpret_cast<IUnknown**>(&task)); | |
| 128 | |
| 129 if (FAILED(hr)) { | |
| 130 UTIL_LOG(LE, (_T("[GetScheduledTaskPriority][Activate failed][0x%x]"), hr)); | |
| 131 return 0; | |
| 132 } | |
| 133 | |
| 134 DWORD priority = 0; | |
| 135 hr = task->GetPriority(&priority); | |
| 136 if (FAILED(hr)) { | |
| 137 UTIL_LOG(LE, (_T("[ITask.GetMostRecentRunTime failed][0x%x]"), hr)); | |
| 138 return 0; | |
| 139 } | |
| 140 | |
| 141 ASSERT1(priority); | |
| 142 return priority; | |
| 143 } | |
| 144 | |
| 145 bool HasScheduledTaskEverRun(const TCHAR* task_name) { | |
| 146 ASSERT1(task_name && *task_name); | |
| 147 | |
| 148 CComPtr<ITaskScheduler> scheduler; | |
| 149 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 150 NULL, | |
| 151 CLSCTX_INPROC_SERVER); | |
| 152 if (FAILED(hr)) { | |
| 153 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 154 return false; | |
| 155 } | |
| 156 | |
| 157 CComPtr<ITask> task; | |
| 158 hr = scheduler->Activate(task_name, | |
| 159 __uuidof(ITask), | |
| 160 reinterpret_cast<IUnknown**>(&task)); | |
| 161 | |
| 162 if (FAILED(hr)) { | |
| 163 UTIL_LOG(LE, (_T("[HasScheduledTaskEverRun][Activate failed][0x%x]"), hr)); | |
| 164 return false; | |
| 165 } | |
| 166 | |
| 167 SYSTEMTIME recent_run_time = {0}; | |
| 168 hr = task->GetMostRecentRunTime(&recent_run_time); | |
| 169 if (FAILED(hr)) { | |
| 170 UTIL_LOG(LE, (_T("[ITask.GetMostRecentRunTime failed][0x%x]"), hr)); | |
| 171 return false; | |
| 172 } | |
| 173 | |
| 174 // hr == SCHED_S_TASK_HAS_NOT_RUN if the task has never run. | |
| 175 return hr == S_OK; | |
| 176 } | |
| 177 | |
| 178 HRESULT GetScheduledTaskStatus(const TCHAR* task_name) { | |
| 179 ASSERT1(task_name && *task_name); | |
| 180 | |
| 181 CComPtr<ITaskScheduler> scheduler; | |
| 182 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 183 NULL, | |
| 184 CLSCTX_INPROC_SERVER); | |
| 185 if (FAILED(hr)) { | |
| 186 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 187 return hr; | |
| 188 } | |
| 189 | |
| 190 CComPtr<ITask> task; | |
| 191 hr = scheduler->Activate(task_name, | |
| 192 __uuidof(ITask), | |
| 193 reinterpret_cast<IUnknown**>(&task)); | |
| 194 | |
| 195 if (FAILED(hr)) { | |
| 196 UTIL_LOG(LE, (_T("[GetScheduledTaskStatus: Activate failed][0x%x]"), hr)); | |
| 197 return hr; | |
| 198 } | |
| 199 | |
| 200 HRESULT task_status(S_OK); | |
| 201 hr = task->GetStatus(&task_status); | |
| 202 if (FAILED(hr)) { | |
| 203 UTIL_LOG(LE, (_T("[ITask.GetStatus failed][0x%x]"), hr)); | |
| 204 return hr; | |
| 205 } | |
| 206 | |
| 207 return task_status; | |
| 208 } | |
| 209 | |
| 210 HRESULT GetScheduledTaskExitCode(const TCHAR* task_name) { | |
| 211 ASSERT1(task_name && *task_name); | |
| 212 | |
| 213 CComPtr<ITaskScheduler> scheduler; | |
| 214 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 215 NULL, | |
| 216 CLSCTX_INPROC_SERVER); | |
| 217 if (FAILED(hr)) { | |
| 218 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 219 return hr; | |
| 220 } | |
| 221 | |
| 222 CComPtr<ITask> task; | |
| 223 hr = scheduler->Activate(task_name, | |
| 224 __uuidof(ITask), | |
| 225 reinterpret_cast<IUnknown**>(&task)); | |
| 226 | |
| 227 if (FAILED(hr)) { | |
| 228 UTIL_LOG(LE, (_T("[ITask.Activate failed][0x%x]"), hr)); | |
| 229 return hr; | |
| 230 } | |
| 231 | |
| 232 DWORD exit_code(0); | |
| 233 hr = task->GetExitCode(&exit_code); | |
| 234 if (FAILED(hr)) { | |
| 235 UTIL_LOG(LE, (_T("[ITask.GetExitCode failed][0x%x]"), hr)); | |
| 236 return hr; | |
| 237 } | |
| 238 | |
| 239 return hr == SCHED_S_TASK_HAS_NOT_RUN ? hr : exit_code; | |
| 240 } | |
| 241 | |
| 242 HRESULT StartScheduledTask(const TCHAR* task_name) { | |
| 243 ASSERT1(task_name && *task_name); | |
| 244 | |
| 245 if (v2::IsTaskScheduler2APIAvailable()) { | |
| 246 return v2::StartScheduledTask(task_name); | |
| 247 } | |
| 248 | |
| 249 if (GetScheduledTaskStatus(task_name) == SCHED_S_TASK_RUNNING) { | |
| 250 return S_OK; | |
| 251 } | |
| 252 | |
| 253 CComPtr<ITaskScheduler> scheduler; | |
| 254 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 255 NULL, | |
| 256 CLSCTX_INPROC_SERVER); | |
| 257 if (FAILED(hr)) { | |
| 258 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 259 return hr; | |
| 260 } | |
| 261 | |
| 262 CComPtr<ITask> task; | |
| 263 hr = scheduler->Activate(task_name, | |
| 264 __uuidof(ITask), | |
| 265 reinterpret_cast<IUnknown**>(&task)); | |
| 266 | |
| 267 if (FAILED(hr)) { | |
| 268 UTIL_LOG(LE, (_T("[ITaskScheduler.Activate failed][0x%x]"), hr)); | |
| 269 return hr; | |
| 270 } | |
| 271 | |
| 272 hr = task->Run(); | |
| 273 if (FAILED(hr)) { | |
| 274 UTIL_LOG(LE, (_T("[ITask.Run failed][0x%x]"), hr)); | |
| 275 return hr; | |
| 276 } | |
| 277 | |
| 278 return hr; | |
| 279 } | |
| 280 | |
| 281 HRESULT StopScheduledTask(const TCHAR* task_name) { | |
| 282 ASSERT1(task_name && *task_name); | |
| 283 | |
| 284 if (v2::IsTaskScheduler2APIAvailable()) { | |
| 285 return v2::StopScheduledTask(task_name); | |
| 286 } | |
| 287 | |
| 288 if (GetScheduledTaskStatus(task_name) != SCHED_S_TASK_RUNNING) { | |
| 289 return S_OK; | |
| 290 } | |
| 291 | |
| 292 CComPtr<ITaskScheduler> scheduler; | |
| 293 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 294 NULL, | |
| 295 CLSCTX_INPROC_SERVER); | |
| 296 if (FAILED(hr)) { | |
| 297 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 298 return hr; | |
| 299 } | |
| 300 | |
| 301 CComPtr<ITask> task; | |
| 302 hr = scheduler->Activate(task_name, | |
| 303 __uuidof(ITask), | |
| 304 reinterpret_cast<IUnknown**>(&task)); | |
| 305 | |
| 306 if (FAILED(hr)) { | |
| 307 UTIL_LOG(LE, (_T("[ITaskScheduler.Activate failed][0x%x]"), hr)); | |
| 308 return hr; | |
| 309 } | |
| 310 | |
| 311 hr = task->Terminate(); | |
| 312 if (FAILED(hr)) { | |
| 313 UTIL_LOG(LE, (_T("[ITask.Run failed][0x%x]"), hr)); | |
| 314 return hr; | |
| 315 } | |
| 316 | |
| 317 return hr; | |
| 318 } | |
| 319 | |
| 320 HRESULT CreateLogonTrigger(ITask* task) { | |
| 321 ASSERT1(task); | |
| 322 | |
| 323 CComPtr<ITaskTrigger> trigger; | |
| 324 WORD index = 0; | |
| 325 | |
| 326 // Create a trigger to run on every user logon. | |
| 327 HRESULT hr = task->CreateTrigger(&index, &trigger); | |
| 328 if (FAILED(hr)) { | |
| 329 UTIL_LOG(LE, (_T("[ITask.CreateTrigger failed][0x%x]"), hr)); | |
| 330 return hr; | |
| 331 } | |
| 332 | |
| 333 TASK_TRIGGER trigger_config = {0}; | |
| 334 trigger_config.cbTriggerSize = sizeof(trigger_config); | |
| 335 // These are required parameters. A past start date is good. | |
| 336 trigger_config.wBeginDay = 1; | |
| 337 trigger_config.wBeginMonth = 1; | |
| 338 trigger_config.wBeginYear = 1999; | |
| 339 | |
| 340 // Run on every user logon. | |
| 341 trigger_config.TriggerType = TASK_EVENT_TRIGGER_AT_LOGON; | |
| 342 | |
| 343 hr = trigger->SetTrigger(&trigger_config); | |
| 344 if (FAILED(hr)) { | |
| 345 UTIL_LOG(LE, (_T("[ITaskTrigger.SetTrigger failed][0x%x]"), hr)); | |
| 346 return hr; | |
| 347 } | |
| 348 | |
| 349 return S_OK; | |
| 350 } | |
| 351 | |
| 352 HRESULT CreatePeriodicTrigger(ITask* task, bool create_hourly_trigger) { | |
| 353 ASSERT1(task); | |
| 354 | |
| 355 CComPtr<ITaskTrigger> trigger; | |
| 356 WORD index = 0; | |
| 357 | |
| 358 // Create a trigger to run every day. | |
| 359 HRESULT hr = task->CreateTrigger(&index, &trigger); | |
| 360 if (FAILED(hr)) { | |
| 361 UTIL_LOG(LE, (_T("[ITask.CreateTrigger failed][0x%x]"), hr)); | |
| 362 return hr; | |
| 363 } | |
| 364 | |
| 365 // Start time set to 5 minutes from the current time. | |
| 366 time64 start_time = GetCurrent100NSTime() + (5 * kMinsTo100ns); | |
| 367 SYSTEMTIME sys_time = Time64ToSystemTime(start_time); | |
| 368 SYSTEMTIME locale_time = {0}; | |
| 369 hr = SystemTimeToTzSpecificLocalTime(NULL, &sys_time, &locale_time); | |
| 370 if (FAILED(hr)) { | |
| 371 UTIL_LOG(LE, (_T("[SystemTimeToTzSpecificLocalTime failed][0x%x]"), hr)); | |
| 372 return hr; | |
| 373 } | |
| 374 | |
| 375 TASK_TRIGGER trigger_config = {0}; | |
| 376 trigger_config.cbTriggerSize = sizeof(trigger_config); | |
| 377 trigger_config.wBeginYear = locale_time.wYear; | |
| 378 trigger_config.wBeginMonth = locale_time.wMonth; | |
| 379 trigger_config.wBeginDay = locale_time.wDay; | |
| 380 trigger_config.wStartHour = locale_time.wHour; | |
| 381 trigger_config.wStartMinute = locale_time.wMinute; | |
| 382 | |
| 383 trigger_config.TriggerType = TASK_TIME_TRIGGER_DAILY; | |
| 384 trigger_config.Type.Daily.DaysInterval = 1; // every 1 day | |
| 385 | |
| 386 if (create_hourly_trigger) { | |
| 387 // The task will be run daily at 24 hour intervals. And the task will be | |
| 388 // repeated every au_timer_interval_minutes within a single 24 hour | |
| 389 // interval. | |
| 390 const DWORD kTaskTrigger24HoursDuration = 24 * 60; | |
| 391 int au_timer_interval_minutes = | |
| 392 ConfigManager::Instance()->GetAutoUpdateTimerIntervalMs() / (60 * 1000); | |
| 393 ASSERT1(au_timer_interval_minutes > 0 && | |
| 394 au_timer_interval_minutes < kTaskTrigger24HoursDuration); | |
| 395 | |
| 396 trigger_config.MinutesDuration = kTaskTrigger24HoursDuration; | |
| 397 trigger_config.MinutesInterval = au_timer_interval_minutes; | |
| 398 } | |
| 399 | |
| 400 hr = trigger->SetTrigger(&trigger_config); | |
| 401 if (FAILED(hr)) { | |
| 402 UTIL_LOG(LE, (_T("[ITaskTrigger.SetTrigger failed][0x%x]"), hr)); | |
| 403 return hr; | |
| 404 } | |
| 405 | |
| 406 return S_OK; | |
| 407 } | |
| 408 | |
| 409 HRESULT CreateScheduledTask(ITask* task, | |
| 410 const TCHAR* task_path, | |
| 411 const TCHAR* task_parameters, | |
| 412 const TCHAR* task_comment, | |
| 413 bool is_machine, | |
| 414 bool create_logon_trigger, | |
| 415 bool create_daily_trigger, | |
| 416 bool create_hourly_trigger) { | |
| 417 ASSERT1(task); | |
| 418 ASSERT1(task_path && *task_path); | |
| 419 ASSERT1(task_parameters); | |
| 420 ASSERT1(task_comment && *task_comment); | |
| 421 ASSERT1(create_logon_trigger || create_daily_trigger); | |
| 422 ASSERT1(!create_logon_trigger || (create_logon_trigger && is_machine)); | |
| 423 ASSERT1(!create_hourly_trigger || | |
| 424 (create_hourly_trigger && create_daily_trigger)); | |
| 425 | |
| 426 UTIL_LOG(L3, (_T("[CreateScheduledTask][%s][%s][%d]"), | |
| 427 task_path, task_parameters, is_machine)); | |
| 428 | |
| 429 HRESULT hr = task->SetApplicationName(task_path); | |
| 430 if (FAILED(hr)) { | |
| 431 UTIL_LOG(LE, (_T("[ITask.SetApplicationName failed][0x%x]"), hr)); | |
| 432 return hr; | |
| 433 } | |
| 434 | |
| 435 hr = task->SetParameters(task_parameters); | |
| 436 if (FAILED(hr)) { | |
| 437 UTIL_LOG(LE, (_T("[ITask.SetParameters failed][0x%x]"), hr)); | |
| 438 return hr; | |
| 439 } | |
| 440 | |
| 441 hr = task->SetComment(task_comment); | |
| 442 if (FAILED(hr)) { | |
| 443 UTIL_LOG(LE, (_T("[ITask.SetComment failed][0x%x]"), hr)); | |
| 444 return hr; | |
| 445 } | |
| 446 | |
| 447 if (is_machine) { | |
| 448 // Run using SYSTEM credentials, by passing in an empty username string. | |
| 449 hr = task->SetAccountInformation(_T(""), NULL); | |
| 450 } else { | |
| 451 // Run as current user. | |
| 452 // For the user task, we set TASK_FLAG_RUN_ONLY_IF_LOGGED_ON, so that we do | |
| 453 // not need the user password for task creation. | |
| 454 hr = task->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON); | |
| 455 if (FAILED(hr)) { | |
| 456 UTIL_LOG(LE, (_T("[ITask.SetFlags failed][0x%x]"), hr)); | |
| 457 return hr; | |
| 458 } | |
| 459 | |
| 460 CString user_name; | |
| 461 DWORD buffer_size = UNLEN + 1; | |
| 462 if (!::GetUserName(CStrBuf(user_name, buffer_size), &buffer_size)) { | |
| 463 hr = HRESULTFromLastError(); | |
| 464 UTIL_LOG(LE, (_T("[::GetUserName failed][0x%x]"), hr)); | |
| 465 return hr; | |
| 466 } | |
| 467 hr = task->SetAccountInformation(user_name, NULL); | |
| 468 } | |
| 469 | |
| 470 if (FAILED(hr)) { | |
| 471 UTIL_LOG(LE, (_T("[ITask.SetAccountInformation failed][0x%x]"), hr)); | |
| 472 return hr; | |
| 473 } | |
| 474 | |
| 475 // The default is to run for a finite number of days. We want to run | |
| 476 // indefinitely. | |
| 477 // Due to a bug introduced in Vista, and propogated to Windows 7, setting the | |
| 478 // MaxRunTime to INFINITE results in the task only running for 72 hours. For | |
| 479 // these operating systems, setting the RunTime to "INFINITE - 1" gets the | |
| 480 // desired behavior of allowing an "infinite" run of the task. | |
| 481 DWORD max_time = INFINITE - (SystemInfo::IsRunningOnVistaOrLater() ? 1 : 0); | |
| 482 hr = task->SetMaxRunTime(max_time); | |
| 483 if (FAILED(hr)) { | |
| 484 UTIL_LOG(LE, (_T("[ITask.SetMaxRunTime failed][0x%x]"), hr)); | |
| 485 return hr; | |
| 486 } | |
| 487 | |
| 488 CComPtr<ITaskTrigger> trigger; | |
| 489 WORD index = 0; | |
| 490 | |
| 491 if (create_logon_trigger && is_machine) { | |
| 492 // Create a trigger to run on every user logon. Non-admin users are not able | |
| 493 // to create logon triggers, so we create only for machine. | |
| 494 hr = CreateLogonTrigger(task); | |
| 495 if (FAILED(hr)) { | |
| 496 return hr; | |
| 497 } | |
| 498 } | |
| 499 | |
| 500 if (create_daily_trigger) { | |
| 501 hr = CreatePeriodicTrigger(task, create_hourly_trigger); | |
| 502 if (FAILED(hr)) { | |
| 503 return hr; | |
| 504 } | |
| 505 } | |
| 506 | |
| 507 // Save task. | |
| 508 CComQIPtr<IPersistFile> persist(task); | |
| 509 if (!persist) { | |
| 510 hr = E_NOINTERFACE; | |
| 511 UTIL_LOG(LE, (_T("[ITask.QueryInterface IPersistFile failed][0x%x]"), hr)); | |
| 512 return hr; | |
| 513 } | |
| 514 | |
| 515 hr = persist->Save(NULL, TRUE); | |
| 516 if (FAILED(hr)) { | |
| 517 UTIL_LOG(LE, (_T("[IPersistFile.Save failed][0x%x]"), hr)); | |
| 518 return hr; | |
| 519 } | |
| 520 | |
| 521 if (is_machine) { | |
| 522 return S_OK; | |
| 523 } | |
| 524 | |
| 525 // Adjust privileges to explicitly allow the current user to be able to | |
| 526 // manipulate this task. User applications, and consequently, Omaha, can be | |
| 527 // installed in an elevated mode. This can happen, for instance, if the user | |
| 528 // installs on XP, then upgrades to Vista. Or chooses "Run as Administrator" | |
| 529 // when running the meta-installer on Vista. Subsequently, Omaha running at | |
| 530 // medium integrity needs to be able to manipulate the installed task. | |
| 531 scoped_ptr_cotask<OLECHAR> job_file; | |
| 532 hr = persist->GetCurFile(address(job_file)); | |
| 533 if (FAILED(hr)) { | |
| 534 UTIL_LOG(LE, (_T("[IPersistFile.GetCurFile failed][0x%x]"), hr)); | |
| 535 return hr; | |
| 536 } | |
| 537 | |
| 538 persist.Release(); | |
| 539 | |
| 540 CAccessToken token; | |
| 541 CSid current_sid; | |
| 542 if (!token.GetEffectiveToken(TOKEN_QUERY) || !token.GetUser(¤t_sid)) { | |
| 543 hr = HRESULTFromLastError(); | |
| 544 UTIL_LOG(LE, (_T("[Failed to get current user sid][0x%x]"), hr)); | |
| 545 return hr; | |
| 546 } | |
| 547 | |
| 548 hr = AddAllowedAce(job_file.get(), | |
| 549 SE_FILE_OBJECT, | |
| 550 current_sid, | |
| 551 FILE_ALL_ACCESS, | |
| 552 0); | |
| 553 if (FAILED(hr)) { | |
| 554 UTIL_LOG(LE, (_T("[Could not adjust DACL][%s][0x%x]"), job_file.get(), hr)); | |
| 555 return hr; | |
| 556 } | |
| 557 | |
| 558 return S_OK; | |
| 559 } | |
| 560 | |
| 561 HRESULT UpgradeScheduledTask(const TCHAR* task_name, | |
| 562 const TCHAR* task_path, | |
| 563 const TCHAR* task_parameters, | |
| 564 const TCHAR* task_comment, | |
| 565 bool is_machine, | |
| 566 bool create_logon_trigger, | |
| 567 bool create_daily_trigger, | |
| 568 bool create_hourly_trigger) { | |
| 569 ASSERT1(task_name && *task_name); | |
| 570 ASSERT1(IsInstalledScheduledTask(task_name)); | |
| 571 | |
| 572 UTIL_LOG(L3, (_T("[UpgradeScheduledTask][%s][%s][%s][%d]"), | |
| 573 task_name, task_path, task_parameters, is_machine)); | |
| 574 | |
| 575 // TODO(Omaha): Perhaps pass the ITaskScheduler around where possible. | |
| 576 CComPtr<ITaskScheduler> scheduler; | |
| 577 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 578 NULL, | |
| 579 CLSCTX_INPROC_SERVER); | |
| 580 if (FAILED(hr)) { | |
| 581 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 582 return hr; | |
| 583 } | |
| 584 | |
| 585 CComPtr<ITask> task; | |
| 586 hr = scheduler->Activate(task_name, | |
| 587 __uuidof(ITask), | |
| 588 reinterpret_cast<IUnknown**>(&task)); | |
| 589 | |
| 590 if (FAILED(hr)) { | |
| 591 UTIL_LOG(LE, (_T("[UpgradeScheduledTask][Activate failed][0x%x]"), hr)); | |
| 592 return hr; | |
| 593 } | |
| 594 | |
| 595 // Delete existing triggers. CreateScheduledTask() will recreate them anew. | |
| 596 WORD trigger_count(0); | |
| 597 hr = task->GetTriggerCount(&trigger_count); | |
| 598 if (FAILED(hr)) { | |
| 599 UTIL_LOG(LE, (_T("[ITaskScheduler.GetTriggerCount failed][0x%x]"), hr)); | |
| 600 return hr; | |
| 601 } | |
| 602 | |
| 603 for (int i = 0; i < trigger_count; ++i) { | |
| 604 hr = task->DeleteTrigger(0); | |
| 605 if (FAILED(hr)) { | |
| 606 UTIL_LOG(LE, (_T("[ITaskScheduler.DeleteTrigger failed][0x%x]"), hr)); | |
| 607 return hr; | |
| 608 } | |
| 609 } | |
| 610 | |
| 611 return CreateScheduledTask(task, | |
| 612 task_path, | |
| 613 task_parameters, | |
| 614 task_comment, | |
| 615 is_machine, | |
| 616 create_logon_trigger, | |
| 617 create_daily_trigger, | |
| 618 create_hourly_trigger); | |
| 619 } | |
| 620 | |
| 621 // TODO(Omaha): Change the apis to avoid specifying hourly and daily triggers. | |
| 622 HRESULT InstallScheduledTask(const TCHAR* task_name, | |
| 623 const TCHAR* task_path, | |
| 624 const TCHAR* task_parameters, | |
| 625 const TCHAR* task_comment, | |
| 626 bool is_machine, | |
| 627 bool create_logon_trigger, | |
| 628 bool create_daily_trigger, | |
| 629 bool create_hourly_trigger) { | |
| 630 if (IsInstalledScheduledTask(task_name)) { | |
| 631 return UpgradeScheduledTask(task_name, | |
| 632 task_path, | |
| 633 task_parameters, | |
| 634 task_comment, | |
| 635 is_machine, | |
| 636 create_logon_trigger, | |
| 637 create_daily_trigger, | |
| 638 create_hourly_trigger); | |
| 639 } | |
| 640 | |
| 641 CComPtr<ITaskScheduler> scheduler; | |
| 642 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 643 NULL, | |
| 644 CLSCTX_INPROC_SERVER); | |
| 645 if (FAILED(hr)) { | |
| 646 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 647 return hr; | |
| 648 } | |
| 649 | |
| 650 CComPtr<ITask> task; | |
| 651 hr = scheduler->NewWorkItem(task_name, | |
| 652 CLSID_CTask, | |
| 653 __uuidof(ITask), | |
| 654 reinterpret_cast<IUnknown**>(&task)); | |
| 655 | |
| 656 if (FAILED(hr)) { | |
| 657 UTIL_LOG(LE, (_T("[ITaskScheduler.NewWorkItem failed][0x%x]"), hr)); | |
| 658 return hr; | |
| 659 } | |
| 660 | |
| 661 return CreateScheduledTask(task, | |
| 662 task_path, | |
| 663 task_parameters, | |
| 664 task_comment, | |
| 665 is_machine, | |
| 666 create_logon_trigger, | |
| 667 create_daily_trigger, | |
| 668 create_hourly_trigger); | |
| 669 } | |
| 670 | |
| 671 HRESULT UninstallScheduledTask(const TCHAR* task_name) { | |
| 672 ASSERT1(task_name && *task_name); | |
| 673 | |
| 674 CComPtr<ITaskScheduler> scheduler; | |
| 675 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 676 NULL, | |
| 677 CLSCTX_INPROC_SERVER); | |
| 678 if (FAILED(hr)) { | |
| 679 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 680 return hr; | |
| 681 } | |
| 682 | |
| 683 // Stop the task before deleting it. Ignore return value. | |
| 684 VERIFY1(SUCCEEDED(StopScheduledTask(task_name))); | |
| 685 | |
| 686 // delete the task. | |
| 687 hr = scheduler->Delete(task_name); | |
| 688 if (FAILED(hr) && COR_E_FILENOTFOUND != hr) { | |
| 689 UTIL_LOG(LE, (_T("[GetScheduledTaskStatus][Delete failed][0x%x]"), hr)); | |
| 690 return hr; | |
| 691 } | |
| 692 | |
| 693 return S_OK; | |
| 694 } | |
| 695 | |
| 696 HRESULT UninstallScheduledTasks(const TCHAR* task_prefix) { | |
| 697 ASSERT1(task_prefix && *task_prefix); | |
| 698 | |
| 699 CComPtr<ITaskScheduler> scheduler; | |
| 700 HRESULT hr = scheduler.CoCreateInstance(CLSID_CTaskScheduler, | |
| 701 NULL, | |
| 702 CLSCTX_INPROC_SERVER); | |
| 703 if (FAILED(hr)) { | |
| 704 UTIL_LOG(LE, (_T("[ITaskScheduler.CoCreateInstance failed][0x%x]"), hr)); | |
| 705 return hr; | |
| 706 } | |
| 707 | |
| 708 CComPtr<IEnumWorkItems> enum_items; | |
| 709 hr = scheduler->Enum(&enum_items); | |
| 710 if (FAILED(hr)) { | |
| 711 UTIL_LOG(LE, (_T("[ITaskScheduler.Enum failed][0x%x]"), hr)); | |
| 712 return hr; | |
| 713 } | |
| 714 | |
| 715 TCHAR** task_names = NULL; | |
| 716 DWORD task_count = 0; | |
| 717 while (enum_items->Next(1, &task_names, &task_count) == S_OK) { | |
| 718 ASSERT1(task_count == 1); | |
| 719 scoped_co_task_ptr task_names_guard(task_names); | |
| 720 scoped_co_task_ptr task_name_guard(task_names[0]); | |
| 721 | |
| 722 if (String_StartsWith(task_names[0], task_prefix, true)) { | |
| 723 UninstallScheduledTask(task_names[0]); | |
| 724 } | |
| 725 } | |
| 726 | |
| 727 return S_OK; | |
| 728 } | |
| 729 | |
| 730 // Returns the task name Omaha used to install in Omaha 1.2.x. | |
| 731 CString GetOmaha1LegacyTaskName(bool is_machine) { | |
| 732 const TCHAR* const kLegacyOmaha1TaskNameMachine = _T("GoogleUpdateTask"); | |
| 733 const TCHAR* const kLegacyOmaha1TaskNameUser = _T("GoogleUpdateTaskUser"); | |
| 734 return is_machine ? kLegacyOmaha1TaskNameMachine : kLegacyOmaha1TaskNameUser; | |
| 735 } | |
| 736 | |
| 737 // Returns the task name Omaha used to install in Omaha 2 before the | |
| 738 // "GoogleUpdate.exe does not run all the time" refactoring. | |
| 739 CString GetOmaha2LegacyTaskName(bool is_machine) { | |
| 740 const TCHAR* kLegacyOmaha2TaskNameUserPrefix = _T("GoogleUpdateTaskUser"); | |
| 741 const TCHAR* kLegacyOmaha2TaskNameMachine = _T("GoogleUpdateTaskMachine"); | |
| 742 if (is_machine) { | |
| 743 return kLegacyOmaha2TaskNameMachine; | |
| 744 } | |
| 745 | |
| 746 CString task_name_user = kLegacyOmaha2TaskNameUserPrefix; | |
| 747 CString user_sid; | |
| 748 VERIFY1(SUCCEEDED(user_info::GetProcessUser(NULL, NULL, &user_sid))); | |
| 749 task_name_user += user_sid; | |
| 750 return task_name_user; | |
| 751 } | |
| 752 | |
| 753 HRESULT WaitForTaskStatus(const TCHAR* task_name, HRESULT status, int time_ms) { | |
| 754 int kSleepBetweenRetriesMs = 100; | |
| 755 Timer timer(true); | |
| 756 while (timer.GetMilliseconds() < time_ms) { | |
| 757 if (GetScheduledTaskStatus(task_name) == status) { | |
| 758 return status; | |
| 759 } | |
| 760 ::Sleep(kSleepBetweenRetriesMs); | |
| 761 } | |
| 762 return GetScheduledTaskStatus(task_name); | |
| 763 } | |
| 764 | |
| 765 namespace v2 { | |
| 766 | |
| 767 bool IsTaskScheduler2APIAvailable() { | |
| 768 CComPtr<ITaskService> task_service; | |
| 769 return SUCCEEDED(task_service.CoCreateInstance(CLSID_TaskScheduler, | |
| 770 NULL, | |
| 771 CLSCTX_INPROC_SERVER)); | |
| 772 } | |
| 773 | |
| 774 HRESULT GetRegisteredTask(const TCHAR* task_name, IRegisteredTask** task) { | |
| 775 ASSERT1(IsTaskScheduler2APIAvailable()); | |
| 776 ASSERT1(task_name && *task_name); | |
| 777 ASSERT1(task); | |
| 778 | |
| 779 CComPtr<ITaskService> task_service; | |
| 780 HRESULT hr = task_service.CoCreateInstance(CLSID_TaskScheduler, | |
| 781 NULL, | |
| 782 CLSCTX_INPROC_SERVER); | |
| 783 if (FAILED(hr)) { | |
| 784 UTIL_LOG(LE, (_T("[ITaskService.CoCreateInstance failed][0x%x]"), hr)); | |
| 785 return hr; | |
| 786 } | |
| 787 | |
| 788 hr = task_service->Connect(CComVariant(), CComVariant(), | |
| 789 CComVariant(), CComVariant()); | |
| 790 if (FAILED(hr)) { | |
| 791 UTIL_LOG(LE, (_T("[ITaskService::Connect failed][0x%x]"), hr)); | |
| 792 return hr; | |
| 793 } | |
| 794 | |
| 795 CComPtr<ITaskFolder> task_folder; | |
| 796 hr = task_service->GetFolder(CComBSTR(_T("\\")) , &task_folder); | |
| 797 if (FAILED(hr)) { | |
| 798 UTIL_LOG(LE, (_T("[Cannot get Root Folder pointer][0x%x]"), hr)); | |
| 799 return hr; | |
| 800 } | |
| 801 | |
| 802 CComPtr<IRegisteredTask> registered_task; | |
| 803 hr = task_folder->GetTask(CComBSTR(task_name), ®istered_task); | |
| 804 if (FAILED(hr)) { | |
| 805 UTIL_LOG(LE, (_T("[Cannot get the registered task][0x%x]"), hr)); | |
| 806 return hr; | |
| 807 } | |
| 808 | |
| 809 *task = registered_task.Detach(); | |
| 810 return S_OK; | |
| 811 } | |
| 812 | |
| 813 bool IsScheduledTaskRunning(const TCHAR* task_name) { | |
| 814 ASSERT1(IsTaskScheduler2APIAvailable()); | |
| 815 ASSERT1(task_name && *task_name); | |
| 816 | |
| 817 CComPtr<IRegisteredTask> registered_task; | |
| 818 HRESULT hr = GetRegisteredTask(task_name, ®istered_task); | |
| 819 if (FAILED(hr)) { | |
| 820 return false; | |
| 821 } | |
| 822 | |
| 823 CComPtr<IRunningTaskCollection> running_task_collection; | |
| 824 hr = registered_task->GetInstances(0, &running_task_collection); | |
| 825 if (FAILED(hr)) { | |
| 826 UTIL_LOG(LE, (_T("[IRegisteredTask.GetInstances failed][0x%x]"), hr)); | |
| 827 return false; | |
| 828 } | |
| 829 | |
| 830 long count = 0; | |
| 831 hr = running_task_collection->get_Count(&count); | |
| 832 if (FAILED(hr)) { | |
| 833 UTIL_LOG(LE, (_T("[IRunningTaskCollection.get_Count failed][0x%x]"), hr)); | |
| 834 return false; | |
| 835 } | |
| 836 | |
| 837 return count > 0; | |
| 838 } | |
| 839 | |
| 840 HRESULT StartScheduledTask(const TCHAR* task_name) { | |
| 841 ASSERT1(IsTaskScheduler2APIAvailable()); | |
| 842 ASSERT1(task_name && *task_name); | |
| 843 | |
| 844 if (IsScheduledTaskRunning(task_name)) { | |
| 845 return S_OK; | |
| 846 } | |
| 847 | |
| 848 CComPtr<IRegisteredTask> registered_task; | |
| 849 HRESULT hr = GetRegisteredTask(task_name, ®istered_task); | |
| 850 if (FAILED(hr)) { | |
| 851 return hr; | |
| 852 } | |
| 853 | |
| 854 hr = registered_task->Run(CComVariant(), NULL); | |
| 855 if (FAILED(hr)) { | |
| 856 UTIL_LOG(LE, (_T("[IRegisteredTask.Run failed][0x%x]"), hr)); | |
| 857 return hr; | |
| 858 } | |
| 859 | |
| 860 return hr; | |
| 861 } | |
| 862 | |
| 863 HRESULT StopScheduledTask(const TCHAR* task_name) { | |
| 864 ASSERT1(IsTaskScheduler2APIAvailable()); | |
| 865 ASSERT1(task_name && *task_name); | |
| 866 | |
| 867 if (!IsScheduledTaskRunning(task_name)) { | |
| 868 return S_OK; | |
| 869 } | |
| 870 | |
| 871 CComPtr<IRegisteredTask> registered_task; | |
| 872 HRESULT hr = GetRegisteredTask(task_name, ®istered_task); | |
| 873 if (FAILED(hr)) { | |
| 874 return hr; | |
| 875 } | |
| 876 | |
| 877 CComPtr<IRunningTaskCollection> running_task_collection; | |
| 878 hr = registered_task->GetInstances(0, &running_task_collection); | |
| 879 if (FAILED(hr)) { | |
| 880 UTIL_LOG(LE, (_T("[IRegisteredTask.GetInstances failed][0x%x]"), hr)); | |
| 881 return hr; | |
| 882 } | |
| 883 | |
| 884 long count = 0; | |
| 885 hr = running_task_collection->get_Count(&count); | |
| 886 if (FAILED(hr)) { | |
| 887 UTIL_LOG(LE, (_T("[IRunningTaskCollection.get_Count failed][0x%x]"), hr)); | |
| 888 return hr; | |
| 889 } | |
| 890 | |
| 891 if (count <= 0) { | |
| 892 return S_OK; | |
| 893 } | |
| 894 | |
| 895 for (long i = 0; i < count; ++i) { | |
| 896 CComPtr<IRunningTask> running_task; | |
| 897 hr = running_task_collection->get_Item(CComVariant(i+1), &running_task); | |
| 898 if (FAILED(hr)) { | |
| 899 UTIL_LOG(LE, (_T("[IRunningTaskCollection.get_Item][%d][0x%x]"), i, hr)); | |
| 900 return hr; | |
| 901 } | |
| 902 | |
| 903 hr = running_task->Stop(); | |
| 904 if (FAILED(hr)) { | |
| 905 UTIL_LOG(LE, (_T("[IRunningTask.Stop failed][%d][0x%x]"), i, hr)); | |
| 906 return hr; | |
| 907 } | |
| 908 } | |
| 909 | |
| 910 return S_OK; | |
| 911 } | |
| 912 | |
| 913 } // namespace v2 | |
| 914 | |
| 915 } // namespace internal | |
| 916 | |
| 917 CString GetDefaultGoopdateTaskName(bool is_machine, CommandLineMode mode) { | |
| 918 ASSERT1(mode == COMMANDLINE_MODE_CORE || mode == COMMANDLINE_MODE_UA); | |
| 919 | |
| 920 CString task_name; | |
| 921 if (is_machine) { | |
| 922 task_name = kScheduledTaskNameMachinePrefix; | |
| 923 } else { | |
| 924 task_name = kScheduledTaskNameUserPrefix; | |
| 925 CString user_sid; | |
| 926 VERIFY1(SUCCEEDED(user_info::GetProcessUser(NULL, NULL, &user_sid))); | |
| 927 task_name += user_sid; | |
| 928 } | |
| 929 | |
| 930 task_name += (mode == COMMANDLINE_MODE_CORE) ? kScheduledTaskNameCoreSuffix : | |
| 931 kScheduledTaskNameUASuffix; | |
| 932 return task_name; | |
| 933 } | |
| 934 | |
| 935 HRESULT InstallGoopdateTaskForMode(const TCHAR* task_path, | |
| 936 bool is_machine, | |
| 937 CommandLineMode mode) { | |
| 938 ASSERT1(mode == COMMANDLINE_MODE_CORE || mode == COMMANDLINE_MODE_UA); | |
| 939 | |
| 940 CommandLineBuilder builder(mode); | |
| 941 if (mode == COMMANDLINE_MODE_UA) { | |
| 942 builder.set_install_source(kCmdLineInstallSource_Scheduler); | |
| 943 } | |
| 944 const CString task_parameters = builder.GetCommandLineArgs(); | |
| 945 | |
| 946 CString company_name; | |
| 947 VERIFY1(company_name.LoadString(IDS_FRIENDLY_COMPANY_NAME)); | |
| 948 CString task_description; | |
| 949 task_description.FormatMessage(IDS_SCHEDULED_TASK_DESCRIPTION, company_name); | |
| 950 | |
| 951 CString task_name(mode == COMMANDLINE_MODE_CORE ? | |
| 952 internal::GetCurrentTaskNameCore(is_machine) : | |
| 953 internal::GetCurrentTaskNameUA(is_machine)); | |
| 954 if (internal::IsInstalledScheduledTask(task_name)) { | |
| 955 HRESULT hr = internal::InstallScheduledTask(task_name, | |
| 956 task_path, | |
| 957 task_parameters, | |
| 958 task_description, | |
| 959 is_machine, | |
| 960 mode == COMMANDLINE_MODE_CORE && | |
| 961 is_machine, | |
| 962 true, | |
| 963 mode == COMMANDLINE_MODE_UA); | |
| 964 | |
| 965 if (SUCCEEDED(hr)) { | |
| 966 return hr; | |
| 967 } | |
| 968 | |
| 969 // Try to uninstall the task that we failed to upgrade. Then create a new | |
| 970 // task name, and fall through to install that. | |
| 971 internal::UninstallScheduledTask(task_name); | |
| 972 if (mode == COMMANDLINE_MODE_CORE) { | |
| 973 VERIFY1(SUCCEEDED( | |
| 974 internal::CreateAndSetVersionedTaskNameCoreInRegistry(is_machine))); | |
| 975 task_name = internal::GetCurrentTaskNameCore(is_machine); | |
| 976 } else { | |
| 977 VERIFY1(SUCCEEDED( | |
| 978 internal::CreateAndSetVersionedTaskNameUAInRegistry(is_machine))); | |
| 979 task_name = internal::GetCurrentTaskNameUA(is_machine); | |
| 980 } | |
| 981 ASSERT1(!internal::IsInstalledScheduledTask(task_name)); | |
| 982 } | |
| 983 | |
| 984 return internal::InstallScheduledTask(task_name, | |
| 985 task_path, | |
| 986 task_parameters, | |
| 987 task_description, | |
| 988 is_machine, | |
| 989 mode == COMMANDLINE_MODE_CORE && | |
| 990 is_machine, | |
| 991 true, | |
| 992 mode == COMMANDLINE_MODE_UA); | |
| 993 } | |
| 994 | |
| 995 HRESULT InstallGoopdateTasks(const TCHAR* task_path, bool is_machine) { | |
| 996 HRESULT hr = InstallGoopdateTaskForMode(task_path, | |
| 997 is_machine, | |
| 998 COMMANDLINE_MODE_CORE); | |
| 999 if (FAILED(hr)) { | |
| 1000 return hr; | |
| 1001 } | |
| 1002 | |
| 1003 return InstallGoopdateTaskForMode(task_path, is_machine, COMMANDLINE_MODE_UA); | |
| 1004 } | |
| 1005 | |
| 1006 HRESULT UninstallGoopdateTasks(bool is_machine) { | |
| 1007 VERIFY1(SUCCEEDED(internal::UninstallScheduledTask( | |
| 1008 internal::GetCurrentTaskNameCore(is_machine)))); | |
| 1009 VERIFY1(SUCCEEDED(internal::UninstallScheduledTask( | |
| 1010 internal::GetCurrentTaskNameUA(is_machine)))); | |
| 1011 | |
| 1012 // Try to uninstall any tasks that we failed to update during a previous | |
| 1013 // overinstall. It is possible that we fail to uninstall these again here. | |
| 1014 VERIFY1(SUCCEEDED(internal::UninstallScheduledTasks( | |
| 1015 scheduled_task_utils::GetDefaultGoopdateTaskName(is_machine, | |
| 1016 COMMANDLINE_MODE_CORE)))); | |
| 1017 VERIFY1(SUCCEEDED(internal::UninstallScheduledTasks( | |
| 1018 scheduled_task_utils::GetDefaultGoopdateTaskName(is_machine, | |
| 1019 COMMANDLINE_MODE_UA)))); | |
| 1020 return S_OK; | |
| 1021 } | |
| 1022 | |
| 1023 HRESULT UninstallLegacyGoopdateTasks(bool is_machine) { | |
| 1024 const CString& legacy_omaha1_task = | |
| 1025 internal::GetOmaha1LegacyTaskName(is_machine); | |
| 1026 VERIFY1(SUCCEEDED(internal::UninstallScheduledTask(legacy_omaha1_task))); | |
| 1027 | |
| 1028 const CString& legacy_omaha2_task = | |
| 1029 internal::GetOmaha2LegacyTaskName(is_machine); | |
| 1030 VERIFY1(SUCCEEDED(internal::UninstallScheduledTask(legacy_omaha2_task))); | |
| 1031 | |
| 1032 return S_OK; | |
| 1033 } | |
| 1034 | |
| 1035 HRESULT StartGoopdateTaskCore(bool is_machine) { | |
| 1036 return internal::StartScheduledTask( | |
| 1037 internal::GetCurrentTaskNameCore(is_machine)); | |
| 1038 } | |
| 1039 | |
| 1040 bool IsInstalledGoopdateTaskUA(bool is_machine) { | |
| 1041 return internal::IsInstalledScheduledTask( | |
| 1042 internal::GetCurrentTaskNameUA(is_machine)); | |
| 1043 } | |
| 1044 | |
| 1045 bool IsDisabledGoopdateTaskUA(bool is_machine) { | |
| 1046 const CString& task_name(internal::GetCurrentTaskNameUA(is_machine)); | |
| 1047 return internal::GetScheduledTaskStatus(task_name) == SCHED_S_TASK_DISABLED; | |
| 1048 } | |
| 1049 | |
| 1050 HRESULT GetExitCodeGoopdateTaskUA(bool is_machine) { | |
| 1051 const CString& task_name(internal::GetCurrentTaskNameUA(is_machine)); | |
| 1052 return internal::GetScheduledTaskExitCode(task_name); | |
| 1053 } | |
| 1054 | |
| 1055 bool IsUATaskHealthy(bool is_machine) { | |
| 1056 if (!ServiceUtils::IsServiceRunning(SERVICE_SCHEDULE)) { | |
| 1057 UTIL_LOG(LW, (_T("[Task Scheduler Service is not running]"))); | |
| 1058 return false; | |
| 1059 } | |
| 1060 | |
| 1061 if (!IsInstalledGoopdateTaskUA(is_machine)) { | |
| 1062 UTIL_LOG(LW, (_T("[UA Task not installed]"))); | |
| 1063 return false; | |
| 1064 } | |
| 1065 | |
| 1066 if (IsDisabledGoopdateTaskUA(is_machine)) { | |
| 1067 UTIL_LOG(LW, (_T("[UA Task disabled]"))); | |
| 1068 return false; | |
| 1069 } | |
| 1070 | |
| 1071 return true; | |
| 1072 } | |
| 1073 | |
| 1074 } // namespace scheduled_task_utils | |
| 1075 | |
| 1076 } // namespace omaha | |
| OLD | NEW |