#pragma once #include #include #include #include #include "logging.h" #include "circular_buffer.h" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define CLAMP(x, lower, upper) (MIN(upper, MAX(x, lower))) #define ARRAY_SETB(A, k) ((A)[((k) / 8)] |= (1 << ((k) % 8))) #define ARRAY_CLRB(A, k) ((A)[((k) / 8)] &= ~(1 << ((k) % 8))) #define ARRAY_TSTB(A, k) ((A)[((k) / 8)] & (1 << ((k) % 8))) #ifndef RtlOffsetToPointer #define RtlOffsetToPointer(B, O) ((PCHAR) (((PCHAR) (B)) + ((ULONG_PTR) (O)))) #endif static const char HEX_LOOKUP_UPPERCASE[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; const char *inet_ntop(short af, const void *src, char *dst, DWORD size); static inline bool string_begins_with(const std::string &s, const std::string &prefix) { return s.compare(0, prefix.size(), prefix) == 0; } static inline bool string_begins_with(const std::wstring &s, const std::wstring &prefix) { return s.compare(0, prefix.size(), prefix) == 0; } static inline bool string_ends_with(const char *s, const char *suffix) { if (!s || !suffix) { return false; } auto len1 = strlen(s); auto len2 = strlen(suffix); if (len2 > len1) { return false; } return strncmp(s + len1 - len2, suffix, len2) == 0; } static inline bool string_ends_with(const wchar_t *s, const wchar_t *suffix) { if (!s || !suffix) { return false; } auto len1 = wcslen(s); auto len2 = wcslen(suffix); if (len2 > len1) { return false; } return wcsncmp(s + len1 - len2, suffix, len2) == 0; } template static inline void strsplit(const std::string &str, Container &cont, char delim = ' ') { std::istringstream ss(str); std::string token; while (std::getline(ss, token, delim)) { cont.push_back(token); } } static inline void strreplace(std::string &s, const std::string &search, const std::string &replace) { size_t pos = 0; while ((pos = s.find(search, pos)) != std::string::npos) { s.replace(pos, search.length(), replace); pos += replace.length(); } } static inline std::string strtrim(const std::string& input) { std::string output = input; // trim spaces output.erase(0, output.find_first_not_of("\t\n\v\f\r ")); output.erase(output.find_last_not_of("\t\n\v\f\r ") + 1); return output; } static inline std::string strtolower(const std::string& input) { std::string output = strtrim(input); // replace with lower case std::transform( output.begin(), output.end(), output.begin(), [](unsigned char c){ return std::tolower(c); }); return output; } static inline int _hex2bin_helper(char input) { if (input >= '0' && input <= '9') { return input - '0'; } if (input >= 'A' && input <= 'F') { return input - 'A' + 10; } if (input >= 'a' && input <= 'f') { return input - 'a' + 10; } return -1; } static inline bool hex2bin(const char *src, uint8_t *target) { while (*src) { if (!src[1]) { return false; } auto first = _hex2bin_helper(*src) * 16; auto second = _hex2bin_helper(src[1]); if (first < 0 || second < 0) { return false; } *(target++) = first + second; src += 2; } return true; } template static inline std::string bin2hex(T data) { std::string str; str.reserve(sizeof(T) * 2); for (size_t i = 0; i < sizeof(T); i++) { auto ch = ((uint8_t *) &data)[i]; str.push_back(HEX_LOOKUP_UPPERCASE[(ch & 0xF0) >> 4]); str.push_back(HEX_LOOKUP_UPPERCASE[ch & 0x0F]); } return str; } template static inline std::string bin2hex(T *data, size_t size) { std::string str; str.reserve(size * 2); auto bytes = reinterpret_cast(data); for (size_t i = 0; i < size; i++) { const auto ch = bytes[i]; str.push_back(HEX_LOOKUP_UPPERCASE[(ch & 0xF0) >> 4]); str.push_back(HEX_LOOKUP_UPPERCASE[ch & 0x0F]); } return str; } template static inline std::string bin2hex(const std::vector &data) { std::string str; str.reserve(data.size() * 2); for (const auto ch : data) { str.push_back(HEX_LOOKUP_UPPERCASE[(ch & 0xF0) >> 4]); str.push_back(HEX_LOOKUP_UPPERCASE[ch & 0x0F]); } return str; } template static inline std::string bin2hex(const circular_buffer &data) { std::string str; str.reserve(data.size() * 2); for (size_t i = 0; i < data.size(); i++) { const auto ch = data.peek(i); str.push_back(HEX_LOOKUP_UPPERCASE[(ch & 0xF0) >> 4]); str.push_back(HEX_LOOKUP_UPPERCASE[ch & 0x0F]); } return str; } static inline bool file_exists(const std::string &name) { auto dwAttrib = GetFileAttributes(name.c_str()); return dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY); } static inline std::string get_window_title(HWND hWnd) { char wnd_title[256] { 0 }; GetWindowTextA(hWnd, wnd_title, sizeof(wnd_title)); return std::string(wnd_title); } static inline std::string GetActiveWindowTitle() { return get_window_title(GetForegroundWindow()); } BOOL CALLBACK _find_window_begins_with_cb(HWND wnd, LPARAM lParam); static inline std::vector find_windows_beginning_with(const std::string &title) { // get all windows DWORD dwThreadID = GetCurrentThreadId(); HDESK hDesktop = GetThreadDesktop(dwThreadID); std::vector windows; EnumDesktopWindows(hDesktop, _find_window_begins_with_cb, reinterpret_cast(&windows)); // check window titles windows.erase( std::remove_if( windows.begin(), windows.end(), [title](HWND hWnd) { return !string_begins_with(get_window_title(hWnd), title); } ), windows.end() ); // return found windows return windows; } static inline HWND FindWindowBeginsWith(std::string title) { // get all windows DWORD dwThreadID = GetCurrentThreadId(); HDESK hDesktop = GetThreadDesktop(dwThreadID); std::vector windows; EnumDesktopWindows(hDesktop, _find_window_begins_with_cb, reinterpret_cast(&windows)); // check window titles char wnd_title[256]; for (HWND hWnd : windows) { GetWindowText(hWnd, wnd_title, sizeof(wnd_title)); if (string_begins_with(std::string(wnd_title), title)) { return hWnd; } } // nothing found return nullptr; } static inline std::string get_last_error_string() { // get error DWORD error = GetLastError(); if (error == 0) { return std::string(); } // get error string LPSTR messageBuffer = nullptr; size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, nullptr); // return as string std::string message(messageBuffer, size); LocalFree(messageBuffer); return message; } std::wstring s2ws(const std::string &str); std::string ws2s(const std::wstring &wstr); static inline std::string guid2s(const GUID guid) { return fmt::format("{{{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}}}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); } bool acquire_shutdown_privs(); void generate_ea_card(char card[17]);