OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |