From c76a8579217e34bcaef23efd531f72c203f9e32a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=B3=D0=B4=D0=B0=D0=BD=20=D0=9F=D1=80=D0=BE?= =?UTF-8?q?=D0=B3=D0=B5=D1=80?= Date: Mon, 8 Aug 2022 00:19:06 +0300 Subject: [PATCH] Another patches support added: 1.24e, 1.27a, 1.27b, 1.28f. --- 3rd/Detours/Include/detours.h | 1059 --------------------------------- 3rd/Detours/Include/detver.h | 27 - 3rd/Detours/Include/syelog.h | 89 --- 3rd/Detours/Lib/detours.lib | Bin 234970 -> 0 bytes README.md | 2 +- Src/Detours.cpp | 42 ++ Src/Detours.h | 8 + Src/DllMain.cpp | 24 +- Src/Hooks.cpp | 74 ++- Src/Hooks.h | 4 +- Src/JassMachine.cpp | 14 +- Src/JassMachine.h | 148 ++--- Src/JassNatives.cpp | 10 +- Src/JassNatives.h | 4 +- Src/Logger.cpp | 13 +- Src/Logger.h | 4 +- Src/LuaFunctions.cpp | 6 +- Src/LuaHooks.cpp | 13 +- Src/LuaMachine.cpp | 14 +- Src/LuaMachine.h | 1 + Src/Offsets.cpp | 88 +++ Src/Offsets.h | 20 + Src/Warcraft.cpp | 76 ++- Src/Warcraft.h | 67 ++- Src/pch.h | 4 +- packages.config | 4 + war3_lua.vcxproj | 14 + war3_lua.vcxproj.filters | 15 + 28 files changed, 486 insertions(+), 1358 deletions(-) delete mode 100644 3rd/Detours/Include/detours.h delete mode 100644 3rd/Detours/Include/detver.h delete mode 100644 3rd/Detours/Include/syelog.h delete mode 100644 3rd/Detours/Lib/detours.lib create mode 100644 Src/Detours.cpp create mode 100644 Src/Detours.h create mode 100644 Src/Offsets.cpp create mode 100644 Src/Offsets.h create mode 100644 packages.config diff --git a/3rd/Detours/Include/detours.h b/3rd/Detours/Include/detours.h deleted file mode 100644 index fe7acf1..0000000 --- a/3rd/Detours/Include/detours.h +++ /dev/null @@ -1,1059 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// Core Detours Functionality (detours.h of detours.lib) -// -// Microsoft Research Detours Package, Version 4.0.1 -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// - -#pragma once -#ifndef _DETOURS_H_ -#define _DETOURS_H_ - -#define DETOURS_VERSION 0x4c0c1 // 0xMAJORcMINORcPATCH - -////////////////////////////////////////////////////////////////////////////// -// - -#undef DETOURS_X64 -#undef DETOURS_X86 -#undef DETOURS_IA64 -#undef DETOURS_ARM -#undef DETOURS_ARM64 -#undef DETOURS_BITS -#undef DETOURS_32BIT -#undef DETOURS_64BIT - -#if defined(_X86_) -#define DETOURS_X86 -#define DETOURS_OPTION_BITS 64 - -#elif defined(_AMD64_) -#define DETOURS_X64 -#define DETOURS_OPTION_BITS 32 - -#elif defined(_IA64_) -#define DETOURS_IA64 -#define DETOURS_OPTION_BITS 32 - -#elif defined(_ARM_) -#define DETOURS_ARM - -#elif defined(_ARM64_) -#define DETOURS_ARM64 - -#else -#error Unknown architecture (x86, amd64, ia64, arm, arm64) -#endif - -#ifdef _WIN64 -#undef DETOURS_32BIT -#define DETOURS_64BIT 1 -#define DETOURS_BITS 64 -// If all 64bit kernels can run one and only one 32bit architecture. -//#define DETOURS_OPTION_BITS 32 -#else -#define DETOURS_32BIT 1 -#undef DETOURS_64BIT -#define DETOURS_BITS 32 -// If all 64bit kernels can run one and only one 32bit architecture. -//#define DETOURS_OPTION_BITS 32 -#endif - -#define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) - -////////////////////////////////////////////////////////////////////////////// -// - -#if (_MSC_VER < 1299) -typedef LONG LONG_PTR; -typedef ULONG ULONG_PTR; -#endif - -///////////////////////////////////////////////// SAL 2.0 Annotations w/o SAL. -// -// These definitions are include so that Detours will build even if the -// compiler doesn't have full SAL 2.0 support. -// -#ifndef DETOURS_DONT_REMOVE_SAL_20 - -#ifdef DETOURS_TEST_REMOVE_SAL_20 -#undef _Analysis_assume_ -#undef _Benign_race_begin_ -#undef _Benign_race_end_ -#undef _Field_range_ -#undef _Field_size_ -#undef _In_ -#undef _In_bytecount_ -#undef _In_count_ -#undef _In_opt_ -#undef _In_opt_bytecount_ -#undef _In_opt_count_ -#undef _In_opt_z_ -#undef _In_range_ -#undef _In_reads_ -#undef _In_reads_bytes_ -#undef _In_reads_opt_ -#undef _In_reads_opt_bytes_ -#undef _In_reads_or_z_ -#undef _In_z_ -#undef _Inout_ -#undef _Inout_opt_ -#undef _Inout_z_count_ -#undef _Out_ -#undef _Out_opt_ -#undef _Out_writes_ -#undef _Outptr_result_maybenull_ -#undef _Readable_bytes_ -#undef _Success_ -#undef _Writable_bytes_ -#undef _Pre_notnull_ -#endif - -#if defined(_Deref_out_opt_z_) && !defined(_Outptr_result_maybenull_) -#define _Outptr_result_maybenull_ _Deref_out_opt_z_ -#endif - -#if defined(_In_count_) && !defined(_In_reads_) -#define _In_reads_(x) _In_count_(x) -#endif - -#if defined(_In_opt_count_) && !defined(_In_reads_opt_) -#define _In_reads_opt_(x) _In_opt_count_(x) -#endif - -#if defined(_In_opt_bytecount_) && !defined(_In_reads_opt_bytes_) -#define _In_reads_opt_bytes_(x) _In_opt_bytecount_(x) -#endif - -#if defined(_In_bytecount_) && !defined(_In_reads_bytes_) -#define _In_reads_bytes_(x) _In_bytecount_(x) -#endif - -#ifndef _In_ -#define _In_ -#endif - -#ifndef _In_bytecount_ -#define _In_bytecount_(x) -#endif - -#ifndef _In_count_ -#define _In_count_(x) -#endif - -#ifndef _In_opt_ -#define _In_opt_ -#endif - -#ifndef _In_opt_bytecount_ -#define _In_opt_bytecount_(x) -#endif - -#ifndef _In_opt_count_ -#define _In_opt_count_(x) -#endif - -#ifndef _In_opt_z_ -#define _In_opt_z_ -#endif - -#ifndef _In_range_ -#define _In_range_(x,y) -#endif - -#ifndef _In_reads_ -#define _In_reads_(x) -#endif - -#ifndef _In_reads_bytes_ -#define _In_reads_bytes_(x) -#endif - -#ifndef _In_reads_opt_ -#define _In_reads_opt_(x) -#endif - -#ifndef _In_reads_opt_bytes_ -#define _In_reads_opt_bytes_(x) -#endif - -#ifndef _In_reads_or_z_ -#define _In_reads_or_z_ -#endif - -#ifndef _In_z_ -#define _In_z_ -#endif - -#ifndef _Inout_ -#define _Inout_ -#endif - -#ifndef _Inout_opt_ -#define _Inout_opt_ -#endif - -#ifndef _Inout_z_count_ -#define _Inout_z_count_(x) -#endif - -#ifndef _Out_ -#define _Out_ -#endif - -#ifndef _Out_opt_ -#define _Out_opt_ -#endif - -#ifndef _Out_writes_ -#define _Out_writes_(x) -#endif - -#ifndef _Outptr_result_maybenull_ -#define _Outptr_result_maybenull_ -#endif - -#ifndef _Writable_bytes_ -#define _Writable_bytes_(x) -#endif - -#ifndef _Readable_bytes_ -#define _Readable_bytes_(x) -#endif - -#ifndef _Success_ -#define _Success_(x) -#endif - -#ifndef _Pre_notnull_ -#define _Pre_notnull_ -#endif - -#ifdef DETOURS_INTERNAL - -#pragma warning(disable:4615) // unknown warning type (suppress with older compilers) - -#ifndef _Benign_race_begin_ -#define _Benign_race_begin_ -#endif - -#ifndef _Benign_race_end_ -#define _Benign_race_end_ -#endif - -#ifndef _Field_size_ -#define _Field_size_(x) -#endif - -#ifndef _Field_range_ -#define _Field_range_(x,y) -#endif - -#ifndef _Analysis_assume_ -#define _Analysis_assume_(x) -#endif - -#endif // DETOURS_INTERNAL -#endif // DETOURS_DONT_REMOVE_SAL_20 - -////////////////////////////////////////////////////////////////////////////// -// -#ifndef GUID_DEFINED -#define GUID_DEFINED -typedef struct _GUID -{ - DWORD Data1; - WORD Data2; - WORD Data3; - BYTE Data4[ 8 ]; -} GUID; - -#ifdef INITGUID -#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - const GUID name \ - = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } -#else -#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - const GUID name -#endif // INITGUID -#endif // !GUID_DEFINED - -#if defined(__cplusplus) -#ifndef _REFGUID_DEFINED -#define _REFGUID_DEFINED -#define REFGUID const GUID & -#endif // !_REFGUID_DEFINED -#else // !__cplusplus -#ifndef _REFGUID_DEFINED -#define _REFGUID_DEFINED -#define REFGUID const GUID * const -#endif // !_REFGUID_DEFINED -#endif // !__cplusplus - -#ifndef ARRAYSIZE -#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) -#endif - -// -////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/////////////////////////////////////////////////// Instruction Target Macros. -// -#define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0) -#define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) -#define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" - -extern const GUID DETOUR_EXE_RESTORE_GUID; -extern const GUID DETOUR_EXE_HELPER_GUID; - -#define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! -typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; - -/////////////////////////////////////////////////////////// Binary Structures. -// -#pragma pack(push, 8) -typedef struct _DETOUR_SECTION_HEADER -{ - DWORD cbHeaderSize; - DWORD nSignature; - DWORD nDataOffset; - DWORD cbDataSize; - - DWORD nOriginalImportVirtualAddress; - DWORD nOriginalImportSize; - DWORD nOriginalBoundImportVirtualAddress; - DWORD nOriginalBoundImportSize; - - DWORD nOriginalIatVirtualAddress; - DWORD nOriginalIatSize; - DWORD nOriginalSizeOfImage; - DWORD cbPrePE; - - DWORD nOriginalClrFlags; - DWORD reserved1; - DWORD reserved2; - DWORD reserved3; - - // Followed by cbPrePE bytes of data. -} DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER; - -typedef struct _DETOUR_SECTION_RECORD -{ - DWORD cbBytes; - DWORD nReserved; - GUID guid; -} DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD; - -typedef struct _DETOUR_CLR_HEADER -{ - // Header versioning - ULONG cb; - USHORT MajorRuntimeVersion; - USHORT MinorRuntimeVersion; - - // Symbol table and startup information - IMAGE_DATA_DIRECTORY MetaData; - ULONG Flags; - - // Followed by the rest of the IMAGE_COR20_HEADER -} DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER; - -typedef struct _DETOUR_EXE_RESTORE -{ - DWORD cb; - DWORD cbidh; - DWORD cbinh; - DWORD cbclr; - - PBYTE pidh; - PBYTE pinh; - PBYTE pclr; - - IMAGE_DOS_HEADER idh; - union { - IMAGE_NT_HEADERS inh; - IMAGE_NT_HEADERS32 inh32; - IMAGE_NT_HEADERS64 inh64; - BYTE raw[sizeof(IMAGE_NT_HEADERS64) + - sizeof(IMAGE_SECTION_HEADER) * 32]; - }; - DETOUR_CLR_HEADER clr; - -} DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE; - -typedef struct _DETOUR_EXE_HELPER -{ - DWORD cb; - DWORD pid; - DWORD nDlls; - CHAR rDlls[4]; -} DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER; - -#pragma pack(pop) - -#define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \ -{ \ - sizeof(DETOUR_SECTION_HEADER),\ - DETOUR_SECTION_HEADER_SIGNATURE,\ - sizeof(DETOUR_SECTION_HEADER),\ - (cbSectionSize),\ - \ - 0,\ - 0,\ - 0,\ - 0,\ - \ - 0,\ - 0,\ - 0,\ - 0,\ -} - -/////////////////////////////////////////////////////////////// Helper Macros. -// -#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) -#define DETOURS_STRINGIFY_(x) #x - -///////////////////////////////////////////////////////////// Binary Typedefs. -// -typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)( - _In_opt_ PVOID pContext, - _In_opt_ LPCSTR pszFile, - _Outptr_result_maybenull_ LPCSTR *ppszOutFile); - -typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)( - _In_opt_ PVOID pContext, - _In_ LPCSTR pszOrigFile, - _In_ LPCSTR pszFile, - _Outptr_result_maybenull_ LPCSTR *ppszOutFile); - -typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)( - _In_opt_ PVOID pContext, - _In_ ULONG nOrigOrdinal, - _In_ ULONG nOrdinal, - _Out_ ULONG *pnOutOrdinal, - _In_opt_ LPCSTR pszOrigSymbol, - _In_opt_ LPCSTR pszSymbol, - _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol); - -typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)( - _In_opt_ PVOID pContext); - -typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(_In_opt_ PVOID pContext, - _In_ ULONG nOrdinal, - _In_opt_ LPCSTR pszName, - _In_opt_ PVOID pCode); - -typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(_In_opt_ PVOID pContext, - _In_opt_ HMODULE hModule, - _In_opt_ LPCSTR pszFile); - -typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(_In_opt_ PVOID pContext, - _In_ DWORD nOrdinal, - _In_opt_ LPCSTR pszFunc, - _In_opt_ PVOID pvFunc); - -// Same as PF_DETOUR_IMPORT_FUNC_CALLBACK but extra indirection on last parameter. -typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK_EX)(_In_opt_ PVOID pContext, - _In_ DWORD nOrdinal, - _In_opt_ LPCSTR pszFunc, - _In_opt_ PVOID* ppvFunc); - -typedef VOID * PDETOUR_BINARY; -typedef VOID * PDETOUR_LOADED_BINARY; - -//////////////////////////////////////////////////////////// Transaction APIs. -// -LONG WINAPI DetourTransactionBegin(VOID); -LONG WINAPI DetourTransactionAbort(VOID); -LONG WINAPI DetourTransactionCommit(VOID); -LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer); - -LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread); - -LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer, - _In_ PVOID pDetour); - -LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, - _In_ PVOID pDetour, - _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline, - _Out_opt_ PVOID *ppRealTarget, - _Out_opt_ PVOID *ppRealDetour); - -LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer, - _In_ PVOID pDetour); - -BOOL WINAPI DetourSetIgnoreTooSmall(_In_ BOOL fIgnore); -BOOL WINAPI DetourSetRetainRegions(_In_ BOOL fRetain); -PVOID WINAPI DetourSetSystemRegionLowerBound(_In_ PVOID pSystemRegionLowerBound); -PVOID WINAPI DetourSetSystemRegionUpperBound(_In_ PVOID pSystemRegionUpperBound); - -////////////////////////////////////////////////////////////// Code Functions. -// -PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, - _In_ LPCSTR pszFunction); -PVOID WINAPI DetourCodeFromPointer(_In_ PVOID pPointer, - _Out_opt_ PVOID *ppGlobals); -PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, - _Inout_opt_ PVOID *ppDstPool, - _In_ PVOID pSrc, - _Out_opt_ PVOID *ppTarget, - _Out_opt_ LONG *plExtra); -BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, - _In_ BOOL fLimitReferencesToModule); - -///////////////////////////////////////////////////// Loaded Binary Functions. -// -HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr); -HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast); -PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule); -ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule); -BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule, - _In_opt_ PVOID pContext, - _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport); -BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule, - _In_opt_ PVOID pContext, - _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, - _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc); - -BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule, - _In_opt_ PVOID pContext, - _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, - _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFuncEx); - -_Writable_bytes_(*pcbData) -_Readable_bytes_(*pcbData) -_Success_(return != NULL) -PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, - _In_ REFGUID rguid, - _Out_ DWORD *pcbData); - -_Writable_bytes_(*pcbData) -_Readable_bytes_(*pcbData) -_Success_(return != NULL) -PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, - _Out_ DWORD * pcbData); - -DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule); - -///////////////////////////////////////////////// Persistent Binary Functions. -// - -PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile); - -_Writable_bytes_(*pcbData) -_Readable_bytes_(*pcbData) -_Success_(return != NULL) -PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary, - _Out_opt_ GUID *pGuid, - _Out_ DWORD *pcbData, - _Inout_ DWORD *pnIterator); - -_Writable_bytes_(*pcbData) -_Readable_bytes_(*pcbData) -_Success_(return != NULL) -PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary, - _In_ REFGUID rguid, - _Out_ DWORD *pcbData); - -PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary, - _In_ REFGUID rguid, - _In_reads_opt_(cbData) PVOID pData, - _In_ DWORD cbData); -BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary, _In_ REFGUID rguid); -BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary); -BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary); -BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary, - _In_opt_ PVOID pContext, - _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, - _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile, - _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, - _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit); -BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pBinary, _In_ HANDLE hFile); -BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary); - -/////////////////////////////////////////////////// Create Process & Load Dll. -// -typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)( - _In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation); - -typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)( - _In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation); - -BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourCreateProcessWithDll DetourCreateProcessWithDllW -#define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW -#else -#define DetourCreateProcessWithDll DetourCreateProcessWithDllA -#define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA -#endif // !UNICODE - -BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ LPCSTR lpDllName, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW -#else -#define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA -#endif // !UNICODE - -BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName, - _Inout_opt_ LPSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOA lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, - _Inout_opt_ LPWSTR lpCommandLine, - _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, - _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, - _In_ BOOL bInheritHandles, - _In_ DWORD dwCreationFlags, - _In_opt_ LPVOID lpEnvironment, - _In_opt_ LPCWSTR lpCurrentDirectory, - _In_ LPSTARTUPINFOW lpStartupInfo, - _Out_ LPPROCESS_INFORMATION lpProcessInformation, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourCreateProcessWithDlls DetourCreateProcessWithDllsW -#else -#define DetourCreateProcessWithDlls DetourCreateProcessWithDllsA -#endif // !UNICODE - -BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid, - _In_ LPCSTR lpDllName, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid, - _In_ LPCSTR lpDllName, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourProcessViaHelper DetourProcessViaHelperW -#else -#define DetourProcessViaHelper DetourProcessViaHelperA -#endif // !UNICODE - -BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); - -BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, - _In_ DWORD nDlls, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); - -#ifdef UNICODE -#define DetourProcessViaHelperDlls DetourProcessViaHelperDllsW -#else -#define DetourProcessViaHelperDlls DetourProcessViaHelperDllsA -#endif // !UNICODE - -BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ DWORD nDlls); - -BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, - _In_ HMODULE hImage, - _In_ BOOL bIs32Bit, - _In_reads_(nDlls) LPCSTR *rlpDlls, - _In_ DWORD nDlls); - -BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, - _In_ REFGUID rguid, - _In_reads_bytes_(cbData) PVOID pvData, - _In_ DWORD cbData); -BOOL WINAPI DetourRestoreAfterWith(VOID); -BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, - _In_ DWORD cbData); -BOOL WINAPI DetourIsHelperProcess(VOID); -VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, - _In_ HINSTANCE, - _In_ LPSTR, - _In_ INT); - -// -////////////////////////////////////////////////////////////////////////////// -#ifdef __cplusplus -} -#endif // __cplusplus - -//////////////////////////////////////////////// Detours Internal Definitions. -// -#ifdef __cplusplus -#ifdef DETOURS_INTERNAL - -#define NOTHROW -// #define NOTHROW (nothrow) - -////////////////////////////////////////////////////////////////////////////// -// -#if (_MSC_VER < 1299) -#include -typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; -typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; -typedef IMAGEHLP_SYMBOL SYMBOL_INFO; -typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; - -static inline -LONG InterlockedCompareExchange(_Inout_ LONG *ptr, _In_ LONG nval, _In_ LONG oval) -{ - return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); -} -#else -#pragma warning(push) -#pragma warning(disable:4091) // empty typedef -#include -#pragma warning(pop) -#endif - -#ifdef IMAGEAPI // defined by DBGHELP.H -typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(_In_ LPAPI_VERSION AppVersion); - -typedef BOOL (NTAPI *PF_SymInitialize)(_In_ HANDLE hProcess, - _In_opt_ LPCSTR UserSearchPath, - _In_ BOOL fInvadeProcess); -typedef DWORD (NTAPI *PF_SymSetOptions)(_In_ DWORD SymOptions); -typedef DWORD (NTAPI *PF_SymGetOptions)(VOID); -typedef DWORD64 (NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess, - _In_opt_ HANDLE hFile, - _In_ LPSTR ImageName, - _In_opt_ LPSTR ModuleName, - _In_ DWORD64 BaseOfDll, - _In_opt_ DWORD SizeOfDll); -typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess, - _In_ DWORD64 qwAddr, - _Out_ PIMAGEHLP_MODULE64 ModuleInfo); -typedef BOOL (NTAPI *PF_SymFromName)(_In_ HANDLE hProcess, - _In_ LPSTR Name, - _Out_ PSYMBOL_INFO Symbol); - -typedef struct _DETOUR_SYM_INFO -{ - HANDLE hProcess; - HMODULE hDbgHelp; - PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; - PF_SymInitialize pfSymInitialize; - PF_SymSetOptions pfSymSetOptions; - PF_SymGetOptions pfSymGetOptions; - PF_SymLoadModule64 pfSymLoadModule64; - PF_SymGetModuleInfo64 pfSymGetModuleInfo64; - PF_SymFromName pfSymFromName; -} DETOUR_SYM_INFO, *PDETOUR_SYM_INFO; - -PDETOUR_SYM_INFO DetourLoadImageHlp(VOID); - -#endif // IMAGEAPI - -#if defined(_INC_STDIO) && !defined(_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS) -#error detours.h must be included before stdio.h (or at least define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS earlier) -#endif -#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 - -#ifndef DETOUR_TRACE -#if DETOUR_DEBUG -#define DETOUR_TRACE(x) printf x -#define DETOUR_BREAK() __debugbreak() -#include -#include -#else -#define DETOUR_TRACE(x) -#define DETOUR_BREAK() -#endif -#endif - -#if 1 || defined(DETOURS_IA64) - -// -// IA64 instructions are 41 bits, 3 per bundle, plus 5 bit bundle template => 128 bits per bundle. -// - -#define DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE (3) - -#define DETOUR_IA64_TEMPLATE_OFFSET (0) -#define DETOUR_IA64_TEMPLATE_SIZE (5) - -#define DETOUR_IA64_INSTRUCTION_SIZE (41) -#define DETOUR_IA64_INSTRUCTION0_OFFSET (DETOUR_IA64_TEMPLATE_SIZE) -#define DETOUR_IA64_INSTRUCTION1_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) -#define DETOUR_IA64_INSTRUCTION2_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) - -C_ASSERT(DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * DETOUR_IA64_INSTRUCTION_SIZE == 128); - -__declspec(align(16)) struct DETOUR_IA64_BUNDLE -{ - public: - union - { - BYTE data[16]; - UINT64 wide[2]; - }; - - enum { - A_UNIT = 1u, - I_UNIT = 2u, - M_UNIT = 3u, - B_UNIT = 4u, - F_UNIT = 5u, - L_UNIT = 6u, - X_UNIT = 7u, - }; - struct DETOUR_IA64_METADATA - { - ULONG nTemplate : 8; // Instruction template. - ULONG nUnit0 : 4; // Unit for slot 0 - ULONG nUnit1 : 4; // Unit for slot 1 - ULONG nUnit2 : 4; // Unit for slot 2 - }; - - protected: - static const DETOUR_IA64_METADATA s_rceCopyTable[33]; - - UINT RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; - - bool RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst, - _In_ BYTE slot, - _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; - - // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0 - // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0. - - // 00 - // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0. - // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0] - // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5] - // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42] - // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46] - // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83] - // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87] - // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124] - BYTE GetTemplate() const; - // Get 4 bit opcodes. - BYTE GetInst0() const; - BYTE GetInst1() const; - BYTE GetInst2() const; - BYTE GetUnit(BYTE slot) const; - BYTE GetUnit0() const; - BYTE GetUnit1() const; - BYTE GetUnit2() const; - // Get 37 bit data. - UINT64 GetData0() const; - UINT64 GetData1() const; - UINT64 GetData2() const; - - // Get/set the full 41 bit instructions. - UINT64 GetInstruction(BYTE slot) const; - UINT64 GetInstruction0() const; - UINT64 GetInstruction1() const; - UINT64 GetInstruction2() const; - void SetInstruction(BYTE slot, UINT64 instruction); - void SetInstruction0(UINT64 instruction); - void SetInstruction1(UINT64 instruction); - void SetInstruction2(UINT64 instruction); - - // Get/set bitfields. - static UINT64 GetBits(UINT64 Value, UINT64 Offset, UINT64 Count); - static UINT64 SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field); - - // Get specific read-only fields. - static UINT64 GetOpcode(UINT64 instruction); // 4bit opcode - static UINT64 GetX(UINT64 instruction); // 1bit opcode extension - static UINT64 GetX3(UINT64 instruction); // 3bit opcode extension - static UINT64 GetX6(UINT64 instruction); // 6bit opcode extension - - // Get/set specific fields. - static UINT64 GetImm7a(UINT64 instruction); - static UINT64 SetImm7a(UINT64 instruction, UINT64 imm7a); - static UINT64 GetImm13c(UINT64 instruction); - static UINT64 SetImm13c(UINT64 instruction, UINT64 imm13c); - static UINT64 GetSignBit(UINT64 instruction); - static UINT64 SetSignBit(UINT64 instruction, UINT64 signBit); - static UINT64 GetImm20a(UINT64 instruction); - static UINT64 SetImm20a(UINT64 instruction, UINT64 imm20a); - static UINT64 GetImm20b(UINT64 instruction); - static UINT64 SetImm20b(UINT64 instruction, UINT64 imm20b); - - static UINT64 SignExtend(UINT64 Value, UINT64 Offset); - - BOOL IsMovlGp() const; - - VOID SetInst(BYTE Slot, BYTE nInst); - VOID SetInst0(BYTE nInst); - VOID SetInst1(BYTE nInst); - VOID SetInst2(BYTE nInst); - VOID SetData(BYTE Slot, UINT64 nData); - VOID SetData0(UINT64 nData); - VOID SetData1(UINT64 nData); - VOID SetData2(UINT64 nData); - BOOL SetNop(BYTE Slot); - BOOL SetNop0(); - BOOL SetNop1(); - BOOL SetNop2(); - - public: - BOOL IsBrl() const; - VOID SetBrl(); - VOID SetBrl(UINT64 target); - UINT64 GetBrlTarget() const; - VOID SetBrlTarget(UINT64 target); - VOID SetBrlImm(UINT64 imm); - UINT64 GetBrlImm() const; - - UINT64 GetMovlGp() const; - VOID SetMovlGp(UINT64 gp); - - VOID SetStop(); - - UINT Copy(_Out_ DETOUR_IA64_BUNDLE *pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra = NULL) const; -}; -#endif // DETOURS_IA64 - -#ifdef DETOURS_ARM - -#define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1)) -#define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1)) - -#endif // DETOURS_ARM - -////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#define DETOUR_OFFLINE_LIBRARY(x) \ -PVOID WINAPI DetourCopyInstruction##x(_In_opt_ PVOID pDst, \ - _Inout_opt_ PVOID *ppDstPool, \ - _In_ PVOID pSrc, \ - _Out_opt_ PVOID *ppTarget, \ - _Out_opt_ LONG *plExtra); \ - \ -BOOL WINAPI DetourSetCodeModule##x(_In_ HMODULE hModule, \ - _In_ BOOL fLimitReferencesToModule); \ - -DETOUR_OFFLINE_LIBRARY(X86) -DETOUR_OFFLINE_LIBRARY(X64) -DETOUR_OFFLINE_LIBRARY(ARM) -DETOUR_OFFLINE_LIBRARY(ARM64) -DETOUR_OFFLINE_LIBRARY(IA64) - -#undef DETOUR_OFFLINE_LIBRARY - -////////////////////////////////////////////////////////////////////////////// -// -// Helpers for manipulating page protection. -// - -_Success_(return != FALSE) -BOOL WINAPI DetourVirtualProtectSameExecuteEx(_In_ HANDLE hProcess, - _In_ PVOID pAddress, - _In_ SIZE_T nSize, - _In_ DWORD dwNewProtect, - _Out_ PDWORD pdwOldProtect); - -_Success_(return != FALSE) -BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress, - _In_ SIZE_T nSize, - _In_ DWORD dwNewProtect, - _Out_ PDWORD pdwOldProtect); -#ifdef __cplusplus -} -#endif // __cplusplus - -////////////////////////////////////////////////////////////////////////////// - -#define MM_ALLOCATION_GRANULARITY 0x10000 - -////////////////////////////////////////////////////////////////////////////// - -#endif // DETOURS_INTERNAL -#endif // __cplusplus - -#endif // _DETOURS_H_ -// -//////////////////////////////////////////////////////////////// End of File. diff --git a/3rd/Detours/Include/detver.h b/3rd/Detours/Include/detver.h deleted file mode 100644 index f0aae9b..0000000 --- a/3rd/Detours/Include/detver.h +++ /dev/null @@ -1,27 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// Common version parameters. -// -// Microsoft Research Detours Package, Version 4.0.1 -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// - -#define _USING_V110_SDK71_ 1 -#include "winver.h" -#if 0 -#include -#include -#else -#ifndef DETOURS_STRINGIFY -#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) -#define DETOURS_STRINGIFY_(x) #x -#endif - -#define VER_FILEFLAGSMASK 0x3fL -#define VER_FILEFLAGS 0x0L -#define VER_FILEOS 0x00040004L -#define VER_FILETYPE 0x00000002L -#define VER_FILESUBTYPE 0x00000000L -#endif -#define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) diff --git a/3rd/Detours/Include/syelog.h b/3rd/Detours/Include/syelog.h deleted file mode 100644 index 7cfa9f3..0000000 --- a/3rd/Detours/Include/syelog.h +++ /dev/null @@ -1,89 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// Detours Test Program (syelog.h of syelog.lib) -// -// Microsoft Research Detours Package -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -#pragma once -#ifndef _SYELOGD_H_ -#define _SYELOGD_H_ -#include - -#pragma pack(push, 1) -#pragma warning(push) -#pragma warning(disable: 4200) - -////////////////////////////////////////////////////////////////////////////// -// -// -#define SYELOG_PIPE_NAMEA "\\\\.\\pipe\\syelog" -#define SYELOG_PIPE_NAMEW L"\\\\.\\pipe\\syelog" -#ifdef UNICODE -#define SYELOG_PIPE_NAME SYELOG_PIPE_NAMEW -#else -#define SYELOG_PIPE_NAME SYELOG_PIPE_NAMEA -#endif - -////////////////////////////////////////////////////////////////////////////// -// -#define SYELOG_MAXIMUM_MESSAGE 4086 // 4096 - sizeof(header stuff) - -typedef struct _SYELOG_MESSAGE -{ - USHORT nBytes; - BYTE nFacility; - BYTE nSeverity; - DWORD nProcessId; - FILETIME ftOccurance; - BOOL fTerminate; - CHAR szMessage[SYELOG_MAXIMUM_MESSAGE]; -} SYELOG_MESSAGE, *PSYELOG_MESSAGE; - - -// Facility Codes. -// -#define SYELOG_FACILITY_KERNEL 0x10 // OS Kernel -#define SYELOG_FACILITY_SECURITY 0x20 // OS Security -#define SYELOG_FACILITY_LOGGING 0x30 // OS Logging-internal -#define SYELOG_FACILITY_SERVICE 0x40 // User-mode system daemon -#define SYELOG_FACILITY_APPLICATION 0x50 // User-mode application -#define SYELOG_FACILITY_USER 0x60 // User self-generated. -#define SYELOG_FACILITY_LOCAL0 0x70 // Locally defined. -#define SYELOG_FACILITY_LOCAL1 0x71 // Locally defined. -#define SYELOG_FACILITY_LOCAL2 0x72 // Locally defined. -#define SYELOG_FACILITY_LOCAL3 0x73 // Locally defined. -#define SYELOG_FACILITY_LOCAL4 0x74 // Locally defined. -#define SYELOG_FACILITY_LOCAL5 0x75 // Locally defined. -#define SYELOG_FACILITY_LOCAL6 0x76 // Locally defined. -#define SYELOG_FACILITY_LOCAL7 0x77 // Locally defined. -#define SYELOG_FACILITY_LOCAL8 0x78 // Locally defined. -#define SYELOG_FACILITY_LOCAL9 0x79 // Locally defined. - -// Severity Codes. -// -#define SYELOG_SEVERITY_FATAL 0x00 // System is dead. -#define SYELOG_SEVERITY_ALERT 0x10 // Take action immediately. -#define SYELOG_SEVERITY_CRITICAL 0x20 // Critical condition. -#define SYELOG_SEVERITY_ERROR 0x30 // Error -#define SYELOG_SEVERITY_WARNING 0x40 // Warning -#define SYELOG_SEVERITY_NOTICE 0x50 // Significant condition. -#define SYELOG_SEVERITY_INFORMATION 0x60 // Informational -#define SYELOG_SEVERITY_AUDIT_FAIL 0x66 // Audit Failed -#define SYELOG_SEVERITY_AUDIT_PASS 0x67 // Audit Succeeeded -#define SYELOG_SEVERITY_DEBUG 0x70 // Debugging - -// Logging Functions. -// -VOID SyelogOpen(PCSTR pszIdentifier, BYTE nFacility); -VOID Syelog(BYTE nSeverity, PCSTR pszMsgf, ...); -VOID SyelogV(BYTE nSeverity, PCSTR pszMsgf, va_list args); -VOID SyelogClose(BOOL fTerminate); - -#pragma warning(pop) -#pragma pack(pop) - -#endif // _SYELOGD_H_ -// -///////////////////////////////////////////////////////////////// End of File. diff --git a/3rd/Detours/Lib/detours.lib b/3rd/Detours/Lib/detours.lib deleted file mode 100644 index ce7eaca9ed0b82afc349333325ff0045396a4550..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234970 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%0D=W!^RZRMI@JTtbhB@|;ge6be0f?8+X3Nw`X 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 diff --git a/README.md b/README.md index 91a541f..8bacfd8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# War3 Lua - 1.1.9 (Outland) +# War3 Lua - 1.2.9 (Outland) [![build](https://github.com/Ev3nt/war3_lua/actions/workflows/build.yml/badge.svg)](https://github.com/Ev3nt/war3_lua/actions/workflows/build.yml) ![lua](https://img.shields.io/badge/lua-v5.4.4-blue) diff --git a/Src/Detours.cpp b/Src/Detours.cpp new file mode 100644 index 0000000..63205cf --- /dev/null +++ b/Src/Detours.cpp @@ -0,0 +1,42 @@ +#include "pch.h" +#include "Detours.h" + +namespace Detour { + BOOL Install(UINT_PTR* pointer_ptr, UINT_PTR detour) { + BOOL error = NO_ERROR; + + if ((error = DetourTransactionBegin()) != NO_ERROR) { printf("DetourTransactionBegin failed with error: %d.\n", error); } + if (!error && (error = DetourUpdateThread(GetCurrentThread())) != NO_ERROR) { printf("DetourUpdateThread failed with error: %d.\n", error); } + if (!error && (error = DetourAttach((PVOID*)pointer_ptr, (PVOID)detour)) != NO_ERROR) { printf("DetourAttach failed with error: %d.\n", error); } + if (!error && (error = DetourTransactionCommit()) != NO_ERROR) { printf("DetourTransactionCommit failed with error: %d.\n", error); } + + if (error != NO_ERROR) { DetourTransactionAbort(); } + + return error; + } + + BOOL Uninstall(UINT_PTR* pointer_ptr, UINT_PTR detour) { + BOOL error = NO_ERROR; + + if ((error = DetourTransactionBegin()) != NO_ERROR) { wprintf_s(L"DetourTransactionBegin failed with error: %d.\n", error); } + if (!error && (error = DetourUpdateThread(::GetCurrentThread())) != NO_ERROR) { wprintf_s(L"DetourUpdateThread failed with error: %d.\n", error); } + if (!error && (error = DetourDetach((PVOID*)pointer_ptr, (PVOID)detour)) != NO_ERROR) { wprintf_s(L"DetourAttach failed with error: %d.\n", error); } + if (!error && (error = DetourTransactionCommit()) != NO_ERROR) { wprintf_s(L"DetourTransactionCommit failed with error: %d.\n", error); } + + if (error != NO_ERROR) { DetourTransactionAbort(); } + + return error; + } + + BOOL InstallEx(bool flag, UINT_PTR* pointer_ptr, UINT_PTR detour) { + if (pointer_ptr && *pointer_ptr != NULL) { + return flag ? Install(pointer_ptr, detour) : Uninstall(pointer_ptr, detour); + } + + return -1; + } + + BOOL SetState(bool flag, UINT_PTR* pointer_ptr, UINT_PTR detour) { + return flag ? Install(pointer_ptr, detour) : Uninstall(pointer_ptr, detour); + } +} \ No newline at end of file diff --git a/Src/Detours.h b/Src/Detours.h new file mode 100644 index 0000000..edf0f04 --- /dev/null +++ b/Src/Detours.h @@ -0,0 +1,8 @@ +#pragma once + +namespace Detour { + BOOL Install(UINT_PTR* pointer_ptr, UINT_PTR detour); + BOOL Uninstall(UINT_PTR* pointer_ptr, UINT_PTR detour); + BOOL InstallEx(bool flag, UINT_PTR* pointer_ptr, UINT_PTR detour); + BOOL SetState(bool flag, UINT_PTR* pointer_ptr, UINT_PTR detour); +} \ No newline at end of file diff --git a/Src/DllMain.cpp b/Src/DllMain.cpp index b7ef24b..ad5d4d7 100644 --- a/Src/DllMain.cpp +++ b/Src/DllMain.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "JassMachine.h" #include "JassNatives.h" +#include "Offsets.h" #include "Hooks.h" #include "Logger.h" #include "EasterEgg.h" @@ -30,12 +31,11 @@ BOOL APIENTRY DllMain(HMODULE module, UINT reason, LPVOID reserved) { JassMachine::JassOpcodeInitialize(); - Hooks::AttachHooks(); + Hooks::SetHooksState(true); break; case DLL_PROCESS_DETACH: - - Hooks::DetachHooks(); + Hooks::SetHooksState(false); Logger::CloseConsole(); @@ -48,23 +48,17 @@ BOOL APIENTRY DllMain(HMODULE module, UINT reason, LPVOID reserved) { //--------------------------------------------------------------------- bool StartUp() { - DWORD handle; - DWORD size = GetFileVersionInfoSize("game.dll", &handle); - - LPSTR buffer = new char[size]; - GetFileVersionInfo("game.dll", handle, size, buffer); + if (!InitOffsets()) { + MessageBox(NULL, "Unsupported version of game.dll.\nLua will be unloaded.", "Error", MB_ICONHAND | MB_TOPMOST); - VS_FIXEDFILEINFO* verInfo; - size = sizeof(VS_FIXEDFILEINFO); - VerQueryValue(buffer, "\\", (LPVOID*)&verInfo, (UINT*)&size); - delete[] buffer; + return false; + } - if (((verInfo->dwFileVersionMS >> 16) & 0xffff) != 1 || ((verInfo->dwFileVersionMS >> 0) & 0xffff) != 26 || ((verInfo->dwFileVersionLS >> 16) & 0xffff) != 0 || ((verInfo->dwFileVersionLS >> 0) & 0xffff) != 6401) - { + /*if (Warcraft::GetWarcraftVersion() != Warcraft::VERSION::V126a) { MessageBox(NULL, "Unsupported version of game.dll.\nLua will be unloaded.", "Error", MB_ICONHAND | MB_TOPMOST); return false; - } + }*/ PSTR cmdline = GetCommandLine(); size_t i; diff --git a/Src/Hooks.cpp b/Src/Hooks.cpp index c755208..58194a8 100644 --- a/Src/Hooks.cpp +++ b/Src/Hooks.cpp @@ -1,42 +1,68 @@ #include "pch.h" #include "Hooks.h" +#include "Offsets.h" #include "LuaMachine.h" -#define AttachDetour(pointer, detour) (DetourUpdateThread(GetCurrentThread()), DetourAttach(&(PVOID&)pointer, detour)) -#define DetachDetour(pointer, detour) (DetourUpdateThread(GetCurrentThread()), DetourDetach(&(PVOID&)pointer, detour)) - namespace Hooks { - auto SetJassState = (void(__fastcall*)(BOOL jassState))((std::ptrdiff_t)gameBase + 0x2ab0e0); - auto GetWarcraftID = (DWORD(__stdcall*)())((std::ptrdiff_t)gameBase + 0x537ed0); + enum class EventTypes : UINT { + EVENT_CNET_GAME_START = 0x4009007e, + EVENT_CNET_GAME_LEAVE = 0x40090081, + }; - DWORD GetWarcraftIDCustom() - { - return *(DWORD*)GAME_ID; - } + enum class ObserverRegistryTypes : UINT { + GAME_START_LOADING = 0x00402000, + GAME_FINISH_LOADING = 0x00140800 + }; - void __fastcall SetJassStateCustom(BOOL jassState) { - if (jassState == TRUE) { - LuaMachine::StartLua(); - } + typedef struct { + PVOID vtable; // 0x0 + size_t refCount; // 0x4 + UINT* registry; // 0x8 ObserverRegistry + } CObserver; + + typedef struct { + PVOID vtable; // 0x0 + UINT unk_04; // 0x4 + UINT id; // 0x8 + PVOID object; // 0xC + DWORD data; // 0x10 | serves as keyCode for KeyEvent + } CEvent; - return SetJassState(jassState); + BOOL CGameProcessEvent(CObserver* observer, CEvent* cevent) { + return pOffsets[(UINT)Offset::CGameEventHandler] ? this_call(pOffsets[(UINT)Offset::CGameEventHandler], observer, cevent) : NULL; } - void AttachHooks() { - DetourTransactionBegin(); + DWORD GetWarcraftVersionKey() { + return pOffsets[(UINT)Offset::GetWarcraftVersionKey] ? std_call(pOffsets[(UINT)Offset::GetWarcraftVersionKey]) : NULL; + } - AttachDetour(SetJassState, SetJassStateCustom); - AttachDetour(GetWarcraftID, GetWarcraftIDCustom); + //-------------------------------------------- - DetourTransactionCommit(); + DWORD GetLuaVersionKey() { + return *(DWORD*)GAME_ID; } - void DetachHooks() { - DetourTransactionBegin(); + BOOL __fastcall CGameEventHandler(CObserver* observer, PVOID, CEvent* cevent) { + if (observer && cevent) { + switch (cevent->id) { + case (UINT)EventTypes::EVENT_CNET_GAME_START: + if (*observer->registry == (UINT)ObserverRegistryTypes::GAME_FINISH_LOADING) { + LuaMachine::StartLua(); + } + + break; + case (UINT)EventTypes::EVENT_CNET_GAME_LEAVE: + LuaMachine::DestroyLua(); - DetachDetour(SetJassState, SetJassStateCustom); - DetachDetour(GetWarcraftID, GetWarcraftIDCustom); + break; + } + } + + return CGameProcessEvent(observer, cevent); + } - DetourTransactionCommit(); + void SetHooksState(bool flag) { + Detour::SetState(flag,&pOffsets[(UINT)Offset::CGameEventHandler], (UINT_PTR)CGameEventHandler); + Detour::SetState(flag,&pOffsets[(UINT)Offset::GetWarcraftVersionKey], (UINT_PTR)GetLuaVersionKey); } } \ No newline at end of file diff --git a/Src/Hooks.h b/Src/Hooks.h index 6b83c14..e61df79 100644 --- a/Src/Hooks.h +++ b/Src/Hooks.h @@ -1,7 +1,5 @@ #pragma once namespace Hooks { - void AttachHooks(); - - void DetachHooks(); + void SetHooksState(bool flag); } \ No newline at end of file diff --git a/Src/JassMachine.cpp b/Src/JassMachine.cpp index 975c360..69efbe2 100644 --- a/Src/JassMachine.cpp +++ b/Src/JassMachine.cpp @@ -1,25 +1,25 @@ #include "pch.h" #include "JassMachine.h" #include "LuaMachine.h" +#include "Offsets.h" #include "fp_call.h" namespace JassMachine { - PVOID** ppOpcodeList = (PVOID**)((std::ptrdiff_t)gameBase + 0x45ea5a); - BYTE* pOpcodeListSize = (BYTE*)((std::ptrdiff_t)gameBase + 0x45ea4d); - PVOID opcodeDefaultOutput = (PVOID)((std::ptrdiff_t)gameBase + 0x45f79a); - PVOID OPCODE_FUNCTIONS[44]; DWORD OpcodeStartLuaThread() { LuaMachine::StartLuaThread(); - return c_call(JassMachine::opcodeDefaultOutput); + return c_call(pOffsets[(UINT)Offset::OpcodeDefaultOutput]); // jump } void JassOpcodeInitialize() { + PVOID** ppOpcodeList = (PVOID**)(pOffsets[(UINT)Offset::OpcodeList]); + BYTE* pOpcodeListSize = (BYTE*)(pOffsets[(UINT)Offset::OpcodeSize]); + CopyMemory(OPCODE_FUNCTIONS, *ppOpcodeList, sizeof(OPCODE_FUNCTIONS)); - OPCODE_FUNCTIONS[OPTYPE_STARTLUATHREAD - 2] = OpcodeStartLuaThread; // My own opcode function + OPCODE_FUNCTIONS[(UINT)OPCODE_TYPE::STARTLUATHREAD - 2] = OpcodeStartLuaThread; // My own opcode function DWORD dwOldProtect; VirtualProtect(pOpcodeListSize, sizeof(BYTE), PAGE_EXECUTE_READWRITE, &dwOldProtect); @@ -34,7 +34,7 @@ namespace JassMachine { //----------------------------------------------------------- PJASS_THREAD_LOCAL GetJassThreadLocal() { - return (PJASS_THREAD_LOCAL)GetInstance(5); + return (PJASS_THREAD_LOCAL)Warcraft::GetTLSValueByIndex(5); } PJASS_INSTANCE GetJassMachine(UINT index) { diff --git a/Src/JassMachine.h b/Src/JassMachine.h index 6e8fd23..37b32de 100644 --- a/Src/JassMachine.h +++ b/Src/JassMachine.h @@ -3,71 +3,71 @@ #include "Warcraft.h" #include "JassNatives.h" -namespace JassMachine { - enum OPCODES : BYTE { - OPTYPE_ENDPROGRAM = 1, - OPTYPE_OLDJUMP, - OPTYPE_FUNCTION, - OPTYPE_ENDFUNCTION, - OPTYPE_LOCAL, - OPTYPE_GLOBAL, - OPTYPE_CONSTANT, - OPTYPE_FUNCARG, - OPTYPE_EXTENDS, - OPTYPE_TYPE, - OPTYPE_POPN, - OPTYPE_MOVRLITERAL, - OPTYPE_MOVRR, - OPTYPE_MOVRV, - OPTYPE_MOVRCODE, - OPTYPE_MOVRA, - OPTYPE_MOVVR, - OPTYPE_MOVAR, - OPTYPE_PUSH, - OPTYPE_POP, - OPTYPE_CALLNATIVE, - OPTYPE_CALLJASS, - OPTYPE_I2R, - OPTYPE_AND, - OPTYPE_OR, - OPTYPE_EQUAL, - OPTYPE_NOTEQUAL, - OPTYPE_LESSEREQUAL, - OPTYPE_GREATEREQUAL, - OPTYPE_LESSER, - OPTYPE_GREATER, - OPTYPE_ADD, - OPTYPE_SUB, - OPTYPE_MUL, - OPTYPE_DIV, - OPTYPE_MOD, - OPTYPE_NEGATE, - OPTYPE_NOT, - OPTYPE_RETURN, - OPTYPE_LABE, - OPTYPE_JUMPIFTRUE, - OPTYPE_JUMPIFFALSE, - OPTYPE_JUMP, - OPTYPE_STARTLUATHREAD - }; - - enum OPCODE_VARIABLE_TYPE : BYTE { - OPCODE_VARIABLE_NOTHING = 0, - OPCODE_VARIABLE_UNKNOWN, - OPCODE_VARIABLE_NULL, - OPCODE_VARIABLE_CODE, - OPCODE_VARIABLE_INTEGER, - OPCODE_VARIABLE_REAL, - OPCODE_VARIABLE_STRING, - OPCODE_VARIABLE_HANDLE, - OPCODE_VARIABLE_BOOLEAN, - OPCODE_VARIABLE_INTEGER_ARRAY, - OPCODE_VARIABLE_REAL_ARRAY, - OPCODE_VARIABLE_STRING_ARRAY, - OPCODE_VARIABLE_HANDLE_ARRAY, - OPCODE_VARIABLE_BOOLEAN_ARRAY - }; +enum class OPCODE_TYPE : BYTE { + ENDPROGRAM = 1, + OLDJUMP, + FUNCTION, + ENDFUNCTION, + LOCAL, + GLOBAL, + CONSTANT, + FUNCARG, + EXTENDS, + TYPE, + POPN, + MOVRLITERAL, + MOVRR, + MOVRV, + MOVRCODE, + MOVRA, + MOVVR, + MOVAR, + PUSH, + POP, + CALLNATIVE, + CALLJASS, + I2R, + AND, + OR, + EQUAL, + NOTEQUAL, + LESSEREQUAL, + GREATEREQUAL, + LESSER, + GREATER, + ADD, + SUB, + MUL, + DIV, + MOD, + NEGATE, + NOT, + RETURN, + LABE, + JUMPIFTRUE, + JUMPIFFALSE, + JUMP, + STARTLUATHREAD +}; + +enum class OPCODE_VARIABLE : BYTE { + TYPE_NOTHING = 0, + TYPE_UNKNOWN, + TYPE_NULL, + TYPE_CODE, + TYPE_INTEGER, + TYPE_REAL, + TYPE_STRING, + TYPE_HANDLE, + TYPE_BOOLEAN, + TYPE_INTEGER_ARRAY, + TYPE_REAL_ARRAY, + TYPE_STRING_ARRAY, + TYPE_HANDLE_ARRAY, + TYPE_BOOLEAN_ARRAY +}; +namespace JassMachine { typedef struct { DWORD unk; DWORD zero1; @@ -75,15 +75,15 @@ namespace JassMachine { DWORD zero3; DWORD zero4; DWORD zero5; - DWORD type1; - DWORD type2; + DWORD type1; // OPCODE_VARIABLE + DWORD type2; // OPCODE_VARIABLE DWORD value; DWORD zero6; - void Set(DWORD value, OPCODE_VARIABLE_TYPE type) { + void Set(DWORD value, OPCODE_VARIABLE type) { this->value = value; - type1 = type; - type2 = type; + type1 = (DWORD)type; + type2 = (DWORD)type; } } JASS_DATA_SLOT, * PJASS_DATA_SLOT; @@ -182,10 +182,10 @@ namespace JassMachine { } CODE_TABLE, * PCODE_TABLE; typedef struct { - BYTE returntype; - BYTE type; + OPCODE_VARIABLE returntype; + OPCODE_VARIABLE type; BYTE reg; - BYTE opcode; + OPCODE_TYPE opcode; DWORD value; } JASS_OPCODE, * PJASS_OPCODE; @@ -224,7 +224,7 @@ namespace JassMachine { size_t minArgs; // 0x2c uintptr_t unk5; // 0x30 uintptr_t unk6; // 0x34 - OPCODE_VARIABLE_TYPE returnType; // 0x38 + OPCODE_VARIABLE returnType; // 0x38 }; #pragma pack(pop) @@ -251,7 +251,7 @@ namespace JassMachine { private: std::vector oplist; public: - void AddOperation(OPCODES opcode, BYTE reg = 0, DWORD value = NULL, OPCODE_VARIABLE_TYPE type = OPCODE_VARIABLE_NOTHING, OPCODE_VARIABLE_TYPE returntype = OPCODE_VARIABLE_NOTHING) { + void AddOperation(OPCODE_TYPE opcode, BYTE reg = 0, DWORD value = NULL, OPCODE_VARIABLE type = OPCODE_VARIABLE::TYPE_NOTHING, OPCODE_VARIABLE returntype = OPCODE_VARIABLE::TYPE_NOTHING) { JASS_OPCODE* _opcode = new JASS_OPCODE; _opcode->returntype = returntype; _opcode->type = type; diff --git a/Src/JassNatives.cpp b/Src/JassNatives.cpp index 306218e..e81476d 100644 --- a/Src/JassNatives.cpp +++ b/Src/JassNatives.cpp @@ -21,11 +21,11 @@ namespace Jass { JassMachine::JASS_OPLIST& oplist = jassopcodes[key]; BYTE reg = 0xD8; - oplist.AddOperation(JassMachine::OPTYPE_MOVRLITERAL, reg, LuaMachine::PushFunctionRef(l, index), JassMachine::OPCODE_VARIABLE_INTEGER); - oplist.AddOperation(JassMachine::OPTYPE_PUSH, reg); - oplist.AddOperation(JassMachine::OPTYPE_STARTLUATHREAD); - oplist.AddOperation(JassMachine::OPTYPE_MOVRR); - oplist.AddOperation(JassMachine::OPTYPE_RETURN); + oplist.AddOperation(OPCODE_TYPE::MOVRLITERAL, reg, LuaMachine::PushFunctionRef(l, index), OPCODE_VARIABLE::TYPE_INTEGER); + oplist.AddOperation(OPCODE_TYPE::PUSH, reg); + oplist.AddOperation(OPCODE_TYPE::STARTLUATHREAD); + oplist.AddOperation(OPCODE_TYPE::MOVRR); + oplist.AddOperation(OPCODE_TYPE::RETURN); return oplist.GetCode(); } diff --git a/Src/JassNatives.h b/Src/JassNatives.h index ecdae18..1da1a45 100644 --- a/Src/JassNatives.h +++ b/Src/JassNatives.h @@ -1,5 +1,7 @@ #pragma once +#include "Offsets.h" + //enum JASS_TYPE : BYTE { // TYPE_NONE = 0, // TYPE_BOOLEAN = 'B', @@ -21,7 +23,7 @@ namespace Jass { } inline UINT ToString(LPCSTR string) { - return this_call((std::ptrdiff_t)gameBase + 0x3baa20, string); + return this_call(pOffsets[(UINT)Offset::jStringToString], string); //return std_call((std::ptrdiff_t)gameBase + 0x454930, string, 0); /* UINT* pString = new UINT[8]; diff --git a/Src/Logger.cpp b/Src/Logger.cpp index 5a8ea41..0d91ef8 100644 --- a/Src/Logger.cpp +++ b/Src/Logger.cpp @@ -24,9 +24,6 @@ namespace Logger { } void ClearConsole() { - /*fflush(stdout); - fflush(stderr);*/ - HANDLE hStdOut; CONSOLE_SCREEN_BUFFER_INFO csbi; DWORD count; @@ -56,7 +53,7 @@ namespace Logger { SetConsoleCursorPosition(hStdOut, homeCoords); } - void Log(LOG_LEVEL level, std::string format, ...) { + void Log(LEVEL level, std::string format, ...) { char buffer[8192] = { 0 }; va_list args; @@ -70,22 +67,22 @@ namespace Logger { switch (level) { - case LOG_INFO: + case LEVEL::LOG_INFO: color |= FOREGROUND_GREEN; text = "Info"; break; - case LOG_ERROR: + case LEVEL::LOG_ERROR: color |= FOREGROUND_RED; text = "Error"; break; - case LOG_DEBUG: + case LEVEL::LOG_DEBUG: color |= FOREGROUND_BLUE; text = "Debug"; break; - case LOG_WARNING: + case LEVEL::LOG_WARNING: color |= FOREGROUND_RED | FOREGROUND_GREEN; text = "Warning"; diff --git a/Src/Logger.h b/Src/Logger.h index d79b5ba..b8a6a36 100644 --- a/Src/Logger.h +++ b/Src/Logger.h @@ -7,7 +7,7 @@ #define DEBUG_INFO "[" __FILE__ ":" LINE_STRING "]" namespace Logger { - enum LOG_LEVEL { + enum class LEVEL : BYTE { LOG_NONE, LOG_INFO, LOG_ERROR, @@ -21,7 +21,7 @@ namespace Logger { void ClearConsole(); - void Log(LOG_LEVEL level, std::string format, ...); + void Log(LEVEL level, std::string format, ...); std::string format(std::string format, ...); } \ No newline at end of file diff --git a/Src/LuaFunctions.cpp b/Src/LuaFunctions.cpp index a5674e9..9e80eb0 100644 --- a/Src/LuaFunctions.cpp +++ b/Src/LuaFunctions.cpp @@ -314,7 +314,7 @@ namespace LuaFunctions { std::string string = Logger::format("%s: %08X", lua_tostring(l, 3), handle); if (developerMode && handle > 0x100000) { - string += Logger::format(" | %08X", ConvertHandle(handle)); + string += Logger::format(" | %08X", Warcraft::ConvertHandle(handle)); } lua_pop(l, 2); @@ -370,8 +370,6 @@ namespace LuaFunctions { } void lua_openJassNatives(lua_State* l) { - Jass::JassNativesReset(); - LuaMachine::HandleMetatablesReset(); Jass::JassNativesParse(); for (const auto& type : LuaMachine::handlemetatypes) { @@ -403,7 +401,7 @@ namespace LuaFunctions { int lua_GetMapFileName(lua_State* l) { if (lua_isboolean(l, 1)) { Storm::Archive map; - map.Connect(*pMapMpq); + map.Connect(*(HANDLE*)pOffsets[(UINT)Offset::LastPlayedMap]); std::string name = map.GetArchiveName(); if (!lua_toboolean(l, 1)) { diff --git a/Src/LuaHooks.cpp b/Src/LuaHooks.cpp index 57269d0..c640834 100644 --- a/Src/LuaHooks.cpp +++ b/Src/LuaHooks.cpp @@ -2,6 +2,7 @@ #include "LuaHooks.h" #include "EasyStormLib/EasyStormLib.h" #include "Warcraft.h" +#include "Offsets.h" namespace LuaHooks { //--------------------------------------------------------------------------------- @@ -27,7 +28,7 @@ namespace LuaHooks { } if (scriptName == "war3map") { - map.Connect(*pMapMpq); + map.Connect(*(HANDLE*)pOffsets[(UINT)Offset::LastPlayedMap]); } scriptName += std::string(".lua"); @@ -35,7 +36,7 @@ namespace LuaHooks { std::string mapPath = map.GetArchiveName(scriptName); if (mapPath.empty()) { - map.Connect(*pMapMpq); + map.Connect(*(HANDLE*)pOffsets[(UINT)Offset::LastPlayedMap]); mapPath = map.GetArchiveName(); map.Close(); } @@ -71,7 +72,7 @@ namespace LuaHooks { Storm::Archive map; std::string mapPath = map.GetArchiveName(scriptName); if (mapPath.empty()) { - map.Connect(*pMapMpq); + map.Connect(*(HANDLE*)pOffsets[(UINT)Offset::LastPlayedMap]); mapPath = map.GetArchiveName(); map.Close(); } @@ -123,7 +124,7 @@ namespace LuaHooks { Storm::Archive map; std::string mapPath = map.GetArchiveName(scriptName); if (mapPath.empty()) { - map.Connect(*pMapMpq); + map.Connect(*(HANDLE*)pOffsets[(UINT)Offset::LastPlayedMap]); mapPath = map.GetArchiveName(); map.Close(); } @@ -355,10 +356,10 @@ namespace LuaHooks { LPCSTR s = luaL_tolstring(L, i, &l); if (i > 1) { - PrintChat("\t", 60.f); + Warcraft::PrintChat("\t", 60.f); } - PrintChat(luaL_tolstring(L, -1, NULL), 60.f); + Warcraft::PrintChat(luaL_tolstring(L, -1, NULL), 60.f); lua_pop(L, 1); } diff --git a/Src/LuaMachine.cpp b/Src/LuaMachine.cpp index 2d0aa76..9500191 100644 --- a/Src/LuaMachine.cpp +++ b/Src/LuaMachine.cpp @@ -40,6 +40,8 @@ namespace LuaMachine { lua_close(mainState); mainState = NULL; Jass::JassOpcodesReset(); + Jass::JassNativesReset(); + LuaMachine::HandleMetatablesReset(); } Logger::ClearConsole(); @@ -47,11 +49,9 @@ namespace LuaMachine { void StartLua() { - DestroyLua(); - lua_State* l = GetMainState(); Storm::Archive map; - map.Connect(*pMapMpq); + map.Connect(*(HANDLE*)pOffsets[(UINT)Offset::LastPlayedMap]); if (!map["war3map.lua"].empty()) { lua_pushcfunction(l, stacktrace); lua_getglobal(l, "require"); @@ -83,12 +83,12 @@ namespace LuaMachine { int res; switch (lua_resume(thread, l, 0, &res)) { case LUA_OK: - JassVM->condition_return_value.Set(lua_toboolean(thread, 1), JassMachine::OPCODE_VARIABLE_BOOLEAN); + JassVM->condition_return_value.Set(lua_toboolean(thread, 1), OPCODE_VARIABLE::TYPE_BOOLEAN); break; case LUA_ERRRUN: Error: - PVOID handle = ConvertHandle(Jass::GetNative("GetTriggeringTrigger").Invoke(NULL, NULL) | Jass::GetNative("GetExpiredTimer").Invoke(NULL, NULL)); + PVOID handle = Warcraft::ConvertHandle(Jass::GetNative("GetTriggeringTrigger").Invoke(NULL, NULL) | Jass::GetNative("GetExpiredTimer").Invoke(NULL, NULL)); if (handle) { fast_call((*(UINT*)(*(UINT*)handle + 0x5c)), handle); @@ -156,8 +156,8 @@ namespace LuaMachine { void lua_throwerr(lua_State* l) { std::string error = lua_tostring(l, -1); - Logger::Log(Logger::LOG_LEVEL::LOG_ERROR, error.c_str()); - PrintfChat(100, "\n[|cFFFF0000Error|r] %s\n\n", error.c_str()); + Logger::Log(Logger::LEVEL::LOG_ERROR, error.c_str()); + Warcraft::PrintfChat(100, "\n[|cFFFF0000Error|r] %s\n\n", error.c_str()); //printf("\n%s--------------------Lua Error--------------------%s\n%s\n%s-------------------------------------------------%s\n\n", ANSI_COLOR_RED, ANSI_COLOR_RESET, error, ANSI_COLOR_RED, ANSI_COLOR_RESET); //printfChat(100, "\n|cFFFF0000--------------------Lua Error--------------------|r\n%s\n|cFFFF0000------------------------------------------------------------|r\n\n", error); } diff --git a/Src/LuaMachine.h b/Src/LuaMachine.h index 42330ba..a4fe64e 100644 --- a/Src/LuaMachine.h +++ b/Src/LuaMachine.h @@ -3,6 +3,7 @@ namespace LuaMachine { extern std::map handlemetatypes; + void DestroyLua(); void StartLua(); BOOL __stdcall StartLuaThread(); diff --git a/Src/Offsets.cpp b/Src/Offsets.cpp new file mode 100644 index 0000000..5498654 --- /dev/null +++ b/Src/Offsets.cpp @@ -0,0 +1,88 @@ +#include "pch.h" +#include "Warcraft.h" +#include "Offsets.h" + +UINT_PTR pOffsets[(size_t)Offset::SIZE]; + +bool InitOffsets() { + switch (Warcraft::GetWarcraftVersion()) { + case Warcraft::Version::V124e: + pOffsets[(UINT)Offset::CGameEventHandler] = 0x62a230; + pOffsets[(UINT)Offset::GetWarcraftVersionKey] = 0x5389d0; + pOffsets[(UINT)Offset::OpcodeList] = 0x45f56a; + pOffsets[(UINT)Offset::OpcodeSize] = 0x45f56d; + pOffsets[(UINT)Offset::OpcodeDefaultOutput] = 0x4602aa; + pOffsets[(UINT)Offset::jStringToString] = 0x3bb560; + pOffsets[(UINT)Offset::LastPlayedMap] = 0xac55e0; + pOffsets[(UINT)Offset::GameTLSIndex] = 0xacea4c; + pOffsets[(UINT)Offset::GameObject] = 0xacd44c; + pOffsets[(UINT)Offset::GetGameUI] = 0x301250; + pOffsets[(UINT)Offset::DisplayTimedTextToPlayer] = 0x2f9980; + + break; + case Warcraft::Version::V126a: + pOffsets[(UINT)Offset::CGameEventHandler] = 0x629a90; + pOffsets[(UINT)Offset::GetWarcraftVersionKey] = 0x537ed0; + pOffsets[(UINT)Offset::OpcodeList] = 0x45ea5a; + pOffsets[(UINT)Offset::OpcodeSize] = 0x45ea4d; + pOffsets[(UINT)Offset::OpcodeDefaultOutput] = 0x45f79a; + pOffsets[(UINT)Offset::jStringToString] = 0x3baa20; + pOffsets[(UINT)Offset::LastPlayedMap] = 0xaae788; + pOffsets[(UINT)Offset::GameTLSIndex] = 0xab7bf4; + pOffsets[(UINT)Offset::GameObject] = 0xab65f4; + pOffsets[(UINT)Offset::GetGameUI] = 0x300710; + pOffsets[(UINT)Offset::DisplayTimedTextToPlayer] = 0x2f8e40; + + break; + case Warcraft::Version::V127a: + pOffsets[(UINT)Offset::CGameEventHandler] = 0x0562e0; + pOffsets[(UINT)Offset::GetWarcraftVersionKey] = 0x30d970; + pOffsets[(UINT)Offset::OpcodeList] = 0x7f1aaa; + pOffsets[(UINT)Offset::OpcodeSize] = 0x7f1aad; + pOffsets[(UINT)Offset::OpcodeDefaultOutput] = 0x7f1c3e; + pOffsets[(UINT)Offset::jStringToString] = 0x1da520; + pOffsets[(UINT)Offset::LastPlayedMap] = 0xbee150; + pOffsets[(UINT)Offset::GameTLSIndex] = 0xbb8628; + pOffsets[(UINT)Offset::GameObject] = 0xbe4238; + pOffsets[(UINT)Offset::GetGameUI] = 0x34f3a0; + pOffsets[(UINT)Offset::DisplayTimedTextToPlayer] = 0x357640; + + break; + case Warcraft::Version::V127b: + pOffsets[(UINT)Offset::CGameEventHandler] = 0x071da0; + pOffsets[(UINT)Offset::GetWarcraftVersionKey] = 0x32b0e0; + pOffsets[(UINT)Offset::OpcodeList] = 0x91b4ea; + pOffsets[(UINT)Offset::OpcodeSize] = 0x91b4ed; + pOffsets[(UINT)Offset::OpcodeDefaultOutput] = 0x91c1d5; + pOffsets[(UINT)Offset::jStringToString] = 0x1f7f60; + pOffsets[(UINT)Offset::LastPlayedMap] = 0xd726b8; + pOffsets[(UINT)Offset::GameTLSIndex] = 0xd3cb98; + pOffsets[(UINT)Offset::GameObject] = 0xd687a8; + pOffsets[(UINT)Offset::GetGameUI] = 0x36cb20; + pOffsets[(UINT)Offset::DisplayTimedTextToPlayer] = 0x374de0; + + break; + case Warcraft::Version::V128f: + pOffsets[(UINT)Offset::CGameEventHandler] = 0x09b9d0; + pOffsets[(UINT)Offset::GetWarcraftVersionKey] = 0x35ed70; + pOffsets[(UINT)Offset::OpcodeList] = 0x8d043a; + pOffsets[(UINT)Offset::OpcodeSize] = 0x8d043d; + pOffsets[(UINT)Offset::OpcodeDefaultOutput] = 0x8d1125; + pOffsets[(UINT)Offset::jStringToString] = 0x22a770; + pOffsets[(UINT)Offset::LastPlayedMap] = 0xd3A4f0; + pOffsets[(UINT)Offset::GameTLSIndex] = 0xd047a8; + pOffsets[(UINT)Offset::GameObject] = 0xd305e0; + pOffsets[(UINT)Offset::GetGameUI] = 0x3a0b70; + pOffsets[(UINT)Offset::DisplayTimedTextToPlayer] = 0x3a8eb0; + + break; + default: + return false; + } + + for (auto& offset : pOffsets) { + offset += offset ? (UINT_PTR)gameBase : NULL; + } + + return true; +} \ No newline at end of file diff --git a/Src/Offsets.h b/Src/Offsets.h new file mode 100644 index 0000000..74d620f --- /dev/null +++ b/Src/Offsets.h @@ -0,0 +1,20 @@ +#pragma once + +enum class Offset : UINT { + CGameEventHandler, + GetWarcraftVersionKey, + OpcodeList, + OpcodeSize, + OpcodeDefaultOutput, + jStringToString, + LastPlayedMap, + GameTLSIndex, + GameObject, + GetGameUI, + DisplayTimedTextToPlayer, + SIZE +}; + +extern UINT_PTR pOffsets[(size_t)Offset::SIZE]; + +bool InitOffsets(); \ No newline at end of file diff --git a/Src/Warcraft.cpp b/Src/Warcraft.cpp index 39603f7..0a2a783 100644 --- a/Src/Warcraft.cpp +++ b/Src/Warcraft.cpp @@ -1,31 +1,67 @@ #include "pch.h" #include "Warcraft.h" +#include "Offsets.h" #include "fp_call.h" -auto GetInstanceTrue = (HANDLE(__fastcall*)(UINT))((std::ptrdiff_t)gameBase + 0x4c34d0); -UINT pGameState = (std::ptrdiff_t)gameBase + 0xab65f4; -UINT pGameClass2 = (std::ptrdiff_t)gameBase + 0xab4f80; +namespace Warcraft { + VS_FIXEDFILEINFO* GetFileVersion(LPCSTR filename) { + VS_FIXEDFILEINFO* version = NULL; + DWORD handle; + DWORD size = GetFileVersionInfoSize(filename, &handle); -void PrintChat(LPCSTR text, float duration) { - fast_call((std::ptrdiff_t)gameBase + 0x2f8e40, *(UINT*)pGameClass2, NULL, 0, 0, text, *(UINT*)&duration, 0xFFFFFFFF); - //((void(__fastcall*)(UINT, UINT, UINT, UINT, LPCSTR, UINT, UINT))((UINT)gameBase + 0x2f8e40))(*(UINT*)pGameClass2, NULL, 0, 0, text, *(UINT*)&duration, 0xFFFFFFFF); -} + if (size) { + LPSTR buffer = new char[size]; -void PrintfChat(float duration, LPCSTR format, ...) { - char text[8192] = { NULL }; + if (GetFileVersionInfo(filename, handle, size, buffer) && buffer) { + size = sizeof(VS_FIXEDFILEINFO); + VerQueryValue(buffer, "\\", (LPVOID*)&version, (UINT*)&size); + + } - va_list args; - va_start(args, format); - vsprintf_s(text, format, args); - va_end(args); + delete[] buffer; + } - PrintChat(text, duration); -} + return version; + } -HANDLE GetInstance(UINT index) { - return GetInstanceTrue(index); -} + Version GetWarcraftVersion() { + VS_FIXEDFILEINFO* version = GetFileVersion("game.dll"); -LPVOID ConvertHandle(UINT handle) { - return handle ? *(LPVOID*)(*(UINT*)(*(UINT*)(*(UINT*)pGameState + 0x1c) + 0x19c) + handle * 0xc - 0x2fffff * 4) : NULL; + return version ? Version(version->dwFileVersionLS & 0xFFFF) : Version::NONE; + } + + UINT GetGameUI(BOOL bInit, BOOL bRelease) { + return pOffsets[(UINT)Offset::GetGameUI] ? fast_call(pOffsets[(UINT)Offset::GetGameUI], bInit, bRelease) : NULL; + } + + void PrintChat(LPCSTR text, float duration, DWORD color) { + fast_call(pOffsets[(UINT)Offset::DisplayTimedTextToPlayer], GetGameUI(0, 0), NULL, 0, 0, text, *(UINT*)&duration, color); + } + + void PrintfChat(float duration, LPCSTR format, ...) { + char text[8192] = { NULL }; + + va_list args; + va_start(args, format); + vsprintf_s(text, format, args); + va_end(args); + + PrintChat(text, duration); + } + + HANDLE GetTLSValue() { + return pOffsets[(UINT)Offset::GameTLSIndex] ? TlsGetValue(*(DWORD*)pOffsets[(UINT)Offset::GameTLSIndex]) : NULL; + } + + DWORD GetTLSData(UINT_PTR pOffset) { + return GetTLSValue() ? *(UINT_PTR*)((UINT_PTR)GetTLSValue() + pOffset) : NULL; + } + + DWORD GetTLSValueByIndex(UINT index) { + return GetTLSValue() ? ((DWORD*)GetTLSValue())[index] : NULL; + } + + LPVOID ConvertHandle(UINT handle) { + return handle ? *(LPVOID*)(*(UINT*)(*(UINT*)(*(UINT*)pOffsets[(UINT)Offset::GameObject] + 0x1c) + 0x19c) + handle * 0xc - 0x2fffff * 4) : NULL; + } } \ No newline at end of file diff --git a/Src/Warcraft.h b/Src/Warcraft.h index 6ae3866..4953ab3 100644 --- a/Src/Warcraft.h +++ b/Src/Warcraft.h @@ -1,6 +1,65 @@ #pragma once -void PrintChat(LPCSTR text, float duration); -void PrintfChat(float duration, LPCSTR format, ...); -HANDLE GetInstance(UINT index); -LPVOID ConvertHandle(UINT handle); \ No newline at end of file +namespace Warcraft { + enum class Version : DWORD { + NONE = 0, + V100a = 4448, + V101a = 4482, + V101b = 4483, + V102a = 4531, + V102b = 4563, + V103a = 4653, + V104a = 4709, + V104b = 4709, + V104c = 4905, + V105a = 4944, + V106a = 5551, + V107a = 5535, + V110a = 5610, + V111a = 5616, + V112a = 5636, + V113a = 5816, + V113b = 5818, + V114a = 5840, + V114b = 5846, + V115a = 5917, + V116a = 5926, + V117a = 5988, + V118a = 6030, + V119a = 6041, + V119b = 6046, + V120a = 6048, + V120b = 6056, + V120c = 6065, + V120d = 6070, + V120e = 6074, + V121a = 6263, + V121b = 6300, + V122a = 6328, + V123a = 6352, + V124a = 6372, + V124b = 6374, + V124c = 6378, + V124d = 6384, + V124e = 6387, + V125a = 6396, + V125b = 6397, + V126a = 6401, + V127a = 52240, + V127b = 7085, + V128a = 7205, + V128b = 7365, + V128c = 7395, + V128d = 7554, + V128e = 7608, + V128f = 7680, + }; + + VS_FIXEDFILEINFO* GetFileVersion(LPCSTR filename); + Version GetWarcraftVersion(); + + void PrintChat(LPCSTR text, float duration, DWORD color = 0xFFFFFFFF); + void PrintfChat(float duration, LPCSTR format, ...); + DWORD GetTLSValueByIndex(UINT index); + LPVOID ConvertHandle(UINT handle); +} \ No newline at end of file diff --git a/Src/pch.h b/Src/pch.h index 2f1edaa..da20b58 100644 --- a/Src/pch.h +++ b/Src/pch.h @@ -11,6 +11,7 @@ #include #include #include +#include "Detours.h" #include "fp_call.h" #define ANSI_COLOR_RED "\x1B[31m" @@ -22,7 +23,7 @@ #define ANSI_COLOR_RESET "\x1B[0m" #define WAR3_LUA_MAJOR "1" -#define WAR3_LUA_MINOR "1" +#define WAR3_LUA_MINOR "2" #define WAR3_LUA_RELEASE "9" #define WAR3_LUA_VERSION_NAME ANSI_COLOR_YELLOW "Outland" ANSI_COLOR_RESET @@ -32,7 +33,6 @@ #define GAME_ID "W3L" static HMODULE gameBase = GetModuleHandle("game.dll"); -static HANDLE* pMapMpq = (HANDLE*)((std::ptrdiff_t)gameBase + 0xaae788); extern bool developerMode; diff --git a/packages.config b/packages.config new file mode 100644 index 0000000..31cfc2d --- /dev/null +++ b/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/war3_lua.vcxproj b/war3_lua.vcxproj index 59b7ddf..1401fab 100644 --- a/war3_lua.vcxproj +++ b/war3_lua.vcxproj @@ -384,6 +384,7 @@ NotUsing NotUsing + @@ -399,6 +400,7 @@ + Create Create @@ -436,6 +438,7 @@ + @@ -447,10 +450,21 @@ + + + + + + + + Данный проект ссылается на пакеты NuGet, отсутствующие на этом компьютере. Используйте восстановление пакетов NuGet, чтобы скачать их. Дополнительную информацию см. по адресу: http://go.microsoft.com/fwlink/?LinkID=322105. Отсутствует следующий файл: {0}. + + + \ No newline at end of file diff --git a/war3_lua.vcxproj.filters b/war3_lua.vcxproj.filters index 4e41a62..16644b8 100644 --- a/war3_lua.vcxproj.filters +++ b/war3_lua.vcxproj.filters @@ -153,6 +153,12 @@ Исходные файлы + + Исходные файлы + + + Исходные файлы + @@ -278,5 +284,14 @@ Файлы заголовков + + Файлы заголовков + + + Файлы заголовков + + + + \ No newline at end of file