Skip to content

Commit 15146a2

Browse files
committed
registry setup with logging parameters
1 parent e3df26a commit 15146a2

File tree

8 files changed

+233
-3
lines changed

8 files changed

+233
-3
lines changed

IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
<ClInclude Include="pipe\SecurityMode.h" />
8080
<ClInclude Include="PrecisionWaiter.h" />
8181
<ClInclude Include="Qpc.h" />
82+
<ClInclude Include="reg\Registry.h" />
8283
<ClInclude Include="rng\PairToRange.h" />
8384
<ClInclude Include="str\String.h" />
8485
<ClInclude Include="third\reflect.hpp" />

IntelPresentMon/CommonUtilities/CommonUtilities.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@
225225
<ClInclude Include="pipe\WrapAsio.h">
226226
<Filter>Header Files</Filter>
227227
</ClInclude>
228+
<ClInclude Include="reg\Registry.h">
229+
<Filter>Header Files</Filter>
230+
</ClInclude>
228231
</ItemGroup>
229232
<ItemGroup>
230233
<ClCompile Include="cli\CliFramework.cpp">
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
#pragma once
2+
3+
#include <winreg/winreg.hpp>
4+
5+
#include <optional>
6+
#include <string>
7+
#include <span>
8+
#include "../Exception.h"
9+
#include "../log/Log.h"
10+
#include "../str/String.h"
11+
12+
13+
namespace pmon::util::reg
14+
{
15+
PM_DEFINE_EX(RegistryNotOpen);
16+
17+
class Registry
18+
{
19+
public:
20+
// types
21+
template<typename T>
22+
class Value
23+
{
24+
public:
25+
Value(Registry* pParent, const std::string& valueName)
26+
:
27+
parent_{ *pParent },
28+
valueName_{ str::ToWide(valueName) }
29+
{}
30+
std::optional<T> AsOptional() const noexcept
31+
{
32+
try {
33+
return Get();
34+
}
35+
catch (const RegistryNotOpen&) {
36+
pmlog_warn("Optional access of registry value when key not open");
37+
}
38+
catch (const winreg::RegException& e) {
39+
if (e.code().value() == 2) {
40+
pmlog_dbg("Optional access of absent value");
41+
}
42+
else {
43+
pmlog_error(ReportException("Error during optional access of registry value"));
44+
}
45+
}
46+
catch (...) {
47+
pmlog_error(ReportException("Unknown error during optional access of registry value"));
48+
}
49+
return {};
50+
}
51+
T Get() const
52+
{
53+
auto& key = GetKey_();
54+
if constexpr (std::same_as<bool, T>) {
55+
return (bool)key.GetDwordValue(valueName_);
56+
}
57+
else if constexpr (std::integral<T>) {
58+
if constexpr (sizeof(T) <= 4) {
59+
return (T)key.GetDwordValue(valueName_);
60+
}
61+
else {
62+
return (T)key.GetQwordValue(valueName_);
63+
}
64+
}
65+
else if constexpr (std::is_enum_v<T>) {
66+
using U = std::underlying_type_t<T>;
67+
if constexpr (sizeof(U) <= 4) {
68+
return (T)key.GetDwordValue(valueName_);
69+
}
70+
else {
71+
return (T)key.GetQwordValue(valueName_);
72+
}
73+
}
74+
else if constexpr (std::same_as<std::string, T>) {
75+
return str::ToNarrow(key.GetStringValue(valueName_));
76+
}
77+
}
78+
void Set(const T& val)
79+
{
80+
auto& key = GetKey_();
81+
if constexpr (std::same_as<bool, T>) {
82+
return key.SetDwordValue(valueName_, (DWORD)val);
83+
}
84+
else if constexpr (std::integral<T>) {
85+
if constexpr (sizeof(T) <= 4) {
86+
return key.SetDwordValue(valueName_, (DWORD)val);
87+
}
88+
else {
89+
return key.SetQwordValue(valueName_, (ULONGLONG)val);
90+
}
91+
}
92+
else if constexpr (std::is_enum_v<T>) {
93+
using U = std::underlying_type_t<T>;
94+
if constexpr (sizeof(U) <= 4) {
95+
return key.SetDwordValue(valueName_, (DWORD)val);
96+
}
97+
else {
98+
return key.SetQwordValue(valueName_, (ULONGLONG)val);
99+
}
100+
}
101+
else if constexpr (std::same_as<std::string, T>) {
102+
key.SetStringValue(valueName_, str::ToWide(val));
103+
}
104+
}
105+
bool Exists() const
106+
{
107+
for (auto& v : parent_.key_.EnumValues()) {
108+
if (v.first == valueName_) {
109+
return true;
110+
}
111+
}
112+
return false;
113+
}
114+
void Delete() noexcept
115+
{
116+
try {
117+
parent_.key_.DeleteValue(valueName_);
118+
}
119+
catch (...) {
120+
pmlog_warn(ReportException("Failed to delete registry value"));
121+
}
122+
}
123+
operator T() const
124+
{
125+
return Get();
126+
}
127+
Value& operator=(const T& val)
128+
{
129+
Set(val);
130+
return *this;
131+
}
132+
private:
133+
// functions
134+
winreg::RegKey& GetKey_() const
135+
{
136+
auto& key = parent_.key_;
137+
if (!key.IsValid()) {
138+
throw Except<RegistryNotOpen>();
139+
}
140+
return key;
141+
}
142+
// data
143+
std::wstring valueName_;
144+
Registry& parent_;
145+
};
146+
// functions
147+
bool IsValid() const
148+
{
149+
return key_.IsValid();
150+
}
151+
protected:
152+
Registry(HKEY hive, std::wstring keyPath) noexcept
153+
:
154+
hive_{ hive },
155+
keyPath_{ keyPath }
156+
{
157+
// opening existing key
158+
try {
159+
key_.Open(hive_, keyPath_);
160+
return;
161+
}
162+
catch (const winreg::RegException& e) {
163+
if (e.code().value() == 2) {
164+
pmlog_warn(std::format("Registry key [{}] does not exist, creating...", str::ToNarrow(keyPath)));
165+
}
166+
else {
167+
pmlog_error(ReportException(std::format("Failed to open registry key [{}]", str::ToNarrow(keyPath))));
168+
return;
169+
}
170+
}
171+
catch (...) {
172+
pmlog_error(ReportException(std::format("Failed to open registry key [{}]", str::ToNarrow(keyPath))));
173+
return;
174+
}
175+
// creating new key
176+
try {
177+
key_.Create(hive_, keyPath_);
178+
}
179+
catch (...) {
180+
pmlog_error(ReportException(std::format("Failed to create registry key [{}]", str::ToNarrow(keyPath))));
181+
}
182+
}
183+
private:
184+
HKEY hive_;
185+
std::wstring keyPath_;
186+
winreg::RegKey key_;
187+
};
188+
189+
template<class T>
190+
class RegistryBase : public Registry
191+
{
192+
public:
193+
static T& Get() noexcept
194+
{
195+
static T reg;
196+
return reg;
197+
}
198+
static void SetPrivileged(bool privileged) noexcept
199+
{
200+
privileged_ = privileged;
201+
}
202+
protected:
203+
RegistryBase() : Registry{ privileged_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, T::keyPath_ } {}
204+
private:
205+
inline static bool privileged_ = true;
206+
};
207+
}

IntelPresentMon/PresentMonService/PresentMonService.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@
237237
<ClInclude Include="PMMainThread.h" />
238238
<ClInclude Include="PresentMonSession.h" />
239239
<ClInclude Include="RealtimePresentMonSession.h" />
240+
<ClInclude Include="Registry.h" />
240241
<ClInclude Include="resource.h" />
241242
<ClInclude Include="Service.h" />
242243
<ClInclude Include="ServiceExecutionContext.h" />

IntelPresentMon/PresentMonService/PresentMonService.vcxproj.filters

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
<ClInclude Include="ServiceExecutionContext.h" />
4040
<ClInclude Include="Logging.h" />
4141
<ClInclude Include="acts\SetEtwFlushPeriod.h" />
42+
<ClInclude Include="Registry.h" />
4243
</ItemGroup>
4344
<ItemGroup>
4445
<ResourceCompile Include="PresentMonService.rc" />
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
#include "../CommonUtilities/reg/Registry.h"
3+
#include "../CommonUtilities/log/Level.h"
4+
5+
using namespace pmon::util;
6+
struct Reg : public reg::RegistryBase<Reg>
7+
{
8+
Value<log::Level> logLevel{ this, "logLevel" };
9+
Value<std::string> logDir{ this, "logDir" };
10+
11+
static constexpr const wchar_t* keyPath_ = LR"(SOFTWARE\INTEL\PresentMon\Service)";
12+
};

IntelPresentMon/PresentMonService/ServiceMain.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
#include "Service.h"
88
#include "CliOptions.h"
99
#include "LogSetup.h"
10+
#include "Registry.h"
1011

1112
TCHAR serviceName[MaxBufferLength] = TEXT("Intel PresentMon Service");
1213

1314
// common entry point whether invoked as service or as app
14-
int CommonEntry(DWORD argc, LPTSTR* argv, bool asApp = false)
15+
int CommonEntry(DWORD argc, LPTSTR* argv, bool asApp)
1516
{
1617
logsetup::LogChannelManager logMan_;
1718
// parse command line, return with error code from CLI11 if running as app
@@ -20,6 +21,9 @@ int CommonEntry(DWORD argc, LPTSTR* argv, bool asApp = false)
2021
}
2122
// configure logging based on CLI arguments
2223
logsetup::ConfigureLogging(asApp);
24+
// configure windows registry access
25+
Reg::SetPrivileged(!asApp);
26+
2327
if (asApp) {
2428
auto& svc = ConsoleDebugMockService::Get();
2529
svc.Run();
@@ -38,7 +42,7 @@ int CommonEntry(DWORD argc, LPTSTR* argv, bool asApp = false)
3842
// callback registered with and called by the Service Control Manager
3943
VOID WINAPI ServiceMainCallback(DWORD argc, LPTSTR* argv)
4044
{
41-
CommonEntry(argc, argv);
45+
CommonEntry(argc, argv, false);
4246
}
4347

4448
int __cdecl _tmain(int argc, TCHAR* argv[])

vcpkg.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"boost-process",
1010
"cereal",
1111
"concurrentqueue",
12-
"boost-asio"
12+
"boost-asio",
13+
"winreg"
1314
],
1415
"builtin-baseline": "6062c8fe02d38b10d5291411bc235ae4d02cfe6c"
1516
}

0 commit comments

Comments
 (0)