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

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

Issue 10272029: Make sure the timer is stopped and destroyed on the thread it was created on. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback Created 8 years, 7 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 | « no previous file | no next file » | 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"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 const char kDaemonControllerThreadName[] = "Daemon Controller thread"; 48 const char kDaemonControllerThreadName[] = "Daemon Controller thread";
49 49
50 // The maximum interval between showing UAC prompts. 50 // The maximum interval between showing UAC prompts.
51 const int kUacTimeoutSec = 15 * 60; 51 const int kUacTimeoutSec = 15 * 60;
52 52
53 // A base::Thread implementation that initializes COM on the new thread. 53 // A base::Thread implementation that initializes COM on the new thread.
54 class ComThread : public base::Thread { 54 class ComThread : public base::Thread {
55 public: 55 public:
56 explicit ComThread(const char* name); 56 explicit ComThread(const char* name);
57 57
58 // Activates an elevated instance of the controller and returns the pointer
59 // to the control interface in |control_out|. This class keeps the ownership
60 // of the pointer so the caller should not call call AddRef() or Release().
61 HRESULT ActivateElevatedController(HWND window_handle,
62 IDaemonControl** control_out);
63
64 bool Start(); 58 bool Start();
65 59
66 protected: 60 protected:
67 virtual void Init() OVERRIDE; 61 virtual void Init() OVERRIDE;
68 virtual void CleanUp() OVERRIDE; 62 virtual void CleanUp() OVERRIDE;
69 63
70 void ReleaseElevatedController();
71
72 ScopedComPtr<IDaemonControl> control_;
73
74 // This timer is used to release |control_| after a timeout.
75 base::OneShotTimer<ComThread> release_timer_;
76
77 DISALLOW_COPY_AND_ASSIGN(ComThread); 64 DISALLOW_COPY_AND_ASSIGN(ComThread);
78 }; 65 };
79 66
80 class DaemonControllerWin : public remoting::DaemonController { 67 class DaemonControllerWin : public remoting::DaemonController {
81 public: 68 public:
82 DaemonControllerWin(); 69 DaemonControllerWin();
83 virtual ~DaemonControllerWin(); 70 virtual ~DaemonControllerWin();
84 71
85 virtual State GetState() OVERRIDE; 72 virtual State GetState() OVERRIDE;
86 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; 73 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE;
87 virtual void SetConfigAndStart( 74 virtual void SetConfigAndStart(
88 scoped_ptr<base::DictionaryValue> config, 75 scoped_ptr<base::DictionaryValue> config,
89 const CompletionCallback& done_callback) OVERRIDE; 76 const CompletionCallback& done_callback) OVERRIDE;
90 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, 77 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config,
91 const CompletionCallback& done_callback) OVERRIDE; 78 const CompletionCallback& done_callback) OVERRIDE;
92 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; 79 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE;
93 virtual void SetWindow(void* window_handle) OVERRIDE; 80 virtual void SetWindow(void* window_handle) OVERRIDE;
94 81
95 private: 82 private:
96 // Converts a Windows service status code to a Daemon state. 83 // Activates an elevated instance of the controller and caches it.
97 static State ConvertToDaemonState(DWORD service_state); 84 HRESULT ActivateElevatedController();
98 85
99 // Converts HRESULT to the AsyncResult. 86 // Releases the cached instance of the elevated controller.
100 static AsyncResult HResultToAsyncResult(HRESULT hr); 87 void ReleaseElevatedController();
101 88
102 // Procedes with the daemon configuration if the installation succeeded, 89 // Procedes with the daemon configuration if the installation succeeded,
103 // otherwise reports the error. 90 // otherwise reports the error.
104 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config, 91 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config,
105 const CompletionCallback& done_callback, 92 const CompletionCallback& done_callback,
106 HRESULT result); 93 HRESULT result);
107 94
108 // Opens the Chromoting service returning its handle in |service_out|. 95 // Opens the Chromoting service returning its handle in |service_out|.
109 DWORD OpenService(ScopedScHandle* service_out); 96 DWORD OpenService(ScopedScHandle* service_out);
110 97
111 // Converts a config dictionary to a scoped BSTR. 98 // Converts a config dictionary to a scoped BSTR.
112 static void ConfigToString(const base::DictionaryValue& config, 99 static void ConfigToString(const base::DictionaryValue& config,
113 ScopedBstr* out); 100 ScopedBstr* out);
114 101
102 // Converts a Windows service status code to a Daemon state.
103 static State ConvertToDaemonState(DWORD service_state);
104
105 // Converts HRESULT to the AsyncResult.
106 static AsyncResult HResultToAsyncResult(HRESULT hr);
107
115 // The functions that actually do the work. They should be called in 108 // The functions that actually do the work. They should be called in
116 // the context of |worker_thread_|; 109 // the context of |worker_thread_|;
117 void DoGetConfig(const GetConfigCallback& callback); 110 void DoGetConfig(const GetConfigCallback& callback);
118 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, 111 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config,
119 const CompletionCallback& done_callback); 112 const CompletionCallback& done_callback);
120 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, 113 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config,
121 const CompletionCallback& done_callback); 114 const CompletionCallback& done_callback);
122 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, 115 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config,
123 const CompletionCallback& done_callback); 116 const CompletionCallback& done_callback);
124 void DoStop(const CompletionCallback& done_callback); 117 void DoStop(const CompletionCallback& done_callback);
125 void DoSetWindow(void* window_handle); 118 void DoSetWindow(void* window_handle);
126 119
120 ScopedComPtr<IDaemonControl> control_;
121
122 // This timer is used to release |control_| after a timeout.
123 scoped_ptr<base::OneShotTimer<DaemonControllerWin> > release_timer_;
124
127 // Handle of the plugin window. 125 // Handle of the plugin window.
128 HWND window_handle_; 126 HWND window_handle_;
129 127
130 // The worker thread used for servicing long running operations. 128 // The worker thread used for servicing long running operations.
131 ComThread worker_thread_; 129 ComThread worker_thread_;
132 130
133 scoped_ptr<DaemonInstallerWin> installer_; 131 scoped_ptr<DaemonInstallerWin> installer_;
134 132
135 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); 133 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin);
136 }; 134 };
137 135
138 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { 136 ComThread::ComThread(const char* name) : base::Thread(name) {
139 }
140
141 HRESULT ComThread::ActivateElevatedController(
142 HWND window_handle,
143 IDaemonControl** control_out) {
144 // Cache an instance of the Elevated Controller to prevent a UAC prompt on
145 // every operation.
146 if (control_.get() == NULL) {
147 BIND_OPTS3 bind_options;
148 memset(&bind_options, 0, sizeof(bind_options));
149 bind_options.cbStruct = sizeof(bind_options);
150 bind_options.hwnd = GetTopLevelWindow(window_handle);
151 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
152
153 HRESULT hr = ::CoGetObject(
154 kDaemonControllerElevationMoniker,
155 &bind_options,
156 IID_IDaemonControl,
157 control_.ReceiveVoid());
158 if (FAILED(hr)) {
159 return hr;
160 }
161
162 // Release |control_| upon expiration of the timeout.
163 release_timer_.Start(FROM_HERE,
164 base::TimeDelta::FromSeconds(kUacTimeoutSec),
165 this, &ComThread::ReleaseElevatedController);
166 }
167
168 *control_out = control_.get();
169 return S_OK;
170 } 137 }
171 138
172 bool ComThread::Start() { 139 bool ComThread::Start() {
173 // N.B. The single threaded COM apartment must be run on a UI message loop. 140 // N.B. The single threaded COM apartment must be run on a UI message loop.
174 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); 141 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0);
175 return StartWithOptions(thread_options); 142 return StartWithOptions(thread_options);
176 } 143 }
177 144
178 void ComThread::Init() { 145 void ComThread::Init() {
179 CoInitialize(NULL); 146 CoInitialize(NULL);
180 } 147 }
181 148
182 void ComThread::CleanUp() { 149 void ComThread::CleanUp() {
183 ReleaseElevatedController();
184 CoUninitialize(); 150 CoUninitialize();
185 } 151 }
186 152
187 void ComThread::ReleaseElevatedController() {
188 control_.Release();
189 }
190
191 DaemonControllerWin::DaemonControllerWin() 153 DaemonControllerWin::DaemonControllerWin()
192 : window_handle_(NULL), 154 : window_handle_(NULL),
193 worker_thread_(kDaemonControllerThreadName) { 155 worker_thread_(kDaemonControllerThreadName) {
194 if (!worker_thread_.Start()) { 156 if (!worker_thread_.Start()) {
195 LOG(FATAL) << "Failed to start the Daemon Controller worker thread."; 157 LOG(FATAL) << "Failed to start the Daemon Controller worker thread.";
196 } 158 }
197 } 159 }
198 160
199 DaemonControllerWin::~DaemonControllerWin() { 161 DaemonControllerWin::~DaemonControllerWin() {
162 // Clean up resources allocated on the worker thread.
163 worker_thread_.message_loop_proxy()->PostTask(
164 FROM_HERE,
165 base::Bind(&DaemonControllerWin::ReleaseElevatedController,
166 base::Unretained(this)));
200 worker_thread_.Stop(); 167 worker_thread_.Stop();
201 } 168 }
202 169
203 remoting::DaemonController::State DaemonControllerWin::GetState() { 170 remoting::DaemonController::State DaemonControllerWin::GetState() {
204 // TODO(alexeypa): Make the thread alertable, so we can switch to APC 171 // TODO(alexeypa): Make the thread alertable, so we can switch to APC
205 // notifications rather than polling. 172 // notifications rather than polling.
206 ScopedScHandle service; 173 ScopedScHandle service;
207 DWORD error = OpenService(&service); 174 DWORD error = OpenService(&service);
208 175
209 switch (error) { 176 switch (error) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 done_callback)); 225 done_callback));
259 } 226 }
260 227
261 void DaemonControllerWin::SetWindow(void* window_handle) { 228 void DaemonControllerWin::SetWindow(void* window_handle) {
262 worker_thread_.message_loop_proxy()->PostTask( 229 worker_thread_.message_loop_proxy()->PostTask(
263 FROM_HERE, base::Bind( 230 FROM_HERE, base::Bind(
264 &DaemonControllerWin::DoSetWindow, base::Unretained(this), 231 &DaemonControllerWin::DoSetWindow, base::Unretained(this),
265 window_handle)); 232 window_handle));
266 } 233 }
267 234
268 // static 235 HRESULT DaemonControllerWin::ActivateElevatedController() {
269 remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState( 236 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
270 DWORD service_state) {
271 switch (service_state) {
272 case SERVICE_RUNNING:
273 return STATE_STARTED;
274 237
275 case SERVICE_CONTINUE_PENDING: 238 // Cache an instance of the Elevated Controller to prevent a UAC prompt on
276 case SERVICE_START_PENDING: 239 // every operation.
277 return STATE_STARTING; 240 if (control_.get() == NULL) {
278 break; 241 BIND_OPTS3 bind_options;
242 memset(&bind_options, 0, sizeof(bind_options));
243 bind_options.cbStruct = sizeof(bind_options);
244 bind_options.hwnd = GetTopLevelWindow(window_handle_);
245 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
279 246
280 case SERVICE_PAUSE_PENDING: 247 HRESULT hr = ::CoGetObject(
281 case SERVICE_STOP_PENDING: 248 kDaemonControllerElevationMoniker,
282 return STATE_STOPPING; 249 &bind_options,
283 break; 250 IID_IDaemonControl,
251 control_.ReceiveVoid());
252 if (FAILED(hr)) {
253 return hr;
254 }
284 255
285 case SERVICE_PAUSED: 256 // Release |control_| upon expiration of the timeout.
286 case SERVICE_STOPPED: 257 release_timer_.reset(new base::OneShotTimer<DaemonControllerWin>());
287 return STATE_STOPPED; 258 release_timer_->Start(FROM_HERE,
288 break; 259 base::TimeDelta::FromSeconds(kUacTimeoutSec),
260 this,
261 &DaemonControllerWin::ReleaseElevatedController);
262 }
289 263
290 default: 264 return S_OK;
291 NOTREACHED();
292 return STATE_UNKNOWN;
293 }
294 } 265 }
295 266
296 // static 267 void DaemonControllerWin::ReleaseElevatedController() {
297 DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult( 268 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
298 HRESULT hr) { 269
299 // TODO(sergeyu): Report other errors to the webapp once it knows 270 control_.Release();
300 // how to handle them. 271 release_timer_.reset();
301 return FAILED(hr) ? RESULT_FAILED : RESULT_OK;
302 } 272 }
303 273
304 void DaemonControllerWin::OnInstallationComplete( 274 void DaemonControllerWin::OnInstallationComplete(
305 scoped_ptr<base::DictionaryValue> config, 275 scoped_ptr<base::DictionaryValue> config,
306 const CompletionCallback& done_callback, 276 const CompletionCallback& done_callback,
307 HRESULT result) { 277 HRESULT result) {
308 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 278 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
309 279
310 if (SUCCEEDED(result)) { 280 if (SUCCEEDED(result)) {
311 DoSetConfigAndStart(config.Pass(), done_callback); 281 DoSetConfigAndStart(config.Pass(), done_callback);
(...skipping 27 matching lines...) Expand all
339 LOG_GETLASTERROR(ERROR) 309 LOG_GETLASTERROR(ERROR)
340 << "Failed to open to the '" << kWindowsServiceName << "' service"; 310 << "Failed to open to the '" << kWindowsServiceName << "' service";
341 } 311 }
342 return error; 312 return error;
343 } 313 }
344 314
345 service_out->Set(service.Take()); 315 service_out->Set(service.Take());
346 return ERROR_SUCCESS; 316 return ERROR_SUCCESS;
347 } 317 }
348 318
319 // static
349 void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config, 320 void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config,
350 ScopedBstr* out) { 321 ScopedBstr* out) {
351 std::string config_str; 322 std::string config_str;
352 base::JSONWriter::Write(&config, &config_str); 323 base::JSONWriter::Write(&config, &config_str);
353 ScopedBstr config_scoped_bstr(UTF8ToUTF16(config_str).c_str()); 324 ScopedBstr config_scoped_bstr(UTF8ToUTF16(config_str).c_str());
354 out->Swap(config_scoped_bstr); 325 out->Swap(config_scoped_bstr);
355 } 326 }
356 327
328 // static
329 remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState(
330 DWORD service_state) {
331 switch (service_state) {
332 case SERVICE_RUNNING:
333 return STATE_STARTED;
334
335 case SERVICE_CONTINUE_PENDING:
336 case SERVICE_START_PENDING:
337 return STATE_STARTING;
338 break;
339
340 case SERVICE_PAUSE_PENDING:
341 case SERVICE_STOP_PENDING:
342 return STATE_STOPPING;
343 break;
344
345 case SERVICE_PAUSED:
346 case SERVICE_STOPPED:
347 return STATE_STOPPED;
348 break;
349
350 default:
351 NOTREACHED();
352 return STATE_UNKNOWN;
353 }
354 }
355
356 // static
357 DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult(
358 HRESULT hr) {
359 // TODO(sergeyu): Report other errors to the webapp once it knows
360 // how to handle them.
361 return FAILED(hr) ? RESULT_FAILED : RESULT_OK;
362 }
363
357 void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { 364 void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) {
358 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 365 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
359 366
360 scoped_ptr<base::DictionaryValue> dictionary_null(NULL); 367 scoped_ptr<base::DictionaryValue> dictionary_null(NULL);
361 // Get the name of the configuration file. 368 // Get the name of the configuration file.
362 FilePath dir = remoting::GetConfigDir(); 369 FilePath dir = remoting::GetConfigDir();
363 FilePath filename = dir.Append(kUnprivilegedConfigFileName); 370 FilePath filename = dir.Append(kUnprivilegedConfigFileName);
364 371
365 // Read raw data from the configuration file. 372 // Read raw data from the configuration file.
366 base::win::ScopedHandle file( 373 base::win::ScopedHandle file(
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 value.release(); 412 value.release();
406 413
407 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); 414 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary));
408 } 415 }
409 416
410 void DaemonControllerWin::DoInstallAsNeededAndStart( 417 void DaemonControllerWin::DoInstallAsNeededAndStart(
411 scoped_ptr<base::DictionaryValue> config, 418 scoped_ptr<base::DictionaryValue> config,
412 const CompletionCallback& done_callback) { 419 const CompletionCallback& done_callback) {
413 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 420 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
414 421
415 IDaemonControl* control = NULL; 422 // Configure and start the Daemon Controller if it is installed already.
416 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, 423 HRESULT hr = ActivateElevatedController();
417 &control);
418
419 // Just configure and start the Daemon Controller if it is installed already.
420 if (SUCCEEDED(hr)) { 424 if (SUCCEEDED(hr)) {
421 DoSetConfigAndStart(config.Pass(), done_callback); 425 DoSetConfigAndStart(config.Pass(), done_callback);
422 return; 426 return;
423 } 427 }
424 428
425 // Otherwise, install it if its COM registration entry is missing. 429 // Otherwise, install it if its COM registration entry is missing.
426 if (hr == CO_E_CLASSSTRING) { 430 if (hr == CO_E_CLASSSTRING) {
427 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create( 431 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create(
428 window_handle_, 432 window_handle_,
429 base::Bind(&DaemonControllerWin::OnInstallationComplete, 433 base::Bind(&DaemonControllerWin::OnInstallationComplete,
(...skipping 10 matching lines...) Expand all
440 << "(error: 0x" << std::hex << hr << std::dec << ")."; 444 << "(error: 0x" << std::hex << hr << std::dec << ").";
441 done_callback.Run(HResultToAsyncResult(hr)); 445 done_callback.Run(HResultToAsyncResult(hr));
442 } 446 }
443 } 447 }
444 448
445 void DaemonControllerWin::DoSetConfigAndStart( 449 void DaemonControllerWin::DoSetConfigAndStart(
446 scoped_ptr<base::DictionaryValue> config, 450 scoped_ptr<base::DictionaryValue> config,
447 const CompletionCallback& done_callback) { 451 const CompletionCallback& done_callback) {
448 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 452 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
449 453
450 IDaemonControl* control = NULL; 454 HRESULT hr = ActivateElevatedController();
451 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
452 &control);
453 if (FAILED(hr)) { 455 if (FAILED(hr)) {
454 done_callback.Run(HResultToAsyncResult(hr)); 456 done_callback.Run(HResultToAsyncResult(hr));
455 return; 457 return;
456 } 458 }
457 459
458 // Set the configuration. 460 // Set the configuration.
459 ScopedBstr config_str(NULL); 461 ScopedBstr config_str(NULL);
460 ConfigToString(*config, &config_str); 462 ConfigToString(*config, &config_str);
461 if (config_str == NULL) { 463 if (config_str == NULL) {
462 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); 464 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY));
463 return; 465 return;
464 } 466 }
465 467
466 hr = control->SetConfig(config_str); 468 hr = control_->SetConfig(config_str);
467 if (FAILED(hr)) { 469 if (FAILED(hr)) {
468 done_callback.Run(HResultToAsyncResult(hr)); 470 done_callback.Run(HResultToAsyncResult(hr));
469 return; 471 return;
470 } 472 }
471 473
472 // Start daemon. 474 // Start daemon.
473 hr = control->StartDaemon(); 475 hr = control_->StartDaemon();
474 done_callback.Run(HResultToAsyncResult(hr)); 476 done_callback.Run(HResultToAsyncResult(hr));
475 } 477 }
476 478
477 void DaemonControllerWin::DoUpdateConfig( 479 void DaemonControllerWin::DoUpdateConfig(
478 scoped_ptr<base::DictionaryValue> config, 480 scoped_ptr<base::DictionaryValue> config,
479 const CompletionCallback& done_callback) { 481 const CompletionCallback& done_callback) {
480 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 482 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
481 483
482 IDaemonControl* control = NULL; 484 HRESULT hr = ActivateElevatedController();
483 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
484 &control);
485 if (FAILED(hr)) { 485 if (FAILED(hr)) {
486 done_callback.Run(HResultToAsyncResult(hr)); 486 done_callback.Run(HResultToAsyncResult(hr));
487 return; 487 return;
488 } 488 }
489 489
490 // Update the configuration. 490 // Update the configuration.
491 ScopedBstr config_str(NULL); 491 ScopedBstr config_str(NULL);
492 ConfigToString(*config, &config_str); 492 ConfigToString(*config, &config_str);
493 if (config_str == NULL) { 493 if (config_str == NULL) {
494 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); 494 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY));
495 return; 495 return;
496 } 496 }
497 497
498 hr = control->UpdateConfig(config_str); 498 hr = control_->UpdateConfig(config_str);
499 done_callback.Run(HResultToAsyncResult(hr)); 499 done_callback.Run(HResultToAsyncResult(hr));
500 } 500 }
501 501
502 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { 502 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) {
503 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 503 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
504 504
505 IDaemonControl* control = NULL; 505 HRESULT hr = ActivateElevatedController();
506 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
507 &control);
508 if (FAILED(hr)) { 506 if (FAILED(hr)) {
509 done_callback.Run(HResultToAsyncResult(hr)); 507 done_callback.Run(HResultToAsyncResult(hr));
510 return; 508 return;
511 } 509 }
512 510
513 hr = control->StopDaemon(); 511 hr = control_->StopDaemon();
514 done_callback.Run(HResultToAsyncResult(hr)); 512 done_callback.Run(HResultToAsyncResult(hr));
515 } 513 }
516 514
517 void DaemonControllerWin::DoSetWindow(void* window_handle) { 515 void DaemonControllerWin::DoSetWindow(void* window_handle) {
518 window_handle_ = reinterpret_cast<HWND>(window_handle); 516 window_handle_ = reinterpret_cast<HWND>(window_handle);
519 } 517 }
520 518
521 } // namespace 519 } // namespace
522 520
523 scoped_ptr<DaemonController> remoting::DaemonController::Create() { 521 scoped_ptr<DaemonController> remoting::DaemonController::Create() {
524 return scoped_ptr<DaemonController>(new DaemonControllerWin()); 522 return scoped_ptr<DaemonController>(new DaemonControllerWin());
525 } 523 }
526 524
527 } // namespace remoting 525 } // namespace remoting
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698