xref: /aosp_15_r20/external/cronet/base/win/startup_information_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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