1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 <windows.h>
6
7#include <string>
8
9#include "base/command_line.h"
10#include "base/test/multiprocess_test.h"
11#include "base/win/scoped_handle.h"
12#include "base/win/scoped_process_information.h"
13#include "base/win/startup_information.h"
14#include "base/win/windows_version.h"
15#include "testing/multiprocess_func_list.h"
16
17const wchar_t kSectionName[] = L"EventTestSection";
18const size_t kSectionSize = 4096;
19
20MULTIPROCESS_TEST_MAIN(FireInheritedEvents) {
21  HANDLE section = ::OpenFileMappingW(PAGE_READWRITE, false, kSectionName);
22  HANDLE* events = reinterpret_cast<HANDLE*>(::MapViewOfFile(section,
23      PAGE_READWRITE, 0, 0, kSectionSize));
24  // This event should not be valid because it wasn't explicitly inherited.
25  if (::SetEvent(events[1]))
26    return -1;
27  // This event should be valid because it was explicitly inherited.
28  if (!::SetEvent(events[0]))
29    return -1;
30
31  return 0;
32}
33
34class StartupInformationTest : public base::MultiProcessTest {};
35
36// Verify that only the explicitly specified event is inherited.
37TEST_F(StartupInformationTest, InheritStdOut) {
38  if (base::win::GetVersion() < base::win::VERSION_VISTA)
39    return;
40
41  base::win::StartupInformation startup_info;
42
43  HANDLE section = ::CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
44                                        PAGE_READWRITE, 0, kSectionSize,
45                                        kSectionName);
46  ASSERT_TRUE(section);
47
48  HANDLE* events = reinterpret_cast<HANDLE*>(::MapViewOfFile(section,
49      FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kSectionSize));
50
51  // Make two inheritable events.
52  SECURITY_ATTRIBUTES security_attributes = { sizeof(security_attributes),
53                                              NULL, true };
54  events[0] = ::CreateEvent(&security_attributes, false, false, NULL);
55  ASSERT_TRUE(events[0]);
56  events[1] = ::CreateEvent(&security_attributes, false, false, NULL);
57  ASSERT_TRUE(events[1]);
58
59  ASSERT_TRUE(startup_info.InitializeProcThreadAttributeList(1));
60  ASSERT_TRUE(startup_info.UpdateProcThreadAttribute(
61      PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &events[0],
62      sizeof(events[0])));
63
64  std::wstring cmd_line =
65      MakeCmdLine("FireInheritedEvents").GetCommandLineString();
66
67  PROCESS_INFORMATION temp_process_info = {};
68  ASSERT_TRUE(::CreateProcess(NULL, &cmd_line[0],
69                              NULL, NULL, true, EXTENDED_STARTUPINFO_PRESENT,
70                              NULL, NULL, startup_info.startup_info(),
71                              &temp_process_info)) << ::GetLastError();
72  base::win::ScopedProcessInformation process_info(temp_process_info);
73
74  // Only the first event should be signalled
75  EXPECT_EQ(WAIT_OBJECT_0, ::WaitForMultipleObjects(2, events, false,
76                                                    4000));
77}
78
79