Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Copyright (c) 2019 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_HANDLES_HPP_
0007 #define BOOST_PROCESS_DETAIL_WINDOWS_HANDLES_HPP_
0008 
0009 #include <vector>
0010 #include <system_error>
0011 #include <boost/process/detail/windows/handle_workaround.hpp>
0012 #include <boost/process/detail/windows/handler.hpp>
0013 #include <boost/winapi/get_current_process_id.hpp>
0014 #include <boost/winapi/handles.hpp>
0015 #include <boost/winapi/handle_info.hpp>
0016 
0017 namespace boost { namespace process { namespace detail {
0018 
0019 
0020 template<typename Executor, typename Function>
0021 void foreach_used_handle(Executor &exec, Function &&func);
0022 
0023 
0024 namespace windows {
0025 
0026 
0027 using native_handle_type = ::boost::winapi::HANDLE_ ;
0028 
0029 inline std::vector<native_handle_type> get_handles(std::error_code & ec)
0030 {
0031     auto pid = ::boost::winapi::GetCurrentProcessId();
0032 
0033     std::vector<char> buffer(2048);
0034     constexpr static auto STATUS_INFO_LENGTH_MISMATCH_ = static_cast<::boost::winapi::NTSTATUS_>(0xC0000004l);
0035     auto info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());
0036 
0037     ::boost::winapi::NTSTATUS_ nt_status = STATUS_INFO_LENGTH_MISMATCH_;
0038 
0039     for (;
0040            nt_status == STATUS_INFO_LENGTH_MISMATCH_;
0041            nt_status = workaround::nt_system_query_information(
0042                             workaround::SystemHandleInformation_,
0043                             info_pointer, static_cast<::boost::winapi::ULONG_>(buffer.size()),
0044                             nullptr))
0045     {
0046         buffer.resize(buffer.size() * 2);
0047         info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());
0048     }
0049 
0050 
0051     if (nt_status < 0 || nt_status > 0x7FFFFFFF)
0052     {
0053         ec = ::boost::process::detail::get_last_error();
0054         return {};
0055     }
0056     else
0057         ec.clear();
0058 
0059     std::vector<native_handle_type> res;
0060     for (auto itr = info_pointer->Handle; itr != (info_pointer->Handle + info_pointer->Count); itr++)
0061     {
0062         if (itr->OwnerPid == pid)
0063             res.push_back(reinterpret_cast<native_handle_type>(static_cast<std::uintptr_t>(itr->HandleValue)));
0064     }
0065 
0066     return res;
0067 }
0068 
0069 inline std::vector<native_handle_type> get_handles()
0070 {
0071     std::error_code ec;
0072 
0073     auto res = get_handles(ec);
0074     if (ec)
0075         boost::process::detail::throw_error(ec, "NtQuerySystemInformation failed");
0076 
0077     return res;
0078 }
0079 
0080 
0081 inline bool is_stream_handle(native_handle_type handle, std::error_code & ec)
0082 {
0083     ::boost::winapi::ULONG_ actual_size;
0084     auto nt_status = workaround::nt_query_object(
0085             handle,
0086             workaround::ObjectTypeInformation,
0087             NULL,
0088             0, &actual_size);
0089 
0090     std::vector<char> vec;
0091     vec.resize(actual_size);
0092 
0093     workaround::OBJECT_TYPE_INFORMATION_ * type_info_p = reinterpret_cast<workaround::OBJECT_TYPE_INFORMATION_*>(vec.data());
0094     nt_status = workaround::nt_query_object(
0095             handle,
0096             workaround::ObjectTypeInformation,
0097             type_info_p,
0098             actual_size, &actual_size);
0099 
0100     if (nt_status < 0 || nt_status > 0x7FFFFFFF)
0101     {
0102         ec = ::boost::process::detail::get_last_error();
0103         return false;
0104     }
0105     else
0106         ec.clear();
0107 
0108     auto &nm = type_info_p->TypeName.Buffer;
0109     return type_info_p->TypeName.Length >= 5 &&
0110             nm[0] == L'F' &&
0111             nm[1] == L'i' &&
0112             nm[2] == L'l' &&
0113             nm[3] == L'e' &&
0114             nm[4] == L'\0';
0115 }
0116 
0117 
0118 inline bool is_stream_handle(native_handle_type handle)
0119 {
0120     std::error_code ec;
0121     auto res = is_stream_handle(handle, ec);
0122     if (ec)
0123         boost::process::detail::throw_error(ec, "NtQueryObject failed");
0124 
0125     return res;
0126 }
0127 
0128 
0129 struct limit_handles_ : handler_base_ext
0130 {
0131     mutable std::vector<::boost::winapi::HANDLE_> handles_with_inherit_flag;
0132 
0133     template<typename Executor>
0134     void on_setup(Executor & exec) const
0135     {
0136         auto all_handles = get_handles();
0137         foreach_used_handle(exec,
0138                 [&](::boost::winapi::HANDLE_ handle)
0139                 {
0140                     auto itr = std::find(all_handles.begin(), all_handles .end(), handle);
0141                     ::boost::winapi::DWORD_ flags = 0u;
0142                     if (itr != all_handles.end())
0143                         *itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
0144                     else if ((::boost::winapi::GetHandleInformation(*itr, &flags) != 0)
0145                             &&((flags & ::boost::winapi::HANDLE_FLAG_INHERIT_) == 0)) //it is NOT inherited anyhow, so ignore too
0146                         *itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
0147                 });
0148 
0149         auto part_itr = std::partition(all_handles.begin(), all_handles.end(),
0150                                        [](::boost::winapi::HANDLE_ handle) {return handle != ::boost::winapi::INVALID_HANDLE_VALUE_;});
0151 
0152         all_handles.erase(part_itr, all_handles.end()); //remove invalid handles
0153         handles_with_inherit_flag = std::move(all_handles);
0154 
0155         for (auto handle : handles_with_inherit_flag)
0156             ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, 0);
0157     }
0158 
0159     template<typename Executor>
0160     void on_error(Executor & exec, const std::error_code & ec) const
0161     {
0162         for (auto handle : handles_with_inherit_flag)
0163             ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
0164     }
0165 
0166     template<typename Executor>
0167     void on_success(Executor & exec) const
0168     {
0169         for (auto handle : handles_with_inherit_flag)
0170             ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
0171     }
0172 
0173 };
0174 
0175 
0176 }}}}
0177 
0178 #endif //PROCESS_HANDLES_HPP