pwn++  0.1.4
A (toy) Windows & Linux pwn library to play with modern C++.
Common.hpp
1 #pragma once
2 
3 #include <array>
4 #include <chrono>
5 #include <filesystem>
6 #include <map>
7 #include <memory>
8 #include <mutex>
9 #include <optional>
10 #include <type_traits>
11 #include <vector>
12 
13 #include "Error.hpp"
14 
15 #define __STR(x) #x
16 #define STR(x) __STR(x)
17 #define __WIDE(x) L#x
18 #define WIDECHAR(x) __WIDE(x)
19 #define __WIDE2(x) L##x
20 #define WIDECHAR2(x) __WIDE2(x)
21 #define CONCAT(x, y) (x##y)
22 
23 
24 #if defined(PWN_BUILD_FOR_WINDOWS)
25 #define UMDF_USING_NTSTATUS
26 
27 // Windows Header Files
28 #pragma warning(push)
29 #pragma warning(disable : 4005) // Disable macro re-definition warnings
30 // clang-format off
31 #include <phnt_windows.h>
32 #include <phnt.h>
33 // clang-format on
34 #pragma warning(pop)
35 
36 #elif defined(PWN_BUILD_FOR_LINUX)
37 
38 //
39 // Windows SAL compat stuff
40 //
41 #define _In_
42 #define _In_opt_
43 #define _Out_
44 #define _Out_opt_
45 #define _Inout_
46 #define _Inout_opt_
47 
48 #define _Success_(c)
49 
50 #include <dlfcn.h>
51 #include <stdarg.h>
52 #include <stdint.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <unistd.h>
56 
57 #ifndef MAX_PATH
58 #define MAX_PATH 260
59 #endif // MAX_PATH
60 
61 #endif // defined(PWN_BUILD_FOR_LINUX)
62 
63 #ifndef UNREFERENCED_PARAMETER
64 #define UNREFERENCED_PARAMETER(x) ((void)x)
65 #endif // UNREFERENCED_PARAMETER
66 
67 
68 #ifndef UnusedParameter
69 #define UnusedParameter UNREFERENCED_PARAMETER
70 #endif // UnusedParameter
71 
72 #ifndef UnusedResult
73 #define UnusedResult UNREFERENCED_PARAMETER
74 #endif // UnusedParameter
75 
76 #ifndef PWN_DEPRECATED
77 #define PWN_DEPRECATED __declspec(deprecated)
78 #endif
79 
80 #ifndef PWNAPI
81 #ifdef PWN_BUILD_FOR_WINDOWS
82 #define PWNAPI __declspec(dllexport)
83 #else
84 #define PWNAPI
85 #endif // PWN_BUILD_FOR_WINDOWS
86 #endif
87 
88 #ifndef __countof
89 #define __countof(x) (sizeof(x) / sizeof(x[0]))
90 #endif
91 
92 
93 #ifndef MIN
94 #define MIN(x, y) ((((size_t)x) < ((size_t)y)) ? (x) : (y))
95 #endif
96 
97 
98 using u8 = std::uint8_t;
99 using u16 = std::uint16_t;
100 using u32 = std::uint32_t;
101 using u64 = std::uint64_t;
102 using i8 = std::int8_t;
103 using i16 = std::int16_t;
104 using i32 = std::int32_t;
105 using i64 = std::int64_t;
106 #ifdef _M_IX86
107 using usize = unsigned long;
108 #else
109 using usize = std::size_t;
110 #endif
111 using ssize = std::intptr_t;
112 using uptr = std::uintptr_t;
113 
114 
115 using namespace std::literals::string_view_literals;
116 using namespace std::literals::chrono_literals;
117 
118 #ifdef PWN_BUILD_FOR_WINDOWS
119 constexpr std::string
120 constexpr_concat() noexcept
121 {
122  return std::string("");
123 }
124 
125 
126 template<typename... Args>
127 constexpr std::string
128 constexpr_concat(std::string const& arg, Args... args)
129 {
130  std::string rest = constexpr_concat(args...);
131  return arg + rest;
132 }
133 #endif // PWN_BUILT_FOR_WINDOWS
134 
135 
144 template<typename Key, typename Value, usize Size>
145 struct CMap
146 {
147  using CMapEntry = std::pair<Key, Value>;
148  std::array<CMapEntry, Size> data;
149 
150  [[nodiscard]] constexpr Value
151  at(const Key& key) const
152  {
153  const auto itr = std::find_if(
154  cbegin(data),
155  cend(data),
156  [&key](const auto& v)
157  {
158  return v.first == key;
159  });
160  if ( itr != end(data) )
161  {
162  return itr->second;
163  }
164  throw std::range_error("Not Found");
165  }
166 
167  [[nodiscard]] constexpr Value
168  operator[](const Key& key) const
169  {
170  return at(key);
171  }
172 };
173 
174 
181 template<typename T>
182 class CBuffer
183 {
184 public:
185  constexpr CBuffer(size_t n) noexcept : size_(n), mem_(new T[n])
186  {
187  }
188  constexpr ~CBuffer() noexcept
189  {
190  delete[] mem_;
191  }
192 
193  constexpr CBuffer(const CBuffer& other) noexcept : size_(other.size_)
194  {
195  if ( &other != this )
196  {
197  mem_ = new T[size_];
198  std::copy(other.mem_, other.mem_ + size_, mem_);
199  }
200  }
201 
202  constexpr CBuffer(CBuffer&& other) noexcept
203  {
204  if ( &other != this )
205  {
206  mem_ = other.mem_;
207  size_ = other.size_;
208  other.mem_ = nullptr;
209  other.size_ = 0;
210  }
211  }
212 
213  constexpr CBuffer&
214  operator=(const CBuffer& other) noexcept
215  {
216  if ( &other != this )
217  {
218  mem_ = new T[size_];
219  std::copy(other.mem_, other.mem_ + size_, mem_);
220  }
221  return *this;
222  }
223 
224  constexpr CBuffer&
225  operator=(CBuffer&& other) noexcept
226  {
227  if ( &other != this )
228  {
229  mem_ = other.mem_;
230  size_ = other.size_;
231  other.mem_ = nullptr;
232  other.size_ = 0;
233  }
234  return *this;
235  }
236 
237  constexpr T&
238  operator[](size_t id) noexcept
239  {
240  return mem_[id];
241  }
242  constexpr const T&
243  operator[](size_t id) const noexcept
244  {
245  return mem_[id];
246  }
247 
248  constexpr T*
249  data() const noexcept
250  {
251  return mem_;
252  }
253  constexpr size_t
254  size() const noexcept
255  {
256  return size_;
257  }
258 
259  constexpr T*
260  begin() const noexcept
261  {
262  return mem_;
263  }
264 
265  constexpr T*
266  end() const noexcept
267  {
268  return mem_ + size_;
269  }
270 
271  constexpr const T*
272  cbegin() const noexcept
273  {
274  return mem_;
275  }
276 
277  constexpr const T*
278  cend() const noexcept
279  {
280  return mem_ + size_;
281  }
282 
283 private:
284  T* mem_ {nullptr};
285  size_t size_ {0};
286 };
287 
288 
295 template<typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
296 class CBitMask
297 {
298  using N = typename std::underlying_type<T>::type;
299 
300  static constexpr N
301  get(T a)
302  {
303  return static_cast<N>(a);
304  }
305 
306  explicit constexpr CBitMask(N a) : m_val(a)
307  {
308  }
309 
310 public:
311  constexpr CBitMask() : m_val(0)
312  {
313  }
314 
315  constexpr CBitMask(T a) : m_val(get(a))
316  {
317  }
318 
319  constexpr CBitMask
320  operator|(T t)
321  {
322  return CBitMask(m_val | get(t));
323  }
324 
325  constexpr bool
326  operator&(T t)
327  {
328  return m_val & get(t);
329  }
330 
331  constexpr N const
332  get() const
333  {
334  return m_val;
335  }
336 
337 private:
338  N m_val = 0;
339 };
340 
341 
347 template<typename T>
348 concept Flattenable = std::same_as<T, std::vector<u8>> || std::same_as<T, std::string> || std::same_as<T, std::wstring>;
349 
350 
361 template<Flattenable T, Flattenable... Args>
362 constexpr usize
363 SumSizeOfFlattenable(T arg, Args... args)
364 {
365  usize sz = 0;
366 
367  if constexpr ( std::is_same_v<T, std::string> )
368  {
369  sz += arg.size();
370  }
371  else if constexpr ( std::is_same_v<T, std::wstring> )
372  {
373  sz += arg.size() * sizeof(wchar_t);
374  }
375  else if constexpr ( std::is_same_v<T, std::vector<u8>> )
376  {
377  sz += arg.size();
378  }
379  else
380  {
381  sz += sizeof(arg);
382  }
383 
384  if constexpr ( sizeof...(args) > 0 )
385  {
386  return sz + SumSizeOfFlattenable(args...);
387  }
388 
389  return sz;
390 }
391 
392 
398 // clang-format off
399 template<typename T>
400 concept Indexable = requires(T t)
401 {
402  // {t.Id } -> std::same_as<u32 const&>;
403  { t.Id() }-> std::same_as<u32>;
404 };
405 // clang-format on
406 
407 
414 template<Indexable T>
415 class IndexedVector : public std::vector<T>
416 {
417 public:
418  T&
419  operator[](int Id);
420 };
421 
422 
430 template<Indexable T>
431 T&
433 {
434  return std::find_if(
435  this->cbegin(),
436  this->cend(),
437  [&Id](T const& t)
438  {
439  return t.Id() == Id;
440  });
441 }
A basic constexpr bitmask class.
Definition: Common.hpp:297
A basic constexpr generic buffer https://www.cppstories.com/2021/constexpr-new-cpp20/.
Definition: Common.hpp:183
An IndexedVector is a vector of Indexable types. This allows to override [] to the Id attribute of th...
Definition: Common.hpp:416
T & operator[](int Id)
Definition: Common.hpp:432
A constexpr map https://xuhuisun.com/post/c++-weekly-2-constexpr-map/.
Definition: Common.hpp:146