1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/win/startup_information.h"
6
7 #include <windows.h>
8
9 #include <stddef.h>
10
11 #include "base/files/file_path.h"
12 #include "base/path_service.h"
13 #include "base/strings/string_util.h"
14 #include "base/win/scoped_handle.h"
15 #include "base/win/scoped_process_information.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace {
19 class ScopedProcessTerminator {
20 public:
ScopedProcessTerminator(const PROCESS_INFORMATION & process_info)21 explicit ScopedProcessTerminator(const PROCESS_INFORMATION& process_info)
22 : process_info_(process_info) {}
23
24 ScopedProcessTerminator(const ScopedProcessTerminator&) = delete;
25 ScopedProcessTerminator& operator=(const ScopedProcessTerminator&) = delete;
26
~ScopedProcessTerminator()27 ~ScopedProcessTerminator() {
28 if (process_info_.IsValid())
29 ::TerminateProcess(process_info_.process_handle(), 0);
30 }
31
32 private:
33 base::win::ScopedProcessInformation process_info_;
34 };
35
CreateInheritedHandle()36 base::win::ScopedHandle CreateInheritedHandle() {
37 HANDLE handle;
38 if (!::DuplicateHandle(::GetCurrentProcess(), ::GetCurrentProcess(),
39 ::GetCurrentProcess(), &handle,
40 PROCESS_QUERY_LIMITED_INFORMATION, TRUE, 0)) {
41 return base::win::ScopedHandle();
42 }
43 return base::win::ScopedHandle(handle);
44 }
45
CheckInheritedHandle(HANDLE process,HANDLE check_handle)46 bool CheckInheritedHandle(HANDLE process, HANDLE check_handle) {
47 HANDLE temp_handle;
48 if (!::DuplicateHandle(process, check_handle, ::GetCurrentProcess(),
49 &temp_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
50 return false;
51 }
52 base::win::ScopedHandle dup_handle(temp_handle);
53 return ::GetProcessId(temp_handle) == ::GetCurrentProcessId();
54 }
55 } // namespace
56
57 // Verify that only the explicitly specified process handle is inherited.
TEST(StartupInformationTest,InheritStdOut)58 TEST(StartupInformationTest, InheritStdOut) {
59 base::win::ScopedHandle handle_0 = CreateInheritedHandle();
60 ASSERT_TRUE(handle_0.is_valid());
61 base::win::ScopedHandle handle_1 = CreateInheritedHandle();
62 ASSERT_TRUE(handle_1.is_valid());
63 ASSERT_NE(handle_0.get(), handle_1.get());
64
65 base::win::StartupInformation startup_info;
66 ASSERT_TRUE(startup_info.InitializeProcThreadAttributeList(1));
67
68 HANDLE inherit_process = handle_0.get();
69 ASSERT_TRUE(startup_info.UpdateProcThreadAttribute(
70 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &inherit_process,
71 sizeof(inherit_process)));
72
73 base::FilePath exe_path;
74 ASSERT_TRUE(base::PathService::Get(base::FILE_EXE, &exe_path));
75 WCHAR cmd_line[] = L"dummy";
76
77 PROCESS_INFORMATION temp_process_info = {};
78 ASSERT_TRUE(::CreateProcess(
79 exe_path.value().c_str(), cmd_line, nullptr, nullptr, TRUE,
80 EXTENDED_STARTUPINFO_PRESENT | CREATE_SUSPENDED, nullptr, nullptr,
81 startup_info.startup_info(), &temp_process_info))
82 << ::GetLastError();
83 ScopedProcessTerminator process(temp_process_info);
84 EXPECT_TRUE(CheckInheritedHandle(temp_process_info.hProcess, handle_0.get()));
85 EXPECT_FALSE(
86 CheckInheritedHandle(temp_process_info.hProcess, handle_1.get()));
87 }
88