CommonLibVR
Loading...
Searching...
No Matches
Module.h
Go to the documentation of this file.
1#pragma once
2
3#include "REL/Version.h"
4
5#include "REX/W32/KERNEL32.h"
6
7namespace REL
8{
9 class Segment
10 {
11 public:
24
25 Segment() noexcept = default;
26
27 Segment(std::uintptr_t a_proxyBase, std::uintptr_t a_address, std::uintptr_t a_size) noexcept :
28 _proxyBase(a_proxyBase),
29 _address(a_address),
30 _size(a_size)
31 {}
32
33 [[nodiscard]] std::uintptr_t address() const noexcept { return _address; }
34 [[nodiscard]] std::size_t offset() const noexcept { return address() - _proxyBase; }
35 [[nodiscard]] std::size_t size() const noexcept { return _size; }
36
37 [[nodiscard]] void* pointer() const noexcept { return reinterpret_cast<void*>(address()); }
38
39 template <class T>
40 [[nodiscard]] T* pointer() const noexcept
41 {
42 return static_cast<T*>(pointer());
43 }
44
45 private:
46 std::uintptr_t _proxyBase{ 0 };
47 std::uintptr_t _address{ 0 };
48 std::size_t _size{ 0 };
49 };
50
51 class Module
52 {
53 public:
54 [[nodiscard]] static Module& get()
55 {
56 static Module singleton;
57 return singleton;
58 }
59
60 [[nodiscard]] std::uintptr_t base() const noexcept { return _base; }
61 [[nodiscard]] stl::zwstring filename() const noexcept { return _filename; }
62 [[nodiscard]] Version version() const noexcept { return _version; }
63
64 [[nodiscard]] Segment segment(Segment::Name a_segment) const noexcept { return _segments[a_segment]; }
65
66 [[nodiscard]] REX::W32::HMODULE pointer() const noexcept { return reinterpret_cast<REX::W32::HMODULE>(base()); }
67
68 template <class T>
69 [[nodiscard]] T* pointer() const noexcept
70 {
71 return static_cast<T*>(pointer());
72 }
73
74 private:
75 Module()
76 {
77 const auto getFilename = [&]() {
79 ENVIRONMENT.data(),
80 _filename.data(),
81 static_cast<std::uint32_t>(_filename.size()));
82 };
83
84 _filename.resize(getFilename());
85 if (const auto result = getFilename();
86 result != _filename.size() - 1 ||
87 result == 0) {
88#ifndef SKYRIMVR
89 _filename = L"SkyrimSE.exe"sv;
90#else
91 _filename = L"SkyrimVR.exe"sv;
92#endif
93 }
94
95 load();
96 }
97
98 Module(const Module&) = delete;
99 Module(Module&&) = delete;
100
101 ~Module() noexcept = default;
102
103 Module& operator=(const Module&) = delete;
104 Module& operator=(Module&&) = delete;
105
106 void load()
107 {
108 auto handle = REX::W32::GetModuleHandleW(_filename.c_str());
109 if (handle == nullptr) {
111 std::format(
112 "Failed to obtain module handle for: \"{0}\".\n"
113 "You have likely renamed the executable to something unexpected. "
114 "Renaming the executable back to \"{0}\" may resolve the issue."sv,
115 stl::utf16_to_utf8(_filename).value_or("<unicode conversion error>"s)));
116 }
117 _base = reinterpret_cast<std::uintptr_t>(handle);
118
119 load_version();
120 load_segments();
121 }
122
123 void load_segments();
124
125 void load_version()
126 {
127 const auto version = GetFileVersion(_filename);
128 if (version) {
129 _version = *version;
130 } else {
132 std::format(
133 "Failed to obtain file version info for: {}\n"
134 "Please contact the author of this script extender plugin for further assistance."sv,
135 stl::utf16_to_utf8(_filename).value_or("<unicode conversion error>"s)));
136 }
137 }
138
139 static constexpr std::array SEGMENTS{
140 std::make_pair(".text"sv, REX::W32::IMAGE_SCN_MEM_EXECUTE),
141 std::make_pair(".idata"sv, 0u),
142 std::make_pair(".rdata"sv, 0u),
143 std::make_pair(".data"sv, 0u),
144 std::make_pair(".pdata"sv, 0u),
145 std::make_pair(".tls"sv, 0u),
146 std::make_pair(".text"sv, REX::W32::IMAGE_SCN_MEM_WRITE),
147 std::make_pair(".gfids"sv, 0u)
148 };
149
150 static constexpr auto ENVIRONMENT = L"SKSE_RUNTIME"sv;
151
152 std::wstring _filename;
153 std::array<Segment, Segment::total> _segments;
154 Version _version;
155 std::uintptr_t _base{ 0 };
156 };
157}
Definition Module.h:52
Version version() const noexcept
Definition Module.h:62
T * pointer() const noexcept
Definition Module.h:69
std::uintptr_t base() const noexcept
Definition Module.h:60
stl::zwstring filename() const noexcept
Definition Module.h:61
REX::W32::HMODULE pointer() const noexcept
Definition Module.h:66
static Module & get()
Definition Module.h:54
Segment segment(Segment::Name a_segment) const noexcept
Definition Module.h:64
Definition Module.h:10
std::size_t size() const noexcept
Definition Module.h:35
Name
Definition Module.h:13
@ data
Definition Module.h:17
@ tls
Definition Module.h:19
@ textw
Definition Module.h:20
@ gfids
Definition Module.h:21
@ total
Definition Module.h:22
@ idata
Definition Module.h:15
@ textx
Definition Module.h:14
@ pdata
Definition Module.h:18
@ rdata
Definition Module.h:16
void * pointer() const noexcept
Definition Module.h:37
std::uintptr_t address() const noexcept
Definition Module.h:33
Segment() noexcept=default
std::size_t offset() const noexcept
Definition Module.h:34
T * pointer() const noexcept
Definition Module.h:40
Definition Version.h:6
Definition ID.h:9
std::optional< Version > GetFileVersion(stl::zwstring a_filename)
constexpr auto IMAGE_SCN_MEM_EXECUTE
Definition KERNEL32.h:96
constexpr auto IMAGE_SCN_MEM_WRITE
Definition KERNEL32.h:98
HINSTANCE HMODULE
Definition BASE.h:24
HMODULE GetModuleHandleW(const wchar_t *a_name) noexcept
std::uint32_t GetEnvironmentVariableW(const wchar_t *a_name, wchar_t *a_buf, std::uint32_t a_bufLen) noexcept
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition PCH.h:397
auto utf16_to_utf8(std::wstring_view a_in) noexcept -> std::optional< std::string >
Definition PCH.h:369
basic_zstring< wchar_t > zwstring
Definition PCH.h:83
Definition EffectArchetypes.h:65