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/delete_reg_value_work_item.h" | 5 #include "chrome/installer/util/delete_reg_value_work_item.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/string_util.h" | |
8 #include "base/win/registry.h" | 9 #include "base/win/registry.h" |
9 #include "chrome/installer/util/logging_installer.h" | 10 #include "chrome/installer/util/logging_installer.h" |
10 | 11 |
11 using base::win::RegKey; | 12 using base::win::RegKey; |
12 | 13 |
13 DeleteRegValueWorkItem::DeleteRegValueWorkItem(HKEY predefined_root, | 14 DeleteRegValueWorkItem::DeleteRegValueWorkItem(HKEY predefined_root, |
14 const std::wstring& key_path, | 15 const std::wstring& key_path, |
15 const std::wstring& value_name, | 16 const std::wstring& value_name) |
16 DWORD type) | |
17 : predefined_root_(predefined_root), | 17 : predefined_root_(predefined_root), |
18 key_path_(key_path), | 18 key_path_(key_path), |
19 value_name_(value_name), | 19 value_name_(value_name), |
20 type_(type), | 20 previous_type_(0), |
21 status_(DELETE_VALUE), | 21 status_(DELETE_VALUE) { |
22 old_dw_(0), | |
23 old_qword_(0) { | |
24 DCHECK(type_ == REG_QWORD || type_ == REG_DWORD || type == REG_SZ); | |
25 } | 22 } |
26 | 23 |
27 DeleteRegValueWorkItem::~DeleteRegValueWorkItem() { | 24 DeleteRegValueWorkItem::~DeleteRegValueWorkItem() { |
28 } | 25 } |
29 | 26 |
30 bool DeleteRegValueWorkItem::Do() { | 27 bool DeleteRegValueWorkItem::Do() { |
31 if (status_ != DELETE_VALUE) { | 28 if (status_ != DELETE_VALUE) { |
32 // we already did something. | 29 // we already did something. |
33 LOG(ERROR) << "multiple calls to Do()"; | 30 LOG(ERROR) << "multiple calls to Do()"; |
34 return false; | 31 return false; |
35 } | 32 } |
36 | 33 |
37 status_ = VALUE_UNCHANGED; | 34 status_ = VALUE_UNCHANGED; |
38 | 35 |
39 // A big flaw in the RegKey implementation is that all error information | 36 RegKey key; |
40 // (besides success/failure) is lost in the translation from LSTATUS to bool. | 37 DWORD type = 0; |
41 // So, we resort to direct API calls here. :-/ | 38 DWORD size = 0; |
42 HKEY raw_key = NULL; | 39 LONG result = key.Open(predefined_root_, key_path_.c_str(), KEY_READ); |
43 LSTATUS err = RegOpenKeyEx(predefined_root_, key_path_.c_str(), 0, | 40 if (result == ERROR_SUCCESS) |
44 KEY_READ, &raw_key); | 41 result = key.ReadValue(value_name_.c_str(), NULL, &size, &type); |
45 if (err != ERROR_SUCCESS) { | 42 |
46 if (err == ERROR_FILE_NOT_FOUND) { | 43 if (result == ERROR_FILE_NOT_FOUND) { |
47 LOG(INFO) << "(delete value) can not open " << key_path_; | 44 LOG(INFO) << "(delete value) Key: " << key_path_ << " or Value: " |
48 status_ = VALUE_NOT_FOUND; | 45 << value_name_ << " does not exist."; |
49 return true; | 46 status_ = VALUE_NOT_FOUND; |
50 } | 47 return true; |
51 } else { | |
52 ::RegCloseKey(raw_key); | |
53 } | 48 } |
54 | 49 |
55 RegKey key; | 50 if (result == ERROR_MORE_DATA) { |
grt (UTC plus 2)
2011/01/14 15:53:43
Have you verified this? According to MSDN, you sh
amit
2011/01/15 01:28:11
Done.
| |
56 bool result = false; | 51 result = key.ReadValue(value_name_.c_str(), |
57 | 52 WriteInto(&previous_value_, size), &size, |
58 // Used in REG_QWORD case only | 53 &previous_type_); |
59 DWORD value_size = sizeof(old_qword_); | 54 VLOG_IF(1, result != ERROR_SUCCESS) << "Failed to save original value. " |
60 DWORD type = 0; | 55 "Error: " << result; |
61 | |
62 if (!key.Open(predefined_root_, key_path_.c_str(), KEY_READ | KEY_WRITE)) { | |
63 LOG(ERROR) << "can not open " << key_path_; | |
64 } else if (!key.ValueExists(value_name_.c_str())) { | |
65 status_ = VALUE_NOT_FOUND; | |
66 result = true; | |
67 // Read previous value for rollback and delete | |
68 } else if (((type_ == REG_SZ && key.ReadValue(value_name_.c_str(), | |
69 &old_str_)) || | |
70 (type_ == REG_DWORD && key.ReadValueDW(value_name_.c_str(), | |
71 &old_dw_)) || | |
72 (type_ == REG_QWORD && key.ReadValue(value_name_.c_str(), | |
73 &old_qword_, | |
74 &value_size, &type) && | |
75 type == REG_QWORD && value_size == sizeof(old_qword_))) && | |
76 (key.DeleteValue(value_name_.c_str()))) { | |
77 status_ = VALUE_DELETED; | |
78 result = true; | |
79 } else { | |
80 LOG(ERROR) << "failed to read/delete value " << value_name_; | |
81 } | 56 } |
82 | 57 |
83 return result; | 58 result = key.DeleteValue(value_name_.c_str()); |
59 if (result != ERROR_SUCCESS) { | |
60 VLOG(1) << "Failed to delete value " << value_name_ << " error: " << result; | |
61 return false; | |
62 } | |
63 | |
64 status_ = VALUE_DELETED; | |
65 return true; | |
84 } | 66 } |
85 | 67 |
86 void DeleteRegValueWorkItem::Rollback() { | 68 void DeleteRegValueWorkItem::Rollback() { |
87 if (status_ == DELETE_VALUE || status_ == VALUE_ROLLED_BACK) | 69 if (status_ == DELETE_VALUE || status_ == VALUE_ROLLED_BACK) |
88 return; | 70 return; |
89 if (status_ == VALUE_UNCHANGED || status_ == VALUE_NOT_FOUND) { | 71 if (status_ == VALUE_UNCHANGED || status_ == VALUE_NOT_FOUND) { |
90 status_ = VALUE_ROLLED_BACK; | 72 status_ = VALUE_ROLLED_BACK; |
91 VLOG(1) << "rollback: setting unchanged, nothing to do"; | 73 VLOG(1) << "rollback: setting unchanged, nothing to do"; |
92 return; | 74 return; |
93 } | 75 } |
94 | 76 |
95 // At this point only possible state is VALUE_DELETED. | 77 // At this point only possible state is VALUE_DELETED. |
96 RegKey key; | 78 RegKey key; |
97 if (!key.Open(predefined_root_, key_path_.c_str(), KEY_READ | KEY_WRITE)) { | 79 LONG result = key.Open(predefined_root_, key_path_.c_str(), |
98 LOG(ERROR) << "rollback: can not open " << key_path_; | 80 KEY_READ | KEY_WRITE); |
99 // try to restore the previous value | 81 if (result == ERROR_SUCCESS) { |
100 } else if ((type_ == REG_SZ && key.WriteValue(value_name_.c_str(), | 82 // try to restore the previous value |
101 old_str_.c_str())) || | 83 result = key.WriteValue(value_name_.c_str(), previous_value_.c_str(), |
grt (UTC plus 2)
2011/01/14 15:53:43
If you use std::string where std::vector<uint8> be
| |
102 (type_ == REG_DWORD && key.WriteValue(value_name_.c_str(), | 84 static_cast<DWORD>(previous_value_.size()), |
103 old_dw_)) || | 85 previous_type_); |
104 (type_ == REG_QWORD && key.WriteValue(value_name_.c_str(), | 86 VLOG_IF(1, result != ERROR_SUCCESS) << "rollback: restoring " |
105 &old_qword_, | 87 << value_name_ << " error: " << result; |
106 sizeof(old_qword_), | |
107 REG_QWORD))) { | |
108 status_ = VALUE_ROLLED_BACK; | |
109 VLOG(1) << "rollback: restored " << value_name_; | |
110 } else { | 88 } else { |
111 LOG(ERROR) << "failed to restore value " << value_name_; | 89 VLOG(1) << "can not open " << key_path_ << " error: " << result; |
112 } | 90 } |
113 | |
114 key.Close(); | |
115 return; | |
116 } | 91 } |
OLD | NEW |