|
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. |
|
18 bool CheckAndDuplicateHandle(HANDLE source, HANDLE* target) { |
|
19 if (!source) |
|
20 return true; |
|
21 |
|
22 HANDLE temp = NULL; |
|
23 if (!::DuplicateHandle(::GetCurrentProcess(), source, |
|
24 ::GetCurrentProcess(), &temp, 0, FALSE, |
|
25 DUPLICATE_SAME_ACCESS)) { |
|
26 DPLOG(ERROR) << "Failed to duplicate a handle."; |
|
27 return false; |
|
28 } |
|
29 *target = temp; |
|
30 return true; |
|
31 } |
|
32 |
|
33 } // namespace |
|
34 |
|
35 ScopedProcessInformation::ScopedProcessInformation() |
|
36 : process_id_(0), thread_id_(0) { |
|
37 } |
|
38 |
|
39 ScopedProcessInformation::~ScopedProcessInformation() { |
|
40 Close(); |
|
41 } |
|
42 |
|
43 ScopedProcessInformation::Receiver ScopedProcessInformation::Receive() { |
|
44 DCHECK(!IsValid()) << "process_information_ must be NULL"; |
|
45 return Receiver(this); |
|
46 } |
|
47 |
|
48 bool ScopedProcessInformation::IsValid() const { |
|
49 return process_id_ || process_handle_.Get() || |
|
50 thread_id_ || thread_handle_.Get(); |
|
51 } |
|
52 |
|
53 void ScopedProcessInformation::Close() { |
|
54 process_handle_.Close(); |
|
55 thread_handle_.Close(); |
|
56 process_id_ = 0; |
|
57 thread_id_ = 0; |
|
58 } |
|
59 |
|
60 void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) { |
|
61 if (IsValid()) |
|
62 Close(); |
|
63 |
|
64 process_handle_.Set(process_info.hProcess); |
|
65 thread_handle_.Set(process_info.hThread); |
|
66 process_id_ = process_info.dwProcessId; |
|
67 thread_id_ = process_info.dwThreadId; |
|
68 } |
|
69 |
|
70 bool ScopedProcessInformation::DuplicateFrom( |
|
71 const ScopedProcessInformation& other) { |
|
72 DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL"; |
|
73 DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid"; |
|
74 |
|
75 if (CheckAndDuplicateHandle(other.process_handle(), |
|
76 process_handle_.Receive()) && |
|
77 CheckAndDuplicateHandle(other.thread_handle(), |
|
78 thread_handle_.Receive())) { |
|
79 process_id_ = other.process_id(); |
|
80 thread_id_ = other.thread_id(); |
|
81 return true; |
|
82 } |
|
83 |
|
84 return false; |
|
85 } |
|
86 |
|
87 PROCESS_INFORMATION ScopedProcessInformation::Take() { |
|
88 PROCESS_INFORMATION process_information = {}; |
|
89 process_information.hProcess = process_handle_.Take(); |
|
90 process_information.hThread = thread_handle_.Take(); |
|
91 process_information.dwProcessId = process_id(); |
|
92 process_information.dwThreadId = thread_id(); |
|
93 process_id_ = 0; |
|
94 thread_id_ = 0; |
|
95 |
|
96 return process_information; |
|
97 } |
|
98 |
|
99 HANDLE ScopedProcessInformation::TakeProcessHandle() { |
|
100 process_id_ = 0; |
|
101 return process_handle_.Take(); |
|
102 } |
|
103 |
|
104 HANDLE ScopedProcessInformation::TakeThreadHandle() { |
|
105 thread_id_ = 0; |
|
106 return thread_handle_.Take(); |
|
107 } |
|
108 |
|
109 } // namespace win |
|
110 } // namespace base |