// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/chrome_cleaner/os/task_scheduler.h"

#include <mstask.h>
#include <oleauto.h>
#include <security.h>
#include <taskschd.h>
#include <wrl/client.h>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/native_library.h"
#include "base/path_service.h"
#include "base/strings/strcat.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/scoped_handle.h"
#include "base/win/scoped_variant.h"
#include "base/win/windows_version.h"
#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
#include "chrome/chrome_cleaner/os/file_path_sanitization.h"

namespace chrome_cleaner {

namespace {

// Names of the TaskSchedulerV2 libraries so we can pin them below.
const wchar_t kV2Library[] = L"taskschd.dll";

// Text for times used in the V2 API of the Task Scheduler.
const wchar_t kOneHourText[] = L"PT1H";
const wchar_t kSixHoursText[] = L"PT6H";
const wchar_t kZeroMinuteText[] = L"PT0M";
const wchar_t kFifteenMinutesText[] = L"PT15M";
const wchar_t kTwentyFourHoursText[] = L"PT24H";

// Most of the users with pending logs succeeds within 7 days, so no need to
// try for longer than that, especially for those who keep crashing.
const int kNumDaysBeforeExpiry = 7;
const size_t kNumDeleteTaskRetry = 3;
const size_t kDeleteRetryDelayInMs = 100;

// Return |timestamp| in the following string format YYYY-MM-DDTHH:MM:SS.
base::string16 GetTimestampString(const base::Time& timestamp) {
  base::Time::Exploded exploded_time;
  // The Z timezone info at the end of the string means UTC.
  timestamp.UTCExplode(&exploded_time);
  return base::StringPrintf(L"%04d-%02d-%02dT%02d:%02d:%02dZ",
                            exploded_time.year, exploded_time.month,
                            exploded_time.day_of_month, exploded_time.hour,
                            exploded_time.minute, exploded_time.second);
}

bool LocalSystemTimeToUTCFileTime(const SYSTEMTIME& system_time_local,
                                  FILETIME* file_time_utc) {
  DCHECK(file_time_utc);
  SYSTEMTIME system_time_utc = {};
  if (!::TzSpecificLocalTimeToSystemTime(nullptr, &system_time_local,
                                         &system_time_utc) ||
      !::SystemTimeToFileTime(&system_time_utc, file_time_utc)) {
    PLOG(ERROR) << "Failed to convert local system time to UTC file time.";
    return false;
  }
  return true;
}

bool UTCFileTimeToLocalSystemTime(const FILETIME& file_time_utc,
                                  SYSTEMTIME* system_time_local) {
  DCHECK(system_time_local);
  SYSTEMTIME system_time_utc = {};
  if (!::FileTimeToSystemTime(&file_time_utc, &system_time_utc) ||
      !::SystemTimeToTzSpecificLocalTime(nullptr, &system_time_utc,
                                         system_time_local)) {
    PLOG(ERROR) << "Failed to convert file time to UTC local system.";
    return false;
  }
  return true;
}

bool GetCurrentUser(base::win::ScopedBstr* user_name) {
  DCHECK(user_name);
  ULONG user_name_size = 256;
  // Paranoia... ;-)
  DCHECK_EQ(sizeof(OLECHAR), sizeof(WCHAR));
  if (!::GetUserNameExW(
          NameSamCompatible,
          user_name->AllocateBytes(user_name_size * sizeof(OLECHAR)),
          &user_name_size)) {
    if (::GetLastError() != ERROR_MORE_DATA) {
      PLOG(ERROR) << "GetUserNameEx failed.";
      return false;
    }
    if (!::GetUserNameExW(
            NameSamCompatible,
            user_name->AllocateBytes(user_name_size * sizeof(OLECHAR)),
            &user_name_size)) {
      DCHECK_NE(static_cast<DWORD>(ERROR_MORE_DATA), ::GetLastError());
      PLOG(ERROR) << "GetUserNameEx failed.";
      return false;
    }
  }
  return true;
}

void PinModule(const wchar_t* module_name) {
  // Force the DLL to stay loaded until program termination. We have seen
  // cases where it gets unloaded even though we still have references to
  // the objects we just CoCreated.
  base::NativeLibrary module_handle = nullptr;
  if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, module_name,
                            &module_handle)) {
    PLOG(ERROR) << "Failed to pin '" << module_name << "'.";
  }
}

// Another version of the TaskScheduler class that uses the V2 API of the task
// scheduler for Vista+.
class TaskSchedulerV2 : public TaskScheduler {
 public:
  static bool Initialize() {
    DCHECK(!task_service_);
    DCHECK(!root_task_folder_);

    HRESULT hr =
        ::CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER,
                           IID_PPV_ARGS(&task_service_));
    if (FAILED(hr)) {
      PLOG(ERROR) << "CreateInstance failed for CLSID_TaskScheduler. "
                  << std::hex << hr;
      return false;
    }
    hr = task_service_->Connect(base::win::ScopedVariant::kEmptyVariant,
                                base::win::ScopedVariant::kEmptyVariant,
                                base::win::ScopedVariant::kEmptyVariant,
                                base::win::ScopedVariant::kEmptyVariant);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Failed to connect to task service. " << std::hex << hr;
      return false;
    }
    hr = task_service_->GetFolder(base::win::ScopedBstr(L"\\"),
                                  root_task_folder_.GetAddressOf());
    if (FAILED(hr)) {
      LOG(ERROR) << "Can't get task service folder. " << std::hex << hr;
      return false;
    }
    PinModule(kV2Library);
    return true;
  }

  static void Terminate() {
    root_task_folder_.Reset();
    task_service_.Reset();
  }

  TaskSchedulerV2() {
    DCHECK(task_service_);
    DCHECK(root_task_folder_);
  }

  // TaskScheduler overrides.
  bool IsTaskRegistered(const wchar_t* task_name) override {
    DCHECK(task_name);
    if (!root_task_folder_)
      return false;

    return GetTask(task_name, nullptr);
  }

  bool GetNextTaskRunTime(const wchar_t* task_name,
                          base::Time* next_run_time) override {
    DCHECK(task_name);
    DCHECK(next_run_time);
    if (!root_task_folder_)
      return false;

    Microsoft::WRL::ComPtr<IRegisteredTask> registered_task;
    if (!GetTask(task_name, registered_task.GetAddressOf())) {
      LOG(ERROR) << "Failed to get task named " << task_name;
      return false;
    }

    // We unfortunately can't use get_NextRunTime because of a known bug which
    // requires hotfix: http://support.microsoft.com/kb/2495489/en-us. So fetch
    // one of the run times in the next day.
    // Also, although it's not obvious from MSDN, IRegisteredTask::GetRunTimes
    // expects local time.
    SYSTEMTIME start_system_time = {};
    GetLocalTime(&start_system_time);

    base::Time tomorrow(base::Time::NowFromSystemTime() +
                        base::TimeDelta::FromDays(1));
    SYSTEMTIME end_system_time = {};
    if (!UTCFileTimeToLocalSystemTime(tomorrow.ToFileTime(), &end_system_time))
      return false;

    DWORD num_run_times = 1;
    SYSTEMTIME* raw_run_times = nullptr;
    HRESULT hr = registered_task->GetRunTimes(
        &start_system_time, &end_system_time, &num_run_times, &raw_run_times);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Failed to GetRunTimes, " << std::hex << hr;
      return false;
    }
    if (num_run_times == 0) {
      LOG(WARNING) << "No more run times?";
      return false;
    }

    base::win::ScopedCoMem<SYSTEMTIME> run_times;
    run_times.Reset(raw_run_times);
    // Again, although unclear from MSDN, IRegisteredTask::GetRunTimes returns
    // local times.
    FILETIME file_time = {};
    if (!LocalSystemTimeToUTCFileTime(run_times[0], &file_time))
      return false;
    *next_run_time = base::Time::FromFileTime(file_time);
    return true;
  }

  bool SetTaskEnabled(const wchar_t* task_name, bool enabled) override {
    DCHECK(task_name);
    if (!root_task_folder_)
      return false;

    Microsoft::WRL::ComPtr<IRegisteredTask> registered_task;
    if (!GetTask(task_name, registered_task.GetAddressOf())) {
      LOG(ERROR) << "Failed to find the task " << task_name
                 << " to enable/disable";
      return false;
    }

    HRESULT hr;
    hr = registered_task->put_Enabled(enabled ? VARIANT_TRUE : VARIANT_FALSE);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Failed to set enabled status of task named " << task_name
                  << ". " << std::hex << hr;
      return false;
    }
    return true;
  }

  bool IsTaskEnabled(const wchar_t* task_name) override {
    DCHECK(task_name);
    if (!root_task_folder_)
      return false;

    Microsoft::WRL::ComPtr<IRegisteredTask> registered_task;
    if (!GetTask(task_name, registered_task.GetAddressOf()))
      return false;

    HRESULT hr;
    VARIANT_BOOL is_enabled;
    hr = registered_task->get_Enabled(&is_enabled);
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get enabled status for task named " << task_name
                 << ". " << std::hex << hr << ": "
                 << logging::SystemErrorCodeToString(hr);
      return false;
    }

    return is_enabled == VARIANT_TRUE;
  }

  bool GetTaskNameList(std::vector<base::string16>* task_names) override {
    DCHECK(task_names);
    if (!root_task_folder_)
      return false;

    for (TaskIterator it(root_task_folder_.Get()); !it.done(); it.Next())
      task_names->push_back(it.name());
    return true;
  }

  bool GetTaskInfo(const wchar_t* task_name, TaskInfo* info) override {
    DCHECK(task_name);
    DCHECK(info);
    if (!root_task_folder_)
      return false;

    Microsoft::WRL::ComPtr<IRegisteredTask> registered_task;
    if (!GetTask(task_name, registered_task.GetAddressOf())) {
      LOG(ERROR) << "Failed to get task named " << task_name;
      return false;
    }

    // Collect information into internal storage to ensure that we start with
    // a clean slate and don't return partial results on error.
    TaskInfo info_storage;
    HRESULT hr =
        GetTaskDescription(registered_task.Get(), &info_storage.description);
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get description for task '" << task_name << "'. "
                 << std::hex << hr << ": "
                 << logging::SystemErrorCodeToString(hr);
      return false;
    }

    if (!GetTaskExecActions(registered_task.Get(),
                            &info_storage.exec_actions)) {
      LOG(ERROR) << "Failed to get actions for task '" << task_name << "'";
      return false;
    }

    hr = GetTaskLogonType(registered_task.Get(), &info_storage.logon_type);
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get logon type for task '" << task_name << "'. "
                 << std::hex << hr << ": "
                 << logging::SystemErrorCodeToString(hr);
      return false;
    }
    info_storage.name = task_name;
    std::swap(*info, info_storage);
    return true;
  }

  bool DeleteTask(const wchar_t* task_name) override {
    DCHECK(task_name);
    if (!root_task_folder_)
      return false;

    LOG(INFO) << "Delete Task '" << task_name << "'.";

    HRESULT hr =
        root_task_folder_->DeleteTask(base::win::ScopedBstr(task_name), 0);
    // This can happen, e.g., while running tests, when the file system stresses
    // quite a lot. Give it a few more chances to succeed.
    size_t num_retries_left = kNumDeleteTaskRetry;

    if (FAILED(hr)) {
      while ((hr == HRESULT_FROM_WIN32(ERROR_TRANSACTION_NOT_ACTIVE) ||
              hr == HRESULT_FROM_WIN32(ERROR_TRANSACTION_ALREADY_ABORTED)) &&
             --num_retries_left && IsTaskRegistered(task_name)) {
        LOG(WARNING) << "Retrying delete task because transaction not active, "
                     << std::hex << hr << ".";
        hr = root_task_folder_->DeleteTask(base::win::ScopedBstr(task_name), 0);
        ::Sleep(kDeleteRetryDelayInMs);
      }
      if (!IsTaskRegistered(task_name))
        hr = S_OK;
    }

    if (FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
      PLOG(ERROR) << "Can't delete task. " << std::hex << hr;
      return false;
    }

    DCHECK(!IsTaskRegistered(task_name));
    return true;
  }

  bool RegisterTask(const wchar_t* task_name,
                    const wchar_t* task_description,
                    const base::CommandLine& run_command,
                    TriggerType trigger_type,
                    bool hidden) override {
    DCHECK(task_name);
    DCHECK(task_description);
    if (!DeleteTask(task_name))
      return false;

    // Create the task definition object to create the task.
    Microsoft::WRL::ComPtr<ITaskDefinition> task;
    DCHECK(task_service_);
    HRESULT hr = task_service_->NewTask(0, task.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't create new task. " << std::hex << hr;
      return false;
    }

    base::win::ScopedBstr user_name;
    if (!GetCurrentUser(&user_name))
      return false;

    if (trigger_type != TRIGGER_TYPE_NOW) {
      // Allow the task to run elevated on startup.
      Microsoft::WRL::ComPtr<IPrincipal> principal;
      hr = task->get_Principal(principal.GetAddressOf());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't get principal. " << std::hex << hr;
        return false;
      }

      hr = principal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't set highest run level. " << std::hex << hr;
        return false;
      }

      hr = principal->put_UserId(user_name);
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't put user id. " << std::hex << hr;
        return false;
      }

      hr = principal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't put logon type. " << std::hex << hr;
        return false;
      }
    }

    Microsoft::WRL::ComPtr<IRegistrationInfo> registration_info;
    hr = task->get_RegistrationInfo(registration_info.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't get registration info. " << std::hex << hr;
      return false;
    }

    hr = registration_info->put_Author(user_name);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't set registration info author. " << std::hex << hr;
      return false;
    }

    base::win::ScopedBstr description(task_description);
    hr = registration_info->put_Description(description);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't set description. " << std::hex << hr;
      return false;
    }

    Microsoft::WRL::ComPtr<ITaskSettings> task_settings;
    hr = task->get_Settings(task_settings.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't get task settings. " << std::hex << hr;
      return false;
    }

    hr = task_settings->put_StartWhenAvailable(VARIANT_TRUE);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't put 'StartWhenAvailable' to true. " << std::hex
                  << hr;
      return false;
    }

    // TODO(csharp): Find a way to only set this for log upload retry.
    hr = task_settings->put_DeleteExpiredTaskAfter(
        base::win::ScopedBstr(kZeroMinuteText));
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't put 'DeleteExpiredTaskAfter'. " << std::hex << hr;
      return false;
    }

    hr = task_settings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't put 'DisallowStartIfOnBatteries' to false. "
                  << std::hex << hr;
      return false;
    }

    hr = task_settings->put_StopIfGoingOnBatteries(VARIANT_FALSE);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't put 'StopIfGoingOnBatteries' to false. " << std::hex
                  << hr;
      return false;
    }

    if (hidden) {
      hr = task_settings->put_Hidden(VARIANT_TRUE);
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't put 'Hidden' to true. " << std::hex << hr;
        return false;
      }
    }

    Microsoft::WRL::ComPtr<ITriggerCollection> trigger_collection;
    hr = task->get_Triggers(trigger_collection.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't get trigger collection. " << std::hex << hr;
      return false;
    }

    TASK_TRIGGER_TYPE2 task_trigger_type = TASK_TRIGGER_EVENT;
    base::win::ScopedBstr repetition_interval;
    switch (trigger_type) {
      case TRIGGER_TYPE_POST_REBOOT:
        task_trigger_type = TASK_TRIGGER_LOGON;
        break;
      case TRIGGER_TYPE_NOW:
        task_trigger_type = TASK_TRIGGER_REGISTRATION;
        break;
      case TRIGGER_TYPE_HOURLY:
      case TRIGGER_TYPE_EVERY_SIX_HOURS:
        task_trigger_type = TASK_TRIGGER_DAILY;
        if (base::CommandLine::ForCurrentProcess()->HasSwitch(
                kLogUploadRetryIntervalSwitch)) {
          // String format: PT%lsM
          const base::string16 interval_switch = base::StrCat(
              {L"PT",
               base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
                   kLogUploadRetryIntervalSwitch),
               L"M"});
          LOG(WARNING) << "Command line switch overriding retry interval to: "
                       << interval_switch;
          repetition_interval.Reset(::SysAllocString(interval_switch.c_str()));
        } else if (trigger_type == TRIGGER_TYPE_EVERY_SIX_HOURS) {
          repetition_interval.Reset(::SysAllocString(kSixHoursText));
        } else {
          DCHECK_EQ(TRIGGER_TYPE_HOURLY, trigger_type);
          repetition_interval.Reset(::SysAllocString(kOneHourText));
        }
        break;
      default:
        NOTREACHED() << "Unknown TriggerType?";
    }

    Microsoft::WRL::ComPtr<ITrigger> trigger;
    hr = trigger_collection->Create(task_trigger_type, trigger.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't create trigger of type " << task_trigger_type
                  << ". " << std::hex << hr;
      return false;
    }

    if (trigger_type == TRIGGER_TYPE_HOURLY ||
        trigger_type == TRIGGER_TYPE_EVERY_SIX_HOURS) {
      Microsoft::WRL::ComPtr<IDailyTrigger> daily_trigger;
      hr = trigger.CopyTo(daily_trigger.GetAddressOf());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't Query for registration trigger. " << std::hex
                    << hr;
        return false;
      }

      hr = daily_trigger->put_DaysInterval(1);
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't put 'DaysInterval' to 1, " << std::hex << hr;
        return false;
      }

      Microsoft::WRL::ComPtr<IRepetitionPattern> repetition_pattern;
      hr = trigger->get_Repetition(repetition_pattern.GetAddressOf());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't get 'Repetition'. " << std::hex << hr;
        return false;
      }

      // The duration is the time to keep repeating until the next daily
      // trigger.
      hr = repetition_pattern->put_Duration(
          base::win::ScopedBstr(kTwentyFourHoursText));
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't put 'Duration' to " << kTwentyFourHoursText
                    << ". " << std::hex << hr;
        return false;
      }

      hr = repetition_pattern->put_Interval(repetition_interval);
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't put 'Interval' to " << repetition_interval << ". "
                    << std::hex << hr;
        return false;
      }

      // Start now.
      base::Time now(base::Time::NowFromSystemTime());
      base::win::ScopedBstr start_boundary(GetTimestampString(now));
      hr = trigger->put_StartBoundary(start_boundary);
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't put 'StartBoundary' to " << start_boundary << ". "
                    << std::hex << hr;
        return false;
      }
    }

    if (trigger_type == TRIGGER_TYPE_POST_REBOOT) {
      Microsoft::WRL::ComPtr<ILogonTrigger> logon_trigger;
      hr = trigger.CopyTo(logon_trigger.GetAddressOf());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't query trigger for 'ILogonTrigger'. " << std::hex
                    << hr;
        return false;
      }

      hr = logon_trigger->put_Delay(base::win::ScopedBstr(kFifteenMinutesText));
      if (FAILED(hr)) {
        PLOG(ERROR) << "Can't put 'Delay'. " << std::hex << hr;
        return false;
      }
    }

    // None of the triggers should go beyond kNumDaysBeforeExpiry.
    base::Time expiry_date(base::Time::NowFromSystemTime() +
                           base::TimeDelta::FromDays(kNumDaysBeforeExpiry));
    base::win::ScopedBstr end_boundary(GetTimestampString(expiry_date));
    hr = trigger->put_EndBoundary(end_boundary);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't put 'EndBoundary' to " << end_boundary << ". "
                  << std::hex << hr;
      return false;
    }

    Microsoft::WRL::ComPtr<IActionCollection> actions;
    hr = task->get_Actions(actions.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't get actions collection. " << std::hex << hr;
      return false;
    }

    Microsoft::WRL::ComPtr<IAction> action;
    hr = actions->Create(TASK_ACTION_EXEC, action.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't create exec action. " << std::hex << hr;
      return false;
    }

    Microsoft::WRL::ComPtr<IExecAction> exec_action;
    hr = action.CopyTo(exec_action.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't query for exec action. " << std::hex << hr;
      return false;
    }

    base::win::ScopedBstr path(run_command.GetProgram().value());
    hr = exec_action->put_Path(path);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't set path of exec action. " << std::hex << hr;
      return false;
    }

    base::win::ScopedBstr args(run_command.GetArgumentsString());
    hr = exec_action->put_Arguments(args);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Can't set arguments of exec action. " << std::hex << hr;
      return false;
    }

    Microsoft::WRL::ComPtr<IRegisteredTask> registered_task;
    base::win::ScopedVariant user(user_name);

    DCHECK(root_task_folder_);
    hr = root_task_folder_->RegisterTaskDefinition(
        base::win::ScopedBstr(task_name), task.Get(), TASK_CREATE,
        *user.AsInput(),  // Not really input, but API expect non-const.
        base::win::ScopedVariant::kEmptyVariant, TASK_LOGON_NONE,
        base::win::ScopedVariant::kEmptyVariant,
        registered_task.GetAddressOf());
    if (FAILED(hr)) {
      LOG(ERROR) << "RegisterTaskDefinition failed. " << std::hex << hr << ": "
                 << logging::SystemErrorCodeToString(hr);
      return false;
    }

    DCHECK(IsTaskRegistered(task_name));

    LOG(INFO) << "Successfully registered: "
              << SanitizeCommandLine(run_command);
    return true;
  }

 private:
  // Helper class that lets us iterate over all registered tasks.
  class TaskIterator {
   public:
    explicit TaskIterator(ITaskFolder* task_folder) {
      DCHECK(task_folder);
      HRESULT hr =
          task_folder->GetTasks(TASK_ENUM_HIDDEN, tasks_.GetAddressOf());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to get registered tasks from folder. "
                    << std::hex << hr;
        done_ = true;
        return;
      }
      hr = tasks_->get_Count(&num_tasks_);
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to get registered tasks count. " << std::hex
                    << hr;
        done_ = true;
        return;
      }
      Next();
    }

    // Increment to the next valid item in the task list. Skip entries for
    // which we cannot retrieve a name.
    void Next() {
      DCHECK(!done_);
      task_.Reset();
      name_.clear();
      if (++task_index_ >= num_tasks_) {
        done_ = true;
        return;
      }

      // Note: get_Item uses 1 based indices.
      HRESULT hr = tasks_->get_Item(base::win::ScopedVariant(task_index_ + 1),
                                    task_.GetAddressOf());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to get task at index: " << task_index_ << ". "
                    << std::hex << hr;
        Next();
        return;
      }

      base::win::ScopedBstr task_name_bstr;
      hr = task_->get_Name(task_name_bstr.Receive());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to get name at index: " << task_index_ << ". "
                    << std::hex << hr;
        Next();
        return;
      }
      name_ = base::string16(task_name_bstr ? task_name_bstr : L"");
    }

    // Detach the currently active task and pass ownership to the caller.
    // After this method has been called, the -> operator must no longer be
    // used.
    IRegisteredTask* Detach() { return task_.Detach(); }

    // Provide access to the current task.
    IRegisteredTask* operator->() const {
      IRegisteredTask* result = task_.Get();
      DCHECK(result);
      return result;
    }

    const base::string16& name() const { return name_; }
    bool done() const { return done_; }

   private:
    Microsoft::WRL::ComPtr<IRegisteredTaskCollection> tasks_;
    Microsoft::WRL::ComPtr<IRegisteredTask> task_;
    base::string16 name_;
    long task_index_ = -1;  // NOLINT, API requires a long.
    long num_tasks_ = 0;    // NOLINT, API requires a long.
    bool done_ = false;
  };

  // Return the task with |task_name| and false if not found. |task| can be null
  // when only interested in task's existence.
  bool GetTask(const wchar_t* task_name, IRegisteredTask** task) {
    for (TaskIterator it(root_task_folder_.Get()); !it.done(); it.Next()) {
      if (::_wcsicmp(it.name().c_str(), task_name) == 0) {
        if (task)
          *task = it.Detach();
        return true;
      }
    }
    return false;
  }

  // Return the description of the task.
  HRESULT GetTaskDescription(IRegisteredTask* task,
                             base::string16* description) {
    DCHECK(task);
    DCHECK(description);

    base::win::ScopedBstr task_name_bstr;
    HRESULT hr = task->get_Name(task_name_bstr.Receive());
    base::string16 task_name =
        base::string16(task_name_bstr ? task_name_bstr : L"");
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get task name";
    }

    Microsoft::WRL::ComPtr<ITaskDefinition> task_info;
    hr = task->get_Definition(task_info.GetAddressOf());
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get definition for task, " << task_name << ": "
                 << logging::SystemErrorCodeToString(hr);
      return hr;
    }

    Microsoft::WRL::ComPtr<IRegistrationInfo> reg_info;
    hr = task_info->get_RegistrationInfo(reg_info.GetAddressOf());
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get registration info, " << task_name << ": "
                 << logging::SystemErrorCodeToString(hr);
      return hr;
    }

    base::win::ScopedBstr raw_description;
    hr = reg_info->get_Description(raw_description.Receive());
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get description, " << task_name << ": "
                 << logging::SystemErrorCodeToString(hr);
      return hr;
    }
    *description = base::string16(raw_description ? raw_description : L"");
    return ERROR_SUCCESS;
  }

  // Return all executable actions associated with the given task. Non-exec
  // actions are silently ignored.
  bool GetTaskExecActions(IRegisteredTask* task,
                          std::vector<TaskExecAction>* actions) {
    DCHECK(task);
    DCHECK(actions);
    Microsoft::WRL::ComPtr<ITaskDefinition> task_definition;
    HRESULT hr = task->get_Definition(task_definition.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Failed to get definition of task, " << std::hex << hr;
      return false;
    }

    Microsoft::WRL::ComPtr<IActionCollection> action_collection;
    hr = task_definition->get_Actions(action_collection.GetAddressOf());
    if (FAILED(hr)) {
      PLOG(ERROR) << "Failed to get action collection, " << std::hex << hr;
      return false;
    }

    long actions_count = 0;  // NOLINT, API requires a long.
    hr = action_collection->get_Count(&actions_count);
    if (FAILED(hr)) {
      PLOG(ERROR) << "Failed to get number of actions, " << std::hex << hr;
      return false;
    }

    // Find and return as many exec actions as possible in |actions| and return
    // false if there were any errors on the way. Note that the indexing of
    // actions is 1-based.
    bool success = true;
    for (long action_index = 1;  // NOLINT
         action_index <= actions_count; ++action_index) {
      Microsoft::WRL::ComPtr<IAction> action;
      hr = action_collection->get_Item(action_index, action.GetAddressOf());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to get action at index " << action_index << ", "
                    << std::hex << hr;
        success = false;
        continue;
      }

      ::TASK_ACTION_TYPE action_type;
      hr = action->get_Type(&action_type);
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to get the type of action at index "
                    << action_index << ", " << std::hex << hr;
        success = false;
        continue;
      }

      // We only care about exec actions for now. The other types are
      // TASK_ACTION_COM_HANDLER, TASK_ACTION_SEND_EMAIL,
      // TASK_ACTION_SHOW_MESSAGE. The latter two are marked as deprecated in
      // the Task Scheduler's GUI.
      if (action_type != ::TASK_ACTION_EXEC)
        continue;

      Microsoft::WRL::ComPtr<IExecAction> exec_action;
      hr = action.CopyTo(exec_action.GetAddressOf());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to query from action, " << std::hex << hr;
        success = false;
        continue;
      }

      base::win::ScopedBstr application_path;
      hr = exec_action->get_Path(application_path.Receive());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to get path from action, " << std::hex << hr;
        success = false;
        continue;
      }

      base::win::ScopedBstr working_dir;
      hr = exec_action->get_WorkingDirectory(working_dir.Receive());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to get working directory for action, "
                    << std::hex << hr;
        success = false;
        continue;
      }

      base::win::ScopedBstr parameters;
      hr = exec_action->get_Arguments(parameters.Receive());
      if (FAILED(hr)) {
        PLOG(ERROR) << "Failed to get arguments from action of task, "
                    << std::hex << hr;
        success = false;
        continue;
      }

      actions->push_back(
          {base::FilePath(application_path ? application_path : L""),
           base::FilePath(working_dir ? working_dir : L""),
           base::string16(parameters ? parameters : L"")});
    }
    return success;
  }

  // Return the log-on type required for the task's actions to be run.
  HRESULT GetTaskLogonType(IRegisteredTask* task, uint32_t* logon_type) {
    DCHECK(task);
    DCHECK(logon_type);
    Microsoft::WRL::ComPtr<ITaskDefinition> task_info;
    HRESULT hr = task->get_Definition(task_info.GetAddressOf());
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get definition, " << std::hex << hr << ": "
                 << logging::SystemErrorCodeToString(hr);
      return hr;
    }

    Microsoft::WRL::ComPtr<IPrincipal> principal;
    hr = task_info->get_Principal(principal.GetAddressOf());
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get principal info, " << std::hex << hr << ": "
                 << logging::SystemErrorCodeToString(hr);
      return hr;
    }

    TASK_LOGON_TYPE raw_logon_type;
    hr = principal->get_LogonType(&raw_logon_type);
    if (FAILED(hr)) {
      LOG(ERROR) << "Failed to get logon type info, " << std::hex << hr << ": "
                 << logging::SystemErrorCodeToString(hr);
      return hr;
    }

    switch (raw_logon_type) {
      case TASK_LOGON_INTERACTIVE_TOKEN:
        *logon_type = LOGON_INTERACTIVE;
        break;
      case TASK_LOGON_GROUP:     // fall-thru
      case TASK_LOGON_PASSWORD:  // fall-thru
      case TASK_LOGON_SERVICE_ACCOUNT:
        *logon_type = LOGON_SERVICE;
        break;
      case TASK_LOGON_S4U:
        *logon_type = LOGON_SERVICE | LOGON_S4U;
        break;
      case TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD:
        *logon_type = LOGON_INTERACTIVE | LOGON_SERVICE;
        break;
      default:
        *logon_type = LOGON_UNKNOWN;
        break;
    }
    return ERROR_SUCCESS;
  }

  static Microsoft::WRL::ComPtr<ITaskService> task_service_;
  static Microsoft::WRL::ComPtr<ITaskFolder> root_task_folder_;

  DISALLOW_COPY_AND_ASSIGN(TaskSchedulerV2);
};

Microsoft::WRL::ComPtr<ITaskService> TaskSchedulerV2::task_service_;
Microsoft::WRL::ComPtr<ITaskFolder> TaskSchedulerV2::root_task_folder_;

// This wrapper class is needed so that CreateInstance below can instantiate a
// new one on every call, transferring ownership to the caller, and yet, we need
// to always get the same delegate to be called. So the temporary instantiated
// TaskScheduler is this mocked wrapper class, and each instance will delegate
// to the same mock, passed to the constructor.
// TODO(csharp): Simplify this.
class TaskSchedulerMock : public TaskScheduler {
 public:
  explicit TaskSchedulerMock(TaskScheduler* delegate) : delegate_(delegate) {
    DCHECK(delegate);
  }

  // TaskScheduler.
  bool IsTaskRegistered(const wchar_t* task_name) override {
    return delegate_->IsTaskRegistered(task_name);
  }
  bool GetNextTaskRunTime(const wchar_t* task_name,
                          base::Time* next_run_time) override {
    return delegate_->GetNextTaskRunTime(task_name, next_run_time);
  }
  bool DeleteTask(const wchar_t* task_name) override {
    return delegate_->DeleteTask(task_name);
  }
  bool SetTaskEnabled(const wchar_t* task_name, bool enabled) override {
    return delegate_->SetTaskEnabled(task_name, enabled);
  }
  bool IsTaskEnabled(const wchar_t* task_name) override {
    return delegate_->IsTaskEnabled(task_name);
  }
  bool GetTaskNameList(std::vector<base::string16>* task_names) override {
    return delegate_->GetTaskNameList(task_names);
  }
  bool GetTaskInfo(const wchar_t* task_name, TaskInfo* info) override {
    return delegate_->GetTaskInfo(task_name, info);
  }
  bool RegisterTask(const wchar_t* task_name,
                    const wchar_t* task_description,
                    const base::CommandLine& run_command,
                    TriggerType trigger_type,
                    bool hidden) override {
    return delegate_->RegisterTask(task_name, task_description, run_command,
                                   trigger_type, hidden);
  }

 private:
  TaskScheduler* delegate_;
};

}  // namespace

TaskScheduler* TaskScheduler::mock_delegate_ = nullptr;

TaskScheduler::TaskInfo::TaskInfo() = default;

TaskScheduler::TaskInfo::TaskInfo(const TaskScheduler::TaskInfo&) = default;

TaskScheduler::TaskInfo::TaskInfo(TaskScheduler::TaskInfo&&) = default;

TaskScheduler::TaskInfo& TaskScheduler::TaskInfo::operator=(
    const TaskScheduler::TaskInfo&) = default;

TaskScheduler::TaskInfo& TaskScheduler::TaskInfo::operator=(
    TaskScheduler::TaskInfo&&) = default;

TaskScheduler::TaskInfo::~TaskInfo() = default;

// static.
bool TaskScheduler::Initialize() {
  return TaskSchedulerV2::Initialize();
}

// static.
void TaskScheduler::Terminate() {
  TaskSchedulerV2::Terminate();
}

// static.
TaskScheduler* TaskScheduler::CreateInstance() {
  if (mock_delegate_)
    return new TaskSchedulerMock(mock_delegate_);

  return new TaskSchedulerV2();
}

TaskScheduler::TaskScheduler() = default;

}  // namespace chrome_cleaner
