// Copyright (c) 2012 The Chromium Authors. All rights reserved. // 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 #include #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())); }