Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/installer/util/set_reg_value_work_item.h" | 5 #include "chrome/installer/util/set_reg_value_work_item.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/string_util.h" | |
| 8 #include "base/win/registry.h" | 9 #include "base/win/registry.h" |
| 9 #include "chrome/installer/util/logging_installer.h" | 10 #include "chrome/installer/util/logging_installer.h" |
| 10 | 11 |
| 11 SetRegValueWorkItem::~SetRegValueWorkItem() { | 12 SetRegValueWorkItem::~SetRegValueWorkItem() { |
| 12 } | 13 } |
| 13 | 14 |
| 14 SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, | 15 SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, |
| 15 const std::wstring& key_path, | 16 const std::wstring& key_path, |
| 16 const std::wstring& value_name, | 17 const std::wstring& value_name, |
| 17 const std::wstring& value_data, | 18 const std::wstring& value_data, |
| 18 bool overwrite) | 19 bool overwrite) |
| 19 : predefined_root_(predefined_root), | 20 : predefined_root_(predefined_root), |
| 20 key_path_(key_path), | 21 key_path_(key_path), |
| 21 value_name_(value_name), | 22 value_name_(value_name), |
| 22 value_data_str_(value_data), | |
| 23 value_data_dword_(0), | |
| 24 value_data_qword_(0), | |
| 25 overwrite_(overwrite), | 23 overwrite_(overwrite), |
| 26 status_(SET_VALUE), | 24 status_(SET_VALUE), |
| 27 type_(REG_SZ), | 25 type_(REG_SZ) { |
| 28 previous_value_dword_(0), | 26 const char* data = reinterpret_cast<const char*>(value_data.c_str()); |
| 29 previous_value_qword_(0) { | 27 value_.assign(data, value_data.length() * sizeof(wchar_t)); |
|
grt (UTC plus 2)
2011/01/14 15:53:43
You must use (value_data.length() + 1) * sizeof(wc
amit
2011/01/15 01:28:11
Done.
| |
| 30 } | 28 } |
| 31 | 29 |
| 32 SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, | 30 SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, |
| 33 const std::wstring& key_path, | 31 const std::wstring& key_path, |
| 34 const std::wstring& value_name, | 32 const std::wstring& value_name, |
| 35 DWORD value_data, | 33 DWORD value_data, |
| 36 bool overwrite) | 34 bool overwrite) |
| 37 : predefined_root_(predefined_root), | 35 : predefined_root_(predefined_root), |
| 38 key_path_(key_path), | 36 key_path_(key_path), |
| 39 value_name_(value_name), | 37 value_name_(value_name), |
| 40 value_data_dword_(value_data), | |
| 41 value_data_qword_(0), | |
| 42 overwrite_(overwrite), | 38 overwrite_(overwrite), |
| 43 status_(SET_VALUE), | 39 status_(SET_VALUE), |
| 44 type_(REG_DWORD), | 40 type_(REG_DWORD) { |
| 45 previous_value_dword_(0), | 41 const char* data = reinterpret_cast<const char*>(&value_data); |
| 46 previous_value_qword_(0) { | 42 value_.assign(data, sizeof(value_data)); |
| 47 } | 43 } |
| 48 | 44 |
| 49 SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, | 45 SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, |
| 50 const std::wstring& key_path, | 46 const std::wstring& key_path, |
| 51 const std::wstring& value_name, | 47 const std::wstring& value_name, |
| 52 int64 value_data, | 48 int64 value_data, |
| 53 bool overwrite) | 49 bool overwrite) |
| 54 : predefined_root_(predefined_root), | 50 : predefined_root_(predefined_root), |
| 55 key_path_(key_path), | 51 key_path_(key_path), |
| 56 value_name_(value_name), | 52 value_name_(value_name), |
| 57 value_data_dword_(0), | |
| 58 value_data_qword_(value_data), | |
| 59 overwrite_(overwrite), | 53 overwrite_(overwrite), |
| 60 status_(SET_VALUE), | 54 status_(SET_VALUE), |
| 61 type_(REG_QWORD), | 55 type_(REG_QWORD) { |
| 62 previous_value_dword_(0), | 56 const char* data = reinterpret_cast<const char*>(&value_data); |
| 63 previous_value_qword_(0) { | 57 value_.assign(data, sizeof(value_data)); |
| 64 } | 58 } |
| 65 | 59 |
| 66 bool SetRegValueWorkItem::Do() { | 60 bool SetRegValueWorkItem::Do() { |
| 67 bool success = true; | 61 LONG result = ERROR_SUCCESS; |
| 68 | 62 base::win::RegKey key; |
| 69 if (status_ != SET_VALUE) { | 63 if (status_ != SET_VALUE) { |
| 70 // we already did something. | 64 // we already did something. |
| 71 LOG(ERROR) << "multiple calls to Do()"; | 65 VLOG(1) << "multiple calls to Do()"; |
| 72 success = false; | 66 result = ERROR_CANTWRITE; |
| 67 return ignore_failure_; | |
| 68 } | |
| 69 | |
| 70 status_ = VALUE_UNCHANGED; | |
| 71 result = key.Open(predefined_root_, key_path_.c_str(), | |
| 72 KEY_READ | KEY_SET_VALUE); | |
| 73 if (result != ERROR_SUCCESS) { | |
| 74 VLOG(1) << "can not open " << key_path_ << " error: " << result; | |
| 75 return ignore_failure_; | |
| 76 } | |
| 77 | |
| 78 DWORD type = 0; | |
| 79 DWORD size = 0; | |
| 80 result = key.ReadValue(value_name_.c_str(), NULL, &size, &type); | |
| 81 // If the value exists but we don't want to overwrite then there's | |
| 82 // nothing mroe to do. | |
| 83 if (!overwrite_ && result != ERROR_FILE_NOT_FOUND) { | |
|
grt (UTC plus 2)
2011/01/14 15:53:43
nit: make the order of the tests and the order of
amit
2011/01/15 01:28:11
Done.
| |
| 84 return ignore_failure_; | |
| 85 } | |
| 86 | |
| 87 // If there's something to be saved, save it. | |
| 88 if (result == ERROR_MORE_DATA) { | |
|
grt (UTC plus 2)
2011/01/14 15:53:43
Same comment as before: MSDN leads me to believe t
amit
2011/01/15 01:28:11
Done.
| |
| 89 result = key.ReadValue(value_name_.c_str(), | |
| 90 WriteInto(&previous_value_, size), &size, | |
| 91 &previous_type_); | |
| 92 VLOG_IF(1, result != ERROR_SUCCESS) << "Failed to save original value. " | |
| 93 "Error: " << result; | |
| 94 } | |
| 95 | |
| 96 result = key.WriteValue(value_name_.c_str(), value_.c_str(), | |
|
grt (UTC plus 2)
2011/01/14 15:53:43
If you stick with std::string, use data() rather t
amit
2011/01/15 01:28:11
Done.
| |
| 97 static_cast<DWORD>(value_.size()), type_); | |
| 98 if (result != ERROR_SUCCESS) { | |
| 99 VLOG(1) << "Failed to write value " << key_path_ << " error: " << result; | |
| 100 return ignore_failure_; | |
| 101 } | |
| 102 | |
| 103 status_ = overwrite_ ? VALUE_OVERWRITTEN : NEW_VALUE_CREATED; | |
| 104 return true; | |
| 105 } | |
| 106 | |
| 107 void SetRegValueWorkItem::Rollback() { | |
| 108 if (ignore_failure_) | |
| 109 return; | |
| 110 | |
| 111 if (status_ == SET_VALUE || status_ == VALUE_ROLL_BACK) | |
| 112 return; | |
| 113 | |
| 114 status_ = VALUE_ROLL_BACK; | |
|
grt (UTC plus 2)
2011/01/14 15:53:43
This is wrong.
amit
2011/01/15 01:28:11
Good catch, removed.
| |
| 115 if (status_ == VALUE_UNCHANGED) { | |
| 116 VLOG(1) << "rollback: setting unchanged, nothing to do"; | |
| 117 return; | |
| 73 } | 118 } |
| 74 | 119 |
| 75 base::win::RegKey key; | 120 base::win::RegKey key; |
| 76 if (success && !key.Open(predefined_root_, key_path_.c_str(), | 121 LONG result = key.Open(predefined_root_, key_path_.c_str(), KEY_SET_VALUE); |
| 77 KEY_READ | KEY_SET_VALUE)) { | 122 if (result != ERROR_SUCCESS) { |
| 78 LOG(ERROR) << "can not open " << key_path_; | 123 VLOG(1) << "rollback: can not open " << key_path_ << " error: " << result; |
| 79 status_ = VALUE_UNCHANGED; | 124 return; |
| 80 success = false; | |
| 81 } | 125 } |
| 82 | 126 |
| 83 if (success) { | 127 if (status_ == NEW_VALUE_CREATED) { |
| 84 if (key.ValueExists(value_name_.c_str())) { | 128 result = key.DeleteValue(value_name_.c_str()); |
| 85 if (overwrite_) { | 129 VLOG(1) << "rollback: deleting " << value_name_ << " error: " << result; |
| 86 // Read previous value for rollback and write new value | 130 } else if (status_ == VALUE_OVERWRITTEN) { |
| 87 if (type_ == REG_SZ) { | 131 result = key.WriteValue(value_name_.c_str(), previous_value_.c_str(), |
|
grt (UTC plus 2)
2011/01/14 15:53:43
If you stick with std::string, use data() rather t
| |
| 88 std::wstring data; | 132 static_cast<DWORD>(previous_value_.size()), |
| 89 if (key.ReadValue(value_name_.c_str(), &data)) { | 133 previous_type_); |
| 90 previous_value_str_.assign(data); | 134 VLOG(1) << "rollback: restoring " << value_name_ << " error: " << result; |
| 91 } | 135 } else { |
| 92 success = key.WriteValue(value_name_.c_str(), | 136 NOTREACHED(); |
| 93 value_data_str_.c_str()); | |
| 94 } else if (type_ == REG_DWORD) { | |
| 95 DWORD data; | |
| 96 if (key.ReadValueDW(value_name_.c_str(), &data)) { | |
| 97 previous_value_dword_ = data; | |
| 98 } | |
| 99 success = key.WriteValue(value_name_.c_str(), value_data_dword_); | |
| 100 } else if (type_ == REG_QWORD) { | |
| 101 int64 data; | |
| 102 DWORD data_size = sizeof(data); | |
| 103 DWORD data_type = NULL; | |
| 104 | |
| 105 if (key.ReadValue(value_name_.c_str(), &data, &data_size, | |
| 106 &data_type)) { | |
| 107 previous_value_qword_ = data; | |
| 108 } | |
| 109 success = key.WriteValue(value_name_.c_str(), | |
| 110 &value_data_qword_, | |
| 111 sizeof(value_data_qword_), | |
| 112 REG_QWORD); | |
| 113 } | |
| 114 if (success) { | |
| 115 VLOG(1) << "overwritten value for " << value_name_; | |
| 116 status_ = VALUE_OVERWRITTEN; | |
| 117 } else { | |
| 118 LOG(ERROR) << "failed to overwrite value for " << value_name_; | |
| 119 status_ = VALUE_UNCHANGED; | |
| 120 } | |
| 121 } else { | |
| 122 VLOG(1) << value_name_ << " exists. not changed "; | |
| 123 status_ = VALUE_UNCHANGED; | |
| 124 } | |
| 125 } else { | |
| 126 if (type_ == REG_SZ) { | |
| 127 success = key.WriteValue(value_name_.c_str(), value_data_str_.c_str()); | |
| 128 } else if (type_ == REG_DWORD) { | |
| 129 success = key.WriteValue(value_name_.c_str(), value_data_dword_); | |
| 130 } else if (type_ == REG_QWORD) { | |
| 131 success = key.WriteValue(value_name_.c_str(), | |
| 132 &value_data_qword_, | |
| 133 sizeof(value_data_qword_), | |
| 134 REG_QWORD); | |
| 135 } else { | |
| 136 NOTREACHED() << "Unsupported value type."; | |
| 137 } | |
| 138 if (success) { | |
| 139 VLOG(1) << "created value for " << value_name_; | |
| 140 status_ = NEW_VALUE_CREATED; | |
| 141 } else { | |
| 142 LOG(ERROR) << "failed to create value for " << value_name_; | |
| 143 status_ = VALUE_UNCHANGED; | |
| 144 } | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 LOG_IF(ERROR, !success && !log_message_.empty()) << log_message_; | |
| 149 | |
| 150 if (ignore_failure_) { | |
| 151 success = true; | |
| 152 } | |
| 153 | |
| 154 return success; | |
| 155 } | |
| 156 | |
| 157 void SetRegValueWorkItem::Rollback() { | |
| 158 if (!ignore_failure_) { | |
| 159 if (status_ == SET_VALUE || status_ == VALUE_ROLL_BACK) | |
| 160 return; | |
| 161 | |
| 162 if (status_ == VALUE_UNCHANGED) { | |
| 163 status_ = VALUE_ROLL_BACK; | |
| 164 VLOG(1) << "rollback: setting unchanged, nothing to do"; | |
| 165 return; | |
| 166 } | |
| 167 | |
| 168 base::win::RegKey key; | |
| 169 if (!key.Open(predefined_root_, key_path_.c_str(), KEY_SET_VALUE)) { | |
| 170 status_ = VALUE_ROLL_BACK; | |
| 171 VLOG(1) << "rollback: can not open " << key_path_; | |
| 172 return; | |
| 173 } | |
| 174 | |
| 175 std::wstring result_str(L" failed"); | |
| 176 if (status_ == NEW_VALUE_CREATED) { | |
| 177 if (key.DeleteValue(value_name_.c_str())) | |
| 178 result_str.assign(L" succeeded"); | |
| 179 VLOG(1) << "rollback: deleting " << value_name_ << result_str; | |
| 180 } else if (status_ == VALUE_OVERWRITTEN) { | |
| 181 // try restore the previous value | |
| 182 bool success = true; | |
| 183 if (type_ == REG_SZ) { | |
| 184 success = key.WriteValue(value_name_.c_str(), | |
| 185 previous_value_str_.c_str()); | |
| 186 } else if (type_ == REG_DWORD) { | |
| 187 success = key.WriteValue(value_name_.c_str(), previous_value_dword_); | |
| 188 } else if (type_ == REG_QWORD) { | |
| 189 success = key.WriteValue(value_name_.c_str(), | |
| 190 &previous_value_qword_, | |
| 191 sizeof(previous_value_qword_), | |
| 192 REG_QWORD); | |
| 193 } else { | |
| 194 NOTREACHED(); | |
| 195 } | |
| 196 if (success) | |
| 197 result_str.assign(L" succeeded"); | |
| 198 VLOG(1) << "rollback: restoring " << value_name_ << result_str; | |
| 199 | |
| 200 status_ = VALUE_ROLL_BACK; | |
| 201 return; | |
| 202 } | |
| 203 } | 137 } |
| 204 } | 138 } |
| OLD | NEW |