HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
winreg.hpp
1// Copyright Take Vos 2023.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
8#include "../macros.hpp"
9#include "win32_error_intf.hpp"
10#include <string_view>
11#include <string>
12#include <vector>
13#include <cstdint>
14#include <optional>
15#include <cassert>
16
17hi_export_module(hikogui.win32 : winreg);
18
19hi_export namespace hi { inline namespace v1 {
20
27inline win32_error win32_RegDeleteKeyValue(HKEY key, std::string_view path, std::string_view name) noexcept
28{
29 auto const wpath = win32_MultiByteToWideChar(path);
30 if (not wpath) {
31 return wpath.error();
32 }
33
34 auto const wname = win32_MultiByteToWideChar(name);
35 if (not wname) {
36 return wname.error();
37 }
38
39 return static_cast<win32_error>(::RegDeleteKeyValueW(key, wpath->c_str(), wname->c_str()));
40}
41
47inline win32_error win32_RegDeleteKey(HKEY key, std::string_view path) noexcept
48{
49 auto const wpath = win32_MultiByteToWideChar(path);
50 if (not wpath) {
51 return wpath.error();
52 }
53
54 return static_cast<win32_error>(::RegDeleteKeyW(key, wpath->c_str()));
55}
56
66[[nodiscard]] inline win32_error win32_RegSetKeyValue(HKEY key, std::string_view path, std::string_view name, uint32_t value)
67{
68 auto const wpath = win32_MultiByteToWideChar(path);
69 if (not wpath) {
70 return wpath.error();
71 }
72
73 auto const wname = win32_MultiByteToWideChar(name);
74 if (not wname) {
75 return wname.error();
76 }
77
78 auto const dvalue = static_cast<DWORD>(value);
79
80 return static_cast<win32_error>(::RegSetKeyValueW(key, wpath->c_str(), wname->c_str(), REG_DWORD, &dvalue, sizeof(dvalue)));
81}
82
92[[nodiscard]] inline win32_error win32_RegSetKeyValue(HKEY key, std::string_view path, std::string_view name, std::string_view value)
93{
94 auto const wpath = win32_MultiByteToWideChar(path);
95 if (not wpath) {
96 return wpath.error();
97 }
98
99 auto const wname = win32_MultiByteToWideChar(name);
100 if (not wname) {
101 return wname.error();
102 }
103
104 auto const wvalue = win32_MultiByteToWideChar(value);
105 if (not wvalue) {
106 return wvalue.error();
107 }
108
109 auto const wvalue_size = static_cast<DWORD>((wvalue->size() + 1) * sizeof(wchar_t));
110
111 return static_cast<win32_error>(::RegSetKeyValueW(key, wpath->c_str(), wname->c_str(), REG_SZ, wvalue->c_str(), wvalue_size));
112}
113
117[[nodiscard]] inline std::expected<void, win32_error> win32_RegGetValue_void(HKEY key, std::string_view path, std::string_view name)
118{
119 auto const wpath = win32_MultiByteToWideChar(path);
120 if (not wpath) {
121 return std::unexpected{wpath.error()};
122 }
123
124 auto const wname = win32_MultiByteToWideChar(name);
125 if (not wname) {
126 return std::unexpected{wname.error()};
127 }
128
129 auto status = static_cast<win32_error>(::RegGetValueW(key, wpath->c_str(), wname->c_str(), RRF_RT_ANY, NULL, NULL, NULL));
130 if (status == win32_error::success) {
131 return {};
132 } else {
133 return std::unexpected{status};
134 }
135}
136
144[[nodiscard]] inline std::expected<uint32_t, win32_error> win32_RegGetValue_dword(HKEY key, std::string_view path, std::string_view name) noexcept
145{
146 auto const wpath = win32_MultiByteToWideChar(path);
147 if (not wpath) {
148 return std::unexpected{wpath.error()};
149 }
150
151 auto const wname = win32_MultiByteToWideChar(name);
152 if (not wname) {
153 return std::unexpected{wname.error()};
154 }
155
156 DWORD result;
157 DWORD result_length = sizeof(result);
158 DWORD result_type = 0;
159 auto const status = static_cast<win32_error>(::RegGetValueW(key, wpath->c_str(), wname->c_str(), RRF_RT_ANY, &result_type, &result, &result_length));
160
161 if (static_cast<bool>(status)) {
162 return std::unexpected{status};
163 }
164
165 return static_cast<uint32_t>(result);
166}
167
175[[nodiscard]] inline std::expected<std::string, win32_error> win32_RegGetValue_string(HKEY key, std::string_view path, std::string_view name) noexcept
176{
177 auto const wpath = win32_MultiByteToWideChar(path);
178 if (not wpath) {
179 return std::unexpected{wpath.error()};
180 }
181
182 auto const wname = win32_MultiByteToWideChar(name);
183 if (not wname) {
184 return std::unexpected{wname.error()};
185 }
186
187 auto result = std::wstring{};
188
189 auto expected_size = size_t{64};
190 for (auto repeat = 0; repeat != 5; ++repeat) {
191 auto status = win32_error{};
192
193 result.resize_and_overwrite(expected_size, [&](auto p, auto n) {
194 // size includes the null-terminator.
195 auto result_length = static_cast<DWORD>((n + 1) * sizeof(wchar_t));
196 status = static_cast<win32_error>(::RegGetValueW(key, wpath->c_str(), wname->c_str(), RRF_RT_REG_SZ, NULL, p, &result_length));
197
198 expected_size = (result_length / sizeof(wchar_t)) - 1;
199 return std::min(n, expected_size);
200 });
201
202 switch (status) {
203 case win32_error::success:
204 return win32_WideCharToMultiByte(result);
205 case win32_error::more_data:
206 continue;
207 default:
208 return std::unexpected{status};
209 }
210 }
211
212 // Data size keeps changing.
213 return std::unexpected{win32_error::more_data};
214}
215
224[[nodiscard]] inline std::expected<std::vector<std::string>, win32_error>
225win32_RegGetValue_multi_string(HKEY key, std::string_view path, std::string_view name) noexcept
226{
227 auto const wpath = win32_MultiByteToWideChar(path);
228 if (not wpath) {
229 return std::unexpected{wpath.error()};
230 }
231
232 auto const wname = win32_MultiByteToWideChar(name);
233 if (not wname) {
234 return std::unexpected{wname.error()};
235 }
236
237 auto result = std::wstring{};
238 result.resize(64);
239
240 for (auto repeat = 0; repeat != 5; ++repeat) {
241 auto result_length = static_cast<DWORD>(result.size() * sizeof(wchar_t));
242 auto const status =
243 static_cast<win32_error>(::RegGetValueW(key, wpath->c_str(), wname->c_str(), RRF_RT_REG_MULTI_SZ, NULL, result.data(), &result_length));
244
245 switch (status) {
246 case win32_error::success:
247 return win32_MultiSZToStringVector(result.data(), result.data() + result_length);
248
249 case win32_error::more_data:
250 assert(result_length % 2 == 0);
251 result.resize(result_length / sizeof(wchar_t));
252 break;
253
254 default:
255 return std::unexpected{status};
256 }
257 }
258
259 // Data size keeps changing.
260 return std::unexpected{win32_error::more_data};
261}
262
272template<typename T>
273[[nodiscard]] std::expected<T, win32_error> win32_RegGetValue(HKEY key, std::string_view path, std::string_view name) = delete;
274
275template<>
276[[nodiscard]] inline std::expected<void, win32_error> win32_RegGetValue(HKEY key, std::string_view path, std::string_view name)
277{
278 return win32_RegGetValue_void(key, path, name);
279}
280
281template<std::integral T>
282[[nodiscard]] inline std::expected<T, win32_error> win32_RegGetValue(HKEY key, std::string_view path, std::string_view name)
283{
284 if (auto const tmp = win32_RegGetValue_dword(key, path, name)) {
285 return static_cast<T>(*tmp);
286 } else {
287 return std::unexpected{tmp.error()};
288 }
289}
290
291template<>
292[[nodiscard]] inline std::expected<std::string, win32_error> win32_RegGetValue(HKEY key, std::string_view path, std::string_view name)
293{
294 return win32_RegGetValue_string(key, path, name);
295}
296
297template<>
298[[nodiscard]] inline std::expected<std::vector<std::string>, win32_error>
299win32_RegGetValue(HKEY key, std::string_view path, std::string_view name)
300{
301 return win32_RegGetValue_multi_string(key, path, name);
302}
303
304}} // namespace hi::inline v1
Rules for working with win32 headers.
The HikoGUI namespace.
Definition array_generic.hpp:20
win32_error win32_RegSetKeyValue(HKEY key, std::string_view path, std::string_view name, uint32_t value)
Write a DWORD registry value.
Definition winreg.hpp:66
std::expected< std::string, win32_error > win32_WideCharToMultiByte(std::wstring_view s, unsigned int code_page=CP_UTF8, uint32_t flags=0) noexcept
Convert a win32-API compatible std::wstring to a multi-byte std::string.
Definition stringapiset.hpp:26
std::expected< T, win32_error > win32_RegGetValue(HKEY key, std::string_view path, std::string_view name)=delete
Read from the registry value.
Definition winreg.hpp:282
std::expected< std::vector< std::string >, win32_error > win32_MultiSZToStringVector(wchar_t const *first, wchar_t const *last) noexcept
Convert a win32 zero terminated list of zero terminated strings.
Definition stringapiset.hpp:92
win32_error win32_RegDeleteKeyValue(HKEY key, std::string_view path, std::string_view name) noexcept
Delete a registry value.
Definition winreg.hpp:27
std::expected< void, win32_error > win32_RegGetValue_void(HKEY key, std::string_view path, std::string_view name)
Check if a registry entry exists.
Definition winreg.hpp:117
win32_error win32_RegDeleteKey(HKEY key, std::string_view path) noexcept
Delete all registry values and the last part of the subkey.
Definition winreg.hpp:47
std::expected< uint32_t, win32_error > win32_RegGetValue_dword(HKEY key, std::string_view path, std::string_view name) noexcept
Read a DWORD registry value.
Definition winreg.hpp:144
std::expected< std::string, win32_error > win32_RegGetValue_string(HKEY key, std::string_view path, std::string_view name) noexcept
Read a strings from the registry value.
Definition winreg.hpp:175
std::expected< std::wstring, win32_error > win32_MultiByteToWideChar(std::string_view s, unsigned int code_page=CP_UTF8, uint32_t flags=0) noexcept
Convert a win32-API compatible std::wstring to a multi-byte std::string.
Definition stringapiset.hpp:58
std::expected< std::vector< std::string >, win32_error > win32_RegGetValue_multi_string(HKEY key, std::string_view path, std::string_view name) noexcept
Read a list of strings from the registry value.
Definition winreg.hpp:225
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
T min(T... args)
T resize(T... args)
T unexpected(T... args)