88 lines
3.0 KiB
C++
88 lines
3.0 KiB
C++
|
|
// Copyright 2012 The Chromium Authors
|
||
|
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
|
// found in the LICENSE file.
|
||
|
|
|
||
|
|
#include "base/win/startup_information.h"
|
||
|
|
|
||
|
|
#include <windows.h>
|
||
|
|
|
||
|
|
#include <stddef.h>
|
||
|
|
|
||
|
|
#include "base/files/file_path.h"
|
||
|
|
#include "base/path_service.h"
|
||
|
|
#include "base/strings/string_util.h"
|
||
|
|
#include "base/win/scoped_handle.h"
|
||
|
|
#include "base/win/scoped_process_information.h"
|
||
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
class ScopedProcessTerminator {
|
||
|
|
public:
|
||
|
|
explicit ScopedProcessTerminator(const PROCESS_INFORMATION& process_info)
|
||
|
|
: process_info_(process_info) {}
|
||
|
|
|
||
|
|
ScopedProcessTerminator(const ScopedProcessTerminator&) = delete;
|
||
|
|
ScopedProcessTerminator& operator=(const ScopedProcessTerminator&) = delete;
|
||
|
|
|
||
|
|
~ScopedProcessTerminator() {
|
||
|
|
if (process_info_.IsValid())
|
||
|
|
::TerminateProcess(process_info_.process_handle(), 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
base::win::ScopedProcessInformation process_info_;
|
||
|
|
};
|
||
|
|
|
||
|
|
base::win::ScopedHandle CreateInheritedHandle() {
|
||
|
|
HANDLE handle;
|
||
|
|
if (!::DuplicateHandle(::GetCurrentProcess(), ::GetCurrentProcess(),
|
||
|
|
::GetCurrentProcess(), &handle,
|
||
|
|
PROCESS_QUERY_LIMITED_INFORMATION, TRUE, 0)) {
|
||
|
|
return base::win::ScopedHandle();
|
||
|
|
}
|
||
|
|
return base::win::ScopedHandle(handle);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool CheckInheritedHandle(HANDLE process, HANDLE check_handle) {
|
||
|
|
HANDLE temp_handle;
|
||
|
|
if (!::DuplicateHandle(process, check_handle, ::GetCurrentProcess(),
|
||
|
|
&temp_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
base::win::ScopedHandle dup_handle(temp_handle);
|
||
|
|
return ::GetProcessId(temp_handle) == ::GetCurrentProcessId();
|
||
|
|
}
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
// Verify that only the explicitly specified process handle is inherited.
|
||
|
|
TEST(StartupInformationTest, InheritStdOut) {
|
||
|
|
base::win::ScopedHandle handle_0 = CreateInheritedHandle();
|
||
|
|
ASSERT_TRUE(handle_0.is_valid());
|
||
|
|
base::win::ScopedHandle handle_1 = CreateInheritedHandle();
|
||
|
|
ASSERT_TRUE(handle_1.is_valid());
|
||
|
|
ASSERT_NE(handle_0.get(), handle_1.get());
|
||
|
|
|
||
|
|
base::win::StartupInformation startup_info;
|
||
|
|
ASSERT_TRUE(startup_info.InitializeProcThreadAttributeList(1));
|
||
|
|
|
||
|
|
HANDLE inherit_process = handle_0.get();
|
||
|
|
ASSERT_TRUE(startup_info.UpdateProcThreadAttribute(
|
||
|
|
PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &inherit_process,
|
||
|
|
sizeof(inherit_process)));
|
||
|
|
|
||
|
|
base::FilePath exe_path;
|
||
|
|
ASSERT_TRUE(base::PathService::Get(base::FILE_EXE, &exe_path));
|
||
|
|
WCHAR cmd_line[] = L"dummy";
|
||
|
|
|
||
|
|
PROCESS_INFORMATION temp_process_info = {};
|
||
|
|
ASSERT_TRUE(::CreateProcess(
|
||
|
|
exe_path.value().c_str(), cmd_line, nullptr, nullptr, TRUE,
|
||
|
|
EXTENDED_STARTUPINFO_PRESENT | CREATE_SUSPENDED, nullptr, nullptr,
|
||
|
|
startup_info.startup_info(), &temp_process_info))
|
||
|
|
<< ::GetLastError();
|
||
|
|
ScopedProcessTerminator process(temp_process_info);
|
||
|
|
EXPECT_TRUE(CheckInheritedHandle(temp_process_info.hProcess, handle_0.get()));
|
||
|
|
EXPECT_FALSE(
|
||
|
|
CheckInheritedHandle(temp_process_info.hProcess, handle_1.get()));
|
||
|
|
}
|