scoped_process_information.cc 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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
  3. // found in the LICENSE file.
  4. #include "base/win/scoped_process_information.h"
  5. #include "base/logging.h"
  6. #include "base/win/scoped_handle.h"
  7. namespace base {
  8. namespace win {
  9. namespace {
  10. // Duplicates source into target, returning true upon success. |target| is
  11. // guaranteed to be untouched in case of failure. Succeeds with no side-effects
  12. // if source is NULL.
  13. bool CheckAndDuplicateHandle(HANDLE source, ScopedHandle* target) {
  14. if (!source)
  15. return true;
  16. HANDLE temp = nullptr;
  17. if (!::DuplicateHandle(::GetCurrentProcess(), source, ::GetCurrentProcess(),
  18. &temp, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
  19. DWORD last_error = ::GetLastError();
  20. DPLOG(ERROR) << "Failed to duplicate a handle " << last_error;
  21. ::SetLastError(last_error);
  22. return false;
  23. }
  24. target->Set(temp);
  25. return true;
  26. }
  27. } // namespace
  28. ScopedProcessInformation::ScopedProcessInformation() = default;
  29. ScopedProcessInformation::ScopedProcessInformation(
  30. const PROCESS_INFORMATION& process_info) {
  31. Set(process_info);
  32. }
  33. ScopedProcessInformation::~ScopedProcessInformation() {
  34. Close();
  35. }
  36. bool ScopedProcessInformation::IsValid() const {
  37. return process_id_ || process_handle_.get() || thread_id_ ||
  38. thread_handle_.get();
  39. }
  40. void ScopedProcessInformation::Close() {
  41. process_handle_.Close();
  42. thread_handle_.Close();
  43. process_id_ = 0;
  44. thread_id_ = 0;
  45. }
  46. void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) {
  47. if (IsValid())
  48. Close();
  49. process_handle_.Set(process_info.hProcess);
  50. thread_handle_.Set(process_info.hThread);
  51. process_id_ = process_info.dwProcessId;
  52. thread_id_ = process_info.dwThreadId;
  53. }
  54. bool ScopedProcessInformation::DuplicateFrom(
  55. const ScopedProcessInformation& other) {
  56. DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL";
  57. DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid";
  58. if (CheckAndDuplicateHandle(other.process_handle(), &process_handle_) &&
  59. CheckAndDuplicateHandle(other.thread_handle(), &thread_handle_)) {
  60. process_id_ = other.process_id();
  61. thread_id_ = other.thread_id();
  62. return true;
  63. }
  64. return false;
  65. }
  66. PROCESS_INFORMATION ScopedProcessInformation::Take() {
  67. PROCESS_INFORMATION process_information = {};
  68. process_information.hProcess = process_handle_.release();
  69. process_information.hThread = thread_handle_.release();
  70. process_information.dwProcessId = process_id();
  71. process_information.dwThreadId = thread_id();
  72. process_id_ = 0;
  73. thread_id_ = 0;
  74. return process_information;
  75. }
  76. HANDLE ScopedProcessInformation::TakeProcessHandle() {
  77. process_id_ = 0;
  78. return process_handle_.release();
  79. }
  80. HANDLE ScopedProcessInformation::TakeThreadHandle() {
  81. thread_id_ = 0;
  82. return thread_handle_.release();
  83. }
  84. } // namespace win
  85. } // namespace base