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

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

Issue 14330007: Revert 194643 "Remove scoped_array usage from RegistryKeyBackup." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: 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 <map> 8 #include <limits>
9 #include <utility>
10 #include <vector> 9 #include <vector>
11 10
12 #include "base/logging.h" 11 #include "base/logging.h"
13 #include "base/win/registry.h" 12 #include "base/win/registry.h"
14 13
15 using base::win::RegKey; 14 using base::win::RegKey;
16 15
17 namespace { 16 namespace {
17 const REGSAM kKeyReadNoNotify = (KEY_READ) & ~(KEY_NOTIFY);
18 } // namespace
18 19
19 const REGSAM kKeyReadNoNotify = (KEY_READ) & ~(KEY_NOTIFY); 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 };
20 55
21 // A container for a registry value. 56 // A container for a registry value.
22 class ValueData { 57 class RegistryKeyBackup::KeyData::ValueData {
23 public: 58 public:
24 ValueData(); 59 ValueData();
25 ~ValueData(); 60 ~ValueData();
26 61
27 // Initializes this object with a name (the first |name_size| characters in 62 // Initializes this object with a name (the first |name_size| characters in
28 // |name_buffer|, |type|, and data (the first |data_size| bytes in |data|). 63 // |name_buffer|, |type|, and data (the first |data_size| bytes in |data|).
29 void Initialize(const wchar_t* name_buffer, DWORD name_size, 64 void Initialize(const wchar_t* name_buffer, DWORD name_size,
30 DWORD type, const uint8* data, DWORD data_size); 65 DWORD type, const uint8* data, DWORD data_size);
31 66
32 // The possibly empty name of this value. 67 // The possibly empty name of this value.
(...skipping 14 matching lines...) Expand all
47 82
48 private: 83 private:
49 // This value's name, or the empty string if this is the default (unnamed) 84 // This value's name, or the empty string if this is the default (unnamed)
50 // value. 85 // value.
51 std::wstring name_; 86 std::wstring name_;
52 // This value's data. 87 // This value's data.
53 std::vector<uint8> data_; 88 std::vector<uint8> data_;
54 // This value's type (e.g., REG_DWORD, REG_SZ, REG_QWORD, etc). 89 // This value's type (e.g., REG_DWORD, REG_SZ, REG_QWORD, etc).
55 DWORD type_; 90 DWORD type_;
56 91
57 // Copy constructible and assignable for use in STL containers. 92 DISALLOW_COPY_AND_ASSIGN(ValueData);
58 }; 93 };
59 94
60 } // namespace 95 RegistryKeyBackup::KeyData::ValueData::ValueData()
61 96 : type_(REG_NONE) {
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 // Copy constructible and assignable for use in STL containers.
87 };
88
89 ValueData::ValueData() : type_(REG_NONE) {
90 } 97 }
91 98
92 ValueData::~ValueData() { 99 RegistryKeyBackup::KeyData::ValueData::~ValueData()
100 {
93 } 101 }
94 102
95 void ValueData::Initialize( 103 void RegistryKeyBackup::KeyData::ValueData::Initialize(
96 const wchar_t* name_buffer, 104 const wchar_t* name_buffer,
97 DWORD name_size, 105 DWORD name_size,
98 DWORD type, 106 DWORD type,
99 const uint8* data, 107 const uint8* data,
100 DWORD data_size) { 108 DWORD data_size) {
101 name_.assign(name_buffer, name_size); 109 name_.assign(name_buffer, name_size);
102 type_ = type; 110 type_ = type;
103 data_.assign(data, data + data_size); 111 data_.assign(data, data + data_size);
104 } 112 }
105 113
106 RegistryKeyBackup::KeyData::KeyData() { 114 RegistryKeyBackup::KeyData::KeyData()
115 : num_values_(0),
116 num_subkeys_(0) {
107 } 117 }
108 118
109 RegistryKeyBackup::KeyData::~KeyData() { 119 RegistryKeyBackup::KeyData::~KeyData()
120 {
110 } 121 }
111 122
112 bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { 123 bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) {
113 std::vector<ValueData> values; 124 scoped_array<ValueData> values;
114 std::map<std::wstring, KeyData> subkeys; 125 scoped_array<std::wstring> subkey_names;
126 scoped_array<KeyData> subkeys;
115 127
116 DWORD num_subkeys = 0; 128 DWORD num_subkeys = 0;
117 DWORD max_subkey_name_len = 0; 129 DWORD max_subkey_name_len = 0;
118 DWORD num_values = 0; 130 DWORD num_values = 0;
119 DWORD max_value_name_len = 0; 131 DWORD max_value_name_len = 0;
120 DWORD max_value_len = 0; 132 DWORD max_value_len = 0;
121 LONG result = RegQueryInfoKey(key.Handle(), NULL, NULL, NULL, 133 LONG result = RegQueryInfoKey(key.Handle(), NULL, NULL, NULL,
122 &num_subkeys, &max_subkey_name_len, NULL, 134 &num_subkeys, &max_subkey_name_len, NULL,
123 &num_values, &max_value_name_len, 135 &num_values, &max_value_name_len,
124 &max_value_len, NULL, NULL); 136 &max_value_len, NULL, NULL);
125 if (result != ERROR_SUCCESS) { 137 if (result != ERROR_SUCCESS) {
126 LOG(ERROR) << "Failed getting info of key to backup, result: " << result; 138 LOG(ERROR) << "Failed getting info of key to backup, result: " << result;
127 return false; 139 return false;
128 } 140 }
141 if (max_subkey_name_len >= std::numeric_limits<DWORD>::max() - 1 ||
142 max_value_name_len >= std::numeric_limits<DWORD>::max() - 1) {
143 LOG(ERROR)
144 << "Failed backing up key; subkeys and/or names are out of range.";
145 return false;
146 }
129 DWORD max_name_len = std::max(max_subkey_name_len, max_value_name_len) + 1; 147 DWORD max_name_len = std::max(max_subkey_name_len, max_value_name_len) + 1;
130 std::vector<wchar_t> name_buffer(max_name_len); 148 scoped_array<wchar_t> name_buffer(new wchar_t[max_name_len]);
131 149
132 // Backup the values. 150 // Backup the values.
133 if (num_values != 0) { 151 if (num_values != 0) {
134 values.reserve(num_values); 152 values.reset(new ValueData[num_values]);
135 std::vector<uint8> value_buffer(max_value_len != 0 ? max_value_len : 1); 153 scoped_array<uint8> value_buffer(new uint8[max_value_len]);
136 DWORD name_size = 0; 154 DWORD name_size = 0;
137 DWORD value_type = REG_NONE; 155 DWORD value_type = REG_NONE;
138 DWORD value_size = 0; 156 DWORD value_size = 0;
139 157
140 for (DWORD i = 0; i < num_values; ) { 158 for (DWORD i = 0; i < num_values; ) {
141 name_size = name_buffer.size(); 159 name_size = max_name_len;
142 value_size = value_buffer.size(); 160 value_size = max_value_len;
143 result = RegEnumValue(key.Handle(), i, &name_buffer[0], &name_size, 161 result = RegEnumValue(key.Handle(), i, name_buffer.get(), &name_size,
144 NULL, &value_type, &value_buffer[0], &value_size); 162 NULL, &value_type, value_buffer.get(), &value_size);
145 switch (result) { 163 switch (result) {
146 case ERROR_NO_MORE_ITEMS: 164 case ERROR_NO_MORE_ITEMS:
147 num_values = i; 165 num_values = i;
148 break; 166 break;
149 case ERROR_SUCCESS: 167 case ERROR_SUCCESS:
150 values.push_back(ValueData()); 168 values[i].Initialize(name_buffer.get(), name_size, value_type,
151 values.back().Initialize(&name_buffer[0], name_size, value_type, 169 value_buffer.get(), value_size);
152 &value_buffer[0], value_size);
153 ++i; 170 ++i;
154 break; 171 break;
155 case ERROR_MORE_DATA: 172 case ERROR_MORE_DATA:
156 if (value_size > value_buffer.size()) 173 if (value_size > max_value_len) {
157 value_buffer.resize(value_size); 174 max_value_len = value_size;
158 // |name_size| does not include space for the terminating NULL. 175 value_buffer.reset(); // Release to heap before new allocation.
159 if (name_size + 1 > name_buffer.size()) 176 value_buffer.reset(new uint8[max_value_len]);
160 name_buffer.resize(name_size + 1); 177 } else {
178 DCHECK_LT(max_name_len - 1, name_size);
179 if (name_size >= std::numeric_limits<DWORD>::max() - 1) {
180 LOG(ERROR) << "Failed backing up key; value name out of range.";
181 return false;
182 }
183 max_name_len = name_size + 1;
184 name_buffer.reset(); // Release to heap before new allocation.
185 name_buffer.reset(new wchar_t[max_name_len]);
186 }
161 break; 187 break;
162 default: 188 default:
163 LOG(ERROR) << "Failed backing up value " << i << ", result: " 189 LOG(ERROR) << "Failed backing up value " << i << ", result: "
164 << result; 190 << result;
165 return false; 191 return false;
166 } 192 }
167 } 193 }
168 DLOG_IF(WARNING, RegEnumValue(key.Handle(), num_values, &name_buffer[0], 194 DLOG_IF(WARNING, RegEnumValue(key.Handle(), num_values, name_buffer.get(),
169 &name_size, NULL, &value_type, NULL, 195 &name_size, NULL, &value_type, NULL,
170 NULL) != ERROR_NO_MORE_ITEMS) 196 NULL) != ERROR_NO_MORE_ITEMS)
171 << "Concurrent modifications to registry key during backup operation."; 197 << "Concurrent modifications to registry key during backup operation.";
172 } 198 }
173 199
174 // Backup the subkeys. 200 // Backup the subkeys.
175 if (num_subkeys != 0) { 201 if (num_subkeys != 0) {
202 subkey_names.reset(new std::wstring[num_subkeys]);
203 subkeys.reset(new KeyData[num_subkeys]);
176 DWORD name_size = 0; 204 DWORD name_size = 0;
177 205
178 // Get the names of them. 206 // Get the names of them.
179 for (DWORD i = 0; i < num_subkeys; ) { 207 for (DWORD i = 0; i < num_subkeys; ) {
180 name_size = name_buffer.size(); 208 name_size = max_name_len;
181 result = RegEnumKeyEx(key.Handle(), i, &name_buffer[0], &name_size, 209 result = RegEnumKeyEx(key.Handle(), i, name_buffer.get(), &name_size,
182 NULL, NULL, NULL, NULL); 210 NULL, NULL, NULL, NULL);
183 switch (result) { 211 switch (result) {
184 case ERROR_NO_MORE_ITEMS: 212 case ERROR_NO_MORE_ITEMS:
185 num_subkeys = i; 213 num_subkeys = i;
186 break; 214 break;
187 case ERROR_SUCCESS: 215 case ERROR_SUCCESS:
188 subkeys.insert(std::make_pair(&name_buffer[0], KeyData())); 216 subkey_names[i].assign(name_buffer.get(), name_size);
189 ++i; 217 ++i;
190 break; 218 break;
191 case ERROR_MORE_DATA: 219 case ERROR_MORE_DATA:
192 name_buffer.resize(name_size + 1); 220 if (name_size >= std::numeric_limits<DWORD>::max() - 1) {
221 LOG(ERROR) << "Failed backing up key; subkey name out of range.";
222 return false;
223 }
224 max_name_len = name_size + 1;
225 name_buffer.reset(new wchar_t[max_name_len]);
193 break; 226 break;
194 default: 227 default:
195 LOG(ERROR) << "Failed getting name of subkey " << i 228 LOG(ERROR) << "Failed getting name of subkey " << i
196 << " for backup, result: " << result; 229 << " for backup, result: " << result;
197 return false; 230 return false;
198 } 231 }
199 } 232 }
200 DLOG_IF(WARNING, 233 DLOG_IF(WARNING,
201 RegEnumKeyEx(key.Handle(), num_subkeys, NULL, &name_size, NULL, 234 RegEnumKeyEx(key.Handle(), num_subkeys, NULL, &name_size, NULL,
202 NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS) 235 NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
203 << "Concurrent modifications to registry key during backup operation."; 236 << "Concurrent modifications to registry key during backup operation.";
204 237
205 // Get their values. 238 // Get their values.
206 RegKey subkey; 239 RegKey subkey;
207 for (std::map<std::wstring, KeyData>::iterator it = subkeys.begin(); 240 for (DWORD i = 0; i < num_subkeys; ++i) {
208 it != subkeys.end(); ++it) { 241 result = subkey.Open(key.Handle(), subkey_names[i].c_str(),
209 result = subkey.Open(key.Handle(), it->first.c_str(), kKeyReadNoNotify); 242 kKeyReadNoNotify);
210 if (result != ERROR_SUCCESS) { 243 if (result != ERROR_SUCCESS) {
211 LOG(ERROR) << "Failed opening subkey \"" << it->first 244 LOG(ERROR) << "Failed opening subkey \"" << subkey_names[i]
212 << "\" for backup, result: " << result; 245 << "\" for backup, result: " << result;
213 return false; 246 return false;
214 } 247 }
215 if (!it->second.Initialize(subkey)) { 248 if (!subkeys[i].Initialize(subkey)) {
216 LOG(ERROR) << "Failed backing up subkey \"" << it->first << "\""; 249 LOG(ERROR) << "Failed backing up subkey \"" << subkey_names[i] << "\"";
217 return false; 250 return false;
218 } 251 }
219 } 252 }
220 } 253 }
221 254
222 values_.swap(values); 255 values_.swap(values);
256 subkey_names_.swap(subkey_names);
223 subkeys_.swap(subkeys); 257 subkeys_.swap(subkeys);
258 num_values_ = num_values;
259 num_subkeys_ = num_subkeys;
224 260
225 return true; 261 return true;
226 } 262 }
227 263
228 bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const { 264 bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const {
229 DCHECK(key); 265 DCHECK(key);
230 266
231 LONG result = ERROR_SUCCESS; 267 LONG result = ERROR_SUCCESS;
232 268
233 // Write the values. 269 // Write the values.
234 for (std::vector<ValueData>::const_iterator it = values_.begin(); 270 for (DWORD i = 0; i < num_values_; ++i) {
235 it != values_.end(); ++it) { 271 const ValueData& value = values_[i];
236 const ValueData& value = *it;
237 result = RegSetValueEx(key->Handle(), value.name(), 0, value.type(), 272 result = RegSetValueEx(key->Handle(), value.name(), 0, value.type(),
238 value.data(), value.data_len()); 273 value.data(), value.data_len());
239 if (result != ERROR_SUCCESS) { 274 if (result != ERROR_SUCCESS) {
240 LOG(ERROR) << "Failed writing value \"" << value.name_str() 275 LOG(ERROR) << "Failed writing value \"" << value.name_str()
241 << "\", result: " << result; 276 << "\", result: " << result;
242 return false; 277 return false;
243 } 278 }
244 } 279 }
245 280
246 // Write the subkeys. 281 // Write the subkeys.
247 RegKey subkey; 282 RegKey subkey;
248 for (std::map<std::wstring, KeyData>::const_iterator it = subkeys_.begin(); 283 for (DWORD i = 0; i < num_subkeys_; ++i) {
249 it != subkeys_.end(); ++it) { 284 const std::wstring& name = subkey_names_[i];
250 const std::wstring& name = it->first;
251 285
252 result = subkey.Create(key->Handle(), name.c_str(), KEY_WRITE); 286 result = subkey.Create(key->Handle(), name.c_str(), KEY_WRITE);
253 if (result != ERROR_SUCCESS) { 287 if (result != ERROR_SUCCESS) {
254 LOG(ERROR) << "Failed creating subkey \"" << name << "\", result: " 288 LOG(ERROR) << "Failed creating subkey \"" << name << "\", result: "
255 << result; 289 << result;
256 return false; 290 return false;
257 } 291 }
258 if (!it->second.WriteTo(&subkey)) { 292 if (!subkeys_[i].WriteTo(&subkey)) {
259 LOG(ERROR) << "Failed writing subkey \"" << name << "\", result: " 293 LOG(ERROR) << "Failed writing subkey \"" << name << "\", result: "
260 << result; 294 << result;
261 return false; 295 return false;
262 } 296 }
263 } 297 }
264 298
265 return true; 299 return true;
266 } 300 }
267 301
268 RegistryKeyBackup::RegistryKeyBackup() { 302 RegistryKeyBackup::RegistryKeyBackup() {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 } else { 343 } else {
310 success = key_data_->WriteTo(&dest_key); 344 success = key_data_->WriteTo(&dest_key);
311 LOG_IF(ERROR, !success) << "Failed to write key data."; 345 LOG_IF(ERROR, !success) << "Failed to write key data.";
312 } 346 }
313 } else { 347 } else {
314 success = true; 348 success = true;
315 } 349 }
316 350
317 return success; 351 return success;
318 } 352 }
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