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/copy_reg_key_work_item.h" | 5 #include "chrome/installer/util/copy_reg_key_work_item.h" |
6 | 6 |
7 #include <shlwapi.h> | 7 #include <shlwapi.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/win/registry.h" | 10 #include "base/win/registry.h" |
11 | 11 |
12 using base::win::RegKey; | 12 using base::win::RegKey; |
13 | 13 |
14 CopyRegKeyWorkItem::~CopyRegKeyWorkItem() { | 14 CopyRegKeyWorkItem::~CopyRegKeyWorkItem() { |
15 } | 15 } |
16 | 16 |
17 CopyRegKeyWorkItem::CopyRegKeyWorkItem(HKEY predefined_root, | 17 CopyRegKeyWorkItem::CopyRegKeyWorkItem(HKEY predefined_root, |
18 const std::wstring& source_key_path, | 18 const std::wstring& source_key_path, |
19 const std::wstring& dest_key_path) | 19 const std::wstring& dest_key_path, |
| 20 CopyOverWriteOption overwrite_option) |
20 : predefined_root_(predefined_root), | 21 : predefined_root_(predefined_root), |
21 source_key_path_(source_key_path), | 22 source_key_path_(source_key_path), |
22 dest_key_path_(dest_key_path) { | 23 dest_key_path_(dest_key_path), |
| 24 overwrite_option_(overwrite_option), |
| 25 cleared_destination_(false) { |
23 DCHECK(predefined_root); | 26 DCHECK(predefined_root); |
24 // It's a safe bet that we don't want to copy or overwrite one of the root | 27 // It's a safe bet that we don't want to copy or overwrite one of the root |
25 // trees. | 28 // trees. |
26 DCHECK(!source_key_path.empty()); | 29 DCHECK(!source_key_path.empty()); |
27 DCHECK(!dest_key_path.empty()); | 30 DCHECK(!dest_key_path.empty()); |
| 31 DCHECK(overwrite_option == ALWAYS || overwrite_option == IF_NOT_PRESENT); |
28 } | 32 } |
29 | 33 |
30 bool CopyRegKeyWorkItem::Do() { | 34 bool CopyRegKeyWorkItem::Do() { |
31 if (source_key_path_.empty() || dest_key_path_.empty()) | 35 if (source_key_path_.empty() || dest_key_path_.empty()) |
32 return false; | 36 return false; |
33 | 37 |
| 38 // Leave immediately if we're not supposed to overwrite an existing key and |
| 39 // one is there. |
| 40 if (overwrite_option_ == IF_NOT_PRESENT && |
| 41 RegKey(predefined_root_, dest_key_path_.c_str(), |
| 42 KEY_QUERY_VALUE).Valid()) { |
| 43 return true; |
| 44 } |
| 45 |
34 RegistryKeyBackup backup; | 46 RegistryKeyBackup backup; |
35 RegKey dest_key; | 47 RegKey dest_key; |
36 | 48 |
37 // Only try to make a backup if we're not configured to ignore failures. | 49 // Only try to make a backup if we're not configured to ignore failures. |
38 if (!ignore_failure_) { | 50 if (!ignore_failure_) { |
39 if (!backup.Initialize(predefined_root_, dest_key_path_.c_str())) { | 51 if (!backup.Initialize(predefined_root_, dest_key_path_.c_str())) { |
40 LOG(ERROR) << "Failed to backup destination for registry key copy."; | 52 LOG(ERROR) << "Failed to backup destination for registry key copy."; |
41 return false; | 53 return false; |
42 } | 54 } |
43 } | 55 } |
44 | 56 |
45 // Delete the destination before attempting to copy. | 57 // Delete the destination before attempting to copy. |
46 LONG result = SHDeleteKey(predefined_root_, dest_key_path_.c_str()); | 58 LONG result = SHDeleteKey(predefined_root_, dest_key_path_.c_str()); |
47 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { | 59 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { |
48 LOG(ERROR) << "Failed to delete key at " << dest_key_path_ << ", result: " | 60 LOG(ERROR) << "Failed to delete key at " << dest_key_path_ << ", result: " |
49 << result; | 61 << result; |
50 } else { | 62 } else { |
| 63 cleared_destination_ = true; |
51 // We've just modified the registry, so remember any backup we may have | 64 // We've just modified the registry, so remember any backup we may have |
52 // made so that Rollback can take us back where we started. | 65 // made so that Rollback can take us back where we started. |
53 backup_.swap(backup); | 66 backup_.swap(backup); |
54 // Make the copy. | 67 // Make the copy. |
55 result = dest_key.Create(predefined_root_, dest_key_path_.c_str(), | 68 result = dest_key.Create(predefined_root_, dest_key_path_.c_str(), |
56 KEY_WRITE); | 69 KEY_WRITE); |
57 if (result != ERROR_SUCCESS) { | 70 if (result != ERROR_SUCCESS) { |
58 LOG(ERROR) << "Failed to open destination key at " << dest_key_path_ | 71 LOG(ERROR) << "Failed to open destination key at " << dest_key_path_ |
59 << ", result: " << result; | 72 << ", result: " << result; |
60 } else { | 73 } else { |
(...skipping 17 matching lines...) Expand all Loading... |
78 } | 91 } |
79 } | 92 } |
80 | 93 |
81 return ignore_failure_ ? true : (result == ERROR_SUCCESS); | 94 return ignore_failure_ ? true : (result == ERROR_SUCCESS); |
82 } | 95 } |
83 | 96 |
84 void CopyRegKeyWorkItem::Rollback() { | 97 void CopyRegKeyWorkItem::Rollback() { |
85 if (ignore_failure_) | 98 if (ignore_failure_) |
86 return; | 99 return; |
87 | 100 |
88 // Delete anything in the key before restoring the backup in case someone else | 101 if (cleared_destination_) { |
89 // put new data in the key after Do(). | 102 // Delete anything in the key before restoring the backup in case new data |
90 LONG result = SHDeleteKey(predefined_root_, dest_key_path_.c_str()); | 103 // was written after Do(). |
91 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { | 104 LONG result = SHDeleteKey(predefined_root_, dest_key_path_.c_str()); |
92 LOG(ERROR) << "Failed to delete key at " << dest_key_path_ | 105 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { |
93 << " in rollback, result: " << result; | 106 LOG(ERROR) << "Failed to delete key at " << dest_key_path_ |
| 107 << " in rollback, result: " << result; |
| 108 } |
| 109 |
| 110 // Restore the old contents. The restoration takes on its default security |
| 111 // attributes; any custom attributes are lost. |
| 112 if (!backup_.WriteTo(predefined_root_, dest_key_path_.c_str())) |
| 113 LOG(ERROR) << "Failed to restore key in rollback."; |
94 } | 114 } |
95 | |
96 // Restore the old contents. The restoration takes on its default security | |
97 // attributes; any custom attributes are lost. | |
98 if (!backup_.WriteTo(predefined_root_, dest_key_path_.c_str())) | |
99 LOG(ERROR) << "Failed to restore key in rollback."; | |
100 } | 115 } |
OLD | NEW |