Skip to content

Commit

Permalink
Base: Update ScopedProcessInformation to use ScopedHandle and restric…
Browse files Browse the repository at this point in the history
…t Receive()

to the span of the callsite.

BUG=none
TEST=base_unittests
Review URL: https://codereview.chromium.org/11636061

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@174998 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
rvargas@google.com committed Jan 3, 2013
1 parent b22143d commit eb91232
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 167 deletions.
82 changes: 33 additions & 49 deletions base/win/scoped_process_information.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,6 @@ 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.
Expand All @@ -42,84 +33,77 @@ bool CheckAndDuplicateHandle(HANDLE source, HANDLE* target) {
} // namespace

ScopedProcessInformation::ScopedProcessInformation()
: process_information_() {
: process_id_(0), thread_id_(0) {
}

ScopedProcessInformation::~ScopedProcessInformation() {
Close();
}

PROCESS_INFORMATION* ScopedProcessInformation::Receive() {
ScopedProcessInformation::Receiver ScopedProcessInformation::Receive() {
DCHECK(!IsValid()) << "process_information_ must be NULL";
return &process_information_;
return Receiver(this);
}

bool ScopedProcessInformation::IsValid() const {
return process_information_.hThread || process_information_.hProcess ||
process_information_.dwProcessId || process_information_.dwThreadId;
return process_id_ || process_handle_.Get() ||
thread_id_ || thread_handle_.Get();
}


void ScopedProcessInformation::Close() {
CheckAndCloseHandle(process_information_.hThread);
CheckAndCloseHandle(process_information_.hProcess);
Reset();
process_handle_.Close();
thread_handle_.Close();
process_id_ = 0;
thread_id_ = 0;
}

void ScopedProcessInformation::Swap(ScopedProcessInformation* other) {
DCHECK(other);
PROCESS_INFORMATION temp = other->process_information_;
other->process_information_ = process_information_;
process_information_ = temp;
void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) {
if (IsValid())
Close();

process_handle_.Set(process_info.hProcess);
thread_handle_.Set(process_info.hThread);
process_id_ = process_info.dwProcessId;
thread_id_ = process_info.dwThreadId;
}

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()) &&
process_handle_.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();
thread_handle_.Receive())) {
process_id_ = other.process_id();
thread_id_ = other.thread_id();
return true;
}

return false;
}

PROCESS_INFORMATION ScopedProcessInformation::Take() {
PROCESS_INFORMATION process_information = process_information_;
Reset();
PROCESS_INFORMATION process_information = {};
process_information.hProcess = process_handle_.Take();
process_information.hThread = thread_handle_.Take();
process_information.dwProcessId = process_id();
process_information.dwThreadId = thread_id();
process_id_ = 0;
thread_id_ = 0;

return process_information;
}

HANDLE ScopedProcessInformation::TakeProcessHandle() {
HANDLE process = process_information_.hProcess;
process_information_.hProcess = NULL;
process_information_.dwProcessId = 0;
return process;
process_id_ = 0;
return process_handle_.Take();
}

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;
thread_id_ = 0;
return thread_handle_.Take();
}

} // namespace win
Expand Down
57 changes: 35 additions & 22 deletions base/win/scoped_process_information.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "base/basictypes.h"
#include "base/base_export.h"
#include "base/win/scoped_handle.h"

namespace base {
namespace win {
Expand All @@ -17,72 +18,84 @@ namespace win {
// structures. Allows clients to take ownership of either handle independently.
class BASE_EXPORT ScopedProcessInformation {
public:
// Creates an instance holding a null PROCESS_INFORMATION.
ScopedProcessInformation();
// Helper object to contain the effect of Receive() to the funtion that needs
// a pointer.
class Receiver {
public:
explicit Receiver(ScopedProcessInformation* owner)
: info_(),
owner_(owner) {}
~Receiver() { owner_->Set(info_); }

operator PROCESS_INFORMATION*() { return &info_; }

private:
PROCESS_INFORMATION info_;
ScopedProcessInformation* owner_;
};

// Closes the held thread and process handles, if any.
ScopedProcessInformation();
~ScopedProcessInformation();

// Returns a pointer that may be passed to API calls such as CreateProcess.
// Returns an object that may be passed to API calls such as CreateProcess.
// DCHECKs that the object is not currently holding any handles.
// HANDLEs stored in the returned PROCESS_INFORMATION will be owned by this
// instance.
PROCESS_INFORMATION* Receive();
// The intended use case is something like this:
// if (::CreateProcess(..., startup_info, scoped_proces_info.Receive()))
Receiver Receive();

// Returns true iff this instance is holding a thread and/or process handle.
bool IsValid() const;

// Closes the held thread and process handles, if any, and resets the held
// PROCESS_INFORMATION to null.
// Closes the held thread and process handles, if any.
void Close();

// Swaps contents with the other ScopedProcessInformation.
void Swap(ScopedProcessInformation* other);
// Populates this instance with the provided |process_info|.
void Set(const PROCESS_INFORMATION& process_info);

// Populates this instance with duplicate handles and the thread/process IDs
// from |other|. Returns false in case of failure, in which case this instance
// will be completely unpopulated.
bool DuplicateFrom(const ScopedProcessInformation& other);

// Transfers ownership of the held PROCESS_INFORMATION, if any, away from this
// instance. Resets the held PROCESS_INFORMATION to null.
// instance.
PROCESS_INFORMATION Take();

// Transfers ownership of the held process handle, if any, away from this
// instance. The hProcess and dwProcessId members of the held
// PROCESS_INFORMATION will be reset.
// instance. Note that the related process_id will also be cleared.
HANDLE TakeProcessHandle();

// Transfers ownership of the held thread handle, if any, away from this
// instance. The hThread and dwThreadId members of the held
// PROCESS_INFORMATION will be reset.
// instance. Note that the related thread_id will also be cleared.
HANDLE TakeThreadHandle();

// Returns the held process handle, if any, while retaining ownership.
HANDLE process_handle() const {
return process_information_.hProcess;
return process_handle_.Get();
}

// Returns the held thread handle, if any, while retaining ownership.
HANDLE thread_handle() const {
return process_information_.hThread;
return thread_handle_.Get();
}

// Returns the held process id, if any.
DWORD process_id() const {
return process_information_.dwProcessId;
return process_id_;
}

// Returns the held thread id, if any.
DWORD thread_id() const {
return process_information_.dwThreadId;
return thread_id_;
}

private:
// Resets the held PROCESS_INFORMATION to null.
void Reset();

PROCESS_INFORMATION process_information_;
ScopedHandle process_handle_;
ScopedHandle thread_handle_;
DWORD process_id_;
DWORD thread_id_;

DISALLOW_COPY_AND_ASSIGN(ScopedProcessInformation);
};
Expand Down
Loading

0 comments on commit eb91232

Please sign in to comment.