Index: chrome/installer/util/copy_reg_key_work_item.cc |
diff --git a/chrome/installer/util/copy_reg_key_work_item.cc b/chrome/installer/util/copy_reg_key_work_item.cc |
index a0d2b1fefe5c07a816be23124011d3614f11d319..71f6fd052507756661aea0e8f3b2c5179d3c2748 100644 |
--- a/chrome/installer/util/copy_reg_key_work_item.cc |
+++ b/chrome/installer/util/copy_reg_key_work_item.cc |
@@ -16,21 +16,33 @@ CopyRegKeyWorkItem::~CopyRegKeyWorkItem() { |
CopyRegKeyWorkItem::CopyRegKeyWorkItem(HKEY predefined_root, |
const std::wstring& source_key_path, |
- const std::wstring& dest_key_path) |
+ const std::wstring& dest_key_path, |
+ CopyOverWriteOption overwrite_option) |
: predefined_root_(predefined_root), |
source_key_path_(source_key_path), |
- dest_key_path_(dest_key_path) { |
+ dest_key_path_(dest_key_path), |
+ overwrite_option_(overwrite_option), |
+ cleared_destination_(false) { |
DCHECK(predefined_root); |
// It's a safe bet that we don't want to copy or overwrite one of the root |
// trees. |
DCHECK(!source_key_path.empty()); |
DCHECK(!dest_key_path.empty()); |
+ DCHECK(overwrite_option == ALWAYS || overwrite_option == IF_NOT_PRESENT); |
} |
bool CopyRegKeyWorkItem::Do() { |
if (source_key_path_.empty() || dest_key_path_.empty()) |
return false; |
+ // Leave immediately if we're not supposed to overwrite an existing key and |
+ // one is there. |
+ if (overwrite_option_ == IF_NOT_PRESENT && |
+ RegKey(predefined_root_, dest_key_path_.c_str(), |
+ KEY_QUERY_VALUE).Valid()) { |
+ return true; |
+ } |
+ |
RegistryKeyBackup backup; |
RegKey dest_key; |
@@ -48,6 +60,7 @@ bool CopyRegKeyWorkItem::Do() { |
LOG(ERROR) << "Failed to delete key at " << dest_key_path_ << ", result: " |
<< result; |
} else { |
+ cleared_destination_ = true; |
// We've just modified the registry, so remember any backup we may have |
// made so that Rollback can take us back where we started. |
backup_.swap(backup); |
@@ -85,16 +98,18 @@ void CopyRegKeyWorkItem::Rollback() { |
if (ignore_failure_) |
return; |
- // Delete anything in the key before restoring the backup in case someone else |
- // put new data in the key after Do(). |
- LONG result = SHDeleteKey(predefined_root_, dest_key_path_.c_str()); |
- if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { |
- LOG(ERROR) << "Failed to delete key at " << dest_key_path_ |
- << " in rollback, result: " << result; |
- } |
+ if (cleared_destination_) { |
+ // Delete anything in the key before restoring the backup in case new data |
+ // was written after Do(). |
+ LONG result = SHDeleteKey(predefined_root_, dest_key_path_.c_str()); |
+ if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { |
+ LOG(ERROR) << "Failed to delete key at " << dest_key_path_ |
+ << " in rollback, result: " << result; |
+ } |
- // Restore the old contents. The restoration takes on its default security |
- // attributes; any custom attributes are lost. |
- if (!backup_.WriteTo(predefined_root_, dest_key_path_.c_str())) |
- LOG(ERROR) << "Failed to restore key in rollback."; |
+ // Restore the old contents. The restoration takes on its default security |
+ // attributes; any custom attributes are lost. |
+ if (!backup_.WriteTo(predefined_root_, dest_key_path_.c_str())) |
+ LOG(ERROR) << "Failed to restore key in rollback."; |
+ } |
} |