// Copyright (c) 2012 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/installer/util/delete_reg_value_work_item.h"

#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/win/registry.h"
#include "chrome/installer/util/logging_installer.h"

using base::win::RegKey;

DeleteRegValueWorkItem::DeleteRegValueWorkItem(HKEY predefined_root,
                                               const std::wstring& key_path,
                                               const std::wstring& value_name)
    : predefined_root_(predefined_root),
      key_path_(key_path),
      value_name_(value_name),
      previous_type_(0),
      status_(DELETE_VALUE) {
}

DeleteRegValueWorkItem::~DeleteRegValueWorkItem() {
}

bool DeleteRegValueWorkItem::Do() {
  if (status_ != DELETE_VALUE) {
    // we already did something.
    LOG(ERROR) << "multiple calls to Do()";
    return false;
  }

  status_ = VALUE_UNCHANGED;

  RegKey key;
  DWORD type = 0;
  DWORD size = 0;
  LONG result = key.Open(predefined_root_, key_path_.c_str(),
                         KEY_READ | KEY_WRITE);
  if (result == ERROR_SUCCESS)
    result = key.ReadValue(value_name_.c_str(), NULL, &size, &type);

  if (result == ERROR_FILE_NOT_FOUND) {
    LOG(INFO) << "(delete value) Key: " << key_path_ << " or Value: "
              << value_name_ << " does not exist.";
    status_ = VALUE_NOT_FOUND;
    return true;
  }

  if (result == ERROR_SUCCESS) {
    if (!size) {
      previous_type_ = type;
    } else {
      previous_value_.resize(size);
      result = key.ReadValue(value_name_.c_str(), &previous_value_[0], &size,
                             &previous_type_);
      if (result != ERROR_SUCCESS) {
        previous_value_.erase();
        VLOG(1) << "Failed to save original value. Error: " << result;
      }
    }
  }

  result = key.DeleteValue(value_name_.c_str());
  if (result != ERROR_SUCCESS) {
    VLOG(1) << "Failed to delete value " << value_name_ << " error: " << result;
    return false;
  }

  status_ = VALUE_DELETED;
  return true;
}

void DeleteRegValueWorkItem::Rollback() {
  if (status_ == DELETE_VALUE || status_ == VALUE_ROLLED_BACK)
    return;
  if (status_ == VALUE_UNCHANGED || status_ == VALUE_NOT_FOUND) {
    status_ = VALUE_ROLLED_BACK;
    VLOG(1) << "rollback: setting unchanged, nothing to do";
    return;
  }

  // At this point only possible state is VALUE_DELETED.
  RegKey key;
  LONG result = key.Open(predefined_root_, key_path_.c_str(),
                         KEY_READ | KEY_WRITE);
  if (result == ERROR_SUCCESS) {
    // try to restore the previous value
    DWORD previous_size = static_cast<DWORD>(previous_value_.size());
    const char* previous_value =
        previous_size ? &previous_value_[0] : NULL;
    result = key.WriteValue(value_name_.c_str(), previous_value,
                            previous_size, previous_type_);
    VLOG_IF(1, result != ERROR_SUCCESS) << "rollback: restoring "
                                        << value_name_ << " error: " << result;
  } else {
    VLOG(1) << "can not open " << key_path_ << " error: " << result;
  }
}
