Chromium Code Reviews| 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" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/file_path.h" | 13 #include "base/file_path.h" |
| 14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
| 15 #include "base/json/json_reader.h" | 15 #include "base/json/json_reader.h" |
| 16 #include "base/json/json_writer.h" | 16 #include "base/json/json_writer.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/string16.h" | 18 #include "base/string16.h" |
| 19 #include "base/stringize_macros.h" | 19 #include "base/stringize_macros.h" |
| 20 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
| 21 #include "base/time.h" | |
| 22 #include "base/timer.h" | |
| 21 #include "base/utf_string_conversions.h" | 23 #include "base/utf_string_conversions.h" |
| 22 #include "base/values.h" | 24 #include "base/values.h" |
| 23 #include "base/win/scoped_bstr.h" | 25 #include "base/win/scoped_bstr.h" |
| 24 #include "base/win/scoped_comptr.h" | 26 #include "base/win/scoped_comptr.h" |
| 25 #include "remoting/base/scoped_sc_handle_win.h" | 27 #include "remoting/base/scoped_sc_handle_win.h" |
| 26 #include "remoting/host/branding.h" | 28 #include "remoting/host/branding.h" |
| 27 #include "remoting/host/daemon_controller_common_win.h" | 29 #include "remoting/host/daemon_controller_common_win.h" |
| 28 #include "remoting/host/plugin/daemon_installer_win.h" | 30 #include "remoting/host/plugin/daemon_installer_win.h" |
| 29 | 31 |
| 30 // MIDL-generated declarations and definitions. | 32 // MIDL-generated declarations and definitions. |
| 31 #include "remoting/host/elevated_controller.h" | 33 #include "remoting/host/elevated_controller.h" |
| 32 | 34 |
| 33 using base::win::ScopedBstr; | 35 using base::win::ScopedBstr; |
| 34 using base::win::ScopedComPtr; | 36 using base::win::ScopedComPtr; |
| 35 | 37 |
| 36 namespace remoting { | 38 namespace remoting { |
| 37 | 39 |
| 38 namespace { | 40 namespace { |
| 39 | 41 |
| 40 // The COM elevation moniker for the elevated controller. | 42 // The COM elevation moniker for the Elevated Controller. |
| 41 const char16 kDaemonControllerElevationMoniker[] = | 43 const char16 kDaemonControllerElevationMoniker[] = |
| 42 TO_L_STRING("Elevation:Administrator!new:") | 44 TO_L_STRING("Elevation:Administrator!new:") |
| 43 TO_L_STRING("ChromotingElevatedController.ElevatedController"); | 45 TO_L_STRING("ChromotingElevatedController.ElevatedController"); |
| 44 | 46 |
| 45 // Name of the Daemon Controller's worker thread. | 47 // Name of the Daemon Controller's worker thread. |
| 46 const char kDaemonControllerThreadName[] = "Daemon Controller thread"; | 48 const char kDaemonControllerThreadName[] = "Daemon Controller thread"; |
| 47 | 49 |
| 50 // The maximum interval between showing UAC prompts. | |
| 51 const int kUacTimeoutSec = 15 * 60; | |
|
Jamie
2012/04/25 21:20:37
Is this strictly needed as part of this CL? It fee
alexeypa (please no reviews)
2012/04/25 21:59:24
I'll move it to a separate CL.
| |
| 52 | |
| 48 // A base::Thread implementation that initializes COM on the new thread. | 53 // A base::Thread implementation that initializes COM on the new thread. |
| 49 class ComThread : public base::Thread { | 54 class ComThread : public base::Thread { |
| 50 public: | 55 public: |
| 51 explicit ComThread(const char* name); | 56 explicit ComThread(const char* name); |
| 52 | 57 |
| 53 // Activates an elevated instance of the controller and returns the pointer | 58 // Activates an elevated instance of the controller and returns the pointer |
| 54 // to the control interface in |control_out|. This class keeps the ownership | 59 // to the control interface in |control_out|. This class keeps the ownership |
| 55 // of the pointer so the caller should not call call AddRef() or Release(). | 60 // of the pointer so the caller should not call call AddRef() or Release(). |
| 56 HRESULT ActivateElevatedController(IDaemonControl** control_out); | 61 HRESULT ActivateElevatedController(void* window_handle, |
|
Jamie
2012/04/25 21:20:37
HWND?
alexeypa (please no reviews)
2012/04/25 21:59:24
Done.
| |
| 62 IDaemonControl** control_out); | |
| 57 | 63 |
| 58 bool Start(); | 64 bool Start(); |
| 59 | 65 |
| 60 protected: | 66 protected: |
| 61 virtual void Init() OVERRIDE; | 67 virtual void Init() OVERRIDE; |
| 62 virtual void CleanUp() OVERRIDE; | 68 virtual void CleanUp() OVERRIDE; |
| 63 | 69 |
| 70 void ReleaseElevatedController(); | |
| 71 | |
| 64 ScopedComPtr<IDaemonControl> control_; | 72 ScopedComPtr<IDaemonControl> control_; |
| 65 | 73 |
| 74 // This timer is used to release |control_| after a timeout. | |
| 75 base::OneShotTimer<ComThread> release_timer_; | |
| 76 | |
| 66 DISALLOW_COPY_AND_ASSIGN(ComThread); | 77 DISALLOW_COPY_AND_ASSIGN(ComThread); |
| 67 }; | 78 }; |
| 68 | 79 |
| 69 class DaemonControllerWin : public remoting::DaemonController { | 80 class DaemonControllerWin : public remoting::DaemonController { |
| 70 public: | 81 public: |
| 71 DaemonControllerWin(); | 82 DaemonControllerWin(); |
| 72 virtual ~DaemonControllerWin(); | 83 virtual ~DaemonControllerWin(); |
| 73 | 84 |
| 74 virtual State GetState() OVERRIDE; | 85 virtual State GetState() OVERRIDE; |
| 75 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; | 86 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; |
| 76 virtual void SetConfigAndStart( | 87 virtual void SetConfigAndStart( |
| 77 scoped_ptr<base::DictionaryValue> config, | 88 scoped_ptr<base::DictionaryValue> config, |
| 78 const CompletionCallback& done_callback) OVERRIDE; | 89 const CompletionCallback& done_callback) OVERRIDE; |
| 79 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, | 90 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, |
| 80 const CompletionCallback& done_callback) OVERRIDE; | 91 const CompletionCallback& done_callback) OVERRIDE; |
| 81 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; | 92 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; |
| 93 virtual void SetWindow(void* window_handle) OVERRIDE; | |
| 82 | 94 |
| 83 private: | 95 private: |
| 84 // Converts a Windows service status code to a Daemon state. | 96 // Converts a Windows service status code to a Daemon state. |
| 85 static State ConvertToDaemonState(DWORD service_state); | 97 static State ConvertToDaemonState(DWORD service_state); |
| 86 | 98 |
| 87 // Converts HRESULT to the AsyncResult. | 99 // Converts HRESULT to the AsyncResult. |
| 88 static AsyncResult HResultToAsyncResult(HRESULT hr); | 100 static AsyncResult HResultToAsyncResult(HRESULT hr); |
| 89 | 101 |
| 90 // Procedes with the daemon configuration if the installation succeeded, | 102 // Procedes with the daemon configuration if the installation succeeded, |
| 91 // otherwise reports the error. | 103 // otherwise reports the error. |
| 92 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config, | 104 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config, |
| 93 const CompletionCallback& done_callback, | 105 const CompletionCallback& done_callback, |
| 94 HRESULT result); | 106 HRESULT result); |
| 95 | 107 |
| 96 // Opens the Chromoting service returning its handle in |service_out|. | 108 // Opens the Chromoting service returning its handle in |service_out|. |
| 97 DWORD OpenService(ScopedScHandle* service_out); | 109 DWORD OpenService(ScopedScHandle* service_out); |
| 98 | 110 |
| 99 // The functions that actually do the work. They should be called in | 111 // The functions that actually do the work. They should be called in |
| 100 // the context of |worker_thread_|; | 112 // the context of |worker_thread_|; |
| 101 void DoGetConfig(const GetConfigCallback& callback); | 113 void DoGetConfig(const GetConfigCallback& callback); |
| 102 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, | 114 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, |
| 103 const CompletionCallback& done_callback); | 115 const CompletionCallback& done_callback); |
| 104 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, | 116 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, |
| 105 const CompletionCallback& done_callback); | 117 const CompletionCallback& done_callback); |
| 106 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, | 118 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, |
| 107 const CompletionCallback& done_callback); | 119 const CompletionCallback& done_callback); |
| 108 void DoStop(const CompletionCallback& done_callback); | 120 void DoStop(const CompletionCallback& done_callback); |
| 121 void DoSetWindow(void* window_handle); | |
| 122 | |
| 123 // Handle of the plugin window. | |
| 124 void* window_handle_; | |
|
Jamie
2012/04/25 21:20:37
Store as an HWND?
alexeypa (please no reviews)
2012/04/25 21:59:24
Done.
| |
| 109 | 125 |
| 110 // The worker thread used for servicing long running operations. | 126 // The worker thread used for servicing long running operations. |
| 111 ComThread worker_thread_; | 127 ComThread worker_thread_; |
| 112 | 128 |
| 113 scoped_ptr<DaemonInstallerWin> installer_; | 129 scoped_ptr<DaemonInstallerWin> installer_; |
| 114 | 130 |
| 115 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); | 131 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); |
| 116 }; | 132 }; |
| 117 | 133 |
| 118 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { | 134 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { |
| 119 } | 135 } |
| 120 | 136 |
| 121 void ComThread::Init() { | |
| 122 CoInitialize(NULL); | |
| 123 } | |
| 124 | |
| 125 void ComThread::CleanUp() { | |
| 126 control_.Release(); | |
| 127 CoUninitialize(); | |
| 128 } | |
| 129 | |
| 130 HRESULT ComThread::ActivateElevatedController( | 137 HRESULT ComThread::ActivateElevatedController( |
| 138 void* window_handle, | |
| 131 IDaemonControl** control_out) { | 139 IDaemonControl** control_out) { |
| 132 // Chache the instance of Elevated Controller to prevent a UAC prompt on every | 140 // Cache an instance of the Elevated Controller to prevent a UAC prompt on |
| 133 // operation. | 141 // every operation. |
| 134 if (control_.get() == NULL) { | 142 if (control_.get() == NULL) { |
| 135 BIND_OPTS3 bind_options; | 143 BIND_OPTS3 bind_options; |
| 136 memset(&bind_options, 0, sizeof(bind_options)); | 144 memset(&bind_options, 0, sizeof(bind_options)); |
| 137 bind_options.cbStruct = sizeof(bind_options); | 145 bind_options.cbStruct = sizeof(bind_options); |
| 138 bind_options.hwnd = NULL; | 146 bind_options.hwnd = |
| 147 GetTopLevelWindow(reinterpret_cast<HWND>(window_handle)); | |
| 139 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; | 148 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; |
| 140 | 149 |
| 141 HRESULT hr = ::CoGetObject( | 150 HRESULT hr = ::CoGetObject( |
| 142 kDaemonControllerElevationMoniker, | 151 kDaemonControllerElevationMoniker, |
| 143 &bind_options, | 152 &bind_options, |
| 144 IID_IDaemonControl, | 153 IID_IDaemonControl, |
| 145 control_.ReceiveVoid()); | 154 control_.ReceiveVoid()); |
| 146 if (FAILED(hr)) { | 155 if (FAILED(hr)) { |
| 147 return hr; | 156 return hr; |
| 148 } | 157 } |
| 158 | |
| 159 // Release |control_| upon expiration of the timeout. | |
| 160 release_timer_.Start(FROM_HERE, | |
| 161 base::TimeDelta::FromSeconds(kUacTimeoutSec), | |
| 162 this, &ComThread::ReleaseElevatedController); | |
| 149 } | 163 } |
| 150 | 164 |
| 151 *control_out = control_.get(); | 165 *control_out = control_.get(); |
| 152 return S_OK; | 166 return S_OK; |
| 153 } | 167 } |
| 154 | 168 |
| 155 bool ComThread::Start() { | 169 bool ComThread::Start() { |
| 156 // N.B. The single threaded COM apartment must be run on a UI message loop. | 170 // N.B. The single threaded COM apartment must be run on a UI message loop. |
| 157 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); | 171 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); |
| 158 return StartWithOptions(thread_options); | 172 return StartWithOptions(thread_options); |
| 159 } | 173 } |
| 160 | 174 |
| 175 void ComThread::Init() { | |
| 176 CoInitialize(NULL); | |
| 177 } | |
| 178 | |
| 179 void ComThread::CleanUp() { | |
| 180 ReleaseElevatedController(); | |
| 181 CoUninitialize(); | |
| 182 } | |
| 183 | |
| 184 void ComThread::ReleaseElevatedController() { | |
| 185 control_.Release(); | |
| 186 } | |
| 187 | |
|
Jamie
2012/04/25 21:20:37
It's not clear to me which of the previous functio
alexeypa (please no reviews)
2012/04/25 21:59:24
I'll move the timeout change to a separate CL.
| |
| 161 DaemonControllerWin::DaemonControllerWin() | 188 DaemonControllerWin::DaemonControllerWin() |
| 162 : worker_thread_(kDaemonControllerThreadName) { | 189 : window_handle_(NULL), |
| 190 worker_thread_(kDaemonControllerThreadName) { | |
| 163 if (!worker_thread_.Start()) { | 191 if (!worker_thread_.Start()) { |
| 164 LOG(FATAL) << "Failed to start the Daemon Controller worker thread."; | 192 LOG(FATAL) << "Failed to start the Daemon Controller worker thread."; |
| 165 } | 193 } |
| 166 } | 194 } |
| 167 | 195 |
| 168 DaemonControllerWin::~DaemonControllerWin() { | 196 DaemonControllerWin::~DaemonControllerWin() { |
| 169 worker_thread_.Stop(); | 197 worker_thread_.Stop(); |
| 170 } | 198 } |
| 171 | 199 |
| 172 remoting::DaemonController::State DaemonControllerWin::GetState() { | 200 remoting::DaemonController::State DaemonControllerWin::GetState() { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 base::Unretained(this), base::Passed(&config), done_callback)); | 248 base::Unretained(this), base::Passed(&config), done_callback)); |
| 221 } | 249 } |
| 222 | 250 |
| 223 void DaemonControllerWin::Stop(const CompletionCallback& done_callback) { | 251 void DaemonControllerWin::Stop(const CompletionCallback& done_callback) { |
| 224 worker_thread_.message_loop_proxy()->PostTask( | 252 worker_thread_.message_loop_proxy()->PostTask( |
| 225 FROM_HERE, base::Bind( | 253 FROM_HERE, base::Bind( |
| 226 &DaemonControllerWin::DoStop, base::Unretained(this), | 254 &DaemonControllerWin::DoStop, base::Unretained(this), |
| 227 done_callback)); | 255 done_callback)); |
| 228 } | 256 } |
| 229 | 257 |
| 258 void DaemonControllerWin::SetWindow(void* window_handle) { | |
| 259 worker_thread_.message_loop_proxy()->PostTask( | |
| 260 FROM_HERE, base::Bind( | |
| 261 &DaemonControllerWin::DoSetWindow, base::Unretained(this), | |
| 262 window_handle)); | |
| 263 } | |
| 264 | |
| 230 // static | 265 // static |
| 231 remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState( | 266 remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState( |
| 232 DWORD service_state) { | 267 DWORD service_state) { |
| 233 switch (service_state) { | 268 switch (service_state) { |
| 234 case SERVICE_RUNNING: | 269 case SERVICE_RUNNING: |
| 235 return STATE_STARTED; | 270 return STATE_STARTED; |
| 236 | 271 |
| 237 case SERVICE_CONTINUE_PENDING: | 272 case SERVICE_CONTINUE_PENDING: |
| 238 case SERVICE_START_PENDING: | 273 case SERVICE_START_PENDING: |
| 239 return STATE_STARTING; | 274 return STATE_STARTING; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 | 395 |
| 361 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); | 396 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); |
| 362 } | 397 } |
| 363 | 398 |
| 364 void DaemonControllerWin::DoInstallAsNeededAndStart( | 399 void DaemonControllerWin::DoInstallAsNeededAndStart( |
| 365 scoped_ptr<base::DictionaryValue> config, | 400 scoped_ptr<base::DictionaryValue> config, |
| 366 const CompletionCallback& done_callback) { | 401 const CompletionCallback& done_callback) { |
| 367 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 402 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| 368 | 403 |
| 369 IDaemonControl* control = NULL; | 404 IDaemonControl* control = NULL; |
| 370 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | 405 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, |
| 406 &control); | |
| 371 | 407 |
| 372 // Just configure and start the Daemon Controller if it is installed already. | 408 // Just configure and start the Daemon Controller if it is installed already. |
| 373 if (SUCCEEDED(hr)) { | 409 if (SUCCEEDED(hr)) { |
| 374 DoSetConfigAndStart(config.Pass(), done_callback); | 410 DoSetConfigAndStart(config.Pass(), done_callback); |
| 375 return; | 411 return; |
| 376 } | 412 } |
| 377 | 413 |
| 378 // Otherwise, install it if its COM registration entry is missing. | 414 // Otherwise, install it if its COM registration entry is missing. |
| 379 if (hr == CO_E_CLASSSTRING) { | 415 if (hr == CO_E_CLASSSTRING) { |
| 380 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create( | 416 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create( |
| 417 window_handle_, | |
| 381 base::Bind(&DaemonControllerWin::OnInstallationComplete, | 418 base::Bind(&DaemonControllerWin::OnInstallationComplete, |
| 382 base::Unretained(this), | 419 base::Unretained(this), |
| 383 base::Passed(&config), | 420 base::Passed(&config), |
| 384 done_callback)); | 421 done_callback)); |
| 385 if (installer.get()) { | 422 if (installer.get()) { |
| 386 DCHECK(!installer_.get()); | 423 DCHECK(!installer_.get()); |
| 387 installer_ = installer.Pass(); | 424 installer_ = installer.Pass(); |
| 388 installer_->Install(); | 425 installer_->Install(); |
| 389 } | 426 } |
| 390 } else { | 427 } else { |
| 391 LOG(ERROR) << "Failed to initiate the Chromoting Host installation " | 428 LOG(ERROR) << "Failed to initiate the Chromoting Host installation " |
| 392 << "(error: 0x" << std::hex << hr << std::dec << ")."; | 429 << "(error: 0x" << std::hex << hr << std::dec << ")."; |
| 393 done_callback.Run(HResultToAsyncResult(hr)); | 430 done_callback.Run(HResultToAsyncResult(hr)); |
| 394 } | 431 } |
| 395 } | 432 } |
| 396 | 433 |
| 397 void DaemonControllerWin::DoSetConfigAndStart( | 434 void DaemonControllerWin::DoSetConfigAndStart( |
| 398 scoped_ptr<base::DictionaryValue> config, | 435 scoped_ptr<base::DictionaryValue> config, |
| 399 const CompletionCallback& done_callback) { | 436 const CompletionCallback& done_callback) { |
| 400 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 437 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| 401 | 438 |
| 402 IDaemonControl* control = NULL; | 439 IDaemonControl* control = NULL; |
| 403 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | 440 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, |
| 441 &control); | |
| 404 if (FAILED(hr)) { | 442 if (FAILED(hr)) { |
| 405 done_callback.Run(HResultToAsyncResult(hr)); | 443 done_callback.Run(HResultToAsyncResult(hr)); |
| 406 return; | 444 return; |
| 407 } | 445 } |
| 408 | 446 |
| 409 // Store the configuration. | 447 // Store the configuration. |
| 410 std::string file_content; | 448 std::string file_content; |
| 411 base::JSONWriter::Write(config.get(), &file_content); | 449 base::JSONWriter::Write(config.get(), &file_content); |
| 412 | 450 |
| 413 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str()); | 451 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str()); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 428 } | 466 } |
| 429 | 467 |
| 430 void DaemonControllerWin::DoUpdateConfig( | 468 void DaemonControllerWin::DoUpdateConfig( |
| 431 scoped_ptr<base::DictionaryValue> config, | 469 scoped_ptr<base::DictionaryValue> config, |
| 432 const CompletionCallback& done_callback) { | 470 const CompletionCallback& done_callback) { |
| 433 // TODO(simonmorris): Much of this code was copied from DoSetConfigAndStart(). | 471 // TODO(simonmorris): Much of this code was copied from DoSetConfigAndStart(). |
| 434 // Refactor. | 472 // Refactor. |
| 435 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 473 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| 436 | 474 |
| 437 IDaemonControl* control = NULL; | 475 IDaemonControl* control = NULL; |
| 438 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | 476 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, |
| 477 &control); | |
| 439 if (FAILED(hr)) { | 478 if (FAILED(hr)) { |
| 440 done_callback.Run(HResultToAsyncResult(hr)); | 479 done_callback.Run(HResultToAsyncResult(hr)); |
| 441 return; | 480 return; |
| 442 } | 481 } |
| 443 | 482 |
| 444 // Store the configuration. | 483 // Store the configuration. |
| 445 std::string file_content; | 484 std::string file_content; |
| 446 base::JSONWriter::Write(config.get(), &file_content); | 485 base::JSONWriter::Write(config.get(), &file_content); |
| 447 | 486 |
| 448 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str()); | 487 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str()); |
| 449 if (host_config == NULL) { | 488 if (host_config == NULL) { |
| 450 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); | 489 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); |
| 451 return; | 490 return; |
| 452 } | 491 } |
| 453 | 492 |
| 454 hr = control->UpdateConfig(host_config); | 493 hr = control->UpdateConfig(host_config); |
| 455 done_callback.Run(HResultToAsyncResult(hr)); | 494 done_callback.Run(HResultToAsyncResult(hr)); |
| 456 } | 495 } |
| 457 | 496 |
| 458 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { | 497 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { |
| 459 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 498 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| 460 | 499 |
| 461 IDaemonControl* control = NULL; | 500 IDaemonControl* control = NULL; |
| 462 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | 501 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, |
| 502 &control); | |
| 463 if (FAILED(hr)) { | 503 if (FAILED(hr)) { |
| 464 done_callback.Run(HResultToAsyncResult(hr)); | 504 done_callback.Run(HResultToAsyncResult(hr)); |
| 465 return; | 505 return; |
| 466 } | 506 } |
| 467 | 507 |
| 468 hr = control->StopDaemon(); | 508 hr = control->StopDaemon(); |
| 469 done_callback.Run(HResultToAsyncResult(hr)); | 509 done_callback.Run(HResultToAsyncResult(hr)); |
| 470 } | 510 } |
| 471 | 511 |
| 512 void DaemonControllerWin::DoSetWindow(void* window_handle) { | |
| 513 window_handle_ = window_handle; | |
| 514 } | |
| 515 | |
| 472 } // namespace | 516 } // namespace |
| 473 | 517 |
| 474 scoped_ptr<DaemonController> remoting::DaemonController::Create() { | 518 scoped_ptr<DaemonController> remoting::DaemonController::Create() { |
| 475 return scoped_ptr<DaemonController>(new DaemonControllerWin()); | 519 return scoped_ptr<DaemonController>(new DaemonControllerWin()); |
| 476 } | 520 } |
| 477 | 521 |
| 478 } // namespace remoting | 522 } // namespace remoting |
| OLD | NEW |