- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / installer / util / set_reg_value_work_item.cc
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/strings/string_util.h"
9 #include "base/win/registry.h"
10 #include "chrome/installer/util/logging_installer.h"
11
12 SetRegValueWorkItem::~SetRegValueWorkItem() {
13 }
14
15 SetRegValueWorkItem::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
31 SetRegValueWorkItem::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
47 SetRegValueWorkItem::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
63 bool 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
116 void 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 }