Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(560)

Side by Side Diff: common/scheduled_task_utils.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « common/scheduled_task_utils.h ('k') | common/scheduled_task_utils_internal.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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(&current_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), &registered_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, &registered_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, &registered_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, &registered_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
OLDNEW
« no previous file with comments | « common/scheduled_task_utils.h ('k') | common/scheduled_task_utils_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698