From e9ace26d69347fe56e16fe50fb9f31cdc7896b97 Mon Sep 17 00:00:00 2001
From: REL <25654009+34736384@users.noreply.github.com>
Date: Thu, 10 Oct 2024 05:06:57 -0400
Subject: [PATCH] refactor
---
lib/YaeAchievementLib.vcxproj | 32 ++----
lib/src/dllmain.cpp | 211 ++++++++++++++++++++++++----------
lib/src/globals.h | 28 +++++
lib/src/il2cpp-init.cpp | 32 +++++-
lib/src/il2cpp-types.h | 47 ++++++--
lib/src/util.cpp | 168 ++++++++++++++-------------
lib/src/util.h | 32 ++----
7 files changed, 348 insertions(+), 202 deletions(-)
create mode 100644 lib/src/globals.h
diff --git a/lib/YaeAchievementLib.vcxproj b/lib/YaeAchievementLib.vcxproj
index 39b04e4..c1faaf6 100644
--- a/lib/YaeAchievementLib.vcxproj
+++ b/lib/YaeAchievementLib.vcxproj
@@ -20,9 +20,9 @@
DynamicLibrary
- true
v143
MultiByte
+ true
DynamicLibrary
@@ -30,7 +30,6 @@
v143
true
MultiByte
- false
@@ -45,31 +44,28 @@
- true
$(SolutionDir)build\$(Platform)\$(Configuration)\
build\$(Platform)\$(Configuration)\
YaeLib
+ false
- false
$(SolutionDir)build\$(Platform)\$(Configuration)\
build\$(Platform)\$(Configuration)\
+ false
Level3
true
_DEBUG;YAEACHIEVEMENTLIB_EXPORTS;_WINDOWS;_USRDLL;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)
- true
- NotUsing
- pch.h
+ false
stdcpplatest
- stdc17
+ true
- Windows
- true
- false
+ NotSet
+ DebugFull
copy $(TargetPath) $(ProjectDir)..\bin\Debug\net6.0
@@ -80,29 +76,25 @@
Level3
true
true
- true
_AMD64_;NDEBUG;YAEACHIEVEMENTLIB_EXPORTS;_WINDOWS;_USRDLL;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)
- true
- NotUsing
- pch.h
+ false
stdcpplatest
- stdc17
- None
true
Speed
+ true
- Windows
+ NotSet
true
true
- true
- false
+ DebugFull
copy $(TargetPath) $(ProjectDir)..\bin\Debug\net8.0-windows\win-x64\YaeAchievementLib.dll /y
+
diff --git a/lib/src/dllmain.cpp b/lib/src/dllmain.cpp
index a23bc4a..6ee7a12 100644
--- a/lib/src/dllmain.cpp
+++ b/lib/src/dllmain.cpp
@@ -1,87 +1,174 @@
-// ReSharper disable CppCStyleCast
-// ReSharper disable CppInconsistentNaming
-// ReSharper disable CppClangTidyModernizeUseStdPrint
-// ReSharper disable CppClangTidyClangDiagnosticCastAlign
-// ReSharper disable CppClangTidyHicppMultiwayPathsCovered
-// ReSharper disable CppDefaultCaseNotHandledInSwitchStatement
-// ReSharper disable CppClangTidyClangDiagnosticCastFunctionTypeStrict
-
+// ReSharper disable CppClangTidyCertErr33C
#include
#include
+#include
+#include "globals.h"
#include "util.h"
#include "il2cpp-init.h"
#include "il2cpp-types.h"
-using Genshin::ByteArray;
-
-HWND unityWnd = nullptr;
-HANDLE hPipe = nullptr;
-
-void* baClass;
-std::string checksum;
+CRITICAL_SECTION CriticalSection;
+void SetBreakpoint(HANDLE thread, uintptr_t address, bool enable, uint8_t index = 0);
namespace Hook {
- ByteArray* UnityEngine_RecordUserData(const INT type) {
- /*if (type == 0) {
- const auto len = checksum.length();
- const auto arr = Genshin::il2cpp_array_new_specific(baClass, len);
- memcpy(&arr->vector[0], checksum.data(), len);
- return arr;
- }
- return Genshin::il2cpp_array_new_specific(baClass, 0);*/
- return {};
- }
-
- uint16_t BitConverter_ToUInt16(ByteArray* val, const int startIndex) {
- /*const auto ret = CALL_ORIGIN(BitConverter_ToUInt16, val, startIndex);
- if (ret == 0xAB89 && ReadMapped(val->vector, 2) == 24082) {
- const auto headLength = ReadMapped(val->vector, 4);
- const auto dataLength = ReadMapped(val->vector, 6);
- const auto cStr = base64_encode(val->vector + 10 + headLength, dataLength) + "\n";
- WriteFile(hPipe, cStr.c_str(), (DWORD) cStr.length(), nullptr, nullptr);
- CloseHandle(hPipe);
+
+ uint16_t __fastcall BitConverter_ToUInt16(Array* val, const int startIndex)
+ {
+ using namespace Globals;
+ const auto ToUInt16 = reinterpret_cast(Offset.BitConverter_ToUInt16);
+
+ EnterCriticalSection(&CriticalSection);
+ SetBreakpoint((HANDLE)-2, 0, false);
+ const auto ret = ToUInt16(val, startIndex);
+ SetBreakpoint((HANDLE)-2, Offset.BitConverter_ToUInt16, true);
+ LeaveCriticalSection(&CriticalSection);
+
+ const auto packet = reinterpret_cast(val->data());
+
+ using namespace Globals;
+ if (ret == 0xAB89 && _byteswap_ushort(packet->CmdId) == CmdId)
+ {
+ const auto headLength = _byteswap_ushort(packet->HeaderLength);
+ const auto dataLength = _byteswap_ulong(packet->DataLength);
+
+ const auto base64 = Util::Base64Encode(packet->Data + headLength, dataLength) + "\n";
+
+#ifdef _DEBUG
+ printf("Base64: %s\n", base64.c_str());
+ system("pause");
+#endif
+
+ WriteFile(MessagePipe, base64.c_str(), (DWORD)base64.length(), nullptr, nullptr);
+ CloseHandle(MessagePipe);
ExitProcess(0);
}
- return ret;*/
- return {};
+
+ return ret;
}
}
-void Run(HMODULE* phModule) {
- //AllocConsole();
- //freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
- while ((unityWnd = FindMainWindowByPID(GetCurrentProcessId())) == nullptr) {
- Sleep(1000);
+LONG __stdcall VectoredExceptionHandler(PEXCEPTION_POINTERS ep)
+{
+ using namespace Globals;
+ const auto exceptionRecord = ep->ExceptionRecord;
+ const auto contextRecord = ep->ContextRecord;
+
+ if (exceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)
+ {
+ if (exceptionRecord->ExceptionAddress != reinterpret_cast(Offset.BitConverter_ToUInt16)) {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ contextRecord->Rip = reinterpret_cast(Hook::BitConverter_ToUInt16);
+ contextRecord->EFlags &= ~0x100; // clear the trap flag
+ return EXCEPTION_CONTINUE_EXECUTION;
}
- Sleep(5000);
- DisableVMProtect();
- InitIL2CPP();
- /*for (int i = 0; i < 3; i++) {
- const auto result = Genshin::RecordUserData(i);
- checksum += string(reinterpret_cast(&result->vector[0]), result->max_length);
- baClass = result->klass;
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+void SetBreakpoint(HANDLE thread, uintptr_t address, bool enable, uint8_t index)
+{
+ using namespace Globals;
+
+ if (index > 3) {
+ return;
}
- HookManager::install(Genshin::RecordUserData, Hook::UnityEngine_RecordUserData);
- HookManager::install(Genshin::BitConverter_ToUInt16, Hook::BitConverter_ToUInt16);*/
- hPipe = CreateFile(R"(\\.\pipe\YaeAchievementPipe)", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
- if (hPipe == INVALID_HANDLE_VALUE) {
- Win32ErrorDialog(1001);
+
+ if (!BaseAddress || Offset.BitConverter_ToUInt16 <= BaseAddress) {
+ // not initialized yet
+ return;
+ }
+
+ CONTEXT ctx{};
+ ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ GetThreadContext(thread, &ctx);
+
+ DWORD64* dr = &ctx.Dr0;
+ dr[index] = enable ? address : 0;
+
+ const auto mask = 1ull << (index * 2);
+ ctx.Dr7 |= mask;
+
+ SetThreadContext(thread, &ctx);
+}
+
+DWORD __stdcall ThreadProc(LPVOID hInstance)
+{
+#ifdef _DEBUG
+ AllocConsole();
+ freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
+#endif
+ InitializeCriticalSection(&CriticalSection);
+
+ const auto hInitThread = CreateThread(nullptr, 0, reinterpret_cast(InitIL2CPP), nullptr, 0,
+ nullptr);
+
+ using namespace Globals;
+ const auto pid = GetCurrentProcessId();
+
+ while ((GameWindow = Util::FindMainWindowByPID(pid)) == nullptr) {
+ SwitchToThread();
+ }
+
+ if (!hInitThread) {
+ InitIL2CPP();
+ }
+ else {
+ WaitForSingleObject(hInitThread, INFINITE);
+ CloseHandle(hInitThread);
+ }
+
+ MessagePipe = CreateFileA(R"(\\.\pipe\YaeAchievementPipe)", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
+ if (MessagePipe == INVALID_HANDLE_VALUE)
+ {
+#ifdef _DEBUG
+ Util::ErrorDialog("Failed to open pipe");
+#else
+ Util::Win32ErrorDialog(1001, GetLastError());
ExitProcess(0);
+#endif
}
+
+ AddVectoredExceptionHandler(1, VectoredExceptionHandler);
+ while (true)
+ {
+ THREADENTRY32 te32{};
+ te32.dwSize = sizeof(THREADENTRY32);
+ const auto hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ for (Thread32First(hSnapshot, &te32); Thread32Next(hSnapshot, &te32);)
+ {
+ if (te32.th32OwnerProcessID != pid) {
+ continue;
+ }
+
+ if (const auto hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID))
+ {
+ EnterCriticalSection(&CriticalSection);
+ SetBreakpoint(hThread, Offset.BitConverter_ToUInt16, true);
+ CloseHandle(hThread);
+ LeaveCriticalSection(&CriticalSection);
+ }
+ }
+ CloseHandle(hSnapshot);
+ Sleep(1);
+ }
+
+ return 0;
}
// DLL entry point
-BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReasonForCall, LPVOID lpReserved) {
- switch (ulReasonForCall) {
- case DLL_PROCESS_ATTACH:
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Run, new HMODULE(hModule), 0, NULL);
- break;
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
+BOOL __stdcall DllMain(HMODULE hInstance, DWORD fdwReason, LPVOID lpReserved)
+{
+
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ {
+ if (const auto hThread = CreateThread(nullptr, 0, ThreadProc, hInstance, 0, nullptr)) {
+ CloseHandle(hThread);
+ }
}
+
return TRUE;
}
diff --git a/lib/src/globals.h b/lib/src/globals.h
new file mode 100644
index 0000000..89af9d4
--- /dev/null
+++ b/lib/src/globals.h
@@ -0,0 +1,28 @@
+#pragma once
+#include
+
+#define PROPERTY2(type, name, cn, os) \
+ type name##_cn = cn; \
+ type name##_os = os; \
+ type get_##name() { return Globals::IsCNREL ? name##_cn : name##_os; } \
+ void set_##name(type value) { if (Globals::IsCNREL) name##_cn = value; else name##_os = value; } \
+ __declspec(property(get = get_##name, put = set_##name)) type name;
+
+namespace Globals
+{
+ inline HWND GameWindow = nullptr;
+ inline HANDLE MessagePipe = nullptr;
+ inline bool IsCNREL = true;
+ inline uintptr_t BaseAddress = 0;
+
+ // 5.1.0 - 24082
+ inline uint16_t CmdId = 24082; // use non-zero to override dynamic search
+
+ class Offsets
+ {
+ public:
+ PROPERTY2(uintptr_t, BitConverter_ToUInt16, 0x0F826CF0, 0x0F825F10); // use non-zero to override dynamic search
+ };
+
+ inline Offsets Offset;
+}
\ No newline at end of file
diff --git a/lib/src/il2cpp-init.cpp b/lib/src/il2cpp-init.cpp
index f34e05c..facb984 100644
--- a/lib/src/il2cpp-init.cpp
+++ b/lib/src/il2cpp-init.cpp
@@ -1,12 +1,32 @@
-// ReSharper disable CppCStyleCast
-// ReSharper disable CppInconsistentNaming
-// ReSharper disable CppClangTidyBugproneMacroParentheses
-// ReSharper disable CppClangTidyClangDiagnosticCastAlign
-
#include
#include
+#include "globals.h"
void InitIL2CPP()
{
-
+ std::string buffer;
+ buffer.resize(MAX_PATH);
+ ZeroMemory(buffer.data(), MAX_PATH);
+ const auto pathLength = GetModuleFileNameA(nullptr, buffer.data(), MAX_PATH);
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ buffer.resize(pathLength);
+ ZeroMemory(buffer.data(), pathLength);
+ GetModuleFileNameA(nullptr, buffer.data(), pathLength);
+ }
+ buffer.shrink_to_fit();
+
+ using namespace Globals;
+ IsCNREL = buffer.find("YuanShen.exe") != std::string::npos;
+ BaseAddress = (uintptr_t)GetModuleHandleA(nullptr);
+
+ if (Offset.BitConverter_ToUInt16 != 0) {
+ Offset.BitConverter_ToUInt16 += BaseAddress;
+ }
+
+#ifdef _DEBUG
+ printf("BaseAddress: 0x%llX\n", BaseAddress);
+ printf("IsCNREL: %d\n", IsCNREL);
+ printf("BitConverter_ToUInt16: 0x%llX\n", Offset.BitConverter_ToUInt16);
+#endif
}
diff --git a/lib/src/il2cpp-types.h b/lib/src/il2cpp-types.h
index 0eb9ee7..c043e00 100644
--- a/lib/src/il2cpp-types.h
+++ b/lib/src/il2cpp-types.h
@@ -1,15 +1,38 @@
-// ReSharper disable CppClangTidyClangDiagnosticReservedIdentifier
-// ReSharper disable CppClangTidyBugproneReservedIdentifier
-
#pragma once
+#include
-namespace Genshin {
+template
+class Array
+{
+public:
+ void* klass;
+ void* monitor;
+ void* bounds;
+ size_t max_length;
+ T vector[1];
- struct ByteArray {
- void* klass;
- void* monitor;
- void* bounds;
- uint64_t max_length;
- uint8_t vector[32];
- };
-}
+ Array() = delete;
+
+ T* data() {
+ return vector;
+ }
+};
+
+static_assert(alignof(Array) == 8, "Array alignment is incorrect");
+static_assert(offsetof(Array, vector) == 32, "vector offset is incorrect");
+
+#pragma pack(push, 1)
+struct PacketMeta
+{
+ uint16_t HeadMagic;
+ uint16_t CmdId;
+ uint16_t HeaderLength;
+ uint32_t DataLength;
+ uint8_t Data[1];
+};
+#pragma pack(pop)
+
+static_assert(offsetof(PacketMeta, CmdId) == 2, "CmdId offset is incorrect");
+static_assert(offsetof(PacketMeta, HeaderLength) == 4, "HeadLength offset is incorrect");
+static_assert(offsetof(PacketMeta, DataLength) == 6, "DataLength offset is incorrect");
+static_assert(offsetof(PacketMeta, Data) == 10, "Data offset is incorrect");
\ No newline at end of file
diff --git a/lib/src/util.cpp b/lib/src/util.cpp
index b82eb75..59a0d92 100644
--- a/lib/src/util.cpp
+++ b/lib/src/util.cpp
@@ -1,95 +1,99 @@
-#include
#include
-
#include "util.h"
-
-VOID DisableVMProtect() {
- DWORD oldProtect = 0;
- auto ntdll = GetModuleHandleA("ntdll.dll");
- auto pNtProtectVirtualMemory = GetProcAddress(ntdll, "NtProtectVirtualMemory");
- auto pNtQuerySection = GetProcAddress(ntdll, "NtQuerySection");
- DWORD old;
- VirtualProtect(pNtProtectVirtualMemory, 1, PAGE_EXECUTE_READWRITE, &old);
- *(uintptr_t*)pNtProtectVirtualMemory = *(uintptr_t*)pNtQuerySection & ~(0xFFui64 << 32) | (uintptr_t)(*(uint32_t*)((uintptr_t)pNtQuerySection + 4) - 1) << 32;
- VirtualProtect(pNtProtectVirtualMemory, 1, old, &old);
-}
-
-#pragma region ByteUtils
-
-bool IsLittleEndian() {
- UINT i = 1;
- char* c = (char*)&i;
- return *c;
-}
-
-#pragma endregion
+#include "globals.h"
#pragma region FindMainWindowByPID
-struct HandleData {
- DWORD pid;
- HWND hwnd;
-};
+namespace
+{
+ struct HandleData {
+ DWORD pid;
+ HWND hwnd;
+ };
-BOOL IsMainWindow(HWND handle) {
- return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle) == TRUE;
-}
+ bool IsMainWindow(HWND handle) {
+ return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle) == TRUE;
+ }
-BOOL IsUnityWindow(HWND handle) {
- TCHAR name[256];
- GetClassName(handle, name, 256);
- return _strcmpi(name, "UnityWndClass") == 0;
-}
+ bool IsUnityWindow(HWND handle) {
+ char szName[256]{};
+ GetClassNameA(handle, szName, 256);
+ return _stricmp(szName, "UnityWndClass") == 0;
+ }
-BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) {
- HandleData& data = *(HandleData*)lParam;
- DWORD pid = 0;
- GetWindowThreadProcessId(handle, &pid);
- if (data.pid != pid || !IsMainWindow(handle) || !IsUnityWindow(handle))
- return TRUE;
- data.hwnd = handle;
- return FALSE;
-}
-
-HWND FindMainWindowByPID(DWORD pid) {
- HandleData data = { pid, 0 };
- EnumWindows(EnumWindowsCallback, (LPARAM)&data);
- return data.hwnd;
+ BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) {
+ HandleData& data = *(HandleData*)lParam;
+ DWORD pid = 0;
+ GetWindowThreadProcessId(handle, &pid);
+ if (data.pid != pid || !IsMainWindow(handle) || !IsUnityWindow(handle))
+ return TRUE;
+ data.hwnd = handle;
+ return FALSE;
+ }
}
#pragma endregion
-static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static constexpr LPCSTR base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-std::string base64_encode(BYTE const* buf, unsigned int bufLen) {
- std::string ret;
- int i = 0;
- BYTE char_array_3[3];
- BYTE char_array_4[4];
- while (bufLen--) {
- char_array_3[i++] = *buf++;
- if (i == 3) {
- char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
- char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
- char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
- char_array_4[3] = char_array_3[2] & 0x3f;
- for (i = 0; (i < 4); i++)
- ret += base64_chars[char_array_4[i]];
- i = 0;
- }
- }
- if (i) {
- int j;
- for (j = i; j < 3; j++)
- char_array_3[j] = '\0';
- char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
- char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
- char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
- char_array_4[3] = char_array_3[2] & 0x3f;
- for (j = 0; j < i + 1; j++)
- ret += base64_chars[char_array_4[j]];
- while (i++ < 3)
- ret += '=';
- }
- return ret;
-}
+namespace Util
+{
+ HWND FindMainWindowByPID(DWORD pid)
+ {
+ HandleData data = { pid, 0 };
+ EnumWindows(EnumWindowsCallback, (LPARAM)&data);
+ return data.hwnd;
+ }
+
+ std::string Base64Encode(BYTE const* buf, unsigned int bufLen)
+ {
+ std::string ret;
+ int i = 0;
+ BYTE char_array_3[3];
+ BYTE char_array_4[4];
+ while (bufLen--) {
+ char_array_3[i++] = *buf++;
+ if (i == 3) {
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+ for (i = 0; (i < 4); i++)
+ ret += base64_chars[char_array_4[i]];
+ i = 0;
+ }
+ }
+ if (i) {
+ int j;
+ for (j = i; j < 3; j++)
+ char_array_3[j] = '\0';
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+ for (j = 0; j < i + 1; j++)
+ ret += base64_chars[char_array_4[j]];
+ while (i++ < 3)
+ ret += '=';
+ }
+ return ret;
+ }
+
+ void ErrorDialog(LPCSTR title, LPCSTR msg)
+ {
+ MessageBoxA(Globals::GameWindow, msg, title, MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
+ }
+
+ void ErrorDialog(LPCSTR msg)
+ {
+ ErrorDialog("YaeAchievement", msg);
+ }
+
+ void Win32ErrorDialog(DWORD code, DWORD winerrcode)
+ {
+ const std::string msg = "CRITICAL ERROR!\nError code: " + std::to_string(winerrcode) + "-" + std::to_string(code) +
+ "\n\nPlease take the screenshot and contact developer by GitHub Issue to solve this problem\nNOT MIHOYO/COGNOSPHERE CUSTOMER SERVICE!";
+
+ ErrorDialog("YaeAchievement", msg.c_str());
+ }
+}
\ No newline at end of file
diff --git a/lib/src/util.h b/lib/src/util.h
index 5458f4d..66bd7c0 100644
--- a/lib/src/util.h
+++ b/lib/src/util.h
@@ -1,25 +1,17 @@
+// ReSharper disable CppClangTidyClangDiagnosticLanguageExtensionToken
#pragma once
+#include
+#include
-using std::string;
-VOID DisableVMProtect();
-bool IsLittleEndian();
-HWND FindMainWindowByPID(DWORD pid);
-std::string base64_encode(BYTE const* buf, unsigned int bufLen);
+namespace Util
+{
+ HWND FindMainWindowByPID(DWORD pid);
+ std::string Base64Encode(BYTE const* buf, unsigned int bufLen);
-#define ErrorDialogT(title, msg) MessageBox(unityWnd, msg, title, MB_OK | MB_ICONERROR | MB_SYSTEMMODAL)
-#define ErrorDialog(msg) ErrorDialogT("YaeAchievement", msg)
-#define Win32ErrorDialog(code) ErrorDialogT("YaeAchievement", ("CRITICAL ERROR!\nError code: " + std::to_string(GetLastError()) + "-"#code"\n\nPlease take the screenshot and contact developer by GitHub Issue to solve this problem\nNOT MIHOYO/COGNOSPHERE CUSTOMER SERVICE!").c_str())
+ void ErrorDialog(LPCSTR title, LPCSTR msg);
+ void ErrorDialog(LPCSTR msg);
+ void Win32ErrorDialog(DWORD code, DWORD winerrcode);
-template
-static T ReadMapped(void* data, int offset, bool littleEndian = false) {
- char* cData = (char*)data;
- T result = {};
- if (IsLittleEndian() != littleEndian) {
- for (int i = 0; i < sizeof(T); i++)
- ((char*)&result)[i] = cData[offset + sizeof(T) - i - 1];
- return result;
- }
- memcpy(&result, cData + offset, sizeof(result));
- return result;
-}
+
+}
\ No newline at end of file