Commit a35f783b authored by dcheng@chromium.org's avatar dcheng@chromium.org

Remove scoped_array usage from RegistryKeyBackup.

BUG=171111

Review URL: https://codereview.chromium.org/14265020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194672 0039d316-1c4b-4281-b951-d872f2087c98
parent 7990ad30
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
#include "chrome/installer/util/registry_key_backup.h" #include "chrome/installer/util/registry_key_backup.h"
#include <algorithm> #include <algorithm>
#include <limits> #include <map>
#include <utility>
#include <vector> #include <vector>
#include "base/logging.h" #include "base/logging.h"
...@@ -14,47 +15,11 @@ ...@@ -14,47 +15,11 @@
using base::win::RegKey; using base::win::RegKey;
namespace { 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|. const REGSAM kKeyReadNoNotify = (KEY_READ) & ~(KEY_NOTIFY);
// 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);
};
// A container for a registry value. // A container for a registry value.
class RegistryKeyBackup::KeyData::ValueData { class ValueData {
public: public:
ValueData(); ValueData();
~ValueData(); ~ValueData();
...@@ -89,18 +54,45 @@ class RegistryKeyBackup::KeyData::ValueData { ...@@ -89,18 +54,45 @@ class RegistryKeyBackup::KeyData::ValueData {
// This value's type (e.g., REG_DWORD, REG_SZ, REG_QWORD, etc). // This value's type (e.g., REG_DWORD, REG_SZ, REG_QWORD, etc).
DWORD type_; 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() ValueData::ValueData() : type_(REG_NONE) {
: type_(REG_NONE) {
} }
RegistryKeyBackup::KeyData::ValueData::~ValueData() ValueData::~ValueData() {
{
} }
void RegistryKeyBackup::KeyData::ValueData::Initialize( void ValueData::Initialize(
const wchar_t* name_buffer, const wchar_t* name_buffer,
DWORD name_size, DWORD name_size,
DWORD type, DWORD type,
...@@ -111,19 +103,15 @@ void RegistryKeyBackup::KeyData::ValueData::Initialize( ...@@ -111,19 +103,15 @@ void RegistryKeyBackup::KeyData::ValueData::Initialize(
data_.assign(data, data + data_size); data_.assign(data, data + data_size);
} }
RegistryKeyBackup::KeyData::KeyData() RegistryKeyBackup::KeyData::KeyData() {
: num_values_(0),
num_subkeys_(0) {
} }
RegistryKeyBackup::KeyData::~KeyData() RegistryKeyBackup::KeyData::~KeyData() {
{
} }
bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) {
scoped_array<ValueData> values; std::vector<ValueData> values;
scoped_array<std::wstring> subkey_names; std::map<std::wstring, KeyData> subkeys;
scoped_array<KeyData> subkeys;
DWORD num_subkeys = 0; DWORD num_subkeys = 0;
DWORD max_subkey_name_len = 0; DWORD max_subkey_name_len = 0;
...@@ -138,52 +126,38 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { ...@@ -138,52 +126,38 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) {
LOG(ERROR) << "Failed getting info of key to backup, result: " << result; LOG(ERROR) << "Failed getting info of key to backup, result: " << result;
return false; 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; 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. // Backup the values.
if (num_values != 0) { if (num_values != 0) {
values.reset(new ValueData[num_values]); values.reserve(num_values);
scoped_array<uint8> value_buffer(new uint8[max_value_len]); std::vector<uint8> value_buffer(max_value_len != 0 ? max_value_len : 1);
DWORD name_size = 0; DWORD name_size = 0;
DWORD value_type = REG_NONE; DWORD value_type = REG_NONE;
DWORD value_size = 0; DWORD value_size = 0;
for (DWORD i = 0; i < num_values; ) { for (DWORD i = 0; i < num_values; ) {
name_size = max_name_len; name_size = static_cast<DWORD>(name_buffer.size());
value_size = max_value_len; value_size = static_cast<DWORD>(value_buffer.size());
result = RegEnumValue(key.Handle(), i, name_buffer.get(), &name_size, result = RegEnumValue(key.Handle(), i, &name_buffer[0], &name_size,
NULL, &value_type, value_buffer.get(), &value_size); NULL, &value_type, &value_buffer[0], &value_size);
switch (result) { switch (result) {
case ERROR_NO_MORE_ITEMS: case ERROR_NO_MORE_ITEMS:
num_values = i; num_values = i;
break; break;
case ERROR_SUCCESS: case ERROR_SUCCESS:
values[i].Initialize(name_buffer.get(), name_size, value_type, values.push_back(ValueData());
value_buffer.get(), value_size); values.back().Initialize(&name_buffer[0], name_size, value_type,
&value_buffer[0], value_size);
++i; ++i;
break; break;
case ERROR_MORE_DATA: case ERROR_MORE_DATA:
if (value_size > max_value_len) { if (value_size > value_buffer.size())
max_value_len = value_size; value_buffer.resize(value_size);
value_buffer.reset(); // Release to heap before new allocation. // |name_size| does not include space for the terminating NULL.
value_buffer.reset(new uint8[max_value_len]); if (name_size + 1 > name_buffer.size())
} else { name_buffer.resize(name_size + 1);
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]);
}
break; break;
default: default:
LOG(ERROR) << "Failed backing up value " << i << ", result: " LOG(ERROR) << "Failed backing up value " << i << ", result: "
...@@ -191,7 +165,7 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { ...@@ -191,7 +165,7 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) {
return false; 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, &name_size, NULL, &value_type, NULL,
NULL) != ERROR_NO_MORE_ITEMS) NULL) != ERROR_NO_MORE_ITEMS)
<< "Concurrent modifications to registry key during backup operation."; << "Concurrent modifications to registry key during backup operation.";
...@@ -199,30 +173,23 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { ...@@ -199,30 +173,23 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) {
// Backup the subkeys. // Backup the subkeys.
if (num_subkeys != 0) { if (num_subkeys != 0) {
subkey_names.reset(new std::wstring[num_subkeys]);
subkeys.reset(new KeyData[num_subkeys]);
DWORD name_size = 0; DWORD name_size = 0;
// Get the names of them. // Get the names of them.
for (DWORD i = 0; i < num_subkeys; ) { for (DWORD i = 0; i < num_subkeys; ) {
name_size = max_name_len; name_size = static_cast<DWORD>(name_buffer.size());
result = RegEnumKeyEx(key.Handle(), i, name_buffer.get(), &name_size, result = RegEnumKeyEx(key.Handle(), i, &name_buffer[0], &name_size,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
switch (result) { switch (result) {
case ERROR_NO_MORE_ITEMS: case ERROR_NO_MORE_ITEMS:
num_subkeys = i; num_subkeys = i;
break; break;
case ERROR_SUCCESS: case ERROR_SUCCESS:
subkey_names[i].assign(name_buffer.get(), name_size); subkeys.insert(std::make_pair(&name_buffer[0], KeyData()));
++i; ++i;
break; break;
case ERROR_MORE_DATA: case ERROR_MORE_DATA:
if (name_size >= std::numeric_limits<DWORD>::max() - 1) { name_buffer.resize(name_size + 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]);
break; break;
default: default:
LOG(ERROR) << "Failed getting name of subkey " << i LOG(ERROR) << "Failed getting name of subkey " << i
...@@ -237,26 +204,23 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) { ...@@ -237,26 +204,23 @@ bool RegistryKeyBackup::KeyData::Initialize(const RegKey& key) {
// Get their values. // Get their values.
RegKey subkey; RegKey subkey;
for (DWORD i = 0; i < num_subkeys; ++i) { for (std::map<std::wstring, KeyData>::iterator it = subkeys.begin();
result = subkey.Open(key.Handle(), subkey_names[i].c_str(), it != subkeys.end(); ++it) {
kKeyReadNoNotify); result = subkey.Open(key.Handle(), it->first.c_str(), kKeyReadNoNotify);
if (result != ERROR_SUCCESS) { if (result != ERROR_SUCCESS) {
LOG(ERROR) << "Failed opening subkey \"" << subkey_names[i] LOG(ERROR) << "Failed opening subkey \"" << it->first
<< "\" for backup, result: " << result; << "\" for backup, result: " << result;
return false; return false;
} }
if (!subkeys[i].Initialize(subkey)) { if (!it->second.Initialize(subkey)) {
LOG(ERROR) << "Failed backing up subkey \"" << subkey_names[i] << "\""; LOG(ERROR) << "Failed backing up subkey \"" << it->first << "\"";
return false; return false;
} }
} }
} }
values_.swap(values); values_.swap(values);
subkey_names_.swap(subkey_names);
subkeys_.swap(subkeys); subkeys_.swap(subkeys);
num_values_ = num_values;
num_subkeys_ = num_subkeys;
return true; return true;
} }
...@@ -267,8 +231,9 @@ bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const { ...@@ -267,8 +231,9 @@ bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const {
LONG result = ERROR_SUCCESS; LONG result = ERROR_SUCCESS;
// Write the values. // Write the values.
for (DWORD i = 0; i < num_values_; ++i) { for (std::vector<ValueData>::const_iterator it = values_.begin();
const ValueData& value = values_[i]; it != values_.end(); ++it) {
const ValueData& value = *it;
result = RegSetValueEx(key->Handle(), value.name(), 0, value.type(), result = RegSetValueEx(key->Handle(), value.name(), 0, value.type(),
value.data(), value.data_len()); value.data(), value.data_len());
if (result != ERROR_SUCCESS) { if (result != ERROR_SUCCESS) {
...@@ -280,8 +245,9 @@ bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const { ...@@ -280,8 +245,9 @@ bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const {
// Write the subkeys. // Write the subkeys.
RegKey subkey; RegKey subkey;
for (DWORD i = 0; i < num_subkeys_; ++i) { for (std::map<std::wstring, KeyData>::const_iterator it = subkeys_.begin();
const std::wstring& name = subkey_names_[i]; it != subkeys_.end(); ++it) {
const std::wstring& name = it->first;
result = subkey.Create(key->Handle(), name.c_str(), KEY_WRITE); result = subkey.Create(key->Handle(), name.c_str(), KEY_WRITE);
if (result != ERROR_SUCCESS) { if (result != ERROR_SUCCESS) {
...@@ -289,7 +255,7 @@ bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const { ...@@ -289,7 +255,7 @@ bool RegistryKeyBackup::KeyData::WriteTo(RegKey* key) const {
<< result; << result;
return false; return false;
} }
if (!subkeys_[i].WriteTo(&subkey)) { if (!it->second.WriteTo(&subkey)) {
LOG(ERROR) << "Failed writing subkey \"" << name << "\", result: " LOG(ERROR) << "Failed writing subkey \"" << name << "\", result: "
<< result; << result;
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment