| Index: remoting/host/plugin/daemon_controller_win.cc
|
| diff --git a/remoting/host/plugin/daemon_controller_win.cc b/remoting/host/plugin/daemon_controller_win.cc
|
| index 49b1809b831ebb2ea27ee93ac5379812e3c49bc8..ddf8df4a59510e1885b451fc90545dfc84fd81b7 100644
|
| --- a/remoting/host/plugin/daemon_controller_win.cc
|
| +++ b/remoting/host/plugin/daemon_controller_win.cc
|
| @@ -55,25 +55,12 @@ class ComThread : public base::Thread {
|
| public:
|
| explicit ComThread(const char* name);
|
|
|
| - // Activates an elevated instance of the controller and returns the pointer
|
| - // to the control interface in |control_out|. This class keeps the ownership
|
| - // of the pointer so the caller should not call call AddRef() or Release().
|
| - HRESULT ActivateElevatedController(HWND window_handle,
|
| - IDaemonControl** control_out);
|
| -
|
| bool Start();
|
|
|
| protected:
|
| virtual void Init() OVERRIDE;
|
| virtual void CleanUp() OVERRIDE;
|
|
|
| - void ReleaseElevatedController();
|
| -
|
| - ScopedComPtr<IDaemonControl> control_;
|
| -
|
| - // This timer is used to release |control_| after a timeout.
|
| - base::OneShotTimer<ComThread> release_timer_;
|
| -
|
| DISALLOW_COPY_AND_ASSIGN(ComThread);
|
| };
|
|
|
| @@ -93,11 +80,11 @@ class DaemonControllerWin : public remoting::DaemonController {
|
| virtual void SetWindow(void* window_handle) OVERRIDE;
|
|
|
| private:
|
| - // Converts a Windows service status code to a Daemon state.
|
| - static State ConvertToDaemonState(DWORD service_state);
|
| + // Activates an elevated instance of the controller and caches it.
|
| + HRESULT ActivateElevatedController();
|
|
|
| - // Converts HRESULT to the AsyncResult.
|
| - static AsyncResult HResultToAsyncResult(HRESULT hr);
|
| + // Releases the cached instance of the elevated controller.
|
| + void ReleaseElevatedController();
|
|
|
| // Procedes with the daemon configuration if the installation succeeded,
|
| // otherwise reports the error.
|
| @@ -112,6 +99,12 @@ class DaemonControllerWin : public remoting::DaemonController {
|
| static void ConfigToString(const base::DictionaryValue& config,
|
| ScopedBstr* out);
|
|
|
| + // Converts a Windows service status code to a Daemon state.
|
| + static State ConvertToDaemonState(DWORD service_state);
|
| +
|
| + // Converts HRESULT to the AsyncResult.
|
| + static AsyncResult HResultToAsyncResult(HRESULT hr);
|
| +
|
| // The functions that actually do the work. They should be called in
|
| // the context of |worker_thread_|;
|
| void DoGetConfig(const GetConfigCallback& callback);
|
| @@ -124,6 +117,11 @@ class DaemonControllerWin : public remoting::DaemonController {
|
| void DoStop(const CompletionCallback& done_callback);
|
| void DoSetWindow(void* window_handle);
|
|
|
| + ScopedComPtr<IDaemonControl> control_;
|
| +
|
| + // This timer is used to release |control_| after a timeout.
|
| + scoped_ptr<base::OneShotTimer<DaemonControllerWin> > release_timer_;
|
| +
|
| // Handle of the plugin window.
|
| HWND window_handle_;
|
|
|
| @@ -135,38 +133,7 @@ class DaemonControllerWin : public remoting::DaemonController {
|
| DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin);
|
| };
|
|
|
| -ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) {
|
| -}
|
| -
|
| -HRESULT ComThread::ActivateElevatedController(
|
| - HWND window_handle,
|
| - IDaemonControl** control_out) {
|
| - // Cache an instance of the Elevated Controller to prevent a UAC prompt on
|
| - // every operation.
|
| - if (control_.get() == NULL) {
|
| - BIND_OPTS3 bind_options;
|
| - memset(&bind_options, 0, sizeof(bind_options));
|
| - bind_options.cbStruct = sizeof(bind_options);
|
| - bind_options.hwnd = GetTopLevelWindow(window_handle);
|
| - bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
|
| -
|
| - HRESULT hr = ::CoGetObject(
|
| - kDaemonControllerElevationMoniker,
|
| - &bind_options,
|
| - IID_IDaemonControl,
|
| - control_.ReceiveVoid());
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - // Release |control_| upon expiration of the timeout.
|
| - release_timer_.Start(FROM_HERE,
|
| - base::TimeDelta::FromSeconds(kUacTimeoutSec),
|
| - this, &ComThread::ReleaseElevatedController);
|
| - }
|
| -
|
| - *control_out = control_.get();
|
| - return S_OK;
|
| +ComThread::ComThread(const char* name) : base::Thread(name) {
|
| }
|
|
|
| bool ComThread::Start() {
|
| @@ -180,14 +147,9 @@ void ComThread::Init() {
|
| }
|
|
|
| void ComThread::CleanUp() {
|
| - ReleaseElevatedController();
|
| CoUninitialize();
|
| }
|
|
|
| -void ComThread::ReleaseElevatedController() {
|
| - control_.Release();
|
| -}
|
| -
|
| DaemonControllerWin::DaemonControllerWin()
|
| : window_handle_(NULL),
|
| worker_thread_(kDaemonControllerThreadName) {
|
| @@ -197,6 +159,11 @@ DaemonControllerWin::DaemonControllerWin()
|
| }
|
|
|
| DaemonControllerWin::~DaemonControllerWin() {
|
| + // Clean up resources allocated on the worker thread.
|
| + worker_thread_.message_loop_proxy()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&DaemonControllerWin::ReleaseElevatedController,
|
| + base::Unretained(this)));
|
| worker_thread_.Stop();
|
| }
|
|
|
| @@ -265,40 +232,43 @@ void DaemonControllerWin::SetWindow(void* window_handle) {
|
| window_handle));
|
| }
|
|
|
| -// static
|
| -remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState(
|
| - DWORD service_state) {
|
| - switch (service_state) {
|
| - case SERVICE_RUNNING:
|
| - return STATE_STARTED;
|
| -
|
| - case SERVICE_CONTINUE_PENDING:
|
| - case SERVICE_START_PENDING:
|
| - return STATE_STARTING;
|
| - break;
|
| +HRESULT DaemonControllerWin::ActivateElevatedController() {
|
| + DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
|
|
|
| - case SERVICE_PAUSE_PENDING:
|
| - case SERVICE_STOP_PENDING:
|
| - return STATE_STOPPING;
|
| - break;
|
| + // Cache an instance of the Elevated Controller to prevent a UAC prompt on
|
| + // every operation.
|
| + if (control_.get() == NULL) {
|
| + BIND_OPTS3 bind_options;
|
| + memset(&bind_options, 0, sizeof(bind_options));
|
| + bind_options.cbStruct = sizeof(bind_options);
|
| + bind_options.hwnd = GetTopLevelWindow(window_handle_);
|
| + bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
|
|
|
| - case SERVICE_PAUSED:
|
| - case SERVICE_STOPPED:
|
| - return STATE_STOPPED;
|
| - break;
|
| + HRESULT hr = ::CoGetObject(
|
| + kDaemonControllerElevationMoniker,
|
| + &bind_options,
|
| + IID_IDaemonControl,
|
| + control_.ReceiveVoid());
|
| + if (FAILED(hr)) {
|
| + return hr;
|
| + }
|
|
|
| - default:
|
| - NOTREACHED();
|
| - return STATE_UNKNOWN;
|
| + // Release |control_| upon expiration of the timeout.
|
| + release_timer_.reset(new base::OneShotTimer<DaemonControllerWin>());
|
| + release_timer_->Start(FROM_HERE,
|
| + base::TimeDelta::FromSeconds(kUacTimeoutSec),
|
| + this,
|
| + &DaemonControllerWin::ReleaseElevatedController);
|
| }
|
| +
|
| + return S_OK;
|
| }
|
|
|
| -// static
|
| -DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult(
|
| - HRESULT hr) {
|
| - // TODO(sergeyu): Report other errors to the webapp once it knows
|
| - // how to handle them.
|
| - return FAILED(hr) ? RESULT_FAILED : RESULT_OK;
|
| +void DaemonControllerWin::ReleaseElevatedController() {
|
| + DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
|
| +
|
| + control_.Release();
|
| + release_timer_.reset();
|
| }
|
|
|
| void DaemonControllerWin::OnInstallationComplete(
|
| @@ -346,6 +316,7 @@ DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) {
|
| return ERROR_SUCCESS;
|
| }
|
|
|
| +// static
|
| void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config,
|
| ScopedBstr* out) {
|
| std::string config_str;
|
| @@ -354,6 +325,42 @@ void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config,
|
| out->Swap(config_scoped_bstr);
|
| }
|
|
|
| +// static
|
| +remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState(
|
| + DWORD service_state) {
|
| + switch (service_state) {
|
| + case SERVICE_RUNNING:
|
| + return STATE_STARTED;
|
| +
|
| + case SERVICE_CONTINUE_PENDING:
|
| + case SERVICE_START_PENDING:
|
| + return STATE_STARTING;
|
| + break;
|
| +
|
| + case SERVICE_PAUSE_PENDING:
|
| + case SERVICE_STOP_PENDING:
|
| + return STATE_STOPPING;
|
| + break;
|
| +
|
| + case SERVICE_PAUSED:
|
| + case SERVICE_STOPPED:
|
| + return STATE_STOPPED;
|
| + break;
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + return STATE_UNKNOWN;
|
| + }
|
| +}
|
| +
|
| +// static
|
| +DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult(
|
| + HRESULT hr) {
|
| + // TODO(sergeyu): Report other errors to the webapp once it knows
|
| + // how to handle them.
|
| + return FAILED(hr) ? RESULT_FAILED : RESULT_OK;
|
| +}
|
| +
|
| void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) {
|
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
|
|
|
| @@ -412,11 +419,8 @@ void DaemonControllerWin::DoInstallAsNeededAndStart(
|
| const CompletionCallback& done_callback) {
|
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
|
|
|
| - IDaemonControl* control = NULL;
|
| - HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
|
| - &control);
|
| -
|
| - // Just configure and start the Daemon Controller if it is installed already.
|
| + // Configure and start the Daemon Controller if it is installed already.
|
| + HRESULT hr = ActivateElevatedController();
|
| if (SUCCEEDED(hr)) {
|
| DoSetConfigAndStart(config.Pass(), done_callback);
|
| return;
|
| @@ -447,9 +451,7 @@ void DaemonControllerWin::DoSetConfigAndStart(
|
| const CompletionCallback& done_callback) {
|
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
|
|
|
| - IDaemonControl* control = NULL;
|
| - HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
|
| - &control);
|
| + HRESULT hr = ActivateElevatedController();
|
| if (FAILED(hr)) {
|
| done_callback.Run(HResultToAsyncResult(hr));
|
| return;
|
| @@ -463,14 +465,14 @@ void DaemonControllerWin::DoSetConfigAndStart(
|
| return;
|
| }
|
|
|
| - hr = control->SetConfig(config_str);
|
| + hr = control_->SetConfig(config_str);
|
| if (FAILED(hr)) {
|
| done_callback.Run(HResultToAsyncResult(hr));
|
| return;
|
| }
|
|
|
| // Start daemon.
|
| - hr = control->StartDaemon();
|
| + hr = control_->StartDaemon();
|
| done_callback.Run(HResultToAsyncResult(hr));
|
| }
|
|
|
| @@ -479,9 +481,7 @@ void DaemonControllerWin::DoUpdateConfig(
|
| const CompletionCallback& done_callback) {
|
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
|
|
|
| - IDaemonControl* control = NULL;
|
| - HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
|
| - &control);
|
| + HRESULT hr = ActivateElevatedController();
|
| if (FAILED(hr)) {
|
| done_callback.Run(HResultToAsyncResult(hr));
|
| return;
|
| @@ -495,22 +495,20 @@ void DaemonControllerWin::DoUpdateConfig(
|
| return;
|
| }
|
|
|
| - hr = control->UpdateConfig(config_str);
|
| + hr = control_->UpdateConfig(config_str);
|
| done_callback.Run(HResultToAsyncResult(hr));
|
| }
|
|
|
| void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) {
|
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
|
|
|
| - IDaemonControl* control = NULL;
|
| - HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
|
| - &control);
|
| + HRESULT hr = ActivateElevatedController();
|
| if (FAILED(hr)) {
|
| done_callback.Run(HResultToAsyncResult(hr));
|
| return;
|
| }
|
|
|
| - hr = control->StopDaemon();
|
| + hr = control_->StopDaemon();
|
| done_callback.Run(HResultToAsyncResult(hr));
|
| }
|
|
|
|
|