| 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 |