OpenVPN 3 Core Library
Loading...
Searching...
No Matches
reg.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12
13// registry utilities for Windows
14
15#pragma once
16
17#include <windows.h>
18#include <string>
21
22namespace openvpn::Win {
23
24template <typename E>
25static void check_reg_error(DWORD status, const std::string &key)
26{
27 if (status != ERROR_SUCCESS)
28 {
29 const Win::Error err(status);
30 OPENVPN_THROW(E, "registry key " << key << " error: " << err.message());
31 }
32}
33
38struct Reg
39{
44 class Key
45 {
46 Key(const Key &) = delete;
47 Key &operator=(const Key &) = delete;
48
49 public:
59 Key(HKEY key, const std::wstring &subkey, bool create = false)
60 {
61 LSTATUS error;
62 if (create)
63 {
64 error = ::RegCreateKeyExW(key,
65 subkey.c_str(),
66 0,
67 nullptr,
68 0,
69 KEY_ALL_ACCESS,
70 nullptr,
71 &key_,
72 nullptr);
73 }
74 else
75 {
76 error = ::RegOpenKeyExW(key,
77 subkey.c_str(),
78 0,
79 KEY_ALL_ACCESS,
80 &key_);
81 }
82 if (error)
83 {
84 key_ = static_cast<HKEY>(INVALID_HANDLE_VALUE);
85 }
86 }
87 Key(Key &key, const std::wstring &subkey, bool create = false)
88 : Key(key(), subkey, create)
89 {
90 }
99 Key(const std::wstring &subkey, bool create = false)
100 : Key(HKEY_LOCAL_MACHINE, subkey, create)
101 {
102 }
103
104 Key() = default;
105
106 Key(Key &&rhs)
107 {
108 if (defined())
109 {
110 ::RegCloseKey(key_);
111 key_ = static_cast<HKEY>(INVALID_HANDLE_VALUE);
112 }
113 std::swap(key_, rhs.key_);
114 }
116 {
117 Key copy{std::move(rhs)};
118 std::swap(copy.key_, this->key_);
119 return *this;
120 }
121
123 {
124 if (defined())
125 {
126 ::RegCloseKey(key_);
127 }
128 }
129
136 bool defined() const
137 {
138 return key_ != INVALID_HANDLE_VALUE;
139 }
140
146 PHKEY ref()
147 {
148 return &key_;
149 }
150
156 {
157 return key_;
158 }
159
160 private:
161 HKEY key_ = static_cast<HKEY>(INVALID_HANDLE_VALUE);
162 };
163
171 class KeyEnumerator : public std::vector<std::wstring>
172 {
173 public:
180 {
181 if (!key.defined())
182 return;
183
184 LSTATUS status;
185 DWORD subkeys_num;
186 status = ::RegQueryInfoKeyA(key(),
187 nullptr,
188 nullptr,
189 nullptr,
190 &subkeys_num,
191 nullptr,
192 nullptr,
193 nullptr,
194 nullptr,
195 nullptr,
196 nullptr,
197 nullptr);
198
199 if (status != ERROR_SUCCESS)
200 return;
201
202 constexpr int MAX_KEY_LENGTH = 255;
203 for (DWORD i = 0; i < subkeys_num; ++i)
204 {
205 DWORD subkey_size = MAX_KEY_LENGTH;
206 WCHAR subkey[MAX_KEY_LENGTH];
207 status = ::RegEnumKeyExW(key(),
208 i,
209 subkey,
210 &subkey_size,
211 nullptr,
212 nullptr,
213 nullptr,
214 nullptr);
215 if (status == ERROR_SUCCESS)
216 push_back(subkey);
217 }
218 }
219 };
220
224 static constexpr PCWSTR gpol_nrpt_subkey = LR"(SOFTWARE\Policies\Microsoft\Windows NT\DNSClient\DnsPolicyConfig)";
225 static constexpr PCWSTR local_nrpt_subkey = LR"(SYSTEM\CurrentControlSet\Services\Dnscache\Parameters\DnsPolicyConfig)";
226
230 static constexpr WCHAR subkey_ipv4_itfs[] = LR"(SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces)";
231 static constexpr WCHAR subkey_ipv6_itfs[] = LR"(SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters\Interfaces)";
232
242 static std::pair<DWORD, LSTATUS> get_dword(Key &key, PCWSTR name)
243 {
244 DWORD type;
245 DWORD value;
246 DWORD size = sizeof(value);
247 PBYTE data = reinterpret_cast<PBYTE>(&value);
248 LSTATUS err;
249
250 err = ::RegGetValueW(key(), nullptr, name, RRF_RT_REG_DWORD, &type, data, &size);
251 if (err)
252 {
253 return {0, err};
254 }
255 else if (type != REG_DWORD)
256 {
257 return {0, ERROR_DATATYPE_MISMATCH};
258 }
259
260 return {value, err};
261 }
262
272 static std::pair<std::wstring, LSTATUS> get_string(Key &key, PCWSTR name)
273 {
274 LSTATUS err;
275 DWORD size = 0;
276 DWORD type;
277 err = ::RegGetValueW(key(), nullptr, name, RRF_RT_REG_SZ, &type, nullptr, &size);
278 if (err)
279 {
280 return {{}, err};
281 }
282 else if (type != REG_SZ)
283 {
284 return {{}, ERROR_DATATYPE_MISMATCH};
285 }
286
287 std::wstring str(size / sizeof(std::wstring::value_type) + 1, '\0');
288 PBYTE data = reinterpret_cast<PBYTE>(str.data());
289 err = ::RegGetValueW(key(), nullptr, name, RRF_RT_REG_SZ, nullptr, data, &size);
290 if (err)
291 {
292 return {{}, err};
293 }
294
295 str.resize(::wcslen(str.c_str())); // remove trailing NULs
296 return {str, err};
297 }
298
309 static std::pair<std::string, LSTATUS> get_binary(Key &key, PCWSTR name)
310 {
311 LSTATUS err;
312 DWORD size = 0;
313 DWORD type;
314 err = ::RegGetValueW(key(), nullptr, name, RRF_RT_REG_BINARY, &type, nullptr, &size);
315 if (err)
316 {
317 return {{}, err};
318 }
319 else if (type != REG_BINARY)
320 {
321 return {{}, ERROR_DATATYPE_MISMATCH};
322 }
323
324 std::string str(size, '\0');
325 PBYTE data = reinterpret_cast<PBYTE>(str.data());
326 err = ::RegGetValueW(key(), nullptr, name, RRF_RT_REG_BINARY, nullptr, data, &size);
327 if (err)
328 {
329 return {{}, err};
330 }
331
332 return {str, err};
333 }
334
343 static LSTATUS set_dword(Key &key, PCWSTR name, DWORD value)
344 {
345 const BYTE *bytes = reinterpret_cast<const BYTE *>(&value);
346 DWORD size = static_cast<DWORD>(sizeof(value));
347 return ::RegSetValueExW(key(), name, 0, REG_DWORD, bytes, size);
348 }
349
358 static LSTATUS set_string(Key &key, PCWSTR name, const std::wstring &value)
359 {
360 const BYTE *bytes = reinterpret_cast<const BYTE *>(value.c_str());
361 DWORD size = static_cast<DWORD>((value.size() + 1) * sizeof(std::wstring::value_type));
362 return ::RegSetValueExW(key(), name, 0, REG_SZ, bytes, size);
363 }
364
378 static LSTATUS set_multi_string(Key &key, PCWSTR name, const std::wstring &value)
379 {
380 const BYTE *bytes = reinterpret_cast<const BYTE *>(value.data());
381 DWORD size = static_cast<DWORD>(value.size() * sizeof(std::wstring::value_type));
382 return ::RegSetValueExW(key(), name, 0, REG_MULTI_SZ, bytes, size);
383 }
384
394 static LSTATUS delete_subkey(const std::wstring &subkey)
395 {
396 return ::RegDeleteTreeW(HKEY_LOCAL_MACHINE, subkey.c_str());
397 }
398
406 static LSTATUS delete_value(Key &key, PCWSTR name)
407 {
408 return ::RegDeleteValueW(key(), name);
409 }
410};
411
412} // namespace openvpn::Win
Wrapper for Registry subkey enumeration.
Definition reg.hpp:172
KeyEnumerator(Key &key)
Construct a new Key Enumerator object.
Definition reg.hpp:179
Wrapper class for a Registry key handle.
Definition reg.hpp:45
HKEY operator()()
Return the Registry key handle.
Definition reg.hpp:155
bool defined() const
Check for a valid key handle.
Definition reg.hpp:136
Key(const Key &)=delete
Key(Key &key, const std::wstring &subkey, bool create=false)
Definition reg.hpp:87
Key & operator=(Key &&rhs)
Definition reg.hpp:115
Key(HKEY key, const std::wstring &subkey, bool create=false)
Construct a Key with an open handle for a subkey under key.
Definition reg.hpp:59
Key(const std::wstring &subkey, bool create=false)
Construct a Key with an open handle for a subkey under HKLM.
Definition reg.hpp:99
Key & operator=(const Key &)=delete
PHKEY ref()
Retrun a pointer to the Registry key handle.
Definition reg.hpp:146
#define OPENVPN_THROW(exc, stuff)
static void check_reg_error(DWORD status, const std::string &key)
Definition reg.hpp:25
Abstraction of Windows Registry operations.
Definition reg.hpp:39
static constexpr WCHAR subkey_ipv6_itfs[]
Definition reg.hpp:231
static LSTATUS delete_subkey(const std::wstring &subkey)
Delete a subkey from the Registry.
Definition reg.hpp:394
static LSTATUS delete_value(Key &key, PCWSTR name)
Delete a value from the Registry.
Definition reg.hpp:406
static constexpr PCWSTR gpol_nrpt_subkey
Definition reg.hpp:224
static LSTATUS set_string(Key &key, PCWSTR name, const std::wstring &value)
Set a REG_SZ value in the Registy.
Definition reg.hpp:358
static std::pair< std::string, LSTATUS > get_binary(Key &key, PCWSTR name)
Read a REG_BINARY value from the Windows registry.
Definition reg.hpp:309
static constexpr PCWSTR local_nrpt_subkey
Definition reg.hpp:225
static constexpr WCHAR subkey_ipv4_itfs[]
Definition reg.hpp:230
static std::pair< std::wstring, LSTATUS > get_string(Key &key, PCWSTR name)
Read a REG_SZ value from the Windows registry.
Definition reg.hpp:272
static LSTATUS set_multi_string(Key &key, PCWSTR name, const std::wstring &value)
Set a REG_MULTI_SZ value in the Registry.
Definition reg.hpp:378
static std::pair< DWORD, LSTATUS > get_dword(Key &key, PCWSTR name)
Read a REG_DWORD value from the Windows registry.
Definition reg.hpp:242
static LSTATUS set_dword(Key &key, PCWSTR name, DWORD value)
Set a DWORD value in the Registry.
Definition reg.hpp:343
os<< "Session Name: "<< tbc-> session_name<< '\n';os<< "Layer: "<< tbc-> layer str()<< '\n'
server addresses push_back({address, port})