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