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