15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_process_information.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace win {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Duplicates source into target, returning true upon success. |target| is
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// guaranteed to be untouched in case of failure. Succeeds with no side-effects
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if source is NULL.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckAndDuplicateHandle(HANDLE source, HANDLE* target) {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!source)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE temp = NULL;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::DuplicateHandle(::GetCurrentProcess(), source,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         ::GetCurrentProcess(), &temp, 0, FALSE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         DUPLICATE_SAME_ACCESS)) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DPLOG(ERROR) << "Failed to duplicate a handle.";
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *target = temp;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedProcessInformation::ScopedProcessInformation()
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : process_id_(0), thread_id_(0) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedProcessInformation::~ScopedProcessInformation() {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Close();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScopedProcessInformation::Receiver ScopedProcessInformation::Receive() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsValid()) << "process_information_ must be NULL";
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Receiver(this);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ScopedProcessInformation::IsValid() const {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return process_id_ || process_handle_.Get() ||
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         thread_id_ || thread_handle_.Get();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedProcessInformation::Close() {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_handle_.Close();
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_handle_.Close();
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_id_ = 0;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_id_ = 0;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsValid())
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Close();
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_handle_.Set(process_info.hProcess);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_handle_.Set(process_info.hThread);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_id_ = process_info.dwProcessId;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_id_ = process_info.dwThreadId;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ScopedProcessInformation::DuplicateFrom(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ScopedProcessInformation& other) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL";
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid";
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CheckAndDuplicateHandle(other.process_handle(),
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              process_handle_.Receive()) &&
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckAndDuplicateHandle(other.thread_handle(),
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              thread_handle_.Receive())) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    process_id_ = other.process_id();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thread_id_ = other.thread_id();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PROCESS_INFORMATION ScopedProcessInformation::Take() {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PROCESS_INFORMATION process_information = {};
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_information.hProcess = process_handle_.Take();
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_information.hThread = thread_handle_.Take();
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_information.dwProcessId = process_id();
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_information.dwThreadId = thread_id();
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_id_ = 0;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_id_ = 0;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return process_information;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HANDLE ScopedProcessInformation::TakeProcessHandle() {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  process_id_ = 0;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return process_handle_.Take();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HANDLE ScopedProcessInformation::TakeThreadHandle() {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_id_ = 0;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return thread_handle_.Take();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace win
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
111