Skip to content

Commit 8ae6eee

Browse files
committed
✨ Add AvailableRuntimes to reports
1 parent 062f52e commit 8ae6eee

File tree

5 files changed

+150
-16
lines changed

5 files changed

+150
-16
lines changed

src/Platform.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,50 @@ namespace FredEmmott::OpenXRLayers {
1212

1313
namespace {
1414
std::optional<Runtime> GetRuntimeFromPath(const std::filesystem::path& path) {
15-
using enum Runtime::ManifestError;
16-
1715
if (path.empty()) {
1816
return {};
1917
}
18+
return Runtime(path);
19+
}
2020

21+
std::expected<std::string, Runtime::ManifestError> GetRuntimeName(
22+
const std::filesystem::path& path) {
23+
using enum Runtime::ManifestError;
2124
try {
2225
if (!std::filesystem::exists(path)) {
23-
return Runtime {path, std::unexpected {FileNotFound}};
26+
return std::unexpected {FileNotFound};
2427
}
2528

2629
std::ifstream f(path);
2730
if (!f) {
28-
return Runtime {path, std::unexpected {FileNotReadable}};
31+
return std::unexpected {FileNotReadable};
2932
}
3033

3134
const auto json = nlohmann::json::parse(f);
3235
if (json.contains("runtime") && json.at("runtime").contains("name")) {
33-
return Runtime {path, json.at("runtime").at("name")};
36+
return json.at("runtime").at("name");
3437
}
3538

36-
return Runtime {path, std::unexpected {FieldNotPresent}};
37-
} catch (const std::filesystem::filesystem_error& e) {
38-
return Runtime {path, std::unexpected {FileNotReadable}};
39-
} catch (const nlohmann::json::exception& e) {
40-
return Runtime {path, std::unexpected {InvalidJson}};
39+
return std::unexpected {FieldNotPresent};
40+
} catch (const std::filesystem::filesystem_error&) {
41+
return std::unexpected {FileNotReadable};
42+
} catch (const nlohmann::json::exception&) {
43+
return std::unexpected {InvalidJson};
4144
}
4245
}
46+
4347
}// namespace
4448

49+
Runtime::Runtime(const std::filesystem::path& path)
50+
: mPath(path),
51+
mName(GetRuntimeName(path)) {}
52+
53+
AvailableRuntime::AvailableRuntime(
54+
const std::filesystem::path& path,
55+
const Discoverability discoverability)
56+
: Runtime(path),
57+
mDiscoverability(discoverability) {}
58+
4559
Platform::Platform() = default;
4660
Platform::~Platform() = default;
4761

src/Platform.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,26 @@ struct Runtime {
2727
FieldNotPresent,
2828
};
2929

30+
Runtime() = delete;
31+
explicit Runtime(const std::filesystem::path& path);
32+
3033
std::filesystem::path mPath;
3134
std::expected<std::string, ManifestError> mName;
3235
};
3336

37+
struct AvailableRuntime : Runtime {
38+
enum class Discoverability {
39+
Discoverable,
40+
Hidden,
41+
Win32_NotDWORD,
42+
};
43+
44+
AvailableRuntime() = delete;
45+
AvailableRuntime(const std::filesystem::path& path, Discoverability);
46+
47+
Discoverability mDiscoverability;
48+
};
49+
3450
// Platform-specific functions implemented in PlatformGUI_P*.cpp
3551
class Platform {
3652
public:
@@ -48,6 +64,9 @@ class Platform {
4864
virtual std::unordered_set<std::string> GetEnvironmentVariableNames() = 0;
4965
virtual float GetDPIScaling() = 0;
5066

67+
virtual std::vector<AvailableRuntime> GetAvailable32BitRuntimes() = 0;
68+
virtual std::vector<AvailableRuntime> GetAvailable64BitRuntimes() = 0;
69+
5170
// Use OS/environment equivalent to Explorer
5271
virtual void ShowFolderContainingFile(const std::filesystem::path&) = 0;
5372

src/SaveReport.cpp

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static std::string GenerateReportText(const APILayerStore* store) {
114114
return ret;
115115
}
116116

117-
static std::string GenerateRuntimeText(
117+
static std::string GenerateActiveRuntimeText(
118118
const uint8_t bitness,
119119
const std::optional<Runtime>& runtime) {
120120
if (!runtime) {
@@ -139,6 +139,51 @@ static std::string GenerateRuntimeText(
139139
runtime->mPath.string());
140140
}
141141

142+
static std::string GenerateAvailableRuntimesText(
143+
const uint8_t bitness,
144+
const std::vector<AvailableRuntime>& runtimes) {
145+
auto ret = std::format("\nAvailable {}-bit runtimes:\n", bitness);
146+
if (runtimes.empty()) {
147+
return ret + " NONE\n";
148+
}
149+
150+
for (auto&& runtime: runtimes) {
151+
if (runtime.mName) {
152+
ret += fmt::format(
153+
" - \"{}\" - {}", runtime.mName.value(), runtime.mPath.string());
154+
} else {
155+
using enum Runtime::ManifestError;
156+
switch (runtime.mName.error()) {
157+
case FieldNotPresent:
158+
ret += fmt::format(" - {}", runtime.mPath.string());
159+
break;
160+
case FileNotFound:
161+
ret += fmt::format(" - ❌ FILE MISSING: {}", runtime.mPath.string());
162+
break;
163+
case FileNotReadable:
164+
case InvalidJson:
165+
ret += fmt::format(
166+
" - ❌ FILE NOT READABLE: {}", runtime.mPath.string());
167+
break;
168+
}
169+
}
170+
171+
switch (runtime.mDiscoverability) {
172+
case AvailableRuntime::Discoverability::Discoverable:
173+
ret += " (discoverable)\n";
174+
break;
175+
case AvailableRuntime::Discoverability::Hidden:
176+
ret += " (disabled)\n";
177+
break;
178+
case AvailableRuntime::Discoverability::Win32_NotDWORD:
179+
ret += " (🚨 NOT A DWORD)\n";
180+
break;
181+
}
182+
}
183+
184+
return ret;
185+
}
186+
142187
void SaveReport(const std::filesystem::path& path) {
143188
auto text = std::format(
144189
"OpenXR API Layers GUI v{}\n"
@@ -148,8 +193,13 @@ void SaveReport(const std::filesystem::path& path) {
148193
std::chrono::current_zone(), std::chrono::system_clock::now()));
149194

150195
auto& platform = Platform::Get();
151-
text += GenerateRuntimeText(64, platform.Get64BitRuntime());
152-
text += GenerateRuntimeText(32, platform.Get32BitRuntime());
196+
text += GenerateActiveRuntimeText(64, platform.Get64BitRuntime());
197+
text += GenerateActiveRuntimeText(32, platform.Get32BitRuntime());
198+
199+
text
200+
+= GenerateAvailableRuntimesText(64, platform.GetAvailable64BitRuntimes());
201+
text
202+
+= GenerateAvailableRuntimesText(32, platform.GetAvailable64BitRuntimes());
153203

154204
for (const auto store: APILayerStore::Get()) {
155205
text += GenerateReportText(store);

src/windows/WindowsPlatform.cpp

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <Windows.h>
88

99
#include <wil/com.h>
10+
#include <wil/registry.h>
1011
#include <wil/resource.h>
1112

1213
#include <nlohmann/json.hpp>
@@ -41,17 +42,55 @@ extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(
4142
namespace FredEmmott::OpenXRLayers {
4243

4344
namespace {
45+
46+
std::vector<AvailableRuntime> GetAvailableRuntimes(const REGSAM bitness) {
47+
const REGSAM desiredAccess = bitness | KEY_READ;
48+
wil::unique_hkey hkey;
49+
RegOpenKeyExW(
50+
HKEY_LOCAL_MACHINE,
51+
L"SOFTWARE\\Khronos\\OpenXR\\1\\AvailableRuntimes",
52+
0,
53+
desiredAccess,
54+
hkey.put());
55+
if (!hkey) {
56+
return {};
57+
}
58+
59+
std::vector<AvailableRuntime> ret;
60+
using enum AvailableRuntime::Discoverability;
61+
for (auto&& it: wil::make_range(
62+
wil::reg::value_iterator {hkey.get()}, wil::reg::value_iterator {})) {
63+
if (it.type != REG_DWORD) {
64+
ret.emplace_back(it.name, Win32_NotDWORD);
65+
continue;
66+
}
67+
68+
DWORD value {};
69+
DWORD valueSize {sizeof(value)};
70+
RegGetValueW(
71+
hkey.get(),
72+
nullptr,
73+
it.name.c_str(),
74+
RRF_RT_DWORD,
75+
nullptr,
76+
&value,
77+
&valueSize);
78+
ret.emplace_back(it.name, (value == 0) ? Discoverable : Hidden);
79+
}
80+
return ret;
81+
}
82+
4483
static LSTATUS
4584
GetActiveRuntimePath(const REGSAM desiredAccess, void* data, DWORD* dataSize) {
46-
wil::unique_hkey hKey;
85+
wil::unique_hkey hkey;
4786
RegOpenKeyExW(
4887
HKEY_LOCAL_MACHINE,
4988
L"SOFTWARE\\Khronos\\OpenXR\\1",
5089
0,
5190
desiredAccess,
52-
hKey.put());
91+
hkey.put());
5392
return RegGetValueW(
54-
hKey.get(),
93+
hkey.get(),
5594
nullptr,
5695
L"ActiveRuntime",
5796
RRF_RT_REG_SZ,
@@ -276,6 +315,14 @@ std::unordered_set<std::string> WindowsPlatform::GetEnvironmentVariableNames() {
276315
return ret;
277316
}
278317

318+
std::vector<AvailableRuntime> WindowsPlatform::GetAvailable32BitRuntimes() {
319+
return GetAvailableRuntimes(KEY_WOW64_32KEY);
320+
}
321+
322+
std::vector<AvailableRuntime> WindowsPlatform::GetAvailable64BitRuntimes() {
323+
return GetAvailableRuntimes(KEY_WOW64_64KEY);
324+
}
325+
279326
HWND WindowsPlatform::CreateAppWindow() {
280327
static const auto WindowTitle
281328
= std::format(L"OpenXR API Layers v{}", Config::BUILD_VERSION_W);

src/windows/WindowsPlatform.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class WindowsPlatform final : public Platform {
2828
void ShowFolderContainingFile(const std::filesystem::path& path) override;
2929
std::unordered_set<std::string> GetEnvironmentVariableNames() override;
3030

31+
std::vector<AvailableRuntime> GetAvailable32BitRuntimes() override;
32+
std::vector<AvailableRuntime> GetAvailable64BitRuntimes() override;
33+
34+
protected:
3135
std::filesystem::path Get32BitRuntimePath() override;
3236
std::filesystem::path Get64BitRuntimePath() override;
3337

0 commit comments

Comments
 (0)