summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/win/scoped_process_information.cc82
-rw-r--r--base/win/scoped_process_information.h57
-rw-r--r--base/win/scoped_process_information_unittest.cc165
-rw-r--r--sandbox/win/src/target_process.cc7
4 files changed, 144 insertions, 167 deletions
diff --git a/base/win/scoped_process_information.cc b/base/win/scoped_process_information.cc
index 4adb8d4..cb7a30e 100644
--- a/base/win/scoped_process_information.cc
+++ b/base/win/scoped_process_information.cc
@@ -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.
@@ -42,35 +33,38 @@ 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(
@@ -78,17 +72,12 @@ bool ScopedProcessInformation::DuplicateFrom(
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;
}
@@ -96,30 +85,25 @@ bool ScopedProcessInformation::DuplicateFrom(
}
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
diff --git a/base/win/scoped_process_information.h b/base/win/scoped_process_information.h
index cfa7dc96..1f404c2 100644
--- a/base/win/scoped_process_information.h
+++ b/base/win/scoped_process_information.h
@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/base_export.h"
+#include "base/win/scoped_handle.h"
namespace base {
namespace win {
@@ -17,27 +18,41 @@ 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
@@ -45,44 +60,42 @@ class BASE_EXPORT ScopedProcessInformation {
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);
};
diff --git a/base/win/scoped_process_information_unittest.cc b/base/win/scoped_process_information_unittest.cc
index 906c156..75b69e37 100644
--- a/base/win/scoped_process_information_unittest.cc
+++ b/base/win/scoped_process_information_unittest.cc
@@ -12,6 +12,22 @@
#include "base/win/scoped_process_information.h"
#include "testing/multiprocess_func_list.h"
+namespace {
+
+const DWORD kProcessId = 4321;
+const DWORD kThreadId = 1234;
+const HANDLE kProcessHandle = reinterpret_cast<HANDLE>(7651);
+const HANDLE kThreadHandle = reinterpret_cast<HANDLE>(1567);
+
+void MockCreateProcess(PROCESS_INFORMATION* process_info) {
+ process_info->dwProcessId = kProcessId;
+ process_info->dwThreadId = kThreadId;
+ process_info->hProcess = kProcessHandle;
+ process_info->hThread = kThreadHandle;
+}
+
+} // namespace
+
class ScopedProcessInformationTest : public base::MultiProcessTest {
protected:
void DoCreateProcess(const std::string& main_id,
@@ -39,76 +55,67 @@ void ScopedProcessInformationTest::DoCreateProcess(
&startup_info, process_handle));
}
+TEST_F(ScopedProcessInformationTest, InitiallyInvalid) {
+ base::win::ScopedProcessInformation process_info;
+ ASSERT_FALSE(process_info.IsValid());
+}
+
+TEST_F(ScopedProcessInformationTest, Receive) {
+ base::win::ScopedProcessInformation process_info;
+ MockCreateProcess(process_info.Receive());
+
+ EXPECT_TRUE(process_info.IsValid());
+ EXPECT_EQ(kProcessId, process_info.process_id());
+ EXPECT_EQ(kThreadId, process_info.thread_id());
+ EXPECT_EQ(kProcessHandle, process_info.process_handle());
+ EXPECT_EQ(kThreadHandle, process_info.thread_handle());
+ PROCESS_INFORMATION to_discard = process_info.Take();
+}
+
TEST_F(ScopedProcessInformationTest, TakeProcess) {
base::win::ScopedProcessInformation process_info;
- DoCreateProcess("ReturnSeven", process_info.Receive());
- int exit_code = 0;
- ASSERT_TRUE(base::WaitForExitCode(process_info.TakeProcessHandle(),
- &exit_code));
- ASSERT_EQ(7, exit_code);
- ASSERT_TRUE(process_info.IsValid());
- ASSERT_EQ(0u, process_info.process_id());
- ASSERT_TRUE(process_info.process_handle() == NULL);
- ASSERT_NE(0u, process_info.thread_id());
- ASSERT_FALSE(process_info.thread_handle() == NULL);
+ MockCreateProcess(process_info.Receive());
+
+ HANDLE process = process_info.TakeProcessHandle();
+ EXPECT_EQ(kProcessHandle, process);
+ EXPECT_EQ(NULL, process_info.process_handle());
+ EXPECT_EQ(0, process_info.process_id());
+ EXPECT_TRUE(process_info.IsValid());
+ PROCESS_INFORMATION to_discard = process_info.Take();
}
TEST_F(ScopedProcessInformationTest, TakeThread) {
base::win::ScopedProcessInformation process_info;
- DoCreateProcess("ReturnSeven", process_info.Receive());
- ASSERT_TRUE(::CloseHandle(process_info.TakeThreadHandle()));
- ASSERT_TRUE(process_info.IsValid());
- ASSERT_NE(0u, process_info.process_id());
- ASSERT_FALSE(process_info.process_handle() == NULL);
- ASSERT_EQ(0u, process_info.thread_id());
- ASSERT_TRUE(process_info.thread_handle() == NULL);
+ MockCreateProcess(process_info.Receive());
+
+ HANDLE thread = process_info.TakeThreadHandle();
+ EXPECT_EQ(kThreadHandle, thread);
+ EXPECT_EQ(NULL, process_info.thread_handle());
+ EXPECT_EQ(0, process_info.thread_id());
+ EXPECT_TRUE(process_info.IsValid());
+ PROCESS_INFORMATION to_discard = process_info.Take();
}
TEST_F(ScopedProcessInformationTest, TakeBoth) {
base::win::ScopedProcessInformation process_info;
- DoCreateProcess("ReturnSeven", process_info.Receive());
- int exit_code = 0;
- ASSERT_TRUE(base::WaitForExitCode(process_info.TakeProcessHandle(),
- &exit_code));
- ASSERT_EQ(7, exit_code);
- ASSERT_TRUE(::CloseHandle(process_info.TakeThreadHandle()));
- ASSERT_FALSE(process_info.IsValid());
- ASSERT_EQ(0u, process_info.process_id());
- ASSERT_TRUE(process_info.process_handle() == NULL);
- ASSERT_EQ(0u, process_info.thread_id());
- ASSERT_TRUE(process_info.thread_handle() == NULL);
-}
+ MockCreateProcess(process_info.Receive());
-TEST_F(ScopedProcessInformationTest, TakeNothing) {
- base::win::ScopedProcessInformation process_info;
- DoCreateProcess("ReturnSeven", process_info.Receive());
- ASSERT_TRUE(process_info.IsValid());
- ASSERT_NE(0u, process_info.thread_id());
- ASSERT_FALSE(process_info.thread_handle() == NULL);
- ASSERT_NE(0u, process_info.process_id());
- ASSERT_FALSE(process_info.process_handle() == NULL);
+ HANDLE process = process_info.TakeProcessHandle();
+ HANDLE thread = process_info.TakeThreadHandle();
+ EXPECT_FALSE(process_info.IsValid());
+ PROCESS_INFORMATION to_discard = process_info.Take();
}
TEST_F(ScopedProcessInformationTest, TakeWholeStruct) {
base::win::ScopedProcessInformation process_info;
- DoCreateProcess("ReturnSeven", process_info.Receive());
- base::win::ScopedProcessInformation other;
- *other.Receive() = process_info.Take();
-
- ASSERT_FALSE(process_info.IsValid());
- ASSERT_EQ(0u, process_info.process_id());
- ASSERT_TRUE(process_info.process_handle() == NULL);
- ASSERT_EQ(0u, process_info.thread_id());
- ASSERT_TRUE(process_info.thread_handle() == NULL);
-
- // Validate that what was taken is good.
- ASSERT_NE(0u, other.thread_id());
- ASSERT_NE(0u, other.process_id());
- int exit_code = 0;
- ASSERT_TRUE(base::WaitForExitCode(other.TakeProcessHandle(),
- &exit_code));
- ASSERT_EQ(7, exit_code);
- ASSERT_TRUE(::CloseHandle(other.TakeThreadHandle()));
+ MockCreateProcess(process_info.Receive());
+
+ PROCESS_INFORMATION to_discard = process_info.Take();
+ EXPECT_EQ(kProcessId, to_discard.dwProcessId);
+ EXPECT_EQ(kThreadId, to_discard.dwThreadId);
+ EXPECT_EQ(kProcessHandle, to_discard.hProcess);
+ EXPECT_EQ(kThreadHandle, to_discard.hThread);
+ EXPECT_FALSE(process_info.IsValid());
}
TEST_F(ScopedProcessInformationTest, Duplicate) {
@@ -138,44 +145,16 @@ TEST_F(ScopedProcessInformationTest, Duplicate) {
ASSERT_TRUE(::CloseHandle(duplicate.TakeThreadHandle()));
}
-TEST_F(ScopedProcessInformationTest, Swap) {
- base::win::ScopedProcessInformation seven_to_nine_info;
- DoCreateProcess("ReturnSeven", seven_to_nine_info.Receive());
- base::win::ScopedProcessInformation nine_to_seven_info;
- DoCreateProcess("ReturnNine", nine_to_seven_info.Receive());
-
- HANDLE seven_process = seven_to_nine_info.process_handle();
- DWORD seven_process_id = seven_to_nine_info.process_id();
- HANDLE seven_thread = seven_to_nine_info.thread_handle();
- DWORD seven_thread_id = seven_to_nine_info.thread_id();
- HANDLE nine_process = nine_to_seven_info.process_handle();
- DWORD nine_process_id = nine_to_seven_info.process_id();
- HANDLE nine_thread = nine_to_seven_info.thread_handle();
- DWORD nine_thread_id = nine_to_seven_info.thread_id();
-
- seven_to_nine_info.Swap(&nine_to_seven_info);
-
- ASSERT_EQ(seven_process, nine_to_seven_info.process_handle());
- ASSERT_EQ(seven_process_id, nine_to_seven_info.process_id());
- ASSERT_EQ(seven_thread, nine_to_seven_info.thread_handle());
- ASSERT_EQ(seven_thread_id, nine_to_seven_info.thread_id());
- ASSERT_EQ(nine_process, seven_to_nine_info.process_handle());
- ASSERT_EQ(nine_process_id, seven_to_nine_info.process_id());
- ASSERT_EQ(nine_thread, seven_to_nine_info.thread_handle());
- ASSERT_EQ(nine_thread_id, seven_to_nine_info.thread_id());
+TEST_F(ScopedProcessInformationTest, Set) {
+ PROCESS_INFORMATION base_process_info = {};
+ MockCreateProcess(&base_process_info);
- int exit_code = 0;
- ASSERT_TRUE(base::WaitForExitCode(seven_to_nine_info.TakeProcessHandle(),
- &exit_code));
- ASSERT_EQ(9, exit_code);
-
- ASSERT_TRUE(base::WaitForExitCode(nine_to_seven_info.TakeProcessHandle(),
- &exit_code));
- ASSERT_EQ(7, exit_code);
-
-}
-
-TEST_F(ScopedProcessInformationTest, InitiallyInvalid) {
base::win::ScopedProcessInformation process_info;
- ASSERT_FALSE(process_info.IsValid());
+ process_info.Set(base_process_info);
+
+ EXPECT_EQ(kProcessId, process_info.process_id());
+ EXPECT_EQ(kThreadId, process_info.thread_id());
+ EXPECT_EQ(kProcessHandle, process_info.process_handle());
+ EXPECT_EQ(kThreadHandle, process_info.thread_handle());
+ base_process_info = process_info.Take();
}
diff --git a/sandbox/win/src/target_process.cc b/sandbox/win/src/target_process.cc
index 5de6ee0..2bc1fec 100644
--- a/sandbox/win/src/target_process.cc
+++ b/sandbox/win/src/target_process.cc
@@ -198,7 +198,7 @@ DWORD TargetProcess::Create(const wchar_t* exe_path,
}
base_address_ = GetBaseAddress(exe_path, entry_point);
- sandbox_process_info_.Swap(&process_info);
+ sandbox_process_info_.Set(process_info.Take());
return win_result;
}
@@ -324,10 +324,11 @@ void TargetProcess::Terminate() {
::TerminateProcess(sandbox_process_info_.process_handle(), 0);
}
-
TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) {
TargetProcess* target = new TargetProcess(NULL, NULL, NULL, NULL);
- target->sandbox_process_info_.Receive()->hProcess = process;
+ PROCESS_INFORMATION process_info = {};
+ process_info.hProcess = process;
+ target->sandbox_process_info_.Set(process_info);
target->base_address_ = base_address;
return target;
}