1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/installer/util/set_reg_value_work_item.h"
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "base/win/registry.h"
10 #include "chrome/installer/util/logging_installer.h"
12 SetRegValueWorkItem::~SetRegValueWorkItem() {
15 SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root,
16 const std::wstring& key_path,
17 const std::wstring& value_name,
18 const std::wstring& value_data,
20 : predefined_root_(predefined_root),
22 value_name_(value_name),
23 overwrite_(overwrite),
27 const uint8* data = reinterpret_cast<const uint8*>(value_data.c_str());
28 value_.assign(data, data + (value_data.length() + 1) * sizeof(wchar_t));
31 SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root,
32 const std::wstring& key_path,
33 const std::wstring& value_name,
36 : predefined_root_(predefined_root),
38 value_name_(value_name),
39 overwrite_(overwrite),
43 const uint8* data = reinterpret_cast<const uint8*>(&value_data);
44 value_.assign(data, data + sizeof(value_data));
47 SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root,
48 const std::wstring& key_path,
49 const std::wstring& value_name,
52 : predefined_root_(predefined_root),
54 value_name_(value_name),
55 overwrite_(overwrite),
59 const uint8* data = reinterpret_cast<const uint8*>(&value_data);
60 value_.assign(data, data + sizeof(value_data));
63 bool SetRegValueWorkItem::Do() {
64 LONG result = ERROR_SUCCESS;
65 base::win::RegKey key;
66 if (status_ != SET_VALUE) {
67 // we already did something.
68 VLOG(1) << "multiple calls to Do()";
69 result = ERROR_CANTWRITE;
70 return ignore_failure_;
73 status_ = VALUE_UNCHANGED;
74 result = key.Open(predefined_root_, key_path_.c_str(),
75 KEY_READ | KEY_SET_VALUE);
76 if (result != ERROR_SUCCESS) {
77 VLOG(1) << "can not open " << key_path_ << " error: " << result;
78 return ignore_failure_;
83 result = key.ReadValue(value_name_.c_str(), NULL, &size, &type);
84 // If the value exists but we don't want to overwrite then there's
85 // nothing more to do.
86 if ((result != ERROR_FILE_NOT_FOUND) && !overwrite_) {
90 // If there's something to be saved, save it.
91 if (result == ERROR_SUCCESS) {
93 previous_type_ = type;
95 previous_value_.resize(size);
96 result = key.ReadValue(value_name_.c_str(), &previous_value_[0], &size,
98 if (result != ERROR_SUCCESS) {
99 previous_value_.clear();
100 VLOG(1) << "Failed to save original value. Error: " << result;
105 result = key.WriteValue(value_name_.c_str(), &value_[0],
106 static_cast<DWORD>(value_.size()), type_);
107 if (result != ERROR_SUCCESS) {
108 VLOG(1) << "Failed to write value " << key_path_ << " error: " << result;
109 return ignore_failure_;
112 status_ = previous_type_ ? VALUE_OVERWRITTEN : NEW_VALUE_CREATED;
116 void SetRegValueWorkItem::Rollback() {
120 if (status_ == SET_VALUE || status_ == VALUE_ROLL_BACK)
123 if (status_ == VALUE_UNCHANGED) {
124 status_ = VALUE_ROLL_BACK;
125 VLOG(1) << "rollback: setting unchanged, nothing to do";
129 base::win::RegKey key;
130 LONG result = key.Open(predefined_root_, key_path_.c_str(), KEY_SET_VALUE);
131 if (result != ERROR_SUCCESS) {
132 VLOG(1) << "rollback: can not open " << key_path_ << " error: " << result;
136 if (status_ == NEW_VALUE_CREATED) {
137 result = key.DeleteValue(value_name_.c_str());
138 VLOG(1) << "rollback: deleting " << value_name_ << " error: " << result;
139 } else if (status_ == VALUE_OVERWRITTEN) {
140 const unsigned char* previous_value =
141 previous_value_.empty() ? NULL : &previous_value_[0];
142 result = key.WriteValue(value_name_.c_str(), previous_value,
143 static_cast<DWORD>(previous_value_.size()),
145 VLOG(1) << "rollback: restoring " << value_name_ << " error: " << result;
150 status_ = VALUE_ROLL_BACK;