15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/set_reg_value_work_item.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/logging_installer.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SetRegValueWorkItem::~SetRegValueWorkItem() { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& key_path, 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& value_name, 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& value_data, 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool overwrite) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : predefined_root_(predefined_root), 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_path_(key_path), 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_name_(value_name), 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overwrite_(overwrite), 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_(SET_VALUE), 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_(REG_SZ), 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_type_(0) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* data = reinterpret_cast<const uint8*>(value_data.c_str()); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_.assign(data, data + (value_data.length() + 1) * sizeof(wchar_t)); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& key_path, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& value_name, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD value_data, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool overwrite) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : predefined_root_(predefined_root), 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_path_(key_path), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_name_(value_name), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overwrite_(overwrite), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_(SET_VALUE), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_(REG_DWORD), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_type_(0) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* data = reinterpret_cast<const uint8*>(&value_data); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_.assign(data, data + sizeof(value_data)); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SetRegValueWorkItem::SetRegValueWorkItem(HKEY predefined_root, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& key_path, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& value_name, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 value_data, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool overwrite) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : predefined_root_(predefined_root), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_path_(key_path), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_name_(value_name), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overwrite_(overwrite), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_(SET_VALUE), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_(REG_QWORD), 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_type_(0) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* data = reinterpret_cast<const uint8*>(&value_data); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_.assign(data, data + sizeof(value_data)); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetRegValueWorkItem::Do() { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LONG result = ERROR_SUCCESS; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::RegKey key; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ != SET_VALUE) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we already did something. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "multiple calls to Do()"; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = ERROR_CANTWRITE; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ignore_failure_; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = VALUE_UNCHANGED; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = key.Open(predefined_root_, key_path_.c_str(), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_READ | KEY_SET_VALUE); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERROR_SUCCESS) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "can not open " << key_path_ << " error: " << result; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ignore_failure_; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD type = 0; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size = 0; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = key.ReadValue(value_name_.c_str(), NULL, &size, &type); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the value exists but we don't want to overwrite then there's 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // nothing more to do. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((result != ERROR_FILE_NOT_FOUND) && !overwrite_) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there's something to be saved, save it. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == ERROR_SUCCESS) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!size) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_type_ = type; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_value_.resize(size); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = key.ReadValue(value_name_.c_str(), &previous_value_[0], &size, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &previous_type_); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERROR_SUCCESS) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_value_.clear(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Failed to save original value. Error: " << result; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = key.WriteValue(value_name_.c_str(), &value_[0], 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<DWORD>(value_.size()), type_); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERROR_SUCCESS) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Failed to write value " << key_path_ << " error: " << result; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ignore_failure_; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = previous_type_ ? VALUE_OVERWRITTEN : NEW_VALUE_CREATED; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetRegValueWorkItem::Rollback() { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ignore_failure_) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ == SET_VALUE || status_ == VALUE_ROLL_BACK) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ == VALUE_UNCHANGED) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = VALUE_ROLL_BACK; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "rollback: setting unchanged, nothing to do"; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::RegKey key; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LONG result = key.Open(predefined_root_, key_path_.c_str(), KEY_SET_VALUE); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERROR_SUCCESS) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "rollback: can not open " << key_path_ << " error: " << result; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ == NEW_VALUE_CREATED) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = key.DeleteValue(value_name_.c_str()); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "rollback: deleting " << value_name_ << " error: " << result; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (status_ == VALUE_OVERWRITTEN) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned char* previous_value = 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_value_.empty() ? NULL : &previous_value_[0]; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = key.WriteValue(value_name_.c_str(), previous_value, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<DWORD>(previous_value_.size()), 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_type_); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "rollback: restoring " << value_name_ << " error: " << result; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = VALUE_ROLL_BACK; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 152