Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // This file implements the Windows service controlling Me2Me host processes | 5 // This file implements the Windows service controlling Me2Me host processes |
| 6 // running within user sessions. | 6 // running within user sessions. |
| 7 | 7 |
| 8 #include "remoting/host/win/wts_session_process_delegate.h" | 8 #include "remoting/host/win/wts_session_process_delegate.h" |
| 9 | 9 |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 148 // The handle of the worker process, if launched. | 148 // The handle of the worker process, if launched. |
| 149 base::win::ScopedHandle worker_process_; | 149 base::win::ScopedHandle worker_process_; |
| 150 | 150 |
| 151 // If launching elevated, this holds the server handle after launch, until | 151 // If launching elevated, this holds the server handle after launch, until |
| 152 // the final process launches. | 152 // the final process launches. |
| 153 mojo::edk::ScopedPlatformHandle elevated_server_handle_; | 153 mojo::edk::ScopedPlatformHandle elevated_server_handle_; |
| 154 | 154 |
| 155 // If launching elevated, this is the pid of the launcher process. | 155 // If launching elevated, this is the pid of the launcher process. |
| 156 base::ProcessId elevated_launcher_pid_ = base::kNullProcessId; | 156 base::ProcessId elevated_launcher_pid_ = base::kNullProcessId; |
| 157 | 157 |
| 158 // Tracks the id of the worker process. | |
| 159 base::ProcessId worker_process_pid_ = base::kNullProcessId; | |
| 160 | |
| 158 // The mojo child token for the process being launched. | 161 // The mojo child token for the process being launched. |
| 159 std::string mojo_child_token_; | 162 std::string mojo_child_token_; |
| 160 | 163 |
| 161 DISALLOW_COPY_AND_ASSIGN(Core); | 164 DISALLOW_COPY_AND_ASSIGN(Core); |
| 162 }; | 165 }; |
| 163 | 166 |
| 164 WtsSessionProcessDelegate::Core::Core( | 167 WtsSessionProcessDelegate::Core::Core( |
| 165 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, | 168 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, |
| 166 std::unique_ptr<base::CommandLine> target_command, | 169 std::unique_ptr<base::CommandLine> target_command, |
| 167 bool launch_elevated, | 170 bool launch_elevated, |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 if (channel_) { | 248 if (channel_) { |
| 246 channel_->Send(message); | 249 channel_->Send(message); |
| 247 } else { | 250 } else { |
| 248 delete message; | 251 delete message; |
| 249 } | 252 } |
| 250 } | 253 } |
| 251 | 254 |
| 252 void WtsSessionProcessDelegate::Core::CloseChannel() { | 255 void WtsSessionProcessDelegate::Core::CloseChannel() { |
| 253 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 256 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 254 | 257 |
| 255 if (!channel_) | 258 if (!channel_) { |
| 256 return; | 259 return; |
| 260 } | |
| 257 | 261 |
| 258 channel_.reset(); | 262 channel_.reset(); |
| 259 elevated_server_handle_.reset(); | 263 elevated_server_handle_.reset(); |
| 260 elevated_launcher_pid_ = base::kNullProcessId; | 264 elevated_launcher_pid_ = base::kNullProcessId; |
| 261 if (!mojo_child_token_.empty()) { | 265 if (!mojo_child_token_.empty()) { |
| 262 mojo::edk::ChildProcessLaunchFailed(mojo_child_token_); | 266 mojo::edk::ChildProcessLaunchFailed(mojo_child_token_); |
| 263 mojo_child_token_.clear(); | 267 mojo_child_token_.clear(); |
| 264 } | 268 } |
| 265 } | 269 } |
| 266 | 270 |
| 267 void WtsSessionProcessDelegate::Core::KillProcess() { | 271 void WtsSessionProcessDelegate::Core::KillProcess() { |
| 268 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 272 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 269 | 273 |
| 270 CloseChannel(); | 274 CloseChannel(); |
| 271 | 275 |
| 272 event_handler_ = nullptr; | 276 event_handler_ = nullptr; |
| 273 launch_pending_ = false; | 277 launch_pending_ = false; |
| 274 | 278 |
| 275 if (launch_elevated_) { | 279 if (launch_elevated_) { |
| 276 if (job_.IsValid()) | 280 if (job_.IsValid()) { |
| 277 TerminateJobObject(job_.Get(), CONTROL_C_EXIT); | 281 TerminateJobObject(job_.Get(), CONTROL_C_EXIT); |
| 282 } | |
| 278 } else { | 283 } else { |
| 279 if (worker_process_.IsValid()) | 284 if (worker_process_.IsValid()) { |
| 280 TerminateProcess(worker_process_.Get(), CONTROL_C_EXIT); | 285 TerminateProcess(worker_process_.Get(), CONTROL_C_EXIT); |
| 286 } | |
| 281 } | 287 } |
| 282 | 288 |
| 283 worker_process_.Close(); | 289 worker_process_.Close(); |
| 284 } | 290 } |
| 285 | 291 |
| 286 WtsSessionProcessDelegate::Core::~Core() { | 292 WtsSessionProcessDelegate::Core::~Core() { |
| 287 DCHECK(!channel_); | 293 DCHECK(!channel_); |
| 288 DCHECK(!event_handler_); | 294 DCHECK(!event_handler_); |
| 289 DCHECK(!worker_process_.IsValid()); | 295 DCHECK(!worker_process_.IsValid()); |
| 290 } | 296 } |
| 291 | 297 |
| 292 void WtsSessionProcessDelegate::Core::OnIOCompleted( | 298 void WtsSessionProcessDelegate::Core::OnIOCompleted( |
| 293 base::MessagePumpForIO::IOContext* context, | 299 base::MessagePumpForIO::IOContext* context, |
| 294 DWORD bytes_transferred, | 300 DWORD bytes_transferred, |
| 295 DWORD error) { | 301 DWORD error) { |
| 296 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 302 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 297 | 303 |
| 298 // |bytes_transferred| is used in job object notifications to supply | 304 // |bytes_transferred| is used in job object notifications to supply |
| 299 // the message ID; |context| carries process ID. | 305 // the message ID; |context| carries process ID. |
| 300 switch (bytes_transferred) { | 306 switch (bytes_transferred) { |
| 301 case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: { | 307 case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: { |
| 302 caller_task_runner_->PostTask( | 308 caller_task_runner_->PostTask( |
| 303 FROM_HERE, base::Bind(&Core::OnActiveProcessZero, this)); | 309 FROM_HERE, base::Bind(&Core::OnActiveProcessZero, this)); |
| 304 break; | 310 break; |
| 305 } | 311 } |
| 306 case JOB_OBJECT_MSG_NEW_PROCESS: { | 312 case JOB_OBJECT_MSG_NEW_PROCESS: { |
| 307 caller_task_runner_->PostTask( | 313 base::ProcessId new_process_id = |
| 308 FROM_HERE, base::Bind(&Core::OnProcessLaunchDetected, this, | 314 static_cast<base::ProcessId>(reinterpret_cast<uintptr_t>(context)); |
|
Sergey Ulanov
2016/12/13 01:10:37
nit: move this above the switch statement and rena
joedow
2016/12/13 03:52:42
Done. The cast dance seems to be required, I get
| |
| 309 static_cast<base::ProcessId>( | 315 if (elevated_launcher_pid_ == base::kNullProcessId) { |
| 310 reinterpret_cast<uintptr_t>(context)))); | 316 // Ignore process launch events when we don't have a valid launcher pid. |
| 317 return; | |
| 318 } | |
| 319 | |
| 320 if (new_process_id != elevated_launcher_pid_) { | |
| 321 DCHECK_EQ(worker_process_pid_, base::kNullProcessId); | |
| 322 worker_process_pid_ = new_process_id; | |
| 323 } | |
| 324 break; | |
| 325 } | |
| 326 case JOB_OBJECT_MSG_EXIT_PROCESS: { | |
| 327 base::ProcessId exiting_process_id = | |
| 328 static_cast<base::ProcessId>(reinterpret_cast<uintptr_t>(context)); | |
| 329 if (exiting_process_id == worker_process_pid_) { | |
| 330 // In official builds the first launch of a UiAccess enabled binary | |
| 331 // will fail due to 'STATUS_ELEVATION_REQUIRED'. In that scenario, we | |
| 332 // will clear out the previously stored value for |worker_process_pid_| | |
| 333 // and retry after the subsequent relaunch of the worker process. | |
|
Sergey Ulanov
2016/12/13 01:10:37
It's not clear from this comment who relaunches th
joedow
2016/12/13 03:52:42
Done.
| |
| 334 worker_process_pid_ = base::kNullProcessId; | |
| 335 } else if (exiting_process_id == elevated_launcher_pid_) { | |
| 336 if (worker_process_pid_ == base::kNullProcessId) { | |
| 337 // The elevated launcher process can fail to launch without attemping | |
| 338 // to launch the worker. In this scenario, the failure will be | |
| 339 // detected outside this method and the elevated launcher will be | |
| 340 // launched again. | |
| 341 return; | |
| 342 } | |
| 343 | |
| 344 caller_task_runner_->PostTask( | |
| 345 FROM_HERE, base::Bind(&Core::OnProcessLaunchDetected, this, | |
| 346 worker_process_pid_)); | |
| 347 } | |
| 311 break; | 348 break; |
| 312 } | 349 } |
| 313 } | 350 } |
| 314 } | 351 } |
| 315 | 352 |
| 316 bool WtsSessionProcessDelegate::Core::OnMessageReceived( | 353 bool WtsSessionProcessDelegate::Core::OnMessageReceived( |
| 317 const IPC::Message& message) { | 354 const IPC::Message& message) { |
| 318 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 355 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 319 | 356 |
| 320 return event_handler_->OnMessageReceived(message); | 357 return event_handler_->OnMessageReceived(message); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 caller_task_runner_->PostTask(FROM_HERE, base::Bind( | 519 caller_task_runner_->PostTask(FROM_HERE, base::Bind( |
| 483 &Core::InitializeJobCompleted, this, base::Passed(&job))); | 520 &Core::InitializeJobCompleted, this, base::Passed(&job))); |
| 484 } | 521 } |
| 485 | 522 |
| 486 void WtsSessionProcessDelegate::Core::InitializeJobCompleted(ScopedHandle job) { | 523 void WtsSessionProcessDelegate::Core::InitializeJobCompleted(ScopedHandle job) { |
| 487 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 524 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 488 DCHECK(!job_.IsValid()); | 525 DCHECK(!job_.IsValid()); |
| 489 | 526 |
| 490 job_ = std::move(job); | 527 job_ = std::move(job); |
| 491 | 528 |
| 492 if (launch_pending_) | 529 if (launch_pending_) { |
| 493 DoLaunchProcess(); | 530 DoLaunchProcess(); |
| 531 } | |
| 494 } | 532 } |
| 495 | 533 |
| 496 void WtsSessionProcessDelegate::Core::OnActiveProcessZero() { | 534 void WtsSessionProcessDelegate::Core::OnActiveProcessZero() { |
| 497 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 535 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 498 | 536 |
| 499 if (launch_pending_) { | 537 if (launch_pending_) { |
| 500 LOG(ERROR) << "The worker process exited before connecting via IPC."; | 538 LOG(ERROR) << "The worker process exited before connecting via IPC."; |
| 501 launch_pending_ = false; | 539 launch_pending_ = false; |
| 502 ReportFatalError(); | 540 ReportFatalError(); |
| 503 } | 541 } |
| 504 } | 542 } |
| 505 | 543 |
| 506 void WtsSessionProcessDelegate::Core::OnProcessLaunchDetected( | 544 void WtsSessionProcessDelegate::Core::OnProcessLaunchDetected( |
| 507 base::ProcessId pid) { | 545 base::ProcessId pid) { |
| 508 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 546 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 509 if (!elevated_server_handle_.is_valid()) | 547 DCHECK_NE(pid, elevated_launcher_pid_); |
| 548 | |
| 549 if (!elevated_server_handle_.is_valid()) { | |
| 510 return; | 550 return; |
| 511 | 551 } |
| 512 if (pid == elevated_launcher_pid_) | |
| 513 return; | |
| 514 | 552 |
| 515 DWORD desired_access = | 553 DWORD desired_access = |
| 516 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; | 554 SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; |
| 517 base::win::ScopedHandle worker_process( | 555 base::win::ScopedHandle worker_process( |
| 518 OpenProcess(desired_access, false, pid)); | 556 OpenProcess(desired_access, false, pid)); |
| 519 if (!worker_process.IsValid()) { | 557 if (!worker_process.IsValid()) { |
| 520 PLOG(ERROR) << "Failed to open process " << pid; | 558 PLOG(ERROR) << "Failed to open process " << pid; |
| 521 ReportFatalError(); | 559 ReportFatalError(); |
| 522 return; | 560 return; |
| 523 } | 561 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 594 | 632 |
| 595 void WtsSessionProcessDelegate::CloseChannel() { | 633 void WtsSessionProcessDelegate::CloseChannel() { |
| 596 core_->CloseChannel(); | 634 core_->CloseChannel(); |
| 597 } | 635 } |
| 598 | 636 |
| 599 void WtsSessionProcessDelegate::KillProcess() { | 637 void WtsSessionProcessDelegate::KillProcess() { |
| 600 core_->KillProcess(); | 638 core_->KillProcess(); |
| 601 } | 639 } |
| 602 | 640 |
| 603 } // namespace remoting | 641 } // namespace remoting |
| OLD | NEW |