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
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 = NULL;
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
ScopedProcessInformation()36 ScopedProcessInformation::ScopedProcessInformation()
37 : process_id_(0), thread_id_(0) {}
38
ScopedProcessInformation(const PROCESS_INFORMATION & process_info)39 ScopedProcessInformation::ScopedProcessInformation(
40 const PROCESS_INFORMATION& process_info)
41 : process_id_(0), thread_id_(0) {
42 Set(process_info);
43 }
44
~ScopedProcessInformation()45 ScopedProcessInformation::~ScopedProcessInformation() {
46 Close();
47 }
48
IsValid() const49 bool ScopedProcessInformation::IsValid() const {
50 return process_id_ || process_handle_.Get() || thread_id_ ||
51 thread_handle_.Get();
52 }
53
Close()54 void ScopedProcessInformation::Close() {
55 process_handle_.Close();
56 thread_handle_.Close();
57 process_id_ = 0;
58 thread_id_ = 0;
59 }
60
Set(const PROCESS_INFORMATION & process_info)61 void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) {
62 if (IsValid())
63 Close();
64
65 process_handle_.Set(process_info.hProcess);
66 thread_handle_.Set(process_info.hThread);
67 process_id_ = process_info.dwProcessId;
68 thread_id_ = process_info.dwThreadId;
69 }
70
DuplicateFrom(const ScopedProcessInformation & other)71 bool ScopedProcessInformation::DuplicateFrom(
72 const ScopedProcessInformation& other) {
73 DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL";
74 DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid";
75
76 if (CheckAndDuplicateHandle(other.process_handle(), &process_handle_) &&
77 CheckAndDuplicateHandle(other.thread_handle(), &thread_handle_)) {
78 process_id_ = other.process_id();
79 thread_id_ = other.thread_id();
80 return true;
81 }
82
83 return false;
84 }
85
Take()86 PROCESS_INFORMATION ScopedProcessInformation::Take() {
87 PROCESS_INFORMATION process_information = {};
88 process_information.hProcess = process_handle_.Take();
89 process_information.hThread = thread_handle_.Take();
90 process_information.dwProcessId = process_id();
91 process_information.dwThreadId = thread_id();
92 process_id_ = 0;
93 thread_id_ = 0;
94
95 return process_information;
96 }
97
TakeProcessHandle()98 HANDLE ScopedProcessInformation::TakeProcessHandle() {
99 process_id_ = 0;
100 return process_handle_.Take();
101 }
102
TakeThreadHandle()103 HANDLE ScopedProcessInformation::TakeThreadHandle() {
104 thread_id_ = 0;
105 return thread_handle_.Take();
106 }
107
108 } // namespace win
109 } // namespace base
110