|  | // 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 <windows.h> | 
|  | #include <stddef.h> | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include "base/command_line.h" | 
|  | #include "base/test/multiprocess_test.h" | 
|  | #include "base/win/scoped_handle.h" | 
|  | #include "base/win/scoped_process_information.h" | 
|  | #include "base/win/startup_information.h" | 
|  | #include "testing/multiprocess_func_list.h" | 
|  |  | 
|  | const wchar_t kSectionName[] = L"EventTestSection"; | 
|  | const size_t kSectionSize = 4096; | 
|  |  | 
|  | MULTIPROCESS_TEST_MAIN(FireInheritedEvents) { | 
|  | HANDLE section = ::OpenFileMappingW(PAGE_READWRITE, false, kSectionName); | 
|  | HANDLE* events = reinterpret_cast<HANDLE*>(::MapViewOfFile(section, | 
|  | PAGE_READWRITE, 0, 0, kSectionSize)); | 
|  | // This event should not be valid because it wasn't explicitly inherited. | 
|  | if (::SetEvent(events[1])) | 
|  | return -1; | 
|  | // This event should be valid because it was explicitly inherited. | 
|  | if (!::SetEvent(events[0])) | 
|  | return -1; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | class StartupInformationTest : public base::MultiProcessTest {}; | 
|  |  | 
|  | // Verify that only the explicitly specified event is inherited. | 
|  | TEST_F(StartupInformationTest, InheritStdOut) { | 
|  | base::win::StartupInformation startup_info; | 
|  |  | 
|  | HANDLE section = ::CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, | 
|  | PAGE_READWRITE, 0, kSectionSize, | 
|  | kSectionName); | 
|  | ASSERT_TRUE(section); | 
|  |  | 
|  | HANDLE* events = reinterpret_cast<HANDLE*>(::MapViewOfFile(section, | 
|  | FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kSectionSize)); | 
|  |  | 
|  | // Make two inheritable events. | 
|  | SECURITY_ATTRIBUTES security_attributes = { sizeof(security_attributes), | 
|  | NULL, true }; | 
|  | events[0] = ::CreateEvent(&security_attributes, false, false, NULL); | 
|  | ASSERT_TRUE(events[0]); | 
|  | events[1] = ::CreateEvent(&security_attributes, false, false, NULL); | 
|  | ASSERT_TRUE(events[1]); | 
|  |  | 
|  | ASSERT_TRUE(startup_info.InitializeProcThreadAttributeList(1)); | 
|  | ASSERT_TRUE(startup_info.UpdateProcThreadAttribute( | 
|  | PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &events[0], | 
|  | sizeof(events[0]))); | 
|  |  | 
|  | std::wstring cmd_line = | 
|  | MakeCmdLine("FireInheritedEvents").GetCommandLineString(); | 
|  |  | 
|  | PROCESS_INFORMATION temp_process_info = {}; | 
|  | ASSERT_TRUE(::CreateProcess(NULL, &cmd_line[0], | 
|  | NULL, NULL, true, EXTENDED_STARTUPINFO_PRESENT, | 
|  | NULL, NULL, startup_info.startup_info(), | 
|  | &temp_process_info)) << ::GetLastError(); | 
|  | base::win::ScopedProcessInformation process_info(temp_process_info); | 
|  |  | 
|  | // Only the first event should be signalled | 
|  | EXPECT_EQ(WAIT_OBJECT_0, ::WaitForMultipleObjects(2, events, false, | 
|  | 4000)); | 
|  | } | 
|  |  |