]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/process/detail/windows/handles.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / process / detail / windows / handles.hpp
CommitLineData
92f5a8d4
TL
1// Copyright (c) 2019 Klemens D. Morgenstern
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef BOOST_PROCESS_DETAIL_WINDOWS_HANDLES_HPP_
7#define BOOST_PROCESS_DETAIL_WINDOWS_HANDLES_HPP_
8
9#include <vector>
10#include <system_error>
11#include <boost/process/detail/windows/handle_workaround.hpp>
12#include <boost/process/detail/windows/handler.hpp>
13#include <boost/winapi/get_current_process_id.hpp>
14
15namespace boost { namespace process { namespace detail {
16
17
18template<typename Executor, typename Function>
19void foreach_used_handle(Executor &exec, Function &&func);
20
21
22namespace windows {
23
24
25using native_handle_type = ::boost::winapi::HANDLE_ ;
26
27inline std::vector<native_handle_type> get_handles(std::error_code & ec)
28{
29 auto pid = ::boost::winapi::GetCurrentProcessId();
30
31 std::vector<char> buffer(2048);
32 constexpr static auto STATUS_INFO_LENGTH_MISMATCH_ = static_cast<::boost::winapi::NTSTATUS_>(0xC0000004l);
33 auto info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());
34
35 ::boost::winapi::NTSTATUS_ nt_status = STATUS_INFO_LENGTH_MISMATCH_;
36
f67539c2 37 for (;
92f5a8d4
TL
38 nt_status == STATUS_INFO_LENGTH_MISMATCH_;
39 nt_status = workaround::nt_system_query_information(
40 workaround::SystemHandleInformation_,
f67539c2
TL
41 info_pointer, static_cast<::boost::winapi::ULONG_>(buffer.size()),
42 nullptr))
92f5a8d4
TL
43 {
44 buffer.resize(buffer.size() * 2);
45 info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());
46 }
47
48
49 if (nt_status < 0 || nt_status > 0x7FFFFFFF)
50 {
51 ec = ::boost::process::detail::get_last_error();
52 return {};
53 }
54 else
55 ec.clear();
56
57 std::vector<native_handle_type> res;
58 for (auto itr = info_pointer->Handle; itr != (info_pointer->Handle + info_pointer->Count); itr++)
59 {
60 if (itr->OwnerPid == pid)
61 res.push_back(reinterpret_cast<native_handle_type>(static_cast<std::uintptr_t>(itr->HandleValue)));
62 }
63
64 return res;
65}
66
67inline std::vector<native_handle_type> get_handles()
68{
69 std::error_code ec;
70
71 auto res = get_handles(ec);
72 if (ec)
73 boost::process::detail::throw_error(ec, "NtQuerySystemInformation failed");
74
75 return res;
76}
77
78
79inline bool is_stream_handle(native_handle_type handle, std::error_code & ec)
80{
81 ::boost::winapi::ULONG_ actual_size;
82 auto nt_status = workaround::nt_query_object(
83 handle,
84 workaround::ObjectTypeInformation,
85 NULL,
86 0, &actual_size);
87
88 std::vector<char> vec;
89 vec.resize(actual_size);
90
91 workaround::OBJECT_TYPE_INFORMATION_ * type_info_p = reinterpret_cast<workaround::OBJECT_TYPE_INFORMATION_*>(vec.data());
92 nt_status = workaround::nt_query_object(
93 handle,
94 workaround::ObjectTypeInformation,
95 type_info_p,
96 actual_size, &actual_size);
97
98 if (nt_status < 0 || nt_status > 0x7FFFFFFF)
99 {
100 ec = ::boost::process::detail::get_last_error();
101 return false;
102 }
103 else
104 ec.clear();
105
106 auto &nm = type_info_p->TypeName.Buffer;
107 return type_info_p->TypeName.Length >= 5 &&
108 nm[0] == L'F' &&
109 nm[1] == L'i' &&
110 nm[2] == L'l' &&
111 nm[3] == L'e' &&
112 nm[4] == L'\0';
113}
114
115
116inline bool is_stream_handle(native_handle_type handle)
117{
118 std::error_code ec;
119 auto res = is_stream_handle(handle, ec);
120 if (ec)
121 boost::process::detail::throw_error(ec, "NtQueryObject failed");
122
123 return res;
124}
125
126
127struct limit_handles_ : handler_base_ext
128{
129 mutable std::vector<::boost::winapi::HANDLE_> handles_with_inherit_flag;
130
131 template<typename Executor>
132 void on_setup(Executor & exec) const
133 {
134 auto all_handles = get_handles();
135 foreach_used_handle(exec,
136 [&](::boost::winapi::HANDLE_ handle)
137 {
138 auto itr = std::find(all_handles.begin(), all_handles .end(), handle);
1e59de90 139 ::boost::winapi::DWORD_ flags = 0u;
92f5a8d4
TL
140 if (itr != all_handles.end())
141 *itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
142 else if ((::boost::winapi::GetHandleInformation(*itr, &flags) != 0)
143 &&((flags & ::boost::winapi::HANDLE_FLAG_INHERIT_) == 0)) //it is NOT inherited anyhow, so ignore too
144 *itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
145 });
146
147 auto part_itr = std::partition(all_handles.begin(), all_handles.end(),
148 [](::boost::winapi::HANDLE_ handle) {return handle != ::boost::winapi::INVALID_HANDLE_VALUE_;});
149
150 all_handles.erase(part_itr, all_handles.end()); //remove invalid handles
151 handles_with_inherit_flag = std::move(all_handles);
152
153 for (auto handle : handles_with_inherit_flag)
154 ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, 0);
155 }
156
157 template<typename Executor>
158 void on_error(Executor & exec, const std::error_code & ec) const
159 {
160 for (auto handle : handles_with_inherit_flag)
161 ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
162 }
163
164 template<typename Executor>
165 void on_sucess(Executor & exec) const
166 {
167 for (auto handle : handles_with_inherit_flag)
168 ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
169 }
170
171};
172
173
174}}}}
175
176#endif //PROCESS_HANDLES_HPP