1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/win/scoped_process_information.h"
6
7 #include "base/logging.h"
8 #include "base/win/scoped_handle.h"
9
10 namespace base {
11 namespace win {
12
13 namespace {
14
15 // Duplicates source into target, returning true upon success. |target| is
16 // guaranteed to be untouched in case of failure. Succeeds with no side-effects
17 // if source is NULL.
CheckAndDuplicateHandle(HANDLE source,ScopedHandle * target)18 bool CheckAndDuplicateHandle(HANDLE source, ScopedHandle* target) {
19 if (!source)
20 return true;
21
22 HANDLE temp = nullptr;
23 if (!::DuplicateHandle(::GetCurrentProcess(), source, ::GetCurrentProcess(),
24 &temp, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
25 DWORD last_error = ::GetLastError();
26 DPLOG(ERROR) << "Failed to duplicate a handle " << last_error;
27 ::SetLastError(last_error);
28 return false;
29 }
30 target->Set(temp);
31 return true;
32 }
33
34 } // namespace
35
36 ScopedProcessInformation::ScopedProcessInformation() = default;
37
ScopedProcessInformation(const PROCESS_INFORMATION & process_info)38 ScopedProcessInformation::ScopedProcessInformation(
39 const PROCESS_INFORMATION& process_info) {
40 Set(process_info);
41 }
42
43 ScopedProcessInformation::ScopedProcessInformation(ScopedProcessInformation&&) =
44 default;
45
46 ScopedProcessInformation& ScopedProcessInformation::operator=(
47 ScopedProcessInformation&&) = default;
48
~ScopedProcessInformation()49 ScopedProcessInformation::~ScopedProcessInformation() {
50 Close();
51 }
52
IsValid() const53 bool ScopedProcessInformation::IsValid() const {
54 return process_id_ || process_handle_.get() || thread_id_ ||
55 thread_handle_.get();
56 }
57
Close()58 void ScopedProcessInformation::Close() {
59 process_handle_.Close();
60 thread_handle_.Close();
61 process_id_ = 0;
62 thread_id_ = 0;
63 }
64
Set(const PROCESS_INFORMATION & process_info)65 void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) {
66 if (IsValid())
67 Close();
68
69 process_handle_.Set(process_info.hProcess);
70 thread_handle_.Set(process_info.hThread);
71 process_id_ = process_info.dwProcessId;
72 thread_id_ = process_info.dwThreadId;
73 }
74
DuplicateFrom(const ScopedProcessInformation & other)75 bool ScopedProcessInformation::DuplicateFrom(
76 const ScopedProcessInformation& other) {
77 DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL";
78 DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid";
79
80 if (CheckAndDuplicateHandle(other.process_handle(), &process_handle_) &&
81 CheckAndDuplicateHandle(other.thread_handle(), &thread_handle_)) {
82 process_id_ = other.process_id();
83 thread_id_ = other.thread_id();
84 return true;
85 }
86
87 return false;
88 }
89
Take()90 PROCESS_INFORMATION ScopedProcessInformation::Take() {
91 PROCESS_INFORMATION process_information = {};
92 process_information.hProcess = process_handle_.release();
93 process_information.hThread = thread_handle_.release();
94 process_information.dwProcessId = process_id();
95 process_information.dwThreadId = thread_id();
96 process_id_ = 0;
97 thread_id_ = 0;
98
99 return process_information;
100 }
101
TakeProcessHandle()102 HANDLE ScopedProcessInformation::TakeProcessHandle() {
103 process_id_ = 0;
104 return process_handle_.release();
105 }
106
TakeThreadHandle()107 HANDLE ScopedProcessInformation::TakeThreadHandle() {
108 thread_id_ = 0;
109 return thread_handle_.release();
110 }
111
112 } // namespace win
113 } // namespace base
114