Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: remoting/host/elevated_controller_win.cc

Issue 9953002: The me2me host is now configurable from the web UI on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Moving the Windows service name to a common location. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "remoting/host/elevated_controller_win.h" 5 #include "remoting/host/elevated_controller_win.h"
6 6
7 #include "base/file_util.h"
8 #include "base/logging.h"
9 #include "base/json/json_reader.h"
10 #include "base/json/json_writer.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/path_service.h"
13 #include "base/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "base/win/scoped_handle.h"
16 #include "remoting/host/branding.h"
17
7 // MIDL-generated definitions. 18 // MIDL-generated definitions.
8 #include <elevated_controller_i.c> 19 #include <elevated_controller_i.c>
9 20
10 using ATL::CComQIPtr; 21 namespace {
11 using ATL::CComPtr; 22
23 // TODO(alexeypa): remove this limitation.
24 const size_t kMaxConfigFileSize = 0x10000;
25
26 const char kHostId[] = "host_id";
27 const char kXmppLogin[] = "xmpp_login";
28
29 // Names of the configuration files.
30 const FilePath::CharType kAuthConfig[] = FILE_PATH_LITERAL("auth.json");
31 const FilePath::CharType kHostConfig[] = FILE_PATH_LITERAL("host.json");
32
33 // TODO(alexeypa): remove the hardcoded undocimented paths and store
34 // the configuration in the registry.
35 #ifdef OFFICIAL_BUILD
36 const FilePath::CharType kConfigDir[] = FILE_PATH_LITERAL(
37 "config\\systemprofile\\AppData\\Local\\Google\\Chrome Remote Desktop");
38 #else
39 const FilePath::CharType kConfigDir[] =
40 FILE_PATH_LITERAL("config\\systemprofile\\AppData\\Local\\Chromoting");
41 #endif
42
43 // Reads and parses a JSON configuration file (up to 64KB in size).
44 HRESULT ReadConfig(const FilePath& filename,
45 scoped_ptr<base::DictionaryValue>* config_out) {
46 // Read raw data from the configuration file.
47 base::win::ScopedHandle file(
48 CreateFileW(filename.value().c_str(),
49 GENERIC_READ,
50 FILE_SHARE_READ | FILE_SHARE_WRITE,
51 NULL,
52 OPEN_EXISTING,
53 FILE_FLAG_SEQUENTIAL_SCAN,
54 NULL));
55
56 if (!file.IsValid()) {
57 DWORD error = GetLastError();
58 LOG_GETLASTERROR(ERROR)
59 << "Failed to read '" << filename.value() << "'";
60 return HRESULT_FROM_WIN32(error);
61 }
62
63 std::vector<char> buffer(kMaxConfigFileSize);
64 DWORD size = static_cast<DWORD>(buffer.size());
65 if (!::ReadFile(file, &buffer[0], size, &size, NULL)) {
66 DWORD error = GetLastError();
67 LOG_GETLASTERROR(ERROR)
68 << "Failed to read '" << filename.value() << "'";
69 return HRESULT_FROM_WIN32(error);
70 }
71
72 // Parse JSON data.
73 std::string file_content(&buffer[0], size);
74 scoped_ptr<base::Value> value(base::JSONReader::Read(file_content, true));
75
76 if (value.get() == NULL || !value->IsType(base::Value::TYPE_DICTIONARY)) {
77 LOG(ERROR) << "Failed to read '" << filename.value() << "'.";
78 return E_FAIL;
79 }
80
81 config_out->reset(static_cast<base::DictionaryValue*>(value.release()));
82 return S_OK;
83 }
84
85 } // namespace
12 86
13 namespace remoting { 87 namespace remoting {
14 88
15 ElevatedControllerWin::ElevatedControllerWin() { 89 ElevatedControllerWin::ElevatedControllerWin() {
16 } 90 }
17 91
18 HRESULT ElevatedControllerWin::FinalConstruct() { 92 HRESULT ElevatedControllerWin::FinalConstruct() {
19 return S_OK; 93 return S_OK;
20 } 94 }
21 95
22 void ElevatedControllerWin::FinalRelease() { 96 void ElevatedControllerWin::FinalRelease() {
23 } 97 }
24 98
25 STDMETHODIMP ElevatedControllerWin::get_State(DaemonState* state_out) { 99 STDMETHODIMP ElevatedControllerWin::GetConfig(BSTR* config_out) {
26 return E_NOTIMPL; 100 FilePath system_profile;
101 PathService::Get(base::DIR_SYSTEM, &system_profile);
102
103 // Build the host configuration.
104 scoped_ptr<base::DictionaryValue> config;
105 HRESULT hr = ReadConfig(system_profile.Append(kConfigDir).Append(kHostConfig),
106 &config);
107 if (FAILED(hr)) {
108 return hr;
109 }
110
111 // Build the filtered config.
112 scoped_ptr<base::DictionaryValue> filtered_config(
113 new base::DictionaryValue());
114
115 std::string value;
116 if (config->GetString(kHostId, &value)) {
117 filtered_config->SetString(kHostId, value);
118 }
119
120 if (config->GetString(kXmppLogin, &value)) {
121 filtered_config->SetString(kXmppLogin, value);
122 }
123
124 // Convert the filtered config back to string and return it to the caller.
125 std::string file_content;
126 base::JSONWriter::Write(filtered_config.get(), &file_content);
127
128 *config_out = ::SysAllocString(UTF8ToUTF16(file_content).c_str());
129 if (config_out == NULL) {
130 return E_OUTOFMEMORY;
131 }
132
133 return S_OK;
27 } 134 }
28 135
29 STDMETHODIMP ElevatedControllerWin::ReadConfig(BSTR* config_out) { 136 STDMETHODIMP ElevatedControllerWin::SetConfig(BSTR config) {
30 return E_NOTIMPL; 137 FilePath system_profile;
31 } 138 PathService::Get(base::DIR_SYSTEM, &system_profile);
32 139
33 STDMETHODIMP ElevatedControllerWin::WriteConfig(BSTR config) { 140 FilePath config_dir = system_profile.Append(kConfigDir);
34 return E_NOTIMPL; 141 if (!file_util::CreateDirectory(config_dir)) {
142 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
143 }
144
145 std::string file_content = UTF16ToUTF8(
146 string16(static_cast<char16*>(config), ::SysStringLen(config)));
147
148 int written = file_util::WriteFile(
149 config_dir.Append(kAuthConfig),
150 file_content.c_str(),
151 file_content.size());
152
153 if (written != static_cast<int>(file_content.size())) {
154 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
155 }
156
157 // TODO(alexeypa): make it a single file.
158 written = file_util::WriteFile(
159 config_dir.Append(kHostConfig),
160 file_content.c_str(),
161 file_content.size());
162
163 if (written != static_cast<int>(file_content.size())) {
164 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
165 }
166
167 return S_OK;
35 } 168 }
36 169
37 STDMETHODIMP ElevatedControllerWin::StartDaemon() { 170 STDMETHODIMP ElevatedControllerWin::StartDaemon() {
38 return E_NOTIMPL; 171 ScopedScHandle service;
39 } 172 HRESULT hr = OpenService(&service);
40 173 if (FAILED(hr)) {
41 STDMETHODIMP ElevatedControllerWin::StopDaemon() { 174 return hr;
42 return E_NOTIMPL;
43 }
44
45 HRESULT ElevatedControllerWin::FireOnStateChange(DaemonState state) {
46 CComPtr<IConnectionPoint> connection_point;
47 FindConnectionPoint(__uuidof(IDaemonEvents), &connection_point);
48 if (!connection_point) {
49 return S_OK;
50 } 175 }
51 176
52 CComPtr<IEnumConnections> connections; 177 if (!StartService(service, 0, NULL)) {
53 if (FAILED(connection_point->EnumConnections(&connections))) { 178 DWORD error = GetLastError();
54 return S_OK; 179 if (error != ERROR_SERVICE_ALREADY_RUNNING) {
55 } 180 LOG_GETLASTERROR(ERROR)
181 << "Failed to start the '" << kWindowsServiceName << "'service";
56 182
57 CONNECTDATA connect_data; 183 return HRESULT_FROM_WIN32(error);
58 while (connections->Next(1, &connect_data, NULL) == S_OK) {
59 if (connect_data.pUnk != NULL) {
60 CComQIPtr<IDaemonEvents, &__uuidof(IDaemonEvents)> sink(
61 connect_data.pUnk);
62
63 if (sink != NULL) {
64 sink->OnStateChange(state);
65 }
66
67 connect_data.pUnk->Release();
68 } 184 }
69 } 185 }
70 186
71 return S_OK; 187 return S_OK;
72 } 188 }
73 189
190 STDMETHODIMP ElevatedControllerWin::StopDaemon() {
191 ScopedScHandle service;
192 HRESULT hr = OpenService(&service);
193 if (FAILED(hr)) {
194 return hr;
195 }
196
197 SERVICE_STATUS status;
198 if (!ControlService(service, SERVICE_CONTROL_STOP, &status)) {
199 DWORD error = GetLastError();
200 if (error != ERROR_SERVICE_NOT_ACTIVE) {
201 LOG_GETLASTERROR(ERROR)
202 << "Failed to stop the '" << kWindowsServiceName << "'service";
203 return HRESULT_FROM_WIN32(error);
204 }
205 }
206
207 return S_OK;
208 }
209
210 HRESULT ElevatedControllerWin::OpenService(ScopedScHandle* service_out) {
211 DWORD error;
212
213 ScopedScHandle scmanager(
214 ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE,
215 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE));
216 if (!scmanager.IsValid()) {
217 error = GetLastError();
218 LOG_GETLASTERROR(ERROR)
219 << "Failed to connect to the service control manager";
220
221 return HRESULT_FROM_WIN32(error);
222 }
223
224 ScopedScHandle service(
225 ::OpenServiceA(scmanager, kWindowsServiceName,
226 SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP));
227 if (!service.IsValid()) {
228 error = GetLastError();
229 LOG_GETLASTERROR(ERROR)
230 << "Failed to open to the '" << kWindowsServiceName << "' service";
231
232 return HRESULT_FROM_WIN32(error);
233 }
234
235 service_out->Set(service.Take());
236 return S_OK;
237 }
238
74 } // namespace remoting 239 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698