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