CommonLibSSE (powerof3)
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 _filename = L"SkyrimSE.exe"sv;
89 }
90
91 load();
92 }
93
94 Module(const Module&) = delete;
95 Module(Module&&) = delete;
96
97 ~Module() noexcept = default;
98
99 Module& operator=(const Module&) = delete;
100 Module& operator=(Module&&) = delete;
101
102 void load()
103 {
104 auto handle = REX::W32::GetModuleHandleW(_filename.c_str());
105 if (handle == nullptr) {
107 std::format(
108 "Failed to obtain module handle for: \"{0}\".\n"
109 "You have likely renamed the executable to something unexpected. "
110 "Renaming the executable back to \"{0}\" may resolve the issue."sv,
111 stl::utf16_to_utf8(_filename).value_or("<unicode conversion error>"s)));
112 }
113 _base = reinterpret_cast<std::uintptr_t>(handle);
114
115 load_version();
116 load_segments();
117 }
118
119 void load_segments();
120
121 void load_version()
122 {
123 const auto version = GetFileVersion(_filename);
124 if (version) {
125 _version = *version;
126 } else {
128 std::format(
129 "Failed to obtain file version info for: {}\n"
130 "Please contact the author of this script extender plugin for further assistance."sv,
131 stl::utf16_to_utf8(_filename).value_or("<unicode conversion error>"s)));
132 }
133 }
134
135 static constexpr std::array SEGMENTS{
136 std::make_pair(".text"sv, REX::W32::IMAGE_SCN_MEM_EXECUTE),
137 std::make_pair(".idata"sv, 0u),
138 std::make_pair(".rdata"sv, 0u),
139 std::make_pair(".data"sv, 0u),
140 std::make_pair(".pdata"sv, 0u),
141 std::make_pair(".tls"sv, 0u),
142 std::make_pair(".text"sv, REX::W32::IMAGE_SCN_MEM_WRITE),
143 std::make_pair(".gfids"sv, 0u)
144 };
145
146 static constexpr auto ENVIRONMENT = L"SKSE_RUNTIME"sv;
147
148 std::wstring _filename;
149 std::array<Segment, Segment::total> _segments;
150 Version _version;
151 std::uintptr_t _base{ 0 };
152 };
153}
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:6
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:82
Definition EffectArchetypes.h:65