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/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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |