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