Home | History | Annotate | Download | only in win
      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
    111