| Index: remoting/host/win/wts_session_process_delegate.cc
|
| diff --git a/remoting/host/win/wts_session_process_delegate.cc b/remoting/host/win/wts_session_process_delegate.cc
|
| index 780531c0e674f70698b203a6e155d828ad4b8e4f..d959aca3711825b75090872f21e65aa07ca12be6 100644
|
| --- a/remoting/host/win/wts_session_process_delegate.cc
|
| +++ b/remoting/host/win/wts_session_process_delegate.cc
|
| @@ -155,6 +155,9 @@ class WtsSessionProcessDelegate::Core
|
| // If launching elevated, this is the pid of the launcher process.
|
| base::ProcessId elevated_launcher_pid_ = base::kNullProcessId;
|
|
|
| + // Tracks the id of the worker process.
|
| + base::ProcessId worker_process_pid_ = base::kNullProcessId;
|
| +
|
| // The mojo child token for the process being launched.
|
| std::string mojo_child_token_;
|
|
|
| @@ -252,8 +255,9 @@ void WtsSessionProcessDelegate::Core::Send(IPC::Message* message) {
|
| void WtsSessionProcessDelegate::Core::CloseChannel() {
|
| DCHECK(caller_task_runner_->BelongsToCurrentThread());
|
|
|
| - if (!channel_)
|
| + if (!channel_) {
|
| return;
|
| + }
|
|
|
| channel_.reset();
|
| elevated_server_handle_.reset();
|
| @@ -273,11 +277,13 @@ void WtsSessionProcessDelegate::Core::KillProcess() {
|
| launch_pending_ = false;
|
|
|
| if (launch_elevated_) {
|
| - if (job_.IsValid())
|
| + if (job_.IsValid()) {
|
| TerminateJobObject(job_.Get(), CONTROL_C_EXIT);
|
| + }
|
| } else {
|
| - if (worker_process_.IsValid())
|
| + if (worker_process_.IsValid()) {
|
| TerminateProcess(worker_process_.Get(), CONTROL_C_EXIT);
|
| + }
|
| }
|
|
|
| worker_process_.Close();
|
| @@ -296,7 +302,9 @@ void WtsSessionProcessDelegate::Core::OnIOCompleted(
|
| DCHECK(io_task_runner_->BelongsToCurrentThread());
|
|
|
| // |bytes_transferred| is used in job object notifications to supply
|
| - // the message ID; |context| carries process ID.
|
| + // the message ID; |context| carries process ID for the events we listen for.
|
| + base::ProcessId process_id =
|
| + static_cast<base::ProcessId>(reinterpret_cast<uintptr_t>(context));
|
| switch (bytes_transferred) {
|
| case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: {
|
| caller_task_runner_->PostTask(
|
| @@ -304,10 +312,38 @@ void WtsSessionProcessDelegate::Core::OnIOCompleted(
|
| break;
|
| }
|
| case JOB_OBJECT_MSG_NEW_PROCESS: {
|
| - caller_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&Core::OnProcessLaunchDetected, this,
|
| - static_cast<base::ProcessId>(
|
| - reinterpret_cast<uintptr_t>(context))));
|
| + if (elevated_launcher_pid_ == base::kNullProcessId) {
|
| + // Ignore process launch events when we don't have a valid launcher pid.
|
| + return;
|
| + }
|
| +
|
| + if (process_id != elevated_launcher_pid_) {
|
| + DCHECK_EQ(worker_process_pid_, base::kNullProcessId);
|
| + worker_process_pid_ = process_id;
|
| + }
|
| + break;
|
| + }
|
| + case JOB_OBJECT_MSG_EXIT_PROCESS: {
|
| + if (process_id == worker_process_pid_) {
|
| + // In official builds the first launch of a UiAccess enabled binary
|
| + // will fail due to 'STATUS_ELEVATION_REQUIRED'. This is an artifact of
|
| + // using ShellExecuteEx() to launch the process. In this scenario, we
|
| + // will clear out the previously stored value for |worker_process_pid_|
|
| + // and retry after the subsequent relaunch of the worker process.
|
| + worker_process_pid_ = base::kNullProcessId;
|
| + } else if (process_id == elevated_launcher_pid_) {
|
| + if (worker_process_pid_ == base::kNullProcessId) {
|
| + // The elevated launcher process can fail to launch without attemping
|
| + // to launch the worker. In this scenario, the failure will be
|
| + // detected outside this method and the elevated launcher will be
|
| + // launched again.
|
| + return;
|
| + }
|
| +
|
| + caller_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&Core::OnProcessLaunchDetected, this,
|
| + worker_process_pid_));
|
| + }
|
| break;
|
| }
|
| }
|
| @@ -489,8 +525,9 @@ void WtsSessionProcessDelegate::Core::InitializeJobCompleted(ScopedHandle job) {
|
|
|
| job_ = std::move(job);
|
|
|
| - if (launch_pending_)
|
| + if (launch_pending_) {
|
| DoLaunchProcess();
|
| + }
|
| }
|
|
|
| void WtsSessionProcessDelegate::Core::OnActiveProcessZero() {
|
| @@ -506,11 +543,11 @@ void WtsSessionProcessDelegate::Core::OnActiveProcessZero() {
|
| void WtsSessionProcessDelegate::Core::OnProcessLaunchDetected(
|
| base::ProcessId pid) {
|
| DCHECK(caller_task_runner_->BelongsToCurrentThread());
|
| - if (!elevated_server_handle_.is_valid())
|
| - return;
|
| + DCHECK_NE(pid, elevated_launcher_pid_);
|
|
|
| - if (pid == elevated_launcher_pid_)
|
| + if (!elevated_server_handle_.is_valid()) {
|
| return;
|
| + }
|
|
|
| DWORD desired_access =
|
| SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION;
|
|
|