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

Side by Side Diff: remoting/host/plugin/daemon_controller_win.cc

Issue 10021003: Implemented on-demand installation of the Chromoting Host on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: The last piece of CR feeback. Rebased. 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
« no previous file with comments | « remoting/host/plugin/DEPS ('k') | remoting/host/plugin/daemon_installer_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/plugin/daemon_controller.h" 5 #include "remoting/host/plugin/daemon_controller.h"
6 6
7 #include <objbase.h> 7 #include <objbase.h>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
11 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
12 #include "base/file_path.h" 13 #include "base/file_path.h"
13 #include "base/file_util.h" 14 #include "base/file_util.h"
14 #include "base/json/json_reader.h" 15 #include "base/json/json_reader.h"
15 #include "base/json/json_writer.h" 16 #include "base/json/json_writer.h"
16 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/string16.h"
19 #include "base/stringize_macros.h"
17 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
18 #include "base/utf_string_conversions.h" 21 #include "base/utf_string_conversions.h"
19 #include "base/values.h" 22 #include "base/values.h"
23 #include "base/win/scoped_bstr.h"
24 #include "base/win/scoped_comptr.h"
20 #include "remoting/base/scoped_sc_handle_win.h" 25 #include "remoting/base/scoped_sc_handle_win.h"
21 #include "remoting/host/branding.h" 26 #include "remoting/host/branding.h"
27 #include "remoting/host/plugin/daemon_installer_win.h"
22 28
23 // MIDL-generated declarations and definitions. 29 // MIDL-generated declarations and definitions.
24 #include "remoting/host/elevated_controller.h" 30 #include "remoting/host/elevated_controller.h"
25 31
32 using base::win::ScopedBstr;
33 using base::win::ScopedComPtr;
34
26 namespace remoting { 35 namespace remoting {
27 36
28 namespace { 37 namespace {
29 38
30 // The COM elevation moniker for the elevated controller. 39 // The COM elevation moniker for the elevated controller.
31 const char kElevationMoniker[] = "Elevation:Administrator!new:" 40 const char16 kDaemonControllerElevationMoniker[] =
32 "{430a9403-8176-4733-afdc-0b325a8fda84}"; 41 TO_L_STRING("Elevation:Administrator!new:")
42 TO_L_STRING("ChromotingElevatedController.ElevatedController");
33 43
34 // Name of the Daemon Controller's worker thread. 44 // Name of the Daemon Controller's worker thread.
35 const char kDaemonControllerThreadName[] = "Daemon Controller thread"; 45 const char kDaemonControllerThreadName[] = "Daemon Controller thread";
36 46
37 // A base::Thread implementation that initializes COM on the new thread. 47 // A base::Thread implementation that initializes COM on the new thread.
38 class ComThread : public base::Thread { 48 class ComThread : public base::Thread {
39 public: 49 public:
40 explicit ComThread(const char* name); 50 explicit ComThread(const char* name);
41 51
42 // Activates an elevated instance of the controller and returns the pointer 52 // Activates an elevated instance of the controller and returns the pointer
43 // to the control interface in |control_out|. This class keeps the ownership 53 // to the control interface in |control_out|. This class keeps the ownership
44 // of the pointer so the caller should not call call AddRef() or Release(). 54 // of the pointer so the caller should not call call AddRef() or Release().
45 HRESULT ActivateElevatedController(IDaemonControl** control_out); 55 HRESULT ActivateElevatedController(IDaemonControl** control_out);
46 56
47 bool Start(); 57 bool Start();
48 58
49 protected: 59 protected:
50 virtual void Init() OVERRIDE; 60 virtual void Init() OVERRIDE;
51 virtual void CleanUp() OVERRIDE; 61 virtual void CleanUp() OVERRIDE;
52 62
53 IDaemonControl* control_; 63 ScopedComPtr<IDaemonControl> control_;
54 64
55 DISALLOW_COPY_AND_ASSIGN(ComThread); 65 DISALLOW_COPY_AND_ASSIGN(ComThread);
56 }; 66 };
57 67
58 class DaemonControllerWin : public remoting::DaemonController { 68 class DaemonControllerWin : public remoting::DaemonController {
59 public: 69 public:
60 DaemonControllerWin(); 70 DaemonControllerWin();
61 virtual ~DaemonControllerWin(); 71 virtual ~DaemonControllerWin();
62 72
63 virtual State GetState() OVERRIDE; 73 virtual State GetState() OVERRIDE;
64 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; 74 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE;
65 virtual void SetConfigAndStart( 75 virtual void SetConfigAndStart(
66 scoped_ptr<base::DictionaryValue> config, 76 scoped_ptr<base::DictionaryValue> config,
67 const CompletionCallback& done_callback) OVERRIDE; 77 const CompletionCallback& done_callback) OVERRIDE;
68 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, 78 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config,
69 const CompletionCallback& done_callback) OVERRIDE; 79 const CompletionCallback& done_callback) OVERRIDE;
70 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; 80 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE;
71 81
72 private: 82 private:
73 // Converts a Windows service status code to a Daemon state. 83 // Converts a Windows service status code to a Daemon state.
74 static State ConvertToDaemonState(DWORD service_state); 84 static State ConvertToDaemonState(DWORD service_state);
75 85
76 // Converts HRESULT to the AsyncResult. 86 // Converts HRESULT to the AsyncResult.
77 static AsyncResult HResultToAsyncResult(HRESULT hr); 87 static AsyncResult HResultToAsyncResult(HRESULT hr);
78 88
89 // Procedes with the daemon configuration if the installation succeeded,
90 // otherwise reports the error.
91 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config,
92 const CompletionCallback& done_callback,
93 HRESULT result);
94
79 // Opens the Chromoting service returning its handle in |service_out|. 95 // Opens the Chromoting service returning its handle in |service_out|.
80 DWORD OpenService(ScopedScHandle* service_out); 96 DWORD OpenService(ScopedScHandle* service_out);
81 97
82 // The functions that actually do the work. They should be called in 98 // The functions that actually do the work. They should be called in
83 // the context of |worker_thread_|; 99 // the context of |worker_thread_|;
84 void DoGetConfig(const GetConfigCallback& callback); 100 void DoGetConfig(const GetConfigCallback& callback);
101 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config,
102 const CompletionCallback& done_callback);
85 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, 103 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config,
86 const CompletionCallback& done_callback); 104 const CompletionCallback& done_callback);
87 void DoStop(const CompletionCallback& done_callback); 105 void DoStop(const CompletionCallback& done_callback);
88 106
89 // The worker thread used for servicing long running operations. 107 // The worker thread used for servicing long running operations.
90 ComThread worker_thread_; 108 ComThread worker_thread_;
91 109
110 scoped_ptr<DaemonInstallerWin> installer_;
111
92 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); 112 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin);
93 }; 113 };
94 114
95 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { 115 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) {
96 } 116 }
97 117
98 void ComThread::Init() { 118 void ComThread::Init() {
99 CoInitialize(NULL); 119 CoInitialize(NULL);
100 } 120 }
101 121
102 void ComThread::CleanUp() { 122 void ComThread::CleanUp() {
103 if (control_ != NULL) 123 control_.Release();
104 control_->Release();
105 CoUninitialize(); 124 CoUninitialize();
106 } 125 }
107 126
108 HRESULT ComThread::ActivateElevatedController( 127 HRESULT ComThread::ActivateElevatedController(
109 IDaemonControl** control_out) { 128 IDaemonControl** control_out) {
110 // Chache the instance of Elevated Controller to prevent a UAC prompt on every 129 // Chache the instance of Elevated Controller to prevent a UAC prompt on every
111 // operation. 130 // operation.
112 if (control_ == NULL) { 131 if (control_.get() == NULL) {
113 BIND_OPTS3 bind_options; 132 BIND_OPTS3 bind_options;
114 memset(&bind_options, 0, sizeof(bind_options)); 133 memset(&bind_options, 0, sizeof(bind_options));
115 bind_options.cbStruct = sizeof(bind_options); 134 bind_options.cbStruct = sizeof(bind_options);
116 bind_options.hwnd = NULL; 135 bind_options.hwnd = NULL;
117 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; 136 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
118 137
119 HRESULT hr = ::CoGetObject(ASCIIToUTF16(kElevationMoniker).c_str(), 138 HRESULT hr = ::CoGetObject(
120 &bind_options, 139 kDaemonControllerElevationMoniker,
121 IID_IDaemonControl, 140 &bind_options,
122 reinterpret_cast<void**>(&control_)); 141 IID_IDaemonControl,
142 control_.ReceiveVoid());
123 if (FAILED(hr)) { 143 if (FAILED(hr)) {
124 LOG(ERROR) << "Failed to create the elevated controller (error: 0x"
125 << std::hex << hr << std::dec << ").";
126 return hr; 144 return hr;
127 } 145 }
128 } 146 }
129 147
130 *control_out = control_; 148 *control_out = control_.get();
131 return S_OK; 149 return S_OK;
132 } 150 }
133 151
134 bool ComThread::Start() { 152 bool ComThread::Start() {
135 // N.B. The single threaded COM apartment must be run on a UI message loop. 153 // N.B. The single threaded COM apartment must be run on a UI message loop.
136 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); 154 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0);
137 return StartWithOptions(thread_options); 155 return StartWithOptions(thread_options);
138 } 156 }
139 157
140 DaemonControllerWin::DaemonControllerWin() 158 DaemonControllerWin::DaemonControllerWin()
(...skipping 20 matching lines...) Expand all
161 return ConvertToDaemonState(status.dwCurrentState); 179 return ConvertToDaemonState(status.dwCurrentState);
162 } else { 180 } else {
163 LOG_GETLASTERROR(ERROR) 181 LOG_GETLASTERROR(ERROR)
164 << "Failed to query the state of the '" << kWindowsServiceName 182 << "Failed to query the state of the '" << kWindowsServiceName
165 << "' service"; 183 << "' service";
166 return STATE_UNKNOWN; 184 return STATE_UNKNOWN;
167 } 185 }
168 break; 186 break;
169 } 187 }
170 case ERROR_SERVICE_DOES_NOT_EXIST: 188 case ERROR_SERVICE_DOES_NOT_EXIST:
171 return STATE_NOT_IMPLEMENTED; 189 return STATE_NOT_INSTALLED;
172 default: 190 default:
173 return STATE_UNKNOWN; 191 return STATE_UNKNOWN;
174 } 192 }
175 } 193 }
176 194
177 void DaemonControllerWin::GetConfig(const GetConfigCallback& callback) { 195 void DaemonControllerWin::GetConfig(const GetConfigCallback& callback) {
178 worker_thread_.message_loop_proxy()->PostTask( 196 worker_thread_.message_loop_proxy()->PostTask(
179 FROM_HERE, 197 FROM_HERE,
180 base::Bind(&DaemonControllerWin::DoGetConfig, 198 base::Bind(&DaemonControllerWin::DoGetConfig,
181 base::Unretained(this), callback)); 199 base::Unretained(this), callback));
182 } 200 }
183 201
184 void DaemonControllerWin::SetConfigAndStart( 202 void DaemonControllerWin::SetConfigAndStart(
185 scoped_ptr<base::DictionaryValue> config, 203 scoped_ptr<base::DictionaryValue> config,
186 const CompletionCallback& done_callback) { 204 const CompletionCallback& done_callback) {
187 205
188 worker_thread_.message_loop_proxy()->PostTask( 206 worker_thread_.message_loop_proxy()->PostTask(
189 FROM_HERE, base::Bind( 207 FROM_HERE, base::Bind(
190 &DaemonControllerWin::DoSetConfigAndStart, base::Unretained(this), 208 &DaemonControllerWin::DoInstallAsNeededAndStart,
191 base::Passed(&config), done_callback)); 209 base::Unretained(this), base::Passed(&config), done_callback));
192 } 210 }
193 211
194 void DaemonControllerWin::UpdateConfig( 212 void DaemonControllerWin::UpdateConfig(
195 scoped_ptr<base::DictionaryValue> config, 213 scoped_ptr<base::DictionaryValue> config,
196 const CompletionCallback& done_callback) { 214 const CompletionCallback& done_callback) {
197 NOTIMPLEMENTED(); 215 NOTIMPLEMENTED();
198 done_callback.Run(RESULT_FAILED); 216 done_callback.Run(RESULT_FAILED);
199 } 217 }
200 218
201 void DaemonControllerWin::Stop(const CompletionCallback& done_callback) { 219 void DaemonControllerWin::Stop(const CompletionCallback& done_callback) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 } 252 }
235 253
236 // static 254 // static
237 DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult( 255 DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult(
238 HRESULT hr) { 256 HRESULT hr) {
239 // TODO(sergeyu): Report other errors to the webapp once it knows 257 // TODO(sergeyu): Report other errors to the webapp once it knows
240 // how to handle them. 258 // how to handle them.
241 return FAILED(hr) ? RESULT_FAILED : RESULT_OK; 259 return FAILED(hr) ? RESULT_FAILED : RESULT_OK;
242 } 260 }
243 261
262 void DaemonControllerWin::OnInstallationComplete(
263 scoped_ptr<base::DictionaryValue> config,
264 const CompletionCallback& done_callback,
265 HRESULT result) {
266 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
267
268 if (SUCCEEDED(result)) {
269 DoSetConfigAndStart(config.Pass(), done_callback);
270 } else {
271 LOG(ERROR) << "Failed to install the Chromoting Host "
272 << "(error: 0x" << std::hex << result << std::dec << ").";
273 done_callback.Run(HResultToAsyncResult(result));
274 }
275
276 DCHECK(installer_.get() != NULL);
277 installer_.reset();
278 }
279
244 DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) { 280 DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) {
245 // Open the service and query its current state. 281 // Open the service and query its current state.
246 ScopedScHandle scmanager( 282 ScopedScHandle scmanager(
247 ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, 283 ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE,
248 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); 284 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE));
249 if (!scmanager.IsValid()) { 285 if (!scmanager.IsValid()) {
250 DWORD error = GetLastError(); 286 DWORD error = GetLastError();
251 LOG_GETLASTERROR(ERROR) 287 LOG_GETLASTERROR(ERROR)
252 << "Failed to connect to the service control manager"; 288 << "Failed to connect to the service control manager";
253 return error; 289 return error;
254 } 290 }
255 291
256 ScopedScHandle service( 292 ScopedScHandle service(
257 ::OpenServiceW(scmanager, UTF8ToUTF16(kWindowsServiceName).c_str(), 293 ::OpenServiceW(scmanager, UTF8ToUTF16(kWindowsServiceName).c_str(),
258 SERVICE_QUERY_STATUS)); 294 SERVICE_QUERY_STATUS));
259 if (!service.IsValid()) { 295 if (!service.IsValid()) {
260 DWORD error = GetLastError(); 296 DWORD error = GetLastError();
261 if (error != ERROR_SERVICE_DOES_NOT_EXIST) { 297 if (error != ERROR_SERVICE_DOES_NOT_EXIST) {
262 LOG_GETLASTERROR(ERROR) 298 LOG_GETLASTERROR(ERROR)
263 << "Failed to open to the '" << kWindowsServiceName << "' service"; 299 << "Failed to open to the '" << kWindowsServiceName << "' service";
264 } 300 }
265 return error; 301 return error;
266 } 302 }
267 303
268 service_out->Set(service.Take()); 304 service_out->Set(service.Take());
269 return ERROR_SUCCESS; 305 return ERROR_SUCCESS;
270 } 306 }
271 307
272 void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { 308 void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) {
309 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
310
273 IDaemonControl* control = NULL; 311 IDaemonControl* control = NULL;
274 HRESULT hr = worker_thread_.ActivateElevatedController(&control); 312 HRESULT hr = worker_thread_.ActivateElevatedController(&control);
275 if (FAILED(hr)) { 313 if (FAILED(hr)) {
276 callback.Run(scoped_ptr<base::DictionaryValue>()); 314 callback.Run(scoped_ptr<base::DictionaryValue>());
277 return; 315 return;
278 } 316 }
279 317
280 // Get the host configuration. 318 // Get the host configuration.
281 BSTR host_config = NULL; 319 ScopedBstr host_config;
282 hr = control->GetConfig(&host_config); 320 hr = control->GetConfig(host_config.Receive());
283 if (FAILED(hr)) { 321 if (FAILED(hr)) {
284 callback.Run(scoped_ptr<base::DictionaryValue>()); 322 callback.Run(scoped_ptr<base::DictionaryValue>());
285 return; 323 return;
286 } 324 }
287 325
288 string16 file_content(static_cast<char16*>(host_config), 326 string16 file_content(static_cast<BSTR>(host_config), host_config.Length());
289 ::SysStringLen(host_config));
290 SysFreeString(host_config);
291 327
292 // Parse the string into a dictionary. 328 // Parse the string into a dictionary.
293 scoped_ptr<base::Value> config( 329 scoped_ptr<base::Value> config(
294 base::JSONReader::Read(UTF16ToUTF8(file_content), true)); 330 base::JSONReader::Read(UTF16ToUTF8(file_content), true));
295 331
296 base::DictionaryValue* dictionary; 332 base::DictionaryValue* dictionary;
297 if (config.get() == NULL || !config->GetAsDictionary(&dictionary)) { 333 if (config.get() == NULL || !config->GetAsDictionary(&dictionary)) {
298 callback.Run(scoped_ptr<base::DictionaryValue>()); 334 callback.Run(scoped_ptr<base::DictionaryValue>());
299 return; 335 return;
300 } 336 }
301 337
302 config.release(); 338 config.release();
303 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); 339 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary));
304 } 340 }
305 341
342 void DaemonControllerWin::DoInstallAsNeededAndStart(
343 scoped_ptr<base::DictionaryValue> config,
344 const CompletionCallback& done_callback) {
345 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
346
347 IDaemonControl* control = NULL;
348 HRESULT hr = worker_thread_.ActivateElevatedController(&control);
349
350 // Just configure and start the Daemon Controller if it is installed already.
351 if (SUCCEEDED(hr)) {
352 DoSetConfigAndStart(config.Pass(), done_callback);
353 return;
354 }
355
356 // Otherwise, install it if it's COM registration entry is missing.
357 if (hr == CO_E_CLASSSTRING) {
358 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create(
359 base::Bind(&DaemonControllerWin::OnInstallationComplete,
360 base::Unretained(this),
361 base::Passed(&config),
362 done_callback));
363 if (installer.get()) {
364 DCHECK(!installer_.get());
365 installer_ = installer.Pass();
366 installer_->Install();
367 }
368 } else {
369 LOG(ERROR) << "Failed to initiate the Chromoting Host installation "
370 << "(error: 0x" << std::hex << hr << std::dec << ").";
371 done_callback.Run(HResultToAsyncResult(hr));
372 }
373 }
374
306 void DaemonControllerWin::DoSetConfigAndStart( 375 void DaemonControllerWin::DoSetConfigAndStart(
307 scoped_ptr<base::DictionaryValue> config, 376 scoped_ptr<base::DictionaryValue> config,
308 const CompletionCallback& done_callback) { 377 const CompletionCallback& done_callback) {
378 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
379
309 IDaemonControl* control = NULL; 380 IDaemonControl* control = NULL;
310 HRESULT hr = worker_thread_.ActivateElevatedController(&control); 381 HRESULT hr = worker_thread_.ActivateElevatedController(&control);
311 if (FAILED(hr)) { 382 if (FAILED(hr)) {
312 done_callback.Run(HResultToAsyncResult(hr)); 383 done_callback.Run(HResultToAsyncResult(hr));
313 return; 384 return;
314 } 385 }
315 386
316 // Store the configuration. 387 // Store the configuration.
317 std::string file_content; 388 std::string file_content;
318 base::JSONWriter::Write(config.get(), &file_content); 389 base::JSONWriter::Write(config.get(), &file_content);
319 390
320 BSTR host_config = ::SysAllocString(UTF8ToUTF16(file_content).c_str()); 391 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str());
321 if (host_config == NULL) { 392 if (host_config == NULL) {
322 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); 393 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY));
323 return; 394 return;
324 } 395 }
325 396
326 hr = control->SetConfig(host_config); 397 hr = control->SetConfig(host_config);
327 ::SysFreeString(host_config);
328 if (FAILED(hr)) { 398 if (FAILED(hr)) {
329 done_callback.Run(HResultToAsyncResult(hr)); 399 done_callback.Run(HResultToAsyncResult(hr));
330 return; 400 return;
331 } 401 }
332 402
333 // Start daemon. 403 // Start daemon.
334 hr = control->StartDaemon(); 404 hr = control->StartDaemon();
335 done_callback.Run(HResultToAsyncResult(hr)); 405 done_callback.Run(HResultToAsyncResult(hr));
336 } 406 }
337 407
338 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { 408 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) {
409 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
410
339 IDaemonControl* control = NULL; 411 IDaemonControl* control = NULL;
340 HRESULT hr = worker_thread_.ActivateElevatedController(&control); 412 HRESULT hr = worker_thread_.ActivateElevatedController(&control);
341 if (FAILED(hr)) { 413 if (FAILED(hr)) {
342 done_callback.Run(HResultToAsyncResult(hr)); 414 done_callback.Run(HResultToAsyncResult(hr));
343 return; 415 return;
344 } 416 }
345 417
346 hr = control->StopDaemon(); 418 hr = control->StopDaemon();
347 done_callback.Run(HResultToAsyncResult(hr)); 419 done_callback.Run(HResultToAsyncResult(hr));
348 } 420 }
349 421
350 } // namespace 422 } // namespace
351 423
352 scoped_ptr<DaemonController> remoting::DaemonController::Create() { 424 scoped_ptr<DaemonController> remoting::DaemonController::Create() {
353 return scoped_ptr<DaemonController>(new DaemonControllerWin()); 425 return scoped_ptr<DaemonController>(new DaemonControllerWin());
354 } 426 }
355 427
356 } // namespace remoting 428 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/plugin/DEPS ('k') | remoting/host/plugin/daemon_installer_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698