Chromium Code Reviews| Index: chrome/installer/util/registry_key_backup.cc |
| diff --git a/chrome/installer/util/registry_key_backup.cc b/chrome/installer/util/registry_key_backup.cc |
| index e3494614250aca9343994711739b7db9c78472c4..e10cb209ac3d25490cc8a5aa864e9148daa754e0 100644 |
| --- a/chrome/installer/util/registry_key_backup.cc |
| +++ b/chrome/installer/util/registry_key_backup.cc |
| @@ -5,7 +5,8 @@ |
| #include "chrome/installer/util/registry_key_backup.h" |
| #include <algorithm> |
| -#include <limits> |
| +#include <map> |
| +#include <utility> |
| #include <vector> |
| #include "base/logging.h" |
| @@ -14,47 +15,11 @@ |
| using base::win::RegKey; |
| namespace { |
| -const REGSAM kKeyReadNoNotify = (KEY_READ) & ~(KEY_NOTIFY); |
| -} // namespace |
| - |
| -// A container for a registry key, its values, and its subkeys. |
| -class RegistryKeyBackup::KeyData { |
| - public: |
| - KeyData(); |
| - ~KeyData(); |
| - |
| - // Initializes this object by reading the values and subkeys of |key|. |
| - // Security descriptors are not backed up. Returns true if the operation was |
| - // successful; false otherwise, in which case the state of this object is not |
| - // modified. |
| - bool Initialize(const RegKey& key); |
| - // Writes the contents of this object to |key|, which must have been opened |
| - // with at least REG_SET_VALUE and KEY_CREATE_SUB_KEY access rights. Returns |
| - // true if the operation was successful; false otherwise, in which case the |
| - // contents of |key| may have been modified. |
| - bool WriteTo(RegKey* key) const; |
| - |
| - private: |
| - class ValueData; |
| - |
| - // The values of this key. |
| - scoped_array<ValueData> values_; |
| - // The names of this key's sub-keys (the data for subkey_names_[i] is in |
| - // subkeys_[i]). |
| - scoped_array<std::wstring> subkey_names_; |
| - // The key data of this key's sub-keys. |
| - scoped_array<KeyData> subkeys_; |
| - // The number of values for this key. |
| - DWORD num_values_; |
| - // The number of subkeys for this key. |
| - DWORD num_subkeys_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(KeyData); |
| -}; |
| +const REGSAM kKeyReadNoNotify = (KEY_READ) & ~(KEY_NOTIFY); |
| // A container for a registry value. |
| -class RegistryKeyBackup::KeyData::ValueData { |
| +class ValueData { |
| public: |
| ValueData(); |
| ~ValueData(); |
| @@ -89,18 +54,45 @@ class RegistryKeyBackup::KeyData::ValueData { |
| // This value's type (e.g., REG_DWORD, REG_SZ, REG_QWORD, etc). |
| DWORD type_; |
| - DISALLOW_COPY_AND_ASSIGN(ValueData); |
| + // Copy constructible and assignable for use in STL containers. |
| +}; |
| + |
| +} // namespace |
| + |
| +// A container for a registry key, its values, and its subkeys. |
| +class RegistryKeyBackup::KeyData { |
| + public: |
| + KeyData(); |
| + ~KeyData(); |
| + |
| + // Initializes this object by reading the values and subkeys of |key|. |
| + // Security descriptors are not backed up. Returns true if the operation was |
| + // successful; false otherwise, in which case the state of this object is not |
| + // modified. |
| + bool Initialize(const RegKey& key); |
| + |
| + // Writes the contents of this object to |key|, which must have been opened |
| + // with at least REG_SET_VALUE and KEY_CREATE_SUB_KEY access rights. Returns |
| + // true if the operation was successful; false otherwise, in which case the |
| + // contents of |key| may have been modified. |
| + bool WriteTo(RegKey* key) const; |
| + |
| + private: |
| + // The values of this key. |
| + std::vector<ValueData> values_; |
| + // Map of subkey names to the corresponding KeyData. |
| + std::map<std::wstring, KeyData> subkeys_; |
| + |
| + // Copy constructible and assignable for use in STL containers. |
| }; |
| -RegistryKeyBackup::KeyData::ValueData::ValueData() |
| - : type_(REG_NONE) { |
| +ValueData::ValueData() : type_(REG_NONE) { |
| } |
| -RegistryKeyBackup::KeyData::ValueData::~ValueData() |
| -{ |
| +ValueData::~ValueData() { |
| } |
| -void RegistryKeyBackup::KeyData::ValueData::Initialize( |
| +void ValueData::Initialize( |
| const wchar_t* name_buffer, |
| DWORD name_size, |
| DWORD type, |
| @@ -111,19 +103,15 @@ void RegistryKeyBackup::KeyData::ValueData::Initialize( |
| data_.assign(data, data + data_size); |
| } |
| -RegistryKeyBackup::KeyData::KeyData() |
| - : num_values_(0), |
| - num_subkeys_(0) { |
| +RegistryKeyBackup::KeyData::KeyData() { |
| } |
| -RegistryKeyBackup::KeyData::~KeyData() |
| -{ |
| +RegistryKeyBackup::KeyData::~KeyData() { |
| } |
| bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { |
| - scoped_array<ValueData> values; |
| - scoped_array<std::wstring> subkey_names; |
| - scoped_array<KeyData> subkeys; |
| + std::vector<ValueData> values; |
| + std::map<std::wstring, KeyData> subkeys; |
| DWORD num_subkeys = 0; |
| DWORD max_subkey_name_len = 0; |
| @@ -138,51 +126,39 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { |
| LOG(ERROR) << "Failed getting info of key to backup, result: " << result; |
| return false; |
| } |
| - if (max_subkey_name_len >= std::numeric_limits<DWORD>::max() - 1 || |
| - max_value_name_len >= std::numeric_limits<DWORD>::max() - 1) { |
| - LOG(ERROR) |
| - << "Failed backing up key; subkeys and/or names are out of range."; |
| - return false; |
| - } |
| DWORD max_name_len = std::max(max_subkey_name_len, max_value_name_len) + 1; |
| - scoped_array<wchar_t> name_buffer(new wchar_t[max_name_len]); |
| + std::vector<wchar_t> name_buffer(max_name_len); |
| // Backup the values. |
| if (num_values != 0) { |
| - values.reset(new ValueData[num_values]); |
| - scoped_array<uint8> value_buffer(new uint8[max_value_len]); |
| + values.reserve(num_values); |
| + std::vector<uint8> value_buffer(max_value_len != 0 ? max_value_len : 1); |
| DWORD name_size = 0; |
| DWORD value_type = REG_NONE; |
| DWORD value_size = 0; |
| for (DWORD i = 0; i < num_values; ) { |
| - name_size = max_name_len; |
| - value_size = max_value_len; |
| - result = RegEnumValue(key.Handle(), i, name_buffer.get(), &name_size, |
| - NULL, &value_type, value_buffer.get(), &value_size); |
| + name_size = name_buffer.size(); |
| + value_size = value_buffer.size(); |
| + result = RegEnumValue(key.Handle(), i, &name_buffer[0], &name_size, |
| + NULL, &value_type, &value_buffer[0], &value_size); |
| switch (result) { |
| case ERROR_NO_MORE_ITEMS: |
| num_values = i; |
| break; |
| case ERROR_SUCCESS: |
| - values[i].Initialize(name_buffer.get(), name_size, value_type, |
| - value_buffer.get(), value_size); |
| + values.push_back(ValueData()); |
| + values.back().Initialize(&name_buffer[0], name_size, value_type, |
| + &value_buffer[0], value_size); |
| ++i; |
| break; |
| case ERROR_MORE_DATA: |
| - if (value_size > max_value_len) { |
| - max_value_len = value_size; |
| - value_buffer.reset(); // Release to heap before new allocation. |
| - value_buffer.reset(new uint8[max_value_len]); |
| - } else { |
| - DCHECK_LT(max_name_len - 1, name_size); |
| - if (name_size >= std::numeric_limits<DWORD>::max() - 1) { |
| - LOG(ERROR) << "Failed backing up key; value name out of range."; |
| - return false; |
| - } |
| - max_name_len = name_size + 1; |
| - name_buffer.reset(); // Release to heap before new allocation. |
| - name_buffer.reset(new wchar_t[max_name_len]); |
| + if (value_size > value_buffer.size()) { |
|
grt (UTC plus 2)
2013/04/17 18:13:56
nit: no braces
|
| + value_buffer.resize(value_size); |
| + } |
| + // |name_size| does not include space for the terminating NULL. |
| + if (name_size > name_buffer.size() - 1) { |
|
grt (UTC plus 2)
2013/04/17 18:13:56
nit: no braces
|
| + name_buffer.resize(name_size + 1); |
| } |
| break; |
| default: |
| @@ -191,7 +167,7 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { |
| return false; |
| } |
| } |
| - DLOG_IF(WARNING, RegEnumValue(key.Handle(), num_values, name_buffer.get(), |
| + DLOG_IF(WARNING, RegEnumValue(key.Handle(), num_values, &name_buffer[0], |
| &name_size, NULL, &value_type, NULL, |
| NULL) != ERROR_NO_MORE_ITEMS) |
| << "Concurrent modifications to registry key during backup operation."; |
| @@ -199,30 +175,23 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { |
| // Backup the subkeys. |
| if (num_subkeys != 0) { |
| - subkey_names.reset(new std::wstring[num_subkeys]); |
| - subkeys.reset(new KeyData[num_subkeys]); |
| DWORD name_size = 0; |
| // Get the names of them. |
| for (DWORD i = 0; i < num_subkeys; ) { |
| - name_size = max_name_len; |
| - result = RegEnumKeyEx(key.Handle(), i, name_buffer.get(), &name_size, |
| + name_size = name_buffer.size(); |
| + result = RegEnumKeyEx(key.Handle(), i, &name_buffer[0], &name_size, |
| NULL, NULL, NULL, NULL); |
| switch (result) { |
| case ERROR_NO_MORE_ITEMS: |
| num_subkeys = i; |
| break; |
| case ERROR_SUCCESS: |
| - subkey_names[i].assign(name_buffer.get(), name_size); |
| + subkeys.insert(std::make_pair(&name_buffer[0], KeyData())); |
| ++i; |
| break; |
| case ERROR_MORE_DATA: |
| - if (name_size >= std::numeric_limits<DWORD>::max() - 1) { |
| - LOG(ERROR) << "Failed backing up key; subkey name out of range."; |
| - return false; |
| - } |
| - max_name_len = name_size + 1; |
| - name_buffer.reset(new wchar_t[max_name_len]); |
| + name_buffer.resize(name_size + 1); |
| break; |
| default: |
| LOG(ERROR) << "Failed getting name of subkey " << i |
| @@ -237,26 +206,23 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { |
| // Get their values. |
| RegKey subkey; |
| - for (DWORD i = 0; i < num_subkeys; ++i) { |
| - result = subkey.Open(key.Handle(), subkey_names[i].c_str(), |
| - kKeyReadNoNotify); |
| + for (std::map<std::wstring, KeyData>::iterator it = subkeys.begin(); |
| + it != subkeys.end(); ++it) { |
| + result = subkey.Open(key.Handle(), it->first.c_str(), kKeyReadNoNotify); |
| if (result != ERROR_SUCCESS) { |
| - LOG(ERROR) << "Failed opening subkey \"" << subkey_names[i] |
| + LOG(ERROR) << "Failed opening subkey \"" << it->first |
| << "\" for backup, result: " << result; |
| return false; |
| } |
| - if (!subkeys[i].Initialize(subkey)) { |
| - LOG(ERROR) << "Failed backing up subkey \"" << subkey_names[i] << "\""; |
| + if (!it->second.Initialize(subkey)) { |
| + LOG(ERROR) << "Failed backing up subkey \"" << it->first << "\""; |
| return false; |
| } |
| } |
| } |
| values_.swap(values); |
| - subkey_names_.swap(subkey_names); |
| subkeys_.swap(subkeys); |
| - num_values_ = num_values; |
| - num_subkeys_ = num_subkeys; |
| return true; |
| } |
| @@ -267,8 +233,9 @@ bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const { |
| LONG result = ERROR_SUCCESS; |
| // Write the values. |
| - for (DWORD i = 0; i < num_values_; ++i) { |
| - const ValueData& value = values_[i]; |
| + for (std::vector<ValueData>::const_iterator it = values_.begin(); |
| + it != values_.end(); ++it) { |
| + const ValueData& value = *it; |
| result = RegSetValueEx(key->Handle(), value.name(), 0, value.type(), |
| value.data(), value.data_len()); |
| if (result != ERROR_SUCCESS) { |
| @@ -280,8 +247,9 @@ bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const { |
| // Write the subkeys. |
| RegKey subkey; |
| - for (DWORD i = 0; i < num_subkeys_; ++i) { |
| - const std::wstring& name = subkey_names_[i]; |
| + for (std::map<std::wstring, KeyData>::const_iterator it = subkeys_.begin(); |
| + it != subkeys_.end(); ++it) { |
| + const std::wstring& name = it->first; |
| result = subkey.Create(key->Handle(), name.c_str(), KEY_WRITE); |
| if (result != ERROR_SUCCESS) { |
| @@ -289,7 +257,7 @@ bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const { |
| << result; |
| return false; |
| } |
| - if (!subkeys_[i].WriteTo(&subkey)) { |
| + if (!it->second.WriteTo(&subkey)) { |
| LOG(ERROR) << "Failed writing subkey \"" << name << "\", result: " |
| << result; |
| return false; |