1 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
2 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
3 // Copyright (c) 2009 Boris Schaeling
4 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
5 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
6 // Copyright (c) 2016 Klemens D. Morgenstern
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
12 #define BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
13 
14 #include <boost/winapi/process.hpp>
15 #include <boost/winapi/handles.hpp>
16 #include <boost/process/detail/used_handles.hpp>
17 #include <boost/process/detail/handler_base.hpp>
18 
19 namespace boost { namespace process { namespace detail { namespace windows {
20 
21 
22 
23 template<int p1, int p2>
24 struct pipe_out : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
25 {
26     ::boost::winapi::HANDLE_ handle;
27 
get_used_handlesboost::process::detail::windows::pipe_out28     ::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
29 
pipe_outboost::process::detail::windows::pipe_out30     pipe_out(::boost::winapi::HANDLE_ handle) : handle(handle) {}
31     template<typename T>
pipe_outboost::process::detail::windows::pipe_out32     pipe_out(T & p) : handle(p.native_sink())
33     {
34         p.assign_sink(::boost::winapi::INVALID_HANDLE_VALUE_);
35     }
36 
37     template<typename WindowsExecutor>
38     void on_setup(WindowsExecutor &e) const;
39 
40     template<typename WindowsExecutor>
on_errorboost::process::detail::windows::pipe_out41     void on_error(WindowsExecutor &, const std::error_code &) const
42     {
43         ::boost::winapi::CloseHandle(handle);
44     }
45 
46     template<typename WindowsExecutor>
on_successboost::process::detail::windows::pipe_out47     void on_success(WindowsExecutor &) const
48     {
49         ::boost::winapi::CloseHandle(handle);
50     }
51 };
52 
53 template<>
54 template<typename WindowsExecutor>
on_setup(WindowsExecutor & e) const55 void pipe_out<1,-1>::on_setup(WindowsExecutor &e) const
56 {
57     boost::winapi::SetHandleInformation(handle,
58             boost::winapi::HANDLE_FLAG_INHERIT_,
59             boost::winapi::HANDLE_FLAG_INHERIT_);
60 
61     e.startup_info.hStdOutput = handle;
62     e.startup_info.dwFlags   |= ::boost::winapi::STARTF_USESTDHANDLES_;
63     e.inherit_handles = true;
64 }
65 
66 template<>
67 template<typename WindowsExecutor>
on_setup(WindowsExecutor & e) const68 void pipe_out<2,-1>::on_setup(WindowsExecutor &e) const
69 {
70     boost::winapi::SetHandleInformation(handle,
71             boost::winapi::HANDLE_FLAG_INHERIT_,
72             boost::winapi::HANDLE_FLAG_INHERIT_);
73 
74 
75     e.startup_info.hStdError = handle;
76     e.startup_info.dwFlags  |= ::boost::winapi::STARTF_USESTDHANDLES_;
77     e.inherit_handles = true;
78 }
79 
80 template<>
81 template<typename WindowsExecutor>
on_setup(WindowsExecutor & e) const82 void pipe_out<1,2>::on_setup(WindowsExecutor &e) const
83 {
84     boost::winapi::SetHandleInformation(handle,
85             boost::winapi::HANDLE_FLAG_INHERIT_,
86             boost::winapi::HANDLE_FLAG_INHERIT_);
87 
88     e.startup_info.hStdOutput = handle;
89     e.startup_info.hStdError  = handle;
90     e.startup_info.dwFlags   |= ::boost::winapi::STARTF_USESTDHANDLES_;
91     e.inherit_handles = true;
92 }
93 
94 template<int p1, int p2>
95 struct async_pipe_out : public pipe_out<p1, p2>
96 {
97     async_pipe &pipe;
98     template<typename AsyncPipe>
async_pipe_outboost::process::detail::windows::async_pipe_out99     async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink()), pipe(p)
100     {
101     }
102 
103     template<typename Pipe, typename Executor>
closeboost::process::detail::windows::async_pipe_out104     static void close(Pipe & pipe, Executor &)
105     {
106         boost::system::error_code ec;
107         std::move(pipe).sink().close(ec);
108     }
109 
110     template<typename Executor>
on_errorboost::process::detail::windows::async_pipe_out111     void on_error(Executor & exec, const std::error_code &)
112     {
113         close(pipe, exec);
114     }
115 
116     template<typename Executor>
on_successboost::process::detail::windows::async_pipe_out117     void on_success(Executor &exec)
118     {
119         close(pipe, exec);
120     }
121 };
122 
123 }}}}
124 
125 #endif
126