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 |