Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Side by Side Diff: chrome/installer/util/registry_key_backup.cc

Issue 14265020: Remove scoped_array usage from RegistryKeyBackup. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Namespace adjustment Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/registry_key_backup.h" 5 #include "chrome/installer/util/registry_key_backup.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <map>
9 #include <vector> 10 #include <vector>
10 11
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/win/registry.h" 13 #include "base/win/registry.h"
13 14
14 using base::win::RegKey; 15 using base::win::RegKey;
15 16
16 namespace { 17 namespace {
18
17 const REGSAM kKeyReadNoNotify = (KEY_READ) & ~(KEY_NOTIFY); 19 const REGSAM kKeyReadNoNotify = (KEY_READ) & ~(KEY_NOTIFY);
18 } // namespace
19
20 // A container for a registry key, its values, and its subkeys.
21 class RegistryKeyBackup::KeyData {
22 public:
23 KeyData();
24 ~KeyData();
25
26 // Initializes this object by reading the values and subkeys of |key|.
27 // Security descriptors are not backed up. Returns true if the operation was
28 // successful; false otherwise, in which case the state of this object is not
29 // modified.
30 bool Initialize(const RegKey& key);
31
32 // Writes the contents of this object to |key|, which must have been opened
33 // with at least REG_SET_VALUE and KEY_CREATE_SUB_KEY access rights. Returns
34 // true if the operation was successful; false otherwise, in which case the
35 // contents of |key| may have been modified.
36 bool WriteTo(RegKey* key) const;
37
38 private:
39 class ValueData;
40
41 // The values of this key.
42 scoped_array<ValueData> values_;
43 // The names of this key's sub-keys (the data for subkey_names_[i] is in
44 // subkeys_[i]).
45 scoped_array<std::wstring> subkey_names_;
46 // The key data of this key's sub-keys.
47 scoped_array<KeyData> subkeys_;
48 // The number of values for this key.
49 DWORD num_values_;
50 // The number of subkeys for this key.
51 DWORD num_subkeys_;
52
53 DISALLOW_COPY_AND_ASSIGN(KeyData);
54 };
55 20
56 // A container for a registry value. 21 // A container for a registry value.
57 class RegistryKeyBackup::KeyData::ValueData { 22 class ValueData {
58 public: 23 public:
59 ValueData(); 24 ValueData();
60 ~ValueData(); 25 ~ValueData();
61 26
62 // Initializes this object with a name (the first |name_size| characters in 27 // Initializes this object with a name (the first |name_size| characters in
63 // |name_buffer|, |type|, and data (the first |data_size| bytes in |data|). 28 // |name_buffer|, |type|, and data (the first |data_size| bytes in |data|).
64 void Initialize(const wchar_t* name_buffer, DWORD name_size, 29 void Initialize(const wchar_t* name_buffer, DWORD name_size,
65 DWORD type, const uint8* data, DWORD data_size); 30 DWORD type, const uint8* data, DWORD data_size);
66 31
67 // The possibly empty name of this value. 32 // The possibly empty name of this value.
(...skipping 14 matching lines...) Expand all
82 47
83 private: 48 private:
84 // This value's name, or the empty string if this is the default (unnamed) 49 // This value's name, or the empty string if this is the default (unnamed)
85 // value. 50 // value.
86 std::wstring name_; 51 std::wstring name_;
87 // This value's data. 52 // This value's data.
88 std::vector<uint8> data_; 53 std::vector<uint8> data_;
89 // This value's type (e.g., REG_DWORD, REG_SZ, REG_QWORD, etc). 54 // This value's type (e.g., REG_DWORD, REG_SZ, REG_QWORD, etc).
90 DWORD type_; 55 DWORD type_;
91 56
92 DISALLOW_COPY_AND_ASSIGN(ValueData); 57 // Explicitly copyable for STL containers.
tommi (sloooow) - chröme 2013/04/16 11:22:09 nit: Isn't it rather implicit since it's not calle
grt (UTC plus 2) 2013/04/16 14:28:25 how about: // CopyConstructible and Assignable f
dcheng 2013/04/16 18:49:53 Done.
93 }; 58 };
94 59
95 RegistryKeyBackup::KeyData::ValueData::ValueData() 60 } // namespace
96 : type_(REG_NONE) { 61
62 // A container for a registry key, its values, and its subkeys.
63 class RegistryKeyBackup::KeyData {
64 public:
65 KeyData();
66 ~KeyData();
67
68 // Initializes this object by reading the values and subkeys of |key|.
69 // Security descriptors are not backed up. Returns true if the operation was
70 // successful; false otherwise, in which case the state of this object is not
71 // modified.
72 bool Initialize(const RegKey& key);
73
74 // Writes the contents of this object to |key|, which must have been opened
75 // with at least REG_SET_VALUE and KEY_CREATE_SUB_KEY access rights. Returns
76 // true if the operation was successful; false otherwise, in which case the
77 // contents of |key| may have been modified.
78 bool WriteTo(RegKey* key) const;
79
80 private:
81 // The values of this key.
82 std::vector<ValueData> values_;
83 // Map of subkey names to the corresponding KeyData.
84 std::map<std::wstring, KeyData> subkeys_;
85
86 // Explicitly copyable for STL containers.
tommi (sloooow) - chröme 2013/04/16 11:22:09 nit: implicit, since the copy ctor etc are compile
grt (UTC plus 2) 2013/04/16 14:28:25 how about: // CopyConstructible and Assignable f
dcheng 2013/04/16 18:49:53 Done.
87 };
88
89 ValueData::ValueData() : type_(REG_NONE) {
97 } 90 }
98 91
99 RegistryKeyBackup::KeyData::ValueData::~ValueData() 92 ValueData::~ValueData() {
100 {
101 } 93 }
102 94
103 void RegistryKeyBackup::KeyData::ValueData::Initialize( 95 void ValueData::Initialize(
104 const wchar_t* name_buffer, 96 const wchar_t* name_buffer,
105 DWORD name_size, 97 DWORD name_size,
106 DWORD type, 98 DWORD type,
107 const uint8* data, 99 const uint8* data,
108 DWORD data_size) { 100 DWORD data_size) {
109 name_.assign(name_buffer, name_size); 101 name_.assign(name_buffer, name_size);
110 type_ = type; 102 type_ = type;
111 data_.assign(data, data + data_size); 103 data_.assign(data, data + data_size);
112 } 104 }
113 105
114 RegistryKeyBackup::KeyData::KeyData() 106 RegistryKeyBackup::KeyData::KeyData() {
115 : num_values_(0),
116 num_subkeys_(0) {
117 } 107 }
118 108
119 RegistryKeyBackup::KeyData::~KeyData() 109 RegistryKeyBackup::KeyData::~KeyData()
120 { 110 {
grt (UTC plus 2) 2013/04/16 14:28:25 nit: move to previous line
dcheng 2013/04/16 18:49:53 Done.
121 } 111 }
122 112
123 bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { 113 bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) {
124 scoped_array<ValueData> values; 114 std::vector<ValueData> values;
125 scoped_array<std::wstring> subkey_names; 115 std::map<std::wstring, KeyData> subkeys;
126 scoped_array<KeyData> subkeys;
127 116
128 DWORD num_subkeys = 0; 117 DWORD num_subkeys = 0;
129 DWORD max_subkey_name_len = 0; 118 DWORD max_subkey_name_len = 0;
130 DWORD num_values = 0; 119 DWORD num_values = 0;
131 DWORD max_value_name_len = 0; 120 DWORD max_value_name_len = 0;
132 DWORD max_value_len = 0; 121 DWORD max_value_len = 0;
133 LONG result = RegQueryInfoKey(key.Handle(), NULL, NULL, NULL, 122 LONG result = RegQueryInfoKey(key.Handle(), NULL, NULL, NULL,
134 &num_subkeys, &max_subkey_name_len, NULL, 123 &num_subkeys, &max_subkey_name_len, NULL,
135 &num_values, &max_value_name_len, 124 &num_values, &max_value_name_len,
136 &max_value_len, NULL, NULL); 125 &max_value_len, NULL, NULL);
137 if (result != ERROR_SUCCESS) { 126 if (result != ERROR_SUCCESS) {
138 LOG(ERROR) << "Failed getting info of key to backup, result: " << result; 127 LOG(ERROR) << "Failed getting info of key to backup, result: " << result;
139 return false; 128 return false;
140 } 129 }
141 if (max_subkey_name_len >= std::numeric_limits<DWORD>::max() - 1 || 130 if (max_subkey_name_len >= std::numeric_limits<DWORD>::max() - 1 ||
142 max_value_name_len >= std::numeric_limits<DWORD>::max() - 1) { 131 max_value_name_len >= std::numeric_limits<DWORD>::max() - 1) {
143 LOG(ERROR) 132 LOG(ERROR)
144 << "Failed backing up key; subkeys and/or names are out of range."; 133 << "Failed backing up key; subkeys and/or names are out of range.";
145 return false; 134 return false;
146 } 135 }
147 DWORD max_name_len = std::max(max_subkey_name_len, max_value_name_len) + 1; 136 DWORD max_name_len = std::max(max_subkey_name_len, max_value_name_len) + 1;
148 scoped_array<wchar_t> name_buffer(new wchar_t[max_name_len]); 137 scoped_array<wchar_t> name_buffer(new wchar_t[max_name_len]);
grt (UTC plus 2) 2013/04/16 14:28:25 std::vector<wchar_t> name_buffer(max_name_len);
dcheng 2013/04/16 18:49:53 Done.
149 138
150 // Backup the values. 139 // Backup the values.
151 if (num_values != 0) { 140 if (num_values != 0) {
grt (UTC plus 2) 2013/04/16 14:28:25 inside this block: values.reserve(num_values);
dcheng 2013/04/16 18:49:53 Done.
152 values.reset(new ValueData[num_values]);
153 scoped_array<uint8> value_buffer(new uint8[max_value_len]); 141 scoped_array<uint8> value_buffer(new uint8[max_value_len]);
grt (UTC plus 2) 2013/04/16 14:28:25 std::vector<uint8> value_buffer(max_value_len ? ma
dcheng 2013/04/16 18:49:53 Done.
154 DWORD name_size = 0; 142 DWORD name_size = 0;
155 DWORD value_type = REG_NONE; 143 DWORD value_type = REG_NONE;
156 DWORD value_size = 0; 144 DWORD value_size = 0;
157 145
158 for (DWORD i = 0; i < num_values; ) { 146 for (DWORD i = 0; i < num_values; ) {
159 name_size = max_name_len; 147 name_size = max_name_len;
160 value_size = max_value_len; 148 value_size = max_value_len;
161 result = RegEnumValue(key.Handle(), i, name_buffer.get(), &name_size, 149 result = RegEnumValue(key.Handle(), i, name_buffer.get(), &name_size,
grt (UTC plus 2) 2013/04/16 14:28:25 name_buffer.get() -> &name_buffer[0]
dcheng 2013/04/16 18:49:53 Done.
162 NULL, &value_type, value_buffer.get(), &value_size); 150 NULL, &value_type, value_buffer.get(), &value_size);
grt (UTC plus 2) 2013/04/16 14:28:25 value_buffer.get() -> &value_buffer[0]
dcheng 2013/04/16 18:49:53 Done.
163 switch (result) { 151 switch (result) {
164 case ERROR_NO_MORE_ITEMS: 152 case ERROR_NO_MORE_ITEMS:
165 num_values = i; 153 num_values = i;
166 break; 154 break;
167 case ERROR_SUCCESS: 155 case ERROR_SUCCESS:
168 values[i].Initialize(name_buffer.get(), name_size, value_type, 156 values.push_back(ValueData());
169 value_buffer.get(), value_size); 157 values.back().Initialize(name_buffer.get(), name_size, value_type,
grt (UTC plus 2) 2013/04/16 14:28:25 name_buffer.get() -> &name_buffer[0]
dcheng 2013/04/16 18:49:53 Done.
158 value_buffer.get(), value_size);
grt (UTC plus 2) 2013/04/16 14:28:25 value_buffer.get() -> &value_buffer[0]
dcheng 2013/04/16 18:49:53 Done.
170 ++i; 159 ++i;
171 break; 160 break;
172 case ERROR_MORE_DATA: 161 case ERROR_MORE_DATA:
173 if (value_size > max_value_len) { 162 if (value_size > max_value_len) {
174 max_value_len = value_size; 163 max_value_len = value_size;
175 value_buffer.reset(); // Release to heap before new allocation. 164 value_buffer.reset(); // Release to heap before new allocation.
grt (UTC plus 2) 2013/04/16 14:28:25 replace this and the next line with: v
dcheng 2013/04/16 18:49:53 Done.
176 value_buffer.reset(new uint8[max_value_len]); 165 value_buffer.reset(new uint8[max_value_len]);
177 } else { 166 } else {
178 DCHECK_LT(max_name_len - 1, name_size); 167 DCHECK_LT(max_name_len - 1, name_size);
179 if (name_size >= std::numeric_limits<DWORD>::max() - 1) { 168 if (name_size >= std::numeric_limits<DWORD>::max() - 1) {
180 LOG(ERROR) << "Failed backing up key; value name out of range."; 169 LOG(ERROR) << "Failed backing up key; value name out of range.";
181 return false; 170 return false;
182 } 171 }
183 max_name_len = name_size + 1; 172 max_name_len = name_size + 1;
184 name_buffer.reset(); // Release to heap before new allocation. 173 name_buffer.reset(); // Release to heap before new allocation.
grt (UTC plus 2) 2013/04/16 14:28:25 replace this and the next line with: n
dcheng 2013/04/16 18:49:53 Done.
185 name_buffer.reset(new wchar_t[max_name_len]); 174 name_buffer.reset(new wchar_t[max_name_len]);
186 } 175 }
187 break; 176 break;
188 default: 177 default:
189 LOG(ERROR) << "Failed backing up value " << i << ", result: " 178 LOG(ERROR) << "Failed backing up value " << i << ", result: "
190 << result; 179 << result;
191 return false; 180 return false;
192 } 181 }
193 } 182 }
194 DLOG_IF(WARNING, RegEnumValue(key.Handle(), num_values, name_buffer.get(), 183 DLOG_IF(WARNING, RegEnumValue(key.Handle(), num_values, name_buffer.get(),
grt (UTC plus 2) 2013/04/16 14:28:25 name_buffer.get() -> &name_buffer[0]
dcheng 2013/04/16 18:49:53 Done.
195 &name_size, NULL, &value_type, NULL, 184 &name_size, NULL, &value_type, NULL,
196 NULL) != ERROR_NO_MORE_ITEMS) 185 NULL) != ERROR_NO_MORE_ITEMS)
197 << "Concurrent modifications to registry key during backup operation."; 186 << "Concurrent modifications to registry key during backup operation.";
198 } 187 }
199 188
200 // Backup the subkeys. 189 // Backup the subkeys.
201 if (num_subkeys != 0) { 190 if (num_subkeys != 0) {
202 subkey_names.reset(new std::wstring[num_subkeys]);
203 subkeys.reset(new KeyData[num_subkeys]);
204 DWORD name_size = 0; 191 DWORD name_size = 0;
205 192
206 // Get the names of them. 193 // Get the names of them.
207 for (DWORD i = 0; i < num_subkeys; ) { 194 for (DWORD i = 0; i < num_subkeys; ) {
208 name_size = max_name_len; 195 name_size = max_name_len;
209 result = RegEnumKeyEx(key.Handle(), i, name_buffer.get(), &name_size, 196 result = RegEnumKeyEx(key.Handle(), i, name_buffer.get(), &name_size,
grt (UTC plus 2) 2013/04/16 14:28:25 name_buffer.get() -> &name_buffer[0]
dcheng 2013/04/16 18:49:53 Done.
210 NULL, NULL, NULL, NULL); 197 NULL, NULL, NULL, NULL);
211 switch (result) { 198 switch (result) {
212 case ERROR_NO_MORE_ITEMS: 199 case ERROR_NO_MORE_ITEMS:
213 num_subkeys = i; 200 num_subkeys = i;
214 break; 201 break;
215 case ERROR_SUCCESS: 202 case ERROR_SUCCESS:
216 subkey_names[i].assign(name_buffer.get(), name_size); 203 subkeys[std::wstring(name_buffer.get(), name_size)] = KeyData();
grt (UTC plus 2) 2013/04/16 14:28:25 name_buffer.get() -> &name_buffer[0]
grt (UTC plus 2) 2013/04/16 14:28:25 nit: " = KeyData()" constructs an extra object tha
dcheng 2013/04/16 18:49:53 That's true, but it's kind of non-obvious. I've ch
dcheng 2013/04/16 18:49:53 Done.
217 ++i; 204 ++i;
218 break; 205 break;
219 case ERROR_MORE_DATA: 206 case ERROR_MORE_DATA:
220 if (name_size >= std::numeric_limits<DWORD>::max() - 1) { 207 if (name_size >= std::numeric_limits<DWORD>::max() - 1) {
221 LOG(ERROR) << "Failed backing up key; subkey name out of range."; 208 LOG(ERROR) << "Failed backing up key; subkey name out of range.";
222 return false; 209 return false;
223 } 210 }
224 max_name_len = name_size + 1; 211 max_name_len = name_size + 1;
225 name_buffer.reset(new wchar_t[max_name_len]); 212 name_buffer.reset(new wchar_t[max_name_len]);
grt (UTC plus 2) 2013/04/16 14:28:25 name_buffer.resize(max_name_len);
dcheng 2013/04/16 18:49:53 Done.
226 break; 213 break;
227 default: 214 default:
228 LOG(ERROR) << "Failed getting name of subkey " << i 215 LOG(ERROR) << "Failed getting name of subkey " << i
229 << " for backup, result: " << result; 216 << " for backup, result: " << result;
230 return false; 217 return false;
231 } 218 }
232 } 219 }
233 DLOG_IF(WARNING, 220 DLOG_IF(WARNING,
234 RegEnumKeyEx(key.Handle(), num_subkeys, NULL, &name_size, NULL, 221 RegEnumKeyEx(key.Handle(), num_subkeys, NULL, &name_size, NULL,
235 NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS) 222 NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
236 << "Concurrent modifications to registry key during backup operation."; 223 << "Concurrent modifications to registry key during backup operation.";
237 224
238 // Get their values. 225 // Get their values.
239 RegKey subkey; 226 RegKey subkey;
240 for (DWORD i = 0; i < num_subkeys; ++i) { 227 for (std::map<std::wstring, KeyData>::iterator it = subkeys.begin();
241 result = subkey.Open(key.Handle(), subkey_names[i].c_str(), 228 it != subkeys.end(); ++it) {
229 result = subkey.Open(key.Handle(), it->first.c_str(),
242 kKeyReadNoNotify); 230 kKeyReadNoNotify);
grt (UTC plus 2) 2013/04/16 14:28:25 nit: move to previous line
dcheng 2013/04/16 18:49:53 Done.
243 if (result != ERROR_SUCCESS) { 231 if (result != ERROR_SUCCESS) {
244 LOG(ERROR) << "Failed opening subkey \"" << subkey_names[i] 232 LOG(ERROR) << "Failed opening subkey \"" << it->first
245 << "\" for backup, result: " << result; 233 << "\" for backup, result: " << result;
246 return false; 234 return false;
247 } 235 }
248 if (!subkeys[i].Initialize(subkey)) { 236 if (!it->second.Initialize(subkey)) {
249 LOG(ERROR) << "Failed backing up subkey \"" << subkey_names[i] << "\""; 237 LOG(ERROR) << "Failed backing up subkey \"" << it->first << "\"";
250 return false; 238 return false;
251 } 239 }
252 } 240 }
253 } 241 }
254 242
255 values_.swap(values); 243 values_.swap(values);
256 subkey_names_.swap(subkey_names);
257 subkeys_.swap(subkeys); 244 subkeys_.swap(subkeys);
258 num_values_ = num_values;
259 num_subkeys_ = num_subkeys;
260 245
261 return true; 246 return true;
262 } 247 }
263 248
264 bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const { 249 bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const {
265 DCHECK(key); 250 DCHECK(key);
266 251
267 LONG result = ERROR_SUCCESS; 252 LONG result = ERROR_SUCCESS;
268 253
269 // Write the values. 254 // Write the values.
270 for (DWORD i = 0; i < num_values_; ++i) { 255 for (std::vector<ValueData>::const_iterator it = values_.begin();
271 const ValueData& value = values_[i]; 256 it != values_.end(); ++it) {
257 const ValueData& value = *it;
272 result = RegSetValueEx(key->Handle(), value.name(), 0, value.type(), 258 result = RegSetValueEx(key->Handle(), value.name(), 0, value.type(),
273 value.data(), value.data_len()); 259 value.data(), value.data_len());
274 if (result != ERROR_SUCCESS) { 260 if (result != ERROR_SUCCESS) {
275 LOG(ERROR) << "Failed writing value \"" << value.name_str() 261 LOG(ERROR) << "Failed writing value \"" << value.name_str()
276 << "\", result: " << result; 262 << "\", result: " << result;
277 return false; 263 return false;
278 } 264 }
279 } 265 }
280 266
281 // Write the subkeys. 267 // Write the subkeys.
282 RegKey subkey; 268 RegKey subkey;
283 for (DWORD i = 0; i < num_subkeys_; ++i) { 269 for (std::map<std::wstring, KeyData>::const_iterator it = subkeys_.begin();
284 const std::wstring& name = subkey_names_[i]; 270 it != subkeys_.end(); ++it) {
271 const std::wstring& name = it->first;
285 272
286 result = subkey.Create(key->Handle(), name.c_str(), KEY_WRITE); 273 result = subkey.Create(key->Handle(), name.c_str(), KEY_WRITE);
287 if (result != ERROR_SUCCESS) { 274 if (result != ERROR_SUCCESS) {
288 LOG(ERROR) << "Failed creating subkey \"" << name << "\", result: " 275 LOG(ERROR) << "Failed creating subkey \"" << name << "\", result: "
289 << result; 276 << result;
290 return false; 277 return false;
291 } 278 }
292 if (!subkeys_[i].WriteTo(&subkey)) { 279 if (!it->second.WriteTo(&subkey)) {
293 LOG(ERROR) << "Failed writing subkey \"" << name << "\", result: " 280 LOG(ERROR) << "Failed writing subkey \"" << name << "\", result: "
294 << result; 281 << result;
295 return false; 282 return false;
296 } 283 }
297 } 284 }
298 285
299 return true; 286 return true;
300 } 287 }
301 288
302 RegistryKeyBackup::RegistryKeyBackup() { 289 RegistryKeyBackup::RegistryKeyBackup() {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 } else { 330 } else {
344 success = key_data_->WriteTo(&dest_key); 331 success = key_data_->WriteTo(&dest_key);
345 LOG_IF(ERROR, !success) << "Failed to write key data."; 332 LOG_IF(ERROR, !success) << "Failed to write key data.";
346 } 333 }
347 } else { 334 } else {
348 success = true; 335 success = true;
349 } 336 }
350 337
351 return success; 338 return success;
352 } 339 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698