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/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 12 #include "base/file_path.h" | 13 #include "base/file_path.h" |
| 13 #include "base/file_util.h" | 14 #include "base/file_util.h" |
| 14 #include "base/json/json_reader.h" | 15 #include "base/json/json_reader.h" |
| 15 #include "base/json/json_writer.h" | 16 #include "base/json/json_writer.h" |
| 16 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/string16.h" | |
| 19 #include "base/stringize_macros.h" | |
| 20 #include "base/synchronization/lock.h" | |
| 17 #include "base/threading/thread.h" | 21 #include "base/threading/thread.h" |
| 18 #include "base/utf_string_conversions.h" | 22 #include "base/utf_string_conversions.h" |
| 19 #include "base/values.h" | 23 #include "base/values.h" |
| 24 #include "base/win/scoped_bstr.h" | |
| 25 #include "base/win/scoped_comptr.h" | |
| 20 #include "remoting/base/scoped_sc_handle_win.h" | 26 #include "remoting/base/scoped_sc_handle_win.h" |
| 21 #include "remoting/host/branding.h" | 27 #include "remoting/host/branding.h" |
| 28 #include "remoting/host/plugin/daemon_installer_win.h" | |
| 22 | 29 |
| 23 // MIDL-generated declarations and definitions. | 30 // MIDL-generated declarations and definitions. |
| 24 #include "remoting/host/elevated_controller.h" | 31 #include "remoting/host/elevated_controller.h" |
| 25 | 32 |
| 33 using base::win::ScopedBstr; | |
| 34 using base::win::ScopedComPtr; | |
| 35 | |
| 26 namespace remoting { | 36 namespace remoting { |
| 27 | 37 |
| 28 namespace { | 38 namespace { |
| 29 | 39 |
| 30 // The COM elevation moniker for the elevated controller. | 40 // The COM elevation moniker for the elevated controller. |
| 31 const char kElevationMoniker[] = "Elevation:Administrator!new:" | 41 const char16 kDaemonControllerElevationMoniker[] = |
| 32 "{430a9403-8176-4733-afdc-0b325a8fda84}"; | 42 TO_L_STRING("Elevation:Administrator!new:") |
| 43 TO_L_STRING("ChromotingElevatedController.ElevatedController"); | |
| 33 | 44 |
| 34 // Name of the Daemon Controller's worker thread. | 45 // Name of the Daemon Controller's worker thread. |
| 35 const char kDaemonControllerThreadName[] = "Daemon Controller thread"; | 46 const char kDaemonControllerThreadName[] = "Daemon Controller thread"; |
| 36 | 47 |
| 37 // A base::Thread implementation that initializes COM on the new thread. | 48 // A base::Thread implementation that initializes COM on the new thread. |
| 38 class ComThread : public base::Thread { | 49 class ComThread : public base::Thread { |
| 39 public: | 50 public: |
| 40 explicit ComThread(const char* name); | 51 explicit ComThread(const char* name); |
| 41 | 52 |
| 42 // Activates an elevated instance of the controller and returns the pointer | 53 // Activates an elevated instance of the controller and returns the pointer |
| 43 // to the control interface in |control_out|. This class keeps the ownership | 54 // to the control interface in |control_out|. This class keeps the ownership |
| 44 // of the pointer so the caller should not call call AddRef() or Release(). | 55 // of the pointer so the caller should not call call AddRef() or Release(). |
| 45 HRESULT ActivateElevatedController(IDaemonControl** control_out); | 56 HRESULT ActivateElevatedController(IDaemonControl** control_out); |
| 46 | 57 |
| 47 bool Start(); | 58 bool Start(); |
| 48 | 59 |
| 49 protected: | 60 protected: |
| 50 virtual void Init() OVERRIDE; | 61 virtual void Init() OVERRIDE; |
| 51 virtual void CleanUp() OVERRIDE; | 62 virtual void CleanUp() OVERRIDE; |
| 52 | 63 |
| 53 IDaemonControl* control_; | 64 ScopedComPtr<IDaemonControl> control_; |
| 54 | 65 |
| 55 DISALLOW_COPY_AND_ASSIGN(ComThread); | 66 DISALLOW_COPY_AND_ASSIGN(ComThread); |
| 56 }; | 67 }; |
| 57 | 68 |
| 58 class DaemonControllerWin : public remoting::DaemonController { | 69 class DaemonControllerWin : public remoting::DaemonController { |
| 59 public: | 70 public: |
| 60 DaemonControllerWin(); | 71 DaemonControllerWin(); |
| 61 virtual ~DaemonControllerWin(); | 72 virtual ~DaemonControllerWin(); |
| 62 | 73 |
| 63 virtual State GetState() OVERRIDE; | 74 virtual State GetState() OVERRIDE; |
| 64 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; | 75 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; |
| 65 virtual void SetConfigAndStart( | 76 virtual void SetConfigAndStart( |
| 66 scoped_ptr<base::DictionaryValue> config, | 77 scoped_ptr<base::DictionaryValue> config, |
| 67 const CompletionCallback& done_callback) OVERRIDE; | 78 const CompletionCallback& done_callback) OVERRIDE; |
| 68 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, | 79 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, |
| 69 const CompletionCallback& done_callback) OVERRIDE; | 80 const CompletionCallback& done_callback) OVERRIDE; |
| 70 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; | 81 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; |
| 71 | 82 |
| 72 private: | 83 private: |
| 73 // Converts a Windows service status code to a Daemon state. | 84 // Converts a Windows service status code to a Daemon state. |
| 74 static State ConvertToDaemonState(DWORD service_state); | 85 static State ConvertToDaemonState(DWORD service_state); |
| 75 | 86 |
| 76 // Converts HRESULT to the AsyncResult. | 87 // Converts HRESULT to the AsyncResult. |
| 77 static AsyncResult HResultToAsyncResult(HRESULT hr); | 88 static AsyncResult HResultToAsyncResult(HRESULT hr); |
| 78 | 89 |
| 90 // Procedes with the daemon configuration if the installation succeeded, | |
| 91 // otherwise reports the error. | |
| 92 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config, | |
| 93 const CompletionCallback& done_callback, | |
| 94 HRESULT result); | |
| 95 | |
| 79 // Opens the Chromoting service returning its handle in |service_out|. | 96 // Opens the Chromoting service returning its handle in |service_out|. |
| 80 DWORD OpenService(ScopedScHandle* service_out); | 97 DWORD OpenService(ScopedScHandle* service_out); |
| 81 | 98 |
| 82 // The functions that actually do the work. They should be called in | 99 // The functions that actually do the work. They should be called in |
| 83 // the context of |worker_thread_|; | 100 // the context of |worker_thread_|; |
| 84 void DoGetConfig(const GetConfigCallback& callback); | 101 void DoGetConfig(const GetConfigCallback& callback); |
| 102 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, | |
| 103 const CompletionCallback& done_callback); | |
| 85 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, | 104 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, |
| 86 const CompletionCallback& done_callback); | 105 const CompletionCallback& done_callback); |
| 87 void DoStop(const CompletionCallback& done_callback); | 106 void DoStop(const CompletionCallback& done_callback); |
| 88 | 107 |
| 89 // The worker thread used for servicing long running operations. | 108 // The worker thread used for servicing long running operations. |
| 90 ComThread worker_thread_; | 109 ComThread worker_thread_; |
| 91 | 110 |
| 111 // The lock protecting the data members below. | |
| 112 base::Lock lock_; | |
|
Sergey Ulanov
2012/04/09 22:32:58
Don't think you need this lock anymore - |installe
alexeypa (please no reviews)
2012/04/10 00:20:06
Done.
| |
| 113 | |
| 114 scoped_ptr<DaemonInstallerWin> installer_; | |
| 115 | |
| 92 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); | 116 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); |
| 93 }; | 117 }; |
| 94 | 118 |
| 95 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { | 119 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { |
| 96 } | 120 } |
| 97 | 121 |
| 98 void ComThread::Init() { | 122 void ComThread::Init() { |
| 99 CoInitialize(NULL); | 123 CoInitialize(NULL); |
| 100 } | 124 } |
| 101 | 125 |
| 102 void ComThread::CleanUp() { | 126 void ComThread::CleanUp() { |
| 103 if (control_ != NULL) | 127 control_.Release(); |
| 104 control_->Release(); | |
| 105 CoUninitialize(); | 128 CoUninitialize(); |
| 106 } | 129 } |
| 107 | 130 |
| 108 HRESULT ComThread::ActivateElevatedController( | 131 HRESULT ComThread::ActivateElevatedController( |
| 109 IDaemonControl** control_out) { | 132 IDaemonControl** control_out) { |
| 110 // Chache the instance of Elevated Controller to prevent a UAC prompt on every | 133 // Chache the instance of Elevated Controller to prevent a UAC prompt on every |
| 111 // operation. | 134 // operation. |
| 112 if (control_ == NULL) { | 135 if (control_.get() == NULL) { |
| 113 BIND_OPTS3 bind_options; | 136 BIND_OPTS3 bind_options; |
| 114 memset(&bind_options, 0, sizeof(bind_options)); | 137 memset(&bind_options, 0, sizeof(bind_options)); |
| 115 bind_options.cbStruct = sizeof(bind_options); | 138 bind_options.cbStruct = sizeof(bind_options); |
| 116 bind_options.hwnd = NULL; | 139 bind_options.hwnd = NULL; |
| 117 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; | 140 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; |
| 118 | 141 |
| 119 HRESULT hr = ::CoGetObject(ASCIIToUTF16(kElevationMoniker).c_str(), | 142 HRESULT hr = ::CoGetObject( |
| 120 &bind_options, | 143 kDaemonControllerElevationMoniker, |
| 121 IID_IDaemonControl, | 144 &bind_options, |
| 122 reinterpret_cast<void**>(&control_)); | 145 IID_IDaemonControl, |
| 146 control_.ReceiveVoid()); | |
| 123 if (FAILED(hr)) { | 147 if (FAILED(hr)) { |
| 124 LOG(ERROR) << "Failed to create the elevated controller (error: 0x" | |
| 125 << std::hex << hr << std::dec << ")."; | |
| 126 return hr; | 148 return hr; |
| 127 } | 149 } |
| 128 } | 150 } |
| 129 | 151 |
| 130 *control_out = control_; | 152 *control_out = control_.get(); |
| 131 return S_OK; | 153 return S_OK; |
| 132 } | 154 } |
| 133 | 155 |
| 134 bool ComThread::Start() { | 156 bool ComThread::Start() { |
| 135 // N.B. The single threaded COM apartment must be run on a UI message loop. | 157 // N.B. The single threaded COM apartment must be run on a UI message loop. |
| 136 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); | 158 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); |
| 137 return StartWithOptions(thread_options); | 159 return StartWithOptions(thread_options); |
| 138 } | 160 } |
| 139 | 161 |
| 140 DaemonControllerWin::DaemonControllerWin() | 162 DaemonControllerWin::DaemonControllerWin() |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 161 return ConvertToDaemonState(status.dwCurrentState); | 183 return ConvertToDaemonState(status.dwCurrentState); |
| 162 } else { | 184 } else { |
| 163 LOG_GETLASTERROR(ERROR) | 185 LOG_GETLASTERROR(ERROR) |
| 164 << "Failed to query the state of the '" << kWindowsServiceName | 186 << "Failed to query the state of the '" << kWindowsServiceName |
| 165 << "' service"; | 187 << "' service"; |
| 166 return STATE_UNKNOWN; | 188 return STATE_UNKNOWN; |
| 167 } | 189 } |
| 168 break; | 190 break; |
| 169 } | 191 } |
| 170 case ERROR_SERVICE_DOES_NOT_EXIST: | 192 case ERROR_SERVICE_DOES_NOT_EXIST: |
| 171 return STATE_NOT_IMPLEMENTED; | 193 return STATE_NOT_INSTALLED; |
| 172 default: | 194 default: |
| 173 return STATE_UNKNOWN; | 195 return STATE_UNKNOWN; |
| 174 } | 196 } |
| 175 } | 197 } |
| 176 | 198 |
| 177 void DaemonControllerWin::GetConfig(const GetConfigCallback& callback) { | 199 void DaemonControllerWin::GetConfig(const GetConfigCallback& callback) { |
| 178 worker_thread_.message_loop_proxy()->PostTask( | 200 worker_thread_.message_loop_proxy()->PostTask( |
| 179 FROM_HERE, | 201 FROM_HERE, |
| 180 base::Bind(&DaemonControllerWin::DoGetConfig, | 202 base::Bind(&DaemonControllerWin::DoGetConfig, |
| 181 base::Unretained(this), callback)); | 203 base::Unretained(this), callback)); |
| 182 } | 204 } |
| 183 | 205 |
| 184 void DaemonControllerWin::SetConfigAndStart( | 206 void DaemonControllerWin::SetConfigAndStart( |
| 185 scoped_ptr<base::DictionaryValue> config, | 207 scoped_ptr<base::DictionaryValue> config, |
| 186 const CompletionCallback& done_callback) { | 208 const CompletionCallback& done_callback) { |
| 187 | 209 |
| 188 worker_thread_.message_loop_proxy()->PostTask( | 210 worker_thread_.message_loop_proxy()->PostTask( |
| 189 FROM_HERE, base::Bind( | 211 FROM_HERE, base::Bind( |
| 190 &DaemonControllerWin::DoSetConfigAndStart, base::Unretained(this), | 212 &DaemonControllerWin::DoInstallAsNeededAndStart, |
| 191 base::Passed(&config), done_callback)); | 213 base::Unretained(this), base::Passed(&config), done_callback)); |
| 192 } | 214 } |
| 193 | 215 |
| 194 void DaemonControllerWin::UpdateConfig( | 216 void DaemonControllerWin::UpdateConfig( |
| 195 scoped_ptr<base::DictionaryValue> config, | 217 scoped_ptr<base::DictionaryValue> config, |
| 196 const CompletionCallback& done_callback) { | 218 const CompletionCallback& done_callback) { |
| 197 NOTIMPLEMENTED(); | 219 NOTIMPLEMENTED(); |
| 198 done_callback.Run(RESULT_FAILED); | 220 done_callback.Run(RESULT_FAILED); |
| 199 } | 221 } |
| 200 | 222 |
| 201 void DaemonControllerWin::Stop(const CompletionCallback& done_callback) { | 223 void DaemonControllerWin::Stop(const CompletionCallback& done_callback) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 } | 256 } |
| 235 | 257 |
| 236 // static | 258 // static |
| 237 DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult( | 259 DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult( |
| 238 HRESULT hr) { | 260 HRESULT hr) { |
| 239 // TODO(sergeyu): Report other errors to the webapp once it knows | 261 // TODO(sergeyu): Report other errors to the webapp once it knows |
| 240 // how to handle them. | 262 // how to handle them. |
| 241 return FAILED(hr) ? RESULT_FAILED : RESULT_OK; | 263 return FAILED(hr) ? RESULT_FAILED : RESULT_OK; |
| 242 } | 264 } |
| 243 | 265 |
| 266 void DaemonControllerWin::OnInstallationComplete( | |
| 267 scoped_ptr<base::DictionaryValue> config, | |
| 268 const CompletionCallback& done_callback, | |
| 269 HRESULT result) { | |
| 270 if (SUCCEEDED(result)) { | |
|
Sergey Ulanov
2012/04/09 22:32:58
add DCHECK(worker_thread.message_loop_proxy()->Bel
alexeypa (please no reviews)
2012/04/10 00:20:06
Done.
| |
| 271 DoSetConfigAndStart(config.Pass(), done_callback); | |
| 272 } else { | |
| 273 LOG(ERROR) << "Failed to install the Chromoting Host " | |
| 274 << "(error: 0x" << std::hex << result << std::dec << ")."; | |
| 275 done_callback.Run(HResultToAsyncResult(result)); | |
| 276 } | |
| 277 | |
| 278 base::AutoLock lock(lock_); | |
| 279 DCHECK(installer_.get() != NULL); | |
| 280 installer_.reset(); | |
| 281 } | |
| 282 | |
| 244 DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) { | 283 DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) { |
| 245 // Open the service and query its current state. | 284 // Open the service and query its current state. |
| 246 ScopedScHandle scmanager( | 285 ScopedScHandle scmanager( |
| 247 ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, | 286 ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, |
| 248 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); | 287 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); |
| 249 if (!scmanager.IsValid()) { | 288 if (!scmanager.IsValid()) { |
| 250 DWORD error = GetLastError(); | 289 DWORD error = GetLastError(); |
| 251 LOG_GETLASTERROR(ERROR) | 290 LOG_GETLASTERROR(ERROR) |
| 252 << "Failed to connect to the service control manager"; | 291 << "Failed to connect to the service control manager"; |
| 253 return error; | 292 return error; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 271 | 310 |
| 272 void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { | 311 void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { |
| 273 IDaemonControl* control = NULL; | 312 IDaemonControl* control = NULL; |
| 274 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | 313 HRESULT hr = worker_thread_.ActivateElevatedController(&control); |
| 275 if (FAILED(hr)) { | 314 if (FAILED(hr)) { |
| 276 callback.Run(scoped_ptr<base::DictionaryValue>()); | 315 callback.Run(scoped_ptr<base::DictionaryValue>()); |
| 277 return; | 316 return; |
| 278 } | 317 } |
| 279 | 318 |
| 280 // Get the host configuration. | 319 // Get the host configuration. |
| 281 BSTR host_config = NULL; | 320 ScopedBstr host_config; |
| 282 hr = control->GetConfig(&host_config); | 321 hr = control->GetConfig(host_config.Receive()); |
| 283 if (FAILED(hr)) { | 322 if (FAILED(hr)) { |
| 284 callback.Run(scoped_ptr<base::DictionaryValue>()); | 323 callback.Run(scoped_ptr<base::DictionaryValue>()); |
| 285 return; | 324 return; |
| 286 } | 325 } |
| 287 | 326 |
| 288 string16 file_content(static_cast<char16*>(host_config), | 327 string16 file_content(static_cast<BSTR>(host_config), host_config.Length()); |
| 289 ::SysStringLen(host_config)); | |
| 290 SysFreeString(host_config); | |
| 291 | 328 |
| 292 // Parse the string into a dictionary. | 329 // Parse the string into a dictionary. |
| 293 scoped_ptr<base::Value> config( | 330 scoped_ptr<base::Value> config( |
| 294 base::JSONReader::Read(UTF16ToUTF8(file_content), true)); | 331 base::JSONReader::Read(UTF16ToUTF8(file_content), true)); |
| 295 | 332 |
| 296 base::DictionaryValue* dictionary; | 333 base::DictionaryValue* dictionary; |
| 297 if (config.get() == NULL || !config->GetAsDictionary(&dictionary)) { | 334 if (config.get() == NULL || !config->GetAsDictionary(&dictionary)) { |
| 298 callback.Run(scoped_ptr<base::DictionaryValue>()); | 335 callback.Run(scoped_ptr<base::DictionaryValue>()); |
| 299 return; | 336 return; |
| 300 } | 337 } |
| 301 | 338 |
| 302 config.release(); | 339 config.release(); |
| 303 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); | 340 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); |
| 304 } | 341 } |
| 305 | 342 |
| 343 void DaemonControllerWin::DoInstallAsNeededAndStart( | |
| 344 scoped_ptr<base::DictionaryValue> config, | |
| 345 const CompletionCallback& done_callback) { | |
| 346 IDaemonControl* control = NULL; | |
|
Sergey Ulanov
2012/04/09 22:32:58
DCHECK(worker_thread.message_loop_proxy()->Belongs
alexeypa (please no reviews)
2012/04/10 00:20:06
Done.
| |
| 347 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | |
| 348 | |
| 349 // Just configure and start the Daemon Controller if it is installed already. | |
| 350 if (SUCCEEDED(hr)) { | |
| 351 DoSetConfigAndStart(config.Pass(), done_callback); | |
| 352 return; | |
| 353 } | |
| 354 | |
| 355 // Otherwise, install it if it's COM registration entry is missing. | |
| 356 if (hr == CO_E_CLASSSTRING) { | |
| 357 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create( | |
| 358 base::Bind(&DaemonControllerWin::OnInstallationComplete, | |
| 359 base::Unretained(this), | |
| 360 base::Passed(&config), | |
| 361 done_callback)); | |
| 362 if (installer.get()) { | |
| 363 { | |
| 364 base::AutoLock lock(lock_); | |
| 365 | |
| 366 DCHECK(!installer_.get()); | |
| 367 installer_ = installer.Pass(); | |
| 368 } | |
| 369 | |
| 370 installer_->Install(); | |
| 371 } | |
| 372 } else { | |
| 373 LOG(ERROR) << "Failed to initiate the Chromoting Host installation " | |
| 374 << "(error: 0x" << std::hex << hr << std::dec << ")."; | |
| 375 done_callback.Run(HResultToAsyncResult(hr)); | |
| 376 } | |
| 377 } | |
| 378 | |
| 306 void DaemonControllerWin::DoSetConfigAndStart( | 379 void DaemonControllerWin::DoSetConfigAndStart( |
| 307 scoped_ptr<base::DictionaryValue> config, | 380 scoped_ptr<base::DictionaryValue> config, |
| 308 const CompletionCallback& done_callback) { | 381 const CompletionCallback& done_callback) { |
| 309 IDaemonControl* control = NULL; | 382 IDaemonControl* control = NULL; |
| 310 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | 383 HRESULT hr = worker_thread_.ActivateElevatedController(&control); |
| 311 if (FAILED(hr)) { | 384 if (FAILED(hr)) { |
| 312 done_callback.Run(HResultToAsyncResult(hr)); | 385 done_callback.Run(HResultToAsyncResult(hr)); |
| 313 return; | 386 return; |
| 314 } | 387 } |
| 315 | 388 |
| 316 // Store the configuration. | 389 // Store the configuration. |
| 317 std::string file_content; | 390 std::string file_content; |
| 318 base::JSONWriter::Write(config.get(), &file_content); | 391 base::JSONWriter::Write(config.get(), &file_content); |
| 319 | 392 |
| 320 BSTR host_config = ::SysAllocString(UTF8ToUTF16(file_content).c_str()); | 393 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str()); |
| 321 if (host_config == NULL) { | 394 if (host_config == NULL) { |
| 322 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); | 395 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); |
| 323 return; | 396 return; |
| 324 } | 397 } |
| 325 | 398 |
| 326 hr = control->SetConfig(host_config); | 399 hr = control->SetConfig(host_config); |
| 327 ::SysFreeString(host_config); | |
| 328 if (FAILED(hr)) { | 400 if (FAILED(hr)) { |
| 329 done_callback.Run(HResultToAsyncResult(hr)); | 401 done_callback.Run(HResultToAsyncResult(hr)); |
| 330 return; | 402 return; |
| 331 } | 403 } |
| 332 | 404 |
| 333 // Start daemon. | 405 // Start daemon. |
| 334 hr = control->StartDaemon(); | 406 hr = control->StartDaemon(); |
| 335 done_callback.Run(HResultToAsyncResult(hr)); | 407 done_callback.Run(HResultToAsyncResult(hr)); |
| 336 } | 408 } |
| 337 | 409 |
| 338 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { | 410 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { |
| 339 IDaemonControl* control = NULL; | 411 IDaemonControl* control = NULL; |
| 340 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | 412 HRESULT hr = worker_thread_.ActivateElevatedController(&control); |
| 341 if (FAILED(hr)) { | 413 if (FAILED(hr)) { |
| 342 done_callback.Run(HResultToAsyncResult(hr)); | 414 done_callback.Run(HResultToAsyncResult(hr)); |
| 343 return; | 415 return; |
| 344 } | 416 } |
| 345 | 417 |
| 346 hr = control->StopDaemon(); | 418 hr = control->StopDaemon(); |
| 347 done_callback.Run(HResultToAsyncResult(hr)); | 419 done_callback.Run(HResultToAsyncResult(hr)); |
| 348 } | 420 } |
| 349 | 421 |
| 350 } // namespace | 422 } // namespace |
| 351 | 423 |
| 352 scoped_ptr<DaemonController> remoting::DaemonController::Create() { | 424 scoped_ptr<DaemonController> remoting::DaemonController::Create() { |
| 353 return scoped_ptr<DaemonController>(new DaemonControllerWin()); | 425 return scoped_ptr<DaemonController>(new DaemonControllerWin()); |
| 354 } | 426 } |
| 355 | 427 |
| 356 } // namespace remoting | 428 } // namespace remoting |
| OLD | NEW |