Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:07

0001 // Copyright (c) 2016 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP
0007 #define BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP
0008 
0009 #include <boost/winapi/basic_types.hpp>
0010 #include <boost/winapi/error_codes.hpp>
0011 #include <boost/winapi/pipes.hpp>
0012 #include <boost/winapi/handles.hpp>
0013 #include <boost/winapi/file_management.hpp>
0014 #include <boost/winapi/get_last_error.hpp>
0015 #include <boost/winapi/access_rights.hpp>
0016 #include <boost/winapi/process.hpp>
0017 #include <boost/process/detail/windows/compare_handles.hpp>
0018 #include <system_error>
0019 #include <string>
0020 
0021 
0022 namespace boost { namespace process { namespace detail { namespace windows {
0023 
0024 template<class CharT, class Traits = std::char_traits<CharT>>
0025 class basic_pipe
0026 {
0027     ::boost::winapi::HANDLE_ _source = ::boost::winapi::INVALID_HANDLE_VALUE_;
0028     ::boost::winapi::HANDLE_ _sink   = ::boost::winapi::INVALID_HANDLE_VALUE_;
0029 public:
0030     typedef CharT                      char_type  ;
0031     typedef          Traits            traits_type;
0032     typedef typename Traits::int_type  int_type   ;
0033     typedef typename Traits::pos_type  pos_type   ;
0034     typedef typename Traits::off_type  off_type   ;
0035     typedef ::boost::winapi::HANDLE_ native_handle_type;
0036 
0037     explicit basic_pipe(::boost::winapi::HANDLE_ source, ::boost::winapi::HANDLE_ sink)
0038             : _source(source), _sink(sink) {}
0039     inline explicit basic_pipe(const std::string & name);
0040     inline basic_pipe(const basic_pipe& p);
0041     basic_pipe(basic_pipe&& lhs)  : _source(lhs._source), _sink(lhs._sink)
0042     {
0043         lhs._source = ::boost::winapi::INVALID_HANDLE_VALUE_;
0044         lhs._sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
0045     }
0046     inline basic_pipe& operator=(const basic_pipe& p);
0047     inline basic_pipe& operator=(basic_pipe&& lhs);
0048     ~basic_pipe()
0049     {
0050         if (_sink   != ::boost::winapi::INVALID_HANDLE_VALUE_)
0051             ::boost::winapi::CloseHandle(_sink);
0052         if (_source != ::boost::winapi::INVALID_HANDLE_VALUE_)
0053             ::boost::winapi::CloseHandle(_source);
0054     }
0055     native_handle_type native_source() const {return _source;}
0056     native_handle_type native_sink  () const {return _sink;}
0057 
0058     void assign_source(native_handle_type h) { _source = h;}
0059     void assign_sink  (native_handle_type h) { _sink = h;}
0060 
0061     basic_pipe()
0062     {
0063         if (!::boost::winapi::CreatePipe(&_source, &_sink, nullptr, 0))
0064             throw_last_error("CreatePipe() failed");
0065 
0066     }
0067 
0068     int_type write(const char_type * data, int_type count)
0069     {
0070         ::boost::winapi::DWORD_ write_len;
0071         if (!::boost::winapi::WriteFile(
0072                 _sink, data, count * sizeof(char_type), &write_len, nullptr
0073                 ))
0074         {
0075             auto ec = ::boost::process::detail::get_last_error();
0076             if ((ec.value() == ::boost::winapi::ERROR_BROKEN_PIPE_) ||
0077                 (ec.value() == ::boost::winapi::ERROR_NO_DATA_))
0078                 return 0;
0079             else
0080                 throw process_error(ec, "WriteFile failed");
0081         }
0082         return static_cast<int_type>(write_len);
0083     }
0084     int_type read(char_type * data, int_type count)
0085     {
0086         ::boost::winapi::DWORD_ read_len;
0087         if (!::boost::winapi::ReadFile(
0088                 _source, data, count * sizeof(char_type), &read_len, nullptr
0089                 ))
0090         {
0091             auto ec = ::boost::process::detail::get_last_error();
0092             if ((ec.value() == ::boost::winapi::ERROR_BROKEN_PIPE_) ||
0093                 (ec.value() == ::boost::winapi::ERROR_NO_DATA_))
0094                 return 0;
0095             else
0096                 throw process_error(ec, "ReadFile failed");
0097         }
0098         return static_cast<int_type>(read_len);
0099     }
0100 
0101     bool is_open() const
0102     {
0103         return (_source != ::boost::winapi::INVALID_HANDLE_VALUE_) ||
0104                (_sink   != ::boost::winapi::INVALID_HANDLE_VALUE_);
0105     }
0106 
0107     void close()
0108     {
0109         ::boost::winapi::CloseHandle(_source);
0110         ::boost::winapi::CloseHandle(_sink);
0111         _source = ::boost::winapi::INVALID_HANDLE_VALUE_;
0112         _sink   = ::boost::winapi::INVALID_HANDLE_VALUE_;
0113     }
0114 };
0115 
0116 template<class Char, class Traits>
0117 basic_pipe<Char, Traits>::basic_pipe(const basic_pipe & p)
0118 {
0119     auto proc = ::boost::winapi::GetCurrentProcess();
0120 
0121     if (p._source == ::boost::winapi::INVALID_HANDLE_VALUE_)
0122         _source = ::boost::winapi::INVALID_HANDLE_VALUE_;
0123     else if (!::boost::winapi::DuplicateHandle(
0124             proc, p._source, proc, &_source, 0,
0125             static_cast<::boost::winapi::BOOL_>(true),
0126              ::boost::winapi::DUPLICATE_SAME_ACCESS_))
0127         throw_last_error("Duplicate Pipe Failed");
0128 
0129     if (p._sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
0130         _sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
0131     else if (!::boost::winapi::DuplicateHandle(
0132             proc, p._sink, proc, &_sink, 0,
0133             static_cast<::boost::winapi::BOOL_>(true),
0134              ::boost::winapi::DUPLICATE_SAME_ACCESS_))
0135         throw_last_error("Duplicate Pipe Failed");
0136 
0137 }
0138 
0139 template<class Char, class Traits>
0140 basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
0141 {
0142     static constexpr int OPEN_EXISTING_         = 3; //temporary.
0143     static constexpr int FILE_FLAG_OVERLAPPED_  = 0x40000000; //temporary
0144     //static constexpr int FILE_ATTRIBUTE_NORMAL_ = 0x00000080; //temporary
0145 
0146 #if BOOST_NO_ANSI_APIS
0147     std::wstring name_ = boost::process::detail::convert(name);
0148 #else
0149     auto &name_ = name;
0150 #endif
0151     ::boost::winapi::HANDLE_ source = ::boost::winapi::create_named_pipe(
0152             name_.c_str(),
0153             ::boost::winapi::PIPE_ACCESS_INBOUND_
0154             | FILE_FLAG_OVERLAPPED_, //write flag
0155             0, ::boost::winapi::PIPE_UNLIMITED_INSTANCES_, 8192, 8192, 0, nullptr);
0156 
0157     if (source == boost::winapi::INVALID_HANDLE_VALUE_)
0158         ::boost::process::detail::throw_last_error("create_named_pipe() failed");
0159 
0160     ::boost::winapi::HANDLE_ sink = boost::winapi::create_file(
0161             name_.c_str(),
0162             ::boost::winapi::GENERIC_WRITE_, 0, nullptr,
0163             OPEN_EXISTING_,
0164             FILE_FLAG_OVERLAPPED_, //to allow read
0165             nullptr);
0166 
0167     if (sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
0168         ::boost::process::detail::throw_last_error("create_file() failed");
0169 
0170     _source = source;
0171     _sink   = sink;
0172 }
0173 
0174 template<class Char, class Traits>
0175 basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(const basic_pipe & p)
0176 {
0177     auto proc = ::boost::winapi::GetCurrentProcess();
0178 
0179     if (p._source == ::boost::winapi::INVALID_HANDLE_VALUE_)
0180         _source = ::boost::winapi::INVALID_HANDLE_VALUE_;
0181     else if (!::boost::winapi::DuplicateHandle(
0182             proc, p._source, proc, &_source, 0,
0183             static_cast<::boost::winapi::BOOL_>(true),
0184              ::boost::winapi::DUPLICATE_SAME_ACCESS_))
0185         throw_last_error("Duplicate Pipe Failed");
0186 
0187     if (p._sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
0188         _sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
0189     else if (!::boost::winapi::DuplicateHandle(
0190             proc, p._sink, proc, &_sink, 0,
0191             static_cast<::boost::winapi::BOOL_>(true),
0192              ::boost::winapi::DUPLICATE_SAME_ACCESS_))
0193         throw_last_error("Duplicate Pipe Failed");
0194 
0195     return *this;
0196 }
0197 
0198 template<class Char, class Traits>
0199 basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(basic_pipe && lhs)
0200 {
0201     if (_source != ::boost::winapi::INVALID_HANDLE_VALUE_)
0202         ::boost::winapi::CloseHandle(_source);
0203 
0204     if (_sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
0205         ::boost::winapi::CloseHandle(_sink);
0206 
0207     _source = lhs._source;
0208     _sink   = lhs._sink;
0209     lhs._source = ::boost::winapi::INVALID_HANDLE_VALUE_;
0210     lhs._sink   = ::boost::winapi::INVALID_HANDLE_VALUE_;
0211     return *this;
0212 }
0213 
0214 template<class Char, class Traits>
0215 inline bool operator==(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
0216 {
0217     return compare_handles(lhs.native_source(), rhs.native_source()) &&
0218            compare_handles(lhs.native_sink(),   rhs.native_sink());
0219 }
0220 
0221 template<class Char, class Traits>
0222 inline bool operator!=(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs)
0223 {
0224     return !compare_handles(lhs.native_source(), rhs.native_source()) ||
0225            !compare_handles(lhs.native_sink(),   rhs.native_sink());
0226 }
0227 
0228 }}}}
0229 
0230 #endif