]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/log/src/windows/object_name.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / log / src / windows / object_name.cpp
CommitLineData
7c673cae
FG
1/*
2 * Copyright Andrey Semashev 2016.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7/*!
8 * \file windows/object_name.cpp
9 * \author Andrey Semashev
10 * \date 06.03.2016
11 *
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14 */
15
16#include <boost/log/detail/config.hpp>
17#include <cstddef>
18#include <cstdlib>
19#include <string>
20#include <vector>
21#include <algorithm>
22#include <boost/memory_order.hpp>
23#include <boost/atomic/atomic.hpp>
24#include <boost/move/utility_core.hpp>
25#include <boost/log/exceptions.hpp>
26#include <boost/log/utility/ipc/object_name.hpp>
b32b8144 27#include <boost/winapi/get_last_error.hpp>
7c673cae
FG
28#include <windows.h>
29#include <lmcons.h>
30#include <security.h>
31#include "windows/auto_handle.hpp"
32#include "windows/utf_code_conversion.hpp"
33#include <boost/log/detail/header.hpp>
34
35namespace boost {
36
37BOOST_LOG_OPEN_NAMESPACE
38
39namespace ipc {
40
41BOOST_LOG_ANONYMOUS_NAMESPACE {
42
43#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
44
45class auto_boundary_descriptor
46{
47private:
48 HANDLE m_handle;
49
50public:
51 explicit auto_boundary_descriptor(HANDLE h = NULL) BOOST_NOEXCEPT : m_handle(h)
52 {
53 }
54
55 ~auto_boundary_descriptor() BOOST_NOEXCEPT
56 {
57 if (m_handle)
58 DeleteBoundaryDescriptor(m_handle);
59 }
60
61 void init(HANDLE h) BOOST_NOEXCEPT
62 {
63 BOOST_ASSERT(m_handle == NULL);
64 m_handle = h;
65 }
66
67 HANDLE get() const BOOST_NOEXCEPT { return m_handle; }
68 HANDLE* get_ptr() BOOST_NOEXCEPT { return &m_handle; }
69
70 void swap(auto_boundary_descriptor& that) BOOST_NOEXCEPT
71 {
72 HANDLE h = m_handle;
73 m_handle = that.m_handle;
74 that.m_handle = h;
75 }
76
77 BOOST_DELETED_FUNCTION(auto_boundary_descriptor(auto_boundary_descriptor const&))
78 BOOST_DELETED_FUNCTION(auto_boundary_descriptor& operator=(auto_boundary_descriptor const&))
79};
80
81//! Handle for the private namespace for \c user scope
82static boost::atomic< HANDLE > g_user_private_namespace;
83
84//! Closes the private namespace on process exit
85void close_user_namespace()
86{
87 HANDLE h = g_user_private_namespace.load(boost::memory_order_acquire);
88 if (h)
89 {
90 ClosePrivateNamespace(h, 0);
91 g_user_private_namespace.store((HANDLE)NULL, boost::memory_order_release);
92 }
93}
94
95//! Attempts to create or open the private namespace
96bool init_user_namespace()
97{
98 HANDLE h = g_user_private_namespace.load(boost::memory_order_acquire);
99 if (BOOST_UNLIKELY(!h))
100 {
101 // Obtain the current user SID
102 boost::log::ipc::aux::auto_handle h_process_token;
103 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, h_process_token.get_ptr()))
104 return false;
105
106 DWORD token_user_size = 0;
107 GetTokenInformation(h_process_token.get(), TokenUser, NULL, 0u, &token_user_size);
108 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || token_user_size < sizeof(TOKEN_USER))
109 return false;
110 std::vector< unsigned char > token_user_storage(static_cast< std::size_t >(token_user_size), static_cast< unsigned char >(0u));
111 if (!GetTokenInformation(h_process_token.get(), TokenUser, &token_user_storage[0], token_user_size, &token_user_size))
112 return false;
113
114 TOKEN_USER const& token_user = *reinterpret_cast< const TOKEN_USER* >(&token_user_storage[0]);
115 if (!token_user.User.Sid)
116 return false;
117
118 // Create a boundary descriptor with the user's SID
119 auto_boundary_descriptor h_boundary(CreateBoundaryDescriptorW(L"User", 0));
120 if (!h_boundary.get())
121 return false;
122
123 if (!AddSIDToBoundaryDescriptor(h_boundary.get_ptr(), token_user.User.Sid))
124 return false;
125
126 // Create or open a namespace for kernel objects
127 h = CreatePrivateNamespaceW(NULL, h_boundary.get(), L"User");
128 if (!h)
129 h = OpenPrivateNamespaceW(h_boundary.get(), L"User");
130
131 if (h)
132 {
133 HANDLE expected = NULL;
134 if (g_user_private_namespace.compare_exchange_strong(expected, h, boost::memory_order_acq_rel, boost::memory_order_acquire))
135 {
136 std::atexit(&close_user_namespace);
137 }
138 else
139 {
140 // Another thread must have opened the namespace
141 ClosePrivateNamespace(h, 0);
142 h = expected;
143 }
144 }
145 }
146
147 return !!h;
148}
149
150#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
151
152//! Returns a prefix string for a shared resource according to the scope
153std::string get_scope_prefix(object_name::scope ns)
154{
155 std::string prefix;
156 switch (ns)
157 {
158 case object_name::process_group:
159 {
160 // For now consider all processes as members of the common process group. It may change if there is found
161 // a way to get a process group id (i.e. id of the closest parent process that was created with the CREATE_NEW_PROCESS_GROUP flag).
162 prefix = "Local\\boost.log.process_group";
163 }
164 break;
165
166 case object_name::session:
167 {
168 prefix = "Local\\boost.log.session";
169 }
170 break;
171
172 case object_name::user:
173 {
174#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
175 if (init_user_namespace())
176 {
177 prefix = "User\\boost.log.user";
178 }
179 else
180#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
181 {
182 wchar_t buf[UNLEN + 1u];
183 ULONG len = sizeof(buf) / sizeof(*buf);
184 if (BOOST_UNLIKELY(!GetUserNameExW(NameSamCompatible, buf, &len)))
185 {
b32b8144 186 const boost::winapi::DWORD_ err = boost::winapi::GetLastError();
7c673cae
FG
187 BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, "Failed to obtain the current user name", (err));
188 }
189
190 std::replace(buf, buf + len, L'\\', L'.');
191
192 prefix = "Local\\boost.log.user." + boost::log::aux::utf16_to_utf8(buf);
193 }
194 }
195 break;
196
197 default:
198 prefix = "Global\\boost.log.global";
199 break;
200 }
201
202 prefix.push_back('.');
203
204 return BOOST_LOG_NRVO_RESULT(prefix);
205}
206
207} // namespace
208
209//! Constructor from the object name
210BOOST_LOG_API object_name::object_name(scope ns, const char* str) :
211 m_name(get_scope_prefix(ns) + str)
212{
213}
214
215//! Constructor from the object name
216BOOST_LOG_API object_name::object_name(scope ns, std::string const& str) :
217 m_name(get_scope_prefix(ns) + str)
218{
219}
220
221} // namespace ipc
222
223BOOST_LOG_CLOSE_NAMESPACE // namespace log
224
225} // namespace boost
226
227#include <boost/log/detail/footer.hpp>