set_reg_value_work_item.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 3// found in the LICENSE file. 4 5#include "chrome/installer/util/set_reg_value_work_item.h" 6 7#include "base/logging.h" 8#include "base/string_util.h" 9#include "base/win/registry.h" 10#include "chrome/installer/util/logging_installer.h" 11 12SetRegValueWorkItem::~SetRegValueWorkItem() { 13} 14 15SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, 16 const std::wstring& key_path, 17 const std::wstring& value_name, 18 const std::wstring& value_data, 19 bool overwrite) 20 : predefined_root_(predefined_root), 21 key_path_(key_path), 22 value_name_(value_name), 23 overwrite_(overwrite), 24 status_(SET_VALUE), 25 type_(REG_SZ), 26 previous_type_(0) { 27 const uint8* data = reinterpret_cast<const uint8*>(value_data.c_str()); 28 value_.assign(data, data + (value_data.length() + 1) * sizeof(wchar_t)); 29} 30 31SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, 32 const std::wstring& key_path, 33 const std::wstring& value_name, 34 DWORD value_data, 35 bool overwrite) 36 : predefined_root_(predefined_root), 37 key_path_(key_path), 38 value_name_(value_name), 39 overwrite_(overwrite), 40 status_(SET_VALUE), 41 type_(REG_DWORD), 42 previous_type_(0) { 43 const uint8* data = reinterpret_cast<const uint8*>(&value_data); 44 value_.assign(data, data + sizeof(value_data)); 45} 46 47SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, 48 const std::wstring& key_path, 49 const std::wstring& value_name, 50 int64 value_data, 51 bool overwrite) 52 : predefined_root_(predefined_root), 53 key_path_(key_path), 54 value_name_(value_name), 55 overwrite_(overwrite), 56 status_(SET_VALUE), 57 type_(REG_QWORD), 58 previous_type_(0) { 59 const uint8* data = reinterpret_cast<const uint8*>(&value_data); 60 value_.assign(data, data + sizeof(value_data)); 61} 62 63bool SetRegValueWorkItem::Do() { 64 LONG result = ERROR_SUCCESS; 65 base::win::RegKey key; 66 if (status_ != SET_VALUE) { 67 // we already did something. 68 VLOG(1) << "multiple calls to Do()"; 69 result = ERROR_CANTWRITE; 70 return ignore_failure_; 71 } 72 73 status_ = VALUE_UNCHANGED; 74 result = key.Open(predefined_root_, key_path_.c_str(), 75 KEY_READ | KEY_SET_VALUE); 76 if (result != ERROR_SUCCESS) { 77 VLOG(1) << "can not open " << key_path_ << " error: " << result; 78 return ignore_failure_; 79 } 80 81 DWORD type = 0; 82 DWORD size = 0; 83 result = key.ReadValue(value_name_.c_str(), NULL, &size, &type); 84 // If the value exists but we don't want to overwrite then there's 85 // nothing more to do. 86 if ((result != ERROR_FILE_NOT_FOUND) && !overwrite_) { 87 return true; 88 } 89 90 // If there's something to be saved, save it. 91 if (result == ERROR_SUCCESS) { 92 if (!size) { 93 previous_type_ = type; 94 } else { 95 previous_value_.resize(size); 96 result = key.ReadValue(value_name_.c_str(), &previous_value_[0], &size, 97 &previous_type_); 98 if (result != ERROR_SUCCESS) { 99 previous_value_.clear(); 100 VLOG(1) << "Failed to save original value. Error: " << result; 101 } 102 } 103 } 104 105 result = key.WriteValue(value_name_.c_str(), &value_[0], 106 static_cast<DWORD>(value_.size()), type_); 107 if (result != ERROR_SUCCESS) { 108 VLOG(1) << "Failed to write value " << key_path_ << " error: " << result; 109 return ignore_failure_; 110 } 111 112 status_ = previous_type_ ? VALUE_OVERWRITTEN : NEW_VALUE_CREATED; 113 return true; 114} 115 116void SetRegValueWorkItem::Rollback() { 117 if (ignore_failure_) 118 return; 119 120 if (status_ == SET_VALUE || status_ == VALUE_ROLL_BACK) 121 return; 122 123 if (status_ == VALUE_UNCHANGED) { 124 status_ = VALUE_ROLL_BACK; 125 VLOG(1) << "rollback: setting unchanged, nothing to do"; 126 return; 127 } 128 129 base::win::RegKey key; 130 LONG result = key.Open(predefined_root_, key_path_.c_str(), KEY_SET_VALUE); 131 if (result != ERROR_SUCCESS) { 132 VLOG(1) << "rollback: can not open " << key_path_ << " error: " << result; 133 return; 134 } 135 136 if (status_ == NEW_VALUE_CREATED) { 137 result = key.DeleteValue(value_name_.c_str()); 138 VLOG(1) << "rollback: deleting " << value_name_ << " error: " << result; 139 } else if (status_ == VALUE_OVERWRITTEN) { 140 const unsigned char* previous_value = 141 previous_value_.empty() ? NULL : &previous_value_[0]; 142 result = key.WriteValue(value_name_.c_str(), previous_value, 143 static_cast<DWORD>(previous_value_.size()), 144 previous_type_); 145 VLOG(1) << "rollback: restoring " << value_name_ << " error: " << result; 146 } else { 147 NOTREACHED(); 148 } 149 150 status_ = VALUE_ROLL_BACK; 151} 152