158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file. 458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "remoting/host/setup/daemon_controller_delegate_win.h" 658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/basictypes.h" 858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/bind.h" 958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/bind_helpers.h" 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/compiler_specific.h" 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/json/json_reader.h" 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/json/json_writer.h" 1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/logging.h" 1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/string16.h" 1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/thread_task_runner_handle.h" 1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/time/time.h" 1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/timer/timer.h" 1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/values.h" 2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/win/scoped_bstr.h" 2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/win/scoped_comptr.h" 2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/win/windows_version.h" 2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "remoting/base/scoped_sc_handle_win.h" 2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "remoting/host/branding.h" 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// chromoting_lib.h contains MIDL-generated declarations. 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "remoting/host/chromoting_lib.h" 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "remoting/host/usage_stats_consent.h" 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using base::win::ScopedBstr; 3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using base::win::ScopedComPtr; 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace remoting { 3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace { 3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// ProgID of the daemon controller. 3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const wchar_t kDaemonController[] = 3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) L"ChromotingElevatedController.ElevatedController"; 3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The COM elevation moniker for the Elevated Controller. 4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const wchar_t kDaemonControllerElevationMoniker[] = 4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) L"Elevation:Administrator!new:" 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) L"ChromotingElevatedController.ElevatedController"; 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The maximum duration of keeping a reference to a privileged instance of 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// the Daemon Controller. This effectively reduces number of UAC prompts a user 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// sees. 4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const int kPrivilegedTimeoutSec = 5 * 60; 4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The maximum duration of keeping a reference to an unprivileged instance of 5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// the Daemon Controller. This interval should not be too long. If upgrade 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// happens while there is a live reference to a Daemon Controller instance 5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// the old binary still can be used. So dropping the references often makes sure 5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// that the old binary will go away sooner. 5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const int kUnprivilegedTimeoutSec = 60; 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ConfigToString(const base::DictionaryValue& config, ScopedBstr* out) { 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string config_str; 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::JSONWriter::Write(&config, &config_str); 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedBstr config_scoped_bstr(base::UTF8ToUTF16(config_str).c_str()); 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) out->Swap(config_scoped_bstr); 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonController::State ConvertToDaemonState(DWORD service_state) { 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) switch (service_state) { 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case SERVICE_RUNNING: 6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_STARTED; 6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case SERVICE_CONTINUE_PENDING: 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case SERVICE_START_PENDING: 7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_STARTING; 7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case SERVICE_PAUSE_PENDING: 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case SERVICE_STOP_PENDING: 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_STOPPING; 7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case SERVICE_PAUSED: 8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case SERVICE_STOPPED: 8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_STOPPED; 8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) default: 8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NOTREACHED(); 8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_UNKNOWN; 8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DWORD OpenService(ScopedScHandle* service_out) { 9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Open the service and query its current state. 9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedScHandle scmanager( 9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, 9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); 9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!scmanager.IsValid()) { 9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DWORD error = GetLastError(); 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "Failed to connect to the service control manager"; 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return error; 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedScHandle service(::OpenServiceW(scmanager.Get(), kWindowsServiceName, 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SERVICE_QUERY_STATUS)); 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!service.IsValid()) { 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DWORD error = GetLastError(); 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (error != ERROR_SERVICE_DOES_NOT_EXIST) { 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "Failed to open to the '" << kWindowsServiceName 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << "' service"; 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return error; 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) service_out->Set(service.Take()); 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return ERROR_SUCCESS; 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonController::AsyncResult HResultToAsyncResult( 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr) { 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (SUCCEEDED(hr)) { 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::RESULT_OK; 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) { 12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::RESULT_CANCELLED; 12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // TODO(sergeyu): Report other errors to the webapp once it knows 12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // how to handle them. 12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::RESULT_FAILED; 12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 129a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid InvokeCompletionCallback( 130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const DaemonController::CompletionCallback& done, HRESULT hr) { 131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch done.Run(HResultToAsyncResult(hr)); 132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace 13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonControllerDelegateWin::DaemonControllerDelegateWin() 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) : control_is_elevated_(false), 13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) window_handle_(NULL) { 13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonControllerDelegateWin::~DaemonControllerDelegateWin() { 14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonController::State DaemonControllerDelegateWin::GetState() { 14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_XP) { 14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_NOT_IMPLEMENTED; 14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // TODO(alexeypa): Make the thread alertable, so we can switch to APC 14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // notifications rather than polling. 15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedScHandle service; 15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DWORD error = OpenService(&service); 15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) switch (error) { 15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case ERROR_SUCCESS: { 15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SERVICE_STATUS status; 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (::QueryServiceStatus(service.Get(), &status)) { 15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return ConvertToDaemonState(status.dwCurrentState); 15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "Failed to query the state of the '" 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << kWindowsServiceName << "' service"; 16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_UNKNOWN; 16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case ERROR_SERVICE_DOES_NOT_EXIST: 16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_NOT_INSTALLED; 16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) default: 16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_UNKNOWN; 16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_ptr<base::DictionaryValue> DaemonControllerDelegateWin::GetConfig() { 17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Configure and start the Daemon Controller if it is installed already. 17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr = ActivateController(); 17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) 17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<base::DictionaryValue>(); 17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Get the host configuration. 17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedBstr host_config; 18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control_->GetConfig(host_config.Receive()); 18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) 18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<base::DictionaryValue>(); 18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Parse the string into a dictionary. 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 file_content( 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<BSTR>(host_config), host_config.Length()); 18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<base::Value> config( 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::JSONReader::Read(base::UTF16ToUTF8(file_content), 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::JSON_ALLOW_TRAILING_COMMAS)); 19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!config || config->GetType() != base::Value::TYPE_DICTIONARY) 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<base::DictionaryValue>(); 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<base::DictionaryValue>( 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) static_cast<base::DictionaryValue*>(config.release())); 19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 198a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid DaemonControllerDelegateWin::InstallHost( 199a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const DaemonController::CompletionCallback& done) { 200a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DoInstallHost(base::Bind(&InvokeCompletionCallback, done)); 201a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 202a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DaemonControllerDelegateWin::SetConfigAndStart( 20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<base::DictionaryValue> config, 20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool consent, 20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const DaemonController::CompletionCallback& done) { 207a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DoInstallHost( 208a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::Bind(&DaemonControllerDelegateWin::StartHostWithConfig, 209a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch base::Unretained(this), base::Passed(&config), consent, done)); 210a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 212a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid DaemonControllerDelegateWin::DoInstallHost( 213a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const DaemonInstallerWin::CompletionCallback& done) { 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Configure and start the Daemon Controller if it is installed already. 21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr = ActivateElevatedController(); 21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (SUCCEEDED(hr)) { 217a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch done.Run(S_OK); 21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Otherwise, install it if its COM registration entry is missing. 22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (hr == CO_E_CLASSSTRING) { 22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(!installer_); 22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) installer_ = DaemonInstallerWin::Create( 226a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch GetTopLevelWindow(window_handle_), done); 22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) installer_->Install(); 22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) LOG(ERROR) << "Failed to initiate the Chromoting Host installation " 23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << "(error: 0x" << std::hex << hr << std::dec << ")."; 233a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch done.Run(hr); 23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DaemonControllerDelegateWin::UpdateConfig( 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<base::DictionaryValue> config, 23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const DaemonController::CompletionCallback& done) { 23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr = ActivateElevatedController(); 24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 241a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Update the configuration. 24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedBstr config_str(NULL); 24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ConfigToString(*config, &config_str); 24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (config_str == NULL) { 249a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, E_OUTOFMEMORY); 25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Make sure that the PIN confirmation dialog is focused properly. 25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control_->SetOwnerWindow( 25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) reinterpret_cast<LONG_PTR>(GetTopLevelWindow(window_handle_))); 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 257a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control_->UpdateConfig(config_str); 262a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DaemonControllerDelegateWin::Stop( 26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const DaemonController::CompletionCallback& done) { 26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr = ActivateElevatedController(); 26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (SUCCEEDED(hr)) 26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control_->StopDaemon(); 27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 271a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DaemonControllerDelegateWin::SetWindow(void* window_handle) { 27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) window_handle_ = reinterpret_cast<HWND>(window_handle); 27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string DaemonControllerDelegateWin::GetVersion() { 27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Configure and start the Daemon Controller if it is installed already. 28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr = ActivateController(); 28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) 28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return std::string(); 28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Get the version string. 28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedBstr version; 28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control_->GetVersion(version.Receive()); 28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) 28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return std::string(); 28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::UTF16ToUTF8( 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16(static_cast<BSTR>(version), version.Length())); 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonController::UsageStatsConsent 29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonControllerDelegateWin::GetUsageStatsConsent() { 29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DaemonController::UsageStatsConsent consent; 29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) consent.supported = true; 29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) consent.allowed = false; 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) consent.set_by_policy = false; 30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Activate the Daemon Controller and see if it supports |IDaemonControl2|. 30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr = ActivateController(); 30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // The host is not installed yet. Assume that the user didn't consent to 30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // collecting crash dumps. 30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return consent; 30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (control2_.get() == NULL) { 31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // The host is installed and does not support crash dump reporting. 31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return consent; 31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Get the recorded user's consent. 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) BOOL allowed; 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) BOOL set_by_policy; 31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control2_->GetUsageStatsConsent(&allowed, &set_by_policy); 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // If the user's consent is not recorded yet, assume that the user didn't 32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // consent to collecting crash dumps. 32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return consent; 32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) consent.allowed = !!allowed; 32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) consent.set_by_policy = !!set_by_policy; 32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return consent; 32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)HRESULT DaemonControllerDelegateWin::ActivateController() { 33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!control_) { 33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CLSID class_id; 33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr = CLSIDFromProgID(kDaemonController, &class_id); 33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return hr; 33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, 33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) IID_IDaemonControl, control_.ReceiveVoid()); 33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return hr; 34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Ignore the error. IID_IDaemonControl2 is optional. 34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) control_.QueryInterface(IID_IDaemonControl2, control2_.ReceiveVoid()); 34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Release |control_| upon expiration of the timeout. 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) release_timer_.reset(new base::OneShotTimer<DaemonControllerDelegateWin>()); 34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) release_timer_->Start(FROM_HERE, 34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::TimeDelta::FromSeconds(kUnprivilegedTimeoutSec), 35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) this, 35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &DaemonControllerDelegateWin::ReleaseController); 35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return S_OK; 35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 35758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)HRESULT DaemonControllerDelegateWin::ActivateElevatedController() { 35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // The COM elevation is supported on Vista and above. 35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_VISTA) 36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return ActivateController(); 36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Release an unprivileged instance of the daemon controller if any. 36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!control_is_elevated_) 36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ReleaseController(); 36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 36658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!control_) { 36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) BIND_OPTS3 bind_options; 36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) memset(&bind_options, 0, sizeof(bind_options)); 36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bind_options.cbStruct = sizeof(bind_options); 37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bind_options.hwnd = GetTopLevelWindow(window_handle_); 37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; 37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr = ::CoGetObject( 37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) kDaemonControllerElevationMoniker, 37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &bind_options, 37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) IID_IDaemonControl, 37758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) control_.ReceiveVoid()); 37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return hr; 38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Ignore the error. IID_IDaemonControl2 is optional. 38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) control_.QueryInterface(IID_IDaemonControl2, control2_.ReceiveVoid()); 38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Note that we hold a reference to an elevated instance now. 38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) control_is_elevated_ = true; 38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Release |control_| upon expiration of the timeout. 38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) release_timer_.reset(new base::OneShotTimer<DaemonControllerDelegateWin>()); 39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) release_timer_->Start(FROM_HERE, 39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::TimeDelta::FromSeconds(kPrivilegedTimeoutSec), 39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) this, 39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &DaemonControllerDelegateWin::ReleaseController); 39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 39658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return S_OK; 39758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 39858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 39958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DaemonControllerDelegateWin::ReleaseController() { 40058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) control_.Release(); 40158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) control2_.Release(); 40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) release_timer_.reset(); 40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) control_is_elevated_ = false; 40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 406a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid DaemonControllerDelegateWin::StartHostWithConfig( 40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<base::DictionaryValue> config, 40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool consent, 40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const DaemonController::CompletionCallback& done, 41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HRESULT hr) { 41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) installer_.reset(); 41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) LOG(ERROR) << "Failed to install the Chromoting Host " 41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << "(error: 0x" << std::hex << hr << std::dec << ")."; 416a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 42058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = ActivateElevatedController(); 42158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 422a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 42558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Record the user's consent. 42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (control2_) { 42858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control2_->SetUsageStatsConsent(consent); 42958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 430a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 43158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 43258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Set the configuration. 43658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedBstr config_str(NULL); 43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ConfigToString(*config, &config_str); 43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (config_str == NULL) { 439a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, E_OUTOFMEMORY); 44058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 44258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 44358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control_->SetOwnerWindow( 44458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) reinterpret_cast<LONG_PTR>(GetTopLevelWindow(window_handle_))); 44558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 446a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 44758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 44858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 44958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 45058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control_->SetConfig(config_str); 45158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (FAILED(hr)) { 452a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 45358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 45558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 45658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Start daemon. 45758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hr = control_->StartDaemon(); 458a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InvokeCompletionCallback(done, hr); 45958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 46058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 46158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_refptr<DaemonController> DaemonController::Create() { 46258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<DaemonController::Delegate> delegate( 46358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new DaemonControllerDelegateWin()); 46458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return new DaemonController(delegate.Pass()); 46558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 46658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 46758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace remoting 468